RADIUS ACL/PSK check during 4-way handshake
Add an alternative sequence for performing the RADIUS ACL check and PSK fetch. The previously used (macaddr_acl=2, wpa_psk_radius=2) combination does this during IEEE 802.11 Authentication frame exchange while the new option (wpa_psk_radius=3) does this during the 4-way handshake. This allows some more information to be provided to the RADIUS authentication server. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
5b5c954c04
commit
1c3438fec4
12 changed files with 172 additions and 19 deletions
|
@ -2929,7 +2929,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||
bss->wpa_psk_radius = atoi(pos);
|
||||
if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
||||
bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
|
||||
bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
|
||||
bss->wpa_psk_radius != PSK_RADIUS_REQUIRED &&
|
||||
bss->wpa_psk_radius != PSK_RADIUS_DURING_4WAY_HS) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: unknown wpa_psk_radius %d",
|
||||
line, bss->wpa_psk_radius);
|
||||
|
|
|
@ -1655,12 +1655,15 @@ own_ip_addr=127.0.0.1
|
|||
#wpa_psk_file=/etc/hostapd.wpa_psk
|
||||
|
||||
# Optionally, WPA passphrase can be received from RADIUS authentication server
|
||||
# This requires macaddr_acl to be set to 2 (RADIUS)
|
||||
# This requires macaddr_acl to be set to 2 (RADIUS) for wpa_psk_radius values
|
||||
# 1 and 2.
|
||||
# 0 = disabled (default)
|
||||
# 1 = optional; use default passphrase/psk if RADIUS server does not include
|
||||
# Tunnel-Password
|
||||
# 2 = required; reject authentication if RADIUS server does not include
|
||||
# Tunnel-Password
|
||||
# 3 = ask RADIUS server during 4-way handshake if there is no locally
|
||||
# configured PSK/passphrase for the STA
|
||||
#wpa_psk_radius=0
|
||||
|
||||
# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd / Configuration helper functions
|
||||
* Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -1243,6 +1243,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||
|
||||
if (full_config && bss->wpa &&
|
||||
bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
||||
bss->wpa_psk_radius != PSK_RADIUS_DURING_4WAY_HS &&
|
||||
bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
|
||||
wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
|
||||
"RADIUS checking (macaddr_acl=2) enabled.");
|
||||
|
@ -1253,6 +1254,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
|
|||
wpa_key_mgmt_wpa_psk_no_sae(bss->wpa_key_mgmt) &&
|
||||
bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
|
||||
bss->ssid.wpa_psk_file == NULL &&
|
||||
bss->wpa_psk_radius != PSK_RADIUS_DURING_4WAY_HS &&
|
||||
(bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
|
||||
bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) {
|
||||
wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd / Configuration definitions and helpers functions
|
||||
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -364,7 +364,8 @@ struct hostapd_bss_config {
|
|||
enum {
|
||||
PSK_RADIUS_IGNORED = 0,
|
||||
PSK_RADIUS_ACCEPTED = 1,
|
||||
PSK_RADIUS_REQUIRED = 2
|
||||
PSK_RADIUS_REQUIRED = 2,
|
||||
PSK_RADIUS_DURING_4WAY_HS = 3,
|
||||
} wpa_psk_radius;
|
||||
int wpa_pairwise;
|
||||
int group_cipher; /* wpa_group value override from configuation */
|
||||
|
|
|
@ -2325,9 +2325,8 @@ static int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int res, struct radius_sta *info)
|
||||
int ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int res, struct radius_sta *info)
|
||||
{
|
||||
u32 session_timeout = info->session_timeout;
|
||||
u32 acct_interim_interval = info->acct_interim_interval;
|
||||
|
|
|
@ -198,5 +198,7 @@ u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
const u8 *ext_capab_ie, size_t ext_capab_ie_len);
|
||||
size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type);
|
||||
u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type);
|
||||
int ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int res, struct radius_sta *info);
|
||||
|
||||
#endif /* IEEE802_11_H */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd / IEEE 802.11 authentication (ACL)
|
||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -20,6 +20,8 @@
|
|||
#include "hostapd.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "sta_info.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "ieee802_1x.h"
|
||||
#include "ieee802_11_auth.h"
|
||||
|
@ -43,6 +45,8 @@ struct hostapd_acl_query_data {
|
|||
u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
|
||||
size_t auth_msg_len;
|
||||
struct hostapd_acl_query_data *next;
|
||||
bool radius_psk;
|
||||
int akm;
|
||||
};
|
||||
|
||||
|
||||
|
@ -153,6 +157,13 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (query->akm &&
|
||||
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_AKM_SUITE,
|
||||
wpa_akm_to_suite(query->akm))) {
|
||||
wpa_printf(MSG_DEBUG, "Could not add WLAN-AKM-Suite");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0)
|
||||
goto fail;
|
||||
return 0;
|
||||
|
@ -557,17 +568,40 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
|
|||
cache->next = hapd->acl_cache;
|
||||
hapd->acl_cache = cache;
|
||||
|
||||
if (query->radius_psk) {
|
||||
struct sta_info *sta;
|
||||
bool success = cache->accepted == HOSTAPD_ACL_ACCEPT;
|
||||
|
||||
sta = ap_get_sta(hapd, query->addr);
|
||||
if (!sta || !sta->wpa_sm) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"No STA/SM entry found for the RADIUS PSK response");
|
||||
goto done;
|
||||
}
|
||||
#ifdef NEED_AP_MLME
|
||||
if (success &&
|
||||
(ieee802_11_set_radius_info(hapd, sta, cache->accepted,
|
||||
info) < 0 ||
|
||||
ap_sta_bind_vlan(hapd, sta) < 0))
|
||||
success = false;
|
||||
#endif /* NEED_AP_MLME */
|
||||
wpa_auth_sta_radius_psk_resp(sta->wpa_sm, success);
|
||||
} else {
|
||||
#ifdef CONFIG_DRIVER_RADIUS_ACL
|
||||
hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
|
||||
info->session_timeout);
|
||||
hostapd_drv_set_radius_acl_auth(hapd, query->addr,
|
||||
cache->accepted,
|
||||
info->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);
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
done:
|
||||
if (prev == NULL)
|
||||
|
@ -649,3 +683,31 @@ void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
|
|||
bin_clear_free(prev, sizeof(*prev));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
void hostapd_acl_req_radius_psk(struct hostapd_data *hapd, const u8 *addr,
|
||||
int key_mgmt, const u8 *anonce,
|
||||
const u8 *eapol, size_t eapol_len)
|
||||
{
|
||||
struct hostapd_acl_query_data *query;
|
||||
|
||||
query = os_zalloc(sizeof(*query));
|
||||
if (!query)
|
||||
return;
|
||||
|
||||
query->radius_psk = true;
|
||||
query->akm = key_mgmt;
|
||||
os_get_reltime(&query->timestamp);
|
||||
os_memcpy(query->addr, addr, ETH_ALEN);
|
||||
if (hostapd_radius_acl_query(hapd, addr, query)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Failed to send Access-Request for RADIUS PSK/ACL query");
|
||||
hostapd_acl_query_free(query);
|
||||
return;
|
||||
}
|
||||
|
||||
query->next = hapd->acl_queries;
|
||||
hapd->acl_queries = query;
|
||||
}
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd / IEEE 802.11 authentication (ACL)
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -36,5 +36,8 @@ void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk);
|
|||
void hostapd_acl_expire(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_acl_req_radius_psk(struct hostapd_data *hapd, const u8 *addr,
|
||||
int key_mgmt, const u8 *anonce,
|
||||
const u8 *eapol, size_t eapol_len);
|
||||
|
||||
#endif /* IEEE802_11_AUTH_H */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* IEEE 802.11 RSN / WPA Authenticator
|
||||
* Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -1481,6 +1481,12 @@ static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx)
|
|||
struct wpa_authenticator *wpa_auth = eloop_ctx;
|
||||
struct wpa_state_machine *sm = timeout_ctx;
|
||||
|
||||
if (sm->waiting_radius_psk) {
|
||||
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"Ignore EAPOL-Key timeout while waiting for RADIUS PSK");
|
||||
return;
|
||||
}
|
||||
|
||||
sm->pending_1_of_4_timeout = 0;
|
||||
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
|
||||
sm->TimeoutEvt = true;
|
||||
|
@ -3017,6 +3023,19 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!ok && wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
|
||||
wpa_auth->conf.radius_psk && wpa_auth->cb->request_radius_psk &&
|
||||
!sm->waiting_radius_psk) {
|
||||
wpa_printf(MSG_DEBUG, "No PSK available - ask RADIUS server");
|
||||
wpa_auth->cb->request_radius_psk(wpa_auth->cb_ctx, sm->addr,
|
||||
sm->wpa_key_mgmt,
|
||||
sm->ANonce,
|
||||
sm->last_rx_eapol_key,
|
||||
sm->last_rx_eapol_key_len);
|
||||
sm->waiting_radius_psk = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"invalid MIC in msg 2/4 of 4-Way Handshake");
|
||||
|
@ -3776,6 +3795,11 @@ SM_STEP(WPA_PTK)
|
|||
} else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
|
||||
SM_ENTER(WPA_PTK, PTKSTART);
|
||||
#endif /* CONFIG_SAE */
|
||||
} else if (wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
|
||||
wpa_auth->conf.radius_psk) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"INITPSK: No PSK yet available for STA - use RADIUS later");
|
||||
SM_ENTER(WPA_PTK, PTKSTART);
|
||||
} else {
|
||||
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
|
||||
"no PSK configured for the STA");
|
||||
|
@ -5689,3 +5713,28 @@ void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
|
|||
}
|
||||
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
|
||||
void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success)
|
||||
{
|
||||
if (!sm->waiting_radius_psk) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Ignore RADIUS PSK response for " MACSTR
|
||||
" that did not wait one",
|
||||
MAC2STR(sm->addr));
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "RADIUS PSK response for " MACSTR " (%s)",
|
||||
MAC2STR(sm->addr), success ? "success" : "fail");
|
||||
sm->waiting_radius_psk = 0;
|
||||
|
||||
if (success) {
|
||||
/* Try to process the EAPOL-Key msg 2/4 again */
|
||||
sm->EAPOLKeyReceived = true;
|
||||
} else {
|
||||
sm->Disconnect = true;
|
||||
}
|
||||
|
||||
eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd - IEEE 802.11i-2004 / WPA Authenticator
|
||||
* Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -273,6 +273,8 @@ struct wpa_auth_config {
|
|||
* PTK derivation regardless of advertised capabilities.
|
||||
*/
|
||||
bool force_kdk_derivation;
|
||||
|
||||
bool radius_psk;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -320,6 +322,9 @@ struct wpa_auth_callbacks {
|
|||
void (*store_ptksa)(void *ctx, const u8 *addr, int cipher,
|
||||
u32 life_time, const struct wpa_ptk *ptk);
|
||||
void (*clear_ptksa)(void *ctx, const u8 *addr, int cipher);
|
||||
void (*request_radius_psk)(void *ctx, const u8 *addr, int key_mgmt,
|
||||
const u8 *anonce,
|
||||
const u8 *eapol, size_t eapol_len);
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
|
||||
int (*add_sta_ft)(void *ctx, const u8 *sta_addr);
|
||||
|
@ -572,4 +577,6 @@ void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
|
|||
enum wpa_auth_ocv_override_frame frame,
|
||||
unsigned int freq);
|
||||
|
||||
void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success);
|
||||
|
||||
#endif /* WPA_AUTH_H */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd / WPA authenticator glue code
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -29,6 +29,7 @@
|
|||
#include "ap_drv_ops.h"
|
||||
#include "ap_config.h"
|
||||
#include "ieee802_11.h"
|
||||
#include "ieee802_11_auth.h"
|
||||
#include "pmksa_cache_auth.h"
|
||||
#include "wpa_auth.h"
|
||||
#include "wpa_auth_glue.h"
|
||||
|
@ -214,6 +215,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
|||
wconf->force_kdk_derivation = conf->force_kdk_derivation;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#endif /* CONFIG_PASN */
|
||||
|
||||
wconf->radius_psk = conf->wpa_psk_radius == PSK_RADIUS_DURING_4WAY_HS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1443,6 +1446,23 @@ static void hostapd_wpa_unregister_ft_oui(struct hostapd_data *hapd)
|
|||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
|
||||
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
static void hostapd_request_radius_psk(void *ctx, const u8 *addr, int key_mgmt,
|
||||
const u8 *anonce,
|
||||
const u8 *eapol, size_t eapol_len)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "RADIUS PSK request for " MACSTR " key_mgmt=0x%x",
|
||||
MAC2STR(addr), key_mgmt);
|
||||
wpa_hexdump(MSG_DEBUG, "ANonce", anonce, WPA_NONCE_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "EAPOL", eapol, eapol_len);
|
||||
hostapd_acl_req_radius_psk(hapd, addr, key_mgmt, anonce, eapol,
|
||||
eapol_len);
|
||||
}
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
|
||||
|
||||
int hostapd_setup_wpa(struct hostapd_data *hapd)
|
||||
{
|
||||
struct wpa_auth_config _conf;
|
||||
|
@ -1486,6 +1506,9 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
|||
.set_session_timeout = hostapd_wpa_auth_set_session_timeout,
|
||||
.get_session_timeout = hostapd_wpa_auth_get_session_timeout,
|
||||
#endif /* CONFIG_IEEE80211R_AP */
|
||||
#ifndef CONFIG_NO_RADIUS
|
||||
.request_radius_psk = hostapd_request_radius_psk,
|
||||
#endif /* CONFIG_NO_RADIUS */
|
||||
};
|
||||
const u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
|
|
|
@ -89,6 +89,7 @@ struct wpa_state_machine {
|
|||
unsigned int rx_eapol_key_secure:1;
|
||||
unsigned int update_snonce:1;
|
||||
unsigned int alt_snonce_valid:1;
|
||||
unsigned int waiting_radius_psk:1;
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
unsigned int ft_completed:1;
|
||||
unsigned int pmk_r1_name_valid:1;
|
||||
|
|
Loading…
Reference in a new issue