Debian Bug report logs - #202836
Add mutexes around GSSAPI calls

version graph

Package: libsasl2; Maintainer for libsasl2 is (unknown);

Reported by: Stephen Frost <sfrost@snowman.net>

Date: Fri, 25 Jul 2003 13:48:03 UTC

Severity: wishlist

Tags: fixed, patch

Found in version 2.1.15-3

Fixed in versions cyrus-sasl-2.1/2.1.22-0~pre01, 2.1.22-0~pre04

Done: "Roberto C. Sanchez" <roberto@connexer.com>

Bug is archived. No further changes may be made.

Toggle useless messages

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to debian-bugs-dist@lists.debian.org, Dima Barsky <dima@debian.org>:
Bug#202836; Package libsasl2. Full text and rfc822 format available.

Acknowledgement sent to Stephen Frost <sfrost@snowman.net>:
New Bug report received and forwarded. Copy sent to Dima Barsky <dima@debian.org>. Full text and rfc822 format available.

Message #5 received at submit@bugs.debian.org (full text, mbox):

From: Stephen Frost <sfrost@snowman.net>
To: submit@bugs.debian.org
Subject: Add mutexes around GSSAPI calls
Date: Fri, 25 Jul 2003 09:47:45 -0400
[Message part 1 (text/plain, inline)]
Package: libsasl2
Version: 2.1.15-3
Severity: Wishlist
Tags: patch

Attached are patches for both 1.5.28 and 2.1.15 to add mutexes around
the gssapi calls.  This will fix problems with the MIT krb5 libraries
not being threadsafe.  I don't know for sure if this needs to only be
applied for the libsasl2-gssapi-mit build or for the main libsasl2
build.

There is also a patch for fixing broken buffer size negotiation in the
1.5.x series.

	Thanks,

		Stephen
[Message part 2 (message/rfc822, inline)]
From: Simon Wilkinson <simon@sxw.org.uk>
To: Stephen Frost <sfrost@snowman.net>
Subject: Re: ACL/ACI && SASL
Date: Wed, 23 Jul 2003 20:41:37 +0100
[Message part 3 (text/plain, inline)]
Stephen Frost wrote:
> * Simon Wilkinson (simon@sxw.org.uk) wrote:
> 
>>Stephen Frost wrote:
>>
>>
>>>Perhaps I missed it somewhere..  Were you able to make this patch
>>>available?  I'd really like to have it..
>>
>>Sorry, up to my eyeballs and on the wrong end of a slow modem at the 
>>moment. I'm back in civilisation at the weekend - if I've not sorted out 
>>making the patch available by Monday, please drop me a mail to remind me.
> 
> 
> Hi, just prodding you again about this.  I'm starting to think I should
> maybe just write my own. :)  Just to remind you- we were talking about
> the patch that added locks to SASL around the gssapi calls so that you
> don't have to worry about the MIT kerberos libs not being threadsafe.

Arggh. Sorry.

I've attached three patches. The first is a fix for the broken buffer 
size negotiation in the 1.5.x series - you'll encounter this if you're 
exchanging PDUs larger than 64k.

The second and third are patches to add mutexes for 1.5.28 and 2.1.15 
respectively. Bear in mind that your application needs to register mutex 
calls with the SASL library for this to work (OpenLDAP does this.)

Sorry once again about the delay.

Cheers,

Simon.
[cyrus-sasl-1.5.28-gssapibuf.patch (text/plain, inline)]
--- cyrus-sasl-1.5.28/plugins/gssapi.c.orig	Mon Apr 15 17:10:12 2002
+++ cyrus-sasl-1.5.28/plugins/gssapi.c	Mon May  5 12:34:22 2003
@@ -745,9 +745,9 @@
 	    sasldata[0] |= 4;
 	}
 
-	sasldata[1] = 0x0F; /* XXX use something non-artificial */
-	sasldata[2] = 0xFF;
-	sasldata[3] = 0xFF;
+	sasldata[1] = params->props.maxbufsize & 0xFF0000;
+	sasldata[2] = params->props.maxbufsize & 0x00FF00;
+	sasldata[3] = params->props.maxbufsize & 0x0000FF;
 	
 	real_input_token.value = (void *)sasldata;
 	real_input_token.length = 4;
@@ -790,6 +790,7 @@
     case SASL_GSSAPI_STATE_SSFREQ:
       {
 	int layerchoice;
+	unsigned peer_maxoutbuf;
 
 	real_input_token.value = (void *)clientin;
 	real_input_token.length = clientinlen;
@@ -849,12 +850,16 @@
 	    
 	    VL(("Got user %s\n",user));
 
-	    memcpy(&oparams->maxoutbuf,((char *) real_output_token.value) + 1,
-		   sizeof(unsigned));
-	    oparams->maxoutbuf = ntohl(oparams->maxoutbuf);
 	    oparams->user = user;
 	}
+	
+        peer_maxoutbuf=(((unsigned char *)output_token->value)[1]<<16)+
+	    		   (((unsigned char *)output_token->value)[2]<<8)+
+	    		    ((unsigned char *)output_token->value)[3];
 
+        oparams->maxoutbuf=peer_maxoutbuf>params->props.maxbufsize ?
+        				peer_maxoutbuf:params->props.maxbufsize;
+	
 	gss_release_buffer(&min_stat, output_token);
 	
 	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
@@ -1271,6 +1276,7 @@
 	unsigned int alen, external = params->external_ssf;
 	sasl_ssf_t need, allowed;
 	char serverhas, mychoice;
+	unsigned peer_maxoutbuf;
 
 	VL(("sasl_gss_client_step: SSFCAP\n"));
 
@@ -1341,7 +1347,13 @@
 	    sasl_gss_free_context_contents(text);
 	    return SASL_TOOWEAK;
 	}
+
+	peer_maxoutbuf=(((unsigned char *)output_token->value)[1]<<16)+
+		       (((unsigned char *)output_token->value)[2]<<8)+
+		        ((unsigned char *)output_token->value)[3];
 	
+	oparams->maxoutbuf=peer_maxoutbuf>secprops.maxbufsize?peer_maxoutbuf:secprops.maxbufsize;
+
 	gss_release_buffer(&min_stat, output_token);
 
 	if (oparams->user)
@@ -1359,13 +1371,11 @@
 	VL(("user: %s,buflen=%d\n",oparams->user,input_token->length));
 	if (oparams->user)
 	    memcpy((char *)input_token->value+4,oparams->user,alen);
-	
-	
+		
 	((unsigned char *)input_token->value)[0] = mychoice;
-	oparams->maxoutbuf = 1024; /* XXX do something real here */
-	((unsigned char *)input_token->value)[1] = 0x0F;
-	((unsigned char *)input_token->value)[2] = 0xFF;
-	((unsigned char *)input_token->value)[3] = 0xFF;
+	((unsigned char *)input_token->value)[1] = secprops.maxbufsize & 0xFF0000;
+	((unsigned char *)input_token->value)[2] = secprops.maxbufsize & 0x00FF00;
+	((unsigned char *)input_token->value)[3] = secprops.maxbufsize & 0x0000FF;
 
 	maj_stat = gss_wrap (&min_stat,
 			     text->gss_ctx,
[cyrus-sasl-1.5.28-gssapimutex.patch (text/plain, inline)]
--- cyrus-sasl-1.5.28/plugins/gssapi.c	Tue May 13 14:49:03 2003
+++ cyrus-sasl-1.5.28.sxw/plugins/gssapi.c	Sun May 11 01:44:39 2003
@@ -97,6 +97,18 @@
  * Important contributions from Sam Hartman <hartmans@fundsxpress.com>.
  */
 
+#define GSS_LOCK_MUTEX(utils)  \
+    if(((sasl_utils_t *)(utils))->mutex_lock(gss_mutex) != 0) { \
+	return SASL_FAIL; \
+    }
+
+#define GSS_UNLOCK_MUTEX(utils) \
+    if(((sasl_utils_t *)(utils))->mutex_unlock(gss_mutex) != 0) { \
+        return SASL_FAIL; \
+    }
+
+static void *gss_mutex = NULL;
+                                                                                                                                                                                                                                                  
 #define GSSAPI_VERSION (3)
 
 typedef struct context {
@@ -113,6 +125,8 @@
     sasl_realloc_t *realloc;       
     sasl_free_t *free;
 
+    const sasl_utils_t *utils;
+    
     /* layers buffering */
     char *buffer;
     int bufsize;
@@ -129,7 +143,7 @@
     SASL_GSSAPI_STATE_AUTHENTICATED = 4
 };
 
-static void
+static int
 sasl_gss_disperr(context_t *context, char **outp, 
 		 OM_uint32 code, int type)
 {
@@ -140,22 +154,29 @@
      
      msg_ctx = 0;
      while (1) {
+     	  GSS_LOCK_MUTEX(context->utils);
 	  maj_stat = gss_display_status(&min_stat, code,
 				       type, GSS_C_NULL_OID,
 				       &msg_ctx, &msg);
+	  GSS_UNLOCK_MUTEX(context->utils);
 	  out = context->realloc((void *) out,
 				     strlen(out) + msg.length + 3);
 	  if (out != NULL) {
 	      strcat(out, (char *) msg.value);
 	      strcat(out, "; ");
 	  }
+
+	  GSS_LOCK_MUTEX(context->utils);
 	  gss_release_buffer(&min_stat, &msg);
-	  
+	  GSS_UNLOCK_MUTEX(context->utils);	  
+
 	  if (!msg_ctx)
 	       break;
      }
 
      *outp = out;
+
+     return SASL_OK;
 }
 
 static void
@@ -193,7 +214,8 @@
   real_input_token.length = inputlen;
   
   output_token = &real_output_token;
-  
+
+  GSS_LOCK_MUTEX(text->utils);  
   maj_stat = gss_wrap (&min_stat,
 		       text->gss_ctx,
 		       privacy,
@@ -201,11 +223,15 @@
 		       input_token,
 		       NULL,
 		       output_token);
+  GSS_UNLOCK_MUTEX(text->utils);
   
   if (GSS_ERROR(maj_stat))
     {
-      if (output_token->value)
+      if (output_token->value) {
+          GSS_LOCK_MUTEX(text->utils);
 	  gss_release_buffer(&min_stat, output_token);
+	  GSS_UNLOCK_MUTEX(text->utils);
+      }
       return SASL_FAIL;
     }
 
@@ -215,7 +241,9 @@
 
       *output = text->malloc(output_token->length + 4);
       if (*output == NULL) {
+          GSS_LOCK_MUTEX(text->utils);
 	  gss_release_buffer(&min_stat, output_token);
+	  GSS_UNLOCK_MUTEX(text->utils);
 	  return SASL_NOMEM;
       }
       len = htonl(output_token->length);
@@ -227,9 +255,11 @@
       *outputlen = output_token->length + 4;
   }
 
-  if (output_token->value)
+  if (output_token->value) {
+      GSS_LOCK_MUTEX(text->utils);
       gss_release_buffer(&min_stat, output_token);
-
+      GSS_UNLOCK_MUTEX(text->utils);
+  }
   return SASL_OK;
 }
 
@@ -317,17 +347,22 @@
   
     output_token = &real_output_token;
     
+    GSS_LOCK_MUTEX(text->utils);
     maj_stat = gss_unwrap (&min_stat,
 			   text->gss_ctx,
 			   input_token,
 			   output_token,
 			   NULL,
 			   NULL);
+    GSS_UNLOCK_MUTEX(text->utils);
     
     if (GSS_ERROR(maj_stat))
     {
-	if (output_token->value)
-	    gss_release_buffer(&min_stat, output_token);
+	if (output_token->value) {
+	    GSS_LOCK_MUTEX(text->utils);
+	    gss_release_buffer(&min_stat, output_token);
+	    GSS_UNLOCK_MUTEX(text->utils);
+	}
 	return SASL_FAIL;
     }
 
@@ -336,8 +371,11 @@
     if (output_token->value) {
 	if (output)
 	    *output = output_token->value;
-	else
+	else {
+	    GSS_LOCK_MUTEX(text->utils);
 	    gss_release_buffer(&min_stat, output_token);
+	    GSS_UNLOCK_MUTEX(text->utils);
+	}
     }
 
     /* reset for the next packet */
@@ -376,6 +414,7 @@
     text->cursize = 0;
     text->size = 0;
     text->needsize = 4;
+    text->utils = params->utils;
 }
 
 static void
@@ -389,6 +428,7 @@
     text->cursize = 0;
     text->size = 0;
     text->needsize = 4;
+    text->utils = params->utils;
 }
 
 static int 
@@ -423,6 +463,8 @@
 {
   OM_uint32 maj_stat, min_stat;
   
+  GSS_LOCK_MUTEX(text->utils);
+ 
   if (text->gss_ctx != GSS_C_NO_CONTEXT) {
     maj_stat = gss_delete_sec_context (&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER);
     text->gss_ctx = GSS_C_NO_CONTEXT;
@@ -443,6 +485,8 @@
     text->server_creds = GSS_C_NO_CREDENTIAL;
   }
 
+  GSS_UNLOCK_MUTEX(text->utils);
+  
   /* if we've allocated space for decryption, free it */
   if (text->buffer) {
       text->free(text->buffer);
@@ -461,6 +505,10 @@
 static void 
 sasl_gss_free(void *global_context, sasl_utils_t *utils)
 {
+  if (gss_mutex) {
+    utils->mutex_dispose(gss_mutex);
+    gss_mutex=NULL;
+  }
   utils->free(global_context);
 }
 
@@ -512,11 +560,13 @@
 	    }
 	  sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
 	  
+	  GSS_LOCK_MUTEX(params->utils);
 	  maj_stat = gss_import_name (&min_stat,
 				      &name_token,
 				      GSS_C_NT_HOSTBASED_SERVICE,
 				      &text->server_name);
-	  
+	  GSS_UNLOCK_MUTEX(params->utils);
+
 	  params->utils->free(name_token.value);
 	  name_token.value = NULL;
 	  
@@ -528,10 +578,13 @@
 	  }
 
 	  if ( text->server_creds != GSS_C_NO_CREDENTIAL) {
-	      maj_stat = gss_release_cred(&min_stat, &text->server_creds);	  
+	      GSS_LOCK_MUTEX(params->utils);
+	      maj_stat = gss_release_cred(&min_stat, &text->server_creds);
+	      GSS_UNLOCK_MUTEX(params->utils);
 	      text->server_creds = GSS_C_NO_CREDENTIAL;
 	  }
 
+	  GSS_LOCK_MUTEX(params->utils);
 	  maj_stat = gss_acquire_cred(&min_stat, 
 				      text->server_name,
 				      GSS_C_INDEFINITE, 
@@ -540,6 +593,7 @@
 				      &text->server_creds, 
 				      NULL, 
 				      NULL);
+	  GSS_UNLOCK_MUTEX(params->utils);
 	  
 	  if (GSS_ERROR(maj_stat)) {
 	      sasl_gss_set_error(text, errstr, "gss_acquire_cred",
@@ -557,6 +611,7 @@
       
       VL(("sasl_gss_server_step: AUTHNEG\n"));
 
+      GSS_LOCK_MUTEX(params->utils);
       maj_stat =
 	gss_accept_sec_context (&min_stat,
 				&(text->gss_ctx),
@@ -569,12 +624,15 @@
 				NULL,
 				NULL,
 				NULL);
+      GSS_UNLOCK_MUTEX(params->utils);
       
       if (GSS_ERROR(maj_stat)) {
 	  sasl_gss_set_error(text, errstr, "gss_accept_sec_context",
 			     maj_stat, min_stat);
 	  if (output_token->value) {
+	      GSS_LOCK_MUTEX(params->utils);
 	      gss_release_buffer(&min_stat, output_token);
+	      GSS_UNLOCK_MUTEX(params->utils);
 	  }
 
 	  sasl_gss_free_context_contents(text);
@@ -586,8 +644,11 @@
       if (output_token->value) {
 	  if (serverout)
 	      *serverout = output_token->value;
-	  else
+	  else {
+	      GSS_LOCK_MUTEX(params->utils);
 	      gss_release_buffer(&min_stat, output_token);
+	      GSS_UNLOCK_MUTEX(params->utils);
+	  }
       }
 
       
@@ -617,11 +678,13 @@
 	
 	/* We ignore whatever the client sent us at this stage */
 
+        GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_display_name (&min_stat,
 				     text->client_name,
 				     &name_token,
 				     NULL);
-
+	GSS_UNLOCK_MUTEX(params->utils);
+	
 	if (GSS_ERROR(maj_stat)) {
 	    sasl_gss_set_error(text, errstr, "gss_display_name",
 			       maj_stat, min_stat);
@@ -629,10 +692,16 @@
 	    if (name_without_realm.value)
 	      params->utils->free(name_without_realm.value);
 
-	    if (name_token.value)
+	    if (name_token.value) {
+	        GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, &name_token);
-	    if (without)
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
+	    if (without) {
+	        GSS_LOCK_MUTEX(params->utils);
 		gss_release_name(&min_stat, &without);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    sasl_gss_free_context_contents(text);
 	    return SASL_BADAUTH;
 	}
@@ -654,46 +723,65 @@
 
 	    name_without_realm.length = nlen;
 
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_import_name (&min_stat,
 					&name_without_realm,
 					GSS_C_NULL_OID,
 					&without);
+	    GSS_UNLOCK_MUTEX(params->utils);
+	    
 	    if (GSS_ERROR(maj_stat)) {
 		sasl_gss_set_error(text, errstr, "gss_display_name",
 				   maj_stat, min_stat);
 		params->utils->free(name_without_realm.value);
-		if (name_token.value)
+		if (name_token.value) {
+		    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_buffer(&min_stat, &name_token);
-		if (without)
+		    GSS_UNLOCK_MUTEX(params->utils);
+		}
+		if (without) {
+		    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_name(&min_stat, &without);
+		    GSS_UNLOCK_MUTEX(params->utils);
+		}
 		sasl_gss_free_context_contents(text);
 		return SASL_BADAUTH;
 	    }
 
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_compare_name(&min_stat,
 					text->client_name,
 					without,
-					&equal);
-    
+					&equal);    
+    	    GSS_UNLOCK_MUTEX(params->utils);
+    	    
 	    if (GSS_ERROR(maj_stat)) {
 		sasl_gss_set_error(text, errstr, "gss_display_name",
 				   maj_stat, min_stat);
 		params->utils->free(name_without_realm.value);
-		if (name_token.value)
+		if (name_token.value) {
+		    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_buffer(&min_stat, &name_token);
-		if (without)
+		    GSS_UNLOCK_MUTEX(params->utils);
+		}
+		if (without) {
+		    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_name(&min_stat, &without);
+		    GSS_UNLOCK_MUTEX(params->utils);
+		}
 		sasl_gss_free_context_contents(text);
 		return SASL_BADAUTH;
 	    }
 
+	    GSS_LOCK_MUTEX(params->utils);
 	    gss_release_name(&min_stat,&without);
-
+            GSS_UNLOCK_MUTEX(params->utils);
+            
 	} else {
 	    equal = 0;
 	}
 
-	if (equal == 1) /* xxx True doesn't seem to exist in gssapi.h */
+	if (equal)
 	{
 	    oparams->authid = 
 		(char *)params->utils->malloc(name_without_realm.length+1);
@@ -716,10 +804,15 @@
 	}
 	
 
-	if (name_token.value)
+	if (name_token.value) {
+	    GSS_LOCK_MUTEX(params->utils);
+	    gss_release_buffer(&min_stat,&name_token);
+	    GSS_UNLOCK_MUTEX(params->utils);
+	}
+
+	if (name_without_realm.value) {
 	    params->utils->free(name_without_realm.value);
-	if (name_without_realm.value)
-	    gss_release_buffer(&min_stat, &name_token);
+        }
 	
 	/* we have to decide what sort of encryption/integrity/etc.,
 	   we support */
@@ -752,6 +845,7 @@
 	real_input_token.value = (void *)sasldata;
 	real_input_token.length = 4;
 	
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_wrap (&min_stat,
 			     text->gss_ctx,
 			     0, /* Just integrity checking here */
@@ -759,12 +853,16 @@
 			     input_token,
 			     NULL,
 			     output_token);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	if (GSS_ERROR(maj_stat)) {
 	    sasl_gss_set_error(text, errstr, "gss_wrap",
 			       maj_stat, min_stat);
-	    if (output_token->value)
+	    if (output_token->value) {
+	        GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    sasl_gss_free_context_contents(text);
 	    return SASL_FAIL;
 	}
@@ -775,8 +873,11 @@
         if (output_token->value) {
 	    if (serverout)
 	        *serverout = output_token->value;
-	    else
+	    else {
+	        GSS_LOCK_MUTEX(params->utils);
 	        gss_release_buffer(&min_stat, output_token);
+	        GSS_UNLOCK_MUTEX(params->utils);
+	    }
         }
 
 	VL(("Sending %d bytes (ssfcap) to client\n",*serveroutlen));
@@ -795,12 +896,14 @@
 	real_input_token.value = (void *)clientin;
 	real_input_token.length = clientinlen;
 	
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_unwrap (&min_stat,
 			       text->gss_ctx,
 			       input_token,
 			       output_token,
 			       NULL,
 			       NULL);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	if (GSS_ERROR(maj_stat)) {
 	    sasl_gss_set_error(text, errstr, "gss_unwrap",
@@ -829,8 +932,11 @@
 	    params->utils->log(params->utils->conn, SASL_LOG_WARNING,
 			       "GSSAPI", SASL_FAIL, 0, 
 		    "protocol violation: client requested invalid layer");
-	    if (output_token->value)
+	    if (output_token->value) {
+	        GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    sasl_gss_free_context_contents(text);
 	    return SASL_FAIL;
 	}
@@ -860,7 +966,9 @@
         oparams->maxoutbuf=peer_maxoutbuf>params->props.maxbufsize ?
         				peer_maxoutbuf:params->props.maxbufsize;
 	
+	GSS_LOCK_MUTEX(params->utils);
 	gss_release_buffer(&min_stat, output_token);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
 
@@ -943,6 +1051,13 @@
     *plugcount = 1;  
     *out_version = GSSAPI_VERSION;
 
+    if (!gss_mutex) {
+       gss_mutex = utils->mutex_new();
+       if (!gss_mutex) {
+           return SASL_FAIL;
+       }
+    }
+    
     return SASL_OK;
 }
 
@@ -1199,10 +1314,13 @@
 	      return SASL_FAIL;
 	    sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
 	    VL(("name: %s\n",(char *)name_token.value)); /* */
+
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_import_name (&min_stat,
 					&name_token,
 					GSS_C_NT_HOSTBASED_SERVICE,
 					&text->server_name);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    
 	    params->utils->free(name_token.value);
 	    name_token.value = NULL;
@@ -1225,10 +1343,13 @@
             * and no input from the server.  However, thanks to Imap,
             * which discards our first output, this happens all the time.
             * Throw away the context and try again. */
+           GSS_LOCK_MUTEX(params->utils);
            maj_stat = gss_delete_sec_context (&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER);
+           GSS_UNLOCK_MUTEX(params->utils);
            text->gss_ctx = GSS_C_NO_CONTEXT;
          }
 
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat =
 	  gss_init_sec_context(&min_stat,
 			       GSS_C_NO_CREDENTIAL,
@@ -1243,11 +1364,15 @@
 			       output_token,
 			       NULL,
 			       NULL);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	if (GSS_ERROR(maj_stat))
 	  {
-	    if (output_token->value)
+	    if (output_token->value) {
+	        GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    sasl_gss_free_context_contents(text);
 	    return SASL_FAIL;
 	  }
@@ -1257,8 +1382,11 @@
         if (output_token->value) {
 	    if (clientout)
 	        *clientout = output_token->value;
-	    else
+	    else {
+	    	GSS_LOCK_MUTEX(params->utils);
 	        gss_release_buffer(&min_stat, output_token);
+	        GSS_UNLOCK_MUTEX(params->utils);
+	    }
         }
 
 	if (maj_stat == GSS_S_COMPLETE)
@@ -1283,17 +1411,22 @@
 	real_input_token.value = (void *) serverin;
 	real_input_token.length = serverinlen;
 
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_unwrap (&min_stat,
 			       text->gss_ctx,
 			       input_token,
 			       output_token,
 			       NULL,
 			       NULL);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	if (GSS_ERROR(maj_stat)) {
 	    sasl_gss_free_context_contents(text);
-	    if (output_token->value)
+	    if (output_token->value) {
+	        GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    return SASL_FAIL;
 	}
 	
@@ -1354,7 +1487,9 @@
 	
 	oparams->maxoutbuf=peer_maxoutbuf>secprops.maxbufsize?peer_maxoutbuf:secprops.maxbufsize;
 
+        GSS_LOCK_MUTEX(params->utils);
 	gss_release_buffer(&min_stat, output_token);
+	GSS_UNLOCK_MUTEX(params->utils);
 
 	if (oparams->user)
 		alen = strlen(oparams->user);
@@ -1377,6 +1512,7 @@
 	((unsigned char *)input_token->value)[2] = secprops.maxbufsize & 0x00FF00;
 	((unsigned char *)input_token->value)[3] = secprops.maxbufsize & 0x0000FF;
 
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_wrap (&min_stat,
 			     text->gss_ctx,
 			     0, /* Just integrity checking here */
@@ -1384,14 +1520,18 @@
 			     input_token,
 			     NULL,
 			     output_token);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	params->utils->free(input_token->value);
 	input_token->value = NULL;
 	
 	if (GSS_ERROR(maj_stat))
 	  {
-	    if (output_token->value)
+	    if (output_token->value) {
+	    	GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    sasl_gss_free_context_contents(text);
 	    return SASL_FAIL;
 	  }
@@ -1401,8 +1541,11 @@
         if (output_token->value) {
 	    if (clientout)
 	        *clientout = output_token->value;
-	    else
+	    else {
+	        GSS_LOCK_MUTEX(params->utils);
 	        gss_release_buffer(&min_stat, output_token);
+	        GSS_UNLOCK_MUTEX(params->utils);
+	    }
         }
 	
 	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
@@ -1457,5 +1600,12 @@
   *plugcount=1;
   *out_version=GSSAPI_VERSION;
 
+  if(!gss_mutex) {
+    gss_mutex = utils->mutex_new();
+    if(!gss_mutex) {
+      return SASL_FAIL;
+    }
+  }                                          
+                                           
   return SASL_OK;
 }
[cyrus-sasl-2.1.15-gssapimutex.patch (text/plain, inline)]
--- plugins/gssapi.c	2003-07-02 14:13:42.000000000 +0100
+++ plugins/gssapi.c.mutex	2003-07-17 13:56:53.000000000 +0100
@@ -106,6 +106,18 @@
  * Important contributions from Sam Hartman <hartmans@fundsxpress.com>.
  */
 
+#define GSS_LOCK_MUTEX(utils)  \
+    if(((sasl_utils_t *)(utils))->mutex_lock(gss_mutex) != 0) { \
+       return SASL_FAIL; \
+    }
+
+#define GSS_UNLOCK_MUTEX(utils) \
+    if(((sasl_utils_t *)(utils))->mutex_unlock(gss_mutex) != 0) { \
+        return SASL_FAIL; \
+    }
+
+static void *gss_mutex = NULL;
+
 typedef struct context {
     int state;
     
@@ -147,7 +159,7 @@
     SASL_GSSAPI_STATE_AUTHENTICATED = 4
 };
 
-static void
+static int
 sasl_gss_seterror(const sasl_utils_t *utils, OM_uint32 maj, OM_uint32 min)
 {
     OM_uint32 maj_stat, min_stat;
@@ -158,25 +170,27 @@
     size_t len, curlen = 0;
     const char prefix[] = "GSSAPI Error: ";
     
-    if(!utils) return;
+    if(!utils) return SASL_OK;
     
     len = sizeof(prefix);
     ret = _plug_buf_alloc(utils, &out, &curlen, 256);
-    if(ret != SASL_OK) return;
+    if(ret != SASL_OK) return SASL_OK;
     
     strcpy(out, prefix);
     
     msg_ctx = 0;
     while (1) {
+	GSS_LOCK_MUTEX(utils);
 	maj_stat = gss_display_status(&min_stat, maj,
 				      GSS_C_GSS_CODE, GSS_C_NULL_OID,
 				      &msg_ctx, &msg);
+	GSS_UNLOCK_MUTEX(utils);
 	if(GSS_ERROR(maj_stat)) {
 	    utils->seterror(utils->conn, 0,
 			    "GSSAPI Failure "
 			    "(could not get major error message)");
 	    utils->free(out);
-	    return;
+	    return SASL_OK;
 	}
 	
 	len += len + msg.length;
@@ -184,12 +198,14 @@
 	
 	if(ret != SASL_OK) {
 	    utils->free(out);
-	    return;
+	    return SASL_OK;
 	}
 	
 	strcat(out, msg.value);
 	
+	GSS_LOCK_MUTEX(utils);
 	gss_release_buffer(&min_stat, &msg);
+	GSS_UNLOCK_MUTEX(utils);
 	
 	if (!msg_ctx)
 	    break;
@@ -201,22 +217,24 @@
     ret = _plug_buf_alloc(utils, &out, &curlen, len);
     if(ret != SASL_OK) {
 	utils->free(out);
-	return;
+	return SASL_OK;
     }
     
     strcat(out, " (");
     
     msg_ctx = 0;
     while (1) {
+	GSS_LOCK_MUTEX(utils);
 	maj_stat = gss_display_status(&min_stat, min,
 				      GSS_C_MECH_CODE, GSS_C_NULL_OID,
 				      &msg_ctx, &msg);
+	GSS_UNLOCK_MUTEX(utils);
 	if(GSS_ERROR(maj_stat)) {
 	    utils->seterror(utils->conn, 0,
 			    "GSSAPI Failure "
 			    "(could not get minor error message)");
 	    utils->free(out);
-	    return;
+	    return SASL_OK;
 	}
 	
 	len += len + msg.length;
@@ -224,12 +242,14 @@
 	
 	if(ret != SASL_OK) {
 	    utils->free(out);
-	    return;
+	    return SASL_OK;
 	}
 	
 	strcat(out, msg.value);
 	
+	GSS_LOCK_MUTEX(utils);
 	gss_release_buffer(&min_stat, &msg);
+	GSS_UNLOCK_MUTEX(utils);
 	
 	if (!msg_ctx)
 	    break;
@@ -239,13 +259,16 @@
     ret = _plug_buf_alloc(utils, &out, &curlen, len);
     if(ret != SASL_OK) {
 	utils->free(out);
-	return;
+	return SASL_OK;
     }
     
     strcat(out, ")");
     
     utils->seterror(utils->conn, 0, out);
     utils->free(out);
+
+    return SASL_OK;
+
 }
 
 static int 
@@ -282,6 +305,7 @@
     output_token->value = NULL;
     output_token->length = 0;
     
+    GSS_LOCK_MUTEX(text->utils);
     maj_stat = gss_wrap (&min_stat,
 			 text->gss_ctx,
 			 privacy,
@@ -289,12 +313,16 @@
 			 input_token,
 			 NULL,
 			 output_token);
+    GSS_UNLOCK_MUTEX(text->utils);
     
     if (GSS_ERROR(maj_stat))
 	{
 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
-	    if (output_token->value)
+	    if (output_token->value) {
+		GSS_LOCK_MUTEX(text->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(text->utils);
+	    }
 	    return SASL_FAIL;
 	}
     
@@ -305,7 +333,9 @@
 			      &(text->encode_buf_len), output_token->length + 4);
 	
 	if (ret != SASL_OK) {
+	    GSS_LOCK_MUTEX(text->utils);
 	    gss_release_buffer(&min_stat, output_token);
+	    GSS_UNLOCK_MUTEX(text->utils);
 	    return ret;
 	}
 	
@@ -320,9 +350,11 @@
     
     *output = text->encode_buf;
     
-    if (output_token->value)
+    if (output_token->value) {
+	GSS_LOCK_MUTEX(text->utils);
 	gss_release_buffer(&min_stat, output_token);
-    
+	GSS_UNLOCK_MUTEX(text->utils);
+    } 
     return SASL_OK;
 }
 
@@ -418,18 +450,23 @@
     output_token->value = NULL;
     output_token->length = 0;
     
+    GSS_LOCK_MUTEX(text->utils);
     maj_stat = gss_unwrap (&min_stat,
 			   text->gss_ctx,
 			   input_token,
 			   output_token,
 			   NULL,
 			   NULL);
+    GSS_UNLOCK_MUTEX(text->utils);
     
     if (GSS_ERROR(maj_stat))
 	{
 	    sasl_gss_seterror(text->utils,maj_stat,min_stat);
-	    if (output_token->value)
+	    if (output_token->value) {
+		GSS_LOCK_MUTEX(text->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(text->utils);
+	    }
 	    return SASL_FAIL;
 	}
     
@@ -442,13 +479,17 @@
 				     &text->decode_once_buf_len,
 				     *outputlen);
 	    if(result != SASL_OK) {
+		GSS_LOCK_MUTEX(text->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(text->utils);
 		return result;
 	    }
 	    *output = text->decode_once_buf;
 	    memcpy(*output, output_token->value, *outputlen);
 	}
+	GSS_LOCK_MUTEX(text->utils);
 	gss_release_buffer(&min_stat, output_token);
+	GSS_UNLOCK_MUTEX(text->utils);
     }
     
     /* reset for the next packet */
@@ -489,12 +530,14 @@
     return ret;
 }
 
-static void sasl_gss_free_context_contents(context_t *text)
+static int sasl_gss_free_context_contents(context_t *text)
 {
     OM_uint32 maj_stat, min_stat;
     
-    if (!text) return;
+    if (!text) return SASL_OK;
     
+    GSS_LOCK_MUTEX(text->utils);
+
     if (text->gss_ctx != GSS_C_NO_CONTEXT) {
 	maj_stat = gss_delete_sec_context (&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER);
 	text->gss_ctx = GSS_C_NO_CONTEXT;
@@ -514,6 +557,8 @@
 	maj_stat = gss_release_cred(&min_stat, &text->server_creds);
 	text->server_creds = GSS_C_NO_CREDENTIAL;
     }
+
+    GSS_UNLOCK_MUTEX(text->utils);
     
     if (text->out_buf) {
 	text->utils->free(text->out_buf);
@@ -550,12 +595,19 @@
 	text->utils->free(text->authid);
 	text->authid = NULL;
     }
+
+    return SASL_OK;
+
 }
 
 static void gssapi_common_mech_dispose(void *conn_context,
 				       const sasl_utils_t *utils)
 {
     sasl_gss_free_context_contents((context_t *)(conn_context));
+    if (gss_mutex) {
+      utils->mutex_free(gss_mutex);
+      gss_mutex=NULL;
+    }
     utils->free(conn_context);
 }
 
@@ -629,10 +681,12 @@
 	    }
 	    sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
 	    
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_import_name (&min_stat,
 					&name_token,
 					GSS_C_NT_HOSTBASED_SERVICE,
 					&text->server_name);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    
 	    params->utils->free(name_token.value);
 	    name_token.value = NULL;
@@ -644,10 +698,13 @@
 	    }
 	    
 	    if ( text->server_creds != GSS_C_NO_CREDENTIAL) {
+	    	GSS_LOCK_MUTEX(params->utils);
 		maj_stat = gss_release_cred(&min_stat, &text->server_creds);
+	    	GSS_UNLOCK_MUTEX(params->utils);
 		text->server_creds = GSS_C_NO_CREDENTIAL;
 	    }
 	    
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_acquire_cred(&min_stat, 
 					text->server_name,
 					GSS_C_INDEFINITE, 
@@ -656,6 +713,7 @@
 					&text->server_creds, 
 					NULL, 
 					NULL);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    
 	    if (GSS_ERROR(maj_stat)) {
 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
@@ -669,6 +727,7 @@
 	    real_input_token.length = clientinlen;
 	}
 	
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat =
 	    gss_accept_sec_context(&min_stat,
 				   &(text->gss_ctx),
@@ -681,10 +740,13 @@
 				   NULL,
 				   NULL,
 				   NULL);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	if (GSS_ERROR(maj_stat)) {
 	    if (output_token->value) {
+		GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
 	    }
 	    text->utils->seterror(text->utils->conn, SASL_NOLOG, "GSSAPI Failure: gss_accept_sec_context");
 	    text->utils->log(NULL, SASL_LOG_DEBUG, "GSSAPI Failure: gss_accept_sec_context");
@@ -699,14 +761,18 @@
 		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
 				      &(text->out_buf_len), *serveroutlen);
 		if(ret != SASL_OK) {
+		    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_buffer(&min_stat, output_token);
+		    GSS_UNLOCK_MUTEX(params->utils);
 		    return ret;
 		}
 		memcpy(text->out_buf, output_token->value, *serveroutlen);
 		*serverout = text->out_buf;
 	    }
 	    
+	    GSS_LOCK_MUTEX(params->utils);
 	    gss_release_buffer(&min_stat, output_token);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	} else {
 	    /* No output token, send an empty string */
 	    *serverout = GSSAPI_BLANK_STRING;
@@ -732,19 +798,27 @@
 	
 	/* We ignore whatever the client sent us at this stage */
 	
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_display_name (&min_stat,
 				     text->client_name,
 				     &name_token,
 				     NULL);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	if (GSS_ERROR(maj_stat)) {
 	    if (name_without_realm.value)
 		params->utils->free(name_without_realm.value);
 	    
-	    if (name_token.value)
+	    if (name_token.value) {
+		GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, &name_token);
-	    if (without)
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
+	    if (without) {
+		GSS_LOCK_MUTEX(params->utils);
 		gss_release_name(&min_stat, &without);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    SETERROR(text->utils, "GSSAPI Failure");
 	    sasl_gss_free_context_contents(text);
 	    return SASL_BADAUTH;
@@ -770,6 +844,7 @@
 	    
 	    name_without_realm.length = strlen( (char *) name_without_realm.value );
 	    
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_import_name (&min_stat,
 					&name_without_realm,
 	    /* Solaris 8/9 gss_import_name doesn't accept GSS_C_NULL_OID here,
@@ -780,35 +855,53 @@
 					GSS_C_NULL_OID,
 #endif
 					&without);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    
 	    if (GSS_ERROR(maj_stat)) {
 		params->utils->free(name_without_realm.value);
-		if (name_token.value)
+		if (name_token.value) {
+	    	    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_buffer(&min_stat, &name_token);
-		if (without)
+	    	    GSS_UNLOCK_MUTEX(params->utils);
+		}
+		if (without) {
+	    	    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_name(&min_stat, &without);
+	    	    GSS_UNLOCK_MUTEX(params->utils);
+		}
 		SETERROR(text->utils, "GSSAPI Failure");
 		sasl_gss_free_context_contents(text);
 		return SASL_BADAUTH;
 	    }
 	    
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_compare_name(&min_stat,
 					text->client_name,
 					without,
 					&equal);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    
 	    if (GSS_ERROR(maj_stat)) {
 		params->utils->free(name_without_realm.value);
-		if (name_token.value)
+		if (name_token.value) {
+	    	    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_buffer(&min_stat, &name_token);
-		if (without)
+	    	    GSS_UNLOCK_MUTEX(params->utils);
+		}
+		if (without) {
+	    	    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_name(&min_stat, &without);
+	    	    GSS_UNLOCK_MUTEX(params->utils);
+		}
 		SETERROR(text->utils, "GSSAPI Failure");
 		sasl_gss_free_context_contents(text);
 		return SASL_BADAUTH;
 	    }
 	    
+	    GSS_LOCK_MUTEX(params->utils);
 	    gss_release_name(&min_stat,&without);
+	    GSS_UNLOCK_MUTEX(params->utils);
+
 	} else {
 	    equal = 0;
 	}
@@ -829,11 +922,14 @@
 	    }
 	}
 	
-	if (name_token.value)
+	if (name_token.value) {
+	    GSS_LOCK_MUTEX(params->utils);
 	    gss_release_buffer(&min_stat, &name_token);
-	if (name_without_realm.value)
+	    GSS_UNLOCK_MUTEX(params->utils);
+	}
+	if (name_without_realm.value) {
 	    params->utils->free(name_without_realm.value);
-	
+	}	
 	
 	/* we have to decide what sort of encryption/integrity/etc.,
 	   we support */
@@ -880,6 +976,7 @@
 	real_input_token.value = (void *)sasldata;
 	real_input_token.length = 4;
 	
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_wrap(&min_stat,
 			    text->gss_ctx,
 			    0, /* Just integrity checking here */
@@ -887,11 +984,15 @@
 			    input_token,
 			    NULL,
 			    output_token);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	if (GSS_ERROR(maj_stat)) {
 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
-	    if (output_token->value)
+	    if (output_token->value) {
+		GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    sasl_gss_free_context_contents(text);
 	    return SASL_FAIL;
 	}
@@ -904,14 +1005,18 @@
 		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
 				      &(text->out_buf_len), *serveroutlen);
 		if(ret != SASL_OK) {
+		    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_buffer(&min_stat, output_token);
+		    GSS_UNLOCK_MUTEX(params->utils);
 		    return ret;
 		}
 		memcpy(text->out_buf, output_token->value, *serveroutlen);
 		*serverout = text->out_buf;
 	    }
 	    
+	    GSS_LOCK_MUTEX(params->utils);
 	    gss_release_buffer(&min_stat, output_token);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	}
 	
 	/* Wait for ssf request and authid */
@@ -926,12 +1031,14 @@
 	real_input_token.value = (void *)clientin;
 	real_input_token.length = clientinlen;
 	
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_unwrap(&min_stat,
 			      text->gss_ctx,
 			      input_token,
 			      output_token,
 			      NULL,
 			      NULL);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	if (GSS_ERROR(maj_stat)) {
 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
@@ -960,8 +1067,11 @@
 		     "protocol violation: client requested invalid layer");
 	    /* Mark that we attempted negotiation */
 	    oparams->mech_ssf = 2;
-	    if (output_token->value)
+	    if (output_token->value) {
+		GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    sasl_gss_free_context_contents(text);
 	    return SASL_FAIL;
 	}
@@ -1004,7 +1114,9 @@
 	} else {
 	    SETERROR(text->utils,
 		     "token too short");
+	    GSS_LOCK_MUTEX(params->utils);
 	    gss_release_buffer(&min_stat, output_token);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    sasl_gss_free_context_contents(text);
 	    return SASL_FAIL;
 	}	
@@ -1020,7 +1132,9 @@
 	    oparams->maxoutbuf -= 50;
 	}
 	
+	GSS_LOCK_MUTEX(params->utils);
 	gss_release_buffer(&min_stat, output_token);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
 	
@@ -1113,6 +1227,13 @@
     *out_version = SASL_SERVER_PLUG_VERSION;
     *pluglist = gssapi_server_plugins;
     *plugcount = 1;  
+
+    if (!gss_mutex) {
+       gss_mutex = utils->mutex_alloc();
+       if (!gss_mutex) {
+           return SASL_FAIL;
+       }
+    }
     
     return SASL_OK;
 }
@@ -1220,10 +1341,12 @@
 	    
 	    sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN);
 	    
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_import_name (&min_stat,
 					&name_token,
 					GSS_C_NT_HOSTBASED_SERVICE,
 					&text->server_name);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    
 	    params->utils->free(name_token.value);
 	    name_token.value = NULL;
@@ -1247,7 +1370,9 @@
 	     * and no input from the server.  However, thanks to Imap,
 	     * which discards our first output, this happens all the time.
 	     * Throw away the context and try again. */
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_delete_sec_context (&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    text->gss_ctx = GSS_C_NO_CONTEXT;
 	}
 	    
@@ -1262,6 +1387,7 @@
 	    }
 	}
 	
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_init_sec_context(&min_stat,
 					GSS_C_NO_CREDENTIAL,
 					&text->gss_ctx,
@@ -1275,11 +1401,15 @@
 					output_token,
 					&out_req_flags,
 					NULL);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	if (GSS_ERROR(maj_stat)) {
 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
-	    if (output_token->value)
+	    if (output_token->value) {
+		GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    sasl_gss_free_context_contents(text);
 	    return SASL_FAIL;
 	}
@@ -1291,17 +1421,22 @@
 		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
 				      &(text->out_buf_len), *clientoutlen);
 		if(ret != SASL_OK) {
+		    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_buffer(&min_stat, output_token);
+		    GSS_UNLOCK_MUTEX(params->utils);
 		    return ret;
 		}
 		memcpy(text->out_buf, output_token->value, *clientoutlen);
 		*clientout = text->out_buf;
 	    }
 	    
+	    GSS_LOCK_MUTEX(params->utils);
 	    gss_release_buffer(&min_stat, output_token);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	}
 	
 	if (maj_stat == GSS_S_COMPLETE) {
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_inquire_context(&min_stat,
 					   text->gss_ctx,
 					   &text->client_name,
@@ -1311,6 +1446,7 @@
 					   NULL,       /* flags */
 					   NULL,       /* local init */
 					   NULL);      /* open */
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    
 	    if (GSS_ERROR(maj_stat)) {
 		sasl_gss_seterror(text->utils, maj_stat, min_stat);
@@ -1319,14 +1455,19 @@
 	    }
 	    
 	    name_token.length = 0;
+	    GSS_LOCK_MUTEX(params->utils);
 	    maj_stat = gss_display_name(&min_stat,
 					text->client_name,
 					&name_token,
 					NULL);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    
 	    if (GSS_ERROR(maj_stat)) {
-		if (name_token.value)
+		if (name_token.value) {
+		    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_buffer(&min_stat, &name_token);
+		    GSS_UNLOCK_MUTEX(params->utils);
+		}
 		SETERROR(text->utils, "GSSAPI Failure");
 		sasl_gss_free_context_contents(text);
 		return SASL_FAIL;
@@ -1346,7 +1487,9 @@
 					 SASL_CU_AUTHID | SASL_CU_AUTHZID,
 					 oparams);
 	    }
+	    GSS_LOCK_MUTEX(params->utils);
 	    gss_release_buffer(&min_stat, &name_token);
+	    GSS_UNLOCK_MUTEX(params->utils);
 	    
 	    if (ret != SASL_OK) return ret;
 	    
@@ -1365,18 +1508,23 @@
 	real_input_token.value = (void *) serverin;
 	real_input_token.length = serverinlen;
 	
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_unwrap(&min_stat,
 			      text->gss_ctx,
 			      input_token,
 			      output_token,
 			      NULL,
 			      NULL);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	if (GSS_ERROR(maj_stat)) {
 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
 	    sasl_gss_free_context_contents(text);
-	    if (output_token->value)
+	    if (output_token->value) {
+		GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    return SASL_FAIL;
 	}
 	
@@ -1438,7 +1586,9 @@
 	    oparams->maxoutbuf -= 50;
 	}
 	
+	GSS_LOCK_MUTEX(params->utils);
 	gss_release_buffer(&min_stat, output_token);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	/* oparams->user is always set, due to canon_user requirements.
 	 * Make sure the client actually requested it though, by checking
@@ -1477,6 +1627,7 @@
         }
 	((unsigned char *)input_token->value)[0] = mychoice;
 	
+	GSS_LOCK_MUTEX(params->utils);
 	maj_stat = gss_wrap (&min_stat,
 			     text->gss_ctx,
 			     0, /* Just integrity checking here */
@@ -1484,14 +1635,18 @@
 			     input_token,
 			     NULL,
 			     output_token);
+	GSS_UNLOCK_MUTEX(params->utils);
 	
 	params->utils->free(input_token->value);
 	input_token->value = NULL;
 	
 	if (GSS_ERROR(maj_stat)) {
 	    sasl_gss_seterror(text->utils, maj_stat, min_stat);
-	    if (output_token->value)
+	    if (output_token->value) {
+		GSS_LOCK_MUTEX(params->utils);
 		gss_release_buffer(&min_stat, output_token);
+		GSS_UNLOCK_MUTEX(params->utils);
+	    }
 	    sasl_gss_free_context_contents(text);
 	    return SASL_FAIL;
 	}
@@ -1503,14 +1658,19 @@
 		ret = _plug_buf_alloc(text->utils, &(text->out_buf),
 				      &(text->out_buf_len), *clientoutlen);
 		if (ret != SASL_OK) {
+		    GSS_LOCK_MUTEX(params->utils);
 		    gss_release_buffer(&min_stat, output_token);
+		    GSS_UNLOCK_MUTEX(params->utils);
 		    return ret;
 		}
 		memcpy(text->out_buf, output_token->value, *clientoutlen);
 		*clientout = text->out_buf;
 	    }
 	    
+	    GSS_LOCK_MUTEX(params->utils);
 	    gss_release_buffer(&min_stat, output_token);
+	    GSS_UNLOCK_MUTEX(params->utils);
+
 	}
 	
 	text->state = SASL_GSSAPI_STATE_AUTHENTICATED;
@@ -1570,6 +1730,13 @@
     *out_version = SASL_CLIENT_PLUG_VERSION;
     *pluglist = gssapi_client_plugins;
     *plugcount = 1;
+
+    if(!gss_mutex) {
+      gss_mutex = utils->mutex_alloc();
+      if(!gss_mutex) {
+        return SASL_FAIL;
+      }
+    }
     
     return SASL_OK;
 }
[Message part 7 (application/pgp-signature, inline)]

Information forwarded to debian-bugs-dist@lists.debian.org, Dima Barsky <dima@debian.org>:
Bug#202836; Package libsasl2. Full text and rfc822 format available.

Acknowledgement sent to Stephen Frost <sfrost@snowman.net>:
Extra info received and forwarded to list. Copy sent to Dima Barsky <dima@debian.org>. Full text and rfc822 format available.

Message #10 received at 202836@bugs.debian.org (full text, mbox):

From: Stephen Frost <sfrost@snowman.net>
To: 202836@bugs.debian.org
Subject: (forw) [simon@sxw.org.uk: Re: ACL/ACI && SASL]
Date: Fri, 25 Jul 2003 09:54:54 -0400
[Message part 1 (text/plain, inline)]
Here is some additional information from Simon regarding the patches.

	Stephen
[Message part 2 (message/rfc822, inline)]
From: Simon Wilkinson <simon@sxw.org.uk>
To: Stephen Frost <sfrost@snowman.net>
Subject: Re: ACL/ACI && SASL
Date: Thu, 24 Jul 2003 09:55:49 +0100
Stephen Frost wrote:
> * Simon Wilkinson (simon@sxw.org.uk) wrote:
> 
>>Arggh. Sorry.
>>
>>I've attached three patches. The first is a fix for the broken buffer 
>>size negotiation in the 1.5.x series - you'll encounter this if you're 
>>exchanging PDUs larger than 64k.
>>
>>The second and third are patches to add mutexes for 1.5.28 and 2.1.15 
>>respectively. Bear in mind that your application needs to register mutex 
>>calls with the SASL library for this to work (OpenLDAP does this.)
> 
> 
> Great!  Thanks!  Are these patches under the license of the respective
> works which they modify, or no?  

Yes, they are.

> I'm going to be trying to get these
> patches incorporated at least into the Debian SASL packages.

Excellent - I keep meaning on contributing the 2.x patch back to the 
SASL folk, but haven't quite got round to it yet.

Cheers,

Simon.
[Message part 3 (application/pgp-signature, inline)]

Bug 202836 cloned as bug 202842. Request was from Stephen Frost <sfrost@snowman.net> to control@bugs.debian.org. Full text and rfc822 format available.

Tags added: fixed Request was from Henrique de Moraes Holschuh <hmh@debian.org> to control@bugs.debian.org. Full text and rfc822 format available.

Tags added: pending Request was from hartmans@mit.edu to control@bugs.debian.org. Full text and rfc822 format available.

Tags added: pending Request was from hartmans@mit.edu to control@bugs.debian.org. Full text and rfc822 format available.

Tags added: pending Request was from "Roberto C. Sanchez" <roberto@connexer.com> to control@bugs.debian.org. Full text and rfc822 format available.

Reply sent to Fabian Fagerholm <fabbe@debian.org>:
You have taken responsibility. Full text and rfc822 format available.

Notification sent to Stephen Frost <sfrost@snowman.net>:
Bug acknowledged by developer. Full text and rfc822 format available.

Message #25 received at 202836-close@bugs.debian.org (full text, mbox):

From: Fabian Fagerholm <fabbe@debian.org>
To: 202836-close@bugs.debian.org
Subject: Bug#202836: fixed in cyrus-sasl-2.1 2.1.22-0~pre01
Date: Wed, 25 Oct 2006 06:49:14 -0700
Source: cyrus-sasl-2.1
Source-Version: 2.1.22-0~pre01

We believe that the bug you reported is fixed in the latest version of
cyrus-sasl-2.1, which is due to be installed in the Debian FTP archive:

cyrus-sasl-2.1-bin_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/cyrus-sasl-2.1-bin_2.1.22-0~pre01_i386.deb
cyrus-sasl-2.1-doc_2.1.22-0~pre01_all.deb
  to pool/main/c/cyrus-sasl-2.1/cyrus-sasl-2.1-doc_2.1.22-0~pre01_all.deb
cyrus-sasl-2.1_2.1.22-0~pre01.diff.gz
  to pool/main/c/cyrus-sasl-2.1/cyrus-sasl-2.1_2.1.22-0~pre01.diff.gz
cyrus-sasl-2.1_2.1.22-0~pre01.dsc
  to pool/main/c/cyrus-sasl-2.1/cyrus-sasl-2.1_2.1.22-0~pre01.dsc
cyrus-sasl-2.1_2.1.22.orig.tar.gz
  to pool/main/c/cyrus-sasl-2.1/cyrus-sasl-2.1_2.1.22.orig.tar.gz
libsasl2-2-dev_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2-2-dev_2.1.22-0~pre01_i386.deb
libsasl2-2-modules-gssapi-mit_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2-2-modules-gssapi-mit_2.1.22-0~pre01_i386.deb
libsasl2-2-modules-otp_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2-2-modules-otp_2.1.22-0~pre01_i386.deb
libsasl2-2-modules-sql_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2-2-modules-sql_2.1.22-0~pre01_i386.deb
libsasl2-2-modules_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2-2-modules_2.1.22-0~pre01_i386.deb
libsasl2-2_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2-2_2.1.22-0~pre01_i386.deb
libsasl2-dev_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2-dev_2.1.22-0~pre01_i386.deb
libsasl2-modules-gssapi-heimdal_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2-modules-gssapi-heimdal_2.1.22-0~pre01_i386.deb
libsasl2-modules-sql_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2-modules-sql_2.1.22-0~pre01_i386.deb
libsasl2-modules_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2-modules_2.1.22-0~pre01_i386.deb
libsasl2_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/libsasl2_2.1.22-0~pre01_i386.deb
sasl2-bin_2.1.22-0~pre01_i386.deb
  to pool/main/c/cyrus-sasl-2.1/sasl2-bin_2.1.22-0~pre01_i386.deb



A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 202836@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Fabian Fagerholm <fabbe@debian.org> (supplier of updated cyrus-sasl-2.1 package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@debian.org)


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Format: 1.7
Date: Thu, 19 Oct 2006 23:26:02 +0300
Source: cyrus-sasl-2.1
Binary: libsasl2-2 cyrus-sasl-2.1-bin libsasl2 libsasl2-2-dev sasl2-bin libsasl2-dev libsasl2-2-modules-gssapi-mit libsasl2-modules-gssapi-heimdal libsasl2-2-modules-otp cyrus-sasl-2.1-doc libsasl2-modules-sql libsasl2-2-modules-sql libsasl2-modules libsasl2-2-modules
Architecture: source i386 all
Version: 2.1.22-0~pre01
Distribution: experimental
Urgency: low
Maintainer: Fabian Fagerholm <fabbe@debian.org>
Changed-By: Fabian Fagerholm <fabbe@debian.org>
Description: 
 cyrus-sasl-2.1-bin - Administration programs for SASL users database
 cyrus-sasl-2.1-doc - Documentation for Cyrus SASL library and utilities
 libsasl2   - Authentication abstraction library
 libsasl2-2 - Authentication abstraction library
 libsasl2-2-dev - Development files for SASL authentication abstraction library
 libsasl2-2-modules - Pluggable Authentication Modules for SASL
 libsasl2-2-modules-gssapi-mit - Pluggable Authentication Modules for SASL (GSSAPI)
 libsasl2-2-modules-otp - Pluggable Authentication Modules for SASL (OTP)
 libsasl2-2-modules-sql - Pluggable Authentication Modules for SASL (SQL)
 libsasl2-dev - Development files for SASL authentication abstraction library
 libsasl2-modules - Pluggable Authentication Modules for SASL
 libsasl2-modules-gssapi-heimdal - Pluggable Authentication Modules for SASL (GSSAPI)
 libsasl2-modules-sql - Pluggable Authentication Modules for SASL (SQL)
 sasl2-bin  - Administration programs for SASL users database
Closes: 190658 202836 205589 211156 242184 245818 248333 251735 254298 256808 257181 257306 262339 265751 274087 274402 275498 276637 276849 282775 285605 286285 287313 296449 300710 302280 310438 314724 315177 316404 321760 324288 327479 328879 332703 336485 344686 345880 348685 354413 357527 361937 362511 365183 365287 368370 379846 392571
Changes: 
 cyrus-sasl-2.1 (2.1.22-0~pre01) experimental; urgency=low
 .
   * Acknowledged previous NMUs (Closes: #274087, #344686, #362511, #245818)
     (Closes: #276637, #285605, #332703, #336485, #345880, #357527, #379846)
     (Closes: #248333, #315177, #324288, #361937, #242184, #256808, #202836)
     (Closes: #262339, #265751, #275498, #276849)
   * Fabian Fagerholm
     - Adopted package (Closes: #368370)
     - Fixed static linking against libsasl2 (Closes: #282775)
     - Exit with an error if any of the auto* commands fail. (Closes: #321760)
     - New upstream version (Closes: #316404)
       + Fixed crash with DIGEST-MD5 (Closes: #286285, #314724)
       + Built with courier authdaemon support (Closes: #328879)
       + sql plugin respects log_level settings (Closes: #296449)
     - Included a watch file (Closes: #205589)
     - Switched from Heimdal to MIT Kerberos (Closes: #257306, #310438)
     - Repackaged upstream source to remove non-free docs (Closes: #365183)
     - Added symbol versioning (Closes: #327479)
     - Document why libsasl2-modules is recommended (Closes: #302280, #365287)
     - Strip rpath from binaries and shared libraries when build inserts one.
   * Roberto C. Sanchez
     - Added myself to Uploaders field
     - Added missing Build-Depends on groff-base
     - Changed build dependency from db4.2 to db4.4 (Closes: #354413)
     - Made it so that README.configure-options is actually populated
     - Fixed debian/rules so that bogus ldconfig calls are not in post(inst|rm)
     - Added manual page for testsaslauthd(8)
     - Improved socket and pidfile location flexibility
       (Closes: #254298, #300710, #287313)
     - Changed -modules-sql to depend on -modules (Closes: #392571)
     - Put /etc/sasl at start of the config search path (Closes: #211156)
     - Split OTP plugin into its own package (Closes: #251735)
     - Made modules suggest modules-{sql,otp,gssapi-heimdal} (Closes: #348685)
     - Fixed saslauthd init script so it gives useful error (Closes: #257181)
     - Added NTLM to -modules description (Closes: #274402)
     - Added necessary config.h and Makefile to build samples (Closes: #190658)
Files: 
 1b59eac130f785c1f390d751c50eb9cb 1320 libs important cyrus-sasl-2.1_2.1.22-0~pre01.dsc
 47424be7f2f976b40de959fe821308e2 1612191 libs important cyrus-sasl-2.1_2.1.22.orig.tar.gz
 72122bac75b27fe4f82f3ff3570594ac 38623 libs important cyrus-sasl-2.1_2.1.22-0~pre01.diff.gz
 c6ec6775496cee74d1269b8c93306495 96586 doc important cyrus-sasl-2.1-doc_2.1.22-0~pre01_all.deb
 35b71f2bb85f205c043662b773a63388 96044 utils important cyrus-sasl-2.1-bin_2.1.22-0~pre01_i386.deb
 c8fe4c25365b963903a57cf8496fffed 38696 libs important sasl2-bin_2.1.22-0~pre01_i386.deb
 244106234aac3adc1d1f7e952e4d93dc 38684 oldlibs important libsasl2_2.1.22-0~pre01_i386.deb
 45ff84eb7261a35708586449da9b90a4 97556 libs important libsasl2-2_2.1.22-0~pre01_i386.deb
 fbe701feab3406f8f81463ef0e5ba4bd 38706 oldlibs important libsasl2-modules_2.1.22-0~pre01_i386.deb
 485f5b121078de5b6cc31c536fc2a6b6 144452 libs important libsasl2-2-modules_2.1.22-0~pre01_i386.deb
 1791ba0603100e48c129af5a4910669d 69586 libs optional libsasl2-2-modules-otp_2.1.22-0~pre01_i386.deb
 5ab82e92327e2971e671071fec383e1b 38714 oldlibs important libsasl2-modules-sql_2.1.22-0~pre01_i386.deb
 ae5826556e94222904e0e40bd0218df8 58720 libs optional libsasl2-2-modules-sql_2.1.22-0~pre01_i386.deb
 3b09f26d0b41be509b4fbc8305462dc7 38740 oldlibs important libsasl2-modules-gssapi-heimdal_2.1.22-0~pre01_i386.deb
 bb2afbbb23630128d7bf384cc19cb90b 60464 libs optional libsasl2-2-modules-gssapi-mit_2.1.22-0~pre01_i386.deb
 fb7d5bbba30cc041b1bf6d2da7b216f1 38706 oldlibs important libsasl2-dev_2.1.22-0~pre01_i386.deb
 407a2c1962d232bfe0125ab6aa938d5f 254872 libdevel optional libsasl2-2-dev_2.1.22-0~pre01_i386.deb

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)

iD8DBQFFN+WE76VUNpZBmeIRAiSoAJ9CwVgUjeRTu8olBC3aME1YdW3OngCfUQtr
4O8S+CUd53fCiIMCZOFcZhc=
=tnmS
-----END PGP SIGNATURE-----




Reply sent to "Roberto C. Sanchez" <roberto@connexer.com>:
You have taken responsibility. Full text and rfc822 format available.

Notification sent to Stephen Frost <sfrost@snowman.net>:
Bug acknowledged by developer. Full text and rfc822 format available.

Message #30 received at 202836-done@bugs.debian.org (full text, mbox):

From: "Roberto C. Sanchez" <roberto@connexer.com>
To: 254298-done@bugs.debian.org, 257306-done@bugs.debian.org, 274402-done@bugs.debian.org, 190658-done@bugs.debian.org, 248333-done@bugs.debian.org, 324288-done@bugs.debian.org, 242184-done@bugs.debian.org, 256808-done@bugs.debian.org, 202836-done@bugs.debian.org, 262339-done@bugs.debian.org
Subject: These bugs were closed in the now defunct cyrus-sasl-2.1 source package
Date: Tue, 28 Nov 2006 22:33:45 -0500
[Message part 1 (text/plain, inline)]
Version: 2.1.22-0~pre04

-- 
Roberto C. Sanchez
http://people.connexer.com/~roberto
http://www.connexer.com
[signature.asc (application/pgp-signature, inline)]

Bug archived. Request was from Debbugs Internal Request <owner@bugs.debian.org> to internal_control@bugs.debian.org. (Mon, 25 Jun 2007 05:25:12 GMT) Full text and rfc822 format available.

Send a report that this bug log contains spam.


Debian bug tracking system administrator <owner@bugs.debian.org>. Last modified: Wed Apr 16 14:06:40 2014; Machine Name: beach.debian.org

Debian Bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.