summary refs log tree commit diff
path: root/src/core/supplicant
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/supplicant')
-rw-r--r--src/core/supplicant/nm-supplicant-config.c51
-rw-r--r--src/core/supplicant/nm-supplicant-config.h1
-rw-r--r--src/core/supplicant/nm-supplicant-interface.c28
-rw-r--r--src/core/supplicant/nm-supplicant-manager.c9
-rw-r--r--src/core/supplicant/nm-supplicant-types.h6
-rw-r--r--src/core/supplicant/tests/test-supplicant-config.c1
6 files changed, 86 insertions, 10 deletions
diff --git a/src/core/supplicant/nm-supplicant-config.c b/src/core/supplicant/nm-supplicant-config.c
index 96c23579..a4e5cc4d 100644
--- a/src/core/supplicant/nm-supplicant-config.c
+++ b/src/core/supplicant/nm-supplicant-config.c
@@ -805,6 +805,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
                                                    NMSettingWirelessSecurity    *setting,
                                                    NMSetting8021x               *setting_8021x,
                                                    const char                   *con_uuid,
+                                                   const char                   *mode,
                                                    guint32                       mtu,
                                                    NMSettingWirelessSecurityPmf  pmf,
                                                    NMSettingWirelessSecurityFils fils,
@@ -815,12 +816,20 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
     const char                   *key_mgmt, *auth_alg;
     const char                   *psk;
     gboolean                      set_pmf, wps_disabled;
+    gboolean                      is_ap;
 
     g_return_val_if_fail(NM_IS_SUPPLICANT_CONFIG(self), FALSE);
     g_return_val_if_fail(setting != NULL, FALSE);
     g_return_val_if_fail(con_uuid != NULL, FALSE);
     g_return_val_if_fail(!error || !*error, FALSE);
 
+    /* Currently wpa_supplicant doesn't support FT in AP mode. Even
+     * if it did, it  would require additional parameters as the nas
+     * identifier and the mobility domain. Therefore we disable all
+     * FT key-mgmts in AP mode.
+     */
+    is_ap = nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP);
+
     /* Check if we actually support FILS */
     if (!_get_capability(priv, NM_SUPPL_CAP_TYPE_FILS)) {
         if (fils == NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED) {
@@ -852,11 +861,39 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
             g_string_append(key_mgmt_conf, "WPA-PSK");
         if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF))
             g_string_append(key_mgmt_conf, " WPA-PSK-SHA256");
-        if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT))
+        if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT))
             g_string_append(key_mgmt_conf, " FT-PSK");
-        if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SAE)) {
+
+        /* For NM "key-mgmt=wpa-psk" doesn't strictly mean WPA1/wPA2 only,
+         * but also allows WPA3 (SAE), so that existing connections can
+         * benefit from the improved security when the AP gets upgraded.
+         *
+         * According to WPA3_Specification_v3.0 section 2.3, when operating
+         * in WPA3-Personal transition mode a STA:
+         *
+         * - should allow AKM suite selector: 00-0F-AC:6 (WPA-PSK-SHA256) to
+         *   be selected for an association;
+         * - shall negotiate PMF when associating to an AP using SAE.
+         *
+         * Those conditions are met when the interface has capabilities
+         * SAE, PMF, BIP.
+         *
+         * According to WPA3_Specification_v3.0 section 2.3, when operating
+         * in WPA3-Personal transition mode an AP:
+         *
+         * - shall set MFPC to 1, MFPR to 0.
+         *
+         * Therefore, do not operate in WPA3-Personal transition mode when PMF
+         * is set to disabled. This also provides a way to be compatible with
+         * some devices that are not fully compatible with WPA3-Personal
+         * transition mode.
+         */
+        if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SAE)
+            && _get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)
+            && _get_capability(priv, NM_SUPPL_CAP_TYPE_BIP)
+            && (!is_ap || pmf != NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE)) {
             g_string_append(key_mgmt_conf, " SAE");
-            if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT))
+            if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT))
                 g_string_append(key_mgmt_conf, " FT-SAE");
         }
 
@@ -864,13 +901,13 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
         pmf = NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED;
 
         g_string_append(key_mgmt_conf, "SAE");
-        if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT))
+        if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT))
             g_string_append(key_mgmt_conf, " FT-SAE");
 
     } else if (nm_streq(key_mgmt, "wpa-eap")) {
         if (pmf != NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED)
             g_string_append(key_mgmt_conf, "WPA-EAP");
-        if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) {
+        if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) {
             g_string_append(key_mgmt_conf, " FT-EAP");
             if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384))
                 g_string_append(key_mgmt_conf, " FT-EAP-SHA384");
@@ -891,7 +928,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
         case NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL:
             if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) {
                 g_string_append(key_mgmt_conf, " FILS-SHA256 FILS-SHA384");
-                if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) {
+                if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) {
                     g_string_append(key_mgmt_conf, " FT-FILS-SHA256");
                     if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384))
                         g_string_append(key_mgmt_conf, " FT-FILS-SHA384");
@@ -907,7 +944,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
         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)
+        if (!is_ap && _get_capability(priv, NM_SUPPL_CAP_TYPE_FT)
             && _get_capability(priv, NM_SUPPL_CAP_TYPE_SHA384))
             g_string_append(key_mgmt_conf, " FT-EAP-SHA384");
     }
diff --git a/src/core/supplicant/nm-supplicant-config.h b/src/core/supplicant/nm-supplicant-config.h
index 349c310f..ee7f4dc8 100644
--- a/src/core/supplicant/nm-supplicant-config.h
+++ b/src/core/supplicant/nm-supplicant-config.h
@@ -51,6 +51,7 @@ gboolean nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig
                                                             NMSettingWirelessSecurity *setting,
                                                             NMSetting8021x *setting_8021x,
                                                             const char     *con_uuid,
+                                                            const char     *mode,
                                                             guint32         mtu,
                                                             NMSettingWirelessSecurityPmf  pmf,
                                                             NMSettingWirelessSecurityFils fils,
diff --git a/src/core/supplicant/nm-supplicant-interface.c b/src/core/supplicant/nm-supplicant-interface.c
index d8276144..e502ae85 100644
--- a/src/core/supplicant/nm-supplicant-interface.c
+++ b/src/core/supplicant/nm-supplicant-interface.c
@@ -1225,8 +1225,10 @@ parse_capabilities(NMSupplicantInterface *self, GVariant *capabilities)
     const guint32                 old_max_scan_ssids   = priv->max_scan_ssids;
     gboolean                      have_ft              = FALSE;
     gboolean                      have_sae             = FALSE;
+    gboolean                      have_bip             = FALSE;
     gint32                        max_scan_ssids;
     const char                  **array;
+    guint                         i;
 
     nm_assert(capabilities && g_variant_is_of_type(capabilities, G_VARIANT_TYPE_VARDICT));
 
@@ -1236,12 +1238,28 @@ parse_capabilities(NMSupplicantInterface *self, GVariant *capabilities)
         g_free(array);
     }
 
+    if (g_variant_lookup(capabilities, "GroupMgmt", "^a&s", &array)) {
+        for (i = 0; array[i]; i++) {
+            if (NM_IN_STRSET(array[i],
+                             "aes-128-cmac",
+                             "bip-gmac-128",
+                             "bip-gmac-256",
+                             "bip-cmac-256")) {
+                have_bip = TRUE;
+                break;
+            }
+        }
+    }
+
     priv->iface_capabilities = NM_SUPPL_CAP_MASK_SET(priv->iface_capabilities,
                                                      NM_SUPPL_CAP_TYPE_FT,
                                                      have_ft ? NM_TERNARY_TRUE : NM_TERNARY_FALSE);
     priv->iface_capabilities = NM_SUPPL_CAP_MASK_SET(priv->iface_capabilities,
                                                      NM_SUPPL_CAP_TYPE_SAE,
                                                      have_sae ? NM_TERNARY_TRUE : NM_TERNARY_FALSE);
+    priv->iface_capabilities = NM_SUPPL_CAP_MASK_SET(priv->iface_capabilities,
+                                                     NM_SUPPL_CAP_TYPE_BIP,
+                                                     have_bip ? NM_TERNARY_TRUE : NM_TERNARY_FALSE);
 
     if (g_variant_lookup(capabilities, "Modes", "^a&s", &array)) {
         /* Setting p2p_capable might toggle _prop_p2p_available_get(). However,
@@ -1317,10 +1335,12 @@ _starting_check_ready(NMSupplicantInterface *self)
           " AP%c"
           " FT%c"
           " SAE%c"
+          " BIP%c"
           "",
           NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_AP),
           NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_FT),
-          NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_SAE));
+          NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_SAE),
+          NM_SUPPL_CAP_TO_CHAR(priv->iface_capabilities, NM_SUPPL_CAP_TYPE_BIP));
 
     /* Other global properties are set in constructed() because they don't
      * depend on interface capabilities. */
@@ -1362,6 +1382,7 @@ _get_capability(NMSupplicantInterfacePrivate *priv, NMSupplCapType type)
         }
         break;
     case NM_SUPPL_CAP_TYPE_SAE:
+    case NM_SUPPL_CAP_TYPE_BIP:
         nm_assert(NM_SUPPL_CAP_MASK_GET(priv->global_capabilities, type) == NM_TERNARY_DEFAULT);
         value = NM_SUPPL_CAP_MASK_GET(priv->iface_capabilities, type);
         break;
@@ -1395,10 +1416,13 @@ nm_supplicant_interface_get_capabilities(NMSupplicantInterface *self)
     caps = NM_SUPPL_CAP_MASK_SET(caps,
                                  NM_SUPPL_CAP_TYPE_SAE,
                                  _get_capability(priv, NM_SUPPL_CAP_TYPE_SAE));
+    caps = NM_SUPPL_CAP_MASK_SET(caps,
+                                 NM_SUPPL_CAP_TYPE_BIP,
+                                 _get_capability(priv, NM_SUPPL_CAP_TYPE_BIP));
 
     nm_assert(!NM_FLAGS_ANY(priv->iface_capabilities,
                             ~(NM_SUPPL_CAP_MASK_T_AP_MASK | NM_SUPPL_CAP_MASK_T_FT_MASK
-                              | NM_SUPPL_CAP_MASK_T_SAE_MASK)));
+                              | NM_SUPPL_CAP_MASK_T_SAE_MASK | NM_SUPPL_CAP_MASK_T_BIP_MASK)));
 
 #if NM_MORE_ASSERTS > 10
     {
diff --git a/src/core/supplicant/nm-supplicant-manager.c b/src/core/supplicant/nm-supplicant-manager.c
index 9de845f0..2ec7db23 100644
--- a/src/core/supplicant/nm-supplicant-manager.c
+++ b/src/core/supplicant/nm-supplicant-manager.c
@@ -920,6 +920,7 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data)
                     _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);
+                    _caps_set(priv, NM_SUPPL_CAP_TYPE_WEP, NM_TERNARY_TRUE);
                     if (array) {
                         for (a = array; *a; a++) {
                             if (nm_streq(*a, "ap")) {
@@ -954,6 +955,10 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data)
                                 _caps_set(priv, NM_SUPPL_CAP_TYPE_SUITEB192, NM_TERNARY_TRUE);
                                 continue;
                             }
+                            if (nm_streq(*a, "wep_disabled")) {
+                                _caps_set(priv, NM_SUPPL_CAP_TYPE_WEP, NM_TERNARY_FALSE);
+                                continue;
+                            }
                         }
                     }
                 }
@@ -994,6 +999,7 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data)
           " FAST%c"
           " WFD%c"
           " SUITEB192%c"
+          " WEP%c"
           "",
           NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_AP),
           NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_PMF),
@@ -1004,7 +1010,8 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data)
           NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_MESH),
           NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_FAST),
           NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_WFD),
-          NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_SUITEB192));
+          NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_SUITEB192),
+          NM_SUPPL_CAP_TO_CHAR(priv->capabilities, NM_SUPPL_CAP_TYPE_WEP));
 
     nm_assert(g_hash_table_size(priv->supp_ifaces) == 0);
     nm_assert(c_list_is_empty(&priv->supp_lst_head));
diff --git a/src/core/supplicant/nm-supplicant-types.h b/src/core/supplicant/nm-supplicant-types.h
index d5cf1bf7..1ae67e13 100644
--- a/src/core/supplicant/nm-supplicant-types.h
+++ b/src/core/supplicant/nm-supplicant-types.h
@@ -48,6 +48,10 @@ typedef enum {
     NM_SUPPL_CAP_TYPE_FAST,
     NM_SUPPL_CAP_TYPE_WFD,
     NM_SUPPL_CAP_TYPE_SUITEB192,
+    NM_SUPPL_CAP_TYPE_WEP,
+    NM_SUPPL_CAP_TYPE_BIP,
+    /* Note: if you're adding a capability here, log its presence at the
+     * bottom of _dbus_get_capabilities_cb(). */
     _NM_SUPPL_CAP_TYPE_NUM,
 } NMSupplCapType;
 
@@ -75,6 +79,8 @@ typedef enum {
     _NM_SUPPL_CAP_MASK_DEFINE(FT),
     _NM_SUPPL_CAP_MASK_DEFINE(SAE),
     _NM_SUPPL_CAP_MASK_DEFINE(SHA384),
+    _NM_SUPPL_CAP_MASK_DEFINE(WEP),
+    _NM_SUPPL_CAP_MASK_DEFINE(BIP),
 #undef _NM_SUPPL_CAP_MASK_DEFINE
 } NMSupplCapMask;
 
diff --git a/src/core/supplicant/tests/test-supplicant-config.c b/src/core/supplicant/tests/test-supplicant-config.c
index 53c5f70f..237b1a96 100644
--- a/src/core/supplicant/tests/test-supplicant-config.c
+++ b/src/core/supplicant/tests/test-supplicant-config.c
@@ -116,6 +116,7 @@ build_supplicant_config(NMConnection  *connection,
                                                                s_wsec,
                                                                s_8021x,
                                                                nm_connection_get_uuid(connection),
+                                                               nm_setting_wireless_get_mode(s_wifi),
                                                                mtu,
                                                                pmf,
                                                                fils,