From fcddcc04e03b46cc17986062f912f6798e857de3 Mon Sep 17 00:00:00 2001 From: MSVSphere Packaging Team Date: Thu, 14 Nov 2024 15:20:08 +0300 Subject: [PATCH] import NetworkManager-libreswan-1.2.22-4.el9_5 --- .NetworkManager-libreswan.metadata | 2 +- .gitignore | 2 +- ...01-ipsec-conf-escaping-cve-2024-9050.patch | 1691 +++++++++++++++++ ...es-add-support-for-leftmodecfgclient.patch | 79 - ...-new-API-to-send-configuration-to-NM.patch | 137 -- ...nd-IPv4-config-if-mode-config-client.patch | 72 - ...g-refcounting-in-D-Bus-handler-for-C.patch | 67 - ...es-support-type-hostaddrfamily-clien.patch | 91 - SOURCES/0006-add-support-leftsubnet.patch | 71 - SOURCES/0007-add-rightcert-property.patch | 107 -- SPECS/NetworkManager-libreswan.spec | 30 +- 11 files changed, 1710 insertions(+), 639 deletions(-) create mode 100644 SOURCES/0001-ipsec-conf-escaping-cve-2024-9050.patch delete mode 100644 SOURCES/0001-service-properties-add-support-for-leftmodecfgclient.patch delete mode 100644 SOURCES/0002-service-use-new-API-to-send-configuration-to-NM.patch delete mode 100644 SOURCES/0003-service-don-t-send-IPv4-config-if-mode-config-client.patch delete mode 100644 SOURCES/0004-service-fix-wrong-refcounting-in-D-Bus-handler-for-C.patch delete mode 100644 SOURCES/0005-service-properties-support-type-hostaddrfamily-clien.patch delete mode 100644 SOURCES/0006-add-support-leftsubnet.patch delete mode 100644 SOURCES/0007-add-rightcert-property.patch diff --git a/.NetworkManager-libreswan.metadata b/.NetworkManager-libreswan.metadata index 5f9e2f2..2188a15 100644 --- a/.NetworkManager-libreswan.metadata +++ b/.NetworkManager-libreswan.metadata @@ -1 +1 @@ -a57014f8a1c360546cb7fed5231efd7cfbf85bf3 SOURCES/NetworkManager-libreswan-1.2.18.tar.xz +7f62450f66f2a21789fd6cfebbf3355ae99553ea SOURCES/NetworkManager-libreswan-1.2.22.tar.xz diff --git a/.gitignore b/.gitignore index ccdf14f..6fe0fdb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/NetworkManager-libreswan-1.2.18.tar.xz +SOURCES/NetworkManager-libreswan-1.2.22.tar.xz diff --git a/SOURCES/0001-ipsec-conf-escaping-cve-2024-9050.patch b/SOURCES/0001-ipsec-conf-escaping-cve-2024-9050.patch new file mode 100644 index 0000000..e7f78e4 --- /dev/null +++ b/SOURCES/0001-ipsec-conf-escaping-cve-2024-9050.patch @@ -0,0 +1,1691 @@ +From f9f321fc00f9016569a592140d9e5a24f9c4db01 Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Fri, 13 Sep 2024 14:49:12 +0200 +Subject: [PATCH 1/6] shared/nm-glib: import newer g_steal_pointer() + +The version that's there doesn't work with current glib, still +considering g_steal_pointer() deprecated. + +We should probably do a full import, but it's became such a mess +in NetworkManager.git that it's not feasible at this point. + +[lkundrak@v3.sk: Backported from 1.24.0] +--- + shared/nm-utils/nm-glib.h | 32 +++++++++++++++++--------------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +diff --git a/shared/nm-utils/nm-glib.h b/shared/nm-utils/nm-glib.h +index 770cf0f..1b6487c 100644 +--- a/shared/nm-utils/nm-glib.h ++++ b/shared/nm-utils/nm-glib.h +@@ -412,24 +412,26 @@ _nm_g_hash_table_get_keys_as_array (GHashTable *hash_table, + + /*****************************************************************************/ + +-#if !GLIB_CHECK_VERSION(2, 44, 0) +-static inline gpointer +-g_steal_pointer (gpointer pp) +-{ +- gpointer *ptr = (gpointer *) pp; +- gpointer ref; ++#define _NM_ENSURE_POINTER(value) \ ++ do { \ ++ _nm_unused const void *const _unused_for_type_check = 0 ? (value) : NULL; \ ++ } while (0) + +- ref = *ptr; +- *ptr = NULL; +- +- return ref; +-} +- +-/* type safety */ +-#define g_steal_pointer(pp) \ +- (0 ? (*(pp)) : (g_steal_pointer) (pp)) ++#ifdef g_steal_pointer ++#undef g_steal_pointer + #endif + ++#define g_steal_pointer(pp) \ ++ ({ \ ++ typeof(*(pp)) *const _pp = (pp); \ ++ typeof(*_pp) _p = *_pp; \ ++ \ ++ _NM_ENSURE_POINTER(_p); \ ++ \ ++ *_pp = NULL; \ ++ _p; \ ++ }) ++ + /*****************************************************************************/ + + static inline gboolean +-- +2.46.0 + +From 72816f82b029063e4d8aaff6703f175da5232293 Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Tue, 17 Sep 2024 13:28:58 +0200 +Subject: [PATCH 2/6] build: get rid of {properties,src}/libutils.la + +Useless build of an extra libraries, just making the build slower and +more complicated. Get rid of then, and just roll src/libutils.la. + +[lkundrak@v3.sk: Backported from 1.24.0] +--- + Makefile.am | 69 +++++++++++++++++++++-------------------------------- + 1 file changed, 27 insertions(+), 42 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 29084a9..d46cfcd 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -33,6 +33,26 @@ nmvpnservice_DATA = nm-libreswan-service.name + + ############################################################################### + ++noinst_LTLIBRARIES += shared/libutils.la ++ ++shared_libutils_la_SOURCES = \ ++ shared/nm-utils/nm-shared-utils.c \ ++ shared/nm-utils/nm-shared-utils.h \ ++ shared/utils.c \ ++ shared/utils.h \ ++ shared/nm-service-defines.h ++ ++shared_libutils_la_CFLAGS = \ ++ -DPREFIX=\""$(prefix)"\" \ ++ $(common_CFLAGS) \ ++ $(LIBNM_CFLAGS) ++ ++shared_libutils_la_LIBADD = \ ++ $(GLIB_LIBS) \ ++ $(LIBNM_LIBS) ++ ++############################################################################### ++ + properties/resources.h: properties/gresource.xml + $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $< --target=$@ --sourcedir=$(srcdir)/properties --generate-header --internal + +@@ -53,10 +73,6 @@ gtk4/%.ui: properties/%.ui + EXTRA_DIST += \ + gtk4/nm-libreswan-dialog.ui + +-plugin_sources = \ +- properties/nm-libreswan-editor-plugin.c \ +- properties/nm-libreswan-editor-plugin.h +- + editor_sources = \ + properties/nm-libreswan-editor.c \ + properties/nm-libreswan-editor.h +@@ -68,23 +84,6 @@ common_CFLAGS = \ + + ############################################################################### + +-noinst_LTLIBRARIES += properties/libutils.la +- +-properties_libutils_la_SOURCES = \ +- shared/utils.c \ +- shared/utils.h \ +- shared/nm-utils/nm-vpn-plugin-utils.c \ +- shared/nm-utils/nm-vpn-plugin-utils.h \ +- shared/nm-utils/nm-shared-utils.c \ +- shared/nm-utils/nm-shared-utils.h \ +- shared/nm-service-defines.h +- +-properties_libutils_la_CPPFLAGS = \ +- -DPREFIX=\""$(prefix)"\" \ +- -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB_BASE \ +- $(common_CFLAGS) \ +- $(LIBNM_CFLAGS) +- + plugin_LTLIBRARIES += properties/libnm-vpn-plugin-libreswan.la + + properties_libnm_vpn_plugin_libreswan_la_CFLAGS = \ +@@ -93,10 +92,13 @@ properties_libnm_vpn_plugin_libreswan_la_CFLAGS = \ + $(LIBNM_CFLAGS) + + properties_libnm_vpn_plugin_libreswan_la_SOURCES = \ +- $(plugin_sources) ++ shared/nm-utils/nm-vpn-plugin-utils.c \ ++ shared/nm-utils/nm-vpn-plugin-utils.h \ ++ properties/nm-libreswan-editor-plugin.c \ ++ properties/nm-libreswan-editor-plugin.h + + properties_libnm_vpn_plugin_libreswan_la_LIBADD = \ +- properties/libutils.la \ ++ shared/libutils.la \ + $(LIBNM_LIBS) \ + $(DL_LIBS) + +@@ -198,7 +200,6 @@ auth_dialog_nm_libreswan_auth_dialog_LDADD = \ + + src_cppflags = \ + -DBINDIR=\"$(bindir)\" \ +- -DPREFIX=\""$(prefix)"\" \ + -DLIBDIR=\""$(libdir)"\" \ + -DLIBEXECDIR=\""$(libexecdir)"\" \ + -DLOCALSTATEDIR=\""$(localstatedir)"\" \ +@@ -230,22 +231,6 @@ src/nm-libreswan-helper-service-dbus.h: src/nm-libreswan-helper-service.xml + src/nm-libreswan-helper-service-dbus.c: src/nm-libreswan-helper-service-dbus.h + @true + +-noinst_LTLIBRARIES += src/libutils.la +- +-src_libutils_la_SOURCES = \ +- shared/nm-utils/nm-shared-utils.c \ +- shared/nm-utils/nm-shared-utils.h \ +- shared/utils.c \ +- shared/utils.h \ +- shared/nm-service-defines.h +- +-src_libutils_la_CPPFLAGS = \ +- $(src_cppflags) +- +-src_libutils_la_LIBADD = \ +- $(GLIB_LIBS) \ +- $(LIBNM_LIBS) +- + ############################################################################### + + libexec_PROGRAMS += src/nm-libreswan-service +@@ -255,7 +240,7 @@ src_nm_libreswan_service_CPPFLAGS = \ + + src_nm_libreswan_service_LDADD = \ + src/libnm-libreswan-helper-service-dbus.la \ +- src/libutils.la \ ++ shared/libutils.la \ + $(GLIB_LIBS) \ + $(LIBNM_LIBS) \ + $(LIBNL_LIBS) \ +@@ -272,7 +257,7 @@ src_nm_libreswan_service_helper_CPPFLAGS = \ + + src_nm_libreswan_service_helper_LDADD = \ + src/libnm-libreswan-helper-service-dbus.la \ +- src/libutils.la \ ++ shared/libutils.la \ + $(GLIB_LIBS) \ + $(LIBNM_LIBS) + +-- +2.46.0 + +From cf9777bd065ddc40c627e1d994432e95b1e70a82 Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Mon, 23 Sep 2024 11:39:22 +0200 +Subject: [PATCH 3/6] shared/test-utils: cover config write with unit tests + +Test that we generate good configuration for typical IKEv1 and IKEv2 +cases. + +[lkundrak@v3.sk: Backported from 1.24.0] +--- + Makefile.am | 16 ++++++ + shared/test-utils.c | 127 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 143 insertions(+) + create mode 100644 shared/test-utils.c + +diff --git a/Makefile.am b/Makefile.am +index d46cfcd..3f4e85c 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -21,6 +21,8 @@ libexec_PROGRAMS = + + noinst_PROGRAMS = + ++TESTS = ++ + SUBDIRS = po man + + ############################################################################### +@@ -51,6 +53,20 @@ shared_libutils_la_LIBADD = \ + $(GLIB_LIBS) \ + $(LIBNM_LIBS) + ++noinst_PROGRAMS += shared/test-utils ++ ++TESTS += shared/test-utils ++ ++shared_test_utils_SOURCES = shared/test-utils.c ++ ++shared_test_utils_CFLAGS = \ ++ $(common_CFLAGS) \ ++ $(LIBNM_CFLAGS) ++ ++shared_test_utils_LDADD = \ ++ shared/libutils.la \ ++ $(LIBNM_LIBS) ++ + ############################################################################### + + properties/resources.h: properties/gresource.xml +diff --git a/shared/test-utils.c b/shared/test-utils.c +new file mode 100644 +index 0000000..82ee933 +--- /dev/null ++++ b/shared/test-utils.c +@@ -0,0 +1,127 @@ ++#include "nm-default.h" ++ ++#include "utils.h" ++ ++#include ++ ++static char * ++_setting_into_ipsec_conf (NMSetting *s_vpn, const char *name, GError **error) ++{ ++ gs_unref_object NMConnection *connection = NULL; ++ gs_unref_object GFile *tmp = NULL; ++ GFileIOStream *tmpstream; ++ char buf[4096]; ++ gboolean res; ++ gsize count; ++ gint fd; ++ ++ connection = nm_simple_connection_new (); ++ nm_connection_add_setting (connection, s_vpn); ++ ++ tmp = g_file_new_tmp (NULL, &tmpstream, error); ++ if (tmp == NULL) ++ return NULL; ++ ++ res = g_file_delete (tmp, NULL, error); ++ if (res == FALSE) ++ return NULL; ++ ++ fd = g_file_descriptor_based_get_fd(G_FILE_DESCRIPTOR_BASED( ++ g_io_stream_get_output_stream(G_IO_STREAM (tmpstream)))); ++ ++ res = nm_libreswan_config_write (fd, 4, connection, ++ name, NULL, ++ FALSE, TRUE, NULL, ++ error); ++ if (res == FALSE) ++ return NULL; ++ ++ res = g_seekable_seek (G_SEEKABLE(tmpstream), ++ 0, G_SEEK_SET, NULL, error); ++ if (res == FALSE) ++ return NULL; ++ ++ res = g_input_stream_read_all ( ++ g_io_stream_get_input_stream(G_IO_STREAM (tmpstream)), ++ buf, ++ sizeof(buf)-1, ++ &count, ++ NULL, ++ error); ++ if (res == FALSE) ++ return NULL; ++ ++ buf[count] = '\0'; ++ return g_strdup(buf); ++} ++ ++static void ++test_config_write (void) ++{ ++ GError *error = NULL; ++ NMSetting *s_vpn; ++ char *str; ++ ++ s_vpn = nm_setting_vpn_new (); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "right", "11.12.13.14"); ++ str = _setting_into_ipsec_conf (s_vpn, "con_name", &error); ++ g_assert_no_error (error); ++ g_assert_cmpstr (str, ==, ++ "conn con_name\n" ++ " authby=secret\n" ++ " left=%defaultroute\n" ++ " leftmodecfgclient=yes\n" ++ " right=11.12.13.14\n" ++ " rightmodecfgserver=yes\n" ++ " modecfgpull=yes\n" ++ " rightsubnet=0.0.0.0/0\n" ++ " leftxauthclient=yes\n" ++ " remote-peer-type=cisco\n" ++ " rightxauthserver=yes\n" ++ " ikelifetime=24h\n" ++ " salifetime=24h\n" ++ " rekey=yes\n" ++ " keyingtries=1\n" ++ " ikev2=never\n" ++ " nm-configured=yes\n" ++ " auto=add\n"); ++ g_free (str); ++ ++ s_vpn = nm_setting_vpn_new (); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "ikev2", "insist"); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "leftcert", "LibreswanClient"); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "leftid", "%fromcert"); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "right", "11.12.13.14"); ++ str = _setting_into_ipsec_conf (s_vpn, ++ "f0008435-07af-4836-a53d-b43e8730e68f", ++ &error); ++ g_assert_no_error (error); ++ g_assert_cmpstr (str, ==, ++ "conn f0008435-07af-4836-a53d-b43e8730e68f\n" ++ " leftid=%fromcert\n" ++ " leftcert=LibreswanClient\n" ++ " leftrsasigkey=%cert\n" ++ " rightrsasigkey=%cert\n" ++ " left=%defaultroute\n" ++ " leftmodecfgclient=yes\n" ++ " right=11.12.13.14\n" ++ " rightmodecfgserver=yes\n" ++ " modecfgpull=yes\n" ++ " rightsubnet=0.0.0.0/0\n" ++ " rekey=yes\n" ++ " keyingtries=1\n" ++ " ikev2=insist\n" ++ " nm-configured=yes\n" ++ " auto=add\n"); ++ g_free (str); ++} ++ ++int ++main (int argc, char **argv) ++{ ++ g_test_init (&argc, &argv, NULL); ++ ++ g_test_add_func ("/utils/config/write", test_config_write); ++ ++ return g_test_run (); ++} +-- +2.46.0 + +From 2b07bfeec5e67cbdce9b23b7c0648cb0ee55416d Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Sun, 22 Sep 2024 14:20:22 +0200 +Subject: [PATCH 4/6] all: rework formatting of ipsec.conf + +Simplify the interface and validate each item carefully. + +Note this fixes a security issue (CVE-2024-9050), with an "Important" +impact severity, where insufficient validation could lead to injection +of potentialy malicious values into the ipsec.conf snippet we send over +to pluto. + +https://issues.redhat.com/browse/RHEL-59565 + +[lkundrak@v3.sk: Backported from 1.24.0] +--- + properties/nm-libreswan-editor-plugin.c | 30 +- + shared/test-utils.c | 97 +---- + shared/utils.c | 491 ++++++++++++++---------- + shared/utils.h | 28 +- + src/nm-libreswan-service.c | 183 +++++---- + 5 files changed, 423 insertions(+), 406 deletions(-) + +diff --git a/properties/nm-libreswan-editor-plugin.c b/properties/nm-libreswan-editor-plugin.c +index fe473d1..9393212 100644 +--- a/properties/nm-libreswan-editor-plugin.c ++++ b/properties/nm-libreswan-editor-plugin.c +@@ -286,19 +286,11 @@ export_to_file (NMVpnEditorPlugin *self, + { + NMSettingVpn *s_vpn; + gboolean openswan = FALSE; +- int fd, errsv; + gs_free_error GError *local = NULL; ++ gs_free char *ipsec_conf = NULL; + gboolean is_openswan; + int version; + +- fd = g_open (path, O_WRONLY | O_CREAT, 0666); +- if (fd == -1) { +- errsv = errno; +- g_set_error (error, NMV_EDITOR_PLUGIN_ERROR, NMV_EDITOR_PLUGIN_ERROR_FAILED, +- _("Can’t open file “%s”: %s"), path, g_strerror (errsv)); +- return FALSE; +- } +- + s_vpn = nm_connection_get_setting_vpn (connection); + if (s_vpn) + openswan = nm_streq (nm_setting_vpn_get_service_type (s_vpn), NM_VPN_SERVICE_TYPE_OPENSWAN); +@@ -306,24 +298,18 @@ export_to_file (NMVpnEditorPlugin *self, + nm_libreswan_detect_version (nm_libreswan_find_helper_bin ("ipsec", NULL), + &is_openswan, &version, NULL); + +- if (!nm_libreswan_config_write (fd, +- version, +- connection, +- nm_connection_get_id (connection), +- NULL, +- openswan, +- TRUE, +- NULL, +- &local)) { +- g_close (fd, NULL); ++ ipsec_conf = nm_libreswan_get_ipsec_conf (version, s_vpn, ++ nm_connection_get_id (connection), ++ NULL, openswan, TRUE, error); ++ if (ipsec_conf == NULL) ++ return FALSE; ++ ++ if (!g_file_set_contents (path, ipsec_conf, -1, &local)) { + g_set_error (error, NMV_EDITOR_PLUGIN_ERROR, NMV_EDITOR_PLUGIN_ERROR_FAILED, + _("Error writing to file “%s”: %s"), path, local->message); + return FALSE; + } + +- if (!g_close (fd, error)) +- return FALSE; +- + return TRUE; + } + +diff --git a/shared/test-utils.c b/shared/test-utils.c +index 82ee933..49aa32a 100644 +--- a/shared/test-utils.c ++++ b/shared/test-utils.c +@@ -2,117 +2,60 @@ + + #include "utils.h" + +-#include +- +-static char * +-_setting_into_ipsec_conf (NMSetting *s_vpn, const char *name, GError **error) +-{ +- gs_unref_object NMConnection *connection = NULL; +- gs_unref_object GFile *tmp = NULL; +- GFileIOStream *tmpstream; +- char buf[4096]; +- gboolean res; +- gsize count; +- gint fd; +- +- connection = nm_simple_connection_new (); +- nm_connection_add_setting (connection, s_vpn); +- +- tmp = g_file_new_tmp (NULL, &tmpstream, error); +- if (tmp == NULL) +- return NULL; +- +- res = g_file_delete (tmp, NULL, error); +- if (res == FALSE) +- return NULL; +- +- fd = g_file_descriptor_based_get_fd(G_FILE_DESCRIPTOR_BASED( +- g_io_stream_get_output_stream(G_IO_STREAM (tmpstream)))); +- +- res = nm_libreswan_config_write (fd, 4, connection, +- name, NULL, +- FALSE, TRUE, NULL, +- error); +- if (res == FALSE) +- return NULL; +- +- res = g_seekable_seek (G_SEEKABLE(tmpstream), +- 0, G_SEEK_SET, NULL, error); +- if (res == FALSE) +- return NULL; +- +- res = g_input_stream_read_all ( +- g_io_stream_get_input_stream(G_IO_STREAM (tmpstream)), +- buf, +- sizeof(buf)-1, +- &count, +- NULL, +- error); +- if (res == FALSE) +- return NULL; +- +- buf[count] = '\0'; +- return g_strdup(buf); +-} +- + static void + test_config_write (void) + { + GError *error = NULL; +- NMSetting *s_vpn; ++ NMSettingVpn *s_vpn; + char *str; + +- s_vpn = nm_setting_vpn_new (); ++ s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); + nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "right", "11.12.13.14"); +- str = _setting_into_ipsec_conf (s_vpn, "con_name", &error); ++ str = nm_libreswan_get_ipsec_conf (4, s_vpn, "con_name", NULL, FALSE, TRUE, &error); + g_assert_no_error (error); + g_assert_cmpstr (str, ==, + "conn con_name\n" ++ " ikev2=never\n" ++ " right=11.12.13.14\n" + " authby=secret\n" + " left=%defaultroute\n" + " leftmodecfgclient=yes\n" +- " right=11.12.13.14\n" +- " rightmodecfgserver=yes\n" +- " modecfgpull=yes\n" + " rightsubnet=0.0.0.0/0\n" + " leftxauthclient=yes\n" + " remote-peer-type=cisco\n" + " rightxauthserver=yes\n" + " ikelifetime=24h\n" + " salifetime=24h\n" +- " rekey=yes\n" + " keyingtries=1\n" +- " ikev2=never\n" +- " nm-configured=yes\n" +- " auto=add\n"); ++ " rekey=yes\n" ++ " rightmodecfgserver=yes\n" ++ " modecfgpull=yes\n"); + g_free (str); + +- s_vpn = nm_setting_vpn_new (); ++ s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); + nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "ikev2", "insist"); + nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "leftcert", "LibreswanClient"); + nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "leftid", "%fromcert"); + nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "right", "11.12.13.14"); +- str = _setting_into_ipsec_conf (s_vpn, +- "f0008435-07af-4836-a53d-b43e8730e68f", +- &error); ++ str = nm_libreswan_get_ipsec_conf (4, s_vpn, ++ "f0008435-07af-4836-a53d-b43e8730e68f", ++ NULL, FALSE, TRUE, &error); + g_assert_no_error (error); + g_assert_cmpstr (str, ==, + "conn f0008435-07af-4836-a53d-b43e8730e68f\n" ++ " ikev2=insist\n" ++ " right=11.12.13.14\n" + " leftid=%fromcert\n" +- " leftcert=LibreswanClient\n" +- " leftrsasigkey=%cert\n" +- " rightrsasigkey=%cert\n" ++ " leftcert=\"LibreswanClient\"\n" ++ " leftrsasigkey=\"%cert\"\n" ++ " rightrsasigkey=\"%cert\"\n" + " left=%defaultroute\n" + " leftmodecfgclient=yes\n" +- " right=11.12.13.14\n" +- " rightmodecfgserver=yes\n" +- " modecfgpull=yes\n" + " rightsubnet=0.0.0.0/0\n" +- " rekey=yes\n" + " keyingtries=1\n" +- " ikev2=insist\n" +- " nm-configured=yes\n" +- " auto=add\n"); ++ " rekey=yes\n" ++ " rightmodecfgserver=yes\n" ++ " modecfgpull=yes\n"); + g_free (str); + } + +diff --git a/shared/utils.c b/shared/utils.c +index 65bc603..2482311 100644 +--- a/shared/utils.c ++++ b/shared/utils.c +@@ -30,82 +30,109 @@ + #include + #include + +-gboolean +-write_config_option_newline (int fd, +- gboolean new_line, +- NMDebugWriteFcn debug_write_fcn, +- GError **error, +- const char *format, ...) ++static gboolean ++printable_val (GString *str, const char *val, GError **error) + { +- gs_free char *string = NULL; + const char *p; +- va_list args; +- gsize l; +- int errsv; +- gssize w; + +- va_start (args, format); +- string = g_strdup_vprintf (format, args); +- va_end (args); ++ g_return_val_if_fail (val, FALSE); + +- if (debug_write_fcn) +- debug_write_fcn (string); +- +- l = strlen (string); +- if (new_line) { +- gs_free char *s = string; +- +- string = g_new (char, l + 1 + 1); +- memcpy (string, s, l); +- string[l] = '\n'; +- string[l + 1] = '\0'; +- l++; ++ for (p = val; *p != '\0'; p++) { ++ /* Printable characters except " and space allowed. */ ++ if (*p != '"' && !g_ascii_isspace (*p) && g_ascii_isprint (*p)) ++ continue; ++ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, ++ _("Invalid character in '%s'"), val); ++ return FALSE; + } + +- p = string; +- while (true) { +- w = write (fd, p, l); +- if (w == l) +- return TRUE; +- if (w > 0) { +- g_assert (w < l); +- p += w; +- l -= w; +- continue; +- } +- if (w == 0) { +- errsv = EIO; +- break; +- } +- errsv = errno; +- if (errsv == EINTR) +- continue; +- break; +- } +- g_set_error (error, NMV_EDITOR_PLUGIN_ERROR, NMV_EDITOR_PLUGIN_ERROR, +- _("Error writing config: %s"), g_strerror (errsv)); +- return FALSE; ++ g_string_append (str, val); ++ g_string_append_c (str, '\n'); ++ return TRUE; + } + +-gboolean +-nm_libreswan_config_write (gint fd, +- int ipsec_version, +- NMConnection *connection, +- const char *con_name, +- const char *leftupdown_script, +- gboolean openswan, +- gboolean trailing_newline, +- NMDebugWriteFcn debug_write_fcn, +- GError **error) ++static gboolean ++string_val (GString *str, const char *val, GError **error) + { +- NMSettingVpn *s_vpn; +- const char *props_username; +- const char *default_username; ++ const char *p; ++ ++ g_return_val_if_fail (val, FALSE); ++ ++ for (p = val; *p != '\0'; p++) { ++ /* Printable characters except " allowed. */ ++ if (*p != '"' && g_ascii_isprint (*p)) ++ continue; ++ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, ++ _("Invalid character in '%s'"), val); ++ return FALSE; ++ } ++ ++ g_string_append_printf (str, "\"%s\"\n", val); ++ return TRUE; ++} ++ ++static inline gboolean ++optional_string_val (GString *str, const char *key, const char *val, GError **error) ++{ ++ if (val == NULL || val[0] == '\0') ++ return TRUE; ++ g_string_append_c (str, ' '); ++ g_string_append (str, key); ++ g_string_append_c (str, '='); ++ ++ if (!string_val (str, val, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), key); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static inline gboolean ++optional_printable_val (GString *str, const char *key, const char *val, GError **error) ++{ ++ if (val == NULL || val[0] == '\0') ++ return TRUE; ++ ++ g_string_append_c (str, ' '); ++ g_string_append (str, key); ++ g_string_append_c (str, '='); ++ ++ if (!printable_val (str, val, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), key); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++ ++static inline gboolean ++optional_printable (GString *str, NMSettingVpn *s_vpn, const char *key, GError **error) ++{ ++ return optional_printable_val (str, ++ key, ++ nm_setting_vpn_get_data_item (s_vpn, key), ++ error); ++} ++ ++char * ++nm_libreswan_get_ipsec_conf (int ipsec_version, ++ NMSettingVpn *s_vpn, ++ const char *con_name, ++ const char *leftupdown_script, ++ gboolean openswan, ++ gboolean trailing_newline, ++ GError **error) ++{ ++ nm_auto_free_gstring GString *ipsec_conf = NULL; ++ const char *username; + const char *phase1_alg_str; + const char *phase2_alg_str; + const char *phase1_lifetime_str; + const char *phase2_lifetime_str; + const char *left; ++ const char *right; + const char *leftid; + const char *leftcert; + const char *rightcert; +@@ -116,129 +143,176 @@ nm_libreswan_config_write (gint fd, + const char *remote_network; + const char *ikev2 = NULL; + const char *rightid; +- const char *narrowing; + const char *rekey; +- const char *fragmentation; +- const char *mobike; + const char *pfs; + const char *client_family; + const char *item; + gboolean is_ikev2 = FALSE; + +- g_return_val_if_fail (fd > 0, FALSE); +- g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); ++ g_return_val_if_fail (NM_IS_SETTING_VPN (s_vpn), FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + g_return_val_if_fail (con_name && *con_name, FALSE); + +- s_vpn = nm_connection_get_setting_vpn (connection); +- g_return_val_if_fail (NM_IS_SETTING_VPN (s_vpn), FALSE); ++ ipsec_conf = g_string_sized_new (1024); ++ g_string_append (ipsec_conf, "conn "); ++ if (!printable_val (ipsec_conf, con_name, error)) { ++ g_prefix_error (error, _("Bad connection name: ")); ++ return FALSE; ++ } + +- is_ikev2 = nm_libreswan_utils_setting_is_ikev2 (s_vpn, &ikev2); ++ if (leftupdown_script) { ++ g_string_append (ipsec_conf, " auto=add\n"); ++ g_string_append (ipsec_conf, " nm-configured=yes\n"); ++ g_string_append (ipsec_conf, " leftupdown="); ++ if (!string_val (ipsec_conf, leftupdown_script, error)) ++ g_return_val_if_reached (FALSE); ++ } + + /* When using IKEv1 (default in our plugin), we should ensure that we make + * it explicit to Libreswan (which now defaults to IKEv2): when crypto algorithms + * are not specified ("esp" & "ike") Libreswan will use system-wide crypto + * policies based on the IKE version in place. + */ ++ is_ikev2 = nm_libreswan_utils_setting_is_ikev2 (s_vpn, &ikev2); + if (!ikev2) + ikev2 = NM_LIBRESWAN_IKEV2_NEVER; ++ g_string_append (ipsec_conf, " ikev2="); ++ if (!printable_val (ipsec_conf, ikev2, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), "ikev2"); ++ return FALSE; ++ } ++ ++ right = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHT); ++ if (right && right[0] != '\0') { ++ g_string_append (ipsec_conf, " right="); ++ if (!printable_val (ipsec_conf, right, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), ++ NM_LIBRESWAN_KEY_RIGHT); ++ return FALSE; ++ } ++ } else { ++ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, ++ _("'%s' key needs to be present."), NM_LIBRESWAN_KEY_RIGHT); ++ return FALSE; ++ } + + leftid = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTID); +- +-#define WRITE_CHECK_NEWLINE(fd, new_line, debug_write_fcn, error, ...) \ +- G_STMT_START { \ +- if (!write_config_option_newline ((fd), (new_line), debug_write_fcn, (error), __VA_ARGS__)) \ +- return FALSE; \ +- } G_STMT_END +-#define WRITE_CHECK(fd, debug_write_fcn, error, ...) WRITE_CHECK_NEWLINE (fd, TRUE, debug_write_fcn, error, __VA_ARGS__) +- +- WRITE_CHECK (fd, debug_write_fcn, error, "conn %s", con_name); +- if (leftid && strlen (leftid)) { ++ if (leftid && leftid[0] != '\0') { + if (!is_ikev2) +- WRITE_CHECK (fd, debug_write_fcn, error, " aggrmode=yes"); ++ g_string_append (ipsec_conf, " aggrmode=yes\n"); + + if ( leftid[0] == '%' + || leftid[0] == '@' + || nm_utils_parse_inaddr_bin (AF_UNSPEC, leftid, NULL)) { +- WRITE_CHECK (fd, debug_write_fcn, error, " leftid=%s", leftid); ++ g_string_append (ipsec_conf, " leftid="); + } else +- WRITE_CHECK (fd, debug_write_fcn, error, " leftid=@%s", leftid); ++ g_string_append (ipsec_conf, " leftid=@"); ++ if (!printable_val (ipsec_conf, leftid, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), ++ NM_LIBRESWAN_KEY_LEFTID); ++ return FALSE; ++ } + } + +- item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_HOSTADDRFAMILY); +- if (item && strlen (item)) +- WRITE_CHECK (fd, debug_write_fcn, error, " hostaddrfamily=%s", item); ++ if (!optional_printable (ipsec_conf, s_vpn, NM_LIBRESWAN_KEY_HOSTADDRFAMILY, error)) ++ return FALSE; + + client_family = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_CLIENTADDRFAMILY); +- if (client_family && strlen (client_family)) +- WRITE_CHECK (fd, debug_write_fcn, error, " clientaddrfamily=%s", client_family); ++ if (client_family && client_family[0] != '\0') { ++ g_string_append (ipsec_conf, " clientaddrfamily="); ++ if (!printable_val (ipsec_conf, client_family, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), ++ NM_LIBRESWAN_KEY_CLIENTADDRFAMILY); ++ return FALSE; ++ } ++ } + + leftrsasigkey = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTRSASIGKEY); + rightrsasigkey = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHTRSASIGKEY); + leftcert = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTCERT); + rightcert = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHTCERT); + authby = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_AUTHBY); +- if (rightcert && strlen (rightcert)) { +- WRITE_CHECK (fd, debug_write_fcn, error, " rightcert=%s", rightcert); ++ if (rightcert && rightcert[0] != '\0') { ++ g_string_append (ipsec_conf, " rightcert="); ++ if (!string_val (ipsec_conf, rightcert, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), ++ NM_LIBRESWAN_KEY_RIGHTCERT); ++ return FALSE; ++ } + if (!rightrsasigkey) + rightrsasigkey = "%cert"; + } +- if (leftcert && strlen (leftcert)) { +- WRITE_CHECK (fd, debug_write_fcn, error, " leftcert=%s", leftcert); ++ if (leftcert && leftcert[0] != '\0') { ++ g_string_append (ipsec_conf, " leftcert="); ++ if (!string_val (ipsec_conf, leftcert, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), ++ NM_LIBRESWAN_KEY_LEFTCERT); ++ return FALSE; ++ } + if (!leftrsasigkey) + leftrsasigkey = "%cert"; + if (!rightrsasigkey) + rightrsasigkey = "%cert"; + } +- if (leftrsasigkey && strlen (leftrsasigkey)) +- WRITE_CHECK (fd, debug_write_fcn, error, " leftrsasigkey=%s", leftrsasigkey); +- if (rightrsasigkey && strlen (rightrsasigkey)) +- WRITE_CHECK (fd, debug_write_fcn, error, " rightrsasigkey=%s", rightrsasigkey); ++ if (!optional_string_val (ipsec_conf, NM_LIBRESWAN_KEY_LEFTRSASIGKEY, leftrsasigkey, error)) ++ return FALSE; ++ if (!optional_string_val (ipsec_conf, NM_LIBRESWAN_KEY_RIGHTRSASIGKEY, rightrsasigkey, error)) ++ return FALSE; + +- if (authby && strlen (authby)) { +- WRITE_CHECK (fd, debug_write_fcn, error, " authby=%s", authby); +- } else if ( !(leftrsasigkey && strlen (leftrsasigkey)) +- && !(rightrsasigkey && strlen (rightrsasigkey))) { +- WRITE_CHECK (fd, debug_write_fcn, error, " authby=secret"); ++ if (authby == NULL || authby[0] == '\0') { ++ if ( !(leftrsasigkey && leftrsasigkey[0] != '\0') ++ && !(rightrsasigkey && rightrsasigkey[0] != '\0')) { ++ authby = "secret"; ++ } + } ++ if (!optional_printable_val (ipsec_conf, NM_LIBRESWAN_KEY_AUTHBY, authby, error)) ++ return FALSE; + + left = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFT); +- if (left && strlen (left)) +- WRITE_CHECK (fd, debug_write_fcn, error, " left=%s", left); +- else +- WRITE_CHECK (fd, debug_write_fcn, error, " left=%%defaultroute"); ++ if (left == NULL || left[0] == '\0') ++ left = "%defaultroute"; ++ g_string_append (ipsec_conf, " left="); ++ if (!printable_val (ipsec_conf, left, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), ++ NM_LIBRESWAN_KEY_LEFT); ++ return FALSE; ++ } + + item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTMODECFGCLIENT); + if (nm_streq0 (item, "no")) { +- WRITE_CHECK (fd, debug_write_fcn, error, " leftmodecfgclient=no"); ++ g_string_append (ipsec_conf, " leftmodecfgclient=no\n"); + } else { +- WRITE_CHECK (fd, debug_write_fcn, error, " leftmodecfgclient=yes"); ++ g_string_append (ipsec_conf, " leftmodecfgclient=yes\n"); + } + +- if (leftupdown_script) +- WRITE_CHECK (fd, debug_write_fcn, error, " leftupdown=%s", leftupdown_script); +- +- WRITE_CHECK (fd, debug_write_fcn, error, " right=%s", nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHT)); + rightid = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHTID); +- if (rightid && strlen (rightid)) { ++ if (rightid && rightid[0] != '\0') { + if ( rightid[0] == '@' + || rightid[0] == '%' +- || nm_utils_parse_inaddr_bin (AF_UNSPEC, rightid, NULL)) { +- WRITE_CHECK (fd, debug_write_fcn, error, " rightid=%s", rightid); +- } else +- WRITE_CHECK (fd, debug_write_fcn, error, " rightid=@%s", rightid); ++ || nm_utils_parse_inaddr_bin (AF_UNSPEC, rightid, NULL)) { ++ g_string_append (ipsec_conf, " rightid="); ++ } else { ++ g_string_append (ipsec_conf, " rightid=@"); ++ } ++ if (!printable_val (ipsec_conf, rightid, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), ++ NM_LIBRESWAN_KEY_RIGHTID); ++ return FALSE; ++ } + } +- WRITE_CHECK (fd, debug_write_fcn, error, " rightmodecfgserver=yes"); +- WRITE_CHECK (fd, debug_write_fcn, error, " modecfgpull=yes"); +- + + local_network = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LOCALNETWORK); + if (local_network) { +- WRITE_CHECK (fd, debug_write_fcn, error, " leftsubnet=%s", local_network); ++ g_string_append (ipsec_conf, " leftsubnet="); ++ if (!printable_val (ipsec_conf, local_network, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), ++ NM_LIBRESWAN_KEY_LOCALNETWORK); ++ return FALSE; ++ } + } + + remote_network = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_REMOTENETWORK); +- if (!remote_network || !strlen (remote_network)) { ++ if (!remote_network || remote_network[0] == '\0') { + int addr_family = AF_UNSPEC; + + /* Detect the address family of the remote subnet. We use in order: +@@ -259,43 +333,50 @@ nm_libreswan_config_write (gint fd, + } + + if (addr_family == AF_INET6) { +- WRITE_CHECK (fd, debug_write_fcn, error, " rightsubnet=::/0"); ++ remote_network = "::/0"; + } else { + /* For backwards compatibility, if we can't determine the family + * assume it's IPv4. Anyway, in the future we need to stop adding + * the option automatically. */ +- WRITE_CHECK (fd, debug_write_fcn, error, " rightsubnet=0.0.0.0/0"); ++ remote_network = "0.0.0.0/0"; + } +- } else { +- WRITE_CHECK (fd, debug_write_fcn, error, " rightsubnet=%s", remote_network); ++ } ++ g_string_append (ipsec_conf, " rightsubnet="); ++ if (!printable_val (ipsec_conf, remote_network, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), ++ NM_LIBRESWAN_KEY_REMOTENETWORK); ++ return FALSE; + } + + if (!is_ikev2) { + /* When IKEv1 is in place, we enforce XAUTH: so, use IKE version + * also to check if XAUTH conf options should be passed to Libreswan. + */ +- WRITE_CHECK (fd, debug_write_fcn, error, " leftxauthclient=yes"); ++ g_string_append (ipsec_conf, " leftxauthclient=yes\n"); + +- default_username = nm_setting_vpn_get_user_name (s_vpn); +- props_username = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTXAUTHUSER); +- if (!props_username) +- props_username = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTUSERNAME); +- if (props_username && strlen (props_username)) +- WRITE_CHECK (fd, debug_write_fcn, error, +- ipsec_version >= 4 ? " leftusername=%s" : " leftxauthusername=%s", +- props_username); +- else if (default_username && strlen (default_username)) +- WRITE_CHECK (fd, debug_write_fcn, error, +- ipsec_version >= 4 ? " leftusername=%s" : " leftxauthusername=%s", +- default_username); ++ username = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTXAUTHUSER); ++ if (username == NULL || username[0] == '\0') ++ username = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTUSERNAME); ++ if (username == NULL || username[0] == '\0') ++ username = nm_setting_vpn_get_user_name (s_vpn); ++ if (username != NULL && username[0] != '\0') { ++ g_string_append (ipsec_conf, ++ ipsec_version >= 4 ? ++ " leftusername=" : ++ " leftxauthusername="); ++ if (!string_val (ipsec_conf, username, error)) { ++ g_prefix_error (error, _("Invalid username: ")); ++ return FALSE; ++ } ++ } + +- WRITE_CHECK (fd, debug_write_fcn, error, +- ipsec_version >= 4 ? " remote-peer-type=cisco" : " remote_peer_type=cisco"); +- WRITE_CHECK (fd, debug_write_fcn, error, " rightxauthserver=yes"); ++ g_string_append (ipsec_conf, ++ ipsec_version >= 4 ? ++ " remote-peer-type=cisco\n" : ++ " remote_peer_type=cisco\n"); ++ g_string_append (ipsec_conf, " rightxauthserver=yes\n"); + } + +- +- phase1_alg_str = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_IKE); + /* When the crypto is unspecified, let Libreswan use many sets of crypto + * proposals (just leave the property unset). An exception should be made + * for IKEv1 connections in aggressive mode: there the DH group in the crypto +@@ -304,84 +385,80 @@ nm_libreswan_config_write (gint fd, + * force the best proposal that should be accepted by all obsolete VPN SW/HW + * acting as a remote access VPN server. + */ +- if (phase1_alg_str && strlen (phase1_alg_str)) +- WRITE_CHECK (fd, debug_write_fcn, error, " ike=%s", phase1_alg_str); +- else if (!is_ikev2 && leftid) +- WRITE_CHECK (fd, debug_write_fcn, error, " ike=%s", NM_LIBRESWAN_AGGRMODE_DEFAULT_IKE); ++ phase1_alg_str = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_IKE); ++ if (phase1_alg_str == NULL || phase1_alg_str[0] == '\0') { ++ if (!is_ikev2 && leftid) ++ phase1_alg_str = NM_LIBRESWAN_AGGRMODE_DEFAULT_IKE; ++ } ++ if (!optional_string_val (ipsec_conf, NM_LIBRESWAN_KEY_IKE, phase1_alg_str, error)) ++ return FALSE; + + phase2_alg_str = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_ESP); +- if (phase2_alg_str && strlen (phase2_alg_str)) +- WRITE_CHECK (fd, debug_write_fcn, error, " phase2alg=%s", phase2_alg_str); +- else if (!is_ikev2 && leftid) +- WRITE_CHECK (fd, debug_write_fcn, error, " phase2alg=%s", NM_LIBRESWAN_AGGRMODE_DEFAULT_ESP); ++ if (phase2_alg_str == NULL || phase2_alg_str[0] == '\0') { ++ if (!is_ikev2 && leftid) ++ phase2_alg_str = NM_LIBRESWAN_AGGRMODE_DEFAULT_ESP; ++ } ++ if (!optional_string_val (ipsec_conf, "phase2alg", phase2_alg_str, error)) ++ return FALSE; + + pfs = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_PFS); + if (pfs && !strcmp (pfs, "no")) +- WRITE_CHECK (fd, debug_write_fcn, error, " pfs=no"); ++ g_string_append (ipsec_conf, " pfs=no\n"); + +- phase1_lifetime_str = nm_setting_vpn_get_data_item (s_vpn, +- NM_LIBRESWAN_KEY_IKELIFETIME); +- if (phase1_lifetime_str && strlen (phase1_lifetime_str)) +- WRITE_CHECK (fd, debug_write_fcn, error, " ikelifetime=%s", phase1_lifetime_str); +- else if (!is_ikev2) +- WRITE_CHECK (fd, debug_write_fcn, error, " ikelifetime=%s", NM_LIBRESWAN_IKEV1_DEFAULT_LIFETIME); ++ phase1_lifetime_str = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_IKELIFETIME); ++ if (phase1_lifetime_str == NULL || phase1_lifetime_str[0] == '\0') { ++ if (!is_ikev2) ++ phase1_lifetime_str = NM_LIBRESWAN_IKEV1_DEFAULT_LIFETIME; ++ } ++ if (!optional_printable_val (ipsec_conf, NM_LIBRESWAN_KEY_IKELIFETIME, phase1_lifetime_str, error)) ++ return FALSE; + +- phase2_lifetime_str = nm_setting_vpn_get_data_item (s_vpn, +- NM_LIBRESWAN_KEY_SALIFETIME); +- if (phase2_lifetime_str && strlen (phase2_lifetime_str)) +- WRITE_CHECK (fd, debug_write_fcn, error, " salifetime=%s", phase2_lifetime_str); +- else if (!is_ikev2) +- WRITE_CHECK (fd, debug_write_fcn, error, " salifetime=%s", NM_LIBRESWAN_IKEV1_DEFAULT_LIFETIME); ++ phase2_lifetime_str = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_SALIFETIME); ++ if (phase2_lifetime_str == NULL || phase2_lifetime_str[0] == '\0') { ++ if (!is_ikev2) ++ phase2_lifetime_str = NM_LIBRESWAN_IKEV1_DEFAULT_LIFETIME; ++ } ++ if (!optional_printable_val (ipsec_conf, NM_LIBRESWAN_KEY_SALIFETIME, phase2_lifetime_str, error)) ++ return FALSE; + + rekey = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_REKEY); +- if (!rekey || !strlen (rekey)) { +- WRITE_CHECK (fd, debug_write_fcn, error, " rekey=yes"); +- WRITE_CHECK (fd, debug_write_fcn, error, " keyingtries=1"); +- } else +- WRITE_CHECK (fd, debug_write_fcn, error, " rekey=%s", rekey); ++ if (!rekey || rekey[0] == '\0') { ++ g_string_append (ipsec_conf, " keyingtries=1\n"); ++ rekey = "yes"; ++ } ++ g_string_append (ipsec_conf, " rekey="); ++ if (!printable_val (ipsec_conf, rekey, error)) { ++ g_prefix_error (error, _("Invalid value for '%s': "), ++ NM_LIBRESWAN_KEY_REKEY); ++ return FALSE; ++ } + + if (!openswan && g_strcmp0 (nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_VENDOR), "Cisco") == 0) +- WRITE_CHECK (fd, debug_write_fcn, error, " cisco-unity=yes"); ++ g_string_append (ipsec_conf, " cisco-unity=yes\n"); + +- WRITE_CHECK (fd, debug_write_fcn, error, " ikev2=%s", ikev2); ++ if (!optional_printable (ipsec_conf, s_vpn, NM_LIBRESWAN_KEY_NARROWING, error)) ++ return FALSE; ++ if (!optional_printable (ipsec_conf, s_vpn, NM_LIBRESWAN_KEY_FRAGMENTATION, error)) ++ return FALSE; ++ if (!optional_printable (ipsec_conf, s_vpn, NM_LIBRESWAN_KEY_MOBIKE, error)) ++ return FALSE; ++ if (!optional_printable (ipsec_conf, s_vpn, NM_LIBRESWAN_KEY_DPDDELAY, error)) ++ return FALSE; ++ if (!optional_printable (ipsec_conf, s_vpn, NM_LIBRESWAN_KEY_DPDTIMEOUT, error)) ++ return FALSE; ++ if (!optional_printable (ipsec_conf, s_vpn, NM_LIBRESWAN_KEY_DPDACTION, error)) ++ return FALSE; ++ if (!optional_printable (ipsec_conf, s_vpn, NM_LIBRESWAN_KEY_IPSEC_INTERFACE, error)) ++ return FALSE; ++ if (!optional_printable (ipsec_conf, s_vpn, NM_LIBRESWAN_KEY_TYPE, error)) ++ return FALSE; + +- narrowing = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_NARROWING); +- if (narrowing && strlen (narrowing)) +- WRITE_CHECK (fd, debug_write_fcn, error, " narrowing=%s", narrowing); ++ g_string_append (ipsec_conf, " rightmodecfgserver=yes\n"); ++ g_string_append (ipsec_conf, " modecfgpull=yes"); ++ if (trailing_newline) ++ g_string_append_c (ipsec_conf, '\n'); + +- fragmentation = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_FRAGMENTATION); +- if (fragmentation && strlen (fragmentation)) +- WRITE_CHECK (fd, debug_write_fcn, error, " fragmentation=%s", fragmentation); +- +- mobike = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_MOBIKE); +- if (mobike && strlen (mobike)) +- WRITE_CHECK (fd, debug_write_fcn, error, " mobike=%s", mobike); +- +- item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_DPDDELAY); +- if (item && strlen (item)) +- WRITE_CHECK (fd, debug_write_fcn, error, " dpddelay=%s", item); +- +- item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_DPDTIMEOUT); +- if (item && strlen (item)) +- WRITE_CHECK (fd, debug_write_fcn, error, " dpdtimeout=%s", item); +- +- item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_DPDACTION); +- if (item && strlen (item)) +- WRITE_CHECK (fd, debug_write_fcn, error, " dpdaction=%s", item); +- +- item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_IPSEC_INTERFACE); +- if (item && strlen (item)) +- WRITE_CHECK (fd, debug_write_fcn, error, " ipsec-interface=%s", item); +- +- item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_TYPE); +- if (item && strlen (item)) +- WRITE_CHECK (fd, debug_write_fcn, error, " type=%s", item); +- +- WRITE_CHECK (fd, debug_write_fcn, error, " nm-configured=yes"); +- +- WRITE_CHECK_NEWLINE (fd, trailing_newline, debug_write_fcn, error, " auto=add"); +- +- return TRUE; ++ return g_string_free (g_steal_pointer (&ipsec_conf), FALSE); + } + + static const char * +diff --git a/shared/utils.h b/shared/utils.h +index 7e89841..2e2450c 100644 +--- a/shared/utils.h ++++ b/shared/utils.h +@@ -24,27 +24,13 @@ + #ifndef __UTILS_H__ + #define __UTILS_H__ + +-typedef void (*NMDebugWriteFcn) (const char *setting); +- +-__attribute__((__format__ (__printf__, 5, 6))) +-gboolean write_config_option_newline (int fd, +- gboolean new_line, +- NMDebugWriteFcn debug_write_fcn, +- GError **error, +- const char *format, ...); +- +-#define write_config_option(fd, debug_write_fcn, error, ...) write_config_option_newline((fd), TRUE, debug_write_fcn, error, __VA_ARGS__) +- +-gboolean +-nm_libreswan_config_write (gint fd, +- int ipsec_version, +- NMConnection *connection, +- const char *con_name, +- const char *leftupdown_script, +- gboolean openswan, +- gboolean trailing_newline, +- NMDebugWriteFcn debug_write_fcn, +- GError **error); ++char *nm_libreswan_get_ipsec_conf (int ipsec_version, ++ NMSettingVpn *s_vpn, ++ const char *con_name, ++ const char *leftupdown_script, ++ gboolean openswan, ++ gboolean trailing_newline, ++ GError **error); + + static inline gboolean + nm_libreswan_utils_setting_is_ikev2 (NMSettingVpn *s_vpn, const char **out_ikev2) +diff --git a/src/nm-libreswan-service.c b/src/nm-libreswan-service.c +index e5956af..35f602c 100644 +--- a/src/nm-libreswan-service.c ++++ b/src/nm-libreswan-service.c +@@ -101,12 +101,13 @@ typedef struct { + const char *whack_path; + char *secrets_path; + ++ char *ipsec_conf; ++ + gboolean openswan; + gboolean interactive; + gboolean pending_auth; + gboolean managed; + gboolean xauth_enabled; +- int version; + + GPid pid; + guint watch_id; +@@ -152,12 +153,6 @@ _LOGD_enabled (void) + #define _LOGW(...) _NMLOG(LOG_WARNING, __VA_ARGS__) + #define _LOGE(...) _NMLOG(LOG_EMERG, __VA_ARGS__) + +-static void +-_debug_write_option (const char *setting) +-{ +- _LOGD ("Config %s", setting); +-} +- + /****************************************************************/ + + static gboolean pr_cb (GIOChannel *source, GIOCondition condition, gpointer user_data); +@@ -666,9 +661,9 @@ nm_libreswan_config_psk_write (NMSettingVpn *s_vpn, + GError **error) + { + const char *pw_type, *psk, *leftid, *right; +- int fd; +- int errsv; +- gboolean success; ++ gs_free const char *secrets = NULL; ++ mode_t old_mask; ++ gboolean res; + + /* Check for ignored group password */ + pw_type = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_PSK_INPUT_MODES); +@@ -679,47 +674,32 @@ nm_libreswan_config_psk_write (NMSettingVpn *s_vpn, + if (!psk) + return TRUE; + +- /* Write the PSK */ +- errno = 0; +- fd = open (secrets_path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); +- if (fd < 0) { +- errsv = errno; +- +- if (errsv == ENOENT) { +- gs_free char *dirname = g_path_get_dirname (secrets_path); +- +- if (!g_file_test (dirname, G_FILE_TEST_IS_DIR)) { +- g_set_error (error, +- NM_VPN_PLUGIN_ERROR, +- NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, +- "Failed to open secrets file: no directory %s", +- dirname); +- return FALSE; +- } +- } +- +- g_set_error (error, +- NM_VPN_PLUGIN_ERROR, +- NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, +- "Failed to open secrets file: (%d) %s.", +- errsv, g_strerror (errsv)); +- return FALSE; +- } +- + leftid = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTID); + if (leftid) { +- success = write_config_option (fd, NULL, error, "@%s: PSK \"%s\"", leftid, psk); ++ if (strchr (leftid, '"') || strchr (leftid, '\n')) { ++ g_set_error_literal (error, ++ NM_VPN_PLUGIN_ERROR, ++ NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION, ++ _("Invalid character in password.")); ++ return FALSE; ++ } ++ secrets = g_strdup_printf ("@%s: PSK \"%s\"", leftid, psk); + } else { + right = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHT); +- g_assert (right); +- success = write_config_option (fd, NULL, error, "%s %%any: PSK \"%s\"", right, psk); ++ ++ /* nm_libreswan_get_ipsec_conf() in _connect_common should've check these. */ ++ g_return_val_if_fail (right != NULL, FALSE); ++ g_return_val_if_fail (strchr (right, '"') == NULL, FALSE); ++ g_return_val_if_fail (strchr (right, '\n') == NULL, FALSE); ++ ++ secrets = g_strdup_printf ("%s %%any: PSK \"%s\"", right, psk); + } + +- if (!success) { +- g_close (fd, NULL); +- return FALSE; +- } +- return g_close (fd, error); ++ ++ old_mask = umask (S_IRWXG | S_IRWXO); ++ res = g_file_set_contents (secrets_path, secrets, -1, error); ++ umask (old_mask); ++ return res; + } + + /****************************************************************/ +@@ -1766,6 +1746,44 @@ done: + return success ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE; + } + ++static gboolean ++write_config (int fd, ++ const char *string, ++ GError **error) ++{ ++ const char *p; ++ gsize l; ++ int errsv; ++ gssize w; ++ ++ _LOGD ("Config %s", string); ++ ++ l = strlen (string); ++ p = string; ++ while (true) { ++ w = write (fd, p, l); ++ if (w == l) ++ return TRUE; ++ if (w > 0) { ++ g_assert (w < l); ++ p += w; ++ l -= w; ++ continue; ++ } ++ if (w == 0) { ++ errsv = EIO; ++ break; ++ } ++ errsv = errno; ++ if (errsv == EINTR) ++ continue; ++ break; ++ } ++ g_set_error (error, NMV_EDITOR_PLUGIN_ERROR, NMV_EDITOR_PLUGIN_ERROR, ++ _("Error writing config: %s"), g_strerror (errsv)); ++ return FALSE; ++} ++ + static gboolean + connect_step (NMLibreswanPlugin *self, GError **error) + { +@@ -1848,37 +1866,12 @@ connect_step (NMLibreswanPlugin *self, GError **error) + return TRUE; + + case CONNECT_STEP_CONFIG_ADD: { +- gboolean trailing_newline; +- gs_free char *bus_name = NULL; +- gs_free char *ifupdown_script = NULL; + + if (!do_spawn (self, &priv->pid, &fd, NULL, error, priv->ipsec_path, + "auto", "--replace", "--config", "-", uuid, NULL)) + return FALSE; + priv->watch_id = g_child_watch_add (priv->pid, child_watch_cb, self); +- g_object_get (self, NM_VPN_SERVICE_PLUGIN_DBUS_SERVICE_NAME, &bus_name, NULL); +- +- /* openswan requires a terminating \n (otherwise it segfaults) while +- * libreswan fails parsing the configuration if you include the \n. +- * WTF? +- */ +- trailing_newline = priv->openswan; +- +- ifupdown_script = g_strdup_printf ("\"%s %d %ld %s\"", +- NM_LIBRESWAN_HELPER_PATH, +- LOG_DEBUG, +- (long) getpid (), +- bus_name); +- +- if (!nm_libreswan_config_write (fd, +- priv->version, +- priv->connection, +- uuid, +- ifupdown_script, +- priv->openswan, +- trailing_newline, +- _debug_write_option, +- error)) { ++ if (!write_config (fd, priv->ipsec_conf, error)) { + g_close (fd, NULL); + return FALSE; + } +@@ -1928,19 +1921,31 @@ _connect_common (NMVpnServicePlugin *plugin, + NMSettingVpn *s_vpn; + const char *con_name = nm_connection_get_uuid (connection); + gs_free char *ipsec_banner = NULL; ++ gs_free char *ifupdown_script = NULL; ++ gs_free char *bus_name = NULL; ++ gboolean trailing_newline; ++ int version; + + if (_LOGD_enabled ()) { + _LOGD ("connection:"); + nm_connection_dump (connection); + } + ++ if (priv->connect_step != CONNECT_STEP_FIRST) { ++ g_set_error_literal (error, ++ NM_VPN_PLUGIN_ERROR, ++ NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, ++ "Already connecting!"); ++ return FALSE; ++ } ++ + priv->ipsec_path = nm_libreswan_find_helper_bin ("ipsec", error); + if (!priv->ipsec_path) + return FALSE; + +- nm_libreswan_detect_version (priv->ipsec_path, &priv->openswan, &priv->version, &ipsec_banner); ++ nm_libreswan_detect_version (priv->ipsec_path, &priv->openswan, &version, &ipsec_banner); + _LOGD ("ipsec: version banner: %s", ipsec_banner); +- _LOGD ("ipsec: detected version %d (%s)", priv->version, priv->openswan ? "Openswan" : "Libreswan"); ++ _LOGD ("ipsec: detected version %d (%s)", version, priv->openswan ? "Openswan" : "Libreswan"); + + if (!priv->openswan) { + priv->pluto_path = nm_libreswan_find_helper_libexec ("pluto", error); +@@ -1960,13 +1965,31 @@ _connect_common (NMVpnServicePlugin *plugin, + if (!nm_libreswan_secrets_validate (s_vpn, error)) + return FALSE; + +- if (priv->connect_step != CONNECT_STEP_FIRST) { +- g_set_error_literal (error, +- NM_VPN_PLUGIN_ERROR, +- NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, +- "Already connecting!"); ++ g_object_get (self, NM_VPN_SERVICE_PLUGIN_DBUS_SERVICE_NAME, &bus_name, NULL); ++ ++ ifupdown_script = g_strdup_printf ("%s %d %ld %s", ++ NM_LIBRESWAN_HELPER_PATH, ++ LOG_DEBUG, ++ (long) getpid (), ++ bus_name); ++ ++ /* openswan requires a terminating \n (otherwise it segfaults) while ++ * libreswan fails parsing the configuration if you include the \n. ++ * WTF? ++ */ ++ trailing_newline = priv->openswan; ++ ++ /* Compose the ipsec.conf early, to catch configuration errors before ++ * we initiate the conneciton. */ ++ priv->ipsec_conf = nm_libreswan_get_ipsec_conf (version, ++ s_vpn, ++ con_name, ++ ifupdown_script, ++ priv->openswan, ++ trailing_newline, ++ error); ++ if (priv->ipsec_conf == NULL) + return FALSE; +- } + + /* XAUTH is not part of the IKEv2 standard and we always enforce it in IKEv1 */ + priv->xauth_enabled = !nm_libreswan_utils_setting_is_ikev2 (s_vpn, NULL); +@@ -2141,6 +2164,7 @@ real_disconnect (NMVpnServicePlugin *plugin, GError **error) + priv->watch_id = g_child_watch_add (priv->pid, child_watch_cb, plugin); + + g_clear_object (&priv->connection); ++ g_clear_pointer (&priv->ipsec_conf, g_free); + + return ret; + } +@@ -2173,6 +2197,7 @@ finalize (GObject *object) + { + NMLibreswanPluginPrivate *priv = NM_LIBRESWAN_PLUGIN_GET_PRIVATE (object); + ++ g_clear_pointer (&priv->ipsec_conf, g_free); + delete_secrets_file (NM_LIBRESWAN_PLUGIN (object)); + connect_cleanup (NM_LIBRESWAN_PLUGIN (object)); + g_clear_object (&priv->connection); +-- +2.46.0 + +From 8cbc188222d6a3dcff7ed937d44415f75e34b503 Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Tue, 24 Sep 2024 10:55:02 +0200 +Subject: [PATCH 6/6] shared/test-utils: add more test cases + +Test ipsec.conf formatting more thoroughly, include negative cases. + +[lkundrak@v3.sk: Backported from 1.24.0] +--- + shared/test-utils.c | 82 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 82 insertions(+) + +diff --git a/shared/test-utils.c b/shared/test-utils.c +index 49aa32a..0a92d2b 100644 +--- a/shared/test-utils.c ++++ b/shared/test-utils.c +@@ -2,6 +2,8 @@ + + #include "utils.h" + ++#include "nm-utils/nm-shared-utils.h" ++ + static void + test_config_write (void) + { +@@ -57,6 +59,86 @@ test_config_write (void) + " rightmodecfgserver=yes\n" + " modecfgpull=yes\n"); + g_free (str); ++ ++ s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "ikev2", "insist"); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "leftrsasigkey", "hello"); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "rightrsasigkey", "world"); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "right", "11.12.13.14"); ++ 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" ++ " leftrsasigkey=\"hello\"\n" ++ " rightrsasigkey=\"world\"\n" ++ " left=%defaultroute\n" ++ " leftmodecfgclient=yes\n" ++ " rightsubnet=0.0.0.0/0\n" ++ " keyingtries=1\n" ++ " rekey=yes\n" ++ " rightmodecfgserver=yes\n" ++ " modecfgpull=yes\n"); ++ g_free (str); ++ ++ ++ s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "right", "11.12.13.14"); ++ str = nm_libreswan_get_ipsec_conf (3, s_vpn, ++ "my_con", ++ "/foo/bar/ifupdown hello 123 456", ++ TRUE, FALSE, &error); ++ g_assert_no_error (error); ++ g_assert_cmpstr (str, ==, ++ "conn my_con\n" ++ " auto=add\n" ++ " nm-configured=yes\n" ++ " leftupdown=\"/foo/bar/ifupdown hello 123 456\"\n" ++ " ikev2=never\n" ++ " right=11.12.13.14\n" ++ " authby=secret\n" ++ " left=%defaultroute\n" ++ " leftmodecfgclient=yes\n" ++ " rightsubnet=0.0.0.0/0\n" ++ " leftxauthclient=yes\n" ++ " remote_peer_type=cisco\n" ++ " rightxauthserver=yes\n" ++ " ikelifetime=24h\n" ++ " salifetime=24h\n" ++ " keyingtries=1\n" ++ " rekey=yes\n" ++ " rightmodecfgserver=yes\n" ++ " modecfgpull=yes"); ++ g_free (str); ++ ++ 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); ++ g_assert_null (str); ++ g_clear_error (&error); ++ ++ s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "right", "11.12.13.14"); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "ikev2", "hello world"); ++ 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); ++ ++ s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(s_vpn), "right", "11.12\n13.14"); ++ 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); ++ ++ s_vpn = NM_SETTING_VPN (nm_setting_vpn_new ()); ++ nm_setting_vpn_add_data_item (NM_SETTING_VPN(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); + } + + int +-- +2.46.0 + diff --git a/SOURCES/0001-service-properties-add-support-for-leftmodecfgclient.patch b/SOURCES/0001-service-properties-add-support-for-leftmodecfgclient.patch deleted file mode 100644 index f66bf0f..0000000 --- a/SOURCES/0001-service-properties-add-support-for-leftmodecfgclient.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0f0b2d375901e302e8a619e3911321f511b52885 Mon Sep 17 00:00:00 2001 -From: Beniamino Galvani -Date: Tue, 9 Jan 2024 23:30:42 +0100 -Subject: [PATCH 1/5] service,properties: add support for leftmodecfgclient - -Previously the plugin always set leftmodecfgclient=yes, which is used -for roaming clients to obtain a dynamic IP. In a server-to-server -scenario we don't want that option; allow omitting it by passing -leftmodecfgclient=no. It's somehow confusing that the new option has -the opposite default value than Libreswan, but that's the only way to -keep backwards compatibility for existing configurations. ---- - properties/nm-libreswan-dialog.ui | 26 +++++++++++++++++++++++++ - properties/nm-libreswan-editor-plugin.c | 2 ++ - properties/nm-libreswan-editor.c | 9 +++++++++ - shared/nm-service-defines.h | 1 + - shared/utils.c | 8 +++++++- - src/nm-libreswan-service.c | 1 + - 6 files changed, 46 insertions(+), 1 deletion(-) - -diff --git a/properties/nm-libreswan-editor-plugin.c b/properties/nm-libreswan-editor-plugin.c -index b5c0d9e..89243cc 100644 ---- a/properties/nm-libreswan-editor-plugin.c -+++ b/properties/nm-libreswan-editor-plugin.c -@@ -182,6 +182,8 @@ import_from_file (NMVpnEditorPlugin *self, - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTUSERNAME, &str[13]); - else if (g_str_has_prefix (str, "leftcert=")) - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTCERT, &str[9]); -+ else if (nm_streq0 (str, "leftmodecfgclient=no")) -+ nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTMODECFGCLIENT, "no"); - else if (g_str_has_prefix (str, "pfs=no")) - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_PFS, "no"); - else if (g_str_has_prefix (str, "cisco-unity=yes")) -diff --git a/shared/nm-service-defines.h b/shared/nm-service-defines.h -index 3fdf2ef..14170ad 100644 ---- a/shared/nm-service-defines.h -+++ b/shared/nm-service-defines.h -@@ -41,6 +41,7 @@ - #define NM_LIBRESWAN_KEY_LEFTID "leftid" - #define NM_LIBRESWAN_KEY_LEFTRSASIGKEY "leftrsasigkey" - #define NM_LIBRESWAN_KEY_LEFTCERT "leftcert" -+#define NM_LIBRESWAN_KEY_LEFTMODECFGCLIENT "leftmodecfgclient" - #define NM_LIBRESWAN_KEY_AUTHBY "authby" - #define NM_LIBRESWAN_KEY_PSK_VALUE "pskvalue" - #define NM_LIBRESWAN_KEY_PSK_INPUT_MODES "pskinputmodes" -diff --git a/shared/utils.c b/shared/utils.c -index cbc117c..0bac9e6 100644 ---- a/shared/utils.c -+++ b/shared/utils.c -@@ -191,7 +191,13 @@ nm_libreswan_config_write (gint fd, - else - WRITE_CHECK (fd, debug_write_fcn, error, " left=%%defaultroute"); - -- WRITE_CHECK (fd, debug_write_fcn, error, " leftmodecfgclient=yes"); -+ item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTMODECFGCLIENT); -+ if (nm_streq0 (item, "no")) { -+ WRITE_CHECK (fd, debug_write_fcn, error, " leftmodecfgclient=no"); -+ } else { -+ WRITE_CHECK (fd, debug_write_fcn, error, " leftmodecfgclient=yes"); -+ } -+ - if (leftupdown_script) - WRITE_CHECK (fd, debug_write_fcn, error, " leftupdown=%s", leftupdown_script); - -diff --git a/src/nm-libreswan-service.c b/src/nm-libreswan-service.c -index fc470a6..874f767 100644 ---- a/src/nm-libreswan-service.c -+++ b/src/nm-libreswan-service.c -@@ -256,6 +256,7 @@ static ValidProperty valid_properties[] = { - { NM_LIBRESWAN_KEY_LEFTUSERNAME, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_LEFTRSASIGKEY, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_LEFTCERT, G_TYPE_STRING, 0, 0 }, -+ { NM_LIBRESWAN_KEY_LEFTMODECFGCLIENT, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_AUTHBY, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_DOMAIN, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_DHGROUP, G_TYPE_STRING, 0, 0 }, --- -2.43.0 - diff --git a/SOURCES/0002-service-use-new-API-to-send-configuration-to-NM.patch b/SOURCES/0002-service-use-new-API-to-send-configuration-to-NM.patch deleted file mode 100644 index 6c4d2d9..0000000 --- a/SOURCES/0002-service-use-new-API-to-send-configuration-to-NM.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 09ee8838162cb6ea097375fb7d8b698566bb1c4d Mon Sep 17 00:00:00 2001 -From: Beniamino Galvani -Date: Wed, 10 Jan 2024 09:29:50 +0100 -Subject: [PATCH 2/5] service: use new API to send configuration to NM - -Instead of emitting the "Ip4Config" signal that contains both generic -and IPv4 configurations, use the more recent API and send two signals: -"Config" for the generic configuration and "Ip4Config" for IPv4 -configuration. - -In this way, it will be possible in the next commit to return no IPv4 -configuration at all. ---- - src/nm-libreswan-service.c | 61 +++++++++++++++++++++++++------------- - 1 file changed, 40 insertions(+), 21 deletions(-) - -diff --git a/src/nm-libreswan-service.c b/src/nm-libreswan-service.c -index 874f767..2aca78f 100644 ---- a/src/nm-libreswan-service.c -+++ b/src/nm-libreswan-service.c -@@ -1270,16 +1270,14 @@ handle_callback (NMDBusLibreswanHelper *object, - goto out; - } - -+ /* First build and send the generic config */ - g_variant_builder_init (&config, G_VARIANT_TYPE_VARDICT); - -- /* Right peer (or Gateway) */ -- val = addr4_to_gvariant (lookup_string (env, "PLUTO_PEER")); -- if (val) -- g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY, val); -- else { -- _LOGW ("IPsec/Pluto Right Peer (VPN Gateway)"); -- goto out; -- } -+ /* -+ * Enabled address families -+ */ -+ g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP4, g_variant_new_boolean (TRUE)); -+ g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP6, g_variant_new_boolean (FALSE)); - - /* - * Tunnel device -@@ -1290,15 +1288,43 @@ handle_callback (NMDBusLibreswanHelper *object, - } else { - val = g_variant_new_string (NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV_NONE); - } -+ g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_CONFIG_TUNDEV, val); -+ -+ /* Banner */ -+ val = str_to_gvariant (lookup_string (env, "PLUTO_PEER_BANNER"), TRUE); -+ if (val) -+ g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_CONFIG_BANNER, val); -+ -+ /* Right peer (or Gateway) */ -+ val = addr4_to_gvariant (lookup_string (env, "PLUTO_PEER")); -+ if (val) -+ g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY, val); -+ else { -+ _LOGW ("IPsec/Pluto Right Peer (VPN Gateway) is missing"); -+ goto out; -+ } -+ -+ nm_vpn_service_plugin_set_config (NM_VPN_SERVICE_PLUGIN (user_data), -+ g_variant_builder_end (&config)); - -- g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val); -+ /* Then build and send the IPv4 config */ -+ g_variant_builder_init (&config, G_VARIANT_TYPE_VARDICT); -+ -+ /* Right peer (or Gateway) */ -+ val = addr4_to_gvariant (lookup_string (env, "PLUTO_PEER")); -+ if (val) -+ g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY, val); -+ else { -+ _LOGW ("IPsec/Pluto Right Peer (VPN Gateway) is missing"); -+ goto out; -+ } - - /* IP address */ - val = addr4_to_gvariant (lookup_string (env, "PLUTO_MY_SOURCEIP")); - if (val) - g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val); - else { -- _LOGW ("IP4 Address"); -+ _LOGW ("IP4 Address is missing"); - goto out; - } - -@@ -1307,7 +1333,7 @@ handle_callback (NMDBusLibreswanHelper *object, - if (val) - g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PTP, val); - else { -- _LOGW ("IP4 PTP Address"); -+ _LOGW ("IP4 PTP Address is missing"); - goto out; - } - -@@ -1324,7 +1350,6 @@ handle_callback (NMDBusLibreswanHelper *object, - if (val) - g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DNS, val); - -- - /* Default domain */ - val = str_to_gvariant (lookup_string (env, "PLUTO_CISCO_DOMAIN_INFO"), TRUE); - if (!val) { -@@ -1334,11 +1359,6 @@ handle_callback (NMDBusLibreswanHelper *object, - if (val) - g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN, val); - -- /* Banner */ -- val = str_to_gvariant (lookup_string (env, "PLUTO_PEER_BANNER"), TRUE); -- if (val) -- g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_BANNER, val); -- - /* Indicates whether the VPN is using a XFRM interface (via option ipsec-interface=) */ - is_xfrmi = nm_streq0 (lookup_string (env, "PLUTO_XFRMI_ROUTE"), "yes"); - -@@ -1369,12 +1389,11 @@ handle_callback (NMDBusLibreswanHelper *object, - g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT, g_variant_new_boolean (TRUE)); - - success = TRUE; -+ nm_vpn_service_plugin_set_ip4_config (NM_VPN_SERVICE_PLUGIN (user_data), -+ g_variant_builder_end (&config)); - - out: -- if (success) { -- nm_vpn_service_plugin_set_ip4_config (NM_VPN_SERVICE_PLUGIN (user_data), -- g_variant_builder_end (&config)); -- } else { -+ if (!success) { - connect_failed (NM_LIBRESWAN_PLUGIN (user_data), NULL, - NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); - } --- -2.43.0 - diff --git a/SOURCES/0003-service-don-t-send-IPv4-config-if-mode-config-client.patch b/SOURCES/0003-service-don-t-send-IPv4-config-if-mode-config-client.patch deleted file mode 100644 index 11d8fcc..0000000 --- a/SOURCES/0003-service-don-t-send-IPv4-config-if-mode-config-client.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 74ec0f7dc18939dd4a5992584527ab044b284fc0 Mon Sep 17 00:00:00 2001 -From: Beniamino Galvani -Date: Wed, 10 Jan 2024 09:31:48 +0100 -Subject: [PATCH 3/5] service: don't send IPv4 config if mode config client is - disabled - -If the mode config client is disabled (i.e. in server-to-server -scenario) we are not going to receive a dynamic IP. The IP address -already configured on the existing interface is enough. ---- - src/nm-libreswan-service.c | 20 +++++++++++++++++++- - 1 file changed, 19 insertions(+), 1 deletion(-) - -diff --git a/src/nm-libreswan-service.c b/src/nm-libreswan-service.c -index 2aca78f..12cf6f2 100644 ---- a/src/nm-libreswan-service.c -+++ b/src/nm-libreswan-service.c -@@ -1253,6 +1253,7 @@ handle_callback (NMDBusLibreswanHelper *object, - gpointer user_data) - { - NMLibreswanPluginPrivate *priv = NM_LIBRESWAN_PLUGIN_GET_PRIVATE (user_data); -+ NMSettingVpn *s_vpn; - GVariantBuilder config; - GVariantBuilder builder; - GVariant *val; -@@ -1260,7 +1261,9 @@ handle_callback (NMDBusLibreswanHelper *object, - guint i; - const char *verb; - const char *virt_if; -+ const char *str; - gboolean is_xfrmi = FALSE; -+ gboolean has_ip4; - - _LOGI ("Configuration from the helper received."); - -@@ -1273,10 +1276,21 @@ handle_callback (NMDBusLibreswanHelper *object, - /* First build and send the generic config */ - g_variant_builder_init (&config, G_VARIANT_TYPE_VARDICT); - -+ if ( priv->connection -+ && (s_vpn = nm_connection_get_setting_vpn (priv->connection)) -+ && (str = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTMODECFGCLIENT)) -+ && nm_streq (str, "no")) { -+ has_ip4 = FALSE; -+ } else { -+ has_ip4 = TRUE; -+ } -+ -+ _LOGD ("Configuration has IPv4: %d", has_ip4); -+ - /* - * Enabled address families - */ -- g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP4, g_variant_new_boolean (TRUE)); -+ g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP4, g_variant_new_boolean (has_ip4)); - g_variant_builder_add (&config, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP6, g_variant_new_boolean (FALSE)); - - /* -@@ -1306,6 +1320,10 @@ handle_callback (NMDBusLibreswanHelper *object, - - nm_vpn_service_plugin_set_config (NM_VPN_SERVICE_PLUGIN (user_data), - g_variant_builder_end (&config)); -+ if (!has_ip4) { -+ success = TRUE; -+ goto out; -+ } - - /* Then build and send the IPv4 config */ - g_variant_builder_init (&config, G_VARIANT_TYPE_VARDICT); --- -2.43.0 - diff --git a/SOURCES/0004-service-fix-wrong-refcounting-in-D-Bus-handler-for-C.patch b/SOURCES/0004-service-fix-wrong-refcounting-in-D-Bus-handler-for-C.patch deleted file mode 100644 index d0a3624..0000000 --- a/SOURCES/0004-service-fix-wrong-refcounting-in-D-Bus-handler-for-C.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 8ceb901719acac3778e1d76779d9c14289185157 Mon Sep 17 00:00:00 2001 -From: Beniamino Galvani -Date: Sat, 13 Jan 2024 18:10:02 +0100 -Subject: [PATCH 4/5] service: fix wrong refcounting in D-Bus handler for - Callback() - -The Callback() D-Bus method is handled via a GDBus-generated skeleton -code in nm-libreswan-helper-service-dbus.c, function -_nmdbus_libreswan_helper_skeleton_handle_method_call(). The function -emits signal "handle-callback" to let the program handle the incoming -method. As documented in the GDoc comments, the signal handler must -return TRUE if it handles the call. - -``` - /** - * NMDBusLibreswanHelper::handle-callback: - * @object: A #NMDBusLibreswanHelper. - * @invocation: A #GDBusMethodInvocation. - * @arg_environment: Argument passed by remote caller. - - * Signal emitted when a remote caller is invoking the Callback() - D-Bus method. - - * If a signal handler returns %TRUE, it means the signal handler - will handle the invocation (e.g. take a reference to @invocation - and eventually call nmdbus_libreswan_helper_complete_callback() - or e.g. g_dbus_method_invocation_return_error() on it) and no - other signal handlers will run. If no signal handler handles the - invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned. - - * Returns: %G_DBUS_METHOD_INVOCATION_HANDLED or %TRUE if the - invocation was handled, %G_DBUS_METHOD_INVOCATION_UNHANDLED or - %FALSE to let other signal handlers run. - */ -``` - -At the moment, in case of error the handler first calls -nmdbus_libreswan_helper_complete_callback() which decreases the -refcount of "invocation", and then returns FALSE which tells the -skeleton code to return an error, also unreferencing the -invocation. This causes a crash. - -Since the G_DBUS_METHOD_INVOCATION_HANDLED alias for TRUE is only -available since GLib 2.68 (while we target 2.36), just return TRUE. - -Fixes: acb9eb9de50b ('service: process the configuration in the service, not the helper') ---- - src/nm-libreswan-service.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/nm-libreswan-service.c b/src/nm-libreswan-service.c -index 12cf6f2..0d5c4b8 100644 ---- a/src/nm-libreswan-service.c -+++ b/src/nm-libreswan-service.c -@@ -1417,7 +1417,8 @@ out: - } - - nmdbus_libreswan_helper_complete_callback (object, invocation); -- return success; -+ -+ return TRUE; - } - - /****************************************************************/ --- -2.43.0 - diff --git a/SOURCES/0005-service-properties-support-type-hostaddrfamily-clien.patch b/SOURCES/0005-service-properties-support-type-hostaddrfamily-clien.patch deleted file mode 100644 index d54e26b..0000000 --- a/SOURCES/0005-service-properties-support-type-hostaddrfamily-clien.patch +++ /dev/null @@ -1,91 +0,0 @@ -From b4ba2add64bd9d362fe2e66748f23449f072216b Mon Sep 17 00:00:00 2001 -From: Beniamino Galvani -Date: Mon, 15 Jan 2024 13:23:45 +0100 -Subject: [PATCH 5/5] service,properties: support type, hostaddrfamily, - clientaddrfamily - -Add support for: - - type - - hostaddrfamily - - clientaddrfamily - -Since those are very advanced options, don't implement the GUI part -for now. ---- - properties/nm-libreswan-editor-plugin.c | 6 ++++++ - shared/nm-service-defines.h | 3 +++ - shared/utils.c | 12 ++++++++++++ - src/nm-libreswan-service.c | 3 +++ - 4 files changed, 24 insertions(+) - -diff --git a/properties/nm-libreswan-editor-plugin.c b/properties/nm-libreswan-editor-plugin.c -index 89243cc..fe85c81 100644 ---- a/properties/nm-libreswan-editor-plugin.c -+++ b/properties/nm-libreswan-editor-plugin.c -@@ -206,6 +206,12 @@ import_from_file (NMVpnEditorPlugin *self, - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_IPSEC_INTERFACE, &str[16]); - else if (g_str_has_prefix (str, "authby=")) - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_AUTHBY, &str[7]); -+ else if (g_str_has_prefix (str, "type=")) -+ nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_TYPE, str + NM_STRLEN("type=")); -+ else if (g_str_has_prefix (str, "hostaddrfamily=")) -+ nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_HOSTADDRFAMILY, str + NM_STRLEN("hostaddrfamily=")); -+ else if (g_str_has_prefix (str, "clientaddrfamily=")) -+ nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_CLIENTADDRFAMILY, str + NM_STRLEN("clientaddrfamily=")); - else if (g_str_has_prefix (str, "rightsubnet=")) { - if (!g_str_has_prefix (str, "rightsubnet=0.0.0.0/0")) - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_REMOTENETWORK, &str[12]); -diff --git a/shared/nm-service-defines.h b/shared/nm-service-defines.h -index 14170ad..95e19d4 100644 ---- a/shared/nm-service-defines.h -+++ b/shared/nm-service-defines.h -@@ -68,6 +68,9 @@ - #define NM_LIBRESWAN_KEY_FRAGMENTATION "fragmentation" - #define NM_LIBRESWAN_KEY_MOBIKE "mobike" - #define NM_LIBRESWAN_KEY_IPSEC_INTERFACE "ipsec-interface" -+#define NM_LIBRESWAN_KEY_TYPE "type" -+#define NM_LIBRESWAN_KEY_HOSTADDRFAMILY "hostaddrfamily" -+#define NM_LIBRESWAN_KEY_CLIENTADDRFAMILY "clientaddrfamily" - - #define NM_LIBRESWAN_IKEV2_NO "no" - #define NM_LIBRESWAN_IKEV2_NEVER "never" -diff --git a/shared/utils.c b/shared/utils.c -index 0bac9e6..9e616f8 100644 ---- a/shared/utils.c -+++ b/shared/utils.c -@@ -325,6 +325,18 @@ nm_libreswan_config_write (gint fd, - if (item && strlen (item)) - WRITE_CHECK (fd, debug_write_fcn, error, " ipsec-interface=%s", item); - -+ item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_TYPE); -+ if (item && strlen (item)) -+ WRITE_CHECK (fd, debug_write_fcn, error, " type=%s", item); -+ -+ item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_HOSTADDRFAMILY); -+ if (item && strlen (item)) -+ WRITE_CHECK (fd, debug_write_fcn, error, " hostaddrfamily=%s", item); -+ -+ item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_CLIENTADDRFAMILY); -+ if (item && strlen (item)) -+ WRITE_CHECK (fd, debug_write_fcn, error, " clientaddrfamily=%s", item); -+ - WRITE_CHECK (fd, debug_write_fcn, error, " nm-configured=yes"); - - WRITE_CHECK_NEWLINE (fd, trailing_newline, debug_write_fcn, error, " auto=add"); -diff --git a/src/nm-libreswan-service.c b/src/nm-libreswan-service.c -index 0d5c4b8..7e96230 100644 ---- a/src/nm-libreswan-service.c -+++ b/src/nm-libreswan-service.c -@@ -277,6 +277,9 @@ static ValidProperty valid_properties[] = { - { NM_LIBRESWAN_KEY_FRAGMENTATION, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_MOBIKE, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_IPSEC_INTERFACE, G_TYPE_STRING, 0, 0 }, -+ { NM_LIBRESWAN_KEY_TYPE, G_TYPE_STRING, 0, 0 }, -+ { NM_LIBRESWAN_KEY_HOSTADDRFAMILY, G_TYPE_STRING, 0, 0 }, -+ { NM_LIBRESWAN_KEY_CLIENTADDRFAMILY, G_TYPE_STRING, 0, 0 }, - /* Ignored option for internal use */ - { NM_LIBRESWAN_KEY_PSK_INPUT_MODES, G_TYPE_NONE, 0, 0 }, - { NM_LIBRESWAN_KEY_XAUTH_PASSWORD_INPUT_MODES, G_TYPE_NONE, 0, 0 }, --- -2.43.0 - diff --git a/SOURCES/0006-add-support-leftsubnet.patch b/SOURCES/0006-add-support-leftsubnet.patch deleted file mode 100644 index d8310c1..0000000 --- a/SOURCES/0006-add-support-leftsubnet.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 2045cdf3dec79ae7d7b03ca7a081b8c444e242ef Mon Sep 17 00:00:00 2001 -From: Beniamino Galvani -Date: Wed, 10 Apr 2024 13:23:56 +0200 -Subject: [PATCH] service,properties: support "leftsubnet" - -https://gitlab.gnome.org/GNOME/NetworkManager-libreswan/-/merge_requests/30 ---- - properties/nm-libreswan-dialog.ui | 42 ++++++++++++++++++++----- - properties/nm-libreswan-editor-plugin.c | 2 ++ - properties/nm-libreswan-editor.c | 12 +++++++ - shared/nm-service-defines.h | 1 + - shared/utils.c | 5 +++ - src/nm-libreswan-service.c | 1 + - 6 files changed, 56 insertions(+), 7 deletions(-) - -diff --git a/properties/nm-libreswan-editor-plugin.c b/properties/nm-libreswan-editor-plugin.c -index fe85c81..bb1685d 100644 ---- a/properties/nm-libreswan-editor-plugin.c -+++ b/properties/nm-libreswan-editor-plugin.c -@@ -215,6 +215,8 @@ import_from_file (NMVpnEditorPlugin *self, - else if (g_str_has_prefix (str, "rightsubnet=")) { - if (!g_str_has_prefix (str, "rightsubnet=0.0.0.0/0")) - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_REMOTENETWORK, &str[12]); -+ } else if (g_str_has_prefix (str, "leftsubnet=")) { -+ nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_LOCALNETWORK, str + NM_STRLEN("leftsubnet=")); - } else if (g_str_has_prefix (str, "leftrsasigkey=")) { - if (str[14] != '%') - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTRSASIGKEY, &str[14]); -diff --git a/shared/nm-service-defines.h b/shared/nm-service-defines.h -index 95e19d4..96e5c71 100644 ---- a/shared/nm-service-defines.h -+++ b/shared/nm-service-defines.h -@@ -62,6 +62,7 @@ - #define NM_LIBRESWAN_KEY_SALIFETIME "salifetime" - #define NM_LIBRESWAN_KEY_VENDOR "vendor" - #define NM_LIBRESWAN_KEY_REMOTENETWORK "rightsubnet" -+#define NM_LIBRESWAN_KEY_LOCALNETWORK "leftsubnet" - #define NM_LIBRESWAN_KEY_IKEV2 "ikev2" - #define NM_LIBRESWAN_KEY_NARROWING "narrowing" - #define NM_LIBRESWAN_KEY_REKEY "rekey" -diff --git a/shared/utils.c b/shared/utils.c -index 9e616f8..926d12d 100644 ---- a/shared/utils.c -+++ b/shared/utils.c -@@ -222,6 +222,11 @@ nm_libreswan_config_write (gint fd, - WRITE_CHECK (fd, debug_write_fcn, error, " rightsubnet=%s", - remote_network); - -+ item = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LOCALNETWORK); -+ if (item) { -+ WRITE_CHECK (fd, debug_write_fcn, error, " leftsubnet=%s", item); -+ } -+ - if (!is_ikev2) { - /* When IKEv1 is in place, we enforce XAUTH: so, use IKE version - * also to check if XAUTH conf options should be passed to Libreswan. -diff --git a/src/nm-libreswan-service.c b/src/nm-libreswan-service.c -index 7e96230..88c07d7 100644 ---- a/src/nm-libreswan-service.c -+++ b/src/nm-libreswan-service.c -@@ -271,6 +271,7 @@ static ValidProperty valid_properties[] = { - { NM_LIBRESWAN_KEY_SALIFETIME, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_VENDOR, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_REMOTENETWORK, G_TYPE_STRING, 0, 0 }, -+ { NM_LIBRESWAN_KEY_LOCALNETWORK, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_IKEV2, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_NARROWING, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_REKEY, G_TYPE_STRING, 0, 0 }, --- -2.44.0 - diff --git a/SOURCES/0007-add-rightcert-property.patch b/SOURCES/0007-add-rightcert-property.patch deleted file mode 100644 index 6c4e8dc..0000000 --- a/SOURCES/0007-add-rightcert-property.patch +++ /dev/null @@ -1,107 +0,0 @@ -0001-properties-service-suppor-rightcert-configuration.patch -0002-properties-add-Remote-certificate-field-to-the-dialo.patch -From a980e399694c0a9887d98f1e0f0f24a201cb29c7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= -Date: Mon, 15 Apr 2024 10:42:08 +0200 -Subject: [PATCH 1/2] properties, service: suppor rightcert configuration - -This configuration allows to specify a certificate from the NSS database -to identify the remote, instead of pulling it. - -(cherry picked from commit 2684233fd1c65c221d1f18c9d5b779c616c6d091) ---- - properties/nm-libreswan-editor-plugin.c | 2 ++ - shared/nm-service-defines.h | 1 + - shared/utils.c | 7 +++++++ - src/nm-libreswan-service.c | 8 ++++++-- - 4 files changed, 16 insertions(+), 2 deletions(-) - -diff --git a/properties/nm-libreswan-editor-plugin.c b/properties/nm-libreswan-editor-plugin.c -index bb1685d..fe473d1 100644 ---- a/properties/nm-libreswan-editor-plugin.c -+++ b/properties/nm-libreswan-editor-plugin.c -@@ -182,6 +182,8 @@ import_from_file (NMVpnEditorPlugin *self, - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTUSERNAME, &str[13]); - else if (g_str_has_prefix (str, "leftcert=")) - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTCERT, &str[9]); -+ else if (g_str_has_prefix (str, "rightcert=")) -+ nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHTCERT, &str[10]); - else if (nm_streq0 (str, "leftmodecfgclient=no")) - nm_setting_vpn_add_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTMODECFGCLIENT, "no"); - else if (g_str_has_prefix (str, "pfs=no")) -diff --git a/shared/nm-service-defines.h b/shared/nm-service-defines.h -index 96e5c71..167b837 100644 ---- a/shared/nm-service-defines.h -+++ b/shared/nm-service-defines.h -@@ -37,6 +37,7 @@ - #define NM_LIBRESWAN_KEY_RIGHT "right" - #define NM_LIBRESWAN_KEY_RIGHTID "rightid" - #define NM_LIBRESWAN_KEY_RIGHTRSASIGKEY "rightrsasigkey" -+#define NM_LIBRESWAN_KEY_RIGHTCERT "rightcert" - #define NM_LIBRESWAN_KEY_LEFT "left" - #define NM_LIBRESWAN_KEY_LEFTID "leftid" - #define NM_LIBRESWAN_KEY_LEFTRSASIGKEY "leftrsasigkey" -diff --git a/shared/utils.c b/shared/utils.c -index 926d12d..5e19316 100644 ---- a/shared/utils.c -+++ b/shared/utils.c -@@ -108,6 +108,7 @@ nm_libreswan_config_write (gint fd, - const char *left; - const char *leftid; - const char *leftcert; -+ const char *rightcert; - const char *leftrsasigkey; - const char *rightrsasigkey; - const char *authby; -@@ -165,7 +166,13 @@ nm_libreswan_config_write (gint fd, - leftrsasigkey = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTRSASIGKEY); - rightrsasigkey = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHTRSASIGKEY); - leftcert = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTCERT); -+ rightcert = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHTCERT); - authby = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_AUTHBY); -+ if (rightcert && strlen (rightcert)) { -+ WRITE_CHECK (fd, debug_write_fcn, error, " rightcert=%s", rightcert); -+ if (!rightrsasigkey) -+ rightrsasigkey = "%cert"; -+ } - if (leftcert && strlen (leftcert)) { - WRITE_CHECK (fd, debug_write_fcn, error, " leftcert=%s", leftcert); - if (!leftrsasigkey) -diff --git a/src/nm-libreswan-service.c b/src/nm-libreswan-service.c -index 88c07d7..516eaac 100644 ---- a/src/nm-libreswan-service.c -+++ b/src/nm-libreswan-service.c -@@ -250,6 +250,7 @@ static ValidProperty valid_properties[] = { - { NM_LIBRESWAN_KEY_RIGHT, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_RIGHTID, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_RIGHTRSASIGKEY, G_TYPE_STRING, 0, 0 }, -+ { NM_LIBRESWAN_KEY_RIGHTCERT, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_LEFT, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_LEFTID, G_TYPE_STRING, 0, 0 }, - { NM_LIBRESWAN_KEY_LEFTXAUTHUSER, G_TYPE_STRING, 0, 0 }, -@@ -1801,6 +1802,7 @@ real_need_secrets (NMVpnServicePlugin *plugin, - NMSettingVpn *s_vpn; - const char *leftcert; - const char *leftrsasigkey; -+ const char *rightcert; - const char *rightrsasigkey; - const char *pw_type; - -@@ -1821,10 +1823,12 @@ real_need_secrets (NMVpnServicePlugin *plugin, - if (leftcert) - goto xauth_check; - -- /* If authentication is done through rsasigkeys, only the public keys are required */ -+ /* If authentication is done through rsasigkeys, only the public keys are required. -+ * If rightcert is specified, rightrsasigkey is assumed to be '%cert' */ - leftrsasigkey = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_LEFTRSASIGKEY); - rightrsasigkey = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHTRSASIGKEY); -- if (leftrsasigkey && rightrsasigkey) -+ rightcert = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_RIGHTCERT); -+ if (leftrsasigkey && (rightrsasigkey || rightcert)) - goto xauth_check; - - pw_type = nm_setting_vpn_get_data_item (s_vpn, NM_LIBRESWAN_KEY_PSK_INPUT_MODES); --- -2.44.0 - diff --git a/SPECS/NetworkManager-libreswan.spec b/SPECS/NetworkManager-libreswan.spec index 8f2a72d..f35f8b1 100644 --- a/SPECS/NetworkManager-libreswan.spec +++ b/SPECS/NetworkManager-libreswan.spec @@ -9,9 +9,9 @@ %bcond_without gtk4 %endif -%global real_version 1.2.18 -%global rpm_version 1.2.18 -%global release_version 3 +%global real_version 1.2.22 +%global rpm_version 1.2.22 +%global release_version 4 %global real_version_major %(printf '%s' '%{real_version}' | sed -n 's/^\\([1-9][0-9]*\\.[1-9][0-9]*\\)\\.[1-9][0-9]*$/\\1/p') @@ -27,13 +27,8 @@ License: GPLv2+ URL: http://www.gnome.org/projects/NetworkManager/ Source0: https://download.gnome.org/sources/NetworkManager-libreswan/%{real_version_major}/%{name}-%{real_version}.tar.xz -Patch1: 0001-service-properties-add-support-for-leftmodecfgclient.patch -Patch2: 0002-service-use-new-API-to-send-configuration-to-NM.patch -Patch3: 0003-service-don-t-send-IPv4-config-if-mode-config-client.patch -Patch4: 0004-service-fix-wrong-refcounting-in-D-Bus-handler-for-C.patch -Patch5: 0005-service-properties-support-type-hostaddrfamily-clien.patch -Patch6: 0006-add-support-leftsubnet.patch -Patch7: 0007-add-rightcert-property.patch +# Patch1: 0001-some.patch +Patch1: 0001-ipsec-conf-escaping-cve-2024-9050.patch BuildRequires: make BuildRequires: gcc @@ -135,9 +130,18 @@ rm -f %{buildroot}%{_libdir}/NetworkManager/lib*.la %endif %changelog -* Tue May 07 2024 Fernando Fernandez Mancera - 1.2.18-3 -- Support leftsubnet property (RHEL-33376) -- Support rightcert property (RHEL-33372) +* Thu Oct 03 2024 Lubomir Rintel - 1.2.22-4 +- Unbreak validation of unknown keys + +* Wed Sep 25 2024 Lubomir Rintel - 1.2.22-2 +- Fix improper escaping of Libreswan configuration (CVE-2024-9050) + +* Wed May 22 2024 Beniamino Galvani - 1.2.22-1 +- Add IPv6 support (RHEL-21875) + +* Wed Apr 17 2024 Íñigo Huguet - 1.2.20-1 +- Support "leftsubnet" property (RHEL-26776) +- Support "rightcert" property (RHEL-30370) * Wed Jan 17 2024 Fernando Fernandez Mancera - 1.2.18-2 - Support point-to-point IPSec tunnel (RHEL-20690)