summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2017-05-15 13:00:13 +0200
committerLubomir Rintel <lkundrak@v3.sk>2017-05-15 13:00:13 +0200
commitefafc98147c202d3a754823e2c8a2cc305314a9a (patch)
tree19b1b3fa0b9ec2f2820b4254b26affbeedfab0db
parentfb2ef01d85b4a12295f162b5e116855dbc5c3d8d (diff)
parent1194641afe6a8a18491c2c24120eed5d5eba43b7 (diff)
downloadNetworkManager-efafc98147c202d3a754823e2c8a2cc305314a9a.tar.gz
merge: branch 'lr/wps2'
https://bugzilla.gnome.org/show_bug.cgi?id=781336
-rw-r--r--clients/common/nm-meta-setting-desc.c9
-rw-r--r--clients/common/settings-docs.c.in1
-rw-r--r--libnm-core/nm-dbus-interface.h12
-rw-r--r--libnm-core/nm-setting-wireless-security.c78
-rw-r--r--libnm-core/nm-setting-wireless-security.h26
-rw-r--r--libnm/libnm.ver2
-rw-r--r--src/devices/wifi/nm-device-wifi.c151
-rw-r--r--src/devices/wifi/nm-wifi-ap.c22
-rw-r--r--src/devices/wifi/nm-wifi-ap.h3
-rw-r--r--src/settings/nm-settings-connection.c25
-rw-r--r--src/settings/nm-settings-connection.h6
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c17
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c8
-rw-r--r--src/supplicant/nm-supplicant-interface.c177
-rw-r--r--src/supplicant/nm-supplicant-interface.h11
15 files changed, 525 insertions, 23 deletions
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
};
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-dbus-interface.h b/libnm-core/nm-dbus-interface.h
index 8abc91bbf8..92c8a359d8 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;
/**
@@ -714,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
@@ -726,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,
diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c
index 8ddefba2f2..cbd3ad75e1 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,34 @@ 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
+ **/
+ /* ---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, "", "",
+ 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;
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);
@@ -268,6 +274,10 @@ supplicant_interface_acquire (NMDeviceWifi *self)
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),
self);
@@ -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);
}
@@ -1807,6 +1828,73 @@ wifi_secrets_cancel (NMDeviceWifi *self)
}
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,
NMSecretAgentGetSecretsFlags flags)
@@ -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);
diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c
index c45eaafa93..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.
*/
@@ -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)
{
@@ -782,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 5e64087cca..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.
*/
@@ -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,
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,
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..17a0467de7 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 ());
@@ -3338,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);
@@ -3371,12 +3382,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)
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 */
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__ */