diff options
-rw-r--r-- | clients/common/nm-secret-agent-simple.c | 3 | ||||
-rw-r--r-- | libnm-core/nm-dbus-interface.h | 5 | ||||
-rw-r--r-- | libnm-core/nm-setting-8021x.c | 17 | ||||
-rw-r--r-- | libnm-core/nm-setting-private.h | 2 | ||||
-rw-r--r-- | libnm-core/nm-setting.c | 11 | ||||
-rw-r--r-- | libnm-core/nm-setting.h | 4 | ||||
-rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 124 | ||||
-rw-r--r-- | src/settings/nm-agent-manager.c | 10 |
8 files changed, 121 insertions, 55 deletions
diff --git a/clients/common/nm-secret-agent-simple.c b/clients/common/nm-secret-agent-simple.c index b763bf8985..cf80513166 100644 --- a/clients/common/nm-secret-agent-simple.c +++ b/clients/common/nm-secret-agent-simple.c @@ -859,6 +859,7 @@ nm_secret_agent_simple_new (const char *name) { return g_initable_new (NM_TYPE_SECRET_AGENT_SIMPLE, NULL, NULL, NM_SECRET_AGENT_OLD_IDENTIFIER, name, - NM_SECRET_AGENT_OLD_CAPABILITIES, NM_SECRET_AGENT_CAPABILITY_VPN_HINTS, + NM_SECRET_AGENT_OLD_CAPABILITIES, NM_SECRET_AGENT_CAPABILITY_VPN_HINTS | + NM_SECRET_AGENT_CAPABILITY_MULTIPLE_SETTINGS, NULL); } diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 51ecfab42c..25df771012 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -657,6 +657,8 @@ typedef enum { * the D-Bus API. * @NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS: Internal flag, not part of * the D-Bus API. + * @NM_SECRET_AGENT_GET_SECRETS_FLAG_GET_P11_SOCKET: Internal flag, not part of + * the D-Bus API. * * #NMSecretAgentGetSecretsFlags values modify the behavior of a GetSecrets request. */ @@ -669,6 +671,7 @@ typedef enum { /*< flags >*/ /* Internal to NM; not part of the D-Bus API */ NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM = 0x80000000, NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS = 0x40000000, + NM_SECRET_AGENT_GET_SECRETS_FLAG_GET_P11_SOCKET = 0x20000000, } NMSecretAgentGetSecretsFlags; /** @@ -676,6 +679,7 @@ typedef enum { /*< flags >*/ * @NM_SECRET_AGENT_CAPABILITY_NONE: the agent supports no special capabilities * @NM_SECRET_AGENT_CAPABILITY_VPN_HINTS: the agent supports passing hints to * VPN plugin authentication dialogs. + * @NM_SECRET_AGENT_CAPABILITY_MULTIPLE_SETTINGS: XXX * @NM_SECRET_AGENT_CAPABILITY_LAST: bounds checking value; should not be used. * * #NMSecretAgentCapabilities indicate various capabilities of the agent. @@ -683,6 +687,7 @@ typedef enum { /*< flags >*/ typedef enum /*< flags >*/ { NM_SECRET_AGENT_CAPABILITY_NONE = 0x0, NM_SECRET_AGENT_CAPABILITY_VPN_HINTS = 0x1, + NM_SECRET_AGENT_CAPABILITY_MULTIPLE_SETTINGS = 0x2, /* boundary value */ NM_SECRET_AGENT_CAPABILITY_LAST = NM_SECRET_AGENT_CAPABILITY_VPN_HINTS, diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c index e64769e42d..bc72fe1dbb 100644 --- a/libnm-core/nm-setting-8021x.c +++ b/libnm-core/nm-setting-8021x.c @@ -3209,6 +3209,22 @@ need_secrets (NMSetting *setting) } static gboolean +uses_pkcs11 (NMSetting *setting) +{ + NMSetting8021x *self = NM_SETTING_802_1X (setting); + + if ( nm_setting_802_1x_get_ca_cert_scheme (self) == NM_SETTING_802_1X_CK_SCHEME_PKCS11 + || nm_setting_802_1x_get_client_cert_scheme (self) == NM_SETTING_802_1X_CK_SCHEME_PKCS11 + || nm_setting_802_1x_get_phase2_ca_cert_scheme (self) == NM_SETTING_802_1X_CK_SCHEME_PKCS11 + || nm_setting_802_1x_get_phase2_client_cert_scheme (self) == NM_SETTING_802_1X_CK_SCHEME_PKCS11 + || nm_setting_802_1x_get_private_key_scheme (self) == NM_SETTING_802_1X_CK_SCHEME_PKCS11 + || nm_setting_802_1x_get_phase2_private_key_scheme (self) == NM_SETTING_802_1X_CK_SCHEME_PKCS11) + return TRUE; + + return FALSE; +} + +static gboolean verify_cert (GBytes *bytes, const char *prop_name, const char *password, const char *password_prop_name, GError **error) { @@ -3799,6 +3815,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) parent_class->verify = verify; parent_class->need_secrets = need_secrets; + parent_class->uses_pkcs11 = uses_pkcs11; /* Properties */ diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h index 8d09e3d759..12aa7b0586 100644 --- a/libnm-core/nm-setting-private.h +++ b/libnm-core/nm-setting-private.h @@ -174,4 +174,6 @@ gboolean _nm_setting_use_legacy_property (NMSetting *setting, GPtrArray *_nm_setting_need_secrets (NMSetting *setting); +gboolean _nm_setting_uses_pkcs11 (NMSetting *setting); + #endif /* NM_SETTING_PRIVATE_H */ diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index b9ac5aec97..4975e115d1 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -1667,6 +1667,17 @@ _nm_setting_need_secrets (NMSetting *setting) return secrets; } +gboolean +_nm_setting_uses_pkcs11 (NMSetting *setting) +{ + g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); + + if (NM_SETTING_GET_CLASS (setting)->uses_pkcs11) + return NM_SETTING_GET_CLASS (setting)->uses_pkcs11 (setting); + + return FALSE; +} + static int update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError **error) { diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h index 3083ef6029..e90176e5e6 100644 --- a/libnm-core/nm-setting.h +++ b/libnm-core/nm-setting.h @@ -214,8 +214,10 @@ typedef struct { const GParamSpec *prop_spec, NMSettingCompareFlags flags); + gboolean (*uses_pkcs11) (NMSetting *setting); + /*< private >*/ - gpointer padding[7]; + gpointer padding[6]; } NMSettingClass; /** diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index cfee573e81..5ec70e9316 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -37,6 +37,7 @@ #include "supplicant/nm-supplicant-manager.h" #include "supplicant/nm-supplicant-interface.h" #include "supplicant/nm-supplicant-config.h" +#include "nm-setting-private.h" #include "nm-setting-connection.h" #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" @@ -1896,18 +1897,15 @@ link_timeout_cb (gpointer user_data) return FALSE; } -static gboolean +static const char * need_new_8021x_secrets (NMDeviceWifi *self, - NMSupplicantInterfaceState old_state, - const char **setting_name) + guint32 old_state) { NMSetting8021x *s_8021x; NMSettingWirelessSecurity *s_wsec; NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; NMConnection *connection; - g_assert (setting_name != NULL); - connection = nm_device_get_applied_connection (NM_DEVICE (self)); g_return_val_if_fail (connection != NULL, FALSE); @@ -1915,7 +1913,7 @@ need_new_8021x_secrets (NMDeviceWifi *self, * attempting to authenticate with the AP. */ if (old_state != NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED) - return FALSE; + return NULL; /* If it's an 802.1x or LEAP connection with "always ask"/unsaved secrets * then we need to ask again because it might be an OTP token and the PIN @@ -1930,8 +1928,7 @@ need_new_8021x_secrets (NMDeviceWifi *self, NULL)) g_assert_not_reached (); if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) - *setting_name = NM_SETTING_802_1X_SETTING_NAME; - return *setting_name ? TRUE : FALSE; + return NM_SETTING_802_1X_SETTING_NAME; } s_wsec = nm_connection_get_setting_wireless_security (connection); @@ -1942,32 +1939,28 @@ need_new_8021x_secrets (NMDeviceWifi *self, NULL)) g_assert_not_reached (); if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) - *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; - return *setting_name ? TRUE : FALSE; + return NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; } /* Not a LEAP or 802.1x connection */ - return FALSE; + return NULL; } -static gboolean +static const char * need_new_wpa_psk (NMDeviceWifi *self, NMSupplicantInterfaceState old_state, - gint disconnect_reason, - const char **setting_name) + gint disconnect_reason) { NMSettingWirelessSecurity *s_wsec; NMConnection *connection; const char *key_mgmt = NULL; - g_assert (setting_name != NULL); - connection = nm_device_get_applied_connection (NM_DEVICE (self)); - g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (connection != NULL, NULL); /* A bad PSK will cause the supplicant to disconnect during the 4-way handshake */ if (old_state != NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE) - return FALSE; + return NULL; s_wsec = nm_connection_get_setting_wireless_security (connection); if (s_wsec) @@ -1981,14 +1974,13 @@ need_new_wpa_psk (NMDeviceWifi *self, */ #define LOCAL_WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY -4 if (disconnect_reason == LOCAL_WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY) - return FALSE; + return NULL; - *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; - return TRUE; + return NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; } /* Not a WPA-PSK connection */ - return FALSE; + return NULL; } static gboolean @@ -1999,17 +1991,32 @@ handle_8021x_or_psk_auth_fail (NMDeviceWifi *self, { NMDevice *device = NM_DEVICE (self); NMActRequest *req; + NMConnection *connection; + NMSetting8021x *s_8021x; const char *setting_name = NULL; - gboolean handled = FALSE; + NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION + | NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; g_return_val_if_fail (new_state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, FALSE); req = nm_device_get_act_request (NM_DEVICE (self)); g_return_val_if_fail (req != NULL, FALSE); - if ( need_new_8021x_secrets (self, old_state, &setting_name) - || need_new_wpa_psk (self, old_state, disconnect_reason, &setting_name)) { + connection = nm_device_get_applied_connection (NM_DEVICE (self)); + g_return_val_if_fail (connection != NULL, FALSE); + + setting_name = need_new_8021x_secrets (self, old_state); + if (!setting_name) + setting_name = need_new_wpa_psk (self, old_state, disconnect_reason); + s_8021x = nm_connection_get_setting_802_1x (connection); + if (_nm_setting_uses_pkcs11 (NM_SETTING (s_8021x))) { + if (setting_name) + flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_GET_P11_SOCKET; + else + setting_name = NM_SETTING_CONNECTION_SETTING_NAME; + } + if (setting_name) { nm_act_request_clear_secrets (req); _LOGI (LOGD_DEVICE | LOGD_WIFI, @@ -2017,14 +2024,10 @@ handle_8021x_or_psk_auth_fail (NMDeviceWifi *self, cleanup_association_attempt (self, TRUE); nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); - wifi_secrets_get_secrets (self, - setting_name, - NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION - | NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW); - handled = TRUE; - } - - return handled; + wifi_secrets_get_secrets (self, setting_name, flags); + return TRUE; + } else + return FALSE; } static gboolean @@ -2275,6 +2278,8 @@ handle_auth_or_fail (NMDeviceWifi *self, guint32 tries; NMConnection *applied_connection; NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; + NMSetting8021x *s_8021x; g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NM_ACT_STAGE_RETURN_FAILURE); @@ -2289,14 +2294,25 @@ handle_auth_or_fail (NMDeviceWifi *self, if (tries > 3) return NM_ACT_STAGE_RETURN_FAILURE; - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); + setting_name = nm_connection_need_secrets (applied_connection, NULL); + s_8021x = nm_connection_get_setting_802_1x (applied_connection); + if (_nm_setting_uses_pkcs11 (NM_SETTING (s_8021x))) { + if (setting_name) + flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_GET_P11_SOCKET; + else + setting_name = NM_SETTING_CONNECTION_SETTING_NAME; + } + if (!setting_name) + return NM_ACT_STAGE_RETURN_SUCCESS; + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); nm_act_request_clear_secrets (req); - setting_name = nm_connection_need_secrets (applied_connection, NULL); + + if (new_secrets) + flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; + if (setting_name) { - 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)); + wifi_secrets_get_secrets (self, setting_name, flags); g_object_set_qdata (G_OBJECT (applied_connection), wireless_secrets_tries_quark (), GUINT_TO_POINTER (++tries)); ret = NM_ACT_STAGE_RETURN_POSTPONE; } else @@ -2356,6 +2372,7 @@ supplicant_connection_timeout_cb (gpointer user_data) if (priv->ssid_found && nm_connection_get_setting_wireless_security (connection)) { guint64 timestamp = 0; gboolean new_secrets = TRUE; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; /* Connection failed; either driver problems, the encryption key is * wrong, or the passwords or certificates were wrong. @@ -2371,12 +2388,15 @@ supplicant_connection_timeout_cb (gpointer user_data) if (nm_settings_connection_get_timestamp (nm_act_request_get_settings_connection (req), ×tamp)) new_secrets = !timestamp; - if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) - _LOGW (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) asking for new secrets"); - else { + ret = handle_auth_or_fail (self, req, new_secrets); + if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); } + if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { + _LOGI (LOGD_DEVICE | LOGD_WIFI, + "Activation: (wifi) asking for new secrets"); + } } else { _LOGW (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) association took too long, failing activation"); @@ -2622,7 +2642,6 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) NMActRequest *req; NMWifiAP *ap; NMConnection *connection; - const char *setting_name; NMSettingWireless *s_wireless; GError *error = NULL; @@ -2646,15 +2665,14 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) g_assert (s_wireless); /* If we need secrets, get them */ - setting_name = nm_connection_need_secrets (connection, NULL); - if (setting_name) { + ret = handle_auth_or_fail (self, req, FALSE); + if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + goto out; + } + if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { _LOGI (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) access point '%s' has security, but secrets are required.", - nm_connection_get_id (connection)); - - ret = handle_auth_or_fail (self, req, FALSE); - if (ret == NM_ACT_STAGE_RETURN_FAILURE) - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; + "Activation: (wifi) asking for new secrets"); goto out; } @@ -2853,12 +2871,12 @@ handle_ip_config_timeout (NMDeviceWifi *self, "Activation: (wifi) could not get IP configuration for connection '%s'.", nm_connection_get_id (connection)); - ret = handle_auth_or_fail (self, NULL, TRUE); + ret = handle_auth_or_fail (self, NULL, FALSE); + if (ret == NM_ACT_STAGE_RETURN_FAILURE) + *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { _LOGI (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) asking for new secrets"); - } else { - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; } } else { /* Not static WEP or failure allowed; let superclass handle it */ diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c index dedfc042e3..b745746a54 100644 --- a/src/settings/nm-agent-manager.c +++ b/src/settings/nm-agent-manager.c @@ -956,6 +956,7 @@ static void _con_get_request_start_proceed (Request *req, gboolean include_system_secrets) { NMConnection *tmp; + char *settings; g_return_if_fail (req->request_type == REQUEST_TYPE_CON_GET); @@ -973,6 +974,15 @@ _con_get_request_start_proceed (Request *req, gboolean include_system_secrets) set_secrets_not_required (tmp, req->con.get.existing_secrets); } + if ( req->con.get.flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_GET_P11_SOCKET + && (nm_secret_agent_get_capabilities (req->current) & NM_SECRET_AGENT_CAPABILITY_MULTIPLE_SETTINGS)) { + settings = g_strdup_printf ("%s,%s", + req->con.get.setting_name, + NM_SETTING_CONNECTION_SETTING_NAME); + } else { + settings = g_strdup (req->con.get.setting_name); + } + req->current_call_id = nm_secret_agent_get_secrets (req->current, req->con.path, tmp, |