diff -Nru freerdp2-2.1.1+dfsg1/ChangeLog freerdp2-2.2.0+dfsg1/ChangeLog --- freerdp2-2.1.1+dfsg1/ChangeLog 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/ChangeLog 2020-07-20 13:38:46.000000000 +0000 @@ -1,3 +1,54 @@ +# 2020-07-20 Version 2.2.0 + +Important notes: +* CVE-2020-15103 - Integer overflow due to missing input sanitation in rdpegfx channel + +Noteworty changes: +* fix: memory leak in nsc +* urbdrc + * some fixes and improvements +* build + * use cmake to detect getlogin_r + * improve asan checks/detection +* server/proxy + * new: support for heartbeats + * new: support for rail handshake ex flags + * fix: possible race condition with redirects + +Fixed issues: +* #6263 Sound & mic - filter GSM codec for microphone redirection +* #6335: windows client title length +* #6370 - "Alternate Secondary Drawing Order UNKNOWN" +* #6298 - remoteapp with dialog is disconnecting when it loses focus +* #6299 - v2.1.2: Can't connect to Windows7 + +For a complete and detailed change log since the last release run: +git log 2.1.2..2.2.0 + + +# 2020-06-22 Version 2.1.2 + +Important notes: +* CVE-2020-4033 Out of bound read in RLEDECOMPRESS +* CVE-2020-4031 Use-After-Free in gdi_SelectObject +* CVE-2020-4032 Integer casting vulnerability in `update_recv_secondary_order` +* CVE-2020-4030 OOB read in `TrioParse` +* CVE-2020-11099 OOB Read in license_read_new_or_upgrade_license_packet +* CVE-2020-11098 Out-of-bound read in glyph_cache_put +* CVE-2020-11097 OOB read in ntlm_av_pair_get +* CVE-2020-11095 Global OOB read in update_recv_primary_order +* CVE-2020-11096 Global OOB read in update_read_cache_bitmap_v3_order +* Gateway RPC fixes for windows +* Fixed resource fee race resulting in double free in USB redirection +* Fixed wayland client crashes +* Fixed X11 client mouse mapping issues (X11 mapping on/off) +* Some proxy related improvements (capture module) +* Code cleanup (use getlogin_r, ...) + +For a complete and detailed change log since the last release candidate run: +git log 2.1.1..2.1.2 + + # 2020-05-20 Version 2.1.1 Important notes: diff -Nru freerdp2-2.1.1+dfsg1/channels/drdynvc/client/drdynvc_main.c freerdp2-2.2.0+dfsg1/channels/drdynvc/client/drdynvc_main.c --- freerdp2-2.1.1+dfsg1/channels/drdynvc/client/drdynvc_main.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/drdynvc/client/drdynvc_main.c 2020-07-20 13:38:46.000000000 +0000 @@ -580,10 +580,15 @@ { 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 @@ if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + MessageQueue_Free(drdynvc->queue); + drdynvc->queue = NULL; + if (drdynvc->channel_mgr) { dvcman_free(drdynvc, drdynvc->channel_mgr); drdynvc->channel_mgr = NULL; } - MessageQueue_Free(drdynvc->queue); - drdynvc->queue = NULL; + drdynvc->InitHandle = 0; free(drdynvc->context); free(drdynvc); diff -Nru freerdp2-2.1.1+dfsg1/channels/encomsp/client/encomsp_main.c freerdp2-2.2.0+dfsg1/channels/encomsp/client/encomsp_main.c --- freerdp2-2.1.1+dfsg1/channels/encomsp/client/encomsp_main.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/encomsp/client/encomsp_main.c 2020-07-20 13:38:46.000000000 +0000 @@ -1116,8 +1116,11 @@ if ((error = encomsp_process_receive(encomsp, data))) { WLog_ERR(TAG, "encomsp_process_receive failed with error %" PRIu32 "!", error); + Stream_Free(data, TRUE); break; } + + Stream_Free(data, TRUE); } } diff -Nru freerdp2-2.1.1+dfsg1/channels/geometry/client/geometry_main.c freerdp2-2.2.0+dfsg1/channels/geometry/client/geometry_main.c --- freerdp2-2.1.1+dfsg1/channels/geometry/client/geometry_main.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/geometry/client/geometry_main.c 2020-07-20 13:38:46.000000000 +0000 @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -82,23 +81,6 @@ return *g1 == *g2; } -void mappedGeometryRef(MAPPED_GEOMETRY* g) -{ - InterlockedIncrement(&g->refCounter); -} - -void mappedGeometryUnref(MAPPED_GEOMETRY* g) -{ - if (InterlockedDecrement(&g->refCounter)) - return; - - g->MappedGeometryUpdate = NULL; - g->MappedGeometryClear = NULL; - g->custom = NULL; - free(g->geometry.rects); - free(g); -} - static void freerdp_rgndata_reset(FREERDP_RGNDATA* data) { data->nRectCount = 0; diff -Nru freerdp2-2.1.1+dfsg1/channels/printer/client/cups/printer_cups.c freerdp2-2.2.0+dfsg1/channels/printer/client/cups/printer_cups.c --- freerdp2-2.1.1+dfsg1/channels/printer/client/cups/printer_cups.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/printer/client/cups/printer_cups.c 2020-07-20 13:38:46.000000000 +0000 @@ -69,10 +69,11 @@ static void printer_cups_get_printjob_name(char* buf, size_t size, size_t id) { time_t tt; + struct tm tres; struct tm* t; tt = time(NULL); - t = localtime(&tt); + t = localtime_r(&tt, &tres); sprintf_s(buf, size - 1, "FreeRDP Print %04d-%02d-%02d %02d-%02d-%02d - Job %" PRIdz, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, id); } diff -Nru freerdp2-2.1.1+dfsg1/channels/printer/client/win/printer_win.c freerdp2-2.2.0+dfsg1/channels/printer/client/win/printer_win.c --- freerdp2-2.1.1+dfsg1/channels/printer/client/win/printer_win.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/printer/client/win/printer_win.c 2020-07-20 13:38:46.000000000 +0000 @@ -78,13 +78,14 @@ static WCHAR* printer_win_get_printjob_name(size_t id) { time_t tt; + struct tm tres; struct tm* t; WCHAR* str; size_t len = 1024; int rc; tt = time(NULL); - t = localtime(&tt); + t = localtime_s(&tt, &tres); str = calloc(len, sizeof(WCHAR)); if (!str) diff -Nru freerdp2-2.1.1+dfsg1/channels/rail/rail_common.c freerdp2-2.2.0+dfsg1/channels/rail/rail_common.c --- freerdp2-2.1.1+dfsg1/channels/rail/rail_common.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/rail/rail_common.c 2020-07-20 13:38:46.000000000 +0000 @@ -51,9 +51,13 @@ "", "" }; -const char* rail_get_order_type_string(BYTE orderType) +const char* rail_get_order_type_string(UINT16 orderType) { - return RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)]; + UINT32 index = ((orderType & 0xF0) >> 3) + (orderType & 0x0F); + if (index >= ARRAYSIZE(RAIL_ORDER_TYPE_STRINGS)) + return "UNKNOWN"; + + return RAIL_ORDER_TYPE_STRINGS[index]; } /** diff -Nru freerdp2-2.1.1+dfsg1/channels/rail/rail_common.h freerdp2-2.2.0+dfsg1/channels/rail/rail_common.h --- freerdp2-2.1.1+dfsg1/channels/rail/rail_common.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/rail/rail_common.h 2020-07-20 13:38:46.000000000 +0000 @@ -26,8 +26,6 @@ #include -const char* rail_get_order_type_string(BYTE orderType); - #define RAIL_PDU_HEADER_LENGTH 4 /* Fixed length of PDUs, excluding variable lengths */ @@ -72,5 +70,6 @@ UINT rail_write_sysparam_order(wStream* s, const RAIL_SYSPARAM_ORDER* sysparam, BOOL extendedSpiSupported); BOOL rail_is_extended_spi_supported(UINT32 channelsFlags); +const char* rail_get_order_type_string(UINT16 orderType); #endif /* FREERDP_CHANNEL_RAIL_COMMON_H */ diff -Nru freerdp2-2.1.1+dfsg1/channels/rail/server/rail_main.c freerdp2-2.2.0+dfsg1/channels/rail/server/rail_main.c --- freerdp2-2.1.1+dfsg1/channels/rail/server/rail_main.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/rail/server/rail_main.c 2020-07-20 13:38:46.000000000 +0000 @@ -60,7 +60,7 @@ * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_send_pdu(RailServerContext* context, wStream* s, UINT16 orderType) +static UINT rail_server_send_pdu(RailServerContext* context, wStream* s, UINT16 orderType) { UINT16 orderLength; @@ -278,7 +278,7 @@ } rail_write_handshake_order(s, handshake); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE); Stream_Free(s, TRUE); return error; } @@ -297,8 +297,6 @@ if (!context || !handshakeEx || !context->priv) return ERROR_INVALID_PARAMETER; - /* Save channel flags to context */ - context->priv->channelFlags = handshakeEx->railHandshakeFlags; s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH); if (!s) @@ -307,8 +305,10 @@ return CHANNEL_RC_NO_MEMORY; } + rail_server_set_handshake_ex_flags(context, handshakeEx->railHandshakeFlags); + rail_write_handshake_ex_order(s, handshakeEx); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE_EX); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE_EX); Stream_Free(s, TRUE); return error; } @@ -344,7 +344,7 @@ } rail_write_sysparam_order(s, sysparam, extendedSpiSupported); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_SYSPARAM); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_SYSPARAM); Stream_Free(s, TRUE); return error; } @@ -372,7 +372,7 @@ } rail_write_local_move_size_order(s, localMoveSize); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_LOCALMOVESIZE); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_LOCALMOVESIZE); Stream_Free(s, TRUE); return error; } @@ -400,7 +400,7 @@ } rail_write_min_max_info_order(s, minMaxInfo); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_MINMAXINFO); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_MINMAXINFO); Stream_Free(s, TRUE); return error; } @@ -428,7 +428,7 @@ } rail_write_taskbar_info_order(s, taskbarInfo); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_TASKBARINFO); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_TASKBARINFO); Stream_Free(s, TRUE); return error; } @@ -456,7 +456,7 @@ } rail_write_langbar_info_order(s, langbarInfo); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_LANGBARINFO); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_LANGBARINFO); Stream_Free(s, TRUE); return error; } @@ -484,7 +484,7 @@ } rail_write_exec_result_order(s, execResult); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_EXEC_RESULT); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_EXEC_RESULT); Stream_Free(s, TRUE); return error; } @@ -512,7 +512,7 @@ } rail_write_z_order_sync_order(s, zOrderSync); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_ZORDER_SYNC); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_ZORDER_SYNC); Stream_Free(s, TRUE); return error; } @@ -539,7 +539,7 @@ } rail_write_cloak_order(s, cloak); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_CLOAK); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_CLOAK); Stream_Free(s, TRUE); return error; } @@ -568,7 +568,7 @@ } rail_write_power_display_request_order(s, powerDisplayRequest); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_POWER_DISPLAY_REQUEST); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_POWER_DISPLAY_REQUEST); Stream_Free(s, TRUE); return error; } @@ -596,7 +596,7 @@ } rail_write_get_app_id_resp_order(s, getAppidResp); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP); Stream_Free(s, TRUE); return error; } @@ -624,7 +624,7 @@ } rail_write_get_appid_resp_ex_order(s, getAppidRespEx); - error = rail_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP_EX); + error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP_EX); Stream_Free(s, TRUE); return error; } @@ -1522,6 +1522,17 @@ free(context); } +void rail_server_set_handshake_ex_flags(RailServerContext* context, DWORD flags) +{ + RailServerPrivate* priv; + + if (!context || !context->priv) + return; + + priv = context->priv; + priv->channelFlags = flags; +} + UINT rail_server_handle_messages(RailServerContext* context) { UINT status = CHANNEL_RC_OK; diff -Nru freerdp2-2.1.1+dfsg1/channels/rdpdr/client/rdpdr_main.c freerdp2-2.2.0+dfsg1/channels/rdpdr/client/rdpdr_main.c --- freerdp2-2.1.1+dfsg1/channels/rdpdr/client/rdpdr_main.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/rdpdr/client/rdpdr_main.c 2020-07-20 13:38:46.000000000 +0000 @@ -598,7 +598,14 @@ size_t x; char buffer[MAX_PATH]; uid_t uid = getuid(); - const char* uname = getlogin(); + char uname[MAX_PATH] = { 0 }; + +#ifndef HAVE_GETLOGIN_R + strncpy(uname, getlogin(), sizeof(uname)); +#else + if (getlogin_r(uname, sizeof(uname)) != 0) + return FALSE; +#endif if (!path) return FALSE; diff -Nru freerdp2-2.1.1+dfsg1/channels/rdpei/client/rdpei_main.c freerdp2-2.2.0+dfsg1/channels/rdpei/client/rdpei_main.c --- freerdp2-2.1.1+dfsg1/channels/rdpei/client/rdpei_main.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/rdpei/client/rdpei_main.c 2020-07-20 13:38:46.000000000 +0000 @@ -604,6 +604,7 @@ IFCALL(mgr->DestroyListener, mgr, rdpei->listener); } free(rdpei->listener_callback); + free(rdpei->contactPoints); free(rdpei->context); free(rdpei); return CHANNEL_RC_OK; diff -Nru freerdp2-2.1.1+dfsg1/channels/rdpei/rdpei_common.c freerdp2-2.2.0+dfsg1/channels/rdpei/rdpei_common.c --- freerdp2-2.1.1+dfsg1/channels/rdpei/rdpei_common.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/rdpei/rdpei_common.c 2020-07-20 13:38:46.000000000 +0000 @@ -306,7 +306,7 @@ value *= -1; } - if (value <= 0x1FUL) + if (value <= 0x1FL) { byte = value & 0x1F; @@ -315,7 +315,7 @@ Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFUL) + else if (value <= 0x1FFFL) { byte = (value >> 8) & 0x1F; @@ -326,7 +326,7 @@ byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFUL) + else if (value <= 0x1FFFFFL) { byte = (value >> 16) & 0x1F; @@ -339,7 +339,7 @@ byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFFFUL) + else if (value <= 0x1FFFFFFFL) { byte = (value >> 24) & 0x1F; diff -Nru freerdp2-2.1.1+dfsg1/channels/rdpgfx/rdpgfx_common.c freerdp2-2.2.0+dfsg1/channels/rdpgfx/rdpgfx_common.c --- freerdp2-2.1.1+dfsg1/channels/rdpgfx/rdpgfx_common.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/rdpgfx/rdpgfx_common.c 2020-07-20 13:38:46.000000000 +0000 @@ -182,6 +182,10 @@ Stream_Read_UINT16(s, rect16->top); /* top (2 bytes) */ Stream_Read_UINT16(s, rect16->right); /* right (2 bytes) */ Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ + if (rect16->left >= rect16->right) + return ERROR_INVALID_DATA; + if (rect16->top >= rect16->bottom) + return ERROR_INVALID_DATA; return CHANNEL_RC_OK; } diff -Nru freerdp2-2.1.1+dfsg1/channels/remdesk/client/remdesk_main.c freerdp2-2.2.0+dfsg1/channels/remdesk/client/remdesk_main.c --- freerdp2-2.1.1+dfsg1/channels/remdesk/client/remdesk_main.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/remdesk/client/remdesk_main.c 2020-07-20 13:38:46.000000000 +0000 @@ -843,8 +843,11 @@ if ((error = remdesk_process_receive(remdesk, data))) { WLog_ERR(TAG, "remdesk_process_receive failed with error %" PRIu32 "!", error); + Stream_Free(data, TRUE); break; } + + Stream_Free(data, TRUE); } } diff -Nru freerdp2-2.1.1+dfsg1/channels/smartcard/client/smartcard_operations.c freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_operations.c --- freerdp2-2.1.1+dfsg1/channels/smartcard/client/smartcard_operations.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_operations.c 2020-07-20 13:38:46.000000000 +0000 @@ -921,15 +921,38 @@ 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 @@ ret.ReturnCode = SCardLocateCardsW(operation->hContext, call->mszCards, call->rgReaderStates, call->cReaders); log_status_error(TAG, "SCardLocateCardsW", ret.ReturnCode); + ret.cReaders = call->cReaders; + ret.rgReaderStates = NULL; + free(call->mszCards); + + if (ret.cReaders > 0) + { + ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return)); + + if (!ret.rgReaderStates) + return STATUS_NO_MEMORY; + } + + for (x = 0; x < ret.cReaders; x++) + { + ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState; + ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState; + ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr; + CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr), + sizeof(ret.rgReaderStates[x].rgbAtr)); + } + + status = smartcard_pack_locate_cards_return(smartcard, irp->output, &ret); + for (x = 0; x < call->cReaders; x++) { SCARD_READERSTATEW* state = &call->rgReaderStates[x]; free(state->szReader); } + free(call->rgReaderStates); - status = smartcard_pack_locate_cards_return(smartcard, irp->output, &ret); if (status != SCARD_S_SUCCESS) return status; diff -Nru freerdp2-2.1.1+dfsg1/channels/smartcard/client/smartcard_pack.c freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_pack.c --- freerdp2-2.1.1+dfsg1/channels/smartcard/client/smartcard_pack.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_pack.c 2020-07-20 13:38:46.000000000 +0000 @@ -389,7 +389,7 @@ 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 @@ 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_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_w_call(SMARTCARD_DEVICE* smartcard, const ReadCacheW_Call* call) { - char* tmp; + char* tmp = NULL; char buffer[1024]; WINPR_UNUSED(smartcard); if (!WLog_IsLevelActive(WLog_Get(TAG), g_LogLevel)) diff -Nru freerdp2-2.1.1+dfsg1/channels/urbdrc/client/data_transfer.c freerdp2-2.2.0+dfsg1/channels/urbdrc/client/data_transfer.c --- freerdp2-2.1.1+dfsg1/channels/urbdrc/client/data_transfer.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/urbdrc/client/data_transfer.c 2020-07-20 13:38:46.000000000 +0000 @@ -767,8 +767,6 @@ callback->channel->Write(callback->channel, Stream_GetPosition(out), Stream_Buffer(out), NULL); } - - Stream_Free(out, TRUE); } static UINT urb_isoch_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callback, wStream* s, diff -Nru freerdp2-2.1.1+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.c freerdp2-2.2.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.c --- freerdp2-2.1.1+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.c 2020-07-20 13:38:46.000000000 +0000 @@ -81,6 +81,22 @@ #endif }; +static BOOL log_libusb_result(wLog* log, DWORD lvl, const char* fmt, int error, ...) +{ + if (error < 0) + { + char buffer[8192] = { 0 }; + va_list ap; + va_start(ap, error); + vsnprintf(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + WLog_Print(log, lvl, "%s: error %s[%d]", buffer, libusb_error_name(error), error); + return TRUE; + } + return FALSE; +} + const char* usb_interface_class_to_string(uint8_t class) { switch (class) @@ -296,7 +312,7 @@ 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); } @@ -391,11 +407,8 @@ { int ret = libusb_release_interface(libusb_handle, i); - if (ret < 0) - { - WLog_Print(urbdrc->log, WLOG_ERROR, "config_release_all_interface: error num %d", ret); + if (log_libusb_result(urbdrc->log, WLOG_WARN, "libusb_release_interface", ret)) return -1; - } } return 0; @@ -410,11 +423,8 @@ { ret = libusb_claim_interface(libusb_handle, i); - if (ret < 0) - { - WLog_Print(urbdrc->log, WLOG_ERROR, "claim_all_interface: error num %d", ret); + if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_claim_interface", ret)) return -1; - } } return 0; @@ -447,14 +457,14 @@ static LIBUSB_DEVICE_DESCRIPTOR* udev_new_descript(URBDRC_PLUGIN* urbdrc, LIBUSB_DEVICE* libusb_dev) { int ret; - LIBUSB_DEVICE_DESCRIPTOR* descriptor; - descriptor = (LIBUSB_DEVICE_DESCRIPTOR*)malloc(sizeof(LIBUSB_DEVICE_DESCRIPTOR)); + LIBUSB_DEVICE_DESCRIPTOR* descriptor = + (LIBUSB_DEVICE_DESCRIPTOR*)calloc(1, sizeof(LIBUSB_DEVICE_DESCRIPTOR)); + if (!descriptor) + return NULL; ret = libusb_get_device_descriptor(libusb_dev, descriptor); - if (ret < 0) + if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_get_device_descriptor", ret)) { - WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_get_device_descriptor: error %s [%d]", - libusb_error_name(ret), ret); free(descriptor); return NULL; } @@ -465,7 +475,7 @@ 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 +490,26 @@ if (MsConfig) { MsInterfaces = MsConfig->MsInterfaces; - - if ((MsInterfaces) && (MsInterfaces[InterfaceNumber]->AlternateSetting == AlternateSetting)) + if (MsInterfaces) { - diff = 0; - } - } + WLog_Print(urbdrc->log, WLOG_INFO, + "select Interface(%" PRIu8 ") curr AlternateSetting(%" PRIu8 + ") new AlternateSetting(" PRIu8 ")", + InterfaceNumber, MsInterfaces[InterfaceNumber]->AlternateSetting, + AlternateSetting); - if (diff) - { - error = libusb_set_interface_alt_setting(pdev->libusb_handle, InterfaceNumber, - AlternateSetting); + if (MsInterfaces[InterfaceNumber]->AlternateSetting != AlternateSetting) + { + diff = 1; + } + } - if (error < 0) + if (diff) { - WLog_Print(urbdrc->log, WLOG_ERROR, "Set interface altsetting get error num %d", error); + error = libusb_set_interface_alt_setting(pdev->libusb_handle, InterfaceNumber, + AlternateSetting); + + log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_set_interface_alt_setting", error); } } @@ -548,8 +563,7 @@ for (pnum = 0; pnum < LibusbNumEndpoint; pnum++) { - t_MsPipe = (MSUSB_PIPE_DESCRIPTOR*)malloc(sizeof(MSUSB_PIPE_DESCRIPTOR)); - memset(t_MsPipe, 0, sizeof(MSUSB_PIPE_DESCRIPTOR)); + t_MsPipe = (MSUSB_PIPE_DESCRIPTOR*)calloc(1, sizeof(MSUSB_PIPE_DESCRIPTOR)); if (pnum < MsInterface->NumberOfPipes && MsInterface->MsPipes) { @@ -687,10 +701,8 @@ else ret = libusb_set_configuration(libusb_handle, bConfigurationValue); - if (ret < 0) + if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_set_configuration", ret)) { - WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_set_configuration: error %s [%d]", - libusb_error_name(ret), ret); func_claim_all_interface(urbdrc, libusb_handle, (*LibusbConfig)->bNumInterfaces); return -1; } @@ -698,10 +710,8 @@ { ret = libusb_get_active_config_descriptor(libusb_dev, LibusbConfig); - if (ret < 0) + if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_set_configuration", ret)) { - WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_set_configuration: error %s [%d]", - libusb_error_name(ret), ret); func_claim_all_interface(urbdrc, libusb_handle, (*LibusbConfig)->bNumInterfaces); return -1; } @@ -753,7 +763,7 @@ { UDEVICE* pdev = (UDEVICE*)idev; LIBUSB_DEVICE_DESCRIPTOR* devDescriptor; - const char* strDesc = "Generic Usb String"; + const char strDesc[] = "Generic Usb String"; char deviceLocation[25] = { 0 }; BYTE bus_number; BYTE device_address; @@ -786,13 +796,16 @@ slen = data[0]; locale = data[1]; - if ((ret <= 0) || (ret < 4) || (slen < 4) || (locale != LIBUSB_DT_STRING) || + if ((ret <= 0) || (ret <= 4) || (slen <= 4) || (locale != LIBUSB_DT_STRING) || (ret > UINT8_MAX)) { + char* msg = "SHORT_DESCRIPTOR"; + if (ret < 0) + msg = libusb_error_name(ret); WLog_Print(urbdrc->log, WLOG_DEBUG, "libusb_get_string_descriptor: " - "ERROR num %d, iProduct: %" PRIu8 "!", - ret, devDescriptor->iProduct); + "%s [%d], iProduct: %" PRIu8 "!", + msg, ret, devDescriptor->iProduct); len = MIN(sizeof(strDesc), inSize); for (i = 0; i < len; i++) @@ -851,21 +864,20 @@ BYTE* Buffer, int Timeout) { UDEVICE* pdev = (UDEVICE*)idev; - BYTE ms_string_desc[0x13]; + BYTE ms_string_desc[0x13] = { 0 }; int error = 0; /* pdev->request_queue->register_request(pdev->request_queue, RequestId, NULL, 0); */ - memset(ms_string_desc, 0, 0x13); error = libusb_control_transfer(pdev->libusb_handle, LIBUSB_ENDPOINT_IN | Recipient, LIBUSB_REQUEST_GET_DESCRIPTOR, 0x03ee, 0, ms_string_desc, 0x12, Timeout); - // WLog_Print(urbdrc->log, WLOG_ERROR, "Get ms string: result number %d", error); + log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_control_transfer", error); + if (error > 0) { const BYTE bMS_Vendorcode = ms_string_desc[16]; - // WLog_Print(urbdrc->log, WLOG_ERROR, "bMS_Vendorcode:0x%x", bMS_Vendorcode); /** get os descriptor */ error = libusb_control_transfer(pdev->libusb_handle, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | Recipient, @@ -953,14 +965,12 @@ for (i = 0; i < pdev->LibusbConfig->bNumInterfaces; i++) { err = libusb_kernel_driver_active(pdev->libusb_handle, i); - WLog_Print(urbdrc->log, WLOG_DEBUG, "libusb_kernel_driver_active = %s [%d]", - libusb_error_name(err), err); + log_libusb_result(urbdrc->log, WLOG_DEBUG, "libusb_kernel_driver_active", err); if (err) { err = libusb_detach_kernel_driver(pdev->libusb_handle, i); - WLog_Print(urbdrc->log, WLOG_DEBUG, "libusb_detach_kernel_driver = %s [%d]", - libusb_error_name(err), err); + log_libusb_result(urbdrc->log, WLOG_DEBUG, "libusb_detach_kernel_driver", err); } } @@ -982,17 +992,13 @@ { err = libusb_release_interface(pdev->libusb_handle, i); - if (err < 0) - { - WLog_Print(pdev->urbdrc->log, WLOG_DEBUG, "libusb_release_interface: error num %d = %d", - i, err); - } + log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_release_interface", err); if (err != LIBUSB_ERROR_NO_DEVICE) { err = libusb_attach_kernel_driver(pdev->libusb_handle, i); - WLog_Print(pdev->urbdrc->log, WLOG_DEBUG, "libusb_attach_kernel_driver if%d = %d", i, - err); + log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_attach_kernel_driver if=%d", + err, i); } } @@ -1085,7 +1091,6 @@ return -1; urbdrc = pdev->urbdrc; - WLog_Print(urbdrc->log, WLOG_DEBUG, "..."); if (pdev->hub_handle != NULL) { @@ -1094,11 +1099,8 @@ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_OTHER, LIBUSB_REQUEST_GET_STATUS, 0, pdev->port_number, UsbdStatus, BufferSize, Buffer, 1000); - if (ret < 0) - { - WLog_Print(urbdrc->log, WLOG_DEBUG, "libusb_control_transfer: error num %d", ret); + if (log_libusb_result(urbdrc->log, WLOG_DEBUG, "libusb_control_transfer", ret)) *BufferSize = 0; - } else { WLog_Print(urbdrc->log, WLOG_DEBUG, @@ -1168,6 +1170,7 @@ 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); } @@ -1189,8 +1192,7 @@ if (status >= 0) *BufferSize = (UINT32)status; else - WLog_Print(pdev->urbdrc->log, WLOG_ERROR, "libusb_control_transfer %s [%d]", - libusb_error_name(status), status); + log_libusb_result(pdev->urbdrc->log, WLOG_ERROR, "libusb_control_transfer", status); if (!func_set_usbd_status(pdev->urbdrc, pdev, UrbdStatus, status)) return FALSE; @@ -1292,13 +1294,9 @@ return -1; status = libusb_cancel_transfer(transfer); - HashTable_Remove(queue, (void*)(size_t)streamID); - if (status < 0) + if (log_libusb_result(urbdrc->log, WLOG_WARN, "libusb_cancel_transfer", status)) { - WLog_Print(urbdrc->log, WLOG_WARN, "libusb_cancel_transfer: error num %s [%d]", - libusb_error_name(status), status); - if (status == LIBUSB_ERROR_NOT_FOUND) return -1; } @@ -1348,6 +1346,7 @@ 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); } @@ -1399,11 +1398,7 @@ { rc = libusb_reset_device(udev->libusb_handle); - if (rc != LIBUSB_SUCCESS) - { - WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_reset_device: error %s [%d]", - libusb_error_name(rc), rc); - } + log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_reset_device", rc); } /* release all interface and attach kernel driver */ @@ -1480,12 +1475,8 @@ error = libusb_open(libusb_list[i], &handle); - if (error < 0) - { - WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_open error: %i - %s", error, - libusb_error_name(error)); + if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_open", error)) break; - } /* get port number */ error = libusb_get_port_numbers(libusb_list[i], port_numbers, sizeof(port_numbers)); @@ -1494,8 +1485,7 @@ if (error < 1) { /* Prevent open hub, treat as error. */ - WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_get_port_numbers error: %i - %s", error, - libusb_error_name(error)); + log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_get_port_numbers", error); break; } @@ -1503,7 +1493,8 @@ error = 0; WLog_Print(urbdrc->log, WLOG_DEBUG, " Port: %d", pdev->port_number); /* gen device path */ - sprintf(pdev->path, "ugen%" PRIu16 ".%" PRIu16 "", bus_number, dev_number); + sprintf(pdev->path, "%" PRIu16 "-%" PRIu16 "", bus_number, pdev->port_number); + WLog_Print(urbdrc->log, WLOG_DEBUG, " DevPath: %s", pdev->path); break; } @@ -1525,10 +1516,7 @@ WLog_Print(urbdrc->log, WLOG_DEBUG, " Open hub: %" PRIu16 "", bus_number); error = libusb_open(libusb_list[i], &handle); - if (error < 0) - WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_open error: %i - %s", error, - libusb_error_name(error)); - else + if (!log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_open", error)) pdev->hub_handle = handle; break; @@ -1598,10 +1586,9 @@ if (status != LIBUSB_SUCCESS) { - WLog_Print( - urbdrc->log, WLOG_ERROR, - "libusb_open error: %i - %s [b=0x%02X,p=0x%02X,a=0x%02X,VID=0x%04X,PID=0x%04X]", - status, libusb_error_name(status), bus, port, addr, desc.idVendor, desc.idProduct); + log_libusb_result(urbdrc->log, WLOG_ERROR, + "libusb_open [b=0x%02X,p=0x%02X,a=0x%02X,VID=0x%04X,PID=0x%04X]", + status, bus, port, addr, desc.idVendor, desc.idProduct); goto fail; } } @@ -1635,9 +1622,9 @@ { pdev->isCompositeDevice = 1; } - else if ((devDescriptor->bDeviceClass == LIBUSB_CLASS_APPLICATION) && + else if ((devDescriptor->bDeviceClass == 0xef) && (devDescriptor->bDeviceSubClass == LIBUSB_CLASS_COMM) && - (devDescriptor->bDeviceProtocol == LIBUSB_CLASS_AUDIO)) + (devDescriptor->bDeviceProtocol == 0x01)) { pdev->isCompositeDevice = 1; } diff -Nru freerdp2-2.1.1+dfsg1/channels/urbdrc/client/libusb/libusb_udevman.c freerdp2-2.2.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevman.c --- freerdp2-2.1.1+dfsg1/channels/urbdrc/client/libusb/libusb_udevman.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevman.c 2020-07-20 13:38:46.000000000 +0000 @@ -665,7 +665,7 @@ } else { - idpair = malloc(sizeof(VID_PID_PAIR)); + idpair = calloc(1, sizeof(VID_PID_PAIR)); if (!idpair) return CHANNEL_RC_NO_MEMORY; idpair->vid = id1; diff -Nru freerdp2-2.1.1+dfsg1/channels/urbdrc/client/urbdrc_main.c freerdp2-2.2.0+dfsg1/channels/urbdrc/client/urbdrc_main.c --- freerdp2-2.1.1+dfsg1/channels/urbdrc/client/urbdrc_main.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/urbdrc/client/urbdrc_main.c 2020-07-20 13:38:46.000000000 +0000 @@ -86,7 +86,7 @@ static int func_container_id_generate(IUDEVICE* pdev, char* strContainerId) { char *p, *path; - UINT8 containerId[17]; + UINT8 containerId[17] = { 0 }; UINT16 idVendor, idProduct; idVendor = (UINT16)pdev->query_device_descriptor(pdev, ID_VENDOR); idProduct = (UINT16)pdev->query_device_descriptor(pdev, ID_PRODUCT); @@ -97,7 +97,6 @@ else p = path; - ZeroMemory(containerId, sizeof(containerId)); sprintf_s((char*)containerId, sizeof(containerId), "%04" PRIX16 "%04" PRIX16 "%s", idVendor, idProduct, p); /* format */ @@ -114,7 +113,7 @@ static int func_instance_id_generate(IUDEVICE* pdev, char* strInstanceId, size_t len) { - char instanceId[17]; + char instanceId[17] = { 0 }; sprintf_s(instanceId, sizeof(instanceId), "\\%s", pdev->getPath(pdev)); /* format */ sprintf_s(strInstanceId, len, diff -Nru freerdp2-2.1.1+dfsg1/channels/urbdrc/CMakeLists.txt freerdp2-2.2.0+dfsg1/channels/urbdrc/CMakeLists.txt --- freerdp2-2.1.1+dfsg1/channels/urbdrc/CMakeLists.txt 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/urbdrc/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 @@ -21,6 +21,8 @@ add_subdirectory(common) if(WITH_CLIENT_CHANNELS) + option(WITH_DEBUG_URBDRC "Dump data send/received in URBDRC channel" OFF) + find_package(libusb-1.0 REQUIRED) include_directories(${LIBUSB_1_INCLUDE_DIRS}) diff -Nru freerdp2-2.1.1+dfsg1/channels/urbdrc/common/urbdrc_helpers.c freerdp2-2.2.0+dfsg1/channels/urbdrc/common/urbdrc_helpers.c --- freerdp2-2.1.1+dfsg1/channels/urbdrc/common/urbdrc_helpers.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/channels/urbdrc/common/urbdrc_helpers.c 2020-07-20 13:38:46.000000000 +0000 @@ -17,8 +17,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "urbdrc_helpers.h" #include "urbdrc_types.h" +#include const char* mask_to_string(UINT32 mask) { @@ -405,4 +410,12 @@ ", FunctionId=%08" PRIx32 ", length=%" PRIdz, type, call_to_string(client, InterfaceId, FunctionId), FunctionId, InterfaceId, MessageId, FunctionId, length); +#if defined(WITH_DEBUG_URBDRC) + if (write) + WLog_Print(log, WLOG_TRACE, "-------------------------- URBDRC sent: ---"); + else + WLog_Print(log, WLOG_TRACE, "-------------------------- URBDRC received:"); + winpr_HexLogDump(log, WLOG_TRACE, Stream_Buffer(s), length); + WLog_Print(log, WLOG_TRACE, "-------------------------- URBDRC end -----"); +#endif } diff -Nru freerdp2-2.1.1+dfsg1/client/common/client.c freerdp2-2.2.0+dfsg1/client/common/client.c --- freerdp2-2.1.1+dfsg1/client/common/client.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/client/common/client.c 2020-07-20 13:38:46.000000000 +0000 @@ -467,14 +467,17 @@ { case 'y': case 'Y': + fgetc(stdin); return 1; case 't': case 'T': + fgetc(stdin); return 2; case 'n': case 'N': + fgetc(stdin); return 0; default: diff -Nru freerdp2-2.1.1+dfsg1/client/common/CMakeLists.txt freerdp2-2.2.0+dfsg1/client/common/CMakeLists.txt --- freerdp2-2.1.1+dfsg1/client/common/CMakeLists.txt 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/client/common/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 @@ -30,7 +30,8 @@ cmdline.c compatibility.c compatibility.h - file.c) + file.c + geometry.c) foreach(FREERDP_CHANNELS_CLIENT_SRC ${FREERDP_CHANNELS_CLIENT_SRCS}) get_filename_component(NINC ${FREERDP_CHANNELS_CLIENT_SRC} PATH) diff -Nru freerdp2-2.1.1+dfsg1/client/common/geometry.c freerdp2-2.2.0+dfsg1/client/common/geometry.c --- freerdp2-2.1.1+dfsg1/client/common/geometry.c 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/client/common/geometry.c 2020-07-20 13:38:46.000000000 +0000 @@ -0,0 +1,42 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Geometry tracking Virtual Channel Extension + * + * Copyright 2017 David Fort + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +void mappedGeometryRef(MAPPED_GEOMETRY* g) +{ + InterlockedIncrement(&g->refCounter); +} + +void mappedGeometryUnref(MAPPED_GEOMETRY* g) +{ + if (InterlockedDecrement(&g->refCounter)) + return; + + g->MappedGeometryUpdate = NULL; + g->MappedGeometryClear = NULL; + g->custom = NULL; + free(g->geometry.rects); + free(g); +} diff -Nru freerdp2-2.1.1+dfsg1/client/Wayland/wlf_input.c freerdp2-2.2.0+dfsg1/client/Wayland/wlf_input.c --- freerdp2-2.1.1+dfsg1/client/Wayland/wlf_input.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/client/Wayland/wlf_input.c 2020-07-20 13:38:46.000000000 +0000 @@ -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 @@ } } + 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 @@ 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 @@ } } + 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 @@ } } + if (i == MAX_CONTACTS) + return FALSE; + WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y); if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE)) diff -Nru freerdp2-2.1.1+dfsg1/client/Wayland/wlfreerdp.c freerdp2-2.2.0+dfsg1/client/Wayland/wlfreerdp.c --- freerdp2-2.1.1+dfsg1/client/Wayland/wlfreerdp.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/client/Wayland/wlfreerdp.c 2020-07-20 13:38:46.000000000 +0000 @@ -62,6 +62,7 @@ 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 @@ 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 @@ 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 @@ 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 BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display) { + BOOL rc; UwacEvent event; wlfContext* context; @@ -321,9 +330,11 @@ 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 @@ if (!wfl->displayHandle) return FALSE; + InitializeCriticalSection(&wfl->critical); + return TRUE; } @@ -567,6 +580,7 @@ if (wlf->displayHandle) CloseHandle(wlf->displayHandle); + DeleteCriticalSection(&wlf->critical); } static int wfl_client_start(rdpContext* context) diff -Nru freerdp2-2.1.1+dfsg1/client/Wayland/wlfreerdp.h freerdp2-2.2.0+dfsg1/client/Wayland/wlfreerdp.h --- freerdp2-2.1.1+dfsg1/client/Wayland/wlfreerdp.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/client/Wayland/wlfreerdp.h 2020-07-20 13:38:46.000000000 +0000 @@ -50,6 +50,7 @@ wfClipboard* clipboard; wlfDispContext* disp; wLog* log; + CRITICAL_SECTION critical; }; BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP); diff -Nru freerdp2-2.1.1+dfsg1/client/X11/generate_argument_docbook.c freerdp2-2.2.0+dfsg1/client/X11/generate_argument_docbook.c --- freerdp2-2.1.1+dfsg1/client/X11/generate_argument_docbook.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/client/X11/generate_argument_docbook.c 2020-07-20 13:38:46.000000000 +0000 @@ -89,7 +89,7 @@ strncpy(&tmp[cs], "", len); else /* coverity[buffer_size] */ - strncpy(&tmp[cs], "<", len); + strncpy(&tmp[cs], ">", len); cs += len; break; diff -Nru freerdp2-2.1.1+dfsg1/client/X11/xf_client.c freerdp2-2.2.0+dfsg1/client/X11/xf_client.c --- freerdp2-2.1.1+dfsg1/client/X11/xf_client.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/client/X11/xf_client.c 2020-07-20 13:38:46.000000000 +0000 @@ -1120,7 +1120,7 @@ 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 @@ 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,16 @@ if (!settings->Username && !settings->CredentialsFromStdin && !settings->SmartcardLogon) { - char* login_name = getlogin(); + int rc; + char login_name[MAX_PATH] = { 0 }; - if (login_name) +#ifdef HAVE_GETLOGIN_R + rc = getlogin_r(login_name, sizeof(login_name)); +#else + strncpy(login_name, getlogin(), sizeof(login_name)); + rc = 0; +#endif + if (rc == 0) { settings->Username = _strdup(login_name); diff -Nru freerdp2-2.1.1+dfsg1/client/X11/xf_event.c freerdp2-2.2.0+dfsg1/client/X11/xf_event.c --- freerdp2-2.1.1+dfsg1/client/X11/xf_event.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/client/X11/xf_event.c 2020-07-20 13:38:46.000000000 +0000 @@ -374,12 +374,12 @@ } static BOOL xf_event_MotionNotify(xfContext* xfc, const XMotionEvent* event, BOOL app) { - if (xfc->use_xinput) - return TRUE; - if (xfc->window) xf_floatbar_set_root_y(xfc->window->floatbar, event->y); + if (xfc->use_xinput) + return TRUE; + return xf_generic_MotionNotify(xfc, event->x, event->y, event->state, event->window, app); } diff -Nru freerdp2-2.1.1+dfsg1/CMakeLists.txt freerdp2-2.2.0+dfsg1/CMakeLists.txt --- freerdp2-2.1.1+dfsg1/CMakeLists.txt 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 @@ -81,7 +81,7 @@ endif() set(WITH_LIBRARY_VERSIONING "ON") -set(RAW_VERSION_STRING "2.1.1") +set(RAW_VERSION_STRING "2.2.0") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) @@ -341,106 +341,99 @@ endif() endif() +set(THREAD_PREFER_PTHREAD_FLAG TRUE) + +if(NOT IOS) + find_package(Threads REQUIRED) +endif() + +if(NOT WIN32) + CHECK_SYMBOL_EXISTS(pthread_mutex_timedlock pthread.h HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL) + if (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL) + CHECK_LIBRARY_EXISTS(pthread pthread_mutex_timedlock "" HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB) + endif (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL) + if (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB) + CHECK_LIBRARY_EXISTS(pthreads pthread_mutex_timedlock "" HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIBS) + endif (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB) + + if (HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIBS) + set(HAVE_PTHREAD_MUTEX_TIMEDLOCK ON) + endif (HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIBS) +endif() + # Enable address sanitizer, where supported and when required if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCC) - set(CMAKE_REQUIRED_FLAGS_SAVED ${CMAKE_REQUIRED_FLAGS}) - CHECK_C_COMPILER_FLAG ("-fno-omit-frame-pointer" fno-omit-frame-pointer) + if (fno-omit-frame-pointer) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer") + endif() + + set(CMAKE_REQUIRED_LINK_OPTIONS_SAVED ${CMAKE_REQUIRED_LINK_OPTIONS}) file(WRITE ${CMAKE_BINARY_DIR}/foo.txt "") if(WITH_SANITIZE_ADDRESS) - set(CMAKE_REQUIRED_FLAGS "-fsanitize=address") + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "-fsanitize=address") CHECK_C_COMPILER_FLAG ("-fsanitize=address" fsanitize-address) CHECK_C_COMPILER_FLAG ("-fsanitize-blacklist=${CMAKE_BINARY_DIR}/foo.txt" fsanitize-blacklist) CHECK_C_COMPILER_FLAG ("-fsanitize-address-use-after-scope" fsanitize-address-use-after-scope) - unset(CMAKE_REQUIRED_FLAGS) - if(fsanitize-address) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") - - if(fsanitize-blacklist) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-address-sanitizer.txt") - endif(fsanitize-blacklist) - - if(fsanitize-address-use-after-scope) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-address-use-after-scope") - endif(fsanitize-address-use-after-scope) - - else(fsanitize-address) - message(WARNING "Missing support for address sanitizer!") - endif(fsanitize-address) - - if(fno-omit-frame-pointer) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer") - endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") + + if(fsanitize-blacklist) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-address-sanitizer.txt") + endif(fsanitize-blacklist) + + if(fsanitize-address-use-after-scope) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-address-use-after-scope") + endif(fsanitize-address-use-after-scope) elseif(WITH_SANITIZE_MEMORY) - set(CMAKE_REQUIRED_FLAGS "-fsanitize=memory") + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "-fsanitize=memory") CHECK_C_COMPILER_FLAG ("-fsanitize=memory" fsanitize-memory) CHECK_C_COMPILER_FLAG ("-fsanitize-blacklist=${CMAKE_BINARY_DIR}/foo.txt" fsanitize-blacklist) CHECK_C_COMPILER_FLAG ("-fsanitize-memory-use-after-dtor" fsanitize-memory-use-after-dtor) CHECK_C_COMPILER_FLAG ("-fsanitize-memory-track-origins" fsanitize-memory-track-origins) - unset(CMAKE_REQUIRED_FLAGS) - - if(fsanitize-memory) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=memory") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=memory") - - if(fsanitize-blacklist) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-memory-sanitizer.txt") - endif(fsanitize-blacklist) - - if (fsanitize-memory-use-after-dtor) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-memory-use-after-dtor") - endif(fsanitize-memory-use-after-dtor) - - if (fsanitize-memory-track-origins) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-memory-track-origins") - endif(fsanitize-memory-track-origins) - - else(fsanitize-memory) - message(WARNING "Missing support for memory sanitizer!") - endif(fsanitize-memory) - if(fno-omit-frame-pointer) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer") - endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=memory") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=memory") + + if(fsanitize-blacklist) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-memory-sanitizer.txt") + endif(fsanitize-blacklist) + + if (fsanitize-memory-use-after-dtor) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-memory-use-after-dtor") + endif(fsanitize-memory-use-after-dtor) + + if (fsanitize-memory-track-origins) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-memory-track-origins") + endif(fsanitize-memory-track-origins) elseif(WITH_SANITIZE_THREAD) + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "-fsanitize=thread") CHECK_C_COMPILER_FLAG ("-fsanitize=thread" fsanitize-thread) CHECK_C_COMPILER_FLAG ("-fsanitize-blacklist=${CMAKE_BINARY_DIR}/foo.txt" fsanitize-blacklist) - unset(CMAKE_REQUIRED_FLAGS) - if(fsanitize-thread) - set(CMAKE_REQUIRED_FLAGS "-Werror -fsanitize=thread") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread") - if(fsanitize-blacklist) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-thread-sanitizer.txt") - endif(fsanitize-blacklist) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=thread") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread") - else(fsanitize-thread) - message(WARNING "Missing support for thread sanitizer!") - endif(fsanitize-thread) - if(fno-omit-frame-pointer) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer") - endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread") + if(fsanitize-blacklist) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-thread-sanitizer.txt") + endif(fsanitize-blacklist) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=thread") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread") endif() file(REMOVE ${CMAKE_BINARY_DIR}/foo.txt) + set(CMAKE_REQUIRED_LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS_SAVED}) if (WITH_NO_UNDEFINED) - set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined") CHECK_C_COMPILER_FLAG (-Wl,--no-undefined no-undefined) - unset(CMAKE_REQUIRED_FLAGS) if(no-undefined) + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined" ) SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined" ) endif() endif() - - set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVED}) endif() if(MSVC) @@ -626,26 +619,6 @@ endif(WITH_GPROF) endif() -set(CMAKE_THREAD_PREFER_PTHREAD TRUE) - -if(NOT IOS) - find_package(Threads REQUIRED) -endif() - -if(NOT WIN32) - CHECK_SYMBOL_EXISTS(pthread_mutex_timedlock pthread.h HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL) - if (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL) - CHECK_LIBRARY_EXISTS(pthread pthread_mutex_timedlock "" HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB) - endif (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL) - if (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB) - CHECK_LIBRARY_EXISTS(pthreads pthread_mutex_timedlock "" HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIBS) - endif (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB) - - if (HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIBS) - set(HAVE_PTHREAD_MUTEX_TIMEDLOCK ON) - endif (HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIBS) -endif() - if(WITH_VALGRIND_MEMCHECK) check_include_files(valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H) else() @@ -671,6 +644,10 @@ list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES m) set(X11_FEATURE_TYPE "RECOMMENDED") set(WAYLAND_FEATURE_TYPE "RECOMMENDED") + + include(CheckFunctionExists) + + check_function_exists(getlogin_r HAVE_GETLOGIN_R) else() set(X11_FEATURE_TYPE "DISABLED") set(WAYLAND_FEATURE_TYPE "DISABLED") diff -Nru freerdp2-2.1.1+dfsg1/config.h.in freerdp2-2.2.0+dfsg1/config.h.in --- freerdp2-2.1.1+dfsg1/config.h.in 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/config.h.in 2020-07-20 13:38:46.000000000 +0000 @@ -24,6 +24,7 @@ #cmakedefine HAVE_PTHREAD_MUTEX_TIMEDLOCK #cmakedefine HAVE_VALGRIND_MEMCHECK_H #cmakedefine HAVE_EXECINFO_H +#cmakedefine HAVE_GETLOGIN_R /* Features */ #cmakedefine SWRESAMPLE_FOUND @@ -159,6 +160,7 @@ #cmakedefine WITH_DEBUG_RDPEI #cmakedefine WITH_DEBUG_TIMEZONE #cmakedefine WITH_DEBUG_THREADS +#cmakedefine WITH_DEBUG_URBDRC #cmakedefine WITH_DEBUG_MUTEX #cmakedefine WITH_DEBUG_TRANSPORT #cmakedefine WITH_DEBUG_WND diff -Nru freerdp2-2.1.1+dfsg1/debian/changelog freerdp2-2.2.0+dfsg1/debian/changelog --- freerdp2-2.1.1+dfsg1/debian/changelog 2020-05-25 16:58:15.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/debian/changelog 2020-08-26 11:33:46.000000000 +0000 @@ -1,3 +1,13 @@ +freerdp2 (2.2.0+dfsg1-0ubuntu0.20.04.1) focal-security; urgency=medium + + * Updated to 2.2.0 to fix multiple security issues. + - debian/*symbols: updated for new version. + - CVE-2020-4030, CVE-2020-4031, CVE-2020-4032, CVE-2020-4033, + CVE-2020-11095, CVE-2020-11096, CVE-2020-11097, CVE-2020-11098, + CVE-2020-11099, CVE-2020-15103 + + -- Marc Deslauriers Wed, 26 Aug 2020 07:33:46 -0400 + freerdp2 (2.1.1+dfsg1-0ubuntu0.20.04.1) focal-security; urgency=medium * Updated to 2.1.1 to fix multiple security issues. diff -Nru freerdp2-2.1.1+dfsg1/debian/libfreerdp2-2.symbols freerdp2-2.2.0+dfsg1/debian/libfreerdp2-2.symbols --- freerdp2-2.1.1+dfsg1/debian/libfreerdp2-2.symbols 2020-05-16 09:37:38.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/debian/libfreerdp2-2.symbols 2020-08-26 11:33:46.000000000 +0000 @@ -269,6 +269,7 @@ freerdp_get_version_string@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_glyph_convert@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_handle_signals@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + freerdp_heartbeat_send_heartbeat_pdu@Base 2.2.0+dfsg1 freerdp_image_copy@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_image_copy_from_icon_data@Base 2.1.0+dfsg1 freerdp_image_copy_from_monochrome@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 diff -Nru freerdp2-2.1.1+dfsg1/debian/libfreerdp-server2-2.symbols freerdp2-2.2.0+dfsg1/debian/libfreerdp-server2-2.symbols --- freerdp2-2.1.1+dfsg1/debian/libfreerdp-server2-2.symbols 2020-05-25 16:58:15.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/debian/libfreerdp-server2-2.symbols 2020-08-26 11:33:46.000000000 +0000 @@ -15,6 +15,7 @@ rail_server_context_free@Base 2.1.0+dfsg1 rail_server_context_new@Base 2.1.0+dfsg1 rail_server_handle_messages@Base 2.1.0+dfsg1 + rail_server_set_handshake_ex_flags@Base 2.2.0+dfsg1 rdpdr_server_context_free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rdpdr_server_context_new@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rdpei_server_context_free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 diff -Nru freerdp2-2.1.1+dfsg1/debian/libwinpr2-2.symbols freerdp2-2.2.0+dfsg1/debian/libwinpr2-2.symbols --- freerdp2-2.1.1+dfsg1/debian/libwinpr2-2.symbols 2020-05-25 16:58:15.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/debian/libwinpr2-2.symbols 2020-08-26 11:33:46.000000000 +0000 @@ -1569,6 +1569,7 @@ winpr_backtrace_free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 winpr_backtrace_symbols@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 winpr_backtrace_symbols_fd@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + winpr_bitmap_construct_header@Base 2.1.2+dfsg1 winpr_bitmap_write@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 winpr_get_build_config@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 winpr_get_build_date@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 diff -Nru freerdp2-2.1.1+dfsg1/include/freerdp/freerdp.h freerdp2-2.2.0+dfsg1/include/freerdp/freerdp.h --- freerdp2-2.1.1+dfsg1/include/freerdp/freerdp.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/include/freerdp/freerdp.h 2020-07-20 13:38:46.000000000 +0000 @@ -54,6 +54,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" @@ -309,7 +310,9 @@ ALIGN64 rdpAutoDetect* autodetect; /* (offset 19) Auto-Detect handle for the connection. Will be initialized by a call to freerdp_context_new() */ - UINT64 paddingB[32 - 20]; /* 20 */ + ALIGN64 rdpHeartbeat* heartbeat; /* (offset 21) */ + + UINT64 paddingB[32 - 21]; /* 21 */ ALIGN64 size_t ContextSize; /* (offset 32) diff -Nru freerdp2-2.1.1+dfsg1/include/freerdp/heartbeat.h freerdp2-2.2.0+dfsg1/include/freerdp/heartbeat.h --- freerdp2-2.1.1+dfsg1/include/freerdp/heartbeat.h 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/include/freerdp/heartbeat.h 2020-07-20 13:38:46.000000000 +0000 @@ -0,0 +1,46 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Heartbeat PDUs + * + * Copyright 2014 Dell Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_HEARTBEAT_H +#define FREERDP_HEARTBEAT_H + +#include + +typedef struct rdp_heartbeat rdpHeartbeat; + +typedef BOOL (*pServerHeartbeat)(freerdp* instance, BYTE period, BYTE count1, BYTE count2); + +struct rdp_heartbeat +{ + pServerHeartbeat ServerHeartbeat; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + + FREERDP_API BOOL freerdp_heartbeat_send_heartbeat_pdu(freerdp_peer* peer, BYTE period, + BYTE count1, BYTE count2); + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_HEARTBEAT_H */ diff -Nru freerdp2-2.1.1+dfsg1/include/freerdp/scancode.h freerdp2-2.2.0+dfsg1/include/freerdp/scancode.h --- freerdp2-2.1.1+dfsg1/include/freerdp/scancode.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/include/freerdp/scancode.h 2020-07-20 13:38:46.000000000 +0000 @@ -166,7 +166,6 @@ #define RDP_SCANCODE_TAB_JP MAKE_RDP_SCANCODE(0x7C, FALSE) /* JP TAB */ #define RDP_SCANCODE_BACKSLASH_JP MAKE_RDP_SCANCODE(0x7D, FALSE) /* JP OEM_5 ('\') */ #define RDP_SCANCODE_ABNT_C2 MAKE_RDP_SCANCODE(0x7E, FALSE) /* VK_ABNT_C2, JP */ -#define RDP_SCANCODE_ABNT_C2 MAKE_RDP_SCANCODE(0x7E, FALSE) /* JP OEM_PA2 */ #define RDP_SCANCODE_HANJA MAKE_RDP_SCANCODE(0x71, FALSE) /* KR VK_HANJA */ #define RDP_SCANCODE_HANGUL MAKE_RDP_SCANCODE(0x72, FALSE) /* KR VK_HANGUL */ @@ -229,4 +228,10 @@ /* Misc. */ #define RDP_SCANCODE_LAUNCH_MAIL MAKE_RDP_SCANCODE(0x6C, TRUE) /* VK_LAUNCH_MAIL */ +#define RDP_SCANCODE_LAUNCH_MEDIA_SELECT \ + MAKE_RDP_SCANCODE(0x6D, TRUE) /* VK_LAUNCH_MEDIA_SELECT \ + */ +#define RDP_SCANCODE_LAUNCH_APP1 MAKE_RDP_SCANCODE(0x6E, TRUE) /* VK_LAUNCH_APP1 */ +#define RDP_SCANCODE_LAUNCH_APP2 MAKE_RDP_SCANCODE(0x6F, TRUE) /* VK_LAUNCH_APP2 */ + #endif /* FREERDP_LOCALE_KEYBOARD_RDP_SCANCODE_H */ diff -Nru freerdp2-2.1.1+dfsg1/include/freerdp/server/rail.h freerdp2-2.2.0+dfsg1/include/freerdp/server/rail.h --- freerdp2-2.1.1+dfsg1/include/freerdp/server/rail.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/include/freerdp/server/rail.h 2020-07-20 13:38:46.000000000 +0000 @@ -141,6 +141,7 @@ FREERDP_API RailServerContext* rail_server_context_new(HANDLE vcm); FREERDP_API void rail_server_context_free(RailServerContext* context); FREERDP_API UINT rail_server_handle_messages(RailServerContext* context); + FREERDP_API void rail_server_set_handshake_ex_flags(RailServerContext* context, DWORD flags); #ifdef __cplusplus } diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/cache/glyph.c freerdp2-2.2.0+dfsg1/libfreerdp/cache/glyph.c --- freerdp2-2.1.1+dfsg1/libfreerdp/cache/glyph.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/cache/glyph.c 2020-07-20 13:38:46.000000000 +0000 @@ -579,7 +579,7 @@ return FALSE; } - if (index > glyphCache->glyphCache[id].number) + if (index >= glyphCache->glyphCache[id].number) { WLog_ERR(TAG, "invalid glyph cache index: %" PRIu32 " in cache id: %" PRIu32 "", index, id); return FALSE; diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/codec/dsp_ffmpeg.c freerdp2-2.2.0+dfsg1/libfreerdp/codec/dsp_ffmpeg.c --- freerdp2-2.1.1+dfsg1/libfreerdp/codec/dsp_ffmpeg.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/codec/dsp_ffmpeg.c 2020-07-20 13:38:46.000000000 +0000 @@ -79,6 +79,7 @@ case AV_CODEC_ID_NONE: return TRUE; + case AV_CODEC_ID_GSM_MS: case AV_CODEC_ID_AAC: case AV_CODEC_ID_AAC_LATM: #if !defined(WITH_DSP_EXPERIMENTAL) diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/codec/include/bitmap.c freerdp2-2.2.0+dfsg1/libfreerdp/codec/include/bitmap.c --- freerdp2-2.1.1+dfsg1/libfreerdp/codec/include/bitmap.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/codec/include/bitmap.c 2020-07-20 13:38:46.000000000 +0000 @@ -201,6 +201,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ return FALSE; UNROLL(runLength, { + if (pbSrc >= pbEnd) + return FALSE; SRCREADPIXEL(temp, pbSrc); SRCNEXTPIXEL(pbSrc); DESTWRITEPIXEL(pbDest, temp); diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/codec/interleaved.c freerdp2-2.2.0+dfsg1/libfreerdp/codec/interleaved.c --- freerdp2-2.1.1+dfsg1/libfreerdp/codec/interleaved.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/codec/interleaved.c 2020-07-20 13:38:46.000000000 +0000 @@ -232,7 +232,8 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix) { - *(UINT16*)_buf = _pix; + _buf[0] = _pix & 0xFF; + _buf[1] = (_pix >> 8) & 0xFF; } #undef DESTWRITEPIXEL diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/codec/nsc.c freerdp2-2.2.0+dfsg1/libfreerdp/codec/nsc.c --- freerdp2-2.1.1+dfsg1/libfreerdp/codec/nsc.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/codec/nsc.c 2020-07-20 13:38:46.000000000 +0000 @@ -364,7 +364,7 @@ if (context->priv) { - for (i = 0; i < 4; i++) + for (i = 0; i < 5; i++) free(context->priv->PlaneBuffers[i]); nsc_profiler_print(context->priv); diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/common/assistance.c freerdp2-2.2.0+dfsg1/libfreerdp/common/assistance.c --- freerdp2-2.1.1+dfsg1/libfreerdp/common/assistance.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/common/assistance.c 2020-07-20 13:38:46.000000000 +0000 @@ -361,6 +361,14 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ return -1; } + if (p > q) + { + WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field order for "); + return -1; + } + q += sizeof("") - 1; length = q - p; file->ConnectionString2 = (char*)malloc(length + 1); diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/freerdp.c freerdp2-2.2.0+dfsg1/libfreerdp/core/freerdp.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/freerdp.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/freerdp.c 2020-07-20 13:38:46.000000000 +0000 @@ -672,6 +672,7 @@ instance->update = rdp->update; instance->settings = rdp->settings; instance->autodetect = rdp->autodetect; + instance->heartbeat = rdp->heartbeat; context->graphics = graphics_new(context); if (!context->graphics) diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/ntlm.c freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/ntlm.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/ntlm.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/ntlm.c 2020-07-20 13:38:46.000000000 +0000 @@ -160,7 +160,7 @@ 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 @@ if (!ntlm->ServicePrincipalName) goto error; - if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName) != - ERROR_SUCCESS) + if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, hostnameX, &SpnLength, + ntlm->ServicePrincipalName) != ERROR_SUCCESS) goto error; status = TRUE; diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rdg.c freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rdg.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rdg.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rdg.c 2020-07-20 13:38:46.000000000 +0000 @@ -1167,7 +1167,7 @@ return TRUE; } -BOOL rdg_connect(rdpRdg* rdg, int timeout, BOOL* rpcFallback) +BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback) { BOOL status; SOCKET outConnSocket = 0; diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rdg.h freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rdg.h --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rdg.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rdg.h 2020-07-20 13:38:46.000000000 +0000 @@ -44,7 +44,7 @@ FREERDP_LOCAL BIO* rdg_get_front_bio_and_take_ownership(rdpRdg* rdg); -FREERDP_LOCAL BOOL rdg_connect(rdpRdg* rdg, int timeout, BOOL* rpcFallback); +FREERDP_LOCAL BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback); FREERDP_LOCAL DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count); #endif /* FREERDP_LIB_CORE_GATEWAY_RDG_H */ diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rpc_bind.c freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc_bind.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rpc_bind.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc_bind.c 2020-07-20 13:38:46.000000000 +0000 @@ -190,12 +190,13 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ offset = 20; rpc_offset_pad(&offset, auth_3_pdu->auth_verifier.auth_pad_length); CopyMemory(&buffer[offset], &auth_3_pdu->auth_verifier.auth_type, 8); - CopyMemory(&buffer[offset + 8], auth_3_pdu->auth_verifier.auth_value, auth_3_pdu->auth_length); - offset += (8 + auth_3_pdu->auth_length); - length = auth_3_pdu->frag_length; - clientCall = rpc_client_call_new(auth_3_pdu->call_id, 0); + CopyMemory(&buffer[offset + 8], auth_3_pdu->auth_verifier.auth_value, + auth_3_pdu->header.auth_length); + offset += (8 + auth_3_pdu->header.auth_length); + length = auth_3_pdu->header.frag_length; + clientCall = rpc_client_call_new(auth_3_pdu->header.call_id, 0); if (ArrayList_Add(rpc->client->ClientCallList, clientCall) >= 0) { diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rpc.c freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rpc.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc.c 2020-07-20 13:38:46.000000000 +0000 @@ -139,14 +139,14 @@ } } -void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_hdr_t* header) +void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header) { - header->common.rpc_vers = rpc->rpc_vers; - header->common.rpc_vers_minor = rpc->rpc_vers_minor; - header->common.packed_drep[0] = rpc->packed_drep[0]; - header->common.packed_drep[1] = rpc->packed_drep[1]; - header->common.packed_drep[2] = rpc->packed_drep[2]; - header->common.packed_drep[3] = rpc->packed_drep[3]; + header->rpc_vers = rpc->rpc_vers; + header->rpc_vers_minor = rpc->rpc_vers_minor; + header->packed_drep[0] = rpc->packed_drep[0]; + header->packed_drep[1] = rpc->packed_drep[1]; + header->packed_drep[2] = rpc->packed_drep[2]; + header->packed_drep[3] = rpc->packed_drep[3]; } UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment) diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rpc_client.c freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc_client.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rpc_client.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc_client.c 2020-07-20 13:38:46.000000000 +0000 @@ -895,7 +895,7 @@ 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 @@ 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 @@ 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 @@ CopyMemory(&buffer[offset], Buffers[1].pvBuffer, Buffers[1].cbBuffer); offset += Buffers[1].cbBuffer; - if (rpc_in_channel_send_pdu(inChannel, buffer, request_pdu->frag_length) < 0) + if (rpc_in_channel_send_pdu(inChannel, buffer, request_pdu.header.frag_length) < 0) goto fail; rc = TRUE; fail: free(buffer); free(Buffers[1].pvBuffer); - free(request_pdu); Stream_Free(s, TRUE); return rc; } diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rpc.h freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc.h --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rpc.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc.h 2020-07-20 13:38:46.000000000 +0000 @@ -34,21 +34,23 @@ #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 @@ #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 { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT16 max_xmit_frag; UINT16 max_recv_frag; @@ -328,7 +325,7 @@ typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT16 max_xmit_frag; UINT16 max_recv_frag; @@ -345,7 +342,7 @@ /* 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 { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; UINT16 max_xmit_frag; UINT16 max_recv_frag; @@ -375,7 +372,7 @@ 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 { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; p_reject_reason_t provider_reject_reason; @@ -394,7 +391,7 @@ typedef struct { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; auth_verifier_co_t auth_verifier; @@ -460,7 +457,7 @@ 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 { - 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 { - 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 { - DEFINE_RPC_COMMON_FIELDS(); + rpcconn_common_hdr_t header; } rpcconn_shutdown_hdr_t; typedef union { @@ -768,7 +765,7 @@ }; FREERDP_LOCAL void rpc_pdu_header_print(rpcconn_hdr_t* header); -FREERDP_LOCAL void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_hdr_t* header); +FREERDP_LOCAL void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header); FREERDP_LOCAL UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment); FREERDP_LOCAL UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad); diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rts.c freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rts.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rts.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rts.c 2020-07-20 13:38:46.000000000 +0000 @@ -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 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 @@ 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 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 @@ 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 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ { 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 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 @@ 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 @@ 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 @@ SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */ rts_receive_window_size_command_write(&buffer[88], ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */ - status = rpc_channel_write(&nextOutChannel->common, buffer, header.frag_length); + status = rpc_channel_write(&nextOutChannel->common, buffer, header.header.frag_length); free(buffer); return (status > 0) ? 1 : -1; } diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rts_signature.c freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rts_signature.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/rts_signature.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rts_signature.c 2020-07-20 13:38:46.000000000 +0000 @@ -302,7 +302,7 @@ 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 @@ CommandLength = (UINT32)status; offset += CommandLength; - length = rts->frag_length - offset; + length = rts->header.frag_length - offset; } return TRUE; @@ -342,7 +342,7 @@ 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 @@ CommandLength = (UINT32)status; offset += CommandLength; - length = rts->frag_length - offset; + length = rts->header.frag_length - offset; } return TRUE; diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/tsg.c freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/tsg.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/tsg.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/tsg.c 2020-07-20 13:38:46.000000000 +0000 @@ -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 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ UINT32 idleTimeout; PTSG_PACKET packet = NULL; PTSG_PACKET_RESPONSE packetResponse = NULL; - WLog_DBG(TAG, "TsProxyAuthorizeTunnelReadResponse"); if (!pdu) return FALSE; @@ -902,6 +1123,8 @@ 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 @@ 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 @@ 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 tsg_transition_to_state(rdpTsg* tsg, TSG_STATE state) { - const char* str = "TSG_STATE_UNKNOWN"; - - switch (state) - { - case TSG_STATE_INITIAL: - str = "TSG_STATE_INITIAL"; - break; - - case TSG_STATE_CONNECTED: - str = "TSG_STATE_CONNECTED"; - break; - - case TSG_STATE_AUTHORIZED: - str = "TSG_STATE_AUTHORIZED"; - break; - - case TSG_STATE_CHANNEL_CREATED: - str = "TSG_STATE_CHANNEL_CREATED"; - break; - - case TSG_STATE_PIPE_CREATED: - str = "TSG_STATE_PIPE_CREATED"; - break; + const char* oldState = tsg_state_to_string(tsg->state); + const char* newState = tsg_state_to_string(state); - case TSG_STATE_TUNNEL_CLOSE_PENDING: - str = "TSG_STATE_TUNNEL_CLOSE_PENDING"; - break; - - case TSG_STATE_CHANNEL_CLOSE_PENDING: - str = "TSG_STATE_CHANNEL_CLOSE_PENDING"; - break; - - case TSG_STATE_FINAL: - str = "TSG_STATE_FINAL"; - break; - } - - WLog_DBG(TAG, "%s", str); + WLog_DBG(TAG, "%s -> %s", oldState, newState); return tsg_set_state(tsg, state); } BOOL tsg_proxy_begin(rdpTsg* tsg) { - TSG_PACKET tsgPacket; + TSG_PACKET tsgPacket = { 0 }; PTSG_CAPABILITY_NAP tsgCapNap; PTSG_PACKET_VERSIONCAPS packetVersionCaps; @@ -1443,7 +1633,7 @@ 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 @@ 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 @@ while (tsg->state != TSG_STATE_PIPE_CREATED) { - WaitForMultipleObjects(nCount, events, FALSE, 250); + const DWORD polltimeout = 250; + DWORD status = WaitForMultipleObjects(nCount, events, FALSE, polltimeout); + if (status == WAIT_TIMEOUT) + { + if (timeout > 0) + { + if (looptimeout < polltimeout) + return FALSE; + looptimeout -= polltimeout; + } + } + else + looptimeout = timeout * 1000ULL; if (!tsg_check_event_handles(tsg)) { diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/tsg.h freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/tsg.h --- freerdp2-2.1.1+dfsg1/libfreerdp/core/gateway/tsg.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/tsg.h 2020-07-20 13:38:46.000000000 +0000 @@ -62,19 +62,6 @@ #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 BOOL tsg_proxy_begin(rdpTsg* tsg); -FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout); +FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout); FREERDP_LOCAL BOOL tsg_disconnect(rdpTsg* tsg); FREERDP_LOCAL BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu); diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/heartbeat.c freerdp2-2.2.0+dfsg1/libfreerdp/core/heartbeat.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/heartbeat.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/heartbeat.c 2020-07-20 13:38:46.000000000 +0000 @@ -31,6 +31,7 @@ BYTE period; BYTE count1; BYTE count2; + BOOL rc; if (Stream_GetRemainingLength(s) < 4) return -1; @@ -44,9 +45,39 @@ "received Heartbeat PDU -> period=%" PRIu8 ", count1=%" PRIu8 ", count2=%" PRIu8 "", period, count1, count2); + rc = IFCALLRESULT(TRUE, rdp->heartbeat->ServerHeartbeat, rdp->instance, period, count1, count2); + if (!rc) + { + WLog_ERR(HEARTBEAT_TAG, "heartbeat->ServerHeartbeat callback failed!"); + return -1; + } + return 0; } +BOOL freerdp_heartbeat_send_heartbeat_pdu(freerdp_peer* peer, BYTE period, BYTE count1, BYTE count2) +{ + rdpRdp* rdp = peer->context->rdp; + wStream* s = rdp_message_channel_pdu_init(rdp); + + if (!s) + return FALSE; + + Stream_Seek_UINT8(s); /* reserved (1 byte) */ + Stream_Write_UINT8(s, period); /* period (1 byte) */ + Stream_Write_UINT8(s, count1); /* count1 (1 byte) */ + Stream_Write_UINT8(s, count2); /* count2 (1 byte) */ + + WLog_DBG(HEARTBEAT_TAG, + "sending Heartbeat PDU -> period=%" PRIu8 ", count1=%" PRIu8 ", count2=%" PRIu8 "", + period, count1, count2); + + if (!rdp_send_message_channel_pdu(rdp, s, SEC_HEARTBEAT)) + return FALSE; + + return TRUE; +} + rdpHeartbeat* heartbeat_new(void) { rdpHeartbeat* heartbeat = (rdpHeartbeat*)calloc(1, sizeof(rdpHeartbeat)); diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/heartbeat.h freerdp2-2.2.0+dfsg1/libfreerdp/core/heartbeat.h --- freerdp2-2.1.1+dfsg1/libfreerdp/core/heartbeat.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/heartbeat.h 2020-07-20 13:38:46.000000000 +0000 @@ -20,21 +20,15 @@ #ifndef FREERDP_LIB_CORE_HEARTBEET_H #define FREERDP_LIB_CORE_HEARTBEET_H -typedef struct rdp_heartbeat rdpHeartbeat; - #include "rdp.h" +#include #include #include #include #include -struct rdp_heartbeat -{ - UINT32 placeholder; -}; - int rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s); FREERDP_LOCAL rdpHeartbeat* heartbeat_new(void); diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/license.c freerdp2-2.2.0+dfsg1/libfreerdp/core/license.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/license.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/license.c 2020-07-20 13:38:46.000000000 +0000 @@ -1252,6 +1252,9 @@ 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 @@ 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 @@ 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 @@ Stream_Seek(licenseStream, cbProductId); /* licenseInfo */ + if (Stream_GetRemainingLength(licenseStream) < 4) + goto out_free_stream; Stream_Read_UINT32(licenseStream, cbLicenseInfo); if (Stream_GetRemainingLength(licenseStream) < cbLicenseInfo) goto out_free_stream; diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/orders.c freerdp2-2.2.0+dfsg1/libfreerdp/core/orders.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/orders.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/orders.c 2020-07-20 13:38:46.000000000 +0000 @@ -43,54 +43,148 @@ #define TAG FREERDP_TAG("core.orders") -const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[] = { DSTBLT_ORDER_FIELD_BYTES, - PATBLT_ORDER_FIELD_BYTES, - SCRBLT_ORDER_FIELD_BYTES, - 0, - 0, - 0, - 0, - DRAW_NINE_GRID_ORDER_FIELD_BYTES, - MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES, - LINE_TO_ORDER_FIELD_BYTES, - OPAQUE_RECT_ORDER_FIELD_BYTES, - SAVE_BITMAP_ORDER_FIELD_BYTES, - 0, - MEMBLT_ORDER_FIELD_BYTES, - MEM3BLT_ORDER_FIELD_BYTES, - MULTI_DSTBLT_ORDER_FIELD_BYTES, - MULTI_PATBLT_ORDER_FIELD_BYTES, - MULTI_SCRBLT_ORDER_FIELD_BYTES, - MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES, - FAST_INDEX_ORDER_FIELD_BYTES, - POLYGON_SC_ORDER_FIELD_BYTES, - POLYGON_CB_ORDER_FIELD_BYTES, - POLYLINE_ORDER_FIELD_BYTES, - 0, - FAST_GLYPH_ORDER_FIELD_BYTES, - ELLIPSE_SC_ORDER_FIELD_BYTES, - ELLIPSE_CB_ORDER_FIELD_BYTES, - GLYPH_INDEX_ORDER_FIELD_BYTES }; - -#define PRIMARY_DRAWING_ORDER_COUNT (ARRAYSIZE(PRIMARY_DRAWING_ORDER_FIELD_BYTES)) - -static const BYTE CBR2_BPP[] = { 0, 0, 0, 8, 16, 24, 32 }; - -static const BYTE BPP_CBR2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 }; - -static const BYTE CBR23_BPP[] = { 0, 0, 0, 8, 16, 24, 32 }; - -static const BYTE BPP_CBR23[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 }; +BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid) +{ + if (pValid) + *pValid = TRUE; + switch (orderType) + { + case 0: + return DSTBLT_ORDER_FIELD_BYTES; + case 1: + return PATBLT_ORDER_FIELD_BYTES; + case 2: + return SCRBLT_ORDER_FIELD_BYTES; + case 3: + return 0; + case 4: + return 0; + case 5: + return 0; + case 6: + return 0; + case 7: + return DRAW_NINE_GRID_ORDER_FIELD_BYTES; + case 8: + return MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES; + case 9: + return LINE_TO_ORDER_FIELD_BYTES; + case 10: + return OPAQUE_RECT_ORDER_FIELD_BYTES; + case 11: + return SAVE_BITMAP_ORDER_FIELD_BYTES; + case 12: + return 0; + case 13: + return MEMBLT_ORDER_FIELD_BYTES; + case 14: + return MEM3BLT_ORDER_FIELD_BYTES; + case 15: + return MULTI_DSTBLT_ORDER_FIELD_BYTES; + case 16: + return MULTI_PATBLT_ORDER_FIELD_BYTES; + case 17: + return MULTI_SCRBLT_ORDER_FIELD_BYTES; + case 18: + return MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES; + case 19: + return FAST_INDEX_ORDER_FIELD_BYTES; + case 20: + return POLYGON_SC_ORDER_FIELD_BYTES; + case 21: + return POLYGON_CB_ORDER_FIELD_BYTES; + case 22: + return POLYLINE_ORDER_FIELD_BYTES; + case 23: + return 0; + case 24: + return FAST_GLYPH_ORDER_FIELD_BYTES; + case 25: + return ELLIPSE_SC_ORDER_FIELD_BYTES; + case 26: + return ELLIPSE_CB_ORDER_FIELD_BYTES; + case 27: + return GLYPH_INDEX_ORDER_FIELD_BYTES; + default: + if (pValid) + *pValid = FALSE; + WLog_WARN(TAG, "Invalid orderType 0x%08X received", orderType); + return 0; + } +} -static const BYTE BMF_BPP[] = { 0, 1, 0, 8, 16, 24, 32, 0 }; +static BYTE get_cbr2_bpp(UINT32 bpp, BOOL* pValid) +{ + if (pValid) + *pValid = TRUE; + switch (bpp) + { + case 3: + return 8; + case 4: + return 16; + case 5: + return 24; + case 6: + return 32; + default: + WLog_WARN(TAG, "Invalid bpp %" PRIu32, bpp); + if (pValid) + *pValid = FALSE; + return 0; + } +} -static const BYTE BPP_BMF[] = { 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 }; +static BYTE get_bmf_bpp(UINT32 bmf, BOOL* pValid) +{ + if (pValid) + *pValid = TRUE; + /* Mask out highest bit */ + switch (bmf & (~CACHED_BRUSH)) + { + 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) + BOOL condition, const char* extendedMessage) { if (!condition) { @@ -99,6 +193,8 @@ WLog_Print(log, WLOG_WARN, "%s - SERVER BUG: The support for this feature was not announced!", orderName); + if (extendedMessage) + WLog_Print(log, WLOG_WARN, "%s", extendedMessage); return TRUE; } else @@ -107,6 +203,8 @@ "%s - SERVER BUG: The support for this feature was not announced! Use " "/relax-order-checks to ignore", orderName); + if (extendedMessage) + WLog_Print(log, WLOG_WARN, "%s", extendedMessage); return FALSE; } } @@ -117,6 +215,7 @@ static BOOL check_alt_order_supported(wLog* log, rdpSettings* settings, BYTE orderType, const char* orderName) { + const char* extendedMessage = NULL; BOOL condition = FALSE; switch (orderType) @@ -124,6 +223,7 @@ case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP: case ORDER_TYPE_SWITCH_SURFACE: condition = settings->OffscreenSupportLevel != 0; + extendedMessage = "Adding +offscreen-cache might mitigate"; break; case ORDER_TYPE_CREATE_NINE_GRID_BITMAP: @@ -159,12 +259,13 @@ break; } - return check_order_activated(log, settings, orderName, condition); + return check_order_activated(log, settings, orderName, condition, extendedMessage); } static BOOL check_secondary_order_supported(wLog* log, rdpSettings* settings, BYTE orderType, const char* orderName) { + const char* extendedMessage = NULL; BOOL condition = FALSE; switch (orderType) @@ -172,15 +273,18 @@ case ORDER_TYPE_BITMAP_UNCOMPRESSED: case ORDER_TYPE_CACHE_BITMAP_COMPRESSED: condition = settings->BitmapCacheEnabled; + extendedMessage = "Adding +bitmap-cache might mitigate"; break; case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2: case ORDER_TYPE_BITMAP_COMPRESSED_V2: condition = settings->BitmapCacheEnabled; + extendedMessage = "Adding +bitmap-cache might mitigate"; break; case ORDER_TYPE_BITMAP_COMPRESSED_V3: condition = settings->BitmapCacheV3Enabled; + extendedMessage = "Adding +bitmap-cache might mitigate"; break; case ORDER_TYPE_CACHE_COLOR_TABLE: @@ -215,12 +319,13 @@ break; } - return check_order_activated(log, settings, orderName, condition); + return check_order_activated(log, settings, orderName, condition, extendedMessage); } static BOOL check_primary_order_supported(wLog* log, rdpSettings* settings, UINT32 orderType, const char* orderName) { + const char* extendedMessage = NULL; BOOL condition = FALSE; switch (orderType) @@ -318,7 +423,7 @@ break; } - return check_order_activated(log, settings, orderName, condition); + return check_order_activated(log, settings, orderName, condition, extendedMessage); } static const char* primary_order_string(UINT32 orderType) @@ -775,9 +880,11 @@ 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 +926,11 @@ 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 +2086,7 @@ 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 +2101,9 @@ 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 +2182,16 @@ 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 +2253,7 @@ 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 +2271,9 @@ 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 +2321,7 @@ 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 +2330,9 @@ 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) */ @@ -2502,7 +2623,7 @@ const BYTE* palette = Stream_Pointer(s) + 16; const INT32 bytesPerPixel = ((bpp + 1) / 8); - if (!Stream_SafeSeek(s, 16ULL + 7ULL * bytesPerPixel)) // 64 / 4 + if (Stream_GetRemainingLength(s) < 16 + bytesPerPixel * 4) return FALSE; for (y = 7; y >= 0; y--) @@ -2535,6 +2656,7 @@ 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 +2670,10 @@ 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 +2744,16 @@ { 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 +3365,7 @@ 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 +3389,11 @@ 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; @@ -3488,7 +3617,7 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags) { BOOL rc = FALSE; - size_t start, end, diff; + size_t start, end, pos, diff; BYTE orderType; UINT16 extraFlags; UINT16 orderLength; @@ -3506,7 +3635,7 @@ 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); @@ -3637,20 +3766,21 @@ WLog_Print(update->log, WLOG_ERROR, "SECONDARY ORDER %s failed", name); } - start += orderLength + 7; - end = Stream_GetPosition(s); - if (start > end) + end = start + orderLength + 7; + pos = Stream_GetPosition(s); + if (pos > end) { WLog_Print(update->log, WLOG_WARN, "SECONDARY_ORDER %s: read %" PRIuz "bytes too much", - name, end - start); + name, pos - end); return FALSE; } - diff = start - end; + diff = end - pos; if (diff > 0) { WLog_Print(update->log, WLOG_DEBUG, "SECONDARY_ORDER %s: read %" PRIuz "bytes short, skipping", name, diff); - Stream_Seek(s, diff); + if (!Stream_SafeSeek(s, diff)) + return FALSE; } return rc; } diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/orders.h freerdp2-2.2.0+dfsg1/libfreerdp/core/orders.h --- freerdp2-2.1.1+dfsg1/libfreerdp/core/orders.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/orders.h 2020-07-20 13:38:46.000000000 +0000 @@ -189,7 +189,7 @@ #define CG_GLYPH_UNICODE_PRESENT 0x0010 -FREERDP_LOCAL extern const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[]; +FREERDP_LOCAL BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid); FREERDP_LOCAL BOOL update_recv_order(rdpUpdate* update, wStream* s); diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/rdp.c freerdp2-2.2.0+dfsg1/libfreerdp/core/rdp.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/rdp.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/rdp.c 2020-07-20 13:38:46.000000000 +0000 @@ -167,7 +167,7 @@ return TRUE; } - if ((len < 4) || ((len - 2) > Stream_GetRemainingLength(s))) + if ((len < 4U) || ((len - 2U) > Stream_GetRemainingLength(s))) return FALSE; if (tpktLength) diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/security.c freerdp2-2.2.0+dfsg1/libfreerdp/core/security.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/security.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/security.c 2020-07-20 13:38:46.000000000 +0000 @@ -394,6 +394,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ if (!winpr_HMAC_Final(hmac, buf, WINPR_SHA1_DIGEST_LENGTH)) goto out; - rdp->decrypt_use_count++; - if (!memcmp(sig, buf, 8)) result = TRUE; diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/tcp.c freerdp2-2.2.0+dfsg1/libfreerdp/core/tcp.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/tcp.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/tcp.c 2020-07-20 13:38:46.000000000 +0000 @@ -1060,7 +1060,7 @@ } int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings, const char* hostname, int port, - int timeout) + DWORD timeout) { int sockfd; UINT32 optval; diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/tcp.h freerdp2-2.2.0+dfsg1/libfreerdp/core/tcp.h --- freerdp2-2.1.1+dfsg1/libfreerdp/core/tcp.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/tcp.h 2020-07-20 13:38:46.000000000 +0000 @@ -64,7 +64,7 @@ FREERDP_LOCAL BIO_METHOD* BIO_s_buffered_socket(void); FREERDP_LOCAL int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings, - const char* hostname, int port, int timeout); + const char* hostname, int port, DWORD timeout); FREERDP_LOCAL char* freerdp_tcp_get_peer_address(SOCKET sockfd); diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/tpdu.c freerdp2-2.2.0+dfsg1/libfreerdp/core/tpdu.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/tpdu.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/tpdu.c 2020-07-20 13:38:46.000000000 +0000 @@ -84,7 +84,7 @@ if (*li + 4 > tpktlength) { - WLog_ERR(TAG, "tpdu length %" PRIu16 " > tpkt header length %" PRIu16, li, tpktlength); + WLog_ERR(TAG, "tpdu length %" PRIu8 " > tpkt header length %" PRIu16, *li, tpktlength); return FALSE; } diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/transport.c freerdp2-2.2.0+dfsg1/libfreerdp/core/transport.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/transport.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/transport.c 2020-07-20 13:38:46.000000000 +0000 @@ -354,7 +354,7 @@ return TRUE; } -BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, int timeout) +BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, DWORD timeout) { int sockfd; BOOL status = FALSE; diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/transport.h freerdp2-2.2.0+dfsg1/libfreerdp/core/transport.h --- freerdp2-2.1.1+dfsg1/libfreerdp/core/transport.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/transport.h 2020-07-20 13:38:46.000000000 +0000 @@ -81,7 +81,7 @@ FREERDP_LOCAL wStream* transport_send_stream_init(rdpTransport* transport, int size); FREERDP_LOCAL BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, - int timeout); + DWORD timeout); FREERDP_LOCAL BOOL transport_attach(rdpTransport* transport, int sockfd); FREERDP_LOCAL BOOL transport_disconnect(rdpTransport* transport); FREERDP_LOCAL BOOL transport_connect_rdp(rdpTransport* transport); diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/core/update.c freerdp2-2.2.0+dfsg1/libfreerdp/core/update.c --- freerdp2-2.1.1+dfsg1/libfreerdp/core/update.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/core/update.c 2020-07-20 13:38:46.000000000 +0000 @@ -1087,7 +1087,7 @@ 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 @@ Stream_Write_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */ update_write_field_flags(s, orderInfo->fieldFlags, orderInfo->controlFlags, - PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]); + get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL)); update_write_bounds(s, orderInfo); Stream_SetPosition(s, position); return 0; diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/crypto/crypto.c freerdp2-2.2.0+dfsg1/libfreerdp/crypto/crypto.c --- freerdp2-2.1.1+dfsg1/libfreerdp/crypto/crypto.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/crypto/crypto.c 2020-07-20 13:38:46.000000000 +0000 @@ -105,11 +105,18 @@ BIGNUM* exp = NULL; BIGNUM* x = NULL; BIGNUM* y = NULL; - size_t bufferSize = 2 * key_length + exponent_size; + size_t bufferSize; if (!input || (length < 0) || (exponent_size < 0) || !modulus || !exponent || !output) return -1; + if (exponent_size > SIZE_MAX / 2) + return -1; + + if (key_length >= SIZE_MAX / 2 - exponent_size) + return -1; + + bufferSize = 2ULL * key_length + exponent_size; if (length > bufferSize) bufferSize = length; diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/gdi/gfx.c freerdp2-2.2.0+dfsg1/libfreerdp/gdi/gfx.c --- freerdp2-2.1.1+dfsg1/libfreerdp/gdi/gfx.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/gdi/gfx.c 2020-07-20 13:38:46.000000000 +0000 @@ -31,6 +31,17 @@ #define TAG FREERDP_TAG("gdi") +static BOOL is_rect_valid(const RECTANGLE_16* rect, size_t width, size_t height) +{ + if (!rect) + return FALSE; + if ((rect->left > rect->right) || (rect->right > width)) + return FALSE; + if ((rect->top > rect->bottom) || (rect->bottom > height)) + return FALSE; + return TRUE; +} + static DWORD gfx_align_scanline(DWORD widthInBytes, DWORD alignment) { const UINT32 align = alignment; @@ -141,7 +152,10 @@ 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); @@ -1111,7 +1125,6 @@ BOOL sameSurface; UINT32 nWidth, nHeight; const RECTANGLE_16* rectSrc; - RDPGFX_POINT16* destPt; RECTANGLE_16 invalidRect; gdiGfxSurface* surfaceSrc; gdiGfxSurface* surfaceDst; @@ -1131,12 +1144,18 @@ if (!surfaceSrc || !surfaceDst) goto fail; + if (!is_rect_valid(rectSrc, surfaceSrc->width, surfaceSrc->height)) + goto fail; + nWidth = rectSrc->right - rectSrc->left; nHeight = rectSrc->bottom - rectSrc->top; for (index = 0; index < surfaceToSurface->destPtsCount; index++) { - destPt = &surfaceToSurface->destPts[index]; + const RDPGFX_POINT16* destPt = &surfaceToSurface->destPts[index]; + const RECTANGLE_16 rect = { destPt->x, destPt->y, destPt->x + nWidth, destPt->y + nHeight }; + if (!is_rect_valid(&rect, surfaceDst->width, surfaceDst->height)) + goto fail; if (!freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, @@ -1189,6 +1208,9 @@ if (!surface) goto fail; + if (!is_rect_valid(rect, surface->width, surface->height)) + goto fail; + cacheEntry = (gdiGfxCacheEntry*)calloc(1, sizeof(gdiGfxCacheEntry)); if (!cacheEntry) @@ -1231,7 +1253,6 @@ { UINT status = ERROR_INTERNAL_ERROR; UINT16 index; - RDPGFX_POINT16* destPt; gdiGfxSurface* surface; gdiGfxCacheEntry* cacheEntry; RECTANGLE_16 invalidRect; @@ -1245,7 +1266,12 @@ for (index = 0; index < cacheToSurface->destPtsCount; index++) { - destPt = &cacheToSurface->destPts[index]; + const RDPGFX_POINT16* destPt = &cacheToSurface->destPts[index]; + const RECTANGLE_16 rect = { destPt->x, destPt->y, destPt->x + cacheEntry->width, + destPt->y + cacheEntry->height }; + + if (!is_rect_valid(&rect, surface->width, surface->height)) + goto fail; if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, destPt->x, destPt->y, cacheEntry->width, cacheEntry->height, cacheEntry->data, diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/gdi/graphics.c freerdp2-2.2.0+dfsg1/libfreerdp/gdi/graphics.c --- freerdp2-2.1.1+dfsg1/libfreerdp/gdi/graphics.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/gdi/graphics.c 2020-07-20 13:38:46.000000000 +0000 @@ -93,6 +93,7 @@ if (!gdi_bitmap->bitmap) { gdi_DeleteDC(gdi_bitmap->hdc); + gdi_bitmap->hdc = NULL; return FALSE; } diff -Nru freerdp2-2.1.1+dfsg1/libfreerdp/utils/pcap.c freerdp2-2.2.0+dfsg1/libfreerdp/utils/pcap.c --- freerdp2-2.1.1+dfsg1/libfreerdp/utils/pcap.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/libfreerdp/utils/pcap.c 2020-07-20 13:38:46.000000000 +0000 @@ -170,22 +170,17 @@ { 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 @@ return pcap; fail: - free(pcap); -fail_close: - fclose(pcap_fp); + pcap_close(pcap); return NULL; } @@ -231,6 +224,9 @@ void pcap_close(rdpPcap* pcap) { + if (!pcap) + return; + pcap_flush(pcap); if (pcap->fp != NULL) diff -Nru freerdp2-2.1.1+dfsg1/scripts/create_release_taball.sh freerdp2-2.2.0+dfsg1/scripts/create_release_taball.sh --- freerdp2-2.1.1+dfsg1/scripts/create_release_taball.sh 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/scripts/create_release_taball.sh 2020-07-20 13:38:46.000000000 +0000 @@ -0,0 +1,49 @@ +#!/bin/bash -e + +function run { + "$@" + RES=$? + if [[ $RES -ne 0 ]]; + then + echo "[ERROR] $@ returned $RES" >&2 + 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 -r freerdp-${TAG}.zip freerdp-${TAG} +run md5sum freerdp-${TAG}.zip > freerdp-${TAG}.zip.md5 +run sha1sum freerdp-${TAG}.zip > freerdp-${TAG}.zip.sha1 +run sha256sum freerdp-${TAG}.zip > freerdp-${TAG}.zip.sha256 +popd + +run mv ${TMPDIR}/freerdp-${TAG}.tar.gz* . +run mv ${TMPDIR}/freerdp-${TAG}.zip* . +run rm -rf ${TMPDIR} +exit 0 diff -Nru freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/cap_config.c freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_config.c --- freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/cap_config.c 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_config.c 2020-07-20 13:38:46.000000000 +0000 @@ -0,0 +1,97 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server Session Capture Module + * + * Copyright 2019 Kobi Mizrachi + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "cap_config.h" + +BOOL capture_plugin_init_config(captureConfig* config) +{ + const char* name = "PROXY_CAPTURE_TARGET"; + char* tmp = NULL; + DWORD nSize = GetEnvironmentVariableA(name, NULL, 0); + + if (nSize > 0) + { + char* colon; + int addrLen; + unsigned long port; + + tmp = (LPSTR)malloc(nSize); + if (!tmp) + return FALSE; + + if (GetEnvironmentVariableA(name, tmp, nSize) != nSize - 1) + { + free(tmp); + return FALSE; + } + + colon = strchr(tmp, ':'); + + if (!colon) + { + free(tmp); + return FALSE; + } + + addrLen = (int)(colon - tmp); + config->host = malloc(addrLen + 1); + if (!config->host) + { + free(tmp); + return FALSE; + } + + strncpy(config->host, tmp, addrLen); + config->host[addrLen] = '\0'; + + port = strtoul(colon + 1, NULL, 0); + + if ((errno != 0) || (port > UINT16_MAX)) + { + free(config->host); + config->host = NULL; + + free(tmp); + return FALSE; + } + + config->port = port; + free(tmp); + } + else + { + config->host = _strdup("127.0.0.1"); + if (!config->host) + return FALSE; + + config->port = 8889; + } + + return TRUE; +} + +void capture_plugin_config_free_internal(captureConfig* config) +{ + free(config->host); + config->host = NULL; +} diff -Nru freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/cap_config.h freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_config.h --- freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/cap_config.h 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_config.h 2020-07-20 13:38:46.000000000 +0000 @@ -0,0 +1,29 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server Session Capture Module + * + * Copyright 2019 Kobi Mizrachi + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +typedef struct capture_config +{ + UINT16 port; + char* host; +} captureConfig; + +BOOL capture_plugin_init_config(captureConfig* config); +void capture_plugin_config_free_internal(captureConfig* config); diff -Nru freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/cap_main.c freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_main.c --- freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/cap_main.c 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_main.c 2020-07-20 13:38:46.000000000 +0000 @@ -0,0 +1,288 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server Session Capture Module + * + * Copyright 2019 Kobi Mizrachi + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define TAG MODULE_TAG("capture") + +#define PLUGIN_NAME "capture" +#define PLUGIN_DESC "stream egfx connections over tcp" + +#include +#include +#include +#include + +#include "pf_log.h" +#include "modules_api.h" +#include "pf_context.h" +#include "cap_config.h" +#include "cap_protocol.h" + +#define BUFSIZE 8092 + +static proxyPluginsManager* g_plugins_manager = NULL; +static captureConfig config = { 0 }; + +static SOCKET capture_plugin_init_socket(void) +{ + int status; + int sockfd; + struct sockaddr_in addr = { 0 }; + sockfd = _socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (sockfd == -1) + return -1; + + addr.sin_family = AF_INET; + addr.sin_port = htons(config.port); + inet_pton(AF_INET, config.host, &(addr.sin_addr)); + + status = _connect(sockfd, (const struct sockaddr*)&addr, sizeof(addr)); + if (status < 0) + { + close(sockfd); + return -1; + } + + return sockfd; +} + +static BOOL capture_plugin_send_data(SOCKET sockfd, const BYTE* buffer, size_t len) +{ + size_t chunk_len; + int nsent; + + if (!buffer) + return FALSE; + + while (len > 0) + { + chunk_len = len > BUFSIZE ? BUFSIZE : len; + nsent = _send(sockfd, (const char*)buffer, chunk_len, 0); + if (nsent == -1) + return FALSE; + + buffer += nsent; + len -= nsent; + } + + return TRUE; +} + +static BOOL capture_plugin_send_packet(SOCKET sockfd, wStream* packet) +{ + size_t len; + BYTE* buffer; + BOOL result = FALSE; + + if (!packet) + return FALSE; + + buffer = Stream_Buffer(packet); + len = Stream_Capacity(packet); + + if (!capture_plugin_send_data(sockfd, buffer, len)) + { + WLog_ERR(TAG, "error while transmitting frame: errno=%d", errno); + goto error; + } + + result = TRUE; + +error: + Stream_Free(packet, TRUE); + return result; +} + +static SOCKET capture_plugin_get_socket(proxyData* pdata) +{ + void* custom; + + custom = g_plugins_manager->GetPluginData(PLUGIN_NAME, pdata); + if (!custom) + return -1; + + return (SOCKET)custom; +} + +static BOOL capture_plugin_session_end(proxyData* pdata) +{ + SOCKET socket; + BOOL ret; + wStream* s; + + socket = capture_plugin_get_socket(pdata); + if (socket == -1) + return FALSE; + + s = capture_plugin_packet_new(SESSION_END_PDU_BASE_SIZE, MESSAGE_TYPE_SESSION_END); + if (!s) + return FALSE; + + ret = capture_plugin_send_packet(socket, s); + + closesocket(socket); + return ret; +} + +static BOOL capture_plugin_send_frame(pClientContext* pc, SOCKET socket, const BYTE* buffer) +{ + size_t frame_size; + BOOL ret = FALSE; + wStream* s = NULL; + BYTE* bmp_header = NULL; + rdpSettings* settings = pc->context.settings; + + frame_size = settings->DesktopWidth * settings->DesktopHeight * (settings->ColorDepth / 8); + bmp_header = winpr_bitmap_construct_header(settings->DesktopWidth, settings->DesktopHeight, + settings->ColorDepth); + + if (!bmp_header) + return FALSE; + + /* + * capture frame packet indicates a packet that contains a frame buffer. payload length is + * marked as 0, and receiving side must read `frame_size` bytes, a constant size of + * width*height*(bpp/8) from the socket, to receive the full frame buffer. + */ + s = capture_plugin_packet_new(0, MESSAGE_TYPE_CAPTURED_FRAME); + if (!s) + goto error; + + if (!capture_plugin_send_packet(socket, s)) + goto error; + + ret = capture_plugin_send_data(socket, bmp_header, WINPR_IMAGE_BMP_HEADER_LEN); + if (!ret) + goto error; + + ret = capture_plugin_send_data(socket, buffer, frame_size); + +error: + free(bmp_header); + return ret; +} + +static BOOL capture_plugin_client_end_paint(proxyData* pdata) +{ + pClientContext* pc = pdata->pc; + rdpGdi* gdi = pc->context.gdi; + SOCKET socket; + + if (gdi->suppressOutput) + return TRUE; + + if (gdi->primary->hdc->hwnd->ninvalid < 1) + return TRUE; + + socket = capture_plugin_get_socket(pdata); + if (socket == -1) + return FALSE; + + if (!capture_plugin_send_frame(pc, socket, gdi->primary_buffer)) + { + WLog_ERR(TAG, "capture_plugin_send_frame failed!"); + return FALSE; + } + + gdi->primary->hdc->hwnd->invalid->null = TRUE; + gdi->primary->hdc->hwnd->ninvalid = 0; + return TRUE; +} + +static BOOL capture_plugin_client_post_connect(proxyData* pdata) +{ + SOCKET socket; + wStream* s; + pClientContext* pc = pdata->pc; + rdpSettings* settings = pc->context.settings; + + socket = capture_plugin_init_socket(); + if (socket == -1) + { + WLog_ERR(TAG, "failed to establish a connection"); + return FALSE; + } + + g_plugins_manager->SetPluginData(PLUGIN_NAME, pdata, (void*)socket); + + s = capture_plugin_create_session_info_packet(settings); + if (!s) + return FALSE; + + return capture_plugin_send_packet(socket, s); +} + +static BOOL capture_plugin_server_post_connect(proxyData* pdata) +{ + pServerContext* ps = pdata->ps; + proxyConfig* config = pdata->config; + rdpSettings* settings = ps->context.settings; + + if (!config->GFX || !config->SessionCapture) + { + WLog_ERR(TAG, "config options 'GFX' and 'SessionCapture' options must be set to true!"); + return FALSE; + } + + if (!settings->SupportGraphicsPipeline) + { + WLog_ERR(TAG, "session capture is only supported for GFX clients, denying connection"); + return FALSE; + } + + return TRUE; +} + +static BOOL capture_plugin_unload(void) +{ + capture_plugin_config_free_internal(&config); + return TRUE; +} + +static proxyPlugin demo_plugin = { + PLUGIN_NAME, /* name */ + PLUGIN_DESC, /* description */ + capture_plugin_unload, /* PluginUnload */ + NULL, /* ClientPreConnect */ + capture_plugin_client_post_connect, /* ClientPostConnect */ + NULL, /* ClientLoginFailure */ + capture_plugin_client_end_paint, /* ClientEndPaint */ + capture_plugin_server_post_connect, /* ServerPostConnect */ + NULL, /* ServerChannelsInit */ + NULL, /* ServerChannelsFree */ + capture_plugin_session_end, /* Session End */ + NULL, /* KeyboardEvent */ + NULL, /* MouseEvent */ + NULL, /* ClientChannelData */ + NULL, /* ServerChannelData */ +}; + +BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager) +{ + g_plugins_manager = plugins_manager; + + if (!capture_plugin_init_config(&config)) + { + WLog_ERR(TAG, "failed to load config"); + return FALSE; + } + + WLog_INFO(TAG, "host: %s, port: %" PRIu16 "", config.host, config.port); + return plugins_manager->RegisterPlugin(&demo_plugin); +} diff -Nru freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/cap_protocol.c freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_protocol.c --- freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/cap_protocol.c 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_protocol.c 2020-07-20 13:38:46.000000000 +0000 @@ -0,0 +1,57 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server Session Capture Module + * + * Copyright 2019 Kobi Mizrachi + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cap_protocol.h" + +wStream* capture_plugin_packet_new(UINT32 payload_size, UINT16 type) +{ + wStream* stream = Stream_New(NULL, HEADER_SIZE + payload_size); + + if (!stream) + return NULL; + + Stream_Write_UINT32(stream, payload_size); + Stream_Write_UINT16(stream, type); + return stream; +} + +wStream* capture_plugin_create_session_info_packet(rdpSettings* settings) +{ + UINT16 username_length; + wStream* s = NULL; + + if (!settings || !settings->Username) + return NULL; + + username_length = strlen(settings->Username); + if (username_length == 0) + return NULL; + + s = capture_plugin_packet_new(SESSION_INFO_PDU_BASE_SIZE + username_length, + MESSAGE_TYPE_SESSION_INFO); + if (!s) + return NULL; + + Stream_Write_UINT16(s, username_length); /* username length (2 bytes) */ + Stream_Write(s, settings->Username, username_length); /* username */ + Stream_Write_UINT32(s, settings->DesktopWidth); /* desktop width (4 bytes) */ + Stream_Write_UINT32(s, settings->DesktopHeight); /* desktop height (4 bytes) */ + Stream_Write_UINT32(s, settings->ColorDepth); /* color depth (4 bytes) */ + return s; +} diff -Nru freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/cap_protocol.h freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_protocol.h --- freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/cap_protocol.h 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_protocol.h 2020-07-20 13:38:46.000000000 +0000 @@ -0,0 +1,35 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server Session Capture Module + * + * Copyright 2019 Kobi Mizrachi + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +/* protocol message sizes */ +#define HEADER_SIZE 6 +#define SESSION_INFO_PDU_BASE_SIZE 14 +#define SESSION_END_PDU_BASE_SIZE 0 +#define CAPTURED_FRAME_PDU_BASE_SIZE 0 + +/* protocol message types */ +#define MESSAGE_TYPE_SESSION_INFO 1 +#define MESSAGE_TYPE_CAPTURED_FRAME 2 +#define MESSAGE_TYPE_SESSION_END 3 + +wStream* capture_plugin_packet_new(UINT32 payload_size, UINT16 type); +wStream* capture_plugin_create_session_info_packet(rdpSettings* settings); diff -Nru freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/CMakeLists.txt freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/CMakeLists.txt --- freerdp2-2.1.1+dfsg1/server/proxy/modules/capture/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 @@ -0,0 +1,33 @@ +# +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP Proxy Server Capture Module +# +# Copyright 2019 Kobi Mizrachi +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set(PLUGIN_NAME "proxy-capture-plugin") + +add_library(${PLUGIN_NAME} MODULE + cap_main.c + cap_config.c + cap_config.h + cap_protocol.c + cap_protocol.h +) + +set_target_properties(${PLUGIN_NAME} PROPERTIES PREFIX "") +set_target_properties(${PLUGIN_NAME} PROPERTIES NO_SONAME 1) +set_target_properties(${PLUGIN_NAME} PROPERTIES +LIBRARY_OUTPUT_DIRECTORY "${FREERDP_PROXY_PLUGINDIR}") diff -Nru freerdp2-2.1.1+dfsg1/server/proxy/pf_client.c freerdp2-2.2.0+dfsg1/server/proxy/pf_client.c --- freerdp2-2.1.1+dfsg1/server/proxy/pf_client.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/proxy/pf_client.c 2020-07-20 13:38:46.000000000 +0000 @@ -35,6 +35,7 @@ #include "pf_update.h" #include "pf_log.h" #include "pf_modules.h" +#include "pf_input.h" #include "pf_capture.h" #define TAG PROXY_TAG("client") @@ -72,6 +73,19 @@ freerdp_send_error_info(ps->context.rdp); } +static void pf_client_on_activated(void* ctx, ActivatedEventArgs* e) +{ + pClientContext* pc = (pClientContext*)ctx; + pServerContext* ps = pc->pdata->ps; + freerdp_peer* peer = ps->context.peer; + + LOG_INFO(TAG, pc, "client activated, registering server input callbacks"); + + /* Register server input/update callbacks only after proxy client is fully activated */ + pf_server_register_input_callbacks(peer->input); + pf_server_register_update_callbacks(peer->update); +} + static BOOL pf_client_load_rdpsnd(pClientContext* pc) { rdpContext* context = (rdpContext*)pc; @@ -156,12 +170,6 @@ return TRUE; } -/** - * Called before a connection is established. - * - * TODO: Take client to proxy settings and use channel whitelist to filter out - * unwanted channels. - */ static BOOL pf_client_pre_connect(freerdp* instance) { pClientContext* pc = (pClientContext*)instance->context; @@ -203,6 +211,7 @@ PubSub_SubscribeChannelDisconnected(instance->context->pubSub, pf_channels_on_client_channel_disconnect); PubSub_SubscribeErrorInfo(instance->context->pubSub, pf_client_on_error_info); + PubSub_SubscribeActivated(instance->context->pubSub, pf_client_on_activated); /** * Load all required plugins / channels / libraries specified by current * settings. @@ -273,6 +282,13 @@ return client_receive_channel_data_original(instance, channelId, data, size, flags, totalSize); } +static BOOL pf_client_on_server_heartbeat(freerdp* instance, BYTE period, BYTE count1, BYTE count2) +{ + pClientContext* pc = (pClientContext*)instance->context; + pServerContext* ps = pc->pdata->ps; + return freerdp_heartbeat_send_heartbeat_pdu(ps->context.peer, period, count1, count2); +} + /** * Called after a RDP connection was successfully established. * Settings might have changed during negotiation of client / server feature @@ -348,6 +364,8 @@ } } + instance->heartbeat->ServerHeartbeat = pf_client_on_server_heartbeat; + /* * after the connection fully established and settings were negotiated with target server, * send a reactivation sequence to the client with the negotiated settings. This way, diff -Nru freerdp2-2.1.1+dfsg1/server/proxy/pf_config.h freerdp2-2.2.0+dfsg1/server/proxy/pf_config.h --- freerdp2-2.1.1+dfsg1/server/proxy/pf_config.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/proxy/pf_config.h 2020-07-20 13:38:46.000000000 +0000 @@ -79,12 +79,21 @@ typedef struct proxy_config proxyConfig; -FREERDP_API BOOL pf_config_get_uint16(wIniFile* ini, const char* section, const char* key, - UINT16* result); -FREERDP_API BOOL pf_config_get_uint32(wIniFile* ini, const char* section, const char* key, - UINT32* result); -FREERDP_API BOOL pf_config_get_bool(wIniFile* ini, const char* section, const char* key); -FREERDP_API const char* pf_config_get_str(wIniFile* ini, const char* section, const char* key); +#ifdef __cplusplus +extern "C" +{ +#endif + + FREERDP_API BOOL pf_config_get_uint16(wIniFile* ini, const char* section, const char* key, + UINT16* result); + FREERDP_API BOOL pf_config_get_uint32(wIniFile* ini, const char* section, const char* key, + UINT32* result); + FREERDP_API BOOL pf_config_get_bool(wIniFile* ini, const char* section, const char* key); + FREERDP_API const char* pf_config_get_str(wIniFile* ini, const char* section, const char* key); + +#ifdef __cplusplus +}; +#endif proxyConfig* pf_server_config_load(const char* path); void pf_server_config_print(proxyConfig* config); diff -Nru freerdp2-2.1.1+dfsg1/server/proxy/pf_rail.c freerdp2-2.2.0+dfsg1/server/proxy/pf_rail.c --- freerdp2-2.1.1+dfsg1/server/proxy/pf_rail.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/proxy/pf_rail.c 2020-07-20 13:38:46.000000000 +0000 @@ -38,6 +38,15 @@ return FALSE; } + /* + * when mstsc reconnects, it doesn't wait for a second handshake, so update all handshake flags + * to be SET, then set them again when the remote server sends his handshake. + */ + rail_server_set_handshake_ex_flags(rail, + TS_RAIL_ORDER_HANDSHAKEEX_FLAGS_HIDEF | + TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED | + TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED); + rail->rdpcontext = (rdpContext*)ps; return TRUE; } diff -Nru freerdp2-2.1.1+dfsg1/server/proxy/pf_server.c freerdp2-2.2.0+dfsg1/server/proxy/pf_server.c --- freerdp2-2.1.1+dfsg1/server/proxy/pf_server.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/proxy/pf_server.c 2020-07-20 13:38:46.000000000 +0000 @@ -36,7 +36,6 @@ #include "pf_config.h" #include "pf_client.h" #include "pf_context.h" -#include "pf_input.h" #include "pf_update.h" #include "pf_rdpgfx.h" #include "pf_disp.h" @@ -181,8 +180,6 @@ return FALSE; } - pf_server_register_input_callbacks(peer->input); - pf_server_register_update_callbacks(peer->update); return pf_modules_run_hook(HOOK_TYPE_SERVER_POST_CONNECT, pdata); } diff -Nru freerdp2-2.1.1+dfsg1/server/shadow/Mac/mac_shadow.c freerdp2-2.2.0+dfsg1/server/shadow/Mac/mac_shadow.c --- freerdp2-2.1.1+dfsg1/server/shadow/Mac/mac_shadow.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/shadow/Mac/mac_shadow.c 2020-07-20 13:38:46.000000000 +0000 @@ -370,6 +370,7 @@ int width; int height; int nSrcStep; + BOOL empty; BYTE* pSrcData; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; @@ -381,14 +382,17 @@ 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 @@ 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 @@ } ArrayList_Unlock(server->clients); + EnterCriticalSection(&(surface->lock)); region16_clear(&(surface->invalidRegion)); + LeaveCriticalSection(&(surface->lock)); } if (status != kCGDisplayStreamFrameStatusFrameComplete) diff -Nru freerdp2-2.1.1+dfsg1/server/shadow/shadow_client.c freerdp2-2.2.0+dfsg1/server/shadow/shadow_client.c --- freerdp2-2.1.1+dfsg1/server/shadow/shadow_client.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/shadow/shadow_client.c 2020-07-20 13:38:46.000000000 +0000 @@ -1331,12 +1331,12 @@ 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 @@ } out: + LeaveCriticalSection(&surface->lock); region16_uninit(&invalidRegion); return ret; } diff -Nru freerdp2-2.1.1+dfsg1/server/shadow/shadow_server.c freerdp2-2.2.0+dfsg1/server/shadow/shadow_server.c --- freerdp2-2.1.1+dfsg1/server/shadow/shadow_server.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/shadow/shadow_server.c 2020-07-20 13:38:46.000000000 +0000 @@ -586,14 +586,19 @@ char** list = CommandLineParseCommaSeparatedValuesEx(NULL, server->ipcSocket, &count); if (!list || (count <= 1)) { - free(list); if (server->ipcSocket == NULL) { if (!open_port(server, NULL)) + { + free(list); return -1; + } } else + { + free(list); return -1; + } } for (x = 1; x < count; x++) diff -Nru freerdp2-2.1.1+dfsg1/server/shadow/X11/x11_shadow.c freerdp2-2.2.0+dfsg1/server/shadow/X11/x11_shadow.c --- freerdp2-2.1.1+dfsg1/server/shadow/X11/x11_shadow.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/server/shadow/X11/x11_shadow.c 2020-07-20 13:38:46.000000000 +0000 @@ -128,90 +128,69 @@ return pam_status; } -static int x11_shadow_pam_get_service_name(SHADOW_PAM_AUTH_INFO* info) +static BOOL x11_shadow_pam_get_service_name(SHADOW_PAM_AUTH_INFO* info) { - if (PathFileExistsA("/etc/pam.d/lightdm")) - { - info->service_name = _strdup("lightdm"); - } - else if (PathFileExistsA("/etc/pam.d/gdm")) - { - info->service_name = _strdup("gdm"); - } - else if (PathFileExistsA("/etc/pam.d/xdm")) - { - info->service_name = _strdup("xdm"); - } - else if (PathFileExistsA("/etc/pam.d/login")) - { - info->service_name = _strdup("login"); - } - else if (PathFileExistsA("/etc/pam.d/sshd")) - { - info->service_name = _strdup("sshd"); - } - else + size_t x; + const char* base = "/etc/pam.d"; + const char* hints[] = { "lightdm", "gdm", "xdm", "login", "sshd" }; + + for (x = 0; x < ARRAYSIZE(hints); x++) { - return -1; - } + char path[MAX_PATH]; + const char* hint = hints[x]; - if (!info->service_name) - return -1; + _snprintf(path, sizeof(path), "%s/%s", base, hint); + if (PathFileExistsA(path)) + { - return 1; + info->service_name = _strdup(hint); + return info->service_name != NULL; + } + } + WLog_WARN(TAG, "Could not determine PAM service name"); + return FALSE; } static int x11_shadow_pam_authenticate(rdpShadowSubsystem* subsystem, rdpShadowClient* client, const char* user, const char* domain, const char* password) { int pam_status; - SHADOW_PAM_AUTH_INFO* info; + SHADOW_PAM_AUTH_INFO info = { 0 }; WINPR_UNUSED(subsystem); WINPR_UNUSED(client); - info = calloc(1, sizeof(SHADOW_PAM_AUTH_INFO)); - - if (!info) - return PAM_CONV_ERR; - if (x11_shadow_pam_get_service_name(info) < 0) - { - free(info); + if (!x11_shadow_pam_get_service_name(&info)) return -1; - } - info->appdata.user = user; - info->appdata.domain = domain; - info->appdata.password = password; - info->pamc.conv = &x11_shadow_pam_conv; - info->pamc.appdata_ptr = &(info->appdata); - pam_status = pam_start(info->service_name, 0, &(info->pamc), &(info->handle)); + info.appdata.user = user; + info.appdata.domain = domain; + info.appdata.password = password; + info.pamc.conv = &x11_shadow_pam_conv; + info.pamc.appdata_ptr = &info.appdata; + pam_status = pam_start(info.service_name, 0, &info.pamc, &info.handle); if (pam_status != PAM_SUCCESS) { - WLog_ERR(TAG, "pam_start failure: %s", pam_strerror(info->handle, pam_status)); - free(info); + WLog_ERR(TAG, "pam_start failure: %s", pam_strerror(info.handle, pam_status)); return -1; } - pam_status = pam_authenticate(info->handle, 0); + pam_status = pam_authenticate(info.handle, 0); if (pam_status != PAM_SUCCESS) { - WLog_ERR(TAG, "pam_authenticate failure: %s", pam_strerror(info->handle, pam_status)); - free(info); + WLog_ERR(TAG, "pam_authenticate failure: %s", pam_strerror(info.handle, pam_status)); return -1; } - pam_status = pam_acct_mgmt(info->handle, 0); + pam_status = pam_acct_mgmt(info.handle, 0); if (pam_status != PAM_SUCCESS) { - WLog_ERR(TAG, "pam_acct_mgmt failure: %s", pam_strerror(info->handle, pam_status)); - free(info); + WLog_ERR(TAG, "pam_acct_mgmt failure: %s", pam_strerror(info.handle, pam_status)); return -1; } - free(info); return 1; } @@ -757,6 +736,7 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) { + int rc = 0; int count; int status; int x, y; @@ -774,10 +754,13 @@ 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 @@ 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 @@ */ 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 @@ 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 @@ shadow_encoder_preferred_fps(client->encoder); } + EnterCriticalSection(&surface->lock); region16_clear(&(surface->invalidRegion)); + LeaveCriticalSection(&surface->lock); } } - if (!subsystem->use_xshm) - XDestroyImage(image); - - return 1; + rc = 1; fail_capture: - if (!subsystem->use_xshm && image) XDestroyImage(image); - XSetErrorHandler(NULL); - XSync(subsystem->display, False); - XUnlockDisplay(subsystem->display); - return 0; + if (rc != 1) + { + XSetErrorHandler(NULL); + XSync(subsystem->display, False); + XUnlockDisplay(subsystem->display); + } + + return rc; } static int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage* message) diff -Nru freerdp2-2.1.1+dfsg1/uwac/libuwac/uwac-os.c freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-os.c --- freerdp2-2.1.1+dfsg1/uwac/libuwac/uwac-os.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-os.c 2020-07-20 13:38:46.000000000 +0000 @@ -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 @@ return -1; } +#ifdef O_TMPFILE fd = open(path, O_TMPFILE | O_RDWR | O_EXCL, 0600); +#else + /* + * Some platforms (e.g. FreeBSD) won't support O_TMPFILE and can't + * reasonably emulate it at first blush. Opt to make them rely on + * the create_tmpfile_cloexec() path instead. + */ + fd = -1; +#endif if (fd < 0) { diff -Nru freerdp2-2.1.1+dfsg1/uwac/libuwac/uwac-priv.h freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-priv.h --- freerdp2-2.1.1+dfsg1/uwac/libuwac/uwac-priv.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-priv.h 2020-07-20 13:38:46.000000000 +0000 @@ -235,7 +235,8 @@ struct wl_region* opaque_region; struct wl_region* input_region; - UwacBuffer *drawingBuffer, *pendingBuffer; + SSIZE_T drawingBufferIdx; + SSIZE_T pendingBufferIdx; struct wl_surface* surface; struct wl_shell_surface* shell_surface; struct xdg_surface* xdg_surface; diff -Nru freerdp2-2.1.1+dfsg1/uwac/libuwac/uwac-window.c freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-window.c --- freerdp2-2.1.1+dfsg1/uwac/libuwac/uwac-window.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-window.c 2020-07-20 13:38:46.000000000 +0000 @@ -136,13 +136,13 @@ { 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 @@ { 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 @@ { 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 @@ 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 @@ } w->buffers[i].used = true; + if (index) + *index = i; return &w->buffers[i]; } @@ -457,7 +465,8 @@ } 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 @@ 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 @@ 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 @@ 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 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 UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame) { - UwacBuffer* drawingBuffer = window->drawingBuffer; + UwacBuffer* currentDrawingBuffer; + UwacBuffer* nextDrawingBuffer; + UwacBuffer* pendingBuffer; + + if (window->drawingBufferIdx < 0) + return UWAC_ERROR_INTERNAL; + + currentDrawingBuffer = &window->buffers[window->drawingBufferIdx]; - if (window->pendingBuffer || !drawingBuffer->dirty) + if ((window->pendingBufferIdx >= 0) || !currentDrawingBuffer->dirty) return UWAC_SUCCESS; - window->pendingBuffer = drawingBuffer; - window->drawingBuffer = UwacWindowFindFreeBuffer(window); + window->pendingBufferIdx = window->drawingBufferIdx; + nextDrawingBuffer = UwacWindowFindFreeBuffer(window, &window->drawingBufferIdx); + pendingBuffer = &window->buffers[window->pendingBufferIdx]; - if (!window->drawingBuffer) + if ((!nextDrawingBuffer) || (window->drawingBufferIdx < 0)) return UWAC_ERROR_NOMEMORY; if (copyContentForNextFrame) - memcpy(window->drawingBuffer->data, window->pendingBuffer->data, - window->stride * window->height); + memcpy(nextDrawingBuffer->data, pendingBuffer->data, window->stride * window->height); - UwacSubmitBufferPtr(window, drawingBuffer); + UwacSubmitBufferPtr(window, pendingBuffer); return UWAC_SUCCESS; } diff -Nru freerdp2-2.1.1+dfsg1/winpr/CMakeLists.txt freerdp2-2.2.0+dfsg1/winpr/CMakeLists.txt --- freerdp2-2.1.1+dfsg1/winpr/CMakeLists.txt 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 @@ -51,7 +51,7 @@ endif() # Soname versioning -set(RAW_VERSION_STRING "2.1.1") +set(RAW_VERSION_STRING "2.2.0") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) diff -Nru freerdp2-2.1.1+dfsg1/winpr/include/winpr/image.h freerdp2-2.2.0+dfsg1/winpr/include/winpr/image.h --- freerdp2-2.1.1+dfsg1/winpr/include/winpr/image.h 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/include/winpr/image.h 2020-07-20 13:38:46.000000000 +0000 @@ -66,6 +66,8 @@ #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 @@ WINPR_API int winpr_bitmap_write(const char* filename, const BYTE* data, int width, int height, int bpp); + WINPR_API BYTE* winpr_bitmap_construct_header(int width, int height, int bpp); WINPR_API int winpr_image_write(wImage* image, const char* filename); WINPR_API int winpr_image_read(wImage* image, const char* filename); diff -Nru freerdp2-2.1.1+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c --- freerdp2-2.1.1+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c 2020-07-20 13:38:46.000000000 +0000 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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_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 @@ 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 @@ 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 @@ 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 @@ AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvEOL, NULL); if (!AvEOL) - return -1; + goto fail; ZeroMemory(AvEOL, sizeof(NTLM_AV_PAIR)); } return 1; +fail: + sspi_SecBufferFree(&context->AuthenticateTargetInfo); + return -1; } diff -Nru freerdp2-2.1.1+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm.c freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm.c --- freerdp2-2.1.1+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm.c 2020-07-20 13:38:46.000000000 +0000 @@ -961,7 +961,7 @@ 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 @@ 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 @@ } /* 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 @@ free(data); /* RC4-encrypt first 8 bytes of digest */ winpr_RC4_Update(context->SendRc4Seal, 8, digest, checksum); - signature = (BYTE*)signature_buffer->pvBuffer; - /* Concatenate version, ciphertext and sequence number to build signature */ - Data_Write_UINT32(signature, version); - CopyMemory(&signature[4], (void*)checksum, 8); - Data_Write_UINT32(&signature[12], SeqNo); + if ((signature_buffer->BufferType & SECBUFFER_READONLY) == 0) + { + signature = (BYTE*)signature_buffer->pvBuffer; + /* Concatenate version, ciphertext and sequence number to build signature */ + Data_Write_UINT32(signature, version); + CopyMemory(&signature[4], (void*)checksum, 8); + Data_Write_UINT32(&signature[12], SeqNo); + } context->SendSeqNum++; #ifdef WITH_DEBUG_NTLM WLog_DBG(TAG, "Signature (length = %" PRIu32 ")", signature_buffer->cbBuffer); diff -Nru freerdp2-2.1.1+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_message.c freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_message.c --- freerdp2-2.1.1+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_message.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm_message.c 2020-07-20 13:38:46.000000000 +0000 @@ -544,9 +544,9 @@ winpr_HexDump(TAG, WLOG_DEBUG, context->Timestamp, 8); #endif context->state = NTLM_STATE_AUTHENTICATE; - ntlm_free_message_fields_buffer(&(message->TargetName)); status = SEC_I_CONTINUE_NEEDED; fail: + ntlm_free_message_fields_buffer(&(message->TargetName)); Stream_Free(s, FALSE); return status; } diff -Nru freerdp2-2.1.1+dfsg1/winpr/libwinpr/sspicli/sspicli.c freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspicli/sspicli.c --- freerdp2-2.1.1+dfsg1/winpr/libwinpr/sspicli/sspicli.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspicli/sspicli.c 2020-07-20 13:38:46.000000000 +0000 @@ -201,18 +201,23 @@ 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 HAVE_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 @@ break; } - return 0; + return FALSE; } BOOL GetUserNameExW(EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize) diff -Nru freerdp2-2.1.1+dfsg1/winpr/libwinpr/sysinfo/sysinfo.c freerdp2-2.2.0+dfsg1/winpr/libwinpr/sysinfo/sysinfo.c --- freerdp2-2.1.1+dfsg1/winpr/libwinpr/sysinfo/sysinfo.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/libwinpr/sysinfo/sysinfo.c 2020-07-20 13:38:46.000000000 +0000 @@ -213,11 +213,12 @@ 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 @@ VOID GetLocalTime(LPSYSTEMTIME lpSystemTime) { time_t ct = 0; + struct tm tres; struct tm* ltm = NULL; WORD wMilliseconds = 0; ct = time(NULL); wMilliseconds = (WORD)(GetTickCount() % 1000); - ltm = localtime(&ct); + ltm = localtime_r(&ct, &tres); ZeroMemory(lpSystemTime, sizeof(SYSTEMTIME)); if (ltm) diff -Nru freerdp2-2.1.1+dfsg1/winpr/libwinpr/timezone/timezone.c freerdp2-2.2.0+dfsg1/winpr/libwinpr/timezone/timezone.c --- freerdp2-2.1.1+dfsg1/winpr/libwinpr/timezone/timezone.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/libwinpr/timezone/timezone.c 2020-07-20 13:38:46.000000000 +0000 @@ -339,12 +339,16 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) { time_t t; + struct tm tres; struct tm* local_time; - TIME_ZONE_ENTRY* dtz; + TIME_ZONE_ENTRY* dtz = NULL; LPTIME_ZONE_INFORMATION tz = lpTimeZoneInformation; lpTimeZoneInformation->StandardBias = 0; time(&t); - local_time = localtime(&t); + local_time = localtime_r(&t, &tres); + if (!local_time) + goto out_error; + memset(tz, 0, sizeof(TIME_ZONE_INFORMATION)); #ifdef HAVE_TM_GMTOFF { diff -Nru freerdp2-2.1.1+dfsg1/winpr/libwinpr/utils/collections/MessageQueue.c freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/collections/MessageQueue.c --- freerdp2-2.1.1+dfsg1/winpr/libwinpr/utils/collections/MessageQueue.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/collections/MessageQueue.c 2020-07-20 13:38:46.000000000 +0000 @@ -100,12 +100,13 @@ } CopyMemory(&(queue->array[queue->tail]), message, sizeof(wMessage)); - queue->tail = (queue->tail + 1) % queue->capacity; - queue->size++; message = &(queue->array[queue->tail]); message->time = GetTickCount64(); + queue->tail = (queue->tail + 1) % queue->capacity; + queue->size++; + if (queue->size > 0) SetEvent(queue->event); diff -Nru freerdp2-2.1.1+dfsg1/winpr/libwinpr/utils/image.c freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/image.c --- freerdp2-2.1.1+dfsg1/winpr/libwinpr/utils/image.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/image.c 2020-07-20 13:38:46.000000000 +0000 @@ -100,24 +100,18 @@ 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 @@ 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 + */ + +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(Stream_Buffer(s), Stream_Length(s), 1, fp) != 1 || - fwrite((void*)data, bi.biSizeImage, 1, fp) != 1) + if (fwrite(bmp_header, WINPR_IMAGE_BMP_HEADER_LEN, 1, fp) != 1 || + fwrite((void*)data, img_size, 1, fp) != 1) goto fail; ret = 1; fail: fclose(fp); - Stream_Free(s, TRUE); + free(bmp_header); return ret; } diff -Nru freerdp2-2.1.1+dfsg1/winpr/libwinpr/utils/trio/trio.c freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/trio/trio.c --- freerdp2-2.1.1+dfsg1/winpr/libwinpr/utils/trio/trio.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/trio/trio.c 2020-07-20 13:38:46.000000000 +0000 @@ -2729,7 +2729,7 @@ 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 @@ } else { - if (precision == 0) + if (precision <= 0) { length = trio_length(string); } @@ -4754,7 +4754,7 @@ } /* Bail out if namespace is too long */ - if (trio_length(name) >= MAX_USER_NAME) + if (trio_length_max(name, MAX_USER_NAME) >= MAX_USER_NAME) return NULL; /* Bail out if namespace already is registered */ diff -Nru freerdp2-2.1.1+dfsg1/winpr/libwinpr/utils/trio/triostr.c freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/trio/triostr.c --- freerdp2-2.1.1+dfsg1/winpr/libwinpr/utils/trio/triostr.c 2020-05-20 14:45:43.000000000 +0000 +++ freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/trio/triostr.c 2020-07-20 13:38:46.000000000 +0000 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "triodef.h" #include "triostr.h" @@ -328,7 +329,7 @@ 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