18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RSN pre-authentication (supplicant) 340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * Copyright (c) 2003-2015, 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 211d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA) 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 73344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidtstatic void rsn_preauth_eapol_cb(struct eapol_sm *eapol, 74344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt enum eapol_supp_result result, 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx) 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = ctx; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 pmk[PMK_LEN]; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 80344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (result == EAPOL_SUPP_RESULT_SUCCESS) { 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res, pmk_len; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk_len = PMK_LEN; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eapol_sm_get_key(eapol, pmk, PMK_LEN); 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) { 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-LEAP is an exception from other EAP methods: it 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * uses only 16-byte PMK. 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eapol_sm_get_key(eapol, pmk, 16); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk_len = 16; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 0) { 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth", 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmk, pmk_len); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmk_len = pmk_len; 9657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL, 97fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt NULL, 0, 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->preauth_bssid, sm->own_addr, 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->network_ctx, 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_KEY_MGMT_IEEE8021X); 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: failed to get master session key from " 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pre-auth EAPOL state machines"); 105344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt result = EAPOL_SUPP_RESULT_FAILURE; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with " 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " %s", MAC2STR(sm->preauth_bssid), 111344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt result == EAPOL_SUPP_RESULT_SUCCESS ? "completed successfully" : 112344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt "failed"); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_deinit(sm); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_candidate_process(sm); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx) 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with " 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " timed out", MAC2STR(sm->preauth_bssid)); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_deinit(sm); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_candidate_process(sm); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int rsn_preauth_eapol_send(void *ctx, int type, const u8 *buf, 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = ctx; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *msg; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t msglen; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: could add l2_packet_sendmsg that allows fragments to avoid 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * extra copy here */ 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_preauth == NULL) 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpa_sm_alloc_eapol(sm, type, buf, len, &msglen, NULL); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = l2_packet_send(sm->l2_preauth, sm->preauth_bssid, 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_RSN_PREAUTH, msg, msglen); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(msg); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_init - Start new RSN pre-authentication 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Authenticator address (BSSID) with which to preauthenticate 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_conf: Current EAP configuration 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on another pre-authentication is in progress, 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * initialization failure, -4 on memory allocation failure 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function request an RSN pre-authentication with a given destination 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * address. This is usually called for PMKSA candidates found from scan results 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pre-authentication. 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *eap_conf) 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_config eapol_conf; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eapol_ctx *ctx; 175aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt int ret; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol) 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RSN: starting pre-authentication with " MACSTR, MAC2STR(dst)); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr, 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_RSN_PREAUTH, 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_receive, sm, 0); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_preauth == NULL) { 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet " 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "processing for pre-authentication"); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->bridge_ifname) { 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_preauth_br = l2_packet_init(sm->bridge_ifname, 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->own_addr, 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_RSN_PREAUTH, 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_receive, sm, 0); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_preauth_br == NULL) { 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 " 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "packet processing (bridge) for " 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pre-authentication"); 201aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt ret = -2; 202aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt goto fail; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx = os_zalloc(sizeof(*ctx)); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctx == NULL) { 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context."); 209aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt ret = -4; 210aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt goto fail; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->ctx = sm->ctx->ctx; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->msg_ctx = sm->ctx->ctx; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->preauth = 1; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->cb = rsn_preauth_eapol_cb; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->cb_ctx = sm; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->scard_ctx = sm->scard_ctx; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->eapol_send = rsn_preauth_eapol_send; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->eapol_send_ctx = sm; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->set_config_blob = sm->ctx->set_config_blob; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->get_config_blob = sm->ctx->get_config_blob; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->preauth_eapol = eapol_sm_init(ctx); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol == NULL) { 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ctx); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL " 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "state machines for pre-authentication"); 228aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt ret = -3; 229aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt goto fail; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&eapol_conf, 0, sizeof(eapol_conf)); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_conf.accept_802_1x_keys = 0; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_conf.required_keys = 0; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_conf.fast_reauth = sm->fast_reauth; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_conf.workaround = sm->eap_workaround; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_config(sm->preauth_eapol, eap_conf, &eapol_conf); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Use a shorter startPeriod with preauthentication since the first 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * preauth EAPOL-Start frame may end up being dropped due to race 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * condition in the AP between the data receive and key configuration 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * after the 4-Way Handshake. 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->preauth_bssid, dst, ETH_ALEN); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_portValid(sm->preauth_eapol, TRUE); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 802.1X::portControl = Auto */ 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_portEnabled(sm->preauth_eapol, TRUE); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0, 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_timeout, sm, NULL); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 254aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt 255aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidtfail: 256aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt if (sm->l2_preauth_br) { 257aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt l2_packet_deinit(sm->l2_preauth_br); 258aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt sm->l2_preauth_br = NULL; 259aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt } 260aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt l2_packet_deinit(sm->l2_preauth); 261aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt sm->l2_preauth = NULL; 262aff761db795db8b506c6f6af7ff607856cf85a81Dmitry Shmidt return ret; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_deinit - Abort RSN pre-authentication 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function aborts the current RSN pre-authentication (if one is started) 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and frees resources allocated for it. 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_preauth_deinit(struct wpa_sm *sm) 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL || !sm->preauth_eapol) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(rsn_preauth_timeout, sm, NULL); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_deinit(sm->preauth_eapol); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->preauth_eapol = NULL; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(sm->preauth_bssid, 0, ETH_ALEN); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_deinit(sm->l2_preauth); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_preauth = NULL; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_preauth_br) { 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_deinit(sm->l2_preauth_br); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_preauth_br = NULL; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_candidate_process - Process PMKSA candidates 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Go through the PMKSA candidates and start pre-authentication if a candidate 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * without an existing PMKSA cache entry is found. Processed candidates will be 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * removed from the list. 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_preauth_candidate_process(struct wpa_sm *sm) 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate *candidate, *n; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dl_list_empty(&sm->pmksa_candidates)) 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: drop priority for old candidate entries */ 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: processing PMKSA candidate " 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "list"); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol || 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->proto != WPA_PROTO_RSN || 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_get_state(sm) != WPA_COMPLETED || 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X && 315fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256 && 31640b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SUITE_B && 31740b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)) { 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable " 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "state for new pre-authentication"); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* invalid state for new pre-auth */ 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates, 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate, list) { 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *p = NULL; 326c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 && 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (p == NULL || p->opportunistic)) { 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA " 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "candidate " MACSTR 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " selected for pre-authentication", 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(candidate->bssid)); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&candidate->list); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_init(sm, candidate->bssid, 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_conf_ctx); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(candidate); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA candidate " 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " does not need pre-authentication anymore", 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(candidate->bssid)); 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Some drivers (e.g., NDIS) expect to get notified about the 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMKIDs again, so report the existing data now. */ 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p) { 345293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_sm_add_pmkid(sm, NULL, candidate->bssid, p->pmkid); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&candidate->list); 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(candidate); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: no more pending PMKSA " 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "candidates"); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_candidate_add - Add a new PMKSA candidate 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: BSSID (authenticator address) of the candidate 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @prio: Priority (the smaller number, the higher priority) 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @preauth: Whether the candidate AP advertises support for pre-authentication 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to add PMKSA candidates for RSN pre-authentication. It 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is called from scan result processing and from driver events for PMKSA 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * candidates, i.e., EVENT_PMKID_CANDIDATE events to wpa_supplicant_event(). 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int prio, int preauth) 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate *cand, *pos; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->network_ctx && sm->proactive_key_caching) 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bssid); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!preauth) { 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without " 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "preauth flag"); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* If BSSID already on candidate list, update the priority of the old 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entry. Do not override priority based on normal scan results. */ 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand = NULL; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(pos, &sm->pmksa_candidates, 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate, list) { 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(pos->bssid, bssid, ETH_ALEN) == 0) { 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand = pos; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cand) { 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&cand->list); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prio < PMKID_CANDIDATE_PRIO_SCAN) 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand->priority = prio; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand = os_zalloc(sizeof(*cand)); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cand == NULL) 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cand->bssid, bssid, ETH_ALEN); 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand->priority = prio; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add candidate to the list; order by increasing priority value. i.e., 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * highest priority (smallest value) first. */ 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(pos, &sm->pmksa_candidates, 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_candidate, list) { 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cand->priority <= pos->priority) { 410fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (!pos->list.prev) { 411fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt /* 412fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * This cannot really happen in pracrice since 413fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * pos was fetched from the list and the prev 414fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * pointer must be set. It looks like clang 415fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * static analyzer gets confused with the 416fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * dl_list_del(&cand->list) call above and ends 417fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * up assuming pos->list.prev could be NULL. 418fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt */ 419fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt os_free(cand); 420fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return; 421fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt } 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add(pos->list.prev, &cand->list); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cand = NULL; 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cand) 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add_tail(&sm->pmksa_candidates, &cand->list); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: added PMKSA cache " 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "candidate " MACSTR " prio %d", MAC2STR(bssid), prio); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_preauth_candidate_process(sm); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TODO: schedule periodic scans if current AP supports preauth */ 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_scan_results - Start processing scan results for canditates 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 if ready to process results or -1 to skip processing 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This functions is used to notify RSN code about start of new scan results 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * processing. The actual scan results will be provided by calling 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_scan_result() for each BSS if this function returned 0. 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rsn_preauth_scan_results(struct wpa_sm *sm) 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->ssid_len == 0) 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: is it ok to free all candidates? What about the entries 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * received from EVENT_PMKID_CANDIDATE? 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_candidate_free(sm); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_scan_result - Processing scan result for PMKSA canditates 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Add all suitable APs (Authenticators) from scan results into PMKSA 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * candidate list. 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ssid, const u8 *rsn) 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid[1] != sm->ssid_len || 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0) 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* Not for the current SSID */ 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(bssid, sm->bssid, ETH_ALEN) == 0) 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* Ignore current AP */ 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie)) 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 485c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa && (!pmksa->opportunistic || 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(ie.capabilities & WPA_CAPABILITY_PREAUTH))) 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Give less priority to candidates found from normal scan results. */ 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_candidate_add(sm, bssid, PMKID_CANDIDATE_PRIO_SCAN, 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie.capabilities & WPA_CAPABILITY_PREAUTH); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_get_status - Get pre-authentication status 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf. 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Query WPA2 pre-authentication for status information. This function fills in 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a text area with current status information. If the buffer (buf) is not 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * large enough, status information will be truncated to fit the buffer. 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen, 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int verbose) 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos = buf, *end = buf + buflen; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res, ret; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->preauth_eapol) { 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, end - pos, "Pre-authentication " 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAPOL state machines:\n"); 518fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (os_snprintf_error(end - pos, ret)) 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eapol_sm_get_status(sm->preauth_eapol, 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, end - pos, verbose); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res >= 0) 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */ 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_preauth_in_progress - Verify whether pre-authentication is in progress 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rsn_preauth_in_progress(struct wpa_sm *sm) 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->preauth_eapol != NULL; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5411d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt#endif /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */ 542