summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2011-12-16 23:19:01 +0000
committerGreg Hudson <ghudson@mit.edu>2011-12-16 23:19:01 +0000
commite946963e0f8488a8d47c527cca31d4666c32e063 (patch)
tree311fe11a247ddfd6ce677c75d72345a8836e22bb /src
parentcd7d6b08aebaee50a25a8eb519588abbca633d72 (diff)
downloadkrb5-e946963e0f8488a8d47c527cca31d4666c32e063.tar.gz
krb5-e946963e0f8488a8d47c527cca31d4666c32e063.tar.xz
krb5-e946963e0f8488a8d47c527cca31d4666c32e063.zip
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 target_version: 1.10 tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25591 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/lib/gssapi/spnego/spnego_mech.c45
1 files changed, 37 insertions, 8 deletions
diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index ca23b2248..dfb9bada4 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -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;
}