summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2024-08-01 15:09:08 +0000
committerCoprDistGit <infra@openeuler.org>2024-08-01 15:09:08 +0000
commit0b1f438f59e230389519ba100f28b896df14e08b (patch)
tree22651934332deb73602326a03ddb24bffa8d18fc
parent5c96aee787beb29707ea3203fcef7f3b3b637153 (diff)
automatic import of freerdpopeneuler24.03_LTSopeneuler23.09
-rw-r--r--.gitignore1
-rw-r--r--Added-function-_wcsncmp.patch62
-rw-r--r--Added-missing-length-check-in-urb_control_transfer.patch29
-rw-r--r--Added-missing-length-checks-in-zgfx_decompress_segme.patch51
-rw-r--r--Ensure-urb_create_iocompletion-uses-size_t-for-calcu.patch32
-rw-r--r--Fix-length-checks-in-parallel-driver.patch37
-rw-r--r--Fixed-7436-Datatype-mismatch-to-crypto_base64_decode.patch25
-rw-r--r--Fixed-7436-Datatype-mismatch.patch34
-rw-r--r--Fixed-division-by-zero-in-urbdrc.patch39
-rw-r--r--Fixed-format-string-for-Stream_CheckAndLogRequiredLe.patch122
-rw-r--r--Fixed-missing-input-buffer-length-check-in-urbdrc.patch58
-rw-r--r--Fixed-missing-length-check-in-video-channel.patch29
-rw-r--r--Fixed-missing-stream-length-check-in-drive_file_quer.patch28
-rw-r--r--Fixed-path-validation-in-drive-channel.patch296
-rw-r--r--Implement-BIO_CTRL_GET_KTLS_SEND-and-BIO_CTRL_GET_KT.patch67
-rw-r--r--freerdp.spec528
-rw-r--r--sources1
-rw-r--r--winpr-crt-Added-wcsstr-implementation.patch66
-rw-r--r--winpr-crt-Fix-wcs-cmp-and-wcs-len-checks.patch90
-rw-r--r--winpr-ssl-Load-legacy-provider-when-initializing-Ope.patch61
20 files changed, 1656 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..9388d5c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/FreeRDP-2.4.1.tar.gz
diff --git a/Added-function-_wcsncmp.patch b/Added-function-_wcsncmp.patch
new file mode 100644
index 0000000..cef8a66
--- /dev/null
+++ b/Added-function-_wcsncmp.patch
@@ -0,0 +1,62 @@
+From e482b394efc371412ce659b731a9b1e1d73bdf0e Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Mon, 24 Oct 2022 10:42:56 +0200
+Subject: [PATCH] Added function _wcsncmp
+
+* Compare WCHAR strings up to n characters
+
+(cherry picked from commit 8178ed26a459356ece17414c6e871a7e0735a4ec)
+---
+ winpr/include/winpr/string.h | 2 ++
+ winpr/libwinpr/crt/string.c | 15 ++++++++++++++-
+ 2 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/winpr/include/winpr/string.h b/winpr/include/winpr/string.h
+index 8ce83bc1d..3b907c444 100644
+--- a/winpr/include/winpr/string.h
++++ b/winpr/include/winpr/string.h
+@@ -57,6 +57,7 @@ extern "C"
+ WINPR_API int _strnicmp(const char* string1, const char* string2, size_t count);
+
+ WINPR_API int _wcscmp(const WCHAR* string1, const WCHAR* string2);
++ WINPR_API int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count);
+
+ WINPR_API size_t _wcslen(const WCHAR* str);
+ WINPR_API size_t _wcsnlen(const WCHAR* str, size_t maxNumberOfElements);
+@@ -70,6 +71,7 @@ extern "C"
+ #else
+
+ #define _wcscmp wcscmp
++#define _wcsncmp wcsncmp
+ #define _wcslen wcslen
+ #define _wcsnlen wcsnlen
+ #define _wcschr wcschr
+diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c
+index 37fcb4b25..c25ffa279 100644
+--- a/winpr/libwinpr/crt/string.c
++++ b/winpr/libwinpr/crt/string.c
+@@ -90,7 +90,20 @@ int _wcscmp(const WCHAR* string1, const WCHAR* string2)
+
+ Data_Read_UINT16(string1, value1);
+ Data_Read_UINT16(string2, value2);
+- return value1 - value2;
++ return (int)value1 - value2;
++}
++
++int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count)
++{
++ for (size_t x = 0; x < count; x++)
++ {
++ const WCHAR a = string1[x];
++ const WCHAR b = string2[x];
++
++ if (a != b)
++ return (int)a - b;
++ }
++ return 0;
+ }
+
+ /* _wcslen -> wcslen */
+--
+2.37.1
+
diff --git a/Added-missing-length-check-in-urb_control_transfer.patch b/Added-missing-length-check-in-urb_control_transfer.patch
new file mode 100644
index 0000000..406161b
--- /dev/null
+++ b/Added-missing-length-check-in-urb_control_transfer.patch
@@ -0,0 +1,29 @@
+From 8c513f127549433c830575202d1551b0e9dd182d Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Thu, 13 Oct 2022 09:00:48 +0200
+Subject: [PATCH] Added missing length check in urb_control_transfer
+
+(cherry picked from commit ce838e2477cb8173ea5e98f35ad55ff41ea5117d)
+---
+ channels/urbdrc/client/data_transfer.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c
+index 9a44e6e09..bb2784055 100644
+--- a/channels/urbdrc/client/data_transfer.c
++++ b/channels/urbdrc/client/data_transfer.c
+@@ -673,7 +673,11 @@ static UINT urb_control_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callba
+ buffer = Stream_Pointer(out);
+
+ if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
++ {
++ if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
++ return ERROR_INVALID_DATA;
+ Stream_Copy(s, out, OutputBufferSize);
++ }
+
+ /** process TS_URB_CONTROL_TRANSFER */
+ if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
+--
+2.37.1
+
diff --git a/Added-missing-length-checks-in-zgfx_decompress_segme.patch b/Added-missing-length-checks-in-zgfx_decompress_segme.patch
new file mode 100644
index 0000000..a478489
--- /dev/null
+++ b/Added-missing-length-checks-in-zgfx_decompress_segme.patch
@@ -0,0 +1,51 @@
+From babbd1e433d273634637f5199429986714864033 Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Thu, 13 Oct 2022 09:09:28 +0200
+Subject: [PATCH] Added missing length checks in zgfx_decompress_segment
+
+(cherry picked from commit 64716b335858109d14f27b51acc4c4d71a92a816)
+---
+ libfreerdp/codec/zgfx.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c
+index 1a2878bd9..04ddeadb2 100644
+--- a/libfreerdp/codec/zgfx.c
++++ b/libfreerdp/codec/zgfx.c
+@@ -230,19 +230,19 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
+ BYTE* pbSegment;
+ size_t cbSegment;
+
+- if (!zgfx || !stream)
++ if (!zgfx || !stream || (segmentSize < 2))
+ return FALSE;
+
+ cbSegment = segmentSize - 1;
+
+- if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize < 1) ||
+- (segmentSize > UINT32_MAX))
++ if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize > UINT32_MAX))
+ return FALSE;
+
+ Stream_Read_UINT8(stream, flags); /* header (1 byte) */
+ zgfx->OutputCount = 0;
+ pbSegment = Stream_Pointer(stream);
+- Stream_Seek(stream, cbSegment);
++ if (!Stream_SafeSeek(stream, cbSegment))
++ return FALSE;
+
+ if (!(flags & PACKET_COMPRESSED))
+ {
+@@ -346,6 +346,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
+ if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount)
+ return FALSE;
+
++ if (count > zgfx->cBitsRemaining / 8)
++ return FALSE;
++
+ CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent,
+ count);
+ zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count);
+--
+2.37.1
+
diff --git a/Ensure-urb_create_iocompletion-uses-size_t-for-calcu.patch b/Ensure-urb_create_iocompletion-uses-size_t-for-calcu.patch
new file mode 100644
index 0000000..7f0efa4
--- /dev/null
+++ b/Ensure-urb_create_iocompletion-uses-size_t-for-calcu.patch
@@ -0,0 +1,32 @@
+From b3a695e9f38a42f1ef0cade0d5e1fe60cf68864e Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Thu, 13 Oct 2022 08:36:26 +0200
+Subject: [PATCH] Ensure urb_create_iocompletion uses size_t for calculation
+
+(cherry picked from commit de7e0f062ee53d00b4a966a43855a716e3478150)
+---
+ channels/urbdrc/client/data_transfer.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c
+index 80e84af48..8642c8506 100644
+--- a/channels/urbdrc/client/data_transfer.c
++++ b/channels/urbdrc/client/data_transfer.c
+@@ -97,7 +97,13 @@ static wStream* urb_create_iocompletion(UINT32 InterfaceField, UINT32 MessageId,
+ UINT32 OutputBufferSize)
+ {
+ const UINT32 InterfaceId = (STREAM_ID_PROXY << 30) | (InterfaceField & 0x3FFFFFFF);
+- wStream* out = Stream_New(NULL, OutputBufferSize + 28);
++
++#if UINT32_MAX >= SIZE_MAX
++ if (OutputBufferSize > UINT32_MAX - 28ull)
++ return NULL;
++#endif
++
++ wStream* out = Stream_New(NULL, OutputBufferSize + 28ull);
+
+ if (!out)
+ return NULL;
+--
+2.37.1
+
diff --git a/Fix-length-checks-in-parallel-driver.patch b/Fix-length-checks-in-parallel-driver.patch
new file mode 100644
index 0000000..cd3c022
--- /dev/null
+++ b/Fix-length-checks-in-parallel-driver.patch
@@ -0,0 +1,37 @@
+From 64544c7f4ed72b3023955ebe6ad3b118ebb8d6c7 Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Thu, 6 Oct 2022 09:12:40 +0200
+Subject: [PATCH] Fix length checks in parallel driver
+
+The length requested was not checked against the length read from
+the port.
+
+(cherry picked from commit 094cc5a4596c299595b732effd59ee149181fd61)
+---
+ channels/parallel/client/parallel_main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c
+index af3e82703..993605a65 100644
+--- a/channels/parallel/client/parallel_main.c
++++ b/channels/parallel/client/parallel_main.c
+@@ -159,7 +159,7 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
+ return ERROR_INVALID_DATA;
+ Stream_Read_UINT32(irp->input, Length);
+ Stream_Read_UINT64(irp->input, Offset);
+- buffer = (BYTE*)malloc(Length);
++ buffer = (BYTE*)calloc(Length, sizeof(BYTE));
+
+ if (!buffer)
+ {
+@@ -178,6 +178,7 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
+ }
+ else
+ {
++ Length = status;
+ }
+
+ Stream_Write_UINT32(irp->output, Length);
+--
+2.37.1
+
diff --git a/Fixed-7436-Datatype-mismatch-to-crypto_base64_decode.patch b/Fixed-7436-Datatype-mismatch-to-crypto_base64_decode.patch
new file mode 100644
index 0000000..3279a28
--- /dev/null
+++ b/Fixed-7436-Datatype-mismatch-to-crypto_base64_decode.patch
@@ -0,0 +1,25 @@
+From 2ddb22f7a453f3429b3246ca8ffa1ff2c31fe71d Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Fri, 12 Nov 2021 11:24:38 +0100
+Subject: [PATCH] Fixed #7436: Datatype mismatch to crypto_base64_decode
+
+---
+ libfreerdp/core/gateway/rdg.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c
+index 72019ede8..44de2c137 100644
+--- a/libfreerdp/core/gateway/rdg.c
++++ b/libfreerdp/core/gateway/rdg.c
+@@ -1190,7 +1190,7 @@ static BOOL rdg_handle_ntlm_challenge(rdpNtlm* ntlm, HttpResponse* response)
+ BOOL continueNeeded = FALSE;
+ size_t len;
+ const char* token64 = NULL;
+- size_t ntlmTokenLength = 0;
++ int ntlmTokenLength = 0;
+ BYTE* ntlmTokenData = NULL;
+ long StatusCode;
+
+--
+2.33.1
+
diff --git a/Fixed-7436-Datatype-mismatch.patch b/Fixed-7436-Datatype-mismatch.patch
new file mode 100644
index 0000000..22c3987
--- /dev/null
+++ b/Fixed-7436-Datatype-mismatch.patch
@@ -0,0 +1,34 @@
+From 403402607214092d20277af3aa959ce87768580a Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Fri, 12 Nov 2021 16:01:39 +0100
+Subject: [PATCH] Fixed #7436: Datatype mismatch
+
+---
+ libfreerdp/core/gateway/ncacn_http.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c
+index f288a0f3c..75da83d62 100644
+--- a/libfreerdp/core/gateway/ncacn_http.c
++++ b/libfreerdp/core/gateway/ncacn_http.c
+@@ -105,7 +105,7 @@ BOOL rpc_ncacn_http_send_in_channel_request(RpcChannel* inChannel)
+ BOOL rpc_ncacn_http_recv_in_channel_response(RpcChannel* inChannel, HttpResponse* response)
+ {
+ const char* token64 = NULL;
+- size_t ntlmTokenLength = 0;
++ int ntlmTokenLength = 0;
+ BYTE* ntlmTokenData = NULL;
+ rdpNtlm* ntlm;
+
+@@ -259,7 +259,7 @@ BOOL rpc_ncacn_http_send_out_channel_request(RpcChannel* outChannel, BOOL replac
+ BOOL rpc_ncacn_http_recv_out_channel_response(RpcChannel* outChannel, HttpResponse* response)
+ {
+ const char* token64 = NULL;
+- size_t ntlmTokenLength = 0;
++ int ntlmTokenLength = 0;
+ BYTE* ntlmTokenData = NULL;
+ rdpNtlm* ntlm;
+
+--
+2.33.1
+
diff --git a/Fixed-division-by-zero-in-urbdrc.patch b/Fixed-division-by-zero-in-urbdrc.patch
new file mode 100644
index 0000000..bc87552
--- /dev/null
+++ b/Fixed-division-by-zero-in-urbdrc.patch
@@ -0,0 +1,39 @@
+From b9c5e3668c4022b34734ac8ccb07dd044d4ff38c Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Thu, 13 Oct 2022 08:27:41 +0200
+Subject: [PATCH] Fixed division by zero in urbdrc
+
+(cherry picked from commit 731f8419d04b481d7160de1f34062d630ed48765)
+---
+ channels/urbdrc/client/libusb/libusb_udevice.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c
+index aa69890ae..5784d9fe2 100644
+--- a/channels/urbdrc/client/libusb/libusb_udevice.c
++++ b/channels/urbdrc/client/libusb/libusb_udevice.c
+@@ -1214,12 +1214,18 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c
+ if (!Buffer)
+ Stream_Seek(user_data->data, (NumberOfPackets * 12));
+
+- iso_packet_size = BufferSize / NumberOfPackets;
+- iso_transfer = libusb_alloc_transfer(NumberOfPackets);
++ if (NumberOfPackets > 0)
++ {
++ iso_packet_size = BufferSize / NumberOfPackets;
++ iso_transfer = libusb_alloc_transfer((int)NumberOfPackets);
++ }
+
+ if (iso_transfer == NULL)
+ {
+- WLog_Print(urbdrc->log, WLOG_ERROR, "Error: libusb_alloc_transfer.");
++ WLog_Print(urbdrc->log, WLOG_ERROR,
++ "Error: libusb_alloc_transfer [NumberOfPackets=%" PRIu32 ", BufferSize=%" PRIu32
++ " ]",
++ NumberOfPackets, BufferSize);
+ async_transfer_user_data_free(user_data);
+ return -1;
+ }
+--
+2.37.1
+
diff --git a/Fixed-format-string-for-Stream_CheckAndLogRequiredLe.patch b/Fixed-format-string-for-Stream_CheckAndLogRequiredLe.patch
new file mode 100644
index 0000000..3cda0db
--- /dev/null
+++ b/Fixed-format-string-for-Stream_CheckAndLogRequiredLe.patch
@@ -0,0 +1,122 @@
+From 6ed2f7d1a379f69cca102e8166d20eb5ed38652b Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Fri, 22 Apr 2022 16:27:21 +0200
+Subject: [PATCH] Fixed format string for Stream_CheckAndLogRequiredLength
+
+__LINE__ requires %d and not %PRIuz
+
+(cherry picked from commit 74c1a006e940308b0653427d25a87ea5a24cb573)
+---
+ winpr/include/winpr/stream.h | 14 ++++++++
+ winpr/libwinpr/utils/stream.c | 65 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 79 insertions(+)
+
+diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h
+index f351eaa15..ed637f034 100644
+--- a/winpr/include/winpr/stream.h
++++ b/winpr/include/winpr/stream.h
+@@ -27,6 +27,8 @@
+ #include <winpr/wtypes.h>
+ #include <winpr/endian.h>
+ #include <winpr/synch.h>
++#include <winpr/wlog.h>
++#include <winpr/debug.h>
+
+ #ifdef __cplusplus
+ extern "C"
+@@ -56,6 +57,19 @@ extern "C"
+ WINPR_API void Stream_StaticInit(wStream* s, BYTE* buffer, size_t size);
+ WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer);
+
++#define Stream_CheckAndLogRequiredLength(tag, s, len) \
++ Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, len, "%s(%s:%d)", __FUNCTION__, \
++ __FILE__, __LINE__)
++ WINPR_API BOOL Stream_CheckAndLogRequiredLengthEx(const char* tag, DWORD level, wStream* s,
++ UINT64 len, const char* fmt, ...);
++ WINPR_API BOOL Stream_CheckAndLogRequiredLengthExVa(const char* tag, DWORD level, wStream* s,
++ UINT64 len, const char* fmt, va_list args);
++ WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s,
++ UINT64 len, const char* fmt, ...);
++ WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s,
++ UINT64 len, const char* fmt,
++ va_list args);
++
+ static INLINE void Stream_Seek(wStream* s, size_t _offset)
+ {
+ s->pointer += (_offset);
+diff --git a/winpr/libwinpr/utils/stream.c b/winpr/libwinpr/utils/stream.c
+index 1271981b7..cc119c771 100644
+--- a/winpr/libwinpr/utils/stream.c
++++ b/winpr/libwinpr/utils/stream.c
+@@ -132,3 +132,68 @@ void Stream_Free(wStream* s, BOOL bFreeBuffer)
+ free(s);
+ }
+ }
++
++BOOL Stream_CheckAndLogRequiredLengthEx(const char* tag, DWORD level, wStream* s, UINT64 len,
++ const char* fmt, ...)
++{
++ const size_t actual = Stream_GetRemainingLength(s);
++
++ if (actual < len)
++ {
++ va_list args;
++
++ va_start(args, fmt);
++ Stream_CheckAndLogRequiredLengthExVa(tag, level, s, len, fmt, args);
++ va_end(args);
++
++ return FALSE;
++ }
++ return TRUE;
++}
++
++BOOL Stream_CheckAndLogRequiredLengthExVa(const char* tag, DWORD level, wStream* s, UINT64 len,
++ const char* fmt, va_list args)
++{
++ const size_t actual = Stream_GetRemainingLength(s);
++
++ if (actual < len)
++ return Stream_CheckAndLogRequiredLengthWLogExVa(WLog_Get(tag), level, s, len, fmt, args);
++ return TRUE;
++}
++
++BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s, UINT64 len,
++ const char* fmt, ...)
++{
++ const size_t actual = Stream_GetRemainingLength(s);
++
++ if (actual < len)
++ {
++ va_list args;
++
++ va_start(args, fmt);
++ Stream_CheckAndLogRequiredLengthWLogExVa(log, level, s, len, fmt, args);
++ va_end(args);
++
++ return FALSE;
++ }
++ return TRUE;
++}
++
++BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s, UINT64 len,
++ const char* fmt, va_list args)
++{
++ const size_t actual = Stream_GetRemainingLength(s);
++
++ if (actual < len)
++ {
++ char prefix[1024] = { 0 };
++
++ vsnprintf(prefix, sizeof(prefix), fmt, args);
++
++ WLog_Print(log, level, "[%s] invalid length, got %" PRIuz ", require at least %" PRIu64,
++ prefix, actual, len);
++ winpr_log_backtrace_ex(log, level, 20);
++ return FALSE;
++ }
++ return TRUE;
++}
+--
+2.38.1
+
diff --git a/Fixed-missing-input-buffer-length-check-in-urbdrc.patch b/Fixed-missing-input-buffer-length-check-in-urbdrc.patch
new file mode 100644
index 0000000..ea85996
--- /dev/null
+++ b/Fixed-missing-input-buffer-length-check-in-urbdrc.patch
@@ -0,0 +1,58 @@
+From ddf9b3f852c31311f8d726012131f657c9857276 Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Thu, 13 Oct 2022 08:47:51 +0200
+Subject: [PATCH] Fixed missing input buffer length check in urbdrc
+
+(cherry picked from commit 497df00f741dd4fc89292aaef2db7368aee45d0d)
+---
+ channels/urbdrc/client/data_transfer.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c
+index bb2784055..80e84af48 100644
+--- a/channels/urbdrc/client/data_transfer.c
++++ b/channels/urbdrc/client/data_transfer.c
+@@ -241,6 +241,10 @@ static UINT urbdrc_process_io_control(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* c
+
+ Stream_Read_UINT32(s, OutputBufferSize);
+ Stream_Read_UINT32(s, RequestId);
++
++ if (OutputBufferSize > UINT32_MAX - 4)
++ return ERROR_INVALID_DATA;
++
+ InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
+ out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
+
+@@ -724,6 +728,15 @@ static UINT urb_bulk_or_interrupt_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBA
+ Stream_Read_UINT32(s, TransferFlags); /** TransferFlags */
+ Stream_Read_UINT32(s, OutputBufferSize);
+ EndpointAddress = (PipeHandle & 0x000000ff);
++
++ if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
++ {
++ if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
++ {
++ return ERROR_INVALID_DATA;
++ }
++ }
++
+ /** process TS_URB_BULK_OR_INTERRUPT_TRANSFER */
+ return pdev->bulk_or_interrupt_transfer(
+ pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
+@@ -808,6 +821,13 @@ static UINT urb_isoch_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callback
+ packetDescriptorData = Stream_Pointer(s);
+ Stream_Seek(s, NumberOfPackets * 12);
+ Stream_Read_UINT32(s, OutputBufferSize);
++
++ if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
++ {
++ if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
++ return ERROR_INVALID_DATA;
++ }
++
+ return pdev->isoch_transfer(
+ pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
+ ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
+--
+2.37.1
+
diff --git a/Fixed-missing-length-check-in-video-channel.patch b/Fixed-missing-length-check-in-video-channel.patch
new file mode 100644
index 0000000..3ba3d3d
--- /dev/null
+++ b/Fixed-missing-length-check-in-video-channel.patch
@@ -0,0 +1,29 @@
+From bf28ea249de57acc6dfadbd778afef2093c1c283 Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Thu, 6 Oct 2022 09:15:40 +0200
+Subject: [PATCH] Fixed missing length check in video channel
+
+Data received in video redirection channel was not checked for
+proper length.
+
+(cherry picked from commit eeffd1050e9284d1464b58e049b2b4d88726632b)
+---
+ channels/video/client/video_main.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/channels/video/client/video_main.c b/channels/video/client/video_main.c
+index a21e7cdf2..a8031fc86 100644
+--- a/channels/video/client/video_main.c
++++ b/channels/video/client/video_main.c
+@@ -930,6 +930,8 @@ static UINT video_data_on_data_received(IWTSVirtualChannelCallback* pChannelCall
+ Stream_Read_UINT16(s, data.PacketsInSample);
+ Stream_Read_UINT32(s, data.SampleNumber);
+ Stream_Read_UINT32(s, data.cbSample);
++ if (!Stream_CheckAndLogRequiredLength(TAG, s, data.cbSample))
++ return ERROR_INVALID_DATA;
+ data.pSample = Stream_Pointer(s);
+
+ /*
+--
+2.37.1
+
diff --git a/Fixed-missing-stream-length-check-in-drive_file_quer.patch b/Fixed-missing-stream-length-check-in-drive_file_quer.patch
new file mode 100644
index 0000000..0c31cf5
--- /dev/null
+++ b/Fixed-missing-stream-length-check-in-drive_file_quer.patch
@@ -0,0 +1,28 @@
+From 80b2483373c00baec3a26b1d82027f16dfdd8859 Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Mon, 24 Oct 2022 08:45:05 +0200
+Subject: [PATCH] Fixed missing stream length check in
+ drive_file_query_directory
+
+(cherry picked from commit 4e4bb79795d6ac85473fb7a83e53ccf63d204b93)
+---
+ channels/drive/client/drive_main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c
+index d3776381c..b6cf2ad32 100644
+--- a/channels/drive/client/drive_main.c
++++ b/channels/drive/client/drive_main.c
+@@ -629,6 +629,9 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
+ Stream_Read_UINT32(irp->input, PathLength);
+ Stream_Seek(irp->input, 23); /* Padding */
+ path = (WCHAR*)Stream_Pointer(irp->input);
++ if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
++ return ERROR_INVALID_DATA;
++
+ file = drive_get_file_by_id(drive, irp->FileId);
+
+ if (file == NULL)
+--
+2.37.1
+
diff --git a/Fixed-path-validation-in-drive-channel.patch b/Fixed-path-validation-in-drive-channel.patch
new file mode 100644
index 0000000..e4567f2
--- /dev/null
+++ b/Fixed-path-validation-in-drive-channel.patch
@@ -0,0 +1,296 @@
+From 865ba07a0fd4fbc7a8203482411aacca3bbfbb9f Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Mon, 24 Oct 2022 10:41:55 +0200
+Subject: [PATCH] Fixed path validation in drive channel
+
+Check that canonical path is a subpath of the shared directory
+
+(cherry picked from commit 844c94e6d0438fa7bd8ff8d5513c3f69c3018b85)
+---
+ channels/drive/client/drive_file.c | 106 ++++++++++++++++++-----------
+ channels/drive/client/drive_file.h | 8 +--
+ channels/drive/client/drive_main.c | 8 +--
+ 3 files changed, 73 insertions(+), 49 deletions(-)
+
+diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c
+index 305438593..1ea4ab9da 100644
+--- a/channels/drive/client/drive_file.c
++++ b/channels/drive/client/drive_file.c
+@@ -34,6 +34,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <time.h>
++#include <assert.h>
+
+ #include <winpr/wtypes.h>
+ #include <winpr/crt.h>
+@@ -61,10 +62,14 @@
+ } while (0)
+ #endif
+
+-static void drive_file_fix_path(WCHAR* path)
++static BOOL drive_file_fix_path(WCHAR* path, size_t length)
+ {
+ size_t i;
+- size_t length = _wcslen(path);
++
++ if ((length == 0) || (length > UINT32_MAX))
++ return FALSE;
++
++ assert(path);
+
+ for (i = 0; i < length; i++)
+ {
+@@ -75,58 +79,82 @@ static void drive_file_fix_path(WCHAR* path)
+ #ifdef WIN32
+
+ if ((length == 3) && (path[1] == L':') && (path[2] == L'/'))
+- return;
++ return FALSE;
+
+ #else
+
+ if ((length == 1) && (path[0] == L'/'))
+- return;
++ return FALSE;
+
+ #endif
+
+ if ((length > 0) && (path[length - 1] == L'/'))
+ path[length - 1] = L'\0';
++
++ return TRUE;
+ }
+
+ static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* path,
+- size_t PathLength)
++ size_t PathWCharLength)
+ {
+- WCHAR* fullpath;
+- size_t base_path_length;
++ BOOL ok = FALSE;
++ WCHAR* fullpath = NULL;
++ size_t length;
+
+- if (!base_path || (!path && (PathLength > 0)))
+- return NULL;
++ if (!base_path || (!path && (PathWCharLength > 0)))
++ goto fail;
+
+- base_path_length = _wcslen(base_path) * 2;
+- fullpath = (WCHAR*)calloc(1, base_path_length + PathLength + sizeof(WCHAR));
++ const size_t base_path_length = _wcsnlen(base_path, MAX_PATH);
++ length = base_path_length + PathWCharLength + 1;
++ fullpath = (WCHAR*)calloc(length, sizeof(WCHAR));
+
+ if (!fullpath)
++ goto fail;
++
++ CopyMemory(fullpath, base_path, base_path_length * sizeof(WCHAR));
++ if (path)
++ CopyMemory(&fullpath[base_path_length], path, PathWCharLength * sizeof(WCHAR));
++
++ if (!drive_file_fix_path(fullpath, length))
++ goto fail;
++
++ /* Ensure the path does not contain sequences like '..' */
++ const WCHAR dotdot[] = { '.', '.', '\0' };
++ if (_wcsstr(&fullpath[base_path_length], dotdot))
+ {
+- WLog_ERR(TAG, "malloc failed!");
+- return NULL;
++ char abuffer[MAX_PATH] = { 0 };
++ ConvertFromUnicode(CP_UTF8, 0, &fullpath[base_path_length], -1, (char**)&abuffer,
++ ARRAYSIZE(abuffer) - 1, NULL, NULL);
++
++ WLog_WARN(TAG, "[rdpdr] received invalid file path '%s' from server, aborting!",
++ &abuffer[base_path_length]);
++ goto fail;
+ }
+
+- CopyMemory(fullpath, base_path, base_path_length);
+- if (path)
+- CopyMemory((char*)fullpath + base_path_length, path, PathLength);
+- drive_file_fix_path(fullpath);
++ ok = TRUE;
++fail:
++ if (!ok)
++ {
++ free(fullpath);
++ fullpath = NULL;
++ }
+ return fullpath;
+ }
+
+ static BOOL drive_file_remove_dir(const WCHAR* path)
+ {
+- WIN32_FIND_DATAW findFileData;
++ WIN32_FIND_DATAW findFileData = { 0 };
+ BOOL ret = TRUE;
+- HANDLE dir;
+- WCHAR* fullpath;
+- WCHAR* path_slash;
+- size_t base_path_length;
++ HANDLE dir = INVALID_HANDLE_VALUE;
++ WCHAR* fullpath = NULL;
++ WCHAR* path_slash = NULL;
++ size_t base_path_length = 0;
+
+ if (!path)
+ return FALSE;
+
+- base_path_length = _wcslen(path) * 2;
+- path_slash = (WCHAR*)calloc(1, base_path_length + sizeof(WCHAR) * 3);
++ base_path_length = _wcslen(path);
++ path_slash = (WCHAR*)calloc(base_path_length + 3, sizeof(WCHAR));
+
+ if (!path_slash)
+ {
+@@ -134,12 +162,11 @@ static BOOL drive_file_remove_dir(const WCHAR* path)
+ return FALSE;
+ }
+
+- CopyMemory(path_slash, path, base_path_length);
+- path_slash[base_path_length / 2] = L'/';
+- path_slash[base_path_length / 2 + 1] = L'*';
++ CopyMemory(path_slash, path, base_path_length * sizeof(WCHAR));
++ path_slash[base_path_length] = L'/';
++ path_slash[base_path_length + 1] = L'*';
+ DEBUG_WSTR("Search in %s", path_slash);
+ dir = FindFirstFileW(path_slash, &findFileData);
+- path_slash[base_path_length / 2 + 1] = 0;
+
+ if (dir == INVALID_HANDLE_VALUE)
+ {
+@@ -149,7 +176,7 @@ static BOOL drive_file_remove_dir(const WCHAR* path)
+
+ do
+ {
+- size_t len = _wcslen(findFileData.cFileName);
++ const size_t len = _wcsnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName));
+
+ if ((len == 1 && findFileData.cFileName[0] == L'.') ||
+ (len == 2 && findFileData.cFileName[0] == L'.' && findFileData.cFileName[1] == L'.'))
+@@ -157,7 +184,7 @@ static BOOL drive_file_remove_dir(const WCHAR* path)
+ continue;
+ }
+
+- fullpath = drive_file_combine_fullpath(path_slash, findFileData.cFileName, len * 2);
++ fullpath = drive_file_combine_fullpath(path_slash, findFileData.cFileName, len);
+ DEBUG_WSTR("Delete %s", fullpath);
+
+ if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+@@ -333,13 +360,13 @@ static BOOL drive_file_init(DRIVE_FILE* file)
+ return file->file_handle != INVALID_HANDLE_VALUE;
+ }
+
+-DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id,
+- UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions,
+- UINT32 FileAttributes, UINT32 SharedAccess)
++DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathWCharLength,
++ UINT32 id, UINT32 DesiredAccess, UINT32 CreateDisposition,
++ UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess)
+ {
+ DRIVE_FILE* file;
+
+- if (!base_path || (!path && (PathLength > 0)))
++ if (!base_path || (!path && (PathWCharLength > 0)))
+ return NULL;
+
+ file = (DRIVE_FILE*)calloc(1, sizeof(DRIVE_FILE));
+@@ -359,7 +386,7 @@ DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 Pat
+ file->CreateDisposition = CreateDisposition;
+ file->CreateOptions = CreateOptions;
+ file->SharedAccess = SharedAccess;
+- drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path, PathLength));
++ drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path, PathWCharLength));
+
+ if (!drive_file_init(file))
+ {
+@@ -714,13 +741,10 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
+ return FALSE;
+
+ fullpath = drive_file_combine_fullpath(file->basepath, (WCHAR*)Stream_Pointer(input),
+- FileNameLength);
++ FileNameLength / sizeof(WCHAR));
+
+ if (!fullpath)
+- {
+- WLog_ERR(TAG, "drive_file_combine_fullpath failed!");
+ return FALSE;
+- }
+
+ #ifdef _WIN32
+
+@@ -759,7 +783,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
+ }
+
+ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
+- const WCHAR* path, UINT32 PathLength, wStream* output)
++ const WCHAR* path, UINT32 PathWCharLength, wStream* output)
+ {
+ size_t length;
+ WCHAR* ent_path;
+@@ -773,7 +797,7 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
+ if (file->find_handle != INVALID_HANDLE_VALUE)
+ FindClose(file->find_handle);
+
+- ent_path = drive_file_combine_fullpath(file->basepath, path, PathLength);
++ ent_path = drive_file_combine_fullpath(file->basepath, path, PathWCharLength);
+ /* open new search handle and retrieve the first entry */
+ file->find_handle = FindFirstFileW(ent_path, &file->find_data);
+ free(ent_path);
+diff --git a/channels/drive/client/drive_file.h b/channels/drive/client/drive_file.h
+index ed789d6f0..6d3bd7045 100644
+--- a/channels/drive/client/drive_file.h
++++ b/channels/drive/client/drive_file.h
+@@ -51,9 +51,9 @@ struct _DRIVE_FILE
+ UINT32 CreateOptions;
+ };
+
+-DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id,
+- UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions,
+- UINT32 FileAttributes, UINT32 SharedAccess);
++DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathWCharLength,
++ UINT32 id, UINT32 DesiredAccess, UINT32 CreateDisposition,
++ UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess);
+ BOOL drive_file_free(DRIVE_FILE* file);
+
+ BOOL drive_file_open(DRIVE_FILE* file);
+@@ -64,6 +64,6 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w
+ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length,
+ wStream* input);
+ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
+- const WCHAR* path, UINT32 PathLength, wStream* output);
++ const WCHAR* path, UINT32 PathWCharLength, wStream* output);
+
+ #endif /* FREERDP_CHANNEL_DRIVE_FILE_H */
+diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c
+index 1b5422522..d3776381c 100644
+--- a/channels/drive/client/drive_main.c
++++ b/channels/drive/client/drive_main.c
+@@ -184,8 +184,8 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
+
+ path = (const WCHAR*)Stream_Pointer(irp->input);
+ FileId = irp->devman->id_sequence++;
+- file = drive_file_new(drive->path, path, PathLength, FileId, DesiredAccess, CreateDisposition,
+- CreateOptions, FileAttributes, SharedAccess);
++ file = drive_file_new(drive->path, path, PathLength / sizeof(WCHAR), FileId, DesiredAccess,
++ CreateDisposition, CreateOptions, FileAttributes, SharedAccess);
+
+ if (!file)
+ {
+@@ -636,8 +636,8 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
+ irp->IoStatus = STATUS_UNSUCCESSFUL;
+ Stream_Write_UINT32(irp->output, 0); /* Length */
+ }
+- else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path, PathLength,
+- irp->output))
++ else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path,
++ PathLength / sizeof(WCHAR), irp->output))
+ {
+ irp->IoStatus = drive_map_windows_err(GetLastError());
+ }
+--
+2.37.1
+
diff --git a/Implement-BIO_CTRL_GET_KTLS_SEND-and-BIO_CTRL_GET_KT.patch b/Implement-BIO_CTRL_GET_KTLS_SEND-and-BIO_CTRL_GET_KT.patch
new file mode 100644
index 0000000..ec9391b
--- /dev/null
+++ b/Implement-BIO_CTRL_GET_KTLS_SEND-and-BIO_CTRL_GET_KT.patch
@@ -0,0 +1,67 @@
+From 1a0f68d2058f361fc23ed9babcd618a838744bf8 Mon Sep 17 00:00:00 2001
+From: akarl <mike@mwsys.mine.bz>
+Date: Sun, 24 Apr 2022 21:16:52 +0200
+Subject: [PATCH] Implement BIO_CTRL_GET_KTLS_SEND and BIO_CTRL_GET_KTLS_SEND
+
+Openssl 3.0 requires to respond to this controls. According to there
+documentation it should not need them, but in practice openssl's own source
+is full of places where negative return values are not checked.
+
+(cherry picked from commit 9d7c20ce8fe50bd6de54e7480b5096761a510daf)
+---
+ libfreerdp/core/gateway/rdg.c | 18 +++++++++++++++++-
+ libfreerdp/core/gateway/tsg.c | 9 ++++++++-
+ 2 files changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c
+index 72019ede8..5d970f39e 100644
+--- a/libfreerdp/core/gateway/rdg.c
++++ b/libfreerdp/core/gateway/rdg.c
+@@ -2483,7 +2483,23 @@ static long rdg_bio_ctrl(BIO* in_bio, int cmd, long arg1, void* arg2)
+ */
+ status = BIO_ctrl(tlsOut->bio, cmd, arg1, arg2);
+ }
+-
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++ else if (cmd == BIO_CTRL_GET_KTLS_SEND)
++ {
++ /* Even though BIO_get_ktls_send says that returning negative values is valid
++ * openssl internal sources are full of if(!BIO_get_ktls_send && ) stuff. This has some
++ * nasty sideeffects. return 0 as proper no KTLS offloading flag
++ */
++ status = 0;
++ }
++ else if (cmd == BIO_CTRL_GET_KTLS_RECV)
++ {
++ /* Even though BIO_get_ktls_recv says that returning negative values is valid
++ * there is no reason to trust trust negative values are implemented right everywhere
++ */
++ status = 0;
++ }
++#endif
+ return status;
+ }
+
+diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c
+index c03f266f2..70fdf9e27 100644
+--- a/libfreerdp/core/gateway/tsg.c
++++ b/libfreerdp/core/gateway/tsg.c
+@@ -2716,7 +2716,14 @@ static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
+ status = 1;
+ }
+ break;
+-
++#if OPENSSL_VERSION_NUMBER >= 0x30000000L
++ case BIO_CTRL_GET_KTLS_SEND:
++ status = 0;
++ break;
++ case BIO_CTRL_GET_KTLS_RECV:
++ status = 0;
++ break;
++#endif
+ default:
+ break;
+ }
+--
+2.36.1
+
diff --git a/freerdp.spec b/freerdp.spec
new file mode 100644
index 0000000..feadb04
--- /dev/null
+++ b/freerdp.spec
@@ -0,0 +1,528 @@
+# Can be rebuilt with FFmpeg/H264 support enabled by passing "--with=ffmpeg",
+# "--with=x264" or "--with=openh264" to mock/rpmbuild; or by globally setting
+# these variables:
+
+#global _with_ffmpeg 1
+#global _with_x264 1
+#global _with_openh264 1
+
+# Momentarily disable GSS support
+# https://github.com/FreeRDP/FreeRDP/issues/4348
+#global _with_gss 1
+
+# Disable server support in RHEL
+# https://bugzilla.redhat.com/show_bug.cgi?id=1639165
+%{!?rhel:%global _with_server 1}
+
+# Disable support for missing codecs in RHEL
+%{!?rhel:%global _with_soxr 1}
+%if 0%{?fedora} || 0%{?rhel} >= 8
+%global _with_lame 1
+%endif
+
+Name: freerdp
+Version: 2.4.1
+Release: 5%{?dist}
+Epoch: 2
+Summary: Free implementation of the Remote Desktop Protocol (RDP)
+License: ASL 2.0
+URL: http://www.freerdp.com/
+
+Source0: https://github.com/FreeRDP/FreeRDP/archive/%{version}/FreeRDP-%{version}.tar.gz
+
+# https://github.com/FreeRDP/FreeRDP/issues/7436
+Patch0: Fixed-7436-Datatype-mismatch-to-crypto_base64_decode.patch
+Patch1: Fixed-7436-Datatype-mismatch.patch
+
+# https://github.com/FreeRDP/FreeRDP/pull/7448
+Patch2: winpr-ssl-Load-legacy-provider-when-initializing-Ope.patch
+
+# https://bugzilla.redhat.com/show_bug.cgi?id=2023262
+Patch3: Implement-BIO_CTRL_GET_KTLS_SEND-and-BIO_CTRL_GET_KT.patch
+
+# https://bugzilla.redhat.com/show_bug.cgi?id=2136152
+Patch4: Fix-length-checks-in-parallel-driver.patch
+
+# https://bugzilla.redhat.com/show_bug.cgi?id=2136154
+Patch5: Fixed-missing-length-check-in-video-channel.patch
+
+# https://bugzilla.redhat.com/show_bug.cgi?id=2145140
+Patch6: Added-missing-length-checks-in-zgfx_decompress_segme.patch
+Patch7: Fixed-division-by-zero-in-urbdrc.patch
+Patch8: Added-missing-length-check-in-urb_control_transfer.patch
+Patch9: Fixed-missing-input-buffer-length-check-in-urbdrc.patch
+Patch10: Ensure-urb_create_iocompletion-uses-size_t-for-calcu.patch
+Patch11: Added-function-_wcsncmp.patch
+Patch12: winpr-crt-Fix-wcs-cmp-and-wcs-len-checks.patch
+Patch13: winpr-crt-Added-wcsstr-implementation.patch
+Patch14: Fixed-path-validation-in-drive-channel.patch
+Patch15: Fixed-missing-stream-length-check-in-drive_file_quer.patch
+Patch16: Fixed-format-string-for-Stream_CheckAndLogRequiredLe.patch
+
+BuildRequires: gcc
+BuildRequires: gcc-c++
+BuildRequires: alsa-lib-devel
+BuildRequires: cmake >= 2.8
+BuildRequires: cups-devel
+BuildRequires: gsm-devel
+%{?_with_lame:BuildRequires: lame-devel}
+BuildRequires: libicu-devel
+BuildRequires: libjpeg-turbo-devel
+BuildRequires: libX11-devel
+BuildRequires: libXcursor-devel
+BuildRequires: libXdamage-devel
+BuildRequires: libXext-devel
+BuildRequires: libXi-devel
+BuildRequires: libXinerama-devel
+BuildRequires: libxkbfile-devel
+BuildRequires: libXrandr-devel
+%{?_with_server:BuildRequires: libXtst-devel}
+BuildRequires: libXv-devel
+%{?_with_openh264:BuildRequires: openh264-devel}
+%{?_with_x264:BuildRequires: x264-devel}
+%{?_with_server:BuildRequires: pam-devel}
+BuildRequires: xmlto
+BuildRequires: zlib-devel
+BuildRequires: multilib-rpm-config
+
+BuildRequires: pkgconfig(cairo)
+BuildRequires: pkgconfig(dbus-1)
+BuildRequires: pkgconfig(dbus-glib-1)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gstreamer-1.0)
+BuildRequires: pkgconfig(gstreamer-base-1.0)
+BuildRequires: pkgconfig(gstreamer-app-1.0)
+BuildRequires: pkgconfig(gstreamer-audio-1.0)
+BuildRequires: pkgconfig(gstreamer-fft-1.0)
+BuildRequires: pkgconfig(gstreamer-pbutils-1.0)
+BuildRequires: pkgconfig(gstreamer-video-1.0)
+%{?_with_gss:BuildRequires: pkgconfig(krb5) >= 1.13}
+BuildRequires: pkgconfig(libpcsclite)
+BuildRequires: pkgconfig(libpulse)
+BuildRequires: pkgconfig(libsystemd)
+BuildRequires: pkgconfig(libusb-1.0)
+BuildRequires: pkgconfig(openssl)
+%{?_with_soxr:BuildRequires: pkgconfig(soxr)}
+BuildRequires: pkgconfig(wayland-client)
+BuildRequires: pkgconfig(wayland-scanner)
+BuildRequires: pkgconfig(xkbcommon)
+
+%{?_with_ffmpeg:
+BuildRequires: pkgconfig(libavcodec) >= 57.48.101
+BuildRequires: pkgconfig(libavutil)
+}
+
+Provides: xfreerdp = %{?epoch}:%{version}-%{release}
+Requires: %{name}-libs%{?_isa} = %{?epoch}:%{version}-%{release}
+Requires: libwinpr%{?_isa} = %{?epoch}:%{version}-%{release}
+
+%description
+The xfreerdp & wlfreerdp Remote Desktop Protocol (RDP) clients from the FreeRDP
+project.
+
+xfreerdp & wlfreerdp can connect to RDP servers such as Microsoft Windows
+machines, xrdp and VirtualBox.
+
+%package libs
+Summary: Core libraries implementing the RDP protocol
+Requires: libwinpr%{?_isa} = %{?epoch}:%{version}-%{release}
+Obsoletes: %{name}-plugins < 1:1.1.0
+Provides: %{name}-plugins = %{?epoch}:%{version}-%{release}
+%description libs
+libfreerdp-core can be embedded in applications.
+
+libfreerdp-channels and libfreerdp-kbd might be convenient to use in X
+applications together with libfreerdp-core.
+
+libfreerdp-core can be extended with plugins handling RDP channels.
+
+%package devel
+Summary: Development files for %{name}
+Requires: %{name}-libs%{?_isa} = %{?epoch}:%{version}-%{release}
+Requires: pkgconfig
+Requires: cmake >= 2.8
+
+%description devel
+The %{name}-devel package contains libraries and header files for developing
+applications that use %{name}-libs.
+
+%{?_with_server:
+%package server
+Summary: Server support for %{name}
+Requires: libwinpr%{?_isa} = %{?epoch}:%{version}-%{release}
+Requires: %{name}-libs%{?_isa} = %{?epoch}:%{version}-%{release}
+
+%description server
+The %{name}-server package contains servers which can export a desktop via
+the RDP protocol.
+}
+
+%package -n libwinpr
+Summary: Windows Portable Runtime
+Provides: %{name}-libwinpr = %{?epoch}:%{version}-%{release}
+Obsoletes: %{name}-libwinpr < 1:1.2.0
+
+%description -n libwinpr
+WinPR provides API compatibility for applications targeting non-Windows
+environments. When on Windows, the original native API is being used instead of
+the equivalent WinPR implementation, without having to modify the code using it.
+
+%package -n libwinpr-devel
+Summary: Windows Portable Runtime development files
+Requires: libwinpr%{?_isa} = %{?epoch}:%{version}-%{release}
+Requires: pkgconfig
+Requires: cmake >= 2.8
+
+%description -n libwinpr-devel
+The %{name}-libwinpr-devel package contains libraries and header files for
+developing applications that use %{name}-libwinpr.
+
+%prep
+%autosetup -p1 -n FreeRDP-%{version}
+
+# Rpmlint fixes
+find . -name "*.h" -exec chmod 664 {} \;
+find . -name "*.c" -exec chmod 664 {} \;
+
+%build
+%cmake %{?_cmake_skip_rpath} \
+ -DCMAKE_INSTALL_LIBDIR:PATH=%{_lib} \
+ -DWITH_ALSA=ON \
+ -DWITH_CAIRO=ON \
+ -DWITH_CUPS=ON \
+ -DWITH_CHANNELS=ON -DBUILTIN_CHANNELS=OFF \
+ -DWITH_CLIENT=ON \
+ -DWITH_DIRECTFB=OFF \
+ -DWITH_FFMPEG=%{?_with_ffmpeg:ON}%{?!_with_ffmpeg:OFF} \
+ -DWITH_GSM=ON \
+ -DWITH_GSSAPI=%{?_with_gss:ON}%{?!_with_gss:OFF} \
+ -DWITH_GSTREAMER_1_0=ON -DWITH_GSTREAMER_0_10=OFF \
+ -DWITH_ICU=ON \
+ -DWITH_IPP=OFF \
+ -DWITH_JPEG=ON \
+ -DWITH_LAME=%{?_with_lame:ON}%{?!_with_lame:OFF} \
+ -DWITH_MANPAGES=ON \
+ -DWITH_OPENH264=%{?_with_openh264:ON}%{?!_with_openh264:OFF} \
+ -DWITH_OPENSSL=ON \
+ -DWITH_PCSC=ON \
+ -DWITH_PULSE=ON \
+ -DWITH_SERVER=%{?_with_server:ON}%{?!_with_server:OFF} \
+ -DWITH_SERVER_INTERFACE=%{?_with_server:ON}%{?!_with_server:OFF} \
+ -DWITH_SHADOW_X11=%{?_with_server:ON}%{?!_with_server:OFF} \
+ -DWITH_SHADOW_MAC=%{?_with_server:ON}%{?!_with_server:OFF} \
+ -DWITH_SOXR=%{?_with_soxr:ON}%{?!_with_soxr:OFF} \
+ -DWITH_WAYLAND=ON \
+ -DWITH_X11=ON \
+ -DWITH_X264=%{?_with_x264:ON}%{?!_with_x264:OFF} \
+ -DWITH_XCURSOR=ON \
+ -DWITH_XEXT=ON \
+ -DWITH_XKBFILE=ON \
+ -DWITH_XI=ON \
+ -DWITH_XINERAMA=ON \
+ -DWITH_XRENDER=ON \
+ -DWITH_XTEST=%{?_with_server:ON}%{?!_with_server:OFF} \
+ -DWITH_XV=ON \
+ -DWITH_ZLIB=ON \
+%ifarch x86_64
+ -DWITH_SSE2=ON \
+ -DWITH_VAAPI=%{?_with_ffmpeg:ON}%{?!_with_ffmpeg:OFF} \
+%else
+ -DWITH_SSE2=OFF \
+%endif
+%ifarch armv7hl
+ -DARM_FP_ABI=hard \
+ -DWITH_NEON=OFF \
+%endif
+%ifarch armv7hnl
+ -DARM_FP_ABI=hard \
+ -DWITH_NEON=ON \
+%endif
+%ifarch armv5tel armv6l armv7l
+ -DARM_FP_ABI=soft \
+ -DWITH_NEON=OFF \
+%endif
+ .
+
+%cmake_build
+
+%install
+%cmake_install
+
+find %{buildroot} -name "*.a" -delete
+
+%multilib_fix_c_header --file %{_includedir}/freerdp2/freerdp/build-config.h
+
+%files
+%{_bindir}/winpr-hash
+%{_bindir}/winpr-makecert
+%{_bindir}/wlfreerdp
+%{_bindir}/xfreerdp
+%{_mandir}/man1/winpr-hash.1*
+%{_mandir}/man1/winpr-makecert.1*
+%{_mandir}/man1/wlfreerdp.1*
+%{_mandir}/man1/xfreerdp.1*
+
+%files libs
+%license LICENSE
+%doc README.md ChangeLog
+%{_libdir}/freerdp2/
+%{_libdir}/libfreerdp-client2.so.*
+%{?_with_server:
+%{_libdir}/libfreerdp-server2.so.*
+%{_libdir}/libfreerdp-shadow2.so.*
+%{_libdir}/libfreerdp-shadow-subsystem2.so.*
+}
+%{_libdir}/libfreerdp2.so.*
+%{_libdir}/libuwac0.so.*
+%{_mandir}/man7/wlog.*
+
+%files devel
+%{_includedir}/freerdp2
+%{_includedir}/uwac0
+%{_libdir}/cmake/FreeRDP2
+%{_libdir}/cmake/FreeRDP-Client2
+%{?_with_server:
+%{_libdir}/cmake/FreeRDP-Server2
+%{_libdir}/cmake/FreeRDP-Shadow2
+}
+%{_libdir}/cmake/uwac0
+%{_libdir}/libfreerdp-client2.so
+%{?_with_server:
+%{_libdir}/libfreerdp-server2.so
+%{_libdir}/libfreerdp-shadow2.so
+%{_libdir}/libfreerdp-shadow-subsystem2.so
+}
+%{_libdir}/libfreerdp2.so
+%{_libdir}/libuwac0.so
+%{_libdir}/pkgconfig/freerdp2.pc
+%{_libdir}/pkgconfig/freerdp-client2.pc
+%{?_with_server:
+%{_libdir}/pkgconfig/freerdp-server2.pc
+%{_libdir}/pkgconfig/freerdp-shadow2.pc
+}
+%{_libdir}/pkgconfig/uwac0.pc
+
+%{?_with_server:
+%files server
+%{_bindir}/freerdp-proxy
+%{_bindir}/freerdp-shadow-cli
+%{_mandir}/man1/freerdp-shadow-cli.1*
+}
+
+%files -n libwinpr
+%license LICENSE
+%doc README.md ChangeLog
+%{_libdir}/libwinpr2.so.*
+%{_libdir}/libwinpr-tools2.so.*
+
+%files -n libwinpr-devel
+%{_libdir}/cmake/WinPR2
+%{_includedir}/winpr2
+%{_libdir}/libwinpr2.so
+%{_libdir}/libwinpr-tools2.so
+%{_libdir}/pkgconfig/winpr2.pc
+%{_libdir}/pkgconfig/winpr-tools2.pc
+
+%changelog
+* Tue Dec 13 2022 Ondrej Holy <oholy@redhat.com> - 2:2.4.1-5
+- Fix "implicit declaration of function" errors (#2136155, #2145140)
+
+* Thu Dec 08 2022 Ondrej Holy <oholy@redhat.com> - - 2:2.4.1-4
+- CVE-2022-39282: Fix length checks in parallel driver (#2136152)
+- CVE-2022-39283: Add missing length check in video channel (#2136154)
+- CVE-2022-39316, CVE-2022-39317: Add missing length checks in zgfx (#2145140)
+- CVE-2022-39318: Fix division by zero in urbdrc channel (#2145140)
+- CVE-2022-39319: Add missing length checks in urbdrc channel (#2145140)
+- CVE-2022-39320: Ensure urb_create_iocompletion uses size_t (#2145140)
+- CVE-2022-39347: Fix path validation in drive channel (#2145140)
+- CVE-2022-41877: Add missing length check in drive channel (#2145140)
+
+* Wed Jun 22 2022 Ondrej Holy <oholy@redhat.com> - - 2:2.4.1-3
+- Fix gateway functionality with OpenSSL 3.0 (#2023262)
+
+* Fri Nov 26 2021 Ondrej Holy <oholy@redhat.com> - 2:2.4.1-2
+- Fix datatype mismatch / big-endian breakage
+- Load legacy provider when initializing OpenSSL 3.0
+
+* Wed Nov 10 2021 Ondrej Holy <oholy@redhat.com> - 2:2.4.1-1
+- Update to 2.4.1 (CVE-2021-41159, CVE-2021-41160).
+
+* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 2:2.4.0-3
+- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
+ Related: rhbz#1991688
+
+* Tue Aug 03 2021 Ondrej Holy <oholy@redhat.com> - 2:2.4.0-2
+- Load legacy provider to fix rc4 with OpenSSL 3.0 (#1988443).
+
+* Thu Jul 29 2021 Ondrej Holy <oholy@redhat.com> - 2:2.4.0-1
+- Update to 2.4.0.
+
+* Wed Jun 16 2021 Mohan Boddu <mboddu@redhat.com> - 2:2.3.2-2
+- Rebuilt for RHEL 9 BETA for openssl 3.0
+ Related: rhbz#1971065
+
+* Mon May 17 2021 Ondrej Holy <oholy@redhat.com> - 2:2.3.2-1
+- Update to 2.3.2 (#1951123).
+
+* Mon May 17 2021 Ondrej Holy <oholy@redhat.com> - 2:2.2.0-8
+- Fix build with OpenSSL 3.0 (#1952937).
+
+* Thu Apr 15 2021 Mohan Boddu <mboddu@redhat.com> - 2:2.2.0-7
+- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
+
+* Tue Mar 23 2021 Simone Caronni <negativo17@gmail.com> - 2:2.2.0-6
+- Explicitly enable Cairo support (#1938393).
+
+* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.2.0-5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
+
+* Tue Aug 11 2020 Ondrej Holy <oholy@redhat.com> - 2:2.2.0-4
+- Use %%cmake_ macros to fix out-of-source builds (#1863586)
+
+* Sat Aug 01 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.2.0-3
+- Second attempt - Rebuilt for
+ https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.2.0-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Thu Jul 23 2020 Simone Caronni <negativo17@gmail.com> - 2:2.2.0-1
+- Update to 2.2.0.
+
+* Tue Jun 30 2020 Simone Caronni <negativo17@gmail.com> - 2:2.1.2-1
+- Update to 2.1.2.
+
+* Thu May 21 2020 Ondrej Holy <oholy@redhat.com> - 2:2.1.1-1
+- Update to 2.1.1.
+
+* Fri May 15 2020 Ondrej Holy <oholy@redhat.com> - 2:2.1.0-1
+- Update to 2.1.0 (#1833540).
+
+* Fri May 15 2020 Pete Walter <pwalter@fedoraproject.org> - 2:2.0.0-57.20200207git245fc60
+- Rebuild for ICU 67
+
+* Fri Feb 07 2020 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-56.20200207git245fc60
+- Update to latest snapshot.
+
+* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.0.0-55.20190820git6015229
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
+
+* Fri Nov 01 2019 Pete Walter <pwalter@fedoraproject.org> - 2:2.0.0-54.20190820git6015229
+- Rebuild for ICU 65
+
+* Tue Aug 20 2019 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-53.20190820git6015229
+- Update to latest snapshot.
+
+* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.0.0-52.20190918git5e672d4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
+
+* Sun Jul 21 2019 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-51.20190918git5e672d4
+- Update to latest snapshot.
+
+* Sat May 18 2019 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-50.20190517gitb907324
+- Update to latest snapshot.
+
+* Wed Mar 06 2019 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-49.20190304git435872b
+- Fix for GFX color depth (Windows 10).
+
+* Thu Feb 28 2019 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-48.20190228gitce386c8
+- Update to latest snapshot post rc4.
+- CVE-2018-1000852 (#1661642).
+
+* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.0.0-47.rc4.1
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
+
+* Thu Nov 29 2018 Ondrej Holy <oholy@redhat.com> - 2:2.0.0-47.rc4
+- Update to 2.0.0-rc4
+
+* Mon Oct 15 2018 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-46.20181008git00af869
+- Enable Xtest option (#1559606).
+
+* Mon Oct 15 2018 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-45.20181008git00af869
+- Update to last snapshot post 2.0.0-rc3.
+
+* Mon Aug 20 2018 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-44.rc3
+- Update SPEC file.
+
+* Sat Aug 04 2018 Mike DePaulo <mikedep333@fedoraproject.org> - 2:2.0.0-43.20180801.rc3
+- Update to 2.0.0-rc3
+
+* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.0.0-42.20180405gita9ecd6a
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
+
+* Mon Apr 09 2018 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-41.20180405gita9ecd6a
+- Update to latest snapshot.
+
+* Wed Mar 21 2018 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-40.20180320gitde83f4d
+- Add PAM support (fixes freerdp-shadow-cli). Thanks Paolo Zeppegno.
+- Update to latest snapshot.
+
+* Thu Mar 15 2018 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-39.20180314gitf8baeb7
+- Update to latest snapshot.
+- Fixes connection to RDP servers with the latest Microsoft patches:
+ https://github.com/FreeRDP/FreeRDP/issues/4449
+
+* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.0.0-38.20180115git8f52c7e
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+
+* Thu Jan 18 2018 Karsten Hopp <karsten@redhat.com> - 2.0.0-37git}
+- use versioned build requirement on pkgconfig(openssl) to prevent using
+ compat-openssl10-devel instead of openssl-devel
+
+* Tue Jan 16 2018 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-36.20180115git8f52c7e
+- Update to latest snapshot.
+- Make GSS support optional and disable it for now (#1534094 and FreeRDP #4348,
+ #1435, #4363).
+
+* Wed Dec 20 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-35.20171220gitbfe8359
+- Update to latest snapshot post 2.0.0rc1.
+
+* Mon Sep 11 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-34.20170831git3b83526
+- Update to latest snapshot.
+- Trim changelog.
+
+* Mon Aug 07 2017 Björn Esser <besser82@fedoraproject.org> - 2:2.0.0-33.20170724gitf8c9f43
+- Rebuilt for AutoReq cmake-filesystem
+
+* Wed Aug 02 2017 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.0.0-32.20170724gitf8c9f43
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
+
+* Thu Jul 27 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-31.20170724gitf8c9f43
+- Update to latest snapshot, Talos security fixes.
+
+* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.0.0-30.20170710gitf580bea
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
+
+* Wed Jul 12 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-29.20170710gitf580bea
+- Update to latest snapshot.
+
+* Mon Jun 26 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-28.20170623git9904c32
+- Update to latest snapshot.
+
+* Mon May 15 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-27.20170512gitb1df835
+- Update to latest snapshot.
+
+* Thu Apr 20 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-26.20170419gitbfcf8e7
+- Update to latest 2.0 snapshot.
+
+* Thu Apr 13 2017 Orion Poplawski <orion@cora.nwra.com> - 2:2.0.0-25.20170317git8c68761
+- Install tools via make install
+
+* Wed Mar 22 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-24.20170317git8c68761
+- Update to latest snapshot.
+
+* Mon Mar 06 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-23.20170302git210de68
+- Remove shared libxfreerdp-client shared library.
+
+* Thu Mar 02 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-22.20170302git210de68
+- Move libxfreerdp-client shared object into devel subpackage.
+
+* Thu Mar 02 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-21.20170302git210de68
+- Update to latest snapshot.
+- Update build requirements, tune build options.
+
+* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 2:2.0.0-20.20161228git90877f5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
+
+* Mon Jan 09 2017 Simone Caronni <negativo17@gmail.com> - 2:2.0.0-19.20161228git90877f5
+- Update to latest snapshot.
diff --git a/sources b/sources
new file mode 100644
index 0000000..5d55732
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+9e46a3184439b55b5ab3ad0fba4169c9 FreeRDP-2.4.1.tar.gz
diff --git a/winpr-crt-Added-wcsstr-implementation.patch b/winpr-crt-Added-wcsstr-implementation.patch
new file mode 100644
index 0000000..533ef44
--- /dev/null
+++ b/winpr-crt-Added-wcsstr-implementation.patch
@@ -0,0 +1,66 @@
+From ddc6dacd06b41ed5001b1c884b5d5c9e0a70e275 Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Thu, 10 Nov 2022 15:54:28 +0100
+Subject: [PATCH] [winpr, crt] Added wcsstr implementation
+
+(cherry picked from commit 6c034ba6117a4efc9266e845fe9a9a92ed4ee61d)
+---
+ winpr/include/winpr/string.h | 3 +++
+ winpr/libwinpr/crt/string.c | 20 ++++++++++++++++++++
+ 2 files changed, 23 insertions(+)
+
+diff --git a/winpr/include/winpr/string.h b/winpr/include/winpr/string.h
+index 3b907c444..2d7126210 100644
+--- a/winpr/include/winpr/string.h
++++ b/winpr/include/winpr/string.h
+@@ -62,6 +62,8 @@ extern "C"
+ WINPR_API size_t _wcslen(const WCHAR* str);
+ WINPR_API size_t _wcsnlen(const WCHAR* str, size_t maxNumberOfElements);
+
++ WINPR_API WCHAR* _wcsstr(const WCHAR* str, const WCHAR* strSearch);
++
+ WINPR_API WCHAR* _wcschr(const WCHAR* str, WCHAR c);
+ WINPR_API WCHAR* _wcsrchr(const WCHAR* str, WCHAR c);
+
+@@ -74,6 +76,7 @@ extern "C"
+ #define _wcsncmp wcsncmp
+ #define _wcslen wcslen
+ #define _wcsnlen wcsnlen
++#define _wcsstr wcsstr
+ #define _wcschr wcschr
+ #define _wcsrchr wcsrchr
+
+diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c
+index 5dcf4b3f1..efd7d166c 100644
+--- a/winpr/libwinpr/crt/string.c
++++ b/winpr/libwinpr/crt/string.c
+@@ -147,6 +147,26 @@ size_t _wcsnlen(const WCHAR* str, size_t max)
+ return x;
+ }
+
++/* _wcsstr -> wcsstr */
++
++WCHAR* _wcsstr(const WCHAR* str, const WCHAR* strSearch)
++{
++ assert(str);
++ assert(strSearch);
++
++ if (strSearch[0] == '\0')
++ return str;
++
++ const size_t searchLen = _wcslen(strSearch);
++ while (*str)
++ {
++ if (_wcsncmp(str, strSearch, searchLen) == 0)
++ return str;
++ str++;
++ }
++ return NULL;
++}
++
+ /* _wcschr -> wcschr */
+
+ WCHAR* _wcschr(const WCHAR* str, WCHAR c)
+--
+2.37.1
+
diff --git a/winpr-crt-Fix-wcs-cmp-and-wcs-len-checks.patch b/winpr-crt-Fix-wcs-cmp-and-wcs-len-checks.patch
new file mode 100644
index 0000000..1ae664d
--- /dev/null
+++ b/winpr-crt-Fix-wcs-cmp-and-wcs-len-checks.patch
@@ -0,0 +1,90 @@
+From fb9d753af70b449dd7a17898d46fd57822a08dc1 Mon Sep 17 00:00:00 2001
+From: akallabeth <akallabeth@posteo.net>
+Date: Thu, 10 Nov 2022 14:21:22 +0100
+Subject: [PATCH] [winpr, crt] Fix wcs*cmp and wcs*len checks
+
+(cherry picked from commit b60fac1a0470fe83e8d0b448f0fd7e9e6d6a0f96)
+---
+ winpr/libwinpr/crt/string.c | 30 +++++++++++++++++++-----------
+ 1 file changed, 19 insertions(+), 11 deletions(-)
+
+diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c
+index c25ffa279..5dcf4b3f1 100644
+--- a/winpr/libwinpr/crt/string.c
++++ b/winpr/libwinpr/crt/string.c
+@@ -26,6 +26,7 @@
+ #include <wctype.h>
+
+ #include <winpr/crt.h>
++#include <assert.h>
+ #include <winpr/endian.h>
+
+ /* String Manipulation (CRT): http://msdn.microsoft.com/en-us/library/f0151s4x.aspx */
+@@ -80,21 +81,28 @@ int _strnicmp(const char* string1, const char* string2, size_t count)
+
+ int _wcscmp(const WCHAR* string1, const WCHAR* string2)
+ {
+- WCHAR value1, value2;
++ assert(string1);
++ assert(string2);
+
+- while (*string1 && (*string1 == *string2))
++ while (TRUE)
+ {
+- string1++;
+- string2++;
++ const WCHAR w1 = *string1++;
++ const WCHAR w2 = *string2++;
++
++ if (w1 != w2)
++ return (int)w1 - w2;
++ else if ((w1 == '\0') || (w2 == '\0'))
++ return (int)w1 - w2;
+ }
+
+- Data_Read_UINT16(string1, value1);
+- Data_Read_UINT16(string2, value2);
+- return (int)value1 - value2;
++ return 0;
+ }
+
+ int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count)
+ {
++ assert(string1);
++ assert(string2);
++
+ for (size_t x = 0; x < count; x++)
+ {
+ const WCHAR a = string1[x];
+@@ -102,6 +110,8 @@ int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count)
+
+ if (a != b)
+ return (int)a - b;
++ else if ((a == '\0') || (b == '\0'))
++ return (int)a - b;
+ }
+ return 0;
+ }
+@@ -112,8 +122,7 @@ size_t _wcslen(const WCHAR* str)
+ {
+ const WCHAR* p = (const WCHAR*)str;
+
+- if (!p)
+- return 0;
++ assert(p);
+
+ while (*p)
+ p++;
+@@ -127,8 +136,7 @@ size_t _wcsnlen(const WCHAR* str, size_t max)
+ {
+ size_t x;
+
+- if (!str)
+- return 0;
++ assert(str);
+
+ for (x = 0; x < max; x++)
+ {
+--
+2.37.1
+
diff --git a/winpr-ssl-Load-legacy-provider-when-initializing-Ope.patch b/winpr-ssl-Load-legacy-provider-when-initializing-Ope.patch
new file mode 100644
index 0000000..9f20750
--- /dev/null
+++ b/winpr-ssl-Load-legacy-provider-when-initializing-Ope.patch
@@ -0,0 +1,61 @@
+From 2d0b58759ba823bbc372ac19fea5080f4261c26e Mon Sep 17 00:00:00 2001
+From: Ondrej Holy <oholy@redhat.com>
+Date: Tue, 16 Nov 2021 16:12:33 +0100
+Subject: [PATCH] winpr/ssl: Load legacy provider when initializing OpenSSL 3.0
+
+With OpenSSL 3.O, FreeRDP log contains errors like:
+
+```
+4036740A4C7F0000:error:0308010C:digital envelope routines:
+inner_evp_generic_fetch:unsupported:crypto/evp/evp_fetch.c:346:
+Global default library context, Algorithm (MD4 : 85), Properties ()
+```
+
+This leads to connection failures in some cases. This is because algorithms
+like MD4 are now part of the legacy provider, which is not loaded by
+default. Let's explicitly load that provider. With this change, also the
+other provides has to be explicitely loaded.
+---
+ winpr/libwinpr/utils/ssl.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/winpr/libwinpr/utils/ssl.c b/winpr/libwinpr/utils/ssl.c
+index 74ef156e7..392f8e227 100644
+--- a/winpr/libwinpr/utils/ssl.c
++++ b/winpr/libwinpr/utils/ssl.c
+@@ -33,6 +33,10 @@
+ #include <openssl/ssl.h>
+ #include <openssl/err.h>
+
++#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
++#include <openssl/provider.h>
++#endif
++
+ #include "../log.h"
+ #define TAG WINPR_TAG("utils.ssl")
+
+@@ -245,6 +249,7 @@ static BOOL winpr_enable_fips(DWORD flags)
+ WLog_DBG(TAG, "Ensuring openssl fips mode is ENabled");
+
+ #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
++ OSSL_PROVIDER_load(NULL, "fips");
+ if (!EVP_default_properties_is_fips_enabled(NULL))
+ #else
+ if (FIPS_mode() != 1)
+@@ -305,6 +310,13 @@ static BOOL CALLBACK _winpr_openssl_initialize(PINIT_ONCE once, PVOID param, PVO
+ return FALSE;
+
+ #endif
++
++#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
++ /* The legacy provider is needed for MD4. */
++ OSSL_PROVIDER_load(NULL, "legacy");
++ OSSL_PROVIDER_load(NULL, "default");
++#endif
++
+ g_winpr_openssl_initialized_by_winpr = TRUE;
+ return winpr_enable_fips(flags);
+ }
+--
+2.33.1
+