summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2008-03-10 21:08:29 +0100
committerVolker Lendecke <vl@samba.org>2008-03-10 21:08:45 +0100
commit1ebfc66b2c145289d1e1314e8415d9e3c6f405ae (patch)
tree30b3ca059640ecc963a8744c2a69ef4151dbac7b
parentd634ab06b34990b6eecee751435f2436ff76ec44 (diff)
downloadsamba-1ebfc66b2c145289d1e1314e8415d9e3c6f405ae.tar.gz
samba-1ebfc66b2c145289d1e1314e8415d9e3c6f405ae.tar.bz2
samba-1ebfc66b2c145289d1e1314e8415d9e3c6f405ae.zip
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 f94a63cd8f94490780ad9331da229c0bcb2ca5d6)
-rw-r--r--source3/auth/auth_domain.c16
-rw-r--r--source3/auth/auth_server.c16
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/lib/server_mutex.c57
-rw-r--r--source3/libads/kerberos_verify.c15
-rw-r--r--source3/passdb/secrets.c31
-rw-r--r--source3/winbindd/winbindd_cm.c17
7 files changed, 71 insertions, 82 deletions
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index df51966f4c..26474089fb 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -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 "
diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c
index 095f0b9fb8..b07884c49b 100644
--- a/source3/auth/auth_server.c
+++ b/source3/auth/auth_server.c
@@ -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"));
diff --git a/source3/include/smb.h b/source3/include/smb.h
index c582a97e5c..bf9ca6b92c 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -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;
diff --git a/source3/lib/server_mutex.c b/source3/lib/server_mutex.c
index 2700aa103b..43c0de1975 100644
--- a/source3/lib/server_mutex.c
+++ b/source3/lib/server_mutex.c
@@ -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;
+ tdb_unlock_bystring(mutex->tdb->tdb, mutex->name);
+ return 0;
+}
+
+struct named_mutex *grab_named_mutex(TALLOC_CTX *mem_ctx, const char *name,
+ int timeout)
+{
+ struct named_mutex *result;
+
+ result = talloc(mem_ctx, struct named_mutex);
+ if (result == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return NULL;
}
- 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;
+
+ result->name = talloc_strdup(result, name);
+ if (result->name == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(result);
+ return NULL;
}
- return True;
-}
+ 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;
+ }
-void release_server_mutex(void)
-{
- if (mutex_server_name) {
- secrets_named_mutex_release(mutex_server_name);
- SAFE_FREE(mutex_server_name);
+ 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;
}
diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c
index f112dd34e3..6b482ecd20 100644
--- a/source3/libads/kerberos_verify.c
+++ b/source3/libads/kerberos_verify.c
@@ -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);
diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c
index 2c0d648716..8448f795b4 100644
--- a/source3/passdb/secrets.c
+++ b/source3/passdb/secrets.c
@@ -1029,37 +1029,6 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
}
/*******************************************************************************
- 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.
*******************************************************************************/
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 0f536cdfb8..072b4ee98f 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -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);