mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-30 18:07:52 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			973 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			973 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 658484bf494873895a1e78835a65ed8297e67348 Mon Sep 17 00:00:00 2001
 | |
| From: John Crispin <john@phrozen.org>
 | |
| Date: Mon, 30 May 2022 14:57:44 +0200
 | |
| Subject: [PATCH 14/15] hostapd: add psk2-radius support
 | |
| 
 | |
| Signed-off-by: John Crispin <john@phrozen.org>
 | |
| ---
 | |
|  ...ACL-PSK-check-during-4-way-handshake.patch | 484 ++++++++++++++++++
 | |
|  ...ributes-with-Extended-Types-RFC-6929.patch | 350 +++++++++++++
 | |
|  ...ibutes-for-EAPOL-Key-message-details.patch | 102 ++++
 | |
|  3 files changed, 936 insertions(+)
 | |
|  create mode 100644 package/network/services/hostapd/patches/n00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch
 | |
|  create mode 100644 package/network/services/hostapd/patches/n00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch
 | |
|  create mode 100644 package/network/services/hostapd/patches/n00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch
 | |
| 
 | |
| diff --git a/package/network/services/hostapd/patches/n00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch b/package/network/services/hostapd/patches/n00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch
 | |
| new file mode 100644
 | |
| index 0000000000..7a265ecc6b
 | |
| --- /dev/null
 | |
| +++ b/package/network/services/hostapd/patches/n00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch
 | |
| @@ -0,0 +1,484 @@
 | |
| +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(-)
 | |
| +
 | |
| +Index: hostapd-2022-01-16-cff80b4f/hostapd/config_file.c
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/hostapd/config_file.c
 | |
| ++++ hostapd-2022-01-16-cff80b4f/hostapd/config_file.c
 | |
| +@@ -2989,7 +2989,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);
 | |
| +Index: hostapd-2022-01-16-cff80b4f/hostapd/hostapd.conf
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/hostapd/hostapd.conf
 | |
| ++++ hostapd-2022-01-16-cff80b4f/hostapd/hostapd.conf
 | |
| +@@ -1651,12 +1651,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
 | |
| +Index: hostapd-2022-01-16-cff80b4f/src/ap/ap_config.c
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/src/ap/ap_config.c
 | |
| ++++ hostapd-2022-01-16-cff80b4f/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 "
 | |
| +Index: hostapd-2022-01-16-cff80b4f/src/ap/ap_config.h
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/src/ap/ap_config.h
 | |
| ++++ hostapd-2022-01-16-cff80b4f/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.
 | |
| +@@ -369,7 +369,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 */
 | |
| +Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/src/ap/ieee802_11.c
 | |
| ++++ hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
 | |
| +@@ -2315,9 +2315,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;
 | |
| +Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.h
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/src/ap/ieee802_11.h
 | |
| ++++ hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.h
 | |
| +@@ -196,5 +196,7 @@ void auth_sae_process_commit(void *eloop
 | |
| + u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t 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 */
 | |
| +Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11_auth.c
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/src/ap/ieee802_11_auth.c
 | |
| ++++ hostapd-2022-01-16-cff80b4f/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;
 | |
| +@@ -557,17 +568,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)
 | |
| +@@ -649,3 +683,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 */
 | |
| +Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11_auth.h
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/src/ap/ieee802_11_auth.h
 | |
| ++++ hostapd-2022-01-16-cff80b4f/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 */
 | |
| +Index: hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth.c
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/src/ap/wpa_auth.c
 | |
| ++++ hostapd-2022-01-16-cff80b4f/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.
 | |
| +@@ -1481,6 +1481,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;
 | |
| +@@ -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");
 | |
| +@@ -3774,6 +3793,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");
 | |
| +@@ -5688,3 +5712,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);
 | |
| ++}
 | |
| +Index: hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth.h
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/src/ap/wpa_auth.h
 | |
| ++++ hostapd-2022-01-16-cff80b4f/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);
 | |
| +@@ -572,4 +577,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 */
 | |
| +Index: hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth_glue.c
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/src/ap/wpa_auth_glue.c
 | |
| ++++ hostapd-2022-01-16-cff80b4f/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;
 | |
| + }
 | |
| + 
 | |
| + 
 | |
| +@@ -1444,6 +1447,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;
 | |
| +@@ -1487,6 +1507,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;
 | |
| +Index: hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth_i.h
 | |
| +===================================================================
 | |
| +--- hostapd-2022-01-16-cff80b4f.orig/src/ap/wpa_auth_i.h
 | |
| ++++ hostapd-2022-01-16-cff80b4f/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;
 | |
| diff --git a/package/network/services/hostapd/patches/n00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch b/package/network/services/hostapd/patches/n00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch
 | |
| new file mode 100644
 | |
| index 0000000000..eef9117176
 | |
| --- /dev/null
 | |
| +++ b/package/network/services/hostapd/patches/n00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch
 | |
| @@ -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
 | |
| +
 | |
| diff --git a/package/network/services/hostapd/patches/n00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch b/package/network/services/hostapd/patches/n00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch
 | |
| new file mode 100644
 | |
| index 0000000000..df8baa7856
 | |
| --- /dev/null
 | |
| +++ b/package/network/services/hostapd/patches/n00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch
 | |
| @@ -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
 | |
| +
 | |
| -- 
 | |
| 2.25.1
 | |
| 
 | 
