[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