From 3ea80883fefc620d1ee60e594b3735fb7be92801 Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Mon, 23 Sep 2024 20:07:13 +0800 Subject: [PATCH] Add `nm-auto-defaults` option The NetworkManager-libreswan add additional values when user undefined which is causing incapability `ipsec.conf` and NM-libreswan config. Instead of breaking existing users, this introduced `nm-auto-defaults` option and set default to yes preserving previous behaviour. For other user wish NM-libreswan do not add default values, explicit `nm-auto-defaults: no` is required in NetworkManager `vpn.data`. These are for advanced use cases, no GUI access required. [lkundrak@v3.sk: rebased this on top of reworked ipsec.conf configuration writer/serializer, added test cases, wrote docs.] --- man/nm-settings-libreswan.5.in | 11 +++++++++-- shared/nm-service-defines.h | 1 + shared/test-utils.c | 34 ++++++++++++++++++++++++++++++++++ shared/utils.c | 12 +++++++++++- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/man/nm-settings-libreswan.5.in b/man/nm-settings-libreswan.5.in index c98fe77..6152590 100644 --- a/man/nm-settings-libreswan.5.in +++ b/man/nm-settings-libreswan.5.in @@ -19,9 +19,9 @@ .\" with this manual; if not, write to the Free Software Foundation, Inc., .\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. .\" -.\" Copyright (C) 2018 Red Hat, Inc. +.\" Copyright (C) 2018,2025 Red Hat, Inc. .\" -.TH NM-SETTINGS-LIBRESWAN "5" "9 July 2018" +.TH NM-SETTINGS-LIBRESWAN "5" "7 Apr 2025" .SH NAME nm\-setting\-libreswan \- NetworkManager Libreswan plugin supported options @@ -167,6 +167,13 @@ parameter of the same name. .I "pskinputmodes" where the 'pskvalue' can be retrieved. Used internally by the plugin. Allowed values are: 'unused', 'save', 'ask'. .TP +.I "nm-auto-defaults" +Allowed values are: 'yes' and 'no'. +This options indicates that the VPN plugin should not substitute default values for keys that are not +present in \fBvpn.data\fR or alter the values for the keys that are specified. Malformed values will be +rejected for security reasons, but other than that the user is responsible for ensuring the configuration +will work. This is mainly useful when connections are created with a management tool like \fBnmstatectl\fR(8). +.TP .I "xauthpasswordinputmodes" where the 'xauthpassword' can be retrieved. Used internally by the plugin. Allowed values are: 'unused', 'save', 'ask'. .TP diff --git a/shared/nm-service-defines.h b/shared/nm-service-defines.h index f29923f..736fa56 100644 --- a/shared/nm-service-defines.h +++ b/shared/nm-service-defines.h @@ -76,6 +76,7 @@ #define NM_LIBRESWAN_KEY_HOSTADDRFAMILY "hostaddrfamily" #define NM_LIBRESWAN_KEY_CLIENTADDRFAMILY "clientaddrfamily" #define NM_LIBRESWAN_KEY_REQUIRE_ID_ON_CERTIFICATE "require-id-on-certificate" +#define NM_LIBRESWAN_KEY_NM_AUTO_DEFAULTS "nm-auto-defaults" #define NM_LIBRESWAN_IKEV2_NO "no" #define NM_LIBRESWAN_IKEV2_NEVER "never" diff --git a/shared/test-utils.c b/shared/test-utils.c index c7ad8dd..2dc4532 100644 --- a/shared/test-utils.c +++ b/shared/test-utils.c @@ -164,6 +164,23 @@ test_config_write (void) g_free (str); g_object_unref (s_vpn); + s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); + nm_setting_vpn_add_data_item (s_vpn, "ikev2", "insist"); + nm_setting_vpn_add_data_item (s_vpn, "leftrsasigkey", "hello"); + nm_setting_vpn_add_data_item (s_vpn, "rightrsasigkey", "world"); + nm_setting_vpn_add_data_item (s_vpn, "right", "11.12.13.14"); + nm_setting_vpn_add_data_item (s_vpn, "nm-auto-defaults", "false"); + str = nm_libreswan_get_ipsec_conf (4, s_vpn, "conn", NULL, FALSE, TRUE, &error); + g_assert_no_error (error); + g_assert_cmpstr (str, ==, + "conn conn\n" + " ikev2=insist\n" + " right=11.12.13.14\n" + " rightrsasigkey=\"world\"\n" + " leftrsasigkey=\"hello\"\n"); + g_free (str); + g_object_unref (s_vpn); + s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); str = nm_libreswan_get_ipsec_conf (4, s_vpn, "conn", NULL, FALSE, TRUE, &error); g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT); @@ -195,6 +212,23 @@ test_config_write (void) g_assert_null (str); g_clear_error (&error); g_object_unref (s_vpn); + + s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); + nm_setting_vpn_add_data_item (s_vpn, "nm-auto-defaults", "false"); + nm_setting_vpn_add_data_item (s_vpn, "rightcert", "\"cert\""); + str = nm_libreswan_get_ipsec_conf (4, s_vpn, "conn", NULL, FALSE, TRUE, &error); + g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT); + g_assert_null (str); + g_clear_error (&error); + g_object_unref (s_vpn); + + s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); + nm_setting_vpn_add_data_item (s_vpn, "nm-auto-defaults", "false"); + str = nm_libreswan_get_ipsec_conf (4, s_vpn, "conn", NULL, FALSE, TRUE, &error); + g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT); + g_assert_null (str); + g_clear_error (&error); + g_object_unref (s_vpn); } static void diff --git a/shared/utils.c b/shared/utils.c index e6dec8a..9c33315 100644 --- a/shared/utils.c +++ b/shared/utils.c @@ -341,6 +341,7 @@ static const struct LibreswanParam params[] = { { NM_LIBRESWAN_KEY_XAUTH_PASSWORD_INPUT_MODES, add, PARAM_IGNORE }, { NM_LIBRESWAN_KEY_PSK_VALUE "-flags", add, PARAM_IGNORE }, { NM_LIBRESWAN_KEY_XAUTH_PASSWORD "-flags", add, PARAM_IGNORE }, + { NM_LIBRESWAN_KEY_NM_AUTO_DEFAULTS, add, PARAM_IGNORE }, { NULL } }; @@ -368,6 +369,7 @@ sanitize_setting_vpn (NMSettingVpn *s_vpn, GError **error) { gs_unref_object NMSettingVpn *sanitized = NULL; + gboolean auto_defaults = TRUE; int handled_items = 0; const char *val; int i; @@ -380,6 +382,10 @@ sanitize_setting_vpn (NMSettingVpn *s_vpn, NM_SETTING_VPN_SERVICE_TYPE, NM_VPN_SERVICE_TYPE_LIBRESWAN, NULL); + auto_defaults = _nm_utils_ascii_str_to_bool ( + nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_NM_AUTO_DEFAULTS), + TRUE); + for (i = 0; params[i].name != NULL; i++) { val = nm_setting_vpn_get_data_item (s_vpn, params[i].name); if (val != NULL) { @@ -393,7 +399,11 @@ sanitize_setting_vpn (NMSettingVpn *s_vpn, return NULL; } - params[i].add_sanitized (sanitized, params[i].name, val); + if (auto_defaults) { + params[i].add_sanitized (sanitized, params[i].name, val); + } else { + nm_setting_vpn_add_data_item (sanitized, params[i].name, val); + } val = nm_setting_vpn_get_data_item (sanitized, params[i].name); if (val == NULL) -- GitLab