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_memdup(msg, 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 		query->auth_msg_len = len;
    338 		query->next = hapd->acl_queries;
    339 		hapd->acl_queries = query;
    340 
    341 		/* Queued data will be processed in hostapd_acl_recv_radius()
    342 		 * when RADIUS server replies to the sent Access-Request. */
    343 		return HOSTAPD_ACL_PENDING;
    344 #endif /* CONFIG_NO_RADIUS */
    345 	}
    346 
    347 	return HOSTAPD_ACL_REJECT;
    348 }
    349 
    350 
    351 #ifndef CONFIG_NO_RADIUS
    352 static void hostapd_acl_expire_cache(struct hostapd_data *hapd,
    353 				     struct os_reltime *now)
    354 {
    355 	struct hostapd_cached_radius_acl *prev, *entry, *tmp;
    356 
    357 	prev = NULL;
    358 	entry = hapd->acl_cache;
    359 
    360 	while (entry) {
    361 		if (os_reltime_expired(now, &entry->timestamp,
    362 				       RADIUS_ACL_TIMEOUT)) {
    363 			wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR
    364 				   " has expired.", MAC2STR(entry->addr));
    365 			if (prev)
    366 				prev->next = entry->next;
    367 			else
    368 				hapd->acl_cache = entry->next;
    369 			hostapd_drv_set_radius_acl_expire(hapd, entry->addr);
    370 			tmp = entry;
    371 			entry = entry->next;
    372 			hostapd_acl_cache_free_entry(tmp);
    373 			continue;
    374 		}
    375 
    376 		prev = entry;
    377 		entry = entry->next;
    378 	}
    379 }
    380 
    381 
    382 static void hostapd_acl_expire_queries(struct hostapd_data *hapd,
    383 				       struct os_reltime *now)
    384 {
    385 	struct hostapd_acl_query_data *prev, *entry, *tmp;
    386 
    387 	prev = NULL;
    388 	entry = hapd->acl_queries;
    389 
    390 	while (entry) {
    391 		if (os_reltime_expired(now, &entry->timestamp,
    392 				       RADIUS_ACL_TIMEOUT)) {
    393 			wpa_printf(MSG_DEBUG, "ACL query for " MACSTR
    394 				   " has expired.", MAC2STR(entry->addr));
    395 			if (prev)
    396 				prev->next = entry->next;
    397 			else
    398 				hapd->acl_queries = entry->next;
    399 
    400 			tmp = entry;
    401 			entry = entry->next;
    402 			hostapd_acl_query_free(tmp);
    403 			continue;
    404 		}
    405 
    406 		prev = entry;
    407 		entry = entry->next;
    408 	}
    409 }
    410 
    411 
    412 /**
    413  * hostapd_acl_expire - ACL cache expiration callback
    414  * @hapd: struct hostapd_data *
    415  */
    416 void hostapd_acl_expire(struct hostapd_data *hapd)
    417 {
    418 	struct os_reltime now;
    419 
    420 	os_get_reltime(&now);
    421 	hostapd_acl_expire_cache(hapd, &now);
    422 	hostapd_acl_expire_queries(hapd, &now);
    423 }
    424 
    425 
    426 static void decode_tunnel_passwords(struct hostapd_data *hapd,
    427 				    const u8 *shared_secret,
    428 				    size_t shared_secret_len,
    429 				    struct radius_msg *msg,
    430 				    struct radius_msg *req,
    431 				    struct hostapd_cached_radius_acl *cache)
    432 {
    433 	int passphraselen;
    434 	char *passphrase;
    435 	size_t i;
    436 	struct hostapd_sta_wpa_psk_short *psk;
    437 
    438 	/*
    439 	 * Decode all tunnel passwords as PSK and save them into a linked list.
    440 	 */
    441 	for (i = 0; ; i++) {
    442 		passphrase = radius_msg_get_tunnel_password(
    443 			msg, &passphraselen, shared_secret, shared_secret_len,
    444 			req, i);
    445 		/*
    446 		 * Passphrase is NULL iff there is no i-th Tunnel-Password
    447 		 * attribute in msg.
    448 		 */
    449 		if (passphrase == NULL)
    450 			break;
    451 
    452 		/*
    453 		 * Passphase should be 8..63 chars (to be hashed with SSID)
    454 		 * or 64 chars hex string (no separate hashing with SSID).
    455 		 */
    456 
    457 		if (passphraselen < MIN_PASSPHRASE_LEN ||
    458 		    passphraselen > MAX_PASSPHRASE_LEN + 1)
    459 			goto free_pass;
    460 
    461 		/*
    462 		 * passphrase does not contain the NULL termination.
    463 		 * Add it here as pbkdf2_sha1() requires it.
    464 		 */
    465 		psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
    466 		if (psk) {
    467 			if ((passphraselen == MAX_PASSPHRASE_LEN + 1) &&
    468 			    (hexstr2bin(passphrase, psk->psk, PMK_LEN) < 0)) {
    469 				hostapd_logger(hapd, cache->addr,
    470 					       HOSTAPD_MODULE_RADIUS,
    471 					       HOSTAPD_LEVEL_WARNING,
    472 					       "invalid hex string (%d chars) in Tunnel-Password",
    473 					       passphraselen);
    474 				goto skip;
    475 			} else if (passphraselen <= MAX_PASSPHRASE_LEN) {
    476 				os_memcpy(psk->passphrase, passphrase,
    477 					  passphraselen);
    478 				psk->is_passphrase = 1;
    479 			}
    480 			psk->next = cache->psk;
    481 			cache->psk = psk;
    482 			psk = NULL;
    483 		}
    484 skip:
    485 		os_free(psk);
    486 free_pass:
    487 		os_free(passphrase);
    488 	}
    489 }
    490 
    491 
    492 /**
    493  * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages
    494  * @msg: RADIUS response message
    495  * @req: RADIUS request message
    496  * @shared_secret: RADIUS shared secret
    497  * @shared_secret_len: Length of shared_secret in octets
    498  * @data: Context data (struct hostapd_data *)
    499  * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and
    500  * was processed here) or RADIUS_RX_UNKNOWN if not.
    501  */
    502 static RadiusRxResult
    503 hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
    504 			const u8 *shared_secret, size_t shared_secret_len,
    505 			void *data)
    506 {
    507 	struct hostapd_data *hapd = data;
    508 	struct hostapd_acl_query_data *query, *prev;
    509 	struct hostapd_cached_radius_acl *cache;
    510 	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
    511 	int *untagged, *tagged, *notempty;
    512 
    513 	query = hapd->acl_queries;
    514 	prev = NULL;
    515 	while (query) {
    516 		if (query->radius_id == hdr->identifier)
    517 			break;
    518 		prev = query;
    519 		query = query->next;
    520 	}
    521 	if (query == NULL)
    522 		return RADIUS_RX_UNKNOWN;
    523 
    524 	wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS "
    525 		   "message (id=%d)", query->radius_id);
    526 
    527 	if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
    528 		wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have "
    529 			   "correct authenticator - dropped\n");
    530 		return RADIUS_RX_INVALID_AUTHENTICATOR;
    531 	}
    532 
    533 	if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
    534 	    hdr->code != RADIUS_CODE_ACCESS_REJECT) {
    535 		wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL "
    536 			   "query", hdr->code);
    537 		return RADIUS_RX_UNKNOWN;
    538 	}
    539 
    540 	/* Insert Accept/Reject info into ACL cache */
    541 	cache = os_zalloc(sizeof(*cache));
    542 	if (cache == NULL) {
    543 		wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
    544 		goto done;
    545 	}
    546 	os_get_reltime(&cache->timestamp);
    547 	os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
    548 	if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
    549 		u8 *buf;
    550 		size_t len;
    551 
    552 		if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
    553 					      &cache->session_timeout) == 0)
    554 			cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
    555 		else
    556 			cache->accepted = HOSTAPD_ACL_ACCEPT;
    557 
    558 		if (radius_msg_get_attr_int32(
    559 			    msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
    560 			    &cache->acct_interim_interval) == 0 &&
    561 		    cache->acct_interim_interval < 60) {
    562 			wpa_printf(MSG_DEBUG, "Ignored too small "
    563 				   "Acct-Interim-Interval %d for STA " MACSTR,
    564 				   cache->acct_interim_interval,
    565 				   MAC2STR(query->addr));
    566 			cache->acct_interim_interval = 0;
    567 		}
    568 
    569 		notempty = &cache->vlan_id.notempty;
    570 		untagged = &cache->vlan_id.untagged;
    571 		tagged = cache->vlan_id.tagged;
    572 		*notempty = !!radius_msg_get_vlanid(msg, untagged,
    573 						    MAX_NUM_TAGGED_VLAN,
    574 						    tagged);
    575 
    576 		decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
    577 					msg, req, cache);
    578 
    579 		if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME,
    580 					    &buf, &len, NULL) == 0) {
    581 			cache->identity = os_zalloc(len + 1);
    582 			if (cache->identity)
    583 				os_memcpy(cache->identity, buf, len);
    584 		}
    585 		if (radius_msg_get_attr_ptr(
    586 			    msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
    587 			    &buf, &len, NULL) == 0) {
    588 			cache->radius_cui = os_zalloc(len + 1);
    589 			if (cache->radius_cui)
    590 				os_memcpy(cache->radius_cui, buf, len);
    591 		}
    592 
    593 		if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
    594 		    !cache->psk)
    595 			cache->accepted = HOSTAPD_ACL_REJECT;
    596 
    597 		if (cache->vlan_id.notempty &&
    598 		    !hostapd_vlan_valid(hapd->conf->vlan, &cache->vlan_id)) {
    599 			hostapd_logger(hapd, query->addr,
    600 				       HOSTAPD_MODULE_RADIUS,
    601 				       HOSTAPD_LEVEL_INFO,
    602 				       "Invalid VLAN %d%s received from RADIUS server",
    603 				       cache->vlan_id.untagged,
    604 				       cache->vlan_id.tagged[0] ? "+" : "");
    605 			os_memset(&cache->vlan_id, 0, sizeof(cache->vlan_id));
    606 		}
    607 		if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
    608 		    !cache->vlan_id.notempty)
    609 			cache->accepted = HOSTAPD_ACL_REJECT;
    610 	} else
    611 		cache->accepted = HOSTAPD_ACL_REJECT;
    612 	cache->next = hapd->acl_cache;
    613 	hapd->acl_cache = cache;
    614 
    615 #ifdef CONFIG_DRIVER_RADIUS_ACL
    616 	hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
    617 					cache->session_timeout);
    618 #else /* CONFIG_DRIVER_RADIUS_ACL */
    619 #ifdef NEED_AP_MLME
    620 	/* Re-send original authentication frame for 802.11 processing */
    621 	wpa_printf(MSG_DEBUG, "Re-sending authentication frame after "
    622 		   "successful RADIUS ACL query");
    623 	ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL);
    624 #endif /* NEED_AP_MLME */
    625 #endif /* CONFIG_DRIVER_RADIUS_ACL */
    626 
    627  done:
    628 	if (prev == NULL)
    629 		hapd->acl_queries = query->next;
    630 	else
    631 		prev->next = query->next;
    632 
    633 	hostapd_acl_query_free(query);
    634 
    635 	return RADIUS_RX_PROCESSED;
    636 }
    637 #endif /* CONFIG_NO_RADIUS */
    638 
    639 
    640 /**
    641  * hostapd_acl_init: Initialize IEEE 802.11 ACL
    642  * @hapd: hostapd BSS data
    643  * Returns: 0 on success, -1 on failure
    644  */
    645 int hostapd_acl_init(struct hostapd_data *hapd)
    646 {
    647 #ifndef CONFIG_NO_RADIUS
    648 	if (radius_client_register(hapd->radius, RADIUS_AUTH,
    649 				   hostapd_acl_recv_radius, hapd))
    650 		return -1;
    651 #endif /* CONFIG_NO_RADIUS */
    652 
    653 	return 0;
    654 }
    655 
    656 
    657 /**
    658  * hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL
    659  * @hapd: hostapd BSS data
    660  */
    661 void hostapd_acl_deinit(struct hostapd_data *hapd)
    662 {
    663 	struct hostapd_acl_query_data *query, *prev;
    664 
    665 #ifndef CONFIG_NO_RADIUS
    666 	hostapd_acl_cache_free(hapd->acl_cache);
    667 	hapd->acl_cache = NULL;
    668 #endif /* CONFIG_NO_RADIUS */
    669 
    670 	query = hapd->acl_queries;
    671 	hapd->acl_queries = NULL;
    672 	while (query) {
    673 		prev = query;
    674 		query = query->next;
    675 		hostapd_acl_query_free(prev);
    676 	}
    677 }
    678 
    679 
    680 void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
    681 {
    682 	if (psk && psk->ref) {
    683 		/* This will be freed when the last reference is dropped. */
    684 		psk->ref--;
    685 		return;
    686 	}
    687 
    688 	while (psk) {
    689 		struct hostapd_sta_wpa_psk_short *prev = psk;
    690 		psk = psk->next;
    691 		os_free(prev);
    692 	}
    693 }
    694