18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-TTLS (RFC 5281) 31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/ms_funcs.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/chap.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_ttls.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "mschapv2.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_tls_common.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_config.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define EAP_TTLS_VERSION 0 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_deinit(struct eap_sm *sm, void *priv); 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_ttls_data { 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data ssl; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ttls_version; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_method *phase2_method; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *phase2_priv; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int phase2_success; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int phase2_start; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum phase2_types { 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_PHASE2_EAP, 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_PHASE2_MSCHAPV2, 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_PHASE2_MSCHAP, 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_PHASE2_PAP, 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_PHASE2_CHAP 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } phase2_type; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_type phase2_eap_type; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_type *phase2_eap_types; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_phase2_eap_types; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN]; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int auth_response_valid; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; /* MSCHAPv2 master key */ 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ident; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int resuming; /* starting a resumed session */ 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reauth; /* reauthentication */ 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key_data; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pending_phase2_req; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ready_for_tnc; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tnc_started; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_ttls_init(struct eap_sm *sm) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *selected; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version = EAP_TTLS_VERSION; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selected = "EAP"; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type = EAP_TTLS_PHASE2_EAP; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config && config->phase2) { 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(config->phase2, "autheap=")) { 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selected = "EAP"; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type = EAP_TTLS_PHASE2_EAP; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strstr(config->phase2, "auth=MSCHAPV2")) { 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selected = "MSCHAPV2"; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strstr(config->phase2, "auth=MSCHAP")) { 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selected = "MSCHAP"; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type = EAP_TTLS_PHASE2_MSCHAP; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strstr(config->phase2, "auth=PAP")) { 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selected = "PAP"; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type = EAP_TTLS_PHASE2_PAP; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (os_strstr(config->phase2, "auth=CHAP")) { 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selected = "CHAP"; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_type = EAP_TTLS_PHASE2_CHAP; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_type == EAP_TTLS_PHASE2_EAP) { 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peer_select_phase2_methods(config, "autheap=", 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->phase2_eap_types, 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->num_phase2_eap_types) 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) { 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_deinit(sm, data); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.vendor = EAP_VENDOR_IETF; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.method = EAP_TYPE_NONE; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) { 1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL."); 1151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_deinit(sm, data); 1161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_phase2_eap_deinit(struct eap_sm *sm, 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data) 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv && data->phase2_method) { 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->deinit(sm, data->phase2_priv); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method = NULL; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_priv = NULL; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_deinit(struct eap_sm *sm, void *priv) 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_phase2_eap_deinit(sm, data); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->phase2_eap_types); 1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_peer_tls_ssl_deinit(sm, &data->ssl); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->key_data); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_req); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id, 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int mandatory, size_t len) 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_avp_vendor *avp; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t hdrlen; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp = (struct ttls_avp_vendor *) avphdr; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = mandatory ? AVP_FLAGS_MANDATORY : 0; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vendor_id) { 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= AVP_FLAGS_VENDOR; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdrlen = sizeof(*avp); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp->vendor_id = host_to_be32(vendor_id); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdrlen = sizeof(struct ttls_avp); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp->avp_code = host_to_be32(avp_code); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp->avp_length = host_to_be32((flags << 24) | (u32) (hdrlen + len)); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return avphdr + hdrlen; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code, 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 vendor_id, int mandatory, 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t len) 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data, len); 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += len; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AVP_PAD(start, pos); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code, 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int mandatory) 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *avp, *pos; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(*resp); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = NULL; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp = wpabuf_mhead(msg); 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, wpabuf_len(*resp)); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp)); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpabuf_len(*resp); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AVP_PAD(avp, pos); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(*resp); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(msg, pos - avp); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = msg; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_v0_derive_key(struct eap_sm *sm, 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data) 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->key_data); 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ttls keying material", 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TLS_KEY_LEN); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->key_data) { 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Failed to derive key"); 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_data, EAP_TLS_KEY_LEN); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, size_t len) 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data, 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 method) 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < data->num_phase2_eap_types; i++) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF || 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_types[i].method != method) 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.vendor = 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_types[i].vendor; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.method = 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_types[i].method; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP vendor %d method %d", 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.vendor, 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.method); 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_eap_process(struct eap_sm *sm, 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr, size_t len, 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **resp) 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf msg; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret iret; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&iret, 0, sizeof(iret)); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msg, hdr, len); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = data->phase2_method->process(sm, data->phase2_priv, &iret, 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &msg); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((iret.methodState == METHOD_DONE || 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iret.methodState == METHOD_MAY_CONT) && 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (iret.decision == DECISION_UNCOND_SUCC || 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iret.decision == DECISION_COND_SUCC || 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iret.decision == DECISION_FAIL)) { 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = iret.methodState; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = iret.decision; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr, size_t len, 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 method, struct wpabuf **resp) 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tnc_started && data->phase2_method && 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_priv && method == EAP_TYPE_TNC && 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.method == EAP_TYPE_TNC) 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->ready_for_tnc && !data->tnc_started && 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt method == EAP_TYPE_TNC) { 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed " 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP method"); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tnc_started = 1; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tnc_started) { 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_eap_type.vendor != EAP_VENDOR_IETF || 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.method == EAP_TYPE_TNC) { 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected EAP " 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "type %d for TNC", method); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.vendor = EAP_VENDOR_IETF; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.method = method; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP vendor %d method %d (TNC)", 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.vendor, 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.method); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_type == EAP_TTLS_PHASE2_EAP) 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_phase2_eap_deinit(sm, data); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF && 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_eap_type.method == EAP_TYPE_NONE) 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_phase2_select_eap_method(data, method); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE) 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peer_tls_phase2_nak(data->phase2_eap_types, 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_phase2_eap_types, 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr, resp)) 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv == NULL) { 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method = eap_peer_get_eap_method( 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, method); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_method) { 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->init_phase2 = 1; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_priv = data->phase2_method->init(sm); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->init_phase2 = 0; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv == NULL || data->phase2_method == NULL) { 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize " 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP method %d", method); 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, resp); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_request_eap(struct eap_sm *sm, 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr, 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **resp) 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = be_to_host16(hdr->length); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len <= sizeof(struct eap_hdr)) { 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: too short " 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 request (len=%lu)", (unsigned long) len); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (*pos) { 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TYPE_IDENTITY: 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len, 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos, resp) < 0) 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*resp == NULL && 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (config->pending_req_identity || config->pending_req_password || 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->pending_req_otp)) { 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*resp == NULL) 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response", 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_ttls_avp_encapsulate(resp, RADIUS_ATTR_EAP_MESSAGE, 1); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **resp) 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos, *challenge, *peer_challenge; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *password; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, password_len; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pwhash; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request"); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password2(sm, &password_len, &pwhash); 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL || password == NULL) 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(identity_len + 1000); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS/MSCHAPV2: Failed to allocate memory"); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf = wpabuf_mhead(msg); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* User-Name */ 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MS-CHAP-Challenge */ 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge = eap_ttls_implicit_challenge( 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge == NULL) { 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "implicit challenge"); 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_VENDOR_ID_MICROSOFT, 1, 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MS-CHAP2-Response */ 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE, 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_VENDOR_ID_MICROSOFT, 1, 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_MSCHAPV2_RESPONSE_LEN); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = data->ident; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0; /* Flags */ 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(pos, 0, 8); /* Reserved, must be zero */ 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 8; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mschapv2_derive_response(identity, identity_len, password, 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password_len, pwhash, challenge, 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge, pos, data->auth_response, 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->master_key)) { 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "response"); 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auth_response_valid = 1; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 24; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(challenge); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AVP_PAD(buf, pos); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(msg, pos - buf); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = msg; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->workaround) { 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* At least FreeRADIUS seems to be terminating 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * packet. */ 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - " 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "allow success without tunneled response"); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_COND_SUCC; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_request_mschap(struct eap_sm *sm, 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **resp) 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos, *challenge; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *password; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, password_len; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pwhash; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request"); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password2(sm, &password_len, &pwhash); 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL || password == NULL) 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(identity_len + 1000); 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS/MSCHAP: Failed to allocate memory"); 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf = wpabuf_mhead(msg); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* User-Name */ 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MS-CHAP-Challenge */ 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge = eap_ttls_implicit_challenge( 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge == NULL) { 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive " 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "implicit challenge"); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_VENDOR_ID_MICROSOFT, 1, 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MS-CHAP-Response */ 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE, 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_VENDOR_ID_MICROSOFT, 1, 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_MSCHAP_RESPONSE_LEN); 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN]; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = data->ident; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 1; /* Flags: Use NT style passwords */ 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(pos, 0, 24); /* LM-Response */ 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 24; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pwhash) { 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_response(challenge, password, pos); /* NT-Response */ 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash", 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password, 16); 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_challenge_response(challenge, password, password_len, 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos); /* NT-Response */ 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password", 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password, password_len); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge", 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24); 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 24; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(challenge); 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AVP_PAD(buf, pos); 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(msg, pos - buf); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = msg; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* EAP-TTLS/MSCHAP does not provide tunneled success 5611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * notification, so assume that Phase2 succeeds. */ 5621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret->methodState = METHOD_DONE; 5631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret->decision = DECISION_COND_SUCC; 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_request_pap(struct eap_sm *sm, 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **resp) 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t pad; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *password; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, password_len; 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request"); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL || password == NULL) 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(identity_len + password_len + 100); 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS/PAP: Failed to allocate memory"); 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf = wpabuf_mhead(msg); 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* User-Name */ 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the data, so no separate encryption is used in the AVP itself. 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * However, the password is padded to obfuscate its length. */ 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad = password_len == 0 ? 16 : (16 - (password_len & 15)) & 15; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1, 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password_len + pad); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, password, password_len); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += password_len; 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(pos, 0, pad); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += pad; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AVP_PAD(buf, pos); 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(msg, pos - buf); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = msg; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* EAP-TTLS/PAP does not provide tunneled success notification, 6151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * so assume that Phase2 succeeds. */ 6161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret->methodState = METHOD_DONE; 6171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret->decision = DECISION_COND_SUCC; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_request_chap(struct eap_sm *sm, 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **resp) 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos, *challenge; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *password; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, password_len; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request"); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL || password == NULL) 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(identity_len + 1000); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS/CHAP: Failed to allocate memory"); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf = wpabuf_mhead(msg); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* User-Name */ 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* CHAP-Challenge */ 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge = eap_ttls_implicit_challenge( 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1); 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge == NULL) { 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive " 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "implicit challenge"); 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1, 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* CHAP-Password */ 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1, 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1 + EAP_TTLS_CHAP_PASSWORD_LEN); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN]; 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = data->ident; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MD5(Ident + Password + Challenge) */ 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chap_md5(data->ident, password, password_len, challenge, 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_CHAP_CHALLENGE_LEN, pos); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username", 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password", 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password, password_len); 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge", 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password", 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, EAP_TTLS_CHAP_PASSWORD_LEN); 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_TTLS_CHAP_PASSWORD_LEN; 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(challenge); 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AVP_PAD(buf, pos); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(msg, pos - buf); 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = msg; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* EAP-TTLS/CHAP does not provide tunneled success 6911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * notification, so assume that Phase2 succeeds. */ 6921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret->methodState = METHOD_DONE; 6931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret->decision = DECISION_COND_SUCC; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_request(struct eap_sm *sm, 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr, 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **resp) 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = 0; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum phase2_types phase2_type = data->phase2_type; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tnc_started) { 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Processing TNC"); 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phase2_type = EAP_TTLS_PHASE2_EAP; 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 || 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phase2_type == EAP_TTLS_PHASE2_MSCHAP || 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phase2_type == EAP_TTLS_PHASE2_PAP || 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phase2_type == EAP_TTLS_PHASE2_CHAP) { 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_get_config_identity(sm, &len) == NULL) { 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS: Identity not configured"); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_identity(sm); 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_get_config_password(sm, &len) == NULL) 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_password(sm); 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_get_config_password(sm, &len) == NULL) { 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS: Password not configured"); 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_password(sm); 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (phase2_type) { 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_EAP: 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_ttls_phase2_request_eap(sm, data, ret, hdr, resp); 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_MSCHAPV2: 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_ttls_phase2_request_mschapv2(sm, data, ret, resp); 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_MSCHAP: 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_ttls_phase2_request_mschap(sm, data, ret, resp); 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_PAP: 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_ttls_phase2_request_pap(sm, data, ret, resp); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_CHAP: 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_ttls_phase2_request_chap(sm, data, ret, resp); 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown"); 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = -1; 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ttls_parse_avp { 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mschapv2; 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *eapdata; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t eap_len; 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int mschapv2_error; 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_parse_attr_eap(const u8 *dpos, size_t dlen, 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_parse_avp *parse) 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message"); 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse->eapdata == NULL) { 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eapdata = os_malloc(dlen); 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse->eapdata == NULL) { 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate " 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "memory for Phase 2 EAP data"); 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(parse->eapdata, dpos, dlen); 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eap_len = dlen; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *neweap = os_realloc(parse->eapdata, parse->eap_len + dlen); 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (neweap == NULL) { 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate " 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "memory for Phase 2 EAP data"); 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(neweap + parse->eap_len, dpos, dlen); 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eapdata = neweap; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eap_len += dlen; 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_parse_avp(u8 *pos, size_t left, 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_parse_avp *parse) 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_avp *avp; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 avp_code, avp_length, vendor_id = 0; 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 avp_flags, *dpos; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t dlen; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp = (struct ttls_avp *) pos; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code = be_to_host32(avp->avp_code); 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_length = be_to_host32(avp->avp_length); 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_flags = (avp_length >> 24) & 0xff; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_length &= 0xffffff; 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x " 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length=%d", (int) avp_code, avp_flags, 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) avp_length); 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (avp_length > left) { 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow " 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(len=%d, left=%lu) - dropped", 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) avp_length, (unsigned long) left); 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (avp_length < sizeof(*avp)) { 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length %d", 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_length); 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos = (u8 *) (avp + 1); 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dlen = avp_length - sizeof(*avp); 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (avp_flags & AVP_FLAGS_VENDOR) { 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dlen < 4) { 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Vendor AVP " 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "underflow"); 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor_id = WPA_GET_BE32(dpos); 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d", 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) vendor_id); 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos += 4; 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dlen -= 4; 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen); 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) { 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_parse_attr_eap(dpos, dlen, parse) < 0) 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (vendor_id == 0 && avp_code == RADIUS_ATTR_REPLY_MESSAGE) { 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* This is an optional message that can be displayed to 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the user. */ 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: AVP - Reply-Message", 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos, dlen); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) { 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP2-Success", 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos, dlen); 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dlen != 43) { 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Unexpected " 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MS-CHAP2-Success length " 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(len=%lu, expected 43)", 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) dlen); 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->mschapv2 = dpos; 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code == RADIUS_ATTR_MS_CHAP_ERROR) { 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP-Error", 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos, dlen); 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->mschapv2_error = 1; 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (avp_flags & AVP_FLAGS_MANDATORY) { 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported mandatory AVP " 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "code %d vendor_id %d - dropped", 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) avp_code, (int) vendor_id); 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported AVP " 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "code %d vendor_id %d", 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) avp_code, (int) vendor_id); 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return avp_length; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_parse_avps(struct wpabuf *in_decrypted, 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_parse_avp *parse) 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left, pad; 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int avp_length; 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_mhead(in_decrypted); 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = wpabuf_len(in_decrypted); 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs", pos, left); 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < sizeof(struct ttls_avp)) { 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame" 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " len=%lu expected %lu or more - dropped", 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) left, 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) sizeof(struct ttls_avp)); 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Parse AVPs */ 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(parse, 0, sizeof(*parse)); 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left > 0) { 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_length = eap_ttls_parse_avp(pos, left, parse); 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (avp_length < 0) 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad = (4 - (avp_length & 3)) & 3; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += avp_length + pad; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < avp_length + pad) 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = 0; 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= avp_length + pad; 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_fake_identity_request(void) 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr; 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of " 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 - use fake EAP-Request Identity"); 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(sizeof(*hdr) + 1); 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate " 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "memory for fake EAP-Identity Request"); 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct eap_hdr *) buf; 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code = EAP_CODE_REQUEST; 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->identifier = 0; 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->length = host_to_be16(sizeof(*hdr) + 1); 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[sizeof(*hdr)] = EAP_TYPE_IDENTITY; 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_encrypt_response(struct eap_sm *sm, 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp, u8 identifier, 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Encrypting Phase 2 data", 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp); 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS, 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version, identifier, 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp, out_data)) { 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt a Phase 2 " 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame"); 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_process_phase2_eap(struct eap_sm *sm, 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_parse_avp *parse, 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **resp) 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse->eapdata == NULL) { 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: No EAP Message in the " 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet - dropped"); 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP", 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eapdata, parse->eap_len); 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct eap_hdr *) parse->eapdata; 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse->eap_len < sizeof(*hdr)) { 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 EAP " 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame (len=%lu, expected %lu or more) - dropped", 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) parse->eap_len, 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) sizeof(*hdr)); 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = be_to_host16(hdr->length); 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > parse->eap_len) { 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Length mismatch in Phase 2 " 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP frame (EAP hdr len=%lu, EAP data len in " 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AVP=%lu)", 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) parse->eap_len); 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d " 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "identifier=%d length=%lu", 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code, hdr->identifier, (unsigned long) len); 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->code) { 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_REQUEST: 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_request(sm, data, ret, hdr, resp)) { 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request " 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "processing failed"); 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Unexpected code=%d in " 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP header", hdr->code); 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm, 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_parse_avp *parse) 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse->mschapv2_error) { 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received " 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MS-CHAP-Error - failed"); 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Reply with empty data to ACK error */ 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse->mschapv2 == NULL) { 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_success && parse->eapdata) { 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Allow EAP-TNC to be started after successfully 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * completed MSCHAPV2. 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success AVP " 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received for Phase2 MSCHAPV2"); 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse->mschapv2[0] != data->ident) { 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Ident mismatch for Phase 2 " 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MSCHAPV2 (received Ident 0x%02x, expected 0x%02x)", 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->mschapv2[0], data->ident); 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->auth_response_valid || 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mschapv2_verify_auth_response(data->auth_response, 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->mschapv2 + 1, 42)) { 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid authenticator " 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "response in Phase 2 MSCHAPV2 success request"); 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 " 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication succeeded"); 10771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret->methodState = METHOD_DONE; 10781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 10791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt data->phase2_success = 1; 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Reply with empty data; authentication server will reply 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with EAP-Success after this. 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_process_tnc_start(struct eap_sm *sm, 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_parse_avp *parse, 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **resp) 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TNC uses inner EAP method after non-EAP TTLS phase 2. */ 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse->eapdata == NULL) { 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received " 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected tunneled data (no EAP)"); 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->ready_for_tnc) { 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received " 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP after non-EAP, but not ready for TNC"); 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed " 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "non-EAP method"); 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tnc_started = 1; 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_process_phase2_eap(sm, data, ret, parse, resp) < 0) 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_process_decrypted(struct eap_sm *sm, 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier, 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_parse_avp *parse, 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_decrypted, 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp = NULL; 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum phase2_types phase2_type = data->phase2_type; 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tnc_started) 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phase2_type = EAP_TTLS_PHASE2_EAP; 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (phase2_type) { 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_EAP: 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_process_phase2_eap(sm, data, ret, parse, &resp) < 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_MSCHAPV2: 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_ttls_process_phase2_mschapv2(sm, data, ret, parse); 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 1 && parse->eapdata && data->phase2_success) { 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TNC may be required as the next 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication method within the tunnel. 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ready_for_tnc = 1; 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_process_tnc_start(sm, data, ret, parse, 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &resp) == 0) 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_MSCHAP: 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_PAP: 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_CHAP: 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_process_tnc_start(sm, data, ret, parse, &resp) < 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* EAP_TNC */ 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* EAP-TTLS/{MSCHAP,PAP,CHAP} should not send any TLS tunneled 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * requests to the supplicant */ 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received unexpected " 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tunneled data"); 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp) { 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_encrypt_response(sm, data, resp, identifier, 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data) < 0) 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (config->pending_req_identity || 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->pending_req_password || 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->pending_req_otp || 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->pending_req_new_password) { 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_req); 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_req = wpabuf_dup(in_decrypted); 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_implicit_identity_request(struct eap_sm *sm, 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier, 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int retval = 0; 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr; 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct eap_hdr *) eap_ttls_fake_identity_request(); 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr == NULL) { 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = NULL; 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_request(sm, data, ret, hdr, &resp)) { 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request " 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "processing failed"); 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt retval = -1; 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 12181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (resp == NULL && 12191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (config->pending_req_identity || 12201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt config->pending_req_password || 12211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt config->pending_req_otp || 12221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt config->pending_req_new_password)) { 12231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 12241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Use empty buffer to force implicit request 12251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * processing when EAP request is re-processed after 12261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * user input. 12271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 12281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(data->pending_phase2_req); 12291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt data->pending_phase2_req = wpabuf_alloc(0); 12301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt retval = eap_ttls_encrypt_response(sm, data, resp, identifier, 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data); 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (retval < 0) { 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return retval; 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_start(struct eap_sm *sm, struct eap_ttls_data *data, 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, u8 identifier, 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_start = 0; 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-TTLS does not use Phase2 on fast re-auth; this must be done only 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * if TLS part was indeed resuming a previous session. Most 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Authentication Servers terminate EAP-TTLS before reaching this 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * point, but some do not. Make wpa_supplicant stop phase 2 here, if 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * needed. 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth && 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - " 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "skip phase 2"); 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_data = eap_peer_tls_build_ack(identifier, EAP_TYPE_TTLS, 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version); 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success = 1; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_ttls_implicit_identity_request(sm, data, ret, identifier, 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data); 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, u8 identifier, 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_decrypted = NULL; 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int retval = 0; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_parse_avp parse; 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&parse, 0, sizeof(parse)); 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Phase 2", 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_data ? (unsigned long) wpabuf_len(in_data) : 0); 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->pending_phase2_req) { 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - " 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "skip decryption and use old data"); 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Clear TLS reassembly state. */ 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(&data->ssl); 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted = data->pending_phase2_req; 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_req = NULL; 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(in_decrypted) == 0) { 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_ttls_implicit_identity_request( 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, data, ret, identifier, out_data); 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto continue_req; 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((in_data == NULL || wpabuf_len(in_data) == 0) && 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_start) { 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_ttls_phase2_start(sm, data, ret, identifier, 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data); 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_data == NULL || wpabuf_len(in_data) == 0) { 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Received TLS ACK - requesting more fragments */ 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS, 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version, 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identifier, NULL, out_data); 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (retval) 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtcontinue_req: 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_start = 0; 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_parse_avps(in_decrypted, &parse) < 0) { 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt retval = -1; 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt retval = eap_ttls_process_decrypted(sm, data, ret, identifier, 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &parse, in_decrypted, out_data); 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone: 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(parse.eapdata); 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (retval < 0) { 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return retval; 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_process_handshake(struct eap_sm *sm, 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 identifier, 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *in_data, size_t in_len, 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version, identifier, 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_data, in_len, out_data); 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to " 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2"); 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->resuming) { 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth - may " 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "skip Phase 2"); 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_COND_SUCC; 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_start = 1; 13721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_v0_derive_key(sm, data); 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*out_data == NULL || wpabuf_len(*out_data) == 0) { 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_decrypt(sm, data, ret, identifier, 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, out_data)) { 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: " 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed to process early " 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "start for Phase 2"); 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = 0; 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->resuming = 0; 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 2) { 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf msg; 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Application data included in the handshake message. 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_req); 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_req = *out_data; 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_data = NULL; 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msg, in_data, in_len); 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_ttls_decrypt(sm, data, ret, identifier, &msg, 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data); 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_check_auth_status(struct eap_sm *sm, 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret) 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret->methodState == METHOD_DONE) { 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret->decision == DECISION_UNCOND_SUCC || 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision == DECISION_COND_SUCC) { 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "completed successfully"); 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success = 1; 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->ready_for_tnc && !data->tnc_started) { 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TNC may be required as the next 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication method within the tunnel. 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ready_for_tnc = 1; 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (ret->methodState == METHOD_MAY_CONT && 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ret->decision == DECISION_UNCOND_SUCC || 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision == DECISION_COND_SUCC)) { 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "completed successfully (MAY_CONT)"); 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success = 1; 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags, id; 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret, 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reqData, &left, &flags); 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id = eap_get_id(reqData); 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & EAP_TLS_FLAGS_START) { 14531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own " 14541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ver=%d)", flags & EAP_TLS_VERSION_MASK, 14551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt data->ttls_version); 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 5281, Ch. 9.2: 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * "This packet MAY contain additional information in the form 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * of AVPs, which may provide useful hints to the client" 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * For now, ignore any potential extra data. 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = 0; 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = NULL; 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !data->resuming) { 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf msg; 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msg, pos, left); 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_ttls_decrypt(sm, data, ret, id, &msg, &resp); 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_ttls_process_handshake(sm, data, ret, id, 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, left, &resp); 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_check_auth_status(sm, data, ret); 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: what about res == -1? Could just move all error processing into 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the other functions and get rid of this res==1 case here. */ 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 1) { 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS, 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version); 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success; 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv) 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_req); 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_req = NULL; 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_TNC 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ready_for_tnc = 0; 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tnc_started = 0; 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_TNC */ 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv) 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->key_data); 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_data = NULL; 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv && data->phase2_method && 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->init_for_reauth) 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->init_for_reauth(sm, data->phase2_priv); 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_start = 0; 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_success = 0; 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->resuming = 1; 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = 1; 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf, 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen, int verbose) 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len, ret; 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLSv%d Phase2 method=", 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version); 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->phase2_type) { 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_EAP: 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, "EAP-%s\n", 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method ? 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->name : "?"); 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_MSCHAPV2: 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, "MSCHAPV2\n"); 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_MSCHAP: 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, "MSCHAP\n"); 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_PAP: 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, "PAP\n"); 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_TTLS_PHASE2_CHAP: 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, "CHAP\n"); 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv) 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->key_data != NULL && data->phase2_success; 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->key_data == NULL || !data->phase2_success) 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_TLS_KEY_LEN); 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_TLS_KEY_LEN; 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_ttls_register(void) 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS"); 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_ttls_init; 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_ttls_deinit; 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_ttls_process; 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isKeyAvailable = eap_ttls_isKeyAvailable; 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_ttls_getKey; 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_status = eap_ttls_get_status; 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->has_reauth_data = eap_ttls_has_reauth_data; 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit_for_reauth = eap_ttls_deinit_for_reauth; 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init_for_reauth = eap_ttls_init_for_reauth; 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1623