Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package xrdp for openSUSE:Factory checked in at 2026-05-19 17:51:31 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/xrdp (Old) and /work/SRC/openSUSE:Factory/.xrdp.new.1966 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "xrdp" Tue May 19 17:51:31 2026 rev:60 rq:1354033 version:0.9.27 Changes: -------- --- /work/SRC/openSUSE:Factory/xrdp/xrdp.changes 2026-02-04 21:06:46.198290180 +0100 +++ /work/SRC/openSUSE:Factory/.xrdp.new.1966/xrdp.changes 2026-05-19 17:52:09.713081179 +0200 @@ -1,0 +2,19 @@ +Sat May 16 03:06:33 UTC 2026 - Yifan Jiang <[email protected]> + +- Add patches for security fixes: + * xrdp-CVE-2026-32105-1-fips-slowpath.patch (bsc#1262312, + CVE-2026-32105) + * xrdp-CVE-2026-32105-2-fips-fastpath.patch (bsc#1262312, + CVE-2026-32105) + * xrdp-CVE-2026-32105-3-nonfips-slowpath.patch (bsc#1262312, + CVE-2026-32105) + * xrdp-CVE-2026-32105-4-nonfips-fastpath.patch (bsc#1262312, + CVE-2026-32105) + * xrdp-CVE-2026-32624.patch (bsc#1262321, CVE-2026-32624) + * xrdp-CVE-2026-32107.patch (bsc#1262313, CVE-2026-32107) + * xrdp-CVE-2026-32623.patch (bsc#1262316, CVE-2026-32623) + * xrdp-CVE-2026-33145.patch (bsc#1262331, CVE-2026-33145) + * xrdp-CVE-2026-33689.patch (bsc#1262332, CVE-2026-33689) + * xrdp-CVE-2026-35512.patch (bsc#1262333, CVE-2026-35512) + +------------------------------------------------------------------- @@ -8,0 +28,25 @@ +- Drop upstreamed patches: + * xrdp-memory-allocation-security-fix.patch + * xrdp-remove-unecessary-gmalloc.patch + * xrdp-safe-data-chunk-reassembly.patch + * xrdp-add-stub-implementation-for-s_check_rem_and_log.patch + * xrdp-CVE-2022-23468.patch + * xrdp-CVE-2022-23478.patch + * xrdp-CVE-2022-23479.patch + * xrdp-CVE-2022-23480.patch + * xrdp-CVE-2022-23481.patch + * xrdp-CVE-2022-23482.patch + * xrdp-CVE-2022-23483.patch + * xrdp-CVE-2022-23484.patch + * xrdp-CVE-2022-23493.patch + * xrdp-CVE-2022-23477.patch + * xrdp-CVE-2023-40184.patch + * xrdp-CVE-2023-42822.patch + * xrdp-CVE-2024-39917.patch + * xrdp-CVE-2025-68670.patch + +------------------------------------------------------------------- +Fri Jan 30 06:19:37 UTC 2026 - Xiaoguang Wang <[email protected]> + +- Add xrdp-CVE-2025-68670.patch: Fix a potential overflow + (bsc#1257362 CVE-2025-68670). @@ -35,0 +80,8 @@ +Fri Jan 24 08:49:57 UTC 2025 - Yifan Jiang <[email protected]> + +- Enforce no login screen if require_credentials is set + (bsc#1227769) + + Add xrdp-CVE-2024-39917.patch + + Rebase xrdp-fate318398-change-expired-password.patch + +------------------------------------------------------------------- @@ -54,0 +107,6 @@ +Fri Dec 8 01:46:15 UTC 2023 - Daike Yu <[email protected]> + +- Update xrdp-CVE-2023-42822.patch + + fix bsc#1217759: xrdp login screen does not show any text + +------------------------------------------------------------------- @@ -67,0 +126,6 @@ +Tue Nov 21 02:45:32 UTC 2023 - Daike Yu <[email protected]> + +- xrdp-CVE-2023-42822.patch (bsc#1215803) + + unchecked access to font glyph info + +------------------------------------------------------------------- @@ -89,0 +154,6 @@ +Tue Sep 12 07:47:53 UTC 2023 - Daike Yu <[email protected]> + +- xrdp-CVE-2023-40184.patch (bsc#1214805) + + restriction bypass via improper session handling + +------------------------------------------------------------------- @@ -134,0 +205,9 @@ +Mon Jul 10 15:20:01 UTC 2023 - Josef Cejka <[email protected]> + + - Convert username exported to env variables to canonical form + to prevent issues with different username and domain formats (bsc#1211740) + + xrdp-Add-function-to-get-user-information-by-UID.patch + + xrdp-Moved-initgroups-call-to-before-auth_start_session.patch + + xrdp-fix-username-in-env.patch + +------------------------------------------------------------------- @@ -177,0 +257,2 @@ + + xrdp-add-stub-implementation-for-s_check_rem_and_log.patch + * add stub implementation for s_check_rem_and_log() @@ -322,0 +404,9 @@ + +------------------------------------------------------------------- +Mon Nov 9 07:31:16 UTC 2020 - Yifan Jiang <[email protected]> + +- Introduce more buffer protection fixes (jsc#SLE-11518): + + Add xrdp-memory-allocation-security-fix.patch + + Add xrdp-remove-unecessary-gmalloc.patch + + Add xrdp-safe-data-chunk-reassembly.patch +- Make the serial number of SLE patches on the bottom New: ---- xrdp-Add-function-to-get-user-information-by-UID.patch xrdp-CVE-2026-32105-1-fips-slowpath.patch xrdp-CVE-2026-32105-2-fips-fastpath.patch xrdp-CVE-2026-32105-3-nonfips-slowpath.patch xrdp-CVE-2026-32105-4-nonfips-fastpath.patch xrdp-CVE-2026-32107.patch xrdp-CVE-2026-32623.patch xrdp-CVE-2026-32624.patch xrdp-CVE-2026-33145.patch xrdp-CVE-2026-33689.patch xrdp-CVE-2026-35512.patch xrdp-Moved-initgroups-call-to-before-auth_start_session.patch xrdp-fix-username-in-env.patch ----------(New B)---------- New: to prevent issues with different username and domain formats (bsc#1211740) + xrdp-Add-function-to-get-user-information-by-UID.patch + xrdp-Moved-initgroups-call-to-before-auth_start_session.patch New:- Add patches for security fixes: * xrdp-CVE-2026-32105-1-fips-slowpath.patch (bsc#1262312, CVE-2026-32105) New: CVE-2026-32105) * xrdp-CVE-2026-32105-2-fips-fastpath.patch (bsc#1262312, CVE-2026-32105) New: CVE-2026-32105) * xrdp-CVE-2026-32105-3-nonfips-slowpath.patch (bsc#1262312, CVE-2026-32105) New: CVE-2026-32105) * xrdp-CVE-2026-32105-4-nonfips-fastpath.patch (bsc#1262312, CVE-2026-32105) New: * xrdp-CVE-2026-32624.patch (bsc#1262321, CVE-2026-32624) * xrdp-CVE-2026-32107.patch (bsc#1262313, CVE-2026-32107) * xrdp-CVE-2026-32623.patch (bsc#1262316, CVE-2026-32623) New: * xrdp-CVE-2026-32107.patch (bsc#1262313, CVE-2026-32107) * xrdp-CVE-2026-32623.patch (bsc#1262316, CVE-2026-32623) * xrdp-CVE-2026-33145.patch (bsc#1262331, CVE-2026-33145) New: CVE-2026-32105) * xrdp-CVE-2026-32624.patch (bsc#1262321, CVE-2026-32624) * xrdp-CVE-2026-32107.patch (bsc#1262313, CVE-2026-32107) New: * xrdp-CVE-2026-32623.patch (bsc#1262316, CVE-2026-32623) * xrdp-CVE-2026-33145.patch (bsc#1262331, CVE-2026-33145) * xrdp-CVE-2026-33689.patch (bsc#1262332, CVE-2026-33689) New: * xrdp-CVE-2026-33145.patch (bsc#1262331, CVE-2026-33145) * xrdp-CVE-2026-33689.patch (bsc#1262332, CVE-2026-33689) * xrdp-CVE-2026-35512.patch (bsc#1262333, CVE-2026-35512) New: * xrdp-CVE-2026-33689.patch (bsc#1262332, CVE-2026-33689) * xrdp-CVE-2026-35512.patch (bsc#1262333, CVE-2026-35512) New: + xrdp-Add-function-to-get-user-information-by-UID.patch + xrdp-Moved-initgroups-call-to-before-auth_start_session.patch + xrdp-fix-username-in-env.patch New: + xrdp-Moved-initgroups-call-to-before-auth_start_session.patch + xrdp-fix-username-in-env.patch ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ xrdp.spec ++++++ --- /var/tmp/diff_new_pack.WMNbXk/_old 2026-05-19 17:52:10.813126691 +0200 +++ /var/tmp/diff_new_pack.WMNbXk/_new 2026-05-19 17:52:10.817126856 +0200 @@ -38,12 +38,37 @@ # PATCH-FIX-OPENSUSE xrdp-pam.patch - [email protected] refreshed by [email protected] Patch1: xrdp-pam.patch # PATCH-FIX-OPENSUSE xrdp-disable-8-bpp-vnc-support.patch bsc#991059 - [email protected] -- disable 8 bpp support for vnc connections -Patch4: xrdp-disable-8-bpp-vnc-support.patch +Patch2: xrdp-disable-8-bpp-vnc-support.patch # PATCH-FIX-OPENSUSE xrdp-support-KillDisconnected-for-Xvnc.patch boo#1101506 - [email protected] -- Support the KillDisconnected option for TigerVNC Xvnc sessions -Patch5: xrdp-support-KillDisconnected-for-Xvnc.patch +Patch3: xrdp-support-KillDisconnected-for-Xvnc.patch # PATCH-FIX-OPENSUSE xrdp-systemd-services.patch boo#1138954 boo#1144327 - [email protected] -- Let systemd handle the daemons -Patch6: xrdp-systemd-services.patch - +Patch4: xrdp-systemd-services.patch +# PATCH-FIX-UPSTREAM xrdp-Add-function-to-get-user-information-by-UID.patch bsc#1211740 - [email protected] -- Moved initgroups call to before auth_start_session() +Patch21: xrdp-Moved-initgroups-call-to-before-auth_start_session.patch +# PATCH-FEATURE-UPSTREAM xrdp-Add-function-to-get-user-information-by-UID.patch bsc#1211740 - [email protected] -- Add function to get user information by UID +Patch22: xrdp-Add-function-to-get-user-information-by-UID.patch +# PATCH-FIX-OPENSUSE xrdp-fix-username-in-env.patch bsc#1211740 - [email protected] -- convert username in USER and LOGNAME env variables to canonical form +Patch23: xrdp-fix-username-in-env.patch +# PATCH-FIX-UPSTREAM xrdp-CVE-2026-32105-1-fips-slowpath.patch bsc#1262312 - [email protected] -- Check HMAC on FIPS slowpath input +Patch24: xrdp-CVE-2026-32105-1-fips-slowpath.patch +# PATCH-FIX-UPSTREAM xrdp-CVE-2026-32105-2-fips-fastpath.patch bsc#1262312 - [email protected] -- Check HMAC on FIPS fastpath input +Patch25: xrdp-CVE-2026-32105-2-fips-fastpath.patch +# PATCH-FIX-UPSTREAM xrdp-CVE-2026-32105-3-nonfips-slowpath.patch bsc#1262312 - [email protected] -- Check HMAC on non-FIPS slowpath input +Patch26: xrdp-CVE-2026-32105-3-nonfips-slowpath.patch +# PATCH-FIX-UPSTREAM xrdp-CVE-2026-32105-4-nonfips-fastpath.patch bsc#1262312 - [email protected] -- Check HMAC on non-FIPS fastpath input +Patch27: xrdp-CVE-2026-32105-4-nonfips-fastpath.patch +# PATCH-FIX-UPSTREAM xrdp-CVE-2026-32624.patch bsc#1262321 - [email protected] -- Fix buffer overflow if domain sep used +Patch28: xrdp-CVE-2026-32624.patch +# PATCH-FIX-UPSTREAM xrdp-CVE-2026-32107.patch bsc#1262313 - [email protected] -- Exit on failure of env_set_user() +Patch29: xrdp-CVE-2026-32107.patch +# PATCH-FIX-UPSTREAM xrdp-CVE-2026-32623.patch bsc#1262316 - [email protected] -- adding length and status checks in neutrinordp fragment reassembly +Patch30: xrdp-CVE-2026-32623.patch +# PATCH-FIX-UPSTREAM xrdp-CVE-2026-33145.patch bsc#1262331 - [email protected] -- Default AllowAlternateShell to 'no' +Patch31: xrdp-CVE-2026-33145.patch +# PATCH-FIX-UPSTREAM xrdp-CVE-2026-33689.patch bsc#1262332 - [email protected] -- Fix length check on channel open +Patch32: xrdp-CVE-2026-33689.patch +# PATCH-FIX-UPSTREAM xrdp-CVE-2026-35512.patch bsc#1262333 - [email protected] -- Check length for the EGFX dynamic virtual channel +Patch33: xrdp-CVE-2026-35512.patch # Keep SLE only patches on the bottom starting from patch number 1001 # PATCH-FEATURE-SLE xrdp-avahi.diff bnc#586785 - [email protected] -- Add Avahi support. Patch1001: xrdp-avahi.diff @@ -102,9 +127,22 @@ %prep %setup -q %patch -P 1 -p1 +%patch -P 2 -p1 +%patch -P 3 -p1 %patch -P 4 -p1 -%patch -P 5 -p1 -%patch -P 6 -p1 +%patch -P 21 -p1 +%patch -P 22 -p1 +%patch -P 23 -p1 +%patch -P 24 -p1 +%patch -P 25 -p1 +%patch -P 26 -p1 +%patch -P 27 -p1 +%patch -P 28 -p1 +%patch -P 29 -p1 +%patch -P 30 -p1 +%patch -P 31 -p1 +%patch -P 32 -p1 +%patch -P 33 -p1 %if 0%{?sle_version} %patch -P 1001 -p1 %patch -P 1002 -p1 ++++++ xrdp-Add-function-to-get-user-information-by-UID.patch ++++++ >From a16e56f711d1109311d1e51b612ef33ed55444c6 Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Thu, 8 Sep 2022 14:00:36 +0100 Subject: [PATCH 01/11] Add function to get user information by UID Moving to a uid_t to store the user information makes a lot of sense. When doing this, we need a function to get information about a user from the uid_t As well as creating the function g_getuser_info_by_uid() we also rename g_getuser_info() to g_getuser_info_by_name() and make the parameter ordering more usual. --- common/os_calls.c | 76 ++++++++++++++++++++++++++++++++++++++++------- common/os_calls.h | 6 ++-- sesman/access.c | 4 +-- sesman/env.c | 3 +- 4 files changed, 73 insertions(+), 16 deletions(-) Index: xrdp-0.9.27/common/os_calls.c =================================================================== --- xrdp-0.9.27.orig/common/os_calls.c +++ xrdp-0.9.27/common/os_calls.c @@ -2825,7 +2825,7 @@ g_initgroups(const char *username) return 0; #else int gid; - int error = g_getuser_info(username, &gid, NULL, NULL, NULL, NULL); + int error = g_getuser_info_by_name(username, NULL, &gid, NULL, NULL, NULL); if (error == 0) { error = initgroups(username, gid); @@ -3076,26 +3076,85 @@ g_sigterm(int pid) /* the caller is responsible to free the buffs */ /* does not work in win32 */ int -g_getuser_info(const char *username, int *gid, int *uid, char **shell, - char **dir, char **gecos) +g_getuser_info_by_name(const char *username, int *uid, int *gid, + char **shell, char **dir, char **gecos) +{ + int rv = 1; +#if !defined(_WIN32) + + if (username == NULL) + { + log_message(LOG_LEVEL_ERROR, "g_getuser_info_by_name() called for NULL user"); + } + else + { + struct passwd *pwd_1 = getpwnam(username); + + if (pwd_1 != 0) + { + rv = 0; + + if (uid != 0) + { + *uid = pwd_1->pw_uid; + } + + if (gid != 0) + { + *gid = pwd_1->pw_gid; + } + + if (shell != 0) + { + *shell = g_strdup(pwd_1->pw_shell); + } + + if (dir != 0) + { + *dir = g_strdup(pwd_1->pw_dir); + } + + if (gecos != 0) + { + *gecos = g_strdup(pwd_1->pw_gecos); + } + } + } +#endif + return rv; +} + + +/*****************************************************************************/ +/* returns 0 if ok */ +/* the caller is responsible to free the buffs */ +/* does not work in win32 */ +int +g_getuser_info_by_uid(int uid, char **username, int *gid, + char **shell, char **dir, char **gecos) { #if defined(_WIN32) return 1; #else struct passwd *pwd_1; - pwd_1 = getpwnam(username); + pwd_1 = getpwuid(uid); if (pwd_1 != 0) { + if (username != NULL) + { + *username = g_strdup(pwd_1->pw_name); + } + if (gid != 0) { *gid = pwd_1->pw_gid; } - if (uid != 0) + if (shell != 0) { - *uid = pwd_1->pw_uid; + *shell = g_strdup(pwd_1->pw_shell); } if (dir != 0) @@ -3103,11 +3162,6 @@ g_getuser_info(const char *username, int *dir = g_strdup(pwd_1->pw_dir); } - if (shell != 0) - { - *shell = g_strdup(pwd_1->pw_shell); - } - if (gecos != 0) { *gecos = g_strdup(pwd_1->pw_gecos); Index: xrdp-0.9.27/common/os_calls.h =================================================================== --- xrdp-0.9.27.orig/common/os_calls.h +++ xrdp-0.9.27/common/os_calls.h @@ -170,8 +170,10 @@ char *g_getenv(const char *name); int g_exit(int exit_code); int g_getpid(void); int g_sigterm(int pid); -int g_getuser_info(const char *username, int *gid, int *uid, char **shell, - char **dir, char **gecos); +int g_getuser_info_by_name(const char *username, int *uid, int *gid, + char **shell, char **dir, char **gecos); +int g_getuser_info_by_uid(int uid, char **username, int *gid, + char **shell, char **dir, char **gecos); int g_getgroup_info(const char *groupname, int *gid); /** * Checks whether a user is in the specified group Index: xrdp-0.9.27/sesman/env.c =================================================================== --- xrdp-0.9.27.orig/sesman/env.c +++ xrdp-0.9.27/sesman/env.c @@ -107,7 +107,8 @@ env_set_user(const char *username, char pw_shell = 0; pw_dir = 0; - error = g_getuser_info(username, &pw_gid, &pw_uid, &pw_shell, &pw_dir, 0); + error = g_getuser_info_by_name(username, &pw_uid, &pw_gid, &pw_shell, + &pw_dir, 0); if (error == 0) { ++++++ xrdp-CVE-2026-32105-1-fips-slowpath.patch ++++++ >From 0d8cf57e9d12393bd452a2b6cb1af0e38887d8a2 Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Tue, 10 Mar 2026 18:24:40 +0000 Subject: [PATCH] security: Check HMAC on FIPS slowpath input CVE-2026-32105: Add a check that the HMAC signature supplied with a FIPS slowpath input PDU matches the calculated signature. --- libxrdp/xrdp_sec.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 5943af96ad..d19d5c6d9c 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -1124,7 +1124,7 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) int len; int ver; int pad; - + const char *data_signature; if (xrdp_mcs_recv(self->mcs_layer, s, chan) != 0) { @@ -1168,7 +1168,7 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) in_uint16_le(s, len); /* length */ in_uint8(s, ver); /* version */ in_uint8(s, pad); /* padlen */ - in_uint8s(s, 8); /* signature(8) */ + in_uint8p(s, data_signature, 8); LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SECURITY_HEADER2 " "length %d, version %d, padlen %d, dataSignature (ignored)", len, ver, pad); @@ -1186,6 +1186,12 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) } xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); s->end -= pad; + if (!xrdp_sec_fips_check_sig(self, data_signature, 8, + s->p, (int)(s->end - s->p))) + { + LOG(LOG_LEVEL_ERROR, "MAC checksum error for FIPS PDU"); + return 1; + } } else if (self->crypt_level > CRYPT_LEVEL_NONE) { ++++++ xrdp-CVE-2026-32105-2-fips-fastpath.patch ++++++ >From 2a411f752591c0293a7698a452f00a46ef6c09bf Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Tue, 10 Mar 2026 18:03:39 +0000 Subject: [PATCH] security: Check HMAC on FIPS fastpath input CVE-2026-32105: Add a check that the HMAC signature supplied with a FIPS fastpath input PDU matches the calculated signature. --- libxrdp/xrdp_sec.c | 87 +++++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 32ce7d740d..5943af96ad 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -832,6 +832,54 @@ xrdp_sec_hash_48(char *out, char *in, char *salt1, char *salt2, int salt) ssl_md5_info_delete(md5_info); } +/*****************************************************************************/ +/* Output a uint32 into a buffer (little-endian) */ +static void +buf_out_uint32(char *buffer, int value) +{ + buffer[0] = (value) & 0xff; + buffer[1] = (value >> 8) & 0xff; + buffer[2] = (value >> 16) & 0xff; + buffer[3] = (value >> 24) & 0xff; +} + +/*****************************************************************************/ +/* Generate a MAC hash (5.2.3.1), using SHA1 for outgoing data */ +static void +xrdp_sec_fips_sign(struct xrdp_sec *self, char *out, int out_len, + char *data, int data_len) +{ + char buf[20]; + char lenhdr[4]; + + buf_out_uint32(lenhdr, self->encrypt_use_count); + ssl_hmac_sha1_init(self->sign_fips_info, self->fips_sign_key, 20); + ssl_hmac_transform(self->sign_fips_info, data, data_len); + ssl_hmac_transform(self->sign_fips_info, lenhdr, 4); + ssl_hmac_complete(self->sign_fips_info, buf, 20); + g_memcpy(out, buf, out_len); +} + +/*****************************************************************************/ +/* Check a FIPS hash is valid */ +static int +xrdp_sec_fips_check_sig(struct xrdp_sec *self, const char *sig, int sig_len, + char *data, int data_len) +{ + char buf[20]; + char lenhdr[4]; + + // Account for the decrypt operation which has just happened when + // creating the HMAC + buf_out_uint32(lenhdr, self->decrypt_use_count - 1); + ssl_hmac_sha1_init(self->sign_fips_info, self->fips_sign_key, 20); + ssl_hmac_transform(self->sign_fips_info, data, data_len); + ssl_hmac_transform(self->sign_fips_info, lenhdr, 4); + ssl_hmac_complete(self->sign_fips_info, buf, 20); + + return memcmp(buf, sig, sig_len) == 0; +} + /*****************************************************************************/ static void xrdp_sec_hash_16(char *out, char *in, char *salt1, char *salt2) @@ -984,6 +1032,7 @@ xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s) int ver; int len; int pad; + const char *data_signature; #ifndef USE_DEVEL_LOGGING /* TODO: remove UNUSED_VAR once the `ver` variable is used for more than @@ -1019,11 +1068,15 @@ xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s) } /* remainder of TS_FP_INPUT_PDU */ - in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */ - LOG_DEVEL(LOG_LEVEL_TRACE, "CRYPT_LEVEL_FIPS - data len %d", - (int)(s->end - s->p)); + in_uint8p(s, data_signature, 8); xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); s->end -= pad; + if (!xrdp_sec_fips_check_sig(self, data_signature, 8, + s->p, (int)(s->end - s->p))) + { + LOG(LOG_LEVEL_ERROR, "MAC checksum error for FP-FIPS PDU"); + return 1; + } } else { @@ -1215,34 +1268,6 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) return 0; } -/*****************************************************************************/ -/* Output a uint32 into a buffer (little-endian) */ -static void -buf_out_uint32(char *buffer, int value) -{ - buffer[0] = (value) & 0xff; - buffer[1] = (value >> 8) & 0xff; - buffer[2] = (value >> 16) & 0xff; - buffer[3] = (value >> 24) & 0xff; -} - -/*****************************************************************************/ -/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ -static void -xrdp_sec_fips_sign(struct xrdp_sec *self, char *out, int out_len, - char *data, int data_len) -{ - char buf[20]; - char lenhdr[4]; - - buf_out_uint32(lenhdr, self->encrypt_use_count); - ssl_hmac_sha1_init(self->sign_fips_info, self->fips_sign_key, 20); - ssl_hmac_transform(self->sign_fips_info, data, data_len); - ssl_hmac_transform(self->sign_fips_info, lenhdr, 4); - ssl_hmac_complete(self->sign_fips_info, buf, 20); - g_memcpy(out, buf, out_len); -} - /*****************************************************************************/ /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ static void ++++++ xrdp-CVE-2026-32105-3-nonfips-slowpath.patch ++++++ >From 759104912c64b33b2442ed788c1806e36d028db0 Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Tue, 10 Mar 2026 20:33:15 +0000 Subject: [PATCH] security: Check HMAC on non-FIPS slowpath input CVE-2026-32105: Add a check that the HMAC signature supplied with a non-FIPS slowpath input PDU matches the calculated signature. --- libxrdp/xrdp_sec.c | 104 +++++++++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 33 deletions(-) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index d19d5c6d9c..744b60c6dc 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -861,7 +861,10 @@ xrdp_sec_fips_sign(struct xrdp_sec *self, char *out, int out_len, } /*****************************************************************************/ -/* Check a FIPS hash is valid */ +/* Check a FIPS hash is valid + * + * Result is boolean (i.e. != 0 is OK) + * */ static int xrdp_sec_fips_check_sig(struct xrdp_sec *self, const char *sig, int sig_len, char *data, int data_len) @@ -880,6 +883,66 @@ xrdp_sec_fips_check_sig(struct xrdp_sec *self, const char *sig, int sig_len, return memcmp(buf, sig, sig_len) == 0; } +/*****************************************************************************/ +/* Generate a MAC hash (5.3.6.1), using a combination of SHA1 and MD5 + * + * Salted MAC is not currently supported */ +static void +xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len, + char *data, int data_len) +{ + char shasig[20]; + char md5sig[16]; + char lenhdr[4]; + void *sha1_info; + void *md5_info; + + buf_out_uint32(lenhdr, data_len); + sha1_info = ssl_sha1_info_create(); + md5_info = ssl_md5_info_create(); + ssl_sha1_clear(sha1_info); + ssl_sha1_transform(sha1_info, self->sign_key, self->rc4_key_len); + ssl_sha1_transform(sha1_info, (char *)g_pad_54, 40); + ssl_sha1_transform(sha1_info, lenhdr, 4); + ssl_sha1_transform(sha1_info, data, data_len); + ssl_sha1_complete(sha1_info, shasig); + ssl_md5_clear(md5_info); + ssl_md5_transform(md5_info, self->sign_key, self->rc4_key_len); + ssl_md5_transform(md5_info, (char *)g_pad_92, 48); + ssl_md5_transform(md5_info, shasig, 20); + ssl_md5_complete(md5_info, md5sig); + g_memcpy(out, md5sig, out_len); + ssl_sha1_info_delete(sha1_info); + ssl_md5_info_delete(md5_info); +} + +/*****************************************************************************/ +/* Check a non-FIPS hash is valid + * + * Salted MAC is not currently supported + * + * Result is boolean (i.e. != 0 is OK) */ +static int +xrdp_sec_check_sig(struct xrdp_sec *self, const char *sig, int sig_len, + char *data, int data_len) +{ + char computed[8]; + int rv = 0; + if (sig_len > (int)sizeof(computed)) + { + LOG(LOG_LEVEL_ERROR, + "xrdp_sec_check_sig() Buffer overflow (got %d expected %d)", + sig_len, (int)sizeof(computed)); + } + else + { + xrdp_sec_sign(self, computed, sig_len, data, data_len); + rv = (memcmp(computed, sig, sig_len) == 0); + } + + return rv; +} + /*****************************************************************************/ static void xrdp_sec_hash_16(char *out, char *in, char *salt1, char *salt2) @@ -1200,10 +1263,16 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) return 1; } /* TS_SECURITY_HEADER1 */ - in_uint8s(s, 8); /* signature(8) */ + in_uint8p(s, data_signature, 8); LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SECURITY_HEADER1 " "dataSignature (ignored)"); xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); + if (!xrdp_sec_check_sig(self, data_signature, 8, + s->p, (int)(s->end - s->p))) + { + LOG(LOG_LEVEL_ERROR, "MAC checksum error for non-FIPS PDU"); + return 1; + } } } @@ -1274,37 +1343,6 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) return 0; } -/*****************************************************************************/ -/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ -static void -xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len, - char *data, int data_len) -{ - char shasig[20]; - char md5sig[16]; - char lenhdr[4]; - void *sha1_info; - void *md5_info; - - buf_out_uint32(lenhdr, data_len); - sha1_info = ssl_sha1_info_create(); - md5_info = ssl_md5_info_create(); - ssl_sha1_clear(sha1_info); - ssl_sha1_transform(sha1_info, self->sign_key, self->rc4_key_len); - ssl_sha1_transform(sha1_info, (char *)g_pad_54, 40); - ssl_sha1_transform(sha1_info, lenhdr, 4); - ssl_sha1_transform(sha1_info, data, data_len); - ssl_sha1_complete(sha1_info, shasig); - ssl_md5_clear(md5_info); - ssl_md5_transform(md5_info, self->sign_key, self->rc4_key_len); - ssl_md5_transform(md5_info, (char *)g_pad_92, 48); - ssl_md5_transform(md5_info, shasig, 20); - ssl_md5_complete(md5_info, md5sig); - g_memcpy(out, md5sig, out_len); - ssl_sha1_info_delete(sha1_info); - ssl_md5_info_delete(md5_info); -} - /*****************************************************************************/ /* returns error */ int ++++++ xrdp-CVE-2026-32105-4-nonfips-fastpath.patch ++++++ >From 187d22cef89e8d60091d52e4abf64b82c49d57ee Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Tue, 10 Mar 2026 20:38:50 +0000 Subject: [PATCH] security: Check HMAC on non-FIPS fastpath input CVE-2026-32105: Add a check that the HMAC signature supplied with a non-FIPS fastpath input PDU matches the calculated signature. --- libxrdp/xrdp_sec.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 744b60c6dc..6b2b9ec446 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -1149,8 +1149,14 @@ xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s) return 1; } /* remainder of TS_FP_INPUT_PDU */ - in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */ + in_uint8p(s, data_signature, 8); xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); + if (!xrdp_sec_check_sig(self, data_signature, 8, + s->p, (int)(s->end - s->p))) + { + LOG(LOG_LEVEL_ERROR, "MAC checksum error for FP-non-FIPS PDU"); + return 1; + } } } ++++++ xrdp-CVE-2026-32107.patch ++++++ >From 53bc57cf59a9f72a1c3c31221841c8ee6d240f98 Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Fri, 6 Mar 2026 11:44:56 +0000 Subject: [PATCH] security: Exit on failure of env_set_user() CVE-2026-32107. Prevent possible privilege escalation if setuid() fails. --- sesman/env.c | 150 +++++++++++++++++++++++-------------------- sesman/env.h | 6 +- 2 files changed, 83 insertions(+), 73 deletions(-) Index: xrdp-0.9.27/sesman/env.c =================================================================== --- xrdp-0.9.27.orig/sesman/env.c +++ xrdp-0.9.27/sesman/env.c @@ -87,14 +87,13 @@ env_check_password_file(const char *file /******************************************************************************/ /* its the responsibility of the caller to free passwd_file */ -int +void env_set_user(const char *username, char **passwd_file, int display, const struct list *env_names, const struct list *env_values) { int error; int pw_uid; int pw_gid; - int uid; int index; int len; char *name; @@ -124,120 +123,113 @@ env_set_user(const char *username, char pw_username = g_strdup(username); } - g_rm_temp_dir(); - /* - * Set the primary group. Note that secondary groups should already - * have been set */ - error = g_setgid(pw_gid); - - if (error == 0) + if (g_setgid(pw_gid) != 0 || g_setuid(pw_uid) != 0) { - uid = pw_uid; - error = g_setuid(uid); + LOG(LOG_LEVEL_ALWAYS, + "fatal error getting setting uid:gid to %d:%d - %s", + pw_uid, pw_gid, g_get_strerror()); + goto fatal; } + g_rm_temp_dir(); g_mk_socket_path(0); - - if (error == 0) - { - g_clearenv(); - g_setenv("SHELL", pw_shell, 1); - g_setenv("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin", 1); - g_setenv("USER", pw_username, 1); - g_setenv("LOGNAME", pw_username, 1); - g_sprintf(text, "%d", uid); - g_setenv("UID", text, 1); - g_setenv("HOME", pw_dir, 1); - g_set_current_dir(pw_dir); - g_sprintf(text, ":%d.0", display); - g_setenv("DISPLAY", text, 1); - g_setenv("XRDP_SESSION", "1", 1); - /* XRDP_SOCKET_PATH should be set even here. It's used by - * xorgxrdp and the pulseaudio plugin */ - g_setenv("XRDP_SOCKET_PATH", XRDP_SOCKET_PATH, 1); - /* pulse sink socket */ - g_snprintf(text, sizeof(text) - 1, CHANSRV_PORT_OUT_BASE_STR, display); - g_setenv("XRDP_PULSE_SINK_SOCKET", text, 1); - /* pulse source socket */ - g_snprintf(text, sizeof(text) - 1, CHANSRV_PORT_IN_BASE_STR, display); - g_setenv("XRDP_PULSE_SOURCE_SOCKET", text, 1); - if ((env_names != 0) && (env_values != 0) && - (env_names->count == env_values->count)) + g_clearenv(); + g_setenv("SHELL", pw_shell, 1); + g_setenv("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin", 1); + g_setenv("USER", pw_username, 1); + g_setenv("LOGNAME", pw_username, 1); + g_sprintf(text, "%d", pw_uid); + g_setenv("UID", text, 1); + g_setenv("HOME", pw_dir, 1); + g_set_current_dir(pw_dir); + g_sprintf(text, ":%d.0", display); + g_setenv("DISPLAY", text, 1); + g_setenv("XRDP_SESSION", "1", 1); + /* XRDP_SOCKET_PATH should be set even here. It's used by + * xorgxrdp and the pulseaudio plugin */ + g_setenv("XRDP_SOCKET_PATH", XRDP_SOCKET_PATH, 1); + /* pulse sink socket */ + g_snprintf(text, sizeof(text) - 1, CHANSRV_PORT_OUT_BASE_STR, display); + g_setenv("XRDP_PULSE_SINK_SOCKET", text, 1); + /* pulse source socket */ + g_snprintf(text, sizeof(text) - 1, CHANSRV_PORT_IN_BASE_STR, display); + g_setenv("XRDP_PULSE_SOURCE_SOCKET", text, 1); + if ((env_names != 0) && (env_values != 0) && + (env_names->count == env_values->count)) { for (index = 0; index < env_names->count; index++) - { - name = (char *) list_get_item(env_names, index), - value = (char *) list_get_item(env_values, index), - g_setenv(name, value, 1); - } + { + name = (char *) list_get_item(env_names, index), + value = (char *) list_get_item(env_values, index), + g_setenv(name, value, 1); + } } - g_gethostname(hostname, 255); - hostname[255] = 0; - if (passwd_file != 0) + g_gethostname(hostname, 255); + hostname[255] = 0; + if (passwd_file != 0) { if (0 == g_cfg->auth_file_path) - { - /* if no auth_file_path is set, then we go for - $HOME/.vnc/sesman_passwd-USERNAME@HOSTNAME:DISPLAY */ - if (!g_directory_exist(".vnc")) { - if (g_mkdir(".vnc") < 0) - { - LOG(LOG_LEVEL_ERROR, - "Error creating .vnc directory: %s", - g_get_strerror()); - } + /* if no auth_file_path is set, then we go for + $HOME/.vnc/sesman_passwd-USERNAME@HOSTNAME:DISPLAY */ + if (!g_directory_exist(".vnc")) + { + if (g_mkdir(".vnc") < 0) + { + LOG(LOG_LEVEL_ERROR, + "Error creating .vnc directory: %s", + g_get_strerror()); + } + } + + len = g_snprintf(NULL, 0, "%s/.vnc/sesman_passwd-%s@%s:%d", + pw_dir, pw_username, hostname, display); + + *passwd_file = (char *) g_malloc(len + 1, 1); + if (*passwd_file != NULL) + { + /* Try legacy names first, remove if found */ + g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd:%d", + pw_dir, pw_username, display); + if (g_file_exist(*passwd_file)) + { + LOG(LOG_LEVEL_WARNING, "Removing old " + "password file %s", *passwd_file); + g_file_delete(*passwd_file); + } + g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd", + pw_dir, pw_username); + if (g_file_exist(*passwd_file)) + { + LOG(LOG_LEVEL_WARNING, "Removing insecure " + "password file %s", *passwd_file); + g_file_delete(*passwd_file); + } + g_sprintf(*passwd_file, "%s/.vnc/sesman_passwd-%s@%s:%d", + pw_dir, pw_username, hostname, display); + } } - - len = g_snprintf(NULL, 0, "%s/.vnc/sesman_passwd-%s@%s:%d", - pw_dir, pw_username, hostname, display); - - *passwd_file = (char *) g_malloc(len + 1, 1); - if (*passwd_file != NULL) - { - /* Try legacy names first, remove if found */ - g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd:%d", - pw_dir, pw_username, display); - if (g_file_exist(*passwd_file)) - { - LOG(LOG_LEVEL_WARNING, "Removing old " - "password file %s", *passwd_file); - g_file_delete(*passwd_file); - } - g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd", - pw_dir, pw_username); - if (g_file_exist(*passwd_file)) - { - LOG(LOG_LEVEL_WARNING, "Removing insecure " - "password file %s", *passwd_file); - g_file_delete(*passwd_file); - } - g_sprintf(*passwd_file, "%s/.vnc/sesman_passwd-%s@%s:%d", - pw_dir, pw_username, hostname, display); - } - } else - { - /* we use auth_file_path as requested */ - len = g_snprintf(NULL, 0, g_cfg->auth_file_path, pw_username); - - *passwd_file = (char *) g_malloc(len + 1, 1); - if (*passwd_file != NULL) { - g_sprintf(*passwd_file, g_cfg->auth_file_path, pw_username); + /* we use auth_file_path as requested */ + len = g_snprintf(NULL, 0, g_cfg->auth_file_path, pw_username); + + *passwd_file = (char *) g_malloc(len + 1, 1); + if (*passwd_file != NULL) + { + g_sprintf(*passwd_file, g_cfg->auth_file_path, pw_username); + } } - } if (*passwd_file != NULL) - { - LOG_DEVEL(LOG_LEVEL_DEBUG, "pass file: %s", *passwd_file); - } + { + LOG_DEVEL(LOG_LEVEL_DEBUG, "pass file: %s", *passwd_file); + } } - g_free(pw_username); - g_free(pw_dir); - g_free(pw_shell); - } + g_free(pw_username); + g_free(pw_dir); + g_free(pw_shell); } else { @@ -246,5 +238,13 @@ env_set_user(const char *username, char username); } - return error; + return; + +fatal: + g_free(pw_username); + g_free(pw_dir); + g_free(pw_shell); + + g_exit(1); + } Index: xrdp-0.9.27/sesman/env.h =================================================================== --- xrdp-0.9.27.orig/sesman/env.h +++ xrdp-0.9.27/sesman/env.h @@ -46,10 +46,11 @@ env_check_password_file(const char *file * @param username Username * @param passwd_file VNC password file * @param display The session display - * @return 0 on success, g_getuser_info() error codes on error + * On error, the calling process exits, to prevent privilege + * escalations. * */ -int +void env_set_user(const char *username, char **passwd_file, int display, const struct list *env_names, const struct list *env_values); ++++++ xrdp-CVE-2026-32623.patch ++++++ >From 3f0f7df6ffc639092b872600ac263db3af6bd643 Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Mon, 9 Mar 2026 14:20:35 +0000 Subject: [PATCH] CVE-2026-32623: vulns in neutrinordp fragment reassembly This PR addresses potential buffer overflows in fragment reassembly in the neutrinordp shim by adding length and status checks. --- neutrinordp/xrdp-neutrinordp.c | 109 +++++++++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 13 deletions(-) diff --git a/neutrinordp/xrdp-neutrinordp.c b/neutrinordp/xrdp-neutrinordp.c index 76985bba94..8fdc3d7ec3 100644 --- a/neutrinordp/xrdp-neutrinordp.c +++ b/neutrinordp/xrdp-neutrinordp.c @@ -491,7 +491,6 @@ lxrdp_event(struct mod *mod, int msg, long param1, long param2, size = (int)param2; data = (char *)param3; total_size = (int)param4; - LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_event: client to server ,chanid= %d flags= %d", chanid, flags); if ((chanid < 0) || (chanid >= mod->inst->settings->num_channels)) @@ -500,40 +499,124 @@ lxrdp_event(struct mod *mod, int msg, long param1, long param2, break; } + if (size < 0 || total_size < 0) + { + LOG(LOG_LEVEL_ERROR, "Bad WM_CHANNEL_DATA received"); + g_free(mod->chan_buf); + mod->chan_buf = NULL; + mod->chan_buf_bytes = 0; + mod->chan_buf_valid = 0; + break; + } + lchid = mod->inst->settings->channels[chanid].channel_id; switch (flags & 3) { case 3: - mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)data, total_size); + if (mod->chan_buf != NULL) + { + // This shouldn't happen. Lose the fragments we have + LOG(LOG_LEVEL_WARNING, + "WM_CHANNEL_DATA - unexpected full chunk received"); + g_free(mod->chan_buf); + mod->chan_buf = NULL; + mod->chan_buf_bytes = 0; + mod->chan_buf_valid = 0; + } + if (size != total_size) + { + LOG(LOG_LEVEL_ERROR, + "WM_CHANNEL_DATA - inconsistent full chunk size"); + } + else + { + mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)data, total_size); + } break; case 2: /* end */ - g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); - mod->chan_buf_valid += size; - mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)(mod->chan_buf), - total_size); + if (size != (mod->chan_buf_bytes - mod->chan_buf_valid)) + { + LOG(LOG_LEVEL_ERROR, + "WM_CHANNEL_DATA - bad end fragment size." + " Was %d s/b %d", + size, mod->chan_buf_bytes - mod->chan_buf_valid); + } + else + { + g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); + mod->chan_buf_valid += size; + mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)(mod->chan_buf), + total_size); + } g_free(mod->chan_buf); - mod->chan_buf = 0; + mod->chan_buf = NULL; mod->chan_buf_bytes = 0; mod->chan_buf_valid = 0; break; case 1: /* start */ + if (mod->chan_buf != NULL) + { + // This shouldn't happen + LOG(LOG_LEVEL_WARNING, + "WM_CHANNEL_DATA - unexpected start chunk received"); + } g_free(mod->chan_buf); - mod->chan_buf = (char *)g_malloc(total_size, 0); - mod->chan_buf_bytes = total_size; + mod->chan_buf = NULL; + mod->chan_buf_bytes = 0; mod->chan_buf_valid = 0; - g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); - mod->chan_buf_valid += size; + if (size > total_size) + { + LOG(LOG_LEVEL_ERROR, + "WM_CHANNEL_DATA - bad start fragment size"); + } + else + { + if (total_size == 0) + { + // Nothing in the specification disallows this, + // but it seems pathological + mod->chan_buf = (char *)g_malloc(1, 0); + } + else + { + mod->chan_buf = (char *)g_malloc(total_size, 0); + } + if (mod->chan_buf == NULL) + { + LOG(LOG_LEVEL_ERROR, + "WM_CHANNEL_DATA - can't allocate %d bytes", + total_size); + } + else + { + mod->chan_buf_bytes = total_size; + g_memcpy(mod->chan_buf, data, size); + mod->chan_buf_valid += size; + } + } break; default: /* middle */ - g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); - mod->chan_buf_valid += size; + if (size > (mod->chan_buf_bytes - mod->chan_buf_valid)) + { + LOG(LOG_LEVEL_ERROR, + "WM_CHANNEL_DATA - oversized middle fragment"); + g_free(mod->chan_buf); + mod->chan_buf = NULL; + mod->chan_buf_bytes = 0; + mod->chan_buf_valid = 0; + } + else + { + g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); + mod->chan_buf_valid += size; + } break; } ++++++ xrdp-CVE-2026-32624.patch ++++++ >From f1a2bec41560ccc420931d94f07a18c31141c069 Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Fri, 6 Mar 2026 11:03:48 +0000 Subject: [PATCH] CVE-2026-32624: buffer overflow if domain sep used Check the username buffer is not overflowed if the domain separator feature is used. --- libxrdp/xrdp_sec.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) Index: xrdp-0.9.27/libxrdp/xrdp_sec.c =================================================================== --- xrdp-0.9.27.orig/libxrdp/xrdp_sec.c +++ xrdp-0.9.27/libxrdp/xrdp_sec.c @@ -1062,10 +1062,23 @@ xrdp_sec_process_logon_info(struct xrdp_ if (self->rdp_layer->client_info.domain_user_separator[0] != '\0' && self->rdp_layer->client_info.domain[0] != '\0') { - LOG(LOG_LEVEL_DEBUG, "Client supplied domain with user name. Overwriting user name with user name parsed from domain."); - int size = sizeof(self->rdp_layer->client_info.username); - g_strncat(self->rdp_layer->client_info.username, self->rdp_layer->client_info.domain_user_separator, size - 1 - g_strlen(self->rdp_layer->client_info.domain_user_separator)); - g_strncat(self->rdp_layer->client_info.username, self->rdp_layer->client_info.domain, size - 1 - g_strlen(self->rdp_layer->client_info.domain)); + // Check the composite string is not too long + unsigned int size = + g_strlen(self->rdp_layer->client_info.username) + + g_strlen(self->rdp_layer->client_info.domain_user_separator) + + g_strlen(self->rdp_layer->client_info.domain); + + if (size >= sizeof(self->rdp_layer->client_info.username)) + { + LOG(LOG_LEVEL_ERROR, "Username/domain is too long"); + return 1; + } + LOG(LOG_LEVEL_DEBUG, "Client supplied domain with user name." + " Overwriting user name with user name parsed from domain."); + g_strcat(self->rdp_layer->client_info.username, + self->rdp_layer->client_info.domain_user_separator); + g_strcat(self->rdp_layer->client_info.username, + self->rdp_layer->client_info.domain); } if (unicode_utf16_in(s, len_program, self->rdp_layer->client_info.program, sizeof(self->rdp_layer->client_info.program) - 1) != 0) ++++++ xrdp-CVE-2026-33145.patch ++++++ >From 45f62bdedda425d323c8a1b926503edd02df1681 Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Wed, 11 Mar 2026 15:55:04 +0000 Subject: [PATCH] CVE-2026-33145: Default AllowAlternateShell to 'no' --- docs/man/sesman.ini.5.in | 3 ++- sesman/libsesman/sesman_config.c | 2 +- sesman/sesman.ini.in | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) Index: xrdp-0.9.27/docs/man/sesman.ini.5.in =================================================================== --- xrdp-0.9.27.orig/docs/man/sesman.ini.5.in +++ xrdp-0.9.27/docs/man/sesman.ini.5.in @@ -285,7 +285,8 @@ if the group specified in \fBTerminalSer .TP \fBAllowAlternateShell\fR=\fI[true|false]\fR -If set to \fB0\fR, \fBfalse\fR or \fBno\fR, prevent usage of alternate shells by users. +Set to \fB1\fR, \fBtrue\fR or \fByes\fR, to allow alternate shells to +be specified by users. .SH "X11 SERVER" Following parameters can be used in the \fB[X11rdp]\fR, \fB[Xvnc]\fR and Index: xrdp-0.9.27/sesman/config.c =================================================================== --- xrdp-0.9.27.orig/sesman/config.c +++ xrdp-0.9.27/sesman/config.c @@ -213,7 +213,7 @@ config_read_security(int file, struct co sc->ts_admins_enable = 0; sc->restrict_outbound_clipboard = 0; sc->restrict_inbound_clipboard = 0; - sc->allow_alternate_shell = 1; + sc->allow_alternate_shell = 0; file_read_section(file, SESMAN_CFG_SECURITY, param_n, param_v); Index: xrdp-0.9.27/sesman/sesman.ini =================================================================== --- xrdp-0.9.27.orig/sesman/sesman.ini +++ xrdp-0.9.27/sesman/sesman.ini @@ -37,8 +37,8 @@ RestrictOutboundClipboard=none ; false: an alias of none ; yes: an alias of all RestrictInboundClipboard=none -; Set to 'no' to prevent users from logging in with alternate shells -#AllowAlternateShell=true +; Set to 'yes' to allow users to log in with alternate shells +#AllowAlternateShell=no [Sessions] ;; X11DisplayOffset - x11 display number offset ++++++ xrdp-CVE-2026-33689.patch ++++++ >From 3c131a9f5e2bd01fff4f5912c324ffad0fc71ab6 Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Mon, 23 Mar 2026 13:42:50 +0000 Subject: [PATCH] CVE-2026-33689: Fix length check on channel open A check for at least two bytes remaining in a buffer should be 4 bytes. --- xrdp/xrdp_mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 0857021816..72755f638c 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -2243,7 +2243,7 @@ xrdp_mm_trans_process_drdynvc_channel_open(struct xrdp_mm *self, char name[1024 + 1]; struct xrdp_drdynvc_procs procs; - if (!s_check_rem(s, 2)) + if (!s_check_rem(s, 4)) { return 1; } ++++++ xrdp-CVE-2026-35512.patch ++++++ >From 41a4af0a362724f4e7899dc98ac388b2d7e09df4 Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Wed, 1 Apr 2026 10:49:51 +0100 Subject: [PATCH] CVE-2026-35512: Heap overflow in dynvc processing Length checking for the EGFX dynamic virtual channel is inadequate, allowing for heap overflows to be forced by a malicious client before authentication. --- libxrdp/xrdp_channel.c | 11 ++++++++++- xrdp/xrdp_egfx.c | 9 ++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) Index: xrdp-0.9.27/libxrdp/xrdp_channel.c =================================================================== --- xrdp-0.9.27.orig/libxrdp/xrdp_channel.c +++ xrdp-0.9.27/libxrdp/xrdp_channel.c @@ -468,6 +468,15 @@ drdynvc_process_data_first(struct xrdp_c "ChannelId %d, Length %d, Data (omitted from the log)", chan_id, total_bytes); + // See [MS-RDPBCGR] 2.2.3 + if (total_bytes < 1590 || bytes > total_bytes) + { + LOG(LOG_LEVEL_ERROR, + "Badly formed DYNVC_DATA_FIRST PDU received on dynamic channel %d", + chan_id); + return 1; + } + session = self->sec_layer->rdp_layer->session; if (chan_id > 255) { @@ -513,7 +522,7 @@ drdynvc_process_data(struct xrdp_channel session = self->sec_layer->rdp_layer->session; if (chan_id > 255) { - LOG(LOG_LEVEL_ERROR, "Received message for an invalid " + LOG(LOG_LEVEL_ERROR, "Received DYNVC_DATA PDU for an invalid " "channel id. channel id %d", chan_id); return 1; } ++++++ xrdp-Moved-initgroups-call-to-before-auth_start_session.patch ++++++ >From 4183d8ddbfd1399a1c7255f6de31298bea18655b Mon Sep 17 00:00:00 2001 From: matt335672 <[email protected]> Date: Thu, 2 Sep 2021 11:44:51 +0100 Subject: [PATCH] Moved initgroups call to before auth_start_session() This is required for PAM systems that depend on group membership being available during PAM processing. This is used by pam_group on FreeBSD and pam_group on Linux-PAM, although the functionality of both is different. --- common/os_calls.c | 10 ++++++++-- common/os_calls.h | 2 +- sesman/env.c | 8 +++----- sesman/session.c | 10 ++++++++++ 4 files changed, 22 insertions(+), 8 deletions(-) Index: xrdp-0.9.27/common/os_calls.c =================================================================== --- xrdp-0.9.27.orig/common/os_calls.c +++ xrdp-0.9.27/common/os_calls.c @@ -2819,12 +2819,18 @@ g_setgid(int pid) /* returns error, zero is success, non zero is error */ /* does not work in win32 */ int -g_initgroups(const char *user, int gid) +g_initgroups(const char *username) { #if defined(_WIN32) return 0; #else - return initgroups(user, gid); + int gid; + int error = g_getuser_info(username, &gid, NULL, NULL, NULL, NULL); + if (error == 0) + { + error = initgroups(username, gid); + } + return error; #endif } Index: xrdp-0.9.27/common/os_calls.h =================================================================== --- xrdp-0.9.27.orig/common/os_calls.h +++ xrdp-0.9.27/common/os_calls.h @@ -154,7 +154,7 @@ void g_signal_pipe(void (*func)(int) void g_signal_usr1(void (*func)(int)); int g_fork(void); int g_setgid(int pid); -int g_initgroups(const char *user, int gid); +int g_initgroups(const char *user); int g_getuid(void); int g_getgid(void); int g_setuid(int pid); Index: xrdp-0.9.27/sesman/env.c =================================================================== --- xrdp-0.9.27.orig/sesman/env.c +++ xrdp-0.9.27/sesman/env.c @@ -112,15 +112,13 @@ env_set_user(const char *username, char if (error == 0) { g_rm_temp_dir(); + /* + * Set the primary group. Note that secondary groups should already + * have been set */ error = g_setgid(pw_gid); if (error == 0) { - error = g_initgroups(username, pw_gid); - } - - if (error == 0) - { uid = pw_uid; error = g_setuid(uid); } Index: xrdp-0.9.27/sesman/session.c =================================================================== --- xrdp-0.9.27.orig/sesman/session.c +++ xrdp-0.9.27/sesman/session.c @@ -512,6 +512,16 @@ session_start_fork(tbus data, tui8 type, "[session start] (display %d): calling auth_start_session from pid %d", display, g_getpid()); + /* Set the secondary groups before starting the session to prevent + * problems on PAM-based systems (see pam_setcred(3)) */ + if (g_initgroups(s->username) != 0) + { + log_message(LOG_LEVEL_ERROR, + "Failed to initialise secondary groups for %s: %s", + s->username, g_get_strerror()); + g_exit(1); + } + /* Clone the session object, as the passed-in copy will be * deleted by sesman_close_all() */ if ((s = scp_session_clone(s)) == NULL) ++++++ xrdp-avahi.diff ++++++ --- /var/tmp/diff_new_pack.WMNbXk/_old 2026-05-19 17:52:11.113139103 +0200 +++ /var/tmp/diff_new_pack.WMNbXk/_new 2026-05-19 17:52:11.117139268 +0200 @@ -1,19 +1,19 @@ -Index: xrdp-0.9.23.1/configure.ac +Index: xrdp-0.9.27/configure.ac =================================================================== ---- xrdp-0.9.23.1.orig/configure.ac -+++ xrdp-0.9.23.1/configure.ac -@@ -9,6 +9,7 @@ AC_PROG_CC - AC_C_CONST +--- xrdp-0.9.27.orig/configure.ac ++++ xrdp-0.9.27/configure.ac +@@ -9,6 +9,7 @@ AC_CONFIG_MACRO_DIR([m4]) + AC_PROG_CC AC_PROG_LIBTOOL +PKG_CHECK_MODULES(AVAHI, avahi-client >= 0.6.4) PKG_PROG_PKG_CONFIG if test "x$PKG_CONFIG" = "x"; then AC_MSG_ERROR([please install pkg-config]) -Index: xrdp-0.9.23.1/xrdp/Makefile.am +Index: xrdp-0.9.27/xrdp/Makefile.am =================================================================== ---- xrdp-0.9.23.1.orig/xrdp/Makefile.am -+++ xrdp-0.9.23.1/xrdp/Makefile.am +--- xrdp-0.9.27.orig/xrdp/Makefile.am ++++ xrdp-0.9.27/xrdp/Makefile.am @@ -14,6 +14,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/common \ -I$(top_srcdir)/sesman/libscp \ @@ -38,11 +38,11 @@ $(XRDP_EXTRA_LIBS) xrdpsysconfdir=$(sysconfdir)/xrdp -Index: xrdp-0.9.23.1/xrdp/xrdp.h +Index: xrdp-0.9.27/xrdp/xrdp.h =================================================================== ---- xrdp-0.9.23.1.orig/xrdp/xrdp.h -+++ xrdp-0.9.23.1/xrdp/xrdp.h -@@ -580,3 +580,10 @@ server_add_char_alpha(struct xrdp_mod *m +--- xrdp-0.9.27.orig/xrdp/xrdp.h ++++ xrdp-0.9.27/xrdp/xrdp.h +@@ -582,3 +582,10 @@ server_add_char_alpha(struct xrdp_mod *m int server_session_info(struct xrdp_mod *mod, const char *data, int data_bytes); @@ -53,10 +53,10 @@ +xrdp_avahi_fini(void); +void +xrdp_avahi_get_port(char *port); -Index: xrdp-0.9.23.1/xrdp/xrdp_avahi.c +Index: xrdp-0.9.27/xrdp/xrdp_avahi.c =================================================================== --- /dev/null -+++ xrdp-0.9.23.1/xrdp/xrdp_avahi.c ++++ xrdp-0.9.27/xrdp/xrdp_avahi.c @@ -0,0 +1,182 @@ +/* + This program is free software; you can redistribute it and/or modify @@ -240,10 +240,10 @@ + if (fd != -1) + g_file_close(fd); +} -Index: xrdp-0.9.23.1/common/arch.h +Index: xrdp-0.9.27/common/arch.h =================================================================== ---- xrdp-0.9.23.1.orig/common/arch.h -+++ xrdp-0.9.23.1/common/arch.h +--- xrdp-0.9.27.orig/common/arch.h ++++ xrdp-0.9.27/common/arch.h @@ -22,27 +22,7 @@ #include <stdlib.h> #include <string.h> ++++++ xrdp-fix-username-in-env.patch ++++++ Convert username entered by user to canonical form before exporting to environment variables. Username can use different formats with domain prefixes or suffixes. Conversion of username to uid and back from uid to username gives us canonical username form as it's stored in passwd database. Patch implements a small subset of functionality from upstream pull request https://github.com/neutrinolabs/xrdp/pull/2472 Index: xrdp-0.9.27/sesman/env.c =================================================================== --- xrdp-0.9.27.orig/sesman/env.c +++ xrdp-0.9.27/sesman/env.c @@ -99,6 +99,7 @@ env_set_user(const char *username, char int len; char *name; char *value; + char *pw_username; char *pw_shell; char *pw_dir; char text[256]; @@ -112,6 +113,17 @@ env_set_user(const char *username, char if (error == 0) { + + /* Convert username to uid and back to pw_username to get unique username + * form with(out) various domain suffixes. + */ + error = g_getuser_info_by_uid(pw_uid, &pw_username, 0, 0, 0, 0); + + if (error != 0) + { + pw_username = g_strdup(username); + } + g_rm_temp_dir(); /* * Set the primary group. Note that secondary groups should already @@ -131,8 +143,8 @@ env_set_user(const char *username, char g_clearenv(); g_setenv("SHELL", pw_shell, 1); g_setenv("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin", 1); - g_setenv("USER", username, 1); - g_setenv("LOGNAME", username, 1); + g_setenv("USER", pw_username, 1); + g_setenv("LOGNAME", pw_username, 1); g_sprintf(text, "%d", uid); g_setenv("UID", text, 1); g_setenv("HOME", pw_dir, 1); @@ -178,14 +190,14 @@ env_set_user(const char *username, char } len = g_snprintf(NULL, 0, "%s/.vnc/sesman_passwd-%s@%s:%d", - pw_dir, username, hostname, display); + pw_dir, pw_username, hostname, display); *passwd_file = (char *) g_malloc(len + 1, 1); if (*passwd_file != NULL) { /* Try legacy names first, remove if found */ g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd:%d", - pw_dir, username, display); + pw_dir, pw_username, display); if (g_file_exist(*passwd_file)) { LOG(LOG_LEVEL_WARNING, "Removing old " @@ -193,7 +205,7 @@ env_set_user(const char *username, char g_file_delete(*passwd_file); } g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd", - pw_dir, username); + pw_dir, pw_username); if (g_file_exist(*passwd_file)) { LOG(LOG_LEVEL_WARNING, "Removing insecure " @@ -201,18 +213,18 @@ env_set_user(const char *username, char g_file_delete(*passwd_file); } g_sprintf(*passwd_file, "%s/.vnc/sesman_passwd-%s@%s:%d", - pw_dir, username, hostname, display); + pw_dir, pw_username, hostname, display); } } else { /* we use auth_file_path as requested */ - len = g_snprintf(NULL, 0, g_cfg->auth_file_path, username); + len = g_snprintf(NULL, 0, g_cfg->auth_file_path, pw_username); *passwd_file = (char *) g_malloc(len + 1, 1); if (*passwd_file != NULL) { - g_sprintf(*passwd_file, g_cfg->auth_file_path, username); + g_sprintf(*passwd_file, g_cfg->auth_file_path, pw_username); } } @@ -222,6 +234,7 @@ env_set_user(const char *username, char } } + g_free(pw_username); g_free(pw_dir); g_free(pw_shell); }
