From patchwork Fri Apr 16 06:13:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: michael-dev X-Patchwork-Id: 1466856 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2001:8b0:10b:1:d65d:64ff:fe57:4e05; helo=desiato.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=desiato.20200630 header.b=p5Suakfn; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=infradead.org header.i=@infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=kRDJLKN4; dkim-atps=neutral Received: from desiato.infradead.org (desiato.infradead.org [IPv6:2001:8b0:10b:1:d65d:64ff:fe57:4e05]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FM5bL5PYwz9sRK for ; Fri, 16 Apr 2021 16:17:18 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=bnK5POvQ/k3ENEfd+y6Bnnsm9U5Ih27PlHWj5qRDpgQ=; b=p5SuakfnblG80uNDuPYBcSUwU 7HNYN/8JLfh6Fkzuoxv/qs55+e1UlT9DWUW06wMxPmaLG6XtetZJdhRwbvox9xzHfwt9G0cHeSlp9 OwzGfiA6InBqd/YfcpscdvzSsX3bih6KC05JHb47O10Po41pstBICXODjj6aFwV7sRq9jC5IH6CkY 6bOvDNd8hD82hcGmGWhleY6aWMdvYyWhtfztsWf9ZaJt1qOXdMApgPYj7malvuPxYfnV3SSIIT/di RRHXFoUlcYuMLbfMUnOOU398gUluDBslU8hgc8jguQSgSPSrETIXHbDEpbbsWGEzftv0Qn6n4+ppW p7FGgMZew==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lXHmP-000zjI-RY; Fri, 16 Apr 2021 06:16:38 +0000 Received: from bombadil.infradead.org ([2607:7c80:54:e::133]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lXHjZ-000z9y-Ai for hostap@desiato.infradead.org; Fri, 16 Apr 2021 06:13:43 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=gMdB34Vi6n3H5PA6SSEaKNWcZzlLR0bZoIXxwuRz13k=; b=kRDJLKN4XXsnRHxigLyMWi0nxd BlGc1vfU522Jj0QuiV4Dk+7jwzd1r2S3jaFC4EsTZYKyVkn8U3Cwl+IrfVKdaNs4ZzX8L+1h3cz0O oIfhTseL3EM0xfrMQJLNLHctRqgCopcGE3Re8SyLbpkS67DKxtsKYkQlv37aH2DWtSJeepxixJov8 jY8ZQVrmlsj+0lHYPBD1DhS+Txya3kHg6SXYZ9uA43DNdc/ICZdQ8Poa+W6jV5ohFxuSIK+Edejxq kcxjdjfum38yZM50KJm53D1Mir3ksY0WdA1q6awUCiTYwshqFCWvT208dMvX705kN3Pr2dP5upJV1 l7A4r/RQ==; Received: from smail.fem.tu-ilmenau.de ([141.24.220.41]) by bombadil.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lXHjU-0096nI-Ti for hostap@lists.infradead.org; Fri, 16 Apr 2021 06:13:40 +0000 Received: from a234.fem.tu-ilmenau.de (ray-controller.net.fem.tu-ilmenau.de [10.42.51.234]) by smail.fem.tu-ilmenau.de (Postfix) with ESMTP id C76B32031C; Fri, 16 Apr 2021 08:13:34 +0200 (CEST) Received: by a234.fem.tu-ilmenau.de (Postfix, from userid 1000) id 9748030D7133; Fri, 16 Apr 2021 08:13:34 +0200 (CEST) From: michael-dev@fami-braun.de To: hostap@lists.infradead.org Cc: projekt-wlan@fem.tu-ilmenau.de, michael-dev@fami-braun.de Subject: [PATCH 1/2] SAE: add RADIUS Tunnel-Password support Date: Fri, 16 Apr 2021 08:13:31 +0200 Message-Id: <20210416061332.16388-2-michael-dev@fami-braun.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210416061332.16388-1-michael-dev@fami-braun.de> References: <20210416061332.16388-1-michael-dev@fami-braun.de> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210415_231337_307513_12DFD97D X-CRM114-Status: GOOD ( 30.02 ) X-Spam-Score: -2.3 (--) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Michael Braun If no matching sae_password is configured in hostapd, use the RADIUS supplied Tunnel-Password as SAE password. Though, that is still subject to the length constraint of WPA passphrase (8..63 chars) to [...] Content analysis details: (-2.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [141.24.220.41 listed in list.dnswl.org] 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Michael Braun If no matching sae_password is configured in hostapd, use the RADIUS supplied Tunnel-Password as SAE password. Though, that is still subject to the length constraint of WPA passphrase (8..63 chars) to avoid ambiguation. The SAE password identifier can be optionally supplied using Tunnel-Client-Auth-ID. Signed-off-by: Michael Braun --- hostapd/hostapd.conf | 6 ++ src/ap/ap_config.c | 8 ++ src/ap/ap_config.h | 9 +- src/ap/ieee802_11.c | 61 +++++++++++++ src/ap/ieee802_11_auth.c | 145 ++++++++++++++++++++++-------- src/ap/wpa_auth_glue.c | 28 ++++-- src/radius/radius.c | 188 +++++++++++++++++++++++++-------------- src/radius/radius.h | 7 +- 8 files changed, 334 insertions(+), 118 deletions(-) diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 7932cb862..7ccad8912 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1867,6 +1867,12 @@ own_ip_addr=127.0.0.1 # WPA-PSK and both values are set, SAE uses the sae_password values and WPA-PSK # uses the wpa_passphrase value. # +# If no sae_password matches, RADIUS supplied Tunnel-Password are used with +# higher priority than wpa_passphrase if wpa_psk_radius > 0 except. Thought, +# the WPA-PSK constraints (8..63 chars) apply here was well. +# The corresponding SAE password identifier can optionally be supplied using +# Tunnel-Client-Auth-ID. +# # Each sae_password entry is added to a list of available passwords. This # corresponds to the dot11RSNAConfigPasswordValueEntry. sae_password value # starts with the password (dot11RSNAConfigPasswordCredential). That value can diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 7b6249bbe..5357f08d2 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -1588,6 +1588,11 @@ int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf) if (conf->ssid.wpa_passphrase) without_id = 1; + if (conf->wpa_psk_radius != PSK_RADIUS_IGNORED) { + with_id = 1; + without_id = 1; + } + for (pw = conf->sae_passwords; pw; pw = pw->next) { if (pw->identifier) with_id = 1; @@ -1627,6 +1632,9 @@ bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf) if (conf->ssid.wpa_passphrase) return false; + if (conf->wpa_psk_radius != PSK_RADIUS_IGNORED) + return false; + for (pw = conf->sae_passwords; pw; pw = pw->next) { if (!pw->pk) return false; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 95bd79873..4778b3937 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -148,9 +148,12 @@ struct hostapd_vlan { #define MAX_PASSPHRASE_LEN 63 struct hostapd_sta_wpa_psk_short { struct hostapd_sta_wpa_psk_short *next; - unsigned int is_passphrase:1; - u8 psk[PMK_LEN]; - char passphrase[MAX_PASSPHRASE_LEN + 1]; + u8 *psk; + char *passphrase; +#ifdef CONFIG_SAE + char *sae_identifier; + struct sae_pt *sae_pt; +#endif /* CONFIG_SAE */ int ref; /* (number of references held) - 1 */ }; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index b404e84af..90f8cef67 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -487,6 +487,63 @@ static void sae_set_state(struct sta_info *sta, enum sae_state state, } +static void sae_derive_pt_from_psk(struct hostapd_data *hapd, + struct hostapd_sta_wpa_psk_short *psk) +{ + struct hostapd_ssid *ssid; + + if (!psk->passphrase) + return; + if (psk->sae_pt) + return; + + ssid = &hapd->conf->ssid; + + psk->sae_pt = sae_derive_pt(hapd->conf->sae_groups, ssid->ssid, + ssid->ssid_len, (u8 *) psk->passphrase, + os_strlen(psk->passphrase), + psk->sae_identifier); + +} + + +static const char * sae_get_password_from_psk(struct hostapd_data *hapd, + struct sta_info *sta, + const char *rx_id, + struct sae_pt **s_pt) +{ + struct hostapd_sta_wpa_psk_short *pos; + wpa_printf(MSG_DEBUG, "SAE: get password for peer " MACSTR + " with rx_id=%s", MAC2STR(sta->addr), + (rx_id ? rx_id : "")); + + for (pos = sta->psk; pos; pos = pos->next) { + wpa_printf(MSG_DEBUG, "SAE: rx_id=%s pos->id=%s", (rx_id ? rx_id : "NULL"), (pos->sae_identifier ? pos->sae_identifier : "NULL")); + if ((rx_id && !pos->sae_identifier) || + (!rx_id && pos->sae_identifier)) + continue; + if (rx_id && pos->sae_identifier && + os_strcmp(rx_id, pos->sae_identifier) != 0) + continue; + wpa_printf(MSG_DEBUG, "SAE: found with id matching"); + + sae_derive_pt_from_psk(hapd, pos); + + wpa_printf(MSG_DEBUG, "SAE: found with id matching got sae_pt=%p", pos->sae_pt); + + if (!pos->sae_pt) + continue; + + if (s_pt) + *s_pt = pos->sae_pt; + + return pos->passphrase; + } + + return NULL; +} + + static const char * sae_get_password(struct hostapd_data *hapd, struct sta_info *sta, const char *rx_id, @@ -514,6 +571,10 @@ static const char * sae_get_password(struct hostapd_data *hapd, pk = pw->pk; break; } + + if (!password) + password = sae_get_password_from_psk(hapd, sta, rx_id, &pt); + if (!password) { password = hapd->conf->ssid.wpa_passphrase; pt = hapd->conf->ssid.pt; diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c index 783ee6dea..7023ae103 100644 --- a/src/ap/ieee802_11_auth.c +++ b/src/ap/ieee802_11_auth.c @@ -23,6 +23,7 @@ #include "ieee802_11.h" #include "ieee802_1x.h" #include "ieee802_11_auth.h" +#include "common/sae.h" #define RADIUS_ACL_TIMEOUT 30 @@ -368,72 +369,133 @@ void hostapd_acl_expire(struct hostapd_data *hapd) hostapd_acl_expire_queries(hapd, &now); } +#ifdef CONFIG_SAE +static int get_tunnel_sae_id(struct radius_msg *msg, u8 tag, u8** buf, + size_t *len, size_t idx, size_t *next_idx) +{ + const u8 type = RADIUS_ATTR_TUNNEL_CLIENT_AUTH_ID; -static void decode_tunnel_passwords(struct hostapd_data *hapd, - const u8 *shared_secret, - size_t shared_secret_len, - struct radius_msg *msg, - struct radius_msg *req, - struct hostapd_cached_radius_acl *cache) + return radius_msg_get_attr_tag_ptr(msg, type, tag, buf, len, idx, + next_idx); +} +#endif /* CONFIG_SAE */ + + +static void decode_tunnel_password(struct hostapd_data *hapd, + const u8 *shared_secret, + size_t shared_secret_len, + struct radius_msg *msg, + struct radius_msg *req, + struct hostapd_cached_radius_acl *cache, + size_t psk_idx, size_t *psk_next) { int passphraselen; char *passphrase; - size_t i; struct hostapd_sta_wpa_psk_short *psk; - + int has_sae_id = 0; +#ifdef CONFIG_SAE + u8 tag; + u8 *sae_id; + size_t sae_id_len; + size_t sae_idx = 0, sae_idx_next; +#endif /* CONFIG_SAE */ + + passphrase = radius_msg_get_tunnel_password( + msg, &passphraselen, shared_secret, shared_secret_len, + req, psk_idx, &tag, psk_next); /* - * Decode all tunnel passwords as PSK and save them into a linked list. + * Passphrase is NULL iff there is no i-th Tunnel-Password + * attribute in msg. */ - for (i = 0; ; i++) { - passphrase = radius_msg_get_tunnel_password( - msg, &passphraselen, shared_secret, shared_secret_len, - req, i); - /* - * Passphrase is NULL iff there is no i-th Tunnel-Password - * attribute in msg. - */ - if (passphrase == NULL) - break; + if (passphrase == NULL) { + *psk_next = 0; + return; + } - /* - * Passphase should be 8..63 chars (to be hashed with SSID) - * or 64 chars hex string (no separate hashing with SSID). - */ + /* + * Passphase should be 8..63 chars (to be hashed with SSID) + * or 64 chars hex string (no separate hashing with SSID). + */ - if (passphraselen < MIN_PASSPHRASE_LEN || - passphraselen > MAX_PASSPHRASE_LEN + 1) - goto free_pass; + if (passphraselen < MIN_PASSPHRASE_LEN || + passphraselen > MAX_PASSPHRASE_LEN + 1) + goto free_pass; + do { /* * passphrase does not contain the NULL termination. * Add it here as pbkdf2_sha1() requires it. */ psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short)); - if (psk) { - if ((passphraselen == MAX_PASSPHRASE_LEN + 1) && - (hexstr2bin(passphrase, psk->psk, PMK_LEN) < 0)) { + if (!psk) + goto skip; + if (passphraselen == MAX_PASSPHRASE_LEN + 1) { + psk->psk = os_zalloc(PMK_LEN); + if (!psk->psk) + goto skip; + if (hexstr2bin(passphrase, psk->psk, PMK_LEN) < 0) { hostapd_logger(hapd, cache->addr, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_WARNING, "invalid hex string (%d chars) in Tunnel-Password", passphraselen); goto skip; - } else if (passphraselen <= MAX_PASSPHRASE_LEN) { - os_memcpy(psk->passphrase, passphrase, - passphraselen); - psk->is_passphrase = 1; } - psk->next = cache->info.psk; - cache->info.psk = psk; - psk = NULL; + } else { + psk->passphrase = os_zalloc(passphraselen + 1); + os_memcpy(psk->passphrase, passphrase, passphraselen); +#ifdef CONFIG_SAE + /* + * Lookup Tunnel-Client-Auth-ID by tag + */ + has_sae_id = !get_tunnel_sae_id(msg, tag, &sae_id, + &sae_id_len, sae_idx, + &sae_idx_next); + if (has_sae_id) { + psk->sae_identifier = os_zalloc(sae_id_len+1); + if (!psk->sae_identifier) + goto skip; + os_memcpy(psk->sae_identifier, sae_id, sae_id_len); + sae_idx = sae_idx_next; + } else if (sae_idx > 0) + goto skip; +#endif /* CONFIG_SAE */ } + psk->next = cache->info.psk; + cache->info.psk = psk; + psk = NULL; + } while (has_sae_id); + skip: + if (psk) { + os_free(psk->psk); + os_free(psk->passphrase); os_free(psk); -free_pass: - os_free(passphrase); } +free_pass: + os_free(passphrase); } +static void decode_tunnel_passwords(struct hostapd_data *hapd, + const u8 *shared_secret, + size_t shared_secret_len, + struct radius_msg *msg, + struct radius_msg *req, + struct hostapd_cached_radius_acl *cache) +{ + size_t psk_idx = 0, psk_next; + + /* + * Decode all tunnel passwords as PSK and save them into a linked list. + */ + while (1) { + decode_tunnel_password(hapd, shared_secret, shared_secret_len, + msg, req, cache, psk_idx, &psk_next); + if (psk_next == 0) + break; + psk_idx = psk_next; + } +} /** * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages @@ -646,6 +708,13 @@ void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk) while (psk) { struct hostapd_sta_wpa_psk_short *prev = psk; psk = psk->next; +#ifdef CONFIG_SAE + if (prev->sae_pt) + sae_deinit_pt(prev->sae_pt); + os_free(prev->sae_identifier); + os_free(prev->psk); + os_free(prev->passphrase); +#endif /* CONFIG_SAE */ os_free(prev); } } diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index c3b2e81e2..eb52ad248 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -381,23 +381,33 @@ static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, * logic list (all hostapd_get_psk; all sta->psk) */ if (sta && sta->psk && !psk) { - struct hostapd_sta_wpa_psk_short *pos; + struct hostapd_sta_wpa_psk_short *pos, *prev = NULL; if (vlan_id) *vlan_id = 0; - psk = sta->psk->psk; - for (pos = sta->psk; pos; pos = pos->next) { - if (pos->is_passphrase) { + + for (pos = sta->psk; pos; prev = pos, pos = pos->next) { + if (pos->passphrase && !pos->psk) { + if (prev && prev->psk && prev->passphrase && + !os_strcmp(pos->passphrase, prev->passphrase)) + continue; + + pos->psk = os_zalloc(PMK_LEN); + if (!pos->psk) + continue; + pbkdf2_sha1(pos->passphrase, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len, 4096, pos->psk, PMK_LEN); - pos->is_passphrase = 0; - } - if (pos->psk == prev_psk) { - psk = pos->next ? pos->next->psk : NULL; - break; } + + if (!pos->psk || + (prev_psk && (!prev || prev->psk != prev_psk))) + continue; + + psk = pos->psk; + break; } } return psk; diff --git a/src/radius/radius.c b/src/radius/radius.c index be16e27b9..64396d319 100644 --- a/src/radius/radius.c +++ b/src/radius/radius.c @@ -165,101 +165,108 @@ struct radius_attr_type { RADIUS_ATTR_UNDIST, RADIUS_ATTR_TEXT, RADIUS_ATTR_IP, RADIUS_ATTR_HEXDUMP, RADIUS_ATTR_INT32, RADIUS_ATTR_IPV6 } data_type; + enum { + RADIUS_ATTR_F_TAGGED = BIT(0), + RADIUS_ATTR_F_TAGGED_LIM = BIT(1), + } flags; }; static const struct radius_attr_type radius_attrs[] = { - { RADIUS_ATTR_USER_NAME, "User-Name", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_USER_PASSWORD, "User-Password", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_NAS_IP_ADDRESS, "NAS-IP-Address", RADIUS_ATTR_IP }, - { RADIUS_ATTR_NAS_PORT, "NAS-Port", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_SERVICE_TYPE, "Service-Type", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_FRAMED_IP_ADDRESS, "Framed-IP-Address", RADIUS_ATTR_IP }, - { RADIUS_ATTR_FRAMED_MTU, "Framed-MTU", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_REPLY_MESSAGE, "Reply-Message", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_STATE, "State", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_CLASS, "Class", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_VENDOR_SPECIFIC, "Vendor-Specific", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_SESSION_TIMEOUT, "Session-Timeout", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_IDLE_TIMEOUT, "Idle-Timeout", RADIUS_ATTR_INT32 }, + { RADIUS_ATTR_USER_NAME, "User-Name", RADIUS_ATTR_TEXT, 0}, + { RADIUS_ATTR_USER_PASSWORD, "User-Password", RADIUS_ATTR_UNDIST, 0}, + { RADIUS_ATTR_NAS_IP_ADDRESS, "NAS-IP-Address", RADIUS_ATTR_IP, 0}, + { RADIUS_ATTR_NAS_PORT, "NAS-Port", RADIUS_ATTR_INT32, 0}, + { RADIUS_ATTR_SERVICE_TYPE, "Service-Type", RADIUS_ATTR_INT32, 0}, + { RADIUS_ATTR_FRAMED_IP_ADDRESS, "Framed-IP-Address", RADIUS_ATTR_IP, 0}, + { RADIUS_ATTR_FRAMED_MTU, "Framed-MTU", RADIUS_ATTR_INT32, 0}, + { RADIUS_ATTR_REPLY_MESSAGE, "Reply-Message", RADIUS_ATTR_TEXT, 0}, + { RADIUS_ATTR_STATE, "State", RADIUS_ATTR_UNDIST, 0}, + { RADIUS_ATTR_CLASS, "Class", RADIUS_ATTR_UNDIST, 0}, + { RADIUS_ATTR_VENDOR_SPECIFIC, "Vendor-Specific", RADIUS_ATTR_UNDIST, 0}, + { RADIUS_ATTR_SESSION_TIMEOUT, "Session-Timeout", RADIUS_ATTR_INT32, 0}, + { RADIUS_ATTR_IDLE_TIMEOUT, "Idle-Timeout", RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_TERMINATION_ACTION, "Termination-Action", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_CALLED_STATION_ID, "Called-Station-Id", - RADIUS_ATTR_TEXT }, + RADIUS_ATTR_TEXT, 0}, { RADIUS_ATTR_CALLING_STATION_ID, "Calling-Station-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_NAS_IDENTIFIER, "NAS-Identifier", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_PROXY_STATE, "Proxy-State", RADIUS_ATTR_UNDIST }, + RADIUS_ATTR_TEXT, 0}, + { RADIUS_ATTR_NAS_IDENTIFIER, "NAS-Identifier", RADIUS_ATTR_TEXT, 0}, + { RADIUS_ATTR_PROXY_STATE, "Proxy-State", RADIUS_ATTR_UNDIST, 0}, { RADIUS_ATTR_ACCT_STATUS_TYPE, "Acct-Status-Type", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_DELAY_TIME, "Acct-Delay-Time", RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, + { RADIUS_ATTR_ACCT_DELAY_TIME, "Acct-Delay-Time", RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_ACCT_INPUT_OCTETS, "Acct-Input-Octets", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_ACCT_OUTPUT_OCTETS, "Acct-Output-Octets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_SESSION_ID, "Acct-Session-Id", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_ACCT_AUTHENTIC, "Acct-Authentic", RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, + { RADIUS_ATTR_ACCT_SESSION_ID, "Acct-Session-Id", RADIUS_ATTR_TEXT, 0}, + { RADIUS_ATTR_ACCT_AUTHENTIC, "Acct-Authentic", RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_ACCT_SESSION_TIME, "Acct-Session-Time", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_ACCT_INPUT_PACKETS, "Acct-Input-Packets", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_ACCT_OUTPUT_PACKETS, "Acct-Output-Packets", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_ACCT_TERMINATE_CAUSE, "Acct-Terminate-Cause", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_ACCT_MULTI_SESSION_ID, "Acct-Multi-Session-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_ACCT_LINK_COUNT, "Acct-Link-Count", RADIUS_ATTR_INT32 }, + RADIUS_ATTR_TEXT, 0}, + { RADIUS_ATTR_ACCT_LINK_COUNT, "Acct-Link-Count", RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_ACCT_INPUT_GIGAWORDS, "Acct-Input-Gigawords", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS, "Acct-Output-Gigawords", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_EVENT_TIMESTAMP, "Event-Timestamp", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_EGRESS_VLANID, "EGRESS-VLANID", RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_NAS_PORT_TYPE, "NAS-Port-Type", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_TUNNEL_TYPE, "Tunnel-Type", RADIUS_ATTR_HEXDUMP }, + RADIUS_ATTR_INT32, 0}, + { RADIUS_ATTR_EGRESS_VLANID, "EGRESS-VLANID", RADIUS_ATTR_HEXDUMP, 0}, + { RADIUS_ATTR_NAS_PORT_TYPE, "NAS-Port-Type", RADIUS_ATTR_INT32, 0}, + { RADIUS_ATTR_TUNNEL_TYPE, "Tunnel-Type", RADIUS_ATTR_HEXDUMP, + RADIUS_ATTR_F_TAGGED}, { RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, "Tunnel-Medium-Type", - RADIUS_ATTR_HEXDUMP }, + RADIUS_ATTR_HEXDUMP, RADIUS_ATTR_F_TAGGED}, { RADIUS_ATTR_TUNNEL_PASSWORD, "Tunnel-Password", - RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_CONNECT_INFO, "Connect-Info", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_EAP_MESSAGE, "EAP-Message", RADIUS_ATTR_UNDIST }, + RADIUS_ATTR_UNDIST, RADIUS_ATTR_F_TAGGED}, + { RADIUS_ATTR_CONNECT_INFO, "Connect-Info", RADIUS_ATTR_TEXT, 0}, + { RADIUS_ATTR_EAP_MESSAGE, "EAP-Message", RADIUS_ATTR_UNDIST, 0}, { RADIUS_ATTR_MESSAGE_AUTHENTICATOR, "Message-Authenticator", - RADIUS_ATTR_UNDIST }, + RADIUS_ATTR_UNDIST, 0}, { RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID, "Tunnel-Private-Group-Id", - RADIUS_ATTR_HEXDUMP }, + RADIUS_ATTR_HEXDUMP, RADIUS_ATTR_F_TAGGED_LIM }, { RADIUS_ATTR_ACCT_INTERIM_INTERVAL, "Acct-Interim-Interval", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, "Chargeable-User-Identity", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_NAS_IPV6_ADDRESS, "NAS-IPv6-Address", RADIUS_ATTR_IPV6 }, - { RADIUS_ATTR_ERROR_CAUSE, "Error-Cause", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_EAP_KEY_NAME, "EAP-Key-Name", RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_OPERATOR_NAME, "Operator-Name", RADIUS_ATTR_TEXT }, + RADIUS_ATTR_TEXT, 0}, + { RADIUS_ATTR_TUNNEL_CLIENT_AUTH_ID, "Tunnel-Client-Auth-ID", + RADIUS_ATTR_TEXT, RADIUS_ATTR_F_TAGGED}, + { RADIUS_ATTR_NAS_IPV6_ADDRESS, "NAS-IPv6-Address", RADIUS_ATTR_IPV6, 0}, + { RADIUS_ATTR_ERROR_CAUSE, "Error-Cause", RADIUS_ATTR_INT32, 0}, + { RADIUS_ATTR_EAP_KEY_NAME, "EAP-Key-Name", RADIUS_ATTR_HEXDUMP, 0}, + { RADIUS_ATTR_OPERATOR_NAME, "Operator-Name", RADIUS_ATTR_TEXT, 0}, { RADIUS_ATTR_LOCATION_INFO, "Location-Information", - RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_LOCATION_DATA, "Location-Data", RADIUS_ATTR_HEXDUMP }, + RADIUS_ATTR_HEXDUMP, 0}, + { RADIUS_ATTR_LOCATION_DATA, "Location-Data", RADIUS_ATTR_HEXDUMP, 0}, { RADIUS_ATTR_BASIC_LOCATION_POLICY_RULES, - "Basic-Location-Policy-Rules", RADIUS_ATTR_HEXDUMP }, + "Basic-Location-Policy-Rules", RADIUS_ATTR_HEXDUMP, 0}, { RADIUS_ATTR_EXTENDED_LOCATION_POLICY_RULES, - "Extended-Location-Policy-Rules", RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_LOCATION_CAPABLE, "Location-Capable", RADIUS_ATTR_INT32 }, + "Extended-Location-Policy-Rules", RADIUS_ATTR_HEXDUMP, 0}, + { RADIUS_ATTR_LOCATION_CAPABLE, "Location-Capable", RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_REQUESTED_LOCATION_INFO, "Requested-Location-Info", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_MOBILITY_DOMAIN_ID, "Mobility-Domain-Id", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_WLAN_HESSID, "WLAN-HESSID", RADIUS_ATTR_TEXT }, + RADIUS_ATTR_INT32, 0}, + { RADIUS_ATTR_WLAN_HESSID, "WLAN-HESSID", RADIUS_ATTR_TEXT, 0}, { RADIUS_ATTR_WLAN_REASON_CODE, "WLAN-Reason-Code", - RADIUS_ATTR_INT32 }, + RADIUS_ATTR_INT32, 0}, { RADIUS_ATTR_WLAN_PAIRWISE_CIPHER, "WLAN-Pairwise-Cipher", - RADIUS_ATTR_HEXDUMP }, + RADIUS_ATTR_HEXDUMP, 0}, { RADIUS_ATTR_WLAN_GROUP_CIPHER, "WLAN-Group-Cipher", - RADIUS_ATTR_HEXDUMP }, + RADIUS_ATTR_HEXDUMP, 0}, { RADIUS_ATTR_WLAN_AKM_SUITE, "WLAN-AKM-Suite", - RADIUS_ATTR_HEXDUMP }, + RADIUS_ATTR_HEXDUMP, 0}, { RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER, "WLAN-Group-Mgmt-Pairwise-Cipher", - RADIUS_ATTR_HEXDUMP }, + RADIUS_ATTR_HEXDUMP, 0}, }; #define RADIUS_ATTRS ARRAY_SIZE(radius_attrs) @@ -295,6 +302,18 @@ static void radius_msg_dump_attr(struct radius_attr_hdr *hdr) len = hdr->length - sizeof(struct radius_attr_hdr); pos = (unsigned char *) (hdr + 1); + if (len > 0 && (attr->flags & RADIUS_ATTR_F_TAGGED)) { + wpa_printf(MSG_INFO, " Tag: %u", pos[0]); + pos++; + len--; + } + if (len > 0 && (attr->flags & RADIUS_ATTR_F_TAGGED_LIM) && + pos[0] <= 0x1F) { + wpa_printf(MSG_INFO, " Tag: %u", pos[0]); + pos++; + len--; + } + switch (attr->data_type) { case RADIUS_ATTR_TEXT: printf_encode(buf, sizeof(buf), pos, len); @@ -1379,6 +1398,39 @@ int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len) } +int radius_msg_get_attr_tag_ptr(struct radius_msg *msg, u8 type, u8 tag, + u8 **buf, size_t *len, size_t idx, + size_t *next_idx) +{ + size_t i; + struct radius_attr_hdr *attr; + + for (i = idx; i < msg->attr_used; i++) { + attr = radius_get_attr_hdr(msg, i); + if (attr->type != type || + attr->length <= sizeof(*attr)) + continue; + + *buf = (u8 *) (attr + 1); + *len = attr->length - sizeof(*attr) - 1; + + if (*buf[0] != tag) + continue; + + (*buf)++; // skip tag from output + if (next_idx) + *next_idx = i + 1; + + return 0; + } + + *buf = NULL; + *len = 0; + + return -1; +} + + int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf, size_t *len, const u8 *start) { @@ -1554,7 +1606,8 @@ int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged, */ char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, const u8 *secret, size_t secret_len, - struct radius_msg *sent_msg, size_t n) + struct radius_msg *sent_msg, size_t idx, + u8 *out_tag, size_t *next_idx) { u8 *buf = NULL; size_t buflen; @@ -1564,7 +1617,7 @@ char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, size_t len[3]; u8 hash[16]; u8 *pos; - size_t i, j = 0; + size_t i; struct radius_attr_hdr *attr; const u8 *data; size_t dlen; @@ -1573,7 +1626,7 @@ char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, char *ret = NULL; /* find n-th valid Tunnel-Password attribute */ - for (i = 0; i < msg->attr_used; i++) { + for (i = idx; i < msg->attr_used; i++) { attr = radius_get_attr_hdr(msg, i); if (attr == NULL || attr->type != RADIUS_ATTR_TUNNEL_PASSWORD) { @@ -1585,9 +1638,8 @@ char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, dlen = attr->length - sizeof(*attr); if (dlen <= 3 || dlen % 16 != 3) continue; - j++; - if (j <= n) - continue; + if (next_idx) + *next_idx = i + 1; fdata = data; fdlen = dlen; @@ -1603,6 +1655,8 @@ char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, buflen = fdlen; /* init pointers */ + if (out_tag) + *out_tag = *buf; salt = buf + 1; str = buf + 3; diff --git a/src/radius/radius.h b/src/radius/radius.h index fb8148180..f2b5e8540 100644 --- a/src/radius/radius.h +++ b/src/radius/radius.h @@ -92,6 +92,7 @@ enum { RADIUS_ATTR_USER_NAME = 1, RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID = 81, RADIUS_ATTR_ACCT_INTERIM_INTERVAL = 85, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY = 89, + RADIUS_ATTR_TUNNEL_CLIENT_AUTH_ID = 90, RADIUS_ATTR_NAS_IPV6_ADDRESS = 95, RADIUS_ATTR_ERROR_CAUSE = 101, RADIUS_ATTR_EAP_KEY_NAME = 102, @@ -297,7 +298,8 @@ int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged, int *tagged); char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, const u8 *secret, size_t secret_len, - struct radius_msg *sent_msg, size_t n); + struct radius_msg *sent_msg, size_t idx, + u8 *out_tag, size_t *next_idx); static inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type, u32 value) @@ -321,6 +323,9 @@ static inline int radius_msg_get_attr_int32(struct radius_msg *msg, u8 type, int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf, size_t *len, const u8 *start); int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len); +int radius_msg_get_attr_tag_ptr(struct radius_msg *msg, u8 type, u8 tag, + u8 **buf, size_t *len, size_t idx, + size_t *next_idx); struct radius_attr_data { From patchwork Fri Apr 16 06:13:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: michael-dev X-Patchwork-Id: 1466854 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2001:8b0:10b:1:d65d:64ff:fe57:4e05; helo=desiato.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=desiato.20200630 header.b=SrDq/Id5; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=infradead.org header.i=@infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=f9cVHKMM; dkim-atps=neutral Received: from desiato.infradead.org (desiato.infradead.org [IPv6:2001:8b0:10b:1:d65d:64ff:fe57:4e05]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FM5bB6GLmz9sRK for ; Fri, 16 Apr 2021 16:17:10 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=5+8litZDrHsVBQMcPiPzxzNBKvpb0WpSAqdtIt8m718=; b=SrDq/Id52pOzbKCvqmEyam3Uj qykTqOhwGmnrGVzLPSFErkr1lwGoFOMlo3rUICIWmlWZc4E26kyeQ3Tpzff3SlNMU6Aq1uPfuQkbU F5EixqNU8nTZ7Vqnn4T1LuzEWSoaktLLXRMcyf+XNUFVyZw61xslkKyg5wlQ6K/BrgGMenViRbZev bh+t7XLJlM/IMku+/uFJKEJOgwaCe8BXAoM6wtHjzG07Ww1LEzqRpIzBpEQwuS859llhHG3NwBI5w L6crNhrw3nVn3VL9Byb/qtvHQNMEEH75wnLVMtvE85Y52ktfD9YAfmX1aciwjrbgCi5tfqThdo9zw q7f9rQKHg==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lXHm2-000zei-PG; Fri, 16 Apr 2021 06:16:15 +0000 Received: from bombadil.infradead.org ([2607:7c80:54:e::133]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lXHjX-000z9u-Ae for hostap@desiato.infradead.org; Fri, 16 Apr 2021 06:13:43 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender :Reply-To:Content-Type:Content-ID:Content-Description; bh=rhAjSBztXGUCBHL7JBbuamAjaqwjjzDRktUqop6+7RU=; b=f9cVHKMMQeCbD0Zt14kGyCUhQG SnZfbvCrK4Ds9voKH3PAaSDOOnf1OfObAHznxqjavEzlRPTfrfJ/68Ke4wOJjk7ybQVLTA1l2t1ER bxorBcIhY9neS2h5tCU1Z1GrPr2jzaHt3iMjL00nOBxXFlYrpNvIKlnpMBr7A5dVF0UQDnYygGMr3 3Gde7cv3aBxuXYbOWce5i/Y8kIl2JpXiAcs+Ae5702gVLYK+pr/XrSeEHvjdRY9gn5uz5rrec8JMr wEcGwbZpHTRwIj9DVNnjmdTykAejLYUTjMOsfY1x3NVxIIrWJIp0x7UX61Xf7LM0I0aECtDDix7PY vvqZozag==; Received: from smail2.fem.tu-ilmenau.de ([141.24.40.15]) by bombadil.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lXHjU-0096nH-9i for hostap@lists.infradead.org; Fri, 16 Apr 2021 06:13:38 +0000 Received: from a234.fem.tu-ilmenau.de (ray-controller.net.fem.tu-ilmenau.de [10.42.51.234]) by smail2.fem.tu-ilmenau.de (Postfix) with ESMTP id D4561DEC9E; Fri, 16 Apr 2021 08:13:34 +0200 (CEST) Received: by a234.fem.tu-ilmenau.de (Postfix, from userid 1000) id B717230DAC3E; Fri, 16 Apr 2021 08:13:34 +0200 (CEST) From: michael-dev@fami-braun.de To: hostap@lists.infradead.org Cc: projekt-wlan@fem.tu-ilmenau.de, michael-dev@fami-braun.de Subject: [PATCH 2/2] test: SAE password with Tunnel-Password Date: Fri, 16 Apr 2021 08:13:32 +0200 Message-Id: <20210416061332.16388-3-michael-dev@fami-braun.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210416061332.16388-1-michael-dev@fami-braun.de> References: <20210416061332.16388-1-michael-dev@fami-braun.de> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210415_231336_671185_17AB8344 X-CRM114-Status: UNSURE ( 9.79 ) X-CRM114-Notice: Please train this message. X-Spam-Score: 0.0 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Michael Braun Signed-off-by: Michael Braun --- tests/hwsim/dictionary.radius | 1 + tests/hwsim/test_radius.py | 119 +++++++++++++++++++++++++++++++++- 2 files changed, 119 insertions(+), [...] Content analysis details: (0.0 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Michael Braun Signed-off-by: Michael Braun --- tests/hwsim/dictionary.radius | 1 + tests/hwsim/test_radius.py | 119 +++++++++++++++++++++++++++++++++- 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/dictionary.radius b/tests/hwsim/dictionary.radius index d2112dad3..923c1220e 100644 --- a/tests/hwsim/dictionary.radius +++ b/tests/hwsim/dictionary.radius @@ -17,4 +17,5 @@ ATTRIBUTE Message-Authenticator 80 octets ATTRIBUTE Tunnel-Private-Group-ID 81 string ATTRIBUTE Acct-Interim-Interval 85 integer ATTRIBUTE Chargeable-User-Identity 89 string +ATTRIBUTE Tunnel-Client-Auth-ID 90 octets ATTRIBUTE Error-Cause 101 integer diff --git a/tests/hwsim/test_radius.py b/tests/hwsim/test_radius.py index ca96c979e..ec359bd0e 100644 --- a/tests/hwsim/test_radius.py +++ b/tests/hwsim/test_radius.py @@ -1167,8 +1167,12 @@ def build_tunnel_password(secret, authenticator, psk): data = b'\x00' + a + bytes(cc_all) return data +def build_tunnel_identity(id): + return b'\x00' + id.encode() + def start_radius_psk_server(psk, invalid_code=False, acct_interim_interval=0, - session_timeout=0, reject=False): + session_timeout=0, reject=False, sae_identity=None, + sae_identity2=None): try: import pyrad.server import pyrad.packet @@ -1195,6 +1199,13 @@ def start_radius_psk_server(psk, invalid_code=False, acct_interim_interval=0, if self.t_events['session_timeout']: reply.AddAttribute("Session-Timeout", self.t_events['session_timeout']) + if self.t_events['sae_identity']: + data = build_tunnel_identity(self.t_events['sae_identity']) + reply.AddAttribute("Tunnel-Client-Auth-ID", data) + if self.t_events['sae_identity2']: + data = build_tunnel_identity(self.t_events['sae_identity2']) + reply.AddAttribute("Tunnel-Client-Auth-ID", data) + self.SendReplyPacket(pkt.fd, reply) def RunWithStop(self, t_events): @@ -1231,6 +1242,8 @@ def start_radius_psk_server(psk, invalid_code=False, acct_interim_interval=0, t_events['invalid_code'] = invalid_code t_events['acct_interim_interval'] = acct_interim_interval t_events['session_timeout'] = session_timeout + t_events['sae_identity'] = sae_identity + t_events['sae_identity2'] = sae_identity2 t_events['reject'] = reject t = threading.Thread(target=run_pyrad_server, args=(srv, t_events)) t.start() @@ -1247,6 +1260,28 @@ def hostapd_radius_psk_test_params(): params['auth_server_port'] = "18138" return params +def hostapd_radius_sae_test_params(): + params = hostapd.radius_params() + params['ssid'] = "test-wpa3-sae" + params["wpa"] = "2" + params["wpa_key_mgmt"] = "SAE" + params["rsn_pairwise"] = "CCMP" + params['macaddr_acl'] = '2' + params['wpa_psk_radius'] = '2' + params['auth_server_port'] = "18138" + return params + +def hostapd_radius_sae_ft_test_params(): + params = hostapd.radius_params() + params['ssid'] = "test-wpa3-sae-ft" + params["wpa"] = "2" + params["wpa_key_mgmt"] = "FT-SAE" + params["rsn_pairwise"] = "CCMP" + params['macaddr_acl'] = '2' + params['wpa_psk_radius'] = '2' + params['auth_server_port'] = "18138" + return params + def test_radius_psk(dev, apdev): """WPA2 with PSK from RADIUS""" t, t_events = start_radius_psk_server("12345678") @@ -1708,3 +1743,85 @@ def test_radius_acct_failure_sta_data(dev, apdev): dev[0].request("DISCONNECT") dev[0].wait_disconnected() hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=1) + +def test_radius_sae(dev, apdev): + """WPA3 with SAE from RADIUS""" + t, t_events = start_radius_psk_server("12345678") + + try: + params = hostapd_radius_sae_test_params() + hapd = hostapd.add_ap(apdev[0], params) + dev[0].connect("test-wpa3-sae", sae_password="12345678", key_mgmt="SAE", + scan_freq="2412") + t_events['psk'] = "0123456789abcdef" + dev[1].connect("test-wpa3-sae", sae_password="0123456789abcdef", key_mgmt="SAE", + scan_freq="2412") + finally: + t_events['stop'].set() + t.join() + +def test_radius_sae_ft(dev, apdev): + """WPA3 with FT-SAE from RADIUS""" + t, t_events = start_radius_psk_server("12345678") + + try: + params = hostapd_radius_sae_ft_test_params() + hapd = hostapd.add_ap(apdev[0], params) + dev[0].connect("test-wpa3-sae-ft", sae_password="12345678", key_mgmt="FT-SAE", + scan_freq="2412") + t_events['psk'] = "0123456789abcdef" + dev[1].connect("test-wpa3-sae-ft", sae_password="0123456789abcdef", key_mgmt="FT-SAE", + scan_freq="2412") + finally: + t_events['stop'].set() + t.join() + +def test_radius_sae_id(dev, apdev): + """WPA3 with SAE from RADIUS with SAE password identity""" + t, t_events = start_radius_psk_server("12345678", sae_identity="user0") + + try: + params = hostapd_radius_sae_test_params() + hapd = hostapd.add_ap(apdev[0], params) + dev[0].connect("test-wpa3-sae", sae_password="12345678", key_mgmt="SAE", + scan_freq="2412", sae_password_id="user0") + t_events['psk'] = "0123456789abcdef" + t_events['sae_identity'] = "user1" + dev[1].connect("test-wpa3-sae", sae_password="0123456789abcdef", key_mgmt="SAE", + scan_freq="2412", sae_password_id="user1") + finally: + t_events['stop'].set() + t.join() + +def test_radius_sae_id_ft(dev, apdev): + """WPA3 with FT-SAE from RADIUS with SAE password identity""" + t, t_events = start_radius_psk_server("12345678", sae_identity="user0") + + try: + params = hostapd_radius_sae_ft_test_params() + hapd = hostapd.add_ap(apdev[0], params) + dev[0].connect("test-wpa3-sae-ft", sae_password="12345678", key_mgmt="FT-SAE", + scan_freq="2412", sae_password_id="user0") + t_events['psk'] = "0123456789abcdef" + t_events['sae_identity'] = "user1" + dev[1].connect("test-wpa3-sae-ft", sae_password="0123456789abcdef", key_mgmt="FT-SAE", + scan_freq="2412", sae_password_id="user1") + finally: + t_events['stop'].set() + t.join() + +def test_radius_sae_multi_id(dev, apdev): + """WPA3 with SAE from RADIUS with multiple SAE password identity""" + t, t_events = start_radius_psk_server("12345678", sae_identity="user0", sae_identity2="user1") + + try: + params = hostapd_radius_sae_test_params() + hapd = hostapd.add_ap(apdev[0], params) + dev[0].connect("test-wpa3-sae", sae_password="12345678", key_mgmt="SAE", + scan_freq="2412", sae_password_id="user0") + dev[1].connect("test-wpa3-sae", sae_password="12345678", key_mgmt="SAE", + scan_freq="2412", sae_password_id="user1") + finally: + t_events['stop'].set() + t.join() +