1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP-WSC peer 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 "uuid.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_i.h" 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_common/eap_wsc_common.h" 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wps/wps.h" 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wps/wps_defs.h" 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_wsc_data { 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt enum { WAIT_START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int registrar; 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *in_buf; 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *out_buf; 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt enum wsc_op_code in_op_code, out_op_code; 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t out_used; 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t fragment_size; 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wps_data *wps; 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wps_context *wps_ctx; 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const char * eap_wsc_state_txt(int state) 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (state) { 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WAIT_START: 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "WAIT_START"; 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case MESG: 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "MESG"; 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case FRAG_ACK: 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "FRAG_ACK"; 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WAIT_FRAG_ACK: 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "WAIT_FRAG_ACK"; 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case DONE: 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "DONE"; 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case FAIL: 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "FAIL"; 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return "?"; 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_wsc_state(struct eap_wsc_data *data, int state) 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s", 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state_txt(data->state), 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state_txt(state)); 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = state; 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * eap_wsc_init(struct eap_sm *sm) 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_wsc_data *data; 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *identity; 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t identity_len; 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int registrar; 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wps_config cfg; 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const char *pos; 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const char *phase1; 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wps_context *wps; 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wps = sm->wps; 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wps == NULL) { 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "EAP-WSC: WPS context not available"); 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (identity && identity_len == WSC_ID_REGISTRAR_LEN && 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt registrar = 1; /* Supplicant is Registrar */ 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else if (identity && identity_len == WSC_ID_ENROLLEE_LEN && 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt registrar = 0; /* Supplicant is Enrollee */ 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else { 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt identity, identity_len); 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data = os_zalloc(sizeof(*data)); 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = registrar ? MESG : WAIT_START; 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->registrar = registrar; 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->wps_ctx = wps; 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&cfg, 0, sizeof(cfg)); 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cfg.wps = wps; 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cfg.registrar = registrar; 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt phase1 = eap_get_config_phase1(sm); 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (phase1 == NULL) { 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: phase1 configuration data not " 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "set"); 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = os_strstr(phase1, "pin="); 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos) { 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 4; 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cfg.pin = (const u8 *) pos; 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (*pos != '\0' && *pos != ' ') 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos++; 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cfg.pin_len = pos - (const char *) cfg.pin; 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = os_strstr(phase1, "pbc=1"); 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos) 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cfg.pbc = 1; 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (cfg.pin == NULL && !cfg.pbc) { 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 " 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "configuration data"); 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->wps = wps_init(&cfg); 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->wps == NULL) { 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->fragment_size = WSC_FRAGMENT_SIZE; 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (registrar && cfg.pin) { 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wps_registrar_add_pin(data->wps_ctx->registrar, NULL, 147dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt cfg.pin, cfg.pin_len, 0); 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data; 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_wsc_deinit(struct eap_sm *sm, void *priv) 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_wsc_data *data = priv; 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->in_buf); 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->out_buf); 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wps_deinit(data->wps); 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->wps_ctx->network_key); 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->wps_ctx->network_key = NULL; 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, u8 id) 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *resp; 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 flags; 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t send_len, plen; 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = FALSE; 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Generating Response"); 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->allowNotifications = TRUE; 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt flags = 0; 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt send_len = wpabuf_len(data->out_buf) - data->out_used; 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (2 + send_len > data->fragment_size) { 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt send_len = data->fragment_size - 2; 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt flags |= WSC_FLAGS_MF; 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->out_used == 0) { 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt flags |= WSC_FLAGS_LF; 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt send_len -= 2; 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen = 2 + send_len; 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (flags & WSC_FLAGS_LF) 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt plen += 2; 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen, 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_CODE_RESPONSE, id); 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (resp == NULL) 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(resp, data->out_op_code); /* Op-Code */ 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(resp, flags); /* Flags */ 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (flags & WSC_FLAGS_LF) 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_be16(resp, wpabuf_len(data->out_buf)); 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used, 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt send_len); 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_used += send_len; 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_MAY_CONT; 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_FAIL; 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->out_used == wpabuf_len(data->out_buf)) { 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(message sent completely)", 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) send_len); 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->out_buf); 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_buf = NULL; 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_used = 0; 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if ((data->state == FAIL && data->out_op_code == WSC_ACK) || 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_op_code == WSC_NACK || 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_op_code == WSC_Done) { 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_DONE; 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, MESG); 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(%lu more to send)", (unsigned long) send_len, 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) wpabuf_len(data->out_buf) - 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_used); 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, WAIT_FRAG_ACK); 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return resp; 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_wsc_process_cont(struct eap_wsc_data *data, 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *buf, size_t len, u8 op_code) 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Process continuation of a pending message */ 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (op_code != data->in_op_code) { 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in " 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "fragment (expected %d)", 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code, data->in_op_code); 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len > wpabuf_tailroom(data->in_buf)) { 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow"); 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting " 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "for %lu bytes more", (unsigned long) len, 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data, 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 id, u8 flags, u8 op_code, 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 message_length, 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *buf, size_t len) 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Process a fragment that is not the last one of the message */ 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length field in a " 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "fragmented packet"); 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf == NULL) { 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* First fragment of the message */ 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->in_buf = wpabuf_alloc(message_length); 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf == NULL) { 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "message"); 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->in_op_code = op_code; 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in first " 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "fragment, waiting for %lu bytes more", 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) len, 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE); 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpabuf *reqData) 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_wsc_data *data = priv; 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *start, *pos, *end; 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 op_code, flags, id; 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u16 message_length = 0; 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt enum wps_process_res res; 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf tmpbuf; 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, reqData, 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &len); 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos == NULL || len < 2) { 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt id = eap_get_id(reqData); 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt start = pos; 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt end = start + len; 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code = *pos++; 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt flags = *pos++; 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (flags & WSC_FLAGS_LF) { 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (end - pos < 2) { 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt message_length = WPA_GET_BE16(pos); 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (message_length < end - pos) { 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Length"); 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Flags 0x%x Message Length %d", 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code, flags, message_length); 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state == WAIT_FRAG_ACK) { 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (op_code != WSC_FRAG_ACK) { 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in WAIT_FRAG_ACK state", op_code); 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, MESG); 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_wsc_build_msg(data, ret, id); 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code != WSC_Done && op_code != WSC_Start) { 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code); 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->state == WAIT_START) { 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (op_code != WSC_Start) { 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in WAIT_START state", op_code); 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Received start"); 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, MESG); 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Start message has empty payload, skip processing */ 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto send_msg; 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (op_code == WSC_Start) { 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt op_code); 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf && 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (flags & WSC_FLAGS_MF) { 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_wsc_process_fragment(data, ret, id, flags, op_code, 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt message_length, pos, 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt end - pos); 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf == NULL) { 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Wrap unfragmented messages as wpabuf without extra copy */ 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_set(&tmpbuf, pos, end - pos); 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->in_buf = &tmpbuf; 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt res = wps_process_msg(data->wps, op_code, data->in_buf); 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (res) { 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPS_DONE: 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "successfully - wait for EAP failure"); 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPS_CONTINUE: 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, MESG); 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPS_FAILURE: 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case WPS_PENDING: 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, FAIL); 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->in_buf != &tmpbuf) 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->in_buf); 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->in_buf = NULL; 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtsend_msg: 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->out_buf == NULL) { 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_buf = wps_get_msg(data->wps, &data->out_op_code); 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->out_buf == NULL) { 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to receive " 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "message from WPS"); 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->out_used = 0; 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_wsc_state(data, MESG); 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_wsc_build_msg(data, ret, id); 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_peer_wsc_register(void) 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method *eap; 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "WSC"); 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap == NULL) 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->init = eap_wsc_init; 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->deinit = eap_wsc_deinit; 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->process = eap_wsc_process; 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = eap_peer_method_register(eap); 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret) 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_peer_method_free(eap); 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 454