eap_server_ttls.c revision c28170251eb54dbf64a9074a07fee377587425b2
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); 339c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt bin_clear_free(data, sizeof(*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 || 512c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memcmp_const(sm->user->password, user_password, 513c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt user_password_len) != 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 561c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN) 562c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt != 0 || 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password[0] != chal[EAP_TTLS_CHAP_CHALLENGE_LEN]) { 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Challenge mismatch"); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MD5(Ident + Password + Challenge) */ 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chap_md5(password[0], sm->user->password, sm->user->password_len, 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge, challenge_len, hash); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 575c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 576c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 0) { 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password"); 5781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_state(data, SUCCESS); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid user password"); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_mschap(struct eap_sm *sm, 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *challenge, size_t challenge_len, 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *response, size_t response_len) 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *chal, nt_response[24]; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge == NULL || response == NULL || 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_len != EAP_TTLS_MSCHAP_CHALLENGE_LEN || 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt response_len != EAP_TTLS_MSCHAP_RESPONSE_LEN) { 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid MS-CHAP " 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attributes (challenge len %lu response len %lu)", 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) challenge_len, 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) response_len); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->user || !sm->user->password || 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAP)) { 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: No user password " 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configured"); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chal = eap_ttls_implicit_challenge(sm, data, 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chal == NULL) { 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Failed to generate " 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "challenge from TLS data"); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 621c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN) 622c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt != 0 || 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) { 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Challenge mismatch"); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->password_hash) 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_response(challenge, sm->user->password, nt_response); 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_challenge_response(challenge, sm->user->password, 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password_len, nt_response); 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 637c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(nt_response, response + 2 + 24, 24) == 0) { 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response"); 6391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_state(data, SUCCESS); 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid NT-Response"); 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Received", 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt response + 2 + 24, 24); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Expected", 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_response, 24); 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_mschapv2(struct eap_sm *sm, 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *challenge, 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t challenge_len, 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *response, size_t response_len) 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *chal, *username, nt_response[24], *rx_resp, *peer_challenge, 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *auth_challenge; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t username_len, i; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge == NULL || response == NULL || 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_len != EAP_TTLS_MSCHAPV2_CHALLENGE_LEN || 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt response_len != EAP_TTLS_MSCHAPV2_RESPONSE_LEN) { 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid MS-CHAP2 " 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attributes (challenge len %lu response len %lu)", 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) challenge_len, 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) response_len); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->user || !sm->user->password || 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAPV2)) { 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user password " 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configured"); 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 68061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->identity == NULL) { 68161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user identity " 68261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "known"); 68361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap_ttls_state(data, FAILURE); 68461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 68561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 68661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MSCHAPv2 does not include optional domain name in the 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * challenge-response calculation, so remove domain prefix 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (if present). */ 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username = sm->identity; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username_len = sm->identity_len; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < username_len; i++) { 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (username[i] == '\\') { 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username_len -= i + 1; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username += i + 1; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chal = eap_ttls_implicit_challenge( 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chal == NULL) { 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Failed to generate " 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "challenge from TLS data"); 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 709c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) 710c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt != 0 || 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt response[0] != chal[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]) { 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Challenge mismatch"); 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(chal); 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_challenge = challenge; 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge = response + 2; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: User", 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len); 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: auth_challenge", 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: peer_challenge", 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->password_hash) { 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt generate_nt_response_pwhash(auth_challenge, peer_challenge, 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password, 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_response); 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt generate_nt_response(auth_challenge, peer_challenge, 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password, 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password_len, 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_response); 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8; 743c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(nt_response, rx_resp, 24) == 0) { 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct " 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NT-Response"); 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mschapv2_resp_ok = 1; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->password_hash) { 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt generate_authenticator_response_pwhash( 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password, 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge, auth_challenge, 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, nt_response, 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mschapv2_auth_response); 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt generate_authenticator_response( 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password, sm->user->password_len, 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge, auth_challenge, 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, nt_response, 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mschapv2_auth_response); 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid " 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NT-Response"); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Received", 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rx_resp, 24); 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Expected", 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_response, 24); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mschapv2_resp_ok = 0; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, PHASE2_MSCHAPV2_RESP); 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mschapv2_ident = response[0]; 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_phase2_eap_init(struct eap_sm *sm, 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EapType eap_type) 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2_priv && data->phase2_method) { 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method->reset(sm, data->phase2_priv); 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method = NULL; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_priv = NULL; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_type); 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->phase2_method) 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->init_phase2 = 1; 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2_priv = data->phase2_method->init(sm); 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->init_phase2 = 0; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->phase2_priv == NULL ? -1 : 0; 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_eap_response(struct eap_sm *sm, 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *in_data, size_t in_len) 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 next_type = EAP_TYPE_NONE; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf buf; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_method *m = data->phase2_method; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *priv = data->phase2_priv; 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (priv == NULL) { 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: %s - Phase2 not " 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialized?!", __func__); 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct eap_hdr *) in_data; 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = in_len - sizeof(*hdr); 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 type Nak'ed; " 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "allowed types", pos + 1, left - 1); 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_process_nak(sm, pos + 1, left - 1); 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[sm->user_eap_method_index].method != 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_NONE) { 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = sm->user->methods[ 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user_eap_method_index++].method; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type); 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_eap_init(sm, data, next_type)) { 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to " 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialize EAP type %d", 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type); 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&buf, in_data, in_len); 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (m->check(sm, priv, &buf)) { 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to " 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore the packet"); 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt m->process(sm, priv, &buf); 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->method_pending == METHOD_PENDING_WAIT) { 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method is in " 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pending wait state - save decrypted response"); 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_eap_resp); 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_eap_resp = wpabuf_dup(&buf); 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!m->isDone(sm, priv)) 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!m->isSuccess(sm, priv)) { 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method failed"); 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_START: 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP_TTLS: Phase2 " 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Identity not found in the user " 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "database", 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, sm->identity_len); 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, PHASE2_METHOD); 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next_type = sm->user->methods[0].method; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user_eap_method_index = 1; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type); 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_eap_init(sm, data, next_type)) { 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize " 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP type %d", next_type); 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_METHOD: 8901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_state(data, SUCCESS); 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, data->state); 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2_eap(struct eap_sm *sm, 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *eap, size_t eap_len) 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr; 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == PHASE2_START) { 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: initializing Phase 2"); 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_IDENTITY) < 0) 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to " 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialize EAP-Identity"); 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_len < sizeof(*hdr)) { 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: too short Phase 2 EAP " 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet (len=%lu)", (unsigned long) eap_len); 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct eap_hdr *) eap; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = be_to_host16(hdr->length); 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d " 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "identifier=%d length=%lu", hdr->code, hdr->identifier, 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > eap_len) { 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Length mismatch in Phase 2" 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " EAP frame (hdr len=%lu, data len in AVP=%lu)", 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, (unsigned long) eap_len); 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->code) { 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_CODE_RESPONSE: 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_eap_response(sm, data, (u8 *) hdr, 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len); 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Unexpected code=%d in " 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Phase 2 EAP header", hdr->code); 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_phase2(struct eap_sm *sm, 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data, 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_buf) 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_decrypted; 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_avp parse; 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Phase 2", (unsigned long) wpabuf_len(in_buf)); 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->pending_phase2_eap_resp) { 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response " 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "- skip decryption and use old data"); 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_eap( 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, data, wpabuf_head(data->pending_phase2_eap_resp), 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(data->pending_phase2_eap_resp)); 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->pending_phase2_eap_resp); 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_phase2_eap_resp = NULL; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_buf); 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_decrypted == NULL) { 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 " 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data"); 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP", 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_decrypted); 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_avp_parse(in_decrypted, &parse) < 0) { 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs"); 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse.user_name) { 991818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt char *nbuf; 992b5d893b5dec601a58c3ce0fc9e5d6da3816ce97aDmitry Shmidt nbuf = os_malloc(parse.user_name_len * 4 + 1); 993818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt if (nbuf) { 994b5d893b5dec601a58c3ce0fc9e5d6da3816ce97aDmitry Shmidt printf_encode(nbuf, parse.user_name_len * 4 + 1, 995818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt parse.user_name, 996818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt parse.user_name_len); 997818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt eap_log_msg(sm, "TTLS-User-Name '%s'", nbuf); 998818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt os_free(nbuf); 999818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt } 1000818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->identity); 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity = os_malloc(parse.user_name_len); 100361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->identity == NULL) { 100461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt eap_ttls_state(data, FAILURE); 100561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt goto done; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 100761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(sm->identity, parse.user_name, parse.user_name_len); 100861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sm->identity_len = parse.user_name_len; 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user_get(sm, parse.user_name, parse.user_name_len, 1) 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt != 0) { 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 Identity not " 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found in the user database"); 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tnc_started && parse.eap == NULL) { 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: TNC started but no EAP " 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "response from peer"); 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (parse.eap) { 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_eap(sm, data, parse.eap, 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.eap_len); 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (parse.user_password) { 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_pap(sm, data, parse.user_password, 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.user_password_len); 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (parse.chap_password) { 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_chap(sm, data, 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.chap_challenge, 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.chap_challenge_len, 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.chap_password, 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.chap_password_len); 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (parse.mschap_response) { 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_mschap(sm, data, 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_challenge, 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_challenge_len, 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_response, 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_response_len); 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (parse.mschap2_response) { 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2_mschapv2(sm, data, 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_challenge, 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap_challenge_len, 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap2_response, 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt parse.mschap2_response_len); 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone: 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(in_decrypted); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(parse.eap); 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data) 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_TNC 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->tnc || data->state != SUCCESS || data->tnc_started) 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Initialize TNC"); 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_TNC)) { 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize TNC"); 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tnc_started = 1; 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, PHASE2_METHOD); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_TNC */ 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_ttls_process_version(struct eap_sm *sm, void *priv, 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int peer_version) 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer_version < data->ttls_version) { 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; " 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "use version %d", 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_version, data->ttls_version, peer_version); 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ttls_version = peer_version; 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process_msg(struct eap_sm *sm, void *priv, 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *respData) 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE1: 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_server_tls_phase1(sm, &data->ssl) < 0) 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_START: 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_METHOD: 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_phase2(sm, data, data->ssl.tls_in); 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_start_tnc(sm, data); 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PHASE2_MSCHAPV2_RESP: 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.tls_in) == 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "acknowledged response"); 11131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eap_ttls_state(data, SUCCESS); 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!data->mschapv2_resp_ok) { 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "acknowledged error"); 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected " 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame from peer (payload len %lu, " 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "expected empty frame)", 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(data->ssl.tls_in)); 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_start_tnc(sm, data); 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s", 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state, __func__); 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_ttls_process(struct eap_sm *sm, void *priv, 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_server_tls_process(sm, &data->ssl, respData, data, 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_TTLS, eap_ttls_process_version, 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_process_msg) < 0) 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_ttls_state(data, FAILURE); 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv) 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *eapKeyData; 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, 11631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "ttls keying material", 11641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt EAP_TLS_KEY_LEN); 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eapKeyData) { 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_TLS_KEY_LEN; 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapKeyData, EAP_TLS_KEY_LEN); 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eapKeyData; 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv) 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ttls_data *data = priv; 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_ttls_register(void) 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS"); 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_ttls_init; 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_ttls_reset; 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_ttls_buildReq; 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_ttls_check; 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_ttls_process; 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_ttls_isDone; 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_ttls_getKey; 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_ttls_isSuccess; 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1208