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