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