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