18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-WSC server for Wi-Fi Protected Setup 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2007-2008, 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 "eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_wsc_common.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p/p2p.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_wsc_data { 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int registrar; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_buf; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *out_buf; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wsc_op_code in_op_code, out_op_code; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t out_used; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t fragment_size; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_data *wps; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ext_reg_timeout; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_wsc_state_txt(int state) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "START"; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case MESG: 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "MESG"; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FRAG_ACK: 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FRAG_ACK"; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WAIT_FRAG_ACK: 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WAIT_FRAG_ACK"; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case DONE: 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "DONE"; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAIL: 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAIL"; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "?"; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */ 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_wsc_state(struct eap_wsc_data *data, int state) 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s", 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state_txt(data->state), 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state_txt(state)); 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_wsc_ext_reg_timeout(void *eloop_ctx, void *timeout_ctx) 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *sm = eloop_ctx; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data = timeout_ctx; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->method_pending != METHOD_PENDING_WAIT) 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Timeout while waiting for an External " 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Registrar"); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ext_reg_timeout = 1; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_pending_cb(sm); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_wsc_init(struct eap_sm *sm) 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int registrar; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_config cfg; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->identity && sm->identity_len == WSC_ID_REGISTRAR_LEN && 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(sm->identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt registrar = 0; /* Supplicant is Registrar */ 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (sm->identity && sm->identity_len == WSC_ID_ENROLLEE_LEN && 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(sm->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt == 0) 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt registrar = 1; /* Supplicant is Enrollee */ 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, sm->identity_len); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = registrar ? START : MESG; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->registrar = registrar; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&cfg, 0, sizeof(cfg)); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.wps = sm->wps; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.registrar = registrar; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (registrar) { 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wps == NULL || sm->wps->registrar == NULL) { 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: WPS Registrar not " 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initialized"); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user == NULL || sm->user->password == NULL) { 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * In theory, this should not really be needed, but 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Windows 7 uses Registrar mode to probe AP's WPS 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * capabilities before trying to use Enrollee and fails 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * if the AP does not allow that probing to happen.. 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No AP PIN (password) " 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configured for Enrollee functionality - " 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "allow for probing capabilities (M1)"); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pin = sm->user->password; 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.pin_len = sm->user->password_len; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.assoc_wps_ie = sm->assoc_wps_ie; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.peer_addr = sm->peer_addr; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->assoc_p2p_ie) { 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Prefer PSK format for P2P " 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "client"); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.use_psk_key = 1; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */ 14187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen cfg.pbc_in_m1 = sm->pbc_in_m1; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->wps = wps_init(&cfg); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->wps == NULL) { 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->fragment_size = sm->fragment_size > 0 ? sm->fragment_size : 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WSC_FRAGMENT_SIZE; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_wsc_reset(struct eap_sm *sm, void *priv) 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data = priv; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->in_buf); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->out_buf); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_deinit(data->wps); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_wsc_build_start(struct eap_sm *sm, 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data, u8 id) 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2, 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_REQUEST, id); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/Start"); 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(req, WSC_Start); /* Op-Code */ 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(req, 0); /* Flags */ 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 id) 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t send_len, plen; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = 0; 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = wpabuf_len(data->out_buf) - data->out_used; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (2 + send_len > data->fragment_size) { 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = data->fragment_size - 2; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= WSC_FLAGS_MF; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_used == 0) { 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= WSC_FLAGS_LF; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len -= 2; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = 2 + send_len; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_LF) 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen += 2; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen, 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_REQUEST, id); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(req, data->out_op_code); /* Op-Code */ 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(req, flags); /* Flags */ 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_LF) 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(req, wpabuf_len(data->out_buf)); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used += send_len; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_used == wpabuf_len(data->out_buf)) { 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(message sent completely)", 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) send_len); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->out_buf); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_buf = NULL; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used = 0; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%lu more to send)", (unsigned long) send_len, 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(data->out_buf) - 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, WAIT_FRAG_ACK); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_wsc_buildReq(struct eap_sm *sm, void *priv, u8 id) 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data = priv; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_wsc_build_start(sm, data, id); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case MESG: 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_buf == NULL) { 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_buf = wps_get_msg(data->wps, 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->out_op_code); 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_buf == NULL) { 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to " 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "receive message from WPS"); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used = 0; 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* pass through */ 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WAIT_FRAG_ACK: 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_wsc_build_msg(data, id); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FRAG_ACK: 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_wsc_build_frag_ack(id, EAP_CODE_REQUEST); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected state %d in " 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "buildReq", data->state); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_wsc_check(struct eap_sm *sm, void *priv, 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt respData, &len); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 2) { 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: Invalid frame"); 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_wsc_process_cont(struct eap_wsc_data *data, 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len, u8 op_code) 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process continuation of a pending message */ 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != data->in_op_code) { 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in " 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragment (expected %d)", 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code, data->in_op_code); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > wpabuf_tailroom(data->in_buf)) { 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow"); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting for %lu " 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bytes more", (unsigned long) len, 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_wsc_process_fragment(struct eap_wsc_data *data, 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags, u8 op_code, u16 message_length, 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process a fragment that is not the last one of the message */ 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length " 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "field in a fragmented packet"); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* First fragment of the message */ 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = wpabuf_alloc(message_length); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_op_code = op_code; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in " 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "first fragment, waiting for %lu bytes more", 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_wsc_process(struct eap_sm *sm, void *priv, 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data = priv; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *start, *pos, *end; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 op_code, flags; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 message_length = 0; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wps_process_res res; 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf tmpbuf; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->ext_reg_timeout) { 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt respData, &len); 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 2) 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* Should not happen; message already verified */ 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = pos; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = start + len; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code = *pos++; 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = *pos++; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_LF) { 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 2) { 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_length = WPA_GET_BE16(pos); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (message_length < end - pos) { 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Length"); 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Flags 0x%x Message Length %d", 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code, flags, message_length); 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == WAIT_FRAG_ACK) { 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != WSC_FRAG_ACK) { 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in WAIT_FRAG_ACK state", op_code); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code != WSC_Done) { 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt op_code); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf && 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WSC_FLAGS_MF) { 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_wsc_process_fragment(data, flags, op_code, 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_length, pos, end - pos) < 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FRAG_ACK); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Wrap unfragmented messages as wpabuf without extra copy */ 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&tmpbuf, pos, end - pos); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = &tmpbuf; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wps_process_msg(data->wps, op_code, data->in_buf); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (res) { 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_DONE: 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "successfully - report EAP failure"); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_CONTINUE: 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_FAILURE: 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, FAIL); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPS_PENDING: 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_wsc_state(data, MESG); 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->method_pending = METHOD_PENDING_WAIT; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout, 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, data); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf != &tmpbuf) 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->in_buf); 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = NULL; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_wsc_isDone(struct eap_sm *sm, void *priv) 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_wsc_data *data = priv; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == FAIL; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_wsc_isSuccess(struct eap_sm *sm, void *priv) 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* EAP-WSC will always result in EAP-Failure */ 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_wsc_getTimeout(struct eap_sm *sm, void *priv) 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Recommended retransmit times: retransmit timeout 5 seconds, 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * per-message timeout 15 seconds, i.e., 3 tries. */ 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->MaxRetrans = 2; /* total 3 attempts */ 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 5; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_wsc_register(void) 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WSC"); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_wsc_init; 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_wsc_reset; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_wsc_buildReq; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_wsc_check; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_wsc_process; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_wsc_isDone; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_wsc_isSuccess; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getTimeout = eap_wsc_getTimeout; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 513