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])
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)
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;
void
gssEapFinalize(void)
{
+ wpa_printf(MSG_INFO, "### gssEapFinalize()");
eap_peer_unregister_methods();
}
#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;
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);
+}
#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[] = {
} /* else log failures? */
}
+#ifdef HAVE_MOONSHOT_GET_IDENTITY
static int cert_to_byte_array(X509 *cert, unsigned char **bytes)
{
unsigned char *buf;
return hash_len;
}
-
static int peerValidateServerCert(int ok_so_far, X509* cert, void *ca_ctx)
{
char *realm = NULL;
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)
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;
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)
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;
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;
}
#ifdef HAVE_HEIMDAL_VERSION
+#include <der.h>
+
#define KRB_TIME_FOREVER ((time_t)~0L)
#define KRB_KEY_TYPE(key) ((key)->keytype)
(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
(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 { \
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:
GSSEAP_ASSERT(major == GSS_S_COMPLETE);
#endif
+ wpa_printf(MSG_INFO, "### gssEapAttrProvidersInitInternal(): Setting gssEapAttrProvidersInitStatus to %08X", major);
gssEapAttrProvidersInitStatus = major;
GSSEAP_ONCE_LEAVE;
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
} 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;
*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
return 0;
}
+#ifdef GSSEAP_ENABLE_REAUTH
krb5_error_code
krbMakeAuthDataKdcIssued(krb5_context context,
const krb5_keyblock *key,
return code;
#endif /* HAVE_HEIMDAL_VERSION */
}
+#endif /* GSSEAP_ENABLE_REAUTH */
*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;
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;
{
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;
}
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();
}
return dst;
}
+
OM_uint32
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;
}
#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;
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);
}