Skip to content

Improve text clipboard interoperability with strict clients#3805

Open
YTjungle666 wants to merge 2 commits into
neutrinolabs:develfrom
YTjungle666:clipboard-strict-client-text-fix-20260509
Open

Improve text clipboard interoperability with strict clients#3805
YTjungle666 wants to merge 2 commits into
neutrinolabs:develfrom
YTjungle666:clipboard-strict-client-text-fix-20260509

Conversation

@YTjungle666
Copy link
Copy Markdown

@YTjungle666 YTjungle666 commented May 8, 2026

Summary

This updates chansrv clipboard text handling to improve interoperability with stricter RDP clients, including current Microsoft Remote Desktop / Windows App clients.

The change:

  • supports additional X11 text targets (text/plain;charset=utf-8, text/plain, COMPOUND_TEXT, and TEXT) in addition to UTF8_STRING and STRING
  • converts COMPOUND_TEXT to/from UTF-8 so older X11 clients can still exchange text through the RDP clipboard
  • removes trailing bytes written outside the CLIPRDR dataLen from clipboard PDUs
  • advertises only the lossless CF_UNICODETEXT format for server-to-client text clipboard updates, allowing Windows to synthesize CF_TEXT / CF_OEMTEXT locally instead of rejecting a redundant text format list
  • still responds to client requests for CF_LOCALE, CF_TEXT, CF_OEMTEXT, and CF_UNICODETEXT when those formats are requested
  • flushes the X11 selection conversion request after a new server-side clipboard owner notification, so clipboard updates copied after the RDP client is connected are sent promptly

Rationale

The CLIPRDR payload length should match the dataLen field. Some clients tolerate extra trailing bytes, but stricter clients can reject the format list. In local testing, the Windows client returned CB_FORMAT_LIST_RESPONSE with CB_RESPONSE_FAIL when the server advertised a redundant text format list. Advertising CF_UNICODETEXT only for server-to-client text avoids the rejection while keeping the Unicode path lossless. Windows can synthesize the legacy text formats from CF_UNICODETEXT when applications request them.

The X11 selection conversion request is only issued after an XFixes owner notification for a new server-side copy operation. This avoids synchronizing clipboard content that existed before the RDP client connected, while still ensuring server-side copies made after connection are announced without waiting for another X11 event.

Testing

  • scripts/run_astyle.sh -v 3.4.14
  • ./bootstrap
  • ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --runstatedir=/run --libdir=/usr/lib/x86_64-linux-gnu --libexecdir=/usr/lib/x86_64-linux-gnu --with-pkgconfigdir=/usr/lib/x86_64-linux-gnu/pkgconfig --with-socketdir=/run/xrdp/sockdir --with-systemdsystemunitdir=/usr/lib/systemd/system --enable-ipv6 --enable-jpeg --enable-fuse --enable-rfxcodec --enable-painter --enable-pam
  • make -j$(nproc)
  • make check
  • Manual validation with Win11 RDP and Apache Guacamole clients: server-to-client text copied after the client was connected, including Chinese and ASCII text, was accepted by the client and could be pasted locally.
  • Manual privacy validation: clipboard content that existed on the server before a new/reconnected client session was not proactively synchronized on connection.

@YTjungle666 YTjungle666 force-pushed the clipboard-strict-client-text-fix-20260509 branch from 7f3f75c to de91730 Compare May 9, 2026 02:12
@YTjungle666 YTjungle666 force-pushed the clipboard-strict-client-text-fix-20260509 branch from de91730 to 2a7793e Compare May 9, 2026 02:37
Copy link
Copy Markdown
Member

@matt335672 matt335672 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments below.

It should also be noted that we also have a number of XFreeRDP clients, and these may require other text formats being advertised.

If I RDP in to an XFCE session using XFreeRDP and copy some text in the session, I get this result in the session:

$ xclip -o -selection clipboard -t TARGETS
TIMESTAMP
TARGETS
MULTIPLE
SAVE_TARGETS
UTF8_STRING
COMPOUND_TEXT
TEXT
STRING
text/plain;charset=utf-8
text/plain

but on the host I get:

xclip -o -selection clipboard -t TARGETS
TIMESTAMP
TARGETS
MULTIPLE
text/plain;charset=utf-8
UTF8_STRING

I don't think this is a regression as such; using the latest devel I also get text/plain and TEXT targets advertised, but they don't actually work.

}
else if (atom == XA_STRING)
text_priority = clipboard_text_target_priority(atom);
if (text_priority > 0)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test combined with the next seems to be redundant, as got_text_priority is always >= 0

return 1;
}

len = g_strlen(text_list[0]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been reviewing a few security advisories recently, so need to check that len is not equal to INT_MAX before adding 1 to it.

return 1;
}

text = (char *)g_malloc(utf8_size + 1, 0);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check utf8_size is not equal to INT_MAX before adding 1`.

out_uint16_le(s, 12); /* lengthCapability */
out_uint32_le(s, g_cliprdr_version); /* version */
out_uint32_le(s, g_cliprdr_flags); /* generalFlags */
out_uint32_le(s, 0); /* extra 4 bytes ? */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for removing these - they've been here a long time.

Comment thread sesman/chansrv/clipboard.c Outdated
/* Advertise the lossless text format only. Windows can
* synthesize CF_TEXT and CF_OEMTEXT from CF_UNICODETEXT, and
* some strict clients reject a redundant text format list. */
out_uint32_le(s, 0x0000000d);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, CF_UNICODETEXT is defined in common/xrdp_constants.h, and can replace the magic number here.

Comment thread sesman/chansrv/clipboard.c Outdated
/* Advertise the lossless text format only. Windows can
* synthesize CF_TEXT and CF_OEMTEXT from CF_UNICODETEXT, and
* some strict clients reject a redundant text format list. */
out_uint32_le(s, 0x0000000d);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Address review feedback for text target handling by converting legacy X text targets through Xlib text properties and adding allocation overflow guards.

Also replace the CF_UNICODETEXT magic number with the existing constant and simplify redundant target priority logic.
@YTjungle666
Copy link
Copy Markdown
Author

Thanks for the review and for the detailed XFreeRDP TARGETS comparison.

I've updated the patch:

  • Simplified the redundant got_text_priority check.
  • Added overflow guards before the len + 1 and utf8_size + 1 allocations.
  • Replaced the 0x0000000d magic values with CF_UNICODETEXT.
  • Kept the obsolete extra capability bytes removed.

For the XFreeRDP case, I don't currently have an XFreeRDP clipboard test environment available, so I couldn't verify that path directly. However, I used your TARGETS output as guidance and updated the X-side text target handling so these targets are treated more consistently instead of advertising text targets which can't actually be served.

In particular, the updated patch now handles COMPOUND_TEXT and TEXT through Xlib text-property conversion, while still keeping the UTF-8-oriented targets preferred where available.

The advertised/requested text target order has also been adjusted to cover the legacy/interoperability targets you pointed out:

COMPOUND_TEXT
TEXT
STRING
text/plain;charset=utf-8
text/plain

Hopefully this improves compatibility with XFreeRDP-style clients without regressing the strict Windows client behaviour this PR was originally targeting.

@matt335672
Copy link
Copy Markdown
Member

Thanks @YTjungle666

I don't think I managed to explain the XFreeRDP client interoperability very well. Previously we were advertising all text formats to 'Windows' clients, and now we're relying on the client to do the conversion from CF_UNICODETEXT to other formats.

Before this change, that meant an XFreeRDP client would see TEXT and text/plain being advertised, but they didn't work. After the change, these types aren't advertised. Whereas that's a small change in behaviour from the xrdp perspective, in practice it makes no difference.

I'm wondering whether we could simplify a lot of this by simply dropping support for older formats. Converting from UTF-8 to TEXT is possible but doesn't give useful results. For example, If I copy this string on an XFreeRDP client:

这真是一段文字

I get this on the xrdp side:-

$ xclip -o -selection clipboard -t TARGETS
TARGETS
TIMESTAMP
MULTIPLE
UTF8_STRING
COMPOUND_TEXT
TEXT
STRING
text/plain;charset=utf-8
text/plain

$ xclip -o -selection clipboard -t UTF8_STRING
这真是一段文字

$ xclip -o -selection clipboard -t TEXT
UbUfJGR;6NNDWV

I can't see any usefulness in the TEXT result at all. It's not clear to me what it represents.

I can see two ways in which xrdp should behave in this situation:

  1. Only advertise TEXT and text/plain if a conversion to these types produces a meaningful result.
  2. Skip the conversions and return UTF-8 for everything.

Option 2) is a lot closer to where we are at the moment.

@metalefty - do you have any thoughts on this? Are we gaining anything by supporting older text formats other than a potential maintenance burden in the future?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants