--- Begin Message ---
Stephen Frost wrote:
* Simon Wilkinson ([EMAIL PROTECTED]) 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/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/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 <[EMAIL PROTECTED]>.
*/
+#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,"[EMAIL PROTECTED]", 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,"[EMAIL PROTECTED]", 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;
}
--- 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 <[EMAIL PROTECTED]>.
*/
+#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,"[EMAIL PROTECTED]", 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,"[EMAIL PROTECTED]", 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;
}
--- End Message ---