case GSSEAP_STATE_ACCEPTOR_EXTS:
s = "ACCEPTOR_EXTS";
break;
+#ifdef GSSEAP_ENABLE_REAUTH
case GSSEAP_STATE_REAUTHENTICATE:
s = "REAUTHENTICATE";
break;
+#endif
case GSSEAP_STATE_ESTABLISHED:
s = "ESTABLISHED";
break;
void
gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state)
{
- assert(state > ctx->state);
+ assert(state >= GSSEAP_STATE_INITIAL);
assert(state <= GSSEAP_STATE_ESTABLISHED);
fprintf(stderr, "GSS-EAP: state transition %s->%s\n",
- gssEapStateToString(ctx->state), gssEapStateToString(state));
+ gssEapStateToString(GSSEAP_SM_STATE(ctx)),
+ gssEapStateToString(state));
ctx->state = state;
}
unsigned int smFlags = 0;
size_t i, j;
int initialContextToken = 0;
+ enum gss_eap_token_type tokType;
assert(smCount > 0);
outputToken->value = NULL;
if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0) {
- enum gss_eap_token_type tokType;
-
major = gssEapVerifyToken(minor, ctx, inputToken, &tokType,
&unwrappedInputToken);
if (GSS_ERROR(major))
goto cleanup;
- if (tokType != TOK_TYPE_ESTABLISH_CONTEXT) {
+ if (tokType != (CTX_IS_INITIATOR(ctx)
+ ? TOK_TYPE_ACCEPTOR_CONTEXT : TOK_TYPE_INITIATOR_CONTEXT)) {
major = GSS_S_DEFECTIVE_TOKEN;
*minor = GSSEAP_WRONG_TOK_ID;
goto cleanup;
initialContextToken = 1;
}
- if (ctx->state == GSSEAP_STATE_ESTABLISHED) {
+ if (CTX_IS_ESTABLISHED(ctx)) {
major = GSS_S_BAD_STATUS;
*minor = GSSEAP_CONTEXT_ESTABLISHED;
goto cleanup;
enum gss_eap_state oldState = ctx->state;
smFlags = 0;
+ if (inputTokenType != NULL && (*inputTokenType & ITOK_FLAG_CRITICAL))
+ smFlags |= SM_FLAG_INPUT_TOKEN_CRITICAL;
major = smp->processToken(minor, cred, ctx, target, mech, reqFlags,
timeReq, chanBindings, innerInputToken,
if (inputTokenType != NULL)
*inputTokenType |= ITOK_FLAG_VERIFIED;
- if (ctx->state != oldState)
+ if (ctx->state < oldState)
+ i = 0; /* restart */
+ else 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)
+ if (smFlags & SM_FLAG_OUTPUT_TOKEN_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.
+ * Break out 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))) {
+ if ((smFlags & SM_FLAG_TRANSITED) &&
+ ((smFlags & SM_FLAG_FORCE_SEND_TOKEN) || innerOutputTokens->count != 0)) {
SM_ASSERT_VALID(ctx, major);
break;
}
/* Format output token from inner tokens */
if (innerOutputTokens->count != 0 || /* inner tokens to send */
!CTX_IS_INITIATOR(ctx) || /* any leg acceptor */
- ctx->state != GSSEAP_STATE_ESTABLISHED) { /* non-last leg initiator */
+ !CTX_IS_ESTABLISHED(ctx)) { /* non-last leg initiator */
tmpMajor = gssEapEncodeInnerTokens(&tmpMinor, innerOutputTokens,
outputTokenTypes, &unwrappedOutputToken);
if (tmpMajor == GSS_S_COMPLETE) {
+ if (CTX_IS_INITIATOR(ctx))
+ tokType = TOK_TYPE_INITIATOR_CONTEXT;
+ else
+ tokType = TOK_TYPE_ACCEPTOR_CONTEXT;
+
tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &unwrappedOutputToken,
- TOK_TYPE_ESTABLISH_CONTEXT, outputToken);
+ tokType, outputToken);
if (GSS_ERROR(tmpMajor)) {
major = tmpMajor;
*minor = tmpMinor;
}
}
+ /* If the context is established, empty tokens only to be emitted by initiator */
+ assert(!CTX_IS_ESTABLISHED(ctx) || ((outputToken->length == 0) == CTX_IS_INITIATOR(ctx)));
+
SM_ASSERT_VALID(ctx, major);
cleanup: