From 6c460eaf7e33b52ac7976ddf87133bdbfe050d41 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 31 Jul 2014 19:53:25 +0300 Subject: [PATCH] Add RSN cipher/AKM suite attributes into RADIUS messages This adds hostapd support for the new WLAN-Pairwise-Cipher, WLAN-Group-Cipher, WLAN-AKM-Suite, and WLAN-Group-Mgmt-Pairwise-Cipher attributes defined in RFC 7268. These attributes are added to RADIUS messages when the station negotiates use of WPA/RSN. Signed-off-by: Jouni Malinen --- src/ap/ieee802_1x.c | 65 +++++++++++++++++++++++++++++++++++++++++ src/common/wpa_common.c | 24 +++++++++++++++ src/common/wpa_common.h | 1 + src/radius/radius.c | 8 +++++ src/radius/radius.h | 4 +++ 5 files changed, 102 insertions(+) diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index c5285aadb..e4681e90d 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -306,6 +306,67 @@ static void ieee802_1x_learn_identity(struct hostapd_data *hapd, } +static int add_common_radius_sta_attr_rsn(struct hostapd_data *hapd, + struct hostapd_radius_attr *req_attr, + struct sta_info *sta, + struct radius_msg *msg) +{ + u32 suite; + int ver, val; + + ver = wpa_auth_sta_wpa_version(sta->wpa_sm); + val = wpa_auth_get_pairwise(sta->wpa_sm); + suite = wpa_cipher_to_suite(ver, val); + if (val != -1 && + !hostapd_config_get_radius_attr(req_attr, + RADIUS_ATTR_WLAN_PAIRWISE_CIPHER) && + !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_PAIRWISE_CIPHER, + suite)) { + wpa_printf(MSG_ERROR, "Could not add WLAN-Pairwise-Cipher"); + return -1; + } + + suite = wpa_cipher_to_suite((hapd->conf->wpa & 0x2) ? + WPA_PROTO_RSN : WPA_PROTO_WPA, + hapd->conf->wpa_group); + if (!hostapd_config_get_radius_attr(req_attr, + RADIUS_ATTR_WLAN_GROUP_CIPHER) && + !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_GROUP_CIPHER, + suite)) { + wpa_printf(MSG_ERROR, "Could not add WLAN-Group-Cipher"); + return -1; + } + + val = wpa_auth_sta_key_mgmt(sta->wpa_sm); + suite = wpa_akm_to_suite(val); + if (val != -1 && + !hostapd_config_get_radius_attr(req_attr, + RADIUS_ATTR_WLAN_AKM_SUITE) && + !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_AKM_SUITE, + suite)) { + wpa_printf(MSG_ERROR, "Could not add WLAN-AKM-Suite"); + return -1; + } + +#ifdef CONFIG_IEEE80211W + if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { + suite = wpa_cipher_to_suite(WPA_PROTO_RSN, + hapd->conf->group_mgmt_cipher); + if (!hostapd_config_get_radius_attr( + req_attr, RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER) && + !radius_msg_add_attr_int32( + msg, RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER, suite)) { + wpa_printf(MSG_ERROR, + "Could not add WLAN-Group-Mgmt-Cipher"); + return -1; + } + } +#endif /* CONFIG_IEEE80211W */ + + return 0; +} + + static int add_common_radius_sta_attr(struct hostapd_data *hapd, struct hostapd_radius_attr *req_attr, struct sta_info *sta, @@ -372,6 +433,10 @@ static int add_common_radius_sta_attr(struct hostapd_data *hapd, } #endif /* CONFIG_IEEE80211R */ + if (hapd->conf->wpa && sta->wpa_sm && + add_common_radius_sta_attr_rsn(hapd, req_attr, sta, msg) < 0) + return -1; + return 0; } diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index adb22c76e..7aeb706c2 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -1002,6 +1002,30 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto) } +u32 wpa_akm_to_suite(int akm) +{ + if (akm & WPA_KEY_MGMT_FT_IEEE8021X) + return WLAN_AKM_SUITE_FT_8021X; + if (akm & WPA_KEY_MGMT_FT_PSK) + return WLAN_AKM_SUITE_FT_PSK; + if (akm & WPA_KEY_MGMT_IEEE8021X) + return WLAN_AKM_SUITE_8021X; + if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256) + return WLAN_AKM_SUITE_8021X_SHA256; + if (akm & WPA_KEY_MGMT_IEEE8021X) + return WLAN_AKM_SUITE_8021X; + if (akm & WPA_KEY_MGMT_PSK_SHA256) + return WLAN_AKM_SUITE_PSK_SHA256; + if (akm & WPA_KEY_MGMT_PSK) + return WLAN_AKM_SUITE_PSK; + if (akm & WPA_KEY_MGMT_CCKM) + return WLAN_AKM_SUITE_CCKM; + if (akm & WPA_KEY_MGMT_OSEN) + return WLAN_AKM_SUITE_OSEN; + return 0; +} + + int wpa_compare_rsn_ie(int ft_initial_assoc, const u8 *ie1, size_t ie1len, const u8 *ie2, size_t ie2len) diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index c0b2caaed..0ef5a9d1a 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -377,6 +377,7 @@ void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, const char * wpa_cipher_txt(int cipher); const char * wpa_key_mgmt_txt(int key_mgmt, int proto); +u32 wpa_akm_to_suite(int akm); int wpa_compare_rsn_ie(int ft_initial_assoc, const u8 *ie1, size_t ie1len, const u8 *ie2, size_t ie2len); diff --git a/src/radius/radius.c b/src/radius/radius.c index 8bcf2f55c..f3b645dca 100644 --- a/src/radius/radius.c +++ b/src/radius/radius.c @@ -236,6 +236,14 @@ static struct radius_attr_type radius_attrs[] = { RADIUS_ATTR_MOBILITY_DOMAIN_ID, "Mobility-Domain-Id", RADIUS_ATTR_INT32 }, { RADIUS_ATTR_WLAN_HESSID, "WLAN-HESSID", RADIUS_ATTR_TEXT }, + { RADIUS_ATTR_WLAN_PAIRWISE_CIPHER, "WLAN-Pairwise-Cipher", + RADIUS_ATTR_HEXDUMP }, + { RADIUS_ATTR_WLAN_GROUP_CIPHER, "WLAN-Group-Cipher", + RADIUS_ATTR_HEXDUMP }, + { RADIUS_ATTR_WLAN_AKM_SUITE, "WLAN-AKM-Suite", + RADIUS_ATTR_HEXDUMP }, + { RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER, "WLAN-Group-Mgmt-Pairwise-Cipher", + RADIUS_ATTR_HEXDUMP }, }; #define RADIUS_ATTRS ARRAY_SIZE(radius_attrs) diff --git a/src/radius/radius.h b/src/radius/radius.h index 4ff73914e..62faae10c 100644 --- a/src/radius/radius.h +++ b/src/radius/radius.h @@ -94,6 +94,10 @@ enum { RADIUS_ATTR_USER_NAME = 1, RADIUS_ATTR_EAP_KEY_NAME = 102, RADIUS_ATTR_MOBILITY_DOMAIN_ID = 177, RADIUS_ATTR_WLAN_HESSID = 181, + RADIUS_ATTR_WLAN_PAIRWISE_CIPHER = 186, + RADIUS_ATTR_WLAN_GROUP_CIPHER = 187, + RADIUS_ATTR_WLAN_AKM_SUITE = 188, + RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER = 189, };