From 1ec29f67054aa1be5b6e5e6f3bb7b58149135927 Mon Sep 17 00:00:00 2001 From: Arif Alam Date: Mon, 25 Mar 2024 09:41:39 -0400 Subject: [PATCH] Fix psk2-radius feature Add psk2-radius functionality in hostapd and fix config via netifd. Fixes WIFI-13183 Signed-off-by: Arif Alam --- ...ACL-PSK-check-during-4-way-handshake.patch | 459 ++++++++++++++++++ ...ributes-with-Extended-Types-RFC-6929.patch | 350 +++++++++++++ ...ibutes-for-EAPOL-Key-message-details.patch | 102 ++++ patches/0077-netifd-add-psk2-radius.patch | 32 ++ 4 files changed, 943 insertions(+) create mode 100644 feeds/ipq807x_v5.4/hostapd/patches/s00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch create mode 100644 feeds/ipq807x_v5.4/hostapd/patches/s00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch create mode 100644 feeds/ipq807x_v5.4/hostapd/patches/s00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch create mode 100644 patches/0077-netifd-add-psk2-radius.patch diff --git a/feeds/ipq807x_v5.4/hostapd/patches/s00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch b/feeds/ipq807x_v5.4/hostapd/patches/s00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch new file mode 100644 index 000000000..75dd7ddb0 --- /dev/null +++ b/feeds/ipq807x_v5.4/hostapd/patches/s00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch @@ -0,0 +1,459 @@ +From 1c3438fec4bad13a676617915ff56af54e7b4542 Mon Sep 17 00:00:00 2001 +From: Jouni Malinen +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 +--- + 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 ++ * Copyright (c) 2003-2022, Jouni Malinen + * + * 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 ++ * Copyright (c) 2003-2022, Jouni Malinen + * + * 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 ++ * Copyright (c) 2003-2022, Jouni Malinen + * + * 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 ++ * Copyright (c) 2003-2022, Jouni Malinen + * + * 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 ++ * Copyright (c) 2004-2022, Jouni Malinen + * + * 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 ++ * Copyright (c) 2004-2022, Jouni Malinen + * + * 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 ++ * Copyright (c) 2002-2022, Jouni Malinen + * + * 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; diff --git a/feeds/ipq807x_v5.4/hostapd/patches/s00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch b/feeds/ipq807x_v5.4/hostapd/patches/s00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch new file mode 100644 index 000000000..eef911717 --- /dev/null +++ b/feeds/ipq807x_v5.4/hostapd/patches/s00-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 +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 +--- + 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 ++ * Copyright (c) 2002-2009, 2011-2022, Jouni Malinen + * + * 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) | 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 ++ * Copyright (c) 2002-2009, 2012, 2014-2022, Jouni Malinen + * + * 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/feeds/ipq807x_v5.4/hostapd/patches/s00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch b/feeds/ipq807x_v5.4/hostapd/patches/s00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch new file mode 100644 index 000000000..df8baa785 --- /dev/null +++ b/feeds/ipq807x_v5.4/hostapd/patches/s00-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 +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 +--- + 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 + diff --git a/patches/0077-netifd-add-psk2-radius.patch b/patches/0077-netifd-add-psk2-radius.patch new file mode 100644 index 000000000..b4d53d7d4 --- /dev/null +++ b/patches/0077-netifd-add-psk2-radius.patch @@ -0,0 +1,32 @@ +From d1e6c2041e21cccdd4fd30b28b3b48765825f976 Mon Sep 17 00:00:00 2001 +From: Arif Alam +Date: Sun, 24 Mar 2024 12:18:11 -0400 +Subject: [PATCH] netifd: add psk2-radius + +Signed-off-by: Arif Alam +--- + .../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 +