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