18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / 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_server/eap_i.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_tls_common.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/chap.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_ttls.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define EAP_TTLS_VERSION 0 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_reset(struct eap_sm *sm, void *priv); 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_ttls_data { 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data ssl; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt START, PHASE1, PHASE2_START, PHASE2_METHOD, 311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt PHASE2_MSCHAPV2_RESP, SUCCESS, FAILURE 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } state; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ttls_version; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_method *phase2_method; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *phase2_priv; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int mschapv2_resp_ok; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mschapv2_auth_response[20]; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mschapv2_ident; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pending_phase2_eap_resp; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tnc_started; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_ttls_state_txt(int state) 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "START"; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1: 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE1"; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_START: 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE2_START"; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_METHOD: 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE2_METHOD"; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_MSCHAPV2_RESP: 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "PHASE2_MSCHAPV2_RESP"; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS: 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS"; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE"; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Unknown?!"; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_state(struct eap_ttls_data *data, int state) 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: %s -> %s", 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state_txt(data->state), 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state_txt(state)); 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id, 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int mandatory, size_t len) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_avp_vendor *avp; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t hdrlen; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp = (struct ttls_avp_vendor *) avphdr; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = mandatory ? AVP_FLAGS_MANDATORY : 0; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vendor_id) { 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= AVP_FLAGS_VENDOR; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdrlen = sizeof(*avp); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp->vendor_id = host_to_be32(vendor_id); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdrlen = sizeof(struct ttls_avp); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp->avp_code = host_to_be32(avp_code); 951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt avp->avp_length = host_to_be32(((u32) flags << 24) | 961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ((u32) (hdrlen + len))); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return avphdr + hdrlen; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_avp_encapsulate(struct wpabuf *resp, 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 avp_code, int mandatory) 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *avp; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(resp) + 4); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (avp == NULL) { 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_hdr(wpabuf_mhead(avp), avp_code, 0, mandatory, 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(resp)); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, wpabuf_head(resp), wpabuf_len(resp)); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpabuf_len(resp); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AVP_PAD((const u8 *) wpabuf_head(avp), pos); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(avp, pos - (u8 *) wpabuf_head(avp)); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return avp; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_ttls_avp { 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: eap is allocated memory; caller is responsible for freeing 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it. All the other pointers are pointing to the packet data, i.e., 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * they must not be freed separately. */ 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *eap; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t eap_len; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *user_name; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t user_name_len; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *user_password; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t user_password_len; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *chap_challenge; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t chap_challenge_len; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *chap_password; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t chap_password_len; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mschap_challenge; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mschap_challenge_len; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mschap_response; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mschap_response_len; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mschap2_response; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t mschap2_response_len; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_avp_parse(struct wpabuf *buf, struct eap_ttls_avp *parse) 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ttls_avp *avp; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int left; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_mhead(buf); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = wpabuf_len(buf); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(parse, 0, sizeof(*parse)); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left > 0) { 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 avp_code, avp_length, vendor_id = 0; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 avp_flags, *dpos; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t pad, dlen; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp = (struct ttls_avp *) pos; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code = be_to_host32(avp->avp_code); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_length = be_to_host32(avp->avp_length); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_flags = (avp_length >> 24) & 0xff; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_length &= 0xffffff; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x " 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length=%d", (int) avp_code, avp_flags, 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) avp_length); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((int) avp_length > left) { 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow " 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(len=%d, left=%d) - dropped", 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) avp_length, left); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (avp_length < sizeof(*avp)) { 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length " 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d", avp_length); 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos = (u8 *) (avp + 1); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dlen = avp_length - sizeof(*avp); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (avp_flags & AVP_FLAGS_VENDOR) { 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dlen < 4) { 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: vendor AVP " 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "underflow"); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vendor_id = be_to_host32(* (be32 *) dpos); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d", 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) vendor_id); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos += 4; 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dlen -= 4; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) { 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message"); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse->eap == NULL) { 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eap = os_malloc(dlen); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse->eap == NULL) { 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: " 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed to allocate memory " 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for Phase 2 EAP data"); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(parse->eap, dpos, dlen); 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eap_len = dlen; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *neweap = os_realloc(parse->eap, 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eap_len + dlen); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (neweap == NULL) { 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: " 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed to allocate memory " 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for Phase 2 EAP data"); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(neweap + parse->eap_len, dpos, dlen); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eap = neweap; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eap_len += dlen; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (vendor_id == 0 && 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code == RADIUS_ATTR_USER_NAME) { 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: User-Name", 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos, dlen); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->user_name = dpos; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->user_name_len = dlen; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (vendor_id == 0 && 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code == RADIUS_ATTR_USER_PASSWORD) { 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *password = dpos; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t password_len = dlen; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (password_len > 0 && 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password[password_len - 1] == '\0') { 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password_len--; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: " 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "User-Password (PAP)", 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password, password_len); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->user_password = password; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->user_password_len = password_len; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (vendor_id == 0 && 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code == RADIUS_ATTR_CHAP_CHALLENGE) { 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS: CHAP-Challenge (CHAP)", 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos, dlen); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->chap_challenge = dpos; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->chap_challenge_len = dlen; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (vendor_id == 0 && 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code == RADIUS_ATTR_CHAP_PASSWORD) { 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS: CHAP-Password (CHAP)", 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos, dlen); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->chap_password = dpos; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->chap_password_len = dlen; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code == RADIUS_ATTR_MS_CHAP_CHALLENGE) { 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS: MS-CHAP-Challenge", 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos, dlen); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->mschap_challenge = dpos; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->mschap_challenge_len = dlen; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code == RADIUS_ATTR_MS_CHAP_RESPONSE) { 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS: MS-CHAP-Response (MSCHAP)", 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos, dlen); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->mschap_response = dpos; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->mschap_response_len = dlen; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt avp_code == RADIUS_ATTR_MS_CHAP2_RESPONSE) { 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS: MS-CHAP2-Response (MSCHAPV2)", 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dpos, dlen); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->mschap2_response = dpos; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->mschap2_response_len = dlen; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (avp_flags & AVP_FLAGS_MANDATORY) { 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported " 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "mandatory AVP code %d vendor_id %d - " 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropped", (int) avp_code, (int) vendor_id); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported " 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AVP code %d vendor_id %d", 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) avp_code, (int) vendor_id); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad = (4 - (avp_length & 3)) & 3; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += avp_length + pad; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= avp_length + pad; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(parse->eap); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse->eap = NULL; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, size_t len) 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return eap_server_tls_derive_key(sm, &data->ssl, "ttls challenge", 3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_ttls_init(struct eap_sm *sm) 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version = EAP_TTLS_VERSION; 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = START; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) { 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL."); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_reset(sm, data); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_reset(struct eap_sm *sm, void *priv) 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv && data->phase2_method) 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->reset(sm, data->phase2_priv); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_tls_ssl_deinit(sm, &data->ssl); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_eap_resp); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_build_start(struct eap_sm *sm, 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, u8 id) 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, 1, 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_REQUEST, id); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to allocate memory for" 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " request"); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->ttls_version); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, PHASE1); 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_build_phase2_eap_req( 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *sm, struct eap_ttls_data *data, u8 id) 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf, *encr_req; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = data->phase2_method->buildReq(sm, data->phase2_priv, id); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-TTLS/EAP: Encapsulate Phase 2 data", buf); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = eap_ttls_avp_encapsulate(buf, RADIUS_ATTR_EAP_MESSAGE, 1); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Failed to encapsulate " 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet"); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated " 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 data", buf); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf); 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return encr_req; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_build_phase2_mschapv2( 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *sm, struct eap_ttls_data *data) 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *encr_req, msgbuf; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *req, *pos, *end; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = req = os_malloc(100); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = req + 100; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->mschapv2_resp_ok) { 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_SUCCESS, 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_VENDOR_ID_MICROSOFT, 1, 43); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = data->mschapv2_ident; 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf((char *) pos, end - pos, "S="); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret >= 0 && ret < end - pos) 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpa_snprintf_hex_uppercase( 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (char *) pos, end - pos, data->mschapv2_auth_response, 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(data->mschapv2_auth_response)); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_ERROR, 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_VENDOR_ID_MICROSOFT, 1, 6); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, "Failed", 6); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 6; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AVP_PAD(req, pos); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msgbuf, req, pos - req); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 " 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data", &msgbuf); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(req); 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return encr_req; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id) 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->ssl.state == FRAG_ACK) { 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_server_tls_build_ack(id, EAP_TYPE_TTLS, 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->ssl.state == WAIT_FRAG_ACK) { 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS, 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version, id); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_ttls_build_start(sm, data, id); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1: 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, " 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "starting Phase2"); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, PHASE2_START); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_METHOD: 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->ssl.tls_out); 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out_pos = 0; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out = eap_ttls_build_phase2_eap_req(sm, data, 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_MSCHAPV2_RESP: 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->ssl.tls_out); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out_pos = 0; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ssl.tls_out = eap_ttls_build_phase2_mschapv2(sm, data); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, data->state); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS, 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version, id); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_check(struct eap_sm *sm, void *priv, 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData, &len); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 1) { 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Invalid frame"); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_pap(struct eap_sm *sm, 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *user_password, 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t user_password_len) 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->user || !sm->user->password || sm->user->password_hash || 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(sm->user->ttls_auth & EAP_TTLS_AUTH_PAP)) { 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: No plaintext user " 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "password configured"); 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->password_len != user_password_len || 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(sm->user->password, user_password, user_password_len) != 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Invalid user password"); 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Correct user password"); 5201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_state(data, SUCCESS); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_chap(struct eap_sm *sm, 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *challenge, 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t challenge_len, 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *password, 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t password_len) 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *chal, hash[CHAP_MD5_LEN]; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge == NULL || password == NULL || 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_len != EAP_TTLS_CHAP_CHALLENGE_LEN || 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password_len != 1 + EAP_TTLS_CHAP_PASSWORD_LEN) { 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid CHAP attributes " 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(challenge len %lu password len %lu)", 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) challenge_len, 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) password_len); 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->user || !sm->user->password || sm->user->password_hash || 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(sm->user->ttls_auth & EAP_TTLS_AUTH_CHAP)) { 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: No plaintext user " 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "password configured"); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chal = eap_ttls_implicit_challenge(sm, data, 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_CHAP_CHALLENGE_LEN + 1); 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chal == NULL) { 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Failed to generate " 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "challenge from TLS data"); 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN) != 0 || 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password[0] != chal[EAP_TTLS_CHAP_CHALLENGE_LEN]) { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Challenge mismatch"); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MD5(Ident + Password + Challenge) */ 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chap_md5(password[0], sm->user->password, sm->user->password_len, 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge, challenge_len, hash); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 0) { 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password"); 5761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_state(data, SUCCESS); 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid user password"); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_mschap(struct eap_sm *sm, 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *challenge, size_t challenge_len, 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *response, size_t response_len) 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *chal, nt_response[24]; 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge == NULL || response == NULL || 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_len != EAP_TTLS_MSCHAP_CHALLENGE_LEN || 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt response_len != EAP_TTLS_MSCHAP_RESPONSE_LEN) { 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid MS-CHAP " 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attributes (challenge len %lu response len %lu)", 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) challenge_len, 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) response_len); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->user || !sm->user->password || 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAP)) { 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: No user password " 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configured"); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chal = eap_ttls_implicit_challenge(sm, data, 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chal == NULL) { 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Failed to generate " 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "challenge from TLS data"); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN) != 0 || 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) { 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Challenge mismatch"); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->password_hash) 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_response(challenge, sm->user->password, nt_response); 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_challenge_response(challenge, sm->user->password, 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password_len, nt_response); 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(nt_response, response + 2 + 24, 24) == 0) { 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response"); 6361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_state(data, SUCCESS); 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid NT-Response"); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Received", 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt response + 2 + 24, 24); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Expected", 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_response, 24); 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_mschapv2(struct eap_sm *sm, 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *challenge, 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t challenge_len, 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *response, size_t response_len) 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *chal, *username, nt_response[24], *rx_resp, *peer_challenge, 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *auth_challenge; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t username_len, i; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge == NULL || response == NULL || 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_len != EAP_TTLS_MSCHAPV2_CHALLENGE_LEN || 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt response_len != EAP_TTLS_MSCHAPV2_RESPONSE_LEN) { 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid MS-CHAP2 " 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attributes (challenge len %lu response len %lu)", 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) challenge_len, 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) response_len); 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->user || !sm->user->password || 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAPV2)) { 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user password " 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configured"); 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 67761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->identity == NULL) { 67861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user identity " 67961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "known"); 68061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap_ttls_state(data, FAILURE); 68161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 68261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 68361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MSCHAPv2 does not include optional domain name in the 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * challenge-response calculation, so remove domain prefix 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (if present). */ 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username = sm->identity; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username_len = sm->identity_len; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < username_len; i++) { 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (username[i] == '\\') { 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username_len -= i + 1; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username += i + 1; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chal = eap_ttls_implicit_challenge( 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chal == NULL) { 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Failed to generate " 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "challenge from TLS data"); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) != 0 || 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt response[0] != chal[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]) { 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Challenge mismatch"); 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_challenge = challenge; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge = response + 2; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: User", 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len); 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: auth_challenge", 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: peer_challenge", 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->password_hash) { 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt generate_nt_response_pwhash(auth_challenge, peer_challenge, 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password, 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_response); 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt generate_nt_response(auth_challenge, peer_challenge, 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password, 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password_len, 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_response); 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8; 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(nt_response, rx_resp, 24) == 0) { 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct " 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NT-Response"); 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mschapv2_resp_ok = 1; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->password_hash) { 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt generate_authenticator_response_pwhash( 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password, 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge, auth_challenge, 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, nt_response, 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mschapv2_auth_response); 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt generate_authenticator_response( 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password, sm->user->password_len, 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge, auth_challenge, 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, nt_response, 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mschapv2_auth_response); 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid " 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NT-Response"); 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Received", 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rx_resp, 24); 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Expected", 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_response, 24); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mschapv2_resp_ok = 0; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, PHASE2_MSCHAPV2_RESP); 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mschapv2_ident = response[0]; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_eap_init(struct eap_sm *sm, 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EapType eap_type) 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv && data->phase2_method) { 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->reset(sm, data->phase2_priv); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method = NULL; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_priv = NULL; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_type); 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->phase2_method) 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->init_phase2 = 1; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_priv = data->phase2_method->init(sm); 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->init_phase2 = 0; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->phase2_priv == NULL ? -1 : 0; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_eap_response(struct eap_sm *sm, 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *in_data, size_t in_len) 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 next_type = EAP_TYPE_NONE; 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf buf; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_method *m = data->phase2_method; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *priv = data->phase2_priv; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv == NULL) { 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: %s - Phase2 not " 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialized?!", __func__); 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct eap_hdr *) in_data; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = in_len - sizeof(*hdr); 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 type Nak'ed; " 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "allowed types", pos + 1, left - 1); 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_process_nak(sm, pos + 1, left - 1); 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[sm->user_eap_method_index].method != 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_NONE) { 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = sm->user->methods[ 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user_eap_method_index++].method; 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type); 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_eap_init(sm, data, next_type)) { 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to " 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialize EAP type %d", 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type); 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&buf, in_data, in_len); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m->check(sm, priv, &buf)) { 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to " 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore the packet"); 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m->process(sm, priv, &buf); 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->method_pending == METHOD_PENDING_WAIT) { 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method is in " 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pending wait state - save decrypted response"); 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_eap_resp); 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_eap_resp = wpabuf_dup(&buf); 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!m->isDone(sm, priv)) 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!m->isSuccess(sm, priv)) { 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method failed"); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_START: 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP_TTLS: Phase2 " 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Identity not found in the user " 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "database", 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, sm->identity_len); 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, PHASE2_METHOD); 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = sm->user->methods[0].method; 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user_eap_method_index = 1; 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type); 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_eap_init(sm, data, next_type)) { 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize " 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP type %d", next_type); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_METHOD: 8861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_state(data, SUCCESS); 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, data->state); 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_eap(struct eap_sm *sm, 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *eap, size_t eap_len) 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr; 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == PHASE2_START) { 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: initializing Phase 2"); 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_IDENTITY) < 0) 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to " 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialize EAP-Identity"); 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_len < sizeof(*hdr)) { 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: too short Phase 2 EAP " 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet (len=%lu)", (unsigned long) eap_len); 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct eap_hdr *) eap; 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = be_to_host16(hdr->length); 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d " 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "identifier=%d length=%lu", hdr->code, hdr->identifier, 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > eap_len) { 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Length mismatch in Phase 2" 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " EAP frame (hdr len=%lu, data len in AVP=%lu)", 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, (unsigned long) eap_len); 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->code) { 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_RESPONSE: 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_eap_response(sm, data, (u8 *) hdr, 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len); 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Unexpected code=%d in " 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP header", hdr->code); 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2(struct eap_sm *sm, 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_buf) 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_decrypted; 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_avp parse; 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Phase 2", (unsigned long) wpabuf_len(in_buf)); 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->pending_phase2_eap_resp) { 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response " 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- skip decryption and use old data"); 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_eap( 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, data, wpabuf_head(data->pending_phase2_eap_resp), 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(data->pending_phase2_eap_resp)); 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_eap_resp); 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_eap_resp = NULL; 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_buf); 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_decrypted == NULL) { 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 " 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data"); 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP", 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted); 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_avp_parse(in_decrypted, &parse) < 0) { 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs"); 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse.user_name) { 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->identity); 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity = os_malloc(parse.user_name_len); 98961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->identity == NULL) { 99061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap_ttls_state(data, FAILURE); 99161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto done; 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 99361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(sm->identity, parse.user_name, parse.user_name_len); 99461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->identity_len = parse.user_name_len; 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user_get(sm, parse.user_name, parse.user_name_len, 1) 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt != 0) { 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 Identity not " 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found in the user database"); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tnc_started && parse.eap == NULL) { 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: TNC started but no EAP " 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "response from peer"); 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse.eap) { 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_eap(sm, data, parse.eap, 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.eap_len); 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (parse.user_password) { 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_pap(sm, data, parse.user_password, 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.user_password_len); 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (parse.chap_password) { 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_chap(sm, data, 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.chap_challenge, 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.chap_challenge_len, 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.chap_password, 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.chap_password_len); 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (parse.mschap_response) { 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_mschap(sm, data, 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_challenge, 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_challenge_len, 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_response, 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_response_len); 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (parse.mschap2_response) { 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_mschapv2(sm, data, 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_challenge, 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_challenge_len, 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap2_response, 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap2_response_len); 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone: 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(parse.eap); 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data) 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->tnc || data->state != SUCCESS || data->tnc_started) 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Initialize TNC"); 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_TNC)) { 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize TNC"); 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tnc_started = 1; 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, PHASE2_METHOD); 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_process_version(struct eap_sm *sm, void *priv, 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int peer_version) 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer_version < data->ttls_version) { 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; " 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "use version %d", 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_version, data->ttls_version, peer_version); 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version = peer_version; 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_msg(struct eap_sm *sm, void *priv, 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *respData) 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1: 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_server_tls_phase1(sm, &data->ssl) < 0) 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_START: 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_METHOD: 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2(sm, data, data->ssl.tls_in); 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_start_tnc(sm, data); 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_MSCHAPV2_RESP: 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.tls_in) == 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "acknowledged response"); 10991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_state(data, SUCCESS); 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!data->mschapv2_resp_ok) { 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "acknowledged error"); 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected " 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame from peer (payload len %lu, " 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "expected empty frame)", 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(data->ssl.tls_in)); 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_start_tnc(sm, data); 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s", 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state, __func__); 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process(struct eap_sm *sm, void *priv, 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_server_tls_process(sm, &data->ssl, respData, data, 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_TTLS, eap_ttls_process_version, 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_msg) < 0) 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv) 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *eapKeyData; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, 11491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ttls keying material", 11501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt EAP_TLS_KEY_LEN); 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapKeyData) { 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_TLS_KEY_LEN; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapKeyData, EAP_TLS_KEY_LEN); 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eapKeyData; 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv) 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_ttls_register(void) 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS"); 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_ttls_init; 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_ttls_reset; 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_ttls_buildReq; 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_ttls_check; 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_ttls_process; 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_ttls_isDone; 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_ttls_getKey; 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_ttls_isSuccess; 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1194