X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=mech_eap%2Futil_krb.c;h=f629a321f99535ad04d012debba97c5506927978;hp=88ad6dd202a0556270158eb8c6e584e3d5d5e09c;hb=HEAD;hpb=ccf542544c4add8d720da2e5c9e048bab695732d diff --git a/mech_eap/util_krb.c b/mech_eap/util_krb.c index 88ad6dd..f629a32 100644 --- a/mech_eap/util_krb.c +++ b/mech_eap/util_krb.c @@ -36,24 +36,13 @@ #include "gssapiP_eap.h" -static GSSEAP_THREAD_ONCE krbContextKeyOnce = GSSEAP_ONCE_INITIALIZER; -static GSSEAP_THREAD_KEY krbContextKey; - -static void -destroyKrbContext(void *arg) +void +gssEapDestroyKrbContext(krb5_context context) { - krb5_context context = (krb5_context)arg; - if (context != NULL) krb5_free_context(context); } -static void -createKrbContextKey(void) -{ - GSSEAP_KEY_CREATE(&krbContextKey, destroyKrbContext); -} - static krb5_error_code initKrbContext(krb5_context *pKrbContext) { @@ -79,35 +68,41 @@ initKrbContext(krb5_context *pKrbContext) *pKrbContext = krbContext; cleanup: +#ifdef HAVE_HEIMDAL_VERSION + krb5_xfree(defaultRealm); +#else + krb5_free_default_realm(krbContext, defaultRealm); +#endif + if (code != 0 && krbContext != NULL) krb5_free_context(krbContext); - if (defaultRealm != NULL) - GSSEAP_FREE(defaultRealm); - return code; } OM_uint32 gssEapKerberosInit(OM_uint32 *minor, krb5_context *context) { - *minor = 0; + struct gss_eap_thread_local_data *tld; - GSSEAP_ONCE(&krbContextKeyOnce, createKrbContextKey); - - *context = GSSEAP_GETSPECIFIC(krbContextKey); - if (*context == NULL) { - *minor = initKrbContext(context); - if (*minor == 0) { - if (GSSEAP_SETSPECIFIC(krbContextKey, *context) != 0) { - *minor = errno; - krb5_free_context(*context); - *context = NULL; - } + *minor = 0; + *context = NULL; + + tld = gssEapGetThreadLocalData(); + if (tld != NULL) { + if (tld->krbContext == NULL) { + *minor = initKrbContext(&tld->krbContext); + if (*minor != 0) + tld->krbContext = NULL; } + *context = tld->krbContext; + } else { + *minor = GSSEAP_GET_LAST_ERROR(); } - return *minor == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; + GSSEAP_ASSERT(*context != NULL || *minor != 0); + + return (*minor == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; } /* @@ -118,6 +113,9 @@ gssEapKerberosInit(OM_uint32 *minor, krb5_context *context) * Tn = pseudo-random(KMSK, n || "rfc4121-gss-eap") * L = output key size * K = truncate(L, T1 || T2 || .. || Tn) + * + * The output must be freed by krb5_free_keyblock_contents(), + * not GSSEAP_FREE(). */ OM_uint32 gssEapDeriveRfc3961Key(OM_uint32 *minor, @@ -127,44 +125,48 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, krb5_keyblock *pKey) { krb5_context krbContext; -#ifndef HAVE_HEIMDAL_VERSION +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto krbCrypto = NULL; +#else krb5_data data; #endif - krb5_data ns, t, prfOut; + krb5_data ns, t, derivedKeyData; krb5_keyblock kd; krb5_error_code code; size_t randomLength, keyLength, prfLength; unsigned char constant[4 + sizeof("rfc4121-gss-eap") - 1], *p; ssize_t i, remain; - assert(encryptionType != ENCTYPE_NULL); - - memset(pKey, 0, sizeof(*pKey)); - GSSEAP_KRB_INIT(&krbContext); + GSSEAP_ASSERT(encryptionType != ENCTYPE_NULL); + KRB_KEY_INIT(pKey); KRB_KEY_INIT(&kd); KRB_KEY_TYPE(&kd) = encryptionType; - t.data = NULL; - t.length = 0; + KRB_DATA_INIT(&ns); + KRB_DATA_INIT(&t); + KRB_DATA_INIT(&derivedKeyData); - prfOut.data = NULL; - prfOut.length = 0; +#ifdef HAVE_HEIMDAL_VERSION + code = krb5_enctype_keybits(krbContext, encryptionType, &randomLength); + if (code != 0) + goto cleanup; + randomLength = (randomLength + 7) / 8; /* from mit_glue.c */ + + code = krb5_enctype_keysize(krbContext, encryptionType, &keyLength); + if (code != 0) + goto cleanup; +#else code = krb5_c_keylengths(krbContext, encryptionType, &randomLength, &keyLength); if (code != 0) goto cleanup; +#endif /* HAVE_HEIMDAL_VERSION */ - KRB_KEY_DATA(&kd) = GSSEAP_MALLOC(keyLength); - if (KRB_KEY_DATA(&kd) == NULL) { - code = ENOMEM; - goto cleanup; - } - KRB_KEY_LENGTH(&kd) = keyLength; + /* Convert EAP MSK into a Kerberos key */ - /* Convert MSK into a Kerberos key */ #ifdef HAVE_HEIMDAL_VERSION code = krb5_random_to_key(krbContext, encryptionType, inputKey, MIN(inputKeyLength, randomLength), &kd); @@ -172,8 +174,15 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, data.length = MIN(inputKeyLength, randomLength); data.data = (char *)inputKey; + KRB_KEY_DATA(&kd) = KRB_MALLOC(keyLength); + if (KRB_KEY_DATA(&kd) == NULL) { + code = ENOMEM; + goto cleanup; + } + KRB_KEY_LENGTH(&kd) = keyLength; + code = krb5_c_random_to_key(krbContext, encryptionType, &data, &kd); -#endif +#endif /* HAVE_HEIMDAL_VERSION */ if (code != 0) goto cleanup; @@ -184,31 +193,45 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, ns.data = (char *)constant; /* Plug derivation constant and key into PRF */ +#ifdef HAVE_HEIMDAL_VERSION + code = krb5_crypto_prf_length(krbContext, encryptionType, &prfLength); +#else code = krb5_c_prf_length(krbContext, encryptionType, &prfLength); +#endif if (code != 0) goto cleanup; +#ifdef HAVE_HEIMDAL_VERSION + code = krb5_crypto_init(krbContext, &kd, 0, &krbCrypto); + if (code != 0) + goto cleanup; +#else t.length = prfLength; t.data = GSSEAP_MALLOC(t.length); if (t.data == NULL) { code = ENOMEM; goto cleanup; } +#endif - prfOut.length = randomLength; - prfOut.data = GSSEAP_MALLOC(prfOut.length); - if (prfOut.data == NULL) { + derivedKeyData.length = randomLength; + derivedKeyData.data = GSSEAP_MALLOC(derivedKeyData.length); + if (derivedKeyData.data == NULL) { code = ENOMEM; goto cleanup; } - for (i = 0, p = (unsigned char *)prfOut.data, remain = randomLength; + for (i = 0, p = (unsigned char *)derivedKeyData.data, remain = randomLength; remain > 0; p += t.length, remain -= t.length, i++) { store_uint32_be(i, ns.data); +#ifdef HAVE_HEIMDAL_VERSION + code = krb5_crypto_prf(krbContext, krbCrypto, &ns, &t); +#else code = krb5_c_prf(krbContext, &kd, &ns, &t); +#endif if (code != 0) goto cleanup; @@ -217,31 +240,39 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, /* Finally, convert PRF output into a new key which we will return */ #ifdef HAVE_HEIMDAL_VERSION + krb5_free_keyblock_contents(krbContext, &kd); + KRB_KEY_INIT(&kd); + code = krb5_random_to_key(krbContext, encryptionType, - prfOut.data, prfOut.length, &kd); + derivedKeyData.data, derivedKeyData.length, &kd); #else - code = krb5_c_random_to_key(krbContext, encryptionType, &prfOut, &kd); + code = krb5_c_random_to_key(krbContext, encryptionType, + &derivedKeyData, &kd); #endif if (code != 0) goto cleanup; *pKey = kd; - KRB_KEY_DATA(&kd) = NULL; cleanup: - if (KRB_KEY_DATA(&kd) != NULL) { - memset(KRB_KEY_DATA(&kd), 0, KRB_KEY_LENGTH(&kd)); - GSSEAP_FREE(KRB_KEY_DATA(&kd)); - } + if (code != 0) + krb5_free_keyblock_contents(krbContext, &kd); +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto_destroy(krbContext, krbCrypto); + krb5_data_free(&t); +#else if (t.data != NULL) { memset(t.data, 0, t.length); GSSEAP_FREE(t.data); } - if (prfOut.data != NULL) { - memset(prfOut.data, 0, prfOut.length); - GSSEAP_FREE(prfOut.data); +#endif + if (derivedKeyData.data != NULL) { + memset(derivedKeyData.data, 0, derivedKeyData.length); + GSSEAP_FREE(derivedKeyData.data); } + *minor = code; + return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; } @@ -256,10 +287,13 @@ rfc3961ChecksumTypeForKey(OM_uint32 *minor, krb5_cksumtype *cksumtype) { krb5_context krbContext; -#ifndef HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE +#if !defined(HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE) && !defined(HAVE_HEIMDAL_VERSION) krb5_data data; krb5_checksum cksum; #endif +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto krbCrypto = NULL; +#endif GSSEAP_KRB_INIT(&krbContext); @@ -268,9 +302,19 @@ rfc3961ChecksumTypeForKey(OM_uint32 *minor, cksumtype); if (*minor != 0) return GSS_S_FAILURE; +#elif defined(HAVE_HEIMDAL_VERSION) + *minor = krb5_crypto_init(krbContext, key, 0, &krbCrypto); + if (*minor != 0) + return GSS_S_FAILURE; + + *minor = krb5_crypto_get_checksum_type(krbContext, krbCrypto, cksumtype); + + krb5_crypto_destroy(krbContext, krbCrypto); + + if (*minor != 0) + return GSS_S_FAILURE; #else - data.length = 0; - data.data = NULL; + KRB_DATA_INIT(&data); memset(&cksum, 0, sizeof(cksum)); @@ -283,17 +327,18 @@ rfc3961ChecksumTypeForKey(OM_uint32 *minor, if (*minor != 0) return GSS_S_FAILURE; -#ifdef HAVE_HEIMDAL_VERSION - *cksumtype = cksum.cksumtype; -#else - *cksumtype = cksum.checksum_type; -#endif + *cksumtype = KRB_CHECKSUM_TYPE(&cksum); - krb5_free_checksum_contents(krbContext, &cksum); + KRB_CHECKSUM_FREE(krbContext, &cksum); #endif /* HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE */ - if (!krb5_c_is_keyed_cksum(*cksumtype)) { - *minor = KRB5KRB_AP_ERR_INAPP_CKSUM; +#ifdef HAVE_HEIMDAL_VERSION + if (!krb5_checksum_is_keyed(krbContext, *cksumtype)) +#else + if (!krb5_c_is_keyed_cksum(*cksumtype)) +#endif + { + *minor = (OM_uint32)KRB5KRB_AP_ERR_INAPP_CKSUM; return GSS_S_FAILURE; } @@ -305,7 +350,7 @@ krbCryptoLength(krb5_context krbContext, #ifdef HAVE_HEIMDAL_VERSION krb5_crypto krbCrypto, #else - krb5_keyblock *key, + const krb5_keyblock *key, #endif int type, size_t *length) @@ -329,7 +374,7 @@ krbPaddingLength(krb5_context krbContext, #ifdef HAVE_HEIMDAL_VERSION krb5_crypto krbCrypto, #else - krb5_keyblock *key, + const krb5_keyblock *key, #endif size_t dataLength, size_t *padLength) @@ -372,7 +417,7 @@ krbBlockSize(krb5_context krbContext, #ifdef HAVE_HEIMDAL_VERSION krb5_crypto krbCrypto, #else - krb5_keyblock *key, + const krb5_keyblock *key, #endif size_t *blockSize) { @@ -435,6 +480,7 @@ krbEnctypeToString( return 0; } +#ifdef GSSEAP_ENABLE_REAUTH krb5_error_code krbMakeAuthDataKdcIssued(krb5_context context, const krb5_keyblock *key, @@ -476,7 +522,7 @@ krbMakeAuthDataKdcIssued(krb5_context context, if (code != 0) goto cleanup; - GSSEAP_FREE(buf); + free(buf); /* match ASN1_MALLOC_ENCODE */ buf = NULL; ASN1_MALLOC_ENCODE(AD_KDCIssued, buf, buf_size, &kdcIssued, &len, code); @@ -493,7 +539,7 @@ krbMakeAuthDataKdcIssued(krb5_context context, cleanup: if (buf != NULL) - GSSEAP_FREE(buf); + free(buf); /* match ASN1_MALLOC_ENCODE */ if (crypto != NULL) krb5_crypto_destroy(context, crypto); free_Checksum(&kdcIssued.ad_checksum); @@ -630,3 +676,4 @@ cleanup: return code; #endif /* HAVE_HEIMDAL_VERSION */ } +#endif /* GSSEAP_ENABLE_REAUTH */