diff --git a/SOURCES/cyrus-sasl-2.1.26-gssapi-use-per-connection-mutex.patch b/SOURCES/cyrus-sasl-2.1.26-gssapi-use-per-connection-mutex.patch new file mode 100644 index 0000000..1b3278b --- /dev/null +++ b/SOURCES/cyrus-sasl-2.1.26-gssapi-use-per-connection-mutex.patch @@ -0,0 +1,710 @@ +From 70a144cc53d09b56aa088fa1f6d433acea31afa7 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Tue, 15 Sep 2015 12:21:22 +0300 +Subject: [PATCH] gssapi: use per-connection mutex where possible + +If the same application uses SASL GSSAPI for both client and server operations, +it may be possible to deadlock in plugins/gssapi.c due to use of a +global mutex by both client and server code. Multiple outstanding connections should +be possible, thus introduce per-context locking and use it where it +makes sense. Note that there are still multiple places where context is +not available and where a global lock should be in use. + +Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1263017 +--- + plugins/gssapi.c | 225 +++++++++++++++++++++++++++++++------------------------ + 1 file changed, 126 insertions(+), 99 deletions(-) + +diff --git a/plugins/gssapi.c b/plugins/gssapi.c +index 2fd1b3b..f5d3354 100644 +--- a/plugins/gssapi.c ++++ b/plugins/gssapi.c +@@ -126,20 +126,29 @@ extern gss_OID gss_nt_service_name; + */ + + #ifdef GSS_USE_MUTEXES +-#define GSS_LOCK_MUTEX(utils) \ +- if(((sasl_utils_t *)(utils))->mutex_lock(gss_mutex) != 0) { \ ++#define GSS_LOCK_MUTEX_EXT(utils, mutex) \ ++ if(((sasl_utils_t *)(utils))->mutex_lock(mutex) != 0) { \ + return SASL_FAIL; \ + } + +-#define GSS_UNLOCK_MUTEX(utils) \ +- if(((sasl_utils_t *)(utils))->mutex_unlock(gss_mutex) != 0) { \ ++#define GSS_UNLOCK_MUTEX_EXT(utils, mutex) \ ++ if(((sasl_utils_t *)(utils))->mutex_unlock(mutex) != 0) { \ + return SASL_FAIL; \ + } + ++#define GSS_LOCK_MUTEX(utils) GSS_LOCK_MUTEX_EXT(utils, gss_mutex) ++#define GSS_UNLOCK_MUTEX(utils) GSS_UNLOCK_MUTEX_EXT(utils, gss_mutex) ++ ++#define GSS_LOCK_MUTEX_CTX(utils, ctx) GSS_LOCK_MUTEX_EXT(utils, (ctx)->ctx_mutex) ++#define GSS_UNLOCK_MUTEX_CTX(utils, ctx) GSS_UNLOCK_MUTEX_EXT(utils, (ctx)->ctx_mutex) ++ ++ + static void *gss_mutex = NULL; + #else + #define GSS_LOCK_MUTEX(utils) + #define GSS_UNLOCK_MUTEX(utils) ++#define GSS_LOCK_MUTEX_CTX(utils, ctx) ++#define GSS_UNLOCK_MUTEX_CTX(utils, ctx) + #endif + + typedef struct context { +@@ -176,6 +185,7 @@ typedef struct context { + + char *authid; /* hold the authid between steps - server */ + const char *user; /* hold the userid between steps - client */ ++ void *ctx_mutex; /* A per-context mutex */ + } context_t; + + enum { +@@ -355,7 +365,7 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, + output_token->value = NULL; + output_token->length = 0; + +- GSS_LOCK_MUTEX(text->utils); ++ GSS_LOCK_MUTEX_CTX(text->utils, text); + maj_stat = gss_wrap (&min_stat, + text->gss_ctx, + privacy, +@@ -363,14 +373,14 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, + input_token, + NULL, + output_token); +- GSS_UNLOCK_MUTEX(text->utils); ++ GSS_UNLOCK_MUTEX_CTX(text->utils, text); + + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils, maj_stat, min_stat); + if (output_token->value) { +- GSS_LOCK_MUTEX(text->utils); ++ GSS_LOCK_MUTEX_CTX(text->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(text->utils); ++ GSS_UNLOCK_MUTEX_CTX(text->utils, text); + } + return SASL_FAIL; + } +@@ -384,9 +394,9 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, + output_token->length + 4); + + if (ret != SASL_OK) { +- GSS_LOCK_MUTEX(text->utils); ++ GSS_LOCK_MUTEX_CTX(text->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(text->utils); ++ GSS_UNLOCK_MUTEX_CTX(text->utils, text); + return ret; + } + +@@ -407,9 +417,9 @@ sasl_gss_encode(void *context, const struct iovec *invec, unsigned numiov, + *output = text->encode_buf; + + if (output_token->value) { +- GSS_LOCK_MUTEX(text->utils); ++ GSS_LOCK_MUTEX_CTX(text->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(text->utils); ++ GSS_UNLOCK_MUTEX_CTX(text->utils, text); + } + + return SASL_OK; +@@ -455,21 +465,21 @@ gssapi_decode_packet(void *context, + output_token->value = NULL; + output_token->length = 0; + +- GSS_LOCK_MUTEX(text->utils); ++ GSS_LOCK_MUTEX_CTX(text->utils, text); + maj_stat = gss_unwrap (&min_stat, + text->gss_ctx, + input_token, + output_token, + NULL, + NULL); +- GSS_UNLOCK_MUTEX(text->utils); ++ GSS_UNLOCK_MUTEX_CTX(text->utils, text); + + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils,maj_stat,min_stat); + if (output_token->value) { +- GSS_LOCK_MUTEX(text->utils); ++ GSS_LOCK_MUTEX_CTX(text->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(text->utils); ++ GSS_UNLOCK_MUTEX_CTX(text->utils, text); + } + return SASL_FAIL; + } +@@ -484,17 +494,17 @@ gssapi_decode_packet(void *context, + &text->decode_once_buf_len, + *outputlen); + if (result != SASL_OK) { +- GSS_LOCK_MUTEX(text->utils); ++ GSS_LOCK_MUTEX_CTX(text->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(text->utils); ++ GSS_UNLOCK_MUTEX_CTX(text->utils, text); + return result; + } + *output = text->decode_once_buf; + memcpy(*output, output_token->value, *outputlen); + } +- GSS_LOCK_MUTEX(text->utils); ++ GSS_LOCK_MUTEX_CTX(text->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(text->utils); ++ GSS_UNLOCK_MUTEX_CTX(text->utils, text); + } + + return SASL_OK; +@@ -525,7 +535,14 @@ static context_t *sasl_gss_new_context(const sasl_utils_t *utils) + + memset(ret,0,sizeof(context_t)); + ret->utils = utils; +- ++#ifdef GSS_USE_MUTEXES ++ ret->ctx_mutex = utils->mutex_alloc(); ++ if (!ret->ctx_mutex) { ++ utils->free(ret); ++ return NULL; ++ } ++#endif ++ + return ret; + } + +@@ -535,7 +552,11 @@ static int sasl_gss_free_context_contents(context_t *text) + + if (!text) return SASL_OK; + +- GSS_LOCK_MUTEX(text->utils); ++#ifdef GSS_USE_MUTEXES ++ if (text->ctx_mutex) { ++ GSS_LOCK_MUTEX_CTX(text->utils, text); ++ } ++#endif + + if (text->gss_ctx != GSS_C_NO_CONTEXT) { + maj_stat = gss_delete_sec_context(&min_stat,&text->gss_ctx, +@@ -563,8 +584,6 @@ static int sasl_gss_free_context_contents(context_t *text) + text->client_creds = GSS_C_NO_CREDENTIAL; + } + +- GSS_UNLOCK_MUTEX(text->utils); +- + if (text->out_buf) { + text->utils->free(text->out_buf); + text->out_buf = NULL; +@@ -598,6 +617,14 @@ static int sasl_gss_free_context_contents(context_t *text) + text->authid = NULL; + } + ++#ifdef GSS_USE_MUTEXES ++ if (text->ctx_mutex) { ++ GSS_UNLOCK_MUTEX_CTX(text->utils, text); ++ text->utils->mutex_free(text->ctx_mutex); ++ text->ctx_mutex = NULL; ++ } ++#endif ++ + return SASL_OK; + + } +@@ -692,12 +719,12 @@ gssapi_server_mech_authneg(context_t *text, + } + sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN); + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_import_name (&min_stat, + &name_token, + GSS_C_NT_HOSTBASED_SERVICE, + &text->server_name); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + params->utils->free(name_token.value); + name_token.value = NULL; +@@ -709,15 +736,15 @@ gssapi_server_mech_authneg(context_t *text, + } + + if ( text->server_creds != GSS_C_NO_CREDENTIAL) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_release_cred(&min_stat, &text->server_creds); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + text->server_creds = GSS_C_NO_CREDENTIAL; + } + + /* If caller didn't provide creds already */ + if ( server_creds == GSS_C_NO_CREDENTIAL) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_acquire_cred(&min_stat, + text->server_name, + GSS_C_INDEFINITE, +@@ -726,7 +753,7 @@ gssapi_server_mech_authneg(context_t *text, + &text->server_creds, + NULL, + NULL); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils, maj_stat, min_stat); +@@ -743,7 +770,7 @@ gssapi_server_mech_authneg(context_t *text, + } + + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = + gss_accept_sec_context(&min_stat, + &(text->gss_ctx), +@@ -756,15 +783,15 @@ gssapi_server_mech_authneg(context_t *text, + &out_flags, + NULL, /* context validity period */ + &(text->client_creds)); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + sasl_gss_log(text->utils, maj_stat, min_stat); + text->utils->seterror(text->utils->conn, SASL_NOLOG, "GSSAPI Failure: gss_accept_sec_context"); + if (output_token->value) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + } + sasl_gss_free_context_contents(text); + return SASL_BADAUTH; +@@ -778,18 +805,18 @@ gssapi_server_mech_authneg(context_t *text, + ret = _plug_buf_alloc(text->utils, &(text->out_buf), + &(text->out_buf_len), *serveroutlen); + if(ret != SASL_OK) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + return ret; + } + memcpy(text->out_buf, output_token->value, *serveroutlen); + *serverout = text->out_buf; + } + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + } else { + /* No output token, send an empty string */ + *serverout = GSSAPI_BLANK_STRING; +@@ -832,12 +859,12 @@ gssapi_server_mech_authneg(context_t *text, + /* continue with authentication */ + } + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_canonicalize_name(&min_stat, + text->client_name, + mech_type, + &client_name_MN); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + SETERROR(text->utils, "GSSAPI Failure: gss_canonicalize_name"); +@@ -848,12 +875,12 @@ gssapi_server_mech_authneg(context_t *text, + name_token.value = NULL; + name_without_realm.value = NULL; + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_display_name (&min_stat, + client_name_MN, + &name_token, + NULL); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + SETERROR(text->utils, "GSSAPI Failure: gss_display_name"); +@@ -883,7 +910,7 @@ gssapi_server_mech_authneg(context_t *text, + + name_without_realm.length = strlen( (char *) name_without_realm.value ); + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_import_name (&min_stat, + &name_without_realm, + /* Solaris 8/9 gss_import_name doesn't accept GSS_C_NULL_OID here, +@@ -894,7 +921,7 @@ gssapi_server_mech_authneg(context_t *text, + GSS_C_NULL_OID, + #endif + &without); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + SETERROR(text->utils, "GSSAPI Failure: gss_import_name"); +@@ -903,12 +930,12 @@ gssapi_server_mech_authneg(context_t *text, + goto cleanup; + } + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_compare_name(&min_stat, + client_name_MN, + without, + &equal); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + SETERROR(text->utils, "GSSAPI Failure: gss_compare_name"); +@@ -1053,7 +1080,7 @@ gssapi_server_mech_ssfcap(context_t *text, + real_input_token.value = (void *)sasldata; + real_input_token.length = 4; + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_wrap(&min_stat, + text->gss_ctx, + 0, /* Just integrity checking here */ +@@ -1061,14 +1088,14 @@ gssapi_server_mech_ssfcap(context_t *text, + input_token, + NULL, + output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils, maj_stat, min_stat); + if (output_token->value) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + } + sasl_gss_free_context_contents(text); + return SASL_FAIL; +@@ -1082,18 +1109,18 @@ gssapi_server_mech_ssfcap(context_t *text, + ret = _plug_buf_alloc(text->utils, &(text->out_buf), + &(text->out_buf_len), *serveroutlen); + if(ret != SASL_OK) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + return ret; + } + memcpy(text->out_buf, output_token->value, *serveroutlen); + *serverout = text->out_buf; + } + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + } + + /* Wait for ssf request and authid */ +@@ -1124,14 +1151,14 @@ gssapi_server_mech_ssfreq(context_t *text, + real_input_token.value = (void *)clientin; + real_input_token.length = clientinlen; + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_unwrap(&min_stat, + text->gss_ctx, + input_token, + output_token, + NULL, + NULL); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils, maj_stat, min_stat); +@@ -1142,9 +1169,9 @@ gssapi_server_mech_ssfreq(context_t *text, + if (output_token->length < 4) { + SETERROR(text->utils, + "token too short"); +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + sasl_gss_free_context_contents(text); + return SASL_FAIL; + } +@@ -1175,9 +1202,9 @@ gssapi_server_mech_ssfreq(context_t *text, + /* Mark that we attempted negotiation */ + oparams->mech_ssf = 2; + if (output_token->value) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + } + sasl_gss_free_context_contents(text); + return SASL_FAIL; +@@ -1221,9 +1248,9 @@ gssapi_server_mech_ssfreq(context_t *text, + } + } + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + text->state = SASL_GSSAPI_STATE_AUTHENTICATED; + +@@ -1547,12 +1574,12 @@ static int gssapi_client_mech_step(void *conn_context, + + sprintf(name_token.value,"%s@%s", params->service, params->serverFQDN); + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_import_name (&min_stat, + &name_token, + GSS_C_NT_HOSTBASED_SERVICE, + &text->server_name); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + params->utils->free(name_token.value); + name_token.value = NULL; +@@ -1576,9 +1603,9 @@ static int gssapi_client_mech_step(void *conn_context, + * 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); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_delete_sec_context (&min_stat,&text->gss_ctx,GSS_C_NO_BUFFER); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + text->gss_ctx = GSS_C_NO_CONTEXT; + } + +@@ -1600,7 +1627,7 @@ static int gssapi_client_mech_step(void *conn_context, + req_flags = req_flags | GSS_C_DELEG_FLAG; + } + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_init_sec_context(&min_stat, + client_creds, /* GSS_C_NO_CREDENTIAL */ + &text->gss_ctx, +@@ -1614,14 +1641,14 @@ static int gssapi_client_mech_step(void *conn_context, + output_token, + &out_req_flags, + NULL); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils, maj_stat, min_stat); + if (output_token->value) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + } + sasl_gss_free_context_contents(text); + return SASL_FAIL; +@@ -1652,22 +1679,22 @@ static int gssapi_client_mech_step(void *conn_context, + ret = _plug_buf_alloc(text->utils, &(text->out_buf), + &(text->out_buf_len), *clientoutlen); + if(ret != SASL_OK) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + return ret; + } + memcpy(text->out_buf, output_token->value, *clientoutlen); + *clientout = text->out_buf; + } + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + } + + if (maj_stat == GSS_S_COMPLETE) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_inquire_context(&min_stat, + text->gss_ctx, + &text->client_name, +@@ -1678,7 +1705,7 @@ static int gssapi_client_mech_step(void *conn_context, + NULL, /* flags */ + NULL, /* local init */ + NULL); /* open */ +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils, maj_stat, min_stat); +@@ -1687,18 +1714,18 @@ static int gssapi_client_mech_step(void *conn_context, + } + + name_token.length = 0; +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_display_name(&min_stat, + text->client_name, + &name_token, + NULL); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + if (name_token.value) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, &name_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + } + SETERROR(text->utils, "GSSAPI Failure"); + sasl_gss_free_context_contents(text); +@@ -1719,9 +1746,9 @@ static int gssapi_client_mech_step(void *conn_context, + SASL_CU_AUTHID | SASL_CU_AUTHZID, + oparams); + } +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, &name_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (ret != SASL_OK) return ret; + +@@ -1747,32 +1774,32 @@ static int gssapi_client_mech_step(void *conn_context, + real_input_token.value = (void *) serverin; + real_input_token.length = serverinlen; + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_unwrap(&min_stat, + text->gss_ctx, + input_token, + output_token, + NULL, + NULL); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils, maj_stat, min_stat); +- sasl_gss_free_context_contents(text); + if (output_token->value) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + } ++ sasl_gss_free_context_contents(text); + return SASL_FAIL; + } + + if (output_token->length != 4) { + SETERROR(text->utils, + (output_token->length < 4) ? "token too short" : "token too long"); +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + sasl_gss_free_context_contents(text); + return SASL_FAIL; + } +@@ -1873,9 +1900,9 @@ static int gssapi_client_mech_step(void *conn_context, + } + } + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + /* oparams->user is always set, due to canon_user requirements. + * Make sure the client actually requested it though, by checking +@@ -1921,7 +1948,7 @@ static int gssapi_client_mech_step(void *conn_context, + } + ((unsigned char *)input_token->value)[0] = mychoice; + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + maj_stat = gss_wrap (&min_stat, + text->gss_ctx, + 0, /* Just integrity checking here */ +@@ -1929,7 +1956,7 @@ static int gssapi_client_mech_step(void *conn_context, + input_token, + NULL, + output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + params->utils->free(input_token->value); + input_token->value = NULL; +@@ -1937,9 +1964,9 @@ static int gssapi_client_mech_step(void *conn_context, + if (GSS_ERROR(maj_stat)) { + sasl_gss_seterror(text->utils, maj_stat, min_stat); + if (output_token->value) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + } + sasl_gss_free_context_contents(text); + return SASL_FAIL; +@@ -1955,18 +1982,18 @@ static int gssapi_client_mech_step(void *conn_context, + &(text->out_buf_len), + *clientoutlen); + if (ret != SASL_OK) { +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + return ret; + } + memcpy(text->out_buf, output_token->value, *clientoutlen); + *clientout = text->out_buf; + } + +- GSS_LOCK_MUTEX(params->utils); ++ GSS_LOCK_MUTEX_CTX(params->utils, text); + gss_release_buffer(&min_stat, output_token); +- GSS_UNLOCK_MUTEX(params->utils); ++ GSS_UNLOCK_MUTEX_CTX(params->utils, text); + + } + +-- +2.4.3 + + diff --git a/SPECS/cyrus-sasl.spec b/SPECS/cyrus-sasl.spec index 62f90f6..2124c7f 100644 --- a/SPECS/cyrus-sasl.spec +++ b/SPECS/cyrus-sasl.spec @@ -10,7 +10,7 @@ Summary: The Cyrus SASL library Name: cyrus-sasl Version: 2.1.26 -Release: 19.2%{?dist} +Release: 20%{?dist} License: BSD with advertising Group: System Environment/Libraries # Source0 originally comes from ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/; @@ -62,6 +62,8 @@ Patch55: cyrus-sasl-2.1.26-make-client-thread-sage.patch Patch56: cyrus-sasl-2.1.26-handle-single-character-mechanisms.patch # Fix confusing message when config file has typo (#1022479) Patch57: cyrus-sasl-2.1.26-error-message-when-config-has-typo.patch +# GSSAPI: Use per-connection mutex where possible (#1263017) +Patch58: cyrus-sasl-2.1.26-gssapi-use-per-connection-mutex.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: autoconf, automake, libtool, gdbm-devel, groff @@ -211,6 +213,7 @@ chmod -x include/*.h %patch55 -p1 -b .threads %patch56 -p1 -b .prefix %patch57 -p1 -b .typo +%patch58 -p1 -b .mutex %build @@ -434,6 +437,9 @@ getent passwd %{username} >/dev/null || useradd -r -g %{username} -d %{homedir} %{_sbindir}/sasl2-shared-mechlist %changelog +* Fri Dec 04 2015 Jakub Jelen 2.1.26-20 +- GSSAPI: Use per-connection mutex where possible (#1263017) + * Thu Jul 16 2015 Jakub Jelen 2.1.26-19.2 - Revert tmpfiles.d and use new systemd feature RuntimeDirectory (#1188065)