18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / IEEE 802.11 authentication (ACL)
361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry 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 * Access control list for IEEE 802.11 authentication can uses statically
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configured ACL from configuration files or an external RADIUS server.
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Results from external RADIUS queries are cached to allow faster
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication frame processing.
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h"
181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "crypto/sha1.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius_client.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_drv_ops.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11.h"
2561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "ieee802_1x.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11_auth.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_ACL_TIMEOUT 30
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct hostapd_cached_radius_acl {
3204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	struct os_reltime timestamp;
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	macaddr addr;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int accepted; /* HOSTAPD_ACL_* */
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_cached_radius_acl *next;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 session_timeout;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 acct_interim_interval;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int vlan_id;
39d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	struct hostapd_sta_wpa_psk_short *psk;
4061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char *identity;
4161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	char *radius_cui;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct hostapd_acl_query_data {
4604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	struct os_reltime timestamp;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 radius_id;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	macaddr addr;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t auth_msg_len;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_acl_query_data *next;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS
5661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e)
5761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(e->identity);
5961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(e->radius_cui);
60d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	hostapd_free_psk_list(e->psk);
6161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(e);
6261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
6361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_cached_radius_acl *prev;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (acl_cache) {
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = acl_cache;
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		acl_cache = acl_cache->next;
7261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		hostapd_acl_cache_free_entry(prev);
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
77d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
78d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			  struct hostapd_sta_wpa_psk_short *src)
79d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
80d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	struct hostapd_sta_wpa_psk_short **copy_to;
81d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	struct hostapd_sta_wpa_psk_short *copy_from;
82d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
83d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	/* Copy PSK linked list */
84d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	copy_to = psk;
85d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	copy_from = src;
86d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	while (copy_from && copy_to) {
87d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		*copy_to = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
88d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (*copy_to == NULL)
89d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			break;
90d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		os_memcpy(*copy_to, copy_from,
91d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			  sizeof(struct hostapd_sta_wpa_psk_short));
92d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		copy_from = copy_from->next;
93d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		copy_to = &((*copy_to)->next);
94d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
95d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (copy_to)
96d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		*copy_to = NULL;
97d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
98d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
99d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 u32 *session_timeout,
1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 u32 *acct_interim_interval, int *vlan_id,
103d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				 struct hostapd_sta_wpa_psk_short **psk,
104d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				 char **identity, char **radius_cui)
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_cached_radius_acl *entry;
10704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	struct os_reltime now;
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	os_get_reltime(&now);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for (entry = hapd->acl_cache; entry; entry = entry->next) {
11261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (os_memcmp(entry->addr, addr, ETH_ALEN) != 0)
11361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			continue;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt		if (os_reltime_expired(&now, &entry->timestamp,
11604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt				       RADIUS_ACL_TIMEOUT))
11761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1; /* entry has expired */
11861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
11961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (session_timeout)
12061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				*session_timeout = entry->session_timeout;
12161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (acct_interim_interval)
12261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			*acct_interim_interval =
12361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				entry->acct_interim_interval;
12461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (vlan_id)
12561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			*vlan_id = entry->vlan_id;
126d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		copy_psk_list(psk, entry->psk);
12761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (identity) {
12861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (entry->identity)
12961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				*identity = os_strdup(entry->identity);
13061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			else
13161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				*identity = NULL;
13261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
13361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (radius_cui) {
13461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (entry->radius_cui)
13561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				*radius_cui = os_strdup(entry->radius_cui);
13661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			else
13761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				*radius_cui = NULL;
13861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
13961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return entry->accepted;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_acl_query_free(struct hostapd_acl_query_data *query)
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (query == NULL)
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(query->auth_msg);
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(query);
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    struct hostapd_acl_query_data *query)
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_msg *msg;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[128];
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	query->radius_id = radius_client_get_id(hapd->radius);
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id);
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL)
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_msg_make_authenticator(msg, addr, ETH_ALEN);
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr));
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf,
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 os_strlen(buf))) {
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not add User-Name");
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!radius_msg_add_attr_user_password(
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    msg, (u8 *) buf, os_strlen(buf),
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    hapd->conf->radius->auth_server->shared_secret,
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    hapd->conf->radius->auth_server->shared_secret_len)) {
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not add User-Password");
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr,
18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   NULL, msg) < 0)
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    MAC2STR(addr));
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (u8 *) buf, os_strlen(buf))) {
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id");
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (u8 *) buf, os_strlen(buf))) {
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not add Connect-Info");
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0)
20504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		goto fail;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fail:
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_msg_free(msg);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_allowed_address - Check whether a specified STA can be authenticated
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hapd: hostapd BSS data
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: MAC address of the STA
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: Authentication message
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of msg in octets
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @session_timeout: Buffer for returning session timeout (from RADIUS)
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @acct_interim_interval: Buffer for returning account interval (from RADIUS)
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @vlan_id: Buffer for returning VLAN ID
224d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * @psk: Linked list buffer for returning WPA PSK
22561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @identity: Buffer for returning identity (from RADIUS)
22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @radius_cui: Buffer for returning CUI (from RADIUS)
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
22861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *
22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * The caller is responsible for freeing the returned *identity and *radius_cui
23061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * values with os_free().
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const u8 *msg, size_t len, u32 *session_timeout,
2341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			    u32 *acct_interim_interval, int *vlan_id,
235d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			    struct hostapd_sta_wpa_psk_short **psk,
236d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			    char **identity, char **radius_cui)
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (session_timeout)
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*session_timeout = 0;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (acct_interim_interval)
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*acct_interim_interval = 0;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (vlan_id)
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*vlan_id = 0;
2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (psk)
245d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		*psk = NULL;
24661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (identity)
24761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		*identity = NULL;
24861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (radius_cui)
24961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		*radius_cui = NULL;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_maclist_found(hapd->conf->accept_mac,
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  hapd->conf->num_accept_mac, addr, vlan_id))
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return HOSTAPD_ACL_ACCEPT;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_maclist_found(hapd->conf->deny_mac,
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  hapd->conf->num_deny_mac, addr, vlan_id))
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return HOSTAPD_ACL_REJECT;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED)
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return HOSTAPD_ACL_ACCEPT;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED)
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return HOSTAPD_ACL_REJECT;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) {
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NO_RADIUS
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return HOSTAPD_ACL_REJECT;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NO_RADIUS */
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct hostapd_acl_query_data *query;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Check whether ACL cache has an entry for this station */
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						acct_interim_interval,
273d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						vlan_id, psk,
27461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						identity, radius_cui);
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res == HOSTAPD_ACL_ACCEPT ||
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return res;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res == HOSTAPD_ACL_REJECT)
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return HOSTAPD_ACL_REJECT;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		query = hapd->acl_queries;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (query) {
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/* pending query in RADIUS retransmit queue;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 * do not generate a new one */
28661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				if (identity) {
28761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					os_free(*identity);
28861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					*identity = NULL;
28961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				}
29061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				if (radius_cui) {
29161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					os_free(*radius_cui);
29261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					*radius_cui = NULL;
29361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				}
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return HOSTAPD_ACL_PENDING;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			query = query->next;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!hapd->conf->radius->auth_server)
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return HOSTAPD_ACL_REJECT;
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No entry in the cache - query external RADIUS server */
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		query = os_zalloc(sizeof(*query));
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (query == NULL) {
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "malloc for query data failed");
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return HOSTAPD_ACL_REJECT;
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
30804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt		os_get_reltime(&query->timestamp);
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(query->addr, addr, ETH_ALEN);
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hostapd_radius_acl_query(hapd, addr, query)) {
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to send Access-Request "
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for ACL query.");
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_acl_query_free(query);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return HOSTAPD_ACL_REJECT;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		query->auth_msg = os_malloc(len);
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (query->auth_msg == NULL) {
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to allocate memory for "
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "auth frame.");
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_acl_query_free(query);
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return HOSTAPD_ACL_REJECT;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(query->auth_msg, msg, len);
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		query->auth_msg_len = len;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		query->next = hapd->acl_queries;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->acl_queries = query;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Queued data will be processed in hostapd_acl_recv_radius()
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * when RADIUS server replies to the sent Access-Request. */
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return HOSTAPD_ACL_PENDING;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return HOSTAPD_ACL_REJECT;
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS
34004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidtstatic void hostapd_acl_expire_cache(struct hostapd_data *hapd,
34104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt				     struct os_reltime *now)
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_cached_radius_acl *prev, *entry, *tmp;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev = NULL;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = hapd->acl_cache;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
34904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt		if (os_reltime_expired(now, &entry->timestamp,
35004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt				       RADIUS_ACL_TIMEOUT)) {
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " has expired.", MAC2STR(entry->addr));
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = entry->next;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				hapd->acl_cache = entry->next;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_drv_set_radius_acl_expire(hapd, entry->addr);
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp = entry;
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			entry = entry->next;
36061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			hostapd_acl_cache_free_entry(tmp);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = entry;
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_acl_expire_queries(struct hostapd_data *hapd,
37104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt				       struct os_reltime *now)
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_acl_query_data *prev, *entry, *tmp;
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev = NULL;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = hapd->acl_queries;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
37904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt		if (os_reltime_expired(now, &entry->timestamp,
38004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt				       RADIUS_ACL_TIMEOUT)) {
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "ACL query for " MACSTR
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   " has expired.", MAC2STR(entry->addr));
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = entry->next;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				hapd->acl_queries = entry->next;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tmp = entry;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			entry = entry->next;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_acl_query_free(tmp);
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = entry;
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_acl_expire - ACL cache expiration callback
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eloop_ctx: struct hostapd_data *
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @timeout_ctx: Not used
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = eloop_ctx;
40804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	struct os_reltime now;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	os_get_reltime(&now);
41104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	hostapd_acl_expire_cache(hapd, &now);
41204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	hostapd_acl_expire_queries(hapd, &now);
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic void decode_tunnel_passwords(struct hostapd_data *hapd,
419d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				    const u8 *shared_secret,
420d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				    size_t shared_secret_len,
421d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				    struct radius_msg *msg,
422d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				    struct radius_msg *req,
423d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				    struct hostapd_cached_radius_acl *cache)
424d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
425d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	int passphraselen;
426d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	char *passphrase, *strpassphrase;
427d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	size_t i;
428d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	struct hostapd_sta_wpa_psk_short *psk;
429d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
430d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	/*
431d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * Decode all tunnel passwords as PSK and save them into a linked list.
432d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 */
433d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	for (i = 0; ; i++) {
434d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		passphrase = radius_msg_get_tunnel_password(
435d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			msg, &passphraselen, shared_secret, shared_secret_len,
436d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			req, i);
437d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/*
438d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * Passphrase is NULL iff there is no i-th Tunnel-Password
439d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * attribute in msg.
440d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 */
441d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (passphrase == NULL)
442d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			break;
443d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/*
444d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * passphrase does not contain the NULL termination.
445d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * Add it here as pbkdf2_sha1() requires it.
446d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 */
447d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		strpassphrase = os_zalloc(passphraselen + 1);
448d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
449d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (strpassphrase && psk) {
450d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			os_memcpy(strpassphrase, passphrase, passphraselen);
451d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			pbkdf2_sha1(strpassphrase,
452d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				    hapd->conf->ssid.ssid,
453d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				    hapd->conf->ssid.ssid_len, 4096,
454d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				    psk->psk, PMK_LEN);
455d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			psk->next = cache->psk;
456d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			cache->psk = psk;
457d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			psk = NULL;
458d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
459d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		os_free(strpassphrase);
460d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		os_free(psk);
461d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		os_free(passphrase);
462d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
463d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
464d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
465d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: RADIUS response message
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req: RADIUS request message
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @shared_secret: RADIUS shared secret
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @shared_secret_len: Length of shared_secret in octets
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Context data (struct hostapd_data *)
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was processed here) or RADIUS_RX_UNKNOWN if not.
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic RadiusRxResult
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidthostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *shared_secret, size_t shared_secret_len,
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			void *data)
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = data;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_acl_query_data *query, *prev;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_cached_radius_acl *cache;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	query = hapd->acl_queries;
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev = NULL;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (query) {
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (query->radius_id == hdr->identifier)
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = query;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		query = query->next;
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (query == NULL)
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RADIUS_RX_UNKNOWN;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS "
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "message (id=%d)", query->radius_id);
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have "
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "correct authenticator - dropped\n");
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RADIUS_RX_INVALID_AUTHENTICATOR;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    hdr->code != RADIUS_CODE_ACCESS_REJECT) {
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL "
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "query", hdr->code);
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RADIUS_RX_UNKNOWN;
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Insert Accept/Reject info into ACL cache */
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cache = os_zalloc(sizeof(*cache));
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cache == NULL) {
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto done;
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
51904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt	os_get_reltime(&cache->timestamp);
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
52261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		u8 *buf;
52361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		size_t len;
5241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      &cache->session_timeout) == 0)
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cache->accepted = HOSTAPD_ACL_ACCEPT;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (radius_msg_get_attr_int32(
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    &cache->acct_interim_interval) == 0 &&
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    cache->acct_interim_interval < 60) {
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Ignored too small "
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Acct-Interim-Interval %d for STA " MACSTR,
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   cache->acct_interim_interval,
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   MAC2STR(query->addr));
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cache->acct_interim_interval = 0;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cache->vlan_id = radius_msg_get_vlanid(msg);
5431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
544d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
545d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					msg, req, cache);
546d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
54761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
54861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					    &buf, &len, NULL) == 0) {
54961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			cache->identity = os_zalloc(len + 1);
55061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (cache->identity)
55161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				os_memcpy(cache->identity, buf, len);
55261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
55361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (radius_msg_get_attr_ptr(
55461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
55561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    &buf, &len, NULL) == 0) {
55661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			cache->radius_cui = os_zalloc(len + 1);
55761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (cache->radius_cui)
55861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				os_memcpy(cache->radius_cui, buf, len);
55961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
5601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
562d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		    !cache->psk)
5631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			cache->accepted = HOSTAPD_ACL_REJECT;
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cache->accepted = HOSTAPD_ACL_REJECT;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cache->next = hapd->acl_cache;
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->acl_cache = cache;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_DRIVER_RADIUS_ACL
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					cache->session_timeout);
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_DRIVER_RADIUS_ACL */
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NEED_AP_MLME
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Re-send original authentication frame for 802.11 processing */
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Re-sending authentication frame after "
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "successful RADIUS ACL query");
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL);
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NEED_AP_MLME */
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_DRIVER_RADIUS_ACL */
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt done:
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (prev == NULL)
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->acl_queries = query->next;
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev->next = query->next;
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_acl_query_free(query);
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return RADIUS_RX_PROCESSED;
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_acl_init: Initialize IEEE 802.11 ACL
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hapd: hostapd BSS data
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_acl_init(struct hostapd_data *hapd)
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (radius_client_register(hapd->radius, RADIUS_AUTH,
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   hostapd_acl_recv_radius, hapd))
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hapd: hostapd BSS data
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid hostapd_acl_deinit(struct hostapd_data *hapd)
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_acl_query_data *query, *prev;
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL);
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_acl_cache_free(hapd->acl_cache);
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	query = hapd->acl_queries;
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (query) {
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = query;
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		query = query->next;
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_acl_query_free(prev);
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
634d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
635d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
636d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtvoid hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
637d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
638d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	while (psk) {
639d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		struct hostapd_sta_wpa_psk_short *prev = psk;
640d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		psk = psk->next;
641d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		os_free(prev);
642d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
643d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
644