From b83f79c3b3fd9043d77c6abdd472e733e50e6744 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Wed, 20 May 2020 11:57:01 +0200 Subject: [PATCH 01/65] Read newline from stdio on certificate accept (cherry picked from commit 5b842bc7a78621218b1179923c002d32c41f15fe) --- client/common/client.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/common/client.c b/client/common/client.c index 1f44da41a378..380d7de929af 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -467,14 +467,17 @@ static DWORD client_cli_accept_certificate(rdpSettings* settings) { case 'y': case 'Y': + fgetc(stdin); return 1; case 't': case 'T': + fgetc(stdin); return 2; case 'n': case 'N': + fgetc(stdin); return 0; default: From 37e3b2be56e034287d5870402b1ae0f229e5db3b Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 21 May 2020 11:08:26 +0200 Subject: [PATCH 02/65] new: add release script Add a updated version of script for creating the release tarball. If TAG is set the TAG is used otherwise it is tried to detect the last TAG using git describe. (cherry picked from commit 93d6de297800568b571e373d6989c54345f1e1da) --- scripts/create_release_taball.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 scripts/create_release_taball.sh diff --git a/scripts/create_release_taball.sh b/scripts/create_release_taball.sh new file mode 100755 index 000000000000..67b6cebe2bd1 --- /dev/null +++ b/scripts/create_release_taball.sh @@ -0,0 +1,31 @@ +#!/bin/bash -e + +if [ -z ${TAG:-} ];then + echo "No TAG set - trying to detect" + TAG=$(git describe --tags) + echo "Is the TAG ${TAG} ok (YES|NO)?" + read answ + case "$answ" in + YES): + ;; + *) + echo 'stopping here' + exit 1 + esac +fi + +TMPDIR=$(mktemp -d -t release-${TAG}-XXXXXXXXXX) + +git archive ${TAG} --prefix=freerdp-${TAG}/ |gzip -9 > ${TMPDIR}/freerdp-${TAG}.tar.gz +tar xzvf ${TMPDIR}/freerdp-${TAG}.tar.gz -C ${TMPDIR} +echo ${TAG} > ${TMPDIR}/freerdp-${TAG}/.source_version +pushd . +cd $TMPDIR +tar czvf freerdp-${TAG}.tar.gz freerdp-${TAG} +md5sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.md5 +sha1sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.sha1 +sha256sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.sha256 +popd +mv ${TMPDIR}/freerdp-${TAG}.tar.gz* . +rm -rf ${TMPDIR} +exit 0 From 0c779b4fef811298b466584f8fdd1b4ff171a525 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 22 May 2020 10:59:06 +0200 Subject: [PATCH 03/65] Fixed memory leak in rdpei (cherry picked from commit 8c2c19bbc81eaf69169bd581dbac8c9a906fb5ee) --- channels/rdpei/client/rdpei_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index 0a0cfefb2854..7da9ae73b1ab 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -604,6 +604,7 @@ static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin) IFCALL(mgr->DestroyListener, mgr, rdpei->listener); } free(rdpei->listener_callback); + free(rdpei->contactPoints); free(rdpei->context); free(rdpei); return CHANNEL_RC_OK; From ce6f2a271b5e6ba6306043b68fc4297f7b1607db Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 22 May 2020 11:24:25 +0200 Subject: [PATCH 04/65] Fixed #6221: Update floatbar position with multitouch input (cherry picked from commit 004910ce5d76e114f4f8cfec6429004b26bc4443) --- client/X11/xf_event.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index e7a889efc689..3f7d8727c117 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -374,12 +374,12 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win } static BOOL xf_event_MotionNotify(xfContext* xfc, const XMotionEvent* event, BOOL app) { - if (xfc->use_xinput) - return TRUE; - if (xfc->window) xf_floatbar_set_root_y(xfc->window->floatbar, event->y); + if (xfc->use_xinput) + return TRUE; + return xf_generic_MotionNotify(xfc, event->x, event->y, event->state, event->window, app); } From 987d26b6a5c51a10f6fd85918644d23342778105 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 25 May 2020 19:30:11 +0200 Subject: [PATCH 05/65] Added release zip creation to script. (cherry picked from commit 25f62eedddc8fb249e0936f86f9984ee9724c6a1) --- scripts/create_release_taball.sh | 37 ++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/scripts/create_release_taball.sh b/scripts/create_release_taball.sh index 67b6cebe2bd1..4f91ad4d5d93 100755 --- a/scripts/create_release_taball.sh +++ b/scripts/create_release_taball.sh @@ -1,5 +1,16 @@ #!/bin/bash -e +function run { + echo "[RUN] $@" + "$@" + RES=$? + if [[ $RES -ne 0 ]]; + then + echo "[ERROR] $@ retured $RES" + exit 1 + fi +} + if [ -z ${TAG:-} ];then echo "No TAG set - trying to detect" TAG=$(git describe --tags) @@ -16,16 +27,24 @@ fi TMPDIR=$(mktemp -d -t release-${TAG}-XXXXXXXXXX) -git archive ${TAG} --prefix=freerdp-${TAG}/ |gzip -9 > ${TMPDIR}/freerdp-${TAG}.tar.gz -tar xzvf ${TMPDIR}/freerdp-${TAG}.tar.gz -C ${TMPDIR} -echo ${TAG} > ${TMPDIR}/freerdp-${TAG}/.source_version +run git archive --prefix=freerdp-${TAG}/ --format=tar.gz -o ${TMPDIR}/freerdp-${TAG}.tar.gz ${TAG} +run tar xzvf ${TMPDIR}/freerdp-${TAG}.tar.gz -C ${TMPDIR} +run echo ${TAG} > ${TMPDIR}/freerdp-${TAG}/.source_version + pushd . cd $TMPDIR -tar czvf freerdp-${TAG}.tar.gz freerdp-${TAG} -md5sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.md5 -sha1sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.sha1 -sha256sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.sha256 +run tar czvf freerdp-${TAG}.tar.gz freerdp-${TAG} +run md5sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.md5 +run sha1sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.sha1 +run sha256sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.sha256 + +run zip freerdp-${TAG}.zip freerdp-${TAG} +run md5sum freerdp-${TAG}.zip > freerdp-${TAG}.zip.md5 +run sha1sum freerdp-${TAG}.zip > freerdp-${TAG}.zip.sha1 +run sha256sum freerdp-${TAG}.zip > freerdp-${TAG}.zip.sha256 popd -mv ${TMPDIR}/freerdp-${TAG}.tar.gz* . -rm -rf ${TMPDIR} + +run mv ${TMPDIR}/freerdp-${TAG}.tar.gz* . +run mv ${TMPDIR}/freerdp-${TAG}.zip* . +run rm -rf ${TMPDIR} exit 0 From daf6d8889e1321f0299c1d80dc56df94906adfeb Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 26 May 2020 12:15:27 +0200 Subject: [PATCH 06/65] Added scancodes for launch keys (cherry picked from commit c97c1ca359db825ee6d172b5860b793dcf3a1e83) --- include/freerdp/scancode.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/freerdp/scancode.h b/include/freerdp/scancode.h index 226f711a597f..55d2ebb86d02 100644 --- a/include/freerdp/scancode.h +++ b/include/freerdp/scancode.h @@ -166,7 +166,6 @@ #define RDP_SCANCODE_TAB_JP MAKE_RDP_SCANCODE(0x7C, FALSE) /* JP TAB */ #define RDP_SCANCODE_BACKSLASH_JP MAKE_RDP_SCANCODE(0x7D, FALSE) /* JP OEM_5 ('\') */ #define RDP_SCANCODE_ABNT_C2 MAKE_RDP_SCANCODE(0x7E, FALSE) /* VK_ABNT_C2, JP */ -#define RDP_SCANCODE_ABNT_C2 MAKE_RDP_SCANCODE(0x7E, FALSE) /* JP OEM_PA2 */ #define RDP_SCANCODE_HANJA MAKE_RDP_SCANCODE(0x71, FALSE) /* KR VK_HANJA */ #define RDP_SCANCODE_HANGUL MAKE_RDP_SCANCODE(0x72, FALSE) /* KR VK_HANGUL */ @@ -229,4 +228,10 @@ /* Misc. */ #define RDP_SCANCODE_LAUNCH_MAIL MAKE_RDP_SCANCODE(0x6C, TRUE) /* VK_LAUNCH_MAIL */ +#define RDP_SCANCODE_LAUNCH_MEDIA_SELECT \ + MAKE_RDP_SCANCODE(0x6D, TRUE) /* VK_LAUNCH_MEDIA_SELECT \ + */ +#define RDP_SCANCODE_LAUNCH_APP1 MAKE_RDP_SCANCODE(0x6E, TRUE) /* VK_LAUNCH_APP1 */ +#define RDP_SCANCODE_LAUNCH_APP2 MAKE_RDP_SCANCODE(0x6F, TRUE) /* VK_LAUNCH_APP2 */ + #endif /* FREERDP_LOCALE_KEYBOARD_RDP_SCANCODE_H */ From ef394b61a115c691d41db1af1d865edffb1d4509 Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Wed, 27 May 2020 08:43:00 +0200 Subject: [PATCH 07/65] winpr/library: Use RTLD_GLOBAL for dlopen LoadLibraryA implementation uses the RTLD_LOCAL flag for dlopen currently. This flag doesn't allow the symbols to be used by the subsequently loaded libraries. This is a problem for the video channel when -DBUILTIN_CHANNELS=OFF is used as it uses functions from the geometry channel. Let's use RTLD_GLOBAL instead to prevent "undefined symbol" errors in such cases. Fixes: https://github.com/FreeRDP/FreeRDP/issues/6236 (cherry picked from commit d8cd671cc68d503757e32eb80f7a4dee44e47754) --- winpr/libwinpr/library/library.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/library/library.c b/winpr/libwinpr/library/library.c index f44a96d27fcf..8d33227b2b9a 100644 --- a/winpr/libwinpr/library/library.c +++ b/winpr/libwinpr/library/library.c @@ -125,7 +125,7 @@ HMODULE LoadLibraryA(LPCSTR lpLibFileName) return hModule; #else HMODULE library; - library = dlopen(lpLibFileName, RTLD_LOCAL | RTLD_LAZY); + library = dlopen(lpLibFileName, RTLD_GLOBAL | RTLD_LAZY); if (!library) { From f681d2450f84b1ac2d43528fdb4bae2f79ed7ee7 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Thu, 28 May 2020 17:16:15 +0200 Subject: [PATCH 08/65] only call 'libusb_set_interface_alt_setting' when value is changed (cherry picked from commit ea8c922355c48b6a18900aa543e716b6ae1cd08e) --- .../urbdrc/client/libusb/libusb_udevice.c | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c index 94117bcf3ce7..2c6b42ec60c3 100644 --- a/channels/urbdrc/client/libusb/libusb_udevice.c +++ b/channels/urbdrc/client/libusb/libusb_udevice.c @@ -465,7 +465,7 @@ static LIBUSB_DEVICE_DESCRIPTOR* udev_new_descript(URBDRC_PLUGIN* urbdrc, LIBUSB static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BYTE AlternateSetting) { - int error = 0, diff = 1; + int error = 0, diff = 0; UDEVICE* pdev = (UDEVICE*)idev; URBDRC_PLUGIN* urbdrc; MSUSB_CONFIG_DESCRIPTOR* MsConfig; @@ -480,21 +480,30 @@ static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BY if (MsConfig) { MsInterfaces = MsConfig->MsInterfaces; - - if ((MsInterfaces) && (MsInterfaces[InterfaceNumber]->AlternateSetting == AlternateSetting)) + if (MsInterfaces) { - diff = 0; - } - } + WLog_Print(urbdrc->log, WLOG_INFO, + "select Interface(%" PRIu8 ") curr AlternateSetting(%" PRIu8 + ") new AlternateSetting(" PRIu8 ")", + InterfaceNumber, MsInterfaces[InterfaceNumber]->AlternateSetting, + AlternateSetting); - if (diff) - { - error = libusb_set_interface_alt_setting(pdev->libusb_handle, InterfaceNumber, - AlternateSetting); + if (MsInterfaces[InterfaceNumber]->AlternateSetting != AlternateSetting) + { + diff = 1; + } + } - if (error < 0) + if (diff) { - WLog_Print(urbdrc->log, WLOG_ERROR, "Set interface altsetting get error num %d", error); + error = libusb_set_interface_alt_setting(pdev->libusb_handle, InterfaceNumber, + AlternateSetting); + + if (error < 0) + { + WLog_Print(urbdrc->log, WLOG_ERROR, "Set interface altsetting get error num %d", + error); + } } } From 4f80017786dbbf78a46e781352a911c11909ffde Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 29 May 2020 09:20:05 +0200 Subject: [PATCH 09/65] Lock security_decrypt to avoid simultaneous counter manipulation (cherry picked from commit 164c00f68b64781d8c624a8c71fab6691519d294) --- libfreerdp/core/security.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index e6571c36dfac..54c39cc9a623 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -741,29 +741,34 @@ BOOL security_encrypt(BYTE* data, size_t length, rdpRdp* rdp) BOOL security_decrypt(BYTE* data, size_t length, rdpRdp* rdp) { + BOOL rc = FALSE; + EnterCriticalSection(&rdp->critical); if (rdp->rc4_decrypt_key == NULL) - return FALSE; + goto fail; if (rdp->decrypt_use_count >= 4096) { if (!security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len, rdp)) - return FALSE; + goto fail; winpr_RC4_Free(rdp->rc4_decrypt_key); rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len); if (!rdp->rc4_decrypt_key) - return FALSE; + goto fail; rdp->decrypt_use_count = 0; } if (!winpr_RC4_Update(rdp->rc4_decrypt_key, length, data, data)) - return FALSE; + goto fail; rdp->decrypt_use_count += 1; rdp->decrypt_checksum_use_count++; - return TRUE; + rc = TRUE; +fail: + LeaveCriticalSection(&rdp->critical); + return rc; } BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output, rdpRdp* rdp) From d2c653baf3b8eb2f737adc9f71ac0267418657a2 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 29 May 2020 09:30:25 +0200 Subject: [PATCH 10/65] Lock remaining occurances of security_encrypt/security_decrypt variables (cherry picked from commit f01ae7d2573b677eba6c8a50fe12246a23b15f2e) --- libfreerdp/core/security.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index 54c39cc9a623..7caf5a842e18 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -394,6 +394,8 @@ BOOL security_salted_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length, BYTE md5_digest[WINPR_MD5_DIGEST_LENGTH]; BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; BOOL result = FALSE; + + EnterCriticalSection(&rdp->critical); security_UINT32_le(length_le, length); /* length must be little-endian */ if (encryption) @@ -456,6 +458,7 @@ BOOL security_salted_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length, memcpy(output, md5_digest, 8); result = TRUE; out: + LeaveCriticalSection(&rdp->critical); winpr_Digest_Free(sha1); winpr_Digest_Free(md5); return result; @@ -636,12 +639,14 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) rdp->rc4_key_len = 16; } + EnterCriticalSection(&rdp->critical); memcpy(rdp->decrypt_update_key, rdp->decrypt_key, 16); memcpy(rdp->encrypt_update_key, rdp->encrypt_key, 16); rdp->decrypt_use_count = 0; rdp->decrypt_checksum_use_count = 0; rdp->encrypt_use_count = 0; rdp->encrypt_checksum_use_count = 0; + LeaveCriticalSection(&rdp->critical); return TRUE; } @@ -777,7 +782,9 @@ BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output, rdpR BYTE use_count_le[4]; WINPR_HMAC_CTX* hmac; BOOL result = FALSE; + EnterCriticalSection(&rdp->critical); security_UINT32_le(use_count_le, rdp->encrypt_use_count); + LeaveCriticalSection(&rdp->critical); if (!(hmac = winpr_HMAC_New())) return FALSE; @@ -836,7 +843,9 @@ BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE* BYTE use_count_le[4]; WINPR_HMAC_CTX* hmac; BOOL result = FALSE; - security_UINT32_le(use_count_le, rdp->decrypt_use_count); + EnterCriticalSection(&rdp->critical); + security_UINT32_le(use_count_le, rdp->decrypt_use_count++); + LeaveCriticalSection(&rdp->critical); if (!(hmac = winpr_HMAC_New())) return FALSE; @@ -853,8 +862,6 @@ BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE* if (!winpr_HMAC_Final(hmac, buf, WINPR_SHA1_DIGEST_LENGTH)) goto out; - rdp->decrypt_use_count++; - if (!memcmp(sig, buf, 8)) result = TRUE; From 5491795588a41fe56b79f7fee0140005d4df82f3 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Fri, 29 May 2020 02:20:15 +0200 Subject: [PATCH 11/65] report only actual bytes received, not allocated buffer size (interrupt produces data, timeout doesn't) (cherry picked from commit 2e4f27ac9f7bcecb3c3f453341818e538386207f) --- channels/urbdrc/client/libusb/libusb_udevice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c index 2c6b42ec60c3..7c73e940eef0 100644 --- a/channels/urbdrc/client/libusb/libusb_udevice.c +++ b/channels/urbdrc/client/libusb/libusb_udevice.c @@ -296,7 +296,7 @@ static void func_bulk_transfer_cb(struct libusb_transfer* transfer) user_data->cb(user_data->idev, user_data->callback, user_data->data, InterfaceId, user_data->noack, user_data->MessageId, RequestID, transfer->num_iso_packets, transfer->status, user_data->StartFrame, user_data->ErrorCount, - user_data->OutputBufferSize); + transfer->actual_length); user_data->data = NULL; HashTable_Remove(user_data->queue, (void*)(size_t)streamID); } From 39c524324754cba21002d55546e6ec0dda65c46b Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 29 May 2020 17:24:15 +0200 Subject: [PATCH 12/65] Fixed #6245: Added additional tests to assistance parser (cherry picked from commit 69141aa830b6e73e859f907b9bd2a4cac2777d8f) --- libfreerdp/common/assistance.c | 76 ++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/libfreerdp/common/assistance.c b/libfreerdp/common/assistance.c index c7ae2ba2db0d..508a80be6e2c 100644 --- a/libfreerdp/common/assistance.c +++ b/libfreerdp/common/assistance.c @@ -361,6 +361,14 @@ static BOOL freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) goto out_fail; } + if (p > q) + { + WLog_ERR( + TAG, + "Failed to parse ASSISTANCE file: ConnectionString2 invalid field order for KH"); + goto out_fail; + } + length = q - p; free(file->RASpecificParams); file->RASpecificParams = (char*)malloc(length + 1); @@ -388,6 +396,12 @@ static BOOL freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file) goto out_fail; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 invalid field " + "order for ID"); + return -1; + } length = q - p; free(file->RASessionId); file->RASessionId = (char*)malloc(length + 1); @@ -810,6 +824,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field " + "order for USERNAME"); + return -1; + } + length = q - p; file->Username = (char*)malloc(length + 1); @@ -834,6 +855,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field " + "order for LHTICKET"); + return -1; + } + length = q - p; file->LHTicket = (char*)malloc(length + 1); @@ -858,6 +886,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field " + "order for RCTICKET"); + return -1; + } + length = q - p; file->RCTicket = (char*)malloc(length + 1); @@ -882,6 +917,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field " + "order for RCTICKETENCRYPTED"); + return -1; + } + length = q - p; if ((length == 1) && (p[0] == '1')) @@ -902,6 +944,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field " + "order for PassStub"); + return -1; + } + length = q - p; file->PassStub = (char*)malloc(length + 1); @@ -926,6 +975,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field " + "order for DtStart"); + return -1; + } + length = q - p; r = (char*)malloc(length + 1); @@ -964,6 +1020,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field " + "order for DtLength"); + return -1; + } + length = q - p; r = (char*)malloc(length + 1); @@ -1002,6 +1065,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field " + "order for L"); + return -1; + } + length = q - p; if ((length == 1) && (p[0] == '1')) @@ -1061,6 +1131,12 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu return -1; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field order for "); + return -1; + } + q += sizeof("") - 1; length = q - p; file->ConnectionString2 = (char*)malloc(length + 1); From fa647175cbc5eac78e263a25dab2c8efc0e9c82c Mon Sep 17 00:00:00 2001 From: Patrick Chin Date: Fri, 29 May 2020 23:29:58 +0100 Subject: [PATCH 13/65] Fix memory leaks in client/encomsp_main.c and client/remdesk_main.c (cherry picked from commit 28e29f8ad568b195a9d6a1d785eaa81da13f93ff) --- channels/encomsp/client/encomsp_main.c | 3 +++ channels/remdesk/client/remdesk_main.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/channels/encomsp/client/encomsp_main.c b/channels/encomsp/client/encomsp_main.c index dc2172004f67..b384337fe987 100644 --- a/channels/encomsp/client/encomsp_main.c +++ b/channels/encomsp/client/encomsp_main.c @@ -1116,8 +1116,11 @@ static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg) if ((error = encomsp_process_receive(encomsp, data))) { WLog_ERR(TAG, "encomsp_process_receive failed with error %" PRIu32 "!", error); + Stream_Free(data, TRUE); break; } + + Stream_Free(data, TRUE); } } diff --git a/channels/remdesk/client/remdesk_main.c b/channels/remdesk/client/remdesk_main.c index b3464eea15bb..54d9c60b4cd5 100644 --- a/channels/remdesk/client/remdesk_main.c +++ b/channels/remdesk/client/remdesk_main.c @@ -843,8 +843,11 @@ static DWORD WINAPI remdesk_virtual_channel_client_thread(LPVOID arg) if ((error = remdesk_process_receive(remdesk, data))) { WLog_ERR(TAG, "remdesk_process_receive failed with error %" PRIu32 "!", error); + Stream_Free(data, TRUE); break; } + + Stream_Free(data, TRUE); } } From dc735d3d36cb18fc75385c3c729afbe0b766c2c4 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 30 May 2020 10:57:10 +0100 Subject: [PATCH 14/65] [generate_argument_docbook] Fix typo in XML entity. The character '>' was being rendered as < instead of >. (cherry picked from commit 98930bf2759905f2290e5d777f57a79e7589f220) --- client/X11/generate_argument_docbook.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/X11/generate_argument_docbook.c b/client/X11/generate_argument_docbook.c index 49b1bb1089bb..78de2f9beb9c 100644 --- a/client/X11/generate_argument_docbook.c +++ b/client/X11/generate_argument_docbook.c @@ -89,7 +89,7 @@ LPSTR tr_esc_str(LPCSTR arg, bool format) strncpy(&tmp[cs], "", len); else /* coverity[buffer_size] */ - strncpy(&tmp[cs], "<", len); + strncpy(&tmp[cs], ">", len); cs += len; break; From 25ac571dd797fceb18ba0c23544751faf05d5547 Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Thu, 28 May 2020 08:32:17 +0200 Subject: [PATCH 15/65] gdi: Fix missing unlock This fixes the following defect reported by covscan tool: libfreerdp/gdi/gfx.c:144: missing_unlock: Returning without unlocking "update->mux". (cherry picked from commit 914808f62cd2ac4a6984ee638112e8dc3aad9e52) --- libfreerdp/gdi/gfx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index b76cdd79c3b1..e3a6e66e022e 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -141,7 +141,10 @@ static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) if (!freerdp_image_scale(gdi->primary_buffer, gdi->dstFormat, gdi->stride, nXDst, nYDst, dwidth, dheight, surface->data, surface->format, surface->scanline, nXSrc, nYSrc, swidth, sheight)) - return CHANNEL_RC_NULL_DATA; + { + rc = CHANNEL_RC_NULL_DATA; + goto fail; + } gdi_InvalidateRegion(gdi->primary->hdc, (INT32)nXDst, (INT32)nYDst, (INT32)dwidth, (INT32)dheight); From 9a7180cf9032d62c65ffd34fc4d59d8bce97bd5b Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Wed, 3 Jun 2020 12:03:44 +0200 Subject: [PATCH 16/65] wlfreerdp: Fix array overrun This fixes the following defects reported by covscan tool: - client/Wayland/wlf_input.c:251: overrun-local: Overrunning array "contacts" of 10 32-byte elements at element index 10 (byte offset 351) using index "i" (which evaluates to 10). - client/Wayland/wlf_input.c:308: overrun-local: Overrunning array "contacts" of 10 32-byte elements at element index 10 (byte offset 351) using index "i" (which evaluates to 10). - client/Wayland/wlf_input.c:360: overrun-local: Overrunning array "contacts" of 10 32-byte elements at element index 10 (byte offset 351) using index "i" (which evaluates to 10). - client/Wayland/wlf_input.c:251: error[arrayIndexOutOfBounds]: Array 'contacts[10]' accessed at index 10, which is out of bounds. - client/Wayland/wlf_input.c:308: error[arrayIndexOutOfBounds]: Array 'contacts[10]' accessed at index 10, which is out of bounds. - client/Wayland/wlf_input.c:360: error[arrayIndexOutOfBounds]: Array 'contacts[10]' accessed at index 10, which is out of bounds. - client/Wayland/wlf_input.c:246: uninit_use_in_call: Using uninitialized value "y" when calling "wlf_scale_coordinates". - client/Wayland/wlf_input.c:246: uninit_use_in_call: Using uninitialized value "x" when calling "wlf_scale_coordinates". The maximal number of touches can be higher then 10, see: https://wayland.freedesktop.org/libinput/doc/latest/touchpads.html Let's increse the MAX_CONTACTS count and add checks to prevent usage of uninitialized values. (cherry picked from commit 6ab79961ef09bc0340633319c388b6b7517b1f3d) --- client/Wayland/wlf_input.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/client/Wayland/wlf_input.c b/client/Wayland/wlf_input.c index afa8d4b51aaf..8dcbb5f81422 100644 --- a/client/Wayland/wlf_input.c +++ b/client/Wayland/wlf_input.c @@ -30,7 +30,7 @@ #define TAG CLIENT_TAG("wayland.input") -#define MAX_CONTACTS 10 +#define MAX_CONTACTS 20 typedef struct touch_contact { @@ -241,6 +241,9 @@ BOOL wlf_handle_touch_up(freerdp* instance, const UwacTouchUp* ev) } } + if (i == MAX_CONTACTS) + return FALSE; + WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y); if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE)) @@ -282,8 +285,6 @@ BOOL wlf_handle_touch_down(freerdp* instance, const UwacTouchDown* ev) y = ev->y; touchId = ev->id; - WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y); - for (i = 0; i < MAX_CONTACTS; i++) { if (contacts[i].id == 0) @@ -296,6 +297,11 @@ BOOL wlf_handle_touch_down(freerdp* instance, const UwacTouchDown* ev) } } + if (i == MAX_CONTACTS) + return FALSE; + + WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y); + if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE)) return FALSE; @@ -350,6 +356,9 @@ BOOL wlf_handle_touch_motion(freerdp* instance, const UwacTouchMotion* ev) } } + if (i == MAX_CONTACTS) + return FALSE; + WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y); if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE)) From 5dbb255feb78d7830c50ba29627ca125df99b33d Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Wed, 3 Jun 2020 12:28:32 +0200 Subject: [PATCH 17/65] smartcard: Fix usage of uninitialized values This fixes the following defect reported by covscan tool: - channels/smartcard/client/smartcard_pack.c:942: uninit_use_in_call: Using uninitialized value "tmp" when calling "ConvertFromUnicode". - channels/smartcard/client/smartcard_pack.c:894: uninit_use_in_call: Using uninitialized value "tmp" when calling "ConvertFromUnicode". - channels/smartcard/client/smartcard_pack.c:475: uninit_use_in_call: Using uninitialized value "tmp" when calling "ConvertFromUnicode". (cherry picked from commit e70e25715f89aac823281d7c0674d2387f70f8a6) --- channels/smartcard/client/smartcard_pack.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c index de0e1cec571f..8f7c92f3ced3 100644 --- a/channels/smartcard/client/smartcard_pack.c +++ b/channels/smartcard/client/smartcard_pack.c @@ -389,7 +389,7 @@ static char* smartcard_msz_dump_a(const char* msz, size_t len, char* buffer, siz static char* smartcard_msz_dump_w(const WCHAR* msz, size_t len, char* buffer, size_t bufferLen) { - char* sz; + char* sz = NULL; ConvertFromUnicode(CP_UTF8, 0, msz, (int)len, &sz, 0, NULL, NULL); return smartcard_msz_dump_a(sz, len, buffer, bufferLen); } @@ -466,7 +466,7 @@ static void smartcard_trace_context_and_string_call_w(const char* name, const REDIR_SCARDCONTEXT* phContext, const WCHAR* sz) { - char* tmp; + char* tmp = NULL; if (!WLog_IsLevelActive(WLog_Get(TAG), g_LogLevel)) return; @@ -883,7 +883,7 @@ static void smartcard_trace_write_cache_a_call(SMARTCARD_DEVICE* smartcard, static void smartcard_trace_write_cache_w_call(SMARTCARD_DEVICE* smartcard, const WriteCacheW_Call* call) { - char* tmp; + char* tmp = NULL; char buffer[1024]; WINPR_UNUSED(smartcard); if (!WLog_IsLevelActive(WLog_Get(TAG), g_LogLevel)) @@ -931,7 +931,7 @@ static void smartcard_trace_read_cache_a_call(SMARTCARD_DEVICE* smartcard, static void smartcard_trace_read_cache_w_call(SMARTCARD_DEVICE* smartcard, const ReadCacheW_Call* call) { - char* tmp; + char* tmp= NULL; char buffer[1024]; WINPR_UNUSED(smartcard); if (!WLog_IsLevelActive(WLog_Get(TAG), g_LogLevel)) From 3f86260eaa5628920a24d5ab2f910ee7a2b3b64f Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Wed, 3 Jun 2020 13:03:11 +0200 Subject: [PATCH 18/65] smartcard: Teoretical fix of uninitialized values This tries to fixes the following defects reported by covscan tool: - channels/smartcard/client/smartcard_operations.c:958: uninit_use_in_call: Using uninitialized value "ret.cReaders" when calling "smartcard_pack_locate_cards_return". - channels/smartcard/client/smartcard_operations.c:932: uninit_use_in_call: Using uninitialized value "ret.cReaders" when calling "smartcard_pack_locate_cards_return". But I am not sure about it... (cherry picked from commit 53459883529bf659488c4da81c30707ff3662820) --- .../smartcard/client/smartcard_operations.c | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index b20f2e4df410..5bcd624f9a0e 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -921,15 +921,38 @@ static LONG smartcard_LocateCardsA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O ret.ReturnCode = SCardLocateCardsA(operation->hContext, call->mszCards, call->rgReaderStates, call->cReaders); log_status_error(TAG, "SCardLocateCardsA", ret.ReturnCode); + ret.cReaders = call->cReaders; + ret.rgReaderStates = NULL; + free(call->mszCards); + + if (ret.cReaders > 0) + { + ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return)); + + if (!ret.rgReaderStates) + return STATUS_NO_MEMORY; + } + + for (x = 0; x < ret.cReaders; x++) + { + ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState; + ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState; + ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr; + CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr), + sizeof(ret.rgReaderStates[x].rgbAtr)); + } + + status = smartcard_pack_locate_cards_return(smartcard, irp->output, &ret); + for (x = 0; x < call->cReaders; x++) { SCARD_READERSTATEA* state = &call->rgReaderStates[x]; free(state->szReader); } + free(call->rgReaderStates); - status = smartcard_pack_locate_cards_return(smartcard, irp->output, &ret); if (status != SCARD_S_SUCCESS) return status; @@ -947,15 +970,38 @@ static LONG smartcard_LocateCardsW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O ret.ReturnCode = SCardLocateCardsW(operation->hContext, call->mszCards, call->rgReaderStates, call->cReaders); log_status_error(TAG, "SCardLocateCardsW", ret.ReturnCode); + ret.cReaders = call->cReaders; + ret.rgReaderStates = NULL; + free(call->mszCards); + + if (ret.cReaders > 0) + { + ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return)); + + if (!ret.rgReaderStates) + return STATUS_NO_MEMORY; + } + + for (x = 0; x < ret.cReaders; x++) + { + ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState; + ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState; + ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr; + CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr), + sizeof(ret.rgReaderStates[x].rgbAtr)); + } + + status = smartcard_pack_locate_cards_return(smartcard, irp->output, &ret); + for (x = 0; x < call->cReaders; x++) { SCARD_READERSTATEW* state = &call->rgReaderStates[x]; free(state->szReader); } + free(call->rgReaderStates); - status = smartcard_pack_locate_cards_return(smartcard, irp->output, &ret); if (status != SCARD_S_SUCCESS) return status; From bc8ace351fafc81b20279a2bff5f3c21396c1bfc Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 4 Jun 2020 07:44:08 +0200 Subject: [PATCH 19/65] Fixed formatting. (cherry picked from commit d1b310d970592226b2f0a70710ad3ae3da61c4bc) --- channels/smartcard/client/smartcard_pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c index 8f7c92f3ced3..a85cce6dab13 100644 --- a/channels/smartcard/client/smartcard_pack.c +++ b/channels/smartcard/client/smartcard_pack.c @@ -931,7 +931,7 @@ static void smartcard_trace_read_cache_a_call(SMARTCARD_DEVICE* smartcard, static void smartcard_trace_read_cache_w_call(SMARTCARD_DEVICE* smartcard, const ReadCacheW_Call* call) { - char* tmp= NULL; + char* tmp = NULL; char buffer[1024]; WINPR_UNUSED(smartcard); if (!WLog_IsLevelActive(WLog_Get(TAG), g_LogLevel)) From 66dfa56cc21cf876b0e2f879f75f87e89e370e30 Mon Sep 17 00:00:00 2001 From: Kubistika Date: Wed, 3 Jun 2020 19:45:18 +0300 Subject: [PATCH 20/65] drdynvc: client: fix #6252 use-after-free (cherry picked from commit 6ed765c96052c65f16fb1964705bd5c894b51b78) --- channels/drdynvc/client/drdynvc_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index eb5b418e12ba..4b9799e6127a 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -1583,13 +1583,15 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc) if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + MessageQueue_Free(drdynvc->queue); + drdynvc->queue = NULL; + if (drdynvc->channel_mgr) { dvcman_free(drdynvc, drdynvc->channel_mgr); drdynvc->channel_mgr = NULL; } - MessageQueue_Free(drdynvc->queue); - drdynvc->queue = NULL; + drdynvc->InitHandle = 0; free(drdynvc->context); free(drdynvc); From dd9c07ca6165314155becac3eb0fb73a88136d46 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 7 Jun 2020 23:13:58 -0500 Subject: [PATCH 21/65] uwac: don't try to use O_TMPFILE on FreeBSD Currently, this sets an invalid open flag and attempts to open(), which will fail. Instead of doing that, don't try to define O_TMPFILE where such a definition can't exist and force the fallback rather than making an always-fail open() call. (cherry picked from commit 082ddb3d2bd068536c17a4dbddcafd465ffcba3a) --- uwac/libuwac/uwac-os.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/uwac/libuwac/uwac-os.c b/uwac/libuwac/uwac-os.c index 4f8c8f5161ef..7e36721104ee 100644 --- a/uwac/libuwac/uwac-os.c +++ b/uwac/libuwac/uwac-os.c @@ -34,7 +34,7 @@ #endif /* uClibc and uClibc-ng don't provide O_TMPFILE */ -#ifndef O_TMPFILE +#if !defined(O_TMPFILE) && !defined(__FreeBSD__) #define O_TMPFILE (020000000 | O_DIRECTORY) #endif @@ -230,7 +230,16 @@ int uwac_create_anonymous_file(off_t size) return -1; } +#ifdef O_TMPFILE fd = open(path, O_TMPFILE | O_RDWR | O_EXCL, 0600); +#else + /* + * Some platforms (e.g. FreeBSD) won't support O_TMPFILE and can't + * reasonably emulate it at first blush. Opt to make them rely on + * the create_tmpfile_cloexec() path instead. + */ + fd = -1; +#endif if (fd < 0) { From 072b3d9a0041c8ae5019a5e79e8447d458845d85 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 8 Jun 2020 07:09:07 +0200 Subject: [PATCH 22/65] Fixed #6267: adjust write_pixel_16 endian handling (cherry picked from commit 51d3e07c8a4bca32bf82538075e4518b63e8ed4d) --- libfreerdp/codec/interleaved.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index e9f92c700940..b76fe1ca3c1b 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -232,7 +232,8 @@ static INLINE void write_pixel_24(BYTE* _buf, UINT32 _pix) static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix) { - *(UINT16*)_buf = _pix; + _buf[0] = _pix & 0xFF; + _buf[1] = (_pix >> 8) & 0xFF; } #undef DESTWRITEPIXEL From ab1c021b7085df3b4e8b3b7b587d89c7afac7711 Mon Sep 17 00:00:00 2001 From: Patrick Chin Date: Mon, 8 Jun 2020 19:17:35 +0100 Subject: [PATCH 23/65] MessageQueue write time to current message not the next (cherry picked from commit ea4df3f91a63c17f6a9bbf8d1b54f462004a992c) --- winpr/libwinpr/utils/collections/MessageQueue.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/winpr/libwinpr/utils/collections/MessageQueue.c b/winpr/libwinpr/utils/collections/MessageQueue.c index d288c544fe80..d787f8ff3645 100644 --- a/winpr/libwinpr/utils/collections/MessageQueue.c +++ b/winpr/libwinpr/utils/collections/MessageQueue.c @@ -100,12 +100,13 @@ BOOL MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message) } CopyMemory(&(queue->array[queue->tail]), message, sizeof(wMessage)); - queue->tail = (queue->tail + 1) % queue->capacity; - queue->size++; message = &(queue->array[queue->tail]); message->time = GetTickCount64(); + queue->tail = (queue->tail + 1) % queue->capacity; + queue->size++; + if (queue->size > 0) SetEvent(queue->event); From cb07d5a4f6c4983a215de4f2fa6e06b232f06953 Mon Sep 17 00:00:00 2001 From: Martin Fleisz Date: Mon, 15 Jun 2020 15:06:02 +0200 Subject: [PATCH 24/65] Fix usage of DsMakeSpn with IP address hostnames (cherry picked from commit 4e7b60b0028f5d33139065fb965c5cd9d2f6ec1d) --- libfreerdp/core/gateway/ntlm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libfreerdp/core/gateway/ntlm.c b/libfreerdp/core/gateway/ntlm.c index 084e55096968..35637518c99c 100644 --- a/libfreerdp/core/gateway/ntlm.c +++ b/libfreerdp/core/gateway/ntlm.c @@ -160,7 +160,7 @@ BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, LPCTSTR hostname) return TRUE; } - if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, NULL) != + if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, hostnameX, &SpnLength, NULL) != ERROR_BUFFER_OVERFLOW) goto error; @@ -169,8 +169,8 @@ BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, LPCTSTR hostname) if (!ntlm->ServicePrincipalName) goto error; - if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName) != - ERROR_SUCCESS) + if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, hostnameX, &SpnLength, + ntlm->ServicePrincipalName) != ERROR_SUCCESS) goto error; status = TRUE; From ab107eb640abaa2b43c96cd6cc360a836116dd76 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Wed, 27 May 2020 11:53:28 +0200 Subject: [PATCH 25/65] Improve X11 shadow authentication reason failure log (cherry picked from commit e66ee477c00b91cddc228adaf1577be602e4f725) --- server/shadow/X11/x11_shadow.c | 81 +++++++++++++--------------------- 1 file changed, 30 insertions(+), 51 deletions(-) diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 9dfa12a5e70a..98cf44da84fa 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -128,90 +128,69 @@ static int x11_shadow_pam_conv(int num_msg, const struct pam_message** msg, return pam_status; } -static int x11_shadow_pam_get_service_name(SHADOW_PAM_AUTH_INFO* info) +static BOOL x11_shadow_pam_get_service_name(SHADOW_PAM_AUTH_INFO* info) { - if (PathFileExistsA("/etc/pam.d/lightdm")) - { - info->service_name = _strdup("lightdm"); - } - else if (PathFileExistsA("/etc/pam.d/gdm")) - { - info->service_name = _strdup("gdm"); - } - else if (PathFileExistsA("/etc/pam.d/xdm")) - { - info->service_name = _strdup("xdm"); - } - else if (PathFileExistsA("/etc/pam.d/login")) - { - info->service_name = _strdup("login"); - } - else if (PathFileExistsA("/etc/pam.d/sshd")) - { - info->service_name = _strdup("sshd"); - } - else + size_t x; + const char* base = "/etc/pam.d"; + const char* hints[] = { "lightdm", "gdm", "xdm", "login", "sshd" }; + + for (x = 0; x < ARRAYSIZE(hints); x++) { - return -1; - } + char path[MAX_PATH]; + const char* hint = hints[x]; - if (!info->service_name) - return -1; + _snprintf(path, sizeof(path), "%s/%s", base, hint); + if (PathFileExistsA(path)) + { - return 1; + info->service_name = _strdup(hint); + return info->service_name != NULL; + } + } + WLog_WARN(TAG, "Could not determine PAM service name"); + return FALSE; } static int x11_shadow_pam_authenticate(rdpShadowSubsystem* subsystem, rdpShadowClient* client, const char* user, const char* domain, const char* password) { int pam_status; - SHADOW_PAM_AUTH_INFO* info; + SHADOW_PAM_AUTH_INFO info = { 0 }; WINPR_UNUSED(subsystem); WINPR_UNUSED(client); - info = calloc(1, sizeof(SHADOW_PAM_AUTH_INFO)); - - if (!info) - return PAM_CONV_ERR; - if (x11_shadow_pam_get_service_name(info) < 0) - { - free(info); + if (!x11_shadow_pam_get_service_name(&info)) return -1; - } - info->appdata.user = user; - info->appdata.domain = domain; - info->appdata.password = password; - info->pamc.conv = &x11_shadow_pam_conv; - info->pamc.appdata_ptr = &(info->appdata); - pam_status = pam_start(info->service_name, 0, &(info->pamc), &(info->handle)); + info.appdata.user = user; + info.appdata.domain = domain; + info.appdata.password = password; + info.pamc.conv = &x11_shadow_pam_conv; + info.pamc.appdata_ptr = &(info->appdata); + pam_status = pam_start(info->service_name, 0, &info.pamc, &info.handle); if (pam_status != PAM_SUCCESS) { - WLog_ERR(TAG, "pam_start failure: %s", pam_strerror(info->handle, pam_status)); - free(info); + WLog_ERR(TAG, "pam_start failure: %s", pam_strerror(info.handle, pam_status)); return -1; } - pam_status = pam_authenticate(info->handle, 0); + pam_status = pam_authenticate(info.handle, 0); if (pam_status != PAM_SUCCESS) { - WLog_ERR(TAG, "pam_authenticate failure: %s", pam_strerror(info->handle, pam_status)); - free(info); + WLog_ERR(TAG, "pam_authenticate failure: %s", pam_strerror(info.handle, pam_status)); return -1; } - pam_status = pam_acct_mgmt(info->handle, 0); + pam_status = pam_acct_mgmt(info.handle, 0); if (pam_status != PAM_SUCCESS) { - WLog_ERR(TAG, "pam_acct_mgmt failure: %s", pam_strerror(info->handle, pam_status)); - free(info); + WLog_ERR(TAG, "pam_acct_mgmt failure: %s", pam_strerror(info.handle, pam_status)); return -1; } - free(info); return 1; } From 0121f726d82726b77e317e20488627d05e42c489 Mon Sep 17 00:00:00 2001 From: makki_d Date: Thu, 4 Jun 2020 18:22:55 +0900 Subject: [PATCH 26/65] fix +unmap-buttons option having the opposite effect (cherry picked from commit 4607a2766afd2875696b7b7febd9dc63f778b8d7) --- client/X11/xf_client.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 146c7feeab09..301820e64f83 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -1120,7 +1120,7 @@ static void xf_button_map_init(xfContext* xfc) x11_map[111] = 112; /* query system for actual remapping */ - if (!xfc->context.settings->UnmapButtons) + if (xfc->context.settings->UnmapButtons) { xf_get_x11_button_map(xfc, x11_map); } @@ -1142,8 +1142,8 @@ static void xf_button_map_init(xfContext* xfc) else { button_map* map = &xfc->button_map[pos++]; - map->button = physical + Button1; - map->flags = get_flags_for_button(logical); + map->button = logical; + map->flags = get_flags_for_button(physical + Button1); } } } From 192f922502b7d4279ce2ff859cf2f8f6d3f101b8 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 3 Jun 2020 09:53:18 +0200 Subject: [PATCH 27/65] Fixed sign compare warnings with constants. (cherry picked from commit 5ec66cc6c79dadf4c3426060d5bb30ddb360f292) --- channels/rdpei/rdpei_common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/channels/rdpei/rdpei_common.c b/channels/rdpei/rdpei_common.c index f01d4dd78f37..7628b32a654a 100644 --- a/channels/rdpei/rdpei_common.c +++ b/channels/rdpei/rdpei_common.c @@ -306,7 +306,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value) value *= -1; } - if (value <= 0x1FUL) + if (value <= 0x1FL) { byte = value & 0x1F; @@ -315,7 +315,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value) Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFUL) + else if (value <= 0x1FFFL) { byte = (value >> 8) & 0x1F; @@ -326,7 +326,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFUL) + else if (value <= 0x1FFFFFL) { byte = (value >> 16) & 0x1F; @@ -339,7 +339,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFFFUL) + else if (value <= 0x1FFFFFFFL) { byte = (value >> 24) & 0x1F; From fd42acc594da8535723e03727a08c1bd625091a6 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 3 Jun 2020 08:37:45 +0200 Subject: [PATCH 28/65] Fixed double free in urb_isoch_transfer_cb (cherry picked from commit ef4de12887486857f7eec37ef93df692b2ecedf0) --- channels/urbdrc/client/data_transfer.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c index 30def229800a..ecacc695f99c 100644 --- a/channels/urbdrc/client/data_transfer.c +++ b/channels/urbdrc/client/data_transfer.c @@ -767,8 +767,6 @@ static void urb_isoch_transfer_cb(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callb callback->channel->Write(callback->channel, Stream_GetPosition(out), Stream_Buffer(out), NULL); } - - Stream_Free(out, TRUE); } static UINT urb_isoch_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callback, wStream* s, From b300c8a7382076984a5166508954636bded309bb Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 3 Jun 2020 08:24:17 +0200 Subject: [PATCH 29/65] Do not remove transfer data on usb cancel transfer (cherry picked from commit a5e2d62e48619d5502f5334d431ee7d66ae9e4aa) --- channels/urbdrc/client/libusb/libusb_udevice.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c index 7c73e940eef0..ce231ba3699f 100644 --- a/channels/urbdrc/client/libusb/libusb_udevice.c +++ b/channels/urbdrc/client/libusb/libusb_udevice.c @@ -1177,6 +1177,7 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c user_data->streamID = streamID; #endif libusb_set_iso_packet_lengths(iso_transfer, iso_packet_size); + HashTable_Add(pdev->request_queue, (void*)(size_t)streamID, iso_transfer); return libusb_submit_transfer(iso_transfer); } @@ -1301,7 +1302,6 @@ static int func_cancel_xact_request(URBDRC_PLUGIN* urbdrc, wHashTable* queue, ui return -1; status = libusb_cancel_transfer(transfer); - HashTable_Remove(queue, (void*)(size_t)streamID); if (status < 0) { @@ -1357,6 +1357,7 @@ static int libusb_udev_cancel_transfer_request(IUDEVICE* idev, UINT32 RequestId) urbdrc = (URBDRC_PLUGIN*)pdev->urbdrc; cancelID = (id1) ? cancelID1 : cancelID2; + transfer = HashTable_GetItemValue(pdev->request_queue, (void*)(size_t)cancelID); return func_cancel_xact_request(urbdrc, pdev->request_queue, cancelID, transfer); } From 9a13ba347dc00305d7aff51fb968859fa0462aeb Mon Sep 17 00:00:00 2001 From: akallabeth Date: Wed, 27 May 2020 10:01:04 +0200 Subject: [PATCH 30/65] Fixed surface locking for shadow server. (cherry picked from commit a38d6c53a62cdea302fbeb4e466bce22c006d20c) --- server/shadow/Mac/mac_shadow.c | 11 +++++-- server/shadow/X11/x11_shadow.c | 58 +++++++++++++++++++++++----------- server/shadow/shadow_client.c | 5 +-- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index 053232978018..6dd3ba1ac90d 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -370,6 +370,7 @@ static void (^mac_capture_stream_handler)( int width; int height; int nSrcStep; + BOOL empty; BYTE* pSrcData; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; @@ -381,14 +382,17 @@ static void (^mac_capture_stream_handler)( if (count < 1) return; + EnterCriticalSection(&(surface->lock)); mac_shadow_capture_get_dirty_region(subsystem); surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect); + empty = region16_is_empty(&(surface->invalidRegion)); + LeaveCriticalSection(&(surface->lock)); - if (!region16_is_empty(&(surface->invalidRegion))) + if (!empty) { extents = region16_extents(&(surface->invalidRegion)); x = extents->left; @@ -410,13 +414,12 @@ static void (^mac_capture_stream_handler)( pSrcData, PIXEL_FORMAT_BGRX32, nSrcStep, x, y, NULL, FREERDP_FLIP_NONE); } + LeaveCriticalSection(&(surface->lock)); IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL); ArrayList_Lock(server->clients); count = ArrayList_Count(server->clients); - EnterCriticalSection(&(surface->lock)); shadow_subsystem_frame_update(&subsystem->common); - LeaveCriticalSection(&(surface->lock)); if (count == 1) { @@ -430,7 +433,9 @@ static void (^mac_capture_stream_handler)( } ArrayList_Unlock(server->clients); + EnterCriticalSection(&(surface->lock)); region16_clear(&(surface->invalidRegion)); + LeaveCriticalSection(&(surface->lock)); } if (status != kCGDisplayStreamFrameStatusFrameComplete) diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 98cf44da84fa..e48df014dc7e 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -736,6 +736,7 @@ static int x11_shadow_error_handler_for_capture(Display* display, XErrorEvent* e static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) { + int rc = 0; int count; int status; int x, y; @@ -753,10 +754,13 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) if (count < 1) return 1; + EnterCriticalSection(&surface->lock); surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; + LeaveCriticalSection(&surface->lock); + XLockDisplay(subsystem->display); /* * Ignore BadMatch error during image capture. The screen size may be @@ -769,15 +773,26 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) image = subsystem->fb_image; XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap, subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0); + + EnterCriticalSection(&surface->lock); status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height, (BYTE*)&(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect); + LeaveCriticalSection(&surface->lock); } else { + EnterCriticalSection(&surface->lock); image = XGetImage(subsystem->display, subsystem->root_window, surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap); + if (image) + { + status = shadow_capture_compare(surface->data, surface->scanline, surface->width, + surface->height, (BYTE*)image->data, + image->bytes_per_line, &invalidRect); + } + LeaveCriticalSection(&surface->lock); if (!image) { /* @@ -786,10 +801,6 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) */ goto fail_capture; } - - status = shadow_capture_compare(surface->data, surface->scanline, surface->width, - surface->height, (BYTE*)image->data, image->bytes_per_line, - &invalidRect); } /* Restore the default error handler */ @@ -799,25 +810,32 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) if (status) { + BOOL empty; + EnterCriticalSection(&surface->lock); region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect); + empty = region16_is_empty(&(surface->invalidRegion)); + LeaveCriticalSection(&surface->lock); - if (!region16_is_empty(&(surface->invalidRegion))) + if (!empty) { + BOOL success; + EnterCriticalSection(&surface->lock); extents = region16_extents(&(surface->invalidRegion)); x = extents->left; y = extents->top; width = extents->right - extents->left; height = extents->bottom - extents->top; - - if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y, width, - height, (BYTE*)image->data, PIXEL_FORMAT_BGRX32, - image->bytes_per_line, x, y, NULL, FREERDP_FLIP_NONE)) + success = freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y, + width, height, (BYTE*)image->data, PIXEL_FORMAT_BGRX32, + image->bytes_per_line, x, y, NULL, FREERDP_FLIP_NONE); + LeaveCriticalSection(&surface->lock); + if (!success) goto fail_capture; // x11_shadow_blend_cursor(subsystem); count = ArrayList_Count(server->clients); - shadow_subsystem_frame_update((rdpShadowSubsystem*)subsystem); + shadow_subsystem_frame_update(&subsystem->common); if (count == 1) { @@ -829,23 +847,25 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) shadow_encoder_preferred_fps(client->encoder); } + EnterCriticalSection(&surface->lock); region16_clear(&(surface->invalidRegion)); + LeaveCriticalSection(&surface->lock); } } - if (!subsystem->use_xshm) - XDestroyImage(image); - - return 1; + rc = 1; fail_capture: - if (!subsystem->use_xshm && image) XDestroyImage(image); - XSetErrorHandler(NULL); - XSync(subsystem->display, False); - XUnlockDisplay(subsystem->display); - return 0; + if (rc != 1) + { + XSetErrorHandler(NULL); + XSync(subsystem->display, False); + XUnlockDisplay(subsystem->display); + } + + return rc; } static int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage* message) diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index f32f6497602c..86bc3fc038f0 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -1331,12 +1331,12 @@ static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GF region16_copy(&invalidRegion, &(client->invalidRegion)); region16_clear(&(client->invalidRegion)); LeaveCriticalSection(&(client->lock)); + + EnterCriticalSection(&surface->lock); rects = region16_rects(&(surface->invalidRegion), &numRects); for (index = 0; index < numRects; index++) - { region16_union_rect(&invalidRegion, &invalidRegion, &rects[index]); - } surfaceRect.left = 0; surfaceRect.top = 0; @@ -1410,6 +1410,7 @@ static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GF } out: + LeaveCriticalSection(&surface->lock); region16_uninit(&invalidRegion); return ret; } From 1e248ef7a26e538f7bf1e91e34045d9ec65d69af Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 16 Jun 2020 14:02:49 +0200 Subject: [PATCH 31/65] Fixed compilation issue with shadow pam code (cherry picked from commit e1e0f965e8636c587aea7762a94d611e193e07f3) --- server/shadow/X11/x11_shadow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index e48df014dc7e..4a8aab156e4b 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -166,8 +166,8 @@ static int x11_shadow_pam_authenticate(rdpShadowSubsystem* subsystem, rdpShadowC info.appdata.domain = domain; info.appdata.password = password; info.pamc.conv = &x11_shadow_pam_conv; - info.pamc.appdata_ptr = &(info->appdata); - pam_status = pam_start(info->service_name, 0, &info.pamc, &info.handle); + info.pamc.appdata_ptr = &info.appdata; + pam_status = pam_start(info.service_name, 0, &info.pamc, &info.handle); if (pam_status != PAM_SUCCESS) { From 0dba34e642ed33d50cc92f7aaf424385d54f431e Mon Sep 17 00:00:00 2001 From: Kobi Mizrachi Date: Mon, 1 Jun 2020 09:33:12 +0300 Subject: [PATCH 32/65] winpr: image: add API to construct bmp header (cherry picked from commit 920acd4c0ee7f9112d77756b0c41474212446609) --- winpr/include/winpr/image.h | 3 ++ winpr/libwinpr/utils/image.c | 62 +++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/winpr/include/winpr/image.h b/winpr/include/winpr/image.h index 24ec02dd14c7..66e5960e0bfa 100644 --- a/winpr/include/winpr/image.h +++ b/winpr/include/winpr/image.h @@ -66,6 +66,8 @@ typedef struct _WINPR_BITMAP_CORE_HEADER WINPR_BITMAP_CORE_HEADER; #define WINPR_IMAGE_BITMAP 0 #define WINPR_IMAGE_PNG 1 +#define WINPR_IMAGE_BMP_HEADER_LEN 54 + struct _wImage { int type; @@ -85,6 +87,7 @@ extern "C" WINPR_API int winpr_bitmap_write(const char* filename, const BYTE* data, int width, int height, int bpp); + WINPR_API BYTE* winpr_bitmap_construct_header(int width, int height, int bpp); WINPR_API int winpr_image_write(wImage* image, const char* filename); WINPR_API int winpr_image_read(wImage* image, const char* filename); diff --git a/winpr/libwinpr/utils/image.c b/winpr/libwinpr/utils/image.c index 41b4cc5e1d3c..a1155e5eb00c 100644 --- a/winpr/libwinpr/utils/image.c +++ b/winpr/libwinpr/utils/image.c @@ -100,24 +100,18 @@ static BOOL readBitmapInfoHeader(wStream* s, WINPR_BITMAP_INFO_HEADER* bi) return TRUE; } -/** - * Refer to "Compressed Image File Formats: JPEG, PNG, GIF, XBM, BMP" book - */ - -int winpr_bitmap_write(const char* filename, const BYTE* data, int width, int height, int bpp) +BYTE* winpr_bitmap_construct_header(int width, int height, int bpp) { - FILE* fp; WINPR_BITMAP_FILE_HEADER bf; WINPR_BITMAP_INFO_HEADER bi; - wStream* s; - int ret = -1; - fp = fopen(filename, "w+b"); + wStream s; + BYTE* buffer = NULL; - if (!fp) - { - WLog_ERR(TAG, "failed to open file %s", filename); - return -1; - } + buffer = malloc(WINPR_IMAGE_BMP_HEADER_LEN); + if (!buffer) + return NULL; + + Stream_StaticInit(&s, buffer, WINPR_IMAGE_BMP_HEADER_LEN); bf.bfType[0] = 'B'; bf.bfType[1] = 'M'; @@ -136,27 +130,49 @@ int winpr_bitmap_write(const char* filename, const BYTE* data, int width, int he bi.biClrUsed = 0; bi.biClrImportant = 0; bi.biSize = sizeof(WINPR_BITMAP_INFO_HEADER); - s = Stream_New(NULL, sizeof(WINPR_BITMAP_FILE_HEADER) + sizeof(WINPR_BITMAP_INFO_HEADER)); - if (!s) + if (!writeBitmapFileHeader(&s, &bf)) goto fail; - if (!writeBitmapFileHeader(s, &bf)) + if (!writeBitmapInfoHeader(&s, &bi)) goto fail; - if (!writeBitmapInfoHeader(s, &bi)) - goto fail; + return buffer; +fail: + return NULL; +} + +/** + * Refer to "Compressed Image File Formats: JPEG, PNG, GIF, XBM, BMP" book + */ + +int winpr_bitmap_write(const char* filename, const BYTE* data, int width, int height, int bpp) +{ + FILE* fp; + BYTE* bmp_header = NULL; + UINT32 img_size = width * height * (bpp / 8); + + int ret = -1; + fp = fopen(filename, "w+b"); + + if (!fp) + { + WLog_ERR(TAG, "failed to open file %s", filename); + return -1; + } - Stream_SealLength(s); + bmp_header = winpr_bitmap_construct_header(width, height, bpp); + if (!bmp_header) + return -1; - if (fwrite(Stream_Buffer(s), Stream_Length(s), 1, fp) != 1 || - fwrite((void*)data, bi.biSizeImage, 1, fp) != 1) + if (fwrite(bmp_header, WINPR_IMAGE_BMP_HEADER_LEN, 1, fp) != 1 || + fwrite((void*)data, img_size, 1, fp) != 1) goto fail; ret = 1; fail: fclose(fp); - Stream_Free(s, TRUE); + free(bmp_header); return ret; } From f96a95aca5ee467ec79118dcc67f23f94a4df05c Mon Sep 17 00:00:00 2001 From: Kobi Mizrachi Date: Mon, 1 Jun 2020 09:37:53 +0300 Subject: [PATCH 33/65] server: proxy: implement session capture plugin (cherry picked from commit 19809bf338e5503a33664440d0de9313dca038a3) --- server/proxy/modules/capture/CMakeLists.txt | 33 +++ server/proxy/modules/capture/cap_config.c | 97 +++++++ server/proxy/modules/capture/cap_config.h | 29 ++ server/proxy/modules/capture/cap_main.c | 287 ++++++++++++++++++++ server/proxy/modules/capture/cap_protocol.c | 57 ++++ server/proxy/modules/capture/cap_protocol.h | 35 +++ 6 files changed, 538 insertions(+) create mode 100644 server/proxy/modules/capture/CMakeLists.txt create mode 100644 server/proxy/modules/capture/cap_config.c create mode 100644 server/proxy/modules/capture/cap_config.h create mode 100644 server/proxy/modules/capture/cap_main.c create mode 100644 server/proxy/modules/capture/cap_protocol.c create mode 100644 server/proxy/modules/capture/cap_protocol.h diff --git a/server/proxy/modules/capture/CMakeLists.txt b/server/proxy/modules/capture/CMakeLists.txt new file mode 100644 index 000000000000..80ba3b77e1c6 --- /dev/null +++ b/server/proxy/modules/capture/CMakeLists.txt @@ -0,0 +1,33 @@ +# +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP Proxy Server Capture Module +# +# Copyright 2019 Kobi Mizrachi +# +# 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. +# + +set(PLUGIN_NAME "proxy-capture-plugin") + +add_library(${PLUGIN_NAME} MODULE + cap_main.c + cap_config.c + cap_config.h + cap_protocol.c + cap_protocol.h +) + +set_target_properties(${PLUGIN_NAME} PROPERTIES PREFIX "") +set_target_properties(${PLUGIN_NAME} PROPERTIES NO_SONAME 1) +set_target_properties(${PLUGIN_NAME} PROPERTIES +LIBRARY_OUTPUT_DIRECTORY "${FREERDP_PROXY_PLUGINDIR}") diff --git a/server/proxy/modules/capture/cap_config.c b/server/proxy/modules/capture/cap_config.c new file mode 100644 index 000000000000..ae4b6a6477b1 --- /dev/null +++ b/server/proxy/modules/capture/cap_config.c @@ -0,0 +1,97 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server Session Capture Module + * + * Copyright 2019 Kobi Mizrachi + * + * 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. + */ + +#include +#include +#include + +#include "cap_config.h" + +BOOL capture_plugin_init_config(captureConfig* config) +{ + const char* name = "PROXY_CAPTURE_TARGET"; + char* tmp = NULL; + DWORD nSize = GetEnvironmentVariableA(name, NULL, 0); + + if (nSize) + { + char* colon; + int addrLen; + unsigned long port; + + tmp = (LPSTR)malloc(nSize); + if (!tmp) + return FALSE; + + if (GetEnvironmentVariableA(name, tmp, nSize) != nSize - 1) + { + free(tmp); + return FALSE; + } + + colon = strchr(tmp, ':'); + + if (!colon) + { + free(tmp); + return FALSE; + } + + addrLen = (int)(colon - tmp); + config->host = malloc(addrLen + 1); + if (!config->host) + { + free(tmp); + return FALSE; + } + + strncpy(config->host, tmp, addrLen); + config->host[addrLen] = '\0'; + + port = strtoul(colon + 1, NULL, 0); + + if ((errno != 0) || (port > UINT16_MAX)) + { + free(config->host); + config->host = NULL; + + free(tmp); + return FALSE; + } + + config->port = port; + free(tmp); + } + else + { + config->host = _strdup("127.0.0.1"); + if (!config->host) + return FALSE; + + config->port = 8889; + } + + return TRUE; +} + +void capture_plugin_config_free_internal(captureConfig* config) +{ + free(config->host); + config->host = NULL; +} diff --git a/server/proxy/modules/capture/cap_config.h b/server/proxy/modules/capture/cap_config.h new file mode 100644 index 000000000000..ace5079dc17a --- /dev/null +++ b/server/proxy/modules/capture/cap_config.h @@ -0,0 +1,29 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server Session Capture Module + * + * Copyright 2019 Kobi Mizrachi + * + * 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. + */ + +#include + +typedef struct capture_config +{ + UINT16 port; + char* host; +} captureConfig; + +BOOL capture_plugin_init_config(captureConfig* config); +void capture_plugin_config_free_internal(captureConfig* config); diff --git a/server/proxy/modules/capture/cap_main.c b/server/proxy/modules/capture/cap_main.c new file mode 100644 index 000000000000..8780900aeb48 --- /dev/null +++ b/server/proxy/modules/capture/cap_main.c @@ -0,0 +1,287 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server Session Capture Module + * + * Copyright 2019 Kobi Mizrachi + * + * 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. + */ + +#define TAG MODULE_TAG("capture") + +#define PLUGIN_NAME "capture" +#define PLUGIN_DESC "stream egfx connections over tcp" + +#include +#include +#include +#include + +#include "pf_log.h" +#include "modules_api.h" +#include "pf_context.h" +#include "cap_config.h" +#include "cap_protocol.h" + +#define BUFSIZE 8092 + +static proxyPluginsManager* g_plugins_manager = NULL; +static captureConfig config = { 0 }; + +static SOCKET capture_plugin_init_socket() +{ + int status; + int sockfd; + struct sockaddr_in addr = { 0 }; + sockfd = _socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (sockfd == -1) + return -1; + + addr.sin_family = AF_INET; + addr.sin_port = htons(config.port); + inet_pton(AF_INET, config.host, &(addr.sin_addr)); + + status = _connect(sockfd, (const struct sockaddr*)&addr, sizeof(addr)); + if (status < 0) + { + close(sockfd); + return -1; + } + + return sockfd; +} + +static BOOL capture_plugin_send_data(SOCKET sockfd, const BYTE* buffer, size_t len) +{ + size_t chunk_len; + int nsent; + + if (!buffer) + return FALSE; + + while (len > 0) + { + chunk_len = len > BUFSIZE ? BUFSIZE : len; + nsent = _send(sockfd, (const char*)buffer, chunk_len, 0); + if (nsent == -1) + return FALSE; + + buffer += nsent; + len -= nsent; + } + + return TRUE; +} + +static BOOL capture_plugin_send_packet(SOCKET sockfd, wStream* packet) +{ + size_t len; + BYTE* buffer; + BOOL result = FALSE; + + if (!packet) + return FALSE; + + buffer = Stream_Buffer(packet); + len = Stream_Capacity(packet); + + if (!capture_plugin_send_data(sockfd, buffer, len)) + { + WLog_ERR(TAG, "error while transmitting frame: errno=%d", errno); + goto error; + } + + result = TRUE; + +error: + Stream_Free(packet, TRUE); + return result; +} + +static SOCKET capture_plugin_get_socket(proxyData* pdata) +{ + void* custom; + + custom = g_plugins_manager->GetPluginData(PLUGIN_NAME, pdata); + if (!custom) + return -1; + + return (SOCKET)custom; +} + +static BOOL capture_plugin_session_end(proxyData* pdata) +{ + SOCKET socket; + BOOL ret; + + socket = capture_plugin_get_socket(pdata); + if (socket == -1) + return FALSE; + + wStream* s = capture_plugin_packet_new(SESSION_END_PDU_BASE_SIZE, MESSAGE_TYPE_SESSION_END); + if (!s) + return FALSE; + + ret = capture_plugin_send_packet(socket, s); + + closesocket(socket); + return ret; +} + +static BOOL capture_plugin_send_frame(pClientContext* pc, SOCKET socket, const BYTE* buffer) +{ + size_t frame_size; + BOOL ret = FALSE; + wStream* s = NULL; + BYTE* bmp_header = NULL; + rdpSettings* settings = pc->context.settings; + + frame_size = settings->DesktopWidth * settings->DesktopHeight * (settings->ColorDepth / 8); + bmp_header = winpr_bitmap_construct_header(settings->DesktopWidth, settings->DesktopHeight, + settings->ColorDepth); + + if (!bmp_header) + return FALSE; + + /* + * capture frame packet indicates a packet that contains a frame buffer. payload length is + * marked as 0, and receiving side must read `frame_size` bytes, a constant size of + * width*height*(bpp/8) from the socket, to receive the full frame buffer. + */ + s = capture_plugin_packet_new(0, MESSAGE_TYPE_CAPTURED_FRAME); + if (!s) + goto error; + + if (!capture_plugin_send_packet(socket, s)) + goto error; + + ret = capture_plugin_send_data(socket, bmp_header, WINPR_IMAGE_BMP_HEADER_LEN); + if (!ret) + goto error; + + ret = capture_plugin_send_data(socket, buffer, frame_size); + +error: + free(bmp_header); + return ret; +} + +static BOOL capture_plugin_client_end_paint(proxyData* pdata) +{ + pClientContext* pc = pdata->pc; + rdpGdi* gdi = pc->context.gdi; + SOCKET socket; + + if (gdi->suppressOutput) + return TRUE; + + if (gdi->primary->hdc->hwnd->ninvalid < 1) + return TRUE; + + socket = capture_plugin_get_socket(pdata); + if (socket == -1) + return FALSE; + + if (!capture_plugin_send_frame(pc, socket, gdi->primary_buffer)) + { + WLog_ERR(TAG, "capture_plugin_send_frame failed!"); + return FALSE; + } + + gdi->primary->hdc->hwnd->invalid->null = TRUE; + gdi->primary->hdc->hwnd->ninvalid = 0; + return TRUE; +} + +static BOOL capture_plugin_client_post_connect(proxyData* pdata) +{ + SOCKET socket; + wStream* s; + pClientContext* pc = pdata->pc; + rdpSettings* settings = pc->context.settings; + + socket = capture_plugin_init_socket(); + if (socket == -1) + { + WLog_ERR(TAG, "failed to establish a connection"); + return FALSE; + } + + g_plugins_manager->SetPluginData(PLUGIN_NAME, pdata, (void*)socket); + + s = capture_plugin_create_session_info_packet(settings); + if (!s) + return FALSE; + + return capture_plugin_send_packet(socket, s); +} + +static BOOL capture_plugin_server_post_connect(proxyData* pdata) +{ + pServerContext* ps = pdata->ps; + proxyConfig* config = pdata->config; + rdpSettings* settings = ps->context.settings; + + if (!config->GFX || !config->SessionCapture) + { + WLog_ERR(TAG, "config options 'GFX' and 'SessionCapture' options must be set to true!"); + return FALSE; + } + + if (!settings->SupportGraphicsPipeline) + { + WLog_ERR(TAG, "session capture is only supported for GFX clients, denying connection"); + return FALSE; + } + + return TRUE; +} + +static BOOL capture_plugin_unload() +{ + capture_plugin_config_free_internal(&config); + return TRUE; +} + +static proxyPlugin demo_plugin = { + PLUGIN_NAME, /* name */ + PLUGIN_DESC, /* description */ + capture_plugin_unload, /* PluginUnload */ + NULL, /* ClientPreConnect */ + capture_plugin_client_post_connect, /* ClientPostConnect */ + NULL, /* ClientLoginFailure */ + capture_plugin_client_end_paint, /* ClientEndPaint */ + capture_plugin_server_post_connect, /* ServerPostConnect */ + NULL, /* ServerChannelsInit */ + NULL, /* ServerChannelsFree */ + capture_plugin_session_end, /* Session End */ + NULL, /* KeyboardEvent */ + NULL, /* MouseEvent */ + NULL, /* ClientChannelData */ + NULL, /* ServerChannelData */ +}; + +BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager) +{ + g_plugins_manager = plugins_manager; + + if (!capture_plugin_init_config(&config)) + { + WLog_ERR(TAG, "failed to load config"); + return FALSE; + } + + WLog_INFO(TAG, "host: %s, port: %" PRIu16 "", config.host, config.port); + return plugins_manager->RegisterPlugin(&demo_plugin); +} diff --git a/server/proxy/modules/capture/cap_protocol.c b/server/proxy/modules/capture/cap_protocol.c new file mode 100644 index 000000000000..b56393838049 --- /dev/null +++ b/server/proxy/modules/capture/cap_protocol.c @@ -0,0 +1,57 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server Session Capture Module + * + * Copyright 2019 Kobi Mizrachi + * + * 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. + */ + +#include "cap_protocol.h" + +wStream* capture_plugin_packet_new(UINT32 payload_size, UINT16 type) +{ + wStream* stream = Stream_New(NULL, HEADER_SIZE + payload_size); + + if (!stream) + return NULL; + + Stream_Write_UINT32(stream, payload_size); + Stream_Write_UINT16(stream, type); + return stream; +} + +wStream* capture_plugin_create_session_info_packet(rdpSettings* settings) +{ + UINT16 username_length; + wStream* s = NULL; + + if (!settings || !settings->Username) + return NULL; + + username_length = strlen(settings->Username); + if (username_length == 0) + return NULL; + + s = capture_plugin_packet_new(SESSION_INFO_PDU_BASE_SIZE + username_length, + MESSAGE_TYPE_SESSION_INFO); + if (!s) + return NULL; + + Stream_Write_UINT16(s, username_length); /* username length (2 bytes) */ + Stream_Write(s, settings->Username, username_length); /* username */ + Stream_Write_UINT32(s, settings->DesktopWidth); /* desktop width (4 bytes) */ + Stream_Write_UINT32(s, settings->DesktopHeight); /* desktop height (4 bytes) */ + Stream_Write_UINT32(s, settings->ColorDepth); /* color depth (4 bytes) */ + return s; +} diff --git a/server/proxy/modules/capture/cap_protocol.h b/server/proxy/modules/capture/cap_protocol.h new file mode 100644 index 000000000000..655eb69bdabe --- /dev/null +++ b/server/proxy/modules/capture/cap_protocol.h @@ -0,0 +1,35 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server Session Capture Module + * + * Copyright 2019 Kobi Mizrachi + * + * 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. + */ + +#include +#include + +/* protocol message sizes */ +#define HEADER_SIZE 6 +#define SESSION_INFO_PDU_BASE_SIZE 14 +#define SESSION_END_PDU_BASE_SIZE 0 +#define CAPTURED_FRAME_PDU_BASE_SIZE 0 + +/* protocol message types */ +#define MESSAGE_TYPE_SESSION_INFO 1 +#define MESSAGE_TYPE_CAPTURED_FRAME 2 +#define MESSAGE_TYPE_SESSION_END 3 + +wStream* capture_plugin_packet_new(UINT32 payload_size, UINT16 type); +wStream* capture_plugin_create_session_info_packet(rdpSettings* settings); From c0da1a959f627497698725d899d4d776821a98bb Mon Sep 17 00:00:00 2001 From: Kubistika Date: Wed, 3 Jun 2020 13:56:52 +0300 Subject: [PATCH 34/65] server: proxy: cap plugin: fix var and func declaration (cherry picked from commit 0cf764f170384b1f65aa4950f54c668f8212ac11) --- server/proxy/modules/capture/cap_config.c | 2 +- server/proxy/modules/capture/cap_main.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/server/proxy/modules/capture/cap_config.c b/server/proxy/modules/capture/cap_config.c index ae4b6a6477b1..32e02ae4dab5 100644 --- a/server/proxy/modules/capture/cap_config.c +++ b/server/proxy/modules/capture/cap_config.c @@ -29,7 +29,7 @@ BOOL capture_plugin_init_config(captureConfig* config) char* tmp = NULL; DWORD nSize = GetEnvironmentVariableA(name, NULL, 0); - if (nSize) + if (nSize > 0) { char* colon; int addrLen; diff --git a/server/proxy/modules/capture/cap_main.c b/server/proxy/modules/capture/cap_main.c index 8780900aeb48..0f5d5bc4f637 100644 --- a/server/proxy/modules/capture/cap_main.c +++ b/server/proxy/modules/capture/cap_main.c @@ -38,7 +38,7 @@ static proxyPluginsManager* g_plugins_manager = NULL; static captureConfig config = { 0 }; -static SOCKET capture_plugin_init_socket() +static SOCKET capture_plugin_init_socket(void) { int status; int sockfd; @@ -124,12 +124,13 @@ static BOOL capture_plugin_session_end(proxyData* pdata) { SOCKET socket; BOOL ret; + wStream* s; socket = capture_plugin_get_socket(pdata); if (socket == -1) return FALSE; - wStream* s = capture_plugin_packet_new(SESSION_END_PDU_BASE_SIZE, MESSAGE_TYPE_SESSION_END); + s = capture_plugin_packet_new(SESSION_END_PDU_BASE_SIZE, MESSAGE_TYPE_SESSION_END); if (!s) return FALSE; @@ -248,7 +249,7 @@ static BOOL capture_plugin_server_post_connect(proxyData* pdata) return TRUE; } -static BOOL capture_plugin_unload() +static BOOL capture_plugin_unload(void) { capture_plugin_config_free_internal(&config); return TRUE; From 809a86f0fb1c11069bfbbd687991e18d951d017f Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 15 Jun 2020 15:49:21 +0200 Subject: [PATCH 35/65] Lock wayland buffer updates (cherry picked from commit 7361f75d11b77f998cf7dee08c8aa619df98754a) --- client/Wayland/wlfreerdp.c | 29 ++++++++++++++++++++--------- client/Wayland/wlfreerdp.h | 1 + 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 5086220d2fba..872f20079a37 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -62,6 +62,7 @@ static BOOL wl_begin_paint(rdpContext* context) static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw, INT32 ih) { + BOOL res = FALSE; rdpGdi* gdi; char* data; UINT32 x, y, w, h; @@ -76,6 +77,7 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw if ((ix < 0) || (iy < 0) || (iw < 0) || (ih < 0)) return FALSE; + EnterCriticalSection(&context_w->critical); x = (UINT32)ix; y = (UINT32)iy; w = (UINT32)iw; @@ -84,16 +86,19 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw data = UwacWindowGetDrawingBuffer(context_w->window); if (!data || (rc != UWAC_SUCCESS)) - return FALSE; + goto fail; gdi = context_w->context.gdi; if (!gdi) - return FALSE; + goto fail; /* Ignore output if the surface size does not match. */ if (((INT64)x > geometry.width) || ((INT64)y > geometry.height)) - return TRUE; + { + res = TRUE; + goto fail; + } area.left = x; area.top = y; @@ -103,21 +108,24 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw if (!wlf_copy_image(gdi->primary_buffer, gdi->stride, gdi->width, gdi->height, data, stride, geometry.width, geometry.height, &area, context_w->context.settings->SmartSizing)) - return FALSE; + goto fail; if (!wlf_scale_coordinates(&context_w->context, &x, &y, FALSE)) - return FALSE; + goto fail; if (!wlf_scale_coordinates(&context_w->context, &w, &h, FALSE)) - return FALSE; + goto fail; if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS) - return FALSE; + goto fail; if (UwacWindowSubmitBuffer(context_w->window, false) != UWAC_SUCCESS) - return FALSE; + goto fail; - return TRUE; + res = TRUE; +fail: + LeaveCriticalSection(&context_w->critical); + return res; } static BOOL wl_end_paint(rdpContext* context) @@ -552,6 +560,8 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context) if (!wfl->displayHandle) return FALSE; + InitializeCriticalSection(&wfl->critical); + return TRUE; } @@ -567,6 +577,7 @@ static void wlf_client_free(freerdp* instance, rdpContext* context) if (wlf->displayHandle) CloseHandle(wlf->displayHandle); + DeleteCriticalSection(&wlf->critical); } static int wfl_client_start(rdpContext* context) diff --git a/client/Wayland/wlfreerdp.h b/client/Wayland/wlfreerdp.h index 09d056ae4ef3..d647066907f2 100644 --- a/client/Wayland/wlfreerdp.h +++ b/client/Wayland/wlfreerdp.h @@ -50,6 +50,7 @@ struct wlf_context wfClipboard* clipboard; wlfDispContext* disp; wLog* log; + CRITICAL_SECTION critical; }; BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP); From f1e46894cb7f705550d1dcb56e882a7ccdf44c47 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 16 Jun 2020 13:54:12 +0200 Subject: [PATCH 36/65] Fixed double free for uwac buffers (cherry picked from commit 1bc48b058f013a8c88db2a1d7da2ad25dcd3bc4c) --- uwac/libuwac/uwac-priv.h | 3 +- uwac/libuwac/uwac-window.c | 82 ++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/uwac/libuwac/uwac-priv.h b/uwac/libuwac/uwac-priv.h index 75ad6e0fe039..2ef073de1b72 100644 --- a/uwac/libuwac/uwac-priv.h +++ b/uwac/libuwac/uwac-priv.h @@ -235,7 +235,8 @@ struct uwac_window struct wl_region* opaque_region; struct wl_region* input_region; - UwacBuffer *drawingBuffer, *pendingBuffer; + SSIZE_T drawingBufferIdx; + SSIZE_T pendingBufferIdx; struct wl_surface* surface; struct wl_shell_surface* shell_surface; struct xdg_surface* xdg_surface; diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c index f76d43bcc859..2f424e87cab2 100644 --- a/uwac/libuwac/uwac-window.c +++ b/uwac/libuwac/uwac-window.c @@ -136,13 +136,13 @@ static void xdg_handle_toplevel_configure(void* data, struct xdg_toplevel* xdg_t { assert( uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); - window->drawingBuffer = window->pendingBuffer = NULL; + window->drawingBufferIdx = window->pendingBufferIdx = -1; return; } - window->drawingBuffer = &window->buffers[0]; - if (window->pendingBuffer != NULL) - window->pendingBuffer = window->drawingBuffer; + window->drawingBufferIdx = 0; + if (window->pendingBufferIdx != -1) + window->pendingBufferIdx = window->drawingBufferIdx; } else { @@ -219,13 +219,13 @@ static void ivi_handle_configure(void* data, struct ivi_surface* surface, int32_ { assert( uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); - window->drawingBuffer = window->pendingBuffer = NULL; + window->drawingBufferIdx = window->pendingBufferIdx = -1; return; } - window->drawingBuffer = &window->buffers[0]; - if (window->pendingBuffer != NULL) - window->pendingBuffer = window->drawingBuffer; + window->drawingBufferIdx = 0; + if (window->pendingBufferIdx != -1) + window->pendingBufferIdx = window->drawingBufferIdx; } else { @@ -277,13 +277,13 @@ static void shell_configure(void* data, struct wl_shell_surface* surface, uint32 { assert( uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); - window->drawingBuffer = window->pendingBuffer = NULL; + window->drawingBufferIdx = window->pendingBufferIdx = -1; return; } - window->drawingBuffer = &window->buffers[0]; - if (window->pendingBuffer != NULL) - window->pendingBuffer = window->drawingBuffer; + window->drawingBufferIdx = 0; + if (window->pendingBufferIdx != -1) + window->pendingBufferIdx = window->drawingBufferIdx; } else { @@ -364,15 +364,21 @@ int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32 return ret; } -static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w) +static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w, SSIZE_T* index) { - int i, ret; + SSIZE_T i; + int ret; + + if (index) + *index = -1; for (i = 0; i < w->nbuffers; i++) { if (!w->buffers[i].used) { w->buffers[i].used = true; + if (index) + *index = i; return &w->buffers[i]; } } @@ -386,6 +392,8 @@ static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w) } w->buffers[i].used = true; + if (index) + *index = i; return &w->buffers[i]; } @@ -457,7 +465,8 @@ UwacWindow* UwacCreateWindowShm(UwacDisplay* display, uint32_t width, uint32_t h } w->buffers[0].used = true; - w->drawingBuffer = &w->buffers[0]; + w->drawingBufferIdx = 0; + w->pendingBufferIdx = -1; w->surface = wl_compositor_create_surface(display->compositor); if (!w->surface) @@ -603,7 +612,16 @@ UwacReturnCode UwacWindowSetInputRegion(UwacWindow* window, uint32_t x, uint32_t void* UwacWindowGetDrawingBuffer(UwacWindow* window) { - return window->drawingBuffer->data; + UwacBuffer* buffer; + + if (window->drawingBufferIdx < 0) + return NULL; + + buffer = &window->buffers[window->drawingBufferIdx]; + if (!buffer) + return NULL; + + return buffer->data; } static void frame_done_cb(void* data, struct wl_callback* callback, uint32_t time); @@ -654,7 +672,7 @@ static void frame_done_cb(void* data, struct wl_callback* callback, uint32_t tim UwacFrameDoneEvent* event; wl_callback_destroy(callback); - window->pendingBuffer = NULL; + window->pendingBufferIdx = -1; event = (UwacFrameDoneEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE); if (event) @@ -677,13 +695,20 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, u uint32_t height) { RECTANGLE_16 box; + UwacBuffer* buf; box.left = x; box.top = y; box.right = x + width; box.bottom = y + height; - UwacBuffer* buf = window->drawingBuffer; + if (window->drawingBufferIdx < 0) + return UWAC_ERROR_INTERNAL; + + buf = &window->buffers[window->drawingBufferIdx]; + if (!buf) + return UWAC_ERROR_INTERNAL; + if (!region16_union_rect(&buf->damage, &buf->damage, &box)) return UWAC_ERROR_INTERNAL; @@ -695,7 +720,7 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, u UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* geometry, size_t* stride) { - if (!window || !window->drawingBuffer) + if (!window || (window->drawingBufferIdx < 0)) return UWAC_ERROR_INTERNAL; if (geometry) @@ -712,20 +737,25 @@ UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame) { - UwacBuffer* drawingBuffer = window->drawingBuffer; + UwacBuffer* drawingBuffer; + UwacBuffer* nextBuffer; + + if (window->drawingBufferIdx < 0) + return UWAC_ERROR_INTERNAL; + + drawingBuffer = &window->buffers[window->drawingBufferIdx]; - if (window->pendingBuffer || !drawingBuffer->dirty) + if ((window->pendingBufferIdx >= 0) || !drawingBuffer->dirty) return UWAC_SUCCESS; - window->pendingBuffer = drawingBuffer; - window->drawingBuffer = UwacWindowFindFreeBuffer(window); + window->pendingBufferIdx = window->drawingBufferIdx; + nextBuffer = UwacWindowFindFreeBuffer(window, &window->drawingBufferIdx); - if (!window->drawingBuffer) + if ((!nextBuffer) || (window->drawingBufferIdx < 0)) return UWAC_ERROR_NOMEMORY; if (copyContentForNextFrame) - memcpy(window->drawingBuffer->data, window->pendingBuffer->data, - window->stride * window->height); + memcpy(nextBuffer->data, drawingBuffer->data, window->stride * window->height); UwacSubmitBufferPtr(window, drawingBuffer); return UWAC_SUCCESS; From 7f2de8419a2b9ce15d6ec4253cb5972ae73a6a57 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Tue, 16 Jun 2020 16:35:36 +0200 Subject: [PATCH 37/65] fix [client channels]: move exported API calls to client/common The functions mappedGeometryRef and mappedGeometryUnref are API functions ([1]) but were implemented in the geometry channel. In case FreeRDP was built with BUILTIN_CHANNELS=OFF those functions weren't available globally but used by the video channel. Now the functions are fixed part of the freerdp-client library and therefore available for all channels. [1] exported in freerdp/client/geometry.h Fixes #6236 (cherry picked from commit 1628939227fa82fa492f068f178f0cc0a42c518b) --- channels/geometry/client/geometry_main.c | 18 ---------- client/common/CMakeLists.txt | 3 +- client/common/geometry.c | 42 ++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 19 deletions(-) create mode 100644 client/common/geometry.c diff --git a/channels/geometry/client/geometry_main.c b/channels/geometry/client/geometry_main.c index eb65b2ca2765..cb5e2ae40db4 100644 --- a/channels/geometry/client/geometry_main.c +++ b/channels/geometry/client/geometry_main.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -82,23 +81,6 @@ static BOOL mappedGeometryKeyCompare(UINT64* g1, UINT64* g2) return *g1 == *g2; } -void mappedGeometryRef(MAPPED_GEOMETRY* g) -{ - InterlockedIncrement(&g->refCounter); -} - -void mappedGeometryUnref(MAPPED_GEOMETRY* g) -{ - if (InterlockedDecrement(&g->refCounter)) - return; - - g->MappedGeometryUpdate = NULL; - g->MappedGeometryClear = NULL; - g->custom = NULL; - free(g->geometry.rects); - free(g); -} - static void freerdp_rgndata_reset(FREERDP_RGNDATA* data) { data->nRectCount = 0; diff --git a/client/common/CMakeLists.txt b/client/common/CMakeLists.txt index b6805e593e7c..d4588e10bcf7 100644 --- a/client/common/CMakeLists.txt +++ b/client/common/CMakeLists.txt @@ -30,7 +30,8 @@ set(${MODULE_PREFIX}_SRCS cmdline.c compatibility.c compatibility.h - file.c) + file.c + geometry.c) foreach(FREERDP_CHANNELS_CLIENT_SRC ${FREERDP_CHANNELS_CLIENT_SRCS}) get_filename_component(NINC ${FREERDP_CHANNELS_CLIENT_SRC} PATH) diff --git a/client/common/geometry.c b/client/common/geometry.c new file mode 100644 index 000000000000..92f57ccfc25d --- /dev/null +++ b/client/common/geometry.c @@ -0,0 +1,42 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Geometry tracking Virtual Channel Extension + * + * Copyright 2017 David Fort + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +void mappedGeometryRef(MAPPED_GEOMETRY* g) +{ + InterlockedIncrement(&g->refCounter); +} + +void mappedGeometryUnref(MAPPED_GEOMETRY* g) +{ + if (InterlockedDecrement(&g->refCounter)) + return; + + g->MappedGeometryUpdate = NULL; + g->MappedGeometryClear = NULL; + g->custom = NULL; + free(g->geometry.rects); + free(g); +} From ecf172d88127bc42ac1c7fe6e2da854ad05637fe Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Tue, 16 Jun 2020 16:39:36 +0200 Subject: [PATCH 38/65] Revert "winpr/library: Use RTLD_GLOBAL for dlopen" Using RTLD_GLOBAL in LoadLibraryA introduces a different behavior than expected. This reverts commit d566e00258daffcb4c703afc3685e9a42ad01453. (cherry picked from commit 529e30c273ba67e3924b9fe4419410888314d31f) --- winpr/libwinpr/library/library.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/library/library.c b/winpr/libwinpr/library/library.c index 8d33227b2b9a..f44a96d27fcf 100644 --- a/winpr/libwinpr/library/library.c +++ b/winpr/libwinpr/library/library.c @@ -125,7 +125,7 @@ HMODULE LoadLibraryA(LPCSTR lpLibFileName) return hModule; #else HMODULE library; - library = dlopen(lpLibFileName, RTLD_GLOBAL | RTLD_LAZY); + library = dlopen(lpLibFileName, RTLD_LOCAL | RTLD_LAZY); if (!library) { From 4d6a800850049f91a4b2a87667aef0b6cb79e3de Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 18 Jun 2020 08:42:24 +0200 Subject: [PATCH 39/65] Fixed missing lock during buffer submit. (cherry picked from commit c902f583d0911c1e8938c5f14f3f257eb9737745) --- client/Wayland/wlfreerdp.c | 7 +++++-- uwac/libuwac/uwac-window.c | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 872f20079a37..11b747e604cd 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -304,6 +304,7 @@ static void wl_post_disconnect(freerdp* instance) static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display) { + BOOL rc; UwacEvent event; wlfContext* context; @@ -329,9 +330,11 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display) break; case UWAC_EVENT_FRAME_DONE: - if (UwacWindowSubmitBuffer(context->window, false) != UWAC_SUCCESS) + EnterCriticalSection(&context->critical); + rc = UwacWindowSubmitBuffer(context->window, false); + LeaveCriticalSection(&context->critical); + if (rc != UWAC_SUCCESS) return FALSE; - break; case UWAC_EVENT_POINTER_ENTER: diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c index 2f424e87cab2..1dc5574ffa56 100644 --- a/uwac/libuwac/uwac-window.c +++ b/uwac/libuwac/uwac-window.c @@ -737,27 +737,29 @@ UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame) { - UwacBuffer* drawingBuffer; - UwacBuffer* nextBuffer; + UwacBuffer* currentDrawingBuffer; + UwacBuffer* nextDrawingBuffer; + UwacBuffer* pendingBuffer; if (window->drawingBufferIdx < 0) return UWAC_ERROR_INTERNAL; - drawingBuffer = &window->buffers[window->drawingBufferIdx]; + currentDrawingBuffer = &window->buffers[window->drawingBufferIdx]; - if ((window->pendingBufferIdx >= 0) || !drawingBuffer->dirty) + if ((window->pendingBufferIdx >= 0) || !currentDrawingBuffer->dirty) return UWAC_SUCCESS; window->pendingBufferIdx = window->drawingBufferIdx; - nextBuffer = UwacWindowFindFreeBuffer(window, &window->drawingBufferIdx); + nextDrawingBuffer = UwacWindowFindFreeBuffer(window, &window->drawingBufferIdx); + pendingBuffer = &window->buffers[window->pendingBufferIdx]; - if ((!nextBuffer) || (window->drawingBufferIdx < 0)) + if ((!nextDrawingBuffer) || (window->drawingBufferIdx < 0)) return UWAC_ERROR_NOMEMORY; if (copyContentForNextFrame) - memcpy(nextBuffer->data, drawingBuffer->data, window->stride * window->height); + memcpy(nextDrawingBuffer->data, pendingBuffer->data, window->stride * window->height); - UwacSubmitBufferPtr(window, drawingBuffer); + UwacSubmitBufferPtr(window, pendingBuffer); return UWAC_SUCCESS; } From 2d166aea89f103b4a9ae31ac7814b7c7caf4f878 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 17 Jun 2020 08:41:21 +0200 Subject: [PATCH 40/65] TSG improvements * Respect connection timeout during connect * Better debug output * Cleaned up data types, (cherry picked from commit ff79636d3311269ec35fc1d6cc4246eef500ad5e) --- libfreerdp/core/gateway/rdg.c | 2 +- libfreerdp/core/gateway/rdg.h | 2 +- libfreerdp/core/gateway/rpc.c | 14 +- libfreerdp/core/gateway/rpc.h | 57 +++-- libfreerdp/core/gateway/rpc_bind.c | 51 ++-- libfreerdp/core/gateway/rpc_client.c | 58 +++-- libfreerdp/core/gateway/rts.c | 106 ++++----- libfreerdp/core/gateway/rts_signature.c | 8 +- libfreerdp/core/gateway/tsg.c | 295 ++++++++++++++++++++---- libfreerdp/core/gateway/tsg.h | 15 +- libfreerdp/core/orders.c | 2 +- libfreerdp/core/rdp.c | 2 +- libfreerdp/core/tcp.c | 2 +- libfreerdp/core/tcp.h | 2 +- libfreerdp/core/transport.c | 2 +- libfreerdp/core/transport.h | 2 +- 16 files changed, 403 insertions(+), 217 deletions(-) diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c index 6ea9e4f06d7c..107e396cb3cc 100644 --- a/libfreerdp/core/gateway/rdg.c +++ b/libfreerdp/core/gateway/rdg.c @@ -1167,7 +1167,7 @@ static BOOL rdg_tunnel_connect(rdpRdg* rdg) return TRUE; } -BOOL rdg_connect(rdpRdg* rdg, int timeout, BOOL* rpcFallback) +BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback) { BOOL status; SOCKET outConnSocket = 0; diff --git a/libfreerdp/core/gateway/rdg.h b/libfreerdp/core/gateway/rdg.h index 829d0a250657..50d865258a0e 100644 --- a/libfreerdp/core/gateway/rdg.h +++ b/libfreerdp/core/gateway/rdg.h @@ -44,7 +44,7 @@ FREERDP_LOCAL void rdg_free(rdpRdg* rdg); FREERDP_LOCAL BIO* rdg_get_front_bio_and_take_ownership(rdpRdg* rdg); -FREERDP_LOCAL BOOL rdg_connect(rdpRdg* rdg, int timeout, BOOL* rpcFallback); +FREERDP_LOCAL BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback); FREERDP_LOCAL DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count); #endif /* FREERDP_LIB_CORE_GATEWAY_RDG_H */ diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c index 0b47024ca2e0..218a407c0a2c 100644 --- a/libfreerdp/core/gateway/rpc.c +++ b/libfreerdp/core/gateway/rpc.c @@ -139,14 +139,14 @@ void rpc_pdu_header_print(rpcconn_hdr_t* header) } } -void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_hdr_t* header) +void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header) { - header->common.rpc_vers = rpc->rpc_vers; - header->common.rpc_vers_minor = rpc->rpc_vers_minor; - header->common.packed_drep[0] = rpc->packed_drep[0]; - header->common.packed_drep[1] = rpc->packed_drep[1]; - header->common.packed_drep[2] = rpc->packed_drep[2]; - header->common.packed_drep[3] = rpc->packed_drep[3]; + 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]; } UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment) diff --git a/libfreerdp/core/gateway/rpc.h b/libfreerdp/core/gateway/rpc.h index 5c315d90df39..3ca18a7a2aca 100644 --- a/libfreerdp/core/gateway/rpc.h +++ b/libfreerdp/core/gateway/rpc.h @@ -34,21 +34,23 @@ typedef struct rdp_rpc rdpRpc; #pragma pack(push, 1) -#define DEFINE_RPC_COMMON_FIELDS() \ - BYTE rpc_vers; \ - BYTE rpc_vers_minor; \ - BYTE ptype; \ - BYTE pfc_flags; \ - BYTE packed_drep[4]; \ - UINT16 frag_length; \ - UINT16 auth_length; \ - UINT32 call_id - -#define RPC_COMMON_FIELDS_LENGTH 16 +typedef struct +{ + BYTE rpc_vers; + BYTE rpc_vers_minor; + BYTE ptype; + BYTE pfc_flags; + BYTE packed_drep[4]; + UINT16 frag_length; + UINT16 auth_length; + UINT32 call_id; +} rpcconn_common_hdr_t; + +#define RPC_COMMON_FIELDS_LENGTH sizeof(rpcconn_common_hdr_t) typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT16 Flags; UINT16 NumberOfCommands; @@ -141,11 +143,6 @@ typedef struct _RPC_PDU #pragma pack(push, 1) -typedef struct -{ - DEFINE_RPC_COMMON_FIELDS(); -} rpcconn_common_hdr_t; - typedef UINT16 p_context_id_t; typedef UINT16 p_reject_reason_t; @@ -314,7 +311,7 @@ typedef struct auth_verifier_co_s auth_verifier_co_t; typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT16 max_xmit_frag; UINT16 max_recv_frag; @@ -328,7 +325,7 @@ typedef struct typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT16 max_xmit_frag; UINT16 max_recv_frag; @@ -345,7 +342,7 @@ typedef struct /* bind header */ typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT16 max_xmit_frag; UINT16 max_recv_frag; @@ -358,7 +355,7 @@ typedef struct typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT16 max_xmit_frag; UINT16 max_recv_frag; @@ -375,7 +372,7 @@ typedef struct typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT16 max_xmit_frag; UINT16 max_recv_frag; @@ -385,7 +382,7 @@ typedef struct typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; p_reject_reason_t provider_reject_reason; @@ -394,7 +391,7 @@ typedef struct typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; auth_verifier_co_t auth_verifier; @@ -460,7 +457,7 @@ typedef struct _RPC_FAULT_CODE RPC_FAULT_CODE; typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT32 alloc_hint; p_context_id_t p_cont_id; @@ -479,14 +476,14 @@ typedef struct typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; auth_verifier_co_t auth_verifier; } rpcconn_orphaned_hdr_t; typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT32 alloc_hint; @@ -505,7 +502,7 @@ typedef struct typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT32 alloc_hint; p_context_id_t p_cont_id; @@ -522,7 +519,7 @@ typedef struct typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; } rpcconn_shutdown_hdr_t; typedef union { @@ -768,7 +765,7 @@ struct rdp_rpc }; FREERDP_LOCAL void rpc_pdu_header_print(rpcconn_hdr_t* header); -FREERDP_LOCAL void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_hdr_t* header); +FREERDP_LOCAL void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header); FREERDP_LOCAL UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment); FREERDP_LOCAL UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad); diff --git a/libfreerdp/core/gateway/rpc_bind.c b/libfreerdp/core/gateway/rpc_bind.c index 4cfd02219f8f..98ed9a9dc55c 100644 --- a/libfreerdp/core/gateway/rpc_bind.c +++ b/libfreerdp/core/gateway/rpc_bind.c @@ -190,12 +190,13 @@ int rpc_send_bind_pdu(rdpRpc* rpc) if (!sbuffer) goto fail; - rpc_pdu_header_init(rpc, (rpcconn_hdr_t*)bind_pdu); - bind_pdu->auth_length = (UINT16)sbuffer->cbBuffer; + 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->ptype = PTYPE_BIND; - bind_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX; - bind_pdu->call_id = 2; + 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; @@ -240,9 +241,9 @@ int rpc_send_bind_pdu(rdpRpc* rpc) 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->auth_length); - bind_pdu->frag_length = offset; - buffer = (BYTE*)malloc(bind_pdu->frag_length); + offset += (8 + bind_pdu->header.auth_length); + bind_pdu->header.frag_length = offset; + buffer = (BYTE*)malloc(bind_pdu->header.frag_length); if (!buffer) goto fail; @@ -256,10 +257,11 @@ int rpc_send_bind_pdu(rdpRpc* rpc) 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->auth_length); - offset += (8 + bind_pdu->auth_length); - length = bind_pdu->frag_length; - clientCall = rpc_client_call_new(bind_pdu->call_id, 0); + 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 (!clientCall) goto fail; @@ -374,12 +376,12 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc) return -1; } - rpc_pdu_header_init(rpc, (rpcconn_hdr_t*)auth_3_pdu); - auth_3_pdu->auth_length = (UINT16)sbuffer->cbBuffer; + 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->ptype = PTYPE_RPC_AUTH_3; - auth_3_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX; - auth_3_pdu->call_id = 2; + 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; @@ -388,9 +390,9 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc) 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->auth_length); - auth_3_pdu->frag_length = offset; - buffer = (BYTE*)malloc(auth_3_pdu->frag_length); + offset += (8 + auth_3_pdu->header.auth_length); + auth_3_pdu->header.frag_length = offset; + buffer = (BYTE*)malloc(auth_3_pdu->header.frag_length); if (!buffer) { @@ -402,10 +404,11 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc) 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->auth_length); - offset += (8 + auth_3_pdu->auth_length); - length = auth_3_pdu->frag_length; - clientCall = rpc_client_call_new(auth_3_pdu->call_id, 0); + 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 (ArrayList_Add(rpc->client->ClientCallList, clientCall) >= 0) { diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index 23518f871bbd..7edd2bfb0b8b 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -895,7 +895,7 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum) SecBufferDesc Message; RpcClientCall* clientCall = NULL; rdpNtlm* ntlm; - rpcconn_request_hdr_t* request_pdu = NULL; + rpcconn_request_hdr_t request_pdu = { 0 }; RpcVirtualConnection* connection; RpcInChannel* inChannel; size_t length; @@ -931,25 +931,20 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum) if (ntlm_client_query_auth_size(ntlm) < 0) goto fail; - request_pdu = (rpcconn_request_hdr_t*)calloc(1, sizeof(rpcconn_request_hdr_t)); - - if (!request_pdu) - goto fail; - size = ntlm_client_get_context_max_size(ntlm); if (size < 0) goto fail; - rpc_pdu_header_init(rpc, (rpcconn_hdr_t*)request_pdu); - request_pdu->ptype = PTYPE_REQUEST; - request_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; - request_pdu->auth_length = (UINT16)size; - request_pdu->call_id = rpc->CallId++; - request_pdu->alloc_hint = length; - request_pdu->p_cont_id = 0x0000; - request_pdu->opnum = opnum; - clientCall = rpc_client_call_new(request_pdu->call_id, request_pdu->opnum); + rpc_pdu_header_init(rpc, &request_pdu.header); + request_pdu.header.ptype = PTYPE_REQUEST; + request_pdu.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; + request_pdu.header.auth_length = (UINT16)size; + request_pdu.header.call_id = rpc->CallId++; + request_pdu.alloc_hint = length; + request_pdu.p_cont_id = 0x0000; + request_pdu.opnum = opnum; + clientCall = rpc_client_call_new(request_pdu.header.call_id, request_pdu.opnum); if (!clientCall) goto fail; @@ -960,32 +955,32 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum) goto fail; } - if (request_pdu->opnum == TsProxySetupReceivePipeOpnum) - rpc->PipeCallId = request_pdu->call_id; + if (request_pdu.opnum == TsProxySetupReceivePipeOpnum) + rpc->PipeCallId = request_pdu.header.call_id; - request_pdu->stub_data = Stream_Buffer(s); + request_pdu.stub_data = Stream_Buffer(s); offset = 24; stub_data_pad = rpc_offset_align(&offset, 8); offset += length; - request_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4); - request_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT; - request_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; - request_pdu->auth_verifier.auth_reserved = 0x00; - request_pdu->auth_verifier.auth_context_id = 0x00000000; - offset += (8 + request_pdu->auth_length); - request_pdu->frag_length = offset; - buffer = (BYTE*)calloc(1, request_pdu->frag_length); + request_pdu.auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4); + request_pdu.auth_verifier.auth_type = RPC_C_AUTHN_WINNT; + request_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY; + request_pdu.auth_verifier.auth_reserved = 0x00; + request_pdu.auth_verifier.auth_context_id = 0x00000000; + offset += (8 + request_pdu.header.auth_length); + request_pdu.header.frag_length = offset; + buffer = (BYTE*)calloc(1, request_pdu.header.frag_length); if (!buffer) goto fail; - CopyMemory(buffer, request_pdu, 24); + CopyMemory(buffer, &request_pdu, 24); offset = 24; rpc_offset_pad(&offset, stub_data_pad); - CopyMemory(&buffer[offset], request_pdu->stub_data, length); + CopyMemory(&buffer[offset], request_pdu.stub_data, length); offset += length; - rpc_offset_pad(&offset, request_pdu->auth_verifier.auth_pad_length); - CopyMemory(&buffer[offset], &request_pdu->auth_verifier.auth_type, 8); + rpc_offset_pad(&offset, request_pdu.auth_verifier.auth_pad_length); + CopyMemory(&buffer[offset], &request_pdu.auth_verifier.auth_type, 8); offset += 8; Buffers[0].BufferType = SECBUFFER_DATA; /* auth_data */ Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */ @@ -1007,14 +1002,13 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum) CopyMemory(&buffer[offset], Buffers[1].pvBuffer, Buffers[1].cbBuffer); offset += Buffers[1].cbBuffer; - if (rpc_in_channel_send_pdu(inChannel, buffer, request_pdu->frag_length) < 0) + if (rpc_in_channel_send_pdu(inChannel, buffer, request_pdu.header.frag_length) < 0) goto fail; rc = TRUE; fail: free(buffer); free(Buffers[1].pvBuffer); - free(request_pdu); Stream_Free(s, TRUE); return rc; } diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c index 6218f8157c9d..c003b1ea07ac 100644 --- a/libfreerdp/core/gateway/rts.c +++ b/libfreerdp/core/gateway/rts.c @@ -67,19 +67,21 @@ * */ -static void rts_pdu_header_init(rpcconn_rts_hdr_t* header) +static rpcconn_rts_hdr_t rts_pdu_header_init(void) { - ZeroMemory(header, sizeof(*header)); - header->rpc_vers = 5; - header->rpc_vers_minor = 0; - header->ptype = PTYPE_RTS; - header->packed_drep[0] = 0x10; - header->packed_drep[1] = 0x00; - header->packed_drep[2] = 0x00; - header->packed_drep[3] = 0x00; - header->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; - header->auth_length = 0; - 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 int rts_receive_window_size_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, @@ -406,21 +408,21 @@ int rts_send_CONN_A1_pdu(rdpRpc* rpc) { int status; BYTE* buffer; - rpcconn_rts_hdr_t header; + rpcconn_rts_hdr_t header = rts_pdu_header_init(); UINT32 ReceiveWindowSize; BYTE* OUTChannelCookie; BYTE* VirtualConnectionCookie; RpcVirtualConnection* connection = rpc->VirtualConnection; RpcOutChannel* outChannel = connection->DefaultOutChannel; - rts_pdu_header_init(&header); - header.frag_length = 76; + + 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.frag_length); + buffer = (BYTE*)malloc(header.header.frag_length); if (!buffer) return -1; @@ -432,7 +434,7 @@ int rts_send_CONN_A1_pdu(rdpRpc* rpc) 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.frag_length); + status = rpc_channel_write(&outChannel->common, buffer, header.header.frag_length); free(buffer); return (status > 0) ? 1 : -1; } @@ -453,21 +455,21 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc) int status; BYTE* buffer; UINT32 length; - rpcconn_rts_hdr_t header; + rpcconn_rts_hdr_t header = rts_pdu_header_init(); BYTE* INChannelCookie; BYTE* AssociationGroupId; BYTE* VirtualConnectionCookie; RpcVirtualConnection* connection = rpc->VirtualConnection; RpcInChannel* inChannel = connection->DefaultInChannel; - rts_pdu_header_init(&header); - header.frag_length = 104; + + 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.frag_length); + buffer = (BYTE*)malloc(header.header.frag_length); if (!buffer) return -1; @@ -483,7 +485,7 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc) rpc->KeepAliveInterval); /* ClientKeepalive (8 bytes) */ rts_association_group_id_command_write(&buffer[84], AssociationGroupId); /* AssociationGroupId (20 bytes) */ - length = header.frag_length; + length = header.header.frag_length; status = rpc_channel_write(&inChannel->common, buffer, length); free(buffer); return (status > 0) ? 1 : -1; @@ -520,14 +522,14 @@ static int rts_send_keep_alive_pdu(rdpRpc* rpc) int status; BYTE* buffer; UINT32 length; - rpcconn_rts_hdr_t header; + rpcconn_rts_hdr_t header = rts_pdu_header_init(); RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel; - rts_pdu_header_init(&header); - header.frag_length = 28; + + 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.frag_length); + buffer = (BYTE*)malloc(header.header.frag_length); if (!buffer) return -1; @@ -535,7 +537,7 @@ static int rts_send_keep_alive_pdu(rdpRpc* rpc) CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */ rts_client_keepalive_command_write( &buffer[20], rpc->CurrentKeepAliveInterval); /* ClientKeepAlive (8 bytes) */ - length = header.frag_length; + length = header.header.frag_length; status = rpc_channel_write(&inChannel->common, buffer, length); free(buffer); return (status > 0) ? 1 : -1; @@ -546,15 +548,15 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc) int status; BYTE* buffer; UINT32 length; - rpcconn_rts_hdr_t header; + 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; - rts_pdu_header_init(&header); - header.frag_length = 56; + + header.header.frag_length = 56; header.Flags = RTS_FLAG_OTHER_CMD; header.NumberOfCommands = 2; WLog_DBG(TAG, "Sending FlowControlAck RTS PDU"); @@ -562,7 +564,7 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc) AvailableWindow = outChannel->AvailableWindowAdvertised; ChannelCookie = (BYTE*)&(outChannel->common.Cookie); outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised; - buffer = (BYTE*)malloc(header.frag_length); + buffer = (BYTE*)malloc(header.header.frag_length); if (!buffer) return -1; @@ -571,7 +573,7 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc) 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.frag_length; + length = header.header.frag_length; status = rpc_channel_write(&inChannel->common, buffer, length); free(buffer); return (status > 0) ? 1 : -1; @@ -640,20 +642,20 @@ static int rts_send_ping_pdu(rdpRpc* rpc) int status; BYTE* buffer; UINT32 length; - rpcconn_rts_hdr_t header; + rpcconn_rts_hdr_t header = rts_pdu_header_init(); RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel; - rts_pdu_header_init(&header); - header.frag_length = 20; + + header.header.frag_length = 20; header.Flags = RTS_FLAG_PING; header.NumberOfCommands = 0; WLog_DBG(TAG, "Sending Ping RTS PDU"); - buffer = (BYTE*)malloc(header.frag_length); + buffer = (BYTE*)malloc(header.header.frag_length); if (!buffer) return -1; CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */ - length = header.frag_length; + length = header.header.frag_length; status = rpc_channel_write(&inChannel->common, buffer, length); free(buffer); return (status > 0) ? 1 : -1; @@ -737,17 +739,17 @@ static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc) { int status; BYTE* buffer; - rpcconn_rts_hdr_t header; + rpcconn_rts_hdr_t header = rts_pdu_header_init(); BYTE* SuccessorChannelCookie; RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel; RpcOutChannel* nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel; - rts_pdu_header_init(&header); - header.frag_length = 56; + + 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.frag_length); + buffer = (BYTE*)malloc(header.header.frag_length); if (!buffer) return -1; @@ -757,7 +759,7 @@ static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc) 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.frag_length); + status = rpc_channel_write(&inChannel->common, buffer, header.header.frag_length); free(buffer); return (status > 0) ? 1 : -1; } @@ -766,21 +768,21 @@ static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc) { int status; BYTE* buffer; - rpcconn_rts_hdr_t header; + rpcconn_rts_hdr_t header = rts_pdu_header_init(); RpcOutChannel* nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel; - rts_pdu_header_init(&header); - header.frag_length = 24; + + 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.frag_length); + buffer = (BYTE*)malloc(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.frag_length); + status = rpc_channel_write(&nextOutChannel->common, buffer, header.header.frag_length); free(buffer); return (status > 0) ? 1 : -1; } @@ -789,7 +791,7 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc) { int status; BYTE* buffer; - rpcconn_rts_hdr_t header; + rpcconn_rts_hdr_t header = rts_pdu_header_init(); UINT32 ReceiveWindowSize; BYTE* VirtualConnectionCookie; BYTE* PredecessorChannelCookie; @@ -797,8 +799,8 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc) RpcVirtualConnection* connection = rpc->VirtualConnection; RpcOutChannel* outChannel = connection->DefaultOutChannel; RpcOutChannel* nextOutChannel = connection->NonDefaultOutChannel; - rts_pdu_header_init(&header); - header.frag_length = 96; + + header.header.frag_length = 96; header.Flags = RTS_FLAG_RECYCLE_CHANNEL; header.NumberOfCommands = 5; WLog_DBG(TAG, "Sending OUT_R1/A3 RTS PDU"); @@ -806,7 +808,7 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc) PredecessorChannelCookie = (BYTE*)&(outChannel->common.Cookie); SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie); ReceiveWindowSize = outChannel->ReceiveWindow; - buffer = (BYTE*)malloc(header.frag_length); + buffer = (BYTE*)malloc(header.header.frag_length); if (!buffer) return -1; @@ -821,7 +823,7 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc) SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */ rts_receive_window_size_command_write(&buffer[88], ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */ - status = rpc_channel_write(&nextOutChannel->common, buffer, header.frag_length); + status = rpc_channel_write(&nextOutChannel->common, buffer, header.header.frag_length); free(buffer); return (status > 0) ? 1 : -1; } diff --git a/libfreerdp/core/gateway/rts_signature.c b/libfreerdp/core/gateway/rts_signature.c index d3b376d2d1a2..4d605f041689 100644 --- a/libfreerdp/core/gateway/rts_signature.c +++ b/libfreerdp/core/gateway/rts_signature.c @@ -302,7 +302,7 @@ BOOL rts_match_pdu_signature(const RtsPduSignature* signature, const rpcconn_rts buffer = (const BYTE*)rts; offset = RTS_PDU_HEADER_LENGTH; - length = rts->frag_length - offset; + length = rts->header.frag_length - offset; for (i = 0; i < rts->NumberOfCommands; i++) { @@ -319,7 +319,7 @@ BOOL rts_match_pdu_signature(const RtsPduSignature* signature, const rpcconn_rts CommandLength = (UINT32)status; offset += CommandLength; - length = rts->frag_length - offset; + length = rts->header.frag_length - offset; } return TRUE; @@ -342,7 +342,7 @@ BOOL rts_extract_pdu_signature(RtsPduSignature* signature, const rpcconn_rts_hdr signature->NumberOfCommands = rts->NumberOfCommands; buffer = (BYTE*)rts; offset = RTS_PDU_HEADER_LENGTH; - length = rts->frag_length - offset; + length = rts->header.frag_length - offset; for (i = 0; i < rts->NumberOfCommands; i++) { @@ -356,7 +356,7 @@ BOOL rts_extract_pdu_signature(RtsPduSignature* signature, const rpcconn_rts_hdr CommandLength = (UINT32)status; offset += CommandLength; - length = rts->frag_length - offset; + length = rts->header.frag_length - offset; } return TRUE; diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c index 7537f18ddd8d..1626b91c176c 100644 --- a/libfreerdp/core/gateway/tsg.c +++ b/libfreerdp/core/gateway/tsg.c @@ -39,6 +39,19 @@ #define TAG FREERDP_TAG("core.gateway.tsg") +#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 +#define TSG_PACKET_TYPE_AUTH 0x00004054 +#define TSG_PACKET_TYPE_REAUTH 0x00005250 + typedef WCHAR* RESOURCENAME; typedef struct _tsendpointinfo @@ -218,6 +231,214 @@ struct rdp_tsg TSG_PACKET_VERSIONCAPS packetVersionCaps; }; +static const char* tsg_packet_id_to_string(UINT32 packetId) +{ + switch (packetId) + { + case TSG_PACKET_TYPE_HEADER: + return "TSG_PACKET_TYPE_HEADER"; + case TSG_PACKET_TYPE_VERSIONCAPS: + return "TSG_PACKET_TYPE_VERSIONCAPS"; + case TSG_PACKET_TYPE_QUARCONFIGREQUEST: + return "TSG_PACKET_TYPE_QUARCONFIGREQUEST"; + case TSG_PACKET_TYPE_QUARREQUEST: + return "TSG_PACKET_TYPE_QUARREQUEST"; + case TSG_PACKET_TYPE_RESPONSE: + return "TSG_PACKET_TYPE_RESPONSE"; + case TSG_PACKET_TYPE_QUARENC_RESPONSE: + return "TSG_PACKET_TYPE_QUARENC_RESPONSE"; + case TSG_CAPABILITY_TYPE_NAP: + return "TSG_CAPABILITY_TYPE_NAP"; + case TSG_PACKET_TYPE_CAPS_RESPONSE: + return "TSG_PACKET_TYPE_CAPS_RESPONSE"; + case TSG_PACKET_TYPE_MSGREQUEST_PACKET: + return "TSG_PACKET_TYPE_MSGREQUEST_PACKET"; + case TSG_PACKET_TYPE_MESSAGE_PACKET: + return "TSG_PACKET_TYPE_MESSAGE_PACKET"; + case TSG_PACKET_TYPE_AUTH: + return "TSG_PACKET_TYPE_AUTH"; + case TSG_PACKET_TYPE_REAUTH: + return "TSG_PACKET_TYPE_REAUTH"; + default: + return "UNKNOWN"; + } +} + +static const char* tsg_state_to_string(TSG_STATE state) +{ + switch (state) + { + case TSG_STATE_INITIAL: + return "TSG_STATE_INITIAL"; + case TSG_STATE_CONNECTED: + return "TSG_STATE_CONNECTED"; + case TSG_STATE_AUTHORIZED: + return "TSG_STATE_AUTHORIZED"; + case TSG_STATE_CHANNEL_CREATED: + return "TSG_STATE_CHANNEL_CREATED"; + case TSG_STATE_PIPE_CREATED: + return "TSG_STATE_PIPE_CREATED"; + case TSG_STATE_TUNNEL_CLOSE_PENDING: + return "TSG_STATE_TUNNEL_CLOSE_PENDING"; + case TSG_STATE_CHANNEL_CLOSE_PENDING: + return "TSG_STATE_CHANNEL_CLOSE_PENDING"; + case TSG_STATE_FINAL: + return "TSG_STATE_FINAL"; + default: + return "TSG_STATE_UNKNOWN"; + } +} + +static BOOL tsg_print(char** buffer, size_t* len, const char* fmt, ...) +{ + int rc; + va_list ap; + if (!buffer || !len || !fmt) + return FALSE; + va_start(ap, fmt); + rc = vsnprintf(*buffer, *len, fmt, ap); + va_end(ap); + if ((rc < 0) || ((size_t)rc > *len)) + return FALSE; + *len -= (size_t)rc; + *buffer += (size_t)rc; + return TRUE; +} + +static BOOL tsg_packet_header_to_string(char** buffer, size_t* length, + const TSG_PACKET_HEADER* header) +{ + return tsg_print(buffer, length, + "header { ComponentId=0x%04" PRIx16 ", PacketId=0x%04" PRIx16 " }", + header->ComponentId, header->PacketId); +} + +static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length, + const TSG_PACKET_CAPABILITIES* caps, UINT32 numCaps) +{ + UINT32 x; + + if (!tsg_print(buffer, length, "capabilities { ")) + return FALSE; + + for (x = 0; x < numCaps; x++) + { + const TSG_PACKET_CAPABILITIES* cur = &caps[x]; + 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)) + return FALSE; + break; + default: + if (!tsg_print(buffer, length, "TSG_UNKNOWN_CAPABILITY")) + return FALSE; + break; + } + } + return tsg_print(buffer, length, " }"); +} + +static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length, + const TSG_PACKET_VERSIONCAPS* caps) +{ + if (!tsg_print(buffer, length, "versioncaps { ")) + return FALSE; + if (!tsg_packet_header_to_string(buffer, length, &caps->tsgHeader)) + return FALSE; + + if (!tsg_print(buffer, length, " ")) + return FALSE; + + if (!tsg_packet_capabilities_to_string(buffer, length, caps->tsgCaps, caps->numCapabilities)) + return FALSE; + + if (!tsg_print(buffer, length, + " numCapabilities=0x%08" PRIx32 ", majorVersion=0x%04" PRIx16 + ", minorVersion=0x%04" PRIx16 ", quarantineCapabilities=0x%04" PRIx16, + caps->numCapabilities, caps->majorVersion, caps->minorVersion, + caps->quarantineCapabilities)) + return FALSE; + + return tsg_print(buffer, length, " }"); +} + +static const char* tsg_packet_to_string(const TSG_PACKET* packet) +{ + size_t len = 8192; + static char sbuffer[8193] = { 0 }; + char* buffer = sbuffer; + + if (!tsg_print(&buffer, &len, "TSG_PACKET { packetId=%s [0x%08" PRIx32 "], ", + tsg_packet_id_to_string(packet->packetId), packet->packetId)) + goto fail; + + switch (packet->packetId) + { + case TSG_PACKET_TYPE_HEADER: + if (!tsg_packet_header_to_string(&buffer, &len, packet->tsgPacket.packetHeader)) + goto fail; + break; + case TSG_PACKET_TYPE_VERSIONCAPS: + if (!tsg_packet_versioncaps_to_string(&buffer, &len, + packet->tsgPacket.packetVersionCaps)) + goto fail; + break; + case TSG_PACKET_TYPE_QUARCONFIGREQUEST: + if (!tsg_print(&buffer, &len, "TODO")) + goto fail; + break; + case TSG_PACKET_TYPE_QUARREQUEST: + if (!tsg_print(&buffer, &len, "TODO")) + goto fail; + break; + case TSG_PACKET_TYPE_RESPONSE: + if (!tsg_print(&buffer, &len, "TODO")) + 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")) + goto fail; + break; + case TSG_PACKET_TYPE_CAPS_RESPONSE: + if (!tsg_print(&buffer, &len, "TODO")) + goto fail; + break; + case TSG_PACKET_TYPE_MSGREQUEST_PACKET: + if (!tsg_print(&buffer, &len, "TODO")) + goto fail; + break; + case TSG_PACKET_TYPE_MESSAGE_PACKET: + if (!tsg_print(&buffer, &len, "TODO")) + goto fail; + break; + case TSG_PACKET_TYPE_AUTH: + if (!tsg_print(&buffer, &len, "TODO")) + goto fail; + break; + case TSG_PACKET_TYPE_REAUTH: + if (!tsg_print(&buffer, &len, "TODO")) + goto fail; + break; + default: + if (!tsg_print(&buffer, &len, "INVALID")) + goto fail; + break; + } + + if (!tsg_print(&buffer, &len, " }")) + goto fail; + +fail: + return sbuffer; +} + static BOOL tsg_stream_align(wStream* s, size_t align) { size_t pos; @@ -362,7 +583,7 @@ static int TsProxySendToServer(handle_t IDL_handle, const byte pRpcMessage[], UI * ); */ -static BOOL TsProxyCreateTunnelWriteRequest(rdpTsg* tsg, PTSG_PACKET tsgPacket) +static BOOL TsProxyCreateTunnelWriteRequest(rdpTsg* tsg, const PTSG_PACKET tsgPacket) { BOOL rc = FALSE; BOOL write = TRUE; @@ -374,7 +595,7 @@ static BOOL TsProxyCreateTunnelWriteRequest(rdpTsg* tsg, PTSG_PACKET tsgPacket) return FALSE; rpc = tsg->rpc; - WLog_DBG(TAG, "TsProxyCreateTunnelWriteRequest"); + WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_to_string(tsgPacket)); s = Stream_New(NULL, 108); if (!s) @@ -506,7 +727,6 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, PTSG_PACKET_VERSIONCAPS versionCaps = NULL; PTSG_PACKET_CAPS_RESPONSE packetCapsResponse = NULL; PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse = NULL; - WLog_DBG(TAG, "TsProxyCreateTunnelReadResponse"); if (!pdu) return FALSE; @@ -523,6 +743,8 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, Stream_Read_UINT32(pdu->s, packet->packetId); /* PacketId (4 bytes) */ Stream_Read_UINT32(pdu->s, SwitchValue); /* SwitchValue (4 bytes) */ + WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_id_to_string(packet->packetId)); + if ((packet->packetId == TSG_PACKET_TYPE_CAPS_RESPONSE) && (SwitchValue == TSG_PACKET_TYPE_CAPS_RESPONSE)) { @@ -885,7 +1107,6 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu) UINT32 idleTimeout; PTSG_PACKET packet = NULL; PTSG_PACKET_RESPONSE packetResponse = NULL; - WLog_DBG(TAG, "TsProxyAuthorizeTunnelReadResponse"); if (!pdu) return FALSE; @@ -902,6 +1123,8 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu) Stream_Read_UINT32(pdu->s, packet->packetId); /* PacketId (4 bytes) */ Stream_Read_UINT32(pdu->s, SwitchValue); /* SwitchValue (4 bytes) */ + WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_id_to_string(packet->packetId)); + if (packet->packetId == E_PROXY_NAP_ACCESSDENIED) { WLog_ERR(TAG, "status: E_PROXY_NAP_ACCESSDENIED (0x%08X)", E_PROXY_NAP_ACCESSDENIED); @@ -1059,7 +1282,6 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu) TSG_PACKET_MSG_RESPONSE packetMsgResponse = { 0 }; TSG_PACKET_STRING_MESSAGE packetStringMessage = { 0 }; TSG_PACKET_REAUTH_MESSAGE packetReauthMessage = { 0 }; - WLog_DBG(TAG, "TsProxyMakeTunnelCallReadResponse"); /* This is an asynchronous response */ @@ -1073,6 +1295,8 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu) Stream_Read_UINT32(pdu->s, packet.packetId); /* PacketId (4 bytes) */ Stream_Read_UINT32(pdu->s, SwitchValue); /* SwitchValue (4 bytes) */ + WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_id_to_string(packet.packetId)); + if ((packet.packetId != TSG_PACKET_TYPE_MESSAGE_PACKET) || (SwitchValue != TSG_PACKET_TYPE_MESSAGE_PACKET)) { @@ -1357,50 +1581,16 @@ static BOOL TsProxySetupReceivePipeWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* cha static BOOL tsg_transition_to_state(rdpTsg* tsg, TSG_STATE state) { - const char* str = "TSG_STATE_UNKNOWN"; - - switch (state) - { - case TSG_STATE_INITIAL: - str = "TSG_STATE_INITIAL"; - break; - - case TSG_STATE_CONNECTED: - str = "TSG_STATE_CONNECTED"; - break; - - case TSG_STATE_AUTHORIZED: - str = "TSG_STATE_AUTHORIZED"; - break; - - case TSG_STATE_CHANNEL_CREATED: - str = "TSG_STATE_CHANNEL_CREATED"; - break; - - case TSG_STATE_PIPE_CREATED: - str = "TSG_STATE_PIPE_CREATED"; - break; + const char* oldState = tsg_state_to_string(tsg->state); + const char* newState = tsg_state_to_string(state); - case TSG_STATE_TUNNEL_CLOSE_PENDING: - str = "TSG_STATE_TUNNEL_CLOSE_PENDING"; - break; - - case TSG_STATE_CHANNEL_CLOSE_PENDING: - str = "TSG_STATE_CHANNEL_CLOSE_PENDING"; - break; - - case TSG_STATE_FINAL: - str = "TSG_STATE_FINAL"; - break; - } - - WLog_DBG(TAG, "%s", str); + WLog_DBG(TAG, "%s -> %s", oldState, newState); return tsg_set_state(tsg, state); } BOOL tsg_proxy_begin(rdpTsg* tsg) { - TSG_PACKET tsgPacket; + TSG_PACKET tsgPacket = { 0 }; PTSG_CAPABILITY_NAP tsgCapNap; PTSG_PACKET_VERSIONCAPS packetVersionCaps; @@ -1443,7 +1633,7 @@ BOOL tsg_proxy_begin(rdpTsg* tsg) static BOOL tsg_proxy_reauth(rdpTsg* tsg) { - TSG_PACKET tsgPacket; + TSG_PACKET tsgPacket = { 0 }; PTSG_PACKET_REAUTH packetReauth; PTSG_PACKET_VERSIONCAPS packetVersionCaps; @@ -1815,8 +2005,9 @@ static BOOL tsg_set_machine_name(rdpTsg* tsg, const char* machineName) return TRUE; } -BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout) +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; @@ -1847,7 +2038,19 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout) while (tsg->state != TSG_STATE_PIPE_CREATED) { - WaitForMultipleObjects(nCount, events, FALSE, 250); + const DWORD polltimeout = 250; + DWORD status = WaitForMultipleObjects(nCount, events, FALSE, polltimeout); + if (status == WAIT_TIMEOUT) + { + if (timeout > 0) + { + if (looptimeout < polltimeout) + return FALSE; + looptimeout -= polltimeout; + } + } + else + looptimeout = timeout * 1000ULL; if (!tsg_check_event_handles(tsg)) { diff --git a/libfreerdp/core/gateway/tsg.h b/libfreerdp/core/gateway/tsg.h index af9f88671887..9bfb3c7d2da3 100644 --- a/libfreerdp/core/gateway/tsg.h +++ b/libfreerdp/core/gateway/tsg.h @@ -62,19 +62,6 @@ typedef enum _TSG_STATE TSG_STATE; #define TS_GATEWAY_TRANSPORT 0x5452 -#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 -#define TSG_PACKET_TYPE_AUTH 0x00004054 -#define TSG_PACKET_TYPE_REAUTH 0x00005250 - #define TSG_ASYNC_MESSAGE_CONSENT_MESSAGE 0x00000001 #define TSG_ASYNC_MESSAGE_SERVICE_MESSAGE 0x00000002 #define TSG_ASYNC_MESSAGE_REAUTH 0x00000003 @@ -118,7 +105,7 @@ FREERDP_LOCAL void tsg_free(rdpTsg* tsg); FREERDP_LOCAL BOOL tsg_proxy_begin(rdpTsg* tsg); -FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout); +FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout); FREERDP_LOCAL BOOL tsg_disconnect(rdpTsg* tsg); FREERDP_LOCAL BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu); diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index e053bd4809ad..87e0959642c3 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -3506,7 +3506,7 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flag Stream_Read_UINT16(s, orderLength); /* orderLength (2 bytes) */ Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */ Stream_Read_UINT8(s, orderType); /* orderType (1 byte) */ - if (Stream_GetRemainingLength(s) < orderLength + 7) + if (Stream_GetRemainingLength(s) < orderLength + 7U) { WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) %" PRIuz " < %" PRIu16, Stream_GetRemainingLength(s), orderLength + 7); diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index fd771ae3ee2d..1c8990ec8363 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -167,7 +167,7 @@ BOOL rdp_read_share_control_header(wStream* s, UINT16* tpktLength, UINT16* remai return TRUE; } - if ((len < 4) || ((len - 2) > Stream_GetRemainingLength(s))) + if ((len < 4U) || ((len - 2U) > Stream_GetRemainingLength(s))) return FALSE; if (tpktLength) diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index 286dc1f6da42..ef5f7b1939f3 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -1060,7 +1060,7 @@ static BOOL freerdp_tcp_set_keep_alive_mode(const rdpSettings* settings, int soc } int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings, const char* hostname, int port, - int timeout) + DWORD timeout) { int sockfd; UINT32 optval; diff --git a/libfreerdp/core/tcp.h b/libfreerdp/core/tcp.h index abb664403365..74a23114c3c8 100644 --- a/libfreerdp/core/tcp.h +++ b/libfreerdp/core/tcp.h @@ -64,7 +64,7 @@ FREERDP_LOCAL BIO_METHOD* BIO_s_simple_socket(void); FREERDP_LOCAL BIO_METHOD* BIO_s_buffered_socket(void); FREERDP_LOCAL int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings, - const char* hostname, int port, int timeout); + const char* hostname, int port, DWORD timeout); FREERDP_LOCAL char* freerdp_tcp_get_peer_address(SOCKET sockfd); diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index b20d4a2fe898..40795e941e91 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -354,7 +354,7 @@ BOOL transport_connect_nla(rdpTransport* transport) return TRUE; } -BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, int timeout) +BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, DWORD timeout) { int sockfd; BOOL status = FALSE; diff --git a/libfreerdp/core/transport.h b/libfreerdp/core/transport.h index c6509fe57561..944f5ce30ded 100644 --- a/libfreerdp/core/transport.h +++ b/libfreerdp/core/transport.h @@ -81,7 +81,7 @@ struct rdp_transport FREERDP_LOCAL wStream* transport_send_stream_init(rdpTransport* transport, int size); FREERDP_LOCAL BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, - int timeout); + DWORD timeout); FREERDP_LOCAL BOOL transport_attach(rdpTransport* transport, int sockfd); FREERDP_LOCAL BOOL transport_disconnect(rdpTransport* transport); FREERDP_LOCAL BOOL transport_connect_rdp(rdpTransport* transport); From da15d1a3a1d2f1c053017d621194ebaee937c358 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 17 Jun 2020 12:10:33 +0200 Subject: [PATCH 41/65] Added missing SECBUFFER_READONLY flag in rpc_client_write_call (cherry picked from commit 0d80353bf30de860dcf86285c4e5e2770bc036f7) --- libfreerdp/core/gateway/rpc_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index 7edd2bfb0b8b..d4432cbbd83b 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -982,7 +982,7 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum) rpc_offset_pad(&offset, request_pdu.auth_verifier.auth_pad_length); CopyMemory(&buffer[offset], &request_pdu.auth_verifier.auth_type, 8); offset += 8; - Buffers[0].BufferType = SECBUFFER_DATA; /* auth_data */ + Buffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY; /* auth_data */ Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */ Buffers[0].pvBuffer = buffer; Buffers[0].cbBuffer = offset; From c3c02c83ab3d1f0e09298812519417b1691a2432 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 17 Jun 2020 12:18:42 +0200 Subject: [PATCH 42/65] Respect SECBUFFER_READONLY flag in NTLM EncryptMessage (cherry picked from commit 8e45a2dd50d5db6ac6125e0f60e833b6c6c6ea1b) --- winpr/libwinpr/sspi/NTLM/ntlm.c | 40 ++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c index b4ca9c5e8686..66f57175819f 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm.c @@ -961,7 +961,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContex static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) { - int index; + ULONG index; int length; void* data; UINT32 SeqNo; @@ -977,12 +977,14 @@ static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULON SeqNo = MessageSeqNo; context = (NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext); - for (index = 0; index < (int)pMessage->cBuffers; index++) + for (index = 0; index < pMessage->cBuffers; index++) { - if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA) - data_buffer = &pMessage->pBuffers[index]; - else if (pMessage->pBuffers[index].BufferType == SECBUFFER_TOKEN) - signature_buffer = &pMessage->pBuffers[index]; + SecBuffer* cur = &pMessage->pBuffers[index]; + + if (cur->BufferType & SECBUFFER_DATA) + data_buffer = cur; + else if (cur->BufferType & SECBUFFER_TOKEN) + signature_buffer = cur; } if (!data_buffer) @@ -1019,11 +1021,14 @@ static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULON } /* Encrypt message using with RC4, result overwrites original buffer */ - - if (context->confidentiality) - winpr_RC4_Update(context->SendRc4Seal, length, (BYTE*)data, (BYTE*)data_buffer->pvBuffer); - else - CopyMemory(data_buffer->pvBuffer, data, length); + if ((data_buffer->BufferType & SECBUFFER_READONLY) == 0) + { + if (context->confidentiality) + winpr_RC4_Update(context->SendRc4Seal, length, (BYTE*)data, + (BYTE*)data_buffer->pvBuffer); + else + CopyMemory(data_buffer->pvBuffer, data, length); + } #ifdef WITH_DEBUG_NTLM WLog_DBG(TAG, "Data Buffer (length = %d)", length); @@ -1034,11 +1039,14 @@ static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULON free(data); /* RC4-encrypt first 8 bytes of digest */ winpr_RC4_Update(context->SendRc4Seal, 8, digest, checksum); - signature = (BYTE*)signature_buffer->pvBuffer; - /* Concatenate version, ciphertext and sequence number to build signature */ - Data_Write_UINT32(signature, version); - CopyMemory(&signature[4], (void*)checksum, 8); - Data_Write_UINT32(&signature[12], SeqNo); + if ((signature_buffer->BufferType & SECBUFFER_READONLY) == 0) + { + signature = (BYTE*)signature_buffer->pvBuffer; + /* Concatenate version, ciphertext and sequence number to build signature */ + Data_Write_UINT32(signature, version); + CopyMemory(&signature[4], (void*)checksum, 8); + Data_Write_UINT32(&signature[12], SeqNo); + } context->SendSeqNum++; #ifdef WITH_DEBUG_NTLM WLog_DBG(TAG, "Signature (length = %" PRIu32 ")", signature_buffer->cbBuffer); From d5609e5467ce8b18ba643db9f33c0d5e213f2dfd Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 25 May 2020 09:37:48 +0200 Subject: [PATCH 43/65] Fixed OOB Read in license_read_new_or_upgrade_license_packet CVE-2020-11099 thanks to @antonio-morales for finding this. (cherry picked from commit 6ade7b4cbfd71c54b3d724e8f2d6ac76a58e879a) --- libfreerdp/core/license.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index 18bcb9fa47e5..097107b70381 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -1252,6 +1252,9 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s) if (!licenseStream) goto out_free_blob; + if (Stream_GetRemainingLength(licenseStream) < 8) + goto out_free_stream; + Stream_Read_UINT16(licenseStream, os_minor); Stream_Read_UINT16(licenseStream, os_major); @@ -1266,6 +1269,8 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s) Stream_Seek(licenseStream, cbScope); /* CompanyName */ + if (Stream_GetRemainingLength(licenseStream) < 4) + goto out_free_stream; Stream_Read_UINT32(licenseStream, cbCompanyName); if (Stream_GetRemainingLength(licenseStream) < cbCompanyName) goto out_free_stream; @@ -1276,6 +1281,8 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s) Stream_Seek(licenseStream, cbCompanyName); /* productId */ + if (Stream_GetRemainingLength(licenseStream) < 4) + goto out_free_stream; Stream_Read_UINT32(licenseStream, cbProductId); if (Stream_GetRemainingLength(licenseStream) < cbProductId) goto out_free_stream; @@ -1286,6 +1293,8 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s) Stream_Seek(licenseStream, cbProductId); /* licenseInfo */ + if (Stream_GetRemainingLength(licenseStream) < 4) + goto out_free_stream; Stream_Read_UINT32(licenseStream, cbLicenseInfo); if (Stream_GetRemainingLength(licenseStream) < cbLicenseInfo) goto out_free_stream; From d1da09f7e12272dad3d89fa259704f5c7d297c91 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 25 May 2020 09:42:02 +0200 Subject: [PATCH 44/65] Fixed Out-of-bound read in glyph_cache_put CVE-2020-11098 thanks to @antonio-morales for finding this. (cherry picked from commit c0fd449ec0870b050d350d6d844b1ea6dad4bc7d) --- libfreerdp/cache/glyph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/cache/glyph.c b/libfreerdp/cache/glyph.c index 9f5e4a3013aa..5c41f912a10b 100644 --- a/libfreerdp/cache/glyph.c +++ b/libfreerdp/cache/glyph.c @@ -579,7 +579,7 @@ BOOL glyph_cache_put(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index, rdpGlyp return FALSE; } - if (index > glyphCache->glyphCache[id].number) + if (index >= glyphCache->glyphCache[id].number) { WLog_ERR(TAG, "invalid glyph cache index: %" PRIu32 " in cache id: %" PRIu32 "", index, id); return FALSE; From efb99f144b67d1c642b3483d7fe738f0c1ef02f7 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 25 May 2020 10:05:57 +0200 Subject: [PATCH 45/65] Fixed memory leaks in ntlm (cherry picked from commit 057b6df4aebbe8e739139087dfaab15104ca5ba7) --- winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c | 29 +++++++++++++----------- winpr/libwinpr/sspi/NTLM/ntlm_message.c | 2 +- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c index 7b6eabdc4bed..aa873db5e512 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c @@ -572,54 +572,54 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context) size += 8; /* unknown 8-byte padding */ if (!sspi_SecBufferAlloc(&context->AuthenticateTargetInfo, size)) - return -1; + goto fail; AuthenticateTargetInfo = (NTLM_AV_PAIR*)context->AuthenticateTargetInfo.pvBuffer; cbAuthenticateTargetInfo = context->AuthenticateTargetInfo.cbBuffer; if (!ntlm_av_pair_list_init(AuthenticateTargetInfo, cbAuthenticateTargetInfo)) - return -1; + goto fail; if (AvNbDomainName) { if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvNbDomainName, cbAvNbDomainName)) - return -1; + goto fail; } if (AvNbComputerName) { if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvNbComputerName, cbAvNbComputerName)) - return -1; + goto fail; } if (AvDnsDomainName) { if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvDnsDomainName, cbAvDnsDomainName)) - return -1; + goto fail; } if (AvDnsComputerName) { if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvDnsComputerName, cbAvDnsComputerName)) - return -1; + goto fail; } if (AvDnsTreeName) { if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvDnsTreeName, cbAvDnsTreeName)) - return -1; + goto fail; } if (AvTimestamp) { if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvTimestamp, cbAvTimestamp)) - return -1; + goto fail; } if (context->UseMIC) @@ -629,28 +629,28 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context) if (!ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvAvFlags, (PBYTE)&flags, 4)) - return -1; + goto fail; } if (context->SendSingleHostData) { if (!ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvAvSingleHost, (PBYTE)&context->SingleHostData, context->SingleHostData.Size)) - return -1; + goto fail; } if (!context->SuppressExtendedProtection) { if (!ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvChannelBindings, context->ChannelBindingsHash, 16)) - return -1; + goto fail; if (context->ServicePrincipalName.Length > 0) { if (!ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvAvTargetName, (PBYTE)context->ServicePrincipalName.Buffer, context->ServicePrincipalName.Length)) - return -1; + goto fail; } } @@ -660,10 +660,13 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context) AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvEOL, NULL); if (!AvEOL) - return -1; + goto fail; ZeroMemory(AvEOL, sizeof(NTLM_AV_PAIR)); } return 1; +fail: + sspi_SecBufferFree(&context->AuthenticateTargetInfo); + return -1; } diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_message.c b/winpr/libwinpr/sspi/NTLM/ntlm_message.c index 314f5c1475aa..34813a414f22 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_message.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_message.c @@ -544,9 +544,9 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf winpr_HexDump(TAG, WLOG_DEBUG, context->Timestamp, 8); #endif context->state = NTLM_STATE_AUTHENTICATE; - ntlm_free_message_fields_buffer(&(message->TargetName)); status = SEC_I_CONTINUE_NEEDED; fail: + ntlm_free_message_fields_buffer(&(message->TargetName)); Stream_Free(s, FALSE); return status; } From 8c3f6d2b19ed1811007bdb58c4742eb6bf2b2741 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 25 May 2020 13:56:24 +0200 Subject: [PATCH 46/65] Replaced localtime with localtime_r (cherry picked from commit 240fdd07b123594a1f7a460de7e6877b1963d09e) --- channels/printer/client/cups/printer_cups.c | 3 ++- channels/printer/client/win/printer_win.c | 3 ++- winpr/libwinpr/sysinfo/sysinfo.c | 3 ++- winpr/libwinpr/timezone/timezone.c | 7 ++++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/channels/printer/client/cups/printer_cups.c b/channels/printer/client/cups/printer_cups.c index 1f9f07b24aef..56cbacecfe29 100644 --- a/channels/printer/client/cups/printer_cups.c +++ b/channels/printer/client/cups/printer_cups.c @@ -69,10 +69,11 @@ struct rdp_cups_print_job static void printer_cups_get_printjob_name(char* buf, size_t size, size_t id) { time_t tt; + struct tm tres; struct tm* t; tt = time(NULL); - t = localtime(&tt); + t = localtime_r(&tt, &tres); sprintf_s(buf, size - 1, "FreeRDP Print %04d-%02d-%02d %02d-%02d-%02d - Job %" PRIdz, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, id); } diff --git a/channels/printer/client/win/printer_win.c b/channels/printer/client/win/printer_win.c index 5306f59fb116..83dadba9f72b 100644 --- a/channels/printer/client/win/printer_win.c +++ b/channels/printer/client/win/printer_win.c @@ -78,13 +78,14 @@ struct rdp_win_print_job static WCHAR* printer_win_get_printjob_name(size_t id) { time_t tt; + struct tm tres; struct tm* t; WCHAR* str; size_t len = 1024; int rc; tt = time(NULL); - t = localtime(&tt); + t = localtime_r(&tt, &tres); str = calloc(len, sizeof(WCHAR)); if (!str) diff --git a/winpr/libwinpr/sysinfo/sysinfo.c b/winpr/libwinpr/sysinfo/sysinfo.c index 10884f7d13e4..139d6546e7d6 100644 --- a/winpr/libwinpr/sysinfo/sysinfo.c +++ b/winpr/libwinpr/sysinfo/sysinfo.c @@ -242,11 +242,12 @@ BOOL SetSystemTime(CONST SYSTEMTIME* lpSystemTime) VOID GetLocalTime(LPSYSTEMTIME lpSystemTime) { time_t ct = 0; + struct tm tres; struct tm* ltm = NULL; WORD wMilliseconds = 0; ct = time(NULL); wMilliseconds = (WORD)(GetTickCount() % 1000); - ltm = localtime(&ct); + ltm = localtime_r(&ct, &tres); ZeroMemory(lpSystemTime, sizeof(SYSTEMTIME)); if (ltm) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index 5475cb67afeb..507763897010 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -339,12 +339,17 @@ winpr_get_current_time_zone_rule(const TIME_ZONE_RULE_ENTRY* rules, UINT32 count DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) { time_t t; + struct tm tres; + ; struct tm* local_time; TIME_ZONE_ENTRY* dtz; LPTIME_ZONE_INFORMATION tz = lpTimeZoneInformation; lpTimeZoneInformation->StandardBias = 0; time(&t); - local_time = localtime(&t); + local_time = localtime_r(&t, &tres); + if (!local_time) + goto out_error; + memset(tz, 0, sizeof(TIME_ZONE_INFORMATION)); #ifdef HAVE_TM_GMTOFF { From 3606dfa9212ece3f4d76104bd89c72b5834e4722 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 25 May 2020 14:01:23 +0200 Subject: [PATCH 47/65] Replaced getlogin with getlogin_r (cherry picked from commit 36478d3d0b3d7fa378a875f60170a08e94747226) --- channels/rdpdr/client/rdpdr_main.c | 5 ++++- client/X11/xf_client.c | 4 ++-- winpr/libwinpr/sspicli/sspicli.c | 9 +++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 7f6dc945194e..738594edc9b2 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -598,7 +598,10 @@ static BOOL isAutomountLocation(const char* path) size_t x; char buffer[MAX_PATH]; uid_t uid = getuid(); - const char* uname = getlogin(); + const char uname[MAX_PATH] = { 0 }; + + if (getlogin_r(uname, sizeof(uname)) != 0) + return FALSE; if (!path) return FALSE; diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 301820e64f83..189cb17e92a5 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -1181,9 +1181,9 @@ static BOOL xf_pre_connect(freerdp* instance) if (!settings->Username && !settings->CredentialsFromStdin && !settings->SmartcardLogon) { - char* login_name = getlogin(); + char login_name[MAX_PATH] = { 0 }; - if (login_name) + if (getlogin_r(login_name, sizeof(login_name)) == 0) { settings->Username = _strdup(login_name); diff --git a/winpr/libwinpr/sspicli/sspicli.c b/winpr/libwinpr/sspicli/sspicli.c index e88b53d48e4a..220f1e1ba8be 100644 --- a/winpr/libwinpr/sspicli/sspicli.c +++ b/winpr/libwinpr/sspicli/sspicli.c @@ -201,18 +201,19 @@ BOOL LogonUserExW(LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword BOOL GetUserNameExA(EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize) { size_t length; - char* login; + char login[MAX_PATH]; switch (NameFormat) { case NameSamCompatible: - login = getlogin(); + if (getlogin_r(login, sizeof(login)) != 0) + return FALSE; length = strlen(login); if (*nSize >= length) { CopyMemory(lpNameBuffer, login, length + 1); - return 1; + return TRUE; } else { @@ -235,7 +236,7 @@ BOOL GetUserNameExA(EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG break; } - return 0; + return FALSE; } BOOL GetUserNameExW(EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize) From 85b0354dfadae0506450d9caed6c6e3d6cc9f4af Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 25 May 2020 14:03:12 +0200 Subject: [PATCH 48/65] Fixed double free (cherry picked from commit 6d86e20e1e7caaab4f0c7f89e36d32914dbccc52) --- server/shadow/shadow_server.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index 30a63c9fa038..259f22ecd14a 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -586,14 +586,19 @@ int shadow_server_start(rdpShadowServer* server) char** list = CommandLineParseCommaSeparatedValuesEx(NULL, server->ipcSocket, &count); if (!list || (count <= 1)) { - free(list); if (server->ipcSocket == NULL) { if (!open_port(server, NULL)) + { + free(list); return -1; + } } else + { + free(list); return -1; + } } for (x = 1; x < count; x++) From 69eef641d0e236bc69a7745cd56f617b43e90dde Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 25 May 2020 14:03:35 +0200 Subject: [PATCH 49/65] Fixed pcap cleanup (cherry picked from commit 3ac7bb5d6a743b19e8686410d5ec6dcf74869ebe) --- libfreerdp/utils/pcap.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/libfreerdp/utils/pcap.c b/libfreerdp/utils/pcap.c index e50bbd7e7cec..6f6ed258ae14 100644 --- a/libfreerdp/utils/pcap.c +++ b/libfreerdp/utils/pcap.c @@ -170,22 +170,17 @@ rdpPcap* pcap_open(char* name, BOOL write) { rdpPcap* pcap; - FILE* pcap_fp = fopen(name, write ? "w+b" : "rb"); - - if (pcap_fp == NULL) - { - WLog_ERR(TAG, "opening pcap dump"); - return NULL; - } - pcap = (rdpPcap*)calloc(1, sizeof(rdpPcap)); if (!pcap) - goto fail_close; + goto fail; pcap->name = name; pcap->write = write; pcap->record_count = 0; - pcap->fp = pcap_fp; + pcap->fp = fopen(name, write ? "w+b" : "rb"); + + if (pcap->fp == NULL) + goto fail; if (write) { @@ -211,9 +206,7 @@ rdpPcap* pcap_open(char* name, BOOL write) return pcap; fail: - free(pcap); -fail_close: - fclose(pcap_fp); + pcap_close(pcap); return NULL; } @@ -231,6 +224,9 @@ void pcap_flush(rdpPcap* pcap) void pcap_close(rdpPcap* pcap) { + if (!pcap) + return; + pcap_flush(pcap); if (pcap->fp != NULL) From 23161efa6217330bf8d230baf6847aa41d0221e6 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 25 May 2020 14:04:17 +0200 Subject: [PATCH 50/65] Fixed codition with side effects (cherry picked from commit 1a02af5a12b400fcb6ad121a0a71e4440c2e9152) --- channels/drdynvc/client/drdynvc_main.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 4b9799e6127a..507305fc62ad 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -580,10 +580,15 @@ static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelManage { pCallback = channel->channel_callback; - if ((pCallback->OnOpen) && (error = pCallback->OnOpen(pCallback))) + if (pCallback->OnOpen) { - WLog_Print(drdynvc->log, WLOG_ERROR, "OnOpen failed with error %" PRIu32 "!", error); - return error; + error = pCallback->OnOpen(pCallback); + if (error) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "OnOpen failed with error %" PRIu32 "!", + error); + return error; + } } WLog_Print(drdynvc->log, WLOG_DEBUG, "open_channel: ChannelId %" PRIu32 "", ChannelId); From 32717ff9dbc71588882c0c4aeed4af8e5e0cae11 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 25 May 2020 14:07:31 +0200 Subject: [PATCH 51/65] Replaced gmtime with gmtime_r (cherry picked from commit a45afe9db77a19e5a177fe1dc3e85119013f9587) --- winpr/libwinpr/sysinfo/sysinfo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/winpr/libwinpr/sysinfo/sysinfo.c b/winpr/libwinpr/sysinfo/sysinfo.c index 139d6546e7d6..de39e15b1dc7 100644 --- a/winpr/libwinpr/sysinfo/sysinfo.c +++ b/winpr/libwinpr/sysinfo/sysinfo.c @@ -213,11 +213,12 @@ void GetNativeSystemInfo(LPSYSTEM_INFO lpSystemInfo) void GetSystemTime(LPSYSTEMTIME lpSystemTime) { time_t ct = 0; + struct tm tres; struct tm* stm = NULL; WORD wMilliseconds = 0; ct = time(NULL); wMilliseconds = (WORD)(GetTickCount() % 1000); - stm = gmtime(&ct); + stm = gmtime_r(&ct, &tres); ZeroMemory(lpSystemTime, sizeof(SYSTEMTIME)); if (stm) From ac9f5e8f5d61588364da89ad946f8f89b5954536 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 25 May 2020 14:20:23 +0200 Subject: [PATCH 52/65] Use localtime_s on windows (cherry picked from commit c3a1ed780cc4aed639e3391d7cafb9edc9dc623c) --- channels/printer/client/win/printer_win.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/printer/client/win/printer_win.c b/channels/printer/client/win/printer_win.c index 83dadba9f72b..86b5e66d9240 100644 --- a/channels/printer/client/win/printer_win.c +++ b/channels/printer/client/win/printer_win.c @@ -85,7 +85,7 @@ static WCHAR* printer_win_get_printjob_name(size_t id) int rc; tt = time(NULL); - t = localtime_r(&tt, &tres); + t = localtime_s(&tt, &tres); str = calloc(len, sizeof(WCHAR)); if (!str) From c687b8c267ca238acfbc39264967405fec19e39a Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 26 May 2020 07:28:33 +0200 Subject: [PATCH 53/65] Fixed invalid access in update_recv_primary_order CVE-2020-11095 thanks @antonio-morales for finding this. (cherry picked from commit 733ee3208306b1ea32697b356c0215180fc3f049) --- libfreerdp/core/orders.c | 107 +++++++++++++++++++++++++++------------ libfreerdp/core/orders.h | 2 +- libfreerdp/core/update.c | 4 +- 3 files changed, 78 insertions(+), 35 deletions(-) diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 87e0959642c3..90d79f54d6e1 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -43,36 +43,75 @@ #define TAG FREERDP_TAG("core.orders") -const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[] = { DSTBLT_ORDER_FIELD_BYTES, - PATBLT_ORDER_FIELD_BYTES, - SCRBLT_ORDER_FIELD_BYTES, - 0, - 0, - 0, - 0, - DRAW_NINE_GRID_ORDER_FIELD_BYTES, - MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES, - LINE_TO_ORDER_FIELD_BYTES, - OPAQUE_RECT_ORDER_FIELD_BYTES, - SAVE_BITMAP_ORDER_FIELD_BYTES, - 0, - MEMBLT_ORDER_FIELD_BYTES, - MEM3BLT_ORDER_FIELD_BYTES, - MULTI_DSTBLT_ORDER_FIELD_BYTES, - MULTI_PATBLT_ORDER_FIELD_BYTES, - MULTI_SCRBLT_ORDER_FIELD_BYTES, - MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES, - FAST_INDEX_ORDER_FIELD_BYTES, - POLYGON_SC_ORDER_FIELD_BYTES, - POLYGON_CB_ORDER_FIELD_BYTES, - POLYLINE_ORDER_FIELD_BYTES, - 0, - FAST_GLYPH_ORDER_FIELD_BYTES, - ELLIPSE_SC_ORDER_FIELD_BYTES, - ELLIPSE_CB_ORDER_FIELD_BYTES, - GLYPH_INDEX_ORDER_FIELD_BYTES }; - -#define PRIMARY_DRAWING_ORDER_COUNT (ARRAYSIZE(PRIMARY_DRAWING_ORDER_FIELD_BYTES)) +BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid) +{ + if (pValid) + *pValid = TRUE; + switch (orderType) + { + case 0: + return DSTBLT_ORDER_FIELD_BYTES; + case 1: + return PATBLT_ORDER_FIELD_BYTES; + case 2: + return SCRBLT_ORDER_FIELD_BYTES; + case 3: + return 0; + case 4: + return 0; + case 5: + return 0; + case 6: + return 0; + case 7: + return DRAW_NINE_GRID_ORDER_FIELD_BYTES; + case 8: + return MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES; + case 9: + return LINE_TO_ORDER_FIELD_BYTES; + case 10: + return OPAQUE_RECT_ORDER_FIELD_BYTES; + case 11: + return SAVE_BITMAP_ORDER_FIELD_BYTES; + case 12: + return 0; + case 13: + return MEMBLT_ORDER_FIELD_BYTES; + case 14: + return MEM3BLT_ORDER_FIELD_BYTES; + case 15: + return MULTI_DSTBLT_ORDER_FIELD_BYTES; + case 16: + return MULTI_PATBLT_ORDER_FIELD_BYTES; + case 17: + return MULTI_SCRBLT_ORDER_FIELD_BYTES; + case 18: + return MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES; + case 19: + return FAST_INDEX_ORDER_FIELD_BYTES; + case 20: + return POLYGON_SC_ORDER_FIELD_BYTES; + case 21: + return POLYGON_CB_ORDER_FIELD_BYTES; + case 22: + return POLYLINE_ORDER_FIELD_BYTES; + case 23: + return 0; + case 24: + return FAST_GLYPH_ORDER_FIELD_BYTES; + case 25: + return ELLIPSE_SC_ORDER_FIELD_BYTES; + case 26: + return ELLIPSE_CB_ORDER_FIELD_BYTES; + case 27: + return GLYPH_INDEX_ORDER_FIELD_BYTES; + default: + if (pValid) + *pValid = FALSE; + WLog_WARN(TAG, "Invalid orderType 0x%08X received", orderType); + return 0; + } +} static const BYTE CBR2_BPP[] = { 0, 0, 0, 8, 16, 24, 32 }; @@ -3240,6 +3279,7 @@ static BOOL read_primary_order(wLog* log, const char* orderName, wStream* s, static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) { + BYTE field; BOOL rc = FALSE; rdpContext* context = update->context; rdpPrimaryUpdate* primary = update->primary; @@ -3263,8 +3303,11 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) if (!check_primary_order_supported(update->log, settings, orderInfo->orderType, orderName)) return FALSE; - if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, - PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType])) + field = get_primary_drawing_order_field_bytes(orderInfo->orderType, &rc); + if (!rc) + return FALSE; + + if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, field)) { WLog_Print(update->log, WLOG_ERROR, "update_read_field_flags() failed"); return FALSE; diff --git a/libfreerdp/core/orders.h b/libfreerdp/core/orders.h index 76e3d3fe3455..d429dff7046f 100644 --- a/libfreerdp/core/orders.h +++ b/libfreerdp/core/orders.h @@ -189,7 +189,7 @@ #define CG_GLYPH_UNICODE_PRESENT 0x0010 -FREERDP_LOCAL extern const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[]; +FREERDP_LOCAL BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid); FREERDP_LOCAL BOOL update_recv_order(rdpUpdate* update, wStream* s); diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index aac58819fdf9..ebb82fc2df7e 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -1087,7 +1087,7 @@ static int update_prepare_order_info(rdpContext* context, ORDER_INFO* orderInfo, orderInfo->controlFlags = ORDER_STANDARD; orderInfo->controlFlags |= ORDER_TYPE_CHANGE; length += 1; - length += PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]; + length += get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL); length += update_prepare_bounds(context, orderInfo); return length; } @@ -1105,7 +1105,7 @@ static int update_write_order_info(rdpContext* context, wStream* s, ORDER_INFO* Stream_Write_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */ update_write_field_flags(s, orderInfo->fieldFlags, orderInfo->controlFlags, - PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]); + get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL)); update_write_bounds(s, orderInfo); Stream_SetPosition(s, position); return 0; From 746d10179c54e77beccf0b4edf2c9803d5a8e7da Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 26 May 2020 07:50:55 +0200 Subject: [PATCH 54/65] Fixed OOB read in update_read_cache_bitmap_v3_order CVE-2020-11096 thanks @antonio-morales for finding this. (cherry picked from commit b8beb55913471952f92770c90c372139d78c16c0) --- libfreerdp/core/orders.c | 122 +++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 24 deletions(-) diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 90d79f54d6e1..744bf3cd6ac0 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -113,20 +113,74 @@ BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid) } } -static const BYTE CBR2_BPP[] = { 0, 0, 0, 8, 16, 24, 32 }; - -static const BYTE BPP_CBR2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 }; - -static const BYTE CBR23_BPP[] = { 0, 0, 0, 8, 16, 24, 32 }; - -static const BYTE BPP_CBR23[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 }; - -static const BYTE BMF_BPP[] = { 0, 1, 0, 8, 16, 24, 32, 0 }; +static BYTE get_cbr2_bpp(UINT32 bpp, BOOL* pValid) +{ + if (pValid) + *pValid = TRUE; + switch (bpp) + { + case 3: + return 8; + case 4: + return 16; + case 5: + return 24; + case 6: + return 32; + default: + WLog_WARN(TAG, "Invalid bpp %" PRIu32, bpp); + if (pValid) + *pValid = FALSE; + return 0; + } +} -static const BYTE BPP_BMF[] = { 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 }; +static BYTE get_bmf_bpp(UINT32 bmf, BOOL* pValid) +{ + if (pValid) + *pValid = TRUE; + switch (bmf) + { + case 1: + return 1; + case 3: + return 8; + case 4: + return 16; + case 5: + return 24; + case 6: + return 32; + default: + WLog_WARN(TAG, "Invalid bmf %" PRIu32, bmf); + if (pValid) + *pValid = FALSE; + return 0; + } +} +static BYTE get_bpp_bmf(UINT32 bpp, BOOL* pValid) +{ + if (pValid) + *pValid = TRUE; + switch (bpp) + { + case 1: + return 1; + case 8: + return 3; + case 16: + return 4; + case 24: + return 5; + case 32: + return 6; + default: + WLog_WARN(TAG, "Invalid color depth %" PRIu32, bpp); + if (pValid) + *pValid = FALSE; + return 0; + } +} static BOOL check_order_activated(wLog* log, rdpSettings* settings, const char* orderName, BOOL condition) @@ -814,9 +868,11 @@ static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, BYTE fieldFlag if (brush->style & CACHED_BRUSH) { + BOOL rc; brush->index = brush->hatch; - brush->bpp = BMF_BPP[brush->style & 0x07]; - + brush->bpp = get_bmf_bpp(brush->style, &rc); + if (!rc) + return FALSE; if (brush->bpp == 0) brush->bpp = 1; } @@ -858,9 +914,11 @@ static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, BYTE fieldFla if (brush->style & CACHED_BRUSH) { + BOOL rc; brush->hatch = brush->index; - brush->bpp = BMF_BPP[brush->style & 0x07]; - + brush->bpp = get_bmf_bpp(brush->style, &rc); + if (!rc) + return FALSE; if (brush->bpp == 0) brush->bpp = 1; } @@ -2016,6 +2074,7 @@ BOOL update_write_cache_bitmap_order(wStream* s, const CACHE_BITMAP_ORDER* cache static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* update, wStream* s, BOOL compressed, UINT16 flags) { + BOOL rc; BYTE bitsPerPixelId; CACHE_BITMAP_V2_ORDER* cache_bitmap_v2; @@ -2030,7 +2089,9 @@ static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* updat cache_bitmap_v2->cacheId = flags & 0x0003; cache_bitmap_v2->flags = (flags & 0xFF80) >> 7; bitsPerPixelId = (flags & 0x0078) >> 3; - cache_bitmap_v2->bitmapBpp = CBR2_BPP[bitsPerPixelId]; + cache_bitmap_v2->bitmapBpp = get_cbr2_bpp(bitsPerPixelId, &rc); + if (!rc) + goto fail; if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT) { @@ -2109,13 +2170,16 @@ int update_approximate_cache_bitmap_v2_order(CACHE_BITMAP_V2_ORDER* cache_bitmap BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2, BOOL compressed, UINT16* flags) { + BOOL rc; BYTE bitsPerPixelId; if (!Stream_EnsureRemainingCapacity( s, update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, compressed, flags))) return FALSE; - bitsPerPixelId = BPP_CBR2[cache_bitmap_v2->bitmapBpp]; + bitsPerPixelId = get_bpp_bmf(cache_bitmap_v2->bitmapBpp, &rc); + if (!rc) + return FALSE; *flags = (cache_bitmap_v2->cacheId & 0x0003) | (bitsPerPixelId << 3) | ((cache_bitmap_v2->flags << 7) & 0xFF80); @@ -2177,6 +2241,7 @@ BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* update, wStream* s, UINT16 flags) { + BOOL rc; BYTE bitsPerPixelId; BITMAP_DATA_EX* bitmapData; UINT32 new_len; @@ -2194,7 +2259,9 @@ static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* updat cache_bitmap_v3->cacheId = flags & 0x00000003; cache_bitmap_v3->flags = (flags & 0x0000FF80) >> 7; bitsPerPixelId = (flags & 0x00000078) >> 3; - cache_bitmap_v3->bpp = CBR23_BPP[bitsPerPixelId]; + cache_bitmap_v3->bpp = get_cbr2_bpp(bitsPerPixelId, &rc); + if (!rc) + goto fail; if (Stream_GetRemainingLength(s) < 21) goto fail; @@ -2242,6 +2309,7 @@ int update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3, UINT16* flags) { + BOOL rc; BYTE bitsPerPixelId; BITMAP_DATA_EX* bitmapData; @@ -2250,7 +2318,9 @@ BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache return FALSE; bitmapData = &cache_bitmap_v3->bitmapData; - bitsPerPixelId = BPP_CBR23[cache_bitmap_v3->bpp]; + bitsPerPixelId = get_bpp_bmf(cache_bitmap_v3->bpp, &rc); + if (!rc) + return FALSE; *flags = (cache_bitmap_v3->cacheId & 0x00000003) | ((cache_bitmap_v3->flags << 7) & 0x0000FF80) | ((bitsPerPixelId << 3) & 0x00000078); Stream_Write_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */ @@ -2574,6 +2644,7 @@ static BOOL update_compress_brush(wStream* s, const BYTE* input, BYTE bpp) static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, UINT16 flags) { int i; + BOOL rc; BYTE iBitmapFormat; BOOL compressed = FALSE; CACHE_BRUSH_ORDER* cache_brush = calloc(1, sizeof(CACHE_BRUSH_ORDER)); @@ -2587,10 +2658,10 @@ static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */ Stream_Read_UINT8(s, iBitmapFormat); /* iBitmapFormat (1 byte) */ - if (iBitmapFormat >= ARRAYSIZE(BMF_BPP)) + cache_brush->bpp = get_bmf_bpp(iBitmapFormat, &rc); + if (!rc) goto fail; - cache_brush->bpp = BMF_BPP[iBitmapFormat]; Stream_Read_UINT8(s, cache_brush->cx); /* cx (1 byte) */ Stream_Read_UINT8(s, cache_brush->cy); /* cy (1 byte) */ Stream_Read_UINT8(s, cache_brush->style); /* style (1 byte) */ @@ -2661,13 +2732,16 @@ BOOL update_write_cache_brush_order(wStream* s, const CACHE_BRUSH_ORDER* cache_b { int i; BYTE iBitmapFormat; + BOOL rc; BOOL compressed = FALSE; if (!Stream_EnsureRemainingCapacity(s, update_approximate_cache_brush_order(cache_brush, flags))) return FALSE; - iBitmapFormat = BPP_BMF[cache_brush->bpp]; + iBitmapFormat = get_bpp_bmf(cache_brush->bpp, &rc); + if (!rc) + return FALSE; Stream_Write_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */ Stream_Write_UINT8(s, iBitmapFormat); /* iBitmapFormat (1 byte) */ Stream_Write_UINT8(s, cache_brush->cx); /* cx (1 byte) */ From ab18f07873b6f502217712d8029a30ca152f4c32 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 26 May 2020 16:12:58 +0200 Subject: [PATCH 55/65] Fixed TrioParse and trio_length limts. CVE-2020-4030 thanks to @antonio-morales for finding this. (cherry picked from commit 05cd9ea2290d23931f615c1b004d4b2e69074e27) --- winpr/libwinpr/utils/trio/trio.c | 6 +++--- winpr/libwinpr/utils/trio/triostr.c | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/winpr/libwinpr/utils/trio/trio.c b/winpr/libwinpr/utils/trio/trio.c index ec765ce5af41..b278f475b758 100644 --- a/winpr/libwinpr/utils/trio/trio.c +++ b/winpr/libwinpr/utils/trio/trio.c @@ -2729,7 +2729,7 @@ TRIO_PRIVATE void TrioWriteString TRIO_ARGS5((self, string, flags, width, precis trio_class_t* self, TRIO_CONST char* string, trio_flags_t flags, int width, int precision) { - int length; + int length = 0; int ch; assert(VALID(self)); @@ -2747,7 +2747,7 @@ TRIO_PRIVATE void TrioWriteString TRIO_ARGS5((self, string, flags, width, precis } else { - if (precision == 0) + if (precision <= 0) { length = trio_length(string); } @@ -4754,7 +4754,7 @@ TRIO_PUBLIC trio_pointer_t trio_register TRIO_ARGS2((callback, name), trio_callb } /* Bail out if namespace is too long */ - if (trio_length(name) >= MAX_USER_NAME) + if (trio_length_max(name, MAX_USER_NAME) >= MAX_USER_NAME) return NULL; /* Bail out if namespace already is registered */ diff --git a/winpr/libwinpr/utils/trio/triostr.c b/winpr/libwinpr/utils/trio/triostr.c index da12775acf7e..6832ad5aef64 100644 --- a/winpr/libwinpr/utils/trio/triostr.c +++ b/winpr/libwinpr/utils/trio/triostr.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "triodef.h" #include "triostr.h" @@ -328,7 +329,7 @@ TRIO_PUBLIC_STRING void trio_destroy TRIO_ARGS1((string), char* string) TRIO_PUBLIC_STRING size_t trio_length TRIO_ARGS1((string), TRIO_CONST char* string) { - return strlen(string); + return trio_length_max(string, INT_MAX); } #endif From 12800786a8a2c38587942eb20ac184c4867e1ddb Mon Sep 17 00:00:00 2001 From: akallabeth Date: Wed, 27 May 2020 08:10:11 +0200 Subject: [PATCH 56/65] Fixed OOB read in update_recv_secondary_order CVE-2020-4032 thanks to @antonio-morales for finding this. (cherry picked from commit e7bffa64ef5ed70bac94f823e2b95262642f5296) --- libfreerdp/core/orders.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 744bf3cd6ac0..dc4e51a87396 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -3762,12 +3762,13 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flag name, end - start); return FALSE; } - diff = start - end; + diff = end - start; if (diff > 0) { WLog_Print(update->log, WLOG_DEBUG, "SECONDARY_ORDER %s: read %" PRIuz "bytes short, skipping", name, diff); - Stream_Seek(s, diff); + if (!Stream_SafeSeek(s, diff)) + return FALSE; } return rc; } From 6780420343b2a566b5593522728f04c0807621d4 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 2 Jun 2020 08:45:09 +0200 Subject: [PATCH 57/65] Fixed out of bound read in RLEDECOMPRESS CVE-2020-4033 thanks to @antonio-morales for finding this. (cherry picked from commit 0a98c450c58ec150e44781c89aa6f8e7e0f571f5) --- libfreerdp/codec/include/bitmap.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libfreerdp/codec/include/bitmap.c b/libfreerdp/codec/include/bitmap.c index 5b4804f2ea2a..38bcaa859f88 100644 --- a/libfreerdp/codec/include/bitmap.c +++ b/libfreerdp/codec/include/bitmap.c @@ -201,6 +201,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN) { + if (pbSrc >= pbEnd) + return FALSE; SRCREADPIXEL(fgPel, pbSrc); SRCNEXTPIXEL(pbSrc); } @@ -231,8 +233,12 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY case MEGA_MEGA_DITHERED_RUN: runLength = ExtractRunLength(code, pbSrc, &advance); pbSrc = pbSrc + advance; + if (pbSrc >= pbEnd) + return FALSE; SRCREADPIXEL(pixelA, pbSrc); SRCNEXTPIXEL(pbSrc); + if (pbSrc >= pbEnd) + return FALSE; SRCREADPIXEL(pixelB, pbSrc); SRCNEXTPIXEL(pbSrc); @@ -252,6 +258,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY case MEGA_MEGA_COLOR_RUN: runLength = ExtractRunLength(code, pbSrc, &advance); pbSrc = pbSrc + advance; + if (pbSrc >= pbEnd) + return FALSE; SRCREADPIXEL(pixelA, pbSrc); SRCNEXTPIXEL(pbSrc); @@ -272,6 +280,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY runLength = ExtractRunLength(code, pbSrc, &advance); pbSrc = pbSrc + advance; + if (pbSrc >= pbEnd) + return FALSE; if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE) { SRCREADPIXEL(fgPel, pbSrc); @@ -338,6 +348,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY return FALSE; UNROLL(runLength, { + if (pbSrc >= pbEnd) + return FALSE; SRCREADPIXEL(temp, pbSrc); SRCNEXTPIXEL(pbSrc); DESTWRITEPIXEL(pbDest, temp); From 724ceade0f1e75e196fb61f30cff86e5905a5486 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 2 Jun 2020 09:28:47 +0200 Subject: [PATCH 58/65] Reset freed HGDI_DC CVE-2020-4031 thanks to @antonio-morales for finding this. (cherry picked from commit f753c25ad3d5dae7890fe73cfb3c091c015d97ed) --- libfreerdp/gdi/graphics.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c index f63df39833e9..60d82ae995e1 100644 --- a/libfreerdp/gdi/graphics.c +++ b/libfreerdp/gdi/graphics.c @@ -93,6 +93,7 @@ static BOOL gdi_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) if (!gdi_bitmap->bitmap) { gdi_DeleteDC(gdi_bitmap->hdc); + gdi_bitmap->hdc = NULL; return FALSE; } From eb1cf9a2ac9eff612a44ceb9f61da32248d0af4a Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 2 Jun 2020 11:33:48 +0200 Subject: [PATCH 59/65] Fixed broken const variable. (cherry picked from commit 1c6a6923f87dcfb295c508963f21bebbbc4292ae) --- channels/rdpdr/client/rdpdr_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 738594edc9b2..32143984009b 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -598,7 +598,7 @@ static BOOL isAutomountLocation(const char* path) size_t x; char buffer[MAX_PATH]; uid_t uid = getuid(); - const char uname[MAX_PATH] = { 0 }; + char uname[MAX_PATH] = { 0 }; if (getlogin_r(uname, sizeof(uname)) != 0) return FALSE; From de3dab1a7d2b08e4177f7a9daf0a753ea6e5087b Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 2 Jun 2020 12:26:40 +0200 Subject: [PATCH 60/65] Fixed OOB read in ntlm_av_pair_get CVE-2020-11097 thanks to @antonio-morales for finding this. (cherry picked from commit 58a3122250d54de3a944c487776bcd4d1da4721e) --- winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c | 146 ++++++++++++++++++----- 1 file changed, 113 insertions(+), 33 deletions(-) diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c index aa873db5e512..47669bb2e8aa 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c @@ -39,13 +39,50 @@ #include "../../log.h" #define TAG WINPR_TAG("sspi.NTLM") -static const char* const AV_PAIR_STRINGS[] = { - "MsvAvEOL", "MsvAvNbComputerName", "MsvAvNbDomainName", "MsvAvDnsComputerName", - "MsvAvDnsDomainName", "MsvAvDnsTreeName", "MsvAvFlags", "MsvAvTimestamp", - "MsvAvRestrictions", "MsvAvTargetName", "MsvChannelBindings" -}; +static BOOL ntlm_av_pair_get_next_offset(const NTLM_AV_PAIR* pAvPair, size_t size, size_t* pOffset); -static BOOL ntlm_av_pair_check(NTLM_AV_PAIR* pAvPair, size_t cbAvPair); +static BOOL ntlm_av_pair_check_data(const NTLM_AV_PAIR* pAvPair, size_t cbAvPair, size_t size) +{ + size_t offset; + if (!pAvPair || cbAvPair < sizeof(NTLM_AV_PAIR) + size) + return FALSE; + if (!ntlm_av_pair_get_next_offset(pAvPair, cbAvPair, &offset)) + return FALSE; + return cbAvPair >= offset; +} + +static const char* get_av_pair_string(UINT16 pair) +{ + switch (pair) + { + case MsvAvEOL: + return "MsvAvEOL"; + case MsvAvNbComputerName: + return "MsvAvNbComputerName"; + case MsvAvNbDomainName: + return "MsvAvNbDomainName"; + case MsvAvDnsComputerName: + return "MsvAvDnsComputerName"; + case MsvAvDnsDomainName: + return "MsvAvDnsDomainName"; + case MsvAvDnsTreeName: + return "MsvAvDnsTreeName"; + case MsvAvFlags: + return "MsvAvFlags"; + case MsvAvTimestamp: + return "MsvAvTimestamp"; + case MsvAvSingleHost: + return "MsvAvSingleHost"; + case MsvAvTargetName: + return "MsvAvTargetName"; + case MsvChannelBindings: + return "MsvChannelBindings"; + default: + return "UNKNOWN"; + } +} + +static BOOL ntlm_av_pair_check(const NTLM_AV_PAIR* pAvPair, size_t cbAvPair); static NTLM_AV_PAIR* ntlm_av_pair_next(NTLM_AV_PAIR* pAvPairList, size_t* pcbAvPairList); static INLINE void ntlm_av_pair_set_id(NTLM_AV_PAIR* pAvPair, UINT16 id) @@ -70,13 +107,19 @@ static BOOL ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairLis return TRUE; } -static INLINE UINT16 ntlm_av_pair_get_id(const NTLM_AV_PAIR* pAvPair) +static INLINE BOOL ntlm_av_pair_get_id(const NTLM_AV_PAIR* pAvPair, size_t size, UINT16* pair) { UINT16 AvId; + if (!pAvPair || !pair) + return FALSE; + + if (size < sizeof(NTLM_AV_PAIR)) + return FALSE; Data_Read_UINT16(&pAvPair->AvId, AvId); - return AvId; + *pair = AvId; + return TRUE; } ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList) @@ -91,17 +134,24 @@ ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList) return ((PBYTE)pAvPair - (PBYTE)pAvPairList) + sizeof(NTLM_AV_PAIR); } -static INLINE SIZE_T ntlm_av_pair_get_len(const NTLM_AV_PAIR* pAvPair) +static INLINE BOOL ntlm_av_pair_get_len(const NTLM_AV_PAIR* pAvPair, size_t size, size_t* pAvLen) { UINT16 AvLen; + if (!pAvPair) + return FALSE; + + if (size < sizeof(NTLM_AV_PAIR)) + return FALSE; Data_Read_UINT16(&pAvPair->AvLen, AvLen); - return AvLen; + *pAvLen = AvLen; + return TRUE; } void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList) { + UINT16 pair; size_t cbAvPair = cbAvPairList; NTLM_AV_PAIR* pAvPair = pAvPairList; @@ -110,13 +160,13 @@ void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList) WLog_INFO(TAG, "AV_PAIRs ="); - while (pAvPair && ntlm_av_pair_get_id(pAvPair) != MsvAvEOL) + while (pAvPair && ntlm_av_pair_get_id(pAvPair, cbAvPair, &pair) && (pair != MsvAvEOL)) { - WLog_INFO(TAG, "\t%s AvId: %" PRIu16 " AvLen: %" PRIu16 "", - AV_PAIR_STRINGS[ntlm_av_pair_get_id(pAvPair)], ntlm_av_pair_get_id(pAvPair), - ntlm_av_pair_get_len(pAvPair)); - winpr_HexDump(TAG, WLOG_INFO, ntlm_av_pair_get_value_pointer(pAvPair), - ntlm_av_pair_get_len(pAvPair)); + size_t cbLen = 0; + ntlm_av_pair_get_len(pAvPair, cbAvPair, &cbLen); + + WLog_INFO(TAG, "\t%s AvId: %" PRIu16 " AvLen: %" PRIu16 "", get_av_pair_string(pair), pair); + winpr_HexDump(TAG, WLOG_INFO, ntlm_av_pair_get_value_pointer(pAvPair), cbLen); pAvPair = ntlm_av_pair_next(pAvPair, &cbAvPair); } @@ -133,16 +183,21 @@ PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair) return (PBYTE)pAvPair + sizeof(NTLM_AV_PAIR); } -static size_t ntlm_av_pair_get_next_offset(NTLM_AV_PAIR* pAvPair) +static BOOL ntlm_av_pair_get_next_offset(const NTLM_AV_PAIR* pAvPair, size_t size, size_t* pOffset) { - return ntlm_av_pair_get_len(pAvPair) + sizeof(NTLM_AV_PAIR); + size_t avLen; + if (!pOffset) + return FALSE; + + if (!ntlm_av_pair_get_len(pAvPair, size, &avLen)) + return FALSE; + *pOffset = avLen + sizeof(NTLM_AV_PAIR); + return TRUE; } -static BOOL ntlm_av_pair_check(NTLM_AV_PAIR* pAvPair, size_t cbAvPair) +static BOOL ntlm_av_pair_check(const NTLM_AV_PAIR* pAvPair, size_t cbAvPair) { - if (!pAvPair || cbAvPair < sizeof(NTLM_AV_PAIR)) - return FALSE; - return cbAvPair >= ntlm_av_pair_get_next_offset(pAvPair); + return ntlm_av_pair_check_data(pAvPair, cbAvPair, 0); } static NTLM_AV_PAIR* ntlm_av_pair_next(NTLM_AV_PAIR* pAvPair, size_t* pcbAvPair) @@ -154,7 +209,9 @@ static NTLM_AV_PAIR* ntlm_av_pair_next(NTLM_AV_PAIR* pAvPair, size_t* pcbAvPair) if (!ntlm_av_pair_check(pAvPair, *pcbAvPair)) return NULL; - offset = ntlm_av_pair_get_next_offset(pAvPair); + if (!ntlm_av_pair_get_next_offset(pAvPair, *pcbAvPair, &offset)) + return NULL; + *pcbAvPair -= offset; return (NTLM_AV_PAIR*)((PBYTE)pAvPair + offset); } @@ -162,16 +219,15 @@ static NTLM_AV_PAIR* ntlm_av_pair_next(NTLM_AV_PAIR* pAvPair, size_t* pcbAvPair) NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList, NTLM_AV_ID AvId, size_t* pcbAvPairListRemaining) { + UINT16 id; size_t cbAvPair = cbAvPairList; NTLM_AV_PAIR* pAvPair = pAvPairList; if (!ntlm_av_pair_check(pAvPair, cbAvPair)) pAvPair = NULL; - while (pAvPair) + while (pAvPair && ntlm_av_pair_get_id(pAvPair, cbAvPair, &id)) { - UINT16 id = ntlm_av_pair_get_id(pAvPair); - if (id == AvId) break; if (id == MsvAvEOL) @@ -218,11 +274,20 @@ static BOOL ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList, NTL static BOOL ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList, NTLM_AV_PAIR* pAvPair, size_t cbAvPair) { + UINT16 pair; + size_t avLen; + if (!ntlm_av_pair_check(pAvPair, cbAvPair)) return FALSE; - return ntlm_av_pair_add(pAvPairList, cbAvPairList, ntlm_av_pair_get_id(pAvPair), - ntlm_av_pair_get_value_pointer(pAvPair), ntlm_av_pair_get_len(pAvPair)); + if (!ntlm_av_pair_get_id(pAvPair, cbAvPair, &pair)) + return FALSE; + + if (!ntlm_av_pair_get_len(pAvPair, cbAvPair, &avLen)) + return FALSE; + + return ntlm_av_pair_add(pAvPairList, cbAvPairList, pair, + ntlm_av_pair_get_value_pointer(pAvPair), avLen); } static int ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type) @@ -500,32 +565,47 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context) if (AvNbDomainName) { + size_t avLen; + if (!ntlm_av_pair_get_len(AvNbDomainName, cbAvNbDomainName, &avLen)) + goto fail; AvPairsCount++; /* MsvAvNbDomainName */ - AvPairsValueLength += ntlm_av_pair_get_len(AvNbDomainName); + AvPairsValueLength += avLen; } if (AvNbComputerName) { + size_t avLen; + if (!ntlm_av_pair_get_len(AvNbComputerName, cbAvNbComputerName, &avLen)) + goto fail; AvPairsCount++; /* MsvAvNbComputerName */ - AvPairsValueLength += ntlm_av_pair_get_len(AvNbComputerName); + AvPairsValueLength += avLen; } if (AvDnsDomainName) { + size_t avLen; + if (!ntlm_av_pair_get_len(AvDnsDomainName, cbAvDnsDomainName, &avLen)) + goto fail; AvPairsCount++; /* MsvAvDnsDomainName */ - AvPairsValueLength += ntlm_av_pair_get_len(AvDnsDomainName); + AvPairsValueLength += avLen; } if (AvDnsComputerName) { + size_t avLen; + if (!ntlm_av_pair_get_len(AvDnsComputerName, cbAvDnsComputerName, &avLen)) + goto fail; AvPairsCount++; /* MsvAvDnsComputerName */ - AvPairsValueLength += ntlm_av_pair_get_len(AvDnsComputerName); + AvPairsValueLength += avLen; } if (AvDnsTreeName) { + size_t avLen; + if (!ntlm_av_pair_get_len(AvDnsTreeName, cbAvDnsTreeName, &avLen)) + goto fail; AvPairsCount++; /* MsvAvDnsTreeName */ - AvPairsValueLength += ntlm_av_pair_get_len(AvDnsTreeName); + AvPairsValueLength += avLen; } AvPairsCount++; /* MsvAvTimestamp */ From 67ffded1bad8f438904d55799ca012077e206236 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 2 Jun 2020 13:19:26 +0200 Subject: [PATCH 61/65] Removed duplicate semicolon (cherry picked from commit 308c2c3544763873a5bea4d18c72c9f62e1584cb) --- winpr/libwinpr/timezone/timezone.c | 1 - 1 file changed, 1 deletion(-) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index 507763897010..12fcd444ec2b 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -340,7 +340,6 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) { time_t t; struct tm tres; - ; struct tm* local_time; TIME_ZONE_ENTRY* dtz; LPTIME_ZONE_INFORMATION tz = lpTimeZoneInformation; From 813204554db9da5d695f596282cbb9793428446f Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 2 Jun 2020 14:41:37 +0200 Subject: [PATCH 62/65] Fixed fallback to getlogin for android (cherry picked from commit caff01877d4df5f25a983b3aa5e57dde6a16a62f) --- channels/rdpdr/client/rdpdr_main.c | 4 ++++ winpr/libwinpr/sspicli/sspicli.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 32143984009b..98f526d374ac 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -600,8 +600,12 @@ static BOOL isAutomountLocation(const char* path) uid_t uid = getuid(); char uname[MAX_PATH] = { 0 }; +#ifndef getlogin_r + strncpy(uname, getlogin(), sizeof(uname)); +#else if (getlogin_r(uname, sizeof(uname)) != 0) return FALSE; +#endif if (!path) return FALSE; diff --git a/winpr/libwinpr/sspicli/sspicli.c b/winpr/libwinpr/sspicli/sspicli.c index 220f1e1ba8be..671df6e98a31 100644 --- a/winpr/libwinpr/sspicli/sspicli.c +++ b/winpr/libwinpr/sspicli/sspicli.c @@ -206,8 +206,12 @@ BOOL GetUserNameExA(EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG switch (NameFormat) { case NameSamCompatible: +#ifndef getlogin_r + strncpy(login, getlogin(), sizeof(login)); +#else if (getlogin_r(login, sizeof(login)) != 0) return FALSE; +#endif length = strlen(login); if (*nSize >= length) From cb2adc84c0a69997c78709f20e3959b986559a7e Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 15 Jun 2020 08:57:21 +0200 Subject: [PATCH 63/65] Fixed possible integer overflow in crypto_rsa_common Thanks @anticomputer for pointing this out (cherry picked from commit 02c5ec66e5b47fe4cf2fc96e2cd387a18e3f2bb6) --- libfreerdp/crypto/crypto.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 841468339247..29c642ef178d 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -105,11 +105,18 @@ static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, c BIGNUM* exp = NULL; BIGNUM* x = NULL; BIGNUM* y = NULL; - size_t bufferSize = 2 * key_length + exponent_size; + size_t bufferSize; if (!input || (length < 0) || (exponent_size < 0) || !modulus || !exponent || !output) return -1; + if (exponent_size > SIZE_MAX / 2) + return -1; + + if (key_length >= SIZE_MAX / 2 - exponent_size) + return -1; + + bufferSize = 2ULL * key_length + exponent_size; if (length > bufferSize) bufferSize = length; From 96333fd72264e758f5ef4159e243036ebc07f058 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 22 Jun 2020 11:58:07 +0200 Subject: [PATCH 64/65] Added changelog for 2.1.2 (cherry picked from commit 5dc50f64183755862cca75cf151933c42fabbb90) --- ChangeLog | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ChangeLog b/ChangeLog index 593cb89a6d08..1ecea0919d9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +# 2020-06-22 Version 2.1.2 + +Important notes: +* CVE-2020-4033 Out of bound read in RLEDECOMPRESS +* CVE-2020-4031 Use-After-Free in gdi_SelectObject +* CVE-2020-4032 Integer casting vulnerability in `update_recv_secondary_order` +* CVE-2020-4030 OOB read in `TrioParse` +* CVE-2020-11099 OOB Read in license_read_new_or_upgrade_license_packet +* CVE-2020-11098 Out-of-bound read in glyph_cache_put +* CVE-2020-11097 OOB read in ntlm_av_pair_get +* CVE-2020-11095 Global OOB read in update_recv_primary_order +* CVE-2020-11096 Global OOB read in update_read_cache_bitmap_v3_order +* Gateway RPC fixes for windows +* Fixed resource fee race resulting in double free in USB redirection +* Fixed wayland client crashes +* Fixed X11 client mouse mapping issues (X11 mapping on/off) +* Some proxy related improvements (capture module) +* Code cleanup (use getlogin_r, ...) + +For a complete and detailed change log since the last release candidate run: +git log 2.1.1..2.1.2 + + # 2020-05-20 Version 2.1.1 Important notes: From 93bed51ae2eeafa07ea8b0833710653782705d7e Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 22 Jun 2020 12:26:08 +0200 Subject: [PATCH 65/65] Updated versions to 2.1.2 --- CMakeLists.txt | 2 +- client/Android/Studio/build.gradle | 2 +- client/Android/android_freerdp.c | 2 +- winpr/CMakeLists.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d685b9210d9..be4fcbb75db7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ if ($ENV{BUILD_NUMBER}) endif() set(WITH_LIBRARY_VERSIONING "ON") -set(RAW_VERSION_STRING "2.1.1") +set(RAW_VERSION_STRING "2.1.2") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) diff --git a/client/Android/Studio/build.gradle b/client/Android/Studio/build.gradle index 319280d5ed34..01a7ae278ff3 100644 --- a/client/Android/Studio/build.gradle +++ b/client/Android/Studio/build.gradle @@ -29,7 +29,7 @@ def getVersionName = { -> ext { versionName = properties.get('VERSION_NAME', getVersionName()) - versionCode = properties.get('VERSION_CODE', 17) + versionCode = properties.get('VERSION_CODE', 18) println '----------------- Project configuration -------------------' println 'VERSION_NAME: ' + versionName diff --git a/client/Android/android_freerdp.c b/client/Android/android_freerdp.c index 0b0f27b0991d..a9a952017fb6 100644 --- a/client/Android/android_freerdp.c +++ b/client/Android/android_freerdp.c @@ -56,7 +56,7 @@ #define TAG CLIENT_TAG("android") /* Defines the JNI version supported by this library. */ -#define FREERDP_JNI_VERSION "2.1.1" +#define FREERDP_JNI_VERSION "2.1.2" static void android_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e) { diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index a8b66038f907..54a1649f3a34 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -51,7 +51,7 @@ if (NOT WIN32) endif() # Soname versioning -set(RAW_VERSION_STRING "2.1.1") +set(RAW_VERSION_STRING "2.1.2") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG)