X-Git-Url: http://www.project-moonshot.org/gitweb/?p=moonshot.git;a=blobdiff_plain;f=moonshot%2Fmech_eap%2Futil_context.c;h=78c3636ab55628e74a2392431cb5273c1182afa9;hp=8ff6c50d6909f9d7828b86de1707bcb0dca4c805;hb=9da959f11ebc69e0ae63bc3464b258d161d01cd2;hpb=021ec0ef21578fee64f811400b2b243cb6efe734 diff --git a/moonshot/mech_eap/util_context.c b/moonshot/mech_eap/util_context.c index 8ff6c50..78c3636 100644 --- a/moonshot/mech_eap/util_context.c +++ b/moonshot/mech_eap/util_context.c @@ -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; @@ -120,21 +120,22 @@ 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 } +#endif /* GSSEAP_ENABLE_ACCEPTOR */ krb5_free_keyblock_contents(krbContext, &ctx->rfc3961Key); gssEapReleaseName(&tmpMinor, &ctx->initiatorName); gssEapReleaseName(&tmpMinor, &ctx->acceptorName); gssEapReleaseOid(&tmpMinor, &ctx->mechanismUsed); sequenceFree(&tmpMinor, &ctx->seqState); - gssEapReleaseCred(&tmpMinor, &ctx->defaultCred); + gssEapReleaseCred(&tmpMinor, &ctx->cred); GSSEAP_MUTEX_DESTROY(&ctx->mutex); @@ -155,6 +156,8 @@ gssEapMakeToken(OM_uint32 *minor, { unsigned char *p; + assert(ctx->mechanismUsed != GSS_C_NO_OID); + outputToken->length = tokenSize(ctx->mechanismUsed, innerToken->length); outputToken->value = GSSEAP_MALLOC(outputToken->length); if (outputToken->value == NULL) { @@ -232,3 +235,149 @@ 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; + + 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 */ + 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) { + assert(tokenMIC->length >= 16); + + assert(i < 2 + (3 * tokens->buffers.count)); + + iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[i].buffer.length = 16; + iov[i].buffer.value = tokenMIC->value; + i++; + + iov[i].type = GSS_IOV_BUFFER_TYPE_TRAILER; + iov[i].buffer.length = tokenMIC->length - 16; + iov[i].buffer.value = (unsigned char *)tokenMIC->value + 16; + 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); +}