On Tue, 2017-12-05 at 16:26 +0100, Andrew Zaborowski wrote: > Add the PSK agent support to support PSK networks. Note that the PSK > itself will be saved by IWD on the first successful connection to the > network and will not be updated when it is changed by the user on the > NM > side, this still needs fixing like a bunch of other problems. > --- > src/devices/wifi/nm-device-iwd.c | 27 +++++ > src/devices/wifi/nm-device-iwd.h | 2 + > src/devices/wifi/nm-iwd-manager.c | 205 > +++++++++++++++++++++++++++++++++++++- > 3 files changed, 233 insertions(+), 1 deletion(-) > > diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm- > device-iwd.c > index e2be47bcb..b4cb87d14 100644 > --- a/src/devices/wifi/nm-device-iwd.c > +++ b/src/devices/wifi/nm-device-iwd.c > @@ -1766,6 +1766,33 @@ nm_device_iwd_set_dbus_object (NMDeviceIwd > *self, GDBusObject *object) > send_disconnect (self); > } > > +const gchar * > +nm_device_iwd_agent_psk_query (NMDeviceIwd *self) > +{ > + NMActRequest *req; > + NMConnection *connection; > + NMSettingWireless *s_wireless; > + NMSettingWirelessSecurity *s_wireless_sec; > + > + req = nm_device_get_act_request (NM_DEVICE (self)); > + if (!req) > + return NULL; > + > + connection = nm_act_request_get_applied_connection (req); > + if (!connection) > + return NULL; > + > + s_wireless = nm_connection_get_setting_wireless > (connection); > + if (!s_wireless) > + return NULL; > + > + s_wireless_sec = nm_connection_get_setting_wireless_security > (connection); > + if (!s_wireless_sec) > + return NULL; > + > + return nm_setting_wireless_security_get_psk > (s_wireless_sec); > +} > + > /******************************************************************* > **********/ > > static void > diff --git a/src/devices/wifi/nm-device-iwd.h b/src/devices/wifi/nm- > device-iwd.h > index 34cdad0d0..332f4282c 100644 > --- a/src/devices/wifi/nm-device-iwd.h > +++ b/src/devices/wifi/nm-device-iwd.h > @@ -55,4 +55,6 @@ NMDevice *nm_device_iwd_new (const char *iface, > NMDeviceWifiCapabilities capabil > > void nm_device_iwd_set_dbus_object (NMDeviceIwd *device, GDBusObject > *object); > > +const gchar *nm_device_iwd_agent_psk_query (NMDeviceIwd *device); > + > #endif /* __NETWORKMANAGER_DEVICE_IWD_H__ */ > diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm- > iwd-manager.c > index 7561b17b3..a27ecd388 100644 > --- a/src/devices/wifi/nm-iwd-manager.c > +++ b/src/devices/wifi/nm-iwd-manager.c > @@ -35,6 +35,8 @@ typedef struct { > GCancellable *cancellable; > gboolean running; > GDBusObjectManager *object_manager; > + guint agent_id; > + gchar *agent_path; > } NMIwdManagerPrivate; > > struct _NMIWDManager { > @@ -73,6 +75,165 @@ G_DEFINE_TYPE (NMIwdManager, nm_iwd_manager, > G_TYPE_OBJECT) > /******************************************************************* > **********/ > > static void > +psk_agent_dbus_method_cb (GDBusConnection *connection, > + const gchar *sender, const gchar > *object_path, > + const gchar *interface_name, const gchar > *method_name, > + GVariant *parameters, > + GDBusMethodInvocation *invocation, > + gpointer user_data) > +{ > + NMIwdManager *self = user_data; > + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE > (self); > + GDBusObjectManagerClient *omc = G_DBUS_OBJECT_MANAGER_CLIENT > (priv->object_manager); > + const gchar *network_path, *device_path, *ifname; > + gs_unref_object GDBusInterface *network = NULL, *device_obj > = NULL; > + gs_unref_variant GVariant *value = NULL; > + gint ifindex; > + NMManager *manager; > + NMDevice *device; > + const gchar *psk; > + > + /* Be paranoid and check the sender address */ > + if (!nm_streq0 (g_dbus_object_manager_client_get_name_owner > (omc), sender)) > + goto return_error; > + > + g_variant_get (parameters, "(&o)", &network_path); > + > + network = g_dbus_object_manager_get_interface (priv- > >object_manager, > + network_path, > + IWD_NETWORK_I > NTERFACE); > + value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY > (network), "Device"); > + device_path = g_variant_get_string (value, NULL); > + > + if (!device_path) { > + _LOGE ("Device not cached for network %s in IWD > Agent request", > + network_path); > + goto return_error; > + } > + > + device_obj = g_dbus_object_manager_get_interface (priv- > >object_manager, > + device_path, > + IWD_DEVICE_INT > ERFACE); > + g_variant_unref (value); > + value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY > (device_obj), "Name"); > + ifname = g_variant_get_string (value, NULL); > + > + if (!ifname) { > + _LOGE ("Name not cached for device %s in IWD Agent > request", > + device_path); > + goto return_error; > + } > + > + ifindex = if_nametoindex (ifname); > + if (!ifindex) { > + _LOGE ("if_nametoindex failed for Name %s for Device > at %s: %i", > + ifname, device_path, errno); > + goto return_error; > + } > + > + manager = nm_manager_get (); > + > + device = nm_manager_get_device_by_ifindex (manager, > ifindex); > + if (!NM_IS_DEVICE_IWD (device)) { > + _LOGE ("IWD device named %s is not a Wifi device in > IWD Agent request", > + ifname); > + goto return_error; > + } > + > + psk = nm_device_iwd_agent_psk_query (NM_DEVICE_IWD > (device)); > + if (!psk) { > + _LOGW ("Device %s had no PSK for the IWD Agent", > ifname); > + goto return_error; > + } > + > + _LOGI ("Sending the PSK to the IWD Agent for device %s", > ifname); > + g_dbus_method_invocation_return_value (invocation, > + g_variant_new ("(s)", > psk)); > + return; > + > +return_error: > + /* IWD doesn't look at the specific error */ > + g_dbus_method_invocation_return_error_literal (invocation, > NM_DEVICE_ERROR, > + NM_DEVICE_ERR > OR_INVALID_CONNECTION, > + "No PSK > available for this connection"); > +} > + > + > +static guint > +psk_agent_export (GDBusConnection *connection, gpointer user_data, > + gchar **agent_path, GError **error) > +{ > + static const GDBusArgInfo request_passphrase_arg_network = { > + -1, > + (gchar *) "network", > + (gchar *) "o", > + NULL, > + }; > + static const GDBusArgInfo *const > request_passphrase_in_args[] = { > + &request_passphrase_arg_network, > + NULL, > + }; > + static const GDBusArgInfo request_passphrase_arg_passphrase > = { > + -1, > + (gchar *) "passphrase", > + (gchar *) "s", > + NULL, > + }; > + static const GDBusArgInfo *const > request_passphrase_out_args[] = { > + &request_passphrase_arg_passphrase, > + NULL, > + }; > + static const GDBusMethodInfo request_passphrase_info = { > + -1, > + (gchar *) "RequestPassphrase", > + (GDBusArgInfo **) &request_passphrase_in_args, > + (GDBusArgInfo **) &request_passphrase_out_args, > + NULL, > + }; > + static const GDBusMethodInfo *const method_info[] = { > + &request_passphrase_info, > + NULL, > + }; > + static GDBusInterfaceInfo interface_info = { > + -1, > + (gchar *) "net.connman.iwd.Agent", > + (GDBusMethodInfo **) &method_info, > + NULL, > + NULL, > + NULL, > + }; > + static GDBusInterfaceVTable vtable = { > + psk_agent_dbus_method_cb, > + NULL, > + NULL, > + }; > + > + gchar path[50]; > + unsigned int rnd; > + guint id; > + > + if (nm_utils_read_urandom (&rnd, sizeof (rnd)) < 0) { > + g_set_error_literal (error, > + NM_DEVICE_ERROR, > + NM_DEVICE_ERROR_FAILED, > + "Can't read urandom."); > + return 0; > + } > + > + nm_sprintf_buf (path, "/agent/%u", rnd); > + > + id = g_dbus_connection_register_object (connection, path, > + &interface_info, > &vtable, > + user_data, NULL, > error); > + > + if (id) > + *agent_path = g_strdup (path); > + return id; > +} > + > +/******************************************************************* > **********/ > + > +static void > set_device_dbus_object (NMIwdManager *self, GDBusInterface > *interface, > GDBusObject *object) > { > @@ -193,6 +354,23 @@ name_owner_changed (GObject *object, GParamSpec > *pspec, gpointer user_data) > object_added (self, G_DBUS_OBJECT (iter- > >data)); > > g_list_free_full (objects, g_object_unref); > + > + if (priv->agent_id) { > + GDBusInterface *agent_manager; > + > + agent_manager = > g_dbus_object_manager_get_interface (object_manager, > + > "/", > + > IWD_AGENT_MANAGER_INTERFACE); > + > + /* Register our agent */ > + g_dbus_proxy_call (G_DBUS_PROXY > (agent_manager), > + "RegisterAgent", > + g_variant_new ("(o)", > priv->agent_path), > + G_DBUS_CALL_FLAGS_NONE, > -1, > + NULL, NULL, NULL); > + > + g_object_unref (agent_manager); > + } > } else { > NMManager *manager = nm_manager_get (); > const GSList *devices, *iter; > @@ -292,6 +470,14 @@ got_object_manager (GObject *object, > GAsyncResult *result, gpointer user_data) > > connection = g_dbus_object_manager_client_get_connection > (G_DBUS_OBJECT_MANAGER_CLIENT (object_manager)); > > + priv->agent_id = psk_agent_export (connection, self, > + &priv->agent_path, > &error); > + if (!priv->agent_id) { > + _LOGE ("failed to export the IWD Agent: PSK/8021x > WiFi networks will not work: %s", > + NM_G_ERROR_MSG (error)); > + g_clear_error (&error); > + } > + > name_owner_changed (G_OBJECT (object_manager), NULL, self); > > g_signal_connect (manager, "device-added", > @@ -331,8 +517,25 @@ dispose (GObject *object) > NMIwdManager *self = (NMIwdManager *) object; > NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE > (self); > > - if (priv->object_manager) > + if (priv->object_manager) { > + if (priv->agent_id) { > + GDBusConnection *connection; > + GDBusObjectManagerClient *omc = > G_DBUS_OBJECT_MANAGER_CLIENT (priv->object_manager); > + > + /* No need to unregister the agent as IWD > will detect > + * our DBus connection being closed. > + */ > + > + connection = > g_dbus_object_manager_client_get_connection (omc); > + > + g_dbus_connection_unregister_object > (connection, priv->agent_id); > + priv->agent_id = 0; > + } > + > g_clear_object (&priv->object_manager); > + } > + > + g_free (priv->agent_path);
dispose() must be re-entrant. Meaning, you should not leave dangling pointers. For example, use nm_clear_g_free (&priv->agent_path). > > nm_clear_g_cancellable (&priv->cancellable); >
signature.asc
Description: This is a digitally signed message part
_______________________________________________ networkmanager-list mailing list networkmanager-list@gnome.org https://mail.gnome.org/mailman/listinfo/networkmanager-list