LCOV - code coverage report
Current view: top level - src/eap_peer - eap_wsc.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 271 339 79.9 %
Date: 2015-09-27 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :  * EAP-WSC peer for Wi-Fi Protected Setup
       3             :  * Copyright (c) 2007-2009, 2012, Jouni Malinen <j@w1.fi>
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "uuid.h"
      13             : #include "eap_i.h"
      14             : #include "eap_common/eap_wsc_common.h"
      15             : #include "wps/wps.h"
      16             : #include "wps/wps_defs.h"
      17             : 
      18             : 
      19             : struct eap_wsc_data {
      20             :         enum { WAIT_START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state;
      21             :         int registrar;
      22             :         struct wpabuf *in_buf;
      23             :         struct wpabuf *out_buf;
      24             :         enum wsc_op_code in_op_code, out_op_code;
      25             :         size_t out_used;
      26             :         size_t fragment_size;
      27             :         struct wps_data *wps;
      28             :         struct wps_context *wps_ctx;
      29             : };
      30             : 
      31             : 
      32       10482 : static const char * eap_wsc_state_txt(int state)
      33             : {
      34       10482 :         switch (state) {
      35             :         case WAIT_START:
      36         359 :                 return "WAIT_START";
      37             :         case MESG:
      38        9567 :                 return "MESG";
      39             :         case FRAG_ACK:
      40           0 :                 return "FRAG_ACK";
      41             :         case WAIT_FRAG_ACK:
      42          86 :                 return "WAIT_FRAG_ACK";
      43             :         case DONE:
      44           0 :                 return "DONE";
      45             :         case FAIL:
      46         470 :                 return "FAIL";
      47             :         default:
      48           0 :                 return "?";
      49             :         }
      50             : }
      51             : 
      52             : 
      53        5241 : static void eap_wsc_state(struct eap_wsc_data *data, int state)
      54             : {
      55       10482 :         wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s",
      56        5241 :                    eap_wsc_state_txt(data->state),
      57             :                    eap_wsc_state_txt(state));
      58        5241 :         data->state = state;
      59        5241 : }
      60             : 
      61             : 
      62         417 : static int eap_wsc_new_ap_settings(struct wps_credential *cred,
      63             :                                    const char *params)
      64             : {
      65             :         const char *pos, *end;
      66             :         size_t len;
      67             : 
      68         417 :         os_memset(cred, 0, sizeof(*cred));
      69             : 
      70         417 :         pos = os_strstr(params, "new_ssid=");
      71         417 :         if (pos == NULL)
      72         399 :                 return 0;
      73          18 :         pos += 9;
      74          18 :         end = os_strchr(pos, ' ');
      75          18 :         if (end == NULL)
      76           0 :                 len = os_strlen(pos);
      77             :         else
      78          18 :                 len = end - pos;
      79          36 :         if ((len & 1) || len > 2 * sizeof(cred->ssid) ||
      80          18 :             hexstr2bin(pos, cred->ssid, len / 2)) {
      81           0 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_ssid");
      82           0 :                 return -1;
      83             :         }
      84          18 :         cred->ssid_len = len / 2;
      85             : 
      86          18 :         pos = os_strstr(params, "new_auth=");
      87          18 :         if (pos == NULL) {
      88           0 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_auth");
      89           0 :                 return -1;
      90             :         }
      91          18 :         if (os_strncmp(pos + 9, "OPEN", 4) == 0)
      92           2 :                 cred->auth_type = WPS_AUTH_OPEN;
      93          16 :         else if (os_strncmp(pos + 9, "WPAPSK", 6) == 0)
      94           1 :                 cred->auth_type = WPS_AUTH_WPAPSK;
      95          15 :         else if (os_strncmp(pos + 9, "WPA2PSK", 7) == 0)
      96          15 :                 cred->auth_type = WPS_AUTH_WPA2PSK;
      97             :         else {
      98           0 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_auth");
      99           0 :                 return -1;
     100             :         }
     101             : 
     102          18 :         pos = os_strstr(params, "new_encr=");
     103          18 :         if (pos == NULL) {
     104           0 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_encr");
     105           0 :                 return -1;
     106             :         }
     107          18 :         if (os_strncmp(pos + 9, "NONE", 4) == 0)
     108           1 :                 cred->encr_type = WPS_ENCR_NONE;
     109             : #ifdef CONFIG_TESTING_OPTIONS
     110          17 :         else if (os_strncmp(pos + 9, "WEP", 3) == 0)
     111           1 :                 cred->encr_type = WPS_ENCR_WEP;
     112             : #endif /* CONFIG_TESTING_OPTIONS */
     113          16 :         else if (os_strncmp(pos + 9, "TKIP", 4) == 0)
     114           1 :                 cred->encr_type = WPS_ENCR_TKIP;
     115          15 :         else if (os_strncmp(pos + 9, "CCMP", 4) == 0)
     116          15 :                 cred->encr_type = WPS_ENCR_AES;
     117             :         else {
     118           0 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_encr");
     119           0 :                 return -1;
     120             :         }
     121             : 
     122          18 :         pos = os_strstr(params, "new_key=");
     123          18 :         if (pos == NULL)
     124           0 :                 return 0;
     125          18 :         pos += 8;
     126          18 :         end = os_strchr(pos, ' ');
     127          18 :         if (end == NULL)
     128          18 :                 len = os_strlen(pos);
     129             :         else
     130           0 :                 len = end - pos;
     131          36 :         if ((len & 1) || len > 2 * sizeof(cred->key) ||
     132          18 :             hexstr2bin(pos, cred->key, len / 2)) {
     133           0 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_key");
     134           0 :                 return -1;
     135             :         }
     136          18 :         cred->key_len = len / 2;
     137             : 
     138          18 :         return 1;
     139             : }
     140             : 
     141             : 
     142         417 : static void * eap_wsc_init(struct eap_sm *sm)
     143             : {
     144             :         struct eap_wsc_data *data;
     145             :         const u8 *identity;
     146             :         size_t identity_len;
     147             :         int registrar;
     148             :         struct wps_config cfg;
     149             :         const char *pos, *end;
     150             :         const char *phase1;
     151             :         struct wps_context *wps;
     152             :         struct wps_credential new_ap_settings;
     153             :         int res;
     154         417 :         int nfc = 0;
     155             :         u8 pkhash[WPS_OOB_PUBKEY_HASH_LEN];
     156             : 
     157         417 :         wps = sm->wps;
     158         417 :         if (wps == NULL) {
     159           0 :                 wpa_printf(MSG_ERROR, "EAP-WSC: WPS context not available");
     160           0 :                 return NULL;
     161             :         }
     162             : 
     163         417 :         identity = eap_get_config_identity(sm, &identity_len);
     164             : 
     165         473 :         if (identity && identity_len == WSC_ID_REGISTRAR_LEN &&
     166          56 :             os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0)
     167          56 :                 registrar = 1; /* Supplicant is Registrar */
     168         722 :         else if (identity && identity_len == WSC_ID_ENROLLEE_LEN &&
     169         361 :             os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0)
     170         361 :                 registrar = 0; /* Supplicant is Enrollee */
     171             :         else {
     172           0 :                 wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity",
     173             :                                   identity, identity_len);
     174           0 :                 return NULL;
     175             :         }
     176             : 
     177         417 :         data = os_zalloc(sizeof(*data));
     178         417 :         if (data == NULL)
     179           0 :                 return NULL;
     180         417 :         data->state = registrar ? MESG : WAIT_START;
     181         417 :         data->registrar = registrar;
     182         417 :         data->wps_ctx = wps;
     183             : 
     184         417 :         os_memset(&cfg, 0, sizeof(cfg));
     185         417 :         cfg.wps = wps;
     186         417 :         cfg.registrar = registrar;
     187             : 
     188         417 :         phase1 = eap_get_config_phase1(sm);
     189         417 :         if (phase1 == NULL) {
     190           0 :                 wpa_printf(MSG_INFO, "EAP-WSC: phase1 configuration data not "
     191             :                            "set");
     192           0 :                 os_free(data);
     193           0 :                 return NULL;
     194             :         }
     195             : 
     196         417 :         pos = os_strstr(phase1, "pin=");
     197         417 :         if (pos) {
     198         298 :                 pos += 4;
     199         298 :                 cfg.pin = (const u8 *) pos;
     200        3642 :                 while (*pos != '\0' && *pos != ' ')
     201        3046 :                         pos++;
     202         298 :                 cfg.pin_len = pos - (const char *) cfg.pin;
     203         299 :                 if (cfg.pin_len == 6 &&
     204           1 :                     os_strncmp((const char *) cfg.pin, "nfc-pw", 6) == 0) {
     205           1 :                         cfg.pin = NULL;
     206           1 :                         cfg.pin_len = 0;
     207           1 :                         nfc = 1;
     208             :                 }
     209             :         } else {
     210         119 :                 pos = os_strstr(phase1, "pbc=1");
     211         119 :                 if (pos)
     212         101 :                         cfg.pbc = 1;
     213             :         }
     214             : 
     215         417 :         pos = os_strstr(phase1, "dev_pw_id=");
     216         417 :         if (pos) {
     217         260 :                 u16 id = atoi(pos + 10);
     218         260 :                 if (id == DEV_PW_NFC_CONNECTION_HANDOVER)
     219          18 :                         nfc = 1;
     220         260 :                 if (cfg.pin || id == DEV_PW_NFC_CONNECTION_HANDOVER)
     221         260 :                         cfg.dev_pw_id = id;
     222             :         }
     223             : 
     224         417 :         if (cfg.pin == NULL && !cfg.pbc && !nfc) {
     225           0 :                 wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 "
     226             :                            "configuration data");
     227           0 :                 os_free(data);
     228           0 :                 return NULL;
     229             :         }
     230             : 
     231         417 :         pos = os_strstr(phase1, " pkhash=");
     232         417 :         if (pos) {
     233             :                 size_t len;
     234          18 :                 pos += 8;
     235          18 :                 end = os_strchr(pos, ' ');
     236          18 :                 if (end)
     237           0 :                         len = end - pos;
     238             :                 else
     239          18 :                         len = os_strlen(pos);
     240          36 :                 if (len != 2 * WPS_OOB_PUBKEY_HASH_LEN ||
     241          18 :                     hexstr2bin(pos, pkhash, WPS_OOB_PUBKEY_HASH_LEN)) {
     242           0 :                         wpa_printf(MSG_INFO, "EAP-WSC: Invalid pkhash");
     243           0 :                         os_free(data);
     244           0 :                         return NULL;
     245             :                 }
     246          18 :                 cfg.peer_pubkey_hash = pkhash;
     247             :         }
     248             : 
     249         417 :         res = eap_wsc_new_ap_settings(&new_ap_settings, phase1);
     250         417 :         if (res < 0) {
     251           0 :                 os_free(data);
     252           0 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to parse new AP "
     253             :                            "settings");
     254           0 :                 return NULL;
     255             :         }
     256         417 :         if (res == 1) {
     257          18 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Provide new AP settings for "
     258             :                            "WPS");
     259          18 :                 cfg.new_ap_settings = &new_ap_settings;
     260             :         }
     261             : 
     262         417 :         data->wps = wps_init(&cfg);
     263         417 :         if (data->wps == NULL) {
     264           3 :                 os_free(data);
     265           3 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: wps_init failed");
     266           3 :                 return NULL;
     267             :         }
     268         414 :         res = eap_get_config_fragment_size(sm);
     269         414 :         if (res > 0)
     270         414 :                 data->fragment_size = res;
     271             :         else
     272           0 :                 data->fragment_size = WSC_FRAGMENT_SIZE;
     273         414 :         wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment size limit %u",
     274         414 :                    (unsigned int) data->fragment_size);
     275             : 
     276         414 :         if (registrar && cfg.pin) {
     277          54 :                 wps_registrar_add_pin(data->wps_ctx->registrar, NULL, NULL,
     278             :                                       cfg.pin, cfg.pin_len, 0);
     279             :         }
     280             : 
     281             :         /* Use reduced client timeout for WPS to avoid long wait */
     282         414 :         if (sm->ClientTimeout > 30)
     283         414 :                 sm->ClientTimeout = 30;
     284             : 
     285         414 :         return data;
     286             : }
     287             : 
     288             : 
     289         414 : static void eap_wsc_deinit(struct eap_sm *sm, void *priv)
     290             : {
     291         414 :         struct eap_wsc_data *data = priv;
     292         414 :         wpabuf_free(data->in_buf);
     293         414 :         wpabuf_free(data->out_buf);
     294         414 :         wps_deinit(data->wps);
     295         414 :         os_free(data->wps_ctx->network_key);
     296         414 :         data->wps_ctx->network_key = NULL;
     297         414 :         os_free(data);
     298         414 : }
     299             : 
     300             : 
     301        1740 : static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data,
     302             :                                          struct eap_method_ret *ret, u8 id)
     303             : {
     304             :         struct wpabuf *resp;
     305             :         u8 flags;
     306             :         size_t send_len, plen;
     307             : 
     308        1740 :         ret->ignore = FALSE;
     309        1740 :         wpa_printf(MSG_DEBUG, "EAP-WSC: Generating Response");
     310        1740 :         ret->allowNotifications = TRUE;
     311             : 
     312        1740 :         flags = 0;
     313        1740 :         send_len = wpabuf_len(data->out_buf) - data->out_used;
     314        1740 :         if (2 + send_len > data->fragment_size) {
     315          43 :                 send_len = data->fragment_size - 2;
     316          43 :                 flags |= WSC_FLAGS_MF;
     317          43 :                 if (data->out_used == 0) {
     318          14 :                         flags |= WSC_FLAGS_LF;
     319          14 :                         send_len -= 2;
     320             :                 }
     321             :         }
     322        1740 :         plen = 2 + send_len;
     323        1740 :         if (flags & WSC_FLAGS_LF)
     324          14 :                 plen += 2;
     325        1740 :         resp = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen,
     326             :                              EAP_CODE_RESPONSE, id);
     327        1740 :         if (resp == NULL)
     328           0 :                 return NULL;
     329             : 
     330        1740 :         wpabuf_put_u8(resp, data->out_op_code); /* Op-Code */
     331        1740 :         wpabuf_put_u8(resp, flags); /* Flags */
     332        1740 :         if (flags & WSC_FLAGS_LF)
     333          14 :                 wpabuf_put_be16(resp, wpabuf_len(data->out_buf));
     334             : 
     335        1740 :         wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used,
     336             :                         send_len);
     337        1740 :         data->out_used += send_len;
     338             : 
     339        1740 :         ret->methodState = METHOD_MAY_CONT;
     340        1740 :         ret->decision = DECISION_FAIL;
     341             : 
     342        1740 :         if (data->out_used == wpabuf_len(data->out_buf)) {
     343        1697 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
     344             :                            "(message sent completely)",
     345             :                            (unsigned long) send_len);
     346        1697 :                 wpabuf_free(data->out_buf);
     347        1697 :                 data->out_buf = NULL;
     348        1697 :                 data->out_used = 0;
     349        3394 :                 if ((data->state == FAIL && data->out_op_code == WSC_ACK) ||
     350        3296 :                     data->out_op_code == WSC_NACK ||
     351        1599 :                     data->out_op_code == WSC_Done) {
     352         346 :                         eap_wsc_state(data, FAIL);
     353         346 :                         ret->methodState = METHOD_DONE;
     354             :                 } else
     355        1351 :                         eap_wsc_state(data, MESG);
     356             :         } else {
     357          43 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
     358             :                            "(%lu more to send)", (unsigned long) send_len,
     359          43 :                            (unsigned long) wpabuf_len(data->out_buf) -
     360          43 :                            data->out_used);
     361          43 :                 eap_wsc_state(data, WAIT_FRAG_ACK);
     362             :         }
     363             : 
     364        1740 :         return resp;
     365             : }
     366             : 
     367             : 
     368          46 : static int eap_wsc_process_cont(struct eap_wsc_data *data,
     369             :                                 const u8 *buf, size_t len, u8 op_code)
     370             : {
     371             :         /* Process continuation of a pending message */
     372          46 :         if (op_code != data->in_op_code) {
     373           0 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in "
     374             :                            "fragment (expected %d)",
     375           0 :                            op_code, data->in_op_code);
     376           0 :                 return -1;
     377             :         }
     378             : 
     379          46 :         if (len > wpabuf_tailroom(data->in_buf)) {
     380           0 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow");
     381           0 :                 eap_wsc_state(data, FAIL);
     382           0 :                 return -1;
     383             :         }
     384             : 
     385          46 :         wpabuf_put_data(data->in_buf, buf, len);
     386          46 :         wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting "
     387             :                    "for %lu bytes more", (unsigned long) len,
     388          46 :                    (unsigned long) wpabuf_tailroom(data->in_buf));
     389             : 
     390          46 :         return 0;
     391             : }
     392             : 
     393             : 
     394          46 : static struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data,
     395             :                                                 struct eap_method_ret *ret,
     396             :                                                 u8 id, u8 flags, u8 op_code,
     397             :                                                 u16 message_length,
     398             :                                                 const u8 *buf, size_t len)
     399             : {
     400             :         /* Process a fragment that is not the last one of the message */
     401          46 :         if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) {
     402           0 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length field in a "
     403             :                            "fragmented packet");
     404           0 :                 ret->ignore = TRUE;
     405           0 :                 return NULL;
     406             :         }
     407             : 
     408          46 :         if (data->in_buf == NULL) {
     409             :                 /* First fragment of the message */
     410          12 :                 data->in_buf = wpabuf_alloc(message_length);
     411          12 :                 if (data->in_buf == NULL) {
     412           0 :                         wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for "
     413             :                                    "message");
     414           0 :                         ret->ignore = TRUE;
     415           0 :                         return NULL;
     416             :                 }
     417          12 :                 data->in_op_code = op_code;
     418          12 :                 wpabuf_put_data(data->in_buf, buf, len);
     419          12 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in first "
     420             :                            "fragment, waiting for %lu bytes more",
     421             :                            (unsigned long) len,
     422          12 :                            (unsigned long) wpabuf_tailroom(data->in_buf));
     423             :         }
     424             : 
     425          46 :         return eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE);
     426             : }
     427             : 
     428             : 
     429        1820 : static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv,
     430             :                                        struct eap_method_ret *ret,
     431             :                                        const struct wpabuf *reqData)
     432             : {
     433        1820 :         struct eap_wsc_data *data = priv;
     434             :         const u8 *start, *pos, *end;
     435             :         size_t len;
     436             :         u8 op_code, flags, id;
     437        1820 :         u16 message_length = 0;
     438             :         enum wps_process_res res;
     439             :         struct wpabuf tmpbuf;
     440             :         struct wpabuf *r;
     441             : 
     442        1820 :         pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, reqData,
     443             :                                &len);
     444        1820 :         if (pos == NULL || len < 2) {
     445           0 :                 ret->ignore = TRUE;
     446           0 :                 return NULL;
     447             :         }
     448             : 
     449        1820 :         id = eap_get_id(reqData);
     450             : 
     451        1820 :         start = pos;
     452        1820 :         end = start + len;
     453             : 
     454        1820 :         op_code = *pos++;
     455        1820 :         flags = *pos++;
     456        1820 :         if (flags & WSC_FLAGS_LF) {
     457          12 :                 if (end - pos < 2) {
     458           0 :                         wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow");
     459           0 :                         ret->ignore = TRUE;
     460           0 :                         return NULL;
     461             :                 }
     462          12 :                 message_length = WPA_GET_BE16(pos);
     463          12 :                 pos += 2;
     464             : 
     465          12 :                 if (message_length < end - pos || message_length > 50000) {
     466           0 :                         wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message "
     467             :                                    "Length");
     468           0 :                         ret->ignore = TRUE;
     469           0 :                         return NULL;
     470             :                 }
     471             :         }
     472             : 
     473        1820 :         wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d "
     474             :                    "Flags 0x%x Message Length %d",
     475             :                    op_code, flags, message_length);
     476             : 
     477        1820 :         if (data->state == WAIT_FRAG_ACK) {
     478          43 :                 if (op_code != WSC_FRAG_ACK) {
     479           0 :                         wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d "
     480             :                                    "in WAIT_FRAG_ACK state", op_code);
     481           0 :                         ret->ignore = TRUE;
     482           0 :                         return NULL;
     483             :                 }
     484          43 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged");
     485          43 :                 eap_wsc_state(data, MESG);
     486          43 :                 return eap_wsc_build_msg(data, ret, id);
     487             :         }
     488             : 
     489        1777 :         if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG &&
     490         361 :             op_code != WSC_Done && op_code != WSC_Start) {
     491           1 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d",
     492             :                            op_code);
     493           1 :                 ret->ignore = TRUE;
     494           1 :                 return NULL;
     495             :         }
     496             : 
     497        1776 :         if (data->state == WAIT_START) {
     498         359 :                 if (op_code != WSC_Start) {
     499           0 :                         wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d "
     500             :                                    "in WAIT_START state", op_code);
     501           0 :                         ret->ignore = TRUE;
     502           0 :                         return NULL;
     503             :                 }
     504         359 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Received start");
     505         359 :                 eap_wsc_state(data, MESG);
     506             :                 /* Start message has empty payload, skip processing */
     507         359 :                 goto send_msg;
     508        1417 :         } else if (op_code == WSC_Start) {
     509           1 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d",
     510             :                            op_code);
     511           1 :                 ret->ignore = TRUE;
     512           1 :                 return NULL;
     513             :         }
     514             : 
     515        1462 :         if (data->in_buf &&
     516          46 :             eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) {
     517           0 :                 ret->ignore = TRUE;
     518           0 :                 return NULL;
     519             :         }
     520             : 
     521        1416 :         if (flags & WSC_FLAGS_MF) {
     522          46 :                 return eap_wsc_process_fragment(data, ret, id, flags, op_code,
     523             :                                                 message_length, pos,
     524          46 :                                                 end - pos);
     525             :         }
     526             : 
     527        1370 :         if (data->in_buf == NULL) {
     528             :                 /* Wrap unfragmented messages as wpabuf without extra copy */
     529        1358 :                 wpabuf_set(&tmpbuf, pos, end - pos);
     530        1358 :                 data->in_buf = &tmpbuf;
     531             :         }
     532             : 
     533        1370 :         res = wps_process_msg(data->wps, op_code, data->in_buf);
     534        1370 :         switch (res) {
     535             :         case WPS_DONE:
     536           6 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed "
     537             :                            "successfully - wait for EAP failure");
     538           6 :                 eap_wsc_state(data, FAIL);
     539           6 :                 break;
     540             :         case WPS_CONTINUE:
     541        1324 :                 eap_wsc_state(data, MESG);
     542        1324 :                 break;
     543             :         case WPS_FAILURE:
     544             :         case WPS_PENDING:
     545          40 :                 wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed");
     546          40 :                 eap_wsc_state(data, FAIL);
     547          40 :                 break;
     548             :         }
     549             : 
     550        1370 :         if (data->in_buf != &tmpbuf)
     551          12 :                 wpabuf_free(data->in_buf);
     552        1370 :         data->in_buf = NULL;
     553             : 
     554             : send_msg:
     555        1729 :         if (data->out_buf == NULL) {
     556        1729 :                 data->out_buf = wps_get_msg(data->wps, &data->out_op_code);
     557        1729 :                 if (data->out_buf == NULL) {
     558          32 :                         wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to receive "
     559             :                                    "message from WPS");
     560          32 :                         eap_wsc_state(data, FAIL);
     561          32 :                         ret->methodState = METHOD_DONE;
     562          32 :                         ret->decision = DECISION_FAIL;
     563          32 :                         return NULL;
     564             :                 }
     565        1697 :                 data->out_used = 0;
     566             :         }
     567             : 
     568        1697 :         eap_wsc_state(data, MESG);
     569        1697 :         r = eap_wsc_build_msg(data, ret, id);
     570        1697 :         if (data->state == FAIL && ret->methodState == METHOD_DONE) {
     571             :                 /* Use reduced client timeout for WPS to avoid long wait */
     572         343 :                 if (sm->ClientTimeout > 2)
     573         343 :                         sm->ClientTimeout = 2;
     574             :         }
     575        1697 :         return r;
     576             : }
     577             : 
     578             : 
     579          49 : int eap_peer_wsc_register(void)
     580             : {
     581             :         struct eap_method *eap;
     582             :         int ret;
     583             : 
     584          49 :         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
     585             :                                     EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC,
     586             :                                     "WSC");
     587          49 :         if (eap == NULL)
     588           0 :                 return -1;
     589             : 
     590          49 :         eap->init = eap_wsc_init;
     591          49 :         eap->deinit = eap_wsc_deinit;
     592          49 :         eap->process = eap_wsc_process;
     593             : 
     594          49 :         ret = eap_peer_method_register(eap);
     595          49 :         if (ret)
     596           0 :                 eap_peer_method_free(eap);
     597          49 :         return ret;
     598             : }

Generated by: LCOV version 1.10