From 1178f88fc52fe52adc03806de9d78346f21b4798 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Tue, 5 Nov 2024 08:58:51 +0000 Subject: [PATCH] import from CS git freerdp-2.11.7-1.el8 --- .freerdp.metadata | 2 +- .gitignore | 2 +- SOURCES/6741.patch | 315 -- ...bitmap-and-glyph-width-heigth-values.patch | 146 - SOURCES/Added-function-_wcsncmp.patch | 62 - ...length-check-in-urb_control_transfer.patch | 29 - ...ngth-checks-in-zgfx_decompress_segme.patch | 51 - ...e_iocompletion-uses-size_t-for-calcu.patch | 32 - ...Fix-length-checks-in-parallel-driver.patch | 37 - ...st-flag-being-ignored-on-X11-Wayland.patch | 49 - .../Fixed-division-by-zero-in-urbdrc.patch | 39 - ...ing-for-Stream_CheckAndLogRequiredLe.patch | 122 - ...-input-buffer-length-check-in-urbdrc.patch | 58 - ...issing-length-check-in-video-channel.patch | 29 - ...ream-length-check-in-drive_file_quer.patch | 28 - ...xed-path-validation-in-drive-channel.patch | 296 - ...mplement-missing-TSG-debug-functions.patch | 433 -- SOURCES/Refactored-RPC-gateway-parser.patch | 4950 ----------------- ...pboard-utils-to-core-library-fixes-6.patch | 560 ++ ...inpr-crt-Added-wcsstr-implementation.patch | 66 - ...r-crt-Fix-wcs-cmp-and-wcs-len-checks.patch | 90 - SPECS/freerdp.spec | 87 +- 22 files changed, 589 insertions(+), 6894 deletions(-) delete mode 100644 SOURCES/6741.patch delete mode 100644 SOURCES/Add-checks-for-bitmap-and-glyph-width-heigth-values.patch delete mode 100644 SOURCES/Added-function-_wcsncmp.patch delete mode 100644 SOURCES/Added-missing-length-check-in-urb_control_transfer.patch delete mode 100644 SOURCES/Added-missing-length-checks-in-zgfx_decompress_segme.patch delete mode 100644 SOURCES/Ensure-urb_create_iocompletion-uses-size_t-for-calcu.patch delete mode 100644 SOURCES/Fix-length-checks-in-parallel-driver.patch delete mode 100644 SOURCES/Fix-monitor-list-flag-being-ignored-on-X11-Wayland.patch delete mode 100644 SOURCES/Fixed-division-by-zero-in-urbdrc.patch delete mode 100644 SOURCES/Fixed-format-string-for-Stream_CheckAndLogRequiredLe.patch delete mode 100644 SOURCES/Fixed-missing-input-buffer-length-check-in-urbdrc.patch delete mode 100644 SOURCES/Fixed-missing-length-check-in-video-channel.patch delete mode 100644 SOURCES/Fixed-missing-stream-length-check-in-drive_file_quer.patch delete mode 100644 SOURCES/Fixed-path-validation-in-drive-channel.patch delete mode 100644 SOURCES/Implement-missing-TSG-debug-functions.patch delete mode 100644 SOURCES/Refactored-RPC-gateway-parser.patch create mode 100644 SOURCES/Revert-Moved-clipboard-utils-to-core-library-fixes-6.patch delete mode 100644 SOURCES/winpr-crt-Added-wcsstr-implementation.patch delete mode 100644 SOURCES/winpr-crt-Fix-wcs-cmp-and-wcs-len-checks.patch diff --git a/.freerdp.metadata b/.freerdp.metadata index d84b169..8d7363b 100644 --- a/.freerdp.metadata +++ b/.freerdp.metadata @@ -1 +1 @@ -84f51c81388c8b49346b9c5a7c4c982909017443 SOURCES/FreeRDP-2.2.0.tar.gz +14a73f092e227a77f3d483658033d15d4501a753 SOURCES/FreeRDP-2.11.7.tar.gz diff --git a/.gitignore b/.gitignore index bdb416a..21aec21 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/FreeRDP-2.2.0.tar.gz +SOURCES/FreeRDP-2.11.7.tar.gz \ No newline at end of file diff --git a/SOURCES/6741.patch b/SOURCES/6741.patch deleted file mode 100644 index 16861e3..0000000 --- a/SOURCES/6741.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 3ee4cabcfad3a9ccc3c59be21245b57c17e7ae75 Mon Sep 17 00:00:00 2001 -From: Ondrej Holy -Date: Thu, 21 Jan 2021 14:21:09 +0100 -Subject: [PATCH 1/3] client: Fix exit codes for /help and similar option - -Currently, non-zero exit code is returned for /version, /buildconfig, /help, -/monitor-list, /kbd-list and /kbd-lang-list command-line options for several -clients. This is against conventions because 0 is usually returned in -such cases. Also, there is potentially another problem that the returned -codes overflow on UNIX systems (where the exit code is a number between 0 -and 255). Let's fix the clients to return 0 in the mentioned cases to honor -conventions and 1 for the command-line parsing errors (or -1 for clients -who already use that value). - -Fixes: https://github.com/FreeRDP/FreeRDP/issues/6686 ---- - client/Sample/tf_freerdp.c | 9 +++++---- - client/Wayland/wlfreerdp.c | 13 +++++++------ - client/Windows/cli/wfreerdp.c | 4 ++++ - client/X11/cli/xfreerdp.c | 22 +++++++++++++--------- - winpr/include/winpr/cmdline.h | 1 + - 5 files changed, 30 insertions(+), 19 deletions(-) - -diff --git a/client/Sample/tf_freerdp.c b/client/Sample/tf_freerdp.c -index 3ba82c78338..49412cb417c 100644 ---- a/client/Sample/tf_freerdp.c -+++ b/client/Sample/tf_freerdp.c -@@ -338,12 +338,13 @@ int main(int argc, char* argv[]) - goto fail; - - status = freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE); -- status = -- freerdp_client_settings_command_line_status_print(context->settings, status, argc, argv); -- - if (status) - { -- rc = 0; -+ freerdp_client_settings_command_line_status_print(context->settings, status, argc, argv); -+ -+ if (status <= COMMAND_LINE_STATUS_PRINT && status >= COMMAND_LINE_STATUS_PRINT_LAST) -+ rc = 0; -+ - goto fail; - } - -diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c -index 329d1200941..d77b47986ea 100644 ---- a/client/Wayland/wlfreerdp.c -+++ b/client/Wayland/wlfreerdp.c -@@ -628,18 +628,19 @@ int main(int argc, char* argv[]) - settings = context->settings; - - status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE); -- status = freerdp_client_settings_command_line_status_print(settings, status, argc, argv); -- - if (status) - { - BOOL list = settings->ListMonitors; -+ -+ freerdp_client_settings_command_line_status_print(settings, status, argc, argv); -+ - if (list) - wlf_list_monitors(wlc); - -- freerdp_client_context_free(context); -- if (list) -- return 0; -- return status; -+ if (status <= COMMAND_LINE_STATUS_PRINT && status >= COMMAND_LINE_STATUS_PRINT_LAST) -+ rc = 0; -+ -+ goto fail; - } - - if (freerdp_client_start(context) != 0) -diff --git a/client/Windows/cli/wfreerdp.c b/client/Windows/cli/wfreerdp.c -index 7a76eeb9b59..b623067e98e 100644 ---- a/client/Windows/cli/wfreerdp.c -+++ b/client/Windows/cli/wfreerdp.c -@@ -108,6 +108,10 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine - if (status) - { - freerdp_client_settings_command_line_status_print(settings, status, argc, argv); -+ -+ if (status <= COMMAND_LINE_STATUS_PRINT && status >= COMMAND_LINE_STATUS_PRINT_LAST) -+ rc = 0; -+ - goto out; - } - -diff --git a/client/X11/cli/xfreerdp.c b/client/X11/cli/xfreerdp.c -index c8a77f335f4..a3505b24d3c 100644 ---- a/client/X11/cli/xfreerdp.c -+++ b/client/X11/cli/xfreerdp.c -@@ -34,6 +34,7 @@ - - int main(int argc, char* argv[]) - { -+ int rc = 1; - int status; - HANDLE thread; - xfContext* xfc; -@@ -56,31 +57,34 @@ int main(int argc, char* argv[]) - xfc = (xfContext*)context; - - status = freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE); -- -- status = freerdp_client_settings_command_line_status_print(settings, status, argc, argv); -- - if (status) - { - BOOL list = settings->ListMonitors; -+ -+ freerdp_client_settings_command_line_status_print(settings, status, argc, argv); -+ - if (list) - xf_list_monitors(xfc); - -- freerdp_client_context_free(context); -- if (list) -- return 0; -- return status; -+ if (status <= COMMAND_LINE_STATUS_PRINT && status >= COMMAND_LINE_STATUS_PRINT_LAST) -+ rc = 0; -+ -+ goto out; - } - -- freerdp_client_start(context); -+ if (freerdp_client_start(context) != 0) -+ goto out; - - thread = freerdp_client_get_thread(context); - - WaitForSingleObject(thread, INFINITE); - GetExitCodeThread(thread, &dwExitCode); -+ rc = xf_exit_code_from_disconnect_reason(dwExitCode); - - freerdp_client_stop(context); - -+out: - freerdp_client_context_free(context); - -- return xf_exit_code_from_disconnect_reason(dwExitCode); -+ return rc; - } -diff --git a/winpr/include/winpr/cmdline.h b/winpr/include/winpr/cmdline.h -index 865ee8f25c7..9276cda8eb1 100644 ---- a/winpr/include/winpr/cmdline.h -+++ b/winpr/include/winpr/cmdline.h -@@ -81,6 +81,7 @@ - #define COMMAND_LINE_STATUS_PRINT_HELP -2002 - #define COMMAND_LINE_STATUS_PRINT_VERSION -2003 - #define COMMAND_LINE_STATUS_PRINT_BUILDCONFIG -2004 -+#define COMMAND_LINE_STATUS_PRINT_LAST -2999 - - /* Command-Line Macros */ - - -From 531dd81836f2c97fcfcfeabdb9671fb76409ce8d Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Fri, 22 Jan 2021 08:40:03 +0100 -Subject: [PATCH 2/3] Refactored - freerdp_client_settings_command_line_status_print_ex - -Now returns 0 if help or version information was requested. ---- - client/Sample/tf_freerdp.c | 7 ++----- - client/Wayland/wlfreerdp.c | 5 +---- - client/Windows/cli/wfreerdp.c | 6 +----- - client/X11/cli/xfreerdp.c | 5 +---- - client/common/cmdline.c | 14 +++++++++----- - 5 files changed, 14 insertions(+), 23 deletions(-) - -diff --git a/client/Sample/tf_freerdp.c b/client/Sample/tf_freerdp.c -index 49412cb417c..e9b9fe8397e 100644 ---- a/client/Sample/tf_freerdp.c -+++ b/client/Sample/tf_freerdp.c -@@ -340,11 +340,8 @@ int main(int argc, char* argv[]) - status = freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE); - if (status) - { -- freerdp_client_settings_command_line_status_print(context->settings, status, argc, argv); -- -- if (status <= COMMAND_LINE_STATUS_PRINT && status >= COMMAND_LINE_STATUS_PRINT_LAST) -- rc = 0; -- -+ rc = freerdp_client_settings_command_line_status_print(context->settings, status, argc, -+ argv); - goto fail; - } - -diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c -index d77b47986ea..4a583068968 100644 ---- a/client/Wayland/wlfreerdp.c -+++ b/client/Wayland/wlfreerdp.c -@@ -632,14 +632,11 @@ int main(int argc, char* argv[]) - { - BOOL list = settings->ListMonitors; - -- freerdp_client_settings_command_line_status_print(settings, status, argc, argv); -+ rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv); - - if (list) - wlf_list_monitors(wlc); - -- if (status <= COMMAND_LINE_STATUS_PRINT && status >= COMMAND_LINE_STATUS_PRINT_LAST) -- rc = 0; -- - goto fail; - } - -diff --git a/client/Windows/cli/wfreerdp.c b/client/Windows/cli/wfreerdp.c -index b623067e98e..e325f84771f 100644 ---- a/client/Windows/cli/wfreerdp.c -+++ b/client/Windows/cli/wfreerdp.c -@@ -107,11 +107,7 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine - - if (status) - { -- freerdp_client_settings_command_line_status_print(settings, status, argc, argv); -- -- if (status <= COMMAND_LINE_STATUS_PRINT && status >= COMMAND_LINE_STATUS_PRINT_LAST) -- rc = 0; -- -+ ret = freerdp_client_settings_command_line_status_print(settings, status, argc, argv); - goto out; - } - -diff --git a/client/X11/cli/xfreerdp.c b/client/X11/cli/xfreerdp.c -index a3505b24d3c..5b702194448 100644 ---- a/client/X11/cli/xfreerdp.c -+++ b/client/X11/cli/xfreerdp.c -@@ -61,14 +61,11 @@ int main(int argc, char* argv[]) - { - BOOL list = settings->ListMonitors; - -- freerdp_client_settings_command_line_status_print(settings, status, argc, argv); -+ rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv); - - if (list) - xf_list_monitors(xfc); - -- if (status <= COMMAND_LINE_STATUS_PRINT && status >= COMMAND_LINE_STATUS_PRINT_LAST) -- rc = 0; -- - goto out; - } - -diff --git a/client/common/cmdline.c b/client/common/cmdline.c -index ed467afb7d0..dc8367b7cd2 100644 ---- a/client/common/cmdline.c -+++ b/client/common/cmdline.c -@@ -1403,14 +1403,14 @@ int freerdp_client_settings_command_line_status_print_ex(rdpSettings* settings, - if (status == COMMAND_LINE_STATUS_PRINT_VERSION) - { - freerdp_client_print_version(); -- return COMMAND_LINE_STATUS_PRINT_VERSION; -+ goto out; - } - - if (status == COMMAND_LINE_STATUS_PRINT_BUILDCONFIG) - { - freerdp_client_print_version(); - freerdp_client_print_buildconfig(); -- return COMMAND_LINE_STATUS_PRINT_BUILDCONFIG; -+ goto out; - } - else if (status == COMMAND_LINE_STATUS_PRINT) - { -@@ -1465,15 +1465,19 @@ int freerdp_client_settings_command_line_status_print_ex(rdpSettings* settings, - settings->ListMonitors = TRUE; - } - -- return COMMAND_LINE_STATUS_PRINT; -+ goto out; - } - else if (status < 0) - { - freerdp_client_print_command_line_help_ex(argc, argv, custom); -- return COMMAND_LINE_STATUS_PRINT_HELP; -+ status = COMMAND_LINE_STATUS_PRINT_HELP; -+ goto out; - } - -- return 0; -+out: -+ if (status <= COMMAND_LINE_STATUS_PRINT && status >= COMMAND_LINE_STATUS_PRINT_LAST) -+ return 0; -+ return status; - } - - static BOOL ends_with(const char* str, const char* ext) - -From 050a68fec901030c7428852f8f536ace055eb2f7 Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Fri, 22 Jan 2021 09:32:51 +0100 -Subject: [PATCH 3/3] Do not eliminate original error status. - ---- - client/common/cmdline.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/client/common/cmdline.c b/client/common/cmdline.c -index dc8367b7cd2..66d3c4fffef 100644 ---- a/client/common/cmdline.c -+++ b/client/common/cmdline.c -@@ -1470,7 +1470,6 @@ int freerdp_client_settings_command_line_status_print_ex(rdpSettings* settings, - else if (status < 0) - { - freerdp_client_print_command_line_help_ex(argc, argv, custom); -- status = COMMAND_LINE_STATUS_PRINT_HELP; - goto out; - } - diff --git a/SOURCES/Add-checks-for-bitmap-and-glyph-width-heigth-values.patch b/SOURCES/Add-checks-for-bitmap-and-glyph-width-heigth-values.patch deleted file mode 100644 index cde5535..0000000 --- a/SOURCES/Add-checks-for-bitmap-and-glyph-width-heigth-values.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 4a4ecc32b160e93ee1e37e5617a0197e2d022643 Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Thu, 4 Nov 2021 11:07:41 +0100 -Subject: [PATCH] Add checks for bitmap and glyph width/heigth values - -CVE-2021-41160 - -https://github.com/FreeRDP/FreeRDP/pull/7349 - -Signed-off-by: Felipe Borges ---- - libfreerdp/core/orders.c | 14 ++++++++++++ - libfreerdp/core/surface.c | 45 +++++++++++++++++++++++++++++++++++++++ - libfreerdp/core/update.c | 7 ++++++ - 3 files changed, 66 insertions(+) - -diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c -index 74870fae6..44d23a61a 100644 ---- a/libfreerdp/core/orders.c -+++ b/libfreerdp/core/orders.c -@@ -1848,6 +1848,13 @@ static BOOL update_read_fast_glyph_order(wStream* s, const ORDER_INFO* orderInfo - new_cb = ((glyph->cx + 7) / 8) * glyph->cy; - new_cb += ((new_cb % 4) > 0) ? 4 - (new_cb % 4) : 0; - -+ if ((glyph->cx == 0) || (glyph->cy == 0)) -+ { -+ WLog_ERR(TAG, "GLYPH_DATA_V2::cx=%" PRIu32 ", GLYPH_DATA_V2::cy=%" PRIu32, -+ glyph->cx, glyph->cy); -+ return FALSE; -+ } -+ - if (fastGlyph->cbData < new_cb) - return FALSE; - -@@ -2825,6 +2832,13 @@ update_read_create_offscreen_bitmap_order(wStream* s, - Stream_Read_UINT16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */ - deleteList = &(create_offscreen_bitmap->deleteList); - -+ if ((create_offscreen_bitmap->cx == 0) || (create_offscreen_bitmap->cy == 0)) -+ { -+ WLog_ERR(TAG, "Invalid OFFSCREEN_DELETE_LIST: cx=%" PRIu16 ", cy=%" PRIu16, -+ create_offscreen_bitmap->cx, create_offscreen_bitmap->cy); -+ return FALSE; -+ } -+ - if (deleteListPresent) - { - UINT32 i; -diff --git a/libfreerdp/core/surface.c b/libfreerdp/core/surface.c -index d5c709885..ca89d230c 100644 ---- a/libfreerdp/core/surface.c -+++ b/libfreerdp/core/surface.c -@@ -21,6 +21,8 @@ - #include "config.h" - #endif - -+#include -+ - #include - #include - -@@ -62,6 +64,13 @@ static BOOL update_recv_surfcmd_bitmap_ex(wStream* s, TS_BITMAP_DATA_EX* bmp) - Stream_Read_UINT16(s, bmp->height); - Stream_Read_UINT32(s, bmp->bitmapDataLength); - -+ if ((bmp->width == 0) || (bmp->height == 0)) -+ { -+ WLog_ERR(TAG, "invalid size value width=%" PRIu16 ", height=%" PRIu16, bmp->width, -+ bmp->height); -+ return FALSE; -+ } -+ - if ((bmp->bpp < 1) || (bmp->bpp > 32)) - { - WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", bmp->bpp); -@@ -85,6 +94,39 @@ static BOOL update_recv_surfcmd_bitmap_ex(wStream* s, TS_BITMAP_DATA_EX* bmp) - return TRUE; - } - -+static BOOL update_recv_surfcmd_is_rect_valid(const rdpContext* context, -+ const SURFACE_BITS_COMMAND* cmd) -+{ -+ assert(context); -+ assert(context->settings); -+ assert(cmd); -+ -+ /* We need a rectangle with left/top being smaller than right/bottom. -+ * Also do not allow empty rectangles. */ -+ if ((cmd->destTop >= cmd->destBottom) || (cmd->destLeft >= cmd->destRight)) -+ { -+ WLog_WARN(TAG, -+ "Empty surface bits command rectangle: %" PRIu16 "x%" PRIu16 "-%" PRIu16 -+ "x%" PRIu16, -+ cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom); -+ return FALSE; -+ } -+ -+ /* The rectangle needs to fit into our session size */ -+ if ((cmd->destRight > context->settings->DesktopWidth) || -+ (cmd->destBottom > context->settings->DesktopHeight)) -+ { -+ WLog_WARN(TAG, -+ "Invalid surface bits command rectangle: %" PRIu16 "x%" PRIu16 "-%" PRIu16 -+ "x%" PRIu16 " does not fit %" PRIu32 "x%" PRIu32, -+ cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom, -+ context->settings->DesktopWidth, context->settings->DesktopHeight); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ - static BOOL update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT16 cmdType) - { - SURFACE_BITS_COMMAND cmd = { 0 }; -@@ -98,6 +140,9 @@ static BOOL update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT - Stream_Read_UINT16(s, cmd.destRight); - Stream_Read_UINT16(s, cmd.destBottom); - -+ if (!update_recv_surfcmd_is_rect_valid(update->context, &cmd)) -+ goto fail; -+ - if (!update_recv_surfcmd_bitmap_ex(s, &cmd.bmp)) - goto fail; - -diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c -index ebb82fc2d..e137c3de8 100644 ---- a/libfreerdp/core/update.c -+++ b/libfreerdp/core/update.c -@@ -99,6 +99,13 @@ static BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* - Stream_Read_UINT16(s, bitmapData->flags); - Stream_Read_UINT16(s, bitmapData->bitmapLength); - -+ if ((bitmapData->width == 0) || (bitmapData->height == 0)) -+ { -+ WLog_ERR(TAG, "Invalid BITMAP_DATA: width=%" PRIu16 ", height=%" PRIu16, bitmapData->width, -+ bitmapData->height); -+ return FALSE; -+ } -+ - if (bitmapData->flags & BITMAP_COMPRESSION) - { - if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR)) --- -2.32.0 - diff --git a/SOURCES/Added-function-_wcsncmp.patch b/SOURCES/Added-function-_wcsncmp.patch deleted file mode 100644 index cef8a66..0000000 --- a/SOURCES/Added-function-_wcsncmp.patch +++ /dev/null @@ -1,62 +0,0 @@ -From e482b394efc371412ce659b731a9b1e1d73bdf0e Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Mon, 24 Oct 2022 10:42:56 +0200 -Subject: [PATCH] Added function _wcsncmp - -* Compare WCHAR strings up to n characters - -(cherry picked from commit 8178ed26a459356ece17414c6e871a7e0735a4ec) ---- - winpr/include/winpr/string.h | 2 ++ - winpr/libwinpr/crt/string.c | 15 ++++++++++++++- - 2 files changed, 16 insertions(+), 1 deletion(-) - -diff --git a/winpr/include/winpr/string.h b/winpr/include/winpr/string.h -index 8ce83bc1d..3b907c444 100644 ---- a/winpr/include/winpr/string.h -+++ b/winpr/include/winpr/string.h -@@ -57,6 +57,7 @@ extern "C" - WINPR_API int _strnicmp(const char* string1, const char* string2, size_t count); - - WINPR_API int _wcscmp(const WCHAR* string1, const WCHAR* string2); -+ WINPR_API int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count); - - WINPR_API size_t _wcslen(const WCHAR* str); - WINPR_API size_t _wcsnlen(const WCHAR* str, size_t maxNumberOfElements); -@@ -70,6 +71,7 @@ extern "C" - #else - - #define _wcscmp wcscmp -+#define _wcsncmp wcsncmp - #define _wcslen wcslen - #define _wcsnlen wcsnlen - #define _wcschr wcschr -diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c -index 37fcb4b25..c25ffa279 100644 ---- a/winpr/libwinpr/crt/string.c -+++ b/winpr/libwinpr/crt/string.c -@@ -90,7 +90,20 @@ int _wcscmp(const WCHAR* string1, const WCHAR* string2) - - Data_Read_UINT16(string1, value1); - Data_Read_UINT16(string2, value2); -- return value1 - value2; -+ return (int)value1 - value2; -+} -+ -+int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count) -+{ -+ for (size_t x = 0; x < count; x++) -+ { -+ const WCHAR a = string1[x]; -+ const WCHAR b = string2[x]; -+ -+ if (a != b) -+ return (int)a - b; -+ } -+ return 0; - } - - /* _wcslen -> wcslen */ --- -2.37.1 - diff --git a/SOURCES/Added-missing-length-check-in-urb_control_transfer.patch b/SOURCES/Added-missing-length-check-in-urb_control_transfer.patch deleted file mode 100644 index 406161b..0000000 --- a/SOURCES/Added-missing-length-check-in-urb_control_transfer.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 8c513f127549433c830575202d1551b0e9dd182d Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Thu, 13 Oct 2022 09:00:48 +0200 -Subject: [PATCH] Added missing length check in urb_control_transfer - -(cherry picked from commit ce838e2477cb8173ea5e98f35ad55ff41ea5117d) ---- - channels/urbdrc/client/data_transfer.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c -index 9a44e6e09..bb2784055 100644 ---- a/channels/urbdrc/client/data_transfer.c -+++ b/channels/urbdrc/client/data_transfer.c -@@ -673,7 +673,11 @@ static UINT urb_control_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callba - buffer = Stream_Pointer(out); - - if (transferDir == USBD_TRANSFER_DIRECTION_OUT) -+ { -+ if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize)) -+ return ERROR_INVALID_DATA; - Stream_Copy(s, out, OutputBufferSize); -+ } - - /** process TS_URB_CONTROL_TRANSFER */ - if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType, --- -2.37.1 - diff --git a/SOURCES/Added-missing-length-checks-in-zgfx_decompress_segme.patch b/SOURCES/Added-missing-length-checks-in-zgfx_decompress_segme.patch deleted file mode 100644 index a478489..0000000 --- a/SOURCES/Added-missing-length-checks-in-zgfx_decompress_segme.patch +++ /dev/null @@ -1,51 +0,0 @@ -From babbd1e433d273634637f5199429986714864033 Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Thu, 13 Oct 2022 09:09:28 +0200 -Subject: [PATCH] Added missing length checks in zgfx_decompress_segment - -(cherry picked from commit 64716b335858109d14f27b51acc4c4d71a92a816) ---- - libfreerdp/codec/zgfx.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - -diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c -index 1a2878bd9..04ddeadb2 100644 ---- a/libfreerdp/codec/zgfx.c -+++ b/libfreerdp/codec/zgfx.c -@@ -230,19 +230,19 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t - BYTE* pbSegment; - size_t cbSegment; - -- if (!zgfx || !stream) -+ if (!zgfx || !stream || (segmentSize < 2)) - return FALSE; - - cbSegment = segmentSize - 1; - -- if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize < 1) || -- (segmentSize > UINT32_MAX)) -+ if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize > UINT32_MAX)) - return FALSE; - - Stream_Read_UINT8(stream, flags); /* header (1 byte) */ - zgfx->OutputCount = 0; - pbSegment = Stream_Pointer(stream); -- Stream_Seek(stream, cbSegment); -+ if (!Stream_SafeSeek(stream, cbSegment)) -+ return FALSE; - - if (!(flags & PACKET_COMPRESSED)) - { -@@ -346,6 +346,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t - if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount) - return FALSE; - -+ if (count > zgfx->cBitsRemaining / 8) -+ return FALSE; -+ - CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent, - count); - zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count); --- -2.37.1 - diff --git a/SOURCES/Ensure-urb_create_iocompletion-uses-size_t-for-calcu.patch b/SOURCES/Ensure-urb_create_iocompletion-uses-size_t-for-calcu.patch deleted file mode 100644 index 7f0efa4..0000000 --- a/SOURCES/Ensure-urb_create_iocompletion-uses-size_t-for-calcu.patch +++ /dev/null @@ -1,32 +0,0 @@ -From b3a695e9f38a42f1ef0cade0d5e1fe60cf68864e Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Thu, 13 Oct 2022 08:36:26 +0200 -Subject: [PATCH] Ensure urb_create_iocompletion uses size_t for calculation - -(cherry picked from commit de7e0f062ee53d00b4a966a43855a716e3478150) ---- - channels/urbdrc/client/data_transfer.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c -index 80e84af48..8642c8506 100644 ---- a/channels/urbdrc/client/data_transfer.c -+++ b/channels/urbdrc/client/data_transfer.c -@@ -97,7 +97,13 @@ static wStream* urb_create_iocompletion(UINT32 InterfaceField, UINT32 MessageId, - UINT32 OutputBufferSize) - { - const UINT32 InterfaceId = (STREAM_ID_PROXY << 30) | (InterfaceField & 0x3FFFFFFF); -- wStream* out = Stream_New(NULL, OutputBufferSize + 28); -+ -+#if UINT32_MAX >= SIZE_MAX -+ if (OutputBufferSize > UINT32_MAX - 28ull) -+ return NULL; -+#endif -+ -+ wStream* out = Stream_New(NULL, OutputBufferSize + 28ull); - - if (!out) - return NULL; --- -2.37.1 - diff --git a/SOURCES/Fix-length-checks-in-parallel-driver.patch b/SOURCES/Fix-length-checks-in-parallel-driver.patch deleted file mode 100644 index cd3c022..0000000 --- a/SOURCES/Fix-length-checks-in-parallel-driver.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 64544c7f4ed72b3023955ebe6ad3b118ebb8d6c7 Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Thu, 6 Oct 2022 09:12:40 +0200 -Subject: [PATCH] Fix length checks in parallel driver - -The length requested was not checked against the length read from -the port. - -(cherry picked from commit 094cc5a4596c299595b732effd59ee149181fd61) ---- - channels/parallel/client/parallel_main.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c -index af3e82703..993605a65 100644 ---- a/channels/parallel/client/parallel_main.c -+++ b/channels/parallel/client/parallel_main.c -@@ -159,7 +159,7 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) - return ERROR_INVALID_DATA; - Stream_Read_UINT32(irp->input, Length); - Stream_Read_UINT64(irp->input, Offset); -- buffer = (BYTE*)malloc(Length); -+ buffer = (BYTE*)calloc(Length, sizeof(BYTE)); - - if (!buffer) - { -@@ -178,6 +178,7 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) - } - else - { -+ Length = status; - } - - Stream_Write_UINT32(irp->output, Length); --- -2.37.1 - diff --git a/SOURCES/Fix-monitor-list-flag-being-ignored-on-X11-Wayland.patch b/SOURCES/Fix-monitor-list-flag-being-ignored-on-X11-Wayland.patch deleted file mode 100644 index 149456d..0000000 --- a/SOURCES/Fix-monitor-list-flag-being-ignored-on-X11-Wayland.patch +++ /dev/null @@ -1,49 +0,0 @@ -From bf9bce2c3e6c716cc708716484124c1fb47cb531 Mon Sep 17 00:00:00 2001 -From: Max Roncace -Date: Wed, 24 Feb 2021 17:44:28 -0500 -Subject: [PATCH] Fix /monitor-list flag being ignored on X11/Wayland - ---- - client/Wayland/wlfreerdp.c | 4 +++- - client/X11/cli/xfreerdp.c | 4 +++- - 2 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c -index aca734211..26c5452a5 100644 ---- a/client/Wayland/wlfreerdp.c -+++ b/client/Wayland/wlfreerdp.c -@@ -651,10 +651,12 @@ int main(int argc, char* argv[]) - status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE); - if (status) - { -- BOOL list = settings->ListMonitors; -+ BOOL list; - - rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv); - -+ list = settings->ListMonitors; -+ - if (list) - wlf_list_monitors(wlc); - -diff --git a/client/X11/cli/xfreerdp.c b/client/X11/cli/xfreerdp.c -index 5b7021944..786a7eb5d 100644 ---- a/client/X11/cli/xfreerdp.c -+++ b/client/X11/cli/xfreerdp.c -@@ -59,10 +59,12 @@ int main(int argc, char* argv[]) - status = freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE); - if (status) - { -- BOOL list = settings->ListMonitors; -+ BOOL list; - - rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv); - -+ list = settings->ListMonitors; -+ - if (list) - xf_list_monitors(xfc); - --- -2.37.1 - diff --git a/SOURCES/Fixed-division-by-zero-in-urbdrc.patch b/SOURCES/Fixed-division-by-zero-in-urbdrc.patch deleted file mode 100644 index 8792a84..0000000 --- a/SOURCES/Fixed-division-by-zero-in-urbdrc.patch +++ /dev/null @@ -1,39 +0,0 @@ -From b9c5e3668c4022b34734ac8ccb07dd044d4ff38c Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Thu, 13 Oct 2022 08:27:41 +0200 -Subject: [PATCH] Fixed division by zero in urbdrc - -(cherry picked from commit 731f8419d04b481d7160de1f34062d630ed48765) ---- - channels/urbdrc/client/libusb/libusb_udevice.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c -index aa69890ae..5784d9fe2 100644 ---- a/channels/urbdrc/client/libusb/libusb_udevice.c -+++ b/channels/urbdrc/client/libusb/libusb_udevice.c -@@ -1149,12 +1149,18 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c - else - Stream_Seek(user_data->data, (NumberOfPackets * 12)); - -- iso_packet_size = BufferSize / NumberOfPackets; -- iso_transfer = libusb_alloc_transfer(NumberOfPackets); -+ if (NumberOfPackets > 0) -+ { -+ iso_packet_size = BufferSize / NumberOfPackets; -+ iso_transfer = libusb_alloc_transfer((int)NumberOfPackets); -+ } - - if (iso_transfer == NULL) - { -- WLog_Print(urbdrc->log, WLOG_ERROR, "Error: libusb_alloc_transfer."); -+ WLog_Print(urbdrc->log, WLOG_ERROR, -+ "Error: libusb_alloc_transfer [NumberOfPackets=%" PRIu32 ", BufferSize=%" PRIu32 -+ " ]", -+ NumberOfPackets, BufferSize); - async_transfer_user_data_free(user_data); - return -1; - } --- -2.37.1 - diff --git a/SOURCES/Fixed-format-string-for-Stream_CheckAndLogRequiredLe.patch b/SOURCES/Fixed-format-string-for-Stream_CheckAndLogRequiredLe.patch deleted file mode 100644 index 3cda0db..0000000 --- a/SOURCES/Fixed-format-string-for-Stream_CheckAndLogRequiredLe.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 6ed2f7d1a379f69cca102e8166d20eb5ed38652b Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Fri, 22 Apr 2022 16:27:21 +0200 -Subject: [PATCH] Fixed format string for Stream_CheckAndLogRequiredLength - -__LINE__ requires %d and not %PRIuz - -(cherry picked from commit 74c1a006e940308b0653427d25a87ea5a24cb573) ---- - winpr/include/winpr/stream.h | 14 ++++++++ - winpr/libwinpr/utils/stream.c | 65 +++++++++++++++++++++++++++++++++++ - 2 files changed, 79 insertions(+) - -diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h -index f351eaa15..ed637f034 100644 ---- a/winpr/include/winpr/stream.h -+++ b/winpr/include/winpr/stream.h -@@ -27,6 +27,8 @@ - #include - #include - #include -+#include -+#include - - #ifdef __cplusplus - extern "C" -@@ -56,6 +57,19 @@ extern "C" - WINPR_API void Stream_StaticInit(wStream* s, BYTE* buffer, size_t size); - WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer); - -+#define Stream_CheckAndLogRequiredLength(tag, s, len) \ -+ Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, len, "%s(%s:%d)", __FUNCTION__, \ -+ __FILE__, __LINE__) -+ WINPR_API BOOL Stream_CheckAndLogRequiredLengthEx(const char* tag, DWORD level, wStream* s, -+ UINT64 len, const char* fmt, ...); -+ WINPR_API BOOL Stream_CheckAndLogRequiredLengthExVa(const char* tag, DWORD level, wStream* s, -+ UINT64 len, const char* fmt, va_list args); -+ WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s, -+ UINT64 len, const char* fmt, ...); -+ WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s, -+ UINT64 len, const char* fmt, -+ va_list args); -+ - static INLINE void Stream_Seek(wStream* s, size_t _offset) - { - s->pointer += (_offset); -diff --git a/winpr/libwinpr/utils/stream.c b/winpr/libwinpr/utils/stream.c -index 1271981b7..cc119c771 100644 ---- a/winpr/libwinpr/utils/stream.c -+++ b/winpr/libwinpr/utils/stream.c -@@ -132,3 +132,68 @@ void Stream_Free(wStream* s, BOOL bFreeBuffer) - free(s); - } - } -+ -+BOOL Stream_CheckAndLogRequiredLengthEx(const char* tag, DWORD level, wStream* s, UINT64 len, -+ const char* fmt, ...) -+{ -+ const size_t actual = Stream_GetRemainingLength(s); -+ -+ if (actual < len) -+ { -+ va_list args; -+ -+ va_start(args, fmt); -+ Stream_CheckAndLogRequiredLengthExVa(tag, level, s, len, fmt, args); -+ va_end(args); -+ -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+BOOL Stream_CheckAndLogRequiredLengthExVa(const char* tag, DWORD level, wStream* s, UINT64 len, -+ const char* fmt, va_list args) -+{ -+ const size_t actual = Stream_GetRemainingLength(s); -+ -+ if (actual < len) -+ return Stream_CheckAndLogRequiredLengthWLogExVa(WLog_Get(tag), level, s, len, fmt, args); -+ return TRUE; -+} -+ -+BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s, UINT64 len, -+ const char* fmt, ...) -+{ -+ const size_t actual = Stream_GetRemainingLength(s); -+ -+ if (actual < len) -+ { -+ va_list args; -+ -+ va_start(args, fmt); -+ Stream_CheckAndLogRequiredLengthWLogExVa(log, level, s, len, fmt, args); -+ va_end(args); -+ -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s, UINT64 len, -+ const char* fmt, va_list args) -+{ -+ const size_t actual = Stream_GetRemainingLength(s); -+ -+ if (actual < len) -+ { -+ char prefix[1024] = { 0 }; -+ -+ vsnprintf(prefix, sizeof(prefix), fmt, args); -+ -+ WLog_Print(log, level, "[%s] invalid length, got %" PRIuz ", require at least %" PRIu64, -+ prefix, actual, len); -+ winpr_log_backtrace_ex(log, level, 20); -+ return FALSE; -+ } -+ return TRUE; -+} --- -2.38.1 - diff --git a/SOURCES/Fixed-missing-input-buffer-length-check-in-urbdrc.patch b/SOURCES/Fixed-missing-input-buffer-length-check-in-urbdrc.patch deleted file mode 100644 index b438d39..0000000 --- a/SOURCES/Fixed-missing-input-buffer-length-check-in-urbdrc.patch +++ /dev/null @@ -1,58 +0,0 @@ -From ddf9b3f852c31311f8d726012131f657c9857276 Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Thu, 13 Oct 2022 08:47:51 +0200 -Subject: [PATCH] Fixed missing input buffer length check in urbdrc - -(cherry picked from commit 497df00f741dd4fc89292aaef2db7368aee45d0d) ---- - channels/urbdrc/client/data_transfer.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c -index bb2784055..80e84af48 100644 ---- a/channels/urbdrc/client/data_transfer.c -+++ b/channels/urbdrc/client/data_transfer.c -@@ -241,6 +241,10 @@ static UINT urbdrc_process_io_control(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* c - - Stream_Read_UINT32(s, OutputBufferSize); - Stream_Read_UINT32(s, RequestId); -+ -+ if (OutputBufferSize > UINT32_MAX - 4) -+ return ERROR_INVALID_DATA; -+ - InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev)); - out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize); - -@@ -724,6 +728,15 @@ static UINT urb_bulk_or_interrupt_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBA - Stream_Read_UINT32(s, TransferFlags); /** TransferFlags */ - Stream_Read_UINT32(s, OutputBufferSize); - EndpointAddress = (PipeHandle & 0x000000ff); -+ -+ if (transferDir == USBD_TRANSFER_DIRECTION_OUT) -+ { -+ if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize)) -+ { -+ return ERROR_INVALID_DATA; -+ } -+ } -+ - /** process TS_URB_BULK_OR_INTERRUPT_TRANSFER */ - return pdev->bulk_or_interrupt_transfer(pdev, callback, MessageId, RequestId, EndpointAddress, - TransferFlags, noAck, OutputBufferSize, -@@ -808,6 +821,13 @@ static UINT urb_isoch_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callback - packetDescriptorData = Stream_Pointer(s); - Stream_Seek(s, NumberOfPackets * 12); - Stream_Read_UINT32(s, OutputBufferSize); -+ -+ if (transferDir == USBD_TRANSFER_DIRECTION_OUT) -+ { -+ if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize)) -+ return ERROR_INVALID_DATA; -+ } -+ - return pdev->isoch_transfer( - pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame, - ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize, --- -2.37.1 - diff --git a/SOURCES/Fixed-missing-length-check-in-video-channel.patch b/SOURCES/Fixed-missing-length-check-in-video-channel.patch deleted file mode 100644 index 3ba3d3d..0000000 --- a/SOURCES/Fixed-missing-length-check-in-video-channel.patch +++ /dev/null @@ -1,29 +0,0 @@ -From bf28ea249de57acc6dfadbd778afef2093c1c283 Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Thu, 6 Oct 2022 09:15:40 +0200 -Subject: [PATCH] Fixed missing length check in video channel - -Data received in video redirection channel was not checked for -proper length. - -(cherry picked from commit eeffd1050e9284d1464b58e049b2b4d88726632b) ---- - channels/video/client/video_main.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/channels/video/client/video_main.c b/channels/video/client/video_main.c -index a21e7cdf2..a8031fc86 100644 ---- a/channels/video/client/video_main.c -+++ b/channels/video/client/video_main.c -@@ -930,6 +930,8 @@ static UINT video_data_on_data_received(IWTSVirtualChannelCallback* pChannelCall - Stream_Read_UINT16(s, data.PacketsInSample); - Stream_Read_UINT32(s, data.SampleNumber); - Stream_Read_UINT32(s, data.cbSample); -+ if (!Stream_CheckAndLogRequiredLength(TAG, s, data.cbSample)) -+ return ERROR_INVALID_DATA; - data.pSample = Stream_Pointer(s); - - /* --- -2.37.1 - diff --git a/SOURCES/Fixed-missing-stream-length-check-in-drive_file_quer.patch b/SOURCES/Fixed-missing-stream-length-check-in-drive_file_quer.patch deleted file mode 100644 index 0c31cf5..0000000 --- a/SOURCES/Fixed-missing-stream-length-check-in-drive_file_quer.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 80b2483373c00baec3a26b1d82027f16dfdd8859 Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Mon, 24 Oct 2022 08:45:05 +0200 -Subject: [PATCH] Fixed missing stream length check in - drive_file_query_directory - -(cherry picked from commit 4e4bb79795d6ac85473fb7a83e53ccf63d204b93) ---- - channels/drive/client/drive_main.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c -index d3776381c..b6cf2ad32 100644 ---- a/channels/drive/client/drive_main.c -+++ b/channels/drive/client/drive_main.c -@@ -629,6 +629,9 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp) - Stream_Read_UINT32(irp->input, PathLength); - Stream_Seek(irp->input, 23); /* Padding */ - path = (WCHAR*)Stream_Pointer(irp->input); -+ if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength)) -+ return ERROR_INVALID_DATA; -+ - file = drive_get_file_by_id(drive, irp->FileId); - - if (file == NULL) --- -2.37.1 - diff --git a/SOURCES/Fixed-path-validation-in-drive-channel.patch b/SOURCES/Fixed-path-validation-in-drive-channel.patch deleted file mode 100644 index e4567f2..0000000 --- a/SOURCES/Fixed-path-validation-in-drive-channel.patch +++ /dev/null @@ -1,296 +0,0 @@ -From 865ba07a0fd4fbc7a8203482411aacca3bbfbb9f Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Mon, 24 Oct 2022 10:41:55 +0200 -Subject: [PATCH] Fixed path validation in drive channel - -Check that canonical path is a subpath of the shared directory - -(cherry picked from commit 844c94e6d0438fa7bd8ff8d5513c3f69c3018b85) ---- - channels/drive/client/drive_file.c | 106 ++++++++++++++++++----------- - channels/drive/client/drive_file.h | 8 +-- - channels/drive/client/drive_main.c | 8 +-- - 3 files changed, 73 insertions(+), 49 deletions(-) - -diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c -index 305438593..1ea4ab9da 100644 ---- a/channels/drive/client/drive_file.c -+++ b/channels/drive/client/drive_file.c -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -61,10 +62,14 @@ - } while (0) - #endif - --static void drive_file_fix_path(WCHAR* path) -+static BOOL drive_file_fix_path(WCHAR* path, size_t length) - { - size_t i; -- size_t length = _wcslen(path); -+ -+ if ((length == 0) || (length > UINT32_MAX)) -+ return FALSE; -+ -+ assert(path); - - for (i = 0; i < length; i++) - { -@@ -75,58 +79,82 @@ static void drive_file_fix_path(WCHAR* path) - #ifdef WIN32 - - if ((length == 3) && (path[1] == L':') && (path[2] == L'/')) -- return; -+ return FALSE; - - #else - - if ((length == 1) && (path[0] == L'/')) -- return; -+ return FALSE; - - #endif - - if ((length > 0) && (path[length - 1] == L'/')) - path[length - 1] = L'\0'; -+ -+ return TRUE; - } - - static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* path, -- size_t PathLength) -+ size_t PathWCharLength) - { -- WCHAR* fullpath; -- size_t base_path_length; -+ BOOL ok = FALSE; -+ WCHAR* fullpath = NULL; -+ size_t length; - -- if (!base_path || (!path && (PathLength > 0))) -- return NULL; -+ if (!base_path || (!path && (PathWCharLength > 0))) -+ goto fail; - -- base_path_length = _wcslen(base_path) * 2; -- fullpath = (WCHAR*)calloc(1, base_path_length + PathLength + sizeof(WCHAR)); -+ const size_t base_path_length = _wcsnlen(base_path, MAX_PATH); -+ length = base_path_length + PathWCharLength + 1; -+ fullpath = (WCHAR*)calloc(length, sizeof(WCHAR)); - - if (!fullpath) -+ goto fail; -+ -+ CopyMemory(fullpath, base_path, base_path_length * sizeof(WCHAR)); -+ if (path) -+ CopyMemory(&fullpath[base_path_length], path, PathWCharLength * sizeof(WCHAR)); -+ -+ if (!drive_file_fix_path(fullpath, length)) -+ goto fail; -+ -+ /* Ensure the path does not contain sequences like '..' */ -+ const WCHAR dotdot[] = { '.', '.', '\0' }; -+ if (_wcsstr(&fullpath[base_path_length], dotdot)) - { -- WLog_ERR(TAG, "malloc failed!"); -- return NULL; -+ char abuffer[MAX_PATH] = { 0 }; -+ ConvertFromUnicode(CP_UTF8, 0, &fullpath[base_path_length], -1, (char**)&abuffer, -+ ARRAYSIZE(abuffer) - 1, NULL, NULL); -+ -+ WLog_WARN(TAG, "[rdpdr] received invalid file path '%s' from server, aborting!", -+ &abuffer[base_path_length]); -+ goto fail; - } - -- CopyMemory(fullpath, base_path, base_path_length); -- if (path) -- CopyMemory((char*)fullpath + base_path_length, path, PathLength); -- drive_file_fix_path(fullpath); -+ ok = TRUE; -+fail: -+ if (!ok) -+ { -+ free(fullpath); -+ fullpath = NULL; -+ } - return fullpath; - } - - static BOOL drive_file_remove_dir(const WCHAR* path) - { -- WIN32_FIND_DATAW findFileData; -+ WIN32_FIND_DATAW findFileData = { 0 }; - BOOL ret = TRUE; -- HANDLE dir; -- WCHAR* fullpath; -- WCHAR* path_slash; -- size_t base_path_length; -+ HANDLE dir = INVALID_HANDLE_VALUE; -+ WCHAR* fullpath = NULL; -+ WCHAR* path_slash = NULL; -+ size_t base_path_length = 0; - - if (!path) - return FALSE; - -- base_path_length = _wcslen(path) * 2; -- path_slash = (WCHAR*)calloc(1, base_path_length + sizeof(WCHAR) * 3); -+ base_path_length = _wcslen(path); -+ path_slash = (WCHAR*)calloc(base_path_length + 3, sizeof(WCHAR)); - - if (!path_slash) - { -@@ -134,12 +162,11 @@ static BOOL drive_file_remove_dir(const WCHAR* path) - return FALSE; - } - -- CopyMemory(path_slash, path, base_path_length); -- path_slash[base_path_length / 2] = L'/'; -- path_slash[base_path_length / 2 + 1] = L'*'; -+ CopyMemory(path_slash, path, base_path_length * sizeof(WCHAR)); -+ path_slash[base_path_length] = L'/'; -+ path_slash[base_path_length + 1] = L'*'; - DEBUG_WSTR("Search in %s", path_slash); - dir = FindFirstFileW(path_slash, &findFileData); -- path_slash[base_path_length / 2 + 1] = 0; - - if (dir == INVALID_HANDLE_VALUE) - { -@@ -149,7 +176,7 @@ static BOOL drive_file_remove_dir(const WCHAR* path) - - do - { -- size_t len = _wcslen(findFileData.cFileName); -+ const size_t len = _wcsnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName)); - - if ((len == 1 && findFileData.cFileName[0] == L'.') || - (len == 2 && findFileData.cFileName[0] == L'.' && findFileData.cFileName[1] == L'.')) -@@ -157,7 +184,7 @@ static BOOL drive_file_remove_dir(const WCHAR* path) - continue; - } - -- fullpath = drive_file_combine_fullpath(path_slash, findFileData.cFileName, len * 2); -+ fullpath = drive_file_combine_fullpath(path_slash, findFileData.cFileName, len); - DEBUG_WSTR("Delete %s", fullpath); - - if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) -@@ -333,13 +360,13 @@ static BOOL drive_file_init(DRIVE_FILE* file) - return file->file_handle != INVALID_HANDLE_VALUE; - } - --DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id, -- UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions, -- UINT32 FileAttributes, UINT32 SharedAccess) -+DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathWCharLength, -+ UINT32 id, UINT32 DesiredAccess, UINT32 CreateDisposition, -+ UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess) - { - DRIVE_FILE* file; - -- if (!base_path || (!path && (PathLength > 0))) -+ if (!base_path || (!path && (PathWCharLength > 0))) - return NULL; - - file = (DRIVE_FILE*)calloc(1, sizeof(DRIVE_FILE)); -@@ -359,7 +386,7 @@ DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 Pat - file->CreateDisposition = CreateDisposition; - file->CreateOptions = CreateOptions; - file->SharedAccess = SharedAccess; -- drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path, PathLength)); -+ drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path, PathWCharLength)); - - if (!drive_file_init(file)) - { -@@ -714,13 +741,10 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN - return FALSE; - - fullpath = drive_file_combine_fullpath(file->basepath, (WCHAR*)Stream_Pointer(input), -- FileNameLength); -+ FileNameLength / sizeof(WCHAR)); - - if (!fullpath) -- { -- WLog_ERR(TAG, "drive_file_combine_fullpath failed!"); - return FALSE; -- } - - #ifdef _WIN32 - -@@ -759,7 +783,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN - } - - BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery, -- const WCHAR* path, UINT32 PathLength, wStream* output) -+ const WCHAR* path, UINT32 PathWCharLength, wStream* output) - { - size_t length; - WCHAR* ent_path; -@@ -773,7 +797,7 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT - if (file->find_handle != INVALID_HANDLE_VALUE) - FindClose(file->find_handle); - -- ent_path = drive_file_combine_fullpath(file->basepath, path, PathLength); -+ ent_path = drive_file_combine_fullpath(file->basepath, path, PathWCharLength); - /* open new search handle and retrieve the first entry */ - file->find_handle = FindFirstFileW(ent_path, &file->find_data); - free(ent_path); -diff --git a/channels/drive/client/drive_file.h b/channels/drive/client/drive_file.h -index ed789d6f0..6d3bd7045 100644 ---- a/channels/drive/client/drive_file.h -+++ b/channels/drive/client/drive_file.h -@@ -51,9 +51,9 @@ struct _DRIVE_FILE - UINT32 CreateOptions; - }; - --DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id, -- UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions, -- UINT32 FileAttributes, UINT32 SharedAccess); -+DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathWCharLength, -+ UINT32 id, UINT32 DesiredAccess, UINT32 CreateDisposition, -+ UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess); - BOOL drive_file_free(DRIVE_FILE* file); - - BOOL drive_file_open(DRIVE_FILE* file); -@@ -64,6 +64,6 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w - BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, - wStream* input); - BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery, -- const WCHAR* path, UINT32 PathLength, wStream* output); -+ const WCHAR* path, UINT32 PathWCharLength, wStream* output); - - #endif /* FREERDP_CHANNEL_DRIVE_FILE_H */ -diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c -index 1b5422522..d3776381c 100644 ---- a/channels/drive/client/drive_main.c -+++ b/channels/drive/client/drive_main.c -@@ -184,8 +184,8 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp) - - path = (const WCHAR*)Stream_Pointer(irp->input); - FileId = irp->devman->id_sequence++; -- file = drive_file_new(drive->path, path, PathLength, FileId, DesiredAccess, CreateDisposition, -- CreateOptions, FileAttributes, SharedAccess); -+ file = drive_file_new(drive->path, path, PathLength / sizeof(WCHAR), FileId, DesiredAccess, -+ CreateDisposition, CreateOptions, FileAttributes, SharedAccess); - - if (!file) - { -@@ -636,8 +636,8 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp) - irp->IoStatus = STATUS_UNSUCCESSFUL; - Stream_Write_UINT32(irp->output, 0); /* Length */ - } -- else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path, PathLength, -- irp->output)) -+ else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path, -+ PathLength / sizeof(WCHAR), irp->output)) - { - irp->IoStatus = drive_map_windows_err(GetLastError()); - } --- -2.37.1 - diff --git a/SOURCES/Implement-missing-TSG-debug-functions.patch b/SOURCES/Implement-missing-TSG-debug-functions.patch deleted file mode 100644 index 45f8c0a..0000000 --- a/SOURCES/Implement-missing-TSG-debug-functions.patch +++ /dev/null @@ -1,433 +0,0 @@ -From ea20ba13ec764b30d6642cd570929e71e97d00f1 Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Tue, 12 Oct 2021 13:33:41 +0200 -Subject: [PATCH] Implemented missing TSG debug functions - -(cherry picked from commit c06c4638061b0305a269dbb8f7c87009cf886f02) ---- - libfreerdp/core/gateway/tsg.c | 330 ++++++++++++++++++++++++++++++++-- - 1 file changed, 313 insertions(+), 17 deletions(-) - -diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c -index 1626b91..3376fb0 100644 ---- a/libfreerdp/core/gateway/tsg.c -+++ b/libfreerdp/core/gateway/tsg.c -@@ -24,6 +24,7 @@ - #include "config.h" - #endif - -+#include - #include - #include - #include -@@ -39,13 +40,14 @@ - - #define TAG FREERDP_TAG("core.gateway.tsg") - -+#define TSG_CAPABILITY_TYPE_NAP 0x00000001 -+ - #define TSG_PACKET_TYPE_HEADER 0x00004844 - #define TSG_PACKET_TYPE_VERSIONCAPS 0x00005643 - #define TSG_PACKET_TYPE_QUARCONFIGREQUEST 0x00005143 - #define TSG_PACKET_TYPE_QUARREQUEST 0x00005152 - #define TSG_PACKET_TYPE_RESPONSE 0x00005052 - #define TSG_PACKET_TYPE_QUARENC_RESPONSE 0x00004552 --#define TSG_CAPABILITY_TYPE_NAP 0x00000001 - #define TSG_PACKET_TYPE_CAPS_RESPONSE 0x00004350 - #define TSG_PACKET_TYPE_MSGREQUEST_PACKET 0x00004752 - #define TSG_PACKET_TYPE_MESSAGE_PACKET 0x00004750 -@@ -308,16 +310,35 @@ static BOOL tsg_print(char** buffer, size_t* len, const char* fmt, ...) - static BOOL tsg_packet_header_to_string(char** buffer, size_t* length, - const TSG_PACKET_HEADER* header) - { -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(header); -+ - return tsg_print(buffer, length, - "header { ComponentId=0x%04" PRIx16 ", PacketId=0x%04" PRIx16 " }", - header->ComponentId, header->PacketId); - } - -+static BOOL tsg_type_capability_nap_to_string(char** buffer, size_t* length, -+ const TSG_CAPABILITY_NAP* cur) -+{ -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(cur); -+ -+ return tsg_print(buffer, length, "%s { capabilities=0x%08" PRIx32 " }", -+ tsg_packet_id_to_string(TSG_CAPABILITY_TYPE_NAP), cur->capabilities); -+} -+ - static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length, - const TSG_PACKET_CAPABILITIES* caps, UINT32 numCaps) - { - UINT32 x; - -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ - if (!tsg_print(buffer, length, "capabilities { ")) - return FALSE; - -@@ -327,9 +348,7 @@ static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length, - switch (cur->capabilityType) - { - case TSG_CAPABILITY_TYPE_NAP: -- if (!tsg_print(buffer, length, "%s { capabilities=0x%08" PRIx32 " }", -- tsg_packet_id_to_string(cur->capabilityType), -- cur->tsgPacket.tsgCapNap.capabilities)) -+ if (!tsg_type_capability_nap_to_string(buffer, length, &cur->tsgPacket.tsgCapNap)) - return FALSE; - break; - default: -@@ -344,6 +363,10 @@ static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length, - static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length, - const TSG_PACKET_VERSIONCAPS* caps) - { -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ - if (!tsg_print(buffer, length, "versioncaps { ")) - return FALSE; - if (!tsg_packet_header_to_string(buffer, length, &caps->tsgHeader)) -@@ -365,6 +388,277 @@ static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length, - return tsg_print(buffer, length, " }"); - } - -+static BOOL tsg_packet_quarconfigrequest_to_string(char** buffer, size_t* length, -+ const TSG_PACKET_QUARCONFIGREQUEST* caps) -+{ -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ -+ if (!tsg_print(buffer, length, "quarconfigrequest { ")) -+ return FALSE; -+ -+ if (!tsg_print(buffer, length, " ")) -+ return FALSE; -+ -+ if (!tsg_print(buffer, length, " flags=0x%08" PRIx32, caps->flags)) -+ return FALSE; -+ -+ return tsg_print(buffer, length, " }"); -+} -+ -+static BOOL tsg_packet_quarrequest_to_string(char** buffer, size_t* length, -+ const TSG_PACKET_QUARREQUEST* caps) -+{ -+ BOOL rc = FALSE; -+ char* name = NULL; -+ char* strdata = NULL; -+ -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ -+ if (!tsg_print(buffer, length, "quarrequest { ")) -+ return FALSE; -+ -+ if (!tsg_print(buffer, length, " ")) -+ return FALSE; -+ -+ if (caps->nameLength > 0) -+ { -+ if (ConvertFromUnicode(CP_UTF8, 0, caps->machineName, caps->nameLength, &name, 0, NULL, -+ NULL) < 0) -+ return FALSE; -+ } -+ -+ strdata = winpr_BinToHexString(caps->data, caps->dataLen, TRUE); -+ if (strdata || (caps->dataLen == 0)) -+ rc = tsg_print(buffer, length, -+ " flags=0x%08" PRIx32 ", machineName=%s [%" PRIu32 "], data[%" PRIu32 "]=%s", -+ caps->flags, name, caps->nameLength, caps->dataLen, strdata); -+ free(name); -+ free(strdata); -+ if (!rc) -+ return FALSE; -+ -+ return tsg_print(buffer, length, " }"); -+} -+ -+static const char* tsg_bool_to_string(BOOL val) -+{ -+ if (val) -+ return "true"; -+ return "false"; -+} -+ -+static const char* tsg_redirection_flags_to_string(char* buffer, size_t size, -+ const TSG_REDIRECTION_FLAGS* flags) -+{ -+ WINPR_ASSERT(buffer || (size == 0)); -+ WINPR_ASSERT(flags); -+ -+ _snprintf(buffer, size, -+ "enableAllRedirections=%s, disableAllRedirections=%s, driveRedirectionDisabled=%s, " -+ "printerRedirectionDisabled=%s, portRedirectionDisabled=%s, reserved=%s, " -+ "clipboardRedirectionDisabled=%s, pnpRedirectionDisabled=%s", -+ tsg_bool_to_string(flags->enableAllRedirections), -+ tsg_bool_to_string(flags->disableAllRedirections), -+ tsg_bool_to_string(flags->driveRedirectionDisabled), -+ tsg_bool_to_string(flags->printerRedirectionDisabled), -+ tsg_bool_to_string(flags->portRedirectionDisabled), -+ tsg_bool_to_string(flags->reserved), -+ tsg_bool_to_string(flags->clipboardRedirectionDisabled), -+ tsg_bool_to_string(flags->pnpRedirectionDisabled)); -+ return buffer; -+} -+ -+static BOOL tsg_packet_response_to_string(char** buffer, size_t* length, -+ const TSG_PACKET_RESPONSE* caps) -+{ -+ BOOL rc = FALSE; -+ char* strdata = NULL; -+ char tbuffer[8192] = { 0 }; -+ -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ -+ if (!tsg_print(buffer, length, "response { ")) -+ return FALSE; -+ -+ if (!tsg_print(buffer, length, " ")) -+ return FALSE; -+ -+ strdata = winpr_BinToHexString(caps->responseData, caps->responseDataLen, TRUE); -+ if (strdata || (caps->responseDataLen == 0)) -+ rc = tsg_print( -+ buffer, length, -+ " flags=0x%08" PRIx32 ", reserved=0x%08" PRIx32 ", responseData[%" PRIu32 -+ "]=%s, redirectionFlags={ %s }", -+ caps->flags, caps->reserved, caps->responseDataLen, strdata, -+ tsg_redirection_flags_to_string(tbuffer, ARRAYSIZE(tbuffer), &caps->redirectionFlags)); -+ free(strdata); -+ if (!rc) -+ return FALSE; -+ -+ return tsg_print(buffer, length, " }"); -+} -+ -+static BOOL tsg_packet_quarenc_response_to_string(char** buffer, size_t* length, -+ const TSG_PACKET_QUARENC_RESPONSE* caps) -+{ -+ BOOL rc = FALSE; -+ char* strdata = NULL; -+ RPC_CSTR uuid; -+ char tbuffer[8192] = { 0 }; -+ size_t size = ARRAYSIZE(tbuffer); -+ char* ptbuffer = tbuffer; -+ -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ -+ if (!tsg_print(buffer, length, "quarenc_response { ")) -+ return FALSE; -+ -+ if (!tsg_print(buffer, length, " ")) -+ return FALSE; -+ -+ if (caps->certChainLen > 0) -+ { -+ if (ConvertFromUnicode(CP_UTF8, 0, caps->certChainData, caps->certChainLen, &strdata, 0, -+ NULL, NULL) <= 0) -+ return FALSE; -+ } -+ -+ tsg_packet_versioncaps_to_string(&ptbuffer, &size, caps->versionCaps); -+ UuidToStringA(&caps->nonce, &uuid); -+ if (strdata || (caps->certChainLen == 0)) -+ rc = -+ tsg_print(buffer, length, -+ " flags=0x%08" PRIx32 ", certChain[%" PRIu32 "]=%s, nonce=%s, versionCaps=%s", -+ caps->flags, caps->certChainLen, strdata, uuid, tbuffer); -+ free(strdata); -+ free(uuid); -+ if (!rc) -+ return FALSE; -+ -+ return tsg_print(buffer, length, " }"); -+} -+ -+static BOOL tsg_packet_message_response_to_string(char** buffer, size_t* length, -+ const TSG_PACKET_MSG_RESPONSE* caps) -+{ -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ -+ if (!tsg_print(buffer, length, "msg_response { ")) -+ return FALSE; -+ -+ if (!tsg_print(buffer, length, -+ " msgID=0x%08" PRIx32 ", msgType=0x%08" PRIx32 ", isMsgPresent=%" PRId32, -+ caps->msgID, caps->msgType, caps->isMsgPresent)) -+ return FALSE; -+ -+ return tsg_print(buffer, length, " }"); -+} -+ -+static BOOL tsg_packet_caps_response_to_string(char** buffer, size_t* length, -+ const TSG_PACKET_CAPS_RESPONSE* caps) -+{ -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ -+ if (!tsg_print(buffer, length, "caps_response { ")) -+ return FALSE; -+ -+ if (!tsg_packet_quarenc_response_to_string(buffer, length, &caps->pktQuarEncResponse)) -+ return FALSE; -+ -+ if (!tsg_packet_message_response_to_string(buffer, length, &caps->pktConsentMessage)) -+ return FALSE; -+ -+ return tsg_print(buffer, length, " }"); -+} -+ -+static BOOL tsg_packet_message_request_to_string(char** buffer, size_t* length, -+ const TSG_PACKET_MSG_REQUEST* caps) -+{ -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ -+ if (!tsg_print(buffer, length, "caps_message_request { ")) -+ return FALSE; -+ -+ if (!tsg_print(buffer, length, " maxMessagesPerBatch=%" PRIu32, caps->maxMessagesPerBatch)) -+ return FALSE; -+ -+ return tsg_print(buffer, length, " }"); -+} -+ -+static BOOL tsg_packet_auth_to_string(char** buffer, size_t* length, const TSG_PACKET_AUTH* caps) -+{ -+ BOOL rc = FALSE; -+ char* strdata = NULL; -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ -+ if (!tsg_print(buffer, length, "caps_message_request { ")) -+ return FALSE; -+ -+ if (!tsg_packet_versioncaps_to_string(buffer, length, &caps->tsgVersionCaps)) -+ return FALSE; -+ -+ strdata = winpr_BinToHexString(caps->cookie, caps->cookieLen, TRUE); -+ if (strdata || (caps->cookieLen == 0)) -+ rc = tsg_print(buffer, length, " cookie[%" PRIu32 "]=%s", caps->cookieLen, strdata); -+ free(strdata); -+ if (!rc) -+ return FALSE; -+ -+ return tsg_print(buffer, length, " }"); -+} -+ -+static BOOL tsg_packet_reauth_to_string(char** buffer, size_t* length, -+ const TSG_PACKET_REAUTH* caps) -+{ -+ BOOL rc = FALSE; -+ WINPR_ASSERT(buffer); -+ WINPR_ASSERT(length); -+ WINPR_ASSERT(caps); -+ -+ if (!tsg_print(buffer, length, "caps_message_request { ")) -+ return FALSE; -+ -+ if (!tsg_print(buffer, length, " tunnelContext=0x%08" PRIx32 ", packetId=%s [0x%08" PRIx32 "]", -+ caps->tunnelContext, tsg_packet_id_to_string(caps->packetId), caps->packetId)) -+ return FALSE; -+ -+ switch (caps->packetId) -+ { -+ case TSG_PACKET_TYPE_VERSIONCAPS: -+ rc = tsg_packet_versioncaps_to_string(buffer, length, -+ caps->tsgInitialPacket.packetVersionCaps); -+ break; -+ case TSG_PACKET_TYPE_AUTH: -+ rc = tsg_packet_auth_to_string(buffer, length, caps->tsgInitialPacket.packetAuth); -+ break; -+ default: -+ rc = tsg_print(buffer, length, "TODO: Unhandled packet type %s [0x%08" PRIx32 "]", -+ tsg_packet_id_to_string(caps->packetId), caps->packetId); -+ break; -+ } -+ -+ if (!rc) -+ return FALSE; -+ -+ return tsg_print(buffer, length, " }"); -+} -+ - static const char* tsg_packet_to_string(const TSG_PACKET* packet) - { - size_t len = 8192; -@@ -387,43 +681,45 @@ static const char* tsg_packet_to_string(const TSG_PACKET* packet) - goto fail; - break; - case TSG_PACKET_TYPE_QUARCONFIGREQUEST: -- if (!tsg_print(&buffer, &len, "TODO")) -+ if (!tsg_packet_quarconfigrequest_to_string(&buffer, &len, -+ packet->tsgPacket.packetQuarConfigRequest)) - goto fail; - break; - case TSG_PACKET_TYPE_QUARREQUEST: -- if (!tsg_print(&buffer, &len, "TODO")) -+ if (!tsg_packet_quarrequest_to_string(&buffer, &len, -+ packet->tsgPacket.packetQuarRequest)) - goto fail; - break; - case TSG_PACKET_TYPE_RESPONSE: -- if (!tsg_print(&buffer, &len, "TODO")) -+ if (!tsg_packet_response_to_string(&buffer, &len, packet->tsgPacket.packetResponse)) - goto fail; - break; - case TSG_PACKET_TYPE_QUARENC_RESPONSE: -- if (!tsg_print(&buffer, &len, "TODO")) -- goto fail; -- break; -- case TSG_CAPABILITY_TYPE_NAP: -- if (!tsg_print(&buffer, &len, "TODO")) -+ if (!tsg_packet_quarenc_response_to_string(&buffer, &len, -+ packet->tsgPacket.packetQuarEncResponse)) - goto fail; - break; - case TSG_PACKET_TYPE_CAPS_RESPONSE: -- if (!tsg_print(&buffer, &len, "TODO")) -+ if (!tsg_packet_caps_response_to_string(&buffer, &len, -+ packet->tsgPacket.packetCapsResponse)) - goto fail; - break; - case TSG_PACKET_TYPE_MSGREQUEST_PACKET: -- if (!tsg_print(&buffer, &len, "TODO")) -+ if (!tsg_packet_message_request_to_string(&buffer, &len, -+ packet->tsgPacket.packetMsgRequest)) - goto fail; - break; - case TSG_PACKET_TYPE_MESSAGE_PACKET: -- if (!tsg_print(&buffer, &len, "TODO")) -+ if (!tsg_packet_message_response_to_string(&buffer, &len, -+ packet->tsgPacket.packetMsgResponse)) - goto fail; - break; - case TSG_PACKET_TYPE_AUTH: -- if (!tsg_print(&buffer, &len, "TODO")) -+ if (!tsg_packet_auth_to_string(&buffer, &len, packet->tsgPacket.packetAuth)) - goto fail; - break; - case TSG_PACKET_TYPE_REAUTH: -- if (!tsg_print(&buffer, &len, "TODO")) -+ if (!tsg_packet_reauth_to_string(&buffer, &len, packet->tsgPacket.packetReauth)) - goto fail; - break; - default: diff --git a/SOURCES/Refactored-RPC-gateway-parser.patch b/SOURCES/Refactored-RPC-gateway-parser.patch deleted file mode 100644 index 2c0bd90..0000000 --- a/SOURCES/Refactored-RPC-gateway-parser.patch +++ /dev/null @@ -1,4950 +0,0 @@ -From f0a0683fa6a3f696c4bc5ba88c128bc781c54895 Mon Sep 17 00:00:00 2001 -From: Armin Novak -Date: Mon, 11 Oct 2021 12:19:40 +0200 -Subject: [PATCH] Refactored RPC gateway parser - -Utilize wStream instead of custom binary parsing code, add proper -input validation. -Reported by Sunglin from the Knownsec 404 team & 0103 sec team - -(cherry picked from commit f0b44da67c09488178000725ff9f2729ccfdf9fe) ---- - libfreerdp/core/gateway/ncacn_http.c | 6 +- - libfreerdp/core/gateway/rdg.c | 77 +- - libfreerdp/core/gateway/rpc.c | 134 +- - libfreerdp/core/gateway/rpc.h | 18 +- - libfreerdp/core/gateway/rpc_bind.c | 253 +-- - libfreerdp/core/gateway/rpc_bind.h | 2 +- - libfreerdp/core/gateway/rpc_client.c | 265 +-- - libfreerdp/core/gateway/rpc_client.h | 3 +- - libfreerdp/core/gateway/rpc_fault.c | 48 +- - libfreerdp/core/gateway/rts.c | 2085 ++++++++++++++++++----- - libfreerdp/core/gateway/rts.h | 29 +- - libfreerdp/core/gateway/rts_signature.c | 127 +- - libfreerdp/core/gateway/rts_signature.h | 8 +- - libfreerdp/core/gateway/tsg.c | 305 ++-- - libfreerdp/core/surface.c | 8 +- - 15 files changed, 2375 insertions(+), 993 deletions(-) - -diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c -index cffb378..f288a0f 100644 ---- a/libfreerdp/core/gateway/ncacn_http.c -+++ b/libfreerdp/core/gateway/ncacn_http.c -@@ -121,6 +121,7 @@ BOOL rpc_ncacn_http_recv_in_channel_response(RpcChannel* inChannel, HttpResponse - if (ntlmTokenData && ntlmTokenLength) - return ntlm_client_set_input_buffer(ntlm, FALSE, ntlmTokenData, ntlmTokenLength); - -+ free(ntlmTokenData); - return TRUE; - } - -@@ -274,5 +275,6 @@ BOOL rpc_ncacn_http_recv_out_channel_response(RpcChannel* outChannel, HttpRespon - if (ntlmTokenData && ntlmTokenLength) - return ntlm_client_set_input_buffer(ntlm, FALSE, ntlmTokenData, ntlmTokenLength); - -+ free(ntlmTokenData); - return TRUE; - } -diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c -index 107e396..d333880 100644 ---- a/libfreerdp/core/gateway/rdg.c -+++ b/libfreerdp/core/gateway/rdg.c -@@ -1159,6 +1159,9 @@ static BOOL rdg_tunnel_connect(rdpRdg* rdg) - - if (!status) - { -+ assert(rdg); -+ assert(rdg->context); -+ assert(rdg->context->rdp); - rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED; - return FALSE; - } -@@ -1190,6 +1193,9 @@ BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback) - - if (!status) - { -+ assert(rdg); -+ assert(rdg->context); -+ assert(rdg->context->rdp); - rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED; - return FALSE; - } -@@ -1535,10 +1541,10 @@ static int rdg_bio_gets(BIO* bio, char* str, int size) - return -2; - } - --static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2) -+static long rdg_bio_ctrl(BIO* in_bio, int cmd, long arg1, void* arg2) - { - long status = -1; -- rdpRdg* rdg = (rdpRdg*)BIO_get_data(bio); -+ rdpRdg* rdg = (rdpRdg*)BIO_get_data(in_bio); - rdpTls* tlsOut = rdg->tlsOut; - rdpTls* tlsIn = rdg->tlsIn; - -diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c -index 218a407..4ba52f3 100644 ---- a/libfreerdp/core/gateway/rpc.c -+++ b/libfreerdp/core/gateway/rpc.c -@@ -24,6 +24,7 @@ - #endif - - #include -+#include - #include - #include - #include -@@ -46,6 +47,7 @@ - #include "rpc_client.h" - - #include "rpc.h" -+#include "rts.h" - - #define TAG FREERDP_TAG("core.gateway.rpc") - -@@ -88,8 +90,10 @@ static const char* PTYPE_STRINGS[] = { "PTYPE_REQUEST", "PTYPE_PING", - * - */ - --void rpc_pdu_header_print(rpcconn_hdr_t* header) -+void rpc_pdu_header_print(const rpcconn_hdr_t* header) - { -+ assert(header); -+ - WLog_INFO(TAG, "rpc_vers: %" PRIu8 "", header->common.rpc_vers); - WLog_INFO(TAG, "rpc_vers_minor: %" PRIu8 "", header->common.rpc_vers_minor); - -@@ -139,26 +143,30 @@ void rpc_pdu_header_print(rpcconn_hdr_t* header) - } - } - --void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header) -+rpcconn_common_hdr_t rpc_pdu_header_init(const rdpRpc* rpc) - { -- header->rpc_vers = rpc->rpc_vers; -- header->rpc_vers_minor = rpc->rpc_vers_minor; -- header->packed_drep[0] = rpc->packed_drep[0]; -- header->packed_drep[1] = rpc->packed_drep[1]; -- header->packed_drep[2] = rpc->packed_drep[2]; -- header->packed_drep[3] = rpc->packed_drep[3]; -+ rpcconn_common_hdr_t header = { 0 }; -+ assert(rpc); -+ -+ header.rpc_vers = rpc->rpc_vers; -+ header.rpc_vers_minor = rpc->rpc_vers_minor; -+ header.packed_drep[0] = rpc->packed_drep[0]; -+ header.packed_drep[1] = rpc->packed_drep[1]; -+ header.packed_drep[2] = rpc->packed_drep[2]; -+ header.packed_drep[3] = rpc->packed_drep[3]; -+ return header; - } - --UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment) -+size_t rpc_offset_align(size_t* offset, size_t alignment) - { -- UINT32 pad; -+ size_t pad; - pad = *offset; - *offset = (*offset + alignment - 1) & ~(alignment - 1); - pad = *offset - pad; - return pad; - } - --UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad) -+size_t rpc_offset_pad(size_t* offset, size_t pad) - { - *offset += pad; - return pad; -@@ -239,64 +247,67 @@ UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad) - * - */ - --BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* length) -+BOOL rpc_get_stub_data_info(const rpcconn_hdr_t* header, size_t* poffset, size_t* length) - { -- UINT32 alloc_hint = 0; -- rpcconn_hdr_t* header; -+ size_t used = 0; -+ size_t offset = 0; -+ BOOL rc = FALSE; - UINT32 frag_length; - UINT32 auth_length; -- UINT32 auth_pad_length; -+ UINT32 auth_pad_length = 0; - UINT32 sec_trailer_offset; -- rpc_sec_trailer* sec_trailer; -- *offset = RPC_COMMON_FIELDS_LENGTH; -- header = ((rpcconn_hdr_t*)buffer); -+ const rpc_sec_trailer* sec_trailer = NULL; -+ -+ assert(header); -+ assert(poffset); -+ assert(length); -+ -+ offset = RPC_COMMON_FIELDS_LENGTH; - - switch (header->common.ptype) - { - case PTYPE_RESPONSE: -- *offset += 8; -- rpc_offset_align(offset, 8); -- alloc_hint = header->response.alloc_hint; -+ offset += 8; -+ rpc_offset_align(&offset, 8); -+ sec_trailer = &header->response.auth_verifier; - break; - - case PTYPE_REQUEST: -- *offset += 4; -- rpc_offset_align(offset, 8); -- alloc_hint = header->request.alloc_hint; -+ offset += 4; -+ rpc_offset_align(&offset, 8); -+ sec_trailer = &header->request.auth_verifier; - break; - - case PTYPE_RTS: -- *offset += 4; -+ offset += 4; - break; - - default: - WLog_ERR(TAG, "Unknown PTYPE: 0x%02" PRIX8 "", header->common.ptype); -- return FALSE; -+ goto fail; - } - -- if (!length) -- return TRUE; -+ frag_length = header->common.frag_length; -+ auth_length = header->common.auth_length; -+ -+ if (poffset) -+ *poffset = offset; - -- if (header->common.ptype == PTYPE_REQUEST) -+ /* The fragment must be larger than the authentication trailer */ -+ used = offset + auth_length + 8ull; -+ if (sec_trailer) - { -- UINT32 sec_trailer_offset; -- sec_trailer_offset = header->common.frag_length - header->common.auth_length - 8; -- *length = sec_trailer_offset - *offset; -- return TRUE; -+ auth_pad_length = sec_trailer->auth_pad_length; -+ used += sec_trailer->auth_pad_length; - } - -- frag_length = header->common.frag_length; -- auth_length = header->common.auth_length; -+ if (frag_length < used) -+ goto fail; -+ -+ if (!length) -+ return TRUE; -+ - sec_trailer_offset = frag_length - auth_length - 8; -- sec_trailer = (rpc_sec_trailer*)&buffer[sec_trailer_offset]; -- auth_pad_length = sec_trailer->auth_pad_length; --#if 0 -- WLog_DBG(TAG, -- "sec_trailer: type: %"PRIu8" level: %"PRIu8" pad_length: %"PRIu8" reserved: %"PRIu8" context_id: %"PRIu32"", -- sec_trailer->auth_type, sec_trailer->auth_level, -- sec_trailer->auth_pad_length, sec_trailer->auth_reserved, -- sec_trailer->auth_context_id); --#endif - - /** - * According to [MS-RPCE], auth_pad_length is the number of padding -@@ -310,18 +321,21 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l - auth_length, (frag_length - (sec_trailer_offset + 8))); - } - -- *length = frag_length - auth_length - 24 - 8 - auth_pad_length; -- return TRUE; -+ *length = sec_trailer_offset - auth_pad_length - offset; -+ -+ rc = TRUE; -+fail: -+ return rc; - } - - SSIZE_T rpc_channel_read(RpcChannel* channel, wStream* s, size_t length) - { - int status; - -- if (!channel) -+ if (!channel || (length > INT32_MAX)) - return -1; - -- status = BIO_read(channel->tls->bio, Stream_Pointer(s), length); -+ status = BIO_read(channel->tls->bio, Stream_Pointer(s), (INT32)length); - - if (status > 0) - { -@@ -340,10 +354,10 @@ SSIZE_T rpc_channel_write(RpcChannel* channel, const BYTE* data, size_t length) - { - int status; - -- if (!channel) -+ if (!channel || (length > INT32_MAX)) - return -1; - -- status = tls_write_all(channel->tls, data, length); -+ status = tls_write_all(channel->tls, data, (INT32)length); - return status; - } - -@@ -629,7 +643,7 @@ static void rpc_virtual_connection_free(RpcVirtualConnection* connection) - free(connection); - } - --static BOOL rpc_channel_tls_connect(RpcChannel* channel, int timeout) -+static BOOL rpc_channel_tls_connect(RpcChannel* channel, UINT32 timeout) - { - int sockfd; - rdpTls* tls; -@@ -719,7 +733,7 @@ static BOOL rpc_channel_tls_connect(RpcChannel* channel, int timeout) - return TRUE; - } - --static int rpc_in_channel_connect(RpcInChannel* inChannel, int timeout) -+static int rpc_in_channel_connect(RpcInChannel* inChannel, UINT32 timeout) - { - rdpContext* context; - -@@ -814,7 +828,7 @@ int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, int timeout) - return 1; - } - --BOOL rpc_connect(rdpRpc* rpc, int timeout) -+BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout) - { - RpcInChannel* inChannel; - RpcOutChannel* outChannel; -@@ -840,7 +854,15 @@ BOOL rpc_connect(rdpRpc* rpc, int timeout) - - rdpRpc* rpc_new(rdpTransport* transport) - { -- rdpRpc* rpc = (rdpRpc*)calloc(1, sizeof(rdpRpc)); -+ rdpContext* context; -+ rdpRpc* rpc; -+ -+ assert(transport); -+ -+ context = transport->context; -+ assert(context); -+ -+ rpc = (rdpRpc*)calloc(1, sizeof(rdpRpc)); - - if (!rpc) - return NULL; -@@ -848,7 +870,7 @@ rdpRpc* rpc_new(rdpTransport* transport) - rpc->State = RPC_CLIENT_STATE_INITIAL; - rpc->transport = transport; - rpc->settings = transport->settings; -- rpc->context = transport->context; -+ rpc->context = context; - rpc->SendSeqNum = 0; - rpc->ntlm = ntlm_new(); - -@@ -873,7 +895,7 @@ rdpRpc* rpc_new(rdpTransport* transport) - rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval; - rpc->CurrentKeepAliveTime = 0; - rpc->CallId = 2; -- rpc->client = rpc_client_new(rpc->context, rpc->max_recv_frag); -+ rpc->client = rpc_client_new(context, rpc->max_recv_frag); - - if (!rpc->client) - goto out_free; -diff --git a/libfreerdp/core/gateway/rpc.h b/libfreerdp/core/gateway/rpc.h -index 3ca18a7..28f7f30 100644 ---- a/libfreerdp/core/gateway/rpc.h -+++ b/libfreerdp/core/gateway/rpc.h -@@ -73,7 +73,6 @@ typedef struct _RPC_PDU - #include "../tcp.h" - #include "../transport.h" - --#include "rts.h" - #include "http.h" - #include "ntlm.h" - -@@ -522,7 +521,8 @@ typedef struct - rpcconn_common_hdr_t header; - } rpcconn_shutdown_hdr_t; - --typedef union { -+typedef union -+{ - rpcconn_common_hdr_t common; - rpcconn_alter_context_hdr_t alter_context; - rpcconn_alter_context_response_hdr_t alter_context_response; -@@ -764,14 +764,14 @@ struct rdp_rpc - RpcVirtualConnection* VirtualConnection; - }; - --FREERDP_LOCAL void rpc_pdu_header_print(rpcconn_hdr_t* header); --FREERDP_LOCAL void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header); -+FREERDP_LOCAL void rpc_pdu_header_print(const rpcconn_hdr_t* header); -+FREERDP_LOCAL rpcconn_common_hdr_t rpc_pdu_header_init(const rdpRpc* rpc); - --FREERDP_LOCAL UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment); --FREERDP_LOCAL UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad); -+FREERDP_LOCAL size_t rpc_offset_align(size_t* offset, size_t alignment); -+FREERDP_LOCAL size_t rpc_offset_pad(size_t* offset, size_t pad); - --FREERDP_LOCAL BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* header, UINT32* offset, -- UINT32* length); -+FREERDP_LOCAL BOOL rpc_get_stub_data_info(const rpcconn_hdr_t* header, size_t* offset, -+ size_t* length); - - FREERDP_LOCAL SSIZE_T rpc_channel_write(RpcChannel* channel, const BYTE* data, size_t length); - -@@ -791,7 +791,7 @@ FREERDP_LOCAL BOOL rpc_virtual_connection_transition_to_state(rdpRpc* rpc, - RpcVirtualConnection* connection, - VIRTUAL_CONNECTION_STATE state); - --FREERDP_LOCAL BOOL rpc_connect(rdpRpc* rpc, int timeout); -+FREERDP_LOCAL BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout); - - FREERDP_LOCAL rdpRpc* rpc_new(rdpTransport* transport); - FREERDP_LOCAL void rpc_free(rdpRpc* rpc); -diff --git a/libfreerdp/core/gateway/rpc_bind.c b/libfreerdp/core/gateway/rpc_bind.c -index 98ed9a9..bdf54d5 100644 ---- a/libfreerdp/core/gateway/rpc_bind.c -+++ b/libfreerdp/core/gateway/rpc_bind.c -@@ -22,11 +22,14 @@ - #endif - - #include -+#include - - #include - - #include "rpc_client.h" - -+#include "rts.h" -+ - #include "rpc_bind.h" - - #define TAG FREERDP_TAG("core.gateway.rpc") -@@ -106,18 +109,32 @@ int rpc_send_bind_pdu(rdpRpc* rpc) - { - BOOL continueNeeded = FALSE; - int status = -1; -- BYTE* buffer = NULL; -+ wStream* buffer = NULL; - UINT32 offset; -- UINT32 length; - RpcClientCall* clientCall; - p_cont_elem_t* p_cont_elem; -- rpcconn_bind_hdr_t* bind_pdu = NULL; -+ rpcconn_bind_hdr_t bind_pdu = { 0 }; - BOOL promptPassword = FALSE; -- rdpSettings* settings = rpc->settings; -- freerdp* instance = (freerdp*)settings->instance; -- RpcVirtualConnection* connection = rpc->VirtualConnection; -- RpcInChannel* inChannel = connection->DefaultInChannel; -+ rdpSettings* settings; -+ freerdp* instance; -+ RpcVirtualConnection* connection; -+ RpcInChannel* inChannel; - const SecBuffer* sbuffer = NULL; -+ -+ assert(rpc); -+ -+ settings = rpc->settings; -+ assert(settings); -+ -+ instance = (freerdp*)settings->instance; -+ assert(instance); -+ -+ connection = rpc->VirtualConnection; -+ -+ assert(connection); -+ -+ inChannel = connection->DefaultInChannel; -+ - WLog_DBG(TAG, "Sending Bind PDU"); - ntlm_free(rpc->ntlm); - rpc->ntlm = ntlm_new(); -@@ -180,36 +197,31 @@ int rpc_send_bind_pdu(rdpRpc* rpc) - if (!continueNeeded) - goto fail; - -- bind_pdu = (rpcconn_bind_hdr_t*)calloc(1, sizeof(rpcconn_bind_hdr_t)); -- -- if (!bind_pdu) -- goto fail; -- - sbuffer = ntlm_client_get_output_buffer(rpc->ntlm); - - if (!sbuffer) - goto fail; - -- rpc_pdu_header_init(rpc, &bind_pdu->header); -- bind_pdu->header.auth_length = (UINT16)sbuffer->cbBuffer; -- bind_pdu->auth_verifier.auth_value = sbuffer->pvBuffer; -- bind_pdu->header.ptype = PTYPE_BIND; -- bind_pdu->header.pfc_flags = -+ bind_pdu.header = rpc_pdu_header_init(rpc); -+ bind_pdu.header.auth_length = (UINT16)sbuffer->cbBuffer; -+ bind_pdu.auth_verifier.auth_value = sbuffer->pvBuffer; -+ bind_pdu.header.ptype = PTYPE_BIND; -+ bind_pdu.header.pfc_flags = - PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX; -- bind_pdu->header.call_id = 2; -- bind_pdu->max_xmit_frag = rpc->max_xmit_frag; -- bind_pdu->max_recv_frag = rpc->max_recv_frag; -- bind_pdu->assoc_group_id = 0; -- bind_pdu->p_context_elem.n_context_elem = 2; -- bind_pdu->p_context_elem.reserved = 0; -- bind_pdu->p_context_elem.reserved2 = 0; -- bind_pdu->p_context_elem.p_cont_elem = -- calloc(bind_pdu->p_context_elem.n_context_elem, sizeof(p_cont_elem_t)); -- -- if (!bind_pdu->p_context_elem.p_cont_elem) -+ bind_pdu.header.call_id = 2; -+ bind_pdu.max_xmit_frag = rpc->max_xmit_frag; -+ bind_pdu.max_recv_frag = rpc->max_recv_frag; -+ bind_pdu.assoc_group_id = 0; -+ bind_pdu.p_context_elem.n_context_elem = 2; -+ bind_pdu.p_context_elem.reserved = 0; -+ bind_pdu.p_context_elem.reserved2 = 0; -+ bind_pdu.p_context_elem.p_cont_elem = -+ calloc(bind_pdu.p_context_elem.n_context_elem, sizeof(p_cont_elem_t)); -+ -+ if (!bind_pdu.p_context_elem.p_cont_elem) - goto fail; - -- p_cont_elem = &bind_pdu->p_context_elem.p_cont_elem[0]; -+ p_cont_elem = &bind_pdu.p_context_elem.p_cont_elem[0]; - p_cont_elem->p_cont_id = 0; - p_cont_elem->n_transfer_syn = 1; - p_cont_elem->reserved = 0; -@@ -222,7 +234,7 @@ int rpc_send_bind_pdu(rdpRpc* rpc) - - CopyMemory(&(p_cont_elem->transfer_syntaxes[0].if_uuid), &NDR_UUID, sizeof(p_uuid_t)); - p_cont_elem->transfer_syntaxes[0].if_version = NDR_SYNTAX_IF_VERSION; -- p_cont_elem = &bind_pdu->p_context_elem.p_cont_elem[1]; -+ p_cont_elem = &bind_pdu.p_context_elem.p_cont_elem[1]; - p_cont_elem->p_cont_id = 1; - p_cont_elem->n_transfer_syn = 1; - p_cont_elem->reserved = 0; -@@ -236,32 +248,23 @@ int rpc_send_bind_pdu(rdpRpc* rpc) - CopyMemory(&(p_cont_elem->transfer_syntaxes[0].if_uuid), &BTFN_UUID, sizeof(p_uuid_t)); - p_cont_elem->transfer_syntaxes[0].if_version = BTFN_SYNTAX_IF_VERSION; - offset = 116; -- bind_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4); -- bind_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT; -- bind_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; -- bind_pdu->auth_verifier.auth_reserved = 0x00; -- bind_pdu->auth_verifier.auth_context_id = 0x00000000; -- offset += (8 + bind_pdu->header.auth_length); -- bind_pdu->header.frag_length = offset; -- buffer = (BYTE*)malloc(bind_pdu->header.frag_length); -+ -+ bind_pdu.auth_verifier.auth_type = RPC_C_AUTHN_WINNT; -+ bind_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; -+ bind_pdu.auth_verifier.auth_reserved = 0x00; -+ bind_pdu.auth_verifier.auth_context_id = 0x00000000; -+ offset += (8 + bind_pdu.header.auth_length); -+ bind_pdu.header.frag_length = offset; -+ -+ buffer = Stream_New(NULL, bind_pdu.header.frag_length); - - if (!buffer) - goto fail; - -- CopyMemory(buffer, bind_pdu, 24); -- CopyMemory(&buffer[24], &bind_pdu->p_context_elem, 4); -- CopyMemory(&buffer[28], &bind_pdu->p_context_elem.p_cont_elem[0], 24); -- CopyMemory(&buffer[52], bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes, 20); -- CopyMemory(&buffer[72], &bind_pdu->p_context_elem.p_cont_elem[1], 24); -- CopyMemory(&buffer[96], bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes, 20); -- offset = 116; -- rpc_offset_pad(&offset, bind_pdu->auth_verifier.auth_pad_length); -- CopyMemory(&buffer[offset], &bind_pdu->auth_verifier.auth_type, 8); -- CopyMemory(&buffer[offset + 8], bind_pdu->auth_verifier.auth_value, -- bind_pdu->header.auth_length); -- offset += (8 + bind_pdu->header.auth_length); -- length = bind_pdu->header.frag_length; -- clientCall = rpc_client_call_new(bind_pdu->header.call_id, 0); -+ if (!rts_write_pdu_bind(buffer, &bind_pdu)) -+ goto fail; -+ -+ clientCall = rpc_client_call_new(bind_pdu.header.call_id, 0); - - if (!clientCall) - goto fail; -@@ -272,22 +275,19 @@ int rpc_send_bind_pdu(rdpRpc* rpc) - goto fail; - } - -- status = rpc_in_channel_send_pdu(inChannel, buffer, length); -+ Stream_SealLength(buffer); -+ status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer)); - fail: - -- if (bind_pdu) -+ if (bind_pdu.p_context_elem.p_cont_elem) - { -- if (bind_pdu->p_context_elem.p_cont_elem) -- { -- free(bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes); -- free(bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes); -- } -- -- free(bind_pdu->p_context_elem.p_cont_elem); -+ free(bind_pdu.p_context_elem.p_cont_elem[0].transfer_syntaxes); -+ free(bind_pdu.p_context_elem.p_cont_elem[1].transfer_syntaxes); - } - -- free(bind_pdu); -- free(buffer); -+ free(bind_pdu.p_context_elem.p_cont_elem); -+ -+ Stream_Free(buffer, TRUE); - return (status > 0) ? 1 : -1; - } - -@@ -317,31 +317,47 @@ fail: - * example. - */ - --int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) -+BOOL rpc_recv_bind_ack_pdu(rdpRpc* rpc, wStream* s) - { -+ BOOL rc = FALSE; - BOOL continueNeeded = FALSE; -- BYTE* auth_data; -- rpcconn_hdr_t* header; -- header = (rpcconn_hdr_t*)buffer; -+ const BYTE* auth_data; -+ size_t pos, end; -+ rpcconn_hdr_t header = { 0 }; -+ -+ assert(rpc); -+ assert(rpc->ntlm); -+ assert(s); -+ -+ pos = Stream_GetPosition(s); -+ if (!rts_read_pdu_header(s, &header)) -+ goto fail; -+ - WLog_DBG(TAG, "Receiving BindAck PDU"); - -- if (!rpc || !rpc->ntlm) -- return -1; -+ rpc->max_recv_frag = header.bind_ack.max_xmit_frag; -+ rpc->max_xmit_frag = header.bind_ack.max_recv_frag; - -- rpc->max_recv_frag = header->bind_ack.max_xmit_frag; -- rpc->max_xmit_frag = header->bind_ack.max_recv_frag; -- auth_data = buffer + (header->common.frag_length - header->common.auth_length); -+ /* Get the correct offset in the input data and pass that on as input buffer. -+ * rts_read_pdu_header did already do consistency checks */ -+ end = Stream_GetPosition(s); -+ Stream_SetPosition(s, pos + header.common.frag_length - header.common.auth_length); -+ auth_data = Stream_Pointer(s); -+ Stream_SetPosition(s, end); - -- if (!ntlm_client_set_input_buffer(rpc->ntlm, TRUE, auth_data, header->common.auth_length)) -- return -1; -+ if (!ntlm_client_set_input_buffer(rpc->ntlm, TRUE, auth_data, header.common.auth_length)) -+ goto fail; - - if (!ntlm_authenticate(rpc->ntlm, &continueNeeded)) -- return -1; -+ goto fail; - - if (continueNeeded) -- return -1; -+ goto fail; - -- return (int)length; -+ rc = TRUE; -+fail: -+ rts_free_pdu_header(&header, FALSE); -+ return rc; - } - - /** -@@ -354,68 +370,63 @@ int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) - int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc) - { - int status = -1; -- BYTE* buffer; -- UINT32 offset; -- UINT32 length; -+ wStream* buffer; -+ size_t offset; - const SecBuffer* sbuffer; - RpcClientCall* clientCall; -- rpcconn_rpc_auth_3_hdr_t* auth_3_pdu; -- RpcVirtualConnection* connection = rpc->VirtualConnection; -- RpcInChannel* inChannel = connection->DefaultInChannel; -- WLog_DBG(TAG, "Sending RpcAuth3 PDU"); -- auth_3_pdu = (rpcconn_rpc_auth_3_hdr_t*)calloc(1, sizeof(rpcconn_rpc_auth_3_hdr_t)); -+ rpcconn_rpc_auth_3_hdr_t auth_3_pdu = { 0 }; -+ RpcVirtualConnection* connection; -+ RpcInChannel* inChannel; - -- if (!auth_3_pdu) -- return -1; -+ assert(rpc); -+ -+ connection = rpc->VirtualConnection; -+ assert(connection); -+ -+ inChannel = connection->DefaultInChannel; -+ assert(inChannel); -+ -+ WLog_DBG(TAG, "Sending RpcAuth3 PDU"); - - sbuffer = ntlm_client_get_output_buffer(rpc->ntlm); - - if (!sbuffer) -- { -- free(auth_3_pdu); - return -1; -- } - -- rpc_pdu_header_init(rpc, &auth_3_pdu->header); -- auth_3_pdu->header.auth_length = (UINT16)sbuffer->cbBuffer; -- auth_3_pdu->auth_verifier.auth_value = sbuffer->pvBuffer; -- auth_3_pdu->header.ptype = PTYPE_RPC_AUTH_3; -- auth_3_pdu->header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX; -- auth_3_pdu->header.call_id = 2; -- auth_3_pdu->max_xmit_frag = rpc->max_xmit_frag; -- auth_3_pdu->max_recv_frag = rpc->max_recv_frag; -+ auth_3_pdu.header = rpc_pdu_header_init(rpc); -+ auth_3_pdu.header.auth_length = (UINT16)sbuffer->cbBuffer; -+ auth_3_pdu.auth_verifier.auth_value = sbuffer->pvBuffer; -+ auth_3_pdu.header.ptype = PTYPE_RPC_AUTH_3; -+ auth_3_pdu.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX; -+ auth_3_pdu.header.call_id = 2; -+ auth_3_pdu.max_xmit_frag = rpc->max_xmit_frag; -+ auth_3_pdu.max_recv_frag = rpc->max_recv_frag; - offset = 20; -- auth_3_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4); -- auth_3_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT; -- auth_3_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; -- auth_3_pdu->auth_verifier.auth_reserved = 0x00; -- auth_3_pdu->auth_verifier.auth_context_id = 0x00000000; -- offset += (8 + auth_3_pdu->header.auth_length); -- auth_3_pdu->header.frag_length = offset; -- buffer = (BYTE*)malloc(auth_3_pdu->header.frag_length); -+ auth_3_pdu.auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4); -+ auth_3_pdu.auth_verifier.auth_type = RPC_C_AUTHN_WINNT; -+ auth_3_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; -+ auth_3_pdu.auth_verifier.auth_reserved = 0x00; -+ auth_3_pdu.auth_verifier.auth_context_id = 0x00000000; -+ offset += (8 + auth_3_pdu.header.auth_length); -+ auth_3_pdu.header.frag_length = offset; -+ -+ buffer = Stream_New(NULL, auth_3_pdu.header.frag_length); - - if (!buffer) -- { -- free(auth_3_pdu); - return -1; -- } - -- CopyMemory(buffer, auth_3_pdu, 20); -- offset = 20; -- rpc_offset_pad(&offset, auth_3_pdu->auth_verifier.auth_pad_length); -- CopyMemory(&buffer[offset], &auth_3_pdu->auth_verifier.auth_type, 8); -- CopyMemory(&buffer[offset + 8], auth_3_pdu->auth_verifier.auth_value, -- auth_3_pdu->header.auth_length); -- offset += (8 + auth_3_pdu->header.auth_length); -- length = auth_3_pdu->header.frag_length; -- clientCall = rpc_client_call_new(auth_3_pdu->header.call_id, 0); -+ if (!rts_write_pdu_auth3(buffer, &auth_3_pdu)) -+ goto fail; -+ -+ clientCall = rpc_client_call_new(auth_3_pdu.header.call_id, 0); - - if (ArrayList_Add(rpc->client->ClientCallList, clientCall) >= 0) - { -- status = rpc_in_channel_send_pdu(inChannel, buffer, length); -+ Stream_SealLength(buffer); -+ status = rpc_in_channel_send_pdu(inChannel, Stream_Buffer(buffer), Stream_Length(buffer)); - } - -- free(auth_3_pdu); -- free(buffer); -+fail: -+ Stream_Free(buffer, TRUE); - return (status > 0) ? 1 : -1; - } -diff --git a/libfreerdp/core/gateway/rpc_bind.h b/libfreerdp/core/gateway/rpc_bind.h -index 759555f..69758e5 100644 ---- a/libfreerdp/core/gateway/rpc_bind.h -+++ b/libfreerdp/core/gateway/rpc_bind.h -@@ -35,7 +35,7 @@ FREERDP_LOCAL extern const p_uuid_t BTFN_UUID; - #define BTFN_SYNTAX_IF_VERSION 0x00000001 - - FREERDP_LOCAL int rpc_send_bind_pdu(rdpRpc* rpc); --FREERDP_LOCAL int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length); -+FREERDP_LOCAL BOOL rpc_recv_bind_ack_pdu(rdpRpc* rpc, wStream* s); - FREERDP_LOCAL int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc); - - #endif /* FREERDP_LIB_CORE_GATEWAY_RPC_BIND_H */ -diff --git a/libfreerdp/core/gateway/rpc_fault.c b/libfreerdp/core/gateway/rpc_fault.c -index 7259f04..c4cb086 100644 ---- a/libfreerdp/core/gateway/rpc_fault.c -+++ b/libfreerdp/core/gateway/rpc_fault.c -@@ -133,10 +133,7 @@ static const RPC_FAULT_CODE RPC_FAULT_CODES[] = { - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - RPC_S_INVALID_OBJECT, -- CAT_GATEWAY){ -- 0, -- NULL, -- NULL } -+ CAT_GATEWAY) - }; - - static const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] = { -@@ -222,9 +219,7 @@ static const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] = { - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE( - RPC_S_CALL_CANCELLED), -- CAT_GATEWAY){ -- 0, NULL, -- NULL } -+ CAT_GATEWAY) - }; - - /** -@@ -377,22 +372,22 @@ const char* rpc_error_to_string(UINT32 code) - size_t index; - static char buffer[1024]; - -- for (index = 0; RPC_FAULT_CODES[index].name != NULL; index++) -+ for (index = 0; index < ARRAYSIZE(RPC_FAULT_CODES); index++) - { -- if (RPC_FAULT_CODES[index].code == code) -+ const RPC_FAULT_CODE* const current = &RPC_FAULT_CODES[index]; -+ if (current->code == code) - { -- sprintf_s(buffer, ARRAYSIZE(buffer), "%s [0x%08" PRIX32 "]", -- RPC_FAULT_CODES[index].name, code); -+ sprintf_s(buffer, ARRAYSIZE(buffer), "%s", current->name); - goto out; - } - } - -- for (index = 0; RPC_TSG_FAULT_CODES[index].name != NULL; index++) -+ for (index = 0; index < ARRAYSIZE(RPC_TSG_FAULT_CODES); index++) - { -- if (RPC_TSG_FAULT_CODES[index].code == code) -+ const RPC_FAULT_CODE* const current = &RPC_TSG_FAULT_CODES[index]; -+ if (current->code == code) - { -- sprintf_s(buffer, ARRAYSIZE(buffer), "%s [0x%08" PRIX32 "]", -- RPC_TSG_FAULT_CODES[index].name, code); -+ sprintf_s(buffer, ARRAYSIZE(buffer), "%s", current->name); - goto out; - } - } -@@ -406,16 +401,18 @@ const char* rpc_error_to_category(UINT32 code) - { - size_t index; - -- for (index = 0; RPC_FAULT_CODES[index].category != NULL; index++) -+ for (index = 0; index < ARRAYSIZE(RPC_FAULT_CODES); index++) - { -- if (RPC_FAULT_CODES[index].code == code) -- return RPC_FAULT_CODES[index].category; -+ const RPC_FAULT_CODE* const current = &RPC_FAULT_CODES[index]; -+ if (current->code == code) -+ return current->category; - } - -- for (index = 0; RPC_TSG_FAULT_CODES[index].category != NULL; index++) -+ for (index = 0; index < ARRAYSIZE(RPC_TSG_FAULT_CODES); index++) - { -- if (RPC_TSG_FAULT_CODES[index].code == code) -- return RPC_TSG_FAULT_CODES[index].category; -+ const RPC_FAULT_CODE* const current = &RPC_TSG_FAULT_CODES[index]; -+ if (current->code == code) -+ return current->category; - } - - return "UNKNOWN"; -diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c -index d4432cb..50ec8e5 100644 ---- a/libfreerdp/core/gateway/rpc_client.c -+++ b/libfreerdp/core/gateway/rpc_client.c -@@ -24,6 +24,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -35,6 +36,8 @@ - #include "rpc_bind.h" - #include "rpc_fault.h" - #include "rpc_client.h" -+#include "rts_signature.h" -+ - #include "../rdp.h" - #include "../proxy.h" - -@@ -99,7 +102,7 @@ static int rpc_client_receive_pipe_write(RpcClient* client, const BYTE* buffer, - int rpc_client_receive_pipe_read(RpcClient* client, BYTE* buffer, size_t length) - { - int index = 0; -- int status = 0; -+ size_t status = 0; - int nchunks = 0; - DataChunk chunks[2]; - -@@ -122,7 +125,10 @@ int rpc_client_receive_pipe_read(RpcClient* client, BYTE* buffer, size_t length) - ResetEvent(client->PipeEvent); - - LeaveCriticalSection(&(client->PipeLock)); -- return status; -+ -+ if (status > INT_MAX) -+ return -1; -+ return (int)status; - } - - static int rpc_client_transition_to_state(rdpRpc* rpc, RPC_CLIENT_STATE state) -@@ -173,8 +179,15 @@ static int rpc_client_transition_to_state(rdpRpc* rpc, RPC_CLIENT_STATE state) - static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu) - { - int status = -1; -- rpcconn_rts_hdr_t* rts; -- rdpTsg* tsg = rpc->transport->tsg; -+ rdpTsg* tsg; -+ -+ assert(rpc); -+ assert(pdu); -+ -+ Stream_SealLength(pdu->s); -+ Stream_SetPosition(pdu->s, 0); -+ -+ tsg = rpc->transport->tsg; - - if (rpc->VirtualConnection->State < VIRTUAL_CONNECTION_STATE_OPENED) - { -@@ -187,17 +200,13 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu) - break; - - case VIRTUAL_CONNECTION_STATE_WAIT_A3W: -- rts = (rpcconn_rts_hdr_t*)Stream_Buffer(pdu->s); -- -- if (!rts_match_pdu_signature(&RTS_PDU_CONN_A3_SIGNATURE, rts)) -+ if (!rts_match_pdu_signature(&RTS_PDU_CONN_A3_SIGNATURE, pdu->s, NULL)) - { - WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/A3"); - return -1; - } - -- status = rts_recv_CONN_A3_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s)); -- -- if (status < 0) -+ if (!rts_recv_CONN_A3_pdu(rpc, pdu->s)) - { - WLog_ERR(TAG, "rts_recv_CONN_A3_pdu failure"); - return -1; -@@ -209,17 +218,13 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu) - break; - - case VIRTUAL_CONNECTION_STATE_WAIT_C2: -- rts = (rpcconn_rts_hdr_t*)Stream_Buffer(pdu->s); -- -- if (!rts_match_pdu_signature(&RTS_PDU_CONN_C2_SIGNATURE, rts)) -+ if (!rts_match_pdu_signature(&RTS_PDU_CONN_C2_SIGNATURE, pdu->s, NULL)) - { - WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/C2"); - return -1; - } - -- status = rts_recv_CONN_C2_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s)); -- -- if (status < 0) -+ if (!rts_recv_CONN_C2_pdu(rpc, pdu->s)) - { - WLog_ERR(TAG, "rts_recv_CONN_C2_pdu failure"); - return -1; -@@ -252,7 +257,7 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu) - { - if (pdu->Type == PTYPE_BIND_ACK) - { -- if (rpc_recv_bind_ack_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s)) <= 0) -+ if (!rpc_recv_bind_ack_pdu(rpc, pdu->s)) - { - WLog_ERR(TAG, "rpc_recv_bind_ack_pdu failure"); - return -1; -@@ -301,89 +306,117 @@ static int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu) - - static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment) - { -- BYTE* buffer; -+ int rc = -1; - RPC_PDU* pdu; -- UINT32 StubOffset; -- UINT32 StubLength; -+ size_t StubOffset; -+ size_t StubLength; - RpcClientCall* call; -- rpcconn_hdr_t* header; -+ rpcconn_hdr_t header = { 0 }; -+ -+ assert(rpc); -+ assert(rpc->client); -+ assert(fragment); -+ - pdu = rpc->client->pdu; -- buffer = (BYTE*)Stream_Buffer(fragment); -- header = (rpcconn_hdr_t*)Stream_Buffer(fragment); -+ assert(pdu); -+ -+ Stream_SealLength(fragment); -+ Stream_SetPosition(fragment, 0); -+ -+ if (!rts_read_pdu_header(fragment, &header)) -+ goto fail; - -- if (header->common.ptype == PTYPE_RESPONSE) -+ if (header.common.ptype == PTYPE_RESPONSE) - { -- rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length; -+ rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header.common.frag_length; - rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= -- header->common.frag_length; -+ header.common.frag_length; - - if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < - (rpc->ReceiveWindow / 2)) - { -- if (rts_send_flow_control_ack_pdu(rpc) < 0) -- return -1; -+ if (!rts_send_flow_control_ack_pdu(rpc)) -+ goto fail; - } - -- if (!rpc_get_stub_data_info(rpc, buffer, &StubOffset, &StubLength)) -+ if (!rpc_get_stub_data_info(&header, &StubOffset, &StubLength)) - { - WLog_ERR(TAG, "expected stub"); -- return -1; -+ goto fail; - } - - if (StubLength == 4) - { -- if ((header->common.call_id == rpc->PipeCallId) && -- (header->common.pfc_flags & PFC_LAST_FRAG)) -+ if ((header.common.call_id == rpc->PipeCallId) && -+ (header.common.pfc_flags & PFC_LAST_FRAG)) - { - /* End of TsProxySetupReceivePipe */ - TerminateEventArgs e; -- rpc->result = *((UINT32*)&buffer[StubOffset]); -- freerdp_abort_connect(rpc->context->instance); -- tsg_set_state(rpc->transport->tsg, TSG_STATE_TUNNEL_CLOSE_PENDING); -+ rdpContext* context = rpc->transport->context; -+ rdpTsg* tsg = rpc->transport->tsg; -+ -+ assert(context); -+ -+ if (Stream_Length(fragment) < StubOffset + 4) -+ goto fail; -+ Stream_SetPosition(fragment, StubOffset); -+ Stream_Read_UINT32(fragment, rpc->result); -+ -+ freerdp_abort_connect(context->instance); -+ tsg_set_state(tsg, TSG_STATE_TUNNEL_CLOSE_PENDING); - EventArgsInit(&e, "freerdp"); - e.code = 0; -- PubSub_OnTerminate(rpc->context->pubSub, rpc->context, &e); -- return 0; -+ PubSub_OnTerminate(context->pubSub, context, &e); -+ rc = 0; -+ goto success; - } - -- if (header->common.call_id != rpc->PipeCallId) -+ if (header.common.call_id != rpc->PipeCallId) - { - /* Ignoring non-TsProxySetupReceivePipe Response */ -- return 0; -+ rc = 0; -+ goto success; - } - } - - if (rpc->StubFragCount == 0) -- rpc->StubCallId = header->common.call_id; -+ rpc->StubCallId = header.common.call_id; - -- if (rpc->StubCallId != header->common.call_id) -+ if (rpc->StubCallId != header.common.call_id) - { - WLog_ERR(TAG, - "invalid call_id: actual: %" PRIu32 ", expected: %" PRIu32 - ", frag_count: %" PRIu32 "", -- rpc->StubCallId, header->common.call_id, rpc->StubFragCount); -+ rpc->StubCallId, header.common.call_id, rpc->StubFragCount); - } - - call = rpc_client_call_find_by_id(rpc->client, rpc->StubCallId); - - if (!call) -- return -1; -+ goto fail; - - if (call->OpNum != TsProxySetupReceivePipeOpnum) - { -- if (!Stream_EnsureCapacity(pdu->s, header->response.alloc_hint)) -- return -1; -+ const rpcconn_response_hdr_t* response = -+ (const rpcconn_response_hdr_t*)&header.response; -+ if (!Stream_EnsureCapacity(pdu->s, response->alloc_hint)) -+ goto fail; -+ -+ if (Stream_Length(fragment) < StubOffset + StubLength) -+ goto fail; - -- Stream_Write(pdu->s, &buffer[StubOffset], StubLength); -+ Stream_SetPosition(fragment, StubOffset); -+ Stream_Write(pdu->s, Stream_Pointer(fragment), StubLength); - rpc->StubFragCount++; - -- if (header->response.alloc_hint == StubLength) -+ if (response->alloc_hint == StubLength) - { - pdu->Flags = RPC_PDU_FLAG_STUB; - pdu->Type = PTYPE_RESPONSE; - pdu->CallId = rpc->StubCallId; -- Stream_SealLength(pdu->s); -- rpc_client_recv_pdu(rpc, pdu); -+ -+ if (rpc_client_recv_pdu(rpc, pdu) < 0) -+ goto fail; - rpc_pdu_reset(pdu); - rpc->StubFragCount = 0; - rpc->StubCallId = 0; -@@ -391,75 +424,84 @@ static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment) - } - else - { -- rpc_client_receive_pipe_write(rpc->client, &buffer[StubOffset], (size_t)StubLength); -+ const rpcconn_response_hdr_t* response = &header.response; -+ if (Stream_Length(fragment) < StubOffset + StubLength) -+ goto fail; -+ Stream_SetPosition(fragment, StubOffset); -+ rpc_client_receive_pipe_write(rpc->client, Stream_Pointer(fragment), -+ (size_t)StubLength); - rpc->StubFragCount++; - -- if (header->response.alloc_hint == StubLength) -+ if (response->alloc_hint == StubLength) - { - rpc->StubFragCount = 0; - rpc->StubCallId = 0; - } - } - -- return 1; -+ goto success; - } -- else if (header->common.ptype == PTYPE_RTS) -+ else if (header.common.ptype == PTYPE_RTS) - { - if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED) - { - pdu->Flags = 0; -- pdu->Type = header->common.ptype; -- pdu->CallId = header->common.call_id; -+ pdu->Type = header.common.ptype; -+ pdu->CallId = header.common.call_id; - - if (!Stream_EnsureCapacity(pdu->s, Stream_Length(fragment))) -- return -1; -+ goto fail; - -- Stream_Write(pdu->s, buffer, Stream_Length(fragment)); -- Stream_SealLength(pdu->s); -+ Stream_Write(pdu->s, Stream_Buffer(fragment), Stream_Length(fragment)); - - if (rpc_client_recv_pdu(rpc, pdu) < 0) -- return -1; -+ goto fail; - - rpc_pdu_reset(pdu); - } - else - { -- if (rts_recv_out_of_sequence_pdu(rpc, buffer, header->common.frag_length) < 0) -- return -1; -+ if (!rts_recv_out_of_sequence_pdu(rpc, fragment, &header)) -+ goto fail; - } - -- return 1; -+ goto success; - } -- else if (header->common.ptype == PTYPE_BIND_ACK) -+ else if (header.common.ptype == PTYPE_BIND_ACK) - { - pdu->Flags = 0; -- pdu->Type = header->common.ptype; -- pdu->CallId = header->common.call_id; -+ pdu->Type = header.common.ptype; -+ pdu->CallId = header.common.call_id; - - if (!Stream_EnsureCapacity(pdu->s, Stream_Length(fragment))) -- return -1; -+ goto fail; - -- Stream_Write(pdu->s, buffer, Stream_Length(fragment)); -- Stream_SealLength(pdu->s); -+ Stream_Write(pdu->s, Stream_Buffer(fragment), Stream_Length(fragment)); - - if (rpc_client_recv_pdu(rpc, pdu) < 0) -- return -1; -+ goto fail; - - rpc_pdu_reset(pdu); -- return 1; -+ goto success; - } -- else if (header->common.ptype == PTYPE_FAULT) -+ else if (header.common.ptype == PTYPE_FAULT) - { -- rpc_recv_fault_pdu(header->fault.status); -- return -1; -+ const rpcconn_fault_hdr_t* fault = (const rpcconn_fault_hdr_t*)&header.fault; -+ rpc_recv_fault_pdu(fault->status); -+ goto fail; - } - else - { -- WLog_ERR(TAG, "unexpected RPC PDU type 0x%02" PRIX8 "", header->common.ptype); -- return -1; -+ WLog_ERR(TAG, "unexpected RPC PDU type 0x%02" PRIX8 "", header.common.ptype); -+ goto fail; - } - -- return 1; -+success: -+ rc = (rc < 0) ? 1 : 0; /* In case of default error return change to 1, otherwise we already set -+ the return code */ -+fail: -+ rts_free_pdu_header(&header, FALSE); -+ return rc; - } - - static int rpc_client_default_out_channel_recv(rdpRpc* rpc) -@@ -509,7 +551,7 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc) - - /* Send CONN/A1 PDU over OUT channel */ - -- if (rts_send_CONN_A1_pdu(rpc) < 0) -+ if (!rts_send_CONN_A1_pdu(rpc)) - { - http_response_free(response); - WLog_ERR(TAG, "rpc_send_CONN_A1_pdu error!"); -@@ -549,7 +591,8 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc) - - if (statusCode == HTTP_STATUS_DENIED) - { -- freerdp_set_last_error_if_not(rpc->context, FREERDP_ERROR_AUTHENTICATION_FAILED); -+ rdpContext* context = rpc->context; -+ freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED); - } - - http_response_free(response); -@@ -563,12 +606,13 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc) - } - else - { -- wStream* fragment; -- rpcconn_common_hdr_t* header; -- fragment = rpc->client->ReceiveFragment; -+ wStream* fragment = rpc->client->ReceiveFragment; - - while (1) - { -+ size_t pos; -+ rpcconn_common_hdr_t header = { 0 }; -+ - while (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH) - { - status = rpc_channel_read(&outChannel->common, fragment, -@@ -581,22 +625,27 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc) - return 0; - } - -- header = (rpcconn_common_hdr_t*)Stream_Buffer(fragment); -+ pos = Stream_GetPosition(fragment); -+ Stream_SetPosition(fragment, 0); -+ -+ /* Ignore errors, the PDU might not be complete. */ -+ rts_read_common_pdu_header(fragment, &header); -+ Stream_SetPosition(fragment, pos); - -- if (header->frag_length > rpc->max_recv_frag) -+ if (header.frag_length > rpc->max_recv_frag) - { - WLog_ERR(TAG, - "rpc_client_recv: invalid fragment size: %" PRIu16 " (max: %" PRIu16 ")", -- header->frag_length, rpc->max_recv_frag); -+ header.frag_length, rpc->max_recv_frag); - winpr_HexDump(TAG, WLOG_ERROR, Stream_Buffer(fragment), - Stream_GetPosition(fragment)); - return -1; - } - -- while (Stream_GetPosition(fragment) < header->frag_length) -+ while (Stream_GetPosition(fragment) < header.frag_length) - { - status = rpc_channel_read(&outChannel->common, fragment, -- header->frag_length - Stream_GetPosition(fragment)); -+ header.frag_length - Stream_GetPosition(fragment)); - - if (status < 0) - { -@@ -604,14 +653,12 @@ static int rpc_client_default_out_channel_recv(rdpRpc* rpc) - return -1; - } - -- if (Stream_GetPosition(fragment) < header->frag_length) -+ if (Stream_GetPosition(fragment) < header.frag_length) - return 0; - } - - { - /* complete fragment received */ -- Stream_SealLength(fragment); -- Stream_SetPosition(fragment, 0); - status = rpc_client_recv_fragment(rpc, fragment); - - if (status < 0) -@@ -663,10 +710,10 @@ static int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc) - if (rpc_ncacn_http_send_out_channel_request(&nextOutChannel->common, TRUE)) - { - rpc_ncacn_http_ntlm_uninit(&nextOutChannel->common); -- status = rts_send_OUT_R1_A3_pdu(rpc); - -- if (status >= 0) -+ if (rts_send_OUT_R1_A3_pdu(rpc)) - { -+ status = 1; - rpc_out_channel_transition_to_state( - nextOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED_A6W); - } -@@ -687,11 +734,14 @@ static int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc) - - break; - -+ case CLIENT_OUT_CHANNEL_STATE_INITIAL: -+ case CLIENT_OUT_CHANNEL_STATE_CONNECTED: -+ case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED: - default: - WLog_ERR(TAG, - "rpc_client_nondefault_out_channel_recv: Unexpected message %08" PRIx32, - nextOutChannel->State); -- return -1; -+ status = -1; - } - - http_response_free(response); -@@ -769,7 +819,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc) - - /* Send CONN/B1 PDU over IN channel */ - -- if (rts_send_CONN_B1_pdu(rpc) < 0) -+ if (!rts_send_CONN_B1_pdu(rpc)) - { - WLog_ERR(TAG, "rpc_send_CONN_B1_pdu error!"); - http_response_free(response); -@@ -810,8 +860,8 @@ int rpc_client_in_channel_recv(rdpRpc* rpc) - - RpcClientCall* rpc_client_call_find_by_id(RpcClient* client, UINT32 CallId) - { -- int index; -- int count; -+ size_t index; -+ size_t count; - RpcClientCall* clientCall = NULL; - - if (!client) -@@ -856,18 +906,23 @@ static void rpc_array_client_call_free(void* call) - rpc_client_call_free((RpcClientCall*)call); - } - --int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length) -+int rpc_in_channel_send_pdu(RpcInChannel* inChannel, const BYTE* buffer, size_t length) - { -- int status; -+ SSIZE_T status; - RpcClientCall* clientCall; -- rpcconn_common_hdr_t* header; -+ wStream s; -+ rpcconn_common_hdr_t header = { 0 }; -+ - status = rpc_channel_write(&inChannel->common, buffer, length); - - if (status <= 0) - return -1; - -- header = (rpcconn_common_hdr_t*)buffer; -- clientCall = rpc_client_call_find_by_id(inChannel->common.client, header->call_id); -+ Stream_StaticInit(&s, buffer, length); -+ if (!rts_read_common_pdu_header(&s, &header)) -+ return -1; -+ -+ clientCall = rpc_client_call_find_by_id(inChannel->common.client, header.call_id); - clientCall->State = RPC_CLIENT_CALL_STATE_DISPATCHED; - - /* -@@ -877,7 +932,7 @@ int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length - * variables specified by this abstract data model. - */ - -- if (header->ptype == PTYPE_REQUEST) -+ if (header.ptype == PTYPE_REQUEST) - { - inChannel->BytesSent += status; - inChannel->SenderAvailableWindow -= status; -@@ -888,7 +943,7 @@ int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length - - BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum) - { -- UINT32 offset; -+ size_t offset; - BYTE* buffer = NULL; - UINT32 stub_data_pad; - SecBuffer Buffers[2] = { 0 }; -@@ -936,7 +991,7 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum) - if (size < 0) - goto fail; - -- rpc_pdu_header_init(rpc, &request_pdu.header); -+ request_pdu.header = rpc_pdu_header_init(rpc); - request_pdu.header.ptype = PTYPE_REQUEST; - request_pdu.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; - request_pdu.header.auth_length = (UINT16)size; -@@ -1025,7 +1080,7 @@ static BOOL rpc_client_resolve_gateway(rdpSettings* settings, char** host, UINT1 - const char* peerHostname = settings->GatewayHostname; - const char* proxyUsername = settings->ProxyUsername; - const char* proxyPassword = settings->ProxyPassword; -- *port = settings->GatewayPort; -+ *port = (UINT16)settings->GatewayPort; - *isProxy = proxy_prepare(settings, &peerHostname, port, &proxyUsername, &proxyPassword); - result = freerdp_tcp_resolve_host(peerHostname, *port, 0); - -diff --git a/libfreerdp/core/gateway/rpc_client.h b/libfreerdp/core/gateway/rpc_client.h -index af0b8ce..7b509de 100644 ---- a/libfreerdp/core/gateway/rpc_client.h -+++ b/libfreerdp/core/gateway/rpc_client.h -@@ -31,7 +31,8 @@ FREERDP_LOCAL RpcClientCall* rpc_client_call_find_by_id(RpcClient* client, UINT3 - FREERDP_LOCAL RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum); - FREERDP_LOCAL void rpc_client_call_free(RpcClientCall* client_call); - --FREERDP_LOCAL int rpc_in_channel_send_pdu(RpcInChannel* inChannel, BYTE* buffer, UINT32 length); -+FREERDP_LOCAL int rpc_in_channel_send_pdu(RpcInChannel* inChannel, const BYTE* buffer, -+ size_t length); - - FREERDP_LOCAL int rpc_client_in_channel_recv(rdpRpc* rpc); - FREERDP_LOCAL int rpc_client_out_channel_recv(rdpRpc* rpc); -diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c -index c003b1e..ccbe0be 100644 ---- a/libfreerdp/core/gateway/rts.c -+++ b/libfreerdp/core/gateway/rts.c -@@ -21,6 +21,7 @@ - #include "config.h" - #endif - -+#include - #include - #include - #include -@@ -29,6 +30,7 @@ - - #include "ncacn_http.h" - #include "rpc_client.h" -+#include "rts_signature.h" - - #include "rts.h" - -@@ -67,545 +69,1643 @@ - * - */ - -+static const char* rts_pdu_ptype_to_string(UINT32 ptype) -+{ -+ switch (ptype) -+ { -+ case PTYPE_REQUEST: -+ return "PTYPE_REQUEST"; -+ case PTYPE_PING: -+ return "PTYPE_PING"; -+ case PTYPE_RESPONSE: -+ return "PTYPE_RESPONSE"; -+ case PTYPE_FAULT: -+ return "PTYPE_FAULT"; -+ case PTYPE_WORKING: -+ return "PTYPE_WORKING"; -+ case PTYPE_NOCALL: -+ return "PTYPE_NOCALL"; -+ case PTYPE_REJECT: -+ return "PTYPE_REJECT"; -+ case PTYPE_ACK: -+ return "PTYPE_ACK"; -+ case PTYPE_CL_CANCEL: -+ return "PTYPE_CL_CANCEL"; -+ case PTYPE_FACK: -+ return "PTYPE_FACK"; -+ case PTYPE_CANCEL_ACK: -+ return "PTYPE_CANCEL_ACK"; -+ case PTYPE_BIND: -+ return "PTYPE_BIND"; -+ case PTYPE_BIND_ACK: -+ return "PTYPE_BIND_ACK"; -+ case PTYPE_BIND_NAK: -+ return "PTYPE_BIND_NAK"; -+ case PTYPE_ALTER_CONTEXT: -+ return "PTYPE_ALTER_CONTEXT"; -+ case PTYPE_ALTER_CONTEXT_RESP: -+ return "PTYPE_ALTER_CONTEXT_RESP"; -+ case PTYPE_RPC_AUTH_3: -+ return "PTYPE_RPC_AUTH_3"; -+ case PTYPE_SHUTDOWN: -+ return "PTYPE_SHUTDOWN"; -+ case PTYPE_CO_CANCEL: -+ return "PTYPE_CO_CANCEL"; -+ case PTYPE_ORPHANED: -+ return "PTYPE_ORPHANED"; -+ case PTYPE_RTS: -+ return "PTYPE_RTS"; -+ default: -+ return "UNKNOWN"; -+ } -+} - static rpcconn_rts_hdr_t rts_pdu_header_init(void) - { -- rpcconn_rts_hdr_t header = { 0 }; -- header.header.rpc_vers = 5; -- header.header.rpc_vers_minor = 0; -- header.header.ptype = PTYPE_RTS; -- header.header.packed_drep[0] = 0x10; -- header.header.packed_drep[1] = 0x00; -- header.header.packed_drep[2] = 0x00; -- header.header.packed_drep[3] = 0x00; -- header.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; -- header.header.auth_length = 0; -- header.header.call_id = 0; -+ rpcconn_rts_hdr_t header = { 0 }; -+ header.header.rpc_vers = 5; -+ header.header.rpc_vers_minor = 0; -+ header.header.ptype = PTYPE_RTS; -+ header.header.packed_drep[0] = 0x10; -+ header.header.packed_drep[1] = 0x00; -+ header.header.packed_drep[2] = 0x00; -+ header.header.packed_drep[3] = 0x00; -+ header.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; -+ header.header.auth_length = 0; -+ header.header.call_id = 0; -+ -+ return header; -+} -+ -+static BOOL rts_align_stream(wStream* s, size_t alignment) -+{ -+ size_t pos, pad; -+ -+ assert(s); -+ assert(alignment > 0); -+ -+ pos = Stream_GetPosition(s); -+ pad = rpc_offset_align(&pos, alignment); -+ return Stream_SafeSeek(s, pad); -+} -+ -+static char* sdup(const void* src, size_t length) -+{ -+ char* dst; -+ assert(src || (length == 0)); -+ if (length == 0) -+ return NULL; -+ -+ dst = calloc(length + 1, sizeof(char)); -+ if (!dst) -+ return NULL; -+ memcpy(dst, src, length); -+ return dst; -+} -+ -+static BOOL rts_write_common_pdu_header(wStream* s, const rpcconn_common_hdr_t* header) -+{ -+ assert(s); -+ assert(header); -+ if (!Stream_EnsureRemainingCapacity(s, sizeof(rpcconn_common_hdr_t))) -+ return FALSE; -+ -+ Stream_Write_UINT8(s, header->rpc_vers); -+ Stream_Write_UINT8(s, header->rpc_vers_minor); -+ Stream_Write_UINT8(s, header->ptype); -+ Stream_Write_UINT8(s, header->pfc_flags); -+ Stream_Write(s, header->packed_drep, ARRAYSIZE(header->packed_drep)); -+ Stream_Write_UINT16(s, header->frag_length); -+ Stream_Write_UINT16(s, header->auth_length); -+ Stream_Write_UINT32(s, header->call_id); -+ return TRUE; -+} -+ -+BOOL rts_read_common_pdu_header(wStream* s, rpcconn_common_hdr_t* header) -+{ -+ size_t left; -+ assert(s); -+ assert(header); -+ -+ if (Stream_GetRemainingLength(s) < sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ -+ Stream_Read_UINT8(s, header->rpc_vers); -+ Stream_Read_UINT8(s, header->rpc_vers_minor); -+ Stream_Read_UINT8(s, header->ptype); -+ Stream_Read_UINT8(s, header->pfc_flags); -+ Stream_Read(s, header->packed_drep, ARRAYSIZE(header->packed_drep)); -+ Stream_Read_UINT16(s, header->frag_length); -+ Stream_Read_UINT16(s, header->auth_length); -+ Stream_Read_UINT32(s, header->call_id); -+ -+ if (header->frag_length < sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ -+ left = Stream_GetRemainingLength(s); -+ if (left < header->frag_length - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+static BOOL rts_read_auth_verifier_no_checks(wStream* s, auth_verifier_co_t* auth, -+ const rpcconn_common_hdr_t* header, size_t* startPos) -+{ -+ assert(s); -+ assert(auth); -+ assert(header); -+ -+ assert(header->frag_length > header->auth_length); -+ -+ if (startPos) -+ *startPos = Stream_GetPosition(s); -+ -+ /* Read the auth verifier and check padding matches frag_length */ -+ { -+ const size_t expected = header->frag_length - header->auth_length - 8; -+ -+ Stream_SetPosition(s, expected); -+ if (Stream_GetRemainingLength(s) < sizeof(auth_verifier_co_t)) -+ return FALSE; -+ -+ Stream_Read_UINT8(s, auth->auth_type); -+ Stream_Read_UINT8(s, auth->auth_level); -+ Stream_Read_UINT8(s, auth->auth_pad_length); -+ Stream_Read_UINT8(s, auth->auth_reserved); -+ Stream_Read_UINT32(s, auth->auth_context_id); -+ } -+ -+ if (header->auth_length != 0) -+ { -+ const void* ptr = Stream_Pointer(s); -+ if (!Stream_SafeSeek(s, header->auth_length)) -+ return FALSE; -+ auth->auth_value = (BYTE*)sdup(ptr, header->auth_length); -+ if (auth->auth_value == NULL) -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static BOOL rts_read_auth_verifier(wStream* s, auth_verifier_co_t* auth, -+ const rpcconn_common_hdr_t* header) -+{ -+ size_t pos; -+ assert(s); -+ assert(auth); -+ assert(header); -+ -+ if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos)) -+ return FALSE; -+ -+ { -+ const size_t expected = header->frag_length - header->auth_length - 8; -+ assert(pos + auth->auth_pad_length == expected); -+ } -+ -+ return TRUE; -+} -+ -+static BOOL rts_read_auth_verifier_with_stub(wStream* s, auth_verifier_co_t* auth, -+ rpcconn_common_hdr_t* header) -+{ -+ size_t pos; -+ size_t alloc_hint = 0; -+ BYTE** ptr = NULL; -+ -+ if (!rts_read_auth_verifier_no_checks(s, auth, header, &pos)) -+ return FALSE; -+ -+ switch (header->ptype) -+ { -+ case PTYPE_FAULT: -+ { -+ rpcconn_fault_hdr_t* hdr = (rpcconn_fault_hdr_t*)header; -+ alloc_hint = hdr->alloc_hint; -+ ptr = &hdr->stub_data; -+ } -+ break; -+ case PTYPE_RESPONSE: -+ { -+ rpcconn_response_hdr_t* hdr = (rpcconn_response_hdr_t*)header; -+ alloc_hint = hdr->alloc_hint; -+ ptr = &hdr->stub_data; -+ } -+ break; -+ case PTYPE_REQUEST: -+ { -+ rpcconn_request_hdr_t* hdr = (rpcconn_request_hdr_t*)header; -+ alloc_hint = hdr->alloc_hint; -+ ptr = &hdr->stub_data; -+ } -+ break; -+ default: -+ return FALSE; -+ } -+ -+ if (alloc_hint > 0) -+ { -+ const size_t size = -+ header->frag_length - header->auth_length - 8 - auth->auth_pad_length - pos; -+ const void* src = Stream_Buffer(s) + pos; -+ -+ *ptr = (BYTE*)sdup(src, size); -+ if (!*ptr) -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static void rts_free_auth_verifier(auth_verifier_co_t* auth) -+{ -+ if (!auth) -+ return; -+ free(auth->auth_value); -+} -+ -+static BOOL rts_write_auth_verifier(wStream* s, const auth_verifier_co_t* auth, -+ const rpcconn_common_hdr_t* header) -+{ -+ size_t pos; -+ UINT8 auth_pad_length = 0; -+ -+ assert(s); -+ assert(auth); -+ assert(header); -+ -+ /* Align start to a multiple of 4 */ -+ pos = Stream_GetPosition(s); -+ if ((pos % 4) != 0) -+ { -+ auth_pad_length = 4 - (pos % 4); -+ if (!Stream_EnsureRemainingCapacity(s, auth_pad_length)) -+ return FALSE; -+ Stream_Zero(s, auth_pad_length); -+ } -+ -+ assert(header->frag_length + 8ull > header->auth_length); -+ { -+ size_t pos = Stream_GetPosition(s); -+ size_t expected = header->frag_length - header->auth_length - 8; -+ -+ assert(pos == expected); -+ } -+ -+ if (!Stream_EnsureRemainingCapacity(s, sizeof(auth_verifier_co_t))) -+ return FALSE; -+ -+ Stream_Write_UINT8(s, auth->auth_type); -+ Stream_Write_UINT8(s, auth->auth_level); -+ Stream_Write_UINT8(s, auth_pad_length); -+ Stream_Write_UINT8(s, 0); /* auth->auth_reserved */ -+ Stream_Write_UINT32(s, auth->auth_context_id); -+ -+ if (!Stream_EnsureRemainingCapacity(s, header->auth_length)) -+ return FALSE; -+ Stream_Write(s, auth->auth_value, header->auth_length); -+ return TRUE; -+} -+ -+static BOOL rts_read_version(wStream* s, p_rt_version_t* version) -+{ -+ assert(s); -+ assert(version); -+ -+ if (Stream_GetRemainingLength(s) < 2 * sizeof(UINT8)) -+ return FALSE; -+ Stream_Read_UINT8(s, version->major); -+ Stream_Read_UINT8(s, version->minor); -+ return TRUE; -+} -+ -+void rts_free_supported_versions(p_rt_versions_supported_t* versions) -+{ -+ if (!versions) -+ return; -+ free(versions->p_protocols); -+ versions->p_protocols = NULL; -+} -+ -+static BOOL rts_read_supported_versions(wStream* s, p_rt_versions_supported_t* versions) -+{ -+ BYTE x; -+ -+ assert(s); -+ assert(versions); -+ -+ if (Stream_GetRemainingLength(s) < sizeof(UINT8)) -+ return FALSE; -+ -+ Stream_Read_UINT8(s, versions->n_protocols); /* count */ -+ -+ if (versions->n_protocols > 0) -+ { -+ versions->p_protocols = calloc(versions->n_protocols, sizeof(p_rt_version_t)); -+ if (!versions->p_protocols) -+ return FALSE; -+ } -+ for (x = 0; x < versions->n_protocols; x++) -+ { -+ p_rt_version_t* version = &versions->p_protocols[x]; -+ if (!rts_read_version(s, version)) /* size_is(n_protocols) */ -+ { -+ rts_free_supported_versions(versions); -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+static BOOL rts_read_port_any(wStream* s, port_any_t* port) -+{ -+ const void* ptr; -+ -+ assert(s); -+ assert(port); -+ -+ if (Stream_GetRemainingLength(s) < sizeof(UINT16)) -+ return FALSE; -+ -+ Stream_Read_UINT16(s, port->length); -+ if (port->length == 0) -+ return TRUE; -+ -+ ptr = Stream_Pointer(s); -+ if (!Stream_SafeSeek(s, port->length)) -+ return FALSE; -+ port->port_spec = sdup(ptr, port->length); -+ return port->port_spec != NULL; -+} -+ -+static void rts_free_port_any(port_any_t* port) -+{ -+ if (!port) -+ return; -+ free(port->port_spec); -+} -+ -+static BOOL rts_read_uuid(wStream* s, p_uuid_t* uuid) -+{ -+ assert(s); -+ assert(uuid); -+ -+ if (Stream_GetRemainingLength(s) < sizeof(p_uuid_t)) -+ return FALSE; -+ -+ Stream_Read_UINT32(s, uuid->time_low); -+ Stream_Read_UINT16(s, uuid->time_mid); -+ Stream_Read_UINT16(s, uuid->time_hi_and_version); -+ Stream_Read_UINT8(s, uuid->clock_seq_hi_and_reserved); -+ Stream_Read_UINT8(s, uuid->clock_seq_low); -+ Stream_Read(s, uuid->node, ARRAYSIZE(uuid->node)); -+ return TRUE; -+} -+ -+static BOOL rts_write_uuid(wStream* s, const p_uuid_t* uuid) -+{ -+ assert(s); -+ assert(uuid); -+ -+ if (!Stream_EnsureRemainingCapacity(s, sizeof(p_uuid_t))) -+ return FALSE; -+ -+ Stream_Write_UINT32(s, uuid->time_low); -+ Stream_Write_UINT16(s, uuid->time_mid); -+ Stream_Write_UINT16(s, uuid->time_hi_and_version); -+ Stream_Write_UINT8(s, uuid->clock_seq_hi_and_reserved); -+ Stream_Write_UINT8(s, uuid->clock_seq_low); -+ Stream_Write(s, uuid->node, ARRAYSIZE(uuid->node)); -+ return TRUE; -+} -+ -+static p_syntax_id_t* rts_syntax_id_new(size_t count) -+{ -+ return calloc(count, sizeof(p_syntax_id_t)); -+} -+ -+static void rts_syntax_id_free(p_syntax_id_t* ptr) -+{ -+ free(ptr); -+} -+ -+static BOOL rts_read_syntax_id(wStream* s, p_syntax_id_t* syntax_id) -+{ -+ assert(s); -+ assert(syntax_id); -+ -+ if (!rts_read_uuid(s, &syntax_id->if_uuid)) -+ return FALSE; -+ -+ if (Stream_GetRemainingLength(s) < 4) -+ return FALSE; -+ -+ Stream_Read_UINT32(s, syntax_id->if_version); -+ return TRUE; -+} -+ -+static BOOL rts_write_syntax_id(wStream* s, const p_syntax_id_t* syntax_id) -+{ -+ assert(s); -+ assert(syntax_id); -+ -+ if (!rts_write_uuid(s, &syntax_id->if_uuid)) -+ return FALSE; -+ -+ if (!Stream_EnsureRemainingCapacity(s, 4)) -+ return FALSE; -+ -+ Stream_Write_UINT32(s, syntax_id->if_version); -+ return TRUE; -+} -+ -+p_cont_elem_t* rts_context_elem_new(size_t count) -+{ -+ p_cont_elem_t* ctx = calloc(count, sizeof(p_cont_elem_t)); -+ return ctx; -+} -+ -+void rts_context_elem_free(p_cont_elem_t* ptr) -+{ -+ if (!ptr) -+ return; -+ rts_syntax_id_free(ptr->transfer_syntaxes); -+ free(ptr); -+} -+ -+static BOOL rts_read_context_elem(wStream* s, p_cont_elem_t* element) -+{ -+ BYTE x; -+ assert(s); -+ assert(element); -+ -+ if (Stream_GetRemainingLength(s) < 4) -+ return FALSE; -+ -+ Stream_Read_UINT16(s, element->p_cont_id); -+ Stream_Read_UINT8(s, element->n_transfer_syn); /* number of items */ -+ Stream_Read_UINT8(s, element->reserved); /* alignment pad, m.b.z. */ -+ -+ if (!rts_read_syntax_id(s, &element->abstract_syntax)) /* transfer syntax list */ -+ return FALSE; -+ -+ if (element->n_transfer_syn > 0) -+ { -+ element->transfer_syntaxes = rts_syntax_id_new(element->n_transfer_syn); -+ if (!element->transfer_syntaxes) -+ return FALSE; -+ for (x = 0; x < element->n_transfer_syn; x++) -+ { -+ p_syntax_id_t* syn = &element->transfer_syntaxes[x]; -+ if (!rts_read_syntax_id(s, syn)) /* size_is(n_transfer_syn) */ -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+static BOOL rts_write_context_elem(wStream* s, const p_cont_elem_t* element) -+{ -+ BYTE x; -+ assert(s); -+ assert(element); -+ -+ if (!Stream_EnsureRemainingCapacity(s, 4)) -+ return FALSE; -+ Stream_Write_UINT16(s, element->p_cont_id); -+ Stream_Write_UINT8(s, element->n_transfer_syn); /* number of items */ -+ Stream_Write_UINT8(s, element->reserved); /* alignment pad, m.b.z. */ -+ if (!rts_write_syntax_id(s, &element->abstract_syntax)) /* transfer syntax list */ -+ return FALSE; -+ -+ for (x = 0; x < element->n_transfer_syn; x++) -+ { -+ const p_syntax_id_t* syn = &element->transfer_syntaxes[x]; -+ if (!rts_write_syntax_id(s, syn)) /* size_is(n_transfer_syn) */ -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static BOOL rts_read_context_list(wStream* s, p_cont_list_t* list) -+{ -+ BYTE x; -+ -+ assert(s); -+ assert(list); -+ -+ if (Stream_GetRemainingLength(s) < 4) -+ return FALSE; -+ Stream_Read_UINT8(s, list->n_context_elem); /* number of items */ -+ Stream_Read_UINT8(s, list->reserved); /* alignment pad, m.b.z. */ -+ Stream_Read_UINT16(s, list->reserved2); /* alignment pad, m.b.z. */ -+ -+ if (list->n_context_elem > 0) -+ { -+ list->p_cont_elem = rts_context_elem_new(list->n_context_elem); -+ if (!list->p_cont_elem) -+ return FALSE; -+ for (x = 0; x < list->n_context_elem; x++) -+ { -+ p_cont_elem_t* element = &list->p_cont_elem[x]; -+ if (!rts_read_context_elem(s, element)) -+ return FALSE; -+ } -+ } -+ return TRUE; -+} -+ -+static void rts_free_context_list(p_cont_list_t* list) -+{ -+ if (!list) -+ return; -+ rts_context_elem_free(list->p_cont_elem); -+} -+ -+static BOOL rts_write_context_list(wStream* s, const p_cont_list_t* list) -+{ -+ BYTE x; -+ -+ assert(s); -+ assert(list); -+ -+ if (!Stream_EnsureRemainingCapacity(s, 4)) -+ return FALSE; -+ Stream_Write_UINT8(s, list->n_context_elem); /* number of items */ -+ Stream_Write_UINT8(s, 0); /* alignment pad, m.b.z. */ -+ Stream_Write_UINT16(s, 0); /* alignment pad, m.b.z. */ -+ -+ for (x = 0; x < list->n_context_elem; x++) -+ { -+ const p_cont_elem_t* element = &list->p_cont_elem[x]; -+ if (!rts_write_context_elem(s, element)) -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+static p_result_t* rts_result_new(size_t count) -+{ -+ return calloc(count, sizeof(p_result_t)); -+} -+ -+static void rts_result_free(p_result_t* results) -+{ -+ if (!results) -+ return; -+ free(results); -+} -+ -+static BOOL rts_read_result(wStream* s, p_result_t* result) -+{ -+ assert(s); -+ assert(result); -+ -+ if (Stream_GetRemainingLength(s) < 2) -+ return FALSE; -+ Stream_Read_UINT16(s, result->result); -+ Stream_Read_UINT16(s, result->reason); -+ -+ return rts_read_syntax_id(s, &result->transfer_syntax); -+} -+ -+static void rts_free_result(p_result_t* result) -+{ -+ if (!result) -+ return; -+} -+ -+static BOOL rts_read_result_list(wStream* s, p_result_list_t* list) -+{ -+ BYTE x; -+ -+ assert(s); -+ assert(list); -+ -+ if (Stream_GetRemainingLength(s) < 4) -+ return FALSE; -+ Stream_Read_UINT8(s, list->n_results); /* count */ -+ Stream_Read_UINT8(s, list->reserved); /* alignment pad, m.b.z. */ -+ Stream_Read_UINT16(s, list->reserved2); /* alignment pad, m.b.z. */ -+ -+ if (list->n_results > 0) -+ { -+ list->p_results = rts_result_new(list->n_results); -+ if (!list->p_results) -+ return FALSE; -+ -+ for (x = 0; x < list->n_results; x++) -+ { -+ p_result_t* result = &list->p_results[x]; /* size_is(n_results) */ -+ if (!rts_read_result(s, result)) -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+static void rts_free_result_list(p_result_list_t* list) -+{ -+ BYTE x; -+ -+ if (!list) -+ return; -+ for (x = 0; x < list->n_results; x++) -+ { -+ p_result_t* result = &list->p_results[x]; -+ rts_free_result(result); -+ } -+ rts_result_free(list->p_results); -+} -+ -+static void rts_free_pdu_alter_context(rpcconn_alter_context_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ -+ rts_free_context_list(&ctx->p_context_elem); -+ rts_free_auth_verifier(&ctx->auth_verifier); -+} -+ -+static BOOL rts_read_pdu_alter_context(wStream* s, rpcconn_alter_context_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < -+ sizeof(rpcconn_alter_context_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ -+ Stream_Read_UINT16(s, ctx->max_xmit_frag); -+ Stream_Read_UINT16(s, ctx->max_recv_frag); -+ Stream_Read_UINT32(s, ctx->assoc_group_id); -+ -+ if (!rts_read_context_list(s, &ctx->p_context_elem)) -+ return FALSE; -+ -+ if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header)) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+static BOOL rts_read_pdu_alter_context_response(wStream* s, -+ rpcconn_alter_context_response_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < -+ sizeof(rpcconn_alter_context_response_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ Stream_Read_UINT16(s, ctx->max_xmit_frag); -+ Stream_Read_UINT16(s, ctx->max_recv_frag); -+ Stream_Read_UINT32(s, ctx->assoc_group_id); -+ -+ if (!rts_read_port_any(s, &ctx->sec_addr)) -+ return FALSE; -+ -+ if (!rts_align_stream(s, 4)) -+ return FALSE; -+ -+ if (!rts_read_result_list(s, &ctx->p_result_list)) -+ return FALSE; -+ -+ if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header)) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+static void rts_free_pdu_alter_context_response(rpcconn_alter_context_response_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ -+ rts_free_port_any(&ctx->sec_addr); -+ rts_free_result_list(&ctx->p_result_list); -+ rts_free_auth_verifier(&ctx->auth_verifier); -+} -+ -+static BOOL rts_read_pdu_bind(wStream* s, rpcconn_bind_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < sizeof(rpcconn_bind_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ Stream_Read_UINT16(s, ctx->max_xmit_frag); -+ Stream_Read_UINT16(s, ctx->max_recv_frag); -+ Stream_Read_UINT32(s, ctx->assoc_group_id); -+ -+ if (!rts_read_context_list(s, &ctx->p_context_elem)) -+ return FALSE; -+ -+ if (!rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header)) -+ return FALSE; -+ -+ return TRUE; -+} -+ -+static void rts_free_pdu_bind(rpcconn_bind_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ rts_free_context_list(&ctx->p_context_elem); -+ rts_free_auth_verifier(&ctx->auth_verifier); -+} -+ -+static BOOL rts_read_pdu_bind_ack(wStream* s, rpcconn_bind_ack_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < -+ sizeof(rpcconn_bind_ack_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ Stream_Read_UINT16(s, ctx->max_xmit_frag); -+ Stream_Read_UINT16(s, ctx->max_recv_frag); -+ Stream_Read_UINT32(s, ctx->assoc_group_id); -+ -+ if (!rts_read_port_any(s, &ctx->sec_addr)) -+ return FALSE; -+ -+ if (!rts_align_stream(s, 4)) -+ return FALSE; -+ -+ if (!rts_read_result_list(s, &ctx->p_result_list)) -+ return FALSE; -+ -+ return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header); -+} -+ -+static void rts_free_pdu_bind_ack(rpcconn_bind_ack_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ rts_free_port_any(&ctx->sec_addr); -+ rts_free_result_list(&ctx->p_result_list); -+ rts_free_auth_verifier(&ctx->auth_verifier); -+} -+ -+static BOOL rts_read_pdu_bind_nak(wStream* s, rpcconn_bind_nak_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < -+ sizeof(rpcconn_bind_nak_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ Stream_Read_UINT16(s, ctx->provider_reject_reason); -+ return rts_read_supported_versions(s, &ctx->versions); -+} -+ -+static void rts_free_pdu_bind_nak(rpcconn_bind_nak_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ -+ rts_free_supported_versions(&ctx->versions); -+} -+ -+static BOOL rts_read_pdu_auth3(wStream* s, rpcconn_rpc_auth_3_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < -+ sizeof(rpcconn_rpc_auth_3_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ Stream_Read_UINT16(s, ctx->max_xmit_frag); -+ Stream_Read_UINT16(s, ctx->max_recv_frag); -+ -+ return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header); -+} -+ -+static void rts_free_pdu_auth3(rpcconn_rpc_auth_3_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ rts_free_auth_verifier(&ctx->auth_verifier); -+} -+ -+static BOOL rts_read_pdu_fault(wStream* s, rpcconn_fault_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < sizeof(rpcconn_fault_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ Stream_Read_UINT32(s, ctx->alloc_hint); -+ Stream_Read_UINT16(s, ctx->p_cont_id); -+ Stream_Read_UINT8(s, ctx->cancel_count); -+ Stream_Read_UINT8(s, ctx->reserved); -+ Stream_Read_UINT32(s, ctx->status); -+ -+ return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header); -+} -+ -+static void rts_free_pdu_fault(rpcconn_fault_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ rts_free_auth_verifier(&ctx->auth_verifier); -+} -+ -+static BOOL rts_read_pdu_cancel_ack(wStream* s, rpcconn_cancel_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < sizeof(rpcconn_cancel_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header); -+} -+ -+static void rts_free_pdu_cancel_ack(rpcconn_cancel_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ rts_free_auth_verifier(&ctx->auth_verifier); -+} -+ -+static BOOL rts_read_pdu_orphaned(wStream* s, rpcconn_orphaned_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < -+ sizeof(rpcconn_orphaned_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ return rts_read_auth_verifier(s, &ctx->auth_verifier, &ctx->header); -+} -+ -+static void rts_free_pdu_orphaned(rpcconn_orphaned_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ rts_free_auth_verifier(&ctx->auth_verifier); -+} -+ -+static BOOL rts_read_pdu_request(wStream* s, rpcconn_request_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < sizeof(rpcconn_request_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ Stream_Read_UINT32(s, ctx->alloc_hint); -+ Stream_Read_UINT16(s, ctx->p_cont_id); -+ Stream_Read_UINT16(s, ctx->opnum); -+ if (!rts_read_uuid(s, &ctx->object)) -+ return FALSE; -+ -+ return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header); -+} -+ -+static void rts_free_pdu_request(rpcconn_request_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ rts_free_auth_verifier(&ctx->auth_verifier); -+} -+ -+static BOOL rts_read_pdu_response(wStream* s, rpcconn_response_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < -+ sizeof(rpcconn_response_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ Stream_Read_UINT32(s, ctx->alloc_hint); -+ Stream_Read_UINT16(s, ctx->p_cont_id); -+ Stream_Read_UINT8(s, ctx->cancel_count); -+ Stream_Read_UINT8(s, ctx->reserved); -+ -+ if (!rts_align_stream(s, 8)) -+ return FALSE; -+ -+ return rts_read_auth_verifier_with_stub(s, &ctx->auth_verifier, &ctx->header); -+} -+ -+static void rts_free_pdu_response(rpcconn_response_hdr_t* ctx) -+{ -+ if (!ctx) -+ return; -+ free(ctx->stub_data); -+ rts_free_auth_verifier(&ctx->auth_verifier); -+} -+ -+static BOOL rts_read_pdu_rts(wStream* s, rpcconn_rts_hdr_t* ctx) -+{ -+ assert(s); -+ assert(ctx); -+ -+ if (Stream_GetRemainingLength(s) < sizeof(rpcconn_rts_hdr_t) - sizeof(rpcconn_common_hdr_t)) -+ return FALSE; -+ -+ Stream_Read_UINT16(s, ctx->Flags); -+ Stream_Read_UINT16(s, ctx->NumberOfCommands); -+ return TRUE; -+} -+ -+static void rts_free_pdu_rts(rpcconn_rts_hdr_t* ctx) -+{ -+ WINPR_UNUSED(ctx); -+} -+ -+void rts_free_pdu_header(rpcconn_hdr_t* header, BOOL allocated) -+{ -+ if (!header) -+ return; -+ -+ switch (header->common.ptype) -+ { -+ case PTYPE_ALTER_CONTEXT: -+ rts_free_pdu_alter_context(&header->alter_context); -+ break; -+ case PTYPE_ALTER_CONTEXT_RESP: -+ rts_free_pdu_alter_context_response(&header->alter_context_response); -+ break; -+ case PTYPE_BIND: -+ rts_free_pdu_bind(&header->bind); -+ break; -+ case PTYPE_BIND_ACK: -+ rts_free_pdu_bind_ack(&header->bind_ack); -+ break; -+ case PTYPE_BIND_NAK: -+ rts_free_pdu_bind_nak(&header->bind_nak); -+ break; -+ case PTYPE_RPC_AUTH_3: -+ rts_free_pdu_auth3(&header->rpc_auth_3); -+ break; -+ case PTYPE_CANCEL_ACK: -+ rts_free_pdu_cancel_ack(&header->cancel); -+ break; -+ case PTYPE_FAULT: -+ rts_free_pdu_fault(&header->fault); -+ break; -+ case PTYPE_ORPHANED: -+ rts_free_pdu_orphaned(&header->orphaned); -+ break; -+ case PTYPE_REQUEST: -+ rts_free_pdu_request(&header->request); -+ break; -+ case PTYPE_RESPONSE: -+ rts_free_pdu_response(&header->response); -+ break; -+ case PTYPE_RTS: -+ rts_free_pdu_rts(&header->rts); -+ break; -+ /* No extra fields */ -+ case PTYPE_SHUTDOWN: -+ break; -+ -+ /* not handled */ -+ case PTYPE_PING: -+ case PTYPE_WORKING: -+ case PTYPE_NOCALL: -+ case PTYPE_REJECT: -+ case PTYPE_ACK: -+ case PTYPE_CL_CANCEL: -+ case PTYPE_FACK: -+ case PTYPE_CO_CANCEL: -+ default: -+ break; -+ } -+ -+ if (allocated) -+ free(header); -+} -+ -+BOOL rts_read_pdu_header(wStream* s, rpcconn_hdr_t* header) -+{ -+ BOOL rc = FALSE; -+ assert(s); -+ assert(header); -+ -+ if (!rts_read_common_pdu_header(s, &header->common)) -+ return FALSE; -+ -+ WLog_DBG(TAG, "Reading PDU type %s", rts_pdu_ptype_to_string(header->common.ptype)); -+ fflush(stdout); -+ switch (header->common.ptype) -+ { -+ case PTYPE_ALTER_CONTEXT: -+ rc = rts_read_pdu_alter_context(s, &header->alter_context); -+ break; -+ case PTYPE_ALTER_CONTEXT_RESP: -+ rc = rts_read_pdu_alter_context_response(s, &header->alter_context_response); -+ break; -+ case PTYPE_BIND: -+ rc = rts_read_pdu_bind(s, &header->bind); -+ break; -+ case PTYPE_BIND_ACK: -+ rc = rts_read_pdu_bind_ack(s, &header->bind_ack); -+ break; -+ case PTYPE_BIND_NAK: -+ rc = rts_read_pdu_bind_nak(s, &header->bind_nak); -+ break; -+ case PTYPE_RPC_AUTH_3: -+ rc = rts_read_pdu_auth3(s, &header->rpc_auth_3); -+ break; -+ case PTYPE_CANCEL_ACK: -+ rc = rts_read_pdu_cancel_ack(s, &header->cancel); -+ break; -+ case PTYPE_FAULT: -+ rc = rts_read_pdu_fault(s, &header->fault); -+ break; -+ case PTYPE_ORPHANED: -+ rc = rts_read_pdu_orphaned(s, &header->orphaned); -+ break; -+ case PTYPE_REQUEST: -+ rc = rts_read_pdu_request(s, &header->request); -+ break; -+ case PTYPE_RESPONSE: -+ rc = rts_read_pdu_response(s, &header->response); -+ break; -+ case PTYPE_RTS: -+ rc = rts_read_pdu_rts(s, &header->rts); -+ break; -+ case PTYPE_SHUTDOWN: -+ rc = TRUE; /* No extra fields */ -+ break; -+ -+ /* not handled */ -+ case PTYPE_PING: -+ case PTYPE_WORKING: -+ case PTYPE_NOCALL: -+ case PTYPE_REJECT: -+ case PTYPE_ACK: -+ case PTYPE_CL_CANCEL: -+ case PTYPE_FACK: -+ case PTYPE_CO_CANCEL: -+ default: -+ break; -+ } -+ -+ return rc; -+} -+ -+static BOOL rts_write_pdu_header(wStream* s, const rpcconn_rts_hdr_t* header) -+{ -+ assert(s); -+ assert(header); -+ if (!Stream_EnsureRemainingCapacity(s, sizeof(rpcconn_rts_hdr_t))) -+ return FALSE; - -- return header; -+ if (!rts_write_common_pdu_header(s, &header->header)) -+ return FALSE; -+ -+ Stream_Write_UINT16(s, header->Flags); -+ Stream_Write_UINT16(s, header->NumberOfCommands); -+ return TRUE; - } - --static int rts_receive_window_size_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, -+static int rts_receive_window_size_command_read(rdpRpc* rpc, wStream* buffer, - UINT32* ReceiveWindowSize) - { -+ UINT32 val; -+ -+ assert(rpc); -+ assert(buffer); -+ -+ if (Stream_GetRemainingLength(buffer) < 4) -+ return -1; -+ Stream_Read_UINT32(buffer, val); - if (ReceiveWindowSize) -- *ReceiveWindowSize = *((UINT32*)&buffer[0]); /* ReceiveWindowSize (4 bytes) */ -+ *ReceiveWindowSize = val; /* ReceiveWindowSize (4 bytes) */ - - return 4; - } - --static int rts_receive_window_size_command_write(BYTE* buffer, UINT32 ReceiveWindowSize) -+static BOOL rts_receive_window_size_command_write(wStream* s, UINT32 ReceiveWindowSize) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_RECEIVE_WINDOW_SIZE; /* CommandType (4 bytes) */ -- *((UINT32*)&buffer[4]) = ReceiveWindowSize; /* ReceiveWindowSize (4 bytes) */ -- } -+ assert(s); -+ -+ if (!Stream_EnsureRemainingCapacity(s, 2 * sizeof(UINT32))) -+ return FALSE; - -- return 8; -+ Stream_Write_UINT32(s, RTS_CMD_RECEIVE_WINDOW_SIZE); /* CommandType (4 bytes) */ -+ Stream_Write_UINT32(s, ReceiveWindowSize); /* ReceiveWindowSize (4 bytes) */ -+ -+ return TRUE; - } - --static int rts_flow_control_ack_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, -- UINT32* BytesReceived, UINT32* AvailableWindow, -- BYTE* ChannelCookie) -+static int rts_flow_control_ack_command_read(rdpRpc* rpc, wStream* buffer, UINT32* BytesReceived, -+ UINT32* AvailableWindow, BYTE* ChannelCookie) - { -+ UINT32 val; -+ assert(rpc); -+ assert(buffer); -+ - /* Ack (24 bytes) */ -+ if (Stream_GetRemainingLength(buffer) < 24) -+ return -1; -+ -+ Stream_Read_UINT32(buffer, val); - if (BytesReceived) -- *BytesReceived = *((UINT32*)&buffer[0]); /* BytesReceived (4 bytes) */ -+ *BytesReceived = val; /* BytesReceived (4 bytes) */ - -+ Stream_Read_UINT32(buffer, val); - if (AvailableWindow) -- *AvailableWindow = *((UINT32*)&buffer[4]); /* AvailableWindow (4 bytes) */ -+ *AvailableWindow = val; /* AvailableWindow (4 bytes) */ - - if (ChannelCookie) -- CopyMemory(ChannelCookie, &buffer[8], 16); /* ChannelCookie (16 bytes) */ -- -+ Stream_Read(buffer, ChannelCookie, 16); /* ChannelCookie (16 bytes) */ -+ else -+ Stream_Seek(buffer, 16); - return 24; - } - --static int rts_flow_control_ack_command_write(BYTE* buffer, UINT32 BytesReceived, -- UINT32 AvailableWindow, BYTE* ChannelCookie) -+static BOOL rts_flow_control_ack_command_write(wStream* s, UINT32 BytesReceived, -+ UINT32 AvailableWindow, BYTE* ChannelCookie) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_FLOW_CONTROL_ACK; /* CommandType (4 bytes) */ -- /* Ack (24 bytes) */ -- *((UINT32*)&buffer[4]) = BytesReceived; /* BytesReceived (4 bytes) */ -- *((UINT32*)&buffer[8]) = AvailableWindow; /* AvailableWindow (4 bytes) */ -- CopyMemory(&buffer[12], ChannelCookie, 16); /* ChannelCookie (16 bytes) */ -- } -+ assert(s); - -- return 28; --} -+ if (!Stream_EnsureRemainingCapacity(s, 28)) -+ return FALSE; - --static int rts_connection_timeout_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, -- UINT32* ConnectionTimeout) --{ -- if (ConnectionTimeout) -- *ConnectionTimeout = *((UINT32*)&buffer[0]); /* ConnectionTimeout (4 bytes) */ -+ Stream_Write_UINT32(s, RTS_CMD_FLOW_CONTROL_ACK); /* CommandType (4 bytes) */ -+ Stream_Write_UINT32(s, BytesReceived); /* BytesReceived (4 bytes) */ -+ Stream_Write_UINT32(s, AvailableWindow); /* AvailableWindow (4 bytes) */ -+ Stream_Write(s, ChannelCookie, 16); /* ChannelCookie (16 bytes) */ - -- return 4; -+ return TRUE; - } - --static int rts_connection_timeout_command_write(BYTE* buffer, UINT32 ConnectionTimeout) -+static BOOL rts_connection_timeout_command_read(rdpRpc* rpc, wStream* buffer, -+ UINT32* ConnectionTimeout) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_CONNECTION_TIMEOUT; /* CommandType (4 bytes) */ -- *((UINT32*)&buffer[4]) = ConnectionTimeout; /* ConnectionTimeout (4 bytes) */ -- } -+ UINT32 val; -+ assert(rpc); -+ assert(buffer); - -- return 8; --} -+ if (Stream_GetRemainingLength(buffer) < 4) -+ return FALSE; - --static int rts_cookie_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) --{ -- /* Cookie (16 bytes) */ -- return 16; -+ Stream_Read_UINT32(buffer, val); -+ if (ConnectionTimeout) -+ *ConnectionTimeout = val; /* ConnectionTimeout (4 bytes) */ -+ -+ return TRUE; - } - --static int rts_cookie_command_write(BYTE* buffer, BYTE* Cookie) -+static BOOL rts_cookie_command_write(wStream* s, const BYTE* Cookie) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_COOKIE; /* CommandType (4 bytes) */ -- CopyMemory(&buffer[4], Cookie, 16); /* Cookie (16 bytes) */ -- } -+ assert(s); - -- return 20; --} -+ if (!Stream_EnsureRemainingCapacity(s, 20)) -+ return FALSE; - --static int rts_channel_lifetime_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) --{ -- /* ChannelLifetime (4 bytes) */ -- return 4; -+ Stream_Write_UINT32(s, RTS_CMD_COOKIE); /* CommandType (4 bytes) */ -+ Stream_Write(s, Cookie, 16); /* Cookie (16 bytes) */ -+ -+ return TRUE; - } - --static int rts_channel_lifetime_command_write(BYTE* buffer, UINT32 ChannelLifetime) -+static BOOL rts_channel_lifetime_command_write(wStream* s, UINT32 ChannelLifetime) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_CHANNEL_LIFETIME; /* CommandType (4 bytes) */ -- *((UINT32*)&buffer[4]) = ChannelLifetime; /* ChannelLifetime (4 bytes) */ -- } -+ assert(s); - -- return 8; --} -+ if (!Stream_EnsureRemainingCapacity(s, 8)) -+ return FALSE; -+ Stream_Write_UINT32(s, RTS_CMD_CHANNEL_LIFETIME); /* CommandType (4 bytes) */ -+ Stream_Write_UINT32(s, ChannelLifetime); /* ChannelLifetime (4 bytes) */ - --static int rts_client_keepalive_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) --{ -- /* ClientKeepalive (4 bytes) */ -- return 4; -+ return TRUE; - } - --static int rts_client_keepalive_command_write(BYTE* buffer, UINT32 ClientKeepalive) -+static BOOL rts_client_keepalive_command_write(wStream* s, UINT32 ClientKeepalive) - { -+ assert(s); -+ -+ if (!Stream_EnsureRemainingCapacity(s, 8)) -+ return FALSE; - /** - * An unsigned integer that specifies the keep-alive interval, in milliseconds, - * that this connection is configured to use. This value MUST be 0 or in the inclusive - * range of 60,000 through 4,294,967,295. If it is 0, it MUST be interpreted as 300,000. - */ -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_CLIENT_KEEPALIVE; /* CommandType (4 bytes) */ -- *((UINT32*)&buffer[4]) = ClientKeepalive; /* ClientKeepalive (4 bytes) */ -- } - -- return 8; --} -+ Stream_Write_UINT32(s, RTS_CMD_CLIENT_KEEPALIVE); /* CommandType (4 bytes) */ -+ Stream_Write_UINT32(s, ClientKeepalive); /* ClientKeepalive (4 bytes) */ - --static int rts_version_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) --{ -- /* Version (4 bytes) */ -- return 4; -+ return TRUE; - } - --static int rts_version_command_write(BYTE* buffer) -+static BOOL rts_version_command_read(rdpRpc* rpc, wStream* buffer) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_VERSION; /* CommandType (4 bytes) */ -- *((UINT32*)&buffer[4]) = 1; /* Version (4 bytes) */ -- } -+ assert(rpc); -+ assert(buffer); - -- return 8; --} -+ if (!Stream_SafeSeek(buffer, 4)) -+ return FALSE; - --static int rts_empty_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) --{ -- return 0; -+ /* Version (4 bytes) */ -+ return TRUE; - } - --static int rts_empty_command_write(BYTE* buffer) -+static BOOL rts_version_command_write(wStream* buffer) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_EMPTY; /* CommandType (4 bytes) */ -- } -- -- return 4; --} -+ assert(buffer); - --static SSIZE_T rts_padding_command_read(const BYTE* buffer, size_t length) --{ -- UINT32 ConformanceCount; -- ConformanceCount = *((UINT32*)&buffer[0]); /* ConformanceCount (4 bytes) */ -- /* Padding (variable) */ -- return ConformanceCount + 4; --} -+ if (Stream_GetRemainingCapacity(buffer) < 8) -+ return FALSE; - --static int rts_padding_command_write(BYTE* buffer, UINT32 ConformanceCount) --{ -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_PADDING; /* CommandType (4 bytes) */ -- *((UINT32*)&buffer[4]) = ConformanceCount; /* ConformanceCount (4 bytes) */ -- ZeroMemory(&buffer[8], ConformanceCount); /* Padding (variable) */ -- } -+ Stream_Write_UINT32(buffer, RTS_CMD_VERSION); /* CommandType (4 bytes) */ -+ Stream_Write_UINT32(buffer, 1); /* Version (4 bytes) */ - -- return 8 + ConformanceCount; -+ return TRUE; - } - --static int rts_negative_ance_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) -+static BOOL rts_empty_command_write(wStream* s) - { -- return 0; --} -+ assert(s); - --static int rts_negative_ance_command_write(BYTE* buffer) --{ -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_NEGATIVE_ANCE; /* CommandType (4 bytes) */ -- } -+ if (!Stream_EnsureRemainingCapacity(s, 8)) -+ return FALSE; - -- return 4; --} -+ Stream_Write_UINT32(s, RTS_CMD_EMPTY); /* CommandType (4 bytes) */ - --static int rts_ance_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) --{ -- return 0; -+ return TRUE; - } - --static int rts_ance_command_write(BYTE* buffer) -+static BOOL rts_padding_command_read(wStream* s, size_t* length) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_ANCE; /* CommandType (4 bytes) */ -- } -- -- return 4; -+ UINT32 ConformanceCount; -+ assert(s); -+ assert(length); -+ if (Stream_GetRemainingLength(s) < 4) -+ return FALSE; -+ Stream_Read_UINT32(s, ConformanceCount); /* ConformanceCount (4 bytes) */ -+ *length = ConformanceCount + 4; -+ return TRUE; - } - --static SSIZE_T rts_client_address_command_read(const BYTE* buffer, size_t length) -+static BOOL rts_client_address_command_read(wStream* s, size_t* length) - { - UINT32 AddressType; -- AddressType = *((UINT32*)&buffer[0]); /* AddressType (4 bytes) */ -+ -+ assert(s); -+ assert(length); -+ -+ if (Stream_GetRemainingLength(s) < 4) -+ return FALSE; -+ Stream_Read_UINT32(s, AddressType); /* AddressType (4 bytes) */ - - if (AddressType == 0) - { - /* ClientAddress (4 bytes) */ - /* padding (12 bytes) */ -- return 4 + 4 + 12; -+ *length = 4 + 4 + 12; - } - else - { - /* ClientAddress (16 bytes) */ - /* padding (12 bytes) */ -- return 4 + 16 + 12; -+ *length = 4 + 16 + 12; - } -+ return TRUE; - } - --static int rts_client_address_command_write(BYTE* buffer, UINT32 AddressType, BYTE* ClientAddress) -+static BOOL rts_association_group_id_command_write(wStream* s, const BYTE* AssociationGroupId) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_CLIENT_ADDRESS; /* CommandType (4 bytes) */ -- *((UINT32*)&buffer[4]) = AddressType; /* AddressType (4 bytes) */ -- } -+ assert(s); - -- if (AddressType == 0) -- { -- if (buffer) -- { -- CopyMemory(&buffer[8], ClientAddress, 4); /* ClientAddress (4 bytes) */ -- ZeroMemory(&buffer[12], 12); /* padding (12 bytes) */ -- } -- -- return 24; -- } -- else -- { -- if (buffer) -- { -- CopyMemory(&buffer[8], ClientAddress, 16); /* ClientAddress (16 bytes) */ -- ZeroMemory(&buffer[24], 12); /* padding (12 bytes) */ -- } -+ if (!Stream_EnsureRemainingCapacity(s, 20)) -+ return FALSE; - -- return 36; -- } --} -+ Stream_Write_UINT32(s, RTS_CMD_ASSOCIATION_GROUP_ID); /* CommandType (4 bytes) */ -+ Stream_Write(s, AssociationGroupId, 16); /* AssociationGroupId (16 bytes) */ - --static int rts_association_group_id_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) --{ -- /* AssociationGroupId (16 bytes) */ -- return 16; -+ return TRUE; - } - --static int rts_association_group_id_command_write(BYTE* buffer, BYTE* AssociationGroupId) -+static int rts_destination_command_read(rdpRpc* rpc, wStream* buffer, UINT32* Destination) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_ASSOCIATION_GROUP_ID; /* CommandType (4 bytes) */ -- CopyMemory(&buffer[4], AssociationGroupId, 16); /* AssociationGroupId (16 bytes) */ -- } -- -- return 20; --} -+ UINT32 val; -+ assert(rpc); -+ assert(buffer); - --static int rts_destination_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, -- UINT32* Destination) --{ -+ if (Stream_GetRemainingLength(buffer) < 4) -+ return -1; -+ Stream_Read_UINT32(buffer, val); - if (Destination) -- *Destination = *((UINT32*)&buffer[0]); /* Destination (4 bytes) */ -+ *Destination = val; /* Destination (4 bytes) */ - - return 4; - } - --static int rts_destination_command_write(BYTE* buffer, UINT32 Destination) -+static BOOL rts_destination_command_write(wStream* s, UINT32 Destination) - { -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_DESTINATION; /* CommandType (4 bytes) */ -- *((UINT32*)&buffer[4]) = Destination; /* Destination (4 bytes) */ -- } -- -- return 8; --} -+ assert(s); - --static int rts_ping_traffic_sent_notify_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length) --{ -- /* PingTrafficSent (4 bytes) */ -- return 4; --} -+ if (!Stream_EnsureRemainingCapacity(s, 8)) -+ return FALSE; - --static int rts_ping_traffic_sent_notify_command_write(BYTE* buffer, UINT32 PingTrafficSent) --{ -- if (buffer) -- { -- *((UINT32*)&buffer[0]) = RTS_CMD_PING_TRAFFIC_SENT_NOTIFY; /* CommandType (4 bytes) */ -- *((UINT32*)&buffer[4]) = PingTrafficSent; /* PingTrafficSent (4 bytes) */ -- } -+ Stream_Write_UINT32(s, RTS_CMD_DESTINATION); /* CommandType (4 bytes) */ -+ Stream_Write_UINT32(s, Destination); /* Destination (4 bytes) */ - -- return 8; -+ return TRUE; - } - - void rts_generate_cookie(BYTE* cookie) - { -+ assert(cookie); - winpr_RAND(cookie, 16); - } - -+static BOOL rts_send_buffer(RpcChannel* channel, wStream* s, size_t frag_length) -+{ -+ BOOL status = FALSE; -+ SSIZE_T rc; -+ -+ assert(channel); -+ assert(s); -+ -+ Stream_SealLength(s); -+ if (Stream_Length(s) < sizeof(rpcconn_common_hdr_t)) -+ goto fail; -+ if (Stream_Length(s) != frag_length) -+ goto fail; -+ -+ rc = rpc_channel_write(channel, Stream_Buffer(s), Stream_Length(s)); -+ if (rc < 0) -+ goto fail; -+ if ((size_t)rc != Stream_Length(s)) -+ goto fail; -+ status = TRUE; -+fail: -+ return status; -+} -+ - /* CONN/A Sequence */ - --int rts_send_CONN_A1_pdu(rdpRpc* rpc) -+BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc) - { -- int status; -- BYTE* buffer; -+ BOOL status = FALSE; -+ wStream* buffer; - rpcconn_rts_hdr_t header = rts_pdu_header_init(); - UINT32 ReceiveWindowSize; - BYTE* OUTChannelCookie; - BYTE* VirtualConnectionCookie; -- RpcVirtualConnection* connection = rpc->VirtualConnection; -- RpcOutChannel* outChannel = connection->DefaultOutChannel; -+ RpcVirtualConnection* connection; -+ RpcOutChannel* outChannel; -+ -+ assert(rpc); -+ -+ connection = rpc->VirtualConnection; -+ assert(connection); -+ -+ outChannel = connection->DefaultOutChannel; -+ assert(outChannel); - - header.header.frag_length = 76; - header.Flags = RTS_FLAG_NONE; - header.NumberOfCommands = 4; -+ - WLog_DBG(TAG, "Sending CONN/A1 RTS PDU"); - VirtualConnectionCookie = (BYTE*)&(connection->Cookie); - OUTChannelCookie = (BYTE*)&(outChannel->common.Cookie); - ReceiveWindowSize = outChannel->ReceiveWindow; -- buffer = (BYTE*)malloc(header.header.frag_length); -+ -+ buffer = Stream_New(NULL, header.header.frag_length); - - if (!buffer) - return -1; - -- CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */ -- rts_version_command_write(&buffer[20]); /* Version (8 bytes) */ -- rts_cookie_command_write(&buffer[28], -- VirtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */ -- rts_cookie_command_write(&buffer[48], OUTChannelCookie); /* OUTChannelCookie (20 bytes) */ -- rts_receive_window_size_command_write(&buffer[68], -- ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */ -- status = rpc_channel_write(&outChannel->common, buffer, header.header.frag_length); -- free(buffer); -- return (status > 0) ? 1 : -1; -+ if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */ -+ goto fail; -+ status = rts_version_command_write(buffer); /* Version (8 bytes) */ -+ if (!status) -+ goto fail; -+ status = rts_cookie_command_write( -+ buffer, VirtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */ -+ if (!status) -+ goto fail; -+ status = rts_cookie_command_write(buffer, OUTChannelCookie); /* OUTChannelCookie (20 bytes) */ -+ if (!status) -+ goto fail; -+ status = rts_receive_window_size_command_write( -+ buffer, ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */ -+ if (!status) -+ goto fail; -+ status = rts_send_buffer(&outChannel->common, buffer, header.header.frag_length); -+fail: -+ Stream_Free(buffer, TRUE); -+ return status; - } - --int rts_recv_CONN_A3_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) -+BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc, wStream* buffer) - { -+ BOOL rc; - UINT32 ConnectionTimeout; -- rts_connection_timeout_command_read(rpc, &buffer[24], length - 24, &ConnectionTimeout); -+ -+ if (!Stream_SafeSeek(buffer, 24)) -+ return FALSE; -+ -+ rc = rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout); -+ if (!rc) -+ return rc; -+ - WLog_DBG(TAG, "Receiving CONN/A3 RTS PDU: ConnectionTimeout: %" PRIu32 "", ConnectionTimeout); -+ -+ assert(rpc); -+ assert(rpc->VirtualConnection); -+ assert(rpc->VirtualConnection->DefaultInChannel); -+ - rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout; -- return 1; -+ return TRUE; - } - - /* CONN/B Sequence */ - --int rts_send_CONN_B1_pdu(rdpRpc* rpc) -+BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc) - { -- int status; -- BYTE* buffer; -- UINT32 length; -+ BOOL status = FALSE; -+ wStream* buffer; - rpcconn_rts_hdr_t header = rts_pdu_header_init(); - BYTE* INChannelCookie; - BYTE* AssociationGroupId; - BYTE* VirtualConnectionCookie; -- RpcVirtualConnection* connection = rpc->VirtualConnection; -- RpcInChannel* inChannel = connection->DefaultInChannel; -+ RpcVirtualConnection* connection; -+ RpcInChannel* inChannel; -+ -+ assert(rpc); -+ -+ connection = rpc->VirtualConnection; -+ assert(connection); -+ -+ inChannel = connection->DefaultInChannel; -+ assert(inChannel); - - header.header.frag_length = 104; - header.Flags = RTS_FLAG_NONE; - header.NumberOfCommands = 6; -+ - WLog_DBG(TAG, "Sending CONN/B1 RTS PDU"); -+ - VirtualConnectionCookie = (BYTE*)&(connection->Cookie); - INChannelCookie = (BYTE*)&(inChannel->common.Cookie); - AssociationGroupId = (BYTE*)&(connection->AssociationGroupId); -- buffer = (BYTE*)malloc(header.header.frag_length); -+ buffer = Stream_New(NULL, header.header.frag_length); - - if (!buffer) -- return -1; -- -- CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */ -- rts_version_command_write(&buffer[20]); /* Version (8 bytes) */ -- rts_cookie_command_write(&buffer[28], -- VirtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */ -- rts_cookie_command_write(&buffer[48], INChannelCookie); /* INChannelCookie (20 bytes) */ -- rts_channel_lifetime_command_write(&buffer[68], -- rpc->ChannelLifetime); /* ChannelLifetime (8 bytes) */ -- rts_client_keepalive_command_write(&buffer[76], -- rpc->KeepAliveInterval); /* ClientKeepalive (8 bytes) */ -- rts_association_group_id_command_write(&buffer[84], -- AssociationGroupId); /* AssociationGroupId (20 bytes) */ -- length = header.header.frag_length; -- status = rpc_channel_write(&inChannel->common, buffer, length); -- free(buffer); -- return (status > 0) ? 1 : -1; -+ goto fail; -+ if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */ -+ goto fail; -+ if (!rts_version_command_write(buffer)) /* Version (8 bytes) */ -+ goto fail; -+ if (!rts_cookie_command_write(buffer, -+ VirtualConnectionCookie)) /* VirtualConnectionCookie (20 bytes) */ -+ goto fail; -+ if (!rts_cookie_command_write(buffer, INChannelCookie)) /* INChannelCookie (20 bytes) */ -+ goto fail; -+ if (!rts_channel_lifetime_command_write(buffer, -+ rpc->ChannelLifetime)) /* ChannelLifetime (8 bytes) */ -+ goto fail; -+ if (!rts_client_keepalive_command_write(buffer, -+ rpc->KeepAliveInterval)) /* ClientKeepalive (8 bytes) */ -+ goto fail; -+ if (!rts_association_group_id_command_write( -+ buffer, AssociationGroupId)) /* AssociationGroupId (20 bytes) */ -+ goto fail; -+ status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length); -+fail: -+ Stream_Free(buffer, TRUE); -+ return status; - } - - /* CONN/C Sequence */ - --int rts_recv_CONN_C2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) -+BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc, wStream* buffer) - { -- UINT32 offset; -+ BOOL rc; - UINT32 ReceiveWindowSize; - UINT32 ConnectionTimeout; -- offset = 24; -- offset += rts_version_command_read(rpc, &buffer[offset], length - offset) + 4; -- offset += rts_receive_window_size_command_read(rpc, &buffer[offset], length - offset, -- &ReceiveWindowSize) + -- 4; -- offset += rts_connection_timeout_command_read(rpc, &buffer[offset], length - offset, -- &ConnectionTimeout) + -- 4; -+ -+ assert(rpc); -+ assert(buffer); -+ -+ if (!Stream_SafeSeek(buffer, 24)) -+ return FALSE; -+ -+ rc = rts_version_command_read(rpc, buffer); -+ if (rc < 0) -+ return rc; -+ rc = rts_receive_window_size_command_read(rpc, buffer, &ReceiveWindowSize); -+ if (rc < 0) -+ return rc; -+ rc = rts_connection_timeout_command_read(rpc, buffer, &ConnectionTimeout); -+ if (rc < 0) -+ return rc; - WLog_DBG(TAG, - "Receiving CONN/C2 RTS PDU: ConnectionTimeout: %" PRIu32 " ReceiveWindowSize: %" PRIu32 - "", - ConnectionTimeout, ReceiveWindowSize); -+ -+ assert(rpc); -+ assert(rpc->VirtualConnection); -+ assert(rpc->VirtualConnection->DefaultInChannel); -+ - rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout; - rpc->VirtualConnection->DefaultInChannel->PeerReceiveWindow = ReceiveWindowSize; -- return 1; -+ return TRUE; - } - - /* Out-of-Sequence PDUs */ - --static int rts_send_keep_alive_pdu(rdpRpc* rpc) -+BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc) - { -- int status; -- BYTE* buffer; -- UINT32 length; -+ BOOL status = FALSE; -+ wStream* buffer; - rpcconn_rts_hdr_t header = rts_pdu_header_init(); -- RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel; -+ UINT32 BytesReceived; -+ UINT32 AvailableWindow; -+ BYTE* ChannelCookie; -+ RpcVirtualConnection* connection; -+ RpcInChannel* inChannel; -+ RpcOutChannel* outChannel; - -- header.header.frag_length = 28; -- header.Flags = RTS_FLAG_OTHER_CMD; -- header.NumberOfCommands = 1; -- WLog_DBG(TAG, "Sending Keep-Alive RTS PDU"); -- buffer = (BYTE*)malloc(header.header.frag_length); -+ assert(rpc); - -- if (!buffer) -- return -1; -+ connection = rpc->VirtualConnection; -+ assert(connection); - -- CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */ -- rts_client_keepalive_command_write( -- &buffer[20], rpc->CurrentKeepAliveInterval); /* ClientKeepAlive (8 bytes) */ -- length = header.header.frag_length; -- status = rpc_channel_write(&inChannel->common, buffer, length); -- free(buffer); -- return (status > 0) ? 1 : -1; --} -+ inChannel = connection->DefaultInChannel; -+ assert(inChannel); - --int rts_send_flow_control_ack_pdu(rdpRpc* rpc) --{ -- int status; -- BYTE* buffer; -- UINT32 length; -- rpcconn_rts_hdr_t header = rts_pdu_header_init(); -- UINT32 BytesReceived; -- UINT32 AvailableWindow; -- BYTE* ChannelCookie; -- RpcVirtualConnection* connection = rpc->VirtualConnection; -- RpcInChannel* inChannel = connection->DefaultInChannel; -- RpcOutChannel* outChannel = connection->DefaultOutChannel; -+ outChannel = connection->DefaultOutChannel; -+ assert(outChannel); - - header.header.frag_length = 56; - header.Flags = RTS_FLAG_OTHER_CMD; - header.NumberOfCommands = 2; -+ - WLog_DBG(TAG, "Sending FlowControlAck RTS PDU"); -+ - BytesReceived = outChannel->BytesReceived; - AvailableWindow = outChannel->AvailableWindowAdvertised; - ChannelCookie = (BYTE*)&(outChannel->common.Cookie); - outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised; -- buffer = (BYTE*)malloc(header.header.frag_length); -+ buffer = Stream_New(NULL, header.header.frag_length); - - if (!buffer) -- return -1; -+ goto fail; -+ -+ if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */ -+ goto fail; -+ if (!rts_destination_command_write(buffer, FDOutProxy)) /* Destination Command (8 bytes) */ -+ goto fail; - -- CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */ -- rts_destination_command_write(&buffer[20], FDOutProxy); /* Destination Command (8 bytes) */ - /* FlowControlAck Command (28 bytes) */ -- rts_flow_control_ack_command_write(&buffer[28], BytesReceived, AvailableWindow, ChannelCookie); -- length = header.header.frag_length; -- status = rpc_channel_write(&inChannel->common, buffer, length); -- free(buffer); -- return (status > 0) ? 1 : -1; -+ if (!rts_flow_control_ack_command_write(buffer, BytesReceived, AvailableWindow, ChannelCookie)) -+ goto fail; -+ -+ status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length); -+fail: -+ Stream_Free(buffer, TRUE); -+ return status; - } - --static int rts_recv_flow_control_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) -+static int rts_recv_flow_control_ack_pdu(rdpRpc* rpc, wStream* buffer) - { -- UINT32 offset; -+ int rc; - UINT32 BytesReceived; - UINT32 AvailableWindow; -- BYTE ChannelCookie[16]; -- offset = 24; -- offset += -- rts_flow_control_ack_command_read(rpc, &buffer[offset], length - offset, &BytesReceived, -- &AvailableWindow, (BYTE*)&ChannelCookie) + -- 4; -+ BYTE ChannelCookie[16] = { 0 }; -+ -+ rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow, -+ (BYTE*)&ChannelCookie); -+ if (rc < 0) -+ return rc; - WLog_ERR(TAG, - "Receiving FlowControlAck RTS PDU: BytesReceived: %" PRIu32 - " AvailableWindow: %" PRIu32 "", - BytesReceived, AvailableWindow); -+ -+ assert(rpc->VirtualConnection); -+ assert(rpc->VirtualConnection->DefaultInChannel); -+ - rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow = - AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived); - return 1; - } - --static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) -+static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, wStream* buffer) - { -- UINT32 offset; -+ int rc; - UINT32 Destination; - UINT32 BytesReceived; - UINT32 AvailableWindow; -- BYTE ChannelCookie[16]; -+ BYTE ChannelCookie[16] = { 0 }; - /** - * When the sender receives a FlowControlAck RTS PDU, it MUST use the following formula to - * recalculate its Sender AvailableWindow variable: -@@ -622,16 +1722,23 @@ static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, BYTE* buf - * structure in the PDU received. - * - */ -- offset = 24; -- offset += rts_destination_command_read(rpc, &buffer[offset], length - offset, &Destination) + 4; -- offset += -- rts_flow_control_ack_command_read(rpc, &buffer[offset], length - offset, &BytesReceived, -- &AvailableWindow, (BYTE*)&ChannelCookie) + -- 4; -+ -+ rc = rts_destination_command_read(rpc, buffer, &Destination); -+ if (rc < 0) -+ return rc; -+ -+ rc = rts_flow_control_ack_command_read(rpc, buffer, &BytesReceived, &AvailableWindow, -+ ChannelCookie); -+ if (rc < 0) -+ return rc; -+ - WLog_DBG(TAG, - "Receiving FlowControlAckWithDestination RTS PDU: BytesReceived: %" PRIu32 - " AvailableWindow: %" PRIu32 "", - BytesReceived, AvailableWindow); -+ -+ assert(rpc->VirtualConnection); -+ assert(rpc->VirtualConnection->DefaultInChannel); - rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow = - AvailableWindow - (rpc->VirtualConnection->DefaultInChannel->BytesSent - BytesReceived); - return 1; -@@ -639,31 +1746,41 @@ static int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, BYTE* buf - - static int rts_send_ping_pdu(rdpRpc* rpc) - { -- int status; -- BYTE* buffer; -- UINT32 length; -+ BOOL status = FALSE; -+ wStream* buffer; - rpcconn_rts_hdr_t header = rts_pdu_header_init(); -- RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel; -+ RpcInChannel* inChannel; -+ -+ assert(rpc); -+ assert(rpc->VirtualConnection); -+ -+ inChannel = rpc->VirtualConnection->DefaultInChannel; -+ assert(inChannel); - - header.header.frag_length = 20; - header.Flags = RTS_FLAG_PING; - header.NumberOfCommands = 0; -+ - WLog_DBG(TAG, "Sending Ping RTS PDU"); -- buffer = (BYTE*)malloc(header.header.frag_length); -+ buffer = Stream_New(NULL, header.header.frag_length); - - if (!buffer) -- return -1; -- -- CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */ -- length = header.header.frag_length; -- status = rpc_channel_write(&inChannel->common, buffer, length); -- free(buffer); -- return (status > 0) ? 1 : -1; -+ goto fail; -+ -+ if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */ -+ goto fail; -+ status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length); -+fail: -+ Stream_Free(buffer, TRUE); -+ return (status) ? 1 : -1; - } - --SSIZE_T rts_command_length(UINT32 CommandType, const BYTE* buffer, size_t length) -+BOOL rts_command_length(UINT32 CommandType, wStream* s, size_t* length) - { -- int CommandLength = 0; -+ size_t padding = 0; -+ size_t CommandLength = 0; -+ -+ assert(s); - - switch (CommandType) - { -@@ -700,7 +1817,8 @@ SSIZE_T rts_command_length(UINT32 CommandType, const BYTE* buffer, size_t length - break; - - case RTS_CMD_PADDING: /* variable-size */ -- CommandLength = rts_padding_command_read(buffer, length); -+ if (!rts_padding_command_read(s, &padding)) -+ return FALSE; - break; - - case RTS_CMD_NEGATIVE_ANCE: -@@ -712,7 +1830,8 @@ SSIZE_T rts_command_length(UINT32 CommandType, const BYTE* buffer, size_t length - break; - - case RTS_CMD_CLIENT_ADDRESS: /* variable-size */ -- CommandLength = rts_client_address_command_read(buffer, length); -+ if (!rts_client_address_command_read(s, &CommandLength)) -+ return FALSE; - break; - - case RTS_CMD_ASSOCIATION_GROUP_ID: -@@ -729,118 +1848,176 @@ SSIZE_T rts_command_length(UINT32 CommandType, const BYTE* buffer, size_t length - - default: - WLog_ERR(TAG, "Error: Unknown RTS Command Type: 0x%" PRIx32 "", CommandType); -- return -1; -+ return FALSE; - } - -- return CommandLength; -+ CommandLength += padding; -+ if (Stream_GetRemainingLength(s) < CommandLength) -+ return FALSE; -+ -+ if (length) -+ *length = CommandLength; -+ return TRUE; - } - - static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc) - { -- int status; -- BYTE* buffer; -+ BOOL status = FALSE; -+ wStream* buffer; - rpcconn_rts_hdr_t header = rts_pdu_header_init(); - BYTE* SuccessorChannelCookie; -- RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel; -- RpcOutChannel* nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel; -+ RpcInChannel* inChannel; -+ RpcOutChannel* nextOutChannel; -+ -+ assert(rpc); -+ assert(rpc->VirtualConnection); -+ -+ inChannel = rpc->VirtualConnection->DefaultInChannel; -+ assert(inChannel); -+ -+ nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel; -+ assert(nextOutChannel); - - header.header.frag_length = 56; - header.Flags = RTS_FLAG_OUT_CHANNEL; - header.NumberOfCommands = 3; -+ - WLog_DBG(TAG, "Sending OUT_R2/A7 RTS PDU"); -+ - SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie); -- buffer = (BYTE*)malloc(header.header.frag_length); -+ buffer = Stream_New(NULL, header.header.frag_length); - - if (!buffer) - return -1; - -- CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */ -- rts_destination_command_write(&buffer[20], FDServer); /* Destination (8 bytes)*/ -- rts_cookie_command_write(&buffer[28], -- SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */ -- rts_version_command_write(&buffer[48]); /* Version (8 bytes) */ -- status = rpc_channel_write(&inChannel->common, buffer, header.header.frag_length); -- free(buffer); -- return (status > 0) ? 1 : -1; -+ if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */ -+ goto fail; -+ if (!rts_destination_command_write(buffer, FDServer)) /* Destination (8 bytes)*/ -+ goto fail; -+ if (!rts_cookie_command_write(buffer, -+ SuccessorChannelCookie)) /* SuccessorChannelCookie (20 bytes) */ -+ goto fail; -+ if (!rts_version_command_write(buffer)) /* Version (8 bytes) */ -+ goto fail; -+ status = rts_send_buffer(&inChannel->common, buffer, header.header.frag_length); -+fail: -+ Stream_Free(buffer, TRUE); -+ return (status) ? 1 : -1; - } - - static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc) - { -- int status; -- BYTE* buffer; -+ BOOL status = FALSE; -+ wStream* buffer; - rpcconn_rts_hdr_t header = rts_pdu_header_init(); -- RpcOutChannel* nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel; -+ RpcOutChannel* nextOutChannel; -+ -+ assert(rpc); -+ assert(rpc->VirtualConnection); -+ -+ nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel; -+ assert(nextOutChannel); - - header.header.frag_length = 24; - header.Flags = RTS_FLAG_PING; - header.NumberOfCommands = 1; -+ - WLog_DBG(TAG, "Sending OUT_R2/C1 RTS PDU"); -- buffer = (BYTE*)malloc(header.header.frag_length); -+ buffer = Stream_New(NULL, header.header.frag_length); - - if (!buffer) - return -1; - -- CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */ -- rts_empty_command_write(&buffer[20]); /* Empty command (4 bytes) */ -- status = rpc_channel_write(&nextOutChannel->common, buffer, header.header.frag_length); -- free(buffer); -- return (status > 0) ? 1 : -1; -+ if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */ -+ goto fail; -+ -+ if (!rts_empty_command_write(buffer)) /* Empty command (4 bytes) */ -+ goto fail; -+ status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length); -+fail: -+ Stream_Free(buffer, TRUE); -+ return (status) ? 1 : -1; - } - --int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc) -+BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc) - { -- int status; -- BYTE* buffer; -+ BOOL status = FALSE; -+ wStream* buffer; - rpcconn_rts_hdr_t header = rts_pdu_header_init(); - UINT32 ReceiveWindowSize; - BYTE* VirtualConnectionCookie; - BYTE* PredecessorChannelCookie; - BYTE* SuccessorChannelCookie; -- RpcVirtualConnection* connection = rpc->VirtualConnection; -- RpcOutChannel* outChannel = connection->DefaultOutChannel; -- RpcOutChannel* nextOutChannel = connection->NonDefaultOutChannel; -+ RpcVirtualConnection* connection; -+ RpcOutChannel* outChannel; -+ RpcOutChannel* nextOutChannel; -+ -+ assert(rpc); -+ -+ connection = rpc->VirtualConnection; -+ assert(connection); -+ -+ outChannel = connection->DefaultOutChannel; -+ assert(outChannel); -+ -+ nextOutChannel = connection->NonDefaultOutChannel; -+ assert(nextOutChannel); - - header.header.frag_length = 96; - header.Flags = RTS_FLAG_RECYCLE_CHANNEL; - header.NumberOfCommands = 5; -+ - WLog_DBG(TAG, "Sending OUT_R1/A3 RTS PDU"); -+ - VirtualConnectionCookie = (BYTE*)&(connection->Cookie); - PredecessorChannelCookie = (BYTE*)&(outChannel->common.Cookie); - SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie); - ReceiveWindowSize = outChannel->ReceiveWindow; -- buffer = (BYTE*)malloc(header.header.frag_length); -+ buffer = Stream_New(NULL, header.header.frag_length); - - if (!buffer) - return -1; - -- CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */ -- rts_version_command_write(&buffer[20]); /* Version (8 bytes) */ -- rts_cookie_command_write(&buffer[28], -- VirtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */ -- rts_cookie_command_write(&buffer[48], -- PredecessorChannelCookie); /* PredecessorChannelCookie (20 bytes) */ -- rts_cookie_command_write(&buffer[68], -- SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */ -- rts_receive_window_size_command_write(&buffer[88], -- ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */ -- status = rpc_channel_write(&nextOutChannel->common, buffer, header.header.frag_length); -- free(buffer); -- return (status > 0) ? 1 : -1; -+ if (!rts_write_pdu_header(buffer, &header)) /* RTS Header (20 bytes) */ -+ goto fail; -+ if (!rts_version_command_write(buffer)) /* Version (8 bytes) */ -+ goto fail; -+ if (!rts_cookie_command_write(buffer, -+ VirtualConnectionCookie)) /* VirtualConnectionCookie (20 bytes) */ -+ goto fail; -+ if (!rts_cookie_command_write( -+ buffer, PredecessorChannelCookie)) /* PredecessorChannelCookie (20 bytes) */ -+ goto fail; -+ if (!rts_cookie_command_write(buffer, -+ SuccessorChannelCookie)) /* SuccessorChannelCookie (20 bytes) */ -+ goto fail; -+ if (!rts_receive_window_size_command_write(buffer, -+ ReceiveWindowSize)) /* ReceiveWindowSize (8 bytes) */ -+ goto fail; -+ -+ status = rts_send_buffer(&nextOutChannel->common, buffer, header.header.frag_length); -+fail: -+ Stream_Free(buffer, TRUE); -+ return status; - } - --static int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) -+static int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc, wStream* buffer) - { - int status; -- UINT32 offset; - UINT32 Destination = 0; -- RpcVirtualConnection* connection = rpc->VirtualConnection; -+ RpcVirtualConnection* connection; -+ assert(rpc); -+ assert(buffer); -+ -+ connection = rpc->VirtualConnection; -+ assert(connection); -+ - WLog_DBG(TAG, "Receiving OUT R1/A2 RTS PDU"); -- offset = 24; - -- if (length < offset) -- return -1; -+ status = rts_destination_command_read(rpc, buffer, &Destination); -+ if (status < 0) -+ return status; - -- rts_destination_command_read(rpc, &buffer[offset], length - offset, &Destination); - connection->NonDefaultOutChannel = rpc_out_channel_new(rpc); - - if (!connection->NonDefaultOutChannel) -@@ -859,10 +2036,17 @@ static int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) - return 1; - } - --static int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) -+static int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc, wStream* buffer) - { - int status; -- RpcVirtualConnection* connection = rpc->VirtualConnection; -+ RpcVirtualConnection* connection; -+ -+ assert(rpc); -+ assert(buffer); -+ -+ connection = rpc->VirtualConnection; -+ assert(connection); -+ - WLog_DBG(TAG, "Receiving OUT R2/A6 RTS PDU"); - status = rts_send_OUT_R2_C1_pdu(rpc); - -@@ -887,47 +2071,59 @@ static int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) - return 1; - } - --static int rts_recv_OUT_R2_B3_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) -+static int rts_recv_OUT_R2_B3_pdu(rdpRpc* rpc, wStream* buffer) - { -- RpcVirtualConnection* connection = rpc->VirtualConnection; -+ RpcVirtualConnection* connection; -+ -+ assert(rpc); -+ assert(buffer); -+ -+ connection = rpc->VirtualConnection; -+ assert(connection); -+ - WLog_DBG(TAG, "Receiving OUT R2/B3 RTS PDU"); - rpc_out_channel_transition_to_state(connection->DefaultOutChannel, - CLIENT_OUT_CHANNEL_STATE_RECYCLED); - return 1; - } - --int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) -+BOOL rts_recv_out_of_sequence_pdu(rdpRpc* rpc, wStream* buffer, const rpcconn_hdr_t* header) - { -- int status = -1; -+ BOOL status = FALSE; - UINT32 SignatureId; -- rpcconn_rts_hdr_t* rts; -- RtsPduSignature signature; -+ size_t length, total; -+ RtsPduSignature signature = { 0 }; - RpcVirtualConnection* connection; - -- if (!rpc || !buffer) -- return -1; -+ assert(rpc); -+ assert(buffer); -+ assert(header); -+ -+ total = Stream_Length(buffer); -+ length = header->common.frag_length; -+ if (total < length) -+ return FALSE; - - connection = rpc->VirtualConnection; - - if (!connection) -- return -1; -- -- rts = (rpcconn_rts_hdr_t*)buffer; -+ return FALSE; - -- if (!rts_extract_pdu_signature(&signature, rts)) -- return -1; -+ if (!rts_extract_pdu_signature(&signature, buffer, header)) -+ return FALSE; - - SignatureId = rts_identify_pdu_signature(&signature, NULL); - -- if (rts_match_pdu_signature(&RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE, rts)) -+ if (rts_match_pdu_signature(&RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE, buffer, header)) - { -- status = rts_recv_flow_control_ack_pdu(rpc, buffer, length); -+ status = rts_recv_flow_control_ack_pdu(rpc, buffer); - } -- else if (rts_match_pdu_signature(&RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE, rts)) -+ else if (rts_match_pdu_signature(&RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE, buffer, -+ header)) - { -- status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer, length); -+ status = rts_recv_flow_control_ack_with_destination_pdu(rpc, buffer); - } -- else if (rts_match_pdu_signature(&RTS_PDU_PING_SIGNATURE, rts)) -+ else if (rts_match_pdu_signature(&RTS_PDU_PING_SIGNATURE, buffer, header)) - { - status = rts_send_ping_pdu(rpc); - } -@@ -935,28 +2131,28 @@ int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) - { - if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED) - { -- if (rts_match_pdu_signature(&RTS_PDU_OUT_R1_A2_SIGNATURE, rts)) -+ if (rts_match_pdu_signature(&RTS_PDU_OUT_R1_A2_SIGNATURE, buffer, header)) - { -- status = rts_recv_OUT_R1_A2_pdu(rpc, buffer, length); -+ status = rts_recv_OUT_R1_A2_pdu(rpc, buffer); - } - } - else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_A6W) - { -- if (rts_match_pdu_signature(&RTS_PDU_OUT_R2_A6_SIGNATURE, rts)) -+ if (rts_match_pdu_signature(&RTS_PDU_OUT_R2_A6_SIGNATURE, buffer, header)) - { -- status = rts_recv_OUT_R2_A6_pdu(rpc, buffer, length); -+ status = rts_recv_OUT_R2_A6_pdu(rpc, buffer); - } - } - else if (connection->DefaultOutChannel->State == CLIENT_OUT_CHANNEL_STATE_OPENED_B3W) - { -- if (rts_match_pdu_signature(&RTS_PDU_OUT_R2_B3_SIGNATURE, rts)) -+ if (rts_match_pdu_signature(&RTS_PDU_OUT_R2_B3_SIGNATURE, buffer, header)) - { -- status = rts_recv_OUT_R2_B3_pdu(rpc, buffer, length); -+ status = rts_recv_OUT_R2_B3_pdu(rpc, buffer); - } - } - } - -- if (status < 0) -+ if (!status) - { - WLog_ERR(TAG, "error parsing RTS PDU with signature id: 0x%08" PRIX32 "", SignatureId); - rts_print_pdu_signature(&signature); -@@ -964,3 +2160,42 @@ int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) - - return status; - } -+ -+BOOL rts_write_pdu_auth3(wStream* s, const rpcconn_rpc_auth_3_hdr_t* auth) -+{ -+ assert(s); -+ assert(auth); -+ -+ if (!rts_write_common_pdu_header(s, &auth->header)) -+ return FALSE; -+ -+ if (!Stream_EnsureRemainingCapacity(s, 2 * sizeof(UINT16))) -+ return FALSE; -+ -+ Stream_Write_UINT16(s, auth->max_xmit_frag); -+ Stream_Write_UINT16(s, auth->max_recv_frag); -+ -+ return rts_write_auth_verifier(s, &auth->auth_verifier, &auth->header); -+} -+ -+BOOL rts_write_pdu_bind(wStream* s, const rpcconn_bind_hdr_t* bind) -+{ -+ -+ assert(s); -+ assert(bind); -+ -+ if (!rts_write_common_pdu_header(s, &bind->header)) -+ return FALSE; -+ -+ if (!Stream_EnsureRemainingCapacity(s, 8)) -+ return FALSE; -+ -+ Stream_Write_UINT16(s, bind->max_xmit_frag); -+ Stream_Write_UINT16(s, bind->max_recv_frag); -+ Stream_Write_UINT32(s, bind->assoc_group_id); -+ -+ if (!rts_write_context_list(s, &bind->p_context_elem)) -+ return FALSE; -+ -+ return rts_write_auth_verifier(s, &bind->auth_verifier, &bind->header); -+} -diff --git a/libfreerdp/core/gateway/rts.h b/libfreerdp/core/gateway/rts.h -index ccc4cfd..01a66a7 100644 ---- a/libfreerdp/core/gateway/rts.h -+++ b/libfreerdp/core/gateway/rts.h -@@ -24,12 +24,14 @@ - #include "config.h" - #endif - --#include "rpc.h" -+#include - - #include - #include - #include - -+#include "rpc.h" -+ - #define RTS_FLAG_NONE 0x0000 - #define RTS_FLAG_PING 0x0001 - #define RTS_FLAG_OTHER_CMD 0x0002 -@@ -79,21 +81,28 @@ - - FREERDP_LOCAL void rts_generate_cookie(BYTE* cookie); - --FREERDP_LOCAL SSIZE_T rts_command_length(UINT32 CommandType, const BYTE* buffer, size_t length); -+FREERDP_LOCAL BOOL rts_write_pdu_auth3(wStream* s, const rpcconn_rpc_auth_3_hdr_t* auth); -+FREERDP_LOCAL BOOL rts_write_pdu_bind(wStream* s, const rpcconn_bind_hdr_t* bind); -+ -+FREERDP_LOCAL BOOL rts_read_pdu_header(wStream* s, rpcconn_hdr_t* header); -+FREERDP_LOCAL void rts_free_pdu_header(rpcconn_hdr_t* header, BOOL allocated); -+ -+FREERDP_LOCAL BOOL rts_read_common_pdu_header(wStream* s, rpcconn_common_hdr_t* header); - --FREERDP_LOCAL int rts_send_CONN_A1_pdu(rdpRpc* rpc); --FREERDP_LOCAL int rts_recv_CONN_A3_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length); -+FREERDP_LOCAL BOOL rts_command_length(UINT32 CommandType, wStream* s, size_t* length); - --FREERDP_LOCAL int rts_send_CONN_B1_pdu(rdpRpc* rpc); -+FREERDP_LOCAL BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc); -+FREERDP_LOCAL BOOL rts_recv_CONN_A3_pdu(rdpRpc* rpc, wStream* buffer); - --FREERDP_LOCAL int rts_recv_CONN_C2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length); -+FREERDP_LOCAL BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc); - --FREERDP_LOCAL int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc); -+FREERDP_LOCAL BOOL rts_recv_CONN_C2_pdu(rdpRpc* rpc, wStream* buffer); - --FREERDP_LOCAL int rts_send_flow_control_ack_pdu(rdpRpc* rpc); -+FREERDP_LOCAL BOOL rts_send_OUT_R1_A3_pdu(rdpRpc* rpc); - --FREERDP_LOCAL int rts_recv_out_of_sequence_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length); -+FREERDP_LOCAL BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc); - --#include "rts_signature.h" -+FREERDP_LOCAL BOOL rts_recv_out_of_sequence_pdu(rdpRpc* rpc, wStream* buffer, -+ const rpcconn_hdr_t* header); - - #endif /* FREERDP_LIB_CORE_GATEWAY_RTS_H */ -diff --git a/libfreerdp/core/gateway/rts_signature.c b/libfreerdp/core/gateway/rts_signature.c -index 4d605f0..b9319d1 100644 ---- a/libfreerdp/core/gateway/rts_signature.c -+++ b/libfreerdp/core/gateway/rts_signature.c -@@ -17,6 +17,9 @@ - * limitations under the License. - */ - -+#include -+#include -+ - #include - - #include "rts_signature.h" -@@ -276,90 +279,74 @@ static const RTS_PDU_SIGNATURE_ENTRY RTS_PDU_SIGNATURE_TABLE[] = { - { RTS_PDU_PING, TRUE, &RTS_PDU_PING_SIGNATURE, "Ping" }, - { RTS_PDU_FLOW_CONTROL_ACK, TRUE, &RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE, "FlowControlAck" }, - { RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION, TRUE, -- &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE, "FlowControlAckWithDestination" }, -- -- { 0, FALSE, NULL, NULL } -+ &RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE, "FlowControlAckWithDestination" } - }; - --BOOL rts_match_pdu_signature(const RtsPduSignature* signature, const rpcconn_rts_hdr_t* rts) -+BOOL rts_match_pdu_signature(const RtsPduSignature* signature, wStream* src, -+ const rpcconn_hdr_t* header) - { -- UINT16 i; -- int status; -- const BYTE* buffer; -- UINT32 length; -- UINT32 offset; -- UINT32 CommandType; -- UINT32 CommandLength; -- -- if (!signature || !rts) -- return FALSE; -+ RtsPduSignature extracted = { 0 }; - -- if (rts->Flags != signature->Flags) -- return FALSE; -+ assert(signature); -+ assert(src); - -- if (rts->NumberOfCommands != signature->NumberOfCommands) -+ if (!rts_extract_pdu_signature(&extracted, src, header)) - return FALSE; - -- buffer = (const BYTE*)rts; -- offset = RTS_PDU_HEADER_LENGTH; -- length = rts->header.frag_length - offset; -- -- for (i = 0; i < rts->NumberOfCommands; i++) -- { -- CommandType = *((UINT32*)&buffer[offset]); /* CommandType (4 bytes) */ -- offset += 4; -- -- if (CommandType != signature->CommandTypes[i]) -- return FALSE; -+ return memcmp(signature, &extracted, sizeof(extracted)) == 0; -+} - -- status = rts_command_length(CommandType, &buffer[offset], length); -+BOOL rts_extract_pdu_signature(RtsPduSignature* signature, wStream* src, -+ const rpcconn_hdr_t* header) -+{ -+ BOOL rc = FALSE; -+ UINT16 i; -+ wStream tmp; -+ rpcconn_hdr_t rheader = { 0 }; -+ const rpcconn_rts_hdr_t* rts; - -- if (status < 0) -- return FALSE; -+ assert(signature); -+ assert(src); - -- CommandLength = (UINT32)status; -- offset += CommandLength; -- length = rts->header.frag_length - offset; -+ Stream_StaticInit(&tmp, Stream_Pointer(src), Stream_GetRemainingLength(src)); -+ if (!header) -+ { -+ if (!rts_read_pdu_header(&tmp, &rheader)) -+ goto fail; -+ header = &rheader; - } -- -- return TRUE; --} -- --BOOL rts_extract_pdu_signature(RtsPduSignature* signature, const rpcconn_rts_hdr_t* rts) --{ -- int i; -- int status; -- BYTE* buffer; -- UINT32 length; -- UINT32 offset; -- UINT32 CommandType; -- UINT32 CommandLength; -- -- if (!signature || !rts) -- return FALSE; -+ rts = &header->rts; -+ if (rts->header.frag_length < sizeof(rpcconn_rts_hdr_t)) -+ goto fail; - - signature->Flags = rts->Flags; - signature->NumberOfCommands = rts->NumberOfCommands; -- buffer = (BYTE*)rts; -- offset = RTS_PDU_HEADER_LENGTH; -- length = rts->header.frag_length - offset; - - for (i = 0; i < rts->NumberOfCommands; i++) - { -- CommandType = *((UINT32*)&buffer[offset]); /* CommandType (4 bytes) */ -- offset += 4; -- signature->CommandTypes[i] = CommandType; -- status = rts_command_length(CommandType, &buffer[offset], length); -+ UINT32 CommandType; -+ size_t CommandLength; -+ -+ if (Stream_GetRemainingLength(&tmp) < 4) -+ goto fail; -+ -+ Stream_Read_UINT32(&tmp, CommandType); /* CommandType (4 bytes) */ - -- if (status < 0) -- return FALSE; -+ /* We only need this for comparison against known command types */ -+ if (i < ARRAYSIZE(signature->CommandTypes)) -+ signature->CommandTypes[i] = CommandType; - -- CommandLength = (UINT32)status; -- offset += CommandLength; -- length = rts->header.frag_length - offset; -+ if (!rts_command_length(CommandType, &tmp, &CommandLength)) -+ goto fail; -+ if (!Stream_SafeSeek(&tmp, CommandLength)) -+ goto fail; - } - -- return TRUE; -+ rc = TRUE; -+fail: -+ rts_free_pdu_header(&rheader, FALSE); -+ Stream_Free(&tmp, FALSE); -+ return rc; - } - - UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature, -@@ -367,11 +354,15 @@ UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature, - { - size_t i, j; - -- for (i = 0; RTS_PDU_SIGNATURE_TABLE[i].SignatureId != 0; i++) -+ if (entry) -+ *entry = NULL; -+ -+ for (i = 0; i < ARRAYSIZE(RTS_PDU_SIGNATURE_TABLE); i++) - { -- const RtsPduSignature* pSignature = RTS_PDU_SIGNATURE_TABLE[i].Signature; -+ const RTS_PDU_SIGNATURE_ENTRY* current = &RTS_PDU_SIGNATURE_TABLE[i]; -+ const RtsPduSignature* pSignature = current->Signature; - -- if (!RTS_PDU_SIGNATURE_TABLE[i].SignatureClient) -+ if (!current->SignatureClient) - continue; - - if (signature->Flags != pSignature->Flags) -@@ -387,9 +378,9 @@ UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature, - } - - if (entry) -- *entry = &RTS_PDU_SIGNATURE_TABLE[i]; -+ *entry = current; - -- return RTS_PDU_SIGNATURE_TABLE[i].SignatureId; -+ return current->SignatureId; - } - - return 0; -diff --git a/libfreerdp/core/gateway/rts_signature.h b/libfreerdp/core/gateway/rts_signature.h -index 2c43cdc..31f0e81 100644 ---- a/libfreerdp/core/gateway/rts_signature.h -+++ b/libfreerdp/core/gateway/rts_signature.h -@@ -178,10 +178,10 @@ FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_PING_SIGNATURE; - FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_SIGNATURE; - FREERDP_LOCAL extern const RtsPduSignature RTS_PDU_FLOW_CONTROL_ACK_WITH_DESTINATION_SIGNATURE; - --FREERDP_LOCAL BOOL rts_match_pdu_signature(const RtsPduSignature* signature, -- const rpcconn_rts_hdr_t* rts); --FREERDP_LOCAL BOOL rts_extract_pdu_signature(RtsPduSignature* signature, -- const rpcconn_rts_hdr_t* rts); -+FREERDP_LOCAL BOOL rts_match_pdu_signature(const RtsPduSignature* signature, wStream* s, -+ const rpcconn_hdr_t* header); -+FREERDP_LOCAL BOOL rts_extract_pdu_signature(RtsPduSignature* signature, wStream* s, -+ const rpcconn_hdr_t* header); - FREERDP_LOCAL UINT32 rts_identify_pdu_signature(const RtsPduSignature* signature, - const RTS_PDU_SIGNATURE_ENTRY** entry); - FREERDP_LOCAL BOOL rts_print_pdu_signature(const RtsPduSignature* signature); -diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c -index 3376fb0..ee56a38 100644 ---- a/libfreerdp/core/gateway/tsg.c -+++ b/libfreerdp/core/gateway/tsg.c -@@ -24,7 +24,7 @@ - #include "config.h" - #endif - --#include -+#include - #include - #include - #include -@@ -221,7 +221,6 @@ struct rdp_tsg - UINT32 TunnelId; - UINT32 ChannelId; - BOOL reauthSequence; -- rdpSettings* settings; - rdpTransport* transport; - UINT64 ReauthTunnelContext; - CONTEXT_HANDLE TunnelContext; -@@ -310,9 +309,9 @@ static BOOL tsg_print(char** buffer, size_t* len, const char* fmt, ...) - static BOOL tsg_packet_header_to_string(char** buffer, size_t* length, - const TSG_PACKET_HEADER* header) - { -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(header); -+ assert(buffer); -+ assert(length); -+ assert(header); - - return tsg_print(buffer, length, - "header { ComponentId=0x%04" PRIx16 ", PacketId=0x%04" PRIx16 " }", -@@ -322,9 +321,9 @@ static BOOL tsg_packet_header_to_string(char** buffer, size_t* length, - static BOOL tsg_type_capability_nap_to_string(char** buffer, size_t* length, - const TSG_CAPABILITY_NAP* cur) - { -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(cur); -+ assert(buffer); -+ assert(length); -+ assert(cur); - - return tsg_print(buffer, length, "%s { capabilities=0x%08" PRIx32 " }", - tsg_packet_id_to_string(TSG_CAPABILITY_TYPE_NAP), cur->capabilities); -@@ -335,9 +334,9 @@ static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length, - { - UINT32 x; - -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "capabilities { ")) - return FALSE; -@@ -363,9 +362,9 @@ static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length, - static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length, - const TSG_PACKET_VERSIONCAPS* caps) - { -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "versioncaps { ")) - return FALSE; -@@ -391,9 +390,9 @@ static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length, - static BOOL tsg_packet_quarconfigrequest_to_string(char** buffer, size_t* length, - const TSG_PACKET_QUARCONFIGREQUEST* caps) - { -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "quarconfigrequest { ")) - return FALSE; -@@ -414,9 +413,9 @@ static BOOL tsg_packet_quarrequest_to_string(char** buffer, size_t* length, - char* name = NULL; - char* strdata = NULL; - -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "quarrequest { ")) - return FALSE; -@@ -426,7 +425,9 @@ static BOOL tsg_packet_quarrequest_to_string(char** buffer, size_t* length, - - if (caps->nameLength > 0) - { -- if (ConvertFromUnicode(CP_UTF8, 0, caps->machineName, caps->nameLength, &name, 0, NULL, -+ if (caps->nameLength > INT_MAX) -+ return FALSE; -+ if (ConvertFromUnicode(CP_UTF8, 0, caps->machineName, (int)caps->nameLength, &name, 0, NULL, - NULL) < 0) - return FALSE; - } -@@ -454,8 +455,8 @@ static const char* tsg_bool_to_string(BOOL val) - static const char* tsg_redirection_flags_to_string(char* buffer, size_t size, - const TSG_REDIRECTION_FLAGS* flags) - { -- WINPR_ASSERT(buffer || (size == 0)); -- WINPR_ASSERT(flags); -+ assert(buffer || (size == 0)); -+ assert(flags); - - _snprintf(buffer, size, - "enableAllRedirections=%s, disableAllRedirections=%s, driveRedirectionDisabled=%s, " -@@ -479,9 +480,9 @@ static BOOL tsg_packet_response_to_string(char** buffer, size_t* length, - char* strdata = NULL; - char tbuffer[8192] = { 0 }; - -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "response { ")) - return FALSE; -@@ -514,9 +515,9 @@ static BOOL tsg_packet_quarenc_response_to_string(char** buffer, size_t* length, - size_t size = ARRAYSIZE(tbuffer); - char* ptbuffer = tbuffer; - -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "quarenc_response { ")) - return FALSE; -@@ -526,8 +527,10 @@ static BOOL tsg_packet_quarenc_response_to_string(char** buffer, size_t* length, - - if (caps->certChainLen > 0) - { -- if (ConvertFromUnicode(CP_UTF8, 0, caps->certChainData, caps->certChainLen, &strdata, 0, -- NULL, NULL) <= 0) -+ if (caps->certChainLen > INT_MAX) -+ return FALSE; -+ if (ConvertFromUnicode(CP_UTF8, 0, caps->certChainData, (int)caps->certChainLen, &strdata, -+ 0, NULL, NULL) <= 0) - return FALSE; - } - -@@ -549,9 +552,9 @@ static BOOL tsg_packet_quarenc_response_to_string(char** buffer, size_t* length, - static BOOL tsg_packet_message_response_to_string(char** buffer, size_t* length, - const TSG_PACKET_MSG_RESPONSE* caps) - { -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "msg_response { ")) - return FALSE; -@@ -567,9 +570,9 @@ static BOOL tsg_packet_message_response_to_string(char** buffer, size_t* length, - static BOOL tsg_packet_caps_response_to_string(char** buffer, size_t* length, - const TSG_PACKET_CAPS_RESPONSE* caps) - { -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "caps_response { ")) - return FALSE; -@@ -586,9 +589,9 @@ static BOOL tsg_packet_caps_response_to_string(char** buffer, size_t* length, - static BOOL tsg_packet_message_request_to_string(char** buffer, size_t* length, - const TSG_PACKET_MSG_REQUEST* caps) - { -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "caps_message_request { ")) - return FALSE; -@@ -603,9 +606,9 @@ static BOOL tsg_packet_auth_to_string(char** buffer, size_t* length, const TSG_P - { - BOOL rc = FALSE; - char* strdata = NULL; -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "caps_message_request { ")) - return FALSE; -@@ -627,14 +630,14 @@ static BOOL tsg_packet_reauth_to_string(char** buffer, size_t* length, - const TSG_PACKET_REAUTH* caps) - { - BOOL rc = FALSE; -- WINPR_ASSERT(buffer); -- WINPR_ASSERT(length); -- WINPR_ASSERT(caps); -+ assert(buffer); -+ assert(length); -+ assert(caps); - - if (!tsg_print(buffer, length, "caps_message_request { ")) - return FALSE; - -- if (!tsg_print(buffer, length, " tunnelContext=0x%08" PRIx32 ", packetId=%s [0x%08" PRIx32 "]", -+ if (!tsg_print(buffer, length, " tunnelContext=0x%016" PRIx64 ", packetId=%s [0x%08" PRIx32 "]", - caps->tunnelContext, tsg_packet_id_to_string(caps->packetId), caps->packetId)) - return FALSE; - -@@ -793,7 +796,7 @@ static int TsProxySendToServer(handle_t IDL_handle, const byte pRpcMessage[], UI - { - wStream* s; - rdpTsg* tsg; -- int length; -+ size_t length; - const byte* buffer1 = NULL; - const byte* buffer2 = NULL; - const byte* buffer3 = NULL; -@@ -829,7 +832,9 @@ static int TsProxySendToServer(handle_t IDL_handle, const byte pRpcMessage[], UI - totalDataBytes += lengths[2] + 4; - } - -- length = 28 + totalDataBytes; -+ length = 28ull + totalDataBytes; -+ if (length > INT_MAX) -+ return -1; - s = Stream_New(NULL, length); - - if (!s) -@@ -865,7 +870,7 @@ static int TsProxySendToServer(handle_t IDL_handle, const byte pRpcMessage[], UI - if (!rpc_client_write_call(tsg->rpc, s, TsProxySendToServerOpnum)) - return -1; - -- return length; -+ return (int)length; - } - - /** -@@ -1018,12 +1023,20 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, - UINT32 SwitchValue; - UINT32 MessageSwitchValue = 0; - UINT32 IsMessagePresent; -+ rdpContext* context; - UINT32 MsgBytes; -+ TSG_PACKET_STRING_MESSAGE packetStringMessage; - PTSG_PACKET_CAPABILITIES tsgCaps = NULL; - PTSG_PACKET_VERSIONCAPS versionCaps = NULL; - PTSG_PACKET_CAPS_RESPONSE packetCapsResponse = NULL; - PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse = NULL; - -+ assert(tsg); -+ assert(tsg->rpc); -+ -+ context = tsg->rpc->context; -+ assert(context); -+ - if (!pdu) - return FALSE; - -@@ -1170,8 +1183,8 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, - if (Stream_GetRemainingLength(pdu->s) < 16) - goto fail; - -- Stream_Seek_UINT32(pdu->s); /* IsDisplayMandatory (4 bytes) */ -- Stream_Seek_UINT32(pdu->s); /* IsConsent Mandatory (4 bytes) */ -+ Stream_Read_INT32(pdu->s, packetStringMessage.isDisplayMandatory); -+ Stream_Read_INT32(pdu->s, packetStringMessage.isConsentMandatory); - Stream_Read_UINT32(pdu->s, MsgBytes); - Stream_Read_UINT32(pdu->s, Pointer); - -@@ -1351,16 +1364,19 @@ fail: - - static BOOL TsProxyAuthorizeTunnelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnelContext) - { -- UINT32 pad; -+ size_t pad; - wStream* s; - size_t count; -- UINT32 offset; -+ size_t offset; - rdpRpc* rpc; - - if (!tsg || !tsg->rpc || !tunnelContext || !tsg->MachineName) - return FALSE; - - count = _wcslen(tsg->MachineName) + 1; -+ if (count > UINT32_MAX) -+ return FALSE; -+ - rpc = tsg->rpc; - WLog_DBG(TAG, "TsProxyAuthorizeTunnelWriteRequest"); - s = Stream_New(NULL, 1024 + count * 2); -@@ -1377,13 +1393,13 @@ static BOOL TsProxyAuthorizeTunnelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunn - Stream_Write_UINT32(s, 0x00020000); /* PacketQuarRequestPtr (4 bytes) */ - Stream_Write_UINT32(s, 0x00000000); /* Flags (4 bytes) */ - Stream_Write_UINT32(s, 0x00020004); /* MachineNamePtr (4 bytes) */ -- Stream_Write_UINT32(s, count); /* NameLength (4 bytes) */ -+ Stream_Write_UINT32(s, (UINT32)count); /* NameLength (4 bytes) */ - Stream_Write_UINT32(s, 0x00020008); /* DataPtr (4 bytes) */ - Stream_Write_UINT32(s, 0); /* DataLength (4 bytes) */ - /* MachineName */ -- Stream_Write_UINT32(s, count); /* MaxCount (4 bytes) */ -+ Stream_Write_UINT32(s, (UINT32)count); /* MaxCount (4 bytes) */ - Stream_Write_UINT32(s, 0); /* Offset (4 bytes) */ -- Stream_Write_UINT32(s, count); /* ActualCount (4 bytes) */ -+ Stream_Write_UINT32(s, (UINT32)count); /* ActualCount (4 bytes) */ - Stream_Write_UTF16_String(s, tsg->MachineName, count); /* Array */ - /* 4-byte alignment */ - offset = Stream_GetPosition(s); -@@ -1394,7 +1410,7 @@ static BOOL TsProxyAuthorizeTunnelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunn - return rpc_client_write_call(rpc, s, TsProxyAuthorizeTunnelOpnum); - } - --static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu) -+static BOOL TsProxyAuthorizeTunnelReadResponse(RPC_PDU* pdu) - { - BOOL rc = FALSE; - UINT32 Pointer; -@@ -1456,25 +1472,24 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu) - Stream_Seek_UINT32(pdu->s); /* Reserved (4 bytes) */ - Stream_Read_UINT32(pdu->s, Pointer); /* ResponseDataPtr (4 bytes) */ - Stream_Read_UINT32(pdu->s, packetResponse->responseDataLen); /* ResponseDataLength (4 bytes) */ -- Stream_Read_UINT32(pdu->s, packetResponse->redirectionFlags -- .enableAllRedirections); /* EnableAllRedirections (4 bytes) */ -- Stream_Read_UINT32(pdu->s, packetResponse->redirectionFlags -- .disableAllRedirections); /* DisableAllRedirections (4 bytes) */ -- Stream_Read_UINT32(pdu->s, -- packetResponse->redirectionFlags -- .driveRedirectionDisabled); /* DriveRedirectionDisabled (4 bytes) */ -- Stream_Read_UINT32(pdu->s, -- packetResponse->redirectionFlags -- .printerRedirectionDisabled); /* PrinterRedirectionDisabled (4 bytes) */ -- Stream_Read_UINT32(pdu->s, -- packetResponse->redirectionFlags -- .portRedirectionDisabled); /* PortRedirectionDisabled (4 bytes) */ -- Stream_Read_UINT32(pdu->s, packetResponse->redirectionFlags.reserved); /* Reserved (4 bytes) */ -- Stream_Read_UINT32( -+ Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags -+ .enableAllRedirections); /* EnableAllRedirections (4 bytes) */ -+ Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags -+ .disableAllRedirections); /* DisableAllRedirections (4 bytes) */ -+ Stream_Read_INT32(pdu->s, -+ packetResponse->redirectionFlags -+ .driveRedirectionDisabled); /* DriveRedirectionDisabled (4 bytes) */ -+ Stream_Read_INT32(pdu->s, -+ packetResponse->redirectionFlags -+ .printerRedirectionDisabled); /* PrinterRedirectionDisabled (4 bytes) */ -+ Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags -+ .portRedirectionDisabled); /* PortRedirectionDisabled (4 bytes) */ -+ Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags.reserved); /* Reserved (4 bytes) */ -+ Stream_Read_INT32( - pdu->s, packetResponse->redirectionFlags - .clipboardRedirectionDisabled); /* ClipboardRedirectionDisabled (4 bytes) */ -- Stream_Read_UINT32(pdu->s, packetResponse->redirectionFlags -- .pnpRedirectionDisabled); /* PnpRedirectionDisabled (4 bytes) */ -+ Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags -+ .pnpRedirectionDisabled); /* PnpRedirectionDisabled (4 bytes) */ - Stream_Read_UINT32(pdu->s, SizeValue); /* (4 bytes) */ - - if (SizeValue != packetResponse->responseDataLen) -@@ -1574,11 +1589,18 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu) - UINT32 Pointer; - UINT32 SwitchValue; - TSG_PACKET packet; -+ rdpContext* context; - char* messageText = NULL; - TSG_PACKET_MSG_RESPONSE packetMsgResponse = { 0 }; - TSG_PACKET_STRING_MESSAGE packetStringMessage = { 0 }; - TSG_PACKET_REAUTH_MESSAGE packetReauthMessage = { 0 }; - -+ assert(tsg); -+ assert(tsg->rpc); -+ -+ context = tsg->rpc->context; -+ assert(context); -+ - /* This is an asynchronous response */ - - if (!pdu) -@@ -1628,10 +1650,10 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu) - WLog_INFO(TAG, "Consent Message: %s", messageText); - free(messageText); - -- if (tsg->rpc && tsg->rpc->context && tsg->rpc->context->instance) -+ if (context->instance) - { -- rc = IFCALLRESULT(TRUE, tsg->rpc->context->instance->PresentGatewayMessage, -- tsg->rpc->context->instance, SwitchValue, -+ rc = IFCALLRESULT(TRUE, context->instance->PresentGatewayMessage, -+ context->instance, SwitchValue, - packetStringMessage.isDisplayMandatory != 0, - packetStringMessage.isConsentMandatory != 0, - packetStringMessage.msgBytes, packetStringMessage.msgBuffer); -@@ -1649,10 +1671,10 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu) - WLog_INFO(TAG, "Service Message: %s", messageText); - free(messageText); - -- if (tsg->rpc && tsg->rpc->context && tsg->rpc->context->instance) -+ if (context->instance) - { -- rc = IFCALLRESULT(TRUE, tsg->rpc->context->instance->PresentGatewayMessage, -- tsg->rpc->context->instance, SwitchValue, -+ rc = IFCALLRESULT(TRUE, context->instance->PresentGatewayMessage, -+ context->instance, SwitchValue, - packetStringMessage.isDisplayMandatory != 0, - packetStringMessage.isConsentMandatory != 0, - packetStringMessage.msgBytes, packetStringMessage.msgBuffer); -@@ -1704,6 +1726,8 @@ static BOOL TsProxyCreateChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnel - - rpc = tsg->rpc; - count = _wcslen(tsg->Hostname) + 1; -+ if (count > UINT32_MAX) -+ return FALSE; - s = Stream_New(NULL, 60 + count * 2); - - if (!s) -@@ -1723,15 +1747,15 @@ static BOOL TsProxyCreateChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnel - Stream_Write_UINT16(s, tsg->Port); /* PortNumber (0xD3D = 3389) (2 bytes) */ - Stream_Write_UINT32(s, 0x00000001); /* NumResourceNames (4 bytes) */ - Stream_Write_UINT32(s, 0x00020004); /* ResourceNamePtr (4 bytes) */ -- Stream_Write_UINT32(s, count); /* MaxCount (4 bytes) */ -+ Stream_Write_UINT32(s, (UINT32)count); /* MaxCount (4 bytes) */ - Stream_Write_UINT32(s, 0); /* Offset (4 bytes) */ -- Stream_Write_UINT32(s, count); /* ActualCount (4 bytes) */ -+ Stream_Write_UINT32(s, (UINT32)count); /* ActualCount (4 bytes) */ - Stream_Write_UTF16_String(s, tsg->Hostname, count); /* Array */ - return rpc_client_write_call(rpc, s, TsProxyCreateChannelOpnum); - } - --static BOOL TsProxyCreateChannelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, -- CONTEXT_HANDLE* channelContext, UINT32* channelId) -+static BOOL TsProxyCreateChannelReadResponse(RPC_PDU* pdu, CONTEXT_HANDLE* channelContext, -+ UINT32* channelId) - { - BOOL rc = FALSE; - WLog_DBG(TAG, "TsProxyCreateChannelReadResponse"); -@@ -1779,7 +1803,7 @@ static BOOL TsProxyCloseChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* context - return rpc_client_write_call(rpc, s, TsProxyCloseChannelOpnum); - } - --static BOOL TsProxyCloseChannelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, CONTEXT_HANDLE* context) -+static BOOL TsProxyCloseChannelReadResponse(RPC_PDU* pdu, CONTEXT_HANDLE* context) - { - BOOL rc = FALSE; - WLog_DBG(TAG, "TsProxyCloseChannelReadResponse"); -@@ -1826,7 +1850,7 @@ static BOOL TsProxyCloseTunnelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* context) - return rpc_client_write_call(rpc, s, TsProxyCloseTunnelOpnum); - } - --static BOOL TsProxyCloseTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, CONTEXT_HANDLE* context) -+static BOOL TsProxyCloseTunnelReadResponse(RPC_PDU* pdu, CONTEXT_HANDLE* context) - { - BOOL rc = FALSE; - WLog_DBG(TAG, "TsProxyCloseTunnelReadResponse"); -@@ -1977,8 +2001,6 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu) - return FALSE; - - rpc = tsg->rpc; -- Stream_SealLength(pdu->s); -- Stream_SetPosition(pdu->s, 0); - - if (!(pdu->Flags & RPC_PDU_FLAG_STUB)) - { -@@ -2017,7 +2039,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu) - CONTEXT_HANDLE* TunnelContext; - TunnelContext = (tsg->reauthSequence) ? &tsg->NewTunnelContext : &tsg->TunnelContext; - -- if (!TsProxyAuthorizeTunnelReadResponse(tsg, pdu)) -+ if (!TsProxyAuthorizeTunnelReadResponse(pdu)) - { - WLog_ERR(TAG, "TsProxyAuthorizeTunnelReadResponse failure"); - return FALSE; -@@ -2066,7 +2088,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu) - { - CONTEXT_HANDLE ChannelContext; - -- if (!TsProxyCreateChannelReadResponse(tsg, pdu, &ChannelContext, &tsg->ChannelId)) -+ if (!TsProxyCreateChannelReadResponse(pdu, &ChannelContext, &tsg->ChannelId)) - { - WLog_ERR(TAG, "TsProxyCreateChannelReadResponse failure"); - return FALSE; -@@ -2139,7 +2161,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu) - { - CONTEXT_HANDLE ChannelContext; - -- if (!TsProxyCloseChannelReadResponse(tsg, pdu, &ChannelContext)) -+ if (!TsProxyCloseChannelReadResponse(pdu, &ChannelContext)) - { - WLog_ERR(TAG, "TsProxyCloseChannelReadResponse failure"); - return FALSE; -@@ -2151,7 +2173,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu) - { - CONTEXT_HANDLE TunnelContext; - -- if (!TsProxyCloseTunnelReadResponse(tsg, pdu, &TunnelContext)) -+ if (!TsProxyCloseTunnelReadResponse(pdu, &TunnelContext)) - { - WLog_ERR(TAG, "TsProxyCloseTunnelReadResponse failure"); - return FALSE; -@@ -2166,7 +2188,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu) - { - CONTEXT_HANDLE ChannelContext; - -- if (!TsProxyCloseChannelReadResponse(tsg, pdu, &ChannelContext)) -+ if (!TsProxyCloseChannelReadResponse(pdu, &ChannelContext)) - { - WLog_ERR(TAG, "TsProxyCloseChannelReadResponse failure"); - return FALSE; -@@ -2196,7 +2218,7 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu) - { - CONTEXT_HANDLE TunnelContext; - -- if (!TsProxyCloseTunnelReadResponse(tsg, pdu, &TunnelContext)) -+ if (!TsProxyCloseTunnelReadResponse(pdu, &TunnelContext)) - { - WLog_ERR(TAG, "TsProxyCloseTunnelReadResponse failure"); - return FALSE; -@@ -2305,10 +2327,25 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout) - { - UINT64 looptimeout = timeout * 1000ULL; - DWORD nCount; -- HANDLE events[64]; -- rdpRpc* rpc = tsg->rpc; -- rdpSettings* settings = rpc->settings; -- rdpTransport* transport = rpc->transport; -+ HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 }; -+ rdpRpc* rpc; -+ rdpContext* context; -+ rdpSettings* settings; -+ rdpTransport* transport; -+ -+ assert(tsg); -+ -+ rpc = tsg->rpc; -+ assert(rpc); -+ -+ transport = rpc->transport; -+ assert(transport); -+ -+ context = tsg->rpc->context; -+ assert(context); -+ -+ settings = context->settings; -+ - tsg->Port = port; - tsg->transport = transport; - -@@ -2327,7 +2364,7 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout) - return FALSE; - } - -- nCount = tsg_get_event_handles(tsg, events, 64); -+ nCount = tsg_get_event_handles(tsg, events, ARRAYSIZE(events)); - - if (nCount == 0) - return FALSE; -@@ -2410,7 +2447,7 @@ BOOL tsg_disconnect(rdpTsg* tsg) - * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 bytes to read - */ - --static int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length) -+static int tsg_read(rdpTsg* tsg, BYTE* data, size_t length) - { - rdpRpc* rpc; - int status = 0; -@@ -2428,7 +2465,7 @@ static int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length) - - do - { -- status = rpc_client_receive_pipe_read(rpc->client, data, (size_t)length); -+ status = rpc_client_receive_pipe_read(rpc->client, data, length); - - if (status < 0) - return -1; -@@ -2478,7 +2515,7 @@ static int tsg_write(rdpTsg* tsg, const BYTE* data, UINT32 length) - if (status < 0) - return -1; - -- return length; -+ return (int)length; - } - - rdpTsg* tsg_new(rdpTransport* transport) -@@ -2490,7 +2527,6 @@ rdpTsg* tsg_new(rdpTransport* transport) - return NULL; - - tsg->transport = transport; -- tsg->settings = transport->settings; - tsg->rpc = rpc_new(tsg->transport); - - if (!tsg->rpc) -@@ -2518,7 +2554,10 @@ static int transport_bio_tsg_write(BIO* bio, const char* buf, int num) - int status; - rdpTsg* tsg = (rdpTsg*)BIO_get_data(bio); - BIO_clear_flags(bio, BIO_FLAGS_WRITE); -- status = tsg_write(tsg, (BYTE*)buf, num); -+ -+ if (num < 0) -+ return -1; -+ status = tsg_write(tsg, (const BYTE*)buf, (UINT32)num); - - if (status < 0) - { -@@ -2550,7 +2589,7 @@ static int transport_bio_tsg_read(BIO* bio, char* buf, int size) - } - - BIO_clear_flags(bio, BIO_FLAGS_READ); -- status = tsg_read(tsg, (BYTE*)buf, size); -+ status = tsg_read(tsg, (BYTE*)buf, (size_t)size); - - if (status < 0) - { -@@ -2572,17 +2611,22 @@ static int transport_bio_tsg_read(BIO* bio, char* buf, int size) - - static int transport_bio_tsg_puts(BIO* bio, const char* str) - { -+ WINPR_UNUSED(bio); -+ WINPR_UNUSED(str); - return 1; - } - - static int transport_bio_tsg_gets(BIO* bio, char* str, int size) - { -+ WINPR_UNUSED(bio); -+ WINPR_UNUSED(str); -+ WINPR_UNUSED(size); - return 1; - } - - static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2) - { -- int status = -1; -+ long status = -1; - rdpTsg* tsg = (rdpTsg*)BIO_get_data(bio); - RpcVirtualConnection* connection = tsg->rpc->VirtualConnection; - RpcInChannel* inChannel = connection->DefaultInChannel; -@@ -2611,27 +2655,27 @@ static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2) - - case BIO_C_READ_BLOCKED: - { -- BIO* bio = outChannel->common.bio; -- status = BIO_read_blocked(bio); -+ BIO* cbio = outChannel->common.bio; -+ status = BIO_read_blocked(cbio); - } - break; - - case BIO_C_WRITE_BLOCKED: - { -- BIO* bio = inChannel->common.bio; -- status = BIO_write_blocked(bio); -+ BIO* cbio = inChannel->common.bio; -+ status = BIO_write_blocked(cbio); - } - break; - - case BIO_C_WAIT_READ: - { - int timeout = (int)arg1; -- BIO* bio = outChannel->common.bio; -+ BIO* cbio = outChannel->common.bio; - -- if (BIO_read_blocked(bio)) -- return BIO_wait_read(bio, timeout); -- else if (BIO_write_blocked(bio)) -- return BIO_wait_write(bio, timeout); -+ if (BIO_read_blocked(cbio)) -+ return BIO_wait_read(cbio, timeout); -+ else if (BIO_write_blocked(cbio)) -+ return BIO_wait_write(cbio, timeout); - else - status = 1; - } -@@ -2640,12 +2684,12 @@ static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2) - case BIO_C_WAIT_WRITE: - { - int timeout = (int)arg1; -- BIO* bio = inChannel->common.bio; -+ BIO* cbio = inChannel->common.bio; - -- if (BIO_write_blocked(bio)) -- status = BIO_wait_write(bio, timeout); -- else if (BIO_read_blocked(bio)) -- status = BIO_wait_read(bio, timeout); -+ if (BIO_write_blocked(cbio)) -+ status = BIO_wait_write(cbio, timeout); -+ else if (BIO_read_blocked(cbio)) -+ status = BIO_wait_read(cbio, timeout); - else - status = 1; - } -@@ -2660,6 +2704,7 @@ static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2) - - static int transport_bio_tsg_new(BIO* bio) - { -+ assert(bio); - BIO_set_init(bio, 1); - BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY); - return 1; -@@ -2667,6 +2712,8 @@ static int transport_bio_tsg_new(BIO* bio) - - static int transport_bio_tsg_free(BIO* bio) - { -+ assert(bio); -+ WINPR_UNUSED(bio); - return 1; - } - diff --git a/SOURCES/Revert-Moved-clipboard-utils-to-core-library-fixes-6.patch b/SOURCES/Revert-Moved-clipboard-utils-to-core-library-fixes-6.patch new file mode 100644 index 0000000..8b29309 --- /dev/null +++ b/SOURCES/Revert-Moved-clipboard-utils-to-core-library-fixes-6.patch @@ -0,0 +1,560 @@ +From a441e68fccc8ef137c9e8e667fed6adaab34ba37 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Tue, 1 Oct 2024 15:43:07 +0200 +Subject: [PATCH] Revert "Moved clipboard utils to core library, fixes #6760 + (#7752)" + +This reverts commit 26a83e6ccde272c1bbc2b2591325dc7a493811bc. +--- + channels/cliprdr/client/cliprdr_format.c | 195 +++++++++++++++++++ + include/freerdp/channels/cliprdr.h | 12 +- + include/freerdp/utils/cliprdr_utils.h | 48 ----- + libfreerdp/utils/CMakeLists.txt | 1 - + libfreerdp/utils/cliprdr_utils.c | 235 ----------------------- + 5 files changed, 206 insertions(+), 285 deletions(-) + delete mode 100644 include/freerdp/utils/cliprdr_utils.h + delete mode 100644 libfreerdp/utils/cliprdr_utils.c + +diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c +index 0b6111b96..4c31a1b08 100644 +--- a/channels/cliprdr/client/cliprdr_format.c ++++ b/channels/cliprdr/client/cliprdr_format.c +@@ -173,3 +173,198 @@ UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UI + + return error; + } ++ ++static UINT64 filetime_to_uint64(FILETIME value) ++{ ++ UINT64 converted = 0; ++ converted |= (UINT32)value.dwHighDateTime; ++ converted <<= 32; ++ converted |= (UINT32)value.dwLowDateTime; ++ return converted; ++} ++ ++static FILETIME uint64_to_filetime(UINT64 value) ++{ ++ FILETIME converted; ++ converted.dwLowDateTime = (UINT32)(value >> 0); ++ converted.dwHighDateTime = (UINT32)(value >> 32); ++ return converted; ++} ++ ++#define CLIPRDR_FILEDESCRIPTOR_SIZE (4 + 32 + 4 + 16 + 8 + 8 + 520) ++ ++/** ++ * Parse a packed file list. ++ * ++ * The resulting array must be freed with the `free()` function. ++ * ++ * @param [in] format_data packed `CLIPRDR_FILELIST` to parse. ++ * @param [in] format_data_length length of `format_data` in bytes. ++ * @param [out] file_descriptor_array parsed array of `FILEDESCRIPTOR` structs. ++ * @param [out] file_descriptor_count number of elements in `file_descriptor_array`. ++ * ++ * @returns 0 on success, otherwise a Win32 error code. ++ */ ++UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length, ++ FILEDESCRIPTORW** file_descriptor_array, UINT32* file_descriptor_count) ++{ ++ UINT result = NO_ERROR; ++ UINT32 i; ++ UINT32 count = 0; ++ wStream* s = NULL; ++ ++ if (!format_data || !file_descriptor_array || !file_descriptor_count) ++ return ERROR_BAD_ARGUMENTS; ++ ++ s = Stream_New((BYTE*)format_data, format_data_length); ++ if (!s) ++ return ERROR_NOT_ENOUGH_MEMORY; ++ ++ if (Stream_GetRemainingLength(s) < 4) ++ { ++ WLog_ERR(TAG, "invalid packed file list"); ++ ++ result = ERROR_INCORRECT_SIZE; ++ goto out; ++ } ++ ++ Stream_Read_UINT32(s, count); /* cItems (4 bytes) */ ++ ++ if (Stream_GetRemainingLength(s) / CLIPRDR_FILEDESCRIPTOR_SIZE < count) ++ { ++ WLog_ERR(TAG, "packed file list is too short: expected %" PRIuz ", have %" PRIuz, ++ ((size_t)count) * CLIPRDR_FILEDESCRIPTOR_SIZE, Stream_GetRemainingLength(s)); ++ ++ result = ERROR_INCORRECT_SIZE; ++ goto out; ++ } ++ ++ *file_descriptor_count = count; ++ *file_descriptor_array = calloc(count, sizeof(FILEDESCRIPTORW)); ++ if (!*file_descriptor_array) ++ { ++ result = ERROR_NOT_ENOUGH_MEMORY; ++ goto out; ++ } ++ ++ for (i = 0; i < count; i++) ++ { ++ int c; ++ UINT64 lastWriteTime; ++ FILEDESCRIPTORW* file = &((*file_descriptor_array)[i]); ++ ++ Stream_Read_UINT32(s, file->dwFlags); /* flags (4 bytes) */ ++ Stream_Seek(s, 32); /* reserved1 (32 bytes) */ ++ Stream_Read_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */ ++ Stream_Seek(s, 16); /* reserved2 (16 bytes) */ ++ Stream_Read_UINT64(s, lastWriteTime); /* lastWriteTime (8 bytes) */ ++ file->ftLastWriteTime = uint64_to_filetime(lastWriteTime); ++ Stream_Read_UINT32(s, file->nFileSizeHigh); /* fileSizeHigh (4 bytes) */ ++ Stream_Read_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */ ++ for (c = 0; c < 260; c++) /* cFileName (520 bytes) */ ++ Stream_Read_UINT16(s, file->cFileName[c]); ++ } ++ ++ if (Stream_GetRemainingLength(s) > 0) ++ WLog_WARN(TAG, "packed file list has %" PRIuz " excess bytes", ++ Stream_GetRemainingLength(s)); ++out: ++ Stream_Free(s, FALSE); ++ ++ return result; ++} ++ ++#define CLIPRDR_MAX_FILE_SIZE (2U * 1024 * 1024 * 1024) ++ ++/** ++ * Serialize a packed file list. ++ * ++ * The resulting format data must be freed with the `free()` function. ++ * ++ * @param [in] file_descriptor_array array of `FILEDESCRIPTOR` structs to serialize. ++ * @param [in] file_descriptor_count number of elements in `file_descriptor_array`. ++ * @param [out] format_data serialized CLIPRDR_FILELIST. ++ * @param [out] format_data_length length of `format_data` in bytes. ++ * ++ * @returns 0 on success, otherwise a Win32 error code. ++ */ ++UINT cliprdr_serialize_file_list(const FILEDESCRIPTORW* file_descriptor_array, ++ UINT32 file_descriptor_count, BYTE** format_data, ++ UINT32* format_data_length) ++{ ++ return cliprdr_serialize_file_list_ex(CB_STREAM_FILECLIP_ENABLED, file_descriptor_array, ++ file_descriptor_count, format_data, format_data_length); ++} ++ ++UINT cliprdr_serialize_file_list_ex(UINT32 flags, const FILEDESCRIPTORW* file_descriptor_array, ++ UINT32 file_descriptor_count, BYTE** format_data, ++ UINT32* format_data_length) ++{ ++ UINT result = NO_ERROR; ++ UINT32 i; ++ wStream* s = NULL; ++ ++ if (!file_descriptor_array || !format_data || !format_data_length) ++ return ERROR_BAD_ARGUMENTS; ++ ++ if ((flags & CB_STREAM_FILECLIP_ENABLED) == 0) ++ { ++ WLog_WARN(TAG, "No file clipboard support annouonced!"); ++ return ERROR_BAD_ARGUMENTS; ++ } ++ ++ s = Stream_New(NULL, 4 + file_descriptor_count * CLIPRDR_FILEDESCRIPTOR_SIZE); ++ if (!s) ++ return ERROR_NOT_ENOUGH_MEMORY; ++ ++ Stream_Write_UINT32(s, file_descriptor_count); /* cItems (4 bytes) */ ++ ++ for (i = 0; i < file_descriptor_count; i++) ++ { ++ int c; ++ UINT64 lastWriteTime; ++ const FILEDESCRIPTORW* file = &file_descriptor_array[i]; ++ ++ /* ++ * There is a known issue with Windows server getting stuck in ++ * an infinite loop when downloading files that are larger than ++ * 2 gigabytes. Do not allow clients to send such file lists. ++ * ++ * https://support.microsoft.com/en-us/help/2258090 ++ */ ++ if ((flags & CB_HUGE_FILE_SUPPORT_ENABLED) == 0) ++ { ++ if ((file->nFileSizeHigh > 0) || (file->nFileSizeLow >= CLIPRDR_MAX_FILE_SIZE)) ++ { ++ WLog_ERR(TAG, "cliprdr does not support files over 2 GB"); ++ result = ERROR_FILE_TOO_LARGE; ++ goto error; ++ } ++ } ++ ++ Stream_Write_UINT32(s, file->dwFlags); /* flags (4 bytes) */ ++ Stream_Zero(s, 32); /* reserved1 (32 bytes) */ ++ Stream_Write_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */ ++ Stream_Zero(s, 16); /* reserved2 (16 bytes) */ ++ lastWriteTime = filetime_to_uint64(file->ftLastWriteTime); ++ Stream_Write_UINT64(s, lastWriteTime); /* lastWriteTime (8 bytes) */ ++ Stream_Write_UINT32(s, file->nFileSizeHigh); /* fileSizeHigh (4 bytes) */ ++ Stream_Write_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */ ++ for (c = 0; c < 260; c++) /* cFileName (520 bytes) */ ++ Stream_Write_UINT16(s, file->cFileName[c]); ++ } ++ ++ Stream_SealLength(s); ++ ++ Stream_GetBuffer(s, *format_data); ++ Stream_GetLength(s, *format_data_length); ++ ++ Stream_Free(s, FALSE); ++ ++ return result; ++ ++error: ++ Stream_Free(s, TRUE); ++ ++ return result; ++} +diff --git a/include/freerdp/channels/cliprdr.h b/include/freerdp/channels/cliprdr.h +index fbf23f6e5..86fc65890 100644 +--- a/include/freerdp/channels/cliprdr.h ++++ b/include/freerdp/channels/cliprdr.h +@@ -22,7 +22,6 @@ + + #include + #include +-#include + + #include + +@@ -94,6 +93,17 @@ extern "C" + { + #endif + ++ FREERDP_API UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length, ++ FILEDESCRIPTORW** file_descriptor_array, ++ UINT32* file_descriptor_count); ++ FREERDP_API UINT cliprdr_serialize_file_list(const FILEDESCRIPTORW* file_descriptor_array, ++ UINT32 file_descriptor_count, BYTE** format_data, ++ UINT32* format_data_length); ++ FREERDP_API UINT cliprdr_serialize_file_list_ex(UINT32 flags, ++ const FILEDESCRIPTORW* file_descriptor_array, ++ UINT32 file_descriptor_count, ++ BYTE** format_data, UINT32* format_data_length); ++ + #ifdef __cplusplus + } + #endif +diff --git a/include/freerdp/utils/cliprdr_utils.h b/include/freerdp/utils/cliprdr_utils.h +deleted file mode 100644 +index 59ecf848f..000000000 +--- a/include/freerdp/utils/cliprdr_utils.h ++++ /dev/null +@@ -1,48 +0,0 @@ +-/** +- * FreeRDP: A Remote Desktop Protocol Implementation +- * RDPDR utility functions +- * +- * Copyright 2022 Armin Novak +- * Copyright 2022 Thincast Technologies GmbH +- * +- * Licensed under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. +- * You may obtain a copy of the License at +- * +- * http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software +- * distributed under the License is distributed on an "AS IS" BASIS, +- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- * See the License for the specific language governing permissions and +- * limitations under the License. +- */ +- +-#ifndef FREERDP_UTILS_CLIPRDR_H +-#define FREERDP_UTILS_CLIPRDR_H +- +-#include +-#include +-#include +- +-#ifdef __cplusplus +-extern "C" +-{ +-#endif +- +- FREERDP_API UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length, +- FILEDESCRIPTORW** file_descriptor_array, +- UINT32* file_descriptor_count); +- FREERDP_API UINT cliprdr_serialize_file_list(const FILEDESCRIPTORW* file_descriptor_array, +- UINT32 file_descriptor_count, BYTE** format_data, +- UINT32* format_data_length); +- FREERDP_API UINT cliprdr_serialize_file_list_ex(UINT32 flags, +- const FILEDESCRIPTORW* file_descriptor_array, +- UINT32 file_descriptor_count, +- BYTE** format_data, UINT32* format_data_length); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif +diff --git a/libfreerdp/utils/CMakeLists.txt b/libfreerdp/utils/CMakeLists.txt +index 2ec561d33..7bff6736a 100644 +--- a/libfreerdp/utils/CMakeLists.txt ++++ b/libfreerdp/utils/CMakeLists.txt +@@ -20,7 +20,6 @@ set(MODULE_PREFIX "FREERDP_UTILS") + + set(${MODULE_PREFIX}_SRCS + passphrase.c +- cliprdr_utils.c + pcap.c + profiler.c + ringbuffer.c +diff --git a/libfreerdp/utils/cliprdr_utils.c b/libfreerdp/utils/cliprdr_utils.c +deleted file mode 100644 +index 7fb99d63a..000000000 +--- a/libfreerdp/utils/cliprdr_utils.c ++++ /dev/null +@@ -1,235 +0,0 @@ +-/** +- * FreeRDP: A Remote Desktop Protocol Implementation +- * Clipboard Virtual Channel Extension +- * +- * Copyright 2013 Marc-Andre Moreau +- * Copyright 2022 Armin Novak +-#include +-#include +- +-#include +-#define TAG FREERDP_TAG("utils." CLIPRDR_SVC_CHANNEL_NAME) +- +-#define CLIPRDR_FILEDESCRIPTOR_SIZE (4 + 32 + 4 + 16 + 8 + 8 + 520) +-#define CLIPRDR_MAX_FILE_SIZE (2U * 1024 * 1024 * 1024) +- +-static UINT64 filetime_to_uint64(FILETIME value) +-{ +- UINT64 converted = 0; +- converted |= (UINT32)value.dwHighDateTime; +- converted <<= 32; +- converted |= (UINT32)value.dwLowDateTime; +- return converted; +-} +- +-static FILETIME uint64_to_filetime(UINT64 value) +-{ +- FILETIME converted; +- converted.dwLowDateTime = (UINT32)(value >> 0); +- converted.dwHighDateTime = (UINT32)(value >> 32); +- return converted; +-} +- +-/** +- * Parse a packed file list. +- * +- * The resulting array must be freed with the `free()` function. +- * +- * @param [in] format_data packed `CLIPRDR_FILELIST` to parse. +- * @param [in] format_data_length length of `format_data` in bytes. +- * @param [out] file_descriptor_array parsed array of `FILEDESCRIPTOR` structs. +- * @param [out] file_descriptor_count number of elements in `file_descriptor_array`. +- * +- * @returns 0 on success, otherwise a Win32 error code. +- */ +-UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length, +- FILEDESCRIPTORW** file_descriptor_array, UINT32* file_descriptor_count) +-{ +- UINT result = NO_ERROR; +- UINT32 i; +- UINT32 count = 0; +- wStream sbuffer; +- wStream* s = &sbuffer; +- +- if (!format_data || !file_descriptor_array || !file_descriptor_count) +- return ERROR_BAD_ARGUMENTS; +- +- Stream_StaticInit(&sbuffer, format_data, format_data_length); +- if (!s) +- return ERROR_NOT_ENOUGH_MEMORY; +- +- if (Stream_GetRemainingLength(s) < 4) +- { +- WLog_ERR(TAG, "invalid packed file list"); +- +- result = ERROR_INCORRECT_SIZE; +- goto out; +- } +- +- Stream_Read_UINT32(s, count); /* cItems (4 bytes) */ +- +- if (Stream_GetRemainingLength(s) / CLIPRDR_FILEDESCRIPTOR_SIZE < count) +- { +- WLog_ERR(TAG, "packed file list is too short: expected %" PRIuz ", have %" PRIuz, +- ((size_t)count) * CLIPRDR_FILEDESCRIPTOR_SIZE, Stream_GetRemainingLength(s)); +- +- result = ERROR_INCORRECT_SIZE; +- goto out; +- } +- +- *file_descriptor_count = count; +- *file_descriptor_array = calloc(count, sizeof(FILEDESCRIPTORW)); +- if (!*file_descriptor_array) +- { +- result = ERROR_NOT_ENOUGH_MEMORY; +- goto out; +- } +- +- for (i = 0; i < count; i++) +- { +- UINT64 tmp; +- FILEDESCRIPTORW* file = &((*file_descriptor_array)[i]); +- +- Stream_Read_UINT32(s, file->dwFlags); /* flags (4 bytes) */ +- Stream_Read_UINT32(s, file->clsid.Data1); +- Stream_Read_UINT16(s, file->clsid.Data2); +- Stream_Read_UINT16(s, file->clsid.Data3); +- Stream_Read(s, &file->clsid.Data4, sizeof(file->clsid.Data4)); +- Stream_Read_INT32(s, file->sizel.cx); +- Stream_Read_INT32(s, file->sizel.cy); +- Stream_Read_INT32(s, file->pointl.x); +- Stream_Read_INT32(s, file->pointl.y); +- Stream_Read_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */ +- Stream_Read_UINT64(s, tmp); /* ftCreationTime (8 bytes) */ +- file->ftCreationTime = uint64_to_filetime(tmp); +- Stream_Read_UINT64(s, tmp); /* ftLastAccessTime (8 bytes) */ +- file->ftLastAccessTime = uint64_to_filetime(tmp); +- Stream_Read_UINT64(s, tmp); /* lastWriteTime (8 bytes) */ +- file->ftLastWriteTime = uint64_to_filetime(tmp); +- Stream_Read_UINT32(s, file->nFileSizeHigh); /* fileSizeHigh (4 bytes) */ +- Stream_Read_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */ +- Stream_Read_UTF16_String(s, file->cFileName, +- ARRAYSIZE(file->cFileName)); /* cFileName (520 bytes) */ +- } +- +- if (Stream_GetRemainingLength(s) > 0) +- WLog_WARN(TAG, "packed file list has %" PRIuz " excess bytes", +- Stream_GetRemainingLength(s)); +-out: +- +- return result; +-} +- +-/** +- * Serialize a packed file list. +- * +- * The resulting format data must be freed with the `free()` function. +- * +- * @param [in] file_descriptor_array array of `FILEDESCRIPTOR` structs to serialize. +- * @param [in] file_descriptor_count number of elements in `file_descriptor_array`. +- * @param [out] format_data serialized CLIPRDR_FILELIST. +- * @param [out] format_data_length length of `format_data` in bytes. +- * +- * @returns 0 on success, otherwise a Win32 error code. +- */ +-UINT cliprdr_serialize_file_list(const FILEDESCRIPTORW* file_descriptor_array, +- UINT32 file_descriptor_count, BYTE** format_data, +- UINT32* format_data_length) +-{ +- return cliprdr_serialize_file_list_ex(CB_STREAM_FILECLIP_ENABLED, file_descriptor_array, +- file_descriptor_count, format_data, format_data_length); +-} +- +-UINT cliprdr_serialize_file_list_ex(UINT32 flags, const FILEDESCRIPTORW* file_descriptor_array, +- UINT32 file_descriptor_count, BYTE** format_data, +- UINT32* format_data_length) +-{ +- UINT result = NO_ERROR; +- UINT32 i; +- size_t len; +- wStream* s = NULL; +- +- if (!file_descriptor_array || !format_data || !format_data_length) +- return ERROR_BAD_ARGUMENTS; +- +- if ((flags & CB_STREAM_FILECLIP_ENABLED) == 0) +- { +- WLog_WARN(TAG, "No file clipboard support annouonced!"); +- return ERROR_BAD_ARGUMENTS; +- } +- +- s = Stream_New(NULL, 4 + file_descriptor_count * CLIPRDR_FILEDESCRIPTOR_SIZE); +- if (!s) +- return ERROR_NOT_ENOUGH_MEMORY; +- +- Stream_Write_UINT32(s, file_descriptor_count); /* cItems (4 bytes) */ +- +- for (i = 0; i < file_descriptor_count; i++) +- { +- int c; +- UINT64 lastWriteTime; +- const FILEDESCRIPTORW* file = &file_descriptor_array[i]; +- +- /* +- * There is a known issue with Windows server getting stuck in +- * an infinite loop when downloading files that are larger than +- * 2 gigabytes. Do not allow clients to send such file lists. +- * +- * https://support.microsoft.com/en-us/help/2258090 +- */ +- if ((flags & CB_HUGE_FILE_SUPPORT_ENABLED) == 0) +- { +- if ((file->nFileSizeHigh > 0) || (file->nFileSizeLow >= CLIPRDR_MAX_FILE_SIZE)) +- { +- WLog_ERR(TAG, "cliprdr does not support files over 2 GB"); +- result = ERROR_FILE_TOO_LARGE; +- goto error; +- } +- } +- +- Stream_Write_UINT32(s, file->dwFlags); /* flags (4 bytes) */ +- Stream_Zero(s, 32); /* reserved1 (32 bytes) */ +- Stream_Write_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */ +- Stream_Zero(s, 16); /* reserved2 (16 bytes) */ +- lastWriteTime = filetime_to_uint64(file->ftLastWriteTime); +- Stream_Write_UINT64(s, lastWriteTime); /* lastWriteTime (8 bytes) */ +- Stream_Write_UINT32(s, file->nFileSizeHigh); /* fileSizeHigh (4 bytes) */ +- Stream_Write_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */ +- for (c = 0; c < 260; c++) /* cFileName (520 bytes) */ +- Stream_Write_UINT16(s, file->cFileName[c]); +- } +- +- Stream_SealLength(s); +- +- Stream_GetBuffer(s, *format_data); +- Stream_GetLength(s, len); +- if (len > UINT32_MAX) +- goto error; +- +- *format_data_length = (UINT32)len; +- +- Stream_Free(s, FALSE); +- +- return result; +- +-error: +- Stream_Free(s, TRUE); +- +- return result; +-} +-- +2.46.1 + diff --git a/SOURCES/winpr-crt-Added-wcsstr-implementation.patch b/SOURCES/winpr-crt-Added-wcsstr-implementation.patch deleted file mode 100644 index 533ef44..0000000 --- a/SOURCES/winpr-crt-Added-wcsstr-implementation.patch +++ /dev/null @@ -1,66 +0,0 @@ -From ddc6dacd06b41ed5001b1c884b5d5c9e0a70e275 Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Thu, 10 Nov 2022 15:54:28 +0100 -Subject: [PATCH] [winpr, crt] Added wcsstr implementation - -(cherry picked from commit 6c034ba6117a4efc9266e845fe9a9a92ed4ee61d) ---- - winpr/include/winpr/string.h | 3 +++ - winpr/libwinpr/crt/string.c | 20 ++++++++++++++++++++ - 2 files changed, 23 insertions(+) - -diff --git a/winpr/include/winpr/string.h b/winpr/include/winpr/string.h -index 3b907c444..2d7126210 100644 ---- a/winpr/include/winpr/string.h -+++ b/winpr/include/winpr/string.h -@@ -62,6 +62,8 @@ extern "C" - WINPR_API size_t _wcslen(const WCHAR* str); - WINPR_API size_t _wcsnlen(const WCHAR* str, size_t maxNumberOfElements); - -+ WINPR_API WCHAR* _wcsstr(const WCHAR* str, const WCHAR* strSearch); -+ - WINPR_API WCHAR* _wcschr(const WCHAR* str, WCHAR c); - WINPR_API WCHAR* _wcsrchr(const WCHAR* str, WCHAR c); - -@@ -74,6 +76,7 @@ extern "C" - #define _wcsncmp wcsncmp - #define _wcslen wcslen - #define _wcsnlen wcsnlen -+#define _wcsstr wcsstr - #define _wcschr wcschr - #define _wcsrchr wcsrchr - -diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c -index 5dcf4b3f1..efd7d166c 100644 ---- a/winpr/libwinpr/crt/string.c -+++ b/winpr/libwinpr/crt/string.c -@@ -147,6 +147,26 @@ size_t _wcsnlen(const WCHAR* str, size_t max) - return x; - } - -+/* _wcsstr -> wcsstr */ -+ -+WCHAR* _wcsstr(const WCHAR* str, const WCHAR* strSearch) -+{ -+ assert(str); -+ assert(strSearch); -+ -+ if (strSearch[0] == '\0') -+ return str; -+ -+ const size_t searchLen = _wcslen(strSearch); -+ while (*str) -+ { -+ if (_wcsncmp(str, strSearch, searchLen) == 0) -+ return str; -+ str++; -+ } -+ return NULL; -+} -+ - /* _wcschr -> wcschr */ - - WCHAR* _wcschr(const WCHAR* str, WCHAR c) --- -2.37.1 - diff --git a/SOURCES/winpr-crt-Fix-wcs-cmp-and-wcs-len-checks.patch b/SOURCES/winpr-crt-Fix-wcs-cmp-and-wcs-len-checks.patch deleted file mode 100644 index 1ae664d..0000000 --- a/SOURCES/winpr-crt-Fix-wcs-cmp-and-wcs-len-checks.patch +++ /dev/null @@ -1,90 +0,0 @@ -From fb9d753af70b449dd7a17898d46fd57822a08dc1 Mon Sep 17 00:00:00 2001 -From: akallabeth -Date: Thu, 10 Nov 2022 14:21:22 +0100 -Subject: [PATCH] [winpr, crt] Fix wcs*cmp and wcs*len checks - -(cherry picked from commit b60fac1a0470fe83e8d0b448f0fd7e9e6d6a0f96) ---- - winpr/libwinpr/crt/string.c | 30 +++++++++++++++++++----------- - 1 file changed, 19 insertions(+), 11 deletions(-) - -diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c -index c25ffa279..5dcf4b3f1 100644 ---- a/winpr/libwinpr/crt/string.c -+++ b/winpr/libwinpr/crt/string.c -@@ -26,6 +26,7 @@ - #include - - #include -+#include - #include - - /* String Manipulation (CRT): http://msdn.microsoft.com/en-us/library/f0151s4x.aspx */ -@@ -80,21 +81,28 @@ int _strnicmp(const char* string1, const char* string2, size_t count) - - int _wcscmp(const WCHAR* string1, const WCHAR* string2) - { -- WCHAR value1, value2; -+ assert(string1); -+ assert(string2); - -- while (*string1 && (*string1 == *string2)) -+ while (TRUE) - { -- string1++; -- string2++; -+ const WCHAR w1 = *string1++; -+ const WCHAR w2 = *string2++; -+ -+ if (w1 != w2) -+ return (int)w1 - w2; -+ else if ((w1 == '\0') || (w2 == '\0')) -+ return (int)w1 - w2; - } - -- Data_Read_UINT16(string1, value1); -- Data_Read_UINT16(string2, value2); -- return (int)value1 - value2; -+ return 0; - } - - int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count) - { -+ assert(string1); -+ assert(string2); -+ - for (size_t x = 0; x < count; x++) - { - const WCHAR a = string1[x]; -@@ -102,6 +110,8 @@ int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count) - - if (a != b) - return (int)a - b; -+ else if ((a == '\0') || (b == '\0')) -+ return (int)a - b; - } - return 0; - } -@@ -112,8 +122,7 @@ size_t _wcslen(const WCHAR* str) - { - const WCHAR* p = (const WCHAR*)str; - -- if (!p) -- return 0; -+ assert(p); - - while (*p) - p++; -@@ -127,8 +136,7 @@ size_t _wcsnlen(const WCHAR* str, size_t max) - { - size_t x; - -- if (!str) -- return 0; -+ assert(str); - - for (x = 0; x < max; x++) - { --- -2.37.1 - diff --git a/SPECS/freerdp.spec b/SPECS/freerdp.spec index b3aa72b..f052efd 100644 --- a/SPECS/freerdp.spec +++ b/SPECS/freerdp.spec @@ -1,18 +1,23 @@ -# Can be rebuilt with FFmpeg/H264 support enabled by passing "--with=ffmpeg", -# "--with=x264" or "--with=openh264" to mock/rpmbuild; or by globally setting -# these variables: - +# Can be rebuilt with FFmpeg/OpenH264 support enabled by passing +# "--with=ffmpeg", or "--with=openh264" to mock/rpmbuild; or by globally +# setting these variables: +# https://bugzilla.redhat.com/show_bug.cgi?id=2242028 #global _with_ffmpeg 1 -#global _with_x264 1 #global _with_openh264 1 +# Can be rebuilt with OpenCL support enabled by passing # "--with=opencl" +# or by globally setting: +#global _opencl 1 + # Momentarily disable GSS support # https://github.com/FreeRDP/FreeRDP/issues/4348 #global _with_gss 1 # Disable server support in RHEL # https://bugzilla.redhat.com/show_bug.cgi?id=1639165 -%{!?rhel:%global _with_server 1} +%if 0%{?fedora} || 0%{?rhel} >= 10 +%global _with_server 1 +%endif # Disable support for missing codecs in RHEL %{!?rhel:%global _with_soxr 1} @@ -21,8 +26,8 @@ %endif Name: freerdp -Version: 2.2.0 -Release: 10%{?dist} +Version: 2.11.7 +Release: 1%{?dist} Epoch: 2 Summary: Free implementation of the Remote Desktop Protocol (RDP) License: ASL 2.0 @@ -30,37 +35,9 @@ URL: http://www.freerdp.com/ Source0: https://github.com/FreeRDP/FreeRDP/archive/%{version}/FreeRDP-%{version}.tar.gz -# https://bugzilla.redhat.com/show_bug.cgi?id=1910029 -Patch0: 6741.patch - -# CVE-2021-41160 freerdp: improper region checks in all clients allow out of bound write to memory -Patch1: Add-checks-for-bitmap-and-glyph-width-heigth-values.patch - -# CVE-2021-41159 freerdp: improper client input validation for gateway connections allows to overwrite memory -Patch2: Implement-missing-TSG-debug-functions.patch -Patch3: Refactored-RPC-gateway-parser.patch - -# https://bugzilla.redhat.com/show_bug.cgi?id=2108866 -Patch4: Fix-monitor-list-flag-being-ignored-on-X11-Wayland.patch - -# https://bugzilla.redhat.com/show_bug.cgi?id=2136151 -Patch5: Fix-length-checks-in-parallel-driver.patch - -# https://bugzilla.redhat.com/show_bug.cgi?id=2136153 -Patch6: Fixed-missing-length-check-in-video-channel.patch - -# https://bugzilla.redhat.com/show_bug.cgi?id=2145139 -Patch7: Added-missing-length-checks-in-zgfx_decompress_segme.patch -Patch8: Fixed-division-by-zero-in-urbdrc.patch -Patch9: Added-missing-length-check-in-urb_control_transfer.patch -Patch10: Fixed-missing-input-buffer-length-check-in-urbdrc.patch -Patch11: Ensure-urb_create_iocompletion-uses-size_t-for-calcu.patch -Patch12: Added-function-_wcsncmp.patch -Patch13: winpr-crt-Fix-wcs-cmp-and-wcs-len-checks.patch -Patch14: winpr-crt-Added-wcsstr-implementation.patch -Patch15: Fixed-path-validation-in-drive-channel.patch -Patch16: Fixed-missing-stream-length-check-in-drive_file_quer.patch -Patch17: Fixed-format-string-for-Stream_CheckAndLogRequiredLe.patch +# Revert changes that break API +# https://issues.redhat.com/browse/RHEL-53081 +Patch0: Revert-Moved-clipboard-utils-to-core-library-fixes-6.patch BuildRequires: gcc BuildRequires: gcc-c++ @@ -81,6 +58,8 @@ BuildRequires: libxkbfile-devel BuildRequires: libXrandr-devel %{?_with_server:BuildRequires: libXtst-devel} BuildRequires: libXv-devel +%{?_with_opencl:BuildRequires: opencl-headers >= 3.0} +%{?_with_opencl:BuildRequires: ocl-icd-devel} %{?_with_openh264:BuildRequires: openh264-devel} %{?_with_x264:BuildRequires: x264-devel} %{?_with_server:BuildRequires: pam-devel} @@ -89,16 +68,6 @@ BuildRequires: zlib-devel BuildRequires: multilib-rpm-config BuildRequires: pkgconfig(cairo) -BuildRequires: pkgconfig(dbus-1) -BuildRequires: pkgconfig(dbus-glib-1) -BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(gstreamer-1.0) -BuildRequires: pkgconfig(gstreamer-base-1.0) -BuildRequires: pkgconfig(gstreamer-app-1.0) -BuildRequires: pkgconfig(gstreamer-audio-1.0) -BuildRequires: pkgconfig(gstreamer-fft-1.0) -BuildRequires: pkgconfig(gstreamer-pbutils-1.0) -BuildRequires: pkgconfig(gstreamer-video-1.0) %{?_with_gss:BuildRequires: pkgconfig(krb5) >= 1.13} BuildRequires: pkgconfig(libpcsclite) BuildRequires: pkgconfig(libpulse) @@ -191,20 +160,21 @@ find . -name "*.c" -exec chmod 664 {} \; %cmake %{?_cmake_skip_rpath} \ -DCMAKE_INSTALL_LIBDIR:PATH=%{_lib} \ -DWITH_ALSA=ON \ + -DWITH_CAIRO=ON \ -DWITH_CUPS=ON \ -DWITH_CHANNELS=ON -DBUILTIN_CHANNELS=OFF \ -DWITH_CLIENT=ON \ -DWITH_DIRECTFB=OFF \ + -DWITH_DSP_FFMPEG=%{?_with_ffmpeg:ON}%{?!_with_ffmpeg:OFF} \ -DWITH_FFMPEG=%{?_with_ffmpeg:ON}%{?!_with_ffmpeg:OFF} \ -DWITH_GSM=ON \ -DWITH_GSSAPI=%{?_with_gss:ON}%{?!_with_gss:OFF} \ - -DWITH_GSTREAMER_1_0=ON -DWITH_GSTREAMER_0_10=OFF \ - -DGSTREAMER_1_0_INCLUDE_DIRS=%{_includedir}/gstreamer-1.0 \ -DWITH_ICU=ON \ -DWITH_IPP=OFF \ -DWITH_JPEG=ON \ -DWITH_LAME=%{?_with_lame:ON}%{?!_with_lame:OFF} \ -DWITH_MANPAGES=ON \ + -DWITH_OPENCL=%{?_with_opencl:ON}%{?!_with_opencl:OFF} \ -DWITH_OPENH264=%{?_with_openh264:ON}%{?!_with_openh264:OFF} \ -DWITH_OPENSSL=ON \ -DWITH_PCSC=ON \ @@ -216,7 +186,6 @@ find . -name "*.c" -exec chmod 664 {} \; -DWITH_SOXR=%{?_with_soxr:ON}%{?!_with_soxr:OFF} \ -DWITH_WAYLAND=ON \ -DWITH_X11=ON \ - -DWITH_X264=%{?_with_x264:ON}%{?!_with_x264:OFF} \ -DWITH_XCURSOR=ON \ -DWITH_XEXT=ON \ -DWITH_XKBFILE=ON \ @@ -244,17 +213,12 @@ find . -name "*.c" -exec chmod 664 {} \; -DARM_FP_ABI=soft \ -DWITH_NEON=OFF \ %endif - . + %{nil} -%make_build - -pushd winpr/tools/makecert-cli -%make_build -popd +%cmake_build %install -%make_install -%make_install COMPONENT=tools +%cmake_install find %{buildroot} -name "*.a" -delete @@ -332,6 +296,9 @@ find %{buildroot} -name "*.a" -delete %{_libdir}/pkgconfig/winpr-tools2.pc %changelog +* Tue Oct 01 2024 Ondrej Holy - 2:2.11.7-1 +- Update to 2.11.7 (RHEL-53081) + * Tue Dec 13 2022 Ondrej Holy - 2:2.2.0-10 - Fix "implicit declaration of function" errors (#2136153, #2145139)