From 28d968a4d6137043bcdfad5e0f2ee6402a246516 Mon Sep 17 00:00:00 2001 From: Pascal Nowack Date: Wed, 6 Jul 2022 13:46:39 +0200 Subject: [PATCH] client/X11: Relieve CLIPRDR filename restriction when possible Microsoft Windows imposes strict filename restrictions on its platform. As RDP is developed by Microsoft and the RDS in MS Windows is typically used as remote desktop server for the RDP protocol, these filename restrictions are also enforced in WinPR, when copy-pasting files over the clipboard. However, in some connections no peer on MS Windows is involved and in these situations, these filename restrictions are just an annoyance. With a recent API addition in WinPR, it is now possible to override the callback, where the filename is checked, whether it is valid. So, use this new API to relieve the filename restriction, when the connected remote desktop server is not on MS Windows. --- client/X11/xf_client.c | 4 +++- client/X11/xf_cliprdr.c | 29 ++++++++++++++++++++++++++++- client/X11/xf_cliprdr.h | 2 +- libfreerdp/core/capabilities.c | 31 +++++++++++-------------------- 4 files changed, 43 insertions(+), 23 deletions(-) diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 90b05e87d..bd3eb0d56 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -1254,6 +1254,7 @@ static BOOL xf_post_connect(freerdp* instance) context = instance->context; settings = instance->settings; update = context->update; + BOOL serverIsWindowsPlatform; if (!gdi_init(instance, xf_get_local_color_format(xfc, TRUE))) return FALSE; @@ -1323,7 +1324,8 @@ static BOOL xf_post_connect(freerdp* instance) update->SetKeyboardIndicators = xf_keyboard_set_indicators; update->SetKeyboardImeStatus = xf_keyboard_set_ime_status; - if (!(xfc->clipboard = xf_clipboard_new(xfc))) + serverIsWindowsPlatform = (settings->OsMajorType == OSMAJORTYPE_WINDOWS); + if (!(xfc->clipboard = xf_clipboard_new(xfc, !serverIsWindowsPlatform))) return FALSE; if (!(xfc->xfDisp = xf_disp_new(xfc))) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index 85a17363c..37ed538e6 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -1756,7 +1756,27 @@ static UINT xf_cliprdr_clipboard_file_range_failure(wClipboardDelegate* delegate return clipboard->context->ClientFileContentsResponse(clipboard->context, &response); } -xfClipboard* xf_clipboard_new(xfContext* xfc) +static BOOL xf_cliprdr_clipboard_is_valid_unix_filename(LPCWSTR filename) +{ + LPCWSTR c; + + if (!filename) + return FALSE; + + if (filename[0] == L'\0') + return FALSE; + + /* Reserved characters */ + for (c = filename; *c; ++c) + { + if (*c == L'/') + return FALSE; + } + + return TRUE; +} + +xfClipboard* xf_clipboard_new(xfContext* xfc, BOOL relieveFilenameRestriction) { int i, n = 0; rdpChannels* channels; @@ -1885,6 +1905,13 @@ xfClipboard* xf_clipboard_new(xfContext* xfc) clipboard->delegate->ClipboardFileSizeFailure = xf_cliprdr_clipboard_file_size_failure; clipboard->delegate->ClipboardFileRangeSuccess = xf_cliprdr_clipboard_file_range_success; clipboard->delegate->ClipboardFileRangeFailure = xf_cliprdr_clipboard_file_range_failure; + + if (relieveFilenameRestriction) + { + WLog_DBG(TAG, "Relieving CLIPRDR filename restriction"); + clipboard->delegate->IsFileNameComponentValid = xf_cliprdr_clipboard_is_valid_unix_filename; + } + return clipboard; error: diff --git a/client/X11/xf_cliprdr.h b/client/X11/xf_cliprdr.h index f2262f79e..7f571c477 100644 --- a/client/X11/xf_cliprdr.h +++ b/client/X11/xf_cliprdr.h @@ -25,7 +25,7 @@ #include -xfClipboard* xf_clipboard_new(xfContext* xfc); +xfClipboard* xf_clipboard_new(xfContext* xfc, BOOL relieveFilenameRestriction); void xf_clipboard_free(xfClipboard* clipboard); void xf_cliprdr_init(xfContext* xfc, CliprdrClientContext* cliprdr); diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index 30edcbb1c..433f4cefc 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -162,26 +162,17 @@ static BOOL rdp_read_general_capability_set(wStream* s, rdpSettings* settings) if (Stream_GetRemainingLength(s) < 20) return FALSE; - if (settings->ServerMode) - { - Stream_Read_UINT16(s, settings->OsMajorType); /* osMajorType (2 bytes) */ - Stream_Read_UINT16(s, settings->OsMinorType); /* osMinorType (2 bytes) */ - } - else - { - Stream_Seek_UINT16(s); /* osMajorType (2 bytes) */ - Stream_Seek_UINT16(s); /* osMinorType (2 bytes) */ - } - - Stream_Seek_UINT16(s); /* protocolVersion (2 bytes) */ - Stream_Seek_UINT16(s); /* pad2OctetsA (2 bytes) */ - Stream_Seek_UINT16(s); /* generalCompressionTypes (2 bytes) */ - Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */ - Stream_Seek_UINT16(s); /* updateCapabilityFlag (2 bytes) */ - Stream_Seek_UINT16(s); /* remoteUnshareFlag (2 bytes) */ - Stream_Seek_UINT16(s); /* generalCompressionLevel (2 bytes) */ - Stream_Read_UINT8(s, refreshRectSupport); /* refreshRectSupport (1 byte) */ - Stream_Read_UINT8(s, suppressOutputSupport); /* suppressOutputSupport (1 byte) */ + Stream_Read_UINT16(s, settings->OsMajorType); /* osMajorType (2 bytes) */ + Stream_Read_UINT16(s, settings->OsMinorType); /* osMinorType (2 bytes) */ + Stream_Seek_UINT16(s); /* protocolVersion (2 bytes) */ + Stream_Seek_UINT16(s); /* pad2OctetsA (2 bytes) */ + Stream_Seek_UINT16(s); /* generalCompressionTypes (2 bytes) */ + Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */ + Stream_Seek_UINT16(s); /* updateCapabilityFlag (2 bytes) */ + Stream_Seek_UINT16(s); /* remoteUnshareFlag (2 bytes) */ + Stream_Seek_UINT16(s); /* generalCompressionLevel (2 bytes) */ + Stream_Read_UINT8(s, refreshRectSupport); /* refreshRectSupport (1 byte) */ + Stream_Read_UINT8(s, suppressOutputSupport); /* suppressOutputSupport (1 byte) */ settings->NoBitmapCompressionHeader = (extraFlags & NO_BITMAP_COMPRESSION_HDR) ? TRUE : FALSE; settings->LongCredentialsSupported = (extraFlags & LONG_CREDENTIALS_SUPPORTED) ? TRUE : FALSE;