From: Dan Breslau Date: Tue, 1 Aug 2017 18:20:48 +0000 (-0400) Subject: Merge in workaround for broken Kerberos 10.x gssapi.h X-Git-Tag: moonshot-1.0.6-centos6~4 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=commitdiff_plain;h=67134e45772a0ecc64292cdb7023a64ff03529a4;hp=80729efe17cf587c01e0a9dd0d6b43168a58579f Merge in workaround for broken Kerberos 10.x gssapi.h --- diff --git a/configure.ac b/configure.ac index a58e724..6134e8d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.61]) -AC_INIT([mech_eap], [0.9.5], [bugs@project-moonshot.org]) +AC_INIT([mech_eap], [1.0.0], [bugs@project-moonshot.org]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) diff --git a/mech_eap/accept_sec_context.c b/mech_eap/accept_sec_context.c index c284e8b..b594af0 100644 --- a/mech_eap/accept_sec_context.c +++ b/mech_eap/accept_sec_context.c @@ -688,6 +688,9 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, krb5_data data; krb5_checksum cksum; krb5_boolean valid = FALSE; +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto krbCrypto; +#endif if (chanBindings == GSS_C_NO_CHANNEL_BINDINGS || chanBindings->application_data.length == 0) @@ -701,9 +704,29 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, KRB_CHECKSUM_INIT(&cksum, ctx->checksumType, inputToken); +#ifdef HAVE_HEIMDAL_VERSION + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key, 0, &krbCrypto); + if (code != 0) { + *minor = code; + return GSS_S_FAILURE; + } + + code = krb5_verify_checksum(krbContext, krbCrypto, + KEY_USAGE_GSSEAP_CHBIND_MIC, + data.data, data.length, &cksum); + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + code = 0; + valid = FALSE; + } else if (code == 0) { + valid = TRUE; + } + + krb5_crypto_destroy(krbContext, krbCrypto); +#else code = krb5_c_verify_checksum(krbContext, &ctx->rfc3961Key, KEY_USAGE_GSSEAP_CHBIND_MIC, &data, &cksum, &valid); +#endif /* HAVE_HEIMDAL_VERSION */ if (code != 0) { *minor = code; return GSS_S_FAILURE; diff --git a/mech_eap/eap_mech.c b/mech_eap/eap_mech.c index c88ecf6..403e2f8 100644 --- a/mech_eap/eap_mech.c +++ b/mech_eap/eap_mech.c @@ -205,6 +205,7 @@ gssEapInitiatorInit(OM_uint32 *minor) void gssEapFinalize(void) { + wpa_printf(MSG_INFO, "### gssEapFinalize()"); eap_peer_unregister_methods(); } diff --git a/mech_eap/get_mic.c b/mech_eap/get_mic.c index 08dda7d..9a7bfc7 100644 --- a/mech_eap/get_mic.c +++ b/mech_eap/get_mic.c @@ -36,12 +36,12 @@ #include "gssapiP_eap.h" -OM_uint32 GSSAPI_CALLCONV -gss_get_mic_iov(OM_uint32 *minor, - gss_ctx_id_t ctx, - gss_qop_t qop_req, - gss_iov_buffer_desc *iov, - int iov_count) +static OM_uint32 +gssEapGetMIC(OM_uint32 *minor, + gss_ctx_id_t ctx, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + int iov_count) { OM_uint32 major; @@ -101,9 +101,19 @@ gss_get_mic(OM_uint32 *minor, iov[1].buffer.value = NULL; iov[1].buffer.length = 0; - major = gss_get_mic_iov(minor, (gss_ctx_id_t)ctx, qop_req, iov, 2); + major = gssEapGetMIC(minor, (gss_ctx_id_t)ctx, qop_req, iov, 2); if (major == GSS_S_COMPLETE) *message_token = iov[1].buffer; return major; } + +OM_uint32 GSSAPI_CALLCONV +gss_get_mic_iov(OM_uint32 *minor, + gss_ctx_id_t ctx, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + int iov_count) +{ + return gssEapGetMIC(minor, ctx, qop_req, iov, iov_count); +} diff --git a/mech_eap/init_sec_context.c b/mech_eap/init_sec_context.c index 37bd3d0..7a2fb46 100644 --- a/mech_eap/init_sec_context.c +++ b/mech_eap/init_sec_context.c @@ -40,7 +40,9 @@ #include "util_radius.h" #include "utils/radius_utils.h" #include "openssl/err.h" +#ifdef HAVE_MOONSHOT_GET_IDENTITY #include "libmoonshot.h" +#endif /* methods allowed for phase1 authentication*/ static const struct eap_method_type allowed_eap_method_types[] = { @@ -361,6 +363,7 @@ peerProcessChbindResponse(void *context, int code, int nsid, } /* else log failures? */ } +#ifdef HAVE_MOONSHOT_GET_IDENTITY static int cert_to_byte_array(X509 *cert, unsigned char **bytes) { unsigned char *buf; @@ -407,7 +410,6 @@ static int sha256(unsigned char *bytes, int len, unsigned char *hash) return hash_len; } - static int peerValidateServerCert(int ok_so_far, X509* cert, void *ca_ctx) { char *realm = NULL; @@ -444,7 +446,7 @@ static int peerValidateServerCert(int ok_so_far, X509* cert, void *ca_ctx) wpa_printf(MSG_INFO, "peerValidateServerCert: Returning %d\n", ok_so_far); return ok_so_far; } - +#endif static OM_uint32 peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx) @@ -554,7 +556,9 @@ peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx) eapPeerConfig->private_key_passwd = (char *)cred->password.value; } +#ifdef HAVE_MOONSHOT_GET_IDENTITY eapPeerConfig->server_cert_cb = peerValidateServerCert; +#endif eapPeerConfig->server_cert_ctx = eapPeerConfig; *minor = 0; @@ -1102,6 +1106,9 @@ eapGssSmInitGssChannelBindings(OM_uint32 *minor, krb5_data data; krb5_checksum cksum; gss_buffer_desc cksumBuffer; +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto krbCrypto; +#endif if (chanBindings == GSS_C_NO_CHANNEL_BINDINGS || chanBindings->application_data.length == 0) @@ -1113,10 +1120,25 @@ eapGssSmInitGssChannelBindings(OM_uint32 *minor, gssBufferToKrbData(&chanBindings->application_data, &data); +#ifdef HAVE_HEIMDAL_VERSION + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key, 0, &krbCrypto); + if (code != 0) { + *minor = code; + return GSS_S_FAILURE; + } + + code = krb5_create_checksum(krbContext, krbCrypto, + KEY_USAGE_GSSEAP_CHBIND_MIC, + ctx->checksumType, + data.data, data.length, + &cksum); + krb5_crypto_destroy(krbContext, krbCrypto); +#else code = krb5_c_make_checksum(krbContext, ctx->checksumType, &ctx->rfc3961Key, KEY_USAGE_GSSEAP_CHBIND_MIC, &data, &cksum); +#endif /* HAVE_HEIMDAL_VERSION */ if (code != 0) { *minor = code; return GSS_S_FAILURE; @@ -1127,14 +1149,14 @@ eapGssSmInitGssChannelBindings(OM_uint32 *minor, major = duplicateBuffer(minor, &cksumBuffer, outputToken); if (GSS_ERROR(major)) { - krb5_free_checksum_contents(krbContext, &cksum); + KRB_CHECKSUM_FREE(krbContext, &cksum); return major; } *minor = 0; *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL; - krb5_free_checksum_contents(krbContext, &cksum); + KRB_CHECKSUM_FREE(krbContext, &cksum); return GSS_S_CONTINUE_NEEDED; } diff --git a/mech_eap/util.h b/mech_eap/util.h index 588af67..9028257 100644 --- a/mech_eap/util.h +++ b/mech_eap/util.h @@ -377,6 +377,8 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, #ifdef HAVE_HEIMDAL_VERSION +#include + #define KRB_TIME_FOREVER ((time_t)~0L) #define KRB_KEY_TYPE(key) ((key)->keytype) @@ -405,6 +407,11 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, (cksum)->checksum.data = (d)->value; \ } while (0) +#define KRB_CHECKSUM_FREE(ctx, cksum) do { \ + der_free_octet_string(&(cksum)->checksum); \ + memset((cksum), 0, sizeof(*(cksum))); \ + } while (0) + #else #define KRB_TIME_FOREVER KRB5_INT32_MAX @@ -441,6 +448,8 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, (cksum)->contents = (d)->value; \ } while (0) +#define KRB_CHECKSUM_FREE(ctx, cksum) krb5_free_checksum_contents((ctx), (cksum)) + #endif /* HAVE_HEIMDAL_VERSION */ #define KRB_KEY_INIT(key) do { \ diff --git a/mech_eap/util_attr.cpp b/mech_eap/util_attr.cpp index beb283c..1931efe 100644 --- a/mech_eap/util_attr.cpp +++ b/mech_eap/util_attr.cpp @@ -64,9 +64,14 @@ GSSEAP_ONCE_CALLBACK(gssEapAttrProvidersInitInternal) gssEapLocalAttrProviderInit(&minor); #endif #ifdef HAVE_OPENSAML + wpa_printf(MSG_INFO, "### gssEapAttrProvidersInitInternal(): Calling gssEapSamlAttrProvidersInit()"); major = gssEapSamlAttrProvidersInit(&minor); - if (GSS_ERROR(major)) + if (GSS_ERROR(major)) { + wpa_printf(MSG_ERROR, "### gssEapAttrProvidersInitInternal(): Error returned from gssEapSamlAttrProvidersInit; major code is %08X; minor is %08X", major, minor); goto cleanup; + } +#else + wpa_printf(MSG_INFO, "### gssEapAttrProvidersInitInternal(): Don't have OpenSAML; not calling gssEapSamlAttrProvidersInit()"); #endif cleanup: @@ -74,6 +79,7 @@ cleanup: GSSEAP_ASSERT(major == GSS_S_COMPLETE); #endif + wpa_printf(MSG_INFO, "### gssEapAttrProvidersInitInternal(): Setting gssEapAttrProvidersInitStatus to %08X", major); gssEapAttrProvidersInitStatus = major; GSSEAP_ONCE_LEAVE; @@ -90,16 +96,25 @@ gssEapAttrProvidersInit(OM_uint32 *minor) return gssEapAttrProvidersInitStatus; } + namespace { + class finalize_class { public: + + finalize_class() { + wpa_printf(MSG_INFO, "### finalize_class::finalize_class(): Constructing"); + } + ~finalize_class() { OM_uint32 minor = 0; + + wpa_printf(MSG_INFO, "### ~finalize_class::~finalize_class() : initStatus=%08x", gssEapAttrProvidersInitStatus); + if (gssEapAttrProvidersInitStatus == GSS_S_COMPLETE) { -#ifdef HAVE_SHIBRESOLVER - gssEapLocalAttrProviderFinalize(&minor); -#endif + wpa_printf(MSG_INFO, "### ~finalize_class::~finalize_class() : really finalizing"); + #ifdef HAVE_OPENSAML gssEapSamlAttrProvidersFinalize(&minor); #endif diff --git a/mech_eap/util_context.c b/mech_eap/util_context.c index 039cfdb..b7a50c6 100644 --- a/mech_eap/util_context.c +++ b/mech_eap/util_context.c @@ -353,8 +353,13 @@ gssEapMakeOrVerifyTokenMIC(OM_uint32 *minor, } 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; diff --git a/mech_eap/util_krb.c b/mech_eap/util_krb.c index 2a3e970..f629a32 100644 --- a/mech_eap/util_krb.c +++ b/mech_eap/util_krb.c @@ -329,7 +329,7 @@ rfc3961ChecksumTypeForKey(OM_uint32 *minor, *cksumtype = KRB_CHECKSUM_TYPE(&cksum); - krb5_free_checksum_contents(krbContext, &cksum); + KRB_CHECKSUM_FREE(krbContext, &cksum); #endif /* HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE */ #ifdef HAVE_HEIMDAL_VERSION @@ -480,6 +480,7 @@ krbEnctypeToString( return 0; } +#ifdef GSSEAP_ENABLE_REAUTH krb5_error_code krbMakeAuthDataKdcIssued(krb5_context context, const krb5_keyblock *key, @@ -675,3 +676,4 @@ cleanup: return code; #endif /* HAVE_HEIMDAL_VERSION */ } +#endif /* GSSEAP_ENABLE_REAUTH */ diff --git a/mech_eap/util_name.c b/mech_eap/util_name.c index 7a2e60b..b85565c 100644 --- a/mech_eap/util_name.c +++ b/mech_eap/util_name.c @@ -206,8 +206,13 @@ importServiceName(OM_uint32 *minor, *minor = GSSEAP_BAD_SERVICE_NAME; } - if (realm != NULL) + if (realm != NULL) { +#ifdef HAVE_HEIMDAL_VERSION + krb5_xfree(realm); +#else krb5_free_default_realm(krbContext, realm); +#endif + } GSSEAP_FREE(service); return major; diff --git a/mech_eap/util_shib.cpp b/mech_eap/util_shib.cpp index 7b62484..4ba70e0 100644 --- a/mech_eap/util_shib.cpp +++ b/mech_eap/util_shib.cpp @@ -78,6 +78,58 @@ using namespace opensaml; using namespace xercesc; #endif + +namespace { + + + class ShibFinalizer { + public: + + static bool isShibInitialized() {return shibInitialized;} + static void createSingleton(); + + private: + ShibFinalizer(): is_extra(false) { + if (shibInitialized) { + // This should never, ever happen. Initialization is (supposed to be) + // funneled through a single thread, so there should be no race + // conditions here. And only this class sets this flag, and there's + // only a single instance of this class. + wpa_printf(MSG_ERROR, "### ShibFinalizer::ShibFinalizer(): Attempt to construct an extraneous instance!"); + is_extra = true; + } + else { + wpa_printf(MSG_INFO, "### ShibFinalizer::ShibFinalizer(): Constructing"); + shibInitialized = true; + } + } + + ~ShibFinalizer() { + if (!is_extra) { + wpa_printf(MSG_INFO, "### ShibFinalizer::~ShibFinalizer(): Destructing"); + gss_eap_shib_attr_provider::finalize(); + shibInitialized = false; + } + else { + wpa_printf(MSG_INFO, "### ShibFinalizer::~ShibFinalizer(): This was an extraneous instance; not destructing anything."); + } + } + + bool is_extra; + static bool shibInitialized; + }; +} + + +bool ShibFinalizer::shibInitialized = false; + +void ShibFinalizer::createSingleton() { + // This object's constructor is invoked on the first call to this method. + // At exit, its destructor will terminate Shibboleth. + static ShibFinalizer finalizer; +} + + gss_eap_shib_attr_provider::gss_eap_shib_attr_provider(void) { m_initialized = false; @@ -463,13 +515,22 @@ gss_eap_shib_attr_provider::init(void) { bool ret = false; + if (ShibFinalizer::isShibInitialized()) { + wpa_printf(MSG_INFO, "### gss_eap_shib_attr_provider::init(): ShibResolver library is already initialized; ignoring."); + return true; + } + + wpa_printf(MSG_INFO, "### gss_eap_shib_attr_provider::init(): Initializing ShibResolver library"); + try { ret = ShibbolethResolver::init(); } catch (exception &e) { } - if (ret) + if (ret) { + ShibFinalizer::createSingleton(); gss_eap_attr_ctx::registerProvider(ATTR_TYPE_LOCAL, createAttrContext); + } return ret; } @@ -477,6 +538,7 @@ gss_eap_shib_attr_provider::init(void) void gss_eap_shib_attr_provider::finalize(void) { + wpa_printf(MSG_INFO, "### gss_eap_shib_attr_provider::finalize(): calling ShibbolethResolver::term()"); gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_LOCAL); ShibbolethResolver::term(); } @@ -534,6 +596,7 @@ gss_eap_shib_attr_provider::duplicateAttributes(const vector src) return dst; } + OM_uint32 gssEapLocalAttrProviderInit(OM_uint32 *minor) { @@ -541,14 +604,6 @@ gssEapLocalAttrProviderInit(OM_uint32 *minor) *minor = GSSEAP_SHIB_INIT_FAILURE; return GSS_S_FAILURE; } - return GSS_S_COMPLETE; -} - -OM_uint32 -gssEapLocalAttrProviderFinalize(OM_uint32 *minor) -{ - gss_eap_shib_attr_provider::finalize(); - *minor = 0; return GSS_S_COMPLETE; } diff --git a/mech_eap/verify_mic.c b/mech_eap/verify_mic.c index bb9bf19..a93f5f8 100644 --- a/mech_eap/verify_mic.c +++ b/mech_eap/verify_mic.c @@ -36,12 +36,12 @@ #include "gssapiP_eap.h" -OM_uint32 GSSAPI_CALLCONV -gss_verify_mic_iov(OM_uint32 *minor, - gss_ctx_id_t ctx, - gss_qop_t *qop_state, - gss_iov_buffer_desc *iov, - int iov_count) +static OM_uint32 +gssEapVerifyMIC(OM_uint32 *minor, + gss_ctx_id_t ctx, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) { OM_uint32 major; @@ -79,5 +79,15 @@ gss_verify_mic(OM_uint32 *minor, iov[1].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN; iov[1].buffer = *message_token; - return gss_verify_mic_iov(minor, (gss_ctx_id_t)ctx, qop_state, iov, 2); + return gssEapVerifyMIC(minor, (gss_ctx_id_t)ctx, qop_state, iov, 2); +} + +OM_uint32 GSSAPI_CALLCONV +gss_verify_mic_iov(OM_uint32 *minor, + gss_ctx_id_t ctx, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + return gssEapVerifyMIC(minor, ctx, qop_state, iov, iov_count); }