[Pkg-swan-devel] [Git][debian/strongswan][debian/trixie] 8 commits: d/gbp.conf: also follow a trixie branch for pristine-tar

Yves-Alexis Perez (@corsac) gitlab at salsa.debian.org
Thu Dec 18 19:34:06 GMT 2025



Yves-Alexis Perez pushed to branch debian/trixie at Debian / strongswan


Commits:
26fa05fd by Yves-Alexis Perez at 2025-08-27T11:46:58+02:00
d/gbp.conf: also follow a trixie branch for pristine-tar

Gbp-Dch: ignore

- - - - -
4541b934 by Yves-Alexis Perez at 2025-10-15T12:08:34+02:00
d/patches: add fix for buffer overflow in EAP-MSCHAPv2 (CVE-2025-62291)

- - - - -
e8c16471 by Yves-Alexis Perez at 2025-10-15T12:08:52+02:00
finalize changelog

- - - - -
d0753576 by Yves-Alexis Perez at 2025-10-15T12:17:16+02:00
upload strongSwan 6.0.1-6+deb13u2 to trixie-security

- - - - -
8bc0f7c4 by Yves-Alexis Perez at 2025-12-15T14:51:48+01:00
d/patches: add fix for unauthorized credentials access (CVE-2025-9615)

Closes: #1122978

- - - - -
02c99eb6 by Yves-Alexis Perez at 2025-12-15T14:52:13+01:00
finalize changelog

- - - - -
404857e2 by Yves-Alexis Perez at 2025-12-15T14:52:33+01:00
upload strongSwan 6.0.1-6+deb13u3 to trixie-security

- - - - -
738889e9 by Yves-Alexis Perez at 2025-12-18T20:32:45+01:00
d/usr.sbin.swanctl: add setuid/setgid caps to swanctl apparmor profile

- - - - -


6 changed files:

- debian/changelog
- debian/gbp.conf
- + debian/patches/0007-eap-mschapv2-Fix-length-check-for-Failure-Request-pa.patch
- + debian/patches/0008-nm-Create-safe-copies-of-files-for-user-specific-con.patch
- debian/patches/series
- debian/usr.sbin.swanctl


Changes:

=====================================
debian/changelog
=====================================
@@ -1,3 +1,16 @@
+strongswan (6.0.1-6+deb13u3) trixie-security; urgency=medium
+
+  * d/patches: add fix for unauthorized credentials access (CVE-2025-9615)
+    (Closes: #1122978)
+
+ -- Yves-Alexis Perez <corsac at debian.org>  Mon, 15 Dec 2025 14:52:23 +0100
+
+strongswan (6.0.1-6+deb13u2) trixie-security; urgency=medium
+
+  * d/patches: add fix for buffer overflow in EAP-MSCHAPv2 (CVE-2025-62291)
+
+ -- Yves-Alexis Perez <corsac at debian.org>  Wed, 15 Oct 2025 12:09:29 +0200
+
 strongswan (6.0.1-6+deb13u1) trixie; urgency=medium
 
   * d/patches: add patches to fix OpenSSL 3.5.1 support (Closes: #1109942)


=====================================
debian/gbp.conf
=====================================
@@ -1,4 +1,4 @@
 [DEFAULT]
 pristine-tar = True
 debian-branch = debian/trixie
-upstream-branch = upstream/latest
+upstream-branch = upstream/trixie


=====================================
debian/patches/0007-eap-mschapv2-Fix-length-check-for-Failure-Request-pa.patch
=====================================
@@ -0,0 +1,40 @@
+From: Tobias Brunner <tobias at strongswan.org>
+Date: Thu, 9 Oct 2025 11:33:45 +0200
+Subject: eap-mschapv2: Fix length check for Failure Request packets on the
+ client
+
+For message lengths between 6 and 8, subtracting HEADER_LEN (9) causes
+`message_len` to become negative, which is then used in calls to malloc()
+and memcpy() that both take size_t arguments, causing an integer
+underflow.
+
+For 6 and 7, the huge size requested from malloc() will fail (it exceeds
+PTRDIFF_MAX) and the returned NULL pointer will cause a segmentation
+fault in memcpy().
+
+However, for 8, the allocation is 0, which succeeds.  But then the -1
+passed to memcpy() causes a heap-based buffer overflow (and possibly a
+segmentation fault when attempting to read/write that much data).
+Fortunately, if compiled with -D_FORTIFY_SOURCE=3 (the default on e.g.
+Ubuntu), the compiler will use __memcpy_chk(), which prevents that buffer
+overflow and causes the daemon to get aborted immediately instead.
+
+Fixes: f98cdf7a4765 ("adding plugin for EAP-MS-CHAPv2")
+Fixes: CVE-2025-62291
+---
+ src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
+index 1bb54c8..9ad509a 100644
+--- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
++++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
+@@ -974,7 +974,7 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this,
+ 	data = in->get_data(in);
+ 	eap = (eap_mschapv2_header_t*)data.ptr;
+ 
+-	if (data.len < 3) /* we want at least an error code: E=e */
++	if (data.len < HEADER_LEN + 3) /* we want at least an error code: E=e */
+ 	{
+ 		DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: too short");
+ 		return FAILED;


=====================================
debian/patches/0008-nm-Create-safe-copies-of-files-for-user-specific-con.patch
=====================================
@@ -0,0 +1,623 @@
+From: Tobias Brunner <tobias at strongswan.org>
+Date: Wed, 26 Nov 2025 13:55:54 +0100
+Subject: nm: Create safe copies of files for user-specific connections
+
+This ensures that only certificates/private keys accessible by the
+configured user are accessed and prevents attackers from misusing
+other user's credentials.
+
+Also removed setting NM_VERSION_MIN_REQUIRED, which suppresses deprecation
+warnings that were added with newer API versions, and
+NM_VERSION_MAX_ALLOWED, which warns if using functions added in newer
+API versions, so we always build against the latest API available.
+
+But we check explicitly for the required function so this works with
+older NM versions and automatically will use it if the function is
+backported.
+
+Note that we can't use BUILD_FROM_FILE to read the temporary files as that
+uses mmap() which SELinux policies prevent us from using at the location
+these files are stored ([/var]/run/NetworkManager/cert/).
+
+Fixes: CVE-2025-9615
+
+Includes other backported fixes.
+---
+ configure.ac                                       |   6 +-
+ src/charon-nm/nm/nm_service.c                      | 187 +++++++++++++++++++--
+ src/libstrongswan/credentials/builder.c            |   1 +
+ src/libstrongswan/credentials/builder.h            |   2 +
+ src/libstrongswan/plugins/agent/agent_plugin.c     |   7 +
+ .../plugins/agent/agent_private_key.c              |  98 +++++++++--
+ src/libstrongswan/utils/capabilities.h             |   6 +
+ 7 files changed, 275 insertions(+), 32 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index f0160dc..73be8b2 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1261,8 +1261,10 @@ fi
+ 
+ if test x$nm = xtrue; then
+ 	PKG_CHECK_MODULES(nm, [gthread-2.0 libnm])
+-	AC_SUBST(nm_CFLAGS)
+-	AC_SUBST(nm_LIBS)
++	saved_LIBS=$LIBS
++	LIBS="$nm_LIBS"
++	AC_CHECK_FUNCS(nm_utils_copy_cert_as_user)
++	LIBS=$saved_LIBS
+ 
+ 	AC_MSG_CHECKING([for D-Bus policy directory])
+ 	if test -n "$dbuspolicydir" -a "x$dbuspolicydir" != xno; then
+diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
+index b920d58..9c6bcf6 100644
+--- a/src/charon-nm/nm/nm_service.c
++++ b/src/charon-nm/nm/nm_service.c
+@@ -15,6 +15,7 @@
+  */
+ 
+ #include <stdio.h>
++#include <fcntl.h>
+ #include <inttypes.h>
+ #include <net/if.h>
+ 
+@@ -54,6 +55,10 @@ typedef struct {
+ 	tun_device_t *tun;
+ 	/* name of the connection */
+ 	char *name;
++	/* temporary files for safe access */
++	GPtrArray *safe_files;
++	/* already requested the ssh-agent socket for the current connection */
++	bool agent_requested;
+ } NMStrongswanPluginPrivate;
+ 
+ G_DEFINE_TYPE_WITH_PRIVATE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_SERVICE_PLUGIN)
+@@ -417,6 +422,100 @@ METHOD(listener_t, child_updown, bool,
+ 	return TRUE;
+ }
+ 
++/**
++ * Determine the user configured in the given connection (if any).
++ */
++static const char *get_connection_permission_user(NMConnection *connection)
++{
++	NMSettingConnection *s_con;
++	const char *ptype, *pitem, *pdetail;
++	guint num_perms, i;
++
++	s_con = nm_connection_get_setting_connection(connection);
++	if (s_con)
++	{
++		num_perms = nm_setting_connection_get_num_permissions(s_con);
++		if (num_perms > 0)
++		{
++			for (i = 0; i < num_perms; i++)
++			{
++				if (nm_setting_connection_get_permission(s_con, i, &ptype,
++														 &pitem, &pdetail) &&
++					streq(ptype, "user"))
++				{
++					return pitem;
++				}
++			}
++		}
++	}
++	return NULL;
++}
++
++/**
++ * Given a file name and an (optional) user name owning the connection, returns
++ * the file name to be used in the configuration.
++ *
++ * If the user is set, the file is accessed on behalf of the user, and copied
++ * safely to a temporary file readable only by root.
++ *
++ * The returned file name must be freed by the caller.
++ */
++static char *access_file(NMStrongswanPluginPrivate *priv, const char *filename,
++						 const char *user, GError **err)
++{
++#ifdef HAVE_NM_UTILS_COPY_CERT_AS_USER
++	if (user)
++	{
++		char *tmp = nm_utils_copy_cert_as_user(filename, user, err);
++		if (tmp)
++		{
++			g_ptr_array_add(priv->safe_files, g_strdup(tmp));
++		}
++		return tmp;
++	}
++#endif
++	return g_strdup(filename);
++}
++
++/**
++ * Read the contents of the given file. If an (optional) user name owning
++ * the connection is given, the file is accessed safely on behalf of that user.
++ *
++ * We have to do this explicitly via open() because SELinux policies prevent us
++ * from using mmap(), which BUILD_FROM_FILE would use.
++ */
++static chunk_t read_safe_file(NMStrongswanPluginPrivate *priv,
++							  const char *filename, const char *user,
++							  GError **err)
++{
++	chunk_t chunk = chunk_empty;
++	char *safe_path;
++	int fd;
++
++	safe_path = access_file(priv, filename, user, err);
++	if (safe_path)
++	{
++		fd = open(safe_path, O_RDONLY);
++		if (fd != -1)
++		{
++			if (!chunk_from_fd(fd, &chunk))
++			{
++				g_set_error(err, NM_VPN_PLUGIN_ERROR,
++						NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
++						"Unable to read '%s': %s", safe_path, strerror(errno));
++			}
++			close(fd);
++		}
++		else
++		{
++			g_set_error(err, NM_VPN_PLUGIN_ERROR,
++						NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
++						"Unable to open '%s': %s", safe_path, strerror(errno));
++		}
++	}
++	return chunk;
++}
++
+ /**
+  * Find a certificate for which we have a private key on a smartcard
+  */
+@@ -475,12 +574,13 @@ static identification_t *find_smartcard_key(NMStrongswanPluginPrivate *priv,
+  */
+ static bool add_auth_cfg_cert(NMStrongswanPluginPrivate *priv,
+ 							  NMSettingVpn *vpn, peer_cfg_t *peer_cfg,
+-							  GError **err)
++							  const char *user, GError **err)
+ {
+ 	identification_t *id = NULL;
+ 	certificate_t *cert = NULL;
+ 	auth_cfg_t *auth;
+-	const char *str, *method, *cert_source;
++	const char *str, *method, *cert_source, *agent_user;
++	chunk_t safe_file;
+ 
+ 	method = nm_setting_vpn_get_data_item(vpn, "method");
+ 	cert_source = nm_setting_vpn_get_data_item(vpn, "cert-source") ?: method;
+@@ -510,8 +610,14 @@ static bool add_auth_cfg_cert(NMStrongswanPluginPrivate *priv,
+ 
+ 		bool agent = streq(cert_source, "agent");
+ 
++		safe_file = read_safe_file(priv, str, user, err);
++		if (!safe_file.ptr)
++		{
++			return FALSE;
++		}
+ 		cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+-								  BUILD_FROM_FILE, str, BUILD_END);
++								  BUILD_BLOB, safe_file, BUILD_END);
++		chunk_clear(&safe_file);
+ 		if (!cert)
+ 		{
+ 			g_set_error(err, NM_VPN_PLUGIN_ERROR,
+@@ -523,12 +629,15 @@ static bool add_auth_cfg_cert(NMStrongswanPluginPrivate *priv,
+ 		str = nm_setting_vpn_get_secret(vpn, "agent");
+ 		if (agent && str)
+ 		{
++			agent_user = nm_setting_vpn_get_secret(vpn, "agent-user");
++
+ 			public = cert->get_public_key(cert);
+ 			if (public)
+ 			{
+ 				private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+ 											 public->get_type(public),
+ 											 BUILD_AGENT_SOCKET, str,
++											 BUILD_AGENT_USER, agent_user ?: user,
+ 											 BUILD_PUBLIC_KEY, public,
+ 											 BUILD_END);
+ 				public->destroy(public);
+@@ -551,8 +660,14 @@ static bool add_auth_cfg_cert(NMStrongswanPluginPrivate *priv,
+ 			{
+ 				priv->creds->set_key_password(priv->creds, secret);
+ 			}
++			safe_file = read_safe_file(priv, str, user, err);
++			if (!safe_file.ptr)
++			{
++				return FALSE;
++			}
+ 			private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+-									KEY_ANY, BUILD_FROM_FILE, str, BUILD_END);
++								KEY_ANY, BUILD_BLOB, safe_file, BUILD_END);
++			chunk_clear(&safe_file);
+ 			if (!private)
+ 			{
+ 				g_set_error(err, NM_VPN_PLUGIN_ERROR,
+@@ -731,7 +846,8 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
+ 	NMSettingVpn *vpn;
+ 	enumerator_t *enumerator;
+ 	identification_t *gateway = NULL;
+-	const char *str, *method;
++	const char *str, *method, *user;
++	chunk_t safe_file;
+ 	bool virtual, proposal;
+ 	proposal_t *prop;
+ 	ike_cfg_t *ike_cfg;
+@@ -786,6 +902,8 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
+ 	DBG4(DBG_CFG, "%s",
+ 		 nm_setting_to_string(NM_SETTING(vpn)));
+ 
++	user = get_connection_permission_user(connection);
++
+ 	ike.remote = (char*)nm_setting_vpn_get_data_item(vpn, "address");
+ 	if (!ike.remote || !*ike.remote)
+ 	{
+@@ -814,8 +932,14 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
+ 	str = nm_setting_vpn_get_data_item(vpn, "certificate");
+ 	if (str)
+ 	{
++		safe_file = read_safe_file(priv, str, user, err);
++		if (!safe_file.ptr)
++		{
++			return FALSE;
++		}
+ 		cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+-								  BUILD_FROM_FILE, str, BUILD_END);
++								  BUILD_BLOB, safe_file, BUILD_END);
++		chunk_clear(&safe_file);
+ 		if (!cert)
+ 		{
+ 			g_set_error(err, NM_VPN_PLUGIN_ERROR,
+@@ -903,7 +1027,7 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
+ 		streq(method, "agent") ||
+ 		streq(method, "smartcard"))
+ 	{
+-		if (!add_auth_cfg_cert (priv, vpn, peer_cfg, err))
++		if (!add_auth_cfg_cert(priv, vpn, peer_cfg, user, err))
+ 		{
+ 			peer_cfg->destroy(peer_cfg);
+ 			ike_cfg->destroy(ike_cfg);
+@@ -1049,10 +1173,12 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
+ static gboolean need_secrets(NMVpnServicePlugin *plugin, NMConnection *connection,
+ 							 const char **setting_name, GError **error)
+ {
++	NMStrongswanPluginPrivate *priv;
+ 	NMSettingVpn *settings;
+ 	const char *method, *cert_source, *path;
+ 	bool need_secret = FALSE;
+ 
++	priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE((NMStrongswanPlugin*)plugin);
+ 	settings = NM_SETTING_VPN(nm_connection_get_setting(connection,
+ 														NM_TYPE_SETTING_VPN));
+ 	method = nm_setting_vpn_get_data_item(settings, "method");
+@@ -1071,7 +1197,14 @@ static gboolean need_secrets(NMVpnServicePlugin *plugin, NMConnection *connectio
+ 			}
+ 			if (streq(cert_source, "agent"))
+ 			{
+-				need_secret = !nm_setting_vpn_get_secret(settings, "agent");
++				/* always request the socket/username from the current user */
++				need_secret = !priv->agent_requested;
++				if (!priv->agent_requested)
++				{
++					nm_setting_vpn_remove_secret(settings, "agent");
++					nm_setting_vpn_remove_secret(settings, "agent-user");
++					priv->agent_requested = TRUE;
++				}
+ 			}
+ 			else if (streq(cert_source, "smartcard"))
+ 			{
+@@ -1084,18 +1217,27 @@ static gboolean need_secrets(NMVpnServicePlugin *plugin, NMConnection *connectio
+ 				if (path)
+ 				{
+ 					private_key_t *key;
++					const char *user;
++					chunk_t safe_file;
+ 
+-					/* try to load/decrypt the private key */
+-					key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+-									KEY_ANY, BUILD_FROM_FILE, path, BUILD_END);
+-					if (key)
+-					{
+-						key->destroy(key);
+-						need_secret = FALSE;
+-					}
+-					else if (nm_setting_vpn_get_secret(settings, "password"))
++					user = get_connection_permission_user(connection);
++					safe_file = read_safe_file(priv, path, user, error);
++					if (safe_file.ptr)
+ 					{
+-						need_secret = FALSE;
++						/* try to load/decrypt the private key */
++						key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
++											KEY_ANY, BUILD_BLOB, safe_file,
++											BUILD_END);
++						chunk_clear(&safe_file);
++						if (key)
++						{
++							key->destroy(key);
++							need_secret = FALSE;
++						}
++						else if (nm_setting_vpn_get_secret(settings, "password"))
++						{
++							need_secret = FALSE;
++						}
+ 					}
+ 				}
+ 			}
+@@ -1149,6 +1291,8 @@ static gboolean do_disconnect(gpointer plugin)
+ 
+ 	/* delete any allocated interface */
+ 	delete_interface(priv);
++
++	priv->agent_requested = FALSE;
+ 	return FALSE;
+ }
+ 
+@@ -1181,6 +1325,7 @@ static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
+ 	priv->listener.ike_reestablish_post = _ike_reestablish_post;
+ 	charon->bus->add_listener(charon->bus, &priv->listener);
+ 	priv->xfrmi_manager = lib->get(lib, KERNEL_NETLINK_XFRMI_MANAGER);
++	priv->safe_files = g_ptr_array_new_with_free_func(g_free);
+ }
+ 
+ /**
+@@ -1190,11 +1335,17 @@ static void nm_strongswan_plugin_dispose(GObject *obj)
+ {
+ 	NMStrongswanPlugin *plugin;
+ 	NMStrongswanPluginPrivate *priv;
++	int i;
+ 
+ 	plugin = NM_STRONGSWAN_PLUGIN(obj);
+ 	priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
+ 	delete_interface(priv);
+ 	free(priv->name);
++	for (i = 0; i < priv->safe_files->len; i++)
++	{
++		unlink((const char *)priv->safe_files->pdata[i]);
++	}
++	g_ptr_array_unref(priv->safe_files);
+ 	G_OBJECT_CLASS (nm_strongswan_plugin_parent_class)->dispose (obj);
+ }
+ 
+diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c
+index 27ae83c..76bcd39 100644
+--- a/src/libstrongswan/credentials/builder.c
++++ b/src/libstrongswan/credentials/builder.c
+@@ -20,6 +20,7 @@
+ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
+ 	"BUILD_FROM_FILE",
+ 	"BUILD_AGENT_SOCKET",
++	"BUILD_AGENT_USER",
+ 	"BUILD_BLOB",
+ 	"BUILD_BLOB_ASN1_DER",
+ 	"BUILD_BLOB_PEM",
+diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h
+index e95265e..7e2a239 100644
+--- a/src/libstrongswan/credentials/builder.h
++++ b/src/libstrongswan/credentials/builder.h
+@@ -49,6 +49,8 @@ enum builder_part_t {
+ 	BUILD_FROM_FILE,
+ 	/** unix socket of a ssh/pgp agent, char* */
+ 	BUILD_AGENT_SOCKET,
++	/** user to access a ssh/pgp agent socket, char* */
++	BUILD_AGENT_USER,
+ 	/** An arbitrary blob of data, chunk_t */
+ 	BUILD_BLOB,
+ 	/** DER encoded ASN.1 blob, chunk_t */
+diff --git a/src/libstrongswan/plugins/agent/agent_plugin.c b/src/libstrongswan/plugins/agent/agent_plugin.c
+index 9e39d51..2b4028b 100644
+--- a/src/libstrongswan/plugins/agent/agent_plugin.c
++++ b/src/libstrongswan/plugins/agent/agent_plugin.c
+@@ -70,6 +70,13 @@ plugin_t *agent_plugin_create()
+ 		DBG1(DBG_DMN, "agent plugin requires CAP_DAC_OVERRIDE capability");
+ 		return NULL;
+ 	}
++	/* required to switch user/group to access ssh-agent socket */
++	if (!lib->caps->keep(lib->caps, CAP_SETUID) ||
++		!lib->caps->keep(lib->caps, CAP_SETGID))
++	{
++		DBG1(DBG_DMN, "agent plugin requires CAP_SETUID/CAP_SETGID capability");
++		return NULL;
++	}
+ 
+ 	INIT(this,
+ 		.public = {
+diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c
+index 0c1c988..7308055 100644
+--- a/src/libstrongswan/plugins/agent/agent_private_key.c
++++ b/src/libstrongswan/plugins/agent/agent_private_key.c
+@@ -22,7 +22,10 @@
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/un.h>
++#include <sys/wait.h>
+ #include <arpa/inet.h>
++#include <pwd.h>
++#include <grp.h>
+ #include <errno.h>
+ 
+ #include <library.h>
+@@ -50,6 +53,11 @@ struct private_agent_private_key_t {
+ 	 */
+ 	char *path;
+ 
++	/**
++	 * Optional user to connect to socket as
++	 */
++	char *user;
++
+ 	/**
+ 	 * public key encoded in SSH format
+ 	 */
+@@ -142,12 +150,24 @@ static chunk_t read_string(chunk_t *blob)
+ }
+ 
+ /**
+- * open socket connection to the ssh-agent
++ * Connect a UNIX socket to the given path.
+  */
+-static int open_connection(char *path)
++static bool connect_socket(int fd, char *path)
+ {
+ 	struct sockaddr_un addr;
+-	int s;
++
++	addr.sun_family = AF_UNIX;
++	addr.sun_path[UNIX_PATH_MAX - 1] = '\0';
++	strncpy(addr.sun_path, path, UNIX_PATH_MAX - 1);
++	return connect(fd, (struct sockaddr*)&addr, SUN_LEN(&addr)) == 0;
++}
++
++/**
++ * Open socket connection to the ssh-agent, optionally as a given user.
++ */
++static int open_connection(char *path, char *user)
++{
++	int s, pid, status;
+ 
+ 	s = socket(AF_UNIX, SOCK_STREAM, 0);
+ 	if (s == -1)
+@@ -157,14 +177,63 @@ static int open_connection(char *path)
+ 		return -1;
+ 	}
+ 
+-	addr.sun_family = AF_UNIX;
+-	addr.sun_path[UNIX_PATH_MAX - 1] = '\0';
+-	strncpy(addr.sun_path, path, UNIX_PATH_MAX - 1);
+-
+-	if (connect(s, (struct sockaddr*)&addr, SUN_LEN(&addr)) != 0)
++	if (user)
++	{
++		pid = fork();
++		switch (pid)
++		{
++			case -1:
++				DBG1(DBG_LIB, "forking failed after opening ssh-agent "
++					 "socket: %s", strerror(errno));
++				close(s);
++				return -1;
++			case 0:
++			{
++				/* child, do everything manually to avoid interacting with
++				 * mutexes etc. that are potentially locked in the parent */
++				struct passwd *pwp;
++
++				pwp = getpwnam(user);
++				if (pwp)
++				{
++					if (initgroups(user, pwp->pw_gid) == 0)
++					{
++						if (setgid(pwp->pw_gid) == 0 &&
++							setuid(pwp->pw_uid) == 0)
++						{
++							if (connect_socket(s, path))
++							{
++								exit(EXIT_SUCCESS);
++							}
++						}
++					}
++				}
++				exit(EXIT_FAILURE);
++				/* not reached */
++			}
++			default:
++				/* parent */
++				if (waitpid(pid, &status, 0) == -1 ||
++					!WIFEXITED(status))
++				{
++					DBG1(DBG_LIB, "sub-process to connect to ssh-agent didn't "
++						 "terminate normally");
++					close(s);
++					return -1;
++				}
++				if (WEXITSTATUS(status) != 0)
++				{
++					DBG1(DBG_LIB, "connecting to ssh-agent in sub-process "
++						 "failed: %d", WEXITSTATUS(status));
++					close(s);
++					return -1;
++				}
++		}
++	}
++	else if (!connect_socket(s, path))
+ 	{
+ 		DBG1(DBG_LIB, "connecting to ssh-agent socket '%s' failed: %s",
+-			 addr.sun_path, strerror(errno));
++			 path, strerror(errno));
+ 		close(s);
+ 		return -1;
+ 	}
+@@ -181,7 +250,7 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey)
+ 	chunk_t blob, key;
+ 	bool success = FALSE;
+ 
+-	socket = open_connection(this->path);
++	socket = open_connection(this->path, this->user);
+ 	if (socket < 0)
+ 	{
+ 		return FALSE;
+@@ -293,7 +362,7 @@ METHOD(private_key_t, sign, bool,
+ 		return FALSE;
+ 	}
+ 
+-	socket = open_connection(this->path);
++	socket = open_connection(this->path, this->user);
+ 	if (socket < 0)
+ 	{
+ 		return FALSE;
+@@ -512,6 +581,7 @@ METHOD(private_key_t, destroy, void,
+ 		chunk_free(&this->key);
+ 		DESTROY_IF(this->pubkey);
+ 		free(this->path);
++		free(this->user);
+ 		free(this);
+ 	}
+ }
+@@ -523,7 +593,7 @@ agent_private_key_t *agent_private_key_open(key_type_t type, va_list args)
+ {
+ 	private_agent_private_key_t *this;
+ 	public_key_t *pubkey = NULL;
+-	char *path = NULL;
++	char *path = NULL, *user = NULL;
+ 
+ 	while (TRUE)
+ 	{
+@@ -532,6 +602,9 @@ agent_private_key_t *agent_private_key_open(key_type_t type, va_list args)
+ 			case BUILD_AGENT_SOCKET:
+ 				path = va_arg(args, char*);
+ 				continue;
++			case BUILD_AGENT_USER:
++				user = va_arg(args, char*);
++				continue;
+ 			case BUILD_PUBLIC_KEY:
+ 				pubkey = va_arg(args, public_key_t*);
+ 				continue;
+@@ -566,6 +639,7 @@ agent_private_key_t *agent_private_key_open(key_type_t type, va_list args)
+ 			},
+ 		},
+ 		.path = strdup(path),
++		.user = strdupnull(user),
+ 		.ref = 1,
+ 	);
+ 
+diff --git a/src/libstrongswan/utils/capabilities.h b/src/libstrongswan/utils/capabilities.h
+index 681fbb8..9ecde47 100644
+--- a/src/libstrongswan/utils/capabilities.h
++++ b/src/libstrongswan/utils/capabilities.h
+@@ -50,6 +50,12 @@ typedef struct capabilities_t capabilities_t;
+ #ifndef CAP_SETPCAP
+ # define CAP_SETPCAP 8
+ #endif
++#ifndef CAP_SETUID
++# define CAP_SETUID 7
++#endif
++#ifndef CAP_SETGID
++# define CAP_SETGID 6
++#endif
+ 
+ /**
+  * POSIX capability dropping abstraction layer.


=====================================
debian/patches/series
=====================================
@@ -4,3 +4,5 @@
 dont-load-kernel-libipsec-plugin-by-default.patch
 0001-openssl-Fix-testing-KDF_PRF-in-the-constructor-with-.patch
 0002-openssl-Don-t-allocate-salt-if-PRF-hash-is-unknown.patch
+0007-eap-mschapv2-Fix-length-check-for-Failure-Request-pa.patch
+0008-nm-Create-safe-copies-of-files-for-user-specific-con.patch


=====================================
debian/usr.sbin.swanctl
=====================================
@@ -9,6 +9,8 @@
   # CAP_DAC_OVERRIDE is needed for optional charon.user/charon.group
   # configuration
   capability dac_override,
+  capability setuid,
+  capability setgid,
 
   # Allow reading strongswan.conf configuration files
   /etc/strongswan.conf          r,



View it on GitLab: https://salsa.debian.org/debian/strongswan/-/compare/1abe7f5197848e67044cb77a12b3fec1fe2b49da...738889e9cb6b9070ca4db17bd657b9190f8ae3e5

-- 
View it on GitLab: https://salsa.debian.org/debian/strongswan/-/compare/1abe7f5197848e67044cb77a12b3fec1fe2b49da...738889e9cb6b9070ca4db17bd657b9190f8ae3e5
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-swan-devel/attachments/20251218/7e91ab50/attachment-0001.htm>


More information about the Pkg-swan-devel mailing list