diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c index b447da4ccb..efbc33fbc8 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/devices/wifi/nm-device-iwd.c @@ -992,6 +992,127 @@ scanning_prohibited (NMDeviceIwd *self, gboolean periodic) return !priv->can_scan; } +/* + * try_reply_agent_request + * + * Check if the connection settings already have the secrets corresponding + * to the IWD agent method that was invoked. If they do, send the method reply + * with the appropriate secrets. Otherwise return the missing secret's setting + * name and key so the caller can send a NM secrets request with this data. + * Return TRUE in either case, return FALSE if an error is detected. + */ +static gboolean +try_reply_agent_request (NMDeviceIwd *self, + NMConnection *connection, + GDBusMethodInvocation *invocation, + const gchar **setting_name, + const gchar **setting_key, + gboolean *replied) +{ + const gchar *method_name = g_dbus_method_invocation_get_method_name (invocation); + NMSettingWirelessSecurity *s_wireless_sec; + NMSetting8021x *s_8021x; + + s_wireless_sec = nm_connection_get_setting_wireless_security (connection); + s_8021x = nm_connection_get_setting_802_1x (connection); + + *replied = FALSE; + + if (!strcmp (method_name, "RequestPassphrase")) { + const gchar *psk; + + if (!s_wireless_sec) + return FALSE; + + psk = nm_setting_wireless_security_get_psk (s_wireless_sec); + if (psk) { + _LOGD (LOGD_DEVICE | LOGD_WIFI, + "Returning the PSK to the IWD Agent"); + + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(s)", psk)); + *replied = TRUE; + return TRUE; + } + + *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; + *setting_key = NM_SETTING_WIRELESS_SECURITY_PSK; + return TRUE; + } else if (!strcmp (method_name, "RequestPrivateKeyPassphrase")) { + const gchar *password; + + if (!s_8021x) + return FALSE; + + password = nm_setting_802_1x_get_private_key_password (s_8021x); + if (password) { + _LOGD (LOGD_DEVICE | LOGD_WIFI, + "Returning the private key password to the IWD Agent"); + + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(s)", password)); + *replied = TRUE; + return TRUE; + } + + *setting_name = NM_SETTING_802_1X_SETTING_NAME; + *setting_key = NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD; + return TRUE; + } else if (!strcmp (method_name, "RequestUserNameAndPassword")) { + const gchar *identity, *password; + + if (!s_8021x) + return FALSE; + + identity = nm_setting_802_1x_get_identity (s_8021x); + password = nm_setting_802_1x_get_password (s_8021x); + if (identity && password) { + _LOGD (LOGD_DEVICE | LOGD_WIFI, + "Returning the username and password to the IWD Agent"); + + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(ss)", identity, password)); + *replied = TRUE; + return TRUE; + } + + *setting_name = NM_SETTING_802_1X_SETTING_NAME; + if (!identity) + *setting_key = NM_SETTING_802_1X_IDENTITY; + else + *setting_key = NM_SETTING_802_1X_PASSWORD; + return TRUE; + } else if (!strcmp (method_name, "RequestUserPassword")) { + const gchar *password; + + if (!s_8021x) + return FALSE; + + password = nm_setting_802_1x_get_password (s_8021x); + if (password) { + _LOGD (LOGD_DEVICE | LOGD_WIFI, + "Returning the user password to the IWD Agent"); + + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(s)", password)); + *replied = TRUE; + return TRUE; + } + + *setting_name = NM_SETTING_802_1X_SETTING_NAME; + *setting_key = NM_SETTING_802_1X_PASSWORD; + return TRUE; + } else + return FALSE; +} + +static void +wifi_secrets_get_one (NMDeviceIwd *self, + const char *setting_name, + NMSecretAgentGetSecretsFlags flags, + const char *setting_key, + GDBusMethodInvocation *invocation); + static void wifi_secrets_cb (NMActRequest *req, NMActRequestGetSecretsCallId *call_id, @@ -1002,9 +1123,10 @@ wifi_secrets_cb (NMActRequest *req, NMDeviceIwd *self; NMDeviceIwdPrivate *priv; NMDevice *device; - NMSettingWirelessSecurity *s_wireless_sec; - const gchar *psk; GDBusMethodInvocation *invocation; + const gchar *setting_name; + const gchar *setting_key; + gboolean replied; nm_utils_user_data_unpack (user_data, &self, &invocation); @@ -1035,22 +1157,24 @@ wifi_secrets_cb (NMActRequest *req, goto secrets_error; } - s_wireless_sec = nm_connection_get_setting_wireless_security (nm_act_request_get_applied_connection (req)); - if (!s_wireless_sec) + if (!try_reply_agent_request (self, nm_act_request_get_applied_connection (req), + invocation, &setting_name, &setting_key, + &replied)) goto secrets_error; - psk = nm_setting_wireless_security_get_psk (s_wireless_sec); - if (!psk) - goto secrets_error; + if (replied) { + /* Change state back to what it was before NEED_AUTH */ + nm_device_state_changed (device, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); + return; + } - _LOGD (LOGD_DEVICE | LOGD_WIFI, - "Returning a new PSK to the IWD Agent"); - - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(s)", psk)); - - /* Change state back to what it was before NEED_AUTH */ - nm_device_state_changed (device, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); + /* Request further secrets if we still need something */ + wifi_secrets_get_one (self, + setting_name, + NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION + | NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW, + setting_key, + invocation); return; secrets_error: @@ -1066,10 +1190,11 @@ secrets_error: } static void -wifi_secrets_get_secrets (NMDeviceIwd *self, - const char *setting_name, - NMSecretAgentGetSecretsFlags flags, - GDBusMethodInvocation *invocation) +wifi_secrets_get_one (NMDeviceIwd *self, + const char *setting_name, + NMSecretAgentGetSecretsFlags flags, + const char *setting_key, + GDBusMethodInvocation *invocation) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); NMActRequest *req; @@ -1083,7 +1208,7 @@ wifi_secrets_get_secrets (NMDeviceIwd *self, TRUE, setting_name, flags, - NULL, + setting_key, wifi_secrets_cb, nm_utils_user_data_pack (self, invocation)); } @@ -1722,38 +1847,34 @@ nm_device_iwd_set_dbus_object (NMDeviceIwd *self, GDBusObject *object) } gboolean -nm_device_iwd_agent_psk_query (NMDeviceIwd *self, - GDBusMethodInvocation *invocation) +nm_device_iwd_agent_query (NMDeviceIwd *self, + GDBusMethodInvocation *invocation) { NMActRequest *req; - NMSettingWirelessSecurity *s_wireless_sec; - const gchar *psk; + const gchar *setting_name; + const gchar *setting_key; + gboolean replied; req = nm_device_get_act_request (NM_DEVICE (self)); if (!req) return FALSE; - s_wireless_sec = nm_connection_get_setting_wireless_security (nm_act_request_get_applied_connection (req)); - if (!s_wireless_sec) + if (!try_reply_agent_request (self, nm_act_request_get_applied_connection (req), + invocation, &setting_name, &setting_key, + &replied)) return FALSE; - psk = nm_setting_wireless_security_get_psk (s_wireless_sec); - if (psk) { - _LOGD (LOGD_DEVICE | LOGD_WIFI, - "Returning the PSK to the IWD Agent"); - - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(s)", psk)); + if (replied) return TRUE; - } nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NO_SECRETS); - wifi_secrets_get_secrets (self, - NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, - NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION - | NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW, - invocation); + wifi_secrets_get_one (self, + setting_name, + NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION + | NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW, + setting_key, + invocation); return TRUE; } diff --git a/src/devices/wifi/nm-device-iwd.h b/src/devices/wifi/nm-device-iwd.h index a4253f5217..825123b1d8 100644 --- a/src/devices/wifi/nm-device-iwd.h +++ b/src/devices/wifi/nm-device-iwd.h @@ -51,8 +51,8 @@ NMDevice *nm_device_iwd_new (const char *iface, NMDeviceWifiCapabilities capabil void nm_device_iwd_set_dbus_object (NMDeviceIwd *device, GDBusObject *object); -gboolean nm_device_iwd_agent_psk_query (NMDeviceIwd *device, - GDBusMethodInvocation *invocation); +gboolean nm_device_iwd_agent_query (NMDeviceIwd *device, + GDBusMethodInvocation *invocation); const CList *_nm_device_iwd_get_aps (NMDeviceIwd *self); diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c index 39db3a04cd..daa796cbb9 100644 --- a/src/devices/wifi/nm-iwd-manager.c +++ b/src/devices/wifi/nm-iwd-manager.c @@ -84,12 +84,12 @@ 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) +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); @@ -104,7 +104,10 @@ psk_agent_dbus_method_cb (GDBusConnection *connection, if (!nm_streq0 (g_dbus_object_manager_client_get_name_owner (omc), sender)) goto return_error; - g_variant_get (parameters, "(&o)", &network_path); + if (!strcmp (method_name, "RequestUserPassword")) + g_variant_get (parameters, "(&os)", &network_path, NULL); + else + g_variant_get (parameters, "(&o)", &network_path); network = g_dbus_object_manager_get_interface (priv->object_manager, network_path, @@ -145,7 +148,7 @@ psk_agent_dbus_method_cb (GDBusConnection *connection, goto return_error; } - if (nm_device_iwd_agent_psk_query (NM_DEVICE_IWD (device), invocation)) + if (nm_device_iwd_agent_query (NM_DEVICE_IWD (device), invocation)) return; _LOGE ("Device %s did not handle the IWD Agent request", ifname); @@ -154,56 +157,59 @@ return_error: /* IWD doesn't look at the specific error */ g_dbus_method_invocation_return_error_literal (invocation, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, - "No PSK available for this connection"); + "Secrets not available for this connection"); } +static const GDBusInterfaceInfo iwd_agent_iface_info = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( + "net.connman.iwd.Agent", + .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( + NM_DEFINE_GDBUS_METHOD_INFO ( + "RequestPassphrase", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("network", "o"), + ), + .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("passphrase", "s"), + ), + ), + NM_DEFINE_GDBUS_METHOD_INFO ( + "RequestPrivateKeyPassphrase", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("network", "o"), + ), + .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("passphrase", "s"), + ), + ), + NM_DEFINE_GDBUS_METHOD_INFO ( + "RequestUserNameAndPassword", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("network", "o"), + ), + .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("user", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("password", "s"), + ), + ), + NM_DEFINE_GDBUS_METHOD_INFO ( + "RequestUserPassword", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("network", "o"), + NM_DEFINE_GDBUS_ARG_INFO ("user", "s"), + ), + .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("password", "s"), + ), + ), + ), +); + static guint -psk_agent_export (GDBusConnection *connection, gpointer user_data, +iwd_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, + static const GDBusInterfaceVTable vtable = { + .method_call = agent_dbus_method_cb, }; gchar path[50]; @@ -221,8 +227,8 @@ psk_agent_export (GDBusConnection *connection, gpointer user_data, nm_sprintf_buf (path, "/agent/%u", rnd); id = g_dbus_connection_register_object (connection, path, - &interface_info, &vtable, - user_data, NULL, error); + NM_UNCONST_PTR (GDBusInterfaceInfo, &iwd_agent_iface_info), + &vtable, user_data, NULL, error); if (id) *agent_path = g_strdup (path); @@ -549,7 +555,7 @@ 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_id = iwd_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",