18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RSN pre-authentication (supplicant) 3c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "l2_packet/l2_packet.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "preauth.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pmksa_cache.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_i.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define PMKID_CANDIDATE_PRIO_SCAN 1000 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_candidate { 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct dl_list list; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bssid[ETH_ALEN]; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int priority; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_candidate_free - Free all entries in PMKSA candidate list 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid pmksa_candidate_free(struct wpa_sm *sm) 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate *entry, *n; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each_safe(entry, n, &sm->pmksa_candidates, 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate, list) { 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&entry->list); 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(entry); 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void rsn_preauth_receive(void *ctx, const u8 *src_addr, 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = ctx; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RX pre-auth from " MACSTR, MAC2STR(src_addr)); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol == NULL || 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt is_zero_ether_addr(sm->preauth_bssid) || 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(sm->preauth_bssid, src_addr, ETH_ALEN) != 0) { 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN pre-auth frame received from " 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected source " MACSTR " - dropped", 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(src_addr)); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_rx_eapol(sm->preauth_eapol, src_addr, buf, len); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void rsn_preauth_eapol_cb(struct eapol_sm *eapol, int success, 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = ctx; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 pmk[PMK_LEN]; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (success) { 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res, pmk_len; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk_len = PMK_LEN; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eapol_sm_get_key(eapol, pmk, PMK_LEN); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) { 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-LEAP is an exception from other EAP methods: it 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * uses only 16-byte PMK. 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eapol_sm_get_key(eapol, pmk, 16); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk_len = 16; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 0) { 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth", 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk, pmk_len); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_len = pmk_len; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_add(sm->pmksa, pmk, pmk_len, 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->preauth_bssid, sm->own_addr, 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->network_ctx, 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_MGMT_IEEE8021X); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: failed to get master session key from " 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pre-auth EAPOL state machines"); 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt success = 0; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with " 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " %s", MAC2STR(sm->preauth_bssid), 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt success ? "completed successfully" : "failed"); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_deinit(sm); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_candidate_process(sm); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with " 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " timed out", MAC2STR(sm->preauth_bssid)); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_deinit(sm); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_candidate_process(sm); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int rsn_preauth_eapol_send(void *ctx, int type, const u8 *buf, 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = ctx; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *msg; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t msglen; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: could add l2_packet_sendmsg that allows fragments to avoid 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * extra copy here */ 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_preauth == NULL) 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpa_sm_alloc_eapol(sm, type, buf, len, &msglen, NULL); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = l2_packet_send(sm->l2_preauth, sm->preauth_bssid, 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_RSN_PREAUTH, msg, msglen); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(msg); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_init - Start new RSN pre-authentication 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Authenticator address (BSSID) with which to preauthenticate 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_conf: Current EAP configuration 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on another pre-authentication is in progress, 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * initialization failure, -4 on memory allocation failure 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function request an RSN pre-authentication with a given destination 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * address. This is usually called for PMKSA candidates found from scan results 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pre-authentication. 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *eap_conf) 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_config eapol_conf; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_ctx *ctx; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol) 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: starting pre-authentication with " MACSTR, MAC2STR(dst)); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr, 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_RSN_PREAUTH, 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_receive, sm, 0); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_preauth == NULL) { 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet " 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "processing for pre-authentication"); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->bridge_ifname) { 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_preauth_br = l2_packet_init(sm->bridge_ifname, 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_RSN_PREAUTH, 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_receive, sm, 0); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_preauth_br == NULL) { 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 " 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet processing (bridge) for " 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pre-authentication"); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx = os_zalloc(sizeof(*ctx)); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctx == NULL) { 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context."); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -4; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->ctx = sm->ctx->ctx; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->msg_ctx = sm->ctx->ctx; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->preauth = 1; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->cb = rsn_preauth_eapol_cb; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->cb_ctx = sm; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->scard_ctx = sm->scard_ctx; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->eapol_send = rsn_preauth_eapol_send; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->eapol_send_ctx = sm; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->set_config_blob = sm->ctx->set_config_blob; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->get_config_blob = sm->ctx->get_config_blob; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->preauth_eapol = eapol_sm_init(ctx); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol == NULL) { 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ctx); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL " 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "state machines for pre-authentication"); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -3; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&eapol_conf, 0, sizeof(eapol_conf)); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_conf.accept_802_1x_keys = 0; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_conf.required_keys = 0; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_conf.fast_reauth = sm->fast_reauth; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_conf.workaround = sm->eap_workaround; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_config(sm->preauth_eapol, eap_conf, &eapol_conf); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Use a shorter startPeriod with preauthentication since the first 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * preauth EAPOL-Start frame may end up being dropped due to race 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * condition in the AP between the data receive and key configuration 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * after the 4-Way Handshake. 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->preauth_bssid, dst, ETH_ALEN); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_portValid(sm->preauth_eapol, TRUE); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 802.1X::portControl = Auto */ 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_portEnabled(sm->preauth_eapol, TRUE); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0, 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_timeout, sm, NULL); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_deinit - Abort RSN pre-authentication 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function aborts the current RSN pre-authentication (if one is started) 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and frees resources allocated for it. 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_preauth_deinit(struct wpa_sm *sm) 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || !sm->preauth_eapol) 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(rsn_preauth_timeout, sm, NULL); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_deinit(sm->preauth_eapol); 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->preauth_eapol = NULL; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(sm->preauth_bssid, 0, ETH_ALEN); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_deinit(sm->l2_preauth); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_preauth = NULL; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_preauth_br) { 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_deinit(sm->l2_preauth_br); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_preauth_br = NULL; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_candidate_process - Process PMKSA candidates 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Go through the PMKSA candidates and start pre-authentication if a candidate 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * without an existing PMKSA cache entry is found. Processed candidates will be 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * removed from the list. 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_preauth_candidate_process(struct wpa_sm *sm) 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate *candidate, *n; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dl_list_empty(&sm->pmksa_candidates)) 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: drop priority for old candidate entries */ 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: processing PMKSA candidate " 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "list"); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol || 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->proto != WPA_PROTO_RSN || 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_get_state(sm) != WPA_COMPLETED || 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X && 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256)) { 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable " 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "state for new pre-authentication"); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* invalid state for new pre-auth */ 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates, 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate, list) { 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *p = NULL; 308c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 && 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (p == NULL || p->opportunistic)) { 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA " 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "candidate " MACSTR 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " selected for pre-authentication", 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(candidate->bssid)); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&candidate->list); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_init(sm, candidate->bssid, 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_conf_ctx); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(candidate); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA candidate " 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " does not need pre-authentication anymore", 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(candidate->bssid)); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Some drivers (e.g., NDIS) expect to get notified about the 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMKIDs again, so report the existing data now. */ 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p) { 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_add_pmkid(sm, candidate->bssid, p->pmkid); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&candidate->list); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(candidate); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: no more pending PMKSA " 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "candidates"); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_candidate_add - Add a new PMKSA candidate 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: BSSID (authenticator address) of the candidate 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @prio: Priority (the smaller number, the higher priority) 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @preauth: Whether the candidate AP advertises support for pre-authentication 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to add PMKSA candidates for RSN pre-authentication. It 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is called from scan result processing and from driver events for PMKSA 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * candidates, i.e., EVENT_PMKID_CANDIDATE events to wpa_supplicant_event(). 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int prio, int preauth) 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate *cand, *pos; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->network_ctx && sm->proactive_key_caching) 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx, 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bssid); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!preauth) { 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without " 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "preauth flag"); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* If BSSID already on candidate list, update the priority of the old 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entry. Do not override priority based on normal scan results. */ 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand = NULL; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(pos, &sm->pmksa_candidates, 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate, list) { 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(pos->bssid, bssid, ETH_ALEN) == 0) { 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand = pos; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cand) { 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&cand->list); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prio < PMKID_CANDIDATE_PRIO_SCAN) 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand->priority = prio; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand = os_zalloc(sizeof(*cand)); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cand == NULL) 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cand->bssid, bssid, ETH_ALEN); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand->priority = prio; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add candidate to the list; order by increasing priority value. i.e., 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * highest priority (smallest value) first. */ 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(pos, &sm->pmksa_candidates, 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate, list) { 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cand->priority <= pos->priority) { 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add(pos->list.prev, &cand->list); 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand = NULL; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cand) 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add_tail(&sm->pmksa_candidates, &cand->list); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: added PMKSA cache " 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "candidate " MACSTR " prio %d", MAC2STR(bssid), prio); 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_candidate_process(sm); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TODO: schedule periodic scans if current AP supports preauth */ 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_scan_results - Start processing scan results for canditates 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 if ready to process results or -1 to skip processing 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This functions is used to notify RSN code about start of new scan results 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * processing. The actual scan results will be provided by calling 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_scan_result() for each BSS if this function returned 0. 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rsn_preauth_scan_results(struct wpa_sm *sm) 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ssid_len == 0) 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: is it ok to free all candidates? What about the entries 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * received from EVENT_PMKID_CANDIDATE? 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_candidate_free(sm); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_scan_result - Processing scan result for PMKSA canditates 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Add all suitable APs (Authenticators) from scan results into PMKSA 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * candidate list. 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ssid, const u8 *rsn) 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid[1] != sm->ssid_len || 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0) 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* Not for the current SSID */ 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(bssid, sm->bssid, ETH_ALEN) == 0) 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* Ignore current AP */ 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie)) 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 455c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa && (!pmksa->opportunistic || 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(ie.capabilities & WPA_CAPABILITY_PREAUTH))) 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Give less priority to candidates found from normal scan results. */ 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_candidate_add(sm, bssid, PMKID_CANDIDATE_PRIO_SCAN, 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.capabilities & WPA_CAPABILITY_PREAUTH); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_get_status - Get pre-authentication status 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf. 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Query WPA2 pre-authentication for status information. This function fills in 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a text area with current status information. If the buffer (buf) is not 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * large enough, status information will be truncated to fit the buffer. 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen, 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int verbose) 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos = buf, *end = buf + buflen; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res, ret; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol) { 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, end - pos, "Pre-authentication " 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAPOL state machines:\n"); 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - pos) 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eapol_sm_get_status(sm->preauth_eapol, 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, end - pos, verbose); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res >= 0) 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */ 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_in_progress - Verify whether pre-authentication is in progress 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rsn_preauth_in_progress(struct wpa_sm *sm) 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->preauth_eapol != NULL; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ 512