X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=mech_eap%2Finit_sec_context.c;h=2a1d3e029fea549bc43a52974d6a6cd455104b79;hb=cd961180d47d76e55de1c09e3ec6d7448f4e3359;hp=0e1bee1d180ea97d37fdafc7f5343c1dd91a3743;hpb=0f66201ca201328d1108a68ad533e9c8d556018c;p=mech_eap.git diff --git a/mech_eap/init_sec_context.c b/mech_eap/init_sec_context.c index 0e1bee1..2a1d3e0 100644 --- a/mech_eap/init_sec_context.c +++ b/mech_eap/init_sec_context.c @@ -39,6 +39,8 @@ #include "radius/radius.h" #include "util_radius.h" #include "utils/radius_utils.h" +#include "openssl/err.h" +#include "libmoonshot.h" /* methods allowed for phase1 authentication*/ static const struct eap_method_type allowed_eap_method_types[] = { @@ -78,6 +80,9 @@ policyVariableToFlag(enum eapol_bool_var variable) case EAPOL_altReject: flag = CTX_FLAG_EAP_ALT_REJECT; break; + case EAPOL_eapTriggerStart: + flag = CTX_FLAG_EAP_TRIGGER_START; + break; } return flag; @@ -198,6 +203,18 @@ peerNotifyPending(void *ctx GSSEAP_UNUSED) { } +static void peerNotifyCert(void *ctx GSSEAP_UNUSED, + int depth , + const char *subject GSSEAP_UNUSED, + const char *altsubject[] GSSEAP_UNUSED, + int num_altsubject GSSEAP_UNUSED, + const char *cert_hash GSSEAP_UNUSED, + const struct wpabuf *cert GSSEAP_UNUSED) +{ + printf("peerNotifyCert: depth=%d; hash=%s (%p)\n", depth, cert_hash, cert_hash); +} + + static struct eapol_callbacks gssEapPolicyCallbacks = { peerGetConfig, peerGetBool, @@ -208,11 +225,10 @@ static struct eapol_callbacks gssEapPolicyCallbacks = { peerSetConfigBlob, peerGetConfigBlob, peerNotifyPending, + NULL, /* eap_param_needed */ + peerNotifyCert }; -#ifdef GSSEAP_DEBUG -extern int wpa_debug_level; -#endif #define CHBIND_SERVICE_NAME_FLAG 0x01 #define CHBIND_HOST_NAME_FLAG 0x02 @@ -356,6 +372,92 @@ peerProcessChbindResponse(void *context, int code, int nsid, } /* else log failures? */ } +static int cert_to_byte_array(X509 *cert, unsigned char **bytes) +{ + unsigned char *buf; + unsigned char *p; + + int len = i2d_X509(cert, NULL); + if (len <= 0) { + return -1; + } + + p = buf = GSSEAP_MALLOC(len); + if (buf == NULL) { + return -1; + } + + i2d_X509(cert, &buf); + + *bytes = p; + return len; +} + +static int sha256(unsigned char *bytes, int len, unsigned char *hash) +{ + EVP_MD_CTX ctx; + unsigned int hash_len; + + EVP_MD_CTX_init(&ctx); + if (!EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL)) { + printf("sha256(init_sec_context.c): EVP_DigestInit_ex failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + if (!EVP_DigestUpdate(&ctx, bytes, len)) { + printf("sha256(init_sec_context.c): EVP_DigestUpdate failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + if (!EVP_DigestFinal(&ctx, hash, &hash_len)) { + printf("sha256(init_sec_context.c): EVP_DigestFinal failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + + return hash_len; +} + + +static int peerValidateServer(int ok_so_far, X509* cert, void *ca_ctx) +{ + const char *realm = NULL; + unsigned char *cert_bytes = NULL; + int cert_len; + unsigned char hash[32]; + int hash_len; + MoonshotError *error = NULL; + struct eap_peer_config *eap_config = (struct eap_peer_config *) ca_ctx; + char *identity = strdup((const char *) eap_config->identity); + + // Truncate the identity to just the username + char* at = strchr(identity, '@'); + if (at != NULL) { + *at = '\0'; + } + + cert_len = cert_to_byte_array(cert, &cert_bytes); + hash_len = sha256(cert_bytes, cert_len, hash); + GSSEAP_FREE(cert_bytes); + + if (hash_len != 32) { + printf("peerValidateServer: Error: hash_len=%d, not 32!\n", hash_len); + return FALSE; + } + + /* This is ugly, but it works -- anonymous_identity is '@' + realm + * (see peerConfigInit) + */ + realm = ((char *) eap_config->anonymous_identity) + 1; + + ok_so_far = moonshot_confirm_ca_certificate(identity, realm, hash, 32, &error); + free(identity); + + printf("peerValidateServer: Returning %d\n", ok_so_far); + return ok_so_far; +} + + static OM_uint32 peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx) { @@ -380,10 +482,7 @@ peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx) GSSEAP_KRB_INIT(&krbContext); eapPeerConfig->fragment_size = 1024; -#ifdef GSSEAP_DEBUG - wpa_debug_level = 0; -#endif - + GSSEAP_ASSERT(cred->name != GSS_C_NO_NAME); if ((cred->name->flags & (NAME_FLAG_NAI | NAME_FLAG_SERVICE)) == 0) { @@ -464,9 +563,12 @@ peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx) eapPeerConfig->client_cert = (unsigned char *)cred->clientCertificate.value; eapPeerConfig->private_key = (unsigned char *)cred->privateKey.value; } - eapPeerConfig->private_key_passwd = (unsigned char *)cred->password.value; + eapPeerConfig->private_key_passwd = (char *)cred->password.value; } + eapPeerConfig->server_cert_cb = peerValidateServer; + eapPeerConfig->server_cert_ctx = eapPeerConfig; + *minor = 0; return GSS_S_COMPLETE; } @@ -629,7 +731,10 @@ eapGssSmInitError(OM_uint32 *minor, p = (unsigned char *)inputToken->value; major = load_uint32_be(&p[0]); - *minor = ERROR_TABLE_BASE_eapg + load_uint32_be(&p[4]); + *minor = load_uint32_be(&p[4]); + if ((*minor >0) && (*minor < 128)) + * minor += ERROR_TABLE_BASE_eapg; + else *minor = 0; if (!GSS_ERROR(major) || !IS_WIRE_ERROR(*minor)) { major = GSS_S_FAILURE; @@ -838,6 +943,8 @@ eapGssSmInitIdentity(OM_uint32 *minor, OM_uint32 *smFlags) { struct eap_config eapConfig; + memset(&eapConfig, 0, sizeof(eapConfig)); + eapConfig.cert_in_cb = 1; #ifdef GSSEAP_ENABLE_REAUTH if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE) { @@ -854,11 +961,9 @@ eapGssSmInitIdentity(OM_uint32 *minor, GSSEAP_ASSERT((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0); GSSEAP_ASSERT(inputToken == GSS_C_NO_BUFFER); - memset(&eapConfig, 0, sizeof(eapConfig)); - ctx->initiatorCtx.eap = eap_peer_sm_init(ctx, &gssEapPolicyCallbacks, - ctx, + NULL, /* ctx?? */ &eapConfig); if (ctx->initiatorCtx.eap == NULL) { *minor = GSSEAP_PEER_SM_INIT_FAILURE; @@ -1365,5 +1470,7 @@ gss_init_sec_context(OM_uint32 *minor, if (GSS_ERROR(major)) gssEapReleaseContext(&tmpMinor, context_handle); + gssEapTraceStatus( "gss_init_sec_context", major, *minor); return major; } +