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