Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FreeRDP/FreeRDP.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Fleisz <martin.fleisz@thincast.com>2020-06-22 13:44:36 +0300
committerGitHub <noreply@github.com>2020-06-22 13:44:36 +0300
commit584efae073386e8c5f6bc265b05c87d508a9bcbc (patch)
tree550a5fe476ffd151b18e20011f291dd93989f9aa
parent1923e63516c1182bd5e917aeac563431e8c5381a (diff)
parent93bed51ae2eeafa07ea8b0833710653782705d7e (diff)
Merge pull request #6285 from akallabeth/stable-backports22.1.2
Stable backports
-rw-r--r--CMakeLists.txt2
-rw-r--r--ChangeLog23
-rw-r--r--channels/drdynvc/client/drdynvc_main.c17
-rw-r--r--channels/encomsp/client/encomsp_main.c3
-rw-r--r--channels/geometry/client/geometry_main.c18
-rw-r--r--channels/printer/client/cups/printer_cups.c3
-rw-r--r--channels/printer/client/win/printer_win.c3
-rw-r--r--channels/rdpdr/client/rdpdr_main.c9
-rw-r--r--channels/rdpei/client/rdpei_main.c1
-rw-r--r--channels/rdpei/rdpei_common.c8
-rw-r--r--channels/remdesk/client/remdesk_main.c3
-rw-r--r--channels/smartcard/client/smartcard_operations.c50
-rw-r--r--channels/smartcard/client/smartcard_pack.c8
-rw-r--r--channels/urbdrc/client/data_transfer.c2
-rw-r--r--channels/urbdrc/client/libusb/libusb_udevice.c38
-rw-r--r--client/Android/Studio/build.gradle2
-rw-r--r--client/Android/android_freerdp.c2
-rw-r--r--client/Wayland/wlf_input.c15
-rw-r--r--client/Wayland/wlfreerdp.c36
-rw-r--r--client/Wayland/wlfreerdp.h1
-rw-r--r--client/X11/generate_argument_docbook.c2
-rw-r--r--client/X11/xf_client.c10
-rw-r--r--client/X11/xf_event.c6
-rw-r--r--client/common/CMakeLists.txt3
-rw-r--r--client/common/client.c3
-rw-r--r--client/common/geometry.c42
-rw-r--r--include/freerdp/scancode.h7
-rw-r--r--libfreerdp/cache/glyph.c2
-rw-r--r--libfreerdp/codec/include/bitmap.c12
-rw-r--r--libfreerdp/codec/interleaved.c3
-rw-r--r--libfreerdp/common/assistance.c76
-rw-r--r--libfreerdp/core/gateway/ntlm.c6
-rw-r--r--libfreerdp/core/gateway/rdg.c2
-rw-r--r--libfreerdp/core/gateway/rdg.h2
-rw-r--r--libfreerdp/core/gateway/rpc.c14
-rw-r--r--libfreerdp/core/gateway/rpc.h57
-rw-r--r--libfreerdp/core/gateway/rpc_bind.c51
-rw-r--r--libfreerdp/core/gateway/rpc_client.c60
-rw-r--r--libfreerdp/core/gateway/rts.c106
-rw-r--r--libfreerdp/core/gateway/rts_signature.c8
-rw-r--r--libfreerdp/core/gateway/tsg.c295
-rw-r--r--libfreerdp/core/gateway/tsg.h15
-rw-r--r--libfreerdp/core/license.c9
-rw-r--r--libfreerdp/core/orders.c240
-rw-r--r--libfreerdp/core/orders.h2
-rw-r--r--libfreerdp/core/rdp.c2
-rw-r--r--libfreerdp/core/security.c28
-rw-r--r--libfreerdp/core/tcp.c2
-rw-r--r--libfreerdp/core/tcp.h2
-rw-r--r--libfreerdp/core/transport.c2
-rw-r--r--libfreerdp/core/transport.h2
-rw-r--r--libfreerdp/core/update.c4
-rw-r--r--libfreerdp/crypto/crypto.c9
-rw-r--r--libfreerdp/gdi/gfx.c5
-rw-r--r--libfreerdp/gdi/graphics.c1
-rw-r--r--libfreerdp/utils/pcap.c22
-rwxr-xr-xscripts/create_release_taball.sh50
-rw-r--r--server/proxy/modules/capture/CMakeLists.txt33
-rw-r--r--server/proxy/modules/capture/cap_config.c97
-rw-r--r--server/proxy/modules/capture/cap_config.h29
-rw-r--r--server/proxy/modules/capture/cap_main.c288
-rw-r--r--server/proxy/modules/capture/cap_protocol.c57
-rw-r--r--server/proxy/modules/capture/cap_protocol.h35
-rw-r--r--server/shadow/Mac/mac_shadow.c11
-rw-r--r--server/shadow/X11/x11_shadow.c139
-rw-r--r--server/shadow/shadow_client.c5
-rw-r--r--server/shadow/shadow_server.c7
-rw-r--r--uwac/libuwac/uwac-os.c11
-rw-r--r--uwac/libuwac/uwac-priv.h3
-rw-r--r--uwac/libuwac/uwac-window.c86
-rw-r--r--winpr/CMakeLists.txt2
-rw-r--r--winpr/include/winpr/image.h3
-rw-r--r--winpr/libwinpr/sspi/NTLM/ntlm.c40
-rw-r--r--winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c175
-rw-r--r--winpr/libwinpr/sspi/NTLM/ntlm_message.c2
-rw-r--r--winpr/libwinpr/sspicli/sspicli.c13
-rw-r--r--winpr/libwinpr/sysinfo/sysinfo.c6
-rw-r--r--winpr/libwinpr/timezone/timezone.c6
-rw-r--r--winpr/libwinpr/utils/collections/MessageQueue.c5
-rw-r--r--winpr/libwinpr/utils/image.c62
-rw-r--r--winpr/libwinpr/utils/trio/trio.c6
-rw-r--r--winpr/libwinpr/utils/trio/triostr.c3
82 files changed, 1936 insertions, 594 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1d685b921..be4fcbb75 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/ChangeLog b/ChangeLog
index 593cb89a6..1ecea0919 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:
diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c
index eb5b418e1..507305fc6 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);
@@ -1583,13 +1588,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);
diff --git a/channels/encomsp/client/encomsp_main.c b/channels/encomsp/client/encomsp_main.c
index dc2172004..b384337fe 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/geometry/client/geometry_main.c b/channels/geometry/client/geometry_main.c
index eb65b2ca2..cb5e2ae40 100644
--- a/channels/geometry/client/geometry_main.c
+++ b/channels/geometry/client/geometry_main.c
@@ -27,7 +27,6 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
-#include <winpr/interlocked.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include <winpr/cmdline.h>
@@ -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/channels/printer/client/cups/printer_cups.c b/channels/printer/client/cups/printer_cups.c
index 1f9f07b24..56cbacecf 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 5306f59fb..86b5e66d9 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_s(&tt, &tres);
str = calloc(len, sizeof(WCHAR));
if (!str)
diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c
index 7f6dc9451..98f526d37 100644
--- a/channels/rdpdr/client/rdpdr_main.c
+++ b/channels/rdpdr/client/rdpdr_main.c
@@ -598,7 +598,14 @@ static BOOL isAutomountLocation(const char* path)
size_t x;
char buffer[MAX_PATH];
uid_t uid = getuid();
- const char* uname = getlogin();
+ 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/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c
index 0a0cfefb2..7da9ae73b 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;
diff --git a/channels/rdpei/rdpei_common.c b/channels/rdpei/rdpei_common.c
index f01d4dd78..7628b32a6 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;
diff --git a/channels/remdesk/client/remdesk_main.c b/channels/remdesk/client/remdesk_main.c
index b3464eea1..54d9c60b4 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);
}
}
diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c
index b20f2e4df..5bcd624f9 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;
diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c
index de0e1cec5..a85cce6da 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))
diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c
index 30def2298..ecacc695f 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,
diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c
index 94117bcf3..ce231ba36 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);
}
@@ -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);
+ }
}
}
@@ -1168,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);
}
@@ -1292,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)
{
@@ -1348,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);
}
diff --git a/client/Android/Studio/build.gradle b/client/Android/Studio/build.gradle
index 319280d5e..01a7ae278 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 0b0f27b09..a9a952017 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/client/Wayland/wlf_input.c b/client/Wayland/wlf_input.c
index afa8d4b51..8dcbb5f81 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))
diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c
index 5086220d2..11b747e60 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)
@@ -296,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;
@@ -321,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:
@@ -552,6 +563,8 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context)
if (!wfl->displayHandle)
return FALSE;
+ InitializeCriticalSection(&wfl->critical);
+
return TRUE;
}
@@ -567,6 +580,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 09d056ae4..d64706690 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);
diff --git a/client/X11/generate_argument_docbook.c b/client/X11/generate_argument_docbook.c
index 49b1bb108..78de2f9be 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], "</replaceable>", len);
else
/* coverity[buffer_size] */
- strncpy(&tmp[cs], "&lt;", len);
+ strncpy(&tmp[cs], "&gt;", len);
cs += len;
break;
diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c
index 146c7feea..189cb17e9 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);
}
}
}
@@ -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/client/X11/xf_event.c b/client/X11/xf_event.c
index e7a889efc..3f7d8727c 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);
}
diff --git a/client/common/CMakeLists.txt b/client/common/CMakeLists.txt
index b6805e593..d4588e10b 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/client.c b/client/common/client.c
index 1f44da41a..380d7de92 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:
diff --git a/client/common/geometry.c b/client/common/geometry.c
new file mode 100644
index 000000000..92f57ccfc
--- /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 <contact@hardening-consulting.com>
+ *
+ * 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 <freerdp/client/geometry.h>
+#include <winpr/interlocked.h>
+
+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);
+}
diff --git a/include/freerdp/scancode.h b/include/freerdp/scancode.h
index 226f711a5..55d2ebb86 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 */
diff --git a/libfreerdp/cache/glyph.c b/libfreerdp/cache/glyph.c
index 9f5e4a301..5c41f912a 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;
diff --git a/libfreerdp/codec/include/bitmap.c b/libfreerdp/codec/include/bitmap.c
index 5b4804f2e..38bcaa859 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);
diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c
index e9f92c700..b76fe1ca3 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
diff --git a/libfreerdp/common/assistance.c b/libfreerdp/common/assistance.c
index c7ae2ba2d..508a80be6 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 <E>");
+ return -1;
+ }
+
q += sizeof("</E>") - 1;
length = q - p;
file->ConnectionString2 = (char*)malloc(length + 1);
diff --git a/libfreerdp/core/gateway/ntlm.c b/libfreerdp/core/gateway/ntlm.c
index 084e55096..35637518c 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;
diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c
index 6ea9e4f06..107e396cb 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 829d0a250..50d865258 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 0b47024ca..218a407c0 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 5c315d90d..3ca18a7a2 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 4cfd02219..98ed9a9dc 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 23518f871..d4432cbbd 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,34 +955,34 @@ 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[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY; /* auth_data */
Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */
Buffers[0].pvBuffer = buffer;
Buffers[0].cbBuffer = offset;
@@ -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 6218f8157..c003b1ea0 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 d3b376d2d..4d605f041 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 7537f18dd..1626b91c1 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 af9f88671..9bfb3c7d2 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/license.c b/libfreerdp/core/license.c
index 18bcb9fa4..097107b70 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;
diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c
index e053bd480..dc4e51a87 100644
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -43,51 +43,144 @@
#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))
-
-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 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 };
+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 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 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)
@@ -775,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;
}
@@ -819,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;
}
@@ -1977,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;
@@ -1991,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)
{
@@ -2070,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);
@@ -2138,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;
@@ -2155,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;
@@ -2203,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;
@@ -2211,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) */
@@ -2535,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));
@@ -2548,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) */
@@ -2622,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) */
@@ -3240,6 +3353,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 +3377,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;
@@ -3506,7 +3623,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);
@@ -3645,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;
}
diff --git a/libfreerdp/core/orders.h b/libfreerdp/core/orders.h
index 76e3d3fe3..d429dff70 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/rdp.c b/libfreerdp/core/rdp.c
index fd771ae3e..1c8990ec8 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/security.c b/libfreerdp/core/security.c
index e6571c36d..7caf5a842 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;
}
@@ -741,29 +746,34 @@ fail:
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)
@@ -772,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;
@@ -831,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;
@@ -848,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;
diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c
index 286dc1f6d..ef5f7b193 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 abb664403..74a23114c 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 b20d4a2fe..40795e941 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 c6509fe57..944f5ce30 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);
diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c
index aac58819f..ebb82fc2d 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;
diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c
index 841468339..29c642ef1 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;
diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c
index b76cdd79c..e3a6e66e0 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);
diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c
index f63df3983..60d82ae99 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;
}
diff --git a/libfreerdp/utils/pcap.c b/libfreerdp/utils/pcap.c
index e50bbd7e7..6f6ed258a 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)
diff --git a/scripts/create_release_taball.sh b/scripts/create_release_taball.sh
new file mode 100755
index 000000000..4f91ad4d5
--- /dev/null
+++ b/scripts/create_release_taball.sh
@@ -0,0 +1,50 @@
+#!/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)
+ 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)
+
+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
+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
+
+run mv ${TMPDIR}/freerdp-${TAG}.tar.gz* .
+run mv ${TMPDIR}/freerdp-${TAG}.zip* .
+run rm -rf ${TMPDIR}
+exit 0
diff --git a/server/proxy/modules/capture/CMakeLists.txt b/server/proxy/modules/capture/CMakeLists.txt
new file mode 100644
index 000000000..80ba3b77e
--- /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 <kmizrachi18@gmail.com>
+#
+# 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 000000000..32e02ae4d
--- /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 <kmizrachi18@gmail.com>
+ *
+ * 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 <winpr/environment.h>
+#include <freerdp/types.h>
+#include <errno.h>
+
+#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 > 0)
+ {
+ 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 000000000..ace5079dc
--- /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 <kmizrachi18@gmail.com>
+ *
+ * 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 <freerdp/types.h>
+
+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 000000000..0f5d5bc4f
--- /dev/null
+++ b/server/proxy/modules/capture/cap_main.c
@@ -0,0 +1,288 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * FreeRDP Proxy Server Session Capture Module
+ *
+ * Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
+ *
+ * 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 <errno.h>
+#include <winpr/image.h>
+#include <freerdp/gdi/gdi.h>
+#include <winpr/winsock.h>
+
+#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(void)
+{
+ 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;
+ wStream* s;
+
+ socket = capture_plugin_get_socket(pdata);
+ if (socket == -1)
+ return FALSE;
+
+ 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(void)
+{
+ 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 000000000..b56393838
--- /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 <kmizrachi18@gmail.com>
+ *
+ * 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 000000000..655eb69bd
--- /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 <kmizrachi18@gmail.com>
+ *
+ * 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 <winpr/stream.h>
+#include <freerdp/settings.h>
+
+/* 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);
diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c
index 053232978..6dd3ba1ac 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 9dfa12a5e..4a8aab156 100644
--- a/server/shadow/X11/x11_shadow.c
+++ b/server/shadow/X11/x11_shadow.c
@@ -128,90 +128,69 @@ out_fail:
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;
}
@@ -757,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;
@@ -774,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
@@ -790,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)
{
/*
@@ -807,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 */
@@ -820,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)
{
@@ -850,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 f32f64976..86bc3fc03 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;
}
diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c
index 30a63c9fa..259f22ecd 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++)
diff --git a/uwac/libuwac/uwac-os.c b/uwac/libuwac/uwac-os.c
index 4f8c8f516..7e3672110 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)
{
diff --git a/uwac/libuwac/uwac-priv.h b/uwac/libuwac/uwac-priv.h
index 75ad6e0fe..2ef073de1 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 f76d43bcc..1dc5574ff 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 @@ error_mmap:
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,22 +737,29 @@ UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize*
UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame)
{
- UwacBuffer* drawingBuffer = window->drawingBuffer;
+ UwacBuffer* currentDrawingBuffer;
+ UwacBuffer* nextDrawingBuffer;
+ UwacBuffer* pendingBuffer;
+
+ if (window->drawingBufferIdx < 0)
+ return UWAC_ERROR_INTERNAL;
+
+ currentDrawingBuffer = &window->buffers[window->drawingBufferIdx];
- if (window->pendingBuffer || !drawingBuffer->dirty)
+ if ((window->pendingBufferIdx >= 0) || !currentDrawingBuffer->dirty)
return UWAC_SUCCESS;
- window->pendingBuffer = drawingBuffer;
- window->drawingBuffer = UwacWindowFindFreeBuffer(window);
+ window->pendingBufferIdx = window->drawingBufferIdx;
+ nextDrawingBuffer = UwacWindowFindFreeBuffer(window, &window->drawingBufferIdx);
+ pendingBuffer = &window->buffers[window->pendingBufferIdx];
- if (!window->drawingBuffer)
+ if ((!nextDrawingBuffer) || (window->drawingBufferIdx < 0))
return UWAC_ERROR_NOMEMORY;
if (copyContentForNextFrame)
- memcpy(window->drawingBuffer->data, window->pendingBuffer->data,
- window->stride * window->height);
+ memcpy(nextDrawingBuffer->data, pendingBuffer->data, window->stride * window->height);
- UwacSubmitBufferPtr(window, drawingBuffer);
+ UwacSubmitBufferPtr(window, pendingBuffer);
return UWAC_SUCCESS;
}
diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt
index a8b66038f..54a1649f3 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)
diff --git a/winpr/include/winpr/image.h b/winpr/include/winpr/image.h
index 24ec02dd1..66e5960e0 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/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c
index b4ca9c5e8..66f571758 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);
diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c
index 7b6eabdc4..47669bb2e 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 */
@@ -572,54 +652,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 +709,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 +740,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 314f5c147..34813a414 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;
}
diff --git a/winpr/libwinpr/sspicli/sspicli.c b/winpr/libwinpr/sspicli/sspicli.c
index e88b53d48..671df6e98 100644
--- a/winpr/libwinpr/sspicli/sspicli.c
+++ b/winpr/libwinpr/sspicli/sspicli.c
@@ -201,18 +201,23 @@ 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();
+#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)
{
CopyMemory(lpNameBuffer, login, length + 1);
- return 1;
+ return TRUE;
}
else
{
@@ -235,7 +240,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)
diff --git a/winpr/libwinpr/sysinfo/sysinfo.c b/winpr/libwinpr/sysinfo/sysinfo.c
index 10884f7d1..de39e15b1 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)
@@ -242,11 +243,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 5475cb67a..12fcd444e 100644
--- a/winpr/libwinpr/timezone/timezone.c
+++ b/winpr/libwinpr/timezone/timezone.c
@@ -339,12 +339,16 @@ 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
{
diff --git a/winpr/libwinpr/utils/collections/MessageQueue.c b/winpr/libwinpr/utils/collections/MessageQueue.c
index d288c544f..d787f8ff3 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);
diff --git a/winpr/libwinpr/utils/image.c b/winpr/libwinpr/utils/image.c
index 41b4cc5e1..a1155e5eb 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;
}
diff --git a/winpr/libwinpr/utils/trio/trio.c b/winpr/libwinpr/utils/trio/trio.c
index ec765ce5a..b278f475b 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 da12775ac..6832ad5ae 100644
--- a/winpr/libwinpr/utils/trio/triostr.c
+++ b/winpr/libwinpr/utils/trio/triostr.c
@@ -25,6 +25,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <ctype.h>
#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