From ef48a45a71b3ba7efd00d6c570e862f4748e74d7 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Wed, 9 Mar 2011 16:34:55 +1100 Subject: [PATCH] implement preliminary acceptor name exchange --- accept_sec_context.c | 55 ++++++++++++++++++++------- gsseap_err.et | 1 + init_sec_context.c | 102 +++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 116 insertions(+), 42 deletions(-) diff --git a/accept_sec_context.c b/accept_sec_context.c index 608ec58..1690937 100644 --- a/accept_sec_context.c +++ b/accept_sec_context.c @@ -124,6 +124,34 @@ acceptReadyEap(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred) return GSS_S_COMPLETE; } +static OM_uint32 +eapGssSmAcceptAcceptorName(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, + OM_uint32 *smFlags) +{ + OM_uint32 major; + + /* XXX TODO import and validate name from inputToken */ + + if (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; + } + + return GSS_S_CONTINUE_NEEDED; +} + #ifdef GSSEAP_DEBUG static OM_uint32 eapGssSmAcceptVendorInfo(OM_uint32 *minor, @@ -177,14 +205,6 @@ eapGssSmAcceptIdentity(OM_uint32 *minor, return GSS_S_DEFECTIVE_TOKEN; } - assert(ctx->acceptorName == GSS_C_NO_NAME); - - if (cred->name != GSS_C_NO_NAME) { - major = gssEapDuplicateName(minor, cred->name, &ctx->acceptorName); - if (GSS_ERROR(major)) - return major; - } - reqData = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 0, EAP_CODE_REQUEST, 0); if (reqData == NULL) { @@ -690,6 +710,13 @@ eapGssSmAcceptCompleteAcceptorExts(OM_uint32 *minor, } static struct gss_eap_sm eapGssAcceptorSm[] = { + { + ITOK_TYPE_ACCEPTOR_NAME_REQ, + ITOK_TYPE_ACCEPTOR_NAME_RESP, + GSSEAP_STATE_INITIAL, + 0, + eapGssSmAcceptAcceptorName + }, #ifdef GSSEAP_DEBUG { ITOK_TYPE_VENDOR_INFO, @@ -813,6 +840,12 @@ gss_accept_sec_context(OM_uint32 *minor, GSSEAP_MUTEX_LOCK(&cred->mutex); + if (cred->name != GSS_C_NO_NAME) { + major = gssEapDuplicateName(minor, cred->name, &ctx->acceptorName); + if (GSS_ERROR(major)) + goto cleanup; + } + major = gssEapSmStep(minor, cred, ctx, @@ -878,12 +911,6 @@ acceptReadyKrb(OM_uint32 *minor, if (GSS_ERROR(major)) return major; - if (cred->name != GSS_C_NO_NAME) { - major = gssEapDuplicateName(minor, cred->name, &ctx->acceptorName); - if (GSS_ERROR(major)) - return major; - } - major = gssEapReauthComplete(minor, ctx, cred, mech, timeRec); if (GSS_ERROR(major)) return major; diff --git a/gsseap_err.et b/gsseap_err.et index 369d2b8..f76b7d9 100644 --- a/gsseap_err.et +++ b/gsseap_err.et @@ -69,6 +69,7 @@ error_code GSSEAP_BAD_CONTEXT_OPTION, "Bad context option" error_code GSSEAP_BAD_SERVICE_NAME, "Name is not a valid service name" error_code GSSEAP_BAD_INITIATOR_NAME, "Initiator identity must be a valid name" error_code GSSEAP_NO_HOSTNAME, "Could not determine local host name" +error_code GSSEAP_NO_ACCEPTOR_NAME, "Could not determine acceptor identity" # # Credential errors diff --git a/init_sec_context.c b/init_sec_context.c index 9966090..a9dadda 100644 --- a/init_sec_context.c +++ b/init_sec_context.c @@ -326,8 +326,7 @@ initBegin(OM_uint32 *minor, gss_OID mech, OM_uint32 reqFlags, OM_uint32 timeReq, - gss_channel_bindings_t chanBindings, - gss_buffer_t inputToken) + gss_channel_bindings_t chanBindings) { OM_uint32 major; @@ -349,16 +348,18 @@ 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)) { @@ -442,12 +443,6 @@ eapGssSmInitGssReauth(OM_uint32 *minor, 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; @@ -518,6 +513,50 @@ eapGssSmInitVendorInfo(OM_uint32 *minor, #endif static OM_uint32 +eapGssSmInitAcceptorName(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, + OM_uint32 *smFlags) +{ + 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->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_ctx_id_t ctx, @@ -530,7 +569,6 @@ eapGssSmInitIdentity(OM_uint32 *minor, gss_buffer_t outputToken, OM_uint32 *smFlags) { - OM_uint32 major; struct eap_config eapConfig; if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE) { @@ -545,12 +583,6 @@ eapGssSmInitIdentity(OM_uint32 *minor, assert((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0); assert(inputToken == GSS_C_NO_BUFFER); - major = initBegin(minor, cred, ctx, target, mech, - reqFlags, timeReq, chanBindings, - inputToken); - if (GSS_ERROR(major)) - return major; - memset(&eapConfig, 0, sizeof(eapConfig)); ctx->initiatorCtx.eap = eap_peer_sm_init(ctx, @@ -759,7 +791,14 @@ static struct gss_eap_sm eapGssInitiatorSm[] = { ITOK_TYPE_NONE, GSSEAP_STATE_ALL & ~(GSSEAP_STATE_INITIAL), SM_ITOK_FLAG_CRITICAL, - eapGssSmInitError, + eapGssSmInitError + }, + { + ITOK_TYPE_ACCEPTOR_NAME_RESP, + ITOK_TYPE_ACCEPTOR_NAME_REQ, + GSSEAP_STATE_INITIAL | GSSEAP_STATE_AUTHENTICATE, + 0, + eapGssSmInitAcceptorName }, #ifdef GSSEAP_DEBUG { @@ -767,7 +806,7 @@ static struct gss_eap_sm eapGssInitiatorSm[] = { ITOK_TYPE_VENDOR_INFO, GSSEAP_STATE_INITIAL, 0, - eapGssSmInitVendorInfo, + eapGssSmInitVendorInfo }, #endif #ifdef GSSEAP_ENABLE_REAUTH @@ -776,7 +815,7 @@ static struct gss_eap_sm eapGssInitiatorSm[] = { ITOK_TYPE_REAUTH_REQ, GSSEAP_STATE_INITIAL | GSSEAP_STATE_REAUTHENTICATE, 0, - eapGssSmInitGssReauth, + eapGssSmInitGssReauth }, #endif { @@ -784,21 +823,21 @@ static struct gss_eap_sm eapGssInitiatorSm[] = { ITOK_TYPE_NONE, GSSEAP_STATE_INITIAL | GSSEAP_STATE_REAUTHENTICATE, SM_ITOK_FLAG_CRITICAL | SM_ITOK_FLAG_REQUIRED, - eapGssSmInitIdentity, + eapGssSmInitIdentity }, { ITOK_TYPE_EAP_REQ, ITOK_TYPE_EAP_RESP, GSSEAP_STATE_AUTHENTICATE, SM_ITOK_FLAG_CRITICAL | SM_ITOK_FLAG_REQUIRED, - eapGssSmInitAuthenticate, + eapGssSmInitAuthenticate }, { ITOK_TYPE_NONE, ITOK_TYPE_GSS_CHANNEL_BINDINGS, GSSEAP_STATE_INITIATOR_EXTS, SM_ITOK_FLAG_CRITICAL | SM_ITOK_FLAG_REQUIRED, - eapGssSmInitGssChannelBindings, + eapGssSmInitGssChannelBindings }, { ITOK_TYPE_NONE, @@ -813,7 +852,7 @@ static struct gss_eap_sm eapGssInitiatorSm[] = { ITOK_TYPE_NONE, GSSEAP_STATE_ACCEPTOR_EXTS, 0, - eapGssSmInitReauthCreds, + eapGssSmInitReauthCreds }, #endif /* other extensions go here */ @@ -861,6 +900,13 @@ gss_init_sec_context(OM_uint32 *minor, ctx->flags |= CTX_FLAG_INITIATOR; + major = initBegin(minor, cred, ctx, target_name, mech_type, + req_flags, time_req, input_chan_bindings); + if (GSS_ERROR(major)) { + gssEapReleaseContext(minor, &ctx); + return major; + } + *context_handle = ctx; } -- 2.1.4