diff --git a/components/wpa_supplicant/src/common/defs.h b/components/wpa_supplicant/src/common/defs.h index 99759b3c6f..543f1bbd6b 100644 --- a/components/wpa_supplicant/src/common/defs.h +++ b/components/wpa_supplicant/src/common/defs.h @@ -369,6 +369,7 @@ enum wpa_ctrl_req_type { WPA_CTRL_REQ_EAP_PASSPHRASE, WPA_CTRL_REQ_SIM, WPA_CTRL_REQ_PSK_PASSPHRASE, + WPA_CTRL_REQ_EXT_CERT_CHECK, NUM_WPA_CTRL_REQS }; diff --git a/components/wpa_supplicant/src/eap_peer/eap.c b/components/wpa_supplicant/src/eap_peer/eap.c index bce12af1fc..458b077572 100644 --- a/components/wpa_supplicant/src/eap_peer/eap.c +++ b/components/wpa_supplicant/src/eap_peer/eap.c @@ -71,6 +71,8 @@ int (*esp_crt_bundle_attach_fn)(void *conf); void eap_peer_config_deinit(struct eap_sm *sm); void eap_peer_blob_deinit(struct eap_sm *sm); void eap_deinit_prev_method(struct eap_sm *sm, const char *txt); +static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field, + const char *msg, size_t msglen); #ifdef EAP_PEER_METHOD static struct eap_method *eap_methods = NULL; @@ -713,10 +715,10 @@ _out: return ret; } -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field, const char *msg, size_t msglen) { +#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) struct eap_peer_config *config; if (sm == NULL) @@ -741,14 +743,14 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field, case WPA_CTRL_REQ_EAP_PASSPHRASE: config->pending_req_passphrase++; break; + case WPA_CTRL_REQ_EXT_CERT_CHECK: + break; default: return; } -} -#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ -#define eap_sm_request(sm, type, msg, msglen) do { } while (0) #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ +} const char * eap_sm_get_method_name(struct eap_sm *sm) { diff --git a/components/wpa_supplicant/src/eap_peer/eap_peap.c b/components/wpa_supplicant/src/eap_peer/eap_peap.c index 744a6bb6ae..ecd2a39b29 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_peap.c +++ b/components/wpa_supplicant/src/eap_peer/eap_peap.c @@ -1,6 +1,6 @@ /* * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2008, 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. @@ -59,6 +59,7 @@ struct eap_peap_data { size_t id_len; struct wpabuf *pending_phase2_req; + struct wpabuf *pending_resp; enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; int crypto_binding_used; u8 binding_nonce[32]; @@ -200,6 +201,7 @@ eap_peap_deinit(struct eap_sm *sm, void *priv) os_free(data->key_data); os_free(data->session_id); wpabuf_free(data->pending_phase2_req); + wpabuf_free(data->pending_resp); os_free(data); } @@ -1122,6 +1124,34 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, wpabuf_set(&msg, pos, left); res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); } else { + 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-PEAP: External certificate check succeeded - continue handshake"); + resp = data->pending_resp; + data->pending_resp = NULL; + sm->waiting_ext_cert_check = 0; + return resp; + } + + if (config->pending_ext_cert_check == + EXT_CERT_CHECK_BAD) { + wpa_printf(MSG_DEBUG, + "EAP-PEAP: External certificate check failed - force authentication failure"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + sm->waiting_ext_cert_check = 0; + return NULL; + } + + wpa_printf(MSG_DEBUG, + "EAP-PEAP: Continuing to wait external server certificate validation"); + return NULL; + } + res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP, data->peap_version, id, pos, @@ -1135,6 +1165,16 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, return resp; } + + if (sm->waiting_ext_cert_check) { + wpa_printf(MSG_DEBUG, + "EAP-PEAP: Waiting external server certificate validation"); + wpabuf_free(data->pending_resp); + data->pending_resp = resp; + return NULL; + } + + if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { char label[24] = {0}; wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS done, proceed to Phase 2"); @@ -1244,6 +1284,8 @@ eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv) struct eap_peap_data *data = priv; wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = NULL; + wpabuf_free(data->pending_resp); + data->pending_resp = NULL; data->crypto_binding_used = 0; } diff --git a/components/wpa_supplicant/src/eap_peer/eap_tls.c b/components/wpa_supplicant/src/eap_peer/eap_tls.c index 0da0c7f86a..3f7e89e260 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_tls.c +++ b/components/wpa_supplicant/src/eap_peer/eap_tls.c @@ -1,6 +1,6 @@ /* * EAP peer method: EAP-TLS (RFC 2716) - * Copyright (c) 2004-2008, 2012, Jouni Malinen + * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -27,6 +27,7 @@ struct eap_tls_data { size_t id_len; void *ssl_ctx; u8 eap_type; + struct wpabuf *pending_resp; }; @@ -67,6 +68,7 @@ static void eap_tls_deinit(struct eap_sm *sm, void *priv) eap_peer_tls_ssl_deinit(sm, &data->ssl); os_free(data->key_data); os_free(data->session_id); + wpabuf_free(data->pending_resp); os_free(data); } @@ -154,6 +156,32 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, const u8 *pos; struct eap_tls_data *data = priv; + 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-TLS: External certificate check succeeded - continue handshake"); + resp = data->pending_resp; + data->pending_resp = NULL; + sm->waiting_ext_cert_check = 0; + return resp; + } + + if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) { + wpa_printf(MSG_DEBUG, + "EAP-TLS: External certificate check failed - force authentication failure"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + sm->waiting_ext_cert_check = 0; + return NULL; + } + + wpa_printf(MSG_DEBUG, + "EAP-TLS: Continuing to wait external server certificate validation"); + return NULL; + } + pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, reqData, &left, &flags); if (pos == NULL) @@ -174,6 +202,14 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, return eap_tls_failure(sm, data, ret, res, resp, id); } + if (sm->waiting_ext_cert_check) { + wpa_printf(MSG_DEBUG, + "EAP-TLS: Waiting external server certificate validation"); + wpabuf_free(data->pending_resp); + data->pending_resp = resp; + return NULL; + } + if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) eap_tls_success(sm, data, ret); diff --git a/components/wpa_supplicant/src/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/eap_peer/eap_ttls.c index 243544a2c2..84cf9260e0 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_ttls.c +++ b/components/wpa_supplicant/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. @@ -59,6 +59,7 @@ struct eap_ttls_data { size_t id_len; struct wpabuf *pending_phase2_req; + struct wpabuf *pending_resp; #ifdef EAP_TNC int ready_for_tnc; @@ -137,6 +138,7 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv) os_free(data->key_data); os_free(data->session_id); wpabuf_free(data->pending_phase2_req); + wpabuf_free(data->pending_resp); os_free(data); } @@ -1393,10 +1395,52 @@ 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, in_len, out_data); + if (res < 0) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS processing failed"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + 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"); @@ -1537,6 +1581,8 @@ 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; #ifdef EAP_TNC data->ready_for_tnc = 0; data->tnc_started = 0;