From b3e9b5417e483948e1cafb8be28a24eb4f606132 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Tue, 8 Mar 2011 13:50:46 +1100 Subject: [PATCH] make state transition explicit rather than side-effect of GSS status code --- accept_sec_context.c | 44 +++++++++++++++++++++++++++----------------- gssapiP_eap.h | 3 ++- init_sec_context.c | 40 +++++++++++++++++++++++++--------------- util_sm.c | 12 +++++++----- 4 files changed, 61 insertions(+), 38 deletions(-) diff --git a/accept_sec_context.c b/accept_sec_context.c index 6d65647..d9e232e 100644 --- a/accept_sec_context.c +++ b/accept_sec_context.c @@ -48,7 +48,8 @@ eapGssSmAcceptGssReauth(OM_uint32 *minor, OM_uint32 timeReq __attribute__((__unused__)), gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken); + gss_buffer_t outputToken, + int *transitionState); #endif /* @@ -137,7 +138,8 @@ eapGssSmAcceptIdentity(OM_uint32 *minor, OM_uint32 timeReq __attribute__((__unused__)), gss_channel_bindings_t chanBindings __attribute__((__unused__)), gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major; struct wpabuf *reqData; @@ -178,7 +180,9 @@ eapGssSmAcceptIdentity(OM_uint32 *minor, wpabuf_free(reqData); *minor = 0; - return GSS_S_COMPLETE; /* advance state */ + *transitionState = 1; + + return GSS_S_CONTINUE_NEEDED; } /* @@ -425,7 +429,8 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, OM_uint32 timeReq __attribute__((__unused__)), gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major, tmpMinor; struct rs_connection *rconn; @@ -522,8 +527,6 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, &ctx->acceptorCtx.state, TRUE); if (GSS_ERROR(major) && *minor != GSSEAP_NO_SUCH_ATTR) goto cleanup; - - major = GSS_S_CONTINUE_NEEDED; } else { ctx->acceptorCtx.vps = frresp->vps; frresp->vps = NULL; @@ -535,9 +538,12 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, if (GSS_ERROR(major)) goto cleanup; - major = GSS_S_COMPLETE; /* advance state */ + *transitionState = 1; } + major = GSS_S_CONTINUE_NEEDED; + *minor = 0; + cleanup: if (request != NULL) rs_request_destroy(request); @@ -557,7 +563,8 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, OM_uint32 timeReq __attribute__((__unused__)), gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major, tmpMinor; gss_iov_buffer_desc iov[2]; @@ -578,9 +585,6 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, !bufferEqual(&iov[0].buffer, &chanBindings->application_data)) { major = GSS_S_BAD_BINDINGS; *minor = GSSEAP_BINDINGS_MISMATCH; - } else { - major = GSS_S_CONTINUE_NEEDED; /* process additional extensions */ - *minor = 0; } gss_release_buffer(&tmpMinor, &iov[0].buffer); @@ -599,7 +603,8 @@ eapGssSmAcceptReauthCreds(OM_uint32 *minor, OM_uint32 timeReq __attribute__((__unused__)), gss_channel_bindings_t chanBindings __attribute__((__unused__)), gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major; @@ -611,8 +616,7 @@ eapGssSmAcceptReauthCreds(OM_uint32 *minor, if (GSS_ERROR(major)) return major; - *minor = 0; - return GSS_S_CONTINUE_NEEDED; /* process additional extensions */ + return major; } #endif @@ -626,10 +630,12 @@ eapGssSmAcceptNegoExtFinished(OM_uint32 *minor, OM_uint32 timeReq __attribute__((__unused__)), gss_channel_bindings_t chanBindings __attribute__((__unused__)), gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { *minor = 0; - return GSS_S_COMPLETE; /* advance state */ + *transitionState = 1; + return GSS_S_COMPLETE; } static struct gss_eap_sm eapGssAcceptorSm[] = { @@ -667,6 +673,7 @@ static struct gss_eap_sm eapGssAcceptorSm[] = { 1, /* required */ eapGssSmAcceptGssChannelBindings, }, +#ifdef GSSEAP_ENABLE_REAUTH { ITOK_TYPE_NONE, ITOK_TYPE_REAUTH_CREDS, @@ -675,6 +682,7 @@ static struct gss_eap_sm eapGssAcceptorSm[] = { 0, /* required */ eapGssSmAcceptReauthCreds, }, +#endif { ITOK_TYPE_NONE, ITOK_TYPE_NONE, @@ -835,7 +843,8 @@ eapGssSmAcceptGssReauth(OM_uint32 *minor, OM_uint32 timeReq __attribute__((__unused__)), gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major, tmpMinor; gss_name_t krbInitiator = GSS_C_NO_NAME; @@ -864,6 +873,7 @@ eapGssSmAcceptGssReauth(OM_uint32 *minor, if (major == GSS_S_COMPLETE) { major = acceptReadyKrb(minor, ctx, cred, krbInitiator, mech, timeRec); + *transitionState = 1; } ctx->gssFlags = gssFlags; diff --git a/gssapiP_eap.h b/gssapiP_eap.h index bcfdf03..884ed86 100644 --- a/gssapiP_eap.h +++ b/gssapiP_eap.h @@ -166,7 +166,8 @@ struct gss_eap_sm { OM_uint32, gss_channel_bindings_t, gss_buffer_t, - gss_buffer_t); + gss_buffer_t, + int *); }; #define CTX_IS_ESTABLISHED(ctx) ((ctx)->state == GSSEAP_STATE_ESTABLISHED) diff --git a/init_sec_context.c b/init_sec_context.c index f55aec9..56bbd6c 100644 --- a/init_sec_context.c +++ b/init_sec_context.c @@ -391,7 +391,8 @@ eapGssSmInitError(OM_uint32 *minor, OM_uint32 timeReq, gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major; unsigned char *p; @@ -427,7 +428,8 @@ eapGssSmInitGssReauth(OM_uint32 *minor, OM_uint32 timeReq, gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major, tmpMinor; gss_name_t mechTarget = GSS_C_NO_NAME; @@ -480,10 +482,10 @@ eapGssSmInitGssReauth(OM_uint32 *minor, if (GSS_ERROR(major)) goto cleanup; ctx->state = GSSEAP_STATE_NEGO_EXT; /* skip */ - } else { - major = GSS_S_COMPLETE; /* advance state */ } + *transitionState = 1; + cleanup: gssReleaseName(&tmpMinor, &mechTarget); @@ -501,7 +503,8 @@ eapGssSmInitIdentity(OM_uint32 *minor, OM_uint32 timeReq, gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major; int initialContextToken; @@ -524,7 +527,9 @@ eapGssSmInitIdentity(OM_uint32 *minor, outputToken->value = NULL; *minor = 0; - return GSS_S_COMPLETE; /* advance state */ + *transitionState = 1; + + return GSS_S_COMPLETE; } static struct wpabuf emptyWpaBuffer; @@ -539,7 +544,8 @@ eapGssSmInitAuthenticate(OM_uint32 *minor, OM_uint32 timeReq, gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major; OM_uint32 tmpMinor; @@ -576,6 +582,8 @@ eapGssSmInitAuthenticate(OM_uint32 *minor, ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */ + major = GSS_S_CONTINUE_NEEDED; + wpabuf_set(&ctx->initiatorCtx.reqData, inputToken->value, inputToken->length); @@ -584,19 +592,18 @@ eapGssSmInitAuthenticate(OM_uint32 *minor, ctx->flags &= ~(CTX_FLAG_EAP_RESP); resp = eap_get_eapRespData(ctx->initiatorCtx.eap); - major = GSS_S_CONTINUE_NEEDED; } else if (ctx->flags & CTX_FLAG_EAP_SUCCESS) { major = initReady(minor, ctx, reqFlags); if (GSS_ERROR(major)) goto cleanup; ctx->flags &= ~(CTX_FLAG_EAP_SUCCESS); - major = GSS_S_COMPLETE; /* advance state */ + *transitionState = 1; } else if (ctx->flags & CTX_FLAG_EAP_FAIL) { major = GSS_S_DEFECTIVE_CREDENTIAL; *minor = GSSEAP_PEER_AUTH_FAILURE; } else if (code == 0 && initialContextToken) { - major = GSS_S_CONTINUE_NEEDED; + /* */ } else { major = GSS_S_DEFECTIVE_TOKEN; *minor = GSSEAP_PEER_BAD_MESSAGE; @@ -635,7 +642,8 @@ eapGssSmInitGssChannelBindings(OM_uint32 *minor, OM_uint32 timeReq, gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major; gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER; @@ -665,7 +673,8 @@ eapGssSmInitReauthCreds(OM_uint32 *minor, OM_uint32 timeReq, gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { OM_uint32 major; @@ -688,10 +697,12 @@ eapGssSmInitNegoExtFinished(OM_uint32 *minor, OM_uint32 timeReq, gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + int *transitionState) { *minor = 0; - return GSS_S_COMPLETE; /* advance state */ + *transitionState = 1; + return GSS_S_COMPLETE; } static struct gss_eap_sm eapGssInitiatorSm[] = { @@ -713,7 +724,6 @@ static struct gss_eap_sm eapGssInitiatorSm[] = { eapGssSmInitGssReauth, }, #endif - /* first-leg extensions go here, they should return GSS_S_CONTINUE_NEEDED */ { ITOK_TYPE_NONE, ITOK_TYPE_NONE, diff --git a/util_sm.c b/util_sm.c index 9c2ae38..71783e2 100644 --- a/util_sm.c +++ b/util_sm.c @@ -161,6 +161,8 @@ gssEapSmStep(OM_uint32 *minor, * is reached. */ do { + int transitionState = 0; + major = GSS_S_COMPLETE; for (i = 0; i < smCount; i++) { @@ -200,7 +202,7 @@ gssEapSmStep(OM_uint32 *minor, if (processToken) { major = smp->processToken(minor, cred, ctx, target, mech, reqFlags, timeReq, chanBindings, innerInputToken, - &innerOutputToken); + &innerOutputToken, &transitionState); if (GSS_ERROR(major)) break; @@ -215,7 +217,7 @@ gssEapSmStep(OM_uint32 *minor, outputTokenTypes[innerOutputTokens->count] |= ITOK_FLAG_CRITICAL; innerOutputTokens->count++; } - if (major == GSS_S_COMPLETE) + if (transitionState) break; } else if (smp->required && smp->inputTokenType != ITOK_TYPE_NONE) { major = GSS_S_DEFECTIVE_TOKEN; @@ -224,15 +226,15 @@ gssEapSmStep(OM_uint32 *minor, } } - if (major != GSS_S_COMPLETE) - break; /* GSS_S_CONTINUE_NEEDED or error */ + if (GSS_ERROR(major) || !transitionState) + break; assert(ctx->state < GSSEAP_STATE_ESTABLISHED); ctx->state = GSSEAP_STATE_NEXT(ctx->state); if (innerOutputTokens->count != 0) { - major = GSS_S_CONTINUE_NEEDED; + assert(major == GSS_S_CONTINUE_NEEDED); break; /* send any tokens if we have them */ } } while (ctx->state != GSSEAP_STATE_ESTABLISHED); -- 2.1.4