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

Generated by: LCOV version 1.10