LCOV - code coverage report
Current view: top level - src/rsn_supp - preauth.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 167 220 75.9 %
Date: 2015-09-27 Functions: 12 13 92.3 %

          Line data    Source code
       1             : /*
       2             :  * RSN pre-authentication (supplicant)
       3             :  * Copyright (c) 2003-2015, 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 "wpa.h"
      13             : #include "eloop.h"
      14             : #include "l2_packet/l2_packet.h"
      15             : #include "eapol_supp/eapol_supp_sm.h"
      16             : #include "preauth.h"
      17             : #include "pmksa_cache.h"
      18             : #include "wpa_i.h"
      19             : 
      20             : 
      21             : #ifdef IEEE8021X_EAPOL
      22             : 
      23             : #define PMKID_CANDIDATE_PRIO_SCAN 1000
      24             : 
      25             : 
      26             : struct rsn_pmksa_candidate {
      27             :         struct dl_list list;
      28             :         u8 bssid[ETH_ALEN];
      29             :         int priority;
      30             : };
      31             : 
      32             : 
      33             : /**
      34             :  * pmksa_candidate_free - Free all entries in PMKSA candidate list
      35             :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
      36             :  */
      37         831 : void pmksa_candidate_free(struct wpa_sm *sm)
      38             : {
      39             :         struct rsn_pmksa_candidate *entry, *n;
      40             : 
      41         831 :         if (sm == NULL)
      42         856 :                 return;
      43             : 
      44         806 :         dl_list_for_each_safe(entry, n, &sm->pmksa_candidates,
      45             :                               struct rsn_pmksa_candidate, list) {
      46           0 :                 dl_list_del(&entry->list);
      47           0 :                 os_free(entry);
      48             :         }
      49             : }
      50             : 
      51             : 
      52          16 : static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
      53             :                                 const u8 *buf, size_t len)
      54             : {
      55          16 :         struct wpa_sm *sm = ctx;
      56             : 
      57          16 :         wpa_printf(MSG_DEBUG, "RX pre-auth from " MACSTR, MAC2STR(src_addr));
      58          16 :         wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len);
      59             : 
      60          32 :         if (sm->preauth_eapol == NULL ||
      61          32 :             is_zero_ether_addr(sm->preauth_bssid) ||
      62          16 :             os_memcmp(sm->preauth_bssid, src_addr, ETH_ALEN) != 0) {
      63           0 :                 wpa_printf(MSG_WARNING, "RSN pre-auth frame received from "
      64             :                            "unexpected source " MACSTR " - dropped",
      65           0 :                            MAC2STR(src_addr));
      66          16 :                 return;
      67             :         }
      68             : 
      69          16 :         eapol_sm_rx_eapol(sm->preauth_eapol, src_addr, buf, len);
      70             : }
      71             : 
      72             : 
      73           4 : static void rsn_preauth_eapol_cb(struct eapol_sm *eapol,
      74             :                                  enum eapol_supp_result result,
      75             :                                  void *ctx)
      76             : {
      77           4 :         struct wpa_sm *sm = ctx;
      78             :         u8 pmk[PMK_LEN];
      79             : 
      80           4 :         if (result == EAPOL_SUPP_RESULT_SUCCESS) {
      81             :                 int res, pmk_len;
      82           4 :                 pmk_len = PMK_LEN;
      83           4 :                 res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
      84           4 :                 if (res) {
      85             :                         /*
      86             :                          * EAP-LEAP is an exception from other EAP methods: it
      87             :                          * uses only 16-byte PMK.
      88             :                          */
      89           0 :                         res = eapol_sm_get_key(eapol, pmk, 16);
      90           0 :                         pmk_len = 16;
      91             :                 }
      92           4 :                 if (res == 0) {
      93           4 :                         wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth",
      94             :                                         pmk, pmk_len);
      95           4 :                         sm->pmk_len = pmk_len;
      96           8 :                         pmksa_cache_add(sm->pmksa, pmk, pmk_len,
      97             :                                         NULL, 0,
      98           4 :                                         sm->preauth_bssid, sm->own_addr,
      99             :                                         sm->network_ctx,
     100             :                                         WPA_KEY_MGMT_IEEE8021X);
     101             :                 } else {
     102           0 :                         wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
     103             :                                 "RSN: failed to get master session key from "
     104             :                                 "pre-auth EAPOL state machines");
     105           0 :                         result = EAPOL_SUPP_RESULT_FAILURE;
     106             :                 }
     107             :         }
     108             : 
     109          28 :         wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
     110          24 :                 MACSTR " %s", MAC2STR(sm->preauth_bssid),
     111             :                 result == EAPOL_SUPP_RESULT_SUCCESS ? "completed successfully" :
     112             :                 "failed");
     113             : 
     114           4 :         rsn_preauth_deinit(sm);
     115           4 :         rsn_preauth_candidate_process(sm);
     116           4 : }
     117             : 
     118             : 
     119           1 : static void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx)
     120             : {
     121           1 :         struct wpa_sm *sm = eloop_ctx;
     122             : 
     123           6 :         wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
     124           6 :                 MACSTR " timed out", MAC2STR(sm->preauth_bssid));
     125           1 :         rsn_preauth_deinit(sm);
     126           1 :         rsn_preauth_candidate_process(sm);
     127           1 : }
     128             : 
     129             : 
     130          18 : static int rsn_preauth_eapol_send(void *ctx, int type, const u8 *buf,
     131             :                                   size_t len)
     132             : {
     133          18 :         struct wpa_sm *sm = ctx;
     134             :         u8 *msg;
     135             :         size_t msglen;
     136             :         int res;
     137             : 
     138             :         /* TODO: could add l2_packet_sendmsg that allows fragments to avoid
     139             :          * extra copy here */
     140             : 
     141          18 :         if (sm->l2_preauth == NULL)
     142           0 :                 return -1;
     143             : 
     144          18 :         msg = wpa_sm_alloc_eapol(sm, type, buf, len, &msglen, NULL);
     145          18 :         if (msg == NULL)
     146           0 :                 return -1;
     147             : 
     148          18 :         wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen);
     149          18 :         res = l2_packet_send(sm->l2_preauth, sm->preauth_bssid,
     150             :                              ETH_P_RSN_PREAUTH, msg, msglen);
     151          18 :         os_free(msg);
     152          18 :         return res;
     153             : }
     154             : 
     155             : 
     156             : /**
     157             :  * rsn_preauth_init - Start new RSN pre-authentication
     158             :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     159             :  * @dst: Authenticator address (BSSID) with which to preauthenticate
     160             :  * @eap_conf: Current EAP configuration
     161             :  * Returns: 0 on success, -1 on another pre-authentication is in progress,
     162             :  * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine
     163             :  * initialization failure, -4 on memory allocation failure
     164             :  *
     165             :  * This function request an RSN pre-authentication with a given destination
     166             :  * address. This is usually called for PMKSA candidates found from scan results
     167             :  * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger
     168             :  * pre-authentication.
     169             :  */
     170          18 : int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
     171             :                      struct eap_peer_config *eap_conf)
     172             : {
     173             :         struct eapol_config eapol_conf;
     174             :         struct eapol_ctx *ctx;
     175             :         int ret;
     176             : 
     177          18 :         if (sm->preauth_eapol)
     178           0 :                 return -1;
     179             : 
     180         108 :         wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
     181         108 :                 "RSN: starting pre-authentication with " MACSTR, MAC2STR(dst));
     182             : 
     183          18 :         sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr,
     184             :                                         ETH_P_RSN_PREAUTH,
     185             :                                         rsn_preauth_receive, sm, 0);
     186          18 :         if (sm->l2_preauth == NULL) {
     187           1 :                 wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet "
     188             :                            "processing for pre-authentication");
     189           1 :                 return -2;
     190             :         }
     191             : 
     192          17 :         if (sm->bridge_ifname) {
     193           0 :                 sm->l2_preauth_br = l2_packet_init(sm->bridge_ifname,
     194           0 :                                                    sm->own_addr,
     195             :                                                    ETH_P_RSN_PREAUTH,
     196             :                                                    rsn_preauth_receive, sm, 0);
     197           0 :                 if (sm->l2_preauth_br == NULL) {
     198           0 :                         wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 "
     199             :                                    "packet processing (bridge) for "
     200             :                                    "pre-authentication");
     201           0 :                         ret = -2;
     202           0 :                         goto fail;
     203             :                 }
     204             :         }
     205             : 
     206          17 :         ctx = os_zalloc(sizeof(*ctx));
     207          17 :         if (ctx == NULL) {
     208           1 :                 wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context.");
     209           1 :                 ret = -4;
     210           1 :                 goto fail;
     211             :         }
     212          16 :         ctx->ctx = sm->ctx->ctx;
     213          16 :         ctx->msg_ctx = sm->ctx->ctx;
     214          16 :         ctx->preauth = 1;
     215          16 :         ctx->cb = rsn_preauth_eapol_cb;
     216          16 :         ctx->cb_ctx = sm;
     217          16 :         ctx->scard_ctx = sm->scard_ctx;
     218          16 :         ctx->eapol_send = rsn_preauth_eapol_send;
     219          16 :         ctx->eapol_send_ctx = sm;
     220          16 :         ctx->set_config_blob = sm->ctx->set_config_blob;
     221          16 :         ctx->get_config_blob = sm->ctx->get_config_blob;
     222             : 
     223          16 :         sm->preauth_eapol = eapol_sm_init(ctx);
     224          16 :         if (sm->preauth_eapol == NULL) {
     225           4 :                 os_free(ctx);
     226           4 :                 wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL "
     227             :                            "state machines for pre-authentication");
     228           4 :                 ret = -3;
     229           4 :                 goto fail;
     230             :         }
     231          12 :         os_memset(&eapol_conf, 0, sizeof(eapol_conf));
     232          12 :         eapol_conf.accept_802_1x_keys = 0;
     233          12 :         eapol_conf.required_keys = 0;
     234          12 :         eapol_conf.fast_reauth = sm->fast_reauth;
     235          12 :         eapol_conf.workaround = sm->eap_workaround;
     236          12 :         eapol_sm_notify_config(sm->preauth_eapol, eap_conf, &eapol_conf);
     237             :         /*
     238             :          * Use a shorter startPeriod with preauthentication since the first
     239             :          * preauth EAPOL-Start frame may end up being dropped due to race
     240             :          * condition in the AP between the data receive and key configuration
     241             :          * after the 4-Way Handshake.
     242             :          */
     243          12 :         eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6);
     244          12 :         os_memcpy(sm->preauth_bssid, dst, ETH_ALEN);
     245             : 
     246          12 :         eapol_sm_notify_portValid(sm->preauth_eapol, TRUE);
     247             :         /* 802.1X::portControl = Auto */
     248          12 :         eapol_sm_notify_portEnabled(sm->preauth_eapol, TRUE);
     249             : 
     250          12 :         eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0,
     251             :                                rsn_preauth_timeout, sm, NULL);
     252             : 
     253          12 :         return 0;
     254             : 
     255             : fail:
     256           5 :         if (sm->l2_preauth_br) {
     257           0 :                 l2_packet_deinit(sm->l2_preauth_br);
     258           0 :                 sm->l2_preauth_br = NULL;
     259             :         }
     260           5 :         l2_packet_deinit(sm->l2_preauth);
     261           5 :         sm->l2_preauth = NULL;
     262           5 :         return ret;
     263             : }
     264             : 
     265             : 
     266             : /**
     267             :  * rsn_preauth_deinit - Abort RSN pre-authentication
     268             :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     269             :  *
     270             :  * This function aborts the current RSN pre-authentication (if one is started)
     271             :  * and frees resources allocated for it.
     272             :  */
     273        8945 : void rsn_preauth_deinit(struct wpa_sm *sm)
     274             : {
     275        8945 :         if (sm == NULL || !sm->preauth_eapol)
     276       17878 :                 return;
     277             : 
     278          12 :         eloop_cancel_timeout(rsn_preauth_timeout, sm, NULL);
     279          12 :         eapol_sm_deinit(sm->preauth_eapol);
     280          12 :         sm->preauth_eapol = NULL;
     281          12 :         os_memset(sm->preauth_bssid, 0, ETH_ALEN);
     282             : 
     283          12 :         l2_packet_deinit(sm->l2_preauth);
     284          12 :         sm->l2_preauth = NULL;
     285          12 :         if (sm->l2_preauth_br) {
     286           0 :                 l2_packet_deinit(sm->l2_preauth_br);
     287           0 :                 sm->l2_preauth_br = NULL;
     288             :         }
     289             : }
     290             : 
     291             : 
     292             : /**
     293             :  * rsn_preauth_candidate_process - Process PMKSA candidates
     294             :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     295             :  *
     296             :  * Go through the PMKSA candidates and start pre-authentication if a candidate
     297             :  * without an existing PMKSA cache entry is found. Processed candidates will be
     298             :  * removed from the list.
     299             :  */
     300         391 : void rsn_preauth_candidate_process(struct wpa_sm *sm)
     301             : {
     302             :         struct rsn_pmksa_candidate *candidate, *n;
     303             : 
     304         391 :         if (dl_list_empty(&sm->pmksa_candidates))
     305         388 :                 return;
     306             : 
     307             :         /* TODO: drop priority for old candidate entries */
     308             : 
     309           3 :         wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: processing PMKSA candidate "
     310             :                 "list");
     311           6 :         if (sm->preauth_eapol ||
     312           6 :             sm->proto != WPA_PROTO_RSN ||
     313           6 :             wpa_sm_get_state(sm) != WPA_COMPLETED ||
     314           3 :             (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
     315           0 :              sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256 &&
     316           0 :              sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SUITE_B &&
     317           0 :              sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)) {
     318           0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable "
     319             :                         "state for new pre-authentication");
     320           0 :                 return; /* invalid state for new pre-auth */
     321             :         }
     322             : 
     323           3 :         dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates,
     324             :                               struct rsn_pmksa_candidate, list) {
     325           3 :                 struct rsn_pmksa_cache_entry *p = NULL;
     326           3 :                 p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL);
     327           3 :                 if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
     328           0 :                     (p == NULL || p->opportunistic)) {
     329          18 :                         wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
     330             :                                 "candidate " MACSTR
     331             :                                 " selected for pre-authentication",
     332          18 :                                 MAC2STR(candidate->bssid));
     333           3 :                         dl_list_del(&candidate->list);
     334           3 :                         rsn_preauth_init(sm, candidate->bssid,
     335           3 :                                          sm->eap_conf_ctx);
     336           3 :                         os_free(candidate);
     337           3 :                         return;
     338             :                 }
     339           0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA candidate "
     340             :                         MACSTR " does not need pre-authentication anymore",
     341           0 :                         MAC2STR(candidate->bssid));
     342             :                 /* Some drivers (e.g., NDIS) expect to get notified about the
     343             :                  * PMKIDs again, so report the existing data now. */
     344           0 :                 if (p) {
     345           0 :                         wpa_sm_add_pmkid(sm, candidate->bssid, p->pmkid);
     346             :                 }
     347             : 
     348           0 :                 dl_list_del(&candidate->list);
     349           0 :                 os_free(candidate);
     350             :         }
     351           0 :         wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: no more pending PMKSA "
     352             :                 "candidates");
     353             : }
     354             : 
     355             : 
     356             : /**
     357             :  * pmksa_candidate_add - Add a new PMKSA candidate
     358             :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     359             :  * @bssid: BSSID (authenticator address) of the candidate
     360             :  * @prio: Priority (the smaller number, the higher priority)
     361             :  * @preauth: Whether the candidate AP advertises support for pre-authentication
     362             :  *
     363             :  * This function is used to add PMKSA candidates for RSN pre-authentication. It
     364             :  * is called from scan result processing and from driver events for PMKSA
     365             :  * candidates, i.e., EVENT_PMKID_CANDIDATE events to wpa_supplicant_event().
     366             :  */
     367          17 : void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
     368             :                          int prio, int preauth)
     369             : {
     370             :         struct rsn_pmksa_candidate *cand, *pos;
     371             : 
     372          17 :         if (sm->network_ctx && sm->proactive_key_caching)
     373           2 :                 pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx,
     374             :                                               bssid);
     375             : 
     376          17 :         if (!preauth) {
     377          14 :                 wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without "
     378             :                            "preauth flag");
     379          14 :                 return;
     380             :         }
     381             : 
     382             :         /* If BSSID already on candidate list, update the priority of the old
     383             :          * entry. Do not override priority based on normal scan results. */
     384           3 :         cand = NULL;
     385           3 :         dl_list_for_each(pos, &sm->pmksa_candidates,
     386             :                          struct rsn_pmksa_candidate, list) {
     387           0 :                 if (os_memcmp(pos->bssid, bssid, ETH_ALEN) == 0) {
     388           0 :                         cand = pos;
     389           0 :                         break;
     390             :                 }
     391             :         }
     392             : 
     393           3 :         if (cand) {
     394           0 :                 dl_list_del(&cand->list);
     395           0 :                 if (prio < PMKID_CANDIDATE_PRIO_SCAN)
     396           0 :                         cand->priority = prio;
     397             :         } else {
     398           3 :                 cand = os_zalloc(sizeof(*cand));
     399           3 :                 if (cand == NULL)
     400           0 :                         return;
     401           3 :                 os_memcpy(cand->bssid, bssid, ETH_ALEN);
     402           3 :                 cand->priority = prio;
     403             :         }
     404             : 
     405             :         /* Add candidate to the list; order by increasing priority value. i.e.,
     406             :          * highest priority (smallest value) first. */
     407           3 :         dl_list_for_each(pos, &sm->pmksa_candidates,
     408             :                          struct rsn_pmksa_candidate, list) {
     409           0 :                 if (cand->priority <= pos->priority) {
     410           0 :                         if (!pos->list.prev) {
     411             :                                 /*
     412             :                                  * This cannot really happen in pracrice since
     413             :                                  * pos was fetched from the list and the prev
     414             :                                  * pointer must be set. It looks like clang
     415             :                                  * static analyzer gets confused with the
     416             :                                  * dl_list_del(&cand->list) call above and ends
     417             :                                  * up assuming pos->list.prev could be NULL.
     418             :                                  */
     419           0 :                                 os_free(cand);
     420           0 :                                 return;
     421             :                         }
     422           0 :                         dl_list_add(pos->list.prev, &cand->list);
     423           0 :                         cand = NULL;
     424           0 :                         break;
     425             :                 }
     426             :         }
     427           3 :         if (cand)
     428           3 :                 dl_list_add_tail(&sm->pmksa_candidates, &cand->list);
     429             : 
     430          18 :         wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: added PMKSA cache "
     431          18 :                 "candidate " MACSTR " prio %d", MAC2STR(bssid), prio);
     432           3 :         rsn_preauth_candidate_process(sm);
     433             : }
     434             : 
     435             : 
     436             : /* TODO: schedule periodic scans if current AP supports preauth */
     437             : 
     438             : /**
     439             :  * rsn_preauth_scan_results - Start processing scan results for canditates
     440             :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     441             :  * Returns: 0 if ready to process results or -1 to skip processing
     442             :  *
     443             :  * This functions is used to notify RSN code about start of new scan results
     444             :  * processing. The actual scan results will be provided by calling
     445             :  * rsn_preauth_scan_result() for each BSS if this function returned 0.
     446             :  */
     447        1554 : int rsn_preauth_scan_results(struct wpa_sm *sm)
     448             : {
     449        1554 :         if (sm->ssid_len == 0)
     450        1335 :                 return -1;
     451             : 
     452             :         /*
     453             :          * TODO: is it ok to free all candidates? What about the entries
     454             :          * received from EVENT_PMKID_CANDIDATE?
     455             :          */
     456         219 :         pmksa_candidate_free(sm);
     457             : 
     458         219 :         return 0;
     459             : }
     460             : 
     461             : 
     462             : /**
     463             :  * rsn_preauth_scan_result - Processing scan result for PMKSA canditates
     464             :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     465             :  *
     466             :  * Add all suitable APs (Authenticators) from scan results into PMKSA
     467             :  * candidate list.
     468             :  */
     469         187 : void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid,
     470             :                              const u8 *ssid, const u8 *rsn)
     471             : {
     472             :         struct wpa_ie_data ie;
     473             :         struct rsn_pmksa_cache_entry *pmksa;
     474             : 
     475         366 :         if (ssid[1] != sm->ssid_len ||
     476         179 :             os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0)
     477         182 :                 return; /* Not for the current SSID */
     478             : 
     479         175 :         if (os_memcmp(bssid, sm->bssid, ETH_ALEN) == 0)
     480         141 :                 return; /* Ignore current AP */
     481             : 
     482          34 :         if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
     483           0 :                 return;
     484             : 
     485          34 :         pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL);
     486          34 :         if (pmksa && (!pmksa->opportunistic ||
     487           0 :                       !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
     488          17 :                 return;
     489             : 
     490             :         /* Give less priority to candidates found from normal scan results. */
     491          17 :         pmksa_candidate_add(sm, bssid, PMKID_CANDIDATE_PRIO_SCAN,
     492          17 :                             ie.capabilities & WPA_CAPABILITY_PREAUTH);
     493             : }
     494             : 
     495             : 
     496             : #ifdef CONFIG_CTRL_IFACE
     497             : /**
     498             :  * rsn_preauth_get_status - Get pre-authentication status
     499             :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     500             :  * @buf: Buffer for status information
     501             :  * @buflen: Maximum buffer length
     502             :  * @verbose: Whether to include verbose status information
     503             :  * Returns: Number of bytes written to buf.
     504             :  *
     505             :  * Query WPA2 pre-authentication for status information. This function fills in
     506             :  * a text area with current status information. If the buffer (buf) is not
     507             :  * large enough, status information will be truncated to fit the buffer.
     508             :  */
     509        3257 : int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
     510             :                            int verbose)
     511             : {
     512        3257 :         char *pos = buf, *end = buf + buflen;
     513             :         int res, ret;
     514             : 
     515        3257 :         if (sm->preauth_eapol) {
     516           3 :                 ret = os_snprintf(pos, end - pos, "Pre-authentication "
     517             :                                   "EAPOL state machines:\n");
     518           3 :                 if (os_snprintf_error(end - pos, ret))
     519           0 :                         return pos - buf;
     520           3 :                 pos += ret;
     521           3 :                 res = eapol_sm_get_status(sm->preauth_eapol,
     522           3 :                                           pos, end - pos, verbose);
     523           3 :                 if (res >= 0)
     524           3 :                         pos += res;
     525             :         }
     526             : 
     527        3257 :         return pos - buf;
     528             : }
     529             : #endif /* CONFIG_CTRL_IFACE */
     530             : 
     531             : 
     532             : /**
     533             :  * rsn_preauth_in_progress - Verify whether pre-authentication is in progress
     534             :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
     535             :  */
     536           0 : int rsn_preauth_in_progress(struct wpa_sm *sm)
     537             : {
     538           0 :         return sm->preauth_eapol != NULL;
     539             : }
     540             : 
     541             : #endif /* IEEE8021X_EAPOL */

Generated by: LCOV version 1.10