X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=mech_eap%2Finit_sec_context.c;h=2e4b23b9c79788fc562bdc646d78b1f84ca4c4b5;hb=e82fcf22c3b6961beae883fc66bf4567896b7c4b;hp=f55aec96a357e3247ba7635ed7fbd41abddd03c1;hpb=315f3c6eea9abad1e3e45bf7b89e63aed1d0419b;p=moonshot.git diff --git a/mech_eap/init_sec_context.c b/mech_eap/init_sec_context.c index f55aec9..2e4b23b 100644 --- a/mech_eap/init_sec_context.c +++ b/mech_eap/init_sec_context.c @@ -161,18 +161,20 @@ peerGetEapReqData(void *ctx) } static void -peerSetConfigBlob(void *ctx, struct wpa_config_blob *blob) +peerSetConfigBlob(void *ctx GSSEAP_UNUSED, + struct wpa_config_blob *blob GSSEAP_UNUSED) { } static const struct wpa_config_blob * -peerGetConfigBlob(void *ctx, const char *name) +peerGetConfigBlob(void *ctx GSSEAP_UNUSED, + const char *name GSSEAP_UNUSED) { return NULL; } static void -peerNotifyPending(void *ctx) +peerNotifyPending(void *ctx GSSEAP_UNUSED) { } @@ -197,13 +199,16 @@ peerConfigInit(OM_uint32 *minor, gss_cred_id_t cred, gss_ctx_id_t ctx) { + OM_uint32 major; krb5_context krbContext; struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig; - krb5_error_code code; - char *identity, *anonymousIdentity; + gss_buffer_desc identity = GSS_C_EMPTY_BUFFER; + gss_buffer_desc realm = GSS_C_EMPTY_BUFFER; eapPeerConfig->identity = NULL; eapPeerConfig->identity_len = 0; + eapPeerConfig->anonymous_identity = NULL; + eapPeerConfig->anonymous_identity_len = 0; eapPeerConfig->password = NULL; eapPeerConfig->password_len = 0; @@ -223,20 +228,29 @@ peerConfigInit(OM_uint32 *minor, return GSS_S_BAD_NAME; } - code = krb5_unparse_name(krbContext, cred->name->krbPrincipal, &identity); - if (code != 0) { - *minor = code; + /* identity */ + major = gssEapDisplayName(minor, cred->name, &identity, NULL); + if (GSS_ERROR(major)) + return major; + + eapPeerConfig->identity = (unsigned char *)identity.value; + eapPeerConfig->identity_len = identity.length; + + krbPrincRealmToGssBuffer(cred->name->krbPrincipal, &realm); + + /* anonymous_identity */ + eapPeerConfig->anonymous_identity = GSSEAP_MALLOC(realm.length + 2); + if (eapPeerConfig->anonymous_identity == NULL) { + *minor = ENOMEM; return GSS_S_FAILURE; } - anonymousIdentity = strchr(identity, '@'); - if (anonymousIdentity == NULL) - anonymousIdentity = ""; + eapPeerConfig->anonymous_identity[0] = '@'; + memcpy(eapPeerConfig->anonymous_identity + 1, realm.value, realm.length); + eapPeerConfig->anonymous_identity[1 + realm.length] = '\0'; + eapPeerConfig->anonymous_identity_len = 1 + realm.length; - eapPeerConfig->identity = (unsigned char *)identity; - eapPeerConfig->identity_len = strlen(identity); - eapPeerConfig->anonymous_identity = (unsigned char *)anonymousIdentity; - eapPeerConfig->anonymous_identity_len = strlen(anonymousIdentity); + /* password */ eapPeerConfig->password = (unsigned char *)cred->password.value; eapPeerConfig->password_len = cred->password.length; @@ -248,12 +262,19 @@ static OM_uint32 peerConfigFree(OM_uint32 *minor, gss_ctx_id_t ctx) { - krb5_context krbContext; struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig; - GSSEAP_KRB_INIT(&krbContext); + if (eapPeerConfig->identity != NULL) { + GSSEAP_FREE(eapPeerConfig->identity); + eapPeerConfig->identity = NULL; + eapPeerConfig->identity_len = 0; + } - krb5_free_unparsed_name(krbContext, (char *)eapPeerConfig->identity); + if (eapPeerConfig->anonymous_identity != NULL) { + GSSEAP_FREE(eapPeerConfig->anonymous_identity); + eapPeerConfig->anonymous_identity = NULL; + eapPeerConfig->anonymous_identity_len = 0; + } *minor = 0; return GSS_S_COMPLETE; @@ -324,10 +345,9 @@ initBegin(OM_uint32 *minor, gss_ctx_id_t ctx, gss_name_t target, gss_OID mech, - OM_uint32 reqFlags, + OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq, - gss_channel_bindings_t chanBindings, - gss_buffer_t inputToken) + gss_channel_bindings_t chanBindings GSSEAP_UNUSED) { OM_uint32 major; @@ -349,25 +369,22 @@ initBegin(OM_uint32 *minor, if (GSS_ERROR(major)) return major; - GSSEAP_MUTEX_LOCK(&target->mutex); + if (target != GSS_C_NO_NAME) { + GSSEAP_MUTEX_LOCK(&target->mutex); + + major = gssEapDuplicateName(minor, target, &ctx->acceptorName); + if (GSS_ERROR(major)) { + GSSEAP_MUTEX_UNLOCK(&target->mutex); + return major; + } - major = gssEapDuplicateName(minor, target, &ctx->acceptorName); - if (GSS_ERROR(major)) { GSSEAP_MUTEX_UNLOCK(&target->mutex); - return major; } - GSSEAP_MUTEX_UNLOCK(&target->mutex); - - if (mech == GSS_C_NULL_OID) { - major = gssEapDefaultMech(minor, &ctx->mechanismUsed); - } else if (gssEapIsConcreteMechanismOid(mech)) { - if (!gssEapInternalizeOid(mech, &ctx->mechanismUsed)) - major = duplicateOid(minor, mech, &ctx->mechanismUsed); - } else { - major = GSS_S_BAD_MECH; - *minor = GSSEAP_WRONG_MECH; - } + major = gssEapCanonicalizeOid(minor, + mech, + OID_FLAG_NULL_VALID | OID_FLAG_MAP_NULL_TO_DEFAULT_MECH, + &ctx->mechanismUsed); if (GSS_ERROR(major)) return major; @@ -383,15 +400,16 @@ initBegin(OM_uint32 *minor, static OM_uint32 eapGssSmInitError(OM_uint32 *minor, - gss_cred_id_t cred, - gss_ctx_id_t ctx, - gss_name_t target, - gss_OID mech, - OM_uint32 reqFlags, - OM_uint32 timeReq, - gss_channel_bindings_t chanBindings, + gss_cred_id_t cred GSSEAP_UNUSED, + gss_ctx_id_t ctx GSSEAP_UNUSED, + gss_name_t target GSSEAP_UNUSED, + gss_OID mech GSSEAP_UNUSED, + OM_uint32 reqFlags GSSEAP_UNUSED, + OM_uint32 timeReq GSSEAP_UNUSED, + gss_channel_bindings_t chanBindings GSSEAP_UNUSED, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken GSSEAP_UNUSED, + OM_uint32 *smFlags GSSEAP_UNUSED) { OM_uint32 major; unsigned char *p; @@ -422,12 +440,13 @@ eapGssSmInitGssReauth(OM_uint32 *minor, gss_cred_id_t cred, gss_ctx_id_t ctx, gss_name_t target, - gss_OID mech, + gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags, OM_uint32 timeReq, gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken, + OM_uint32 *smFlags GSSEAP_UNUSED) { OM_uint32 major, tmpMinor; gss_name_t mechTarget = GSS_C_NO_NAME; @@ -436,16 +455,10 @@ eapGssSmInitGssReauth(OM_uint32 *minor, assert(cred != GSS_C_NO_CREDENTIAL); - if (ctx->state == GSSEAP_STATE_INITIAL) { + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIAL) { if (!gssEapCanReauthP(cred, target, timeReq)) return GSS_S_CONTINUE_NEEDED; - major = initBegin(minor, cred, ctx, target, mech, - reqFlags, timeReq, chanBindings, - inputToken); - if (GSS_ERROR(major)) - goto cleanup; - ctx->flags |= CTX_FLAG_KRB_REAUTH; } else if ((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) { major = GSS_S_DEFECTIVE_TOKEN; @@ -459,10 +472,10 @@ eapGssSmInitGssReauth(OM_uint32 *minor, major = gssInitSecContext(minor, cred->krbCred, - &ctx->kerberosCtx, + &ctx->reauthCtx, mechTarget, (gss_OID)gss_mech_krb5, - reqFlags, + reqFlags | GSS_C_MUTUAL_FLAG, timeReq, chanBindings, inputToken, @@ -476,12 +489,14 @@ eapGssSmInitGssReauth(OM_uint32 *minor, ctx->gssFlags = gssFlags; if (major == GSS_S_COMPLETE) { + assert(GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE); + major = gssEapReauthComplete(minor, ctx, cred, actualMech, timeRec); if (GSS_ERROR(major)) goto cleanup; - ctx->state = GSSEAP_STATE_NEGO_EXT; /* skip */ + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED); } else { - major = GSS_S_COMPLETE; /* advance state */ + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_REAUTHENTICATE); } cleanup: @@ -491,112 +506,184 @@ cleanup: } #endif /* GSSEAP_ENABLE_REAUTH */ +#ifdef GSSEAP_DEBUG +static OM_uint32 +eapGssSmInitVendorInfo(OM_uint32 *minor, + gss_cred_id_t cred GSSEAP_UNUSED, + gss_ctx_id_t ctx GSSEAP_UNUSED, + gss_name_t target GSSEAP_UNUSED, + gss_OID mech GSSEAP_UNUSED, + OM_uint32 reqFlags GSSEAP_UNUSED, + OM_uint32 timeReq GSSEAP_UNUSED, + gss_channel_bindings_t chanBindings GSSEAP_UNUSED, + gss_buffer_t inputToken GSSEAP_UNUSED, + gss_buffer_t outputToken, + OM_uint32 *smFlags GSSEAP_UNUSED) +{ + OM_uint32 major; + + major = makeStringBuffer(minor, "JANET(UK)", outputToken); + if (GSS_ERROR(major)) + return major; + + return GSS_S_CONTINUE_NEEDED; +} +#endif + +static OM_uint32 +eapGssSmInitAcceptorName(OM_uint32 *minor, + gss_cred_id_t cred GSSEAP_UNUSED, + gss_ctx_id_t ctx, + gss_name_t target GSSEAP_UNUSED, + gss_OID mech GSSEAP_UNUSED, + OM_uint32 reqFlags GSSEAP_UNUSED, + OM_uint32 timeReq GSSEAP_UNUSED, + gss_channel_bindings_t chanBindings GSSEAP_UNUSED, + gss_buffer_t inputToken GSSEAP_UNUSED, + gss_buffer_t outputToken, + OM_uint32 *smFlags GSSEAP_UNUSED) +{ + OM_uint32 major; + + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIAL && + ctx->acceptorName != GSS_C_NO_NAME) { + + /* Send desired target name to acceptor */ + major = gssEapDisplayName(minor, ctx->acceptorName, + outputToken, NULL); + if (GSS_ERROR(major)) + return major; + } else if (inputToken != GSS_C_NO_BUFFER && + ctx->acceptorName == GSS_C_NO_NAME) { + /* Accept target name hint from acceptor */ + major = gssEapImportName(minor, inputToken, + GSS_C_NT_USER_NAME, + ctx->mechanismUsed, + &ctx->acceptorName); + if (GSS_ERROR(major)) + return major; + } + + /* + * Currently, other parts of the code assume that the acceptor name + * is available, hence this check. + */ + if (ctx->acceptorName == GSS_C_NO_NAME) { + *minor = GSSEAP_NO_ACCEPTOR_NAME; + return GSS_S_FAILURE; + } + + return GSS_S_CONTINUE_NEEDED; +} + static OM_uint32 eapGssSmInitIdentity(OM_uint32 *minor, - gss_cred_id_t cred, + gss_cred_id_t cred GSSEAP_UNUSED, gss_ctx_id_t ctx, - gss_name_t target, - gss_OID mech, - OM_uint32 reqFlags, - OM_uint32 timeReq, - gss_channel_bindings_t chanBindings, - gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_name_t target GSSEAP_UNUSED, + gss_OID mech GSSEAP_UNUSED, + OM_uint32 reqFlags GSSEAP_UNUSED, + OM_uint32 timeReq GSSEAP_UNUSED, + gss_channel_bindings_t chanBindings GSSEAP_UNUSED, + gss_buffer_t inputToken GSSEAP_UNUSED, + gss_buffer_t outputToken GSSEAP_UNUSED, + OM_uint32 *smFlags) { - OM_uint32 major; - int initialContextToken; + struct eap_config eapConfig; + +#ifdef GSSEAP_ENABLE_REAUTH + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE) { + OM_uint32 tmpMinor; + + /* server didn't support reauthentication, sent EAP request */ + gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER); + ctx->flags &= ~(CTX_FLAG_KRB_REAUTH); + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_INITIAL); + } else +#endif + *smFlags |= SM_FLAG_FORCE_SEND_TOKEN; assert((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0); + assert(inputToken == GSS_C_NO_BUFFER); - initialContextToken = (inputToken->length == 0); - if (!initialContextToken) { - *minor = GSSEAP_WRONG_SIZE; - return GSS_S_DEFECTIVE_TOKEN; + memset(&eapConfig, 0, sizeof(eapConfig)); + + ctx->initiatorCtx.eap = eap_peer_sm_init(ctx, + &gssEapPolicyCallbacks, + ctx, + &eapConfig); + if (ctx->initiatorCtx.eap == NULL) { + *minor = GSSEAP_PEER_SM_INIT_FAILURE; + return GSS_S_FAILURE; } - major = initBegin(minor, cred, ctx, target, mech, - reqFlags, timeReq, chanBindings, - inputToken); - if (GSS_ERROR(major)) - return major; + ctx->flags |= CTX_FLAG_EAP_RESTART | CTX_FLAG_EAP_PORT_ENABLED; - outputToken->length = 0; - outputToken->value = NULL; + /* poke EAP state machine */ + if (eap_peer_sm_step(ctx->initiatorCtx.eap) != 0) { + *minor = GSSEAP_PEER_SM_STEP_FAILURE; + return GSS_S_FAILURE; + } + + GSSEAP_SM_TRANSITION_NEXT(ctx); *minor = 0; - return GSS_S_COMPLETE; /* advance state */ -} -static struct wpabuf emptyWpaBuffer; + return GSS_S_CONTINUE_NEEDED; +} static OM_uint32 eapGssSmInitAuthenticate(OM_uint32 *minor, gss_cred_id_t cred, gss_ctx_id_t ctx, - gss_name_t target, - gss_OID mech, - OM_uint32 reqFlags, - OM_uint32 timeReq, - gss_channel_bindings_t chanBindings, - gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_name_t target GSSEAP_UNUSED, + gss_OID mech GSSEAP_UNUSED, + OM_uint32 reqFlags GSSEAP_UNUSED, + OM_uint32 timeReq GSSEAP_UNUSED, + gss_channel_bindings_t chanBindings GSSEAP_UNUSED, + gss_buffer_t inputToken GSSEAP_UNUSED, + gss_buffer_t outputToken, + OM_uint32 *smFlags) { OM_uint32 major; OM_uint32 tmpMinor; int code; struct wpabuf *resp = NULL; - int initialContextToken; *minor = 0; - initialContextToken = (inputToken == GSS_C_NO_BUFFER || - inputToken->length == 0); + assert(inputToken != GSS_C_NO_BUFFER); major = peerConfigInit(minor, cred, ctx); if (GSS_ERROR(major)) goto cleanup; - if (ctx->initiatorCtx.eap == NULL) { - struct eap_config eapConfig; - - memset(&eapConfig, 0, sizeof(eapConfig)); - - ctx->initiatorCtx.eap = eap_peer_sm_init(ctx, - &gssEapPolicyCallbacks, - ctx, - &eapConfig); - if (ctx->initiatorCtx.eap == NULL) { - major = GSS_S_FAILURE; - *minor = GSSEAP_PEER_SM_INIT_FAILURE; - goto cleanup; - } - - ctx->flags |= CTX_FLAG_EAP_RESTART | CTX_FLAG_EAP_PORT_ENABLED; - } + assert(ctx->initiatorCtx.eap != NULL); + assert(ctx->flags & CTX_FLAG_EAP_PORT_ENABLED); ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */ wpabuf_set(&ctx->initiatorCtx.reqData, inputToken->value, inputToken->length); + major = GSS_S_CONTINUE_NEEDED; + code = eap_peer_sm_step(ctx->initiatorCtx.eap); if (ctx->flags & CTX_FLAG_EAP_RESP) { 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 */ + major = GSS_S_CONTINUE_NEEDED; + GSSEAP_SM_TRANSITION_NEXT(ctx); } 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; @@ -607,7 +694,7 @@ cleanup: OM_uint32 tmpMajor; gss_buffer_desc respBuf; - assert(!GSS_ERROR(major)); + assert(major == GSS_S_CONTINUE_NEEDED); respBuf.length = wpabuf_len(resp); respBuf.value = (void *)wpabuf_head(resp); @@ -617,6 +704,8 @@ cleanup: major = tmpMajor; *minor = tmpMinor; } + + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL; } wpabuf_set(&ctx->initiatorCtx.reqData, NULL, 0); @@ -627,15 +716,16 @@ cleanup: static OM_uint32 eapGssSmInitGssChannelBindings(OM_uint32 *minor, - gss_cred_id_t cred, + gss_cred_id_t cred GSSEAP_UNUSED, gss_ctx_id_t ctx, - gss_name_t target, - gss_OID mech, - OM_uint32 reqFlags, - OM_uint32 timeReq, + gss_name_t target GSSEAP_UNUSED, + gss_OID mech GSSEAP_UNUSED, + OM_uint32 reqFlags GSSEAP_UNUSED, + OM_uint32 timeReq GSSEAP_UNUSED, gss_channel_bindings_t chanBindings, - gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t inputToken GSSEAP_UNUSED, + gss_buffer_t outputToken, + OM_uint32 *smFlags) { OM_uint32 major; gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER; @@ -651,6 +741,8 @@ eapGssSmInitGssChannelBindings(OM_uint32 *minor, assert(outputToken->value != NULL); *minor = 0; + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL; + return GSS_S_CONTINUE_NEEDED; } @@ -659,19 +751,22 @@ static OM_uint32 eapGssSmInitReauthCreds(OM_uint32 *minor, gss_cred_id_t cred, gss_ctx_id_t ctx, - gss_name_t target, - gss_OID mech, - OM_uint32 reqFlags, - OM_uint32 timeReq, - gss_channel_bindings_t chanBindings, + gss_name_t target GSSEAP_UNUSED, + gss_OID mech GSSEAP_UNUSED, + OM_uint32 reqFlags GSSEAP_UNUSED, + OM_uint32 timeReq GSSEAP_UNUSED, + gss_channel_bindings_t chanBindings GSSEAP_UNUSED, gss_buffer_t inputToken, - gss_buffer_t outputToken) + gss_buffer_t outputToken GSSEAP_UNUSED, + OM_uint32 *smFlags GSSEAP_UNUSED) { OM_uint32 major; - major = gssEapStoreReauthCreds(minor, ctx, cred, inputToken); - if (GSS_ERROR(major)) - return major; + if (ctx->gssFlags & GSS_C_MUTUAL_FLAG) { + major = gssEapStoreReauthCreds(minor, ctx, cred, inputToken); + if (GSS_ERROR(major)) + return major; + } *minor = 0; return GSS_S_CONTINUE_NEEDED; @@ -679,83 +774,126 @@ eapGssSmInitReauthCreds(OM_uint32 *minor, #endif /* GSSEAP_ENABLE_REAUTH */ static OM_uint32 -eapGssSmInitNegoExtFinished(OM_uint32 *minor, - gss_cred_id_t cred, - gss_ctx_id_t ctx, - gss_name_t target, - gss_OID mech, - OM_uint32 reqFlags, - OM_uint32 timeReq, - gss_channel_bindings_t chanBindings, - gss_buffer_t inputToken, - gss_buffer_t outputToken) +eapGssSmInitCompleteInitiatorExts(OM_uint32 *minor, + gss_cred_id_t cred GSSEAP_UNUSED, + gss_ctx_id_t ctx, + gss_name_t target GSSEAP_UNUSED, + gss_OID mech GSSEAP_UNUSED, + OM_uint32 reqFlags GSSEAP_UNUSED, + OM_uint32 timeReq GSSEAP_UNUSED, + gss_channel_bindings_t chanBindings GSSEAP_UNUSED, + gss_buffer_t inputToken GSSEAP_UNUSED, + gss_buffer_t outputToken GSSEAP_UNUSED, + OM_uint32 *smFlags) +{ + GSSEAP_SM_TRANSITION_NEXT(ctx); + + *minor = 0; + *smFlags |= SM_FLAG_FORCE_SEND_TOKEN; + + return GSS_S_CONTINUE_NEEDED; +} + +static OM_uint32 +eapGssSmInitCompleteAcceptorExts(OM_uint32 *minor, + gss_cred_id_t cred GSSEAP_UNUSED, + gss_ctx_id_t ctx, + gss_name_t target GSSEAP_UNUSED, + gss_OID mech GSSEAP_UNUSED, + OM_uint32 reqFlags GSSEAP_UNUSED, + OM_uint32 timeReq GSSEAP_UNUSED, + gss_channel_bindings_t chanBindings GSSEAP_UNUSED, + gss_buffer_t inputToken GSSEAP_UNUSED, + gss_buffer_t outputToken GSSEAP_UNUSED, + OM_uint32 *smFlags GSSEAP_UNUSED) { + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED); + *minor = 0; - return GSS_S_COMPLETE; /* advance state */ + + return GSS_S_COMPLETE; } static struct gss_eap_sm eapGssInitiatorSm[] = { { ITOK_TYPE_CONTEXT_ERR, ITOK_TYPE_NONE, - GSSEAP_STATE_ALL, - 1, /* critical */ - 0, /* required */ - eapGssSmInitError, + GSSEAP_STATE_ALL & ~(GSSEAP_STATE_INITIAL), + 0, + eapGssSmInitError + }, + { + ITOK_TYPE_ACCEPTOR_NAME_RESP, + ITOK_TYPE_ACCEPTOR_NAME_REQ, + GSSEAP_STATE_INITIAL | GSSEAP_STATE_AUTHENTICATE, + 0, + eapGssSmInitAcceptorName + }, +#ifdef GSSEAP_DEBUG + { + ITOK_TYPE_NONE, + ITOK_TYPE_VENDOR_INFO, + GSSEAP_STATE_INITIAL, + 0, + eapGssSmInitVendorInfo }, +#endif #ifdef GSSEAP_ENABLE_REAUTH { ITOK_TYPE_REAUTH_RESP, ITOK_TYPE_REAUTH_REQ, - GSSEAP_STATE_INITIAL | GSSEAP_STATE_AUTHENTICATE, - 0, /* critical */ - 0, /* required */ - eapGssSmInitGssReauth, + GSSEAP_STATE_INITIAL | GSSEAP_STATE_REAUTHENTICATE, + 0, + eapGssSmInitGssReauth }, #endif - /* first-leg extensions go here, they should return GSS_S_CONTINUE_NEEDED */ { ITOK_TYPE_NONE, ITOK_TYPE_NONE, +#ifdef GSSEAP_ENABLE_REAUTH + GSSEAP_STATE_REAUTHENTICATE | +#endif GSSEAP_STATE_INITIAL, - 1, /* critical */ - 1, /* required */ - eapGssSmInitIdentity, + SM_ITOK_FLAG_REQUIRED, + eapGssSmInitIdentity }, { ITOK_TYPE_EAP_REQ, ITOK_TYPE_EAP_RESP, GSSEAP_STATE_AUTHENTICATE, - 1, /* critical */ - 1, /* required */ - eapGssSmInitAuthenticate, + SM_ITOK_FLAG_REQUIRED, + eapGssSmInitAuthenticate }, { ITOK_TYPE_NONE, ITOK_TYPE_GSS_CHANNEL_BINDINGS, - GSSEAP_STATE_NEGO_EXT, - 1, /* critical */ - 1, /* required */ - eapGssSmInitGssChannelBindings, + GSSEAP_STATE_INITIATOR_EXTS, + SM_ITOK_FLAG_REQUIRED, + eapGssSmInitGssChannelBindings + }, + { + ITOK_TYPE_NONE, + ITOK_TYPE_NONE, + GSSEAP_STATE_INITIATOR_EXTS, + 0, + eapGssSmInitCompleteInitiatorExts }, #ifdef GSSEAP_ENABLE_REAUTH { ITOK_TYPE_REAUTH_CREDS, ITOK_TYPE_NONE, - GSSEAP_STATE_NEGO_EXT, - 0, /* critical */ - 0, /* required */ - eapGssSmInitReauthCreds, + GSSEAP_STATE_ACCEPTOR_EXTS, + 0, + eapGssSmInitReauthCreds }, #endif /* other extensions go here */ { ITOK_TYPE_NONE, ITOK_TYPE_NONE, - GSSEAP_STATE_NEGO_EXT, - 1, /* critical */ - 1, /* required */ - eapGssSmInitNegoExtFinished + GSSEAP_STATE_ACCEPTOR_EXTS, + 0, + eapGssSmInitCompleteAcceptorExts } }; @@ -794,8 +932,8 @@ gss_init_sec_context(OM_uint32 *minor, return major; ctx->flags |= CTX_FLAG_INITIATOR; - initialContextToken = 1; + *context_handle = ctx; } @@ -821,13 +959,19 @@ gss_init_sec_context(OM_uint32 *minor, GSSEAP_MUTEX_LOCK(&cred->mutex); - if ((cred->flags & CRED_FLAG_INITIATE) == 0) { major = GSS_S_NO_CRED; *minor = GSSEAP_CRED_USAGE_MISMATCH; goto cleanup; } + if (initialContextToken) { + major = initBegin(minor, cred, ctx, target_name, mech_type, + req_flags, time_req, input_chan_bindings); + if (GSS_ERROR(major)) + goto cleanup; + } + major = gssEapSmStep(minor, cred, ctx, @@ -844,15 +988,21 @@ gss_init_sec_context(OM_uint32 *minor, goto cleanup; if (actual_mech_type != NULL) { - if (!gssEapInternalizeOid(ctx->mechanismUsed, actual_mech_type)) - duplicateOid(&tmpMinor, ctx->mechanismUsed, actual_mech_type); + OM_uint32 tmpMajor; + + tmpMajor = gssEapCanonicalizeOid(&tmpMinor, ctx->mechanismUsed, 0, actual_mech_type); + if (GSS_ERROR(tmpMajor)) { + major = tmpMajor; + *minor = tmpMinor; + goto cleanup; + } } if (ret_flags != NULL) *ret_flags = ctx->gssFlags; if (time_rec != NULL) gssEapContextTime(&tmpMinor, ctx, time_rec); - assert(ctx->state == GSSEAP_STATE_ESTABLISHED || major == GSS_S_CONTINUE_NEEDED); + assert(CTX_IS_ESTABLISHED(ctx) || major == GSS_S_CONTINUE_NEEDED); cleanup: if (cred != GSS_C_NO_CREDENTIAL)