18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2007, 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 "utils/includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_PREAUTH
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "l2_packet/l2_packet.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_common.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth/eapol_auth_sm.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth/eapol_auth_sm_i.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_1x.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sta_info.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "preauth_auth.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef ETH_P_PREAUTH
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* ETH_P_PREAUTH */
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const int dot11RSNAConfigPMKLifetime = 43200;
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_preauth_interface {
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_preauth_interface *next;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct l2_packet_data *l2;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *ifname;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ifindex;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void rsn_preauth_receive(void *ctx, const u8 *src_addr,
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *buf, size_t len)
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_preauth_interface *piface = ctx;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = piface->hapd;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_1x_hdr *hdr;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *sta;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct l2_ethhdr *ethhdr;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "RSN: receive pre-auth packet "
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "from interface '%s'", piface->ifname);
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(*ethhdr) + sizeof(*hdr)) {
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "RSN: too short pre-auth packet "
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(len=%lu)", (unsigned long) len);
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ethhdr = (struct l2_ethhdr *) buf;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) {
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "RSN: pre-auth for foreign address "
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MACSTR, MAC2STR(ethhdr->h_dest));
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta = ap_get_sta(hapd, ethhdr->h_source);
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta && (sta->flags & WLAN_STA_ASSOC)) {
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "RSN: pre-auth for already association "
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "STA " MACSTR, MAC2STR(sta->addr));
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) {
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta = ap_sta_add(hapd, ethhdr->h_source);
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sta == NULL)
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta->flags = WLAN_STA_PREAUTH;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ieee802_1x_new_station(hapd, sta);
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sta->eapol_sm == NULL) {
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ap_free_sta(hapd, sta);
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta = NULL;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta->eapol_sm->radius_identifier = -1;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta->eapol_sm->portValid = TRUE;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta == NULL)
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->preauth_iface = piface;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1),
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   len - sizeof(*ethhdr));
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname)
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_preauth_interface *piface;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname);
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	piface = os_zalloc(sizeof(*piface));
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (piface == NULL)
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	piface->hapd = hapd;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	piface->ifname = os_strdup(ifname);
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (piface->ifname == NULL) {
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail1;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH,
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    rsn_preauth_receive, piface, 1);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (piface->l2 == NULL) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to open register layer 2 access "
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "to ETH_P_PREAUTH");
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail2;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	piface->next = hapd->preauth_iface;
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->preauth_iface = piface;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail2:
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(piface->ifname);
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail1:
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(piface);
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_preauth_iface_deinit(struct hostapd_data *hapd)
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_preauth_interface *piface, *prev;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	piface = hapd->preauth_iface;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->preauth_iface = NULL;
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (piface) {
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = piface;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		piface = piface->next;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		l2_packet_deinit(prev->l2);
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(prev->ifname);
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(prev);
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rsn_preauth_iface_init(struct hostapd_data *hapd)
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *tmp, *start, *end;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->conf->rsn_preauth_interfaces == NULL)
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = os_strdup(hapd->conf->rsn_preauth_interfaces);
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = tmp;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*start == ' ')
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start++;
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*start == '\0')
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = os_strchr(start, ' ');
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*end = '\0';
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rsn_preauth_iface_add(hapd, start)) {
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			rsn_preauth_iface_deinit(hapd);
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(tmp);
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start = end + 1;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(tmp);
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx)
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = eloop_ctx;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *sta = timeout_ctx;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for "
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MACSTR, MAC2STR(sta->addr));
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ap_free_sta(hapd, sta);
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta,
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  int success)
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *key;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       HOSTAPD_LEVEL_INFO, "pre-authentication %s",
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       success ? "succeeded" : "failed");
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key = ieee802_1x_get_key(sta->eapol_sm, &len);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > PMK_LEN)
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = PMK_LEN;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (success && key) {
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len,
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       sta->addr,
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dot11RSNAConfigPMKLifetime,
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       sta->eapol_sm) == 0) {
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_LEVEL_DEBUG,
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "added PMKSA cache entry (pre-auth)");
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_LEVEL_DEBUG,
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "failed to add PMKSA cache entry "
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "(pre-auth)");
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Finish STA entry removal from timeout in order to avoid freeing
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * STA data before the caller has finished processing.
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta);
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      u8 *buf, size_t len)
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_preauth_interface *piface;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct l2_ethhdr *ethhdr;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	piface = hapd->preauth_iface;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (piface) {
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (piface == sta->preauth_iface)
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		piface = piface->next;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (piface == NULL) {
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication "
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "interface for " MACSTR, MAC2STR(sta->addr));
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ethhdr = os_malloc(sizeof(*ethhdr) + len);
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ethhdr == NULL)
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN);
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN);
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ethhdr + 1, buf, len);
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr,
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(*ethhdr) + len) < 0) {
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to send preauth packet using "
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "l2_packet_send\n");
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ethhdr);
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta)
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_PREAUTH */
274