X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=moonshot%2Fmech_eap%2Faccept_sec_context.c;h=9a77714e4737692ee5f9683ac8a4e673e7e61b1e;hb=3e139a96a0be2caa9d0e14a8d700ba55017aa7f0;hp=d010e34fb71b6de10f5a17a2bade707b613534ce;hpb=718b3c72ced52cc2f70abc45f2df13ee5d9a5cec;p=moonshot.git diff --git a/moonshot/mech_eap/accept_sec_context.c b/moonshot/mech_eap/accept_sec_context.c index d010e34..9a77714 100644 --- a/moonshot/mech_eap/accept_sec_context.c +++ b/moonshot/mech_eap/accept_sec_context.c @@ -328,7 +328,7 @@ setAcceptorIdentity(OM_uint32 *minor, krb5_principal krbPrinc; struct rs_context *rc = ctx->acceptorCtx.radContext; - assert(rc != NULL); + GSSEAP_ASSERT(rc != NULL); if (ctx->acceptorName == GSS_C_NO_NAME) { *minor = 0; @@ -343,8 +343,8 @@ setAcceptorIdentity(OM_uint32 *minor, GSSEAP_KRB_INIT(&krbContext); krbPrinc = ctx->acceptorName->krbPrincipal; - assert(krbPrinc != NULL); - assert(KRB_PRINC_LENGTH(krbPrinc) >= 2); + GSSEAP_ASSERT(krbPrinc != NULL); + GSSEAP_ASSERT(KRB_PRINC_LENGTH(krbPrinc) >= 2); /* Acceptor-Service-Name */ krbPrincComponentToGssBuffer(krbPrinc, 0, &nameBuf); @@ -418,58 +418,35 @@ createRadiusHandle(OM_uint32 *minor, gss_ctx_id_t ctx) { struct gss_eap_acceptor_ctx *actx = &ctx->acceptorCtx; - const char *configFile = RS_CONFIG_FILE; - const char *configStanza = "gss-eap"; - struct rs_alloc_scheme ralloc; struct rs_error *err; + const char *configStanza = "gss-eap"; + OM_uint32 major; - assert(actx->radContext == NULL); - assert(actx->radConn == NULL); + GSSEAP_ASSERT(actx->radContext == NULL); + GSSEAP_ASSERT(actx->radConn == NULL); + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL); - if (rs_context_create(&actx->radContext) != 0) { - *minor = GSSEAP_RADSEC_CONTEXT_FAILURE; - return GSS_S_FAILURE; - } + major = gssEapCreateRadiusContext(minor, cred, &actx->radContext); + if (GSS_ERROR(major)) + return major; - if (cred->radiusConfigFile.value != NULL) - configFile = (const char *)cred->radiusConfigFile.value; if (cred->radiusConfigStanza.value != NULL) configStanza = (const char *)cred->radiusConfigStanza.value; - ralloc.calloc = GSSEAP_CALLOC; - ralloc.malloc = GSSEAP_MALLOC; - ralloc.free = GSSEAP_FREE; - ralloc.realloc = GSSEAP_REALLOC; - - rs_context_set_alloc_scheme(actx->radContext, &ralloc); - - if (rs_context_read_config(actx->radContext, configFile) != 0) { - err = rs_err_ctx_pop(actx->radContext); - goto fail; - } - - if (rs_context_init_freeradius_dict(actx->radContext, NULL) != 0) { - err = rs_err_ctx_pop(actx->radContext); - goto fail; - } - if (rs_conn_create(actx->radContext, &actx->radConn, configStanza) != 0) { err = rs_err_conn_pop(actx->radConn); - goto fail; + return gssEapRadiusMapError(minor, err); } if (actx->radServer != NULL) { if (rs_conn_select_peer(actx->radConn, actx->radServer) != 0) { err = rs_err_conn_pop(actx->radConn); - goto fail; + return gssEapRadiusMapError(minor, err); } } *minor = 0; return GSS_S_COMPLETE; - -fail: - return gssEapRadiusMapError(minor, err); } /* @@ -550,7 +527,7 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, goto cleanup; } - assert(resp != NULL); + GSSEAP_ASSERT(resp != NULL); frresp = rs_packet_frpkt(resp); switch (frresp->code) { @@ -606,7 +583,7 @@ cleanup: if (resp != NULL) rs_packet_destroy(resp); if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIATOR_EXTS) { - assert(major == GSS_S_CONTINUE_NEEDED); + GSSEAP_ASSERT(major == GSS_S_CONTINUE_NEEDED); rs_conn_destroy(ctx->acceptorCtx.radConn); ctx->acceptorCtx.radConn = NULL; @@ -631,7 +608,7 @@ eapGssSmAcceptGssFlags(OM_uint32 *minor, unsigned char *p; OM_uint32 initiatorGssFlags; - assert((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0); + GSSEAP_ASSERT((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0); if (inputToken->length < 4) { *minor = GSSEAP_TOK_TRUNC; @@ -662,39 +639,41 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, gss_buffer_t outputToken GSSEAP_UNUSED, OM_uint32 *smFlags GSSEAP_UNUSED) { - OM_uint32 major; - gss_iov_buffer_desc iov[2]; + krb5_error_code code; + krb5_context krbContext; + krb5_data data; + krb5_checksum cksum; + krb5_boolean valid = FALSE; - iov[0].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE; - iov[0].buffer.length = 0; - iov[0].buffer.value = NULL; + if (chanBindings == GSS_C_NO_CHANNEL_BINDINGS || + chanBindings->application_data.length == 0) + return GSS_S_CONTINUE_NEEDED; - iov[1].type = GSS_IOV_BUFFER_TYPE_STREAM | GSS_IOV_BUFFER_FLAG_ALLOCATED; + GSSEAP_KRB_INIT(&krbContext); - /* XXX necessary because decrypted in place and we verify it later */ - major = duplicateBuffer(minor, inputToken, &iov[1].buffer); - if (GSS_ERROR(major)) - return major; + KRB_DATA_INIT(&data); - major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL, - iov, 2, TOK_TYPE_WRAP); - if (GSS_ERROR(major)) { - gssEapReleaseIov(iov, 2); - return major; + gssBufferToKrbData(&chanBindings->application_data, &data); + + KRB_CHECKSUM_INIT(&cksum, ctx->checksumType, inputToken); + + code = krb5_c_verify_checksum(krbContext, &ctx->rfc3961Key, + KEY_USAGE_GSSEAP_CHBIND_MIC, + &data, &cksum, &valid); + if (code != 0) { + *minor = code; + return GSS_S_FAILURE; } - if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS && - !bufferEqual(&iov[0].buffer, &chanBindings->application_data)) { - major = GSS_S_BAD_BINDINGS; + if (valid == FALSE) { *minor = GSSEAP_BINDINGS_MISMATCH; - } else { - major = GSS_S_CONTINUE_NEEDED; - *minor = 0; + return GSS_S_BAD_BINDINGS; } - gssEapReleaseIov(iov, 2); + ctx->flags |= CTX_FLAG_CHANNEL_BINDINGS_VERIFIED; - return major; + *minor = 0; + return GSS_S_CONTINUE_NEEDED; } static OM_uint32 @@ -705,13 +684,27 @@ eapGssSmAcceptInitiatorMIC(OM_uint32 *minor, gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, - gss_channel_bindings_t chanBindings GSSEAP_UNUSED, + gss_channel_bindings_t chanBindings, gss_buffer_t inputToken, gss_buffer_t outputToken GSSEAP_UNUSED, OM_uint32 *smFlags GSSEAP_UNUSED) { OM_uint32 major; + /* + * The channel binding token is optional, however if the caller indicated + * bindings we must raise an error if it was absent. + * + * In the future, we might use a context option to allow the caller to + * indicate that missing bindings are acceptable. + */ + if (chanBindings != NULL && + chanBindings->application_data.length != 0 && + (ctx->flags & CTX_FLAG_CHANNEL_BINDINGS_VERIFIED) == 0) { + *minor = GSSEAP_MISSING_BINDINGS; + return GSS_S_BAD_BINDINGS; + } + major = gssEapVerifyTokenMIC(minor, ctx, inputToken); if (GSS_ERROR(major)) return major; @@ -830,7 +823,7 @@ static struct gss_eap_sm eapGssAcceptorSm[] = { ITOK_TYPE_GSS_CHANNEL_BINDINGS, ITOK_TYPE_NONE, GSSEAP_STATE_INITIATOR_EXTS, - SM_ITOK_FLAG_REQUIRED, + 0, eapGssSmAcceptGssChannelBindings, }, { @@ -890,7 +883,11 @@ gssEapAcceptSecContext(OM_uint32 *minor, cred = ctx->cred; } - GSSEAP_MUTEX_LOCK(&cred->mutex); + /* + * Previously we acquired the credential mutex here, but it should not be + * necessary as the acceptor does not access any mutable elements of the + * credential handle. + */ /* * Calling gssEapInquireCred() forces the default acceptor credential name @@ -943,12 +940,9 @@ gssEapAcceptSecContext(OM_uint32 *minor, } } - assert(CTX_IS_ESTABLISHED(ctx) || major == GSS_S_CONTINUE_NEEDED); + GSSEAP_ASSERT(CTX_IS_ESTABLISHED(ctx) || major == GSS_S_CONTINUE_NEEDED); cleanup: - if (cred != GSS_C_NO_CREDENTIAL) - GSSEAP_MUTEX_UNLOCK(&cred->mutex); - return major; }