X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=moonshot%2Fmech_eap%2Futil_context.c;h=e18edc5a9b6de72e7a547a0b0295557e715f4e0b;hb=e4b199e2a05705c453da2250b17cf3c7e4135dda;hp=054fa0f5dcbb718641721965f89d865bb72a285d;hpb=5d9213b9b590926801deffb121ab8eb01eb858ad;p=moonshot.git diff --git a/moonshot/mech_eap/util_context.c b/moonshot/mech_eap/util_context.c index 054fa0f..e18edc5 100644 --- a/moonshot/mech_eap/util_context.c +++ b/moonshot/mech_eap/util_context.c @@ -43,7 +43,7 @@ gssEapAllocContext(OM_uint32 *minor, OM_uint32 tmpMinor; gss_ctx_id_t ctx; - assert(*pCtx == GSS_C_NO_CONTEXT); + GSSEAP_ASSERT(*pCtx == GSS_C_NO_CONTEXT); ctx = (gss_ctx_id_t)GSSEAP_CALLOC(1, sizeof(*ctx)); if (ctx == NULL) { @@ -52,12 +52,13 @@ gssEapAllocContext(OM_uint32 *minor, } if (GSSEAP_MUTEX_INIT(&ctx->mutex) != 0) { - *minor = errno; + *minor = GSSEAP_GET_LAST_ERROR(); gssEapReleaseContext(&tmpMinor, &ctx); return GSS_S_FAILURE; } ctx->state = GSSEAP_STATE_INITIAL; + ctx->mechanismUsed = GSS_C_NO_OID; /* * Integrity, confidentiality, sequencing and replay detection are @@ -70,8 +71,7 @@ gssEapAllocContext(OM_uint32 *minor, GSS_C_INTEG_FLAG | /* integrity */ GSS_C_CONF_FLAG | /* confidentiality */ GSS_C_SEQUENCE_FLAG | /* sequencing */ - GSS_C_REPLAY_FLAG| /* replay detection */ - GSS_C_MUTUAL_FLAG; /*xxx big hack */ + GSS_C_REPLAY_FLAG; /* replay detection */ *pCtx = ctx; @@ -84,6 +84,7 @@ releaseInitiatorContext(struct gss_eap_initiator_ctx *ctx) eap_peer_sm_deinit(ctx->eap); } +#ifdef GSSEAP_ENABLE_ACCEPTOR static void releaseAcceptorContext(struct gss_eap_acceptor_ctx *ctx) { @@ -99,6 +100,7 @@ releaseAcceptorContext(struct gss_eap_acceptor_ctx *ctx) if (ctx->vps != NULL) gssEapRadiusFreeAvps(&tmpMinor, &ctx->vps); } +#endif /* GSSEAP_ENABLE_ACCEPTOR */ OM_uint32 gssEapReleaseContext(OM_uint32 *minor, @@ -118,12 +120,15 @@ gssEapReleaseContext(OM_uint32 *minor, if (ctx->flags & CTX_FLAG_KRB_REAUTH) { gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER); } else -#endif +#endif /* GSSEAP_ENABLE_REAUTH */ if (CTX_IS_INITIATOR(ctx)) { releaseInitiatorContext(&ctx->initiatorCtx); - } else { + } +#ifdef GSSEAP_ENABLE_ACCEPTOR + else { releaseAcceptorContext(&ctx->acceptorCtx); } +#endif /* GSSEAP_ENABLE_ACCEPTOR */ krb5_free_keyblock_contents(krbContext, &ctx->rfc3961Key); gssEapReleaseName(&tmpMinor, &ctx->initiatorName); @@ -151,6 +156,8 @@ gssEapMakeToken(OM_uint32 *minor, { unsigned char *p; + GSSEAP_ASSERT(ctx->mechanismUsed != GSS_C_NO_OID); + outputToken->length = tokenSize(ctx->mechanismUsed, innerToken->length); outputToken->value = GSSEAP_MALLOC(outputToken->length); if (outputToken->value == NULL) { @@ -228,3 +235,143 @@ gssEapContextTime(OM_uint32 *minor, return GSS_S_COMPLETE; } + +static OM_uint32 +gssEapMakeOrVerifyTokenMIC(OM_uint32 *minor, + gss_ctx_id_t ctx, + gss_buffer_t tokenMIC, + int verifyMIC) +{ + OM_uint32 major; + gss_iov_buffer_desc *iov = NULL; + size_t i = 0, j; + enum gss_eap_token_type tokType; + OM_uint32 micTokType; + unsigned char wireTokType[2]; + unsigned char *innerTokTypes = NULL, *innerTokLengths = NULL; + const struct gss_eap_token_buffer_set *tokens; + + tokens = verifyMIC ? ctx->inputTokens : ctx->outputTokens; + + GSSEAP_ASSERT(tokens != NULL); + + iov = GSSEAP_CALLOC(2 + (3 * tokens->buffers.count) + 1, sizeof(*iov)); + if (iov == NULL) { + major = GSS_S_FAILURE; + *minor = ENOMEM; + goto cleanup; + } + + innerTokTypes = GSSEAP_MALLOC(4 * tokens->buffers.count); + if (innerTokTypes == NULL) { + *minor = ENOMEM; + major = GSS_S_FAILURE; + goto cleanup; + } + + innerTokLengths = GSSEAP_MALLOC(4 * tokens->buffers.count); + if (innerTokLengths == NULL) { + major = GSS_S_FAILURE; + *minor = ENOMEM; + goto cleanup; + } + + /* Mechanism OID */ + GSSEAP_ASSERT(ctx->mechanismUsed != GSS_C_NO_OID); + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[i].buffer.length = ctx->mechanismUsed->length; + iov[i].buffer.value = ctx->mechanismUsed->elements; + i++; + + /* Token type */ + if (CTX_IS_INITIATOR(ctx) ^ verifyMIC) { + tokType = TOK_TYPE_INITIATOR_CONTEXT; + micTokType = ITOK_TYPE_INITIATOR_MIC; + } else { + tokType = TOK_TYPE_ACCEPTOR_CONTEXT; + micTokType = ITOK_TYPE_ACCEPTOR_MIC; + } + store_uint16_be(tokType, wireTokType); + + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[i].buffer.length = sizeof(wireTokType); + iov[i].buffer.value = wireTokType; + i++; + + for (j = 0; j < tokens->buffers.count; j++) { + if (verifyMIC && + (tokens->types[j] & ITOK_TYPE_MASK) == micTokType) + continue; /* will use this slot for trailer */ + + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[i].buffer.length = 4; + iov[i].buffer.value = &innerTokTypes[j * 4]; + store_uint32_be(tokens->types[j] & ~(ITOK_FLAG_VERIFIED), + iov[i].buffer.value); + i++; + + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[i].buffer.length = 4; + iov[i].buffer.value = &innerTokLengths[j * 4]; + store_uint32_be(tokens->buffers.elements[j].length, + iov[i].buffer.value); + i++; + + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[i].buffer = tokens->buffers.elements[j]; + i++; + } + + if (verifyMIC) { + GSSEAP_ASSERT(tokenMIC->length >= 16); + + GSSEAP_ASSERT(i < 2 + (3 * tokens->buffers.count)); + + iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[i].buffer = *tokenMIC; + i++; + + major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL, + iov, i, TOK_TYPE_MIC); + } else { + iov[i++].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL, + iov, i, TOK_TYPE_MIC); + if (!GSS_ERROR(major)) + *tokenMIC = iov[i - 1].buffer; + } + +cleanup: + if (iov != NULL) + gssEapReleaseIov(iov, tokens->buffers.count); + if (innerTokTypes != NULL) + GSSEAP_FREE(innerTokTypes); + if (innerTokLengths != NULL) + GSSEAP_FREE(innerTokLengths); + + return major; +} + +OM_uint32 +gssEapMakeTokenMIC(OM_uint32 *minor, + gss_ctx_id_t ctx, + gss_buffer_t tokenMIC) +{ + tokenMIC->length = 0; + tokenMIC->value = NULL; + + return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, FALSE); +} + +OM_uint32 +gssEapVerifyTokenMIC(OM_uint32 *minor, + gss_ctx_id_t ctx, + const gss_buffer_t tokenMIC) +{ + if (tokenMIC->length < 16) { + *minor = GSSEAP_TOK_TRUNC; + return GSS_S_BAD_SIG; + } + + return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, TRUE); +}