mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-30 18:07:52 +00:00 
			
		
		
		
	Fix psk2-radius feature
Add psk2-radius functionality in hostapd and fix config via netifd. Fixes WIFI-13183 Signed-off-by: Arif Alam <arif.alam@netexperience.com>
This commit is contained in:
		| @@ -0,0 +1,459 @@ | |||||||
|  | From 1c3438fec4bad13a676617915ff56af54e7b4542 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jouni Malinen <j@w1.fi> | ||||||
|  | Date: Sat, 2 Apr 2022 13:12:43 +0300 | ||||||
|  | Subject: [PATCH] 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> | ||||||
|  | --- | ||||||
|  |  hostapd/config_file.c    |  3 +- | ||||||
|  |  hostapd/hostapd.conf     |  5 ++- | ||||||
|  |  src/ap/ap_config.c       |  4 ++- | ||||||
|  |  src/ap/ap_config.h       |  5 +-- | ||||||
|  |  src/ap/ieee802_11.c      |  5 ++- | ||||||
|  |  src/ap/ieee802_11.h      |  2 ++ | ||||||
|  |  src/ap/ieee802_11_auth.c | 76 ++++++++++++++++++++++++++++++++++++---- | ||||||
|  |  src/ap/ieee802_11_auth.h |  5 ++- | ||||||
|  |  src/ap/wpa_auth.c        | 51 ++++++++++++++++++++++++++- | ||||||
|  |  src/ap/wpa_auth.h        |  9 ++++- | ||||||
|  |  src/ap/wpa_auth_glue.c   | 25 ++++++++++++- | ||||||
|  |  src/ap/wpa_auth_i.h      |  1 + | ||||||
|  |  12 files changed, 172 insertions(+), 19 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/hostapd/config_file.c | ||||||
|  | +++ b/hostapd/config_file.c | ||||||
|  | @@ -2858,7 +2858,8 @@ static int hostapd_config_fill(struct ho | ||||||
|  |  		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); | ||||||
|  | --- a/hostapd/hostapd.conf | ||||||
|  | +++ b/hostapd/hostapd.conf | ||||||
|  | @@ -1635,12 +1635,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 | ||||||
|  | --- a/src/ap/ap_config.c | ||||||
|  | +++ b/src/ap/ap_config.c | ||||||
|  | @@ -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. | ||||||
|  | @@ -1245,6 +1245,7 @@ static int hostapd_config_check_bss(stru | ||||||
|  |   | ||||||
|  |  	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."); | ||||||
|  | @@ -1254,6 +1255,7 @@ static int hostapd_config_check_bss(stru | ||||||
|  |  	if (full_config && bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && | ||||||
|  |  	    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 " | ||||||
|  | --- a/src/ap/ap_config.h | ||||||
|  | +++ b/src/ap/ap_config.h | ||||||
|  | @@ -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. | ||||||
|  | @@ -367,7 +367,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 */ | ||||||
|  | --- a/src/ap/ieee802_11.c | ||||||
|  | +++ b/src/ap/ieee802_11.c | ||||||
|  | @@ -2348,9 +2348,8 @@ static int ieee802_11_allowed_address(st | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -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; | ||||||
|  | --- a/src/ap/ieee802_11.h | ||||||
|  | +++ b/src/ap/ieee802_11.h | ||||||
|  | @@ -220,4 +220,6 @@ void auth_sae_process_commit(void *eloop | ||||||
|  |  u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len); | ||||||
|  |  u8 * hostapd_get_rsne(struct hostapd_data *hapd, u8 *pos, size_t len); | ||||||
|  |  u8 * hostapd_get_rsnxe(struct hostapd_data *hapd, u8 *pos, size_t len); | ||||||
|  | +int ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta, | ||||||
|  | +		                              int res, struct radius_sta *info); | ||||||
|  |  #endif /* IEEE802_11_H */ | ||||||
|  | --- 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-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(stru | ||||||
|  |  		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; | ||||||
|  | @@ -566,17 +577,40 @@ hostapd_acl_recv_radius(struct radius_ms | ||||||
|  |  	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) | ||||||
|  | @@ -658,3 +692,31 @@ void hostapd_free_psk_list(struct hostap | ||||||
|  |  		os_free(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 */ | ||||||
|  | --- a/src/ap/ieee802_11_auth.h | ||||||
|  | +++ b/src/ap/ieee802_11_auth.h | ||||||
|  | @@ -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 hostap | ||||||
|  |  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 */ | ||||||
|  | --- a/src/ap/wpa_auth.c | ||||||
|  | +++ b/src/ap/wpa_auth.c | ||||||
|  | @@ -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. | ||||||
|  | @@ -1465,6 +1465,12 @@ static void wpa_send_eapol_timeout(void | ||||||
|  |  	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; | ||||||
|  | @@ -3003,6 +3009,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"); | ||||||
|  | @@ -3758,6 +3777,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"); | ||||||
|  | @@ -5661,3 +5685,28 @@ void wpa_auth_set_ocv_override_freq(stru | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  #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); | ||||||
|  | +} | ||||||
|  | --- a/src/ap/wpa_auth.h | ||||||
|  | +++ b/src/ap/wpa_auth.h | ||||||
|  | @@ -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); | ||||||
|  | @@ -567,4 +572,6 @@ void wpa_auth_set_ocv_override_freq(stru | ||||||
|  |  				    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 */ | ||||||
|  | --- a/src/ap/wpa_auth_glue.c | ||||||
|  | +++ b/src/ap/wpa_auth_glue.c | ||||||
|  | @@ -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 | ||||||
|  |  	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; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |   | ||||||
|  | @@ -1435,6 +1438,23 @@ static void hostapd_wpa_unregister_ft_ou | ||||||
|  |  #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; | ||||||
|  | @@ -1478,6 +1498,9 @@ int hostapd_setup_wpa(struct hostapd_dat | ||||||
|  |  		.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; | ||||||
|  | --- a/src/ap/wpa_auth_i.h | ||||||
|  | +++ b/src/ap/wpa_auth_i.h | ||||||
|  | @@ -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; | ||||||
| @@ -0,0 +1,350 @@ | |||||||
|  | From 24763e3cd0a564eb71f3c501bbb4fbb0d7070762 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jouni Malinen <j@w1.fi> | ||||||
|  | Date: Fri, 15 Apr 2022 17:31:48 +0300 | ||||||
|  | Subject: [PATCH] RADIUS: Attributes with Extended Types (RFC 6929) | ||||||
|  |  | ||||||
|  | Supported extended types for RADIUS attributes for the cases defined in | ||||||
|  | RFC 6929. | ||||||
|  |  | ||||||
|  | Signed-off-by: Jouni Malinen <j@w1.fi> | ||||||
|  | --- | ||||||
|  |  src/radius/radius.c | 195 ++++++++++++++++++++++++++++++++++++++------ | ||||||
|  |  src/radius/radius.h |  26 +++++- | ||||||
|  |  2 files changed, 193 insertions(+), 28 deletions(-) | ||||||
|  |  | ||||||
|  | diff --git a/src/radius/radius.c b/src/radius/radius.c | ||||||
|  | index be16e27b9..a64228067 100644 | ||||||
|  | --- a/src/radius/radius.c | ||||||
|  | +++ b/src/radius/radius.c | ||||||
|  | @@ -1,6 +1,6 @@ | ||||||
|  |  /* | ||||||
|  |   * RADIUS message processing | ||||||
|  | - * Copyright (c) 2002-2009, 2011-2015, Jouni Malinen <j@w1.fi> | ||||||
|  | + * Copyright (c) 2002-2009, 2011-2022, Jouni Malinen <j@w1.fi> | ||||||
|  |   * | ||||||
|  |   * This software may be distributed under the terms of the BSD license. | ||||||
|  |   * See README for more details. | ||||||
|  | @@ -159,7 +159,8 @@ static const char *radius_code_string(u8 code) | ||||||
|  |   | ||||||
|  |   | ||||||
|  |  struct radius_attr_type { | ||||||
|  | -	u8 type; | ||||||
|  | +	u16 type; /* 0..255 for basic types; | ||||||
|  | +		   * (241 << 8) | <ext-type> for extended types */ | ||||||
|  |  	char *name; | ||||||
|  |  	enum { | ||||||
|  |  		RADIUS_ATTR_UNDIST, RADIUS_ATTR_TEXT, RADIUS_ATTR_IP, | ||||||
|  | @@ -260,11 +261,31 @@ static const struct radius_attr_type radius_attrs[] = | ||||||
|  |  	  RADIUS_ATTR_HEXDUMP }, | ||||||
|  |  	{ RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER, "WLAN-Group-Mgmt-Pairwise-Cipher", | ||||||
|  |  	  RADIUS_ATTR_HEXDUMP }, | ||||||
|  | +	{ RADIUS_ATTR_EXT_TYPE_1, "Extended-Type-1", RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_EXT_TYPE_2, "Extended-Type-2", RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_EXT_TYPE_3, "Extended-Type-3", RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_EXT_TYPE_4, "Extended-Type-4", RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_LONG_EXT_TYPE_1, "Long-Extended-Type-1", | ||||||
|  | +	  RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_LONG_EXT_TYPE_2, "Long-Extended-Type-2", | ||||||
|  | +	  RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_1, "Extended-Vendor-Specific-1", | ||||||
|  | +	  RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_2, "Extended-Vendor-Specific-2", | ||||||
|  | +	  RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_3, "Extended-Vendor-Specific-3", | ||||||
|  | +	  RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_4, "Extended-Vendor-Specific-4", | ||||||
|  | +	  RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_5, "Extended-Vendor-Specific-5", | ||||||
|  | +	  RADIUS_ATTR_UNDIST }, | ||||||
|  | +	{ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_6, "Extended-Vendor-Specific-6", | ||||||
|  | +	  RADIUS_ATTR_UNDIST }, | ||||||
|  |  }; | ||||||
|  |  #define RADIUS_ATTRS ARRAY_SIZE(radius_attrs) | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -static const struct radius_attr_type *radius_get_attr_type(u8 type) | ||||||
|  | +static const struct radius_attr_type * radius_get_attr_type(u16 type) | ||||||
|  |  { | ||||||
|  |  	size_t i; | ||||||
|  |   | ||||||
|  | @@ -277,23 +298,60 @@ static const struct radius_attr_type *radius_get_attr_type(u8 type) | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |   | ||||||
|  | +static bool radius_is_long_ext_type(u8 type) | ||||||
|  | +{ | ||||||
|  | +	return type == RADIUS_ATTR_LONG_EXT_TYPE_1 || | ||||||
|  | +		type == RADIUS_ATTR_LONG_EXT_TYPE_2; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | + | ||||||
|  | +static bool radius_is_ext_type(u8 type) | ||||||
|  | +{ | ||||||
|  | +	return type >= RADIUS_ATTR_EXT_TYPE_1 && | ||||||
|  | +		type <= RADIUS_ATTR_LONG_EXT_TYPE_2; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | + | ||||||
|  |  static void radius_msg_dump_attr(struct radius_attr_hdr *hdr) | ||||||
|  |  { | ||||||
|  | +	struct radius_attr_hdr_ext *ext = NULL; | ||||||
|  |  	const struct radius_attr_type *attr; | ||||||
|  |  	int len; | ||||||
|  |  	unsigned char *pos; | ||||||
|  |  	char buf[1000]; | ||||||
|  |   | ||||||
|  | -	attr = radius_get_attr_type(hdr->type); | ||||||
|  | +	if (hdr->length < sizeof(struct radius_attr_hdr)) | ||||||
|  | +		return; | ||||||
|  |   | ||||||
|  | -	wpa_printf(MSG_INFO, "   Attribute %d (%s) length=%d", | ||||||
|  | -		   hdr->type, attr ? attr->name : "?Unknown?", hdr->length); | ||||||
|  | +	if (radius_is_ext_type(hdr->type)) { | ||||||
|  | +		if (hdr->length < 4) { | ||||||
|  | +			wpa_printf(MSG_INFO, | ||||||
|  | +				   "   Invalid attribute %d (too short for extended type)", | ||||||
|  | +				hdr->type); | ||||||
|  | +			return; | ||||||
|  | +		} | ||||||
|  |   | ||||||
|  | -	if (attr == NULL || hdr->length < sizeof(struct radius_attr_hdr)) | ||||||
|  | -		return; | ||||||
|  | +		ext = (struct radius_attr_hdr_ext *) hdr; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (ext) { | ||||||
|  | +		attr = radius_get_attr_type((ext->type << 8) | ext->ext_type); | ||||||
|  | +		wpa_printf(MSG_INFO, "   Attribute %d.%d (%s) length=%d", | ||||||
|  | +			   ext->type, ext->ext_type, | ||||||
|  | +			   attr ? attr->name : "?Unknown?", ext->length); | ||||||
|  | +		pos = (unsigned char *) (ext + 1); | ||||||
|  | +		len = ext->length - sizeof(struct radius_attr_hdr_ext); | ||||||
|  | +	} else { | ||||||
|  | +		attr = radius_get_attr_type(hdr->type); | ||||||
|  | +		wpa_printf(MSG_INFO, "   Attribute %d (%s) length=%d", | ||||||
|  | +			   hdr->type, attr ? attr->name : "?Unknown?", | ||||||
|  | +			   hdr->length); | ||||||
|  | +		pos = (unsigned char *) (hdr + 1); | ||||||
|  | +		len = hdr->length - sizeof(struct radius_attr_hdr); | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  | -	len = hdr->length - sizeof(struct radius_attr_hdr); | ||||||
|  | -	pos = (unsigned char *) (hdr + 1); | ||||||
|  | +	if (!attr) | ||||||
|  | +		return; | ||||||
|  |   | ||||||
|  |  	switch (attr->data_type) { | ||||||
|  |  	case RADIUS_ATTR_TEXT: | ||||||
|  | @@ -627,22 +685,54 @@ static int radius_msg_add_attr_to_array(struct radius_msg *msg, | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |   | ||||||
|  | -struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type, | ||||||
|  | -					    const u8 *data, size_t data_len) | ||||||
|  | +struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u16 type, | ||||||
|  | +					     const u8 *data, size_t data_len) | ||||||
|  |  { | ||||||
|  | -	size_t buf_needed; | ||||||
|  | -	struct radius_attr_hdr *attr; | ||||||
|  | +	size_t buf_needed, max_len; | ||||||
|  | +	struct radius_attr_hdr *attr = NULL; | ||||||
|  | +	struct radius_attr_hdr_ext *ext; | ||||||
|  | +	u8 ext_type = 0; | ||||||
|  |   | ||||||
|  |  	if (TEST_FAIL()) | ||||||
|  |  		return NULL; | ||||||
|  |   | ||||||
|  | -	if (data_len > RADIUS_MAX_ATTR_LEN) { | ||||||
|  | -		wpa_printf(MSG_ERROR, "radius_msg_add_attr: too long attribute (%lu bytes)", | ||||||
|  | -		       (unsigned long) data_len); | ||||||
|  | -		return NULL; | ||||||
|  | +	if (type > 255) { | ||||||
|  | +		if (!radius_is_ext_type(type >> 8)) { | ||||||
|  | +			wpa_printf(MSG_ERROR, | ||||||
|  | +				   "%s: Undefined extended type %d.%d", | ||||||
|  | +				   __func__, type >> 8, type & 0xff); | ||||||
|  | +			return NULL; | ||||||
|  | +		} | ||||||
|  | +		ext_type = type & 0xff; | ||||||
|  | +		type >>= 8; | ||||||
|  | +	} else if (radius_is_ext_type(type)) { | ||||||
|  | +		wpa_printf(MSG_ERROR, "%s: Unexpected extended type use for %d", | ||||||
|  | +			   __func__, type); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	buf_needed = sizeof(*attr) + data_len; | ||||||
|  | +	if (radius_is_long_ext_type(type)) { | ||||||
|  | +		size_t hdr_len = sizeof(struct radius_attr_hdr_ext) + 1; | ||||||
|  | +		size_t plen = 255 - hdr_len; | ||||||
|  | +		size_t num; | ||||||
|  | + | ||||||
|  | +		max_len = 4096; | ||||||
|  | +		num = (data_len + plen - 1) / plen; | ||||||
|  | +		if (num == 0) | ||||||
|  | +			num = 1; | ||||||
|  | +		buf_needed = num * hdr_len + data_len; | ||||||
|  | +	} else if (radius_is_ext_type(type)) { | ||||||
|  | +		max_len = RADIUS_MAX_EXT_ATTR_LEN; | ||||||
|  | +		buf_needed = sizeof(struct radius_attr_hdr_ext) + data_len; | ||||||
|  | +	} else { | ||||||
|  | +		max_len = RADIUS_MAX_ATTR_LEN; | ||||||
|  | +		buf_needed = sizeof(*attr) + data_len; | ||||||
|  | +	} | ||||||
|  | +	if (data_len > max_len) { | ||||||
|  | +		wpa_printf(MSG_ERROR, | ||||||
|  | +			   "%s: too long attribute (%zu > %zu bytes)", | ||||||
|  | +			   __func__, data_len, max_len); | ||||||
|  | +		return NULL; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	if (wpabuf_tailroom(msg->buf) < buf_needed) { | ||||||
|  |  		/* allocate more space for message buffer */ | ||||||
|  | @@ -651,13 +741,44 @@ struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type, | ||||||
|  |  		msg->hdr = wpabuf_mhead(msg->buf); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	attr = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr)); | ||||||
|  | -	attr->type = type; | ||||||
|  | -	attr->length = sizeof(*attr) + data_len; | ||||||
|  | -	wpabuf_put_data(msg->buf, data, data_len); | ||||||
|  | - | ||||||
|  | -	if (radius_msg_add_attr_to_array(msg, attr)) | ||||||
|  | -		return NULL; | ||||||
|  | +	if (radius_is_long_ext_type(type)) { | ||||||
|  | +		size_t plen = 255 - sizeof(struct radius_attr_hdr_ext) - 1; | ||||||
|  | +		size_t alen; | ||||||
|  | + | ||||||
|  | +		do { | ||||||
|  | +			alen = data_len > plen ? plen : data_len; | ||||||
|  | +			ext = wpabuf_put(msg->buf, | ||||||
|  | +					 sizeof(struct radius_attr_hdr_ext)); | ||||||
|  | +			if (!attr) | ||||||
|  | +				attr = (struct radius_attr_hdr *) ext; | ||||||
|  | +			ext->type = type; | ||||||
|  | +			ext->length = sizeof(*ext) + 1 + alen; | ||||||
|  | +			ext->ext_type = ext_type; | ||||||
|  | +			wpabuf_put_u8(msg->buf, data_len > alen ? 0x80 : 0); | ||||||
|  | +			wpabuf_put_data(msg->buf, data, data_len); | ||||||
|  | +			data += alen; | ||||||
|  | +			data_len -= alen; | ||||||
|  | +			if (radius_msg_add_attr_to_array( | ||||||
|  | +				    msg, (struct radius_attr_hdr *) ext)) | ||||||
|  | +				return NULL; | ||||||
|  | +		} while (data_len > 0); | ||||||
|  | +	} else if (radius_is_ext_type(type)) { | ||||||
|  | +		ext = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr_ext)); | ||||||
|  | +		attr = (struct radius_attr_hdr *) ext; | ||||||
|  | +		ext->type = type; | ||||||
|  | +		ext->length = sizeof(*ext) + data_len; | ||||||
|  | +		ext->ext_type = ext_type; | ||||||
|  | +		wpabuf_put_data(msg->buf, data, data_len); | ||||||
|  | +		if (radius_msg_add_attr_to_array(msg, attr)) | ||||||
|  | +			return NULL; | ||||||
|  | +	} else { | ||||||
|  | +		attr = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr)); | ||||||
|  | +		attr->type = type; | ||||||
|  | +		attr->length = sizeof(*attr) + data_len; | ||||||
|  | +		wpabuf_put_data(msg->buf, data, data_len); | ||||||
|  | +		if (radius_msg_add_attr_to_array(msg, attr)) | ||||||
|  | +			return NULL; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	return attr; | ||||||
|  |  } | ||||||
|  | @@ -1285,6 +1406,28 @@ int radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data, | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |   | ||||||
|  | +int radius_msg_add_ext_vs(struct radius_msg *msg, u16 type, u32 vendor_id, | ||||||
|  | +			  u8 vendor_type, const u8 *data, size_t len) | ||||||
|  | +{ | ||||||
|  | +	struct radius_attr_hdr *attr; | ||||||
|  | +	u8 *buf, *pos; | ||||||
|  | +	size_t alen; | ||||||
|  | + | ||||||
|  | +	alen = 4 + 1 + len; | ||||||
|  | +	buf = os_malloc(alen); | ||||||
|  | +	if (!buf) | ||||||
|  | +		return 0; | ||||||
|  | +	pos = buf; | ||||||
|  | +	WPA_PUT_BE32(pos, vendor_id); | ||||||
|  | +	pos += 4; | ||||||
|  | +	*pos++ = vendor_type; | ||||||
|  | +	os_memcpy(pos, data, len); | ||||||
|  | +	attr = radius_msg_add_attr(msg, type, buf, alen); | ||||||
|  | +	os_free(buf); | ||||||
|  | +	return attr != NULL; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | + | ||||||
|  |  int radius_user_password_hide(struct radius_msg *msg, | ||||||
|  |  			      const u8 *data, size_t data_len, | ||||||
|  |  			      const u8 *secret, size_t secret_len, | ||||||
|  | diff --git a/src/radius/radius.h b/src/radius/radius.h | ||||||
|  | index fb8148180..490c8d1f6 100644 | ||||||
|  | --- a/src/radius/radius.h | ||||||
|  | +++ b/src/radius/radius.h | ||||||
|  | @@ -1,6 +1,6 @@ | ||||||
|  |  /* | ||||||
|  |   * RADIUS message processing | ||||||
|  | - * Copyright (c) 2002-2009, 2012, 2014-2015, Jouni Malinen <j@w1.fi> | ||||||
|  | + * Copyright (c) 2002-2009, 2012, 2014-2022, Jouni Malinen <j@w1.fi> | ||||||
|  |   * | ||||||
|  |   * This software may be distributed under the terms of the BSD license. | ||||||
|  |   * See README for more details. | ||||||
|  | @@ -46,7 +46,15 @@ struct radius_attr_hdr { | ||||||
|  |  	/* followed by length-2 octets of attribute value */ | ||||||
|  |  } STRUCT_PACKED; | ||||||
|  |   | ||||||
|  | +struct radius_attr_hdr_ext { | ||||||
|  | +	u8 type; | ||||||
|  | +	u8 length; /* including this header */ | ||||||
|  | +	u8 ext_type; | ||||||
|  | +	/* followed by length-3 octets of attribute value */ | ||||||
|  | +} STRUCT_PACKED; | ||||||
|  | + | ||||||
|  |  #define RADIUS_MAX_ATTR_LEN (255 - sizeof(struct radius_attr_hdr)) | ||||||
|  | +#define RADIUS_MAX_EXT_ATTR_LEN (255 - sizeof(struct radius_attr_hdr_ext)) | ||||||
|  |   | ||||||
|  |  enum { RADIUS_ATTR_USER_NAME = 1, | ||||||
|  |         RADIUS_ATTR_USER_PASSWORD = 2, | ||||||
|  | @@ -113,6 +121,18 @@ enum { RADIUS_ATTR_USER_NAME = 1, | ||||||
|  |         RADIUS_ATTR_WLAN_GROUP_CIPHER = 187, | ||||||
|  |         RADIUS_ATTR_WLAN_AKM_SUITE = 188, | ||||||
|  |         RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER = 189, | ||||||
|  | +       RADIUS_ATTR_EXT_TYPE_1 = 241, | ||||||
|  | +       RADIUS_ATTR_EXT_TYPE_2 = 242, | ||||||
|  | +       RADIUS_ATTR_EXT_TYPE_3 = 243, | ||||||
|  | +       RADIUS_ATTR_EXT_TYPE_4 = 244, | ||||||
|  | +       RADIUS_ATTR_LONG_EXT_TYPE_1 = 245, | ||||||
|  | +       RADIUS_ATTR_LONG_EXT_TYPE_2 = 246, | ||||||
|  | +       RADIUS_ATTR_EXT_VENDOR_SPECIFIC_1 = (241 << 8) | 26, | ||||||
|  | +       RADIUS_ATTR_EXT_VENDOR_SPECIFIC_2 = (242 << 8) | 26, | ||||||
|  | +       RADIUS_ATTR_EXT_VENDOR_SPECIFIC_3 = (243 << 8) | 26, | ||||||
|  | +       RADIUS_ATTR_EXT_VENDOR_SPECIFIC_4 = (244 << 8) | 26, | ||||||
|  | +       RADIUS_ATTR_EXT_VENDOR_SPECIFIC_5 = (245 << 8) | 26, | ||||||
|  | +       RADIUS_ATTR_EXT_VENDOR_SPECIFIC_6 = (246 << 8) | 26, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |   | ||||||
|  | @@ -257,7 +277,7 @@ int radius_msg_verify_acct_req(struct radius_msg *msg, const u8 *secret, | ||||||
|  |  int radius_msg_verify_das_req(struct radius_msg *msg, const u8 *secret, | ||||||
|  |  			      size_t secret_len, | ||||||
|  |  			      int require_message_authenticator); | ||||||
|  | -struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u8 type, | ||||||
|  | +struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u16 type, | ||||||
|  |  					     const u8 *data, size_t data_len); | ||||||
|  |  struct radius_msg * radius_msg_parse(const u8 *data, size_t len); | ||||||
|  |  int radius_msg_add_eap(struct radius_msg *msg, const u8 *data, | ||||||
|  | @@ -284,6 +304,8 @@ int radius_msg_add_mppe_keys(struct radius_msg *msg, | ||||||
|  |  			     const u8 *recv_key, size_t recv_key_len); | ||||||
|  |  int radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data, | ||||||
|  |  		       size_t len); | ||||||
|  | +int radius_msg_add_ext_vs(struct radius_msg *msg, u16 type, u32 vendor_id, | ||||||
|  | +			  u8 vendor_type, const u8 *data, size_t len); | ||||||
|  |  int radius_user_password_hide(struct radius_msg *msg, | ||||||
|  |  			      const u8 *data, size_t data_len, | ||||||
|  |  			      const u8 *secret, size_t secret_len, | ||||||
|  | --  | ||||||
|  | 2.25.1 | ||||||
|  |  | ||||||
| @@ -0,0 +1,102 @@ | |||||||
|  | From b94371af8402f60218716552e571ca72cff4e3c0 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jouni Malinen <j@w1.fi> | ||||||
|  | Date: Fri, 15 Apr 2022 17:36:25 +0300 | ||||||
|  | Subject: [PATCH] RADIUS attributes for EAPOL-Key message details | ||||||
|  |  | ||||||
|  | Use vendor specific RADIUS attributes for sending ANonce and EAPOL-Key | ||||||
|  | msg 2/4 for the wpa_psk_radius=3 case. The vendor specific attributes | ||||||
|  | for this are defined in FreeRADIUS as follows: | ||||||
|  |  | ||||||
|  | BEGIN-VENDOR    FreeRADIUS      format=Extended-Vendor-Specific-5 | ||||||
|  | ATTRIBUTE       FreeRADIUS-802.1X-Anonce        1       octets[32] | ||||||
|  | ATTRIBUTE       FreeRADIUS-802.1X-EAPoL-Key-Msg 2       octets | ||||||
|  | END-VENDOR      FreeRADIUS | ||||||
|  |  | ||||||
|  | Signed-off-by: Jouni Malinen <j@w1.fi> | ||||||
|  | --- | ||||||
|  |  src/ap/ieee802_11_auth.c | 29 +++++++++++++++++++++++++++++ | ||||||
|  |  src/radius/radius.h      |  7 +++++++ | ||||||
|  |  2 files changed, 36 insertions(+) | ||||||
|  |  | ||||||
|  | diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c | ||||||
|  | index a54d7616e..4277d82cb 100644 | ||||||
|  | --- a/src/ap/ieee802_11_auth.c | ||||||
|  | +++ b/src/ap/ieee802_11_auth.c | ||||||
|  | @@ -47,6 +47,9 @@ struct hostapd_acl_query_data { | ||||||
|  |  	struct hostapd_acl_query_data *next; | ||||||
|  |  	bool radius_psk; | ||||||
|  |  	int akm; | ||||||
|  | +	u8 *anonce; | ||||||
|  | +	u8 *eapol; | ||||||
|  | +	size_t eapol_len; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |   | ||||||
|  | @@ -102,6 +105,8 @@ static void hostapd_acl_query_free(struct hostapd_acl_query_data *query) | ||||||
|  |  	if (!query) | ||||||
|  |  		return; | ||||||
|  |  	os_free(query->auth_msg); | ||||||
|  | +	os_free(query->anonce); | ||||||
|  | +	os_free(query->eapol); | ||||||
|  |  	os_free(query); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -164,6 +169,24 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, | ||||||
|  |  		goto fail; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (query->anonce && | ||||||
|  | +	    !radius_msg_add_ext_vs(msg, RADIUS_ATTR_EXT_VENDOR_SPECIFIC_5, | ||||||
|  | +				   RADIUS_VENDOR_ID_FREERADIUS, | ||||||
|  | +				   RADIUS_VENDOR_ATTR_FREERADIUS_802_1X_ANONCE, | ||||||
|  | +				   query->anonce, WPA_NONCE_LEN)) { | ||||||
|  | +		wpa_printf(MSG_DEBUG, "Could not add FreeRADIUS-802.1X-Anonce"); | ||||||
|  | +		goto fail; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (query->eapol && | ||||||
|  | +	    !radius_msg_add_ext_vs(msg, RADIUS_ATTR_EXT_VENDOR_SPECIFIC_5, | ||||||
|  | +				   RADIUS_VENDOR_ID_FREERADIUS, | ||||||
|  | +				   RADIUS_VENDOR_ATTR_FREERADIUS_802_1X_EAPOL_KEY_MSG, | ||||||
|  | +				   query->eapol, query->eapol_len)) { | ||||||
|  | +		wpa_printf(MSG_DEBUG, "Could not add FreeRADIUS-802.1X-EAPoL-Key-Msg"); | ||||||
|  | +		goto fail; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0) | ||||||
|  |  		goto fail; | ||||||
|  |  	return 0; | ||||||
|  | @@ -703,6 +726,12 @@ void hostapd_acl_req_radius_psk(struct hostapd_data *hapd, const u8 *addr, | ||||||
|  |  	query->akm = key_mgmt; | ||||||
|  |  	os_get_reltime(&query->timestamp); | ||||||
|  |  	os_memcpy(query->addr, addr, ETH_ALEN); | ||||||
|  | +	if (anonce) | ||||||
|  | +		query->anonce = os_memdup(anonce, WPA_NONCE_LEN); | ||||||
|  | +	if (eapol) { | ||||||
|  | +		query->eapol = os_memdup(eapol, eapol_len); | ||||||
|  | +		query->eapol_len = eapol_len; | ||||||
|  | +	} | ||||||
|  |  	if (hostapd_radius_acl_query(hapd, addr, query)) { | ||||||
|  |  		wpa_printf(MSG_DEBUG, | ||||||
|  |  			   "Failed to send Access-Request for RADIUS PSK/ACL query"); | ||||||
|  | diff --git a/src/radius/radius.h b/src/radius/radius.h | ||||||
|  | index 490c8d1f6..177c64a66 100644 | ||||||
|  | --- a/src/radius/radius.h | ||||||
|  | +++ b/src/radius/radius.h | ||||||
|  | @@ -208,6 +208,13 @@ enum { RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY = 16, | ||||||
|  |         RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY = 17 | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +/* FreeRADIUS vendor-specific attributes */ | ||||||
|  | +#define RADIUS_VENDOR_ID_FREERADIUS 11344 | ||||||
|  | +/* Extended-Vendor-Specific-5 (245.26; long extended header) */ | ||||||
|  | +enum { | ||||||
|  | +	RADIUS_VENDOR_ATTR_FREERADIUS_802_1X_ANONCE = 1, | ||||||
|  | +	RADIUS_VENDOR_ATTR_FREERADIUS_802_1X_EAPOL_KEY_MSG = 2, | ||||||
|  | +}; | ||||||
|  |   | ||||||
|  |  /* Hotspot 2.0 - WFA Vendor-specific RADIUS Attributes */ | ||||||
|  |  #define RADIUS_VENDOR_ID_WFA 40808 | ||||||
|  | --  | ||||||
|  | 2.25.1 | ||||||
|  |  | ||||||
							
								
								
									
										32
									
								
								patches/0077-netifd-add-psk2-radius.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								patches/0077-netifd-add-psk2-radius.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | From d1e6c2041e21cccdd4fd30b28b3b48765825f976 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Arif Alam <arif.alam@netexperience.com> | ||||||
|  | Date: Sun, 24 Mar 2024 12:18:11 -0400 | ||||||
|  | Subject: [PATCH] netifd: add psk2-radius | ||||||
|  |  | ||||||
|  | Signed-off-by: Arif Alam <arif.alam@netexperience.com> | ||||||
|  | --- | ||||||
|  |  .../config/netifd/patches/005-psk2-radius.patch      | 12 ++++++++++++ | ||||||
|  |  1 file changed, 12 insertions(+) | ||||||
|  |  create mode 100644 package/network/config/netifd/patches/005-psk2-radius.patch | ||||||
|  |  | ||||||
|  | diff --git a/package/network/config/netifd/patches/005-psk2-radius.patch b/package/network/config/netifd/patches/005-psk2-radius.patch | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..f6dab51c8a | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/package/network/config/netifd/patches/005-psk2-radius.patch | ||||||
|  | @@ -0,0 +1,12 @@ | ||||||
|  | +--- a/scripts/netifd-wireless.sh | ||||||
|  | ++++ b/scripts/netifd-wireless.sh | ||||||
|  | +@@ -266,6 +266,9 @@ wireless_vif_parse_encryption() { | ||||||
|  | + 		wpa3*) | ||||||
|  | + 			auth_type=eap2 | ||||||
|  | + 		;; | ||||||
|  | ++		psk2-radius*) | ||||||
|  | ++			auth_type=psk2-radius | ||||||
|  | ++		;; | ||||||
|  | + 		psk3-mixed*|sae-mixed*) | ||||||
|  | + 			auth_type=psk-sae | ||||||
|  | + 		;; | ||||||
|  | --  | ||||||
|  | 2.43.0 | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user
	 Arif Alam
					Arif Alam