mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
Use a separate tdb for mutexes
Another preparation to convert secrets.c to dbwrap: The dbwrap API does not
provide a sane tdb_lock_with_timeout abstraction. In the clustered case the DC
mutex is needed per-node anyway, so it is perfectly fine to use a local mutex
only.
(This used to be commit f94a63cd8f
)
This commit is contained in:
parent
d634ab06b3
commit
1ebfc66b2c
@ -24,6 +24,7 @@
|
||||
#define DBGC_CLASS DBGC_AUTH
|
||||
|
||||
extern bool global_machine_password_needs_changing;
|
||||
static struct named_mutex *mutex;
|
||||
|
||||
/**
|
||||
* Connect to a remote server for (inter)domain security authenticaion.
|
||||
@ -67,7 +68,8 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
|
||||
* ACCESS_DENIED errors if 2 auths are done from the same machine. JRA.
|
||||
*/
|
||||
|
||||
if (!grab_server_mutex(dc_name)) {
|
||||
mutex = grab_named_mutex(NULL, dc_name, 10);
|
||||
if (mutex == NULL) {
|
||||
return NT_STATUS_NO_LOGON_SERVERS;
|
||||
}
|
||||
|
||||
@ -87,7 +89,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
|
||||
*cli = NULL;
|
||||
}
|
||||
|
||||
release_server_mutex();
|
||||
TALLOC_FREE(mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -118,7 +120,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
|
||||
machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
|
||||
cli_shutdown(*cli);
|
||||
*cli = NULL;
|
||||
release_server_mutex();
|
||||
TALLOC_FREE(mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -137,7 +139,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
|
||||
domain));
|
||||
cli_shutdown(*cli);
|
||||
*cli = NULL;
|
||||
release_server_mutex();
|
||||
TALLOC_FREE(mutex);
|
||||
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
|
||||
}
|
||||
|
||||
@ -153,7 +155,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
cli_shutdown(*cli);
|
||||
*cli = NULL;
|
||||
release_server_mutex();
|
||||
TALLOC_FREE(mutex);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -163,7 +165,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
|
||||
machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli)));
|
||||
cli_shutdown(*cli);
|
||||
*cli = NULL;
|
||||
release_server_mutex();
|
||||
TALLOC_FREE(mutex);
|
||||
return NT_STATUS_NO_LOGON_SERVERS;
|
||||
}
|
||||
|
||||
@ -247,7 +249,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
|
||||
/* Let go as soon as possible so we avoid any potential deadlocks
|
||||
with winbind lookup up users or groups. */
|
||||
|
||||
release_server_mutex();
|
||||
TALLOC_FREE(mutex);
|
||||
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
DEBUG(0,("domain_client_validate: unable to validate password "
|
||||
|
@ -37,6 +37,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
|
||||
const char *p;
|
||||
char *pserver = NULL;
|
||||
bool connected_ok = False;
|
||||
struct named_mutex *mutex;
|
||||
|
||||
if (!(cli = cli_initialise()))
|
||||
return NULL;
|
||||
@ -74,7 +75,8 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
|
||||
session setup yet it will send a TCP reset to the first
|
||||
connection (tridge) */
|
||||
|
||||
if (!grab_server_mutex(desthost)) {
|
||||
mutex = grab_named_mutex(talloc_tos(), desthost, 10);
|
||||
if (mutex == NULL) {
|
||||
cli_shutdown(cli);
|
||||
return NULL;
|
||||
}
|
||||
@ -87,7 +89,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
|
||||
}
|
||||
DEBUG(10,("server_cryptkey: failed to connect to server %s. Error %s\n",
|
||||
desthost, nt_errstr(status) ));
|
||||
release_server_mutex();
|
||||
TALLOC_FREE(mutex);
|
||||
}
|
||||
|
||||
if (!connected_ok) {
|
||||
@ -98,7 +100,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
|
||||
|
||||
if (!attempt_netbios_session_request(&cli, global_myname(),
|
||||
desthost, &dest_ss)) {
|
||||
release_server_mutex();
|
||||
TALLOC_FREE(mutex);
|
||||
DEBUG(1,("password server fails session request\n"));
|
||||
cli_shutdown(cli);
|
||||
return NULL;
|
||||
@ -111,16 +113,16 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
|
||||
DEBUG(3,("got session\n"));
|
||||
|
||||
if (!cli_negprot(cli)) {
|
||||
TALLOC_FREE(mutex);
|
||||
DEBUG(1,("%s rejected the negprot\n",desthost));
|
||||
release_server_mutex();
|
||||
cli_shutdown(cli);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cli->protocol < PROTOCOL_LANMAN2 ||
|
||||
!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
|
||||
TALLOC_FREE(mutex);
|
||||
DEBUG(1,("%s isn't in user level security mode\n",desthost));
|
||||
release_server_mutex();
|
||||
cli_shutdown(cli);
|
||||
return NULL;
|
||||
}
|
||||
@ -132,14 +134,14 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
|
||||
|
||||
if (!NT_STATUS_IS_OK(cli_session_setup(cli, "", "", 0, "", 0,
|
||||
""))) {
|
||||
TALLOC_FREE(mutex);
|
||||
DEBUG(0,("%s rejected the initial session setup (%s)\n",
|
||||
desthost, cli_errstr(cli)));
|
||||
release_server_mutex();
|
||||
cli_shutdown(cli);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
release_server_mutex();
|
||||
TALLOC_FREE(mutex);
|
||||
|
||||
DEBUG(3,("password server OK\n"));
|
||||
|
||||
|
@ -420,6 +420,7 @@ struct timed_event;
|
||||
struct idle_event;
|
||||
struct share_mode_entry;
|
||||
struct uuid;
|
||||
struct named_mutex;
|
||||
|
||||
struct vfs_fsp_data {
|
||||
struct vfs_fsp_data *next;
|
||||
|
@ -28,28 +28,51 @@
|
||||
This locking allows smbd's mutlithread architecture to look
|
||||
like the single-connection that NT makes. */
|
||||
|
||||
static char *mutex_server_name;
|
||||
struct named_mutex {
|
||||
struct tdb_wrap *tdb;
|
||||
char *name;
|
||||
};
|
||||
|
||||
bool grab_server_mutex(const char *name)
|
||||
static int unlock_named_mutex(struct named_mutex *mutex)
|
||||
{
|
||||
mutex_server_name = SMB_STRDUP(name);
|
||||
if (!mutex_server_name) {
|
||||
DEBUG(0,("grab_server_mutex: malloc failed for %s\n", name));
|
||||
return False;
|
||||
}
|
||||
if (!secrets_named_mutex(mutex_server_name, 10)) {
|
||||
DEBUG(10,("grab_server_mutex: failed for %s\n", name));
|
||||
SAFE_FREE(mutex_server_name);
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
tdb_unlock_bystring(mutex->tdb->tdb, mutex->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void release_server_mutex(void)
|
||||
struct named_mutex *grab_named_mutex(TALLOC_CTX *mem_ctx, const char *name,
|
||||
int timeout)
|
||||
{
|
||||
if (mutex_server_name) {
|
||||
secrets_named_mutex_release(mutex_server_name);
|
||||
SAFE_FREE(mutex_server_name);
|
||||
struct named_mutex *result;
|
||||
|
||||
result = talloc(mem_ctx, struct named_mutex);
|
||||
if (result == NULL) {
|
||||
DEBUG(0, ("talloc failed\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->name = talloc_strdup(result, name);
|
||||
if (result->name == NULL) {
|
||||
DEBUG(0, ("talloc failed\n"));
|
||||
TALLOC_FREE(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->tdb = tdb_wrap_open(result, lock_path("mutex.tdb"), 0,
|
||||
TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
|
||||
if (result->tdb == NULL) {
|
||||
DEBUG(1, ("Could not open mutex.tdb: %s\n",
|
||||
strerror(errno)));
|
||||
TALLOC_FREE(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (tdb_lock_bystring_with_timeout(result->tdb->tdb, name,
|
||||
timeout) == -1) {
|
||||
DEBUG(1, ("Could not get the lock for %s\n", name));
|
||||
TALLOC_FREE(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
talloc_set_destructor(result, unlock_named_mutex);
|
||||
return result;
|
||||
}
|
||||
|
@ -330,8 +330,8 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
|
||||
krb5_const_principal client_principal = NULL;
|
||||
char *host_princ_s = NULL;
|
||||
bool auth_ok = False;
|
||||
bool got_replay_mutex = False;
|
||||
bool got_auth_data = False;
|
||||
struct named_mutex *mutex = NULL;
|
||||
|
||||
ZERO_STRUCT(packet);
|
||||
ZERO_STRUCT(auth_data);
|
||||
@ -395,15 +395,15 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
|
||||
locking in the MIT krb5 code surrounding the replay
|
||||
cache... */
|
||||
|
||||
if (!grab_server_mutex("replay cache mutex")) {
|
||||
mutex = grab_named_mutex(talloc_tos(), "replay cache mutex",
|
||||
10);
|
||||
if (mutex == NULL) {
|
||||
DEBUG(1,("ads_verify_ticket: unable to protect "
|
||||
"replay cache with mutex.\n"));
|
||||
ret = KRB5_CC_IO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
got_replay_mutex = True;
|
||||
|
||||
/* JRA. We must set the rcache here. This will prevent
|
||||
replay attacks. */
|
||||
|
||||
@ -443,8 +443,7 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
|
||||
}
|
||||
|
||||
if ( use_replay_cache ) {
|
||||
release_server_mutex();
|
||||
got_replay_mutex = False;
|
||||
TALLOC_FREE(mutex);
|
||||
#if 0
|
||||
/* Heimdal leaks here, if we fix the leak, MIT crashes */
|
||||
if (rcache) {
|
||||
@ -539,9 +538,7 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
|
||||
|
||||
out:
|
||||
|
||||
if (got_replay_mutex) {
|
||||
release_server_mutex();
|
||||
}
|
||||
TALLOC_FREE(mutex);
|
||||
|
||||
if (!NT_STATUS_IS_OK(sret)) {
|
||||
data_blob_free(&auth_data);
|
||||
|
@ -1028,37 +1028,6 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Lock the secrets tdb based on a string - this is used as a primitive form of mutex
|
||||
between smbd instances.
|
||||
*******************************************************************************/
|
||||
|
||||
bool secrets_named_mutex(const char *name, unsigned int timeout)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!secrets_init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = tdb_lock_bystring_with_timeout(tdb, name, timeout);
|
||||
if (ret == 0) {
|
||||
DEBUG(10,("secrets_named_mutex: got mutex for %s\n", name ));
|
||||
}
|
||||
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Unlock a named mutex.
|
||||
*******************************************************************************/
|
||||
|
||||
void secrets_named_mutex_release(const char *name)
|
||||
{
|
||||
tdb_unlock_bystring(tdb, name);
|
||||
DEBUG(10,("secrets_named_mutex: released mutex for %s\n", name ));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Store a complete AFS keyfile into secrets.tdb.
|
||||
*******************************************************************************/
|
||||
|
@ -747,7 +747,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
|
||||
char *ipc_domain = NULL;
|
||||
char *ipc_password = NULL;
|
||||
|
||||
bool got_mutex;
|
||||
struct named_mutex *mutex;
|
||||
|
||||
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
@ -761,10 +761,9 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
|
||||
|
||||
*retry = True;
|
||||
|
||||
got_mutex = secrets_named_mutex(controller,
|
||||
WINBIND_SERVER_MUTEX_WAIT_TIME);
|
||||
|
||||
if (!got_mutex) {
|
||||
mutex = grab_named_mutex(talloc_tos(), controller,
|
||||
WINBIND_SERVER_MUTEX_WAIT_TIME);
|
||||
if (mutex == NULL) {
|
||||
DEBUG(0,("cm_prepare_connection: mutex grab failed for %s\n",
|
||||
controller));
|
||||
result = NT_STATUS_POSSIBLE_DEADLOCK;
|
||||
@ -952,8 +951,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
|
||||
goto done;
|
||||
}
|
||||
|
||||
secrets_named_mutex_release(controller);
|
||||
got_mutex = False;
|
||||
TALLOC_FREE(mutex);
|
||||
*retry = False;
|
||||
|
||||
/* set the domain if empty; needed for schannel connections */
|
||||
@ -964,10 +962,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
|
||||
result = NT_STATUS_OK;
|
||||
|
||||
done:
|
||||
if (got_mutex) {
|
||||
secrets_named_mutex_release(controller);
|
||||
}
|
||||
|
||||
TALLOC_FREE(mutex);
|
||||
SAFE_FREE(machine_account);
|
||||
SAFE_FREE(machine_password);
|
||||
SAFE_FREE(machine_krb5_principal);
|
||||
|
Loading…
Reference in New Issue
Block a user