summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2019-07-11 22:13:50 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2019-11-05 10:02:16 +0100
commit2e4444f08ac511fa5e39bb886faa79d592ecbdac (patch)
treefe52d80e75e4484c06769738e75ecdff656d7da8
parenteb8e46dec88cfaa8485a3e81abadf13ca28f880b (diff)
downloadNetworkManager-bg/802-1x-optional-on-1-20.tar.gz
ethernet: honor the 802-1x.optional propertybg/802-1x-optional-on-1-20
If the 802.1X authentication fails and 802-1x.optional is set, continue with activation. In this case, subscribe to the auth-state supplicant property so that any dynamic IP method can be restarted when the authentication succeeds. This is because upon authentication the switch could have changed the VLAN we are connected to. (cherry picked from commit 8afce75bf37eaf8ea7f7c52cf8d58ef2e7a7c180)
-rw-r--r--src/devices/nm-device-ethernet.c104
1 files changed, 81 insertions, 23 deletions
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index b1701c6988..8571e526cb 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -65,6 +65,7 @@ typedef struct Supplicant {
/* signal handler ids */
gulong iface_state_id;
+ gulong auth_state_id;
/* Timeouts and idles */
guint con_timeout_id;
@@ -415,6 +416,7 @@ supplicant_interface_release (NMDeviceEthernet *self)
nm_clear_g_source (&priv->supplicant_timeout_id);
nm_clear_g_source (&priv->supplicant.con_timeout_id);
nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id);
+ nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.auth_state_id);
if (priv->supplicant.iface) {
nm_supplicant_interface_disconnect (priv->supplicant.iface);
@@ -423,6 +425,62 @@ supplicant_interface_release (NMDeviceEthernet *self)
}
static void
+supplicant_auth_state_changed (NMSupplicantInterface *iface,
+ GParamSpec *pspec,
+ NMDeviceEthernet *self)
+{
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
+ NMSupplicantAuthState state;
+
+ state = nm_supplicant_interface_get_auth_state (priv->supplicant.iface);
+ _LOGD (LOGD_CORE, "supplicant auth state changed to %u", (unsigned) state);
+
+ if (state == NM_SUPPLICANT_AUTH_STATE_SUCCESS) {
+ nm_clear_g_signal_handler (priv->supplicant.iface, &priv->supplicant.iface_state_id);
+ nm_device_update_dynamic_ip_setup (NM_DEVICE (self));
+ }
+}
+
+static gboolean
+wired_auth_is_optional (NMDeviceEthernet *self)
+{
+ NMSetting8021x *s_8021x;
+
+ s_8021x = nm_device_get_applied_setting (NM_DEVICE (self), NM_TYPE_SETTING_802_1X);
+ g_return_val_if_fail (s_8021x, FALSE);
+ return nm_setting_802_1x_get_optional (s_8021x);
+}
+
+static void
+wired_auth_cond_fail (NMDeviceEthernet *self, NMDeviceStateReason reason)
+{
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
+ NMDevice *device = NM_DEVICE (self);
+
+ if (wired_auth_is_optional (self)) {
+ _LOGI (LOGD_DEVICE | LOGD_ETHER,
+ "Activation: (ethernet) 802.1X authentication is optional, continuing after a failure");
+ if (NM_IN_SET (nm_device_get_state (device),
+ NM_DEVICE_STATE_CONFIG,
+ NM_DEVICE_STATE_NEED_AUTH))
+ nm_device_activate_schedule_stage3_ip_config_start (device);
+
+ if (!priv->supplicant.auth_state_id) {
+ priv->supplicant.auth_state_id = g_signal_connect (priv->supplicant.iface,
+ "notify::" NM_SUPPLICANT_INTERFACE_AUTH_STATE,
+ G_CALLBACK (supplicant_auth_state_changed),
+ self);
+ }
+ return;
+ }
+
+ supplicant_interface_release (self);
+ nm_device_state_changed (NM_DEVICE (self),
+ NM_DEVICE_STATE_FAILED,
+ reason);
+}
+
+static void
wired_secrets_cb (NMActRequest *req,
NMActRequestGetSecretsCallId *call_id,
NMSettingsConnection *connection,
@@ -451,11 +509,12 @@ wired_secrets_cb (NMActRequest *req,
if (error) {
_LOGW (LOGD_ETHER, "%s", error->message);
- nm_device_state_changed (device,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_NO_SECRETS);
- } else
- nm_device_activate_schedule_stage1_device_prepare (device);
+ wired_auth_cond_fail (self, NM_DEVICE_STATE_REASON_NO_SECRETS);
+ return;
+ }
+
+ supplicant_interface_release (self);
+ nm_device_activate_schedule_stage1_device_prepare (device);
}
static void
@@ -506,9 +565,7 @@ link_timeout_cb (gpointer user_data)
req = nm_device_get_act_request (device);
if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) {
- nm_device_state_changed (device,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT);
+ wired_auth_cond_fail (self, NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT);
return FALSE;
}
@@ -528,7 +585,8 @@ link_timeout_cb (gpointer user_data)
_LOGI (LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) disconnected during authentication, asking for new key.");
- supplicant_interface_release (self);
+ if (!wired_auth_is_optional (self))
+ supplicant_interface_release (self);
nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
wired_secrets_get_secrets (self, setting_name, NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW);
@@ -537,7 +595,7 @@ link_timeout_cb (gpointer user_data)
time_out:
_LOGW (LOGD_DEVICE | LOGD_ETHER, "link timed out.");
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
+ wired_auth_cond_fail (self, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
return FALSE;
}
@@ -652,11 +710,8 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
case NM_SUPPLICANT_INTERFACE_STATE_DOWN:
supplicant_interface_release (self);
- if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) {
- nm_device_state_changed (device,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
- }
+ if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device))
+ wired_auth_cond_fail (self, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
break;
default:
break;
@@ -685,6 +740,15 @@ handle_auth_or_fail (NMDeviceEthernet *self,
return NM_ACT_STAGE_RETURN_FAILURE;
}
+ _LOGI (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) asking for new secrets");
+
+ /* Don't tear down supplicant if the authentication is optional
+ * because in case of a failure in getting new secrets we want to
+ * keep the supplicant alive.
+ */
+ if (!wired_auth_is_optional (self))
+ supplicant_interface_release (self);
+
wired_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));
@@ -710,12 +774,8 @@ supplicant_connection_timeout_cb (gpointer user_data)
_LOGW (LOGD_DEVICE | LOGD_ETHER,
"Activation: (ethernet) association took too long.");
- supplicant_interface_release (self);
req = nm_device_get_act_request (device);
- g_assert (req);
-
connection = nm_act_request_get_settings_connection (req);
- g_assert (connection);
/* Ask for new secrets only if we've never activated this connection
* before. If we've connected before, don't bother the user with dialogs,
@@ -724,10 +784,8 @@ supplicant_connection_timeout_cb (gpointer user_data)
if (nm_settings_connection_get_timestamp (connection, &timestamp))
new_secrets = !timestamp;
- if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE)
- _LOGW (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) asking for new secrets");
- else
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS);
+ if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_FAILURE)
+ wired_auth_cond_fail (self, NM_DEVICE_STATE_REASON_NO_SECRETS);
return FALSE;
}