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