summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2017-01-31 10:00:20 +0100
committerLubomir Rintel <lkundrak@v3.sk>2017-02-17 15:02:10 +0100
commitbd56063b367d74da0647e22f17872bc7bfecd512 (patch)
tree3eddf2fb1134cecdd8bf2bc453cbcb93ca588ea1
parent8131f3a9a983a2659d8423bb3cd48b42aa7d7ea1 (diff)
downloadNetworkManager-lr/pkcs11-remoting.tar.gz
ask multiplelr/pkcs11-remoting
-rw-r--r--clients/common/nm-secret-agent-simple.c3
-rw-r--r--libnm-core/nm-dbus-interface.h5
-rw-r--r--libnm-core/nm-setting-8021x.c17
-rw-r--r--libnm-core/nm-setting-private.h2
-rw-r--r--libnm-core/nm-setting.c11
-rw-r--r--libnm-core/nm-setting.h4
-rw-r--r--src/devices/wifi/nm-device-wifi.c124
-rw-r--r--src/settings/nm-agent-manager.c10
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), &timestamp))
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,