Signed-off-by: Michael Braun <michael-dev@xxxxxxxxxxxxx> --- src/ap/ieee802_11.c | 143 ++++++++++++++++++++++++++++------------------- src/ap/ieee802_11.h | 4 ++ src/ap/ieee802_11_auth.c | 110 ++++++++++++++++++------------------ src/ap/ieee802_11_auth.h | 24 ++++++-- 4 files changed, 166 insertions(+), 115 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index f1c396b..caa05ad 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -980,6 +980,76 @@ int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta) #endif /* CONFIG_SAE */ +void handle_auth_restart_cb(struct hostapd_data *hapd, const u8 *buf, + size_t len, const u8 *mac, int accepted, + u32 session_timeout) +{ +#ifdef CONFIG_DRIVER_RADIUS_ACL + hostapd_drv_set_radius_acl_auth(hapd, mac, accepted, session_timeout); +#else /* CONFIG_DRIVER_RADIUS_ACL */ +#ifdef NEED_AP_MLME + /* Re-send original authentication frame for 802.11 processing */ + wpa_printf(MSG_DEBUG, "Re-sending authentication frame after " + "successful RADIUS ACL query"); + ieee802_11_mgmt(hapd, buf, len, NULL); +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_DRIVER_RADIUS_ACL */ +} + + +int handle_auth_cfg_sta(struct hostapd_data *hapd, struct sta_info *sta, + int res, struct hostapd_allowed_address_info *info, + u16 *resp) +{ + if (info->vlan_id.notempty && + !hostapd_vlan_valid(hapd->conf->vlan, &info->vlan_id)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, + HOSTAPD_LEVEL_INFO, + "Invalid VLAN %d%s received from RADIUS server", + info->vlan_id.untagged, + info->vlan_id.tagged[0] ? "+" : ""); + *resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + return -1; + } + if (ap_sta_set_vlan(hapd, sta, &info->vlan_id) < 0) { + *resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + return -1; + } + if (sta->vlan_id) + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, + HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id); + + hostapd_free_psk_list(sta->psk); + if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) + hostapd_copy_psk_list(&sta->psk, info->psk); + else + sta->psk = NULL; + + os_free(sta->identity); + if (info->identity) + sta->identity = os_strdup(info->identity); + else + sta->identity = NULL; + + os_free(sta->radius_cui); + if (info->radius_cui) + sta->radius_cui = os_strdup(info->radius_cui); + else + sta->radius_cui = NULL; + + if (hapd->conf->acct_interim_interval == 0 && + info->acct_interim_interval) + sta->acct_interim_interval = info->acct_interim_interval; + + if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) + ap_sta_session_timeout(hapd, sta, info->session_timeout); + else + ap_sta_no_session_timeout(hapd, sta); + + return 0; +} + + static void handle_auth(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len) { @@ -989,16 +1059,10 @@ static void handle_auth(struct hostapd_data *hapd, int res, reply_res; u16 fc; const u8 *challenge = NULL; - u32 session_timeout, acct_interim_interval; - struct vlan_description vlan_id; - struct hostapd_sta_wpa_psk_short *psk = NULL; u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; size_t resp_ies_len = 0; - char *identity = NULL; - char *radius_cui = NULL; u16 seq_ctrl; - - os_memset(&vlan_id, 0, sizeof(vlan_id)); + struct hostapd_allowed_address_info details; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)", @@ -1016,6 +1080,8 @@ static void handle_auth(struct hostapd_data *hapd, } #endif /* CONFIG_TESTING_OPTIONS */ + hostapd_allowed_address_init(&details); + auth_alg = le_to_host16(mgmt->u.auth.auth_alg); auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); status_code = le_to_host16(mgmt->u.auth.status_code); @@ -1140,9 +1206,8 @@ static void handle_auth(struct hostapd_data *hapd, } res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len, - &session_timeout, - &acct_interim_interval, &vlan_id, - &psk, &identity, &radius_cui); + &handle_auth_restart_cb, + &details); if (res == HOSTAPD_ACL_REJECT) { wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate", @@ -1157,7 +1222,7 @@ static void handle_auth(struct hostapd_data *hapd, /* Authentication code will re-send the authentication frame * after it has received (and cached) information from the * external source. */ - return; + goto out; } sta = ap_get_sta(hapd, mgmt->sa); @@ -1171,7 +1236,7 @@ static void handle_auth(struct hostapd_data *hapd, HOSTAPD_LEVEL_DEBUG, "Drop repeated authentication frame seq_ctrl=0x%x", seq_ctrl); - return; + goto out; } #ifdef CONFIG_MESH if ((hapd->conf->mesh & MESH_ENABLED) && @@ -1179,7 +1244,7 @@ static void handle_auth(struct hostapd_data *hapd, wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR " is blocked - drop Authentication frame", MAC2STR(mgmt->sa)); - return; + goto out; } #endif /* CONFIG_MESH */ } else { @@ -1197,7 +1262,7 @@ static void handle_auth(struct hostapd_data *hapd, wpabuf_free(hapd->mesh_pending_auth); hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len); os_get_reltime(&hapd->mesh_pending_auth_time); - return; + goto out; } #endif /* CONFIG_MESH */ @@ -1210,47 +1275,12 @@ static void handle_auth(struct hostapd_data *hapd, sta->last_seq_ctrl = seq_ctrl; sta->last_subtype = WLAN_FC_STYPE_AUTH; - if (vlan_id.notempty && - !hostapd_vlan_valid(hapd->conf->vlan, &vlan_id)) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "Invalid VLAN %d%s received from RADIUS server", - vlan_id.untagged, - vlan_id.tagged[0] ? "+" : ""); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - if (ap_sta_set_vlan(hapd, sta, &vlan_id) < 0) { - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + if (handle_auth_cfg_sta(hapd, sta, res, &details, &resp) < 0) goto fail; - } - if (sta->vlan_id) - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id); - - hostapd_free_psk_list(sta->psk); - if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) { - sta->psk = psk; - psk = NULL; - } else { - sta->psk = NULL; - } - - sta->identity = identity; - identity = NULL; - sta->radius_cui = radius_cui; - radius_cui = NULL; sta->flags &= ~WLAN_STA_PREAUTH; ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); - if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval) - sta->acct_interim_interval = acct_interim_interval; - if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) - ap_sta_session_timeout(hapd, sta, session_timeout); - else - ap_sta_no_session_timeout(hapd, sta); - /* * If the driver supports full AP client state, add a station to the * driver before sending authentication reply to make sure the driver @@ -1334,7 +1364,7 @@ static void handle_auth(struct hostapd_data *hapd, sizeof(mgmt->u.auth), handle_auth_ft_finish, hapd); /* handle_auth_ft_finish() callback will complete auth. */ - return; + goto out; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_SAE case WLAN_AUTH_SAE: @@ -1355,15 +1385,11 @@ static void handle_auth(struct hostapd_data *hapd, #endif /* CONFIG_MESH */ handle_auth_sae(hapd, sta, mgmt, len, auth_transaction, status_code); - return; + goto out; #endif /* CONFIG_SAE */ } - fail: - os_free(identity); - os_free(radius_cui); - hostapd_free_psk_list(psk); - +fail: reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg, auth_transaction + 1, resp, resp_ies, resp_ies_len); @@ -1373,6 +1399,9 @@ static void handle_auth(struct hostapd_data *hapd, hostapd_drv_sta_remove(hapd, sta->addr); sta->added_unassoc = 0; } + +out: + hostapd_allowed_address_free(&details); } diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 0327dec..7ce33cb 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -16,6 +16,7 @@ struct hostapd_frame_info; struct ieee80211_ht_capabilities; struct ieee80211_vht_capabilities; struct ieee80211_mgmt; +struct hostapd_allowed_address_info; int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, struct hostapd_frame_info *fi); @@ -109,6 +110,9 @@ static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd, { } #endif /* CONFIG_SAE */ +int handle_auth_cfg_sta(struct hostapd_data *hapd, struct sta_info *sta, + int res, struct hostapd_allowed_address_info *info, + u16 *resp); #ifdef CONFIG_MBO diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c index b890537..d3d4145 100644 --- a/src/ap/ieee802_11_auth.c +++ b/src/ap/ieee802_11_auth.c @@ -47,10 +47,25 @@ struct hostapd_acl_query_data { macaddr addr; u8 *auth_msg; /* IEEE 802.11 authentication frame from station */ size_t auth_msg_len; + void (*cb)(struct hostapd_data *hapd, const u8 *buf, size_t len, + const u8 *mac, int accepted, u32 session_timeout); struct hostapd_acl_query_data *next; }; +void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk, + struct hostapd_sta_wpa_psk_short *src) +{ + if (!psk) + return; + + if (src) + src->ref++; + + *psk = src; +} + + #ifndef CONFIG_NO_RADIUS static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e) { @@ -73,19 +88,6 @@ static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) } -static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk, - struct hostapd_sta_wpa_psk_short *src) -{ - if (!psk) - return; - - if (src) - src->ref++; - - *psk = src; -} - - static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, u32 *session_timeout, u32 *acct_interim_interval, @@ -113,7 +115,7 @@ static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, entry->acct_interim_interval; if (vlan_id) *vlan_id = entry->vlan_id; - copy_psk_list(psk, entry->psk); + hostapd_copy_psk_list(psk, entry->psk); if (identity) { if (entry->identity) *identity = os_strdup(entry->identity); @@ -205,6 +207,23 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, #endif /* CONFIG_NO_RADIUS */ +void hostapd_allowed_address_init(struct hostapd_allowed_address_info *info) +{ + os_memset(info, 0, sizeof(*info)); +} + + +void hostapd_allowed_address_free(struct hostapd_allowed_address_info *info) +{ + os_free(info->identity); + info->identity = NULL; + os_free(info->radius_cui); + info->radius_cui = NULL; + hostapd_free_psk_list(info->psk); + info->psk = NULL; +} + + /** * hostapd_check_acl - Check a specified STA against accept/deny ACLs * @hapd: hostapd BSS data @@ -250,28 +269,16 @@ int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr, * 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, - struct vlan_description *vlan_id, - struct hostapd_sta_wpa_psk_short **psk, - char **identity, char **radius_cui) + const u8 *msg, size_t len, + void (*cb)(struct hostapd_data *hapd, + const u8 *buf, size_t len, + const u8 *mac, int accepted, + u32 session_timeout), + struct hostapd_allowed_address_info *info) { int res; - if (session_timeout) - *session_timeout = 0; - if (acct_interim_interval) - *acct_interim_interval = 0; - if (vlan_id) - os_memset(vlan_id, 0, sizeof(*vlan_id)); - if (psk) - *psk = NULL; - if (identity) - *identity = NULL; - if (radius_cui) - *radius_cui = NULL; - - res = hostapd_check_acl(hapd, addr, vlan_id); + res = hostapd_check_acl(hapd, addr, &info->vlan_id); if (res != HOSTAPD_ACL_PENDING) return res; @@ -282,9 +289,12 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, struct hostapd_acl_query_data *query; /* Check whether ACL cache has an entry for this station */ - res = hostapd_acl_cache_get(hapd, addr, session_timeout, - acct_interim_interval, vlan_id, psk, - identity, radius_cui); + res = hostapd_acl_cache_get(hapd, addr, + &info->session_timeout, + &info->acct_interim_interval, + &info->vlan_id, &info->psk, + &info->identity, + &info->radius_cui); if (res == HOSTAPD_ACL_ACCEPT || res == HOSTAPD_ACL_ACCEPT_TIMEOUT) return res; @@ -296,13 +306,13 @@ 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 (info->identity) { + os_free(info->identity); + info->identity = NULL; } - if (radius_cui) { - os_free(*radius_cui); - *radius_cui = NULL; + if (info->radius_cui) { + os_free(info->radius_cui); + info->radius_cui = NULL; } return HOSTAPD_ACL_PENDING; } @@ -336,6 +346,7 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, } os_memcpy(query->auth_msg, msg, len); query->auth_msg_len = len; + query->cb = cb; query->next = hapd->acl_queries; hapd->acl_queries = query; @@ -613,17 +624,10 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, cache->next = hapd->acl_cache; hapd->acl_cache = cache; -#ifdef CONFIG_DRIVER_RADIUS_ACL - hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted, - cache->session_timeout); -#else /* CONFIG_DRIVER_RADIUS_ACL */ -#ifdef NEED_AP_MLME - /* Re-send original authentication frame for 802.11 processing */ - wpa_printf(MSG_DEBUG, "Re-sending authentication frame after " - "successful RADIUS ACL query"); - ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL); -#endif /* NEED_AP_MLME */ -#endif /* CONFIG_DRIVER_RADIUS_ACL */ + if (query->cb) + query->cb(hapd, query->auth_msg, query->auth_msg_len, + query->addr, cache->accepted, + cache->session_timeout); done: if (prev == NULL) diff --git a/src/ap/ieee802_11_auth.h b/src/ap/ieee802_11_auth.h index 71f53b9..dea889c 100644 --- a/src/ap/ieee802_11_auth.h +++ b/src/ap/ieee802_11_auth.h @@ -16,16 +16,30 @@ enum { HOSTAPD_ACL_ACCEPT_TIMEOUT = 3 }; +struct hostapd_allowed_address_info { + u32 session_timeout; + u32 acct_interim_interval; + struct vlan_description vlan_id; + struct hostapd_sta_wpa_psk_short *psk; + char *identity; + char *radius_cui; +}; + +void hostapd_allowed_address_init(struct hostapd_allowed_address_info *info); +void hostapd_allowed_address_free(struct hostapd_allowed_address_info *info); int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr, struct vlan_description *vlan_id); int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, - const u8 *msg, size_t len, u32 *session_timeout, - u32 *acct_interim_interval, - struct vlan_description *vlan_id, - struct hostapd_sta_wpa_psk_short **psk, - char **identity, char **radius_cui); + const u8 *msg, size_t len, + void (*cb)(struct hostapd_data *hapd, + const u8 *buf, size_t len, + const u8 *mac, int accepted, + u32 session_timeout), + struct hostapd_allowed_address_info *info); int hostapd_acl_init(struct hostapd_data *hapd); void hostapd_acl_deinit(struct hostapd_data *hapd); +void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk, + struct hostapd_sta_wpa_psk_short *src); void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk); void hostapd_acl_expire(struct hostapd_data *hapd); -- 2.1.4 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap