ieee802_11_auth.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / IEEE 802.11 authentication (ACL) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Access control list for IEEE 802.11 authentication can uses statically 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configured ACL from configuration files or an external RADIUS server. 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Results from external RADIUS queries are cached to allow faster 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication frame processing. 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius_client.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h" 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_drv_ops.h" 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11.h" 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11_auth.h" 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RADIUS_ACL_TIMEOUT 30 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct hostapd_cached_radius_acl { 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_time_t timestamp; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt macaddr addr; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int accepted; /* HOSTAPD_ACL_* */ 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_cached_radius_acl *next; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 session_timeout; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 acct_interim_interval; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vlan_id; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct hostapd_acl_query_data { 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_time_t timestamp; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 radius_id; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt macaddr addr; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *auth_msg; /* IEEE 802.11 authentication frame from station */ 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t auth_msg_len; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_acl_query_data *next; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_cached_radius_acl *prev; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (acl_cache) { 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = acl_cache; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt acl_cache = acl_cache->next; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(prev); 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 *session_timeout, 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 *acct_interim_interval, int *vlan_id) 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_cached_radius_acl *entry; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = hapd->acl_cache; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT) 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; /* entry has expired */ 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT) 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (session_timeout) 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *session_timeout = 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->session_timeout; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (acct_interim_interval) 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *acct_interim_interval = 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->acct_interim_interval; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vlan_id) 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *vlan_id = entry->vlan_id; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return entry->accepted; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_acl_query_free(struct hostapd_acl_query_data *query) 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (query == NULL) 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(query->auth_msg); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(query); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_acl_query_data *query) 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_msg *msg; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[128]; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query->radius_id = radius_client_get_id(hapd->radius); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_make_authenticator(msg, addr, ETH_ALEN); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr)); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf, 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(buf))) { 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not add User-Name"); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr_user_password( 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg, (u8 *) buf, os_strlen(buf), 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->radius->auth_server->shared_secret, 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->radius->auth_server->shared_secret_len)) { 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not add User-Password"); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->own_ip_addr.af == AF_INET && 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address"); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IPV6 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->own_ip_addr.af == AF_INET6 && 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address"); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IPV6 */ 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->nas_identifier && 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) hapd->conf->nas_identifier, 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(hapd->conf->nas_identifier))) { 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier"); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id"); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr)); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id"); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type"); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) buf, os_strlen(buf))) { 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not add Connect-Info"); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fail: 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt radius_msg_free(msg); 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_allowed_address - Check whether a specified STA can be authenticated 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hapd: hostapd BSS data 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: MAC address of the STA 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: Authentication message 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of msg in octets 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @session_timeout: Buffer for returning session timeout (from RADIUS) 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @acct_interim_interval: Buffer for returning account interval (from RADIUS) 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @vlan_id: Buffer for returning VLAN ID 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *msg, size_t len, u32 *session_timeout, 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 *acct_interim_interval, int *vlan_id) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (session_timeout) 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *session_timeout = 0; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (acct_interim_interval) 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *acct_interim_interval = 0; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vlan_id) 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *vlan_id = 0; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_maclist_found(hapd->conf->accept_mac, 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->num_accept_mac, addr, vlan_id)) 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_ACCEPT; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_maclist_found(hapd->conf->deny_mac, 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->conf->num_deny_mac, addr, vlan_id)) 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_REJECT; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED) 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_ACCEPT; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED) 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_REJECT; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) { 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NO_RADIUS 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_REJECT; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NO_RADIUS */ 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_acl_query_data *query; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Check whether ACL cache has an entry for this station */ 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = hostapd_acl_cache_get(hapd, addr, session_timeout, 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt acct_interim_interval, 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt vlan_id); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == HOSTAPD_ACL_ACCEPT || 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res == HOSTAPD_ACL_ACCEPT_TIMEOUT) 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == HOSTAPD_ACL_REJECT) 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_REJECT; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query = hapd->acl_queries; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (query) { 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) { 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* pending query in RADIUS retransmit queue; 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * do not generate a new one */ 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_PENDING; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query = query->next; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!hapd->conf->radius->auth_server) 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_REJECT; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No entry in the cache - query external RADIUS server */ 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query = os_zalloc(sizeof(*query)); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (query == NULL) { 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "malloc for query data failed"); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_REJECT; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt time(&query->timestamp); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(query->addr, addr, ETH_ALEN); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_radius_acl_query(hapd, addr, query)) { 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to send Access-Request " 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for ACL query."); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_acl_query_free(query); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_REJECT; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query->auth_msg = os_malloc(len); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (query->auth_msg == NULL) { 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to allocate memory for " 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "auth frame."); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_acl_query_free(query); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_REJECT; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(query->auth_msg, msg, len); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query->auth_msg_len = len; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query->next = hapd->acl_queries; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->acl_queries = query; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Queued data will be processed in hostapd_acl_recv_radius() 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * when RADIUS server replies to the sent Access-Request. */ 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_PENDING; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return HOSTAPD_ACL_REJECT; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now) 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_cached_radius_acl *prev, *entry, *tmp; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = hapd->acl_cache; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) { 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " has expired.", MAC2STR(entry->addr)); 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev) 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = entry->next; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->acl_cache = entry->next; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_drv_set_radius_acl_expire(hapd, entry->addr); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = entry; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(tmp); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = entry; 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_acl_expire_queries(struct hostapd_data *hapd, 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_time_t now) 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_acl_query_data *prev, *entry, *tmp; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = hapd->acl_queries; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) { 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACL query for " MACSTR 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " has expired.", MAC2STR(entry->addr)); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev) 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = entry->next; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->acl_queries = entry->next; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = entry; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_acl_query_free(tmp); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = entry; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_acl_expire - ACL cache expiration callback 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eloop_ctx: struct hostapd_data * 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @timeout_ctx: Not used 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx) 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = eloop_ctx; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_acl_expire_cache(hapd, now.sec); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_acl_expire_queries(hapd, now.sec); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: RADIUS response message 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req: RADIUS request message 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @shared_secret: RADIUS shared secret 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @shared_secret_len: Length of shared_secret in octets 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Context data (struct hostapd_data *) 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was processed here) or RADIUS_RX_UNKNOWN if not. 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic RadiusRxResult 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidthostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *shared_secret, size_t shared_secret_len, 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *data) 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = data; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_acl_query_data *query, *prev; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_cached_radius_acl *cache; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct radius_hdr *hdr = radius_msg_get_hdr(msg); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query = hapd->acl_queries; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (query) { 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (query->radius_id == hdr->identifier) 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = query; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query = query->next; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (query == NULL) 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_UNKNOWN; 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS " 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message (id=%d)", query->radius_id); 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) { 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have " 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "correct authenticator - dropped\n"); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_INVALID_AUTHENTICATOR; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->code != RADIUS_CODE_ACCESS_REJECT) { 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL " 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "query", hdr->code); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_UNKNOWN; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Insert Accept/Reject info into ACL cache */ 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cache = os_zalloc(sizeof(*cache)); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cache == NULL) { 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry"); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt time(&cache->timestamp); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cache->addr, query->addr, sizeof(cache->addr)); 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cache->session_timeout) == 0) 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cache->accepted = HOSTAPD_ACL_ACCEPT; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_msg_get_attr_int32( 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cache->acct_interim_interval) == 0 && 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cache->acct_interim_interval < 60) { 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Ignored too small " 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Acct-Interim-Interval %d for STA " MACSTR, 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cache->acct_interim_interval, 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(query->addr)); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cache->acct_interim_interval = 0; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cache->vlan_id = radius_msg_get_vlanid(msg); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cache->accepted = HOSTAPD_ACL_REJECT; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cache->next = hapd->acl_cache; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->acl_cache = cache; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_DRIVER_RADIUS_ACL 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted, 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cache->session_timeout); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_DRIVER_RADIUS_ACL */ 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef NEED_AP_MLME 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Re-send original authentication frame for 802.11 processing */ 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Re-sending authentication frame after " 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "successful RADIUS ACL query"); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* NEED_AP_MLME */ 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_DRIVER_RADIUS_ACL */ 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt done: 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev == NULL) 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hapd->acl_queries = query->next; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = query->next; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_acl_query_free(query); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return RADIUS_RX_PROCESSED; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_acl_init: Initialize IEEE 802.11 ACL 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hapd: hostapd BSS data 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_acl_init(struct hostapd_data *hapd) 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (radius_client_register(hapd->radius, RADIUS_AUTH, 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_acl_recv_radius, hapd)) 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hapd: hostapd BSS data 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid hostapd_acl_deinit(struct hostapd_data *hapd) 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_acl_query_data *query, *prev; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RADIUS 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL); 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_acl_cache_free(hapd->acl_cache); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RADIUS */ 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query = hapd->acl_queries; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (query) { 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = query; 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt query = query->next; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_acl_query_free(prev); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 525