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