X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=libeap%2Fsrc%2Feap_peer%2Feap_ttls.c;h=12ea169c0f3f12f4e7b51a4ed8f52187d36d8194;hp=c174fe5824aaf44fa35a0957c3e5d5dbfb19ee50;hb=d1dd9aae6741e74f20bfc35e1db598652680279d;hpb=bd3bd69af16ab99706ba70ed11a3e291e968e5c6 diff --git a/libeap/src/eap_peer/eap_ttls.c b/libeap/src/eap_peer/eap_ttls.c index c174fe5..12ea169 100644 --- a/libeap/src/eap_peer/eap_ttls.c +++ b/libeap/src/eap_peer/eap_ttls.c @@ -1,6 +1,6 @@ /* * EAP peer method: EAP-TTLS (RFC 5281) - * Copyright (c) 2004-2011, Jouni Malinen + * Copyright (c) 2004-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -36,6 +36,7 @@ struct eap_ttls_data { void *phase2_priv; int phase2_success; int phase2_start; + EapDecision decision_succ; enum phase2_types { EAP_TTLS_PHASE2_EAP, @@ -59,9 +60,10 @@ struct eap_ttls_data { size_t id_len; struct wpabuf *pending_phase2_req; + struct wpabuf *pending_resp; int chbind_req_sent; /* channel binding request was sent */ int done_butfor_cb; /*we turned METHOD_DONE into METHOD_MAY_CONT to receive cb*/ - EapDecision cbDecision; + EapDecision cbDecision; #ifdef EAP_TNC int ready_for_tnc; int tnc_started; @@ -90,6 +92,7 @@ static void * eap_ttls_init(struct eap_sm *sm) { struct eap_ttls_data *data; struct eap_peer_config *config = eap_get_config(sm); + int selected_non_eap; char *selected; data = os_zalloc(sizeof(*data)); @@ -97,26 +100,67 @@ static void * eap_ttls_init(struct eap_sm *sm) return NULL; data->ttls_version = EAP_TTLS_VERSION; selected = "EAP"; + selected_non_eap = 0; data->phase2_type = EAP_TTLS_PHASE2_EAP; + /* + * Either one auth= type or one or more autheap= methods can be + * specified. + */ if (config && config->phase2) { + const char *token, *last = NULL; + + while ((token = cstr_token(config->phase2, " \t", &last))) { + if (os_strncmp(token, "auth=", 5) != 0) + continue; + token += 5; + + if (last - token == 8 && + os_strncmp(token, "MSCHAPV2", 8) == 0) { + selected = "MSCHAPV2"; + data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2; + } else if (last - token == 6 && + os_strncmp(token, "MSCHAP", 6) == 0) { + selected = "MSCHAP"; + data->phase2_type = EAP_TTLS_PHASE2_MSCHAP; + } else if (last - token == 3 && + os_strncmp(token, "PAP", 3) == 0) { + selected = "PAP"; + data->phase2_type = EAP_TTLS_PHASE2_PAP; + } else if (last - token == 4 && + os_strncmp(token, "CHAP", 4) == 0) { + selected = "CHAP"; + data->phase2_type = EAP_TTLS_PHASE2_CHAP; + } else { + wpa_printf(MSG_ERROR, + "EAP-TTLS: Unsupported Phase2 type '%s'", + token); + eap_ttls_deinit(sm, data); + return NULL; + } + + if (selected_non_eap) { + wpa_printf(MSG_ERROR, + "EAP-TTLS: Only one Phase2 type can be specified"); + eap_ttls_deinit(sm, data); + return NULL; + } + + selected_non_eap = 1; + } + if (os_strstr(config->phase2, "autheap=")) { + if (selected_non_eap) { + wpa_printf(MSG_ERROR, + "EAP-TTLS: Both auth= and autheap= params cannot be specified"); + eap_ttls_deinit(sm, data); + return NULL; + } selected = "EAP"; data->phase2_type = EAP_TTLS_PHASE2_EAP; - } else if (os_strstr(config->phase2, "auth=MSCHAPV2")) { - selected = "MSCHAPV2"; - data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2; - } else if (os_strstr(config->phase2, "auth=MSCHAP")) { - selected = "MSCHAP"; - data->phase2_type = EAP_TTLS_PHASE2_MSCHAP; - } else if (os_strstr(config->phase2, "auth=PAP")) { - selected = "PAP"; - data->phase2_type = EAP_TTLS_PHASE2_PAP; - } else if (os_strstr(config->phase2, "auth=CHAP")) { - selected = "CHAP"; - data->phase2_type = EAP_TTLS_PHASE2_CHAP; } } + wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected); if (data->phase2_type == EAP_TTLS_PHASE2_EAP) { @@ -173,6 +217,7 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv) eap_ttls_free_key(data); os_free(data->session_id); wpabuf_free(data->pending_phase2_req); + wpabuf_free(data->pending_resp); os_free(data); } @@ -1643,6 +1688,32 @@ static int eap_ttls_process_handshake(struct eap_sm *sm, { int res; + if (sm->waiting_ext_cert_check && data->pending_resp) { + struct eap_peer_config *config = eap_get_config(sm); + + if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) { + wpa_printf(MSG_DEBUG, + "EAP-TTLS: External certificate check succeeded - continue handshake"); + *out_data = data->pending_resp; + data->pending_resp = NULL; + sm->waiting_ext_cert_check = 0; + return 0; + } + + if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) { + wpa_printf(MSG_DEBUG, + "EAP-TTLS: External certificate check failed - force authentication failure"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + sm->waiting_ext_cert_check = 0; + return 0; + } + + wpa_printf(MSG_DEBUG, + "EAP-TTLS: Continuing to wait external server certificate validation"); + return 0; + } + res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, data->ttls_version, identifier, in_data, out_data); @@ -1653,6 +1724,15 @@ static int eap_ttls_process_handshake(struct eap_sm *sm, return -1; } + if (sm->waiting_ext_cert_check) { + wpa_printf(MSG_DEBUG, + "EAP-TTLS: Waiting external server certificate validation"); + wpabuf_free(data->pending_resp); + data->pending_resp = *out_data; + *out_data = NULL; + return 0; + } + if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to " "Phase 2"); @@ -1703,6 +1783,7 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " "completed successfully"); data->phase2_success = 1; + data->decision_succ = ret->decision; #ifdef EAP_TNC if (!data->ready_for_tnc && !data->tnc_started) { /* @@ -1720,6 +1801,18 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " "completed successfully (MAY_CONT)"); data->phase2_success = 1; + data->decision_succ = ret->decision; + } else if (data->decision_succ != DECISION_FAIL && + data->phase2_success && + !data->ssl.tls_out) { + /* + * This is needed to cover the case where the final Phase 2 + * message gets fragmented since fragmentation clears + * decision back to FAIL. + */ + wpa_printf(MSG_DEBUG, + "EAP-TTLS: Restore success decision after fragmented frame sent completely"); + ret->decision = data->decision_succ; } } @@ -1792,6 +1885,9 @@ static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv) struct eap_ttls_data *data = priv; wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = NULL; + wpabuf_free(data->pending_resp); + data->pending_resp = NULL; + data->decision_succ = DECISION_FAIL; #ifdef EAP_TNC data->ready_for_tnc = 0; data->tnc_started = 0; @@ -1930,7 +2026,6 @@ static u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_ttls_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS"); @@ -1949,8 +2044,5 @@ int eap_peer_ttls_register(void) eap->init_for_reauth = eap_ttls_init_for_reauth; eap->get_emsk = eap_ttls_get_emsk; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); }