1
0
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:
Volker Lendecke 2008-03-10 21:08:29 +01:00
parent d634ab06b3
commit 1ebfc66b2c
7 changed files with 72 additions and 83 deletions

View File

@ -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 "

View File

@ -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"));

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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.
*******************************************************************************/

View File

@ -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);