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 [email protected] https://mail.gnome.org/mailman/listinfo/networkmanager-list
