LCOV - code coverage report
Current view: top level - wpa_supplicant - wpas_glue.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1401264779 Lines: 354 442 80.1 %
Date: 2014-05-28 Functions: 43 43 100.0 %

          Line data    Source code
       1             : /*
       2             :  * WPA Supplicant - Glue code to setup EAPOL and RSN modules
       3             :  * Copyright (c) 2003-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 "eapol_supp/eapol_supp_sm.h"
      13             : #include "rsn_supp/wpa.h"
      14             : #include "eloop.h"
      15             : #include "config.h"
      16             : #include "l2_packet/l2_packet.h"
      17             : #include "common/wpa_common.h"
      18             : #include "wpa_supplicant_i.h"
      19             : #include "driver_i.h"
      20             : #include "rsn_supp/pmksa_cache.h"
      21             : #include "sme.h"
      22             : #include "common/ieee802_11_defs.h"
      23             : #include "common/wpa_ctrl.h"
      24             : #include "wpas_glue.h"
      25             : #include "wps_supplicant.h"
      26             : #include "bss.h"
      27             : #include "scan.h"
      28             : #include "notify.h"
      29             : #include "wpas_kay.h"
      30             : 
      31             : 
      32             : #ifndef CONFIG_NO_CONFIG_BLOBS
      33             : #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
      34           7 : static void wpa_supplicant_set_config_blob(void *ctx,
      35             :                                            struct wpa_config_blob *blob)
      36             : {
      37           7 :         struct wpa_supplicant *wpa_s = ctx;
      38           7 :         wpa_config_set_blob(wpa_s->conf, blob);
      39           7 :         if (wpa_s->conf->update_config) {
      40           0 :                 int ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
      41           0 :                 if (ret) {
      42           0 :                         wpa_printf(MSG_DEBUG, "Failed to update config after "
      43             :                                    "blob set");
      44             :                 }
      45             :         }
      46           7 : }
      47             : 
      48             : 
      49             : static const struct wpa_config_blob *
      50          20 : wpa_supplicant_get_config_blob(void *ctx, const char *name)
      51             : {
      52          20 :         struct wpa_supplicant *wpa_s = ctx;
      53          20 :         return wpa_config_get_blob(wpa_s->conf, name);
      54             : }
      55             : #endif /* defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) */
      56             : #endif /* CONFIG_NO_CONFIG_BLOBS */
      57             : 
      58             : 
      59             : #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
      60        4308 : static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
      61             :                             const void *data, u16 data_len,
      62             :                             size_t *msg_len, void **data_pos)
      63             : {
      64             :         struct ieee802_1x_hdr *hdr;
      65             : 
      66        4308 :         *msg_len = sizeof(*hdr) + data_len;
      67        4308 :         hdr = os_malloc(*msg_len);
      68        4308 :         if (hdr == NULL)
      69           0 :                 return NULL;
      70             : 
      71        4308 :         hdr->version = wpa_s->conf->eapol_version;
      72        4308 :         hdr->type = type;
      73        4308 :         hdr->length = host_to_be16(data_len);
      74             : 
      75        4308 :         if (data)
      76        3020 :                 os_memcpy(hdr + 1, data, data_len);
      77             :         else
      78        1288 :                 os_memset(hdr + 1, 0, data_len);
      79             : 
      80        4308 :         if (data_pos)
      81        1287 :                 *data_pos = hdr + 1;
      82             : 
      83        4308 :         return (u8 *) hdr;
      84             : }
      85             : 
      86             : 
      87             : /**
      88             :  * wpa_ether_send - Send Ethernet frame
      89             :  * @wpa_s: Pointer to wpa_supplicant data
      90             :  * @dest: Destination MAC address
      91             :  * @proto: Ethertype in host byte order
      92             :  * @buf: Frame payload starting from IEEE 802.1X header
      93             :  * @len: Frame payload length
      94             :  * Returns: >=0 on success, <0 on failure
      95             :  */
      96        4304 : static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
      97             :                           u16 proto, const u8 *buf, size_t len)
      98             : {
      99        4304 :         if (wpa_s->l2) {
     100        4304 :                 return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
     101             :         }
     102             : 
     103           0 :         return wpa_drv_send_eapol(wpa_s, dest, proto, buf, len);
     104             : }
     105             : #endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */
     106             : 
     107             : 
     108             : #ifdef IEEE8021X_EAPOL
     109             : 
     110             : /**
     111             :  * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator
     112             :  * @ctx: Pointer to wpa_supplicant data (wpa_s)
     113             :  * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*)
     114             :  * @buf: EAPOL payload (after IEEE 802.1X header)
     115             :  * @len: EAPOL payload length
     116             :  * Returns: >=0 on success, <0 on failure
     117             :  *
     118             :  * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame
     119             :  * to the current Authenticator.
     120             :  */
     121        3017 : static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf,
     122             :                                      size_t len)
     123             : {
     124        3017 :         struct wpa_supplicant *wpa_s = ctx;
     125             :         u8 *msg, *dst, bssid[ETH_ALEN];
     126             :         size_t msglen;
     127             :         int res;
     128             : 
     129             :         /* TODO: could add l2_packet_sendmsg that allows fragments to avoid
     130             :          * extra copy here */
     131             : 
     132        6033 :         if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
     133        3016 :             wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
     134             :                 /* Current SSID is not using IEEE 802.1X/EAP, so drop possible
     135             :                  * EAPOL frames (mainly, EAPOL-Start) from EAPOL state
     136             :                  * machines. */
     137           1 :                 wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X "
     138             :                            "mode (type=%d len=%lu)", type,
     139             :                            (unsigned long) len);
     140           1 :                 return -1;
     141             :         }
     142             : 
     143        3016 :         if (pmksa_cache_get_current(wpa_s->wpa) &&
     144             :             type == IEEE802_1X_TYPE_EAPOL_START) {
     145             :                 /* Trying to use PMKSA caching - do not send EAPOL-Start frames
     146             :                  * since they will trigger full EAPOL authentication. */
     147           0 :                 wpa_printf(MSG_DEBUG, "RSN: PMKSA caching - do not send "
     148             :                            "EAPOL-Start");
     149           0 :                 return -1;
     150             :         }
     151             : 
     152        3016 :         if (is_zero_ether_addr(wpa_s->bssid)) {
     153           0 :                 wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an "
     154             :                            "EAPOL frame");
     155           0 :                 if (wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
     156           0 :                     !is_zero_ether_addr(bssid)) {
     157           0 :                         dst = bssid;
     158           0 :                         wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR
     159             :                                    " from the driver as the EAPOL destination",
     160           0 :                                    MAC2STR(dst));
     161             :                 } else {
     162           0 :                         dst = wpa_s->last_eapol_src;
     163           0 :                         wpa_printf(MSG_DEBUG, "Using the source address of the"
     164             :                                    " last received EAPOL frame " MACSTR " as "
     165             :                                    "the EAPOL destination",
     166           0 :                                    MAC2STR(dst));
     167             :                 }
     168             :         } else {
     169             :                 /* BSSID was already set (from (Re)Assoc event, so use it as
     170             :                  * the EAPOL destination. */
     171        3016 :                 dst = wpa_s->bssid;
     172             :         }
     173             : 
     174        3016 :         msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL);
     175        3016 :         if (msg == NULL)
     176           0 :                 return -1;
     177             : 
     178        3016 :         wpa_printf(MSG_DEBUG, "TX EAPOL: dst=" MACSTR, MAC2STR(dst));
     179        3016 :         wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen);
     180        3016 :         res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen);
     181        3016 :         os_free(msg);
     182        3016 :         return res;
     183             : }
     184             : 
     185             : 
     186             : /**
     187             :  * wpa_eapol_set_wep_key - set WEP key for the driver
     188             :  * @ctx: Pointer to wpa_supplicant data (wpa_s)
     189             :  * @unicast: 1 = individual unicast key, 0 = broadcast key
     190             :  * @keyidx: WEP key index (0..3)
     191             :  * @key: Pointer to key data
     192             :  * @keylen: Key length in bytes
     193             :  * Returns: 0 on success or < 0 on error.
     194             :  */
     195           4 : static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
     196             :                                  const u8 *key, size_t keylen)
     197             : {
     198           4 :         struct wpa_supplicant *wpa_s = ctx;
     199           4 :         if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
     200           4 :                 int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 :
     201             :                         WPA_CIPHER_WEP104;
     202           4 :                 if (unicast)
     203           2 :                         wpa_s->pairwise_cipher = cipher;
     204             :                 else
     205           2 :                         wpa_s->group_cipher = cipher;
     206             :         }
     207           4 :         return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
     208             :                                unicast ? wpa_s->bssid : NULL,
     209             :                                keyidx, unicast, NULL, 0, key, keylen);
     210             : }
     211             : 
     212             : 
     213          12 : static void wpa_supplicant_aborted_cached(void *ctx)
     214             : {
     215          12 :         struct wpa_supplicant *wpa_s = ctx;
     216          12 :         wpa_sm_aborted_cached(wpa_s->wpa);
     217          12 : }
     218             : 
     219             : 
     220         886 : static const char * result_str(enum eapol_supp_result result)
     221             : {
     222         886 :         switch (result) {
     223             :         case EAPOL_SUPP_RESULT_FAILURE:
     224         244 :                 return "FAILURE";
     225             :         case EAPOL_SUPP_RESULT_SUCCESS:
     226         638 :                 return "SUCCESS";
     227             :         case EAPOL_SUPP_RESULT_EXPECTED_FAILURE:
     228           4 :                 return "EXPECTED_FAILURE";
     229             :         }
     230           0 :         return "?";
     231             : }
     232             : 
     233             : 
     234         886 : static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol,
     235             :                                     enum eapol_supp_result result,
     236             :                                     void *ctx)
     237             : {
     238         886 :         struct wpa_supplicant *wpa_s = ctx;
     239             :         int res, pmk_len;
     240             :         u8 pmk[PMK_LEN];
     241             : 
     242         886 :         wpa_printf(MSG_DEBUG, "EAPOL authentication completed - result=%s",
     243             :                    result_str(result));
     244             : 
     245         886 :         if (wpas_wps_eapol_cb(wpa_s) > 0)
     246        1080 :                 return;
     247             : 
     248         692 :         wpa_s->eap_expected_failure = result ==
     249             :                 EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
     250             : 
     251         692 :         if (result != EAPOL_SUPP_RESULT_SUCCESS) {
     252             :                 /*
     253             :                  * Make sure we do not get stuck here waiting for long EAPOL
     254             :                  * timeout if the AP does not disconnect in case of
     255             :                  * authentication failure.
     256             :                  */
     257          54 :                 wpa_supplicant_req_auth_timeout(wpa_s, 2, 0);
     258             :         } else {
     259         638 :                 ieee802_1x_notify_create_actor(wpa_s, wpa_s->last_eapol_src);
     260             :         }
     261             : 
     262        1330 :         if (result != EAPOL_SUPP_RESULT_SUCCESS ||
     263         638 :             !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
     264         692 :                 return;
     265             : 
     266           0 :         if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
     267           0 :                 return;
     268             : 
     269           0 :         wpa_printf(MSG_DEBUG, "Configure PMK for driver-based RSN 4-way "
     270             :                    "handshake");
     271             : 
     272           0 :         pmk_len = PMK_LEN;
     273           0 :         if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
     274             : #ifdef CONFIG_IEEE80211R
     275             :                 u8 buf[2 * PMK_LEN];
     276           0 :                 wpa_printf(MSG_DEBUG, "RSN: Use FT XXKey as PMK for "
     277             :                            "driver-based 4-way hs and FT");
     278           0 :                 res = eapol_sm_get_key(eapol, buf, 2 * PMK_LEN);
     279           0 :                 if (res == 0) {
     280           0 :                         os_memcpy(pmk, buf + PMK_LEN, PMK_LEN);
     281           0 :                         os_memset(buf, 0, sizeof(buf));
     282             :                 }
     283             : #else /* CONFIG_IEEE80211R */
     284             :                 res = -1;
     285             : #endif /* CONFIG_IEEE80211R */
     286             :         } else {
     287           0 :                 res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
     288           0 :                 if (res) {
     289             :                         /*
     290             :                          * EAP-LEAP is an exception from other EAP methods: it
     291             :                          * uses only 16-byte PMK.
     292             :                          */
     293           0 :                         res = eapol_sm_get_key(eapol, pmk, 16);
     294           0 :                         pmk_len = 16;
     295             :                 }
     296             :         }
     297             : 
     298           0 :         if (res) {
     299           0 :                 wpa_printf(MSG_DEBUG, "Failed to get PMK from EAPOL state "
     300             :                            "machines");
     301           0 :                 return;
     302             :         }
     303             : 
     304           0 :         wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way "
     305             :                         "handshake", pmk, pmk_len);
     306             : 
     307           0 :         if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk,
     308             :                             pmk_len)) {
     309           0 :                 wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver");
     310             :         }
     311             : 
     312           0 :         wpa_supplicant_cancel_scan(wpa_s);
     313           0 :         wpa_supplicant_cancel_auth_timeout(wpa_s);
     314           0 :         wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
     315             : 
     316             : }
     317             : 
     318             : 
     319           4 : static void wpa_supplicant_notify_eapol_done(void *ctx)
     320             : {
     321           4 :         struct wpa_supplicant *wpa_s = ctx;
     322           4 :         wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete");
     323           4 :         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
     324           0 :                 wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE);
     325             :         } else {
     326           4 :                 wpa_supplicant_cancel_auth_timeout(wpa_s);
     327           4 :                 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
     328             :         }
     329           4 : }
     330             : 
     331             : #endif /* IEEE8021X_EAPOL */
     332             : 
     333             : 
     334             : #ifndef CONFIG_NO_WPA
     335             : 
     336           4 : static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
     337             : {
     338           4 :         int ret = 0;
     339           4 :         struct wpa_bss *curr = NULL, *bss;
     340           4 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
     341             :         const u8 *ie;
     342             : 
     343           5 :         dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
     344           5 :                 if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0)
     345           1 :                         continue;
     346           8 :                 if (ssid == NULL ||
     347           8 :                     ((bss->ssid_len == ssid->ssid_len &&
     348           4 :                       os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) == 0) ||
     349           0 :                      ssid->ssid_len == 0)) {
     350           4 :                         curr = bss;
     351           4 :                         break;
     352             :                 }
     353             :         }
     354             : 
     355           4 :         if (curr) {
     356           4 :                 ie = wpa_bss_get_vendor_ie(curr, WPA_IE_VENDOR_TYPE);
     357           4 :                 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
     358           0 :                         ret = -1;
     359             : 
     360           4 :                 ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
     361           4 :                 if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
     362           0 :                         ret = -1;
     363             :         } else {
     364           0 :                 ret = -1;
     365             :         }
     366             : 
     367           4 :         return ret;
     368             : }
     369             : 
     370             : 
     371           4 : static int wpa_supplicant_get_beacon_ie(void *ctx)
     372             : {
     373           4 :         struct wpa_supplicant *wpa_s = ctx;
     374           4 :         if (wpa_get_beacon_ie(wpa_s) == 0) {
     375           4 :                 return 0;
     376             :         }
     377             : 
     378             :         /* No WPA/RSN IE found in the cached scan results. Try to get updated
     379             :          * scan results from the driver. */
     380           0 :         if (wpa_supplicant_update_scan_results(wpa_s) < 0)
     381           0 :                 return -1;
     382             : 
     383           0 :         return wpa_get_beacon_ie(wpa_s);
     384             : }
     385             : 
     386             : 
     387        1292 : static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type,
     388             :                              const void *data, u16 data_len,
     389             :                              size_t *msg_len, void **data_pos)
     390             : {
     391        1292 :         return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos);
     392             : }
     393             : 
     394             : 
     395        1288 : static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto,
     396             :                            const u8 *buf, size_t len)
     397             : {
     398        1288 :         return wpa_ether_send(wpa_s, dest, proto, buf, len);
     399             : }
     400             : 
     401             : 
     402         638 : static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s)
     403             : {
     404         638 :         wpa_supplicant_cancel_auth_timeout(wpa_s);
     405         638 : }
     406             : 
     407             : 
     408        2527 : static void _wpa_supplicant_set_state(void *wpa_s, enum wpa_states state)
     409             : {
     410        2527 :         wpa_supplicant_set_state(wpa_s, state);
     411        2527 : }
     412             : 
     413             : 
     414             : /**
     415             :  * wpa_supplicant_get_state - Get the connection state
     416             :  * @wpa_s: Pointer to wpa_supplicant data
     417             :  * Returns: The current connection state (WPA_*)
     418             :  */
     419        1098 : static enum wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s)
     420             : {
     421        1098 :         return wpa_s->wpa_state;
     422             : }
     423             : 
     424             : 
     425        1098 : static enum wpa_states _wpa_supplicant_get_state(void *wpa_s)
     426             : {
     427        1098 :         return wpa_supplicant_get_state(wpa_s);
     428             : }
     429             : 
     430             : 
     431          28 : static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code)
     432             : {
     433          28 :         wpa_supplicant_deauthenticate(wpa_s, reason_code);
     434             :         /* Schedule a scan to make sure we continue looking for networks */
     435          28 :         wpa_supplicant_req_scan(wpa_s, 5, 0);
     436          28 : }
     437             : 
     438             : 
     439         640 : static void * wpa_supplicant_get_network_ctx(void *wpa_s)
     440             : {
     441         640 :         return wpa_supplicant_get_ssid(wpa_s);
     442             : }
     443             : 
     444             : 
     445          12 : static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid)
     446             : {
     447          12 :         struct wpa_supplicant *wpa_s = ctx;
     448          12 :         return wpa_drv_get_bssid(wpa_s, bssid);
     449             : }
     450             : 
     451             : 
     452        1401 : static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg,
     453             :                                   const u8 *addr, int key_idx, int set_tx,
     454             :                                   const u8 *seq, size_t seq_len,
     455             :                                   const u8 *key, size_t key_len)
     456             : {
     457        1401 :         struct wpa_supplicant *wpa_s = _wpa_s;
     458        1401 :         if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) {
     459             :                 /* Clear the MIC error counter when setting a new PTK. */
     460          15 :                 wpa_s->mic_errors_seen = 0;
     461             :         }
     462             : #ifdef CONFIG_TESTING_GET_GTK
     463             :         if (key_idx > 0 && addr && is_broadcast_ether_addr(addr) &&
     464             :             alg != WPA_ALG_NONE && key_len <= sizeof(wpa_s->last_gtk)) {
     465             :                 os_memcpy(wpa_s->last_gtk, key, key_len);
     466             :                 wpa_s->last_gtk_len = key_len;
     467             :         }
     468             : #endif /* CONFIG_TESTING_GET_GTK */
     469        1401 :         return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
     470             :                                key, key_len);
     471             : }
     472             : 
     473             : 
     474        1240 : static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr,
     475             :                                              int protection_type,
     476             :                                              int key_type)
     477             : {
     478        1240 :         return wpa_drv_mlme_setprotection(wpa_s, addr, protection_type,
     479             :                                           key_type);
     480             : }
     481             : 
     482             : 
     483         274 : static int wpa_supplicant_add_pmkid(void *wpa_s,
     484             :                                     const u8 *bssid, const u8 *pmkid)
     485             : {
     486         274 :         return wpa_drv_add_pmkid(wpa_s, bssid, pmkid);
     487             : }
     488             : 
     489             : 
     490         274 : static int wpa_supplicant_remove_pmkid(void *wpa_s,
     491             :                                        const u8 *bssid, const u8 *pmkid)
     492             : {
     493         274 :         return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid);
     494             : }
     495             : 
     496             : 
     497             : #ifdef CONFIG_IEEE80211R
     498         106 : static int wpa_supplicant_update_ft_ies(void *ctx, const u8 *md,
     499             :                                         const u8 *ies, size_t ies_len)
     500             : {
     501         106 :         struct wpa_supplicant *wpa_s = ctx;
     502         106 :         if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
     503         106 :                 return sme_update_ft_ies(wpa_s, md, ies, ies_len);
     504           0 :         return wpa_drv_update_ft_ies(wpa_s, md, ies, ies_len);
     505             : }
     506             : 
     507             : 
     508          13 : static int wpa_supplicant_send_ft_action(void *ctx, u8 action,
     509             :                                          const u8 *target_ap,
     510             :                                          const u8 *ies, size_t ies_len)
     511             : {
     512          13 :         struct wpa_supplicant *wpa_s = ctx;
     513          13 :         return wpa_drv_send_ft_action(wpa_s, action, target_ap, ies, ies_len);
     514             : }
     515             : 
     516             : 
     517          20 : static int wpa_supplicant_mark_authenticated(void *ctx, const u8 *target_ap)
     518             : {
     519          20 :         struct wpa_supplicant *wpa_s = ctx;
     520             :         struct wpa_driver_auth_params params;
     521             :         struct wpa_bss *bss;
     522             : 
     523          20 :         bss = wpa_bss_get_bssid(wpa_s, target_ap);
     524          20 :         if (bss == NULL)
     525           0 :                 return -1;
     526             : 
     527          20 :         os_memset(&params, 0, sizeof(params));
     528          20 :         params.bssid = target_ap;
     529          20 :         params.freq = bss->freq;
     530          20 :         params.ssid = bss->ssid;
     531          20 :         params.ssid_len = bss->ssid_len;
     532          20 :         params.auth_alg = WPA_AUTH_ALG_FT;
     533          20 :         params.local_state_change = 1;
     534          20 :         return wpa_drv_authenticate(wpa_s, &params);
     535             : }
     536             : #endif /* CONFIG_IEEE80211R */
     537             : 
     538             : 
     539             : #ifdef CONFIG_TDLS
     540             : 
     541          69 : static int wpa_supplicant_tdls_get_capa(void *ctx, int *tdls_supported,
     542             :                                         int *tdls_ext_setup)
     543             : {
     544          69 :         struct wpa_supplicant *wpa_s = ctx;
     545             : 
     546          69 :         *tdls_supported = 0;
     547          69 :         *tdls_ext_setup = 0;
     548             : 
     549          69 :         if (!wpa_s->drv_capa_known)
     550           0 :                 return -1;
     551             : 
     552          69 :         if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)
     553          69 :                 *tdls_supported = 1;
     554             : 
     555          69 :         if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP)
     556          69 :                 *tdls_ext_setup = 1;
     557             : 
     558          69 :         return 0;
     559             : }
     560             : 
     561             : 
     562         127 : static int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst,
     563             :                                          u8 action_code, u8 dialog_token,
     564             :                                          u16 status_code, u32 peer_capab,
     565             :                                          const u8 *buf, size_t len)
     566             : {
     567         127 :         struct wpa_supplicant *wpa_s = ctx;
     568         127 :         return wpa_drv_send_tdls_mgmt(wpa_s, dst, action_code, dialog_token,
     569             :                                       status_code, peer_capab, buf, len);
     570             : }
     571             : 
     572             : 
     573         145 : static int wpa_supplicant_tdls_oper(void *ctx, int oper, const u8 *peer)
     574             : {
     575         145 :         struct wpa_supplicant *wpa_s = ctx;
     576         145 :         return wpa_drv_tdls_oper(wpa_s, oper, peer);
     577             : }
     578             : 
     579             : 
     580          87 : static int wpa_supplicant_tdls_peer_addset(
     581             :         void *ctx, const u8 *peer, int add, u16 aid, u16 capability,
     582             :         const u8 *supp_rates, size_t supp_rates_len,
     583             :         const struct ieee80211_ht_capabilities *ht_capab,
     584             :         const struct ieee80211_vht_capabilities *vht_capab,
     585             :         u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
     586             :         const u8 *supp_channels, size_t supp_channels_len,
     587             :         const u8 *supp_oper_classes, size_t supp_oper_classes_len)
     588             : {
     589          87 :         struct wpa_supplicant *wpa_s = ctx;
     590             :         struct hostapd_sta_add_params params;
     591             : 
     592          87 :         os_memset(&params, 0, sizeof(params));
     593             : 
     594          87 :         params.addr = peer;
     595          87 :         params.aid = aid;
     596          87 :         params.capability = capability;
     597          87 :         params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED;
     598             : 
     599             :         /*
     600             :          * TDLS Setup frames do not contain WMM IEs, hence need to depend on
     601             :          * qosinfo to check if the peer is WMM capable.
     602             :          */
     603          87 :         if (qosinfo)
     604           0 :                 params.flags |= WPA_STA_WMM;
     605             : 
     606          87 :         params.ht_capabilities = ht_capab;
     607          87 :         params.vht_capabilities = vht_capab;
     608          87 :         params.qosinfo = qosinfo;
     609          87 :         params.listen_interval = 0;
     610          87 :         params.supp_rates = supp_rates;
     611          87 :         params.supp_rates_len = supp_rates_len;
     612          87 :         params.set = !add;
     613          87 :         params.ext_capab = ext_capab;
     614          87 :         params.ext_capab_len = ext_capab_len;
     615          87 :         params.supp_channels = supp_channels;
     616          87 :         params.supp_channels_len = supp_channels_len;
     617          87 :         params.supp_oper_classes = supp_oper_classes;
     618          87 :         params.supp_oper_classes_len = supp_oper_classes_len;
     619             : 
     620          87 :         return wpa_drv_sta_add(wpa_s, &params);
     621             : }
     622             : 
     623             : #endif /* CONFIG_TDLS */
     624             : 
     625             : #endif /* CONFIG_NO_WPA */
     626             : 
     627             : 
     628          14 : enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field)
     629             : {
     630          14 :         if (os_strcmp(field, "IDENTITY") == 0)
     631           1 :                 return WPA_CTRL_REQ_EAP_IDENTITY;
     632          13 :         else if (os_strcmp(field, "PASSWORD") == 0)
     633           5 :                 return WPA_CTRL_REQ_EAP_PASSWORD;
     634           8 :         else if (os_strcmp(field, "NEW_PASSWORD") == 0)
     635           0 :                 return WPA_CTRL_REQ_EAP_NEW_PASSWORD;
     636           8 :         else if (os_strcmp(field, "PIN") == 0)
     637           0 :                 return WPA_CTRL_REQ_EAP_PIN;
     638           8 :         else if (os_strcmp(field, "OTP") == 0)
     639           1 :                 return WPA_CTRL_REQ_EAP_OTP;
     640           7 :         else if (os_strcmp(field, "PASSPHRASE") == 0)
     641           1 :                 return WPA_CTRL_REQ_EAP_PASSPHRASE;
     642           6 :         else if (os_strcmp(field, "SIM") == 0)
     643           6 :                 return WPA_CTRL_REQ_SIM;
     644           0 :         return WPA_CTRL_REQ_UNKNOWN;
     645             : }
     646             : 
     647             : 
     648          15 : const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
     649             :                                                const char *default_txt,
     650             :                                                const char **txt)
     651             : {
     652          15 :         const char *ret = NULL;
     653             : 
     654          15 :         *txt = default_txt;
     655             : 
     656          15 :         switch (field) {
     657             :         case WPA_CTRL_REQ_EAP_IDENTITY:
     658           1 :                 *txt = "Identity";
     659           1 :                 ret = "IDENTITY";
     660           1 :                 break;
     661             :         case WPA_CTRL_REQ_EAP_PASSWORD:
     662           6 :                 *txt = "Password";
     663           6 :                 ret = "PASSWORD";
     664           6 :                 break;
     665             :         case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
     666           0 :                 *txt = "New Password";
     667           0 :                 ret = "NEW_PASSWORD";
     668           0 :                 break;
     669             :         case WPA_CTRL_REQ_EAP_PIN:
     670           0 :                 *txt = "PIN";
     671           0 :                 ret = "PIN";
     672           0 :                 break;
     673             :         case WPA_CTRL_REQ_EAP_OTP:
     674           1 :                 ret = "OTP";
     675           1 :                 break;
     676             :         case WPA_CTRL_REQ_EAP_PASSPHRASE:
     677           1 :                 *txt = "Private key passphrase";
     678           1 :                 ret = "PASSPHRASE";
     679           1 :                 break;
     680             :         case WPA_CTRL_REQ_SIM:
     681           6 :                 ret = "SIM";
     682           6 :                 break;
     683             :         default:
     684           0 :                 break;
     685             :         }
     686             : 
     687             :         /* txt needs to be something */
     688          15 :         if (*txt == NULL) {
     689           0 :                 wpa_printf(MSG_WARNING, "No message for request %d", field);
     690           0 :                 ret = NULL;
     691             :         }
     692             : 
     693          15 :         return ret;
     694             : }
     695             : 
     696             : #ifdef IEEE8021X_EAPOL
     697             : #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
     698          15 : static void wpa_supplicant_eap_param_needed(void *ctx,
     699             :                                             enum wpa_ctrl_req_type field,
     700             :                                             const char *default_txt)
     701             : {
     702          15 :         struct wpa_supplicant *wpa_s = ctx;
     703          15 :         struct wpa_ssid *ssid = wpa_s->current_ssid;
     704          15 :         const char *field_name, *txt = NULL;
     705             :         char *buf;
     706             :         size_t buflen;
     707             :         int len;
     708             : 
     709          15 :         if (ssid == NULL)
     710           0 :                 return;
     711             : 
     712          15 :         wpas_notify_network_request(wpa_s, ssid, field, default_txt);
     713             : 
     714          15 :         field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt,
     715             :                                                        &txt);
     716          15 :         if (field_name == NULL) {
     717           0 :                 wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed",
     718             :                            field);
     719           0 :                 return;
     720             :         }
     721             : 
     722          15 :         wpas_notify_eap_status(wpa_s, "eap parameter needed", field_name);
     723             : 
     724          15 :         buflen = 100 + os_strlen(txt) + ssid->ssid_len;
     725          15 :         buf = os_malloc(buflen);
     726          15 :         if (buf == NULL)
     727           0 :                 return;
     728          15 :         len = os_snprintf(buf, buflen,
     729             :                           WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
     730             :                           field_name, ssid->id, txt);
     731          15 :         if (len < 0 || (size_t) len >= buflen) {
     732           0 :                 os_free(buf);
     733           0 :                 return;
     734             :         }
     735          15 :         if (ssid->ssid && buflen > len + ssid->ssid_len) {
     736          15 :                 os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
     737          15 :                 len += ssid->ssid_len;
     738          15 :                 buf[len] = '\0';
     739             :         }
     740          15 :         buf[buflen - 1] = '\0';
     741          15 :         wpa_msg(wpa_s, MSG_INFO, "%s", buf);
     742          15 :         os_free(buf);
     743             : }
     744             : #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
     745             : #define wpa_supplicant_eap_param_needed NULL
     746             : #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
     747             : 
     748             : 
     749        2151 : static void wpa_supplicant_port_cb(void *ctx, int authorized)
     750             : {
     751        2151 :         struct wpa_supplicant *wpa_s = ctx;
     752             : #ifdef CONFIG_AP
     753        2151 :         if (wpa_s->ap_iface) {
     754           0 :                 wpa_printf(MSG_DEBUG, "AP mode active - skip EAPOL Supplicant "
     755             :                            "port status: %s",
     756             :                            authorized ? "Authorized" : "Unauthorized");
     757        2151 :                 return;
     758             :         }
     759             : #endif /* CONFIG_AP */
     760        2151 :         wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s",
     761             :                    authorized ? "Authorized" : "Unauthorized");
     762        2151 :         wpa_drv_set_supp_port(wpa_s, authorized);
     763             : }
     764             : 
     765             : 
     766         396 : static void wpa_supplicant_cert_cb(void *ctx, int depth, const char *subject,
     767             :                                    const char *cert_hash,
     768             :                                    const struct wpabuf *cert)
     769             : {
     770         396 :         struct wpa_supplicant *wpa_s = ctx;
     771             : 
     772         396 :         wpas_notify_certification(wpa_s, depth, subject, cert_hash, cert);
     773         396 : }
     774             : 
     775             : 
     776        2093 : static void wpa_supplicant_status_cb(void *ctx, const char *status,
     777             :                                      const char *parameter)
     778             : {
     779        2093 :         struct wpa_supplicant *wpa_s = ctx;
     780             : 
     781        2093 :         wpas_notify_eap_status(wpa_s, status, parameter);
     782        2093 : }
     783             : 
     784             : 
     785          49 : static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
     786             : {
     787          49 :         struct wpa_supplicant *wpa_s = ctx;
     788             :         char *str;
     789             :         int res;
     790             : 
     791          49 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity",
     792             :                           id, len);
     793             : 
     794          49 :         if (wpa_s->current_ssid == NULL)
     795           0 :                 return;
     796             : 
     797          49 :         if (id == NULL) {
     798           5 :                 if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
     799             :                                    "NULL", 0) < 0)
     800           0 :                         return;
     801             :         } else {
     802          44 :                 str = os_malloc(len * 2 + 1);
     803          44 :                 if (str == NULL)
     804           0 :                         return;
     805          44 :                 wpa_snprintf_hex(str, len * 2 + 1, id, len);
     806          44 :                 res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
     807             :                                      str, 0);
     808          44 :                 os_free(str);
     809          44 :                 if (res < 0)
     810           0 :                         return;
     811             :         }
     812             : 
     813          49 :         if (wpa_s->conf->update_config) {
     814           0 :                 res = wpa_config_write(wpa_s->confname, wpa_s->conf);
     815           0 :                 if (res) {
     816           0 :                         wpa_printf(MSG_DEBUG, "Failed to update config after "
     817             :                                    "anonymous_id update");
     818             :                 }
     819             :         }
     820             : }
     821             : #endif /* IEEE8021X_EAPOL */
     822             : 
     823             : 
     824          69 : int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
     825             : {
     826             : #ifdef IEEE8021X_EAPOL
     827             :         struct eapol_ctx *ctx;
     828          69 :         ctx = os_zalloc(sizeof(*ctx));
     829          69 :         if (ctx == NULL) {
     830           0 :                 wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context.");
     831           0 :                 return -1;
     832             :         }
     833             : 
     834          69 :         ctx->ctx = wpa_s;
     835          69 :         ctx->msg_ctx = wpa_s;
     836          69 :         ctx->eapol_send_ctx = wpa_s;
     837          69 :         ctx->preauth = 0;
     838          69 :         ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done;
     839          69 :         ctx->eapol_send = wpa_supplicant_eapol_send;
     840          69 :         ctx->set_wep_key = wpa_eapol_set_wep_key;
     841             : #ifndef CONFIG_NO_CONFIG_BLOBS
     842          69 :         ctx->set_config_blob = wpa_supplicant_set_config_blob;
     843          69 :         ctx->get_config_blob = wpa_supplicant_get_config_blob;
     844             : #endif /* CONFIG_NO_CONFIG_BLOBS */
     845          69 :         ctx->aborted_cached = wpa_supplicant_aborted_cached;
     846          69 :         ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
     847          69 :         ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
     848          69 :         ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
     849          69 :         ctx->wps = wpa_s->wps;
     850          69 :         ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
     851          69 :         ctx->port_cb = wpa_supplicant_port_cb;
     852          69 :         ctx->cb = wpa_supplicant_eapol_cb;
     853          69 :         ctx->cert_cb = wpa_supplicant_cert_cb;
     854          69 :         ctx->status_cb = wpa_supplicant_status_cb;
     855          69 :         ctx->set_anon_id = wpa_supplicant_set_anon_id;
     856          69 :         ctx->cb_ctx = wpa_s;
     857          69 :         wpa_s->eapol = eapol_sm_init(ctx);
     858          69 :         if (wpa_s->eapol == NULL) {
     859           0 :                 os_free(ctx);
     860           0 :                 wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state "
     861             :                            "machines.");
     862           0 :                 return -1;
     863             :         }
     864             : #endif /* IEEE8021X_EAPOL */
     865             : 
     866          69 :         return 0;
     867             : }
     868             : 
     869             : 
     870             : #ifndef CONFIG_NO_WPA
     871         618 : static void wpa_supplicant_set_rekey_offload(void *ctx, const u8 *kek,
     872             :                                              const u8 *kck,
     873             :                                              const u8 *replay_ctr)
     874             : {
     875         618 :         struct wpa_supplicant *wpa_s = ctx;
     876             : 
     877         618 :         wpa_drv_set_rekey_info(wpa_s, kek, kck, replay_ctr);
     878         618 : }
     879             : #endif /* CONFIG_NO_WPA */
     880             : 
     881             : 
     882          69 : int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
     883             : {
     884             : #ifndef CONFIG_NO_WPA
     885             :         struct wpa_sm_ctx *ctx;
     886          69 :         ctx = os_zalloc(sizeof(*ctx));
     887          69 :         if (ctx == NULL) {
     888           0 :                 wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");
     889           0 :                 return -1;
     890             :         }
     891             : 
     892          69 :         ctx->ctx = wpa_s;
     893          69 :         ctx->msg_ctx = wpa_s;
     894          69 :         ctx->set_state = _wpa_supplicant_set_state;
     895          69 :         ctx->get_state = _wpa_supplicant_get_state;
     896          69 :         ctx->deauthenticate = _wpa_supplicant_deauthenticate;
     897          69 :         ctx->set_key = wpa_supplicant_set_key;
     898          69 :         ctx->get_network_ctx = wpa_supplicant_get_network_ctx;
     899          69 :         ctx->get_bssid = wpa_supplicant_get_bssid;
     900          69 :         ctx->ether_send = _wpa_ether_send;
     901          69 :         ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie;
     902          69 :         ctx->alloc_eapol = _wpa_alloc_eapol;
     903          69 :         ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout;
     904          69 :         ctx->add_pmkid = wpa_supplicant_add_pmkid;
     905          69 :         ctx->remove_pmkid = wpa_supplicant_remove_pmkid;
     906             : #ifndef CONFIG_NO_CONFIG_BLOBS
     907          69 :         ctx->set_config_blob = wpa_supplicant_set_config_blob;
     908          69 :         ctx->get_config_blob = wpa_supplicant_get_config_blob;
     909             : #endif /* CONFIG_NO_CONFIG_BLOBS */
     910          69 :         ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
     911             : #ifdef CONFIG_IEEE80211R
     912          69 :         ctx->update_ft_ies = wpa_supplicant_update_ft_ies;
     913          69 :         ctx->send_ft_action = wpa_supplicant_send_ft_action;
     914          69 :         ctx->mark_authenticated = wpa_supplicant_mark_authenticated;
     915             : #endif /* CONFIG_IEEE80211R */
     916             : #ifdef CONFIG_TDLS
     917          69 :         ctx->tdls_get_capa = wpa_supplicant_tdls_get_capa;
     918          69 :         ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt;
     919          69 :         ctx->tdls_oper = wpa_supplicant_tdls_oper;
     920          69 :         ctx->tdls_peer_addset = wpa_supplicant_tdls_peer_addset;
     921             : #endif /* CONFIG_TDLS */
     922          69 :         ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;
     923             : 
     924          69 :         wpa_s->wpa = wpa_sm_init(ctx);
     925          69 :         if (wpa_s->wpa == NULL) {
     926           0 :                 wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
     927             :                            "machine");
     928           0 :                 return -1;
     929             :         }
     930             : #endif /* CONFIG_NO_WPA */
     931             : 
     932          69 :         return 0;
     933             : }
     934             : 
     935             : 
     936        1091 : void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
     937             :                                         struct wpa_ssid *ssid)
     938             : {
     939             :         struct rsn_supp_config conf;
     940        1091 :         if (ssid) {
     941        1091 :                 os_memset(&conf, 0, sizeof(conf));
     942        1091 :                 conf.network_ctx = ssid;
     943        1091 :                 conf.peerkey_enabled = ssid->peerkey;
     944        1091 :                 conf.allowed_pairwise_cipher = ssid->pairwise_cipher;
     945             : #ifdef IEEE8021X_EAPOL
     946        2182 :                 conf.proactive_key_caching = ssid->proactive_key_caching < 0 ?
     947        1091 :                         wpa_s->conf->okc : ssid->proactive_key_caching;
     948        1091 :                 conf.eap_workaround = ssid->eap_workaround;
     949        1091 :                 conf.eap_conf_ctx = &ssid->eap;
     950             : #endif /* IEEE8021X_EAPOL */
     951        1091 :                 conf.ssid = ssid->ssid;
     952        1091 :                 conf.ssid_len = ssid->ssid_len;
     953        1091 :                 conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey;
     954             : #ifdef CONFIG_P2P
     955        1321 :                 if (ssid->p2p_group && wpa_s->current_bss &&
     956         230 :                     !wpa_s->p2p_disable_ip_addr_req) {
     957             :                         struct wpabuf *p2p;
     958         228 :                         p2p = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss,
     959             :                                                           P2P_IE_VENDOR_TYPE);
     960         228 :                         if (p2p) {
     961             :                                 u8 group_capab;
     962         228 :                                 group_capab = p2p_get_group_capab(p2p);
     963         228 :                                 if (group_capab &
     964             :                                     P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION)
     965         228 :                                         conf.p2p = 1;
     966         228 :                                 wpabuf_free(p2p);
     967             :                         }
     968             :                 }
     969             : #endif /* CONFIG_P2P */
     970             :         }
     971        1091 :         wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
     972        1091 : }

Generated by: LCOV version 1.10