From: Luke Howard Date: Tue, 8 Mar 2011 12:36:11 +0000 (+1100) Subject: more TLV cleanups X-Git-Tag: vm/20110310~31 X-Git-Url: http://www.project-moonshot.org/gitweb/?a=commitdiff_plain;ds=sidebyside;h=36696c5fc69f7b5c59526268b772255107530c90;p=mech_eap.orig more TLV cleanups --- diff --git a/accept_sec_context.c b/accept_sec_context.c index 9627e88..5b3d53f 100644 --- a/accept_sec_context.c +++ b/accept_sec_context.c @@ -179,8 +179,9 @@ eapGssSmAcceptIdentity(OM_uint32 *minor, wpabuf_free(reqData); + GSSEAP_SM_TRANSITION_NEXT(ctx); + *minor = 0; - *smFlags |= SM_FLAG_TRANSITION; return GSS_S_CONTINUE_NEEDED; } @@ -538,7 +539,7 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, if (GSS_ERROR(major)) goto cleanup; - *smFlags |= SM_FLAG_TRANSITION; + GSSEAP_SM_TRANSITION_NEXT(ctx); } major = GSS_S_CONTINUE_NEEDED; @@ -636,9 +637,9 @@ eapGssSmAcceptCompleteInitiatorExts(OM_uint32 *minor, gss_buffer_t outputToken, OM_uint32 *smFlags) { - *minor = 0; + GSSEAP_SM_TRANSITION_NEXT(ctx); - *smFlags |= SM_FLAG_TRANSITION | SM_FLAG_STOP_EVAL; + *minor = 0; return GSS_S_CONTINUE_NEEDED; } @@ -656,10 +657,10 @@ eapGssSmAcceptCompleteAcceptorExts(OM_uint32 *minor, gss_buffer_t outputToken, OM_uint32 *smFlags) { - *minor = 0; + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED); - gssEapSmTransition(ctx, GSSEAP_STATE_ESTABLISHED); - *smFlags |= SM_FLAG_STOP_EVAL; + *minor = 0; + *smFlags |= SM_FLAG_FORCE_SEND_TOKEN; return GSS_S_COMPLETE; } @@ -899,8 +900,7 @@ eapGssSmAcceptGssReauth(OM_uint32 *minor, major = acceptReadyKrb(minor, ctx, cred, krbInitiator, mech, timeRec); if (major == GSS_S_COMPLETE) { - gssEapSmTransition(ctx, GSSEAP_STATE_ESTABLISHED); - *smFlags |= SM_FLAG_STOP_EVAL; + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED); } } diff --git a/init_sec_context.c b/init_sec_context.c index 4c82964..8104a63 100644 --- a/init_sec_context.c +++ b/init_sec_context.c @@ -477,15 +477,13 @@ eapGssSmInitGssReauth(OM_uint32 *minor, ctx->gssFlags = gssFlags; - *smFlags |= SM_FLAG_STOP_EVAL; - if (major == GSS_S_COMPLETE) { major = gssEapReauthComplete(minor, ctx, cred, actualMech, timeRec); if (GSS_ERROR(major)) goto cleanup; - gssEapSmTransition(ctx, GSSEAP_STATE_ESTABLISHED); + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED); } else { - gssEapSmTransition(ctx, GSSEAP_STATE_REAUTHENTICATE); + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_REAUTHENTICATE); } cleanup: @@ -563,9 +561,11 @@ eapGssSmInitIdentity(OM_uint32 *minor, return GSS_S_FAILURE; } + GSSEAP_SM_TRANSITION_NEXT(ctx); + /* force sending of empty token */ *minor = 0; - *smFlags |= SM_FLAG_TRANSITION | SM_FLAG_FORCE_SEND_TOKEN; + *smFlags |= SM_FLAG_FORCE_SEND_TOKEN; return GSS_S_CONTINUE_NEEDED; } @@ -618,7 +618,7 @@ eapGssSmInitAuthenticate(OM_uint32 *minor, ctx->flags &= ~(CTX_FLAG_EAP_SUCCESS); major = GSS_S_CONTINUE_NEEDED; - *smFlags |= SM_FLAG_TRANSITION; + GSSEAP_SM_TRANSITION_NEXT(ctx); } else if (ctx->flags & CTX_FLAG_EAP_FAIL) { major = GSS_S_DEFECTIVE_CREDENTIAL; *minor = GSSEAP_PEER_AUTH_FAILURE; @@ -718,9 +718,10 @@ eapGssSmInitCompleteInitiatorExts(OM_uint32 *minor, gss_buffer_t outputToken, OM_uint32 *smFlags) { - *minor = 0; + GSSEAP_SM_TRANSITION_NEXT(ctx); - *smFlags |= SM_FLAG_TRANSITION | SM_FLAG_STOP_EVAL; + *minor = 0; + *smFlags |= SM_FLAG_FORCE_SEND_TOKEN; return GSS_S_CONTINUE_NEEDED; } @@ -738,10 +739,9 @@ eapGssSmInitCompleteAcceptorExts(OM_uint32 *minor, gss_buffer_t outputToken, OM_uint32 *smFlags) { - *minor = 0; + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED); - gssEapSmTransition(ctx, GSSEAP_STATE_ESTABLISHED); - *smFlags |= SM_FLAG_STOP_EVAL; + *minor = 0; return GSS_S_COMPLETE; } diff --git a/util.h b/util.h index 85123d0..8afc97c 100644 --- a/util.h +++ b/util.h @@ -546,6 +546,15 @@ enum gss_eap_state { #define GSSEAP_STATE_NEXT(s) ((s) << 1) +#ifdef GSSEAP_DEBUG +void gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state); +#define GSSEAP_SM_TRANSITION(ctx, state) gssEapSmTransition((ctx), (state)) +#else +#define GSSEAP_SM_TRANSITION(ctx, state) do { (ctx)->state = (state); } while (0) +#endif + +#define GSSEAP_SM_TRANSITION_NEXT(ctx) GSSEAP_SM_TRANSITION((ctx), GSSEAP_STATE_NEXT((ctx)->state)) + /* state machine entry */ struct gss_eap_sm { OM_uint32 inputTokenType; @@ -565,9 +574,8 @@ struct gss_eap_sm { OM_uint32 *); }; -#define SM_FLAG_TRANSITION 0x00000001 /* transition to next state */ -#define SM_FLAG_FORCE_SEND_TOKEN 0x00000002 /* send token even if empty */ -#define SM_FLAG_STOP_EVAL 0x00000004 /* no more handlers for this state */ +#define SM_FLAG_FORCE_SEND_TOKEN 0x00000001 /* send token even if empty */ +#define SM_FLAG_STOP_EVAL 0x00000002 /* no more handlers for this state */ #define SM_ITOK_FLAG_CRITICAL 0x00000001 /* sent tokens marked critical */ #define SM_ITOK_FLAG_REQUIRED 0x00000002 /* received tokens must be present */ diff --git a/util_sm.c b/util_sm.c index fae6528..d800e82 100644 --- a/util_sm.c +++ b/util_sm.c @@ -36,6 +36,15 @@ #include "gssapiP_eap.h" +/* private flags */ +#define SM_FLAG_TRANSITED 0x80000000 + +#define SM_ASSERT_VALID(ctx, status) do { \ + assert(GSS_ERROR((status)) || \ + ((status) == GSS_S_CONTINUE_NEEDED && ((ctx)->state > GSSEAP_STATE_INITIAL && (ctx)->state < GSSEAP_STATE_ESTABLISHED)) || \ + ((status) == GSS_S_COMPLETE && (ctx)->state == GSSEAP_STATE_ESTABLISHED)); \ + } while (0) + static const char * gssEapStateToString(enum gss_eap_state state) { @@ -68,19 +77,19 @@ gssEapStateToString(enum gss_eap_state state) return s; } +#ifdef GSSEAP_DEBUG void gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state) { assert(state > ctx->state); assert(state <= GSSEAP_STATE_ESTABLISHED); -#ifdef GSSEAP_DEBUG fprintf(stderr, "GSS-EAP: state transition %s->%s\n", gssEapStateToString(ctx->state), gssEapStateToString(state)); -#endif ctx->state = state; } +#endif static OM_uint32 makeErrorToken(OM_uint32 *minor, @@ -116,6 +125,56 @@ makeErrorToken(OM_uint32 *minor, return gss_add_buffer_set_member(minor, &errorBuffer, outputToken); } +static OM_uint32 +allocInnerTokens(OM_uint32 *minor, + size_t count, + gss_buffer_set_t *pTokens, + OM_uint32 **pTokenTypes) +{ + OM_uint32 major, tmpMinor; + gss_buffer_set_t tokens = GSS_C_NO_BUFFER_SET; + OM_uint32 *tokenTypes = NULL; + + major = gss_create_empty_buffer_set(minor, &tokens); + if (GSS_ERROR(major)) + goto cleanup; + + assert(tokens->count == 0); + assert(tokens->elements == NULL); + + tokens->elements = (gss_buffer_desc *)GSSEAP_CALLOC(count, sizeof(gss_buffer_desc)); + if (tokens->elements == NULL) { + major = GSS_S_FAILURE; + *minor = ENOMEM; + goto cleanup; + } + + tokenTypes = (OM_uint32 *)GSSEAP_CALLOC(count, sizeof(OM_uint32)); + if (tokenTypes == NULL) { + major = GSS_S_FAILURE; + *minor = ENOMEM; + goto cleanup; + } + + major = GSS_S_COMPLETE; + *minor = 0; + +cleanup: + if (GSS_ERROR(major)) { + gss_release_buffer_set(&tmpMinor, &tokens); + tokens = GSS_C_NO_BUFFER_SET; + if (tokenTypes != NULL) { + GSSEAP_FREE(tokenTypes); + tokenTypes = NULL; + } + } + + *pTokens = tokens; + *pTokenTypes = tokenTypes; + + return major; +} + OM_uint32 gssEapSmStep(OM_uint32 *minor, gss_cred_id_t cred, @@ -183,111 +242,79 @@ gssEapSmStep(OM_uint32 *minor, assert(innerInputTokens != GSS_C_NO_BUFFER_SET); - major = gss_create_empty_buffer_set(minor, &innerOutputTokens); + major = allocInnerTokens(minor, smCount, &innerOutputTokens, &outputTokenTypes); if (GSS_ERROR(major)) goto cleanup; - assert(innerOutputTokens->count == 0); - assert(innerOutputTokens->elements == NULL); - - innerOutputTokens->elements = (gss_buffer_desc *)GSSEAP_CALLOC(smCount, - sizeof(gss_buffer_desc)); - if (innerOutputTokens->elements == NULL) { - major = GSS_S_FAILURE; - *minor = ENOMEM; - goto cleanup; - } - - outputTokenTypes = (OM_uint32 *)GSSEAP_CALLOC(smCount, sizeof(OM_uint32)); - if (outputTokenTypes == NULL) { - major = GSS_S_FAILURE; - *minor = ENOMEM; - goto cleanup; - } - - /* - * Process all the tokens that are valid for the current state. If - * the processToken function returns GSS_S_COMPLETE, the state is - * advanced until there is a token to send or the ESTABLISHED state - * is reached. - */ - do { - major = GSS_S_COMPLETE; - - for (i = 0; i < smCount; i++) { - struct gss_eap_sm *smp = &sm[i]; - int processToken = 0; - gss_buffer_t innerInputToken = GSS_C_NO_BUFFER; - OM_uint32 *inputTokenType = NULL; - gss_buffer_desc innerOutputToken = GSS_C_EMPTY_BUFFER; - - if ((smp->validStates & ctx->state) == 0) - continue; - - if (smp->inputTokenType == ITOK_TYPE_NONE || initialContextToken) { - processToken = 1; - } else if ((smFlags & SM_FLAG_TRANSITION) == 0) { - for (j = 0; j < innerInputTokens->count; j++) { - if ((inputTokenTypes[j] & ITOK_TYPE_MASK) == smp->inputTokenType) { - processToken = 1; - if (innerInputToken != GSS_C_NO_BUFFER) { - major = GSS_S_DEFECTIVE_TOKEN; - *minor = GSSEAP_DUPLICATE_ITOK; - break; - } + /* Process all the tokens that are valid for the current state. */ + for (i = 0; i < smCount; i++) { + struct gss_eap_sm *smp = &sm[i]; + int processToken = 0; + gss_buffer_t innerInputToken = GSS_C_NO_BUFFER; + OM_uint32 *inputTokenType = NULL; + gss_buffer_desc innerOutputToken = GSS_C_EMPTY_BUFFER; + + if ((smp->validStates & ctx->state) == 0) + continue; + + if (smp->inputTokenType == ITOK_TYPE_NONE || initialContextToken) { + processToken = 1; + } else if ((smFlags & SM_FLAG_TRANSITED) == 0) { + for (j = 0; j < innerInputTokens->count; j++) { + if ((inputTokenTypes[j] & ITOK_TYPE_MASK) == smp->inputTokenType) { + processToken = 1; + if (innerInputToken != GSS_C_NO_BUFFER) { + major = GSS_S_DEFECTIVE_TOKEN; + *minor = GSSEAP_DUPLICATE_ITOK; + break; } - innerInputToken = &innerInputTokens->elements[j]; - inputTokenType = &inputTokenTypes[j]; } + innerInputToken = &innerInputTokens->elements[j]; + inputTokenType = &inputTokenTypes[j]; } + } -#ifdef GSSEAP_DEBUG - fprintf(stderr, "GSS-EAP: state %d processToken %d inputTokenType %08x " - "innerInputToken %p innerOutputTokensCount %zd\n", - ctx->state, processToken, smp->inputTokenType, - innerInputToken, innerOutputTokens->count); -#endif + if (processToken) { + enum gss_eap_state oldState = ctx->state; - if (processToken) { - smFlags = 0; - - major = smp->processToken(minor, cred, ctx, target, mech, reqFlags, - timeReq, chanBindings, innerInputToken, - &innerOutputToken, &smFlags); - if (GSS_ERROR(major)) - break; - - if (inputTokenType != NULL) - *inputTokenType |= ITOK_FLAG_VERIFIED; - - if (innerOutputToken.value != NULL) { - innerOutputTokens->elements[innerOutputTokens->count] = innerOutputToken; - assert(smp->outputTokenType != ITOK_TYPE_NONE); - outputTokenTypes[innerOutputTokens->count] = smp->outputTokenType; - if (smp->itokFlags & SM_ITOK_FLAG_CRITICAL) - outputTokenTypes[innerOutputTokens->count] |= ITOK_FLAG_CRITICAL; - innerOutputTokens->count++; - } - if (smFlags & SM_FLAG_STOP_EVAL) - break; - } else if ((smp->itokFlags & SM_ITOK_FLAG_REQUIRED) && - smp->inputTokenType != ITOK_TYPE_NONE) { - major = GSS_S_DEFECTIVE_TOKEN; - *minor = GSSEAP_MISSING_REQUIRED_ITOK; + smFlags = 0; + + major = smp->processToken(minor, cred, ctx, target, mech, reqFlags, + timeReq, chanBindings, innerInputToken, + &innerOutputToken, &smFlags); + if (GSS_ERROR(major)) break; - } - } - if (GSS_ERROR(major) || (smFlags & SM_FLAG_TRANSITION) == 0) + if (inputTokenType != NULL) + *inputTokenType |= ITOK_FLAG_VERIFIED; + if (ctx->state != oldState) + smFlags |= SM_FLAG_TRANSITED; + + if (innerOutputToken.value != NULL) { + innerOutputTokens->elements[innerOutputTokens->count] = innerOutputToken; + assert(smp->outputTokenType != ITOK_TYPE_NONE); + outputTokenTypes[innerOutputTokens->count] = smp->outputTokenType; + if (smp->itokFlags & SM_ITOK_FLAG_CRITICAL) + outputTokenTypes[innerOutputTokens->count] |= ITOK_FLAG_CRITICAL; + innerOutputTokens->count++; + } + /* + * Break out if explicitly requested, or if we made a state transition + * and have some tokens to send. + */ + if ((smFlags & SM_FLAG_STOP_EVAL) || + ((smFlags & SM_FLAG_TRANSITED) && + ((smFlags & SM_FLAG_FORCE_SEND_TOKEN) || innerOutputTokens->count != 0))) { + SM_ASSERT_VALID(ctx, major); + break; + } + } else if ((smp->itokFlags & SM_ITOK_FLAG_REQUIRED) && + smp->inputTokenType != ITOK_TYPE_NONE) { + major = GSS_S_DEFECTIVE_TOKEN; + *minor = GSSEAP_MISSING_REQUIRED_ITOK; break; - - gssEapSmTransition(ctx, GSSEAP_STATE_NEXT(ctx->state)); - - if (innerOutputTokens->count != 0 || (smFlags & SM_FLAG_FORCE_SEND_TOKEN)) { - assert(major == GSS_S_CONTINUE_NEEDED || ctx->state == GSSEAP_STATE_ESTABLISHED); - break; /* send any tokens if we have them */ } - } while (ctx->state != GSSEAP_STATE_ESTABLISHED); + } assert(innerOutputTokens->count <= smCount); @@ -321,15 +348,6 @@ gssEapSmStep(OM_uint32 *minor, outputTokenTypes[0] = ITOK_TYPE_CONTEXT_ERR | ITOK_FLAG_CRITICAL; } -#ifdef GSSEAP_DEBUG - for (i = 0; i < innerOutputTokens->count; i++) { - fprintf(stderr, "GSS-EAP: type %08x length %zd value %p\n", - outputTokenTypes[i], - innerOutputTokens->elements[i].length, - innerOutputTokens->elements[i].value); - } -#endif - /* Format composite output token */ if (innerOutputTokens->count != 0 || /* inner tokens to send */ !CTX_IS_INITIATOR(ctx) || /* any leg acceptor */ @@ -347,9 +365,7 @@ gssEapSmStep(OM_uint32 *minor, } } - assert(GSS_ERROR(major) || - (major == GSS_S_CONTINUE_NEEDED && (ctx->state > GSSEAP_STATE_INITIAL && ctx->state < GSSEAP_STATE_ESTABLISHED)) || - (major == GSS_S_COMPLETE && ctx->state == GSSEAP_STATE_ESTABLISHED)); + SM_ASSERT_VALID(ctx, major); cleanup: gss_release_buffer_set(&tmpMinor, &innerInputTokens);