X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=mech_eap%2Futil_context.c;h=b7a50c6150aba3fb6bc857db9ede37fc7fd00c97;hb=3f993b33bfbccc6ac801d665a3d77a6f911ff74a;hp=78c3636ab55628e74a2392431cb5273c1182afa9;hpb=4609bebeb14712d07fd7d4a08726bb3f49781192;p=mech_eap.git diff --git a/mech_eap/util_context.c b/mech_eap/util_context.c index 78c3636..b7a50c6 100644 --- a/mech_eap/util_context.c +++ b/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) { @@ -156,7 +156,7 @@ gssEapMakeToken(OM_uint32 *minor, { unsigned char *p; - assert(ctx->mechanismUsed != GSS_C_NO_OID); + GSSEAP_ASSERT(ctx->mechanismUsed != GSS_C_NO_OID); outputToken->length = tokenSize(ctx->mechanismUsed, innerToken->length); outputToken->value = GSSEAP_MALLOC(outputToken->length); @@ -214,7 +214,7 @@ gssEapVerifyToken(OM_uint32 *minor, OM_uint32 gssEapContextTime(OM_uint32 *minor, - gss_ctx_id_t context_handle, + gss_const_ctx_id_t context_handle, OM_uint32 *time_rec) { *minor = 0; @@ -243,21 +243,45 @@ gssEapMakeOrVerifyTokenMIC(OM_uint32 *minor, 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; + ssize_t checksumIndex = -1; + + krb5_keyusage usage; + krb5_error_code code = 0; + krb5_context krbContext; + krb5_crypto_iov *kiov = NULL; +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto krbCrypto = NULL; + krb5_cksumtype cksumType; +#endif + size_t kiovCount; + + GSSEAP_KRB_INIT(&krbContext); tokens = verifyMIC ? ctx->inputTokens : ctx->outputTokens; - assert(tokens != NULL); + GSSEAP_ASSERT(tokens != NULL); - iov = GSSEAP_CALLOC(2 + (3 * tokens->buffers.count) + 1, sizeof(*iov)); - if (iov == NULL) { - major = GSS_S_FAILURE; +#ifdef HAVE_HEIMDAL_VERSION + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key, ETYPE_NULL, &krbCrypto); + if (code != 0) + goto cleanup; +#endif + + kiovCount = 2 + (3 * tokens->buffers.count) + 1; + + if (verifyMIC) { + assert(tokens->buffers.count != 0); + kiovCount -= 3; + } + + kiov = GSSEAP_CALLOC(kiovCount, sizeof(*kiov)); + if (kiov == NULL) { *minor = ENOMEM; goto cleanup; } @@ -265,95 +289,150 @@ gssEapMakeOrVerifyTokenMIC(OM_uint32 *minor, 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; + GSSEAP_ASSERT(ctx->mechanismUsed != GSS_C_NO_OID); + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + kiov[i].data.length = ctx->mechanismUsed->length; + kiov[i].data.data = ctx->mechanismUsed->elements; i++; /* Token type */ if (CTX_IS_INITIATOR(ctx) ^ verifyMIC) { tokType = TOK_TYPE_INITIATOR_CONTEXT; micTokType = ITOK_TYPE_INITIATOR_MIC; + usage = KEY_USAGE_GSSEAP_INITOKEN_MIC; } else { tokType = TOK_TYPE_ACCEPTOR_CONTEXT; micTokType = ITOK_TYPE_ACCEPTOR_MIC; + usage = KEY_USAGE_GSSEAP_ACCTOKEN_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; + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + kiov[i].data.length = sizeof(wireTokType); + kiov[i].data.data = (char *)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 */ + (tokens->types[j] & ITOK_TYPE_MASK) == micTokType) { + continue; + } - iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; - iov[i].buffer.length = 4; - iov[i].buffer.value = &innerTokTypes[j * 4]; + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + kiov[i].data.length = 4; + kiov[i].data.data = (char *)&innerTokTypes[j * 4]; store_uint32_be(tokens->types[j] & ~(ITOK_FLAG_VERIFIED), - iov[i].buffer.value); + kiov[i].data.data); i++; - iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; - iov[i].buffer.length = 4; - iov[i].buffer.value = &innerTokLengths[j * 4]; + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + kiov[i].data.length = 4; + kiov[i].data.data = (char *)&innerTokLengths[j * 4]; store_uint32_be(tokens->buffers.elements[j].length, - iov[i].buffer.value); + kiov[i].data.data); i++; - iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; - iov[i].buffer = tokens->buffers.elements[j]; + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + gssBufferToKrbData(&tokens->buffers.elements[j], &kiov[i].data); i++; } + kiov[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; if (verifyMIC) { - assert(tokenMIC->length >= 16); - - assert(i < 2 + (3 * tokens->buffers.count)); + gssBufferToKrbData(tokenMIC, &kiov[i].data); + } else { + size_t checksumSize; + +#ifdef HAVE_HEIMDAL_VERSION + code = krb5_checksumsize(krbContext, ctx->checksumType, + &checksumSize); +#else + code = krb5_c_checksum_length(krbContext, ctx->checksumType, + &checksumSize); +#endif + if (code != 0) + goto cleanup; + + kiov[i].data.data = GSSEAP_MALLOC(checksumSize); + if (kiov[i].data.data == NULL) { + code = ENOMEM; + goto cleanup; + } + kiov[i].data.length = checksumSize; + checksumIndex = i; + } + i++; + GSSEAP_ASSERT(i == kiovCount); - iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER; - iov[i].buffer.length = 16; - iov[i].buffer.value = tokenMIC->value; - i++; +#ifdef HAVE_HEIMDAL_VERSION + cksumType = ctx->checksumType; - 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++; + if (verifyMIC) { + code = krb5_verify_checksum_iov(krbContext, krbCrypto, usage, + kiov, i, &cksumType); + } else { + code = krb5_create_checksum_iov(krbContext, krbCrypto, usage, + kiov, i, &cksumType); + } +#else + if (verifyMIC) { + krb5_boolean kvalid = FALSE; - major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL, - iov, i, TOK_TYPE_MIC); + code = krb5_c_verify_checksum_iov(krbContext, ctx->checksumType, + &ctx->rfc3961Key, + usage, kiov, i, &kvalid); + if (code == 0 && !kvalid) { + code = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } } 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; + code = krb5_c_make_checksum_iov(krbContext, ctx->checksumType, + &ctx->rfc3961Key, + usage, kiov, i); + } +#endif /* HAVE_HEIMDAL_VERSION */ + + if (code == 0 && !verifyMIC) { + krbDataToGssBuffer(&kiov[checksumIndex].data, tokenMIC); + checksumIndex = -1; } cleanup: - if (iov != NULL) - gssEapReleaseIov(iov, tokens->buffers.count); + if (checksumIndex != -1) + GSSEAP_FREE(kiov[checksumIndex].data.data); + if (kiov != NULL) + GSSEAP_FREE(kiov); if (innerTokTypes != NULL) GSSEAP_FREE(innerTokTypes); if (innerTokLengths != NULL) GSSEAP_FREE(innerTokLengths); +#ifdef HAVE_HEIMDAL_VERSION + if (krbCrypto != NULL) + krb5_crypto_destroy(krbContext, krbCrypto); +#endif + + *minor = code; + + switch (code) { + case KRB5KRB_AP_ERR_BAD_INTEGRITY: + major = GSS_S_BAD_SIG; + break; + case 0: + major = GSS_S_COMPLETE; + break; + default: + major = GSS_S_FAILURE; + break; + } return major; } @@ -374,10 +453,5 @@ 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); }