From ed2c87eadedcedb47132b54086b53580ee3d7bc1 Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Mon, 9 Jan 2012 21:23:43 +0000 Subject: [PATCH] Pull up r25591, r25604 from trunk ------------------------------------------------------------------------ r25604 | ghudson | 2011-12-27 01:39:07 -0500 (Tue, 27 Dec 2011) | 4 lines ticket: 6936 Fix an unlikely memory leak in r25591 ------------------------------------------------------------------------ r25591 | ghudson | 2011-12-16 18:19:01 -0500 (Fri, 16 Dec 2011) | 14 lines ticket: 6936 target_version: 1.10 tags: pullup Do mech fallback for first SPNEGO context token When producing the first SPNEGO security context token, if the first mechanism's init_sec_context fails, fall back to a later mechanism. This fixes a regression in 1.10 for SPNEGO initiators using non-krb5 credentials. The identity selection work causes errors to be deferred from krb5's acquire_cred in some cases, which means SPNEGO doesn't see an error until it tries the krb5 init_sec_context. ticket: 6936 version_fixed: 1.10 status: resolved git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-10@25628 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/gssapi/spnego/spnego_mech.c | 47 +++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c index ca23b2248..70246b6ac 100644 --- a/src/lib/gssapi/spnego/spnego_mech.c +++ b/src/lib/gssapi/spnego/spnego_mech.c @@ -589,7 +589,7 @@ init_ctx_new(OM_uint32 *minor_status, ret = get_negotiable_mechs(minor_status, spcred, GSS_C_INITIATE, &sc->mech_set); if (ret != GSS_S_COMPLETE) - return ret; + goto cleanup; /* Set an initial internal mech to make the first context token. */ sc->internal_mech = &sc->mech_set->elements[0]; @@ -821,7 +821,7 @@ init_ctx_call_init(OM_uint32 *minor_status, OM_uint32 *negState, send_token_flag *send_token) { - OM_uint32 ret; + OM_uint32 ret, tmpret, tmpmin; gss_cred_id_t mcred; mcred = (spcred == NULL) ? GSS_C_NO_CREDENTIAL : spcred->mcred; @@ -862,15 +862,44 @@ init_ctx_call_init(OM_uint32 *minor_status, *negState = ACCEPT_INCOMPLETE; ret = GSS_S_CONTINUE_NEEDED; } - } else if (ret != GSS_S_CONTINUE_NEEDED) { - if (*send_token == INIT_TOKEN_SEND) { - /* Don't output token on error if first call. */ - *send_token = NO_TOKEN_SEND; - } else { - *send_token = ERROR_TOKEN_SEND; - } + return ret; + } + + if (ret == GSS_S_CONTINUE_NEEDED) + return ret; + + if (*send_token != INIT_TOKEN_SEND) { + *send_token = ERROR_TOKEN_SEND; *negState = REJECT; + return ret; } + + /* + * Since this is the first token, we can fall back to later mechanisms + * in the list. Since the mechanism list is expected to be short, we + * can do this with recursion. If all mechanisms produce errors, the + * caller should get the error from the first mech in the list. + */ + memmove(sc->mech_set->elements, sc->mech_set->elements + 1, + --sc->mech_set->count * sizeof(*sc->mech_set->elements)); + if (sc->mech_set->count == 0) + goto fail; + gss_release_buffer(&tmpmin, &sc->DER_mechTypes); + if (put_mech_set(sc->mech_set, &sc->DER_mechTypes) < 0) + goto fail; + tmpret = init_ctx_call_init(&tmpmin, sc, spcred, target_name, + req_flags, time_req, mechtok_in, + actual_mech, mechtok_out, ret_flags, + time_rec, negState, send_token); + if (HARD_ERROR(tmpret)) + goto fail; + *minor_status = tmpmin; + return tmpret; + +fail: + /* Don't output token on error from first call. */ + *send_token = NO_TOKEN_SEND; + *negState = REJECT; return ret; } -- 2.26.2