diff options
Diffstat (limited to 'freebsd/contrib/wpa/src/eap_peer')
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap.c | 80 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_config.h | 20 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_gtc.c | 6 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_i.h | 2 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_leap.c | 6 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_md5.c | 6 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_methods.c | 17 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_methods.h | 1 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c | 6 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_otp.c | 6 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_peap.c | 76 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_psk.c | 6 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_tls.c | 60 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c | 23 | ||||
-rw-r--r-- | freebsd/contrib/wpa/src/eap_peer/eap_ttls.c | 128 |
15 files changed, 310 insertions, 133 deletions
diff --git a/freebsd/contrib/wpa/src/eap_peer/eap.c b/freebsd/contrib/wpa/src/eap_peer/eap.c index cfaf201a..6a183071 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap.c @@ -50,6 +50,8 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req); static const char * eap_sm_method_state_txt(EapMethodState state); static const char * eap_sm_decision_txt(EapDecision decision); #endif /* CONFIG_CTRL_IFACE || !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); @@ -190,6 +192,14 @@ SM_STATE(EAP, INITIALIZE) */ eapol_set_bool(sm, EAPOL_eapResp, FALSE); eapol_set_bool(sm, EAPOL_eapNoResp, FALSE); + /* + * RFC 4137 does not reset ignore here, but since it is possible for + * some method code paths to end up not setting ignore=FALSE, clear the + * value here to avoid issues if a previous authentication attempt + * failed with ignore=TRUE being left behind in the last + * m.check(eapReqData) operation. + */ + sm->ignore = 0; sm->num_rounds = 0; sm->prev_failure = 0; sm->expected_failure = 0; @@ -314,11 +324,14 @@ SM_STATE(EAP, GET_METHOD) wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: " "vendor %u method %u (%s)", sm->reqVendor, method, sm->m->name); - if (reinit) + if (reinit) { sm->eap_method_priv = sm->m->init_for_reauth( sm, sm->eap_method_priv); - else + } else { + sm->waiting_ext_cert_check = 0; + sm->ext_cert_check = 0; sm->eap_method_priv = sm->m->init(sm); + } if (sm->eap_method_priv == NULL) { struct eap_peer_config *config = eap_get_config(sm); @@ -1375,13 +1388,10 @@ static int eap_sm_imsi_identity(struct eap_sm *sm, return 0; } -#endif /* PCSC_FUNCS */ - static int eap_sm_set_scard_pin(struct eap_sm *sm, struct eap_peer_config *conf) { -#ifdef PCSC_FUNCS if (scard_set_pin(sm->scard_ctx, conf->pin)) { /* * Make sure the same PIN is not tried again in order to avoid @@ -1395,24 +1405,20 @@ static int eap_sm_set_scard_pin(struct eap_sm *sm, return -1; } return 0; -#else /* PCSC_FUNCS */ - return -1; -#endif /* PCSC_FUNCS */ } + static int eap_sm_get_scard_identity(struct eap_sm *sm, struct eap_peer_config *conf) { -#ifdef PCSC_FUNCS if (eap_sm_set_scard_pin(sm, conf)) return -1; return eap_sm_imsi_identity(sm, conf); -#else /* PCSC_FUNCS */ - return -1; -#endif /* PCSC_FUNCS */ } +#endif /* PCSC_FUNCS */ + /** * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network @@ -1455,23 +1461,27 @@ struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted) identity, identity_len); } - if (identity == NULL) { - wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity " - "configuration was not available"); - if (config->pcsc) { + if (config->pcsc) { +#ifdef PCSC_FUNCS + if (!identity) { if (eap_sm_get_scard_identity(sm, config) < 0) return NULL; identity = config->identity; identity_len = config->identity_len; - wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from " - "IMSI", identity, identity_len); - } else { - eap_sm_request_identity(sm); + wpa_hexdump_ascii(MSG_DEBUG, + "permanent identity from IMSI", + identity, identity_len); + } else if (eap_sm_set_scard_pin(sm, config) < 0) { return NULL; } - } else if (config->pcsc) { - if (eap_sm_set_scard_pin(sm, config) < 0) - return NULL; +#else /* PCSC_FUNCS */ + return NULL; +#endif /* PCSC_FUNCS */ + } else if (!identity) { + wpa_printf(MSG_WARNING, + "EAP: buildIdentity: identity configuration was not available"); + eap_sm_request_identity(sm); + return NULL; } resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len, @@ -1512,15 +1522,9 @@ static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req) static struct wpabuf * eap_sm_buildNotify(int id) { - struct wpabuf *resp; - wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification"); - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - return resp; + return eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0, + EAP_CODE_RESPONSE, id); } @@ -1852,6 +1856,11 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev, case TLS_CERT_CHAIN_SUCCESS: eap_notify_status(sm, "remote certificate verification", "success"); + if (sm->ext_cert_check) { + sm->waiting_ext_cert_check = 1; + eap_sm_request(sm, WPA_CTRL_REQ_EXT_CERT_CHECK, + NULL, 0); + } break; case TLS_CERT_CHAIN_FAILURE: wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR @@ -2174,10 +2183,10 @@ int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose) #endif /* CONFIG_CTRL_IFACE */ -#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; const char *txt = NULL; char *tmp; @@ -2226,16 +2235,17 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field, case WPA_CTRL_REQ_SIM: txt = msg; break; + case WPA_CTRL_REQ_EXT_CERT_CHECK: + break; default: return; } if (sm->eapol_cb->eap_param_needed) sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt); -} -#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/freebsd/contrib/wpa/src/eap_peer/eap_config.h b/freebsd/contrib/wpa/src/eap_peer/eap_config.h index 2b1a1d5e..f9800726 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_config.h +++ b/freebsd/contrib/wpa/src/eap_peer/eap_config.h @@ -181,13 +181,13 @@ struct eap_peer_config { * subject_match - Constraint for server certificate subject * * This substring is matched against the subject of the authentication - * server certificate. If this string is set, the server sertificate is + * server certificate. If this string is set, the server certificate is * only accepted if it contains this string in the subject. The subject * string is in following format: * * /C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as@n.example.com * - * Note: Since this is a substring match, this cannot be used securily + * Note: Since this is a substring match, this cannot be used securely * to do a suffix match against a possible domain name in the CN entry. * For such a use case, domain_suffix_match should be used instead. */ @@ -198,7 +198,7 @@ struct eap_peer_config { * * Semicolon separated string of entries to be matched against the * alternative subject name of the authentication server certificate. - * If this string is set, the server sertificate is only accepted if it + * If this string is set, the server certificate is only accepted if it * contains one of the entries in an alternative subject name * extension. * @@ -739,6 +739,20 @@ struct eap_peer_config { * erp - Whether EAP Re-authentication Protocol (ERP) is enabled */ int erp; + + /** + * pending_ext_cert_check - External server certificate check status + * + * This field should not be set in configuration step. It is only used + * internally when control interface is used to request external + * validation of server certificate chain. + */ + enum { + NO_CHECK = 0, + PENDING_CHECK, + EXT_CERT_CHECK_GOOD, + EXT_CERT_CHECK_BAD, + } pending_ext_cert_check; }; diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_gtc.c b/freebsd/contrib/wpa/src/eap_peer/eap_gtc.c index 2ffc142c..cacf3d41 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_gtc.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_gtc.c @@ -129,7 +129,6 @@ static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, int eap_peer_gtc_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC"); @@ -140,8 +139,5 @@ int eap_peer_gtc_register(void) eap->deinit = eap_gtc_deinit; eap->process = eap_gtc_process; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_i.h b/freebsd/contrib/wpa/src/eap_peer/eap_i.h index 99b44dae..6ab24834 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_i.h +++ b/freebsd/contrib/wpa/src/eap_peer/eap_i.h @@ -366,6 +366,8 @@ struct eap_sm { int external_sim; unsigned int expected_failure:1; + unsigned int ext_cert_check:1; + unsigned int waiting_ext_cert_check:1; struct dl_list erp_keys; /* struct eap_erp_key */ }; diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_leap.c b/freebsd/contrib/wpa/src/eap_peer/eap_leap.c index e765af14..af63bf88 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_leap.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_leap.c @@ -395,7 +395,6 @@ static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_leap_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_LEAP, "LEAP"); @@ -408,8 +407,5 @@ int eap_peer_leap_register(void) eap->isKeyAvailable = eap_leap_isKeyAvailable; eap->getKey = eap_leap_getKey; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_md5.c b/freebsd/contrib/wpa/src/eap_peer/eap_md5.c index 145bfa8f..2cc66e6d 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_md5.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_md5.c @@ -104,7 +104,6 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, int eap_peer_md5_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5"); @@ -115,8 +114,5 @@ int eap_peer_md5_register(void) eap->deinit = eap_md5_deinit; eap->process = eap_md5_process; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_methods.c b/freebsd/contrib/wpa/src/eap_peer/eap_methods.c index 44b4af92..23004eac 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_methods.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_methods.c @@ -23,6 +23,8 @@ static struct eap_method *eap_methods = NULL; +static void eap_peer_method_free(struct eap_method *method); + /** * eap_peer_get_eap_method - Get EAP method based on type number @@ -300,7 +302,7 @@ struct eap_method * eap_peer_method_alloc(int version, int vendor, * eap_peer_method_free - Free EAP peer method structure * @method: Method structure allocated with eap_peer_method_alloc() */ -void eap_peer_method_free(struct eap_method *method) +static void eap_peer_method_free(struct eap_method *method) { os_free(method); } @@ -308,26 +310,31 @@ void eap_peer_method_free(struct eap_method *method) /** * eap_peer_method_register - Register an EAP peer method - * @method: EAP method to register + * @method: EAP method to register from eap_peer_method_alloc() * Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method * has already been registered * * Each EAP peer method needs to call this function to register itself as a - * supported EAP method. + * supported EAP method. The caller must not free the allocated method data + * regardless of the return value. */ int eap_peer_method_register(struct eap_method *method) { struct eap_method *m, *last = NULL; if (method == NULL || method->name == NULL || - method->version != EAP_PEER_METHOD_INTERFACE_VERSION) + method->version != EAP_PEER_METHOD_INTERFACE_VERSION) { + eap_peer_method_free(method); return -1; + } for (m = eap_methods; m; m = m->next) { if ((m->vendor == method->vendor && m->method == method->method) || - os_strcmp(m->name, method->name) == 0) + os_strcmp(m->name, method->name) == 0) { + eap_peer_method_free(method); return -2; + } last = m; } diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_methods.h b/freebsd/contrib/wpa/src/eap_peer/eap_methods.h index e35c919a..b96b211d 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_methods.h +++ b/freebsd/contrib/wpa/src/eap_peer/eap_methods.h @@ -16,7 +16,6 @@ const struct eap_method * eap_peer_get_methods(size_t *count); struct eap_method * eap_peer_method_alloc(int version, int vendor, EapType method, const char *name); -void eap_peer_method_free(struct eap_method *method); int eap_peer_method_register(struct eap_method *method); diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c b/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c index 18bb04c2..9193a772 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c @@ -882,7 +882,6 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_mschapv2_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, @@ -896,8 +895,5 @@ int eap_peer_mschapv2_register(void) eap->isKeyAvailable = eap_mschapv2_isKeyAvailable; eap->getKey = eap_mschapv2_getKey; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_otp.c b/freebsd/contrib/wpa/src/eap_peer/eap_otp.c index d4d8bc1c..f375d438 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_otp.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_otp.c @@ -85,7 +85,6 @@ static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv, int eap_peer_otp_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_OTP, "OTP"); @@ -96,8 +95,5 @@ int eap_peer_otp_register(void) eap->deinit = eap_otp_deinit; eap->process = eap_otp_process; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_peap.c b/freebsd/contrib/wpa/src/eap_peer/eap_peap.c index 19afa1cf..ab270bbc 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_peap.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_peap.c @@ -2,7 +2,7 @@ /* * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -61,6 +61,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]; @@ -71,8 +72,8 @@ struct eap_peap_data { }; -static int eap_peap_parse_phase1(struct eap_peap_data *data, - const char *phase1) +static void eap_peap_parse_phase1(struct eap_peap_data *data, + const char *phase1) { const char *pos; @@ -127,8 +128,6 @@ static int eap_peap_parse_phase1(struct eap_peap_data *data, wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); } #endif /* EAP_TNC */ - - return 0; } @@ -146,11 +145,8 @@ static void * eap_peap_init(struct eap_sm *sm) data->peap_outer_success = 2; data->crypto_binding = OPTIONAL_BINDING; - if (config && config->phase1 && - eap_peap_parse_phase1(data, config->phase1) < 0) { - eap_peap_deinit(sm, data); - return NULL; - } + if (config && config->phase1) + eap_peap_parse_phase1(data, config->phase1); if (eap_peer_select_phase2_methods(config, "auth=", &data->phase2_types, @@ -193,6 +189,7 @@ static void eap_peap_deinit(struct eap_sm *sm, void *priv) eap_peap_free_key(data); os_free(data->session_id); wpabuf_free(data->pending_phase2_req); + wpabuf_free(data->pending_resp); os_free(data); } @@ -258,6 +255,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) { u8 *tk; u8 isk[32], imck[60]; + int resumed; /* * Tunnel key (TK) is the first 60 octets of the key generated by @@ -268,8 +266,12 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) return -1; wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); - if (data->reauth && - tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { + resumed = tls_connection_resumed(sm->ssl_ctx, data->ssl.conn); + wpa_printf(MSG_DEBUG, + "EAP-PEAP: CMK derivation - reauth=%d resumed=%d phase2_eap_started=%d phase2_success=%d", + data->reauth, resumed, data->phase2_eap_started, + data->phase2_success); + if (data->reauth && !data->phase2_eap_started && resumed) { /* Fast-connect: IPMK|CMK = TK */ os_memcpy(data->ipmk, tk, 40); wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK", @@ -339,7 +341,8 @@ static int eap_tlv_add_cryptobinding(struct eap_sm *sm, addr[0], len[0]); wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", addr[1], len[1]); - hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); + if (hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac) < 0) + return -1; wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN); data->crypto_binding_used = 1; @@ -650,6 +653,7 @@ static int eap_peap_phase2_request(struct eap_sm *sm, if (*resp == NULL) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; + wpabuf_free(buf); return -1; } wpabuf_put_buf(*resp, buf); @@ -1008,6 +1012,34 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, !data->resuming) { 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, &msg, @@ -1020,6 +1052,16 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, ret->decision = DECISION_FAIL; 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; wpa_printf(MSG_DEBUG, @@ -1125,6 +1167,8 @@ static void 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; } @@ -1239,7 +1283,6 @@ static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_peap_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); @@ -1257,8 +1300,5 @@ int eap_peer_peap_register(void) eap->init_for_reauth = eap_peap_init_for_reauth; eap->getSessionId = eap_peap_get_session_id; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_psk.c b/freebsd/contrib/wpa/src/eap_peer/eap_psk.c index f91c9b39..49ed1736 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_psk.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_psk.c @@ -482,7 +482,6 @@ static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_psk_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); @@ -497,8 +496,5 @@ int eap_peer_psk_register(void) eap->getSessionId = eap_psk_get_session_id; eap->get_emsk = eap_psk_get_emsk; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_tls.c b/freebsd/contrib/wpa/src/eap_peer/eap_tls.c index 8ca6db9c..35afcf77 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_tls.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_tls.c @@ -2,7 +2,7 @@ /* * EAP peer method: EAP-TLS (RFC 2716) - * Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen <j@w1.fi> * * 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; }; @@ -144,6 +145,7 @@ static void eap_tls_deinit(struct eap_sm *sm, void *priv) eap_peer_tls_ssl_deinit(sm, &data->ssl); eap_tls_free_key(data); os_free(data->session_id); + wpabuf_free(data->pending_resp); os_free(data); } @@ -218,6 +220,32 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, struct eap_tls_data *data = priv; struct wpabuf msg; + 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) @@ -239,6 +267,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); @@ -260,6 +296,10 @@ static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) { + struct eap_tls_data *data = priv; + + wpabuf_free(data->pending_resp); + data->pending_resp = NULL; } @@ -352,7 +392,6 @@ static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_tls_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); @@ -371,10 +410,7 @@ int eap_peer_tls_register(void) eap->init_for_reauth = eap_tls_init_for_reauth; eap->get_emsk = eap_tls_get_emsk; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } @@ -382,7 +418,6 @@ int eap_peer_tls_register(void) int eap_peer_unauth_tls_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_UNAUTH_TLS, @@ -401,10 +436,7 @@ int eap_peer_unauth_tls_register(void) eap->init_for_reauth = eap_tls_init_for_reauth; eap->get_emsk = eap_tls_get_emsk; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } #endif /* EAP_UNAUTH_TLS */ @@ -413,7 +445,6 @@ int eap_peer_unauth_tls_register(void) int eap_peer_wfa_unauth_tls_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_WFA_NEW, @@ -433,9 +464,6 @@ int eap_peer_wfa_unauth_tls_register(void) eap->init_for_reauth = eap_tls_init_for_reauth; eap->get_emsk = eap_tls_get_emsk; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } #endif /* CONFIG_HS20 */ diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c index ff6c937c..8908dc2f 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c @@ -82,6 +82,10 @@ static void eap_tls_params_flags(struct tls_connection_params *params, params->flags |= TLS_CONN_DISABLE_TLSv1_2; if (os_strstr(txt, "tls_disable_tlsv1_2=0")) params->flags &= ~TLS_CONN_DISABLE_TLSv1_2; + if (os_strstr(txt, "tls_ext_cert_check=1")) + params->flags |= TLS_CONN_EXT_CERT_CHECK; + if (os_strstr(txt, "tls_ext_cert_check=0")) + params->flags &= ~TLS_CONN_EXT_CERT_CHECK; } @@ -179,6 +183,8 @@ static int eap_tls_params_from_conf(struct eap_sm *sm, params->openssl_ciphers = config->openssl_ciphers; + sm->ext_cert_check = !!(params->flags & TLS_CONN_EXT_CERT_CHECK); + return 0; } @@ -192,8 +198,10 @@ static int eap_tls_init_connection(struct eap_sm *sm, if (config->ocsp) params->flags |= TLS_CONN_REQUEST_OCSP; - if (config->ocsp == 2) + if (config->ocsp >= 2) params->flags |= TLS_CONN_REQUIRE_OCSP; + if (config->ocsp == 3) + params->flags |= TLS_CONN_REQUIRE_OCSP_ALL; data->conn = tls_connection_init(data->ssl_ctx); if (data->conn == NULL) { wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " @@ -322,8 +330,8 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, if (out == NULL) return NULL; - if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, 0, - out, len)) { + if (tls_connection_export_key(data->ssl_ctx, data->conn, label, out, + len)) { os_free(out); return NULL; } @@ -352,10 +360,8 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, struct tls_random keys; u8 *out; - if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys)) - return NULL; - - if (keys.client_random == NULL || keys.server_random == NULL) + if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys) || + keys.client_random == NULL || keys.server_random == NULL) return NULL; *len = 1 + keys.client_random_len + keys.server_random_len; @@ -1037,6 +1043,9 @@ int eap_peer_select_phase2_methods(struct eap_peer_config *config, if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) { wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP " "method '%s'", start); + os_free(methods); + os_free(buf); + return -1; } else { num_methods++; _methods = os_realloc_array(methods, num_methods, diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c b/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c index 55788774..f9601e45 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c @@ -2,7 +2,7 @@ /* * EAP peer method: EAP-TTLS (RFC 5281) - * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -37,6 +37,7 @@ struct eap_ttls_data { void *phase2_priv; int phase2_success; int phase2_start; + EapDecision decision_succ; enum phase2_types { EAP_TTLS_PHASE2_EAP, @@ -60,6 +61,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; @@ -72,6 +74,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)); @@ -79,26 +82,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) { @@ -155,6 +199,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); } @@ -1410,6 +1455,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); @@ -1420,6 +1491,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"); @@ -1470,6 +1550,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) { /* @@ -1487,6 +1568,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; } } @@ -1559,6 +1652,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; @@ -1697,7 +1793,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"); @@ -1716,8 +1811,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); } |