diff options
Diffstat (limited to 'src/ap/ieee802_11_auth.c')
-rw-r--r-- | src/ap/ieee802_11_auth.c | 147 |
1 files changed, 84 insertions, 63 deletions
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c index 0c4c5f32..63ae3452 100644 --- a/src/ap/ieee802_11_auth.c +++ b/src/ap/ieee802_11_auth.c @@ -1,6 +1,6 @@ /* * hostapd / IEEE 802.11 authentication (ACL) - * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -22,6 +22,7 @@ #include "ap_config.h" #include "ap_drv_ops.h" #include "ieee802_11.h" +#include "ieee802_1x.h" #include "ieee802_11_auth.h" #define RADIUS_ACL_TIMEOUT 30 @@ -37,6 +38,8 @@ struct hostapd_cached_radius_acl { int vlan_id; int has_psk; u8 psk[PMK_LEN]; + char *identity; + char *radius_cui; }; @@ -51,6 +54,14 @@ struct hostapd_acl_query_data { #ifndef CONFIG_NO_RADIUS +static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e) +{ + os_free(e->identity); + os_free(e->radius_cui); + os_free(e); +} + + static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) { struct hostapd_cached_radius_acl *prev; @@ -58,7 +69,7 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) while (acl_cache) { prev = acl_cache; acl_cache = acl_cache->next; - os_free(prev); + hostapd_acl_cache_free_entry(prev); } } @@ -66,35 +77,45 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, u32 *session_timeout, u32 *acct_interim_interval, int *vlan_id, - u8 *psk, int *has_psk) + u8 *psk, int *has_psk, char **identity, + char **radius_cui) { struct hostapd_cached_radius_acl *entry; struct os_time now; os_get_time(&now); - entry = hapd->acl_cache; - while (entry) { - if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { - if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT) - return -1; /* entry has expired */ - if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT) - if (session_timeout) - *session_timeout = - entry->session_timeout; - if (acct_interim_interval) - *acct_interim_interval = - entry->acct_interim_interval; - if (vlan_id) - *vlan_id = entry->vlan_id; - if (psk) - os_memcpy(psk, entry->psk, PMK_LEN); - if (has_psk) - *has_psk = entry->has_psk; - return entry->accepted; - } + for (entry = hapd->acl_cache; entry; entry = entry->next) { + if (os_memcmp(entry->addr, addr, ETH_ALEN) != 0) + continue; - entry = entry->next; + if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT) + return -1; /* entry has expired */ + if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT) + if (session_timeout) + *session_timeout = entry->session_timeout; + if (acct_interim_interval) + *acct_interim_interval = + entry->acct_interim_interval; + if (vlan_id) + *vlan_id = entry->vlan_id; + if (psk) + os_memcpy(psk, entry->psk, PMK_LEN); + if (has_psk) + *has_psk = entry->has_psk; + if (identity) { + if (entry->identity) + *identity = os_strdup(entry->identity); + else + *identity = NULL; + } + if (radius_cui) { + if (entry->radius_cui) + *radius_cui = os_strdup(entry->radius_cui); + else + *radius_cui = NULL; + } + return entry->accepted; } return -1; @@ -140,37 +161,9 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, goto fail; } - if (hapd->conf->own_ip_addr.af == AF_INET && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { - wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (hapd->conf->own_ip_addr.af == AF_INET6 && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { - wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address"); - goto fail; - } -#endif /* CONFIG_IPV6 */ - - if (hapd->conf->nas_identifier && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, - (u8 *) hapd->conf->nas_identifier, - os_strlen(hapd->conf->nas_identifier))) { - wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier"); + if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr, + NULL, msg) < 0) goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", - MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id"); - goto fail; - } os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(addr)); @@ -180,12 +173,6 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, goto fail; } - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, - RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { - wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type"); - goto fail; - } - os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, (u8 *) buf, os_strlen(buf))) { @@ -215,12 +202,18 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, * @vlan_id: Buffer for returning VLAN ID * @psk: Buffer for returning WPA PSK * @has_psk: Buffer for indicating whether psk was filled + * @identity: Buffer for returning identity (from RADIUS) + * @radius_cui: Buffer for returning CUI (from RADIUS) * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING + * + * The caller is responsible for freeing the returned *identity and *radius_cui + * values with os_free(). */ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, const u8 *msg, size_t len, u32 *session_timeout, u32 *acct_interim_interval, int *vlan_id, - u8 *psk, int *has_psk) + u8 *psk, int *has_psk, char **identity, + char **radius_cui) { if (session_timeout) *session_timeout = 0; @@ -232,6 +225,10 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, *has_psk = 0; if (psk) os_memset(psk, 0, PMK_LEN); + if (identity) + *identity = NULL; + if (radius_cui) + *radius_cui = NULL; if (hostapd_maclist_found(hapd->conf->accept_mac, hapd->conf->num_accept_mac, addr, vlan_id)) @@ -256,7 +253,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, /* Check whether ACL cache has an entry for this station */ int res = hostapd_acl_cache_get(hapd, addr, session_timeout, acct_interim_interval, - vlan_id, psk, has_psk); + vlan_id, psk, has_psk, + identity, radius_cui); if (res == HOSTAPD_ACL_ACCEPT || res == HOSTAPD_ACL_ACCEPT_TIMEOUT) return res; @@ -268,6 +266,14 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) { /* pending query in RADIUS retransmit queue; * do not generate a new one */ + if (identity) { + os_free(*identity); + *identity = NULL; + } + if (radius_cui) { + os_free(*radius_cui); + *radius_cui = NULL; + } return HOSTAPD_ACL_PENDING; } query = query->next; @@ -333,7 +339,7 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now) hostapd_drv_set_radius_acl_expire(hapd, entry->addr); tmp = entry; entry = entry->next; - os_free(tmp); + hostapd_acl_cache_free_entry(tmp); continue; } @@ -450,6 +456,8 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { int passphraselen; char *passphrase; + u8 *buf; + size_t len; if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, &cache->session_timeout) == 0) @@ -491,6 +499,19 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, } os_free(passphrase); } + if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, + &buf, &len, NULL) == 0) { + cache->identity = os_zalloc(len + 1); + if (cache->identity) + os_memcpy(cache->identity, buf, len); + } + if (radius_msg_get_attr_ptr( + msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, + &buf, &len, NULL) == 0) { + cache->radius_cui = os_zalloc(len + 1); + if (cache->radius_cui) + os_memcpy(cache->radius_cui, buf, len); + } if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED && !cache->has_psk) |