diff options
author | Cy Schubert <cy@FreeBSD.org> | 2017-10-18 03:44:27 +0000 |
---|---|---|
committer | Cy Schubert <cy@FreeBSD.org> | 2017-10-18 03:44:27 +0000 |
commit | 256810032c472505440606bd9c1c4f7dbf06b0a2 (patch) | |
tree | d019f4f1ae29b86cbd3e9e74f832689976a267cf /src/eap_peer | |
parent | b834757ea3bcd1bba3381ff7cab216458d8f7efb (diff) |
Notes
Diffstat (limited to 'src/eap_peer')
30 files changed, 461 insertions, 267 deletions
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c index 56c24b5503200..9110ca5b9cfd6 100644 --- a/src/eap_peer/eap.c +++ b/src/eap_peer/eap.c @@ -48,6 +48,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); @@ -188,6 +190,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; @@ -312,11 +322,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); @@ -1373,13 +1386,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 @@ -1393,24 +1403,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 @@ -1453,23 +1459,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, @@ -1510,15 +1520,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); } @@ -1850,6 +1854,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 @@ -2172,10 +2181,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; @@ -2224,16 +2233,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/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c index dc9e8cc34d4af..0bac62dee523a 100644 --- a/src/eap_peer/eap_aka.c +++ b/src/eap_peer/eap_aka.c @@ -1492,7 +1492,6 @@ static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_aka_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); @@ -1511,10 +1510,7 @@ int eap_peer_aka_register(void) eap->get_identity = eap_aka_get_identity; eap->get_emsk = eap_aka_get_emsk; - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; + return eap_peer_method_register(eap); } @@ -1522,7 +1518,6 @@ int eap_peer_aka_register(void) int eap_peer_aka_prime_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, @@ -1542,10 +1537,6 @@ int eap_peer_aka_prime_register(void) eap->get_identity = eap_aka_get_identity; eap->get_emsk = eap_aka_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_AKA_PRIME */ diff --git a/src/eap_peer/eap_config.h b/src/eap_peer/eap_config.h index 2b1a1d5e4b254..f98007263b338 100644 --- a/src/eap_peer/eap_config.h +++ b/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/src/eap_peer/eap_eke.c b/src/eap_peer/eap_eke.c index dfbda5644f6fc..f899f653fdca4 100644 --- a/src/eap_peer/eap_eke.c +++ b/src/eap_peer/eap_eke.c @@ -452,6 +452,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm, /* DHComponent_P = Encr(key, y_p) */ rpos = wpabuf_put(resp, data->sess.dhcomp_len); if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) { + wpabuf_free(resp); wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_P"); os_memset(key, 0, sizeof(key)); return eap_eke_build_fail(data, ret, id, @@ -770,7 +771,6 @@ static u8 * eap_eke_get_session_id(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_eke_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE"); @@ -785,8 +785,5 @@ int eap_peer_eke_register(void) eap->get_emsk = eap_eke_get_emsk; eap->getSessionId = eap_eke_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/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c index 4cbe3bacb0a61..964ebe74fede8 100644 --- a/src/eap_peer/eap_fast.c +++ b/src/eap_peer/eap_fast.c @@ -1,6 +1,6 @@ /* * EAP peer method: EAP-FAST (RFC 4851) - * 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. @@ -67,6 +67,7 @@ struct eap_fast_data { int simck_idx; struct wpabuf *pending_phase2_req; + struct wpabuf *pending_resp; }; @@ -112,8 +113,8 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, } -static int eap_fast_parse_phase1(struct eap_fast_data *data, - const char *phase1) +static void eap_fast_parse_phase1(struct eap_fast_data *data, + const char *phase1) { const char *pos; @@ -139,8 +140,6 @@ static int eap_fast_parse_phase1(struct eap_fast_data *data, wpa_printf(MSG_DEBUG, "EAP-FAST: Using binary format for PAC " "list"); } - - return 0; } @@ -158,10 +157,8 @@ static void * eap_fast_init(struct eap_sm *sm) data->fast_version = EAP_FAST_VERSION; data->max_pac_list_len = 10; - if (config->phase1 && eap_fast_parse_phase1(data, config->phase1) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } + if (config->phase1) + eap_fast_parse_phase1(data, config->phase1); if (eap_peer_select_phase2_methods(config, "auth=", &data->phase2_types, @@ -254,14 +251,16 @@ static void eap_fast_deinit(struct eap_sm *sm, void *priv) os_memset(data->emsk, 0, EAP_EMSK_LEN); os_free(data->session_id); wpabuf_free(data->pending_phase2_req); + wpabuf_free(data->pending_resp); os_free(data); } static int eap_fast_derive_msk(struct eap_fast_data *data) { - eap_fast_derive_eap_msk(data->simck, data->key_data); - eap_fast_derive_eap_emsk(data->simck, data->emsk); + if (eap_fast_derive_eap_msk(data->simck, data->key_data) < 0 || + eap_fast_derive_eap_emsk(data->simck, data->emsk) < 0) + return -1; data->success = 1; return 0; } @@ -276,7 +275,7 @@ static int eap_fast_derive_key_auth(struct eap_sm *sm, * Extra key material after TLS key_block: session_key_seed[40] */ - sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion", + sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, EAP_FAST_SKS_LEN); if (sks == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive " @@ -304,7 +303,6 @@ static int eap_fast_derive_key_provisioning(struct eap_sm *sm, os_free(data->key_block_p); data->key_block_p = (struct eap_fast_key_block_provisioning *) eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, - "key expansion", sizeof(*data->key_block_p)); if (data->key_block_p == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block"); @@ -711,9 +709,10 @@ static int eap_fast_get_cmk(struct eap_sm *sm, struct eap_fast_data *data, if (eap_fast_get_phase2_key(sm, data, isk, sizeof(isk)) < 0) return -1; wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[j]", isk, sizeof(isk)); - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); + if (sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, + "Inner Methods Compound Keys", + isk, sizeof(isk), imck, sizeof(imck)) < 0) + return -1; data->simck_idx++; os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN); wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]", @@ -1096,7 +1095,7 @@ static int eap_fast_parse_decrypted(struct wpabuf *decrypted, /* Parse TLVs from the decrypted Phase 2 data */ pos = wpabuf_mhead(decrypted); end = pos + wpabuf_len(decrypted); - while (pos + 4 < end) { + while (end - pos > 4) { mandatory = pos[0] & 0x80; tlv_type = WPA_GET_BE16(pos) & 0x3fff; pos += 2; @@ -1443,7 +1442,7 @@ static int eap_fast_clear_pac_opaque_ext(struct eap_sm *sm, static int eap_fast_set_provisioning_ciphers(struct eap_sm *sm, struct eap_fast_data *data) { - u8 ciphers[5]; + u8 ciphers[7]; int count = 0; if (data->provisioning_allowed & EAP_FAST_PROV_UNAUTH) { @@ -1455,7 +1454,9 @@ static int eap_fast_set_provisioning_ciphers(struct eap_sm *sm, if (data->provisioning_allowed & EAP_FAST_PROV_AUTH) { wpa_printf(MSG_DEBUG, "EAP-FAST: Enabling authenticated " "provisioning TLS cipher suites"); + ciphers[count++] = TLS_CIPHER_RSA_DHE_AES256_SHA; ciphers[count++] = TLS_CIPHER_RSA_DHE_AES128_SHA; + ciphers[count++] = TLS_CIPHER_AES256_SHA; ciphers[count++] = TLS_CIPHER_AES128_SHA; ciphers[count++] = TLS_CIPHER_RC4_SHA; } @@ -1567,6 +1568,34 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, res = 1; } } 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-FAST: 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-FAST: 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-FAST: Continuing to wait external server certificate validation"); + return NULL; + } + /* Continue processing TLS handshake (phase 1). */ res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_FAST, @@ -1580,6 +1609,14 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, return resp; } + if (sm->waiting_ext_cert_check) { + wpa_printf(MSG_DEBUG, + "EAP-FAST: 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 cipher[80]; wpa_printf(MSG_DEBUG, @@ -1644,6 +1681,8 @@ static void eap_fast_deinit_for_reauth(struct eap_sm *sm, void *priv) data->key_block_p = NULL; wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = NULL; + wpabuf_free(data->pending_resp); + data->pending_resp = NULL; } @@ -1721,7 +1760,7 @@ static u8 * eap_fast_get_session_id(struct eap_sm *sm, void *priv, size_t *len) struct eap_fast_data *data = priv; u8 *id; - if (!data->success) + if (!data->success || !data->session_id) return NULL; id = os_malloc(data->id_len); @@ -1757,7 +1796,6 @@ static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_fast_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_FAST, "FAST"); @@ -1778,8 +1816,5 @@ int eap_peer_fast_register(void) #endif eap->get_emsk = eap_fast_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/src/eap_peer/eap_fast_pac.c b/src/eap_peer/eap_fast_pac.c index 89e604ecf84b0..c815860355137 100644 --- a/src/eap_peer/eap_fast_pac.c +++ b/src/eap_peer/eap_fast_pac.c @@ -455,7 +455,8 @@ int eap_fast_load_pac(struct eap_sm *sm, struct eap_fast_pac **pac_root, } if (pac) { - err = "PAC block not terminated with END"; + if (!err) + err = "PAC block not terminated with END"; eap_fast_free_pac(pac); } @@ -709,7 +710,7 @@ static void eap_fast_pac_get_a_id(struct eap_fast_pac *pac) pos = pac->pac_info; end = pos + pac->pac_info_len; - while (pos + 4 < end) { + while (end - pos > 4) { type = WPA_GET_BE16(pos); pos += 2; len = WPA_GET_BE16(pos); @@ -801,8 +802,10 @@ int eap_fast_load_pac_bin(struct eap_sm *sm, struct eap_fast_pac **pac_root, while (pos < end) { u16 val; - if (end - pos < 2 + EAP_FAST_PAC_KEY_LEN + 2 + 2) + if (end - pos < 2 + EAP_FAST_PAC_KEY_LEN + 2 + 2) { + pac = NULL; goto parse_fail; + } pac = os_zalloc(sizeof(*pac)); if (pac == NULL) diff --git a/src/eap_peer/eap_gpsk.c b/src/eap_peer/eap_gpsk.c index 902b4ba26d6e4..177cbccf58508 100644 --- a/src/eap_peer/eap_gpsk.c +++ b/src/eap_peer/eap_gpsk.c @@ -771,7 +771,6 @@ static u8 * eap_gpsk_get_session_id(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_gpsk_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); @@ -786,8 +785,5 @@ int eap_peer_gpsk_register(void) eap->get_emsk = eap_gpsk_get_emsk; eap->getSessionId = eap_gpsk_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/src/eap_peer/eap_gtc.c b/src/eap_peer/eap_gtc.c index 9f3cfbdacadc8..a519a780a90b6 100644 --- a/src/eap_peer/eap_gtc.c +++ b/src/eap_peer/eap_gtc.c @@ -127,7 +127,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"); @@ -138,8 +137,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/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h index 99b44dae4e34e..6ab24834d654a 100644 --- a/src/eap_peer/eap_i.h +++ b/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/src/eap_peer/eap_ikev2.c b/src/eap_peer/eap_ikev2.c index b5ef71bac3ba4..390f0ec8cf4df 100644 --- a/src/eap_peer/eap_ikev2.c +++ b/src/eap_peer/eap_ikev2.c @@ -513,7 +513,6 @@ static u8 * eap_ikev2_get_session_id(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_ikev2_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_IKEV2, @@ -529,8 +528,5 @@ int eap_peer_ikev2_register(void) eap->get_emsk = eap_ikev2_get_emsk; eap->getSessionId = eap_ikev2_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/src/eap_peer/eap_leap.c b/src/eap_peer/eap_leap.c index e0f8bcf6b0df7..ff6fa4afd2f72 100644 --- a/src/eap_peer/eap_leap.c +++ b/src/eap_peer/eap_leap.c @@ -393,7 +393,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"); @@ -406,8 +405,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/src/eap_peer/eap_md5.c b/src/eap_peer/eap_md5.c index d06befaeb1df5..efae8deba85d5 100644 --- a/src/eap_peer/eap_md5.c +++ b/src/eap_peer/eap_md5.c @@ -102,7 +102,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"); @@ -113,8 +112,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/src/eap_peer/eap_methods.c b/src/eap_peer/eap_methods.c index 1bdd81e1ad52a..9747954952a7b 100644 --- a/src/eap_peer/eap_methods.c +++ b/src/eap_peer/eap_methods.c @@ -18,6 +18,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 @@ -295,7 +297,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); } @@ -303,26 +305,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/src/eap_peer/eap_methods.h b/src/eap_peer/eap_methods.h index e35c919abce94..b96b211de2589 100644 --- a/src/eap_peer/eap_methods.h +++ b/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/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c index 6acf1e8ad390a..ce2227d388ef4 100644 --- a/src/eap_peer/eap_mschapv2.c +++ b/src/eap_peer/eap_mschapv2.c @@ -880,7 +880,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, @@ -894,8 +893,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/src/eap_peer/eap_otp.c b/src/eap_peer/eap_otp.c index 9ac744a7ddade..0ab4c7907ab5a 100644 --- a/src/eap_peer/eap_otp.c +++ b/src/eap_peer/eap_otp.c @@ -83,7 +83,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"); @@ -94,8 +93,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/src/eap_peer/eap_pax.c b/src/eap_peer/eap_pax.c index c920bcd3182f8..a7012d2870cf3 100644 --- a/src/eap_peer/eap_pax.c +++ b/src/eap_peer/eap_pax.c @@ -276,9 +276,16 @@ static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, left -= 2; wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)", pos, EAP_PAX_MAC_LEN); - eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, - data->rand.r.y, EAP_PAX_RAND_LEN, - (u8 *) data->cid, data->cid_len, NULL, 0, mac); + if (eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, + data->rand.r.y, EAP_PAX_RAND_LEN, + (u8 *) data->cid, data->cid_len, NULL, 0, mac) < 0) { + wpa_printf(MSG_INFO, + "EAP-PAX: Could not derive MAC_CK(B, CID)"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + return NULL; + } + if (os_memcmp_const(pos, mac, EAP_PAX_MAC_LEN) != 0) { wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(B, CID) " "received"); @@ -306,9 +313,12 @@ static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, /* Optional ADE could be added here, if needed */ rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN); - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, rpos); + if (eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, + wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN, + NULL, 0, NULL, 0, rpos) < 0) { + wpabuf_free(resp); + return NULL; + } wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN); data->state = PAX_DONE; @@ -472,9 +482,13 @@ static u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len) return NULL; *len = EAP_MSK_LEN; - eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, - "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN, - EAP_MSK_LEN, key); + if (eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, + "Master Session Key", + data->rand.e, 2 * EAP_PAX_RAND_LEN, + EAP_MSK_LEN, key) < 0) { + os_free(key); + return NULL; + } return key; } @@ -493,10 +507,13 @@ static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len) return NULL; *len = EAP_EMSK_LEN; - eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, - "Extended Master Session Key", - data->rand.e, 2 * EAP_PAX_RAND_LEN, - EAP_EMSK_LEN, key); + if (eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, + "Extended Master Session Key", + data->rand.e, 2 * EAP_PAX_RAND_LEN, + EAP_EMSK_LEN, key) < 0) { + os_free(key); + return NULL; + } return key; } @@ -525,7 +542,6 @@ static u8 * eap_pax_get_session_id(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_pax_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX"); @@ -540,8 +556,5 @@ int eap_peer_pax_register(void) eap->get_emsk = eap_pax_get_emsk; eap->getSessionId = eap_pax_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/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c index 98a48a6cf5d31..45ba38168d4fc 100644 --- a/src/eap_peer/eap_peap.c +++ b/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 <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. @@ -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]; @@ -69,8 +70,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; @@ -125,8 +126,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; } @@ -144,11 +143,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, @@ -191,6 +187,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); } @@ -256,6 +253,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 @@ -266,8 +264,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", @@ -337,7 +339,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; @@ -648,6 +651,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); @@ -1006,6 +1010,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, @@ -1018,6 +1050,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, @@ -1123,6 +1165,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; } @@ -1237,7 +1281,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"); @@ -1255,8 +1298,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/src/eap_peer/eap_psk.c b/src/eap_peer/eap_psk.c index f01266354e904..ac18c158ad8bb 100644 --- a/src/eap_peer/eap_psk.c +++ b/src/eap_peer/eap_psk.c @@ -480,7 +480,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"); @@ -495,8 +494,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/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c index 1f785443ee5ac..d2bc981cd06b8 100644 --- a/src/eap_peer/eap_pwd.c +++ b/src/eap_peer/eap_pwd.c @@ -418,7 +418,6 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail"); goto fin; } - BN_clear_free(mask); if (((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { @@ -555,6 +554,7 @@ fin: os_free(element); BN_clear_free(x); BN_clear_free(y); + BN_clear_free(mask); BN_clear_free(cofactor); EC_POINT_clear_free(K); EC_POINT_clear_free(point); @@ -774,7 +774,8 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data, wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN); fin: - bin_clear_free(cruft, BN_num_bytes(data->grp->prime)); + if (data->grp) + bin_clear_free(cruft, BN_num_bytes(data->grp->prime)); BN_clear_free(x); BN_clear_free(y); if (data->outbuf == NULL) { @@ -903,7 +904,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, /* * buffer and ACK the fragment */ - if (EAP_PWD_GET_MORE_BIT(lm_exch)) { + if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) { data->in_frag_pos += len; if (data->in_frag_pos > wpabuf_size(data->inbuf)) { wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack " @@ -916,7 +917,8 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, return NULL; } wpabuf_put_data(data->inbuf, pos, len); - + } + if (EAP_PWD_GET_MORE_BIT(lm_exch)) { resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, EAP_PWD_HDR_SIZE, EAP_CODE_RESPONSE, eap_get_id(reqData)); @@ -930,10 +932,8 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, * we're buffering and this is the last fragment */ if (data->in_frag_pos) { - wpabuf_put_data(data->inbuf, pos, len); wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes", (int) len); - data->in_frag_pos += len; pos = wpabuf_head_u8(data->inbuf); len = data->in_frag_pos; } @@ -1054,7 +1054,6 @@ static u8 * eap_pwd_get_emsk(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_pwd_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_PWD, "PWD"); @@ -1069,8 +1068,5 @@ int eap_peer_pwd_register(void) eap->getSessionId = eap_pwd_get_session_id; eap->get_emsk = eap_pwd_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/src/eap_peer/eap_sake.c b/src/eap_peer/eap_sake.c index c4f9843febb35..330febbefd78c 100644 --- a/src/eap_peer/eap_sake.c +++ b/src/eap_peer/eap_sake.c @@ -309,11 +309,20 @@ static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, return NULL; } - eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 0, - wpabuf_head(reqData), wpabuf_len(reqData), - attr.mic_s, mic_s); + if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, + data->serverid, data->serverid_len, + data->peerid, data->peerid_len, 0, + wpabuf_head(reqData), wpabuf_len(reqData), + attr.mic_s, mic_s)) { + wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); + eap_sake_state(data, FAILURE); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + ret->allowNotifications = FALSE; + wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Auth-Reject"); + return eap_sake_build_msg(data, id, 0, + EAP_SAKE_SUBTYPE_AUTH_REJECT); + } if (os_memcmp_const(attr.mic_s, mic_s, EAP_SAKE_MIC_LEN) != 0) { wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_S"); eap_sake_state(data, FAILURE); @@ -494,7 +503,6 @@ static u8 * eap_sake_get_emsk(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_sake_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_SAKE, "SAKE"); @@ -509,8 +517,5 @@ int eap_peer_sake_register(void) eap->getSessionId = eap_sake_get_session_id; eap->get_emsk = eap_sake_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/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c index 99a2816ce61ed..b97c95db196f0 100644 --- a/src/eap_peer/eap_sim.c +++ b/src/eap_peer/eap_sim.c @@ -249,6 +249,7 @@ static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data) return eap_sim_ext_sim_req(sm, data); } +#ifdef PCSC_FUNCS if (conf->pcsc) { if (scard_gsm_auth(sm->scard_ctx, data->rand[0], data->sres[0], data->kc[0]) || @@ -263,6 +264,7 @@ static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data) } return 0; } +#endif /* PCSC_FUNCS */ #ifdef CONFIG_SIM_SIMULATOR if (conf->password) { @@ -1135,7 +1137,7 @@ static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv) if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " "for NONCE_MT"); - os_free(data); + eap_sim_deinit(sm, data); return NULL; } data->num_id_req = 0; @@ -1235,7 +1237,6 @@ static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_sim_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); @@ -1254,8 +1255,5 @@ int eap_peer_sim_register(void) eap->get_identity = eap_sim_get_identity; eap->get_emsk = eap_sim_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/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c index 66a027a626e0d..ca2354f8a7850 100644 --- a/src/eap_peer/eap_tls.c +++ b/src/eap_peer/eap_tls.c @@ -1,6 +1,6 @@ /* * 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. @@ -25,6 +25,7 @@ struct eap_tls_data { size_t id_len; void *ssl_ctx; u8 eap_type; + struct wpabuf *pending_resp; }; @@ -142,6 +143,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); } @@ -216,6 +218,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) @@ -237,6 +265,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); @@ -258,6 +294,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; } @@ -350,7 +390,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"); @@ -369,10 +408,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); } @@ -380,7 +416,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, @@ -399,10 +434,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 */ @@ -411,7 +443,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, @@ -431,9 +462,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/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c index af2b7541d7016..0dcb9c138f81d 100644 --- a/src/eap_peer/eap_tls_common.c +++ b/src/eap_peer/eap_tls_common.c @@ -80,6 +80,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; } @@ -177,6 +181,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; } @@ -190,8 +196,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 " @@ -320,8 +328,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; } @@ -350,10 +358,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; @@ -1035,6 +1041,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/src/eap_peer/eap_tnc.c b/src/eap_peer/eap_tnc.c index 25b9f124801a1..726221e6b69ca 100644 --- a/src/eap_peer/eap_tnc.c +++ b/src/eap_peer/eap_tnc.c @@ -10,6 +10,7 @@ #include "common.h" #include "eap_i.h" +#include "eap_config.h" #include "tncc.h" @@ -35,12 +36,16 @@ struct eap_tnc_data { static void * eap_tnc_init(struct eap_sm *sm) { struct eap_tnc_data *data; + struct eap_peer_config *config = eap_get_config(sm); data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->state = WAIT_START; - data->fragment_size = 1300; + if (config && config->fragment_size) + data->fragment_size = config->fragment_size; + else + data->fragment_size = 1300; data->tncc = tncc_init(); if (data->tncc == NULL) { os_free(data); @@ -345,11 +350,6 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, ret->decision = DECISION_UNCOND_SUCC; ret->allowNotifications = TRUE; - if (data->out_buf) { - data->state = PROC_MSG; - return eap_tnc_build_msg(data, ret, id); - } - if (tncs_done) { resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, EAP_CODE_RESPONSE, eap_get_id(reqData)); @@ -410,7 +410,6 @@ fail: int eap_peer_tnc_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_TNC, "TNC"); @@ -421,8 +420,5 @@ int eap_peer_tnc_register(void) eap->deinit = eap_tnc_deinit; eap->process = eap_tnc_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/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c index b186c9156a741..92f94dcd60190 100644 --- a/src/eap_peer/eap_ttls.c +++ b/src/eap_peer/eap_ttls.c @@ -1,6 +1,6 @@ /* * 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. @@ -35,6 +35,7 @@ struct eap_ttls_data { void *phase2_priv; int phase2_success; int phase2_start; + EapDecision decision_succ; enum phase2_types { EAP_TTLS_PHASE2_EAP, @@ -58,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; @@ -70,6 +72,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)); @@ -77,26 +80,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) { @@ -153,6 +197,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); } @@ -1408,6 +1453,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); @@ -1418,6 +1489,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"); @@ -1468,6 +1548,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) { /* @@ -1485,6 +1566,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; } } @@ -1557,6 +1650,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; @@ -1695,7 +1791,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"); @@ -1714,8 +1809,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); } diff --git a/src/eap_peer/eap_vendor_test.c b/src/eap_peer/eap_vendor_test.c index b61057ee67555..16e3c39563b72 100644 --- a/src/eap_peer/eap_vendor_test.c +++ b/src/eap_peer/eap_vendor_test.c @@ -169,7 +169,6 @@ static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len) int eap_peer_vendor_test_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_ID, EAP_VENDOR_TYPE, @@ -183,8 +182,5 @@ int eap_peer_vendor_test_register(void) eap->isKeyAvailable = eap_vendor_test_isKeyAvailable; eap->getKey = eap_vendor_test_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/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c index 7ac99c7ce727b..d140c88b8cdd8 100644 --- a/src/eap_peer/eap_wsc.c +++ b/src/eap_peer/eap_wsc.c @@ -17,7 +17,7 @@ struct eap_wsc_data { - enum { WAIT_START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; + enum { WAIT_START, MESG, WAIT_FRAG_ACK, FAIL } state; int registrar; struct wpabuf *in_buf; struct wpabuf *out_buf; @@ -36,12 +36,8 @@ static const char * eap_wsc_state_txt(int state) return "WAIT_START"; case MESG: return "MESG"; - case FRAG_ACK: - return "FRAG_ACK"; case WAIT_FRAG_ACK: return "WAIT_FRAG_ACK"; - case DONE: - return "DONE"; case FAIL: return "FAIL"; default: @@ -579,7 +575,6 @@ send_msg: int eap_peer_wsc_register(void) { struct eap_method *eap; - int ret; eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, @@ -591,8 +586,5 @@ int eap_peer_wsc_register(void) eap->deinit = eap_wsc_deinit; eap->process = eap_wsc_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/src/eap_peer/ikev2.c b/src/eap_peer/ikev2.c index 55ab72aee66c7..ca6502ea02e73 100644 --- a/src/eap_peer/ikev2.c +++ b/src/eap_peer/ikev2.c @@ -128,7 +128,7 @@ static int ikev2_parse_transform(struct ikev2_proposal_data *prop, t = (const struct ikev2_transform *) pos; transform_len = WPA_GET_BE16(t->transform_length); - if (transform_len < (int) sizeof(*t) || pos + transform_len > end) { + if (transform_len < (int) sizeof(*t) || transform_len > end - pos) { wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d", transform_len); return -1; @@ -248,7 +248,7 @@ static int ikev2_parse_proposal(struct ikev2_proposal_data *prop, ppos = (const u8 *) (p + 1); pend = pos + proposal_len; - if (ppos + p->spi_size > pend) { + if (p->spi_size > pend - ppos) { wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI " "in proposal"); return -1; diff --git a/src/eap_peer/tncc.c b/src/eap_peer/tncc.c index 7ca956e5b235d..0c5caa7dd522e 100644 --- a/src/eap_peer/tncc.c +++ b/src/eap_peer/tncc.c @@ -104,7 +104,7 @@ static struct tnc_if_imc *tnc_imc[TNC_MAX_IMC_ID] = { NULL }; /* TNCC functions that IMCs can call */ -TNC_Result TNC_TNCC_ReportMessageTypes( +static TNC_Result TNC_TNCC_ReportMessageTypes( TNC_IMCID imcID, TNC_MessageTypeList supportedTypes, TNC_UInt32 typeCount) @@ -138,7 +138,7 @@ TNC_Result TNC_TNCC_ReportMessageTypes( } -TNC_Result TNC_TNCC_SendMessage( +static TNC_Result TNC_TNCC_SendMessage( TNC_IMCID imcID, TNC_ConnectionID connectionID, TNC_BufferReference message, @@ -183,7 +183,7 @@ TNC_Result TNC_TNCC_SendMessage( } -TNC_Result TNC_TNCC_RequestHandshakeRetry( +static TNC_Result TNC_TNCC_RequestHandshakeRetry( TNC_IMCID imcID, TNC_ConnectionID connectionID, TNC_RetryReason reason) @@ -203,8 +203,8 @@ TNC_Result TNC_TNCC_RequestHandshakeRetry( } -TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity, - const char *message) +static TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity, + const char *message) { wpa_printf(MSG_DEBUG, "TNC: TNC_9048_LogMessage(imcID=%lu " "severity==%lu message='%s')", @@ -213,8 +213,9 @@ TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity, } -TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, TNC_ConnectionID connectionID, - const char *message) +static TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, + TNC_ConnectionID connectionID, + const char *message) { wpa_printf(MSG_DEBUG, "TNC: TNC_9048_UserMessage(imcID=%lu " "connectionID==%lu message='%s')", @@ -223,7 +224,7 @@ TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, TNC_ConnectionID connectionID, } -TNC_Result TNC_TNCC_BindFunction( +static TNC_Result TNC_TNCC_BindFunction( TNC_IMCID imcID, char *functionName, void **pOutfunctionPointer) @@ -694,6 +695,8 @@ enum tncc_process_res tncc_process_if_tnccs(struct tncc_data *tncc, enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION; int recommendation_msg = 0; + wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Received IF-TNCCS message", + msg, len); buf = dup_binstr(msg, len); if (buf == NULL) return TNCCS_PROCESS_ERROR; |