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);
         }

Reply via email to