diff options
| author | Michael Biebl <biebl@debian.org> | 2018-07-01 20:58:23 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-07-01 20:58:23 +0200 |
| commit | 429393567647935d9123e21fd27a7529d50255eb (patch) | |
| tree | b5a99bf0cbbe77fccd7fee81caf71915ccf9eb96 /src/devices/wifi/nm-device-iwd.c | |
| parent | 069cb5c3a525ebcc19cc2927964258acaca87b13 (diff) | |
New upstream version 1.12.0 upstream/1.12.0
Diffstat (limited to 'src/devices/wifi/nm-device-iwd.c')
| -rw-r--r-- | src/devices/wifi/nm-device-iwd.c | 290 |
1 files changed, 197 insertions, 93 deletions
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c index d28fcdbd..7667816a 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/devices/wifi/nm-device-iwd.c @@ -73,7 +73,6 @@ typedef struct { GCancellable * cancellable; NMDeviceWifiCapabilities capabilities; NMActRequestGetSecretsCallId *wifi_secrets_id; - GDBusMethodInvocation *secrets_request; guint periodic_scan_id; bool enabled:1; bool can_scan:1; @@ -379,14 +378,6 @@ wifi_secrets_cancel (NMDeviceIwd *self) if (priv->wifi_secrets_id) nm_act_request_cancel_secrets (NULL, priv->wifi_secrets_id); nm_assert (!priv->wifi_secrets_id); - - if (priv->secrets_request) { - g_dbus_method_invocation_return_error_literal (priv->secrets_request, NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "NM secrets request cancelled"); - priv->secrets_request = NULL; - } - } static void @@ -545,7 +536,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) return FALSE; mode = nm_setting_wireless_get_mode (s_wireless); - if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0) + if (mode && g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0) return FALSE; /* 8021x networks can only be used if they've been provisioned on the IWD side and @@ -575,7 +566,7 @@ check_connection_available (NMDevice *device, /* Only Infrastrusture mode at this time */ mode = nm_setting_wireless_get_mode (s_wifi); - if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0) + if (mode && g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0) return FALSE; /* Hidden SSIDs not supported yet */ @@ -630,7 +621,7 @@ complete_connection (NMDevice *device, mode = s_wifi ? nm_setting_wireless_get_mode (s_wifi) : NULL; - if (s_wifi && !nm_streq0 (mode, NM_SETTING_WIRELESS_MODE_INFRA)) { + if (mode && !nm_streq0 (mode, NM_SETTING_WIRELESS_MODE_INFRA)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, @@ -806,7 +797,7 @@ can_auto_connect (NMDevice *device, /* Only Infrastrusture mode */ mode = nm_setting_wireless_get_mode (s_wifi); - if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0) + if (mode && g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0) return FALSE; /* Don't autoconnect to networks that have been tried at least once @@ -1001,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, @@ -1008,25 +1120,33 @@ wifi_secrets_cb (NMActRequest *req, GError *error, gpointer user_data) { - NMDevice *device = user_data; - NMDeviceIwd *self = user_data; + NMDeviceIwd *self; NMDeviceIwdPrivate *priv; - NMSettingWirelessSecurity *s_wireless_sec; - const gchar *psk; + NMDevice *device; + GDBusMethodInvocation *invocation; + const gchar *setting_name; + const gchar *setting_key; + gboolean replied; + NMSecretAgentGetSecretsFlags get_secret_flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; + + nm_utils_user_data_unpack (user_data, &self, &invocation); g_return_if_fail (NM_IS_DEVICE_IWD (self)); - g_return_if_fail (NM_IS_ACT_REQUEST (req)); priv = NM_DEVICE_IWD_GET_PRIVATE (self); + device = NM_DEVICE (self); g_return_if_fail (priv->wifi_secrets_id == call_id); priv->wifi_secrets_id = NULL; - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_dbus_method_invocation_return_error_literal (invocation, NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "NM secrets request cancelled"); return; + } - g_return_if_fail (priv->secrets_request); g_return_if_fail (req == nm_device_get_act_request (device)); g_return_if_fail (nm_act_request_get_settings_connection (req) == s_connection); @@ -1038,32 +1158,30 @@ 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) - goto secrets_error; - - psk = nm_setting_wireless_security_get_psk (s_wireless_sec); - if (!psk) + if (!try_reply_agent_request (self, nm_act_request_get_applied_connection (req), + invocation, &setting_name, &setting_key, + &replied)) goto secrets_error; - _LOGD (LOGD_DEVICE | LOGD_WIFI, - "Returning a new PSK to the IWD Agent"); + 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; + } - g_dbus_method_invocation_return_value (priv->secrets_request, - g_variant_new ("(s)", psk)); - priv->secrets_request = NULL; + if (nm_settings_connection_get_timestamp (nm_act_request_get_settings_connection (req), + NULL)) + get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; - /* 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, get_secret_flags, + setting_key, invocation); return; secrets_error: - if (priv->secrets_request) { - g_dbus_method_invocation_return_error_literal (priv->secrets_request, NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "NM secrets request failed"); - priv->secrets_request = NULL; - } + g_dbus_method_invocation_return_error_literal (invocation, NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "NM secrets request failed"); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, @@ -1073,9 +1191,11 @@ secrets_error: } static void -wifi_secrets_get_secrets (NMDeviceIwd *self, - const char *setting_name, - NMSecretAgentGetSecretsFlags flags) +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; @@ -1089,9 +1209,9 @@ wifi_secrets_get_secrets (NMDeviceIwd *self, TRUE, setting_name, flags, - NULL, + setting_key, wifi_secrets_cb, - self); + nm_utils_user_data_pack (self, invocation)); } static void @@ -1219,15 +1339,13 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) ap = ap_path ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) : NULL; if (!ap) { ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection); - - /* TODO: assuming hidden networks aren't supported do we need - * to consider the case of APs that are not in the scan list - * yet, for which nm-device-wifi.c creates the temporary fake - * AP object? - */ + if (!ap) { + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); + nm_dbus_object_get_path (NM_DBUS_OBJECT (ap))); } set_current_ap (self, ap, FALSE); @@ -1316,29 +1434,11 @@ out: } static guint32 -get_configured_mtu (NMDevice *device, gboolean *out_is_user_config) +get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) { - NMSettingWireless *setting; - gint64 mtu_default; - guint32 mtu; - - nm_assert (NM_IS_DEVICE (device)); - nm_assert (out_is_user_config); - - setting = NM_SETTING_WIRELESS (nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRELESS)); - if (!setting) - g_return_val_if_reached (0); - - mtu = nm_setting_wireless_get_mtu (setting); - if (mtu == 0) { - mtu_default = nm_device_get_configured_mtu_from_connection_default (device, "wifi.mtu"); - if (mtu_default >= 0) { - *out_is_user_config = TRUE; - return (guint32) mtu_default; - } - } - *out_is_user_config = (mtu != 0); - return mtu; + return nm_device_get_configured_mtu_from_connection (device, + NM_TYPE_SETTING_WIRELESS, + out_source); } static gboolean @@ -1748,40 +1848,44 @@ 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) { - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); NMActRequest *req; - NMSettingWirelessSecurity *s_wireless_sec; - const gchar *psk; + const gchar *setting_name; + const gchar *setting_key; + gboolean replied; + NMSecretAgentGetSecretsFlags get_secret_flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; 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; - } + + /* Normally require new secrets every time IWD asks for them. + * IWD only queries us if it has not saved the secrets (e.g. by policy) + * or a previous attempt has failed with current secrets so it wants + * a fresh set. However if this is a new connection it may include + * all of the needed settings already so allow using these, too. + * Connection timestamp is set after activation or after first + * activation failure (to 0). + */ + if (nm_settings_connection_get_timestamp (nm_act_request_get_settings_connection (req), + NULL)) + get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; 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); + wifi_secrets_get_one (self, setting_name, get_secret_flags, + setting_key, invocation); - priv->secrets_request = invocation; return TRUE; } |