From e874ccc9177c32ef8e19e094a2ddcec32b3b71e1 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Tue, 15 Dec 2020 19:05:11 +0100 Subject: [PATCH] wifi: add WPA-EAP-SUITE-B-192 support Add a new key management option to support WPA3 Enteprise wifi connection. Only supported with wpa_supplicant for the time being. Signed-off-by: Antonio Cardace --- Makefile.am | 1 + clients/cli/devices.c | 2 + .../generate-docs-nm-settings-nmcli.xml.in | 2 +- clients/common/nm-meta-setting-desc.c | 2 +- clients/common/nm-secret-agent-simple.c | 2 +- clients/common/settings-docs.h.in | 2 +- clients/tui/nm-editor-bindings.c | 3 + libnm-core/nm-dbus-interface.h | 31 ++++--- libnm-core/nm-setting-wireless-security.c | 46 +++++----- libnm-core/nm-utils.c | 11 +++ libnm-core/nm-utils.h | 2 + libnm/nm-device-wifi.c | 3 +- src/devices/wifi/nm-wifi-ap.c | 6 +- src/devices/wifi/nm-wifi-utils.c | 13 ++- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 12 +-- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 3 + .../ifcfg-test-wifi-wpa-eap-suite-b-192-tls | 22 +++++ .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 30 +++++++ src/supplicant/nm-supplicant-config.c | 31 +++++-- src/supplicant/nm-supplicant-interface.c | 2 + src/supplicant/nm-supplicant-manager.c | 5 ++ .../nm-supplicant-settings-verify.c | 5 +- src/supplicant/nm-supplicant-types.h | 1 + src/supplicant/tests/test-supplicant-config.c | 86 +++++++++++++++++++ 24 files changed, 267 insertions(+), 56 deletions(-) create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls diff --git a/Makefile.am b/Makefile.am index b5d5e8cb41..2097e39f4a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3264,6 +3264,7 @@ EXTRA_DIST += \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-passphrase \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-tls \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-2 \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc \ diff --git a/clients/cli/devices.c b/clients/cli/devices.c index 62f4fed1ad..97f72cc445 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -53,6 +53,8 @@ ap_wpa_rsn_flags_to_string(NM80211ApSecurityFlags flags, NMMetaAccessorGetType g flags_str[i++] = "802.1X"; if (flags & NM_802_11_AP_SEC_KEY_MGMT_SAE) flags_str[i++] = "sae"; + if (flags & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192) + flags_str[i++] = "wpa-eap-suite-b-192"; if (NM_FLAGS_ANY(flags, NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) flags_str[i++] = "owe"; diff --git a/clients/cli/generate-docs-nm-settings-nmcli.xml.in b/clients/cli/generate-docs-nm-settings-nmcli.xml.in index 1d1a09ba4a..a4e6715cc8 100644 --- a/clients/cli/generate-docs-nm-settings-nmcli.xml.in +++ b/clients/cli/generate-docs-nm-settings-nmcli.xml.in @@ -63,7 +63,7 @@ + description="Key management used for the connection. One of "none" (WEP), "ieee8021x" (Dynamic WEP), "wpa-psk" (infrastructure WPA-PSK), "sae" (SAE), "owe" (Opportunistic Wireless Encryption), "wpa-eap" (WPA-Enterprise) or "wpa-eap-suite-b-192" (WPA3-Enterprise Suite B). This property must be set for any Wi-Fi connection that uses security." /> */ * supported * @NM_802_11_AP_SEC_KEY_MGMT_OWE_TM: WPA/RSN Opportunistic Wireless Encryption * transition mode is supported. Since: 1.26. + * @NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192: WPA3 Enterprise Suite-B 192 bit mode + * is supported. Since: 1.30. * * 802.11 access point security and authentication flags. These flags describe * the current security requirements of an access point as determined from the * access point's beacon. **/ typedef enum { /*< underscore_name=nm_802_11_ap_security_flags, flags >*/ - NM_802_11_AP_SEC_NONE = 0x00000000, - NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001, - NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002, - NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004, - NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008, - NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010, - NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020, - NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040, - NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080, - NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100, - NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200, - NM_802_11_AP_SEC_KEY_MGMT_SAE = 0x00000400, - NM_802_11_AP_SEC_KEY_MGMT_OWE = 0x00000800, - NM_802_11_AP_SEC_KEY_MGMT_OWE_TM = 0x00001000, + NM_802_11_AP_SEC_NONE = 0x00000000, + NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001, + NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002, + NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004, + NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008, + NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010, + NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020, + NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040, + NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080, + NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100, + NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200, + NM_802_11_AP_SEC_KEY_MGMT_SAE = 0x00000400, + NM_802_11_AP_SEC_KEY_MGMT_OWE = 0x00000800, + NM_802_11_AP_SEC_KEY_MGMT_OWE_TM = 0x00001000, + NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192 = 0x00002000, } NM80211ApSecurityFlags; /** diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c index a1db64a24c..a881c211d9 100644 --- a/libnm-core/nm-setting-wireless-security.c +++ b/libnm-core/nm-setting-wireless-security.c @@ -861,8 +861,7 @@ need_secrets(NMSetting *setting) goto no_secrets; } - if ((strcmp(priv->key_mgmt, "ieee8021x") == 0) || (strcmp(priv->key_mgmt, "wpa-eap") == 0) - || (strcmp(priv->key_mgmt, "owe") == 0)) { + if (NM_IN_STRSET(priv->key_mgmt, "ieee8021x", "wpa-eap", "owe", "wpa-eap-suite-b-192")) { /* Let caller check the 802.1x setting for secrets */ goto no_secrets; } @@ -881,11 +880,12 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) { NMSettingWirelessSecurity * self = NM_SETTING_WIRELESS_SECURITY(setting); NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(self); - const char *valid_key_mgmt[] = {"none", "ieee8021x", "wpa-psk", "wpa-eap", "sae", "owe", NULL}; - const char *valid_auth_algs[] = {"open", "shared", "leap", NULL}; - const char *valid_protos[] = {"wpa", "rsn", NULL}; - const char *valid_pairwise[] = {"tkip", "ccmp", NULL}; - const char *valid_groups[] = {"wep40", "wep104", "tkip", "ccmp", NULL}; + const char * valid_key_mgmt[] = + {"none", "ieee8021x", "wpa-psk", "wpa-eap", "wpa-eap-suite-b-192", "sae", "owe", NULL}; + const char * valid_auth_algs[] = {"open", "shared", "leap", NULL}; + const char * valid_protos[] = {"wpa", "rsn", NULL}; + const char * valid_pairwise[] = {"tkip", "ccmp", NULL}; + const char * valid_groups[] = {"wep40", "wep104", "tkip", "ccmp", NULL}; NMSettingWireless *s_wifi; const char * wifi_mode; @@ -961,8 +961,8 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } } else { - if ((strcmp(priv->key_mgmt, "ieee8021x") == 0) - || (strcmp(priv->key_mgmt, "wpa-eap") == 0)) { + if (nm_streq(priv->key_mgmt, "ieee8021x") || nm_streq(priv->key_mgmt, "wpa-eap") + || nm_streq(priv->key_mgmt, "wpa-eap-suite-b-192")) { /* Need an 802.1x setting too */ if (connection && !nm_connection_get_setting_802_1x(connection)) { g_set_error(error, @@ -1098,13 +1098,19 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) if (NM_IN_SET(priv->pmf, NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL, NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) - && !NM_IN_STRSET(priv->key_mgmt, "wpa-eap", "wpa-psk", "sae", "owe")) { - g_set_error(error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' can only be used with 'wpa-eap', 'wpa-psk' or 'sae' key management "), - priv->pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL ? "optional" - : "required"); + && !NM_IN_STRSET(priv->key_mgmt, + "wpa-eap", + "wpa-eap-suite-b-192", + "wpa-psk", + "sae", + "owe")) { + g_set_error( + error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' can only be used with 'wpa-eap', 'wpa-eap-suite-b-192', 'wpa-psk' or 'sae' key " + "management "), + priv->pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL ? "optional" : "required"); g_prefix_error(error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, @@ -1495,14 +1501,14 @@ nm_setting_wireless_security_class_init(NMSettingWirelessSecurityClass *klass) * * Key management used for the connection. One of "none" (WEP), * "ieee8021x" (Dynamic WEP), "wpa-psk" (infrastructure WPA-PSK), "sae" - * (SAE), "owe" (Opportunistic Wireless Encryption) or "wpa-eap" - * (WPA-Enterprise). This property must be set for - * any Wi-Fi connection that uses security. + * (SAE), "owe" (Opportunistic Wireless Encryption), "wpa-eap" + * (WPA-Enterprise) or "wpa-eap-suite-b-192" (WPA3-Enterprise Suite B). + * This property must be set for any Wi-Fi connection that uses security. **/ /* ---ifcfg-rh--- * property: key-mgmt * variable: KEY_MGMT(+) - * values: IEEE8021X, WPA-PSK, WPA-EAP + * values: IEEE8021X, WPA-PSK, WPA-EAP, WPA-EAP-SUITE-B-192 * description: Key management menthod. * ---end--- */ diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 1b6ebfd5a3..3aafc38ff7 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -1085,6 +1085,7 @@ nm_utils_ap_mode_security_valid(NMUtilsSecurityType type, NMDeviceWifiCapabiliti case NMU_SEC_DYNAMIC_WEP: case NMU_SEC_WPA_ENTERPRISE: case NMU_SEC_WPA2_ENTERPRISE: + case NMU_SEC_WPA3_SUITE_B_192: return FALSE; case NMU_SEC_INVALID: break; @@ -1258,6 +1259,16 @@ nm_utils_security_valid(NMUtilsSecurityType type, if (!NM_FLAGS_ANY(ap_rsn, NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) return FALSE; return TRUE; + case NMU_SEC_WPA3_SUITE_B_192: + if (adhoc) + return FALSE; + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) + return FALSE; + if (!have_ap) + return TRUE; + if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192) + return TRUE; + return FALSE; case NMU_SEC_INVALID: break; } diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h index 9589c51499..b4175b7648 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -54,6 +54,7 @@ char * nm_utils_ssid_to_utf8(const guint8 *ssid, gsize len); * @NMU_SEC_WPA2_ENTERPRISE: WPA2 is used with 802.1x authentication * @NMU_SEC_SAE: is used with WPA3 Enterprise * @NMU_SEC_OWE: is used with Enhanced Open + * @NMU_SEC_WPA3_SUITE_B_192: is used with WPA3 Enterprise Suite-B 192 bit mode. Since: 1.30. * * Describes generic security mechanisms that 802.11 access points may offer. * Used with nm_utils_security_valid() for checking whether a given access @@ -71,6 +72,7 @@ typedef enum { NMU_SEC_WPA2_ENTERPRISE, NMU_SEC_SAE, NMU_SEC_OWE, + NMU_SEC_WPA3_SUITE_B_192, } NMUtilsSecurityType; gboolean nm_utils_security_valid(NMUtilsSecurityType type, diff --git a/libnm/nm-device-wifi.c b/libnm/nm-device-wifi.c index df7d26316d..408d1a56f9 100644 --- a/libnm/nm-device-wifi.c +++ b/libnm/nm-device-wifi.c @@ -496,7 +496,8 @@ connection_compatible(NMDevice *device, NMConnection *connection, GError **error if (s_wsec) { /* Connection has security, verify it against the device's capabilities */ key_mgmt = nm_setting_wireless_security_get_key_mgmt(s_wsec); - if (!g_strcmp0(key_mgmt, "wpa-psk") || !g_strcmp0(key_mgmt, "wpa-eap")) { + if (nm_streq(key_mgmt, "wpa-psk") || nm_streq(key_mgmt, "wpa-eap") + || nm_streq(key_mgmt, "wpa-eap-suite-b-192")) { wifi_caps = nm_device_wifi_get_capabilities(NM_DEVICE_WIFI(device)); /* Is device only WEP capable? */ diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index 4fa44f0126..a6ae8192c6 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -794,8 +794,8 @@ nm_wifi_ap_new_fake_from_connection(NMConnection *connection) if (!strcmp(key_mgmt, "none") || !strcmp(key_mgmt, "ieee8021x")) goto done; - psk = !strcmp(key_mgmt, "wpa-psk"); - eap = !strcmp(key_mgmt, "wpa-eap"); + psk = nm_streq(key_mgmt, "wpa-psk"); + eap = nm_streq(key_mgmt, "wpa-eap") || nm_streq(key_mgmt, "wpa-eap-suite-b-192"); if (!adhoc && (psk || eap)) { if (has_proto(s_wireless_sec, PROTO_WPA)) { flags = priv->wpa_flags @@ -888,7 +888,7 @@ nm_wifi_ap_class_init(NMWifiAPClass *ap_class) | NM_802_11_AP_SEC_GROUP_WEP104 | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_GROUP_CCMP \ | NM_802_11_AP_SEC_KEY_MGMT_PSK | NM_802_11_AP_SEC_KEY_MGMT_802_1X \ | NM_802_11_AP_SEC_KEY_MGMT_SAE | NM_802_11_AP_SEC_KEY_MGMT_OWE \ - | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM) + | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM | NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192) GObjectClass * object_class = G_OBJECT_CLASS(ap_class); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(ap_class); diff --git a/src/devices/wifi/nm-wifi-utils.c b/src/devices/wifi/nm-wifi-utils.c index 3fa33256ad..b487c6f29f 100644 --- a/src/devices/wifi/nm-wifi-utils.c +++ b/src/devices/wifi/nm-wifi-utils.c @@ -407,7 +407,7 @@ verify_wpa_eap(NMSettingWirelessSecurity *s_wsec, auth_alg = nm_setting_wireless_security_get_auth_alg(s_wsec); if (key_mgmt) { - if (!strcmp(key_mgmt, "wpa-eap")) { + if (NM_IN_STRSET(key_mgmt, "wpa-eap", "wpa-eap-suite-b-192")) { if (!s_8021x) { g_set_error_literal(error, NM_CONNECTION_ERROR, @@ -444,7 +444,8 @@ verify_wpa_eap(NMSettingWirelessSecurity *s_wsec, if (is_wpa_eap || s_8021x) { /* Make sure the AP's capabilities support WPA-EAP */ if (!(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) - && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { + && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192)) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, @@ -838,6 +839,14 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, /* Leave proto/pairwise/group as client set them; if they are unset the * supplicant will figure out the best combination at connect time. */ + } else if ((key_mgmt && !strcmp(key_mgmt, "wpa-eap-suite-b-192")) + || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192)) { + g_object_set(s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + "wpa-eap-suite-b-192", + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, + "open", + NULL); } else { g_set_error_literal(error, NM_CONNECTION_ERROR, diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 9b7873c01b..68879df84e 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -4008,9 +4008,10 @@ make_wpa_setting(shvarFile * ifcfg, gs_unref_object NMSettingWirelessSecurity *wsec = NULL; gs_free char * value = NULL; const char * v; - gboolean wpa_psk = FALSE, wpa_sae = FALSE, wpa_owe = FALSE, wpa_eap = FALSE, ieee8021x = FALSE; - int i_val; - GError * local = NULL; + gboolean wpa_psk = FALSE, wpa_sae = FALSE, wpa_owe = FALSE, wpa_eap = FALSE, ieee8021x = FALSE, + wpa3_eap = FALSE; + int i_val; + GError *local = NULL; wsec = NM_SETTING_WIRELESS_SECURITY(nm_setting_wireless_security_new()); @@ -4019,8 +4020,9 @@ make_wpa_setting(shvarFile * ifcfg, wpa_sae = nm_streq0(v, "SAE"); wpa_owe = nm_streq0(v, "OWE"); wpa_eap = nm_streq0(v, "WPA-EAP"); + wpa3_eap = nm_streq0(v, "WPA-EAP-SUITE-B-192"); ieee8021x = nm_streq0(v, "IEEE8021X"); - if (!wpa_psk && !wpa_sae && !wpa_owe && !wpa_eap && !ieee8021x) + if (!wpa_psk && !wpa_sae && !wpa_owe && !wpa_eap && !wpa3_eap && !ieee8021x) return NULL; /* Not WPA or Dynamic WEP */ /* WPS */ @@ -4083,7 +4085,7 @@ make_wpa_setting(shvarFile * ifcfg, g_object_set(wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL); } } else { - nm_assert(wpa_eap || ieee8021x || wpa_owe); + nm_assert(wpa_eap || wpa3_eap || ieee8021x || wpa_owe); /* Adhoc mode is mutually exclusive with any 802.1x-based authentication */ if (adhoc) { diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index ee78780282..443732d59d 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -614,6 +614,9 @@ write_wireless_security_setting(NMConnection *connection, } else if (!strcmp(key_mgmt, "wpa-eap")) { svSetValueStr(ifcfg, "KEY_MGMT", "WPA-EAP"); wpa = TRUE; + } else if (!strcmp(key_mgmt, "wpa-eap-suite-b-192")) { + svSetValueStr(ifcfg, "KEY_MGMT", "WPA-EAP-SUITE-B-192"); + wpa = TRUE; } if (auth_alg) { diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls new file mode 100644 index 0000000000..9a74bb4d9b --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls @@ -0,0 +1,22 @@ +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +BOOTPROTO=dhcp +ONBOOT=yes +ONBOOT=yes +USERCTL=yes +IPV6INIT=no +NM_CONTROLLED=yes +PEERDNS=yes +ESSID=blahblah +MODE=Managed +RATE=auto +KEY_MGMT=WPA-EAP-SUITE-B-192 +WPA_ALLOW_WPA=yes +WPA_ALLOW_WPA2=yes +IEEE_8021X_EAP_METHODS=TLS +IEEE_8021X_IDENTITY="Bill Smith" +IEEE_8021X_CA_CERT=test_ca_cert.pem +IEEE_8021X_CLIENT_CERT=test1_key_and_cert.pem +IEEE_8021X_PRIVATE_KEY=test1_key_and_cert.pem + diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index a4e9d8047e..62809e0c77 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -3684,6 +3684,34 @@ test_read_wifi_wpa_eap_ttls_tls(void) g_object_unref(connection); } +static void +test_read_wifi_wpa_eap_suite_b_192_tls(void) +{ + NMConnection * connection; + NMSettingWireless * s_wireless; + NMSettingWirelessSecurity *s_wireless_sec; + + connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-eap-suite-b-192-tls", + NULL, + TYPE_WIRELESS, + NULL); + + /* ===== WIRELESS SETTING ===== */ + + s_wireless = nm_connection_get_setting_wireless(connection); + g_assert(s_wireless); + + /* ===== WIRELESS SECURITY SETTING ===== */ + + s_wireless_sec = nm_connection_get_setting_wireless_security(connection); + g_assert(s_wireless_sec); + g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wireless_sec), + ==, + "wpa-eap-suite-b-192"); + + g_object_unref(connection); +} + static void test_read_wifi_dynamic_wep_leap(void) { @@ -11535,6 +11563,8 @@ main(int argc, char **argv) g_test_add_func(TPATH "wifi/read/dynamic-wep/leap", test_read_wifi_dynamic_wep_leap); g_test_add_func(TPATH "wifi/read/wpa/eap/tls", test_read_wifi_wpa_eap_tls); g_test_add_func(TPATH "wifi/read/wpa/eap/ttls/tls", test_read_wifi_wpa_eap_ttls_tls); + g_test_add_func(TPATH "wifi/read/wpa/eap-suite-b-192/tls", + test_read_wifi_wpa_eap_suite_b_192_tls); g_test_add_func(TPATH "wifi/read/dynamic-wep/eap/ttls/chap", test_read_wifi_wep_eap_ttls_chap); g_test_add_func(TPATH "wifi/read-band-a", test_read_wifi_band_a); g_test_add_func(TPATH "wifi/read-band-a-channel-mismatch", diff --git a/src/supplicant/nm-supplicant-config.c b/src/supplicant/nm-supplicant-config.c index 9a23f18554..26e8c1cb75 100644 --- a/src/supplicant/nm-supplicant-config.c +++ b/src/supplicant/nm-supplicant-config.c @@ -621,7 +621,8 @@ nm_supplicant_config_add_bgscan(NMSupplicantConfig *self, NMConnection *connecti || ((s_wsec = nm_connection_get_setting_wireless_security(connection)) && NM_IN_STRSET(nm_setting_wireless_security_get_key_mgmt(s_wsec), "ieee8021x", - "wpa-eap"))) + "wpa-eap", + "wpa-eap-suite-b-192"))) bgscan = "simple:30:-65:300"; return nm_supplicant_config_add_option(self, "bgscan", bgscan, -1, FALSE, error); @@ -833,8 +834,13 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) g_string_append(key_mgmt_conf, " ft-psk"); } else if (nm_streq(key_mgmt, "wpa-eap")) { - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) { g_string_append(key_mgmt_conf, " wpa-eap-sha256"); + + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SUITEB192) + && pmf == NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) + g_string_append(key_mgmt_conf, " wpa-eap-suite-b-192"); + } if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) g_string_append(key_mgmt_conf, " ft-eap"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT) @@ -863,6 +869,21 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * } else if (nm_streq(key_mgmt, "sae")) { if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) g_string_append(key_mgmt_conf, " ft-sae"); + } else if (nm_streq(key_mgmt, "wpa-eap-suite-b-192")) { + if (!NM_IN_SET(pmf, + NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT, + NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED)) { + g_set_error(error, + NM_SUPPLICANT_ERROR, + NM_SUPPLICANT_ERROR_CONFIG, + "PMF must be set to 'required'"); + return FALSE; + } + + pmf = NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED; + if (!nm_supplicant_config_add_option(self, "pairwise", "GCMP-256", -1, NULL, error) + || !nm_supplicant_config_add_option(self, "group", "GCMP-256", -1, NULL, error)) + return FALSE; } if (!add_string_val(self, key_mgmt_conf->str, "key_mgmt", TRUE, NULL, error)) @@ -932,7 +953,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * } /* Don't try to enable PMF on non-WPA/SAE/OWE networks */ - if (!NM_IN_STRSET(key_mgmt, "wpa-eap", "wpa-psk", "sae", "owe")) + if (!NM_IN_STRSET(key_mgmt, "wpa-eap", "wpa-eap-suite-b-192", "wpa-psk", "sae", "owe")) pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE; /* Check if we actually support PMF */ @@ -1050,7 +1071,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * } } else { /* 802.1x for Dynamic WEP and WPA-Enterprise */ - if (NM_IN_STRSET(key_mgmt, "ieee8021x", "wpa-eap")) { + if (NM_IN_STRSET(key_mgmt, "ieee8021x", "wpa-eap", "wpa-eap-suite-b-192")) { if (!setting_8021x) { g_set_error(error, NM_SUPPLICANT_ERROR, @@ -1068,7 +1089,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * return FALSE; } - if (nm_streq(key_mgmt, "wpa-eap")) { + if (NM_IN_STRSET(key_mgmt, "wpa-eap", "wpa-eap-suite-b-192")) { /* When using WPA-Enterprise, we want to use Proactive Key Caching (also * called Opportunistic Key Caching) to avoid full EAP exchanges when * roaming between access points in the same mobility group. diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index 611372d5da..c498663849 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -280,6 +280,8 @@ security_from_vardict(GVariant *security) flags |= NM_802_11_AP_SEC_KEY_MGMT_SAE; if (g_strv_contains(array, "owe")) flags |= NM_802_11_AP_SEC_KEY_MGMT_OWE; + if (g_strv_contains(array, "wpa-eap-suite-b-192")) + flags |= NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192; g_free(array); } diff --git a/src/supplicant/nm-supplicant-manager.c b/src/supplicant/nm-supplicant-manager.c index a166f61945..b7beb3a07d 100644 --- a/src/supplicant/nm-supplicant-manager.c +++ b/src/supplicant/nm-supplicant-manager.c @@ -933,6 +933,7 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data) _caps_set(priv, NM_SUPPL_CAP_TYPE_AP, NM_TERNARY_FALSE); _caps_set(priv, NM_SUPPL_CAP_TYPE_PMF, NM_TERNARY_FALSE); _caps_set(priv, NM_SUPPL_CAP_TYPE_FILS, NM_TERNARY_FALSE); + _caps_set(priv, NM_SUPPL_CAP_TYPE_SUITEB192, NM_TERNARY_FALSE); if (array) { for (a = array; *a; a++) { if (nm_streq(*a, "ap")) { @@ -963,6 +964,10 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data) _caps_set(priv, NM_SUPPL_CAP_TYPE_MESH, NM_TERNARY_TRUE); continue; } + if (nm_streq(*a, "suiteb192")) { + _caps_set(priv, NM_SUPPL_CAP_TYPE_SUITEB192, NM_TERNARY_TRUE); + continue; + } } } } diff --git a/src/supplicant/nm-supplicant-settings-verify.c b/src/supplicant/nm-supplicant-settings-verify.c index c7209f5f29..1b5337de9c 100644 --- a/src/supplicant/nm-supplicant-settings-verify.c +++ b/src/supplicant/nm-supplicant-settings-verify.c @@ -63,7 +63,7 @@ static const struct Opt opt_table[] = { OPT_INT("fragment_size", 1, 2000), OPT_KEYWORD("freq_list", NULL), OPT_INT("frequency", 2412, 5825), - OPT_KEYWORD("group", NM_MAKE_STRV("CCMP", "TKIP", "WEP104", "WEP40", )), + OPT_KEYWORD("group", NM_MAKE_STRV("CCMP", "TKIP", "WEP104", "WEP40", "GCMP-256", )), OPT_BYTES("identity", 0), OPT_INT("ieee80211w", 0, 2), OPT_INT("ignore_broadcast_ssid", 0, 2), @@ -82,6 +82,7 @@ static const struct Opt opt_table[] = { "FT-FILS-SHA384", "IEEE8021X", "SAE", + "WPA-EAP-SUITE-B-192", "FT-SAE", "OWE", "NONE", )), @@ -92,7 +93,7 @@ static const struct Opt opt_table[] = { OPT_BYTES("mka_ckn", 65536), OPT_BYTES("nai", 0), OPT_BYTES("pac_file", 0), - OPT_KEYWORD("pairwise", NM_MAKE_STRV("CCMP", "TKIP", "NONE", )), + OPT_KEYWORD("pairwise", NM_MAKE_STRV("CCMP", "TKIP", "GCMP-256", "NONE", )), OPT_UTF8("password", 0), OPT_BYTES("pcsc", 0), OPT_KEYWORD("phase1", diff --git a/src/supplicant/nm-supplicant-types.h b/src/supplicant/nm-supplicant-types.h index 72936ddfc2..e43cb56426 100644 --- a/src/supplicant/nm-supplicant-types.h +++ b/src/supplicant/nm-supplicant-types.h @@ -45,6 +45,7 @@ typedef enum { NM_SUPPL_CAP_TYPE_MESH, NM_SUPPL_CAP_TYPE_FAST, NM_SUPPL_CAP_TYPE_WFD, + NM_SUPPL_CAP_TYPE_SUITEB192, _NM_SUPPL_CAP_TYPE_NUM, } NMSupplCapType; diff --git a/src/supplicant/tests/test-supplicant-config.c b/src/supplicant/tests/test-supplicant-config.c index 6edcd8da4f..a7873ba2c9 100644 --- a/src/supplicant/tests/test-supplicant-config.c +++ b/src/supplicant/tests/test-supplicant-config.c @@ -600,6 +600,50 @@ generate_wifi_eap_connection(const char * id, return connection; } +static NMConnection * +generate_wifi_eap_suite_b_192_connection(const char *id, GBytes *ssid, const char *bssid_str) +{ + NMConnection * connection = NULL; + NMSettingWirelessSecurity *s_wsec; + NMSetting8021x * s_8021x; + gboolean success; + GError * error = NULL; + + connection = new_basic_connection(id, ssid, bssid_str); + + /* Wifi Security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); + nm_connection_add_setting(connection, NM_SETTING(s_wsec)); + g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap-suite-b-192", NULL); + + /* 802-1X setting */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + nm_connection_add_setting(connection, NM_SETTING(s_8021x)); + nm_setting_802_1x_add_eap_method(s_8021x, "tls"); + nm_setting_802_1x_set_client_cert(s_8021x, + TEST_CERT_DIR "/test-cert.p12", + NM_SETTING_802_1X_CK_SCHEME_PATH, + NULL, + NULL); + g_assert(nm_setting_802_1x_set_ca_cert(s_8021x, + TEST_CERT_DIR "/test-ca-cert.pem", + NM_SETTING_802_1X_CK_SCHEME_PATH, + NULL, + NULL)); + nm_setting_802_1x_set_private_key(s_8021x, + TEST_CERT_DIR "/test-cert.p12", + NULL, + NM_SETTING_802_1X_CK_SCHEME_PATH, + NULL, + NULL); + + success = nm_connection_verify(connection, &error); + g_assert_no_error(error); + g_assert(success); + + return connection; +} + static void test_wifi_eap_locked_bssid(void) { @@ -755,6 +799,47 @@ test_wifi_eap_fils_disabled(void) validate_opt("wifi-eap", config_dict, "bgscan", NM_SUPPL_OPT_TYPE_BYTES, bgscan); } +static void +test_wifi_eap_suite_b_generation(void) +{ + gs_unref_object NMConnection *connection = NULL; + gs_unref_variant GVariant *config_dict = NULL; + const unsigned char ssid_data[] = {0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44}; + gs_unref_bytes GBytes *ssid = g_bytes_new(ssid_data, sizeof(ssid_data)); + const char * bssid_str = "11:22:33:44:55:66"; + guint32 mtu = 1100; + + connection = generate_wifi_eap_suite_b_192_connection("EAP-TLS Suite B 192", ssid, bssid_str); + + NMTST_EXPECT_NM_INFO("Config: added 'ssid' value 'Test SSID'*"); + NMTST_EXPECT_NM_INFO("Config: added 'scan_ssid' value '1'*"); + NMTST_EXPECT_NM_INFO("Config: added 'bssid' value '11:22:33:44:55:66'*"); + NMTST_EXPECT_NM_INFO("Config: added 'freq_list' value *"); + NMTST_EXPECT_NM_INFO("Config: added 'pairwise' value 'GCMP-256'"); + NMTST_EXPECT_NM_INFO("Config: added 'group' value 'GCMP-256'"); + NMTST_EXPECT_NM_INFO("Config: added 'key_mgmt' value 'WPA-EAP-SUITE-B-192'"); + NMTST_EXPECT_NM_INFO("Config: added 'eap' value 'TLS'"); + NMTST_EXPECT_NM_INFO("Config: added 'fragment_size' value '1086'"); + NMTST_EXPECT_NM_INFO("Config: added 'ca_cert' value '*/test-ca-cert.pem'"); + NMTST_EXPECT_NM_INFO("Config: added 'private_key' value '*/test-cert.p12'"); + NMTST_EXPECT_NM_INFO("Config: added 'proactive_key_caching' value '1'"); + config_dict = build_supplicant_config(connection, mtu, 0, NM_SUPPL_CAP_MASK_T_PMF_YES); + g_test_assert_expected_messages(); + g_assert(config_dict); + + validate_opt("wifi-eap", config_dict, "scan_ssid", NM_SUPPL_OPT_TYPE_INT, GINT_TO_POINTER(1)); + validate_opt("wifi-eap", config_dict, "ssid", NM_SUPPL_OPT_TYPE_BYTES, ssid); + validate_opt("wifi-eap", config_dict, "bssid", NM_SUPPL_OPT_TYPE_KEYWORD, bssid_str); + validate_opt("wifi-eap", + config_dict, + "key_mgmt", + NM_SUPPL_OPT_TYPE_KEYWORD, + "WPA-EAP-SUITE-B-192"); + validate_opt("wifi-eap", config_dict, "eap", NM_SUPPL_OPT_TYPE_KEYWORD, "TLS"); + validate_opt("wifi-eap", config_dict, "pairwise", NM_SUPPL_OPT_TYPE_KEYWORD, "GCMP-256"); + validate_opt("wifi-eap", config_dict, "group", NM_SUPPL_OPT_TYPE_KEYWORD, "GCMP-256"); +} + /*****************************************************************************/ static void @@ -818,6 +903,7 @@ main(int argc, char **argv) g_test_add_func("/supplicant-config/wifi-eap/fils-disabled", test_wifi_eap_fils_disabled); g_test_add_func("/supplicant-config/wifi-sae", test_wifi_sae); g_test_add_func("/supplicant-config/test_suppl_cap_mask", test_suppl_cap_mask); + g_test_add_func("/supplicant-config/wifi-eap-suite-b-192", test_wifi_eap_suite_b_generation); return g_test_run(); }