Home | History | Annotate | Download | only in ap
      1 /*
      2  * hostapd / IEEE 802.11 authentication (ACL)
      3  * Copyright (c) 2003-2012, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  *
      8  * Access control list for IEEE 802.11 authentication can uses statically
      9  * configured ACL from configuration files or an external RADIUS server.
     10  * Results from external RADIUS queries are cached to allow faster
     11  * authentication frame processing.
     12  */
     13 
     14 #include "utils/includes.h"
     15 
     16 #include "utils/common.h"
     17 #include "utils/eloop.h"
     18 #include "radius/radius.h"
     19 #include "radius/radius_client.h"
     20 #include "hostapd.h"
     21 #include "ap_config.h"
     22 #include "ap_drv_ops.h"
     23 #include "ieee802_11.h"
     24 #include "ieee802_1x.h"
     25 #include "ieee802_11_auth.h"
     26 
     27 #define RADIUS_ACL_TIMEOUT 30
     28 
     29 
     30 struct hostapd_cached_radius_acl {
     31 	struct os_reltime timestamp;
     32 	macaddr addr;
     33 	int accepted; /* HOSTAPD_ACL_* */
     34 	struct hostapd_cached_radius_acl *next;
     35 	u32 session_timeout;
     36 	u32 acct_interim_interval;
     37 	struct vlan_description vlan_id;
     38 	struct hostapd_sta_wpa_psk_short *psk;
     39 	char *identity;
     40 	char *radius_cui;
     41 };
     42 
     43 
     44 struct hostapd_acl_query_data {
     45 	struct os_reltime timestamp;
     46 	u8 radius_id;
     47 	macaddr addr;
     48 	u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
     49 	size_t auth_msg_len;
     50 	struct hostapd_acl_query_data *next;
     51 };
     52 
     53 
     54 #ifndef CONFIG_NO_RADIUS
     55 static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e)
     56 {
     57 	os_free(e->identity);
     58 	os_free(e->radius_cui);
     59 	hostapd_free_psk_list(e->psk);
     60 	os_free(e);
     61 }
     62 
     63 
     64 static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
     65 {
     66 	struct hostapd_cached_radius_acl *prev;
     67 
     68 	while (acl_cache) {
     69 		prev = acl_cache;
     70 		acl_cache = acl_cache->next;
     71 		hostapd_acl_cache_free_entry(prev);
     72 	}
     73 }
     74 
     75 
     76 static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
     77 			  struct hostapd_sta_wpa_psk_short *src)
     78 {
     79 	if (!psk)
     80 		return;
     81 
     82 	if (src)
     83 		src->ref++;
     84 
     85 	*psk = src;
     86 }
     87 
     88 
     89 static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
     90 				 u32 *session_timeout,
     91 				 u32 *acct_interim_interval,
     92 				 struct vlan_description *vlan_id,
     93 				 struct hostapd_sta_wpa_psk_short **psk,
     94 				 char **identity, char **radius_cui)
     95 {
     96 	struct hostapd_cached_radius_acl *entry;
     97 	struct os_reltime now;
     98 
     99 	os_get_reltime(&now);
    100 
    101 	for (entry = hapd->acl_cache; entry; entry = entry->next) {
    102 		if (os_memcmp(entry->addr, addr, ETH_ALEN) != 0)
    103 			continue;
    104 
    105 		if (os_reltime_expired(&now, &entry->timestamp,
    106 				       RADIUS_ACL_TIMEOUT))
    107 			return -1; /* entry has expired */
    108 		if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
    109 			if (session_timeout)
    110 				*session_timeout = entry->session_timeout;
    111 		if (acct_interim_interval)
    112 			*acct_interim_interval =
    113 				entry->acct_interim_interval;
    114 		if (vlan_id)
    115 			*vlan_id = entry->vlan_id;
    116 		copy_psk_list(psk, entry->psk);
    117 		if (identity) {
    118 			if (entry->identity)
    119 				*identity = os_strdup(entry->identity);
    120 			else
    121 				*identity = NULL;
    122 		}
    123 		if (radius_cui) {
    124 			if (entry->radius_cui)
    125 				*radius_cui = os_strdup(entry->radius_cui);
    126 			else
    127 				*radius_cui = NULL;
    128 		}
    129 		return entry->accepted;
    130 	}
    131 
    132 	return -1;
    133 }
    134 #endif /* CONFIG_NO_RADIUS */
    135 
    136 
    137 static void hostapd_acl_query_free(struct hostapd_acl_query_data *query)
    138 {
    139 	if (query == NULL)
    140 		return;
    141 	os_free(query->auth_msg);
    142 	os_free(query);
    143 }
    144 
    145 
    146 #ifndef CONFIG_NO_RADIUS
    147 static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
    148 				    struct hostapd_acl_query_data *query)
    149 {
    150 	struct radius_msg *msg;
    151 	char buf[128];
    152 
    153 	query->radius_id = radius_client_get_id(hapd->radius);
    154 	msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id);
    155 	if (msg == NULL)
    156 		return -1;
    157 
    158 	if (radius_msg_make_authenticator(msg) < 0) {
    159 		wpa_printf(MSG_INFO, "Could not make Request Authenticator");
    160 		goto fail;
    161 	}
    162 
    163 	os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr));
    164 	if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf,
    165 				 os_strlen(buf))) {
    166 		wpa_printf(MSG_DEBUG, "Could not add User-Name");
    167 		goto fail;
    168 	}
    169 
    170 	if (!radius_msg_add_attr_user_password(
    171 		    msg, (u8 *) buf, os_strlen(buf),
    172 		    hapd->conf->radius->auth_server->shared_secret,
    173 		    hapd->conf->radius->auth_server->shared_secret_len)) {
    174 		wpa_printf(MSG_DEBUG, "Could not add User-Password");
    175 		goto fail;
    176 	}
    177 
    178 	if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr,
    179 				   NULL, msg) < 0)
    180 		goto fail;
    181 
    182 	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
    183 		    MAC2STR(addr));
    184 	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
    185 				 (u8 *) buf, os_strlen(buf))) {
    186 		wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id");
    187 		goto fail;
    188 	}
    189 
    190 	os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
    191 	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
    192 				 (u8 *) buf, os_strlen(buf))) {
    193 		wpa_printf(MSG_DEBUG, "Could not add Connect-Info");
    194 		goto fail;
    195 	}
    196 
    197 	if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0)
    198 		goto fail;
    199 	return 0;
    200 
    201  fail:
    202 	radius_msg_free(msg);
    203 	return -1;
    204 }
    205 #endif /* CONFIG_NO_RADIUS */
    206 
    207 
    208 /**
    209  * hostapd_check_acl - Check a specified STA against accept/deny ACLs
    210  * @hapd: hostapd BSS data
    211  * @addr: MAC address of the STA
    212  * @vlan_id: Buffer for returning VLAN ID
    213  * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
    214  */
    215 int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr,
    216 		      struct vlan_description *vlan_id)
    217 {
    218 	if (hostapd_maclist_found(hapd->conf->accept_mac,
    219 				  hapd->conf->num_accept_mac, addr, vlan_id))
    220 		return HOSTAPD_ACL_ACCEPT;
    221 
    222 	if (hostapd_maclist_found(hapd->conf->deny_mac,
    223 				  hapd->conf->num_deny_mac, addr, vlan_id))
    224 		return HOSTAPD_ACL_REJECT;
    225 
    226 	if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED)
    227 		return HOSTAPD_ACL_ACCEPT;
    228 	if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED)
    229 		return HOSTAPD_ACL_REJECT;
    230 
    231 	return HOSTAPD_ACL_PENDING;
    232 }
    233 
    234 
    235 /**
    236  * hostapd_allowed_address - Check whether a specified STA can be authenticated
    237  * @hapd: hostapd BSS data
    238  * @addr: MAC address of the STA
    239  * @msg: Authentication message
    240  * @len: Length of msg in octets
    241  * @session_timeout: Buffer for returning session timeout (from RADIUS)
    242  * @acct_interim_interval: Buffer for returning account interval (from RADIUS)
    243  * @vlan_id: Buffer for returning VLAN ID
    244  * @psk: Linked list buffer for returning WPA PSK
    245  * @identity: Buffer for returning identity (from RADIUS)
    246  * @radius_cui: Buffer for returning CUI (from RADIUS)
    247  * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
    248  *
    249  * The caller is responsible for freeing the returned *identity and *radius_cui
    250  * values with os_free().
    251  */
    252 int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
    253 			    const u8 *msg, size_t len, u32 *session_timeout,
    254 			    u32 *acct_interim_interval,
    255 			    struct vlan_description *vlan_id,
    256 			    struct hostapd_sta_wpa_psk_short **psk,
    257 			    char **identity, char **radius_cui)
    258 {
    259 	int res;
    260 
    261 	if (session_timeout)
    262 		*session_timeout = 0;
    263 	if (acct_interim_interval)
    264 		*acct_interim_interval = 0;
    265 	if (vlan_id)
    266 		os_memset(vlan_id, 0, sizeof(*vlan_id));
    267 	if (psk)
    268 		*psk = NULL;
    269 	if (identity)
    270 		*identity = NULL;
    271 	if (radius_cui)
    272 		*radius_cui = NULL;
    273 
    274 	res = hostapd_check_acl(hapd, addr, vlan_id);
    275 	if (res != HOSTAPD_ACL_PENDING)
    276 		return res;
    277 
    278 	if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) {
    279 #ifdef CONFIG_NO_RADIUS
    280 		return HOSTAPD_ACL_REJECT;
    281 #else /* CONFIG_NO_RADIUS */
    282 		struct hostapd_acl_query_data *query;
    283 
    284 		/* Check whether ACL cache has an entry for this station */
    285 		res = hostapd_acl_cache_get(hapd, addr, session_timeout,
    286 					    acct_interim_interval, vlan_id, psk,
    287 					    identity, radius_cui);
    288 		if (res == HOSTAPD_ACL_ACCEPT ||
    289 		    res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
    290 			return res;
    291 		if (res == HOSTAPD_ACL_REJECT)
    292 			return HOSTAPD_ACL_REJECT;
    293 
    294 		query = hapd->acl_queries;
    295 		while (query) {
    296 			if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
    297 				/* pending query in RADIUS retransmit queue;
    298 				 * do not generate a new one */
    299 				if (identity) {
    300 					os_free(*identity);
    301 					*identity = NULL;
    302 				}
    303 				if (radius_cui) {
    304 					os_free(*radius_cui);
    305 					*radius_cui = NULL;
    306 				}
    307 				return HOSTAPD_ACL_PENDING;
    308 			}
    309 			query = query->next;
    310 		}
    311 
    312 		if (!hapd->conf->radius->auth_server)
    313 			return HOSTAPD_ACL_REJECT;
    314 
    315 		/* No entry in the cache - query external RADIUS server */
    316 		query = os_zalloc(sizeof(*query));
    317 		if (query == NULL) {
    318 			wpa_printf(MSG_ERROR, "malloc for query data failed");
    319 			return HOSTAPD_ACL_REJECT;
    320 		}
    321 		os_get_reltime(&query->timestamp);
    322 		os_memcpy(query->addr, addr, ETH_ALEN);
    323 		if (hostapd_radius_acl_query(hapd, addr, query)) {
    324 			wpa_printf(MSG_DEBUG, "Failed to send Access-Request "
    325 				   "for ACL query.");
    326 			hostapd_acl_query_free(query);
    327 			return HOSTAPD_ACL_REJECT;
    328 		}
    329 
    330 		query->auth_msg = os_malloc(len);
    331 		if (query->auth_msg == NULL) {
    332 			wpa_printf(MSG_ERROR, "Failed to allocate memory for "
    333 				   "auth frame.");
    334 			hostapd_acl_query_free(query);
    335 			return HOSTAPD_ACL_REJECT;
    336 		}
    337 		os_memcpy(query->auth_msg, msg, len);
    338 		query->auth_msg_len = len;
    339 		query->next = hapd->acl_queries;
    340 		hapd->acl_queries = query;
    341 
    342 		/* Queued data will be processed in hostapd_acl_recv_radius()
    343 		 * when RADIUS server replies to the sent Access-Request. */
    344 		return HOSTAPD_ACL_PENDING;
    345 #endif /* CONFIG_NO_RADIUS */
    346 	}
    347 
    348 	return HOSTAPD_ACL_REJECT;
    349 }
    350 
    351 
    352 #ifndef CONFIG_NO_RADIUS
    353 static void hostapd_acl_expire_cache(struct hostapd_data *hapd,
    354 				     struct os_reltime *now)
    355 {
    356 	struct hostapd_cached_radius_acl *prev, *entry, *tmp;
    357 
    358 	prev = NULL;
    359 	entry = hapd->acl_cache;
    360 
    361 	while (entry) {
    362 		if (os_reltime_expired(now, &entry->timestamp,
    363 				       RADIUS_ACL_TIMEOUT)) {
    364 			wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR
    365 				   " has expired.", MAC2STR(entry->addr));
    366 			if (prev)
    367 				prev->next = entry->next;
    368 			else
    369 				hapd->acl_cache = entry->next;
    370 			hostapd_drv_set_radius_acl_expire(hapd, entry->addr);
    371 			tmp = entry;
    372 			entry = entry->next;
    373 			hostapd_acl_cache_free_entry(tmp);
    374 			continue;
    375 		}
    376 
    377 		prev = entry;
    378 		entry = entry->next;
    379 	}
    380 }
    381 
    382 
    383 static void hostapd_acl_expire_queries(struct hostapd_data *hapd,
    384 				       struct os_reltime *now)
    385 {
    386 	struct hostapd_acl_query_data *prev, *entry, *tmp;
    387 
    388 	prev = NULL;
    389 	entry = hapd->acl_queries;
    390 
    391 	while (entry) {
    392 		if (os_reltime_expired(now, &entry->timestamp,
    393 				       RADIUS_ACL_TIMEOUT)) {
    394 			wpa_printf(MSG_DEBUG, "ACL query for " MACSTR
    395 				   " has expired.", MAC2STR(entry->addr));
    396 			if (prev)
    397 				prev->next = entry->next;
    398 			else
    399 				hapd->acl_queries = entry->next;
    400 
    401 			tmp = entry;
    402 			entry = entry->next;
    403 			hostapd_acl_query_free(tmp);
    404 			continue;
    405 		}
    406 
    407 		prev = entry;
    408 		entry = entry->next;
    409 	}
    410 }
    411 
    412 
    413 /**
    414  * hostapd_acl_expire - ACL cache expiration callback
    415  * @hapd: struct hostapd_data *
    416  */
    417 void hostapd_acl_expire(struct hostapd_data *hapd)
    418 {
    419 	struct os_reltime now;
    420 
    421 	os_get_reltime(&now);
    422 	hostapd_acl_expire_cache(hapd, &now);
    423 	hostapd_acl_expire_queries(hapd, &now);
    424 }
    425 
    426 
    427 static void decode_tunnel_passwords(struct hostapd_data *hapd,
    428 				    const u8 *shared_secret,
    429 				    size_t shared_secret_len,
    430 				    struct radius_msg *msg,
    431 				    struct radius_msg *req,
    432 				    struct hostapd_cached_radius_acl *cache)
    433 {
    434 	int passphraselen;
    435 	char *passphrase;
    436 	size_t i;
    437 	struct hostapd_sta_wpa_psk_short *psk;
    438 
    439 	/*
    440 	 * Decode all tunnel passwords as PSK and save them into a linked list.
    441 	 */
    442 	for (i = 0; ; i++) {
    443 		passphrase = radius_msg_get_tunnel_password(
    444 			msg, &passphraselen, shared_secret, shared_secret_len,
    445 			req, i);
    446 		/*
    447 		 * Passphrase is NULL iff there is no i-th Tunnel-Password
    448 		 * attribute in msg.
    449 		 */
    450 		if (passphrase == NULL)
    451 			break;
    452 
    453 		/*
    454 		 * Passphase should be 8..63 chars (to be hashed with SSID)
    455 		 * or 64 chars hex string (no separate hashing with SSID).
    456 		 */
    457 
    458 		if (passphraselen < MIN_PASSPHRASE_LEN ||
    459 		    passphraselen > MAX_PASSPHRASE_LEN + 1)
    460 			goto free_pass;
    461 
    462 		/*
    463 		 * passphrase does not contain the NULL termination.
    464 		 * Add it here as pbkdf2_sha1() requires it.
    465 		 */
    466 		psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
    467 		if (psk) {
    468 			if ((passphraselen == MAX_PASSPHRASE_LEN + 1) &&
    469 			    (hexstr2bin(passphrase, psk->psk, PMK_LEN) < 0)) {
    470 				hostapd_logger(hapd, cache->addr,
    471 					       HOSTAPD_MODULE_RADIUS,
    472 					       HOSTAPD_LEVEL_WARNING,
    473 					       "invalid hex string (%d chars) in Tunnel-Password",
    474 					       passphraselen);
    475 				goto skip;
    476 			} else if (passphraselen <= MAX_PASSPHRASE_LEN) {
    477 				os_memcpy(psk->passphrase, passphrase,
    478 					  passphraselen);
    479 				psk->is_passphrase = 1;
    480 			}
    481 			psk->next = cache->psk;
    482 			cache->psk = psk;
    483 			psk = NULL;
    484 		}
    485 skip:
    486 		os_free(psk);
    487 free_pass:
    488 		os_free(passphrase);
    489 	}
    490 }
    491 
    492 
    493 /**
    494  * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages
    495  * @msg: RADIUS response message
    496  * @req: RADIUS request message
    497  * @shared_secret: RADIUS shared secret
    498  * @shared_secret_len: Length of shared_secret in octets
    499  * @data: Context data (struct hostapd_data *)
    500  * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and
    501  * was processed here) or RADIUS_RX_UNKNOWN if not.
    502  */
    503 static RadiusRxResult
    504 hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
    505 			const u8 *shared_secret, size_t shared_secret_len,
    506 			void *data)
    507 {
    508 	struct hostapd_data *hapd = data;
    509 	struct hostapd_acl_query_data *query, *prev;
    510 	struct hostapd_cached_radius_acl *cache;
    511 	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
    512 	int *untagged, *tagged, *notempty;
    513 
    514 	query = hapd->acl_queries;
    515 	prev = NULL;
    516 	while (query) {
    517 		if (query->radius_id == hdr->identifier)
    518 			break;
    519 		prev = query;
    520 		query = query->next;
    521 	}
    522 	if (query == NULL)
    523 		return RADIUS_RX_UNKNOWN;
    524 
    525 	wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS "
    526 		   "message (id=%d)", query->radius_id);
    527 
    528 	if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
    529 		wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have "
    530 			   "correct authenticator - dropped\n");
    531 		return RADIUS_RX_INVALID_AUTHENTICATOR;
    532 	}
    533 
    534 	if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
    535 	    hdr->code != RADIUS_CODE_ACCESS_REJECT) {
    536 		wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL "
    537 			   "query", hdr->code);
    538 		return RADIUS_RX_UNKNOWN;
    539 	}
    540 
    541 	/* Insert Accept/Reject info into ACL cache */
    542 	cache = os_zalloc(sizeof(*cache));
    543 	if (cache == NULL) {
    544 		wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
    545 		goto done;
    546 	}
    547 	os_get_reltime(&cache->timestamp);
    548 	os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
    549 	if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
    550 		u8 *buf;
    551 		size_t len;
    552 
    553 		if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
    554 					      &cache->session_timeout) == 0)
    555 			cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
    556 		else
    557 			cache->accepted = HOSTAPD_ACL_ACCEPT;
    558 
    559 		if (radius_msg_get_attr_int32(
    560 			    msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
    561 			    &cache->acct_interim_interval) == 0 &&
    562 		    cache->acct_interim_interval < 60) {
    563 			wpa_printf(MSG_DEBUG, "Ignored too small "
    564 				   "Acct-Interim-Interval %d for STA " MACSTR,
    565 				   cache->acct_interim_interval,
    566 				   MAC2STR(query->addr));
    567 			cache->acct_interim_interval = 0;
    568 		}
    569 
    570 		notempty = &cache->vlan_id.notempty;
    571 		untagged = &cache->vlan_id.untagged;
    572 		tagged = cache->vlan_id.tagged;
    573 		*notempty = !!radius_msg_get_vlanid(msg, untagged,
    574 						    MAX_NUM_TAGGED_VLAN,
    575 						    tagged);
    576 
    577 		decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
    578 					msg, req, cache);
    579 
    580 		if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
    581 					    &buf, &len, NULL) == 0) {
    582 			cache->identity = os_zalloc(len + 1);
    583 			if (cache->identity)
    584 				os_memcpy(cache->identity, buf, len);
    585 		}
    586 		if (radius_msg_get_attr_ptr(
    587 			    msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
    588 			    &buf, &len, NULL) == 0) {
    589 			cache->radius_cui = os_zalloc(len + 1);
    590 			if (cache->radius_cui)
    591 				os_memcpy(cache->radius_cui, buf, len);
    592 		}
    593 
    594 		if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
    595 		    !cache->psk)
    596 			cache->accepted = HOSTAPD_ACL_REJECT;
    597 
    598 		if (cache->vlan_id.notempty &&
    599 		    !hostapd_vlan_valid(hapd->conf->vlan, &cache->vlan_id)) {
    600 			hostapd_logger(hapd, query->addr,
    601 				       HOSTAPD_MODULE_RADIUS,
    602 				       HOSTAPD_LEVEL_INFO,
    603 				       "Invalid VLAN %d%s received from RADIUS server",
    604 				       cache->vlan_id.untagged,
    605 				       cache->vlan_id.tagged[0] ? "+" : "");
    606 			os_memset(&cache->vlan_id, 0, sizeof(cache->vlan_id));
    607 		}
    608 		if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
    609 		    !cache->vlan_id.notempty)
    610 			cache->accepted = HOSTAPD_ACL_REJECT;
    611 	} else
    612 		cache->accepted = HOSTAPD_ACL_REJECT;
    613 	cache->next = hapd->acl_cache;
    614 	hapd->acl_cache = cache;
    615 
    616 #ifdef CONFIG_DRIVER_RADIUS_ACL
    617 	hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
    618 					cache->session_timeout);
    619 #else /* CONFIG_DRIVER_RADIUS_ACL */
    620 #ifdef NEED_AP_MLME
    621 	/* Re-send original authentication frame for 802.11 processing */
    622 	wpa_printf(MSG_DEBUG, "Re-sending authentication frame after "
    623 		   "successful RADIUS ACL query");
    624 	ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL);
    625 #endif /* NEED_AP_MLME */
    626 #endif /* CONFIG_DRIVER_RADIUS_ACL */
    627 
    628  done:
    629 	if (prev == NULL)
    630 		hapd->acl_queries = query->next;
    631 	else
    632 		prev->next = query->next;
    633 
    634 	hostapd_acl_query_free(query);
    635 
    636 	return RADIUS_RX_PROCESSED;
    637 }
    638 #endif /* CONFIG_NO_RADIUS */
    639 
    640 
    641 /**
    642  * hostapd_acl_init: Initialize IEEE 802.11 ACL
    643  * @hapd: hostapd BSS data
    644  * Returns: 0 on success, -1 on failure
    645  */
    646 int hostapd_acl_init(struct hostapd_data *hapd)
    647 {
    648 #ifndef CONFIG_NO_RADIUS
    649 	if (radius_client_register(hapd->radius, RADIUS_AUTH,
    650 				   hostapd_acl_recv_radius, hapd))
    651 		return -1;
    652 #endif /* CONFIG_NO_RADIUS */
    653 
    654 	return 0;
    655 }
    656 
    657 
    658 /**
    659  * hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL
    660  * @hapd: hostapd BSS data
    661  */
    662 void hostapd_acl_deinit(struct hostapd_data *hapd)
    663 {
    664 	struct hostapd_acl_query_data *query, *prev;
    665 
    666 #ifndef CONFIG_NO_RADIUS
    667 	hostapd_acl_cache_free(hapd->acl_cache);
    668 	hapd->acl_cache = NULL;
    669 #endif /* CONFIG_NO_RADIUS */
    670 
    671 	query = hapd->acl_queries;
    672 	hapd->acl_queries = NULL;
    673 	while (query) {
    674 		prev = query;
    675 		query = query->next;
    676 		hostapd_acl_query_free(prev);
    677 	}
    678 }
    679 
    680 
    681 void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
    682 {
    683 	if (psk && psk->ref) {
    684 		/* This will be freed when the last reference is dropped. */
    685 		psk->ref--;
    686 		return;
    687 	}
    688 
    689 	while (psk) {
    690 		struct hostapd_sta_wpa_psk_short *prev = psk;
    691 		psk = psk->next;
    692 		os_free(prev);
    693 	}
    694 }
    695