From: Luke Howard Date: Thu, 9 Sep 2010 13:18:25 +0000 (+0200) Subject: some testing logic for testing acceptor without radius X-Git-Url: http://www.project-moonshot.org/gitweb/?p=cyrus-sasl.git;a=commitdiff_plain;h=85d2136c9afd05a42c8a881683908419af62b7ca some testing logic for testing acceptor without radius --- diff --git a/mech_eap/accept_sec_context.c b/mech_eap/accept_sec_context.c index 80b2697..8ab9a9b 100644 --- a/mech_eap/accept_sec_context.c +++ b/mech_eap/accept_sec_context.c @@ -32,6 +32,222 @@ #include "gssapiP_eap.h" +#define EAP_MAX_METHODS 8 + +#define EAP_TTLS_AUTH_PAP 1 +#define EAP_TTLS_AUTH_CHAP 2 +#define EAP_TTLS_AUTH_MSCHAP 4 +#define EAP_TTLS_AUTH_MSCHAPV2 8 + +#if 1 +struct eap_user { + struct { + int vendor; + u32 method; + } methods[EAP_MAX_METHODS]; + u8 *password; + size_t password_len; + int password_hash; /* whether password is hashed with + * nt_password_hash() */ + int phase2; + int force_version; + int ttls_auth; /* bitfield of + * EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */ +}; + +struct eap_eapol_interface { + /* Lower layer to full authenticator variables */ + Boolean eapResp; /* shared with EAPOL Backend Authentication */ + struct wpabuf *eapRespData; + Boolean portEnabled; + int retransWhile; + Boolean eapRestart; /* shared with EAPOL Authenticator PAE */ + int eapSRTT; + int eapRTTVAR; + + /* Full authenticator to lower layer variables */ + Boolean eapReq; /* shared with EAPOL Backend Authentication */ + Boolean eapNoReq; /* shared with EAPOL Backend Authentication */ + Boolean eapSuccess; + Boolean eapFail; + Boolean eapTimeout; + struct wpabuf *eapReqData; + u8 *eapKeyData; + size_t eapKeyDataLen; + Boolean eapKeyAvailable; /* called keyAvailable in IEEE 802.1X-2004 */ + + /* AAA interface to full authenticator variables */ + Boolean aaaEapReq; + Boolean aaaEapNoReq; + Boolean aaaSuccess; + Boolean aaaFail; + struct wpabuf *aaaEapReqData; + u8 *aaaEapKeyData; + size_t aaaEapKeyDataLen; + Boolean aaaEapKeyAvailable; + int aaaMethodTimeout; + + /* Full authenticator to AAA interface variables */ + Boolean aaaEapResp; + struct wpabuf *aaaEapRespData; + /* aaaIdentity -> eap_get_identity() */ + Boolean aaaTimeout; +}; + +#define eapol_callbacks SERVER_eapol_callbacks + +struct eapol_callbacks { + int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, + int phase2, struct eap_user *user); + const char * (*get_eap_req_id_text)(void *ctx, size_t *len); +}; + +#define eap_config SERVER_eap_config + +struct eap_config { + void *ssl_ctx; + void *msg_ctx; + void *eap_sim_db_priv; + Boolean backend_auth; + int eap_server; + u8 *pac_opaque_encr_key; + u8 *eap_fast_a_id; + size_t eap_fast_a_id_len; + char *eap_fast_a_id_info; + int eap_fast_prov; + int pac_key_lifetime; + int pac_key_refresh_time; + int eap_sim_aka_result_ind; + int tnc; + struct wps_context *wps; + const struct wpabuf *assoc_wps_ie; + const u8 *peer_addr; + int fragment_size; +}; + +struct eap_sm * eap_server_sm_init(void *eapol_ctx, + struct eapol_callbacks *eapol_cb, + struct eap_config *eap_conf); +void eap_server_sm_deinit(struct eap_sm *sm); +int eap_server_sm_step(struct eap_sm *sm); +void eap_sm_notify_cached(struct eap_sm *sm); +void eap_sm_pending_cb(struct eap_sm *sm); +int eap_sm_method_pending(struct eap_sm *sm); +const u8 * eap_get_identity(struct eap_sm *sm, size_t *len); +struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm); + +static OM_uint32 +initTls(OM_uint32 *minor, + gss_ctx_id_t ctx) +{ + struct tls_config tconf; + struct tls_connection_params tparams; + + memset(&tconf, 0, sizeof(tconf)); + ctx->acceptorCtx.tlsContext = tls_init(&tconf); + if (ctx->acceptorCtx.tlsContext == NULL) + return GSS_S_FAILURE; + + memset(&tparams, 0, sizeof(tparams)); + tparams.ca_cert = "ca.pem"; + tparams.client_cert = "server.pem"; + tparams.private_key = "server-key.pem"; + + if (tls_global_set_params(ctx->acceptorCtx.tlsContext, &tparams)) { + return GSS_S_FAILURE; + } + + if (tls_global_set_verify(ctx->acceptorCtx.tlsContext, 0)) { + return GSS_S_FAILURE; + } + + return GSS_S_COMPLETE; +} + +static int +serverGetEapUser(void *ctx, + const unsigned char *identity, + size_t identityLength, + int phase2, + struct eap_user *user) +{ + gss_ctx_id_t gssCtx = (gss_ctx_id_t)ctx; + OM_uint32 major, minor; + gss_buffer_desc buf; + + memset(user, 0, sizeof(*user)); + + buf.length = identityLength; + buf.value = (void *)identity; + + if (phase2 == 0) { + user->methods[0].vendor = EAP_VENDOR_IETF; + user->methods[0].method = EAP_TYPE_PEAP; + return 0; + } + + major = gssEapImportName(&minor, &buf, GSS_C_NT_USER_NAME, + &gssCtx->initiatorName); + if (GSS_ERROR(major)) + return -1; + + /* + * OK, obviously there is no real security here, this is simply + * for testing the token exchange; this code will be completely + * replaced with libradsec once that library is available. + */ + user->methods[0].vendor = EAP_VENDOR_IETF; + user->methods[0].method = EAP_TYPE_MSCHAPV2; + user->password = (unsigned char *)strdup(""); + user->password_len = 0; + + return 0; +} + +static const char * +serverGetEapReqIdText(void *ctx, + size_t *len) +{ + *len = 0; + return NULL; +} +#endif + +static OM_uint32 +serverDeriveKey(OM_uint32 *minor, + gss_ctx_id_t ctx) +{ + OM_uint32 major; + krb5_context krbContext; + + GSSEAP_KRB_INIT(&krbContext); + + /* Cache encryption type derived from selected mechanism OID */ + major = gssEapOidToEnctype(minor, ctx->mechanismUsed, &ctx->encryptionType); + if (GSS_ERROR(major)) + return major; + + if (ctx->encryptionType != ENCTYPE_NULL && + ctx->acceptorCtx.eapPolInterface->eapKeyAvailable) { + major = gssEapDeriveRFC3961Key(minor, + ctx->acceptorCtx.eapPolInterface->eapKeyData, + ctx->acceptorCtx.eapPolInterface->eapKeyDataLen, + ctx->encryptionType, + &ctx->rfc3961Key); + if (GSS_ERROR(major)) + return major; + } else { + /* + * draft-howlett-eap-gss says that integrity/confidentialty should + * always be advertised as available, but if we have no keying + * material it seems confusing to the caller to advertise this. + */ + ctx->gssFlags &= ~(GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG); + } + + return GSS_S_COMPLETE; +} + static OM_uint32 eapGssSmAcceptAuthenticate(OM_uint32 *minor, gss_ctx_id_t ctx, @@ -40,12 +256,89 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, gss_channel_bindings_t chanBindings, gss_buffer_t outputToken) { - OM_uint32 major, tmpMinor; + OM_uint32 major, tmpMinor, tmpMajor; + int code; + struct wpabuf respData; + struct eap_config *config = (struct eap_config *)&ctx->acceptorCtx.eapConfig; + static struct eapol_callbacks cb = { serverGetEapUser, serverGetEapReqIdText }; + + wpabuf_set(&respData, inputToken->value, inputToken->length); + ctx->acceptorCtx.eapPolInterface->eapRespData = &respData; + ctx->acceptorCtx.eapPolInterface->eapResp = TRUE; + + if (ctx->acceptorCtx.eap == NULL) { + /* initial context token */ + config->eap_server = 1; + config->ssl_ctx = ctx->acceptorCtx.tlsContext; + + major = initTls(minor, ctx); + if (GSS_ERROR(major)) + goto cleanup; + + ctx->acceptorCtx.eap = eap_server_sm_init(ctx, &cb, config); + if (ctx->acceptorCtx.eap == NULL) { + major = GSS_S_FAILURE; + goto cleanup; + } + } + + if (ctx->acceptorName == GSS_C_NO_NAME && cred->name != GSS_C_NO_NAME) { + major = gss_duplicate_name(minor, cred->name, &ctx->acceptorName); + if (GSS_ERROR(major)) + goto cleanup; + } + + code = eap_server_sm_step(ctx->acceptorCtx.eap); + + if (ctx->acceptorCtx.eapPolInterface->eapReq) { + ctx->acceptorCtx.eapPolInterface->eapReq = 0; + major = GSS_S_CONTINUE_NEEDED; + } + + if (ctx->acceptorCtx.eapPolInterface->eapSuccess) { + major = serverDeriveKey(minor, ctx); + if (GSS_ERROR(major)) + goto cleanup; + + ctx->acceptorCtx.eapPolInterface->eapSuccess = 0; + ctx->state = EAP_STATE_ESTABLISHED; + major = GSS_S_COMPLETE; + } else if (ctx->acceptorCtx.eapPolInterface->eapFail) { + ctx->acceptorCtx.eapPolInterface->eapFail = 0; + major = GSS_S_FAILURE; + } else if (code == 0) { + major = GSS_S_FAILURE; + } + + if (ctx->acceptorCtx.eapPolInterface->eapReqData != NULL) { + gss_buffer_desc buf; + + buf.length = wpabuf_len(ctx->acceptorCtx.eapPolInterface->eapReqData); + buf.value = (void *)wpabuf_head(ctx->acceptorCtx.eapPolInterface->eapReqData); + + tmpMajor = duplicateBuffer(&tmpMinor, &buf, outputToken); + if (GSS_ERROR(tmpMajor)) { + major = tmpMajor; + goto cleanup; + } + } cleanup: return major; } +static OM_uint32 +eapGssSmAcceptEstablished(OM_uint32 *minor, + gss_ctx_id_t ctx, + gss_cred_id_t cred, + gss_buffer_t inputToken, + gss_channel_bindings_t chanBindings, + gss_buffer_t outputToken) +{ + /* Called with already established context */ + *minor = EINVAL; + return GSS_S_BAD_STATUS; +} static struct eap_gss_acceptor_sm { enum gss_eap_token_type inputTokenType; @@ -57,7 +350,11 @@ static struct eap_gss_acceptor_sm { gss_channel_bindings_t, gss_buffer_t); } eapGssAcceptorSm[] = { - { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, NULL }, + { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, eapGssSmAcceptAuthenticate }, + { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, NULL }, + { TOK_TYPE_EAP_RESP, TOK_TYPE_EAP_REQ, NULL }, + { TOK_TYPE_GSS_CB, TOK_TYPE_NONE, NULL }, + { TOK_TYPE_NONE, TOK_TYPE_NONE, eapGssSmAcceptEstablished }, }; OM_uint32 @@ -77,7 +374,7 @@ gss_accept_sec_context(OM_uint32 *minor, gss_ctx_id_t ctx = *context_handle; struct eap_gss_acceptor_sm *sm = NULL; gss_buffer_desc innerInputToken, innerOutputToken; - + *minor = 0; innerOutputToken.length = 0; @@ -123,7 +420,7 @@ gss_accept_sec_context(OM_uint32 *minor, } while (major == GSS_S_CONTINUE_NEEDED && innerOutputToken.length == 0); if (src_name != NULL && ctx->initiatorName != GSS_C_NO_NAME) { - major = gss_duplicate_name(&minor, ctx->initiatorName, src_name); + major = gss_duplicate_name(minor, ctx->initiatorName, src_name); if (GSS_ERROR(major)) goto cleanup; } diff --git a/mech_eap/eap_mech.c b/mech_eap/eap_mech.c index da3de43..5a34fb6 100644 --- a/mech_eap/eap_mech.c +++ b/mech_eap/eap_mech.c @@ -141,6 +141,111 @@ eapPeerRegisterMethods(void) } static int +eapServerRegisterMethods(void) +{ + int ret = 0; + +#ifdef EAP_SERVER_IDENTITY + if (ret == 0) + ret = eap_server_identity_register(); +#endif /* EAP_SERVER_IDENTITY */ + +#ifdef EAP_SERVER_MD5 + if (ret == 0) + ret = eap_server_md5_register(); +#endif /* EAP_SERVER_MD5 */ + +#ifdef EAP_SERVER_TLS + if (ret == 0) + ret = eap_server_tls_register(); +#endif /* EAP_SERVER_TLS */ + +#ifdef EAP_SERVER_MSCHAPV2 + if (ret == 0) + ret = eap_server_mschapv2_register(); +#endif /* EAP_SERVER_MSCHAPV2 */ + +#ifdef EAP_SERVER_PEAP + if (ret == 0) + ret = eap_server_peap_register(); +#endif /* EAP_SERVER_PEAP */ + +#ifdef EAP_SERVER_TLV + if (ret == 0) + ret = eap_server_tlv_register(); +#endif /* EAP_SERVER_TLV */ +#ifdef EAP_SERVER_GTC + if (ret == 0) + ret = eap_server_gtc_register(); +#endif /* EAP_SERVER_GTC */ + +#ifdef EAP_SERVER_TTLS + if (ret == 0) + ret = eap_server_ttls_register(); +#endif /* EAP_SERVER_TTLS */ + +#ifdef EAP_SERVER_SIM + if (ret == 0) + ret = eap_server_sim_register(); +#endif /* EAP_SERVER_SIM */ + +#ifdef EAP_SERVER_AKA + if (ret == 0) + ret = eap_server_aka_register(); +#endif /* EAP_SERVER_AKA */ + +#ifdef EAP_SERVER_AKA_PRIME + if (ret == 0) + ret = eap_server_aka_prime_register(); +#endif /* EAP_SERVER_AKA_PRIME */ + +#ifdef EAP_SERVER_PAX + if (ret == 0) + ret = eap_server_pax_register(); +#endif /* EAP_SERVER_PAX */ + +#ifdef EAP_SERVER_PSK + if (ret == 0) + ret = eap_server_psk_register(); +#endif /* EAP_SERVER_PSK */ + +#ifdef EAP_SERVER_SAKE + if (ret == 0) + ret = eap_server_sake_register(); +#endif /* EAP_SERVER_SAKE */ + +#ifdef EAP_SERVER_GPSK + if (ret == 0) + ret = eap_server_gpsk_register(); +#endif /* EAP_SERVER_GPSK */ + +#ifdef EAP_SERVER_VENDOR_TEST + if (ret == 0) + ret = eap_server_vendor_test_register(); +#endif /* EAP_SERVER_VENDOR_TEST */ + +#ifdef EAP_SERVER_FAST + if (ret == 0) + ret = eap_server_fast_register(); +#endif /* EAP_SERVER_FAST */ + +#ifdef EAP_SERVER_WSC + if (ret == 0) + ret = eap_server_wsc_register(); +#endif /* EAP_SERVER_WSC */ + +#ifdef EAP_SERVER_IKEV2 + if (ret == 0) + ret = eap_server_ikev2_register(); +#endif /* EAP_SERVER_IKEV2 */ + +#ifdef EAP_SERVER_TNC + if (ret == 0) + ret = eap_server_tnc_register(); +#endif /* EAP_SERVER_TNC */ +} + +static int gssEapInitLibEap(void) { return eapPeerRegisterMethods(); @@ -162,12 +267,19 @@ gssEapInit(void) ret = gssEapInitLibEap(); if (ret == 0) - gssEapInitLibRadSec(); +#if 0 + ret = gssEapInitLibRadSec(); +#else + ret = eapServerRegisterMethods(); +#endif } static void gssEapFinalize(void) { eap_peer_unregister_methods(); +#if 1 + eap_server_unregister_methods(); +#endif } diff --git a/mech_eap/gssapiP_eap.h b/mech_eap/gssapiP_eap.h index 6013c1d..199048e 100644 --- a/mech_eap/gssapiP_eap.h +++ b/mech_eap/gssapiP_eap.h @@ -50,6 +50,7 @@ #include #include #include +#include /* XXX testing implementation only */ #include /* Kerberos includes */ @@ -121,8 +122,11 @@ struct eap_gss_initiator_ctx { struct wpabuf reqData; }; -/* Acceptor context flags */ struct eap_gss_acceptor_ctx { + struct eap_eapol_interface *eapPolInterface; + void *tlsContext; + struct eap_sm *eap; + struct eap_config eapConfig; /* XXX */ }; struct gss_ctx_id_struct { diff --git a/mech_eap/init_sec_context.c b/mech_eap/init_sec_context.c index 15bdff3..3d55ccd 100644 --- a/mech_eap/init_sec_context.c +++ b/mech_eap/init_sec_context.c @@ -350,7 +350,9 @@ eapGssSmInitAuthenticate(OM_uint32 *minor, if (GSS_ERROR(major)) goto cleanup; + ctx->flags &= ~(CTX_FLAG_EAP_SUCCESS); ctx->state = EAP_STATE_ESTABLISHED; + major = GSS_S_COMPLETE; } else if (code == 0) { major = GSS_S_FAILURE; } diff --git a/mech_eap/util_context.c b/mech_eap/util_context.c index cf2a41f..6352319 100644 --- a/mech_eap/util_context.c +++ b/mech_eap/util_context.c @@ -82,6 +82,8 @@ releaseInitiatorContext(struct eap_gss_initiator_ctx *ctx) static void releaseAcceptorContext(struct eap_gss_acceptor_ctx *ctx) { + eap_server_sm_deinit(ctx->eap); + tls_deinit(ctx->tlsContext); } OM_uint32