New upstream version 2.1.2+dfsg1
This commit is contained in:
parent
912dda7d3e
commit
e672a1bc07
@ -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)
|
||||
|
||||
23
ChangeLog
23
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:
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 (MsInterfaces[InterfaceNumber]->AlternateSetting != AlternateSetting)
|
||||
{
|
||||
diff = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (diff)
|
||||
{
|
||||
error = libusb_set_interface_alt_setting(pdev->libusb_handle, InterfaceNumber,
|
||||
AlternateSetting);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -89,7 +89,7 @@ LPSTR tr_esc_str(LPCSTR arg, bool format)
|
||||
strncpy(&tmp[cs], "</replaceable>", len);
|
||||
else
|
||||
/* coverity[buffer_size] */
|
||||
strncpy(&tmp[cs], "<", len);
|
||||
strncpy(&tmp[cs], ">", len);
|
||||
|
||||
cs += len;
|
||||
break;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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:
|
||||
|
||||
42
client/common/geometry.c
Normal file
42
client/common/geometry.c
Normal file
@ -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);
|
||||
}
|
||||
@ -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 */
|
||||
|
||||
2
libfreerdp/cache/glyph.c
vendored
2
libfreerdp/cache/glyph.c
vendored
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
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 16
|
||||
#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);
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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";
|
||||
const char* oldState = tsg_state_to_string(tsg->state);
|
||||
const char* newState = tsg_state_to_string(state);
|
||||
|
||||
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;
|
||||
|
||||
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))
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 };
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#define PRIMARY_DRAWING_ORDER_COUNT (ARRAYSIZE(PRIMARY_DRAWING_ORDER_FIELD_BYTES))
|
||||
static BYTE get_cbr2_bpp(UINT32 bpp, BOOL* pValid)
|
||||
{
|
||||
if (pValid)
|
||||
*pValid = TRUE;
|
||||
switch (bpp)
|
||||
{
|
||||
case 3:
|
||||
return 8;
|
||||
case 4:
|
||||
return 16;
|
||||
case 5:
|
||||
return 24;
|
||||
case 6:
|
||||
return 32;
|
||||
default:
|
||||
WLog_WARN(TAG, "Invalid bpp %" PRIu32, bpp);
|
||||
if (pValid)
|
||||
*pValid = FALSE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const BYTE 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 };
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
50
scripts/create_release_taball.sh
Executable file
50
scripts/create_release_taball.sh
Executable file
@ -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
|
||||
33
server/proxy/modules/capture/CMakeLists.txt
Normal file
33
server/proxy/modules/capture/CMakeLists.txt
Normal file
@ -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}")
|
||||
97
server/proxy/modules/capture/cap_config.c
Normal file
97
server/proxy/modules/capture/cap_config.c
Normal file
@ -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;
|
||||
}
|
||||
29
server/proxy/modules/capture/cap_config.h
Normal file
29
server/proxy/modules/capture/cap_config.h
Normal file
@ -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);
|
||||
288
server/proxy/modules/capture/cap_main.c
Normal file
288
server/proxy/modules/capture/cap_main.c
Normal file
@ -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);
|
||||
}
|
||||
57
server/proxy/modules/capture/cap_protocol.c
Normal file
57
server/proxy/modules/capture/cap_protocol.c
Normal file
@ -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;
|
||||
}
|
||||
35
server/proxy/modules/capture/cap_protocol.h
Normal file
35
server/proxy/modules/capture/cap_protocol.h
Normal file
@ -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);
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
size_t x;
|
||||
const char* base = "/etc/pam.d";
|
||||
const char* hints[] = { "lightdm", "gdm", "xdm", "login", "sshd" };
|
||||
|
||||
if (!info->service_name)
|
||||
return -1;
|
||||
for (x = 0; x < ARRAYSIZE(hints); x++)
|
||||
{
|
||||
char path[MAX_PATH];
|
||||
const char* hint = hints[x];
|
||||
|
||||
return 1;
|
||||
_snprintf(path, sizeof(path), "%s/%s", base, hint);
|
||||
if (PathFileExistsA(path))
|
||||
{
|
||||
|
||||
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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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++)
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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->pendingBuffer || !drawingBuffer->dirty)
|
||||
if (window->drawingBufferIdx < 0)
|
||||
return UWAC_ERROR_INTERNAL;
|
||||
|
||||
currentDrawingBuffer = &window->buffers[window->drawingBufferIdx];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Stream_SealLength(s);
|
||||
/**
|
||||
* Refer to "Compressed Image File Formats: JPEG, PNG, GIF, XBM, BMP" book
|
||||
*/
|
||||
|
||||
if (fwrite(Stream_Buffer(s), Stream_Length(s), 1, fp) != 1 ||
|
||||
fwrite((void*)data, bi.biSizeImage, 1, fp) != 1)
|
||||
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;
|
||||
}
|
||||
|
||||
bmp_header = winpr_bitmap_construct_header(width, height, bpp);
|
||||
if (!bmp_header)
|
||||
return -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user