1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP-WSC server for Wi-Fi Protected Setup 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2007-2008, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_i.h" 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_common/eap_wsc_common.h" 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wps/wps.h" 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_wsc_data { 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt enum { START, MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int registrar; 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *in_buf; 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *out_buf; 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt enum wsc_op_code in_op_code, out_op_code; 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t out_used; 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t fragment_size; 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wps_data *wps; 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ext_reg_timeout; 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const char * eap_wsc_state_txt(int state) 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (state) { 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case START: 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "START"; 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case MSG: 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "MSG"; 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case FRAG_ACK: 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "FRAG_ACK"; 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WAIT_FRAG_ACK: 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "WAIT_FRAG_ACK"; 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case DONE: 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "DONE"; 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case FAIL: 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "FAIL"; 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "?"; 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_wsc_state(struct eap_wsc_data *data, int state) 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s", 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state_txt(data->state), 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state_txt(state)); 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = state; 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_wsc_ext_reg_timeout(void *eloop_ctx, void *timeout_ctx) 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_sm *sm = eloop_ctx; 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_wsc_data *data = timeout_ctx; 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->method_pending != METHOD_PENDING_WAIT) 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Timeout while waiting for an External " 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Registrar"); 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->ext_reg_timeout = 1; 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_sm_pending_cb(sm); 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * eap_wsc_init(struct eap_sm *sm) 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_wsc_data *data; 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int registrar; 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wps_config cfg; 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->identity && sm->identity_len == WSC_ID_REGISTRAR_LEN && 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(sm->identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 0) 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt registrar = 0; /* Supplicant is Registrar */ 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else if (sm->identity && sm->identity_len == WSC_ID_ENROLLEE_LEN && 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(sm->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt == 0) 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt registrar = 1; /* Supplicant is Enrollee */ 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else { 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->identity, sm->identity_len); 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data = os_zalloc(sizeof(*data)); 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = registrar ? START : MSG; 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->registrar = registrar; 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&cfg, 0, sizeof(cfg)); 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cfg.wps = sm->wps; 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cfg.registrar = registrar; 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (registrar) { 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->wps == NULL || sm->wps->registrar == NULL) { 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: WPS Registrar not " 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "initialized"); 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->user == NULL || sm->user->password == NULL) { 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: No AP PIN (password) " 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "configured for Enrollee functionality"); 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cfg.pin = sm->user->password; 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cfg.pin_len = sm->user->password_len; 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cfg.assoc_wps_ie = sm->assoc_wps_ie; 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->wps = wps_init(&cfg); 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->wps == NULL) { 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->fragment_size = WSC_FRAGMENT_SIZE; 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data; 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_wsc_reset(struct eap_sm *sm, void *priv) 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_wsc_data *data = priv; 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->in_buf); 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->out_buf); 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wps_deinit(data->wps); 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_wsc_build_start(struct eap_sm *sm, 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_wsc_data *data, u8 id) 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *req; 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2, 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_CODE_REQUEST, id); 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (req == NULL) { 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "request"); 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/Start"); 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(req, WSC_Start); /* Op-Code */ 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(req, 0); /* Flags */ 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return req; 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 id) 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *req; 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 flags; 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t send_len, plen; 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt flags = 0; 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt send_len = wpabuf_len(data->out_buf) - data->out_used; 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (2 + send_len > data->fragment_size) { 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt send_len = data->fragment_size - 2; 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt flags |= WSC_FLAGS_MF; 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->out_used == 0) { 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt flags |= WSC_FLAGS_LF; 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt send_len -= 2; 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = 2 + send_len; 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (flags & WSC_FLAGS_LF) 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen += 2; 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen, 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_CODE_REQUEST, id); 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (req == NULL) { 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "request"); 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(req, data->out_op_code); /* Op-Code */ 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(req, flags); /* Flags */ 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (flags & WSC_FLAGS_LF) 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_be16(req, wpabuf_len(data->out_buf)); 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt send_len); 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_used += send_len; 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->out_used == wpabuf_len(data->out_buf)) { 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(message sent completely)", 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) send_len); 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->out_buf); 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_buf = NULL; 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_used = 0; 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, MSG); 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(%lu more to send)", (unsigned long) send_len, 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) wpabuf_len(data->out_buf) - 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_used); 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, WAIT_FRAG_ACK); 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return req; 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_wsc_buildReq(struct eap_sm *sm, void *priv, u8 id) 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_wsc_data *data = priv; 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (data->state) { 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case START: 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_wsc_build_start(sm, data, id); 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case MSG: 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->out_buf == NULL) { 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_buf = wps_get_msg(data->wps, 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &data->out_op_code); 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->out_buf == NULL) { 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to " 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "receive message from WPS"); 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_used = 0; 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* pass through */ 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WAIT_FRAG_ACK: 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_wsc_build_msg(data, id); 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case FRAG_ACK: 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_wsc_build_frag_ack(id, EAP_CODE_REQUEST); 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected state %d in " 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "buildReq", data->state); 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_wsc_check(struct eap_sm *sm, void *priv, 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *respData) 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos; 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt respData, &len); 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos == NULL || len < 2) { 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: Invalid frame"); 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return TRUE; 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return FALSE; 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_wsc_process_cont(struct eap_wsc_data *data, 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *buf, size_t len, u8 op_code) 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Process continuation of a pending message */ 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (op_code != data->in_op_code) { 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in " 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "fragment (expected %d)", 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code, data->in_op_code); 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len > wpabuf_tailroom(data->in_buf)) { 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow"); 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting for %lu " 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "bytes more", (unsigned long) len, 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_wsc_process_fragment(struct eap_wsc_data *data, 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 flags, u8 op_code, u16 message_length, 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *buf, size_t len) 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Process a fragment that is not the last one of the message */ 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length " 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "field in a fragmented packet"); 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf == NULL) { 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* First fragment of the message */ 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->in_buf = wpabuf_alloc(message_length); 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf == NULL) { 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "message"); 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->in_op_code = op_code; 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in " 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "first fragment, waiting for %lu bytes more", 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) len, 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_wsc_process(struct eap_sm *sm, void *priv, 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *respData) 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_wsc_data *data = priv; 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *start, *pos, *end; 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 op_code, flags; 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 message_length = 0; 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt enum wps_process_res res; 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf tmpbuf; 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->ext_reg_timeout) { 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt respData, &len); 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos == NULL || len < 2) 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; /* Should not happen; message already verified */ 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt start = pos; 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt end = start + len; 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code = *pos++; 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt flags = *pos++; 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (flags & WSC_FLAGS_LF) { 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (end - pos < 2) { 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt message_length = WPA_GET_BE16(pos); 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (message_length < end - pos) { 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Length"); 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Flags 0x%x Message Length %d", 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code, flags, message_length); 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state == WAIT_FRAG_ACK) { 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (op_code != WSC_FRAG_ACK) { 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in WAIT_FRAG_ACK state", op_code); 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, MSG); 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code != WSC_Done) { 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code); 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf && 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (flags & WSC_FLAGS_MF) { 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_wsc_process_fragment(data, flags, op_code, 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt message_length, pos, end - pos) < 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 0) 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FRAG_ACK); 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf == NULL) { 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Wrap unfragmented messages as wpabuf without extra copy */ 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_set(&tmpbuf, pos, end - pos); 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->in_buf = &tmpbuf; 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = wps_process_msg(data->wps, op_code, data->in_buf); 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (res) { 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPS_DONE: 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "successfully - report EAP failure"); 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPS_CONTINUE: 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, MSG); 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPS_FAILURE: 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPS_PENDING: 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, MSG); 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->method_pending = METHOD_PENDING_WAIT; 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout, 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm, data); 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf != &tmpbuf) 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->in_buf); 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->in_buf = NULL; 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_wsc_isDone(struct eap_sm *sm, void *priv) 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_wsc_data *data = priv; 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->state == FAIL; 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_wsc_isSuccess(struct eap_sm *sm, void *priv) 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* EAP-WSC will always result in EAP-Failure */ 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return FALSE; 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_wsc_getTimeout(struct eap_sm *sm, void *priv) 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Recommended retransmit times: retransmit timeout 5 seconds, 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * per-message timeout 15 seconds, i.e., 3 tries. */ 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->MaxRetrans = 2; /* total 3 attempts */ 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 5; 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_server_wsc_register(void) 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method *eap; 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "WSC"); 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap == NULL) 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->init = eap_wsc_init; 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->reset = eap_wsc_reset; 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->buildReq = eap_wsc_buildReq; 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->check = eap_wsc_check; 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->process = eap_wsc_process; 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->isDone = eap_wsc_isDone; 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->isSuccess = eap_wsc_isSuccess; 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->getTimeout = eap_wsc_getTimeout; 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = eap_server_method_register(eap); 495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret) 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_server_method_free(eap); 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 499