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