merge: branch 'bg/802-1x-auth-timeout-bgo723084'

Make the 802.1x authentication timeout configurable to allow a faster
fallback to other connections.

https://bugzilla.gnome.org/show_bug.cgi?id=723084
This commit is contained in:
Beniamino Galvani 2017-02-21 09:34:23 +01:00
commit 7e79e913ad
12 changed files with 162 additions and 36 deletions

View file

@ -166,6 +166,7 @@ NmcOutputField nmc_fields_setting_8021X[] = {
SETTING_FIELD (NM_SETTING_802_1X_PIN), /* 41 */
SETTING_FIELD (NM_SETTING_802_1X_PIN_FLAGS), /* 42 */
SETTING_FIELD (NM_SETTING_802_1X_SYSTEM_CA_CERTS), /* 43 */
SETTING_FIELD (NM_SETTING_802_1X_AUTH_TIMEOUT), /* 44 */
{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
};
#define NMC_FIELDS_SETTING_802_1X_ALL "name"","\
@ -211,7 +212,8 @@ NmcOutputField nmc_fields_setting_8021X[] = {
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS","\
NM_SETTING_802_1X_PIN","\
NM_SETTING_802_1X_PIN_FLAGS","\
NM_SETTING_802_1X_SYSTEM_CA_CERTS
NM_SETTING_802_1X_SYSTEM_CA_CERTS","\
NM_SETTING_802_1X_AUTH_TIMEOUT
/* Available fields for NM_SETTING_WIRELESS_SETTING_NAME */
NmcOutputField nmc_fields_setting_wireless[] = {
@ -1713,6 +1715,7 @@ DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_phase2_private_key_password_
DEFINE_GETTER (nmc_property_802_1X_get_pin, NM_SETTING_802_1X_PIN)
DEFINE_SECRET_FLAGS_GETTER (nmc_property_802_1X_get_pin_flags, NM_SETTING_802_1X_PIN_FLAGS)
DEFINE_GETTER (nmc_property_802_1X_get_system_ca_certs, NM_SETTING_802_1X_SYSTEM_CA_CERTS)
DEFINE_GETTER (nmc_property_802_1X_get_auth_timeout, NM_SETTING_802_1X_AUTH_TIMEOUT)
static char *
nmc_property_802_1X_get_ca_cert (NMSetting *setting, NmcPropertyGetType get_type)
@ -6479,6 +6482,13 @@ nmc_properties_init (void)
NULL,
NULL,
NULL);
nmc_add_prop_funcs (GLUE (802_1X, AUTH_TIMEOUT),
nmc_property_802_1X_get_auth_timeout,
nmc_property_set_int,
NULL,
NULL,
NULL,
NULL);
/* Add editable properties for NM_SETTING_ADSL_SETTING_NAME */
nmc_add_prop_funcs (GLUE (ADSL, USERNAME),
@ -8779,6 +8789,7 @@ setting_802_1X_details (NMSetting *setting, NmCli *nmc, const char *one_prop, g
set_val_str (arr, 41, GET_SECRET (secrets, setting, nmc_property_802_1X_get_pin));
set_val_str (arr, 42, nmc_property_802_1X_get_pin_flags (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 43, nmc_property_802_1X_get_system_ca_certs (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 44, nmc_property_802_1X_get_auth_timeout (setting, NMC_PROPERTY_GET_PRETTY));
g_ptr_array_add (nmc->output_data, arr);
print_data (nmc); /* Print all data */

View file

@ -115,6 +115,7 @@ typedef struct {
char *phase2_private_key_password;
NMSettingSecretFlags phase2_private_key_password_flags;
gboolean system_ca_certs;
gint auth_timeout;
} NMSetting8021xPrivate;
enum {
@ -162,6 +163,7 @@ enum {
PROP_PIN,
PROP_PIN_FLAGS,
PROP_SYSTEM_CA_CERTS,
PROP_AUTH_TIMEOUT,
LAST_PROP
};
@ -2724,6 +2726,25 @@ nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting)
return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
}
/**
* nm_setting_802_1x_get_auth_timeout:
* @setting: the #NMSetting8021x
*
* Returns the value contained in the #NMSetting8021x:auth-timeout property.
*
* Returns: the configured authentication timeout in seconds. Zero means the
* global default value.
*
* Since: 1.8
**/
gint
nm_setting_802_1x_get_auth_timeout (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->auth_timeout;
}
static void
need_secrets_password (NMSetting8021x *self,
GPtrArray *secrets,
@ -3590,6 +3611,9 @@ set_property (GObject *object, guint prop_id,
case PROP_SYSTEM_CA_CERTS:
priv->system_ca_certs = g_value_get_boolean (value);
break;
case PROP_AUTH_TIMEOUT:
priv->auth_timeout = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -3733,6 +3757,9 @@ get_property (GObject *object, guint prop_id,
case PROP_SYSTEM_CA_CERTS:
g_value_set_boolean (value, priv->system_ca_certs);
break;
case PROP_AUTH_TIMEOUT:
g_value_set_int (value, priv->auth_timeout);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -4763,4 +4790,28 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
/**
* NMSetting8021x:auth-timeout:
*
* A timeout for the authentication. Zero means the global default; if the
* global default is not set, the authentication timeout is 25 seconds.
*
* Since: 1.8
**/
/* ---ifcfg-rh---
* property: auth-timeout
* variable: IEEE_8021X_AUTH_TIMEOUT(+)
* default: 0
* description: Timeout in seconds for the 802.1X authentication. Zero means the global default or 25.
* ---end---
*/
g_object_class_install_property
(object_class, PROP_AUTH_TIMEOUT,
g_param_spec_int (NM_SETTING_802_1X_AUTH_TIMEOUT, "", "",
0, G_MAXINT32, 0,
G_PARAM_READWRITE |
NM_SETTING_PARAM_FUZZY_IGNORE |
G_PARAM_STATIC_STRINGS));
}

View file

@ -150,6 +150,7 @@ typedef enum { /*< underscore_name=nm_setting_802_1x_auth_flags >*/
#define NM_SETTING_802_1X_PIN "pin"
#define NM_SETTING_802_1X_PIN_FLAGS "pin-flags"
#define NM_SETTING_802_1X_SYSTEM_CA_CERTS "system-ca-certs"
#define NM_SETTING_802_1X_AUTH_TIMEOUT "auth-timeout"
/* PRIVATE KEY NOTE: when setting PKCS#12 private keys directly via properties
* using the "blob" scheme, the data must be passed in PKCS#12 binary format.
@ -355,7 +356,9 @@ NMSettingSecretFlags nm_setting_802_1x_get_phase2_private_key_password_flags (
NMSetting8021xCKFormat nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting);
NM_AVAILABLE_IN_1_8
NMSetting8021xAuthFlags nm_setting_802_1x_get_phase1_auth_flags (NMSetting8021x *setting);
NMSetting8021xAuthFlags nm_setting_802_1x_get_phase1_auth_flags (NMSetting8021x *setting);
NM_AVAILABLE_IN_1_8
gint nm_setting_802_1x_get_auth_timeout (NMSetting8021x *setting);
G_END_DECLS

View file

@ -1147,6 +1147,7 @@ global:
libnm_1_8_0 {
global:
nm_setting_802_1x_auth_flags_get_type;
nm_setting_802_1x_get_auth_timeout;
nm_setting_802_1x_get_ca_cert_password;
nm_setting_802_1x_get_ca_cert_password_flags;
nm_setting_802_1x_get_client_cert_password;

View file

@ -59,8 +59,6 @@ _LOG_DECLARE_SELF(NMDeviceEthernet);
/*****************************************************************************/
static NM_CACHED_QUARK_FCN ("wired-secrets-tries", wired_secret_tries_quark)
#define PPPOE_RECONNECT_DELAY 7
#define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */
@ -258,16 +256,17 @@ _update_s390_subchannels (NMDeviceEthernet *self)
}
static void
clear_secrets_tries (NMDevice *device)
reset_autoconnect_retries (NMDevice *device)
{
NMActRequest *req;
NMConnection *connection;
NMSettingsConnection *connection;
req = nm_device_get_act_request (device);
if (req) {
connection = nm_act_request_get_applied_connection (req);
/* Clear wired secrets tries on success, failure, or when deactivating */
g_object_set_qdata (G_OBJECT (connection), wired_secret_tries_quark (), NULL);
connection = nm_act_request_get_settings_connection (req);
g_return_if_fail (connection);
/* Reset autoconnect retries on success, failure, or when deactivating */
nm_settings_connection_reset_autoconnect_retries (connection);
}
}
@ -283,7 +282,7 @@ device_state_changed (NMDevice *device,
if ( new_state == NM_DEVICE_STATE_ACTIVATED
|| new_state == NM_DEVICE_STATE_FAILED
|| new_state == NM_DEVICE_STATE_DISCONNECTED)
clear_secrets_tries (device);
reset_autoconnect_retries (device);
}
static void
@ -681,15 +680,20 @@ handle_auth_or_fail (NMDeviceEthernet *self,
gboolean new_secrets)
{
const char *setting_name;
guint32 tries;
NMConnection *applied_connection;
NMSettingsConnection *settings_connection;
int tries_left;
applied_connection = nm_act_request_get_applied_connection (req);
settings_connection = nm_act_request_get_settings_connection (req);
tries = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (applied_connection), wired_secret_tries_quark ()));
if (tries > 3)
tries_left = nm_settings_connection_get_autoconnect_retries (settings_connection);
if (tries_left == 0)
return NM_ACT_STAGE_RETURN_FAILURE;
if (tries_left > 0)
nm_settings_connection_set_autoconnect_retries (settings_connection, tries_left - 1);
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
nm_active_connection_clear_secrets (NM_ACTIVE_CONNECTION (req));
@ -699,7 +703,6 @@ handle_auth_or_fail (NMDeviceEthernet *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));
g_object_set_qdata (G_OBJECT (applied_connection), wired_secret_tries_quark (), GUINT_TO_POINTER (++tries));
} else
_LOGI (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets.");
@ -751,6 +754,7 @@ static gboolean
supplicant_interface_init (NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
guint timeout;
supplicant_interface_release (self);
@ -770,8 +774,11 @@ supplicant_interface_init (NMDeviceEthernet *self)
G_CALLBACK (supplicant_iface_state_cb),
self);
/* Set up a timeout on the connection attempt to fail it after 25 seconds */
priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self);
/* Set up a timeout on the connection attempt */
timeout = nm_device_get_supplicant_timeout (NM_DEVICE (self));
priv->supplicant.con_timeout_id = g_timeout_add_seconds (timeout,
supplicant_connection_timeout_cb,
self);
return TRUE;
}
@ -1366,7 +1373,7 @@ deactivate (NMDevice *device)
GError *error = NULL;
/* Clear wired secrets tries when deactivating */
clear_secrets_tries (device);
reset_autoconnect_retries (device);
nm_clear_g_source (&priv->pppoe_wait_id);

View file

@ -89,8 +89,6 @@ G_DEFINE_TYPE (NMDeviceMacsec, nm_device_macsec, NM_TYPE_DEVICE)
/******************************************************************/
static NM_CACHED_QUARK_FCN ("macsec-secrets-tries", macsec_secrets_tries_quark)
static void macsec_secrets_cancel (NMDeviceMacsec *self);
/******************************************************************/
@ -480,15 +478,20 @@ handle_auth_or_fail (NMDeviceMacsec *self,
gboolean new_secrets)
{
const char *setting_name;
guint32 tries;
int tries_left;
NMConnection *applied_connection;
NMSettingsConnection *settings_connection;
applied_connection = nm_act_request_get_applied_connection (req);
settings_connection = nm_act_request_get_settings_connection (req);
tries = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (applied_connection), macsec_secrets_tries_quark ()));
if (tries > 3)
tries_left = nm_settings_connection_get_autoconnect_retries (settings_connection);
if (tries_left == 0)
return NM_ACT_STAGE_RETURN_FAILURE;
if (tries_left > 0)
nm_settings_connection_set_autoconnect_retries (settings_connection, tries_left - 1);
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
nm_active_connection_clear_secrets (NM_ACTIVE_CONNECTION (req));
@ -498,7 +501,6 @@ handle_auth_or_fail (NMDeviceMacsec *self,
macsec_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));
g_object_set_qdata (G_OBJECT (applied_connection), macsec_secrets_tries_quark (), GUINT_TO_POINTER (++tries));
} else
_LOGI (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets.");
@ -551,6 +553,7 @@ supplicant_interface_init (NMDeviceMacsec *self)
{
NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self);
NMDevice *parent;
guint timeout;
parent = nm_device_parent_get_device (NM_DEVICE (self));
g_return_val_if_fail (parent, FALSE);
@ -573,9 +576,11 @@ supplicant_interface_init (NMDeviceMacsec *self)
G_CALLBACK (supplicant_iface_state_cb),
self);
/* Set up a timeout on the connection attempt to fail it after 25 seconds */
priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self);
/* Set up a timeout on the connection attempt */
timeout = nm_device_get_supplicant_timeout (NM_DEVICE (self));
priv->supplicant.con_timeout_id = g_timeout_add_seconds (timeout,
supplicant_connection_timeout_cb,
self);
return TRUE;
}
@ -732,17 +737,19 @@ link_changed (NMDevice *device,
update_properties (device);
}
static void
clear_secrets_tries (NMDevice *device)
reset_autoconnect_retries (NMDevice *device)
{
NMActRequest *req;
NMConnection *connection;
NMSettingsConnection *connection;
req = nm_device_get_act_request (device);
if (req) {
connection = nm_act_request_get_applied_connection (req);
/* Clear macsec secrets tries on success, failure, or when deactivating */
g_object_set_qdata (G_OBJECT (connection), macsec_secrets_tries_quark (), NULL);
connection = nm_act_request_get_settings_connection (req);
g_return_if_fail (connection);
/* Reset autoconnect retries on success, failure, or when deactivating */
nm_settings_connection_reset_autoconnect_retries (connection);
}
}
@ -758,7 +765,7 @@ device_state_changed (NMDevice *device,
if ( new_state == NM_DEVICE_STATE_ACTIVATED
|| new_state == NM_DEVICE_STATE_FAILED
|| new_state == NM_DEVICE_STATE_DISCONNECTED)
clear_secrets_tries (device);
reset_autoconnect_retries (device);
}
/******************************************************************/

View file

@ -12946,6 +12946,33 @@ nm_device_spec_match_list (NMDevice *self, const GSList *specs)
return m == NM_MATCH_SPEC_MATCH;
}
guint
nm_device_get_supplicant_timeout (NMDevice *self)
{
NMConnection *connection;
NMSetting8021x *s_8021x;
gs_free char *value = NULL;
gint timeout;
#define SUPPLICANT_DEFAULT_TIMEOUT 25
g_return_val_if_fail (NM_IS_DEVICE (self), SUPPLICANT_DEFAULT_TIMEOUT);
connection = nm_device_get_applied_connection (self);
g_return_val_if_fail (connection, SUPPLICANT_DEFAULT_TIMEOUT);
s_8021x = nm_connection_get_setting_802_1x (connection);
g_return_val_if_fail (s_8021x, SUPPLICANT_DEFAULT_TIMEOUT);
timeout = nm_setting_802_1x_get_auth_timeout (s_8021x);
if (timeout > 0)
return timeout;
value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
"802-1x.auth-timeout",
self);
return _nm_utils_ascii_str_to_int64 (value, 10, 1, G_MAXINT32,
SUPPLICANT_DEFAULT_TIMEOUT);
}
/*****************************************************************************/
static const char *

View file

@ -640,5 +640,6 @@ gboolean nm_device_update_hw_address (NMDevice *self);
void nm_device_update_initial_hw_address (NMDevice *self);
void nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze);
void nm_device_update_dynamic_ip_setup (NMDevice *self);
guint nm_device_get_supplicant_timeout (NMDevice *self);
#endif /* __NETWORKMANAGER_DEVICE_H__ */

View file

@ -2575,6 +2575,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
const char *setting_name;
NMSettingWireless *s_wireless;
GError *error = NULL;
guint timeout;
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
@ -2646,8 +2647,11 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
nm_supplicant_interface_assoc (priv->sup_iface, config,
supplicant_iface_assoc_cb, self);
/* Set up a timeout on the association attempt to fail after 25 seconds */
priv->sup_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self);
/* Set up a timeout on the association attempt */
timeout = nm_device_get_supplicant_timeout (NM_DEVICE (self));
priv->sup_timeout_id = g_timeout_add_seconds (timeout,
supplicant_connection_timeout_cb,
self);
if (!priv->periodic_source_id)
priv->periodic_source_id = g_timeout_add_seconds (6, periodic_update_cb, self);

View file

@ -2573,7 +2573,7 @@ nm_settings_connection_get_autoconnect_retries (NMSettingsConnection *self)
priv->autoconnect_retries = retries;
}
return NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->autoconnect_retries;
return priv->autoconnect_retries;
}
void
@ -2582,7 +2582,10 @@ nm_settings_connection_set_autoconnect_retries (NMSettingsConnection *self,
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
priv->autoconnect_retries = retries;
if (priv->autoconnect_retries != retries) {
_LOGT ("autoconnect-retries: set %d", retries);
priv->autoconnect_retries = retries;
}
if (retries)
priv->autoconnect_retry_time = 0;
else

View file

@ -3087,6 +3087,7 @@ fill_8021x (shvarFile *ifcfg,
shvarFile *keys = NULL;
char *value;
char **list = NULL, **iter;
gint64 timeout;
value = svGetValueString (ifcfg, "IEEE_8021X_EAP_METHODS");
if (!value) {
@ -3187,6 +3188,9 @@ fill_8021x (shvarFile *ifcfg,
g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, value, NULL);
g_free (value);
timeout = svGetValueInt64 (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", 10, 0, G_MAXINT32, 0);
g_object_set (s_8021x, NM_SETTING_802_1X_AUTH_TIMEOUT, (gint32) timeout, NULL);
if (list)
g_strfreev (list);
if (keys)

View file

@ -366,6 +366,7 @@ write_8021x_setting (NMConnection *connection,
GString *phase2_auth;
GString *str;
guint32 i, num;
gint timeout;
s_8021x = nm_connection_get_setting_802_1x (connection);
if (!s_8021x) {
@ -504,6 +505,12 @@ write_8021x_setting (NMConnection *connection,
svSetValueString (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH",
nm_setting_802_1x_get_phase2_domain_suffix_match (s_8021x));
timeout = nm_setting_802_1x_get_auth_timeout (s_8021x);
if (timeout > 0)
svSetValueInt64 (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", timeout);
else
svUnsetValue (ifcfg, "IEEE_8021X_AUTH_TIMEOUT");
success = write_8021x_certs (s_8021x, FALSE, ifcfg, error);
if (success) {
/* phase2/inner certs */