Blame SOURCES/cyrus-sasl-2.1.26-gssapi-use-per-connection-mutex.patch

b7aa3c
From 70a144cc53d09b56aa088fa1f6d433acea31afa7 Mon Sep 17 00:00:00 2001
b7aa3c
From: Alexander Bokovoy <abokovoy@redhat.com>
b7aa3c
Date: Tue, 15 Sep 2015 12:21:22 +0300
b7aa3c
Subject: [PATCH] gssapi: use per-connection mutex where possible
b7aa3c
b7aa3c
If the same application uses SASL GSSAPI for both client and server operations,
b7aa3c
it may be possible to deadlock in plugins/gssapi.c due to use of a
b7aa3c
global mutex by both client and server code. Multiple outstanding connections should
b7aa3c
be possible, thus introduce per-context locking and use it where it
b7aa3c
makes sense. Note that there are still multiple places where context is
b7aa3c
not available and where a global lock should be in use.
b7aa3c
b7aa3c
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1263017
b7aa3c
---
b7aa3c
 plugins/gssapi.c | 225 +++++++++++++++++++++++++++++++------------------------
b7aa3c
 1 file changed, 126 insertions(+), 99 deletions(-)
b7aa3c
b7aa3c
diff --git a/plugins/gssapi.c b/plugins/gssapi.c
b7aa3c
index 2fd1b3b..f5d3354 100644
b7aa3c
--- a/plugins/gssapi.c
b7aa3c
+++ b/plugins/gssapi.c
b7aa3c
@@ -126,20 +126,29 @@ extern gss_OID gss_nt_service_name;
b7aa3c
  */
b7aa3c
 
b7aa3c
 #ifdef GSS_USE_MUTEXES
b7aa3c
-#define GSS_LOCK_MUTEX(utils)  \
b7aa3c
-    if(((sasl_utils_t *)(utils))->mutex_lock(gss_mutex) != 0) { \
b7aa3c
+#define GSS_LOCK_MUTEX_EXT(utils, mutex)  \
b7aa3c
+    if(((sasl_utils_t *)(utils))->mutex_lock(mutex) != 0) { \
b7aa3c
        return SASL_FAIL; \
b7aa3c
     }
b7aa3c
 
b7aa3c
-#define GSS_UNLOCK_MUTEX(utils) \
b7aa3c
-    if(((sasl_utils_t *)(utils))->mutex_unlock(gss_mutex) != 0) { \
b7aa3c
+#define GSS_UNLOCK_MUTEX_EXT(utils, mutex) \
b7aa3c
+    if(((sasl_utils_t *)(utils))->mutex_unlock(mutex) != 0) { \
b7aa3c
         return SASL_FAIL; \
b7aa3c
     }
b7aa3c
 
b7aa3c
+#define GSS_LOCK_MUTEX(utils) GSS_LOCK_MUTEX_EXT(utils, gss_mutex)
b7aa3c
+#define GSS_UNLOCK_MUTEX(utils) GSS_UNLOCK_MUTEX_EXT(utils, gss_mutex)
b7aa3c
+
b7aa3c
+#define GSS_LOCK_MUTEX_CTX(utils, ctx) GSS_LOCK_MUTEX_EXT(utils, (ctx)->ctx_mutex)
b7aa3c
+#define GSS_UNLOCK_MUTEX_CTX(utils, ctx) GSS_UNLOCK_MUTEX_EXT(utils, (ctx)->ctx_mutex)
b7aa3c
+
b7aa3c
+
b7aa3c
 static void *gss_mutex = NULL;
b7aa3c
 #else
b7aa3c
 #define GSS_LOCK_MUTEX(utils)
b7aa3c
 #define GSS_UNLOCK_MUTEX(utils)
b7aa3c
+#define GSS_LOCK_MUTEX_CTX(utils, ctx)
b7aa3c
+#define GSS_UNLOCK_MUTEX_CTX(utils, ctx)
b7aa3c
 #endif
b7aa3c
 
b7aa3c
 typedef struct context {
b7aa3c
@@ -176,6 +185,7 @@ typedef struct context {
b7aa3c
     
b7aa3c
     char *authid; /* hold the authid between steps - server */
b7aa3c
     const char *user;   /* hold the userid between steps - client */
b7aa3c
+    void *ctx_mutex; /* A per-context mutex */
b7aa3c
 } context_t;
b7aa3c
 
b7aa3c
 enum {
b7aa3c
@@ -355,7 +365,7 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov,
b7aa3c
     output_token->value = NULL;
b7aa3c
     output_token->length = 0;
b7aa3c
     
b7aa3c
-    GSS_LOCK_MUTEX(text->utils);
b7aa3c
+    GSS_LOCK_MUTEX_CTX(text->utils, text);
b7aa3c
     maj_stat = gss_wrap (&min_stat,
b7aa3c
 			 text->gss_ctx,
b7aa3c
 			 privacy,
b7aa3c
@@ -363,14 +373,14 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov,
b7aa3c
 			 input_token,
b7aa3c
 			 NULL,
b7aa3c
 			 output_token);
b7aa3c
-    GSS_UNLOCK_MUTEX(text->utils);
b7aa3c
+    GSS_UNLOCK_MUTEX_CTX(text->utils, text);
b7aa3c
     
b7aa3c
     if (GSS_ERROR(maj_stat)) {
b7aa3c
 	sasl_gss_seterror(text->utils, maj_stat, min_stat);
b7aa3c
 	if (output_token->value) {
b7aa3c
-	    GSS_LOCK_MUTEX(text->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(text->utils, text);
b7aa3c
 	    gss_release_buffer(&min_stat, output_token);
b7aa3c
-	    GSS_UNLOCK_MUTEX(text->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(text->utils, text);
b7aa3c
 	}
b7aa3c
 	return SASL_FAIL;
b7aa3c
     }
b7aa3c
@@ -384,9 +394,9 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov,
b7aa3c
 			      output_token->length + 4);
b7aa3c
 	
b7aa3c
 	if (ret != SASL_OK) {
b7aa3c
-	    GSS_LOCK_MUTEX(text->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(text->utils, text);
b7aa3c
 	    gss_release_buffer(&min_stat, output_token);
b7aa3c
-	    GSS_UNLOCK_MUTEX(text->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(text->utils, text);
b7aa3c
 	    return ret;
b7aa3c
 	}
b7aa3c
 
b7aa3c
@@ -407,9 +417,9 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov,
b7aa3c
     *output = text->encode_buf;
b7aa3c
     
b7aa3c
     if (output_token->value) {
b7aa3c
-	GSS_LOCK_MUTEX(text->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(text->utils, text);
b7aa3c
 	gss_release_buffer(&min_stat, output_token);
b7aa3c
-	GSS_UNLOCK_MUTEX(text->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(text->utils, text);
b7aa3c
     }
b7aa3c
 
b7aa3c
     return SASL_OK;
b7aa3c
@@ -455,21 +465,21 @@ gssapi_decode_packet(void *context,
b7aa3c
     output_token->value = NULL;
b7aa3c
     output_token->length = 0;
b7aa3c
     
b7aa3c
-    GSS_LOCK_MUTEX(text->utils);
b7aa3c
+    GSS_LOCK_MUTEX_CTX(text->utils, text);
b7aa3c
     maj_stat = gss_unwrap (&min_stat,
b7aa3c
 			   text->gss_ctx,
b7aa3c
 			   input_token,
b7aa3c
 			   output_token,
b7aa3c
 			   NULL,
b7aa3c
 			   NULL);
b7aa3c
-    GSS_UNLOCK_MUTEX(text->utils);
b7aa3c
+    GSS_UNLOCK_MUTEX_CTX(text->utils, text);
b7aa3c
     
b7aa3c
     if (GSS_ERROR(maj_stat)) {
b7aa3c
 	sasl_gss_seterror(text->utils,maj_stat,min_stat);
b7aa3c
 	if (output_token->value) {
b7aa3c
-	    GSS_LOCK_MUTEX(text->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(text->utils, text);
b7aa3c
 	    gss_release_buffer(&min_stat, output_token);
b7aa3c
-	    GSS_UNLOCK_MUTEX(text->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(text->utils, text);
b7aa3c
 	}
b7aa3c
 	return SASL_FAIL;
b7aa3c
     }
b7aa3c
@@ -484,17 +494,17 @@ gssapi_decode_packet(void *context,
b7aa3c
 				     &text->decode_once_buf_len,
b7aa3c
 				     *outputlen);
b7aa3c
 	    if (result != SASL_OK) {
b7aa3c
-		GSS_LOCK_MUTEX(text->utils);
b7aa3c
+		GSS_LOCK_MUTEX_CTX(text->utils, text);
b7aa3c
 		gss_release_buffer(&min_stat, output_token);
b7aa3c
-		GSS_UNLOCK_MUTEX(text->utils);
b7aa3c
+		GSS_UNLOCK_MUTEX_CTX(text->utils, text);
b7aa3c
 		return result;
b7aa3c
 	    }
b7aa3c
 	    *output = text->decode_once_buf;
b7aa3c
 	    memcpy(*output, output_token->value, *outputlen);
b7aa3c
 	}
b7aa3c
-	GSS_LOCK_MUTEX(text->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(text->utils, text);
b7aa3c
 	gss_release_buffer(&min_stat, output_token);
b7aa3c
-	GSS_UNLOCK_MUTEX(text->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(text->utils, text);
b7aa3c
     }
b7aa3c
     
b7aa3c
     return SASL_OK;
b7aa3c
@@ -525,7 +535,14 @@ static context_t *sasl_gss_new_context(const sasl_utils_t *utils)
b7aa3c
     
b7aa3c
     memset(ret,0,sizeof(context_t));
b7aa3c
     ret->utils = utils;
b7aa3c
-    
b7aa3c
+#ifdef GSS_USE_MUTEXES
b7aa3c
+    ret->ctx_mutex = utils->mutex_alloc();
b7aa3c
+    if (!ret->ctx_mutex) {
b7aa3c
+           utils->free(ret);
b7aa3c
+           return NULL;
b7aa3c
+    }
b7aa3c
+#endif
b7aa3c
+
b7aa3c
     return ret;
b7aa3c
 }
b7aa3c
 
b7aa3c
@@ -535,7 +552,11 @@ static int sasl_gss_free_context_contents(context_t *text)
b7aa3c
     
b7aa3c
     if (!text) return SASL_OK;
b7aa3c
     
b7aa3c
-    GSS_LOCK_MUTEX(text->utils);
b7aa3c
+#ifdef GSS_USE_MUTEXES
b7aa3c
+    if (text->ctx_mutex) {
b7aa3c
+        GSS_LOCK_MUTEX_CTX(text->utils, text);
b7aa3c
+    }
b7aa3c
+#endif
b7aa3c
 
b7aa3c
     if (text->gss_ctx != GSS_C_NO_CONTEXT) {
b7aa3c
 	maj_stat = gss_delete_sec_context(&min_stat,&text->gss_ctx,
b7aa3c
@@ -563,8 +584,6 @@ static int sasl_gss_free_context_contents(context_t *text)
b7aa3c
 	text->client_creds = GSS_C_NO_CREDENTIAL;
b7aa3c
     }
b7aa3c
 
b7aa3c
-    GSS_UNLOCK_MUTEX(text->utils);
b7aa3c
-    
b7aa3c
     if (text->out_buf) {
b7aa3c
 	text->utils->free(text->out_buf);
b7aa3c
 	text->out_buf = NULL;
b7aa3c
@@ -598,6 +617,14 @@ static int sasl_gss_free_context_contents(context_t *text)
b7aa3c
 	text->authid = NULL;
b7aa3c
     }
b7aa3c
 
b7aa3c
+#ifdef GSS_USE_MUTEXES
b7aa3c
+    if (text->ctx_mutex) {
b7aa3c
+        GSS_UNLOCK_MUTEX_CTX(text->utils, text);
b7aa3c
+        text->utils->mutex_free(text->ctx_mutex);
b7aa3c
+        text->ctx_mutex = NULL;
b7aa3c
+    }
b7aa3c
+#endif
b7aa3c
+
b7aa3c
     return SASL_OK;
b7aa3c
 
b7aa3c
 }
b7aa3c
@@ -692,12 +719,12 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
 	}
b7aa3c
 	sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
b7aa3c
 
b7aa3c
-	GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	maj_stat = gss_import_name (&min_stat,
b7aa3c
 				    &name_token,
b7aa3c
 				    GSS_C_NT_HOSTBASED_SERVICE,
b7aa3c
 				    &text->server_name);
b7aa3c
-	GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
 	params->utils->free(name_token.value);
b7aa3c
 	name_token.value = NULL;
b7aa3c
@@ -709,15 +736,15 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
 	}
b7aa3c
 
b7aa3c
 	if ( text->server_creds != GSS_C_NO_CREDENTIAL) {
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    maj_stat = gss_release_cred(&min_stat, &text->server_creds);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    text->server_creds = GSS_C_NO_CREDENTIAL;
b7aa3c
 	}
b7aa3c
 
b7aa3c
 	/* If caller didn't provide creds already */
b7aa3c
 	if ( server_creds == GSS_C_NO_CREDENTIAL) {
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    maj_stat = gss_acquire_cred(&min_stat, 
b7aa3c
 					text->server_name,
b7aa3c
 					GSS_C_INDEFINITE, 
b7aa3c
@@ -726,7 +753,7 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
 					&text->server_creds, 
b7aa3c
 					NULL, 
b7aa3c
 					NULL);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
 	    if (GSS_ERROR(maj_stat)) {
b7aa3c
 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
b7aa3c
@@ -743,7 +770,7 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
     }
b7aa3c
 
b7aa3c
 
b7aa3c
-    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
     maj_stat =
b7aa3c
 	gss_accept_sec_context(&min_stat,
b7aa3c
 			       &(text->gss_ctx),
b7aa3c
@@ -756,15 +783,15 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
 			       &out_flags,
b7aa3c
 			       NULL,	/* context validity period */
b7aa3c
 			       &(text->client_creds));
b7aa3c
-    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
     if (GSS_ERROR(maj_stat)) {
b7aa3c
 	sasl_gss_log(text->utils, maj_stat, min_stat);
b7aa3c
 	text->utils->seterror(text->utils->conn, SASL_NOLOG, "GSSAPI Failure: gss_accept_sec_context");
b7aa3c
 	if (output_token->value) {
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    gss_release_buffer(&min_stat, output_token);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	}
b7aa3c
 	sasl_gss_free_context_contents(text);
b7aa3c
 	return SASL_BADAUTH;
b7aa3c
@@ -778,18 +805,18 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
 	    ret = _plug_buf_alloc(text->utils, &(text->out_buf),
b7aa3c
 				  &(text->out_buf_len), *serveroutlen);
b7aa3c
 	    if(ret != SASL_OK) {
b7aa3c
-		GSS_LOCK_MUTEX(params->utils);
b7aa3c
+		GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		gss_release_buffer(&min_stat, output_token);
b7aa3c
-		GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+		GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		return ret;
b7aa3c
 	    }
b7aa3c
 	    memcpy(text->out_buf, output_token->value, *serveroutlen);
b7aa3c
 	    *serverout = text->out_buf;
b7aa3c
 	}
b7aa3c
 
b7aa3c
-	GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	gss_release_buffer(&min_stat, output_token);
b7aa3c
-	GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
     } else {
b7aa3c
 	/* No output token, send an empty string */
b7aa3c
 	*serverout = GSSAPI_BLANK_STRING;
b7aa3c
@@ -832,12 +859,12 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
 	    /* continue with authentication */
b7aa3c
 	}
b7aa3c
 
b7aa3c
-    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
     maj_stat = gss_canonicalize_name(&min_stat,
b7aa3c
 				     text->client_name,
b7aa3c
 				     mech_type,
b7aa3c
 				     &client_name_MN);
b7aa3c
-    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
     if (GSS_ERROR(maj_stat)) {
b7aa3c
 	SETERROR(text->utils, "GSSAPI Failure: gss_canonicalize_name");
b7aa3c
@@ -848,12 +875,12 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
     name_token.value = NULL;
b7aa3c
     name_without_realm.value = NULL;
b7aa3c
 
b7aa3c
-    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
     maj_stat = gss_display_name (&min_stat,
b7aa3c
 				 client_name_MN,
b7aa3c
 				 &name_token,
b7aa3c
 				 NULL);
b7aa3c
-    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
     if (GSS_ERROR(maj_stat)) {
b7aa3c
 	SETERROR(text->utils, "GSSAPI Failure: gss_display_name");
b7aa3c
@@ -883,7 +910,7 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
 
b7aa3c
 	name_without_realm.length = strlen( (char *) name_without_realm.value );
b7aa3c
 
b7aa3c
-	GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	maj_stat = gss_import_name (&min_stat,
b7aa3c
 				    &name_without_realm,
b7aa3c
 	    /* Solaris 8/9 gss_import_name doesn't accept GSS_C_NULL_OID here,
b7aa3c
@@ -894,7 +921,7 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
 				    GSS_C_NULL_OID,
b7aa3c
 #endif
b7aa3c
 				    &without);
b7aa3c
-	GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
 	if (GSS_ERROR(maj_stat)) {
b7aa3c
 	    SETERROR(text->utils, "GSSAPI Failure: gss_import_name");
b7aa3c
@@ -903,12 +930,12 @@ gssapi_server_mech_authneg(context_t *text,
b7aa3c
 	    goto cleanup;
b7aa3c
 	}
b7aa3c
 
b7aa3c
-	GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	maj_stat = gss_compare_name(&min_stat,
b7aa3c
 				    client_name_MN,
b7aa3c
 				    without,
b7aa3c
 				    &equal);
b7aa3c
-	GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
 	if (GSS_ERROR(maj_stat)) {
b7aa3c
 	    SETERROR(text->utils, "GSSAPI Failure: gss_compare_name");
b7aa3c
@@ -1053,7 +1080,7 @@ gssapi_server_mech_ssfcap(context_t *text,
b7aa3c
     real_input_token.value = (void *)sasldata;
b7aa3c
     real_input_token.length = 4;
b7aa3c
 
b7aa3c
-    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
     maj_stat = gss_wrap(&min_stat,
b7aa3c
 			text->gss_ctx,
b7aa3c
 			0, /* Just integrity checking here */
b7aa3c
@@ -1061,14 +1088,14 @@ gssapi_server_mech_ssfcap(context_t *text,
b7aa3c
 			input_token,
b7aa3c
 			NULL,
b7aa3c
 			output_token);
b7aa3c
-    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
     if (GSS_ERROR(maj_stat)) {
b7aa3c
 	sasl_gss_seterror(text->utils, maj_stat, min_stat);
b7aa3c
 	if (output_token->value) {
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    gss_release_buffer(&min_stat, output_token);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	}
b7aa3c
 	sasl_gss_free_context_contents(text);
b7aa3c
 	return SASL_FAIL;
b7aa3c
@@ -1082,18 +1109,18 @@ gssapi_server_mech_ssfcap(context_t *text,
b7aa3c
 	    ret = _plug_buf_alloc(text->utils, &(text->out_buf),
b7aa3c
 				  &(text->out_buf_len), *serveroutlen);
b7aa3c
 	    if(ret != SASL_OK) {
b7aa3c
-		GSS_LOCK_MUTEX(params->utils);
b7aa3c
+		GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		gss_release_buffer(&min_stat, output_token);
b7aa3c
-		GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+		GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		return ret;
b7aa3c
 	    }
b7aa3c
 	    memcpy(text->out_buf, output_token->value, *serveroutlen);
b7aa3c
 	    *serverout = text->out_buf;
b7aa3c
 	}
b7aa3c
 
b7aa3c
-	GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	gss_release_buffer(&min_stat, output_token);
b7aa3c
-	GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
     }
b7aa3c
 
b7aa3c
     /* Wait for ssf request and authid */
b7aa3c
@@ -1124,14 +1151,14 @@ gssapi_server_mech_ssfreq(context_t *text,
b7aa3c
     real_input_token.value = (void *)clientin;
b7aa3c
     real_input_token.length = clientinlen;
b7aa3c
 
b7aa3c
-    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
     maj_stat = gss_unwrap(&min_stat,
b7aa3c
 			  text->gss_ctx,
b7aa3c
 			  input_token,
b7aa3c
 			  output_token,
b7aa3c
 			  NULL,
b7aa3c
 			  NULL);
b7aa3c
-    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
     if (GSS_ERROR(maj_stat)) {
b7aa3c
 	sasl_gss_seterror(text->utils, maj_stat, min_stat);
b7aa3c
@@ -1142,9 +1169,9 @@ gssapi_server_mech_ssfreq(context_t *text,
b7aa3c
     if (output_token->length < 4) {
b7aa3c
 	SETERROR(text->utils,
b7aa3c
 		 "token too short");
b7aa3c
-	GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	gss_release_buffer(&min_stat, output_token);
b7aa3c
-	GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	sasl_gss_free_context_contents(text);
b7aa3c
 	return SASL_FAIL;
b7aa3c
     }
b7aa3c
@@ -1175,9 +1202,9 @@ gssapi_server_mech_ssfreq(context_t *text,
b7aa3c
 	/* Mark that we attempted negotiation */
b7aa3c
 	oparams->mech_ssf = 2;
b7aa3c
 	if (output_token->value) {
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    gss_release_buffer(&min_stat, output_token);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	}
b7aa3c
 	sasl_gss_free_context_contents(text);
b7aa3c
 	return SASL_FAIL;
b7aa3c
@@ -1221,9 +1248,9 @@ gssapi_server_mech_ssfreq(context_t *text,
b7aa3c
 	}    
b7aa3c
     }
b7aa3c
 	
b7aa3c
-    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
     gss_release_buffer(&min_stat, output_token);
b7aa3c
-    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
     text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
b7aa3c
 
b7aa3c
@@ -1547,12 +1574,12 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 	    
b7aa3c
 	    sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
b7aa3c
 	    
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    maj_stat = gss_import_name (&min_stat,
b7aa3c
 					&name_token,
b7aa3c
 					GSS_C_NT_HOSTBASED_SERVICE,
b7aa3c
 					&text->server_name);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    
b7aa3c
 	    params->utils->free(name_token.value);
b7aa3c
 	    name_token.value = NULL;
b7aa3c
@@ -1576,9 +1603,9 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 	     * and no input from the server.  However, thanks to Imap,
b7aa3c
 	     * which discards our first output, this happens all the time.
b7aa3c
 	     * Throw away the context and try again. */
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    maj_stat = gss_delete_sec_context (&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    text->gss_ctx = GSS_C_NO_CONTEXT;
b7aa3c
 	}
b7aa3c
 
b7aa3c
@@ -1600,7 +1627,7 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 	    req_flags = req_flags |  GSS_C_DELEG_FLAG;
b7aa3c
 	}
b7aa3c
 
b7aa3c
-	GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	maj_stat = gss_init_sec_context(&min_stat,
b7aa3c
 					client_creds, /* GSS_C_NO_CREDENTIAL */
b7aa3c
 					&text->gss_ctx,
b7aa3c
@@ -1614,14 +1641,14 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 					output_token,
b7aa3c
 					&out_req_flags,
b7aa3c
 					NULL);
b7aa3c
-	GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	
b7aa3c
 	if (GSS_ERROR(maj_stat)) {
b7aa3c
 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
b7aa3c
 	    if (output_token->value) {
b7aa3c
-		GSS_LOCK_MUTEX(params->utils);
b7aa3c
+		GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		gss_release_buffer(&min_stat, output_token);
b7aa3c
-		GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+		GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    }
b7aa3c
 	    sasl_gss_free_context_contents(text);
b7aa3c
 	    return SASL_FAIL;
b7aa3c
@@ -1652,22 +1679,22 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
b7aa3c
 				      &(text->out_buf_len), *clientoutlen);
b7aa3c
 		if(ret != SASL_OK) {
b7aa3c
-		    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+		    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		    gss_release_buffer(&min_stat, output_token);
b7aa3c
-		    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+		    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		    return ret;
b7aa3c
 		}
b7aa3c
 		memcpy(text->out_buf, output_token->value, *clientoutlen);
b7aa3c
 		*clientout = text->out_buf;
b7aa3c
 	    }
b7aa3c
 	    
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    gss_release_buffer(&min_stat, output_token);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	}
b7aa3c
 	
b7aa3c
 	if (maj_stat == GSS_S_COMPLETE) {
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    maj_stat = gss_inquire_context(&min_stat,
b7aa3c
 					   text->gss_ctx,
b7aa3c
 					   &text->client_name,
b7aa3c
@@ -1678,7 +1705,7 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 					   NULL,       /* flags */
b7aa3c
 					   NULL,       /* local init */
b7aa3c
 					   NULL);      /* open */
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    
b7aa3c
 	    if (GSS_ERROR(maj_stat)) {
b7aa3c
 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
b7aa3c
@@ -1687,18 +1714,18 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 	    }
b7aa3c
 	    
b7aa3c
 	    name_token.length = 0;
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    maj_stat = gss_display_name(&min_stat,
b7aa3c
 					text->client_name,
b7aa3c
 					&name_token,
b7aa3c
 					NULL);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    
b7aa3c
 	    if (GSS_ERROR(maj_stat)) {
b7aa3c
 		if (name_token.value) {
b7aa3c
-		    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+		    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		    gss_release_buffer(&min_stat, &name_token);
b7aa3c
-		    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+		    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		}
b7aa3c
 		SETERROR(text->utils, "GSSAPI Failure");
b7aa3c
 		sasl_gss_free_context_contents(text);
b7aa3c
@@ -1719,9 +1746,9 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 					 SASL_CU_AUTHID | SASL_CU_AUTHZID,
b7aa3c
 					 oparams);
b7aa3c
 	    }
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    gss_release_buffer(&min_stat, &name_token);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    
b7aa3c
 	    if (ret != SASL_OK) return ret;
b7aa3c
 	    
b7aa3c
@@ -1747,32 +1774,32 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 	real_input_token.value = (void *) serverin;
b7aa3c
 	real_input_token.length = serverinlen;
b7aa3c
 	
b7aa3c
-	GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	maj_stat = gss_unwrap(&min_stat,
b7aa3c
 			      text->gss_ctx,
b7aa3c
 			      input_token,
b7aa3c
 			      output_token,
b7aa3c
 			      NULL,
b7aa3c
 			      NULL);
b7aa3c
-	GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	
b7aa3c
 	if (GSS_ERROR(maj_stat)) {
b7aa3c
 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
b7aa3c
-	    sasl_gss_free_context_contents(text);
b7aa3c
 	    if (output_token->value) {
b7aa3c
-		GSS_LOCK_MUTEX(params->utils);
b7aa3c
+		GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		gss_release_buffer(&min_stat, output_token);
b7aa3c
-		GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+		GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    }
b7aa3c
+	    sasl_gss_free_context_contents(text);
b7aa3c
 	    return SASL_FAIL;
b7aa3c
 	}
b7aa3c
 	
b7aa3c
 	if (output_token->length != 4) {
b7aa3c
 	    SETERROR(text->utils,
b7aa3c
 		     (output_token->length < 4) ? "token too short" : "token too long");
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    gss_release_buffer(&min_stat, output_token);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    sasl_gss_free_context_contents(text);
b7aa3c
 	    return SASL_FAIL;
b7aa3c
 	}
b7aa3c
@@ -1873,9 +1900,9 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 	    }
b7aa3c
 	}
b7aa3c
 	
b7aa3c
-	GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	gss_release_buffer(&min_stat, output_token);
b7aa3c
-	GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	
b7aa3c
 	/* oparams->user is always set, due to canon_user requirements.
b7aa3c
 	 * Make sure the client actually requested it though, by checking
b7aa3c
@@ -1921,7 +1948,7 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 	}
b7aa3c
 	((unsigned char *)input_token->value)[0] = mychoice;
b7aa3c
 	
b7aa3c
-	GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	maj_stat = gss_wrap (&min_stat,
b7aa3c
 			     text->gss_ctx,
b7aa3c
 			     0, /* Just integrity checking here */
b7aa3c
@@ -1929,7 +1956,7 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 			     input_token,
b7aa3c
 			     NULL,
b7aa3c
 			     output_token);
b7aa3c
-	GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	
b7aa3c
 	params->utils->free(input_token->value);
b7aa3c
 	input_token->value = NULL;
b7aa3c
@@ -1937,9 +1964,9 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 	if (GSS_ERROR(maj_stat)) {
b7aa3c
 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
b7aa3c
 	    if (output_token->value) {
b7aa3c
-		GSS_LOCK_MUTEX(params->utils);
b7aa3c
+		GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		gss_release_buffer(&min_stat, output_token);
b7aa3c
-		GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+		GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    }
b7aa3c
 	    sasl_gss_free_context_contents(text);
b7aa3c
 	    return SASL_FAIL;
b7aa3c
@@ -1955,18 +1982,18 @@ static int gssapi_client_mech_step(void *conn_context,
b7aa3c
 				      &(text->out_buf_len),
b7aa3c
 				      *clientoutlen);
b7aa3c
 		if (ret != SASL_OK) {
b7aa3c
-		    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+		    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		    gss_release_buffer(&min_stat, output_token);
b7aa3c
-		    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+		    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 		    return ret;
b7aa3c
 		}
b7aa3c
 		memcpy(text->out_buf, output_token->value, *clientoutlen);
b7aa3c
 		*clientout = text->out_buf;
b7aa3c
 	    }
b7aa3c
 	    
b7aa3c
-	    GSS_LOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_LOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 	    gss_release_buffer(&min_stat, output_token);
b7aa3c
-	    GSS_UNLOCK_MUTEX(params->utils);
b7aa3c
+	    GSS_UNLOCK_MUTEX_CTX(params->utils, text);
b7aa3c
 
b7aa3c
 	}
b7aa3c
 	
b7aa3c
-- 
b7aa3c
2.4.3
b7aa3c
b7aa3c