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