From 915e92392816a2fdcc574b63a4e8de1c7ae84b1b Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 4 Apr 2022 17:00:26 +0200 Subject: [PATCH] libnm: normalize empty strings in 802-1x setting Supplicant does not allow setting certain properties to empty values. It also does not make sense. Also, ifcfg-rh writer uses svSetValueStr() for these properties, so the ifcfg plugin would always loose having hte values set to "". Also, you couldn't enter these strings in nmcli. It's fair to assume that it makes no sense to have these values set to an empty value. Since we cannot just tighten up verification to reject them, normalize them. It also seems that some GUI now starts setting domain_suffix_match to an empty string. Or maybe it was always doing it, and ifcfg plugin just hid the problem? Anyway, we have users out there who set these properties to "". https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/973 --- src/libnm-core-impl/nm-connection.c | 61 ++++++++++++++++++++++++++ src/libnm-core-impl/nm-setting-8021x.c | 44 +++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/src/libnm-core-impl/nm-connection.c b/src/libnm-core-impl/nm-connection.c index a9b130a792..27cea2cb2b 100644 --- a/src/libnm-core-impl/nm-connection.c +++ b/src/libnm-core-impl/nm-connection.c @@ -1641,6 +1641,66 @@ _normalize_gsm_auto_config(NMConnection *self) return TRUE; } +static gboolean +_normalize_802_1x_empty_strings(NMConnection *self) +{ + NMSetting8021x *s_8021x; + gboolean changed = FALSE; + + s_8021x = _connection_get_setting_by_meta_type(NM_CONNECTION_GET_PRIVATE(self), + NM_META_SETTING_TYPE_802_1X); + if (!s_8021x) + return FALSE; + +#define _norm_8021x(s_8021x, getter, prop_name, p_changed) \ + G_STMT_START \ + { \ + NMSetting8021x *_s_8021x = (s_8021x); \ + gboolean *_p_changed = (p_changed); \ + const char *_v; \ + \ + _v = getter(_s_8021x); \ + if (_v && _v[0] == '\0') { \ + g_object_set(_s_8021x, "" prop_name "", NULL, NULL); \ + *(_p_changed) = TRUE; \ + } \ + } \ + G_STMT_END + + _norm_8021x(s_8021x, nm_setting_802_1x_get_identity, NM_SETTING_802_1X_IDENTITY, &changed); + _norm_8021x(s_8021x, + nm_setting_802_1x_get_anonymous_identity, + NM_SETTING_802_1X_ANONYMOUS_IDENTITY, + &changed); + _norm_8021x(s_8021x, nm_setting_802_1x_get_pac_file, NM_SETTING_802_1X_PAC_FILE, &changed); + _norm_8021x(s_8021x, + nm_setting_802_1x_get_subject_match, + NM_SETTING_802_1X_SUBJECT_MATCH, + &changed); + _norm_8021x(s_8021x, + nm_setting_802_1x_get_phase2_subject_match, + NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, + &changed); + _norm_8021x(s_8021x, + nm_setting_802_1x_get_domain_suffix_match, + NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, + &changed); + _norm_8021x(s_8021x, + nm_setting_802_1x_get_phase2_domain_suffix_match, + NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, + &changed); + _norm_8021x(s_8021x, + nm_setting_802_1x_get_domain_match, + NM_SETTING_802_1X_DOMAIN_MATCH, + &changed); + _norm_8021x(s_8021x, + nm_setting_802_1x_get_phase2_domain_match, + NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH, + &changed); + + return changed; +} + static gboolean _normalize_required_settings(NMConnection *self) { @@ -1952,6 +2012,7 @@ _connection_normalize(NMConnection *connection, was_modified |= _normalize_bridge_vlan_order(connection); was_modified |= _normalize_bridge_port_vlan_order(connection); was_modified |= _normalize_gsm_auto_config(connection); + was_modified |= _normalize_802_1x_empty_strings(connection); was_modified = !!was_modified; diff --git a/src/libnm-core-impl/nm-setting-8021x.c b/src/libnm-core-impl/nm-setting-8021x.c index 8ea3acb87a..41feae57a9 100644 --- a/src/libnm-core-impl/nm-setting-8021x.c +++ b/src/libnm-core-impl/nm-setting-8021x.c @@ -2980,6 +2980,50 @@ verify(NMSetting *setting, NMConnection *connection, GError **error) error)) return FALSE; + /* normalizable warnings from here on. */ + +#define _check_strempty_and_return(priv, prop_name, field, error) \ + G_STMT_START \ + { \ + NMSetting8021xPrivate *_priv = (priv); \ + GError **_error = (error); \ + \ + if (_priv->field && _priv->field[0] == '\0') { \ + g_set_error(_error, \ + NM_CONNECTION_ERROR, \ + NM_CONNECTION_ERROR_INVALID_PROPERTY, \ + _("property is empty")); \ + g_prefix_error(_error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, "" prop_name ""); \ + return NM_SETTING_VERIFY_NORMALIZABLE; \ + } \ + } \ + G_STMT_END + + _check_strempty_and_return(priv, NM_SETTING_802_1X_IDENTITY, identity, error); + _check_strempty_and_return(priv, + NM_SETTING_802_1X_ANONYMOUS_IDENTITY, + anonymous_identity, + error); + _check_strempty_and_return(priv, NM_SETTING_802_1X_PAC_FILE, pac_file, error); + _check_strempty_and_return(priv, NM_SETTING_802_1X_SUBJECT_MATCH, subject_match, error); + _check_strempty_and_return(priv, + NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, + phase2_subject_match, + error); + _check_strempty_and_return(priv, + NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, + domain_suffix_match, + error); + _check_strempty_and_return(priv, + NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, + phase2_domain_suffix_match, + error); + _check_strempty_and_return(priv, NM_SETTING_802_1X_DOMAIN_MATCH, domain_match, error); + _check_strempty_and_return(priv, + NM_SETTING_802_1X_PHASE2_DOMAIN_MATCH, + phase2_domain_match, + error); + return TRUE; }