From 63836f394510ab173aefd24aca3f1e29a5baf046 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 24 Apr 2017 15:42:49 +0200 Subject: [PATCH 01/11] ifcfg-rh: don't skip 802-11-security if there's no WPA-PSK --- src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 5baa9c792b..5dc42e28bb 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -3328,6 +3328,7 @@ make_wpa_setting (shvarFile *ifcfg, char *value, *psk, *lower; gboolean wpa_psk = FALSE, wpa_eap = FALSE, ieee8021x = FALSE; int i_val; + GError *local = NULL; wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ()); @@ -3371,12 +3372,14 @@ make_wpa_setting (shvarFile *ifcfg, /* Read PSK if it's system-owned */ if (psk_flags == NM_SETTING_SECRET_FLAG_NONE) { - psk = parse_wpa_psk (ifcfg, file, ssid, error); + psk = parse_wpa_psk (ifcfg, file, ssid, &local); if (psk) { g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_PSK, psk, NULL); g_free (psk); - } else if (error) + } else if (local) { + g_propagate_error (error, local); goto error; + } } if (adhoc) From 36b6bbdae31dee6d84e1e59f993088e3f1e90379 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 30 Apr 2017 22:49:37 +0200 Subject: [PATCH 02/11] dbus: add WPS methods to AP flags Will be used to indicate WPS method discovered to be supported by the access point. --- libnm-core/nm-dbus-interface.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 8abc91bbf8..7130a92609 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2004 - 2014 Red Hat, Inc. + * Copyright 2004 - 2017 Red Hat, Inc. */ /* Definitions related to NetworkManager's D-Bus interfaces. @@ -289,12 +289,18 @@ typedef enum { /*< flags >*/ * @NM_802_11_AP_FLAGS_NONE: access point has no special capabilities * @NM_802_11_AP_FLAGS_PRIVACY: access point requires authentication and * encryption (usually means WEP) + * @NM_802_11_AP_FLAGS_WPS: access point supports some WPS method + * @NM_802_11_AP_FLAGS_WPS_PBC: access point supports push-button WPS + * @NM_802_11_AP_FLAGS_WPS_PIN: access point supports PIN-based WPS * * 802.11 access point flags. **/ typedef enum { /*< underscore_name=nm_802_11_ap_flags, flags >*/ NM_802_11_AP_FLAGS_NONE = 0x00000000, NM_802_11_AP_FLAGS_PRIVACY = 0x00000001, + NM_802_11_AP_FLAGS_WPS = 0x00000002, + NM_802_11_AP_FLAGS_WPS_PBC = 0x00000004, + NM_802_11_AP_FLAGS_WPS_PIN = 0x00000008, } NM80211ApFlags; /** From e6f95b50c83fae1deb76483bdc5f0652a62a28e1 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 30 Apr 2017 22:52:19 +0200 Subject: [PATCH 03/11] setting-wireless: add wps-method property This property will be used to decide if it makes sense to attempt a WPS enrollment on connection activation. --- clients/common/settings-docs.c.in | 1 + libnm-core/nm-setting-wireless-security.c | 70 ++++++++++++++++++++++- libnm-core/nm-setting-wireless-security.h | 26 ++++++++- libnm/libnm.ver | 2 + 4 files changed, 97 insertions(+), 2 deletions(-) diff --git a/clients/common/settings-docs.c.in b/clients/common/settings-docs.c.in index 5710ce73a5..c4e1a3e30c 100644 --- a/clients/common/settings-docs.c.in +++ b/clients/common/settings-docs.c.in @@ -40,6 +40,7 @@ #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY2 N_("Index 2 WEP key. This WEP index is not used by most networks. See the \"wep-key-type\" property for a description of how this key is interpreted.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_KEY3 N_("Index 3 WEP key. This WEP index is not used by most networks. See the \"wep-key-type\" property for a description of how this key is interpreted.") #define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX N_("When static WEP is used (ie, key-mgmt = \"none\") and a non-default WEP key index is used by the AP, put that WEP key index here. Valid values are 0 (default key) through 3. Note that some consumer access points (like the Linksys WRT54G) number the keys 1 - 4.") +#define DESCRIBE_DOC_NM_SETTING_WIRELESS_SECURITY_WPS_METHOD N_("Flags indicating which mode of WPS is to be used if any. There's little point in changing the default setting as NetworkManager will automatically determine whether it's feasible to start WPS enrollment from the Access Point capabilities. WPS can by disabled by setting this property to a value of 1.") #define DESCRIBE_DOC_NM_SETTING_802_1X_ALTSUBJECT_MATCHES N_("List of strings to be matched against the altSubjectName of the certificate presented by the authentication server. If the list is empty, no verification of the server certificate's altSubjectName is performed.") #define DESCRIBE_DOC_NM_SETTING_802_1X_ANONYMOUS_IDENTITY N_("Anonymous identity string for EAP authentication methods. Used as the unencrypted identity with EAP types that support different tunneled identity like EAP-TTLS.") #define DESCRIBE_DOC_NM_SETTING_802_1X_AUTH_TIMEOUT N_("A timeout for the authentication. Zero means the global default; if the global default is not set, the authentication timeout is 25 seconds.") diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c index 8ddefba2f2..6fdab41b38 100644 --- a/libnm-core/nm-setting-wireless-security.c +++ b/libnm-core/nm-setting-wireless-security.c @@ -16,7 +16,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * Copyright 2007 - 2014 Red Hat, Inc. + * Copyright 2007 - 2017 Red Hat, Inc. * Copyright 2007 - 2008 Novell, Inc. */ @@ -84,6 +84,9 @@ typedef struct { /* WPA-PSK */ char *psk; NMSettingSecretFlags psk_flags; + + /* WPS */ + NMSettingWirelessSecurityWpsMethod wps_method; } NMSettingWirelessSecurityPrivate; enum { @@ -106,6 +109,7 @@ enum { PROP_PSK_FLAGS, PROP_LEAP_PASSWORD, PROP_LEAP_PASSWORD_FLAGS, + PROP_WPS_METHOD, LAST_PROP }; @@ -793,6 +797,23 @@ nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSecurity *settin return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wep_key_type; } +/** + * nm_setting_wireless_security_get_wps_method: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:wps-method property of the setting + * + * Since: 1.10 + **/ +NMSettingWirelessSecurityWpsMethod +nm_setting_wireless_security_get_wps_method (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wps_method; +} + static GPtrArray * need_secrets (NMSetting *setting) { @@ -1056,6 +1077,25 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + /* WPS */ + if (priv->wps_method > NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WPS_METHOD); + return FALSE; + } + + if (priv->wps_method & NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED && priv->wps_method != NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can't be simultaneously disabled and enabled")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WPS_METHOD); + return FALSE; + } + return TRUE; } @@ -1284,6 +1324,9 @@ set_property (GObject *object, guint prop_id, case PROP_WEP_KEY_TYPE: priv->wep_key_type = g_value_get_enum (value); break; + case PROP_WPS_METHOD: + priv->wps_method = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1352,6 +1395,9 @@ get_property (GObject *object, guint prop_id, case PROP_WEP_KEY_TYPE: g_value_set_enum (value, priv->wep_key_type); break; + case PROP_WPS_METHOD: + g_value_set_uint (value, priv->wps_method); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1788,4 +1834,26 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting G_VARIANT_TYPE_UINT32, wep_key_type_to_dbus, NULL); + /** + * NMSettingWirelessSecurity:wps-method: + * + * Flags indicating which mode of WPS is to be used if any. + * + * There's little point in changing the default setting as NetworkManager will + * automatically determine whether it's feasible to start WPS enrollment from + * the Access Point capabilities. + * + * WPS can by disabled by setting this property to a value of 1. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_WPS_METHOD, + g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, "", "", + 0, G_MAXUINT32, NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_STATIC_STRINGS)); + } diff --git a/libnm-core/nm-setting-wireless-security.h b/libnm-core/nm-setting-wireless-security.h index 2c6dcaad62..0aa522f0f9 100644 --- a/libnm-core/nm-setting-wireless-security.h +++ b/libnm-core/nm-setting-wireless-security.h @@ -16,7 +16,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * Copyright 2007 - 2014 Red Hat, Inc. + * Copyright 2007 - 2017 Red Hat, Inc. * Copyright 2007 - 2008 Novell, Inc. */ @@ -89,6 +89,26 @@ typedef enum { NM_SETTING_WIRELESS_SECURITY_PMF_LAST = _NM_SETTING_WIRELESS_SECURITY_PMF_NUM - 1, /*< skip >*/ } NMSettingWirelessSecurityPmf; +/** + * NMSettingWirelessSecurityWpsMethod: + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT: Attempt whichever method AP supports + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED: WPS can not be used. + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO: Use WPS, any method + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC: use WPS push-buthon method + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN: use PIN method + * + * Configure the use of WPS by a connection while it activates. + * + * Since: 1.10 + **/ +typedef enum { + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT = 0x00000000, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED = 0x00000001, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO = 0x00000002, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC = 0x00000004, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN = 0x00000008, +} NMSettingWirelessSecurityWpsMethod; + #define NM_SETTING_WIRELESS_SECURITY_KEY_MGMT "key-mgmt" #define NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX "wep-tx-keyidx" #define NM_SETTING_WIRELESS_SECURITY_AUTH_ALG "auth-alg" @@ -107,6 +127,7 @@ typedef enum { #define NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS "psk-flags" #define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD "leap-password" #define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS "leap-password-flags" +#define NM_SETTING_WIRELESS_SECURITY_WPS_METHOD "wps-method" /** * NMSettingWirelessSecurity: @@ -169,6 +190,9 @@ const char *nm_setting_wireless_security_get_auth_alg (NMSettingWirelessSec NMSettingSecretFlags nm_setting_wireless_security_get_wep_key_flags (NMSettingWirelessSecurity *setting); NMWepKeyType nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSecurity *setting); +NM_AVAILABLE_IN_1_10 +NMSettingWirelessSecurityWpsMethod nm_setting_wireless_security_get_wps_method (NMSettingWirelessSecurity *setting); + G_END_DECLS #endif /* __NM_SETTING_WIRELESS_SECURITY_H__ */ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index f9d826d831..b9a3df2aae 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1181,5 +1181,7 @@ global: libnm_1_10_0 { global: nm_setting_wireless_security_get_pmf; + nm_setting_wireless_security_get_wps_method; nm_setting_wireless_security_pmf_get_type; + nm_setting_wireless_security_wps_method_get_type; } libnm_1_8_0; From 1d15e9c6de7dab60454b6ca2e63b2636c6d7a916 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Thu, 13 Apr 2017 10:42:32 +0200 Subject: [PATCH 04/11] supplicant-interface: add support for WPS enrollment --- src/supplicant/nm-supplicant-interface.c | 177 ++++++++++++++++++++++- src/supplicant/nm-supplicant-interface.h | 11 +- 2 files changed, 180 insertions(+), 8 deletions(-) diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index c4633f2535..84ac640fc7 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2006 - 2012 Red Hat, Inc. + * Copyright (C) 2006 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -31,11 +31,12 @@ #include "nm-core-internal.h" #include "nm-dbus-compat.h" -#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface" -#define WPAS_DBUS_IFACE_BSS WPAS_DBUS_INTERFACE ".BSS" -#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network" -#define WPAS_ERROR_INVALID_IFACE WPAS_DBUS_INTERFACE ".InvalidInterface" -#define WPAS_ERROR_EXISTS_ERROR WPAS_DBUS_INTERFACE ".InterfaceExists" +#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface" +#define WPAS_DBUS_IFACE_INTERFACE_WPS WPAS_DBUS_INTERFACE ".Interface.WPS" +#define WPAS_DBUS_IFACE_BSS WPAS_DBUS_INTERFACE ".BSS" +#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network" +#define WPAS_ERROR_INVALID_IFACE WPAS_DBUS_INTERFACE ".InvalidInterface" +#define WPAS_ERROR_EXISTS_ERROR WPAS_DBUS_INTERFACE ".InterfaceExists" /*****************************************************************************/ @@ -69,6 +70,7 @@ enum { BSS_REMOVED, /* supplicant removed BSS from its scan list */ SCAN_DONE, /* wifi scan is complete */ CREDENTIALS_REQUEST, /* 802.1x identity or password requested */ + WPS_CREDENTIALS, /* WPS credentials received */ LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -107,6 +109,9 @@ typedef struct { GDBusProxy * iface_proxy; GCancellable * other_cancellable; + GDBusProxy * wps_proxy; /* We only have a WPS proxy when the enrollment was initiated */ + GCancellable * wps_cancellable; /* This can cancel the initiation, not the enrollment */ + AssocData * assoc_data; char * net_path; @@ -580,6 +585,152 @@ nm_supplicant_interface_set_pmf_support (NMSupplicantInterface *self, priv->pmf_support = pmf_support; } +typedef struct { + NMSupplicantInterface *self; + const char *type; + char *bssid; + char *pin; +} WpsEnrollStartData; + +static void +wps_enroll_start_data_free (WpsEnrollStartData *data) +{ + g_free (data->pin); + g_free (data->bssid); + g_slice_free (WpsEnrollStartData, data); +} + +static void +wpas_iface_wps_credentials (GDBusProxy *proxy, + GVariant *props, + gpointer user_data) +{ + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + + g_signal_emit (self, signals[WPS_CREDENTIALS], 0, props); +} + +static void +on_wps_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) +{ + WpsEnrollStartData *data = user_data; + NMSupplicantInterface *self = data->self; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + GVariantBuilder start_args; + guint8 bssid_buf[ETH_ALEN]; + gs_free_error GError *error = NULL; + + priv->wps_proxy = g_dbus_proxy_new_for_bus_finish (result, &error); + if (!priv->wps_proxy) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + _LOGW ("failed to acquire WPS proxy: (%s)", error->message); + set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); + } + wps_enroll_start_data_free (data); + return; + } + + /* Enable Credentials processing. */ + _nm_dbus_signal_connect (priv->wps_proxy, "Credentials", G_VARIANT_TYPE ("(a{sv})"), + G_CALLBACK (wpas_iface_wps_credentials), self); + + g_dbus_proxy_call (priv->wps_proxy, + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", + WPAS_DBUS_IFACE_INTERFACE_WPS, + "ProcessCredentials", + g_variant_new_boolean (TRUE)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + NULL); + + /* Initiate the enrollment. */ + g_variant_builder_init (&start_args, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add (&start_args, "{sv}", "Role", g_variant_new_string ("enrollee")); + g_variant_builder_add (&start_args, "{sv}", "Type", g_variant_new_string (data->type)); + if (data->pin) + g_variant_builder_add (&start_args, "{sv}", "Pin", g_variant_new_string (data->pin)); + + if (data->bssid) { + /* The BSSID is in fact not mandatory. If it is not set the supplicant would + * enroll with any BSS in range. */ + if (!nm_utils_hwaddr_aton (data->bssid, bssid_buf, sizeof (bssid_buf))) + g_return_if_reached (); + g_variant_builder_add (&start_args, "{sv}", "Bssid", + g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, bssid_buf, + ETH_ALEN, sizeof (guint8))); + _LOGI ("starting '%s' WPS enrollment for BSSID '%s'", data->type, data->bssid); + } else { + _LOGI ("starting '%s' WPS enrollment", data->type); + } + + g_dbus_proxy_call (priv->wps_proxy, + "Start", + g_variant_new ("(a{sv})", &start_args), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + NULL); + wps_enroll_start_data_free (data); +} + +void +nm_supplicant_interface_enroll_wps (NMSupplicantInterface *self, + const char *type, + const char *bssid, + const char *pin) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + WpsEnrollStartData *data; + + data = g_slice_new0 (WpsEnrollStartData); + data->self = self; + data->type = type; + data->bssid = g_strdup (bssid); + data->pin = g_strdup (pin); + + /* Supersede any previous WPS initiations. */ + nm_supplicant_interface_cancel_wps (self); + + priv->wps_cancellable = g_cancellable_new (); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + WPAS_DBUS_SERVICE, + priv->object_path, + WPAS_DBUS_IFACE_INTERFACE_WPS, + priv->wps_cancellable, + (GAsyncReadyCallback) on_wps_proxy_acquired, + data); +} + +void +nm_supplicant_interface_cancel_wps (NMSupplicantInterface *self) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + nm_clear_g_cancellable (&priv->wps_cancellable); + + if (!priv->wps_proxy) + return; + + _LOGD ("cancelling WPS enrollment"); + g_signal_handlers_disconnect_by_data (priv->wps_proxy, self); + g_dbus_proxy_call (priv->wps_proxy, + "Cancel", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + NULL); + g_clear_object (&priv->wps_proxy); +} + static void iface_introspect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) { @@ -1173,6 +1324,9 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self) g_free (priv->net_path); priv->net_path = NULL; } + + /* Cancel any WPS enrollment, if any */ + nm_supplicant_interface_cancel_wps (self); } static void @@ -1636,6 +1790,8 @@ dispose (GObject *object) g_clear_object (&priv->wpas_proxy); g_clear_pointer (&priv->bss_proxies, (GDestroyNotify) g_hash_table_destroy); + nm_supplicant_interface_cancel_wps (self); + g_clear_pointer (&priv->net_path, g_free); g_clear_pointer (&priv->dev, g_free); g_clear_pointer (&priv->object_path, g_free); @@ -1749,5 +1905,12 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) 0, NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); -} + signals[WPS_CREDENTIALS] = + g_signal_new (NM_SUPPLICANT_INTERFACE_WPS_CREDENTIALS, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_VARIANT); +} diff --git a/src/supplicant/nm-supplicant-interface.h b/src/supplicant/nm-supplicant-interface.h index a31d2b8a81..567cf96ff5 100644 --- a/src/supplicant/nm-supplicant-interface.h +++ b/src/supplicant/nm-supplicant-interface.h @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2006 - 2010 Red Hat, Inc. + * Copyright (C) 2006 - 2017 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ @@ -69,6 +69,7 @@ typedef enum { #define NM_SUPPLICANT_INTERFACE_BSS_REMOVED "bss-removed" #define NM_SUPPLICANT_INTERFACE_SCAN_DONE "scan-done" #define NM_SUPPLICANT_INTERFACE_CREDENTIALS_REQUEST "credentials-request" +#define NM_SUPPLICANT_INTERFACE_WPS_CREDENTIALS "wps-credentials" typedef struct _NMSupplicantInterfaceClass NMSupplicantInterfaceClass; @@ -131,4 +132,12 @@ void nm_supplicant_interface_set_fast_support (NMSupplicantInterface *self, void nm_supplicant_interface_set_pmf_support (NMSupplicantInterface *self, NMSupplicantFeature pmf_support); + +void nm_supplicant_interface_enroll_wps (NMSupplicantInterface *self, + const char *const type, + const char *bssid, + const char *pin); + +void nm_supplicant_interface_cancel_wps (NMSupplicantInterface *self); + #endif /* __NM_SUPPLICANT_INTERFACE_H__ */ From a3040bf92f417aa5e3d4bb826ea92cfefba14c4e Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 30 Apr 2017 22:54:51 +0200 Subject: [PATCH 05/11] wifi/ap: add flags accessor The wifi device will inspect this to decide whether to initiate a WPS enrollment unless the user overrides the default. --- src/devices/wifi/nm-wifi-ap.c | 8 ++++++++ src/devices/wifi/nm-wifi-ap.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index c45eaafa93..90cf8e669c 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -376,6 +376,14 @@ nm_wifi_ap_set_fake (NMWifiAP *ap, gboolean fake) return FALSE; } +NM80211ApFlags +nm_wifi_ap_get_flags (const NMWifiAP *ap) +{ + g_return_val_if_fail (NM_IS_WIFI_AP (ap), NM_802_11_AP_FLAGS_NONE); + + return NM_WIFI_AP_GET_PRIVATE (ap)->flags; +} + static gboolean nm_wifi_ap_set_last_seen (NMWifiAP *ap, gint32 last_seen) { diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index 5e64087cca..c9b4772fa0 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -88,6 +88,7 @@ gboolean nm_wifi_ap_set_max_bitrate (NMWifiAP *ap, gboolean nm_wifi_ap_get_fake (const NMWifiAP *ap); gboolean nm_wifi_ap_set_fake (NMWifiAP *ap, gboolean fake); +NM80211ApFlags nm_wifi_ap_get_flags (const NMWifiAP *self); const char *nm_wifi_ap_to_string (const NMWifiAP *self, char *str_buf, From 5c80571006d784bba4c55cafdb9da0667980011f Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 30 Apr 2017 22:54:40 +0200 Subject: [PATCH 06/11] wifi/ap: maintain the WPS flags Exposure of this property on D-Bus would be useful for the GUIs to encourage the users to enter a PIN or push a button. We'll also use it to decide whether a connection will initiate WPS enrollment unless the user overrides the default. --- src/devices/wifi/nm-wifi-ap.c | 14 +++++++++++++- src/devices/wifi/nm-wifi-ap.h | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index 90cf8e669c..bc823af0a5 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2004 - 2011 Red Hat, Inc. + * Copyright (C) 2004 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -790,6 +790,18 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap, if (g_variant_lookup (properties, "Privacy", "b", &b) && b) changed |= nm_wifi_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_PRIVACY); + v = g_variant_lookup_value (properties, "WPS", G_VARIANT_TYPE_VARDICT); + if (v) { + if (g_variant_lookup (v, "Type", "&s", &s)) { + changed |= nm_wifi_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_WPS); + if (strcmp (s, "pbc") == 0) + changed |= nm_wifi_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_WPS_PBC); + else if (strcmp (s, "pin") == 0) + changed |= nm_wifi_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_WPS_PIN); + } + g_variant_unref (v); + } + if (g_variant_lookup (properties, "Mode", "&s", &s)) { if (!g_strcmp0 (s, "infrastructure")) changed |= nm_wifi_ap_set_mode (ap, NM_802_11_MODE_INFRA); diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index c9b4772fa0..dd5a4ad12b 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2004 - 2011 Red Hat, Inc. + * Copyright (C) 2004 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ From f87912326cad069939953f50d365b04c15fd41d7 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Fri, 28 Apr 2017 18:52:39 +0200 Subject: [PATCH 07/11] settings-connection: all method to internally supply new secrets It's sort of a very very lightweight version of get_secrets_done_cb() that allows as to add secrets to the connection that didn't come from the agent manager. --- src/settings/nm-settings-connection.c | 25 +++++++++++++++++++++++++ src/settings/nm-settings-connection.h | 6 ++++++ 2 files changed, 31 insertions(+) diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 0cb2920c58..76b0ff5a85 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -974,6 +974,31 @@ get_cmp_flags (NMSettingsConnection *self, /* only needed for logging */ } } +gboolean +nm_settings_connection_new_secrets (NMSettingsConnection *self, + NMConnection *applied_connection, + const char *setting_name, + GVariant *secrets, + GError **error) +{ + if (!nm_settings_connection_has_unmodified_applied_connection (self, applied_connection, + NM_SETTING_COMPARE_FLAG_NONE)) { + g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, + "The connection was modified since activation"); + return FALSE; + } + + if (!nm_connection_update_secrets (NM_CONNECTION (self), setting_name, secrets, error)) + return FALSE; + + update_system_secrets_cache (self); + update_agent_secrets_cache (self, NULL); + nm_settings_connection_commit_changes (self, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + new_secrets_commit_cb, NULL); + + return TRUE; +} + static void get_secrets_done_cb (NMAgentManager *manager, NMAgentManagerCallId call_id_a, diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h index b449e2bd14..c50b4515a3 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/settings/nm-settings-connection.h @@ -163,6 +163,12 @@ typedef void (*NMSettingsConnectionSecretsFunc) (NMSettingsConnection *self, GError *error, gpointer user_data); +gboolean nm_settings_connection_new_secrets (NMSettingsConnection *self, + NMConnection *applied_connection, + const char *setting_name, + GVariant *secrets, + GError **error); + NMSettingsConnectionCallId nm_settings_connection_get_secrets (NMSettingsConnection *self, NMConnection *applied_connection, NMAuthSubject *subject, From 0eb76175047057fc466814632f25bfaf10566c37 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Fri, 28 Apr 2017 19:09:17 +0200 Subject: [PATCH 08/11] wifi: attempt a WPS enroll when secrets are missing If the supplicant returns the credentials, update the PSK in the connection and disable further WPS enrollment attempts. --- src/devices/wifi/nm-device-wifi.c | 151 ++++++++++++++++++++++++++++-- 1 file changed, 144 insertions(+), 7 deletions(-) diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index fd0cd0d9f3..79f8babc5d 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2012 Red Hat, Inc. + * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -119,6 +119,8 @@ typedef struct { NMDeviceWifiCapabilities capabilities; gint32 hw_addr_scan_expire; + + guint wps_timeout_id; } NMDeviceWifiPrivate; struct _NMDeviceWifi @@ -169,6 +171,10 @@ static void supplicant_iface_scan_done_cb (NMSupplicantInterface * iface, gboolean success, NMDeviceWifi * self); +static void supplicant_iface_wps_credentials_cb (NMSupplicantInterface *iface, + GVariant *credentials, + NMDeviceWifi *self); + static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface, GParamSpec * pspec, NMDeviceWifi * self); @@ -267,6 +273,10 @@ supplicant_interface_acquire (NMDeviceWifi *self) NM_SUPPLICANT_INTERFACE_SCAN_DONE, G_CALLBACK (supplicant_iface_scan_done_cb), self); + g_signal_connect (priv->sup_iface, + NM_SUPPLICANT_INTERFACE_WPS_CREDENTIALS, + G_CALLBACK (supplicant_iface_wps_credentials_cb), + self); g_signal_connect (priv->sup_iface, "notify::"NM_SUPPLICANT_INTERFACE_SCANNING, G_CALLBACK (supplicant_iface_notify_scanning_cb), @@ -1747,6 +1757,7 @@ cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect) nm_clear_g_source (&priv->sup_timeout_id); nm_clear_g_source (&priv->link_timeout_id); + nm_clear_g_source (&priv->wps_timeout_id); if (disconnect && priv->sup_iface) nm_supplicant_interface_disconnect (priv->sup_iface); } @@ -1789,9 +1800,19 @@ wifi_secrets_cb (NMActRequest *req, if (error) { _LOGW (LOGD_WIFI, "%s", error->message); - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_NO_SECRETS); + + if (g_error_matches (error, NM_AGENT_MANAGER_ERROR, + NM_AGENT_MANAGER_ERROR_USER_CANCELED)) { + /* Don't wait for WPS timeout on an explicit cancel. */ + nm_clear_g_source (&priv->wps_timeout_id); + } + + if (!priv->wps_timeout_id) { + /* Fail the device only if the WPS period is over too. */ + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_NO_SECRETS); + } } else nm_device_activate_schedule_stage1_device_prepare (device); } @@ -1806,6 +1827,73 @@ wifi_secrets_cancel (NMDeviceWifi *self) nm_assert (!priv->wifi_secrets_id); } +static void +supplicant_iface_wps_credentials_cb (NMSupplicantInterface *iface, + GVariant *credentials, + NMDeviceWifi *self) +{ + NMActRequest *req; + GVariant *val, *secrets = NULL; + const char *array; + char psk[64]; + gsize psk_len = 0; + GError *error = NULL; + + if (nm_device_get_state (NM_DEVICE (self)) != NM_DEVICE_STATE_NEED_AUTH) { + _LOGI (LOGD_DEVICE | LOGD_WIFI, "WPS: The connection can't be updated with credentials"); + return; + } + + _LOGI (LOGD_DEVICE | LOGD_WIFI, "WPS: Updating the connection with credentials"); + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_return_if_fail (NM_IS_ACT_REQUEST (req)); + + val = g_variant_lookup_value (credentials, "Key", G_VARIANT_TYPE_BYTESTRING); + if (val) { + array = g_variant_get_fixed_array (val, &psk_len, 1); + if (psk_len >= 8 || psk_len <= 63) { + memcpy (psk, array, psk_len); + psk[psk_len] = '\0'; + secrets = g_variant_new_parsed ("[{%s, [{%s, <%s>}]}]", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_PSK, psk); + } else + _LOGW (LOGD_DEVICE | LOGD_WIFI, "WPS: Ignoring a PSK of invalid length: %zd", psk_len); + g_variant_unref (val); + } + if (secrets) { + if (nm_settings_connection_new_secrets (nm_act_request_get_settings_connection (req), + nm_act_request_get_applied_connection (req), + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + secrets, &error)) { + wifi_secrets_cancel (self); + nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self)); + } else { + _LOGW (LOGD_DEVICE | LOGD_WIFI, "WPS: Could not update the connection with credentials: %s", error->message); + g_error_free (error); + } + g_variant_unref (secrets); + } +} + +static gboolean +wps_timeout_cb (gpointer user_data) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + priv->wps_timeout_id = 0; + if (!priv->wifi_secrets_id) { + /* Fail only if the secrets are not being requested. */ + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_NO_SECRETS); + } + + return G_SOURCE_REMOVE; +} + static void wifi_secrets_get_secrets (NMDeviceWifi *self, const char *setting_name, @@ -2055,6 +2143,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: nm_clear_g_source (&priv->sup_timeout_id); nm_clear_g_source (&priv->link_timeout_id); + nm_clear_g_source (&priv->wps_timeout_id); /* If this is the initial association during device activation, * schedule the next activation stage. @@ -2222,9 +2311,16 @@ handle_auth_or_fail (NMDeviceWifi *self, NMActRequest *req, gboolean new_secrets) { + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); const char *setting_name; guint32 tries; NMConnection *applied_connection; + NMSettingWirelessSecurity *s_wsec; + const char *bssid = NULL; + NM80211ApFlags ap_flags; + NMSettingWirelessSecurityWpsMethod wps_method; + const char *type; + NMSecretAgentGetSecretsFlags get_secret_flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), FALSE); @@ -2241,6 +2337,44 @@ handle_auth_or_fail (NMDeviceWifi *self, nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); + s_wsec = nm_connection_get_setting_wireless_security (applied_connection); + wps_method = nm_setting_wireless_security_get_wps_method (s_wsec); + + /* Negotiate the WPS method */ + if (wps_method == NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT) + wps_method = NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO; + + if ( wps_method & NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO + && priv->current_ap) { + /* Determine the method to use from AP capabilities. */ + ap_flags = nm_wifi_ap_get_flags (priv->current_ap); + if (ap_flags & NM_802_11_AP_FLAGS_WPS_PBC) + wps_method |= NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC; + if (ap_flags & NM_802_11_AP_FLAGS_WPS_PIN) + wps_method |= NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN; + if ( ap_flags & NM_802_11_AP_FLAGS_WPS + && wps_method == NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO) { + /* The AP doesn't specify which methods are supported. Allow all. */ + wps_method |= NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC; + wps_method |= NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN; + } + } + + if (wps_method & NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC) { + get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE; + type = "pbc"; + } else if (wps_method & NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN) { + type = "pin"; + } else + type = NULL; + + if (type) { + priv->wps_timeout_id = g_timeout_add_seconds (30, wps_timeout_cb, self); + if (priv->current_ap) + bssid = nm_wifi_ap_get_address (priv->current_ap); + nm_supplicant_interface_enroll_wps (priv->sup_iface, type, bssid, NULL); + } + nm_act_request_clear_secrets (req); setting_name = nm_connection_need_secrets (applied_connection, NULL); if (!setting_name) { @@ -2248,9 +2382,9 @@ handle_auth_or_fail (NMDeviceWifi *self, return FALSE; } - wifi_secrets_get_secrets (self, setting_name, - NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION - | (new_secrets ? NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW : 0)); + if (new_secrets) + get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; + wifi_secrets_get_secrets (self, setting_name, get_secret_flags); g_object_set_qdata (G_OBJECT (applied_connection), wireless_secrets_tries_quark (), GUINT_TO_POINTER (++tries)); return TRUE; } @@ -2466,6 +2600,8 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) s_wireless = nm_connection_get_setting_wireless (connection); g_return_val_if_fail (s_wireless, NM_ACT_STAGE_RETURN_FAILURE); + nm_supplicant_interface_cancel_wps (priv->sup_iface); + mode = nm_setting_wireless_get_mode (s_wireless); if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) == 0) priv->mode = NM_802_11_MODE_INFRA; @@ -2614,6 +2750,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) nm_clear_g_source (&priv->sup_timeout_id); nm_clear_g_source (&priv->link_timeout_id); + nm_clear_g_source (&priv->wps_timeout_id); req = nm_device_get_act_request (device); g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); From 99c112a4936c469a681e46c6ca92753a721eb92c Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 24 Apr 2017 15:23:19 +0200 Subject: [PATCH 09/11] ifcfg-rh: save/restore WPS properties --- libnm-core/nm-setting-wireless-security.c | 10 +++++++++- src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 10 ++++++++++ src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 8 ++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c index 6fdab41b38..cbd3ad75e1 100644 --- a/libnm-core/nm-setting-wireless-security.c +++ b/libnm-core/nm-setting-wireless-security.c @@ -1847,6 +1847,15 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting * * Since: 1.10 **/ + /* ---ifcfg-rh--- + * property: wps-method + * variable: WPS_METHOD + * description: Used to control the WPS methods to be used + * Valid values are "default", "auto", "disabled", "pin" and "pbc". + * If omitted, whatver the AP announces is used. + * example: WPS_METHOD=disabled, WPS_METHOD="pin pbc" + * ---end--- + */ g_object_class_install_property (object_class, PROP_WPS_METHOD, g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, "", "", @@ -1855,5 +1864,4 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); - } 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 5dc42e28bb..17a0467de7 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -3339,6 +3339,16 @@ make_wpa_setting (shvarFile *ifcfg, if (!wpa_psk && !wpa_eap && !ieee8021x) goto error; /* Not WPA or Dynamic WEP */ + /* WPS */ + i_val = NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT; + if (!svGetValueEnum (ifcfg, "WPS_METHOD", + nm_setting_wireless_security_wps_method_get_type (), + &i_val, error)) + goto error; + g_object_set (wsec, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, (guint) i_val, + NULL); + /* Pairwise and Group ciphers (only relevant for WPA/RSN) */ if (wpa_psk || wpa_eap) { fill_wpa_ciphers (ifcfg, wsec, FALSE, 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 28bea262ed..1358cf4abc 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -527,6 +527,7 @@ write_wireless_security_setting (NMConnection *connection, const char *key_mgmt, *auth_alg, *key, *proto, *cipher; const char *psk = NULL; gboolean wep = FALSE, wpa = FALSE, dynamic_wep = FALSE; + NMSettingWirelessSecurityWpsMethod wps_method; char *tmp; guint32 i, num; GString *str; @@ -580,6 +581,13 @@ write_wireless_security_setting (NMConnection *connection, } } + /* WPS */ + wps_method = nm_setting_wireless_security_get_wps_method (s_wsec); + if (wps_method == NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT) + svUnsetValue (ifcfg, "WPS_METHOD"); + else + svSetValueEnum (ifcfg, "WPS_METHOD", nm_setting_wireless_security_wps_method_get_type (), wps_method); + /* WEP keys */ /* Clear any default key */ From 2899bb34293cb96796bde5602ddc779560a7284d Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 24 Apr 2017 14:39:46 +0200 Subject: [PATCH 10/11] cli: add support for the WPS property --- clients/common/nm-meta-setting-desc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index c2900c4265..ff40b54720 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -1035,7 +1035,6 @@ fail: max = property_info->property_typ_data->subtype.gobject_enum.max; } } - valid_all = nm_utils_enum_get_values (gtype, min, max); valid_str = g_strjoinv (",", (char **) valid_all); g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, @@ -6995,6 +6994,14 @@ static const NMMetaPropertyInfo *const property_infos_WIRELESS_SECURITY[] = { PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, .property_type = &_pt_gobject_secret_flags, ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_wireless_security_wps_method_get_type, + ), + ), + ), NULL }; From 1194641afe6a8a18491c2c24120eed5d5eba43b7 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Fri, 12 May 2017 16:05:28 +0200 Subject: [PATCH 11/11] dbus/secret-agent: add a flag indicating WPS PBC is active The agents may used this to learn that WPS PBC enrollment is active and suggest that user pushes a button on the router instead of supplying a network key. --- libnm-core/nm-dbus-interface.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 7130a92609..92c8a359d8 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -720,6 +720,9 @@ typedef enum { * initiated by user-requested action via the D-Bus interface, as opposed to * automatically initiated by NetworkManager in response to (for example) scan * results or carrier changes. + * @NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE: indicates that WPS enrollment + * is active with PBC method. The agent may suggest that the user pushes a button + * on the router instead of supplying a PSK. * @NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM: Internal flag, not part of * the D-Bus API. * @NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS: Internal flag, not part of @@ -732,6 +735,7 @@ typedef enum { /*< flags >*/ NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 0x1, NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 0x2, NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED = 0x4, + NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE = 0x8, /* Internal to NM; not part of the D-Bus API */ NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM = 0x80000000,