New upstream version 2.1.2+dfsg1

This commit is contained in:
Mike Gabriel 2020-06-29 13:56:21 +02:00
parent 912dda7d3e
commit e672a1bc07
80 changed files with 1932 additions and 590 deletions

View File

@ -81,7 +81,7 @@ if ($ENV{BUILD_NUMBER})
endif()
set(WITH_LIBRARY_VERSIONING "ON")
set(RAW_VERSION_STRING "2.1.1")
set(RAW_VERSION_STRING "2.1.2")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)

View File

@ -1,3 +1,26 @@
# 2020-06-22 Version 2.1.2
Important notes:
* CVE-2020-4033 Out of bound read in RLEDECOMPRESS
* CVE-2020-4031 Use-After-Free in gdi_SelectObject
* CVE-2020-4032 Integer casting vulnerability in `update_recv_secondary_order`
* CVE-2020-4030 OOB read in `TrioParse`
* CVE-2020-11099 OOB Read in license_read_new_or_upgrade_license_packet
* CVE-2020-11098 Out-of-bound read in glyph_cache_put
* CVE-2020-11097 OOB read in ntlm_av_pair_get
* CVE-2020-11095 Global OOB read in update_recv_primary_order
* CVE-2020-11096 Global OOB read in update_read_cache_bitmap_v3_order
* Gateway RPC fixes for windows
* Fixed resource fee race resulting in double free in USB redirection
* Fixed wayland client crashes
* Fixed X11 client mouse mapping issues (X11 mapping on/off)
* Some proxy related improvements (capture module)
* Code cleanup (use getlogin_r, ...)
For a complete and detailed change log since the last release candidate run:
git log 2.1.1..2.1.2
# 2020-05-20 Version 2.1.1
Important notes:

View File

@ -580,10 +580,15 @@ static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelManage
{
pCallback = channel->channel_callback;
if ((pCallback->OnOpen) && (error = pCallback->OnOpen(pCallback)))
if (pCallback->OnOpen)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "OnOpen failed with error %" PRIu32 "!", error);
return error;
error = pCallback->OnOpen(pCallback);
if (error)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "OnOpen failed with error %" PRIu32 "!",
error);
return error;
}
}
WLog_Print(drdynvc->log, WLOG_DEBUG, "open_channel: ChannelId %" PRIu32 "", ChannelId);
@ -1583,13 +1588,15 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
MessageQueue_Free(drdynvc->queue);
drdynvc->queue = NULL;
if (drdynvc->channel_mgr)
{
dvcman_free(drdynvc, drdynvc->channel_mgr);
drdynvc->channel_mgr = NULL;
}
MessageQueue_Free(drdynvc->queue);
drdynvc->queue = NULL;
drdynvc->InitHandle = 0;
free(drdynvc->context);
free(drdynvc);

View File

@ -1116,8 +1116,11 @@ static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg)
if ((error = encomsp_process_receive(encomsp, data)))
{
WLog_ERR(TAG, "encomsp_process_receive failed with error %" PRIu32 "!", error);
Stream_Free(data, TRUE);
break;
}
Stream_Free(data, TRUE);
}
}

View File

@ -27,7 +27,6 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/interlocked.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include <winpr/cmdline.h>
@ -82,23 +81,6 @@ static BOOL mappedGeometryKeyCompare(UINT64* g1, UINT64* g2)
return *g1 == *g2;
}
void mappedGeometryRef(MAPPED_GEOMETRY* g)
{
InterlockedIncrement(&g->refCounter);
}
void mappedGeometryUnref(MAPPED_GEOMETRY* g)
{
if (InterlockedDecrement(&g->refCounter))
return;
g->MappedGeometryUpdate = NULL;
g->MappedGeometryClear = NULL;
g->custom = NULL;
free(g->geometry.rects);
free(g);
}
static void freerdp_rgndata_reset(FREERDP_RGNDATA* data)
{
data->nRectCount = 0;

View File

@ -69,10 +69,11 @@ struct rdp_cups_print_job
static void printer_cups_get_printjob_name(char* buf, size_t size, size_t id)
{
time_t tt;
struct tm tres;
struct tm* t;
tt = time(NULL);
t = localtime(&tt);
t = localtime_r(&tt, &tres);
sprintf_s(buf, size - 1, "FreeRDP Print %04d-%02d-%02d %02d-%02d-%02d - Job %" PRIdz,
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, id);
}

View File

@ -78,13 +78,14 @@ struct rdp_win_print_job
static WCHAR* printer_win_get_printjob_name(size_t id)
{
time_t tt;
struct tm tres;
struct tm* t;
WCHAR* str;
size_t len = 1024;
int rc;
tt = time(NULL);
t = localtime(&tt);
t = localtime_s(&tt, &tres);
str = calloc(len, sizeof(WCHAR));
if (!str)

View File

@ -598,7 +598,14 @@ static BOOL isAutomountLocation(const char* path)
size_t x;
char buffer[MAX_PATH];
uid_t uid = getuid();
const char* uname = getlogin();
char uname[MAX_PATH] = { 0 };
#ifndef getlogin_r
strncpy(uname, getlogin(), sizeof(uname));
#else
if (getlogin_r(uname, sizeof(uname)) != 0)
return FALSE;
#endif
if (!path)
return FALSE;

View File

@ -604,6 +604,7 @@ static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin)
IFCALL(mgr->DestroyListener, mgr, rdpei->listener);
}
free(rdpei->listener_callback);
free(rdpei->contactPoints);
free(rdpei->context);
free(rdpei);
return CHANNEL_RC_OK;

View File

@ -306,7 +306,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value)
value *= -1;
}
if (value <= 0x1FUL)
if (value <= 0x1FL)
{
byte = value & 0x1F;
@ -315,7 +315,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value)
Stream_Write_UINT8(s, byte);
}
else if (value <= 0x1FFFUL)
else if (value <= 0x1FFFL)
{
byte = (value >> 8) & 0x1F;
@ -326,7 +326,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
else if (value <= 0x1FFFFFUL)
else if (value <= 0x1FFFFFL)
{
byte = (value >> 16) & 0x1F;
@ -339,7 +339,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
else if (value <= 0x1FFFFFFFUL)
else if (value <= 0x1FFFFFFFL)
{
byte = (value >> 24) & 0x1F;

View File

@ -843,8 +843,11 @@ static DWORD WINAPI remdesk_virtual_channel_client_thread(LPVOID arg)
if ((error = remdesk_process_receive(remdesk, data)))
{
WLog_ERR(TAG, "remdesk_process_receive failed with error %" PRIu32 "!", error);
Stream_Free(data, TRUE);
break;
}
Stream_Free(data, TRUE);
}
}

View File

@ -921,15 +921,38 @@ static LONG smartcard_LocateCardsA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
ret.ReturnCode = SCardLocateCardsA(operation->hContext, call->mszCards, call->rgReaderStates,
call->cReaders);
log_status_error(TAG, "SCardLocateCardsA", ret.ReturnCode);
ret.cReaders = call->cReaders;
ret.rgReaderStates = NULL;
free(call->mszCards);
if (ret.cReaders > 0)
{
ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
if (!ret.rgReaderStates)
return STATUS_NO_MEMORY;
}
for (x = 0; x < ret.cReaders; x++)
{
ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
sizeof(ret.rgReaderStates[x].rgbAtr));
}
status = smartcard_pack_locate_cards_return(smartcard, irp->output, &ret);
for (x = 0; x < call->cReaders; x++)
{
SCARD_READERSTATEA* state = &call->rgReaderStates[x];
free(state->szReader);
}
free(call->rgReaderStates);
status = smartcard_pack_locate_cards_return(smartcard, irp->output, &ret);
if (status != SCARD_S_SUCCESS)
return status;
@ -947,15 +970,38 @@ static LONG smartcard_LocateCardsW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
ret.ReturnCode = SCardLocateCardsW(operation->hContext, call->mszCards, call->rgReaderStates,
call->cReaders);
log_status_error(TAG, "SCardLocateCardsW", ret.ReturnCode);
ret.cReaders = call->cReaders;
ret.rgReaderStates = NULL;
free(call->mszCards);
if (ret.cReaders > 0)
{
ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
if (!ret.rgReaderStates)
return STATUS_NO_MEMORY;
}
for (x = 0; x < ret.cReaders; x++)
{
ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
sizeof(ret.rgReaderStates[x].rgbAtr));
}
status = smartcard_pack_locate_cards_return(smartcard, irp->output, &ret);
for (x = 0; x < call->cReaders; x++)
{
SCARD_READERSTATEW* state = &call->rgReaderStates[x];
free(state->szReader);
}
free(call->rgReaderStates);
status = smartcard_pack_locate_cards_return(smartcard, irp->output, &ret);
if (status != SCARD_S_SUCCESS)
return status;

View File

@ -389,7 +389,7 @@ static char* smartcard_msz_dump_a(const char* msz, size_t len, char* buffer, siz
static char* smartcard_msz_dump_w(const WCHAR* msz, size_t len, char* buffer, size_t bufferLen)
{
char* sz;
char* sz = NULL;
ConvertFromUnicode(CP_UTF8, 0, msz, (int)len, &sz, 0, NULL, NULL);
return smartcard_msz_dump_a(sz, len, buffer, bufferLen);
}
@ -466,7 +466,7 @@ static void smartcard_trace_context_and_string_call_w(const char* name,
const REDIR_SCARDCONTEXT* phContext,
const WCHAR* sz)
{
char* tmp;
char* tmp = NULL;
if (!WLog_IsLevelActive(WLog_Get(TAG), g_LogLevel))
return;
@ -883,7 +883,7 @@ static void smartcard_trace_write_cache_a_call(SMARTCARD_DEVICE* smartcard,
static void smartcard_trace_write_cache_w_call(SMARTCARD_DEVICE* smartcard,
const WriteCacheW_Call* call)
{
char* tmp;
char* tmp = NULL;
char buffer[1024];
WINPR_UNUSED(smartcard);
if (!WLog_IsLevelActive(WLog_Get(TAG), g_LogLevel))
@ -931,7 +931,7 @@ static void smartcard_trace_read_cache_a_call(SMARTCARD_DEVICE* smartcard,
static void smartcard_trace_read_cache_w_call(SMARTCARD_DEVICE* smartcard,
const ReadCacheW_Call* call)
{
char* tmp;
char* tmp = NULL;
char buffer[1024];
WINPR_UNUSED(smartcard);
if (!WLog_IsLevelActive(WLog_Get(TAG), g_LogLevel))

View File

@ -767,8 +767,6 @@ static void urb_isoch_transfer_cb(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callb
callback->channel->Write(callback->channel, Stream_GetPosition(out), Stream_Buffer(out),
NULL);
}
Stream_Free(out, TRUE);
}
static UINT urb_isoch_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callback, wStream* s,

View File

@ -296,7 +296,7 @@ static void func_bulk_transfer_cb(struct libusb_transfer* transfer)
user_data->cb(user_data->idev, user_data->callback, user_data->data, InterfaceId,
user_data->noack, user_data->MessageId, RequestID, transfer->num_iso_packets,
transfer->status, user_data->StartFrame, user_data->ErrorCount,
user_data->OutputBufferSize);
transfer->actual_length);
user_data->data = NULL;
HashTable_Remove(user_data->queue, (void*)(size_t)streamID);
}
@ -465,7 +465,7 @@ static LIBUSB_DEVICE_DESCRIPTOR* udev_new_descript(URBDRC_PLUGIN* urbdrc, LIBUSB
static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BYTE AlternateSetting)
{
int error = 0, diff = 1;
int error = 0, diff = 0;
UDEVICE* pdev = (UDEVICE*)idev;
URBDRC_PLUGIN* urbdrc;
MSUSB_CONFIG_DESCRIPTOR* MsConfig;
@ -480,21 +480,30 @@ static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BY
if (MsConfig)
{
MsInterfaces = MsConfig->MsInterfaces;
if ((MsInterfaces) && (MsInterfaces[InterfaceNumber]->AlternateSetting == AlternateSetting))
if (MsInterfaces)
{
diff = 0;
WLog_Print(urbdrc->log, WLOG_INFO,
"select Interface(%" PRIu8 ") curr AlternateSetting(%" PRIu8
") new AlternateSetting(" PRIu8 ")",
InterfaceNumber, MsInterfaces[InterfaceNumber]->AlternateSetting,
AlternateSetting);
if (MsInterfaces[InterfaceNumber]->AlternateSetting != AlternateSetting)
{
diff = 1;
}
}
}
if (diff)
{
error = libusb_set_interface_alt_setting(pdev->libusb_handle, InterfaceNumber,
AlternateSetting);
if (error < 0)
if (diff)
{
WLog_Print(urbdrc->log, WLOG_ERROR, "Set interface altsetting get error num %d", error);
error = libusb_set_interface_alt_setting(pdev->libusb_handle, InterfaceNumber,
AlternateSetting);
if (error < 0)
{
WLog_Print(urbdrc->log, WLOG_ERROR, "Set interface altsetting get error num %d",
error);
}
}
}
@ -1168,6 +1177,7 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c
user_data->streamID = streamID;
#endif
libusb_set_iso_packet_lengths(iso_transfer, iso_packet_size);
HashTable_Add(pdev->request_queue, (void*)(size_t)streamID, iso_transfer);
return libusb_submit_transfer(iso_transfer);
}
@ -1292,7 +1302,6 @@ static int func_cancel_xact_request(URBDRC_PLUGIN* urbdrc, wHashTable* queue, ui
return -1;
status = libusb_cancel_transfer(transfer);
HashTable_Remove(queue, (void*)(size_t)streamID);
if (status < 0)
{
@ -1348,6 +1357,7 @@ static int libusb_udev_cancel_transfer_request(IUDEVICE* idev, UINT32 RequestId)
urbdrc = (URBDRC_PLUGIN*)pdev->urbdrc;
cancelID = (id1) ? cancelID1 : cancelID2;
transfer = HashTable_GetItemValue(pdev->request_queue, (void*)(size_t)cancelID);
return func_cancel_xact_request(urbdrc, pdev->request_queue, cancelID, transfer);
}

View File

@ -30,7 +30,7 @@
#define TAG CLIENT_TAG("wayland.input")
#define MAX_CONTACTS 10
#define MAX_CONTACTS 20
typedef struct touch_contact
{
@ -241,6 +241,9 @@ BOOL wlf_handle_touch_up(freerdp* instance, const UwacTouchUp* ev)
}
}
if (i == MAX_CONTACTS)
return FALSE;
WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y);
if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE))
@ -282,8 +285,6 @@ BOOL wlf_handle_touch_down(freerdp* instance, const UwacTouchDown* ev)
y = ev->y;
touchId = ev->id;
WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y);
for (i = 0; i < MAX_CONTACTS; i++)
{
if (contacts[i].id == 0)
@ -296,6 +297,11 @@ BOOL wlf_handle_touch_down(freerdp* instance, const UwacTouchDown* ev)
}
}
if (i == MAX_CONTACTS)
return FALSE;
WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y);
if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE))
return FALSE;
@ -350,6 +356,9 @@ BOOL wlf_handle_touch_motion(freerdp* instance, const UwacTouchMotion* ev)
}
}
if (i == MAX_CONTACTS)
return FALSE;
WLog_DBG(TAG, "%s called | event_id: %u | x: %u / y: %u", __FUNCTION__, touchId, x, y);
if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE))

View File

@ -62,6 +62,7 @@ static BOOL wl_begin_paint(rdpContext* context)
static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw, INT32 ih)
{
BOOL res = FALSE;
rdpGdi* gdi;
char* data;
UINT32 x, y, w, h;
@ -76,6 +77,7 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw
if ((ix < 0) || (iy < 0) || (iw < 0) || (ih < 0))
return FALSE;
EnterCriticalSection(&context_w->critical);
x = (UINT32)ix;
y = (UINT32)iy;
w = (UINT32)iw;
@ -84,16 +86,19 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw
data = UwacWindowGetDrawingBuffer(context_w->window);
if (!data || (rc != UWAC_SUCCESS))
return FALSE;
goto fail;
gdi = context_w->context.gdi;
if (!gdi)
return FALSE;
goto fail;
/* Ignore output if the surface size does not match. */
if (((INT64)x > geometry.width) || ((INT64)y > geometry.height))
return TRUE;
{
res = TRUE;
goto fail;
}
area.left = x;
area.top = y;
@ -103,21 +108,24 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw
if (!wlf_copy_image(gdi->primary_buffer, gdi->stride, gdi->width, gdi->height, data, stride,
geometry.width, geometry.height, &area,
context_w->context.settings->SmartSizing))
return FALSE;
goto fail;
if (!wlf_scale_coordinates(&context_w->context, &x, &y, FALSE))
return FALSE;
goto fail;
if (!wlf_scale_coordinates(&context_w->context, &w, &h, FALSE))
return FALSE;
goto fail;
if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS)
return FALSE;
goto fail;
if (UwacWindowSubmitBuffer(context_w->window, false) != UWAC_SUCCESS)
return FALSE;
goto fail;
return TRUE;
res = TRUE;
fail:
LeaveCriticalSection(&context_w->critical);
return res;
}
static BOOL wl_end_paint(rdpContext* context)
@ -296,6 +304,7 @@ static void wl_post_disconnect(freerdp* instance)
static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
{
BOOL rc;
UwacEvent event;
wlfContext* context;
@ -321,9 +330,11 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
break;
case UWAC_EVENT_FRAME_DONE:
if (UwacWindowSubmitBuffer(context->window, false) != UWAC_SUCCESS)
EnterCriticalSection(&context->critical);
rc = UwacWindowSubmitBuffer(context->window, false);
LeaveCriticalSection(&context->critical);
if (rc != UWAC_SUCCESS)
return FALSE;
break;
case UWAC_EVENT_POINTER_ENTER:
@ -552,6 +563,8 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context)
if (!wfl->displayHandle)
return FALSE;
InitializeCriticalSection(&wfl->critical);
return TRUE;
}
@ -567,6 +580,7 @@ static void wlf_client_free(freerdp* instance, rdpContext* context)
if (wlf->displayHandle)
CloseHandle(wlf->displayHandle);
DeleteCriticalSection(&wlf->critical);
}
static int wfl_client_start(rdpContext* context)

View File

@ -50,6 +50,7 @@ struct wlf_context
wfClipboard* clipboard;
wlfDispContext* disp;
wLog* log;
CRITICAL_SECTION critical;
};
BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP);

View File

@ -89,7 +89,7 @@ LPSTR tr_esc_str(LPCSTR arg, bool format)
strncpy(&tmp[cs], "</replaceable>", len);
else
/* coverity[buffer_size] */
strncpy(&tmp[cs], "&lt;", len);
strncpy(&tmp[cs], "&gt;", len);
cs += len;
break;

View File

@ -1120,7 +1120,7 @@ static void xf_button_map_init(xfContext* xfc)
x11_map[111] = 112;
/* query system for actual remapping */
if (!xfc->context.settings->UnmapButtons)
if (xfc->context.settings->UnmapButtons)
{
xf_get_x11_button_map(xfc, x11_map);
}
@ -1142,8 +1142,8 @@ static void xf_button_map_init(xfContext* xfc)
else
{
button_map* map = &xfc->button_map[pos++];
map->button = physical + Button1;
map->flags = get_flags_for_button(logical);
map->button = logical;
map->flags = get_flags_for_button(physical + Button1);
}
}
}
@ -1181,9 +1181,9 @@ static BOOL xf_pre_connect(freerdp* instance)
if (!settings->Username && !settings->CredentialsFromStdin && !settings->SmartcardLogon)
{
char* login_name = getlogin();
char login_name[MAX_PATH] = { 0 };
if (login_name)
if (getlogin_r(login_name, sizeof(login_name)) == 0)
{
settings->Username = _strdup(login_name);

View File

@ -374,12 +374,12 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win
}
static BOOL xf_event_MotionNotify(xfContext* xfc, const XMotionEvent* event, BOOL app)
{
if (xfc->use_xinput)
return TRUE;
if (xfc->window)
xf_floatbar_set_root_y(xfc->window->floatbar, event->y);
if (xfc->use_xinput)
return TRUE;
return xf_generic_MotionNotify(xfc, event->x, event->y, event->state, event->window, app);
}

View File

@ -30,7 +30,8 @@ set(${MODULE_PREFIX}_SRCS
cmdline.c
compatibility.c
compatibility.h
file.c)
file.c
geometry.c)
foreach(FREERDP_CHANNELS_CLIENT_SRC ${FREERDP_CHANNELS_CLIENT_SRCS})
get_filename_component(NINC ${FREERDP_CHANNELS_CLIENT_SRC} PATH)

View File

@ -467,14 +467,17 @@ static DWORD client_cli_accept_certificate(rdpSettings* settings)
{
case 'y':
case 'Y':
fgetc(stdin);
return 1;
case 't':
case 'T':
fgetc(stdin);
return 2;
case 'n':
case 'N':
fgetc(stdin);
return 0;
default:

42
client/common/geometry.c Normal file
View File

@ -0,0 +1,42 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Geometry tracking Virtual Channel Extension
*
* Copyright 2017 David Fort <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/client/geometry.h>
#include <winpr/interlocked.h>
void mappedGeometryRef(MAPPED_GEOMETRY* g)
{
InterlockedIncrement(&g->refCounter);
}
void mappedGeometryUnref(MAPPED_GEOMETRY* g)
{
if (InterlockedDecrement(&g->refCounter))
return;
g->MappedGeometryUpdate = NULL;
g->MappedGeometryClear = NULL;
g->custom = NULL;
free(g->geometry.rects);
free(g);
}

View File

@ -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 */

View File

@ -579,7 +579,7 @@ BOOL glyph_cache_put(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index, rdpGlyp
return FALSE;
}
if (index > glyphCache->glyphCache[id].number)
if (index >= glyphCache->glyphCache[id].number)
{
WLog_ERR(TAG, "invalid glyph cache index: %" PRIu32 " in cache id: %" PRIu32 "", index, id);
return FALSE;

View File

@ -201,6 +201,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN)
{
if (pbSrc >= pbEnd)
return FALSE;
SRCREADPIXEL(fgPel, pbSrc);
SRCNEXTPIXEL(pbSrc);
}
@ -231,8 +233,12 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
case MEGA_MEGA_DITHERED_RUN:
runLength = ExtractRunLength(code, pbSrc, &advance);
pbSrc = pbSrc + advance;
if (pbSrc >= pbEnd)
return FALSE;
SRCREADPIXEL(pixelA, pbSrc);
SRCNEXTPIXEL(pbSrc);
if (pbSrc >= pbEnd)
return FALSE;
SRCREADPIXEL(pixelB, pbSrc);
SRCNEXTPIXEL(pbSrc);
@ -252,6 +258,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
case MEGA_MEGA_COLOR_RUN:
runLength = ExtractRunLength(code, pbSrc, &advance);
pbSrc = pbSrc + advance;
if (pbSrc >= pbEnd)
return FALSE;
SRCREADPIXEL(pixelA, pbSrc);
SRCNEXTPIXEL(pbSrc);
@ -272,6 +280,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
runLength = ExtractRunLength(code, pbSrc, &advance);
pbSrc = pbSrc + advance;
if (pbSrc >= pbEnd)
return FALSE;
if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE)
{
SRCREADPIXEL(fgPel, pbSrc);
@ -338,6 +348,8 @@ static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BY
return FALSE;
UNROLL(runLength, {
if (pbSrc >= pbEnd)
return FALSE;
SRCREADPIXEL(temp, pbSrc);
SRCNEXTPIXEL(pbSrc);
DESTWRITEPIXEL(pbDest, temp);

View File

@ -232,7 +232,8 @@ static INLINE void write_pixel_24(BYTE* _buf, UINT32 _pix)
static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix)
{
*(UINT16*)_buf = _pix;
_buf[0] = _pix & 0xFF;
_buf[1] = (_pix >> 8) & 0xFF;
}
#undef DESTWRITEPIXEL

View File

@ -361,6 +361,14 @@ static BOOL freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file)
goto out_fail;
}
if (p > q)
{
WLog_ERR(
TAG,
"Failed to parse ASSISTANCE file: ConnectionString2 invalid field order for KH");
goto out_fail;
}
length = q - p;
free(file->RASpecificParams);
file->RASpecificParams = (char*)malloc(length + 1);
@ -388,6 +396,12 @@ static BOOL freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file)
goto out_fail;
}
if (p > q)
{
WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 invalid field "
"order for ID");
return -1;
}
length = q - p;
free(file->RASessionId);
file->RASessionId = (char*)malloc(length + 1);
@ -810,6 +824,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu
return -1;
}
if (p > q)
{
WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field "
"order for USERNAME");
return -1;
}
length = q - p;
file->Username = (char*)malloc(length + 1);
@ -834,6 +855,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu
return -1;
}
if (p > q)
{
WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field "
"order for LHTICKET");
return -1;
}
length = q - p;
file->LHTicket = (char*)malloc(length + 1);
@ -858,6 +886,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu
return -1;
}
if (p > q)
{
WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field "
"order for RCTICKET");
return -1;
}
length = q - p;
file->RCTicket = (char*)malloc(length + 1);
@ -882,6 +917,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu
return -1;
}
if (p > q)
{
WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field "
"order for RCTICKETENCRYPTED");
return -1;
}
length = q - p;
if ((length == 1) && (p[0] == '1'))
@ -902,6 +944,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu
return -1;
}
if (p > q)
{
WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field "
"order for PassStub");
return -1;
}
length = q - p;
file->PassStub = (char*)malloc(length + 1);
@ -926,6 +975,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu
return -1;
}
if (p > q)
{
WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field "
"order for DtStart");
return -1;
}
length = q - p;
r = (char*)malloc(length + 1);
@ -964,6 +1020,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu
return -1;
}
if (p > q)
{
WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field "
"order for DtLength");
return -1;
}
length = q - p;
r = (char*)malloc(length + 1);
@ -1002,6 +1065,13 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu
return -1;
}
if (p > q)
{
WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field "
"order for L");
return -1;
}
length = q - p;
if ((length == 1) && (p[0] == '1'))
@ -1061,6 +1131,12 @@ int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* bu
return -1;
}
if (p > q)
{
WLog_ERR(TAG, "Failed to parse ASSISTANCE file: invalid field order for <E>");
return -1;
}
q += sizeof("</E>") - 1;
length = q - p;
file->ConnectionString2 = (char*)malloc(length + 1);

View File

@ -160,7 +160,7 @@ BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, LPCTSTR hostname)
return TRUE;
}
if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, NULL) !=
if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, hostnameX, &SpnLength, NULL) !=
ERROR_BUFFER_OVERFLOW)
goto error;
@ -169,8 +169,8 @@ BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, LPCTSTR hostname)
if (!ntlm->ServicePrincipalName)
goto error;
if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName) !=
ERROR_SUCCESS)
if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, hostnameX, &SpnLength,
ntlm->ServicePrincipalName) != ERROR_SUCCESS)
goto error;
status = TRUE;

View File

@ -1167,7 +1167,7 @@ static BOOL rdg_tunnel_connect(rdpRdg* rdg)
return TRUE;
}
BOOL rdg_connect(rdpRdg* rdg, int timeout, BOOL* rpcFallback)
BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback)
{
BOOL status;
SOCKET outConnSocket = 0;

View File

@ -44,7 +44,7 @@ FREERDP_LOCAL void rdg_free(rdpRdg* rdg);
FREERDP_LOCAL BIO* rdg_get_front_bio_and_take_ownership(rdpRdg* rdg);
FREERDP_LOCAL BOOL rdg_connect(rdpRdg* rdg, int timeout, BOOL* rpcFallback);
FREERDP_LOCAL BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback);
FREERDP_LOCAL DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count);
#endif /* FREERDP_LIB_CORE_GATEWAY_RDG_H */

View File

@ -139,14 +139,14 @@ void rpc_pdu_header_print(rpcconn_hdr_t* header)
}
}
void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_hdr_t* header)
void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header)
{
header->common.rpc_vers = rpc->rpc_vers;
header->common.rpc_vers_minor = rpc->rpc_vers_minor;
header->common.packed_drep[0] = rpc->packed_drep[0];
header->common.packed_drep[1] = rpc->packed_drep[1];
header->common.packed_drep[2] = rpc->packed_drep[2];
header->common.packed_drep[3] = rpc->packed_drep[3];
header->rpc_vers = rpc->rpc_vers;
header->rpc_vers_minor = rpc->rpc_vers_minor;
header->packed_drep[0] = rpc->packed_drep[0];
header->packed_drep[1] = rpc->packed_drep[1];
header->packed_drep[2] = rpc->packed_drep[2];
header->packed_drep[3] = rpc->packed_drep[3];
}
UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment)

View File

@ -34,21 +34,23 @@ typedef struct rdp_rpc rdpRpc;
#pragma pack(push, 1)
#define DEFINE_RPC_COMMON_FIELDS() \
BYTE rpc_vers; \
BYTE rpc_vers_minor; \
BYTE ptype; \
BYTE pfc_flags; \
BYTE packed_drep[4]; \
UINT16 frag_length; \
UINT16 auth_length; \
UINT32 call_id
typedef struct
{
BYTE rpc_vers;
BYTE rpc_vers_minor;
BYTE ptype;
BYTE pfc_flags;
BYTE packed_drep[4];
UINT16 frag_length;
UINT16 auth_length;
UINT32 call_id;
} rpcconn_common_hdr_t;
#define RPC_COMMON_FIELDS_LENGTH 16
#define RPC_COMMON_FIELDS_LENGTH sizeof(rpcconn_common_hdr_t)
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
UINT16 Flags;
UINT16 NumberOfCommands;
@ -141,11 +143,6 @@ typedef struct _RPC_PDU
#pragma pack(push, 1)
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
} rpcconn_common_hdr_t;
typedef UINT16 p_context_id_t;
typedef UINT16 p_reject_reason_t;
@ -314,7 +311,7 @@ typedef struct auth_verifier_co_s auth_verifier_co_t;
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
UINT16 max_xmit_frag;
UINT16 max_recv_frag;
@ -328,7 +325,7 @@ typedef struct
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
UINT16 max_xmit_frag;
UINT16 max_recv_frag;
@ -345,7 +342,7 @@ typedef struct
/* bind header */
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
UINT16 max_xmit_frag;
UINT16 max_recv_frag;
@ -358,7 +355,7 @@ typedef struct
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
UINT16 max_xmit_frag;
UINT16 max_recv_frag;
@ -375,7 +372,7 @@ typedef struct
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
UINT16 max_xmit_frag;
UINT16 max_recv_frag;
@ -385,7 +382,7 @@ typedef struct
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
p_reject_reason_t provider_reject_reason;
@ -394,7 +391,7 @@ typedef struct
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
auth_verifier_co_t auth_verifier;
@ -460,7 +457,7 @@ typedef struct _RPC_FAULT_CODE RPC_FAULT_CODE;
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
UINT32 alloc_hint;
p_context_id_t p_cont_id;
@ -479,14 +476,14 @@ typedef struct
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
auth_verifier_co_t auth_verifier;
} rpcconn_orphaned_hdr_t;
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
UINT32 alloc_hint;
@ -505,7 +502,7 @@ typedef struct
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
UINT32 alloc_hint;
p_context_id_t p_cont_id;
@ -522,7 +519,7 @@ typedef struct
typedef struct
{
DEFINE_RPC_COMMON_FIELDS();
rpcconn_common_hdr_t header;
} rpcconn_shutdown_hdr_t;
typedef union {
@ -768,7 +765,7 @@ struct rdp_rpc
};
FREERDP_LOCAL void rpc_pdu_header_print(rpcconn_hdr_t* header);
FREERDP_LOCAL void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_hdr_t* header);
FREERDP_LOCAL void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_common_hdr_t* header);
FREERDP_LOCAL UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment);
FREERDP_LOCAL UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad);

View File

@ -190,12 +190,13 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
if (!sbuffer)
goto fail;
rpc_pdu_header_init(rpc, (rpcconn_hdr_t*)bind_pdu);
bind_pdu->auth_length = (UINT16)sbuffer->cbBuffer;
rpc_pdu_header_init(rpc, &bind_pdu->header);
bind_pdu->header.auth_length = (UINT16)sbuffer->cbBuffer;
bind_pdu->auth_verifier.auth_value = sbuffer->pvBuffer;
bind_pdu->ptype = PTYPE_BIND;
bind_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX;
bind_pdu->call_id = 2;
bind_pdu->header.ptype = PTYPE_BIND;
bind_pdu->header.pfc_flags =
PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_SUPPORT_HEADER_SIGN | PFC_CONC_MPX;
bind_pdu->header.call_id = 2;
bind_pdu->max_xmit_frag = rpc->max_xmit_frag;
bind_pdu->max_recv_frag = rpc->max_recv_frag;
bind_pdu->assoc_group_id = 0;
@ -240,9 +241,9 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
bind_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
bind_pdu->auth_verifier.auth_reserved = 0x00;
bind_pdu->auth_verifier.auth_context_id = 0x00000000;
offset += (8 + bind_pdu->auth_length);
bind_pdu->frag_length = offset;
buffer = (BYTE*)malloc(bind_pdu->frag_length);
offset += (8 + bind_pdu->header.auth_length);
bind_pdu->header.frag_length = offset;
buffer = (BYTE*)malloc(bind_pdu->header.frag_length);
if (!buffer)
goto fail;
@ -256,10 +257,11 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
offset = 116;
rpc_offset_pad(&offset, bind_pdu->auth_verifier.auth_pad_length);
CopyMemory(&buffer[offset], &bind_pdu->auth_verifier.auth_type, 8);
CopyMemory(&buffer[offset + 8], bind_pdu->auth_verifier.auth_value, bind_pdu->auth_length);
offset += (8 + bind_pdu->auth_length);
length = bind_pdu->frag_length;
clientCall = rpc_client_call_new(bind_pdu->call_id, 0);
CopyMemory(&buffer[offset + 8], bind_pdu->auth_verifier.auth_value,
bind_pdu->header.auth_length);
offset += (8 + bind_pdu->header.auth_length);
length = bind_pdu->header.frag_length;
clientCall = rpc_client_call_new(bind_pdu->header.call_id, 0);
if (!clientCall)
goto fail;
@ -374,12 +376,12 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
return -1;
}
rpc_pdu_header_init(rpc, (rpcconn_hdr_t*)auth_3_pdu);
auth_3_pdu->auth_length = (UINT16)sbuffer->cbBuffer;
rpc_pdu_header_init(rpc, &auth_3_pdu->header);
auth_3_pdu->header.auth_length = (UINT16)sbuffer->cbBuffer;
auth_3_pdu->auth_verifier.auth_value = sbuffer->pvBuffer;
auth_3_pdu->ptype = PTYPE_RPC_AUTH_3;
auth_3_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX;
auth_3_pdu->call_id = 2;
auth_3_pdu->header.ptype = PTYPE_RPC_AUTH_3;
auth_3_pdu->header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX;
auth_3_pdu->header.call_id = 2;
auth_3_pdu->max_xmit_frag = rpc->max_xmit_frag;
auth_3_pdu->max_recv_frag = rpc->max_recv_frag;
offset = 20;
@ -388,9 +390,9 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
auth_3_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
auth_3_pdu->auth_verifier.auth_reserved = 0x00;
auth_3_pdu->auth_verifier.auth_context_id = 0x00000000;
offset += (8 + auth_3_pdu->auth_length);
auth_3_pdu->frag_length = offset;
buffer = (BYTE*)malloc(auth_3_pdu->frag_length);
offset += (8 + auth_3_pdu->header.auth_length);
auth_3_pdu->header.frag_length = offset;
buffer = (BYTE*)malloc(auth_3_pdu->header.frag_length);
if (!buffer)
{
@ -402,10 +404,11 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
offset = 20;
rpc_offset_pad(&offset, auth_3_pdu->auth_verifier.auth_pad_length);
CopyMemory(&buffer[offset], &auth_3_pdu->auth_verifier.auth_type, 8);
CopyMemory(&buffer[offset + 8], auth_3_pdu->auth_verifier.auth_value, auth_3_pdu->auth_length);
offset += (8 + auth_3_pdu->auth_length);
length = auth_3_pdu->frag_length;
clientCall = rpc_client_call_new(auth_3_pdu->call_id, 0);
CopyMemory(&buffer[offset + 8], auth_3_pdu->auth_verifier.auth_value,
auth_3_pdu->header.auth_length);
offset += (8 + auth_3_pdu->header.auth_length);
length = auth_3_pdu->header.frag_length;
clientCall = rpc_client_call_new(auth_3_pdu->header.call_id, 0);
if (ArrayList_Add(rpc->client->ClientCallList, clientCall) >= 0)
{

View File

@ -895,7 +895,7 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum)
SecBufferDesc Message;
RpcClientCall* clientCall = NULL;
rdpNtlm* ntlm;
rpcconn_request_hdr_t* request_pdu = NULL;
rpcconn_request_hdr_t request_pdu = { 0 };
RpcVirtualConnection* connection;
RpcInChannel* inChannel;
size_t length;
@ -931,25 +931,20 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum)
if (ntlm_client_query_auth_size(ntlm) < 0)
goto fail;
request_pdu = (rpcconn_request_hdr_t*)calloc(1, sizeof(rpcconn_request_hdr_t));
if (!request_pdu)
goto fail;
size = ntlm_client_get_context_max_size(ntlm);
if (size < 0)
goto fail;
rpc_pdu_header_init(rpc, (rpcconn_hdr_t*)request_pdu);
request_pdu->ptype = PTYPE_REQUEST;
request_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
request_pdu->auth_length = (UINT16)size;
request_pdu->call_id = rpc->CallId++;
request_pdu->alloc_hint = length;
request_pdu->p_cont_id = 0x0000;
request_pdu->opnum = opnum;
clientCall = rpc_client_call_new(request_pdu->call_id, request_pdu->opnum);
rpc_pdu_header_init(rpc, &request_pdu.header);
request_pdu.header.ptype = PTYPE_REQUEST;
request_pdu.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
request_pdu.header.auth_length = (UINT16)size;
request_pdu.header.call_id = rpc->CallId++;
request_pdu.alloc_hint = length;
request_pdu.p_cont_id = 0x0000;
request_pdu.opnum = opnum;
clientCall = rpc_client_call_new(request_pdu.header.call_id, request_pdu.opnum);
if (!clientCall)
goto fail;
@ -960,34 +955,34 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum)
goto fail;
}
if (request_pdu->opnum == TsProxySetupReceivePipeOpnum)
rpc->PipeCallId = request_pdu->call_id;
if (request_pdu.opnum == TsProxySetupReceivePipeOpnum)
rpc->PipeCallId = request_pdu.header.call_id;
request_pdu->stub_data = Stream_Buffer(s);
request_pdu.stub_data = Stream_Buffer(s);
offset = 24;
stub_data_pad = rpc_offset_align(&offset, 8);
offset += length;
request_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4);
request_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT;
request_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
request_pdu->auth_verifier.auth_reserved = 0x00;
request_pdu->auth_verifier.auth_context_id = 0x00000000;
offset += (8 + request_pdu->auth_length);
request_pdu->frag_length = offset;
buffer = (BYTE*)calloc(1, request_pdu->frag_length);
request_pdu.auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4);
request_pdu.auth_verifier.auth_type = RPC_C_AUTHN_WINNT;
request_pdu.auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
request_pdu.auth_verifier.auth_reserved = 0x00;
request_pdu.auth_verifier.auth_context_id = 0x00000000;
offset += (8 + request_pdu.header.auth_length);
request_pdu.header.frag_length = offset;
buffer = (BYTE*)calloc(1, request_pdu.header.frag_length);
if (!buffer)
goto fail;
CopyMemory(buffer, request_pdu, 24);
CopyMemory(buffer, &request_pdu, 24);
offset = 24;
rpc_offset_pad(&offset, stub_data_pad);
CopyMemory(&buffer[offset], request_pdu->stub_data, length);
CopyMemory(&buffer[offset], request_pdu.stub_data, length);
offset += length;
rpc_offset_pad(&offset, request_pdu->auth_verifier.auth_pad_length);
CopyMemory(&buffer[offset], &request_pdu->auth_verifier.auth_type, 8);
rpc_offset_pad(&offset, request_pdu.auth_verifier.auth_pad_length);
CopyMemory(&buffer[offset], &request_pdu.auth_verifier.auth_type, 8);
offset += 8;
Buffers[0].BufferType = SECBUFFER_DATA; /* auth_data */
Buffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY; /* auth_data */
Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */
Buffers[0].pvBuffer = buffer;
Buffers[0].cbBuffer = offset;
@ -1007,14 +1002,13 @@ BOOL rpc_client_write_call(rdpRpc* rpc, wStream* s, UINT16 opnum)
CopyMemory(&buffer[offset], Buffers[1].pvBuffer, Buffers[1].cbBuffer);
offset += Buffers[1].cbBuffer;
if (rpc_in_channel_send_pdu(inChannel, buffer, request_pdu->frag_length) < 0)
if (rpc_in_channel_send_pdu(inChannel, buffer, request_pdu.header.frag_length) < 0)
goto fail;
rc = TRUE;
fail:
free(buffer);
free(Buffers[1].pvBuffer);
free(request_pdu);
Stream_Free(s, TRUE);
return rc;
}

View File

@ -67,19 +67,21 @@
*
*/
static void rts_pdu_header_init(rpcconn_rts_hdr_t* header)
static rpcconn_rts_hdr_t rts_pdu_header_init(void)
{
ZeroMemory(header, sizeof(*header));
header->rpc_vers = 5;
header->rpc_vers_minor = 0;
header->ptype = PTYPE_RTS;
header->packed_drep[0] = 0x10;
header->packed_drep[1] = 0x00;
header->packed_drep[2] = 0x00;
header->packed_drep[3] = 0x00;
header->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
header->auth_length = 0;
header->call_id = 0;
rpcconn_rts_hdr_t header = { 0 };
header.header.rpc_vers = 5;
header.header.rpc_vers_minor = 0;
header.header.ptype = PTYPE_RTS;
header.header.packed_drep[0] = 0x10;
header.header.packed_drep[1] = 0x00;
header.header.packed_drep[2] = 0x00;
header.header.packed_drep[3] = 0x00;
header.header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
header.header.auth_length = 0;
header.header.call_id = 0;
return header;
}
static int rts_receive_window_size_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length,
@ -406,21 +408,21 @@ int rts_send_CONN_A1_pdu(rdpRpc* rpc)
{
int status;
BYTE* buffer;
rpcconn_rts_hdr_t header;
rpcconn_rts_hdr_t header = rts_pdu_header_init();
UINT32 ReceiveWindowSize;
BYTE* OUTChannelCookie;
BYTE* VirtualConnectionCookie;
RpcVirtualConnection* connection = rpc->VirtualConnection;
RpcOutChannel* outChannel = connection->DefaultOutChannel;
rts_pdu_header_init(&header);
header.frag_length = 76;
header.header.frag_length = 76;
header.Flags = RTS_FLAG_NONE;
header.NumberOfCommands = 4;
WLog_DBG(TAG, "Sending CONN/A1 RTS PDU");
VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
OUTChannelCookie = (BYTE*)&(outChannel->common.Cookie);
ReceiveWindowSize = outChannel->ReceiveWindow;
buffer = (BYTE*)malloc(header.frag_length);
buffer = (BYTE*)malloc(header.header.frag_length);
if (!buffer)
return -1;
@ -432,7 +434,7 @@ int rts_send_CONN_A1_pdu(rdpRpc* rpc)
rts_cookie_command_write(&buffer[48], OUTChannelCookie); /* OUTChannelCookie (20 bytes) */
rts_receive_window_size_command_write(&buffer[68],
ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */
status = rpc_channel_write(&outChannel->common, buffer, header.frag_length);
status = rpc_channel_write(&outChannel->common, buffer, header.header.frag_length);
free(buffer);
return (status > 0) ? 1 : -1;
}
@ -453,21 +455,21 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc)
int status;
BYTE* buffer;
UINT32 length;
rpcconn_rts_hdr_t header;
rpcconn_rts_hdr_t header = rts_pdu_header_init();
BYTE* INChannelCookie;
BYTE* AssociationGroupId;
BYTE* VirtualConnectionCookie;
RpcVirtualConnection* connection = rpc->VirtualConnection;
RpcInChannel* inChannel = connection->DefaultInChannel;
rts_pdu_header_init(&header);
header.frag_length = 104;
header.header.frag_length = 104;
header.Flags = RTS_FLAG_NONE;
header.NumberOfCommands = 6;
WLog_DBG(TAG, "Sending CONN/B1 RTS PDU");
VirtualConnectionCookie = (BYTE*)&(connection->Cookie);
INChannelCookie = (BYTE*)&(inChannel->common.Cookie);
AssociationGroupId = (BYTE*)&(connection->AssociationGroupId);
buffer = (BYTE*)malloc(header.frag_length);
buffer = (BYTE*)malloc(header.header.frag_length);
if (!buffer)
return -1;
@ -483,7 +485,7 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc)
rpc->KeepAliveInterval); /* ClientKeepalive (8 bytes) */
rts_association_group_id_command_write(&buffer[84],
AssociationGroupId); /* AssociationGroupId (20 bytes) */
length = header.frag_length;
length = header.header.frag_length;
status = rpc_channel_write(&inChannel->common, buffer, length);
free(buffer);
return (status > 0) ? 1 : -1;
@ -520,14 +522,14 @@ static int rts_send_keep_alive_pdu(rdpRpc* rpc)
int status;
BYTE* buffer;
UINT32 length;
rpcconn_rts_hdr_t header;
rpcconn_rts_hdr_t header = rts_pdu_header_init();
RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel;
rts_pdu_header_init(&header);
header.frag_length = 28;
header.header.frag_length = 28;
header.Flags = RTS_FLAG_OTHER_CMD;
header.NumberOfCommands = 1;
WLog_DBG(TAG, "Sending Keep-Alive RTS PDU");
buffer = (BYTE*)malloc(header.frag_length);
buffer = (BYTE*)malloc(header.header.frag_length);
if (!buffer)
return -1;
@ -535,7 +537,7 @@ static int rts_send_keep_alive_pdu(rdpRpc* rpc)
CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */
rts_client_keepalive_command_write(
&buffer[20], rpc->CurrentKeepAliveInterval); /* ClientKeepAlive (8 bytes) */
length = header.frag_length;
length = header.header.frag_length;
status = rpc_channel_write(&inChannel->common, buffer, length);
free(buffer);
return (status > 0) ? 1 : -1;
@ -546,15 +548,15 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc)
int status;
BYTE* buffer;
UINT32 length;
rpcconn_rts_hdr_t header;
rpcconn_rts_hdr_t header = rts_pdu_header_init();
UINT32 BytesReceived;
UINT32 AvailableWindow;
BYTE* ChannelCookie;
RpcVirtualConnection* connection = rpc->VirtualConnection;
RpcInChannel* inChannel = connection->DefaultInChannel;
RpcOutChannel* outChannel = connection->DefaultOutChannel;
rts_pdu_header_init(&header);
header.frag_length = 56;
header.header.frag_length = 56;
header.Flags = RTS_FLAG_OTHER_CMD;
header.NumberOfCommands = 2;
WLog_DBG(TAG, "Sending FlowControlAck RTS PDU");
@ -562,7 +564,7 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc)
AvailableWindow = outChannel->AvailableWindowAdvertised;
ChannelCookie = (BYTE*)&(outChannel->common.Cookie);
outChannel->ReceiverAvailableWindow = outChannel->AvailableWindowAdvertised;
buffer = (BYTE*)malloc(header.frag_length);
buffer = (BYTE*)malloc(header.header.frag_length);
if (!buffer)
return -1;
@ -571,7 +573,7 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc)
rts_destination_command_write(&buffer[20], FDOutProxy); /* Destination Command (8 bytes) */
/* FlowControlAck Command (28 bytes) */
rts_flow_control_ack_command_write(&buffer[28], BytesReceived, AvailableWindow, ChannelCookie);
length = header.frag_length;
length = header.header.frag_length;
status = rpc_channel_write(&inChannel->common, buffer, length);
free(buffer);
return (status > 0) ? 1 : -1;
@ -640,20 +642,20 @@ static int rts_send_ping_pdu(rdpRpc* rpc)
int status;
BYTE* buffer;
UINT32 length;
rpcconn_rts_hdr_t header;
rpcconn_rts_hdr_t header = rts_pdu_header_init();
RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel;
rts_pdu_header_init(&header);
header.frag_length = 20;
header.header.frag_length = 20;
header.Flags = RTS_FLAG_PING;
header.NumberOfCommands = 0;
WLog_DBG(TAG, "Sending Ping RTS PDU");
buffer = (BYTE*)malloc(header.frag_length);
buffer = (BYTE*)malloc(header.header.frag_length);
if (!buffer)
return -1;
CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */
length = header.frag_length;
length = header.header.frag_length;
status = rpc_channel_write(&inChannel->common, buffer, length);
free(buffer);
return (status > 0) ? 1 : -1;
@ -737,17 +739,17 @@ static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
{
int status;
BYTE* buffer;
rpcconn_rts_hdr_t header;
rpcconn_rts_hdr_t header = rts_pdu_header_init();
BYTE* SuccessorChannelCookie;
RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel;
RpcOutChannel* nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
rts_pdu_header_init(&header);
header.frag_length = 56;
header.header.frag_length = 56;
header.Flags = RTS_FLAG_OUT_CHANNEL;
header.NumberOfCommands = 3;
WLog_DBG(TAG, "Sending OUT_R2/A7 RTS PDU");
SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
buffer = (BYTE*)malloc(header.frag_length);
buffer = (BYTE*)malloc(header.header.frag_length);
if (!buffer)
return -1;
@ -757,7 +759,7 @@ static int rts_send_OUT_R2_A7_pdu(rdpRpc* rpc)
rts_cookie_command_write(&buffer[28],
SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */
rts_version_command_write(&buffer[48]); /* Version (8 bytes) */
status = rpc_channel_write(&inChannel->common, buffer, header.frag_length);
status = rpc_channel_write(&inChannel->common, buffer, header.header.frag_length);
free(buffer);
return (status > 0) ? 1 : -1;
}
@ -766,21 +768,21 @@ static int rts_send_OUT_R2_C1_pdu(rdpRpc* rpc)
{
int status;
BYTE* buffer;
rpcconn_rts_hdr_t header;
rpcconn_rts_hdr_t header = rts_pdu_header_init();
RpcOutChannel* nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel;
rts_pdu_header_init(&header);
header.frag_length = 24;
header.header.frag_length = 24;
header.Flags = RTS_FLAG_PING;
header.NumberOfCommands = 1;
WLog_DBG(TAG, "Sending OUT_R2/C1 RTS PDU");
buffer = (BYTE*)malloc(header.frag_length);
buffer = (BYTE*)malloc(header.header.frag_length);
if (!buffer)
return -1;
CopyMemory(buffer, ((BYTE*)&header), 20); /* RTS Header (20 bytes) */
rts_empty_command_write(&buffer[20]); /* Empty command (4 bytes) */
status = rpc_channel_write(&nextOutChannel->common, buffer, header.frag_length);
status = rpc_channel_write(&nextOutChannel->common, buffer, header.header.frag_length);
free(buffer);
return (status > 0) ? 1 : -1;
}
@ -789,7 +791,7 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
{
int status;
BYTE* buffer;
rpcconn_rts_hdr_t header;
rpcconn_rts_hdr_t header = rts_pdu_header_init();
UINT32 ReceiveWindowSize;
BYTE* VirtualConnectionCookie;
BYTE* PredecessorChannelCookie;
@ -797,8 +799,8 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
RpcVirtualConnection* connection = rpc->VirtualConnection;
RpcOutChannel* outChannel = connection->DefaultOutChannel;
RpcOutChannel* nextOutChannel = connection->NonDefaultOutChannel;
rts_pdu_header_init(&header);
header.frag_length = 96;
header.header.frag_length = 96;
header.Flags = RTS_FLAG_RECYCLE_CHANNEL;
header.NumberOfCommands = 5;
WLog_DBG(TAG, "Sending OUT_R1/A3 RTS PDU");
@ -806,7 +808,7 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
PredecessorChannelCookie = (BYTE*)&(outChannel->common.Cookie);
SuccessorChannelCookie = (BYTE*)&(nextOutChannel->common.Cookie);
ReceiveWindowSize = outChannel->ReceiveWindow;
buffer = (BYTE*)malloc(header.frag_length);
buffer = (BYTE*)malloc(header.header.frag_length);
if (!buffer)
return -1;
@ -821,7 +823,7 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
SuccessorChannelCookie); /* SuccessorChannelCookie (20 bytes) */
rts_receive_window_size_command_write(&buffer[88],
ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */
status = rpc_channel_write(&nextOutChannel->common, buffer, header.frag_length);
status = rpc_channel_write(&nextOutChannel->common, buffer, header.header.frag_length);
free(buffer);
return (status > 0) ? 1 : -1;
}

View File

@ -302,7 +302,7 @@ BOOL rts_match_pdu_signature(const RtsPduSignature* signature, const rpcconn_rts
buffer = (const BYTE*)rts;
offset = RTS_PDU_HEADER_LENGTH;
length = rts->frag_length - offset;
length = rts->header.frag_length - offset;
for (i = 0; i < rts->NumberOfCommands; i++)
{
@ -319,7 +319,7 @@ BOOL rts_match_pdu_signature(const RtsPduSignature* signature, const rpcconn_rts
CommandLength = (UINT32)status;
offset += CommandLength;
length = rts->frag_length - offset;
length = rts->header.frag_length - offset;
}
return TRUE;
@ -342,7 +342,7 @@ BOOL rts_extract_pdu_signature(RtsPduSignature* signature, const rpcconn_rts_hdr
signature->NumberOfCommands = rts->NumberOfCommands;
buffer = (BYTE*)rts;
offset = RTS_PDU_HEADER_LENGTH;
length = rts->frag_length - offset;
length = rts->header.frag_length - offset;
for (i = 0; i < rts->NumberOfCommands; i++)
{
@ -356,7 +356,7 @@ BOOL rts_extract_pdu_signature(RtsPduSignature* signature, const rpcconn_rts_hdr
CommandLength = (UINT32)status;
offset += CommandLength;
length = rts->frag_length - offset;
length = rts->header.frag_length - offset;
}
return TRUE;

View File

@ -39,6 +39,19 @@
#define TAG FREERDP_TAG("core.gateway.tsg")
#define TSG_PACKET_TYPE_HEADER 0x00004844
#define TSG_PACKET_TYPE_VERSIONCAPS 0x00005643
#define TSG_PACKET_TYPE_QUARCONFIGREQUEST 0x00005143
#define TSG_PACKET_TYPE_QUARREQUEST 0x00005152
#define TSG_PACKET_TYPE_RESPONSE 0x00005052
#define TSG_PACKET_TYPE_QUARENC_RESPONSE 0x00004552
#define TSG_CAPABILITY_TYPE_NAP 0x00000001
#define TSG_PACKET_TYPE_CAPS_RESPONSE 0x00004350
#define TSG_PACKET_TYPE_MSGREQUEST_PACKET 0x00004752
#define TSG_PACKET_TYPE_MESSAGE_PACKET 0x00004750
#define TSG_PACKET_TYPE_AUTH 0x00004054
#define TSG_PACKET_TYPE_REAUTH 0x00005250
typedef WCHAR* RESOURCENAME;
typedef struct _tsendpointinfo
@ -218,6 +231,214 @@ struct rdp_tsg
TSG_PACKET_VERSIONCAPS packetVersionCaps;
};
static const char* tsg_packet_id_to_string(UINT32 packetId)
{
switch (packetId)
{
case TSG_PACKET_TYPE_HEADER:
return "TSG_PACKET_TYPE_HEADER";
case TSG_PACKET_TYPE_VERSIONCAPS:
return "TSG_PACKET_TYPE_VERSIONCAPS";
case TSG_PACKET_TYPE_QUARCONFIGREQUEST:
return "TSG_PACKET_TYPE_QUARCONFIGREQUEST";
case TSG_PACKET_TYPE_QUARREQUEST:
return "TSG_PACKET_TYPE_QUARREQUEST";
case TSG_PACKET_TYPE_RESPONSE:
return "TSG_PACKET_TYPE_RESPONSE";
case TSG_PACKET_TYPE_QUARENC_RESPONSE:
return "TSG_PACKET_TYPE_QUARENC_RESPONSE";
case TSG_CAPABILITY_TYPE_NAP:
return "TSG_CAPABILITY_TYPE_NAP";
case TSG_PACKET_TYPE_CAPS_RESPONSE:
return "TSG_PACKET_TYPE_CAPS_RESPONSE";
case TSG_PACKET_TYPE_MSGREQUEST_PACKET:
return "TSG_PACKET_TYPE_MSGREQUEST_PACKET";
case TSG_PACKET_TYPE_MESSAGE_PACKET:
return "TSG_PACKET_TYPE_MESSAGE_PACKET";
case TSG_PACKET_TYPE_AUTH:
return "TSG_PACKET_TYPE_AUTH";
case TSG_PACKET_TYPE_REAUTH:
return "TSG_PACKET_TYPE_REAUTH";
default:
return "UNKNOWN";
}
}
static const char* tsg_state_to_string(TSG_STATE state)
{
switch (state)
{
case TSG_STATE_INITIAL:
return "TSG_STATE_INITIAL";
case TSG_STATE_CONNECTED:
return "TSG_STATE_CONNECTED";
case TSG_STATE_AUTHORIZED:
return "TSG_STATE_AUTHORIZED";
case TSG_STATE_CHANNEL_CREATED:
return "TSG_STATE_CHANNEL_CREATED";
case TSG_STATE_PIPE_CREATED:
return "TSG_STATE_PIPE_CREATED";
case TSG_STATE_TUNNEL_CLOSE_PENDING:
return "TSG_STATE_TUNNEL_CLOSE_PENDING";
case TSG_STATE_CHANNEL_CLOSE_PENDING:
return "TSG_STATE_CHANNEL_CLOSE_PENDING";
case TSG_STATE_FINAL:
return "TSG_STATE_FINAL";
default:
return "TSG_STATE_UNKNOWN";
}
}
static BOOL tsg_print(char** buffer, size_t* len, const char* fmt, ...)
{
int rc;
va_list ap;
if (!buffer || !len || !fmt)
return FALSE;
va_start(ap, fmt);
rc = vsnprintf(*buffer, *len, fmt, ap);
va_end(ap);
if ((rc < 0) || ((size_t)rc > *len))
return FALSE;
*len -= (size_t)rc;
*buffer += (size_t)rc;
return TRUE;
}
static BOOL tsg_packet_header_to_string(char** buffer, size_t* length,
const TSG_PACKET_HEADER* header)
{
return tsg_print(buffer, length,
"header { ComponentId=0x%04" PRIx16 ", PacketId=0x%04" PRIx16 " }",
header->ComponentId, header->PacketId);
}
static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length,
const TSG_PACKET_CAPABILITIES* caps, UINT32 numCaps)
{
UINT32 x;
if (!tsg_print(buffer, length, "capabilities { "))
return FALSE;
for (x = 0; x < numCaps; x++)
{
const TSG_PACKET_CAPABILITIES* cur = &caps[x];
switch (cur->capabilityType)
{
case TSG_CAPABILITY_TYPE_NAP:
if (!tsg_print(buffer, length, "%s { capabilities=0x%08" PRIx32 " }",
tsg_packet_id_to_string(cur->capabilityType),
cur->tsgPacket.tsgCapNap.capabilities))
return FALSE;
break;
default:
if (!tsg_print(buffer, length, "TSG_UNKNOWN_CAPABILITY"))
return FALSE;
break;
}
}
return tsg_print(buffer, length, " }");
}
static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length,
const TSG_PACKET_VERSIONCAPS* caps)
{
if (!tsg_print(buffer, length, "versioncaps { "))
return FALSE;
if (!tsg_packet_header_to_string(buffer, length, &caps->tsgHeader))
return FALSE;
if (!tsg_print(buffer, length, " "))
return FALSE;
if (!tsg_packet_capabilities_to_string(buffer, length, caps->tsgCaps, caps->numCapabilities))
return FALSE;
if (!tsg_print(buffer, length,
" numCapabilities=0x%08" PRIx32 ", majorVersion=0x%04" PRIx16
", minorVersion=0x%04" PRIx16 ", quarantineCapabilities=0x%04" PRIx16,
caps->numCapabilities, caps->majorVersion, caps->minorVersion,
caps->quarantineCapabilities))
return FALSE;
return tsg_print(buffer, length, " }");
}
static const char* tsg_packet_to_string(const TSG_PACKET* packet)
{
size_t len = 8192;
static char sbuffer[8193] = { 0 };
char* buffer = sbuffer;
if (!tsg_print(&buffer, &len, "TSG_PACKET { packetId=%s [0x%08" PRIx32 "], ",
tsg_packet_id_to_string(packet->packetId), packet->packetId))
goto fail;
switch (packet->packetId)
{
case TSG_PACKET_TYPE_HEADER:
if (!tsg_packet_header_to_string(&buffer, &len, packet->tsgPacket.packetHeader))
goto fail;
break;
case TSG_PACKET_TYPE_VERSIONCAPS:
if (!tsg_packet_versioncaps_to_string(&buffer, &len,
packet->tsgPacket.packetVersionCaps))
goto fail;
break;
case TSG_PACKET_TYPE_QUARCONFIGREQUEST:
if (!tsg_print(&buffer, &len, "TODO"))
goto fail;
break;
case TSG_PACKET_TYPE_QUARREQUEST:
if (!tsg_print(&buffer, &len, "TODO"))
goto fail;
break;
case TSG_PACKET_TYPE_RESPONSE:
if (!tsg_print(&buffer, &len, "TODO"))
goto fail;
break;
case TSG_PACKET_TYPE_QUARENC_RESPONSE:
if (!tsg_print(&buffer, &len, "TODO"))
goto fail;
break;
case TSG_CAPABILITY_TYPE_NAP:
if (!tsg_print(&buffer, &len, "TODO"))
goto fail;
break;
case TSG_PACKET_TYPE_CAPS_RESPONSE:
if (!tsg_print(&buffer, &len, "TODO"))
goto fail;
break;
case TSG_PACKET_TYPE_MSGREQUEST_PACKET:
if (!tsg_print(&buffer, &len, "TODO"))
goto fail;
break;
case TSG_PACKET_TYPE_MESSAGE_PACKET:
if (!tsg_print(&buffer, &len, "TODO"))
goto fail;
break;
case TSG_PACKET_TYPE_AUTH:
if (!tsg_print(&buffer, &len, "TODO"))
goto fail;
break;
case TSG_PACKET_TYPE_REAUTH:
if (!tsg_print(&buffer, &len, "TODO"))
goto fail;
break;
default:
if (!tsg_print(&buffer, &len, "INVALID"))
goto fail;
break;
}
if (!tsg_print(&buffer, &len, " }"))
goto fail;
fail:
return sbuffer;
}
static BOOL tsg_stream_align(wStream* s, size_t align)
{
size_t pos;
@ -362,7 +583,7 @@ static int TsProxySendToServer(handle_t IDL_handle, const byte pRpcMessage[], UI
* );
*/
static BOOL TsProxyCreateTunnelWriteRequest(rdpTsg* tsg, PTSG_PACKET tsgPacket)
static BOOL TsProxyCreateTunnelWriteRequest(rdpTsg* tsg, const PTSG_PACKET tsgPacket)
{
BOOL rc = FALSE;
BOOL write = TRUE;
@ -374,7 +595,7 @@ static BOOL TsProxyCreateTunnelWriteRequest(rdpTsg* tsg, PTSG_PACKET tsgPacket)
return FALSE;
rpc = tsg->rpc;
WLog_DBG(TAG, "TsProxyCreateTunnelWriteRequest");
WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_to_string(tsgPacket));
s = Stream_New(NULL, 108);
if (!s)
@ -506,7 +727,6 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu,
PTSG_PACKET_VERSIONCAPS versionCaps = NULL;
PTSG_PACKET_CAPS_RESPONSE packetCapsResponse = NULL;
PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse = NULL;
WLog_DBG(TAG, "TsProxyCreateTunnelReadResponse");
if (!pdu)
return FALSE;
@ -523,6 +743,8 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu,
Stream_Read_UINT32(pdu->s, packet->packetId); /* PacketId (4 bytes) */
Stream_Read_UINT32(pdu->s, SwitchValue); /* SwitchValue (4 bytes) */
WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_id_to_string(packet->packetId));
if ((packet->packetId == TSG_PACKET_TYPE_CAPS_RESPONSE) &&
(SwitchValue == TSG_PACKET_TYPE_CAPS_RESPONSE))
{
@ -885,7 +1107,6 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
UINT32 idleTimeout;
PTSG_PACKET packet = NULL;
PTSG_PACKET_RESPONSE packetResponse = NULL;
WLog_DBG(TAG, "TsProxyAuthorizeTunnelReadResponse");
if (!pdu)
return FALSE;
@ -902,6 +1123,8 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
Stream_Read_UINT32(pdu->s, packet->packetId); /* PacketId (4 bytes) */
Stream_Read_UINT32(pdu->s, SwitchValue); /* SwitchValue (4 bytes) */
WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_id_to_string(packet->packetId));
if (packet->packetId == E_PROXY_NAP_ACCESSDENIED)
{
WLog_ERR(TAG, "status: E_PROXY_NAP_ACCESSDENIED (0x%08X)", E_PROXY_NAP_ACCESSDENIED);
@ -1059,7 +1282,6 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
TSG_PACKET_MSG_RESPONSE packetMsgResponse = { 0 };
TSG_PACKET_STRING_MESSAGE packetStringMessage = { 0 };
TSG_PACKET_REAUTH_MESSAGE packetReauthMessage = { 0 };
WLog_DBG(TAG, "TsProxyMakeTunnelCallReadResponse");
/* This is an asynchronous response */
@ -1073,6 +1295,8 @@ static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
Stream_Read_UINT32(pdu->s, packet.packetId); /* PacketId (4 bytes) */
Stream_Read_UINT32(pdu->s, SwitchValue); /* SwitchValue (4 bytes) */
WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_id_to_string(packet.packetId));
if ((packet.packetId != TSG_PACKET_TYPE_MESSAGE_PACKET) ||
(SwitchValue != TSG_PACKET_TYPE_MESSAGE_PACKET))
{
@ -1357,50 +1581,16 @@ static BOOL TsProxySetupReceivePipeWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* cha
static BOOL tsg_transition_to_state(rdpTsg* tsg, TSG_STATE state)
{
const char* str = "TSG_STATE_UNKNOWN";
const char* oldState = tsg_state_to_string(tsg->state);
const char* newState = tsg_state_to_string(state);
switch (state)
{
case TSG_STATE_INITIAL:
str = "TSG_STATE_INITIAL";
break;
case TSG_STATE_CONNECTED:
str = "TSG_STATE_CONNECTED";
break;
case TSG_STATE_AUTHORIZED:
str = "TSG_STATE_AUTHORIZED";
break;
case TSG_STATE_CHANNEL_CREATED:
str = "TSG_STATE_CHANNEL_CREATED";
break;
case TSG_STATE_PIPE_CREATED:
str = "TSG_STATE_PIPE_CREATED";
break;
case TSG_STATE_TUNNEL_CLOSE_PENDING:
str = "TSG_STATE_TUNNEL_CLOSE_PENDING";
break;
case TSG_STATE_CHANNEL_CLOSE_PENDING:
str = "TSG_STATE_CHANNEL_CLOSE_PENDING";
break;
case TSG_STATE_FINAL:
str = "TSG_STATE_FINAL";
break;
}
WLog_DBG(TAG, "%s", str);
WLog_DBG(TAG, "%s -> %s", oldState, newState);
return tsg_set_state(tsg, state);
}
BOOL tsg_proxy_begin(rdpTsg* tsg)
{
TSG_PACKET tsgPacket;
TSG_PACKET tsgPacket = { 0 };
PTSG_CAPABILITY_NAP tsgCapNap;
PTSG_PACKET_VERSIONCAPS packetVersionCaps;
@ -1443,7 +1633,7 @@ BOOL tsg_proxy_begin(rdpTsg* tsg)
static BOOL tsg_proxy_reauth(rdpTsg* tsg)
{
TSG_PACKET tsgPacket;
TSG_PACKET tsgPacket = { 0 };
PTSG_PACKET_REAUTH packetReauth;
PTSG_PACKET_VERSIONCAPS packetVersionCaps;
@ -1815,8 +2005,9 @@ static BOOL tsg_set_machine_name(rdpTsg* tsg, const char* machineName)
return TRUE;
}
BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout)
BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout)
{
UINT64 looptimeout = timeout * 1000ULL;
DWORD nCount;
HANDLE events[64];
rdpRpc* rpc = tsg->rpc;
@ -1847,7 +2038,19 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout)
while (tsg->state != TSG_STATE_PIPE_CREATED)
{
WaitForMultipleObjects(nCount, events, FALSE, 250);
const DWORD polltimeout = 250;
DWORD status = WaitForMultipleObjects(nCount, events, FALSE, polltimeout);
if (status == WAIT_TIMEOUT)
{
if (timeout > 0)
{
if (looptimeout < polltimeout)
return FALSE;
looptimeout -= polltimeout;
}
}
else
looptimeout = timeout * 1000ULL;
if (!tsg_check_event_handles(tsg))
{

View File

@ -62,19 +62,6 @@ typedef enum _TSG_STATE TSG_STATE;
#define TS_GATEWAY_TRANSPORT 0x5452
#define TSG_PACKET_TYPE_HEADER 0x00004844
#define TSG_PACKET_TYPE_VERSIONCAPS 0x00005643
#define TSG_PACKET_TYPE_QUARCONFIGREQUEST 0x00005143
#define TSG_PACKET_TYPE_QUARREQUEST 0x00005152
#define TSG_PACKET_TYPE_RESPONSE 0x00005052
#define TSG_PACKET_TYPE_QUARENC_RESPONSE 0x00004552
#define TSG_CAPABILITY_TYPE_NAP 0x00000001
#define TSG_PACKET_TYPE_CAPS_RESPONSE 0x00004350
#define TSG_PACKET_TYPE_MSGREQUEST_PACKET 0x00004752
#define TSG_PACKET_TYPE_MESSAGE_PACKET 0x00004750
#define TSG_PACKET_TYPE_AUTH 0x00004054
#define TSG_PACKET_TYPE_REAUTH 0x00005250
#define TSG_ASYNC_MESSAGE_CONSENT_MESSAGE 0x00000001
#define TSG_ASYNC_MESSAGE_SERVICE_MESSAGE 0x00000002
#define TSG_ASYNC_MESSAGE_REAUTH 0x00000003
@ -118,7 +105,7 @@ FREERDP_LOCAL void tsg_free(rdpTsg* tsg);
FREERDP_LOCAL BOOL tsg_proxy_begin(rdpTsg* tsg);
FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout);
FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout);
FREERDP_LOCAL BOOL tsg_disconnect(rdpTsg* tsg);
FREERDP_LOCAL BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu);

View File

@ -1252,6 +1252,9 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
if (!licenseStream)
goto out_free_blob;
if (Stream_GetRemainingLength(licenseStream) < 8)
goto out_free_stream;
Stream_Read_UINT16(licenseStream, os_minor);
Stream_Read_UINT16(licenseStream, os_major);
@ -1266,6 +1269,8 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
Stream_Seek(licenseStream, cbScope);
/* CompanyName */
if (Stream_GetRemainingLength(licenseStream) < 4)
goto out_free_stream;
Stream_Read_UINT32(licenseStream, cbCompanyName);
if (Stream_GetRemainingLength(licenseStream) < cbCompanyName)
goto out_free_stream;
@ -1276,6 +1281,8 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
Stream_Seek(licenseStream, cbCompanyName);
/* productId */
if (Stream_GetRemainingLength(licenseStream) < 4)
goto out_free_stream;
Stream_Read_UINT32(licenseStream, cbProductId);
if (Stream_GetRemainingLength(licenseStream) < cbProductId)
goto out_free_stream;
@ -1286,6 +1293,8 @@ BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
Stream_Seek(licenseStream, cbProductId);
/* licenseInfo */
if (Stream_GetRemainingLength(licenseStream) < 4)
goto out_free_stream;
Stream_Read_UINT32(licenseStream, cbLicenseInfo);
if (Stream_GetRemainingLength(licenseStream) < cbLicenseInfo)
goto out_free_stream;

View File

@ -43,51 +43,144 @@
#define TAG FREERDP_TAG("core.orders")
const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[] = { DSTBLT_ORDER_FIELD_BYTES,
PATBLT_ORDER_FIELD_BYTES,
SCRBLT_ORDER_FIELD_BYTES,
0,
0,
0,
0,
DRAW_NINE_GRID_ORDER_FIELD_BYTES,
MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES,
LINE_TO_ORDER_FIELD_BYTES,
OPAQUE_RECT_ORDER_FIELD_BYTES,
SAVE_BITMAP_ORDER_FIELD_BYTES,
0,
MEMBLT_ORDER_FIELD_BYTES,
MEM3BLT_ORDER_FIELD_BYTES,
MULTI_DSTBLT_ORDER_FIELD_BYTES,
MULTI_PATBLT_ORDER_FIELD_BYTES,
MULTI_SCRBLT_ORDER_FIELD_BYTES,
MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES,
FAST_INDEX_ORDER_FIELD_BYTES,
POLYGON_SC_ORDER_FIELD_BYTES,
POLYGON_CB_ORDER_FIELD_BYTES,
POLYLINE_ORDER_FIELD_BYTES,
0,
FAST_GLYPH_ORDER_FIELD_BYTES,
ELLIPSE_SC_ORDER_FIELD_BYTES,
ELLIPSE_CB_ORDER_FIELD_BYTES,
GLYPH_INDEX_ORDER_FIELD_BYTES };
BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid)
{
if (pValid)
*pValid = TRUE;
switch (orderType)
{
case 0:
return DSTBLT_ORDER_FIELD_BYTES;
case 1:
return PATBLT_ORDER_FIELD_BYTES;
case 2:
return SCRBLT_ORDER_FIELD_BYTES;
case 3:
return 0;
case 4:
return 0;
case 5:
return 0;
case 6:
return 0;
case 7:
return DRAW_NINE_GRID_ORDER_FIELD_BYTES;
case 8:
return MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES;
case 9:
return LINE_TO_ORDER_FIELD_BYTES;
case 10:
return OPAQUE_RECT_ORDER_FIELD_BYTES;
case 11:
return SAVE_BITMAP_ORDER_FIELD_BYTES;
case 12:
return 0;
case 13:
return MEMBLT_ORDER_FIELD_BYTES;
case 14:
return MEM3BLT_ORDER_FIELD_BYTES;
case 15:
return MULTI_DSTBLT_ORDER_FIELD_BYTES;
case 16:
return MULTI_PATBLT_ORDER_FIELD_BYTES;
case 17:
return MULTI_SCRBLT_ORDER_FIELD_BYTES;
case 18:
return MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES;
case 19:
return FAST_INDEX_ORDER_FIELD_BYTES;
case 20:
return POLYGON_SC_ORDER_FIELD_BYTES;
case 21:
return POLYGON_CB_ORDER_FIELD_BYTES;
case 22:
return POLYLINE_ORDER_FIELD_BYTES;
case 23:
return 0;
case 24:
return FAST_GLYPH_ORDER_FIELD_BYTES;
case 25:
return ELLIPSE_SC_ORDER_FIELD_BYTES;
case 26:
return ELLIPSE_CB_ORDER_FIELD_BYTES;
case 27:
return GLYPH_INDEX_ORDER_FIELD_BYTES;
default:
if (pValid)
*pValid = FALSE;
WLog_WARN(TAG, "Invalid orderType 0x%08X received", orderType);
return 0;
}
}
#define PRIMARY_DRAWING_ORDER_COUNT (ARRAYSIZE(PRIMARY_DRAWING_ORDER_FIELD_BYTES))
static BYTE get_cbr2_bpp(UINT32 bpp, BOOL* pValid)
{
if (pValid)
*pValid = TRUE;
switch (bpp)
{
case 3:
return 8;
case 4:
return 16;
case 5:
return 24;
case 6:
return 32;
default:
WLog_WARN(TAG, "Invalid bpp %" PRIu32, bpp);
if (pValid)
*pValid = FALSE;
return 0;
}
}
static const BYTE CBR2_BPP[] = { 0, 0, 0, 8, 16, 24, 32 };
static const BYTE BPP_CBR2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };
static const BYTE CBR23_BPP[] = { 0, 0, 0, 8, 16, 24, 32 };
static const BYTE BPP_CBR23[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };
static const BYTE BMF_BPP[] = { 0, 1, 0, 8, 16, 24, 32, 0 };
static const BYTE BPP_BMF[] = { 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0 };
static BYTE get_bmf_bpp(UINT32 bmf, BOOL* pValid)
{
if (pValid)
*pValid = TRUE;
switch (bmf)
{
case 1:
return 1;
case 3:
return 8;
case 4:
return 16;
case 5:
return 24;
case 6:
return 32;
default:
WLog_WARN(TAG, "Invalid bmf %" PRIu32, bmf);
if (pValid)
*pValid = FALSE;
return 0;
}
}
static BYTE get_bpp_bmf(UINT32 bpp, BOOL* pValid)
{
if (pValid)
*pValid = TRUE;
switch (bpp)
{
case 1:
return 1;
case 8:
return 3;
case 16:
return 4;
case 24:
return 5;
case 32:
return 6;
default:
WLog_WARN(TAG, "Invalid color depth %" PRIu32, bpp);
if (pValid)
*pValid = FALSE;
return 0;
}
}
static BOOL check_order_activated(wLog* log, rdpSettings* settings, const char* orderName,
BOOL condition)
@ -775,9 +868,11 @@ static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, BYTE fieldFlag
if (brush->style & CACHED_BRUSH)
{
BOOL rc;
brush->index = brush->hatch;
brush->bpp = BMF_BPP[brush->style & 0x07];
brush->bpp = get_bmf_bpp(brush->style, &rc);
if (!rc)
return FALSE;
if (brush->bpp == 0)
brush->bpp = 1;
}
@ -819,9 +914,11 @@ static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, BYTE fieldFla
if (brush->style & CACHED_BRUSH)
{
BOOL rc;
brush->hatch = brush->index;
brush->bpp = BMF_BPP[brush->style & 0x07];
brush->bpp = get_bmf_bpp(brush->style, &rc);
if (!rc)
return FALSE;
if (brush->bpp == 0)
brush->bpp = 1;
}
@ -1977,6 +2074,7 @@ BOOL update_write_cache_bitmap_order(wStream* s, const CACHE_BITMAP_ORDER* cache
static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* update, wStream* s,
BOOL compressed, UINT16 flags)
{
BOOL rc;
BYTE bitsPerPixelId;
CACHE_BITMAP_V2_ORDER* cache_bitmap_v2;
@ -1991,7 +2089,9 @@ static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* updat
cache_bitmap_v2->cacheId = flags & 0x0003;
cache_bitmap_v2->flags = (flags & 0xFF80) >> 7;
bitsPerPixelId = (flags & 0x0078) >> 3;
cache_bitmap_v2->bitmapBpp = CBR2_BPP[bitsPerPixelId];
cache_bitmap_v2->bitmapBpp = get_cbr2_bpp(bitsPerPixelId, &rc);
if (!rc)
goto fail;
if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT)
{
@ -2070,13 +2170,16 @@ int update_approximate_cache_bitmap_v2_order(CACHE_BITMAP_V2_ORDER* cache_bitmap
BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,
BOOL compressed, UINT16* flags)
{
BOOL rc;
BYTE bitsPerPixelId;
if (!Stream_EnsureRemainingCapacity(
s, update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, compressed, flags)))
return FALSE;
bitsPerPixelId = BPP_CBR2[cache_bitmap_v2->bitmapBpp];
bitsPerPixelId = get_bpp_bmf(cache_bitmap_v2->bitmapBpp, &rc);
if (!rc)
return FALSE;
*flags = (cache_bitmap_v2->cacheId & 0x0003) | (bitsPerPixelId << 3) |
((cache_bitmap_v2->flags << 7) & 0xFF80);
@ -2138,6 +2241,7 @@ BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache
static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* update, wStream* s,
UINT16 flags)
{
BOOL rc;
BYTE bitsPerPixelId;
BITMAP_DATA_EX* bitmapData;
UINT32 new_len;
@ -2155,7 +2259,9 @@ static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* updat
cache_bitmap_v3->cacheId = flags & 0x00000003;
cache_bitmap_v3->flags = (flags & 0x0000FF80) >> 7;
bitsPerPixelId = (flags & 0x00000078) >> 3;
cache_bitmap_v3->bpp = CBR23_BPP[bitsPerPixelId];
cache_bitmap_v3->bpp = get_cbr2_bpp(bitsPerPixelId, &rc);
if (!rc)
goto fail;
if (Stream_GetRemainingLength(s) < 21)
goto fail;
@ -2203,6 +2309,7 @@ int update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap
BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3,
UINT16* flags)
{
BOOL rc;
BYTE bitsPerPixelId;
BITMAP_DATA_EX* bitmapData;
@ -2211,7 +2318,9 @@ BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache
return FALSE;
bitmapData = &cache_bitmap_v3->bitmapData;
bitsPerPixelId = BPP_CBR23[cache_bitmap_v3->bpp];
bitsPerPixelId = get_bpp_bmf(cache_bitmap_v3->bpp, &rc);
if (!rc)
return FALSE;
*flags = (cache_bitmap_v3->cacheId & 0x00000003) |
((cache_bitmap_v3->flags << 7) & 0x0000FF80) | ((bitsPerPixelId << 3) & 0x00000078);
Stream_Write_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */
@ -2535,6 +2644,7 @@ static BOOL update_compress_brush(wStream* s, const BYTE* input, BYTE bpp)
static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, UINT16 flags)
{
int i;
BOOL rc;
BYTE iBitmapFormat;
BOOL compressed = FALSE;
CACHE_BRUSH_ORDER* cache_brush = calloc(1, sizeof(CACHE_BRUSH_ORDER));
@ -2548,10 +2658,10 @@ static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre
Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */
Stream_Read_UINT8(s, iBitmapFormat); /* iBitmapFormat (1 byte) */
if (iBitmapFormat >= ARRAYSIZE(BMF_BPP))
cache_brush->bpp = get_bmf_bpp(iBitmapFormat, &rc);
if (!rc)
goto fail;
cache_brush->bpp = BMF_BPP[iBitmapFormat];
Stream_Read_UINT8(s, cache_brush->cx); /* cx (1 byte) */
Stream_Read_UINT8(s, cache_brush->cy); /* cy (1 byte) */
Stream_Read_UINT8(s, cache_brush->style); /* style (1 byte) */
@ -2622,13 +2732,16 @@ BOOL update_write_cache_brush_order(wStream* s, const CACHE_BRUSH_ORDER* cache_b
{
int i;
BYTE iBitmapFormat;
BOOL rc;
BOOL compressed = FALSE;
if (!Stream_EnsureRemainingCapacity(s,
update_approximate_cache_brush_order(cache_brush, flags)))
return FALSE;
iBitmapFormat = BPP_BMF[cache_brush->bpp];
iBitmapFormat = get_bpp_bmf(cache_brush->bpp, &rc);
if (!rc)
return FALSE;
Stream_Write_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */
Stream_Write_UINT8(s, iBitmapFormat); /* iBitmapFormat (1 byte) */
Stream_Write_UINT8(s, cache_brush->cx); /* cx (1 byte) */
@ -3240,6 +3353,7 @@ static BOOL read_primary_order(wLog* log, const char* orderName, wStream* s,
static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags)
{
BYTE field;
BOOL rc = FALSE;
rdpContext* context = update->context;
rdpPrimaryUpdate* primary = update->primary;
@ -3263,8 +3377,11 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags)
if (!check_primary_order_supported(update->log, settings, orderInfo->orderType, orderName))
return FALSE;
if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags,
PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]))
field = get_primary_drawing_order_field_bytes(orderInfo->orderType, &rc);
if (!rc)
return FALSE;
if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, field))
{
WLog_Print(update->log, WLOG_ERROR, "update_read_field_flags() failed");
return FALSE;
@ -3506,7 +3623,7 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flag
Stream_Read_UINT16(s, orderLength); /* orderLength (2 bytes) */
Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
Stream_Read_UINT8(s, orderType); /* orderType (1 byte) */
if (Stream_GetRemainingLength(s) < orderLength + 7)
if (Stream_GetRemainingLength(s) < orderLength + 7U)
{
WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) %" PRIuz " < %" PRIu16,
Stream_GetRemainingLength(s), orderLength + 7);
@ -3645,12 +3762,13 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flag
name, end - start);
return FALSE;
}
diff = start - end;
diff = end - start;
if (diff > 0)
{
WLog_Print(update->log, WLOG_DEBUG,
"SECONDARY_ORDER %s: read %" PRIuz "bytes short, skipping", name, diff);
Stream_Seek(s, diff);
if (!Stream_SafeSeek(s, diff))
return FALSE;
}
return rc;
}

View File

@ -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);

View File

@ -167,7 +167,7 @@ BOOL rdp_read_share_control_header(wStream* s, UINT16* tpktLength, UINT16* remai
return TRUE;
}
if ((len < 4) || ((len - 2) > Stream_GetRemainingLength(s)))
if ((len < 4U) || ((len - 2U) > Stream_GetRemainingLength(s)))
return FALSE;
if (tpktLength)

View File

@ -394,6 +394,8 @@ BOOL security_salted_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length,
BYTE md5_digest[WINPR_MD5_DIGEST_LENGTH];
BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH];
BOOL result = FALSE;
EnterCriticalSection(&rdp->critical);
security_UINT32_le(length_le, length); /* length must be little-endian */
if (encryption)
@ -456,6 +458,7 @@ BOOL security_salted_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length,
memcpy(output, md5_digest, 8);
result = TRUE;
out:
LeaveCriticalSection(&rdp->critical);
winpr_Digest_Free(sha1);
winpr_Digest_Free(md5);
return result;
@ -636,12 +639,14 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
rdp->rc4_key_len = 16;
}
EnterCriticalSection(&rdp->critical);
memcpy(rdp->decrypt_update_key, rdp->decrypt_key, 16);
memcpy(rdp->encrypt_update_key, rdp->encrypt_key, 16);
rdp->decrypt_use_count = 0;
rdp->decrypt_checksum_use_count = 0;
rdp->encrypt_use_count = 0;
rdp->encrypt_checksum_use_count = 0;
LeaveCriticalSection(&rdp->critical);
return TRUE;
}
@ -741,29 +746,34 @@ fail:
BOOL security_decrypt(BYTE* data, size_t length, rdpRdp* rdp)
{
BOOL rc = FALSE;
EnterCriticalSection(&rdp->critical);
if (rdp->rc4_decrypt_key == NULL)
return FALSE;
goto fail;
if (rdp->decrypt_use_count >= 4096)
{
if (!security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len, rdp))
return FALSE;
goto fail;
winpr_RC4_Free(rdp->rc4_decrypt_key);
rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len);
if (!rdp->rc4_decrypt_key)
return FALSE;
goto fail;
rdp->decrypt_use_count = 0;
}
if (!winpr_RC4_Update(rdp->rc4_decrypt_key, length, data, data))
return FALSE;
goto fail;
rdp->decrypt_use_count += 1;
rdp->decrypt_checksum_use_count++;
return TRUE;
rc = TRUE;
fail:
LeaveCriticalSection(&rdp->critical);
return rc;
}
BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output, rdpRdp* rdp)
@ -772,7 +782,9 @@ BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output, rdpR
BYTE use_count_le[4];
WINPR_HMAC_CTX* hmac;
BOOL result = FALSE;
EnterCriticalSection(&rdp->critical);
security_UINT32_le(use_count_le, rdp->encrypt_use_count);
LeaveCriticalSection(&rdp->critical);
if (!(hmac = winpr_HMAC_New()))
return FALSE;
@ -831,7 +843,9 @@ BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE*
BYTE use_count_le[4];
WINPR_HMAC_CTX* hmac;
BOOL result = FALSE;
security_UINT32_le(use_count_le, rdp->decrypt_use_count);
EnterCriticalSection(&rdp->critical);
security_UINT32_le(use_count_le, rdp->decrypt_use_count++);
LeaveCriticalSection(&rdp->critical);
if (!(hmac = winpr_HMAC_New()))
return FALSE;
@ -848,8 +862,6 @@ BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE*
if (!winpr_HMAC_Final(hmac, buf, WINPR_SHA1_DIGEST_LENGTH))
goto out;
rdp->decrypt_use_count++;
if (!memcmp(sig, buf, 8))
result = TRUE;

View File

@ -1060,7 +1060,7 @@ static BOOL freerdp_tcp_set_keep_alive_mode(const rdpSettings* settings, int soc
}
int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings, const char* hostname, int port,
int timeout)
DWORD timeout)
{
int sockfd;
UINT32 optval;

View File

@ -64,7 +64,7 @@ FREERDP_LOCAL BIO_METHOD* BIO_s_simple_socket(void);
FREERDP_LOCAL BIO_METHOD* BIO_s_buffered_socket(void);
FREERDP_LOCAL int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
const char* hostname, int port, int timeout);
const char* hostname, int port, DWORD timeout);
FREERDP_LOCAL char* freerdp_tcp_get_peer_address(SOCKET sockfd);

View File

@ -354,7 +354,7 @@ BOOL transport_connect_nla(rdpTransport* transport)
return TRUE;
}
BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, int timeout)
BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, DWORD timeout)
{
int sockfd;
BOOL status = FALSE;

View File

@ -81,7 +81,7 @@ struct rdp_transport
FREERDP_LOCAL wStream* transport_send_stream_init(rdpTransport* transport, int size);
FREERDP_LOCAL BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port,
int timeout);
DWORD timeout);
FREERDP_LOCAL BOOL transport_attach(rdpTransport* transport, int sockfd);
FREERDP_LOCAL BOOL transport_disconnect(rdpTransport* transport);
FREERDP_LOCAL BOOL transport_connect_rdp(rdpTransport* transport);

View File

@ -1087,7 +1087,7 @@ static int update_prepare_order_info(rdpContext* context, ORDER_INFO* orderInfo,
orderInfo->controlFlags = ORDER_STANDARD;
orderInfo->controlFlags |= ORDER_TYPE_CHANGE;
length += 1;
length += PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType];
length += get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL);
length += update_prepare_bounds(context, orderInfo);
return length;
}
@ -1105,7 +1105,7 @@ static int update_write_order_info(rdpContext* context, wStream* s, ORDER_INFO*
Stream_Write_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */
update_write_field_flags(s, orderInfo->fieldFlags, orderInfo->controlFlags,
PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]);
get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL));
update_write_bounds(s, orderInfo);
Stream_SetPosition(s, position);
return 0;

View File

@ -105,11 +105,18 @@ static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, c
BIGNUM* exp = NULL;
BIGNUM* x = NULL;
BIGNUM* y = NULL;
size_t bufferSize = 2 * key_length + exponent_size;
size_t bufferSize;
if (!input || (length < 0) || (exponent_size < 0) || !modulus || !exponent || !output)
return -1;
if (exponent_size > SIZE_MAX / 2)
return -1;
if (key_length >= SIZE_MAX / 2 - exponent_size)
return -1;
bufferSize = 2ULL * key_length + exponent_size;
if (length > bufferSize)
bufferSize = length;

View File

@ -141,7 +141,10 @@ static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface)
if (!freerdp_image_scale(gdi->primary_buffer, gdi->dstFormat, gdi->stride, nXDst, nYDst,
dwidth, dheight, surface->data, surface->format, surface->scanline,
nXSrc, nYSrc, swidth, sheight))
return CHANNEL_RC_NULL_DATA;
{
rc = CHANNEL_RC_NULL_DATA;
goto fail;
}
gdi_InvalidateRegion(gdi->primary->hdc, (INT32)nXDst, (INT32)nYDst, (INT32)dwidth,
(INT32)dheight);

View File

@ -93,6 +93,7 @@ static BOOL gdi_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
if (!gdi_bitmap->bitmap)
{
gdi_DeleteDC(gdi_bitmap->hdc);
gdi_bitmap->hdc = NULL;
return FALSE;
}

View File

@ -170,22 +170,17 @@ rdpPcap* pcap_open(char* name, BOOL write)
{
rdpPcap* pcap;
FILE* pcap_fp = fopen(name, write ? "w+b" : "rb");
if (pcap_fp == NULL)
{
WLog_ERR(TAG, "opening pcap dump");
return NULL;
}
pcap = (rdpPcap*)calloc(1, sizeof(rdpPcap));
if (!pcap)
goto fail_close;
goto fail;
pcap->name = name;
pcap->write = write;
pcap->record_count = 0;
pcap->fp = pcap_fp;
pcap->fp = fopen(name, write ? "w+b" : "rb");
if (pcap->fp == NULL)
goto fail;
if (write)
{
@ -211,9 +206,7 @@ rdpPcap* pcap_open(char* name, BOOL write)
return pcap;
fail:
free(pcap);
fail_close:
fclose(pcap_fp);
pcap_close(pcap);
return NULL;
}
@ -231,6 +224,9 @@ void pcap_flush(rdpPcap* pcap)
void pcap_close(rdpPcap* pcap)
{
if (!pcap)
return;
pcap_flush(pcap);
if (pcap->fp != NULL)

View File

@ -0,0 +1,50 @@
#!/bin/bash -e
function run {
echo "[RUN] $@"
"$@"
RES=$?
if [[ $RES -ne 0 ]];
then
echo "[ERROR] $@ retured $RES"
exit 1
fi
}
if [ -z ${TAG:-} ];then
echo "No TAG set - trying to detect"
TAG=$(git describe --tags)
echo "Is the TAG ${TAG} ok (YES|NO)?"
read answ
case "$answ" in
YES):
;;
*)
echo 'stopping here'
exit 1
esac
fi
TMPDIR=$(mktemp -d -t release-${TAG}-XXXXXXXXXX)
run git archive --prefix=freerdp-${TAG}/ --format=tar.gz -o ${TMPDIR}/freerdp-${TAG}.tar.gz ${TAG}
run tar xzvf ${TMPDIR}/freerdp-${TAG}.tar.gz -C ${TMPDIR}
run echo ${TAG} > ${TMPDIR}/freerdp-${TAG}/.source_version
pushd .
cd $TMPDIR
run tar czvf freerdp-${TAG}.tar.gz freerdp-${TAG}
run md5sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.md5
run sha1sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.sha1
run sha256sum freerdp-${TAG}.tar.gz > freerdp-${TAG}.tar.gz.sha256
run zip freerdp-${TAG}.zip freerdp-${TAG}
run md5sum freerdp-${TAG}.zip > freerdp-${TAG}.zip.md5
run sha1sum freerdp-${TAG}.zip > freerdp-${TAG}.zip.sha1
run sha256sum freerdp-${TAG}.zip > freerdp-${TAG}.zip.sha256
popd
run mv ${TMPDIR}/freerdp-${TAG}.tar.gz* .
run mv ${TMPDIR}/freerdp-${TAG}.zip* .
run rm -rf ${TMPDIR}
exit 0

View File

@ -0,0 +1,33 @@
#
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP Proxy Server Capture Module
#
# Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
set(PLUGIN_NAME "proxy-capture-plugin")
add_library(${PLUGIN_NAME} MODULE
cap_main.c
cap_config.c
cap_config.h
cap_protocol.c
cap_protocol.h
)
set_target_properties(${PLUGIN_NAME} PROPERTIES PREFIX "")
set_target_properties(${PLUGIN_NAME} PROPERTIES NO_SONAME 1)
set_target_properties(${PLUGIN_NAME} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${FREERDP_PROXY_PLUGINDIR}")

View File

@ -0,0 +1,97 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy Server Session Capture Module
*
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/environment.h>
#include <freerdp/types.h>
#include <errno.h>
#include "cap_config.h"
BOOL capture_plugin_init_config(captureConfig* config)
{
const char* name = "PROXY_CAPTURE_TARGET";
char* tmp = NULL;
DWORD nSize = GetEnvironmentVariableA(name, NULL, 0);
if (nSize > 0)
{
char* colon;
int addrLen;
unsigned long port;
tmp = (LPSTR)malloc(nSize);
if (!tmp)
return FALSE;
if (GetEnvironmentVariableA(name, tmp, nSize) != nSize - 1)
{
free(tmp);
return FALSE;
}
colon = strchr(tmp, ':');
if (!colon)
{
free(tmp);
return FALSE;
}
addrLen = (int)(colon - tmp);
config->host = malloc(addrLen + 1);
if (!config->host)
{
free(tmp);
return FALSE;
}
strncpy(config->host, tmp, addrLen);
config->host[addrLen] = '\0';
port = strtoul(colon + 1, NULL, 0);
if ((errno != 0) || (port > UINT16_MAX))
{
free(config->host);
config->host = NULL;
free(tmp);
return FALSE;
}
config->port = port;
free(tmp);
}
else
{
config->host = _strdup("127.0.0.1");
if (!config->host)
return FALSE;
config->port = 8889;
}
return TRUE;
}
void capture_plugin_config_free_internal(captureConfig* config)
{
free(config->host);
config->host = NULL;
}

View File

@ -0,0 +1,29 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy Server Session Capture Module
*
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <freerdp/types.h>
typedef struct capture_config
{
UINT16 port;
char* host;
} captureConfig;
BOOL capture_plugin_init_config(captureConfig* config);
void capture_plugin_config_free_internal(captureConfig* config);

View File

@ -0,0 +1,288 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy Server Session Capture Module
*
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define TAG MODULE_TAG("capture")
#define PLUGIN_NAME "capture"
#define PLUGIN_DESC "stream egfx connections over tcp"
#include <errno.h>
#include <winpr/image.h>
#include <freerdp/gdi/gdi.h>
#include <winpr/winsock.h>
#include "pf_log.h"
#include "modules_api.h"
#include "pf_context.h"
#include "cap_config.h"
#include "cap_protocol.h"
#define BUFSIZE 8092
static proxyPluginsManager* g_plugins_manager = NULL;
static captureConfig config = { 0 };
static SOCKET capture_plugin_init_socket(void)
{
int status;
int sockfd;
struct sockaddr_in addr = { 0 };
sockfd = _socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd == -1)
return -1;
addr.sin_family = AF_INET;
addr.sin_port = htons(config.port);
inet_pton(AF_INET, config.host, &(addr.sin_addr));
status = _connect(sockfd, (const struct sockaddr*)&addr, sizeof(addr));
if (status < 0)
{
close(sockfd);
return -1;
}
return sockfd;
}
static BOOL capture_plugin_send_data(SOCKET sockfd, const BYTE* buffer, size_t len)
{
size_t chunk_len;
int nsent;
if (!buffer)
return FALSE;
while (len > 0)
{
chunk_len = len > BUFSIZE ? BUFSIZE : len;
nsent = _send(sockfd, (const char*)buffer, chunk_len, 0);
if (nsent == -1)
return FALSE;
buffer += nsent;
len -= nsent;
}
return TRUE;
}
static BOOL capture_plugin_send_packet(SOCKET sockfd, wStream* packet)
{
size_t len;
BYTE* buffer;
BOOL result = FALSE;
if (!packet)
return FALSE;
buffer = Stream_Buffer(packet);
len = Stream_Capacity(packet);
if (!capture_plugin_send_data(sockfd, buffer, len))
{
WLog_ERR(TAG, "error while transmitting frame: errno=%d", errno);
goto error;
}
result = TRUE;
error:
Stream_Free(packet, TRUE);
return result;
}
static SOCKET capture_plugin_get_socket(proxyData* pdata)
{
void* custom;
custom = g_plugins_manager->GetPluginData(PLUGIN_NAME, pdata);
if (!custom)
return -1;
return (SOCKET)custom;
}
static BOOL capture_plugin_session_end(proxyData* pdata)
{
SOCKET socket;
BOOL ret;
wStream* s;
socket = capture_plugin_get_socket(pdata);
if (socket == -1)
return FALSE;
s = capture_plugin_packet_new(SESSION_END_PDU_BASE_SIZE, MESSAGE_TYPE_SESSION_END);
if (!s)
return FALSE;
ret = capture_plugin_send_packet(socket, s);
closesocket(socket);
return ret;
}
static BOOL capture_plugin_send_frame(pClientContext* pc, SOCKET socket, const BYTE* buffer)
{
size_t frame_size;
BOOL ret = FALSE;
wStream* s = NULL;
BYTE* bmp_header = NULL;
rdpSettings* settings = pc->context.settings;
frame_size = settings->DesktopWidth * settings->DesktopHeight * (settings->ColorDepth / 8);
bmp_header = winpr_bitmap_construct_header(settings->DesktopWidth, settings->DesktopHeight,
settings->ColorDepth);
if (!bmp_header)
return FALSE;
/*
* capture frame packet indicates a packet that contains a frame buffer. payload length is
* marked as 0, and receiving side must read `frame_size` bytes, a constant size of
* width*height*(bpp/8) from the socket, to receive the full frame buffer.
*/
s = capture_plugin_packet_new(0, MESSAGE_TYPE_CAPTURED_FRAME);
if (!s)
goto error;
if (!capture_plugin_send_packet(socket, s))
goto error;
ret = capture_plugin_send_data(socket, bmp_header, WINPR_IMAGE_BMP_HEADER_LEN);
if (!ret)
goto error;
ret = capture_plugin_send_data(socket, buffer, frame_size);
error:
free(bmp_header);
return ret;
}
static BOOL capture_plugin_client_end_paint(proxyData* pdata)
{
pClientContext* pc = pdata->pc;
rdpGdi* gdi = pc->context.gdi;
SOCKET socket;
if (gdi->suppressOutput)
return TRUE;
if (gdi->primary->hdc->hwnd->ninvalid < 1)
return TRUE;
socket = capture_plugin_get_socket(pdata);
if (socket == -1)
return FALSE;
if (!capture_plugin_send_frame(pc, socket, gdi->primary_buffer))
{
WLog_ERR(TAG, "capture_plugin_send_frame failed!");
return FALSE;
}
gdi->primary->hdc->hwnd->invalid->null = TRUE;
gdi->primary->hdc->hwnd->ninvalid = 0;
return TRUE;
}
static BOOL capture_plugin_client_post_connect(proxyData* pdata)
{
SOCKET socket;
wStream* s;
pClientContext* pc = pdata->pc;
rdpSettings* settings = pc->context.settings;
socket = capture_plugin_init_socket();
if (socket == -1)
{
WLog_ERR(TAG, "failed to establish a connection");
return FALSE;
}
g_plugins_manager->SetPluginData(PLUGIN_NAME, pdata, (void*)socket);
s = capture_plugin_create_session_info_packet(settings);
if (!s)
return FALSE;
return capture_plugin_send_packet(socket, s);
}
static BOOL capture_plugin_server_post_connect(proxyData* pdata)
{
pServerContext* ps = pdata->ps;
proxyConfig* config = pdata->config;
rdpSettings* settings = ps->context.settings;
if (!config->GFX || !config->SessionCapture)
{
WLog_ERR(TAG, "config options 'GFX' and 'SessionCapture' options must be set to true!");
return FALSE;
}
if (!settings->SupportGraphicsPipeline)
{
WLog_ERR(TAG, "session capture is only supported for GFX clients, denying connection");
return FALSE;
}
return TRUE;
}
static BOOL capture_plugin_unload(void)
{
capture_plugin_config_free_internal(&config);
return TRUE;
}
static proxyPlugin demo_plugin = {
PLUGIN_NAME, /* name */
PLUGIN_DESC, /* description */
capture_plugin_unload, /* PluginUnload */
NULL, /* ClientPreConnect */
capture_plugin_client_post_connect, /* ClientPostConnect */
NULL, /* ClientLoginFailure */
capture_plugin_client_end_paint, /* ClientEndPaint */
capture_plugin_server_post_connect, /* ServerPostConnect */
NULL, /* ServerChannelsInit */
NULL, /* ServerChannelsFree */
capture_plugin_session_end, /* Session End */
NULL, /* KeyboardEvent */
NULL, /* MouseEvent */
NULL, /* ClientChannelData */
NULL, /* ServerChannelData */
};
BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager)
{
g_plugins_manager = plugins_manager;
if (!capture_plugin_init_config(&config))
{
WLog_ERR(TAG, "failed to load config");
return FALSE;
}
WLog_INFO(TAG, "host: %s, port: %" PRIu16 "", config.host, config.port);
return plugins_manager->RegisterPlugin(&demo_plugin);
}

View File

@ -0,0 +1,57 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy Server Session Capture Module
*
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cap_protocol.h"
wStream* capture_plugin_packet_new(UINT32 payload_size, UINT16 type)
{
wStream* stream = Stream_New(NULL, HEADER_SIZE + payload_size);
if (!stream)
return NULL;
Stream_Write_UINT32(stream, payload_size);
Stream_Write_UINT16(stream, type);
return stream;
}
wStream* capture_plugin_create_session_info_packet(rdpSettings* settings)
{
UINT16 username_length;
wStream* s = NULL;
if (!settings || !settings->Username)
return NULL;
username_length = strlen(settings->Username);
if (username_length == 0)
return NULL;
s = capture_plugin_packet_new(SESSION_INFO_PDU_BASE_SIZE + username_length,
MESSAGE_TYPE_SESSION_INFO);
if (!s)
return NULL;
Stream_Write_UINT16(s, username_length); /* username length (2 bytes) */
Stream_Write(s, settings->Username, username_length); /* username */
Stream_Write_UINT32(s, settings->DesktopWidth); /* desktop width (4 bytes) */
Stream_Write_UINT32(s, settings->DesktopHeight); /* desktop height (4 bytes) */
Stream_Write_UINT32(s, settings->ColorDepth); /* color depth (4 bytes) */
return s;
}

View File

@ -0,0 +1,35 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Proxy Server Session Capture Module
*
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/stream.h>
#include <freerdp/settings.h>
/* protocol message sizes */
#define HEADER_SIZE 6
#define SESSION_INFO_PDU_BASE_SIZE 14
#define SESSION_END_PDU_BASE_SIZE 0
#define CAPTURED_FRAME_PDU_BASE_SIZE 0
/* protocol message types */
#define MESSAGE_TYPE_SESSION_INFO 1
#define MESSAGE_TYPE_CAPTURED_FRAME 2
#define MESSAGE_TYPE_SESSION_END 3
wStream* capture_plugin_packet_new(UINT32 payload_size, UINT16 type);
wStream* capture_plugin_create_session_info_packet(rdpSettings* settings);

View File

@ -370,6 +370,7 @@ static void (^mac_capture_stream_handler)(
int width;
int height;
int nSrcStep;
BOOL empty;
BYTE* pSrcData;
RECTANGLE_16 surfaceRect;
const RECTANGLE_16* extents;
@ -381,14 +382,17 @@ static void (^mac_capture_stream_handler)(
if (count < 1)
return;
EnterCriticalSection(&(surface->lock));
mac_shadow_capture_get_dirty_region(subsystem);
surfaceRect.left = 0;
surfaceRect.top = 0;
surfaceRect.right = surface->width;
surfaceRect.bottom = surface->height;
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
empty = region16_is_empty(&(surface->invalidRegion));
LeaveCriticalSection(&(surface->lock));
if (!region16_is_empty(&(surface->invalidRegion)))
if (!empty)
{
extents = region16_extents(&(surface->invalidRegion));
x = extents->left;
@ -410,13 +414,12 @@ static void (^mac_capture_stream_handler)(
pSrcData, PIXEL_FORMAT_BGRX32, nSrcStep, x, y, NULL,
FREERDP_FLIP_NONE);
}
LeaveCriticalSection(&(surface->lock));
IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL);
ArrayList_Lock(server->clients);
count = ArrayList_Count(server->clients);
EnterCriticalSection(&(surface->lock));
shadow_subsystem_frame_update(&subsystem->common);
LeaveCriticalSection(&(surface->lock));
if (count == 1)
{
@ -430,7 +433,9 @@ static void (^mac_capture_stream_handler)(
}
ArrayList_Unlock(server->clients);
EnterCriticalSection(&(surface->lock));
region16_clear(&(surface->invalidRegion));
LeaveCriticalSection(&(surface->lock));
}
if (status != kCGDisplayStreamFrameStatusFrameComplete)

View File

@ -128,90 +128,69 @@ out_fail:
return pam_status;
}
static int x11_shadow_pam_get_service_name(SHADOW_PAM_AUTH_INFO* info)
static BOOL x11_shadow_pam_get_service_name(SHADOW_PAM_AUTH_INFO* info)
{
if (PathFileExistsA("/etc/pam.d/lightdm"))
{
info->service_name = _strdup("lightdm");
}
else if (PathFileExistsA("/etc/pam.d/gdm"))
{
info->service_name = _strdup("gdm");
}
else if (PathFileExistsA("/etc/pam.d/xdm"))
{
info->service_name = _strdup("xdm");
}
else if (PathFileExistsA("/etc/pam.d/login"))
{
info->service_name = _strdup("login");
}
else if (PathFileExistsA("/etc/pam.d/sshd"))
{
info->service_name = _strdup("sshd");
}
else
{
return -1;
}
size_t x;
const char* base = "/etc/pam.d";
const char* hints[] = { "lightdm", "gdm", "xdm", "login", "sshd" };
if (!info->service_name)
return -1;
for (x = 0; x < ARRAYSIZE(hints); x++)
{
char path[MAX_PATH];
const char* hint = hints[x];
return 1;
_snprintf(path, sizeof(path), "%s/%s", base, hint);
if (PathFileExistsA(path))
{
info->service_name = _strdup(hint);
return info->service_name != NULL;
}
}
WLog_WARN(TAG, "Could not determine PAM service name");
return FALSE;
}
static int x11_shadow_pam_authenticate(rdpShadowSubsystem* subsystem, rdpShadowClient* client,
const char* user, const char* domain, const char* password)
{
int pam_status;
SHADOW_PAM_AUTH_INFO* info;
SHADOW_PAM_AUTH_INFO info = { 0 };
WINPR_UNUSED(subsystem);
WINPR_UNUSED(client);
info = calloc(1, sizeof(SHADOW_PAM_AUTH_INFO));
if (!info)
return PAM_CONV_ERR;
if (x11_shadow_pam_get_service_name(info) < 0)
{
free(info);
if (!x11_shadow_pam_get_service_name(&info))
return -1;
}
info->appdata.user = user;
info->appdata.domain = domain;
info->appdata.password = password;
info->pamc.conv = &x11_shadow_pam_conv;
info->pamc.appdata_ptr = &(info->appdata);
pam_status = pam_start(info->service_name, 0, &(info->pamc), &(info->handle));
info.appdata.user = user;
info.appdata.domain = domain;
info.appdata.password = password;
info.pamc.conv = &x11_shadow_pam_conv;
info.pamc.appdata_ptr = &info.appdata;
pam_status = pam_start(info.service_name, 0, &info.pamc, &info.handle);
if (pam_status != PAM_SUCCESS)
{
WLog_ERR(TAG, "pam_start failure: %s", pam_strerror(info->handle, pam_status));
free(info);
WLog_ERR(TAG, "pam_start failure: %s", pam_strerror(info.handle, pam_status));
return -1;
}
pam_status = pam_authenticate(info->handle, 0);
pam_status = pam_authenticate(info.handle, 0);
if (pam_status != PAM_SUCCESS)
{
WLog_ERR(TAG, "pam_authenticate failure: %s", pam_strerror(info->handle, pam_status));
free(info);
WLog_ERR(TAG, "pam_authenticate failure: %s", pam_strerror(info.handle, pam_status));
return -1;
}
pam_status = pam_acct_mgmt(info->handle, 0);
pam_status = pam_acct_mgmt(info.handle, 0);
if (pam_status != PAM_SUCCESS)
{
WLog_ERR(TAG, "pam_acct_mgmt failure: %s", pam_strerror(info->handle, pam_status));
free(info);
WLog_ERR(TAG, "pam_acct_mgmt failure: %s", pam_strerror(info.handle, pam_status));
return -1;
}
free(info);
return 1;
}
@ -757,6 +736,7 @@ static int x11_shadow_error_handler_for_capture(Display* display, XErrorEvent* e
static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
{
int rc = 0;
int count;
int status;
int x, y;
@ -774,10 +754,13 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
if (count < 1)
return 1;
EnterCriticalSection(&surface->lock);
surfaceRect.left = 0;
surfaceRect.top = 0;
surfaceRect.right = surface->width;
surfaceRect.bottom = surface->height;
LeaveCriticalSection(&surface->lock);
XLockDisplay(subsystem->display);
/*
* Ignore BadMatch error during image capture. The screen size may be
@ -790,15 +773,26 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
image = subsystem->fb_image;
XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap,
subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0);
EnterCriticalSection(&surface->lock);
status = shadow_capture_compare(surface->data, surface->scanline, surface->width,
surface->height, (BYTE*)&(image->data[surface->width * 4]),
image->bytes_per_line, &invalidRect);
LeaveCriticalSection(&surface->lock);
}
else
{
EnterCriticalSection(&surface->lock);
image = XGetImage(subsystem->display, subsystem->root_window, surface->x, surface->y,
surface->width, surface->height, AllPlanes, ZPixmap);
if (image)
{
status = shadow_capture_compare(surface->data, surface->scanline, surface->width,
surface->height, (BYTE*)image->data,
image->bytes_per_line, &invalidRect);
}
LeaveCriticalSection(&surface->lock);
if (!image)
{
/*
@ -807,10 +801,6 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
*/
goto fail_capture;
}
status = shadow_capture_compare(surface->data, surface->scanline, surface->width,
surface->height, (BYTE*)image->data, image->bytes_per_line,
&invalidRect);
}
/* Restore the default error handler */
@ -820,25 +810,32 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
if (status)
{
BOOL empty;
EnterCriticalSection(&surface->lock);
region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
empty = region16_is_empty(&(surface->invalidRegion));
LeaveCriticalSection(&surface->lock);
if (!region16_is_empty(&(surface->invalidRegion)))
if (!empty)
{
BOOL success;
EnterCriticalSection(&surface->lock);
extents = region16_extents(&(surface->invalidRegion));
x = extents->left;
y = extents->top;
width = extents->right - extents->left;
height = extents->bottom - extents->top;
if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y, width,
height, (BYTE*)image->data, PIXEL_FORMAT_BGRX32,
image->bytes_per_line, x, y, NULL, FREERDP_FLIP_NONE))
success = freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y,
width, height, (BYTE*)image->data, PIXEL_FORMAT_BGRX32,
image->bytes_per_line, x, y, NULL, FREERDP_FLIP_NONE);
LeaveCriticalSection(&surface->lock);
if (!success)
goto fail_capture;
// x11_shadow_blend_cursor(subsystem);
count = ArrayList_Count(server->clients);
shadow_subsystem_frame_update((rdpShadowSubsystem*)subsystem);
shadow_subsystem_frame_update(&subsystem->common);
if (count == 1)
{
@ -850,23 +847,25 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
shadow_encoder_preferred_fps(client->encoder);
}
EnterCriticalSection(&surface->lock);
region16_clear(&(surface->invalidRegion));
LeaveCriticalSection(&surface->lock);
}
}
if (!subsystem->use_xshm)
XDestroyImage(image);
return 1;
rc = 1;
fail_capture:
if (!subsystem->use_xshm && image)
XDestroyImage(image);
XSetErrorHandler(NULL);
XSync(subsystem->display, False);
XUnlockDisplay(subsystem->display);
return 0;
if (rc != 1)
{
XSetErrorHandler(NULL);
XSync(subsystem->display, False);
XUnlockDisplay(subsystem->display);
}
return rc;
}
static int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage* message)

View File

@ -1331,12 +1331,12 @@ static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GF
region16_copy(&invalidRegion, &(client->invalidRegion));
region16_clear(&(client->invalidRegion));
LeaveCriticalSection(&(client->lock));
EnterCriticalSection(&surface->lock);
rects = region16_rects(&(surface->invalidRegion), &numRects);
for (index = 0; index < numRects; index++)
{
region16_union_rect(&invalidRegion, &invalidRegion, &rects[index]);
}
surfaceRect.left = 0;
surfaceRect.top = 0;
@ -1410,6 +1410,7 @@ static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GF
}
out:
LeaveCriticalSection(&surface->lock);
region16_uninit(&invalidRegion);
return ret;
}

View File

@ -586,14 +586,19 @@ int shadow_server_start(rdpShadowServer* server)
char** list = CommandLineParseCommaSeparatedValuesEx(NULL, server->ipcSocket, &count);
if (!list || (count <= 1))
{
free(list);
if (server->ipcSocket == NULL)
{
if (!open_port(server, NULL))
{
free(list);
return -1;
}
}
else
{
free(list);
return -1;
}
}
for (x = 1; x < count; x++)

View File

@ -34,7 +34,7 @@
#endif
/* uClibc and uClibc-ng don't provide O_TMPFILE */
#ifndef O_TMPFILE
#if !defined(O_TMPFILE) && !defined(__FreeBSD__)
#define O_TMPFILE (020000000 | O_DIRECTORY)
#endif
@ -230,7 +230,16 @@ int uwac_create_anonymous_file(off_t size)
return -1;
}
#ifdef O_TMPFILE
fd = open(path, O_TMPFILE | O_RDWR | O_EXCL, 0600);
#else
/*
* Some platforms (e.g. FreeBSD) won't support O_TMPFILE and can't
* reasonably emulate it at first blush. Opt to make them rely on
* the create_tmpfile_cloexec() path instead.
*/
fd = -1;
#endif
if (fd < 0)
{

View File

@ -235,7 +235,8 @@ struct uwac_window
struct wl_region* opaque_region;
struct wl_region* input_region;
UwacBuffer *drawingBuffer, *pendingBuffer;
SSIZE_T drawingBufferIdx;
SSIZE_T pendingBufferIdx;
struct wl_surface* surface;
struct wl_shell_surface* shell_surface;
struct xdg_surface* xdg_surface;

View File

@ -136,13 +136,13 @@ static void xdg_handle_toplevel_configure(void* data, struct xdg_toplevel* xdg_t
{
assert(
uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
window->drawingBuffer = window->pendingBuffer = NULL;
window->drawingBufferIdx = window->pendingBufferIdx = -1;
return;
}
window->drawingBuffer = &window->buffers[0];
if (window->pendingBuffer != NULL)
window->pendingBuffer = window->drawingBuffer;
window->drawingBufferIdx = 0;
if (window->pendingBufferIdx != -1)
window->pendingBufferIdx = window->drawingBufferIdx;
}
else
{
@ -219,13 +219,13 @@ static void ivi_handle_configure(void* data, struct ivi_surface* surface, int32_
{
assert(
uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
window->drawingBuffer = window->pendingBuffer = NULL;
window->drawingBufferIdx = window->pendingBufferIdx = -1;
return;
}
window->drawingBuffer = &window->buffers[0];
if (window->pendingBuffer != NULL)
window->pendingBuffer = window->drawingBuffer;
window->drawingBufferIdx = 0;
if (window->pendingBufferIdx != -1)
window->pendingBufferIdx = window->drawingBufferIdx;
}
else
{
@ -277,13 +277,13 @@ static void shell_configure(void* data, struct wl_shell_surface* surface, uint32
{
assert(
uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
window->drawingBuffer = window->pendingBuffer = NULL;
window->drawingBufferIdx = window->pendingBufferIdx = -1;
return;
}
window->drawingBuffer = &window->buffers[0];
if (window->pendingBuffer != NULL)
window->pendingBuffer = window->drawingBuffer;
window->drawingBufferIdx = 0;
if (window->pendingBufferIdx != -1)
window->pendingBufferIdx = window->drawingBufferIdx;
}
else
{
@ -364,15 +364,21 @@ error_mmap:
return ret;
}
static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w)
static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w, SSIZE_T* index)
{
int i, ret;
SSIZE_T i;
int ret;
if (index)
*index = -1;
for (i = 0; i < w->nbuffers; i++)
{
if (!w->buffers[i].used)
{
w->buffers[i].used = true;
if (index)
*index = i;
return &w->buffers[i];
}
}
@ -386,6 +392,8 @@ static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w)
}
w->buffers[i].used = true;
if (index)
*index = i;
return &w->buffers[i];
}
@ -457,7 +465,8 @@ UwacWindow* UwacCreateWindowShm(UwacDisplay* display, uint32_t width, uint32_t h
}
w->buffers[0].used = true;
w->drawingBuffer = &w->buffers[0];
w->drawingBufferIdx = 0;
w->pendingBufferIdx = -1;
w->surface = wl_compositor_create_surface(display->compositor);
if (!w->surface)
@ -603,7 +612,16 @@ UwacReturnCode UwacWindowSetInputRegion(UwacWindow* window, uint32_t x, uint32_t
void* UwacWindowGetDrawingBuffer(UwacWindow* window)
{
return window->drawingBuffer->data;
UwacBuffer* buffer;
if (window->drawingBufferIdx < 0)
return NULL;
buffer = &window->buffers[window->drawingBufferIdx];
if (!buffer)
return NULL;
return buffer->data;
}
static void frame_done_cb(void* data, struct wl_callback* callback, uint32_t time);
@ -654,7 +672,7 @@ static void frame_done_cb(void* data, struct wl_callback* callback, uint32_t tim
UwacFrameDoneEvent* event;
wl_callback_destroy(callback);
window->pendingBuffer = NULL;
window->pendingBufferIdx = -1;
event = (UwacFrameDoneEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE);
if (event)
@ -677,13 +695,20 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, u
uint32_t height)
{
RECTANGLE_16 box;
UwacBuffer* buf;
box.left = x;
box.top = y;
box.right = x + width;
box.bottom = y + height;
UwacBuffer* buf = window->drawingBuffer;
if (window->drawingBufferIdx < 0)
return UWAC_ERROR_INTERNAL;
buf = &window->buffers[window->drawingBufferIdx];
if (!buf)
return UWAC_ERROR_INTERNAL;
if (!region16_union_rect(&buf->damage, &buf->damage, &box))
return UWAC_ERROR_INTERNAL;
@ -695,7 +720,7 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, u
UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* geometry,
size_t* stride)
{
if (!window || !window->drawingBuffer)
if (!window || (window->drawingBufferIdx < 0))
return UWAC_ERROR_INTERNAL;
if (geometry)
@ -712,22 +737,29 @@ UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize*
UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame)
{
UwacBuffer* drawingBuffer = window->drawingBuffer;
UwacBuffer* currentDrawingBuffer;
UwacBuffer* nextDrawingBuffer;
UwacBuffer* pendingBuffer;
if (window->pendingBuffer || !drawingBuffer->dirty)
if (window->drawingBufferIdx < 0)
return UWAC_ERROR_INTERNAL;
currentDrawingBuffer = &window->buffers[window->drawingBufferIdx];
if ((window->pendingBufferIdx >= 0) || !currentDrawingBuffer->dirty)
return UWAC_SUCCESS;
window->pendingBuffer = drawingBuffer;
window->drawingBuffer = UwacWindowFindFreeBuffer(window);
window->pendingBufferIdx = window->drawingBufferIdx;
nextDrawingBuffer = UwacWindowFindFreeBuffer(window, &window->drawingBufferIdx);
pendingBuffer = &window->buffers[window->pendingBufferIdx];
if (!window->drawingBuffer)
if ((!nextDrawingBuffer) || (window->drawingBufferIdx < 0))
return UWAC_ERROR_NOMEMORY;
if (copyContentForNextFrame)
memcpy(window->drawingBuffer->data, window->pendingBuffer->data,
window->stride * window->height);
memcpy(nextDrawingBuffer->data, pendingBuffer->data, window->stride * window->height);
UwacSubmitBufferPtr(window, drawingBuffer);
UwacSubmitBufferPtr(window, pendingBuffer);
return UWAC_SUCCESS;
}

View File

@ -51,7 +51,7 @@ if (NOT WIN32)
endif()
# Soname versioning
set(RAW_VERSION_STRING "2.1.1")
set(RAW_VERSION_STRING "2.1.2")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)

View File

@ -66,6 +66,8 @@ typedef struct _WINPR_BITMAP_CORE_HEADER WINPR_BITMAP_CORE_HEADER;
#define WINPR_IMAGE_BITMAP 0
#define WINPR_IMAGE_PNG 1
#define WINPR_IMAGE_BMP_HEADER_LEN 54
struct _wImage
{
int type;
@ -85,6 +87,7 @@ extern "C"
WINPR_API int winpr_bitmap_write(const char* filename, const BYTE* data, int width, int height,
int bpp);
WINPR_API BYTE* winpr_bitmap_construct_header(int width, int height, int bpp);
WINPR_API int winpr_image_write(wImage* image, const char* filename);
WINPR_API int winpr_image_read(wImage* image, const char* filename);

View File

@ -961,7 +961,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContex
static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
int index;
ULONG index;
int length;
void* data;
UINT32 SeqNo;
@ -977,12 +977,14 @@ static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULON
SeqNo = MessageSeqNo;
context = (NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
for (index = 0; index < (int)pMessage->cBuffers; index++)
for (index = 0; index < pMessage->cBuffers; index++)
{
if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA)
data_buffer = &pMessage->pBuffers[index];
else if (pMessage->pBuffers[index].BufferType == SECBUFFER_TOKEN)
signature_buffer = &pMessage->pBuffers[index];
SecBuffer* cur = &pMessage->pBuffers[index];
if (cur->BufferType & SECBUFFER_DATA)
data_buffer = cur;
else if (cur->BufferType & SECBUFFER_TOKEN)
signature_buffer = cur;
}
if (!data_buffer)
@ -1019,11 +1021,14 @@ static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULON
}
/* Encrypt message using with RC4, result overwrites original buffer */
if (context->confidentiality)
winpr_RC4_Update(context->SendRc4Seal, length, (BYTE*)data, (BYTE*)data_buffer->pvBuffer);
else
CopyMemory(data_buffer->pvBuffer, data, length);
if ((data_buffer->BufferType & SECBUFFER_READONLY) == 0)
{
if (context->confidentiality)
winpr_RC4_Update(context->SendRc4Seal, length, (BYTE*)data,
(BYTE*)data_buffer->pvBuffer);
else
CopyMemory(data_buffer->pvBuffer, data, length);
}
#ifdef WITH_DEBUG_NTLM
WLog_DBG(TAG, "Data Buffer (length = %d)", length);
@ -1034,11 +1039,14 @@ static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULON
free(data);
/* RC4-encrypt first 8 bytes of digest */
winpr_RC4_Update(context->SendRc4Seal, 8, digest, checksum);
signature = (BYTE*)signature_buffer->pvBuffer;
/* Concatenate version, ciphertext and sequence number to build signature */
Data_Write_UINT32(signature, version);
CopyMemory(&signature[4], (void*)checksum, 8);
Data_Write_UINT32(&signature[12], SeqNo);
if ((signature_buffer->BufferType & SECBUFFER_READONLY) == 0)
{
signature = (BYTE*)signature_buffer->pvBuffer;
/* Concatenate version, ciphertext and sequence number to build signature */
Data_Write_UINT32(signature, version);
CopyMemory(&signature[4], (void*)checksum, 8);
Data_Write_UINT32(&signature[12], SeqNo);
}
context->SendSeqNum++;
#ifdef WITH_DEBUG_NTLM
WLog_DBG(TAG, "Signature (length = %" PRIu32 ")", signature_buffer->cbBuffer);

View File

@ -39,13 +39,50 @@
#include "../../log.h"
#define TAG WINPR_TAG("sspi.NTLM")
static const char* const AV_PAIR_STRINGS[] = {
"MsvAvEOL", "MsvAvNbComputerName", "MsvAvNbDomainName", "MsvAvDnsComputerName",
"MsvAvDnsDomainName", "MsvAvDnsTreeName", "MsvAvFlags", "MsvAvTimestamp",
"MsvAvRestrictions", "MsvAvTargetName", "MsvChannelBindings"
};
static BOOL ntlm_av_pair_get_next_offset(const NTLM_AV_PAIR* pAvPair, size_t size, size_t* pOffset);
static BOOL ntlm_av_pair_check(NTLM_AV_PAIR* pAvPair, size_t cbAvPair);
static BOOL ntlm_av_pair_check_data(const NTLM_AV_PAIR* pAvPair, size_t cbAvPair, size_t size)
{
size_t offset;
if (!pAvPair || cbAvPair < sizeof(NTLM_AV_PAIR) + size)
return FALSE;
if (!ntlm_av_pair_get_next_offset(pAvPair, cbAvPair, &offset))
return FALSE;
return cbAvPair >= offset;
}
static const char* get_av_pair_string(UINT16 pair)
{
switch (pair)
{
case MsvAvEOL:
return "MsvAvEOL";
case MsvAvNbComputerName:
return "MsvAvNbComputerName";
case MsvAvNbDomainName:
return "MsvAvNbDomainName";
case MsvAvDnsComputerName:
return "MsvAvDnsComputerName";
case MsvAvDnsDomainName:
return "MsvAvDnsDomainName";
case MsvAvDnsTreeName:
return "MsvAvDnsTreeName";
case MsvAvFlags:
return "MsvAvFlags";
case MsvAvTimestamp:
return "MsvAvTimestamp";
case MsvAvSingleHost:
return "MsvAvSingleHost";
case MsvAvTargetName:
return "MsvAvTargetName";
case MsvChannelBindings:
return "MsvChannelBindings";
default:
return "UNKNOWN";
}
}
static BOOL ntlm_av_pair_check(const NTLM_AV_PAIR* pAvPair, size_t cbAvPair);
static NTLM_AV_PAIR* ntlm_av_pair_next(NTLM_AV_PAIR* pAvPairList, size_t* pcbAvPairList);
static INLINE void ntlm_av_pair_set_id(NTLM_AV_PAIR* pAvPair, UINT16 id)
@ -70,13 +107,19 @@ static BOOL ntlm_av_pair_list_init(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairLis
return TRUE;
}
static INLINE UINT16 ntlm_av_pair_get_id(const NTLM_AV_PAIR* pAvPair)
static INLINE BOOL ntlm_av_pair_get_id(const NTLM_AV_PAIR* pAvPair, size_t size, UINT16* pair)
{
UINT16 AvId;
if (!pAvPair || !pair)
return FALSE;
if (size < sizeof(NTLM_AV_PAIR))
return FALSE;
Data_Read_UINT16(&pAvPair->AvId, AvId);
return AvId;
*pair = AvId;
return TRUE;
}
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList)
@ -91,17 +134,24 @@ ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList)
return ((PBYTE)pAvPair - (PBYTE)pAvPairList) + sizeof(NTLM_AV_PAIR);
}
static INLINE SIZE_T ntlm_av_pair_get_len(const NTLM_AV_PAIR* pAvPair)
static INLINE BOOL ntlm_av_pair_get_len(const NTLM_AV_PAIR* pAvPair, size_t size, size_t* pAvLen)
{
UINT16 AvLen;
if (!pAvPair)
return FALSE;
if (size < sizeof(NTLM_AV_PAIR))
return FALSE;
Data_Read_UINT16(&pAvPair->AvLen, AvLen);
return AvLen;
*pAvLen = AvLen;
return TRUE;
}
void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList)
{
UINT16 pair;
size_t cbAvPair = cbAvPairList;
NTLM_AV_PAIR* pAvPair = pAvPairList;
@ -110,13 +160,13 @@ void ntlm_print_av_pair_list(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList)
WLog_INFO(TAG, "AV_PAIRs =");
while (pAvPair && ntlm_av_pair_get_id(pAvPair) != MsvAvEOL)
while (pAvPair && ntlm_av_pair_get_id(pAvPair, cbAvPair, &pair) && (pair != MsvAvEOL))
{
WLog_INFO(TAG, "\t%s AvId: %" PRIu16 " AvLen: %" PRIu16 "",
AV_PAIR_STRINGS[ntlm_av_pair_get_id(pAvPair)], ntlm_av_pair_get_id(pAvPair),
ntlm_av_pair_get_len(pAvPair));
winpr_HexDump(TAG, WLOG_INFO, ntlm_av_pair_get_value_pointer(pAvPair),
ntlm_av_pair_get_len(pAvPair));
size_t cbLen = 0;
ntlm_av_pair_get_len(pAvPair, cbAvPair, &cbLen);
WLog_INFO(TAG, "\t%s AvId: %" PRIu16 " AvLen: %" PRIu16 "", get_av_pair_string(pair), pair);
winpr_HexDump(TAG, WLOG_INFO, ntlm_av_pair_get_value_pointer(pAvPair), cbLen);
pAvPair = ntlm_av_pair_next(pAvPair, &cbAvPair);
}
@ -133,16 +183,21 @@ PBYTE ntlm_av_pair_get_value_pointer(NTLM_AV_PAIR* pAvPair)
return (PBYTE)pAvPair + sizeof(NTLM_AV_PAIR);
}
static size_t ntlm_av_pair_get_next_offset(NTLM_AV_PAIR* pAvPair)
static BOOL ntlm_av_pair_get_next_offset(const NTLM_AV_PAIR* pAvPair, size_t size, size_t* pOffset)
{
return ntlm_av_pair_get_len(pAvPair) + sizeof(NTLM_AV_PAIR);
size_t avLen;
if (!pOffset)
return FALSE;
if (!ntlm_av_pair_get_len(pAvPair, size, &avLen))
return FALSE;
*pOffset = avLen + sizeof(NTLM_AV_PAIR);
return TRUE;
}
static BOOL ntlm_av_pair_check(NTLM_AV_PAIR* pAvPair, size_t cbAvPair)
static BOOL ntlm_av_pair_check(const NTLM_AV_PAIR* pAvPair, size_t cbAvPair)
{
if (!pAvPair || cbAvPair < sizeof(NTLM_AV_PAIR))
return FALSE;
return cbAvPair >= ntlm_av_pair_get_next_offset(pAvPair);
return ntlm_av_pair_check_data(pAvPair, cbAvPair, 0);
}
static NTLM_AV_PAIR* ntlm_av_pair_next(NTLM_AV_PAIR* pAvPair, size_t* pcbAvPair)
@ -154,7 +209,9 @@ static NTLM_AV_PAIR* ntlm_av_pair_next(NTLM_AV_PAIR* pAvPair, size_t* pcbAvPair)
if (!ntlm_av_pair_check(pAvPair, *pcbAvPair))
return NULL;
offset = ntlm_av_pair_get_next_offset(pAvPair);
if (!ntlm_av_pair_get_next_offset(pAvPair, *pcbAvPair, &offset))
return NULL;
*pcbAvPair -= offset;
return (NTLM_AV_PAIR*)((PBYTE)pAvPair + offset);
}
@ -162,16 +219,15 @@ static NTLM_AV_PAIR* ntlm_av_pair_next(NTLM_AV_PAIR* pAvPair, size_t* pcbAvPair)
NTLM_AV_PAIR* ntlm_av_pair_get(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList, NTLM_AV_ID AvId,
size_t* pcbAvPairListRemaining)
{
UINT16 id;
size_t cbAvPair = cbAvPairList;
NTLM_AV_PAIR* pAvPair = pAvPairList;
if (!ntlm_av_pair_check(pAvPair, cbAvPair))
pAvPair = NULL;
while (pAvPair)
while (pAvPair && ntlm_av_pair_get_id(pAvPair, cbAvPair, &id))
{
UINT16 id = ntlm_av_pair_get_id(pAvPair);
if (id == AvId)
break;
if (id == MsvAvEOL)
@ -218,11 +274,20 @@ static BOOL ntlm_av_pair_add(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList, NTL
static BOOL ntlm_av_pair_add_copy(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList,
NTLM_AV_PAIR* pAvPair, size_t cbAvPair)
{
UINT16 pair;
size_t avLen;
if (!ntlm_av_pair_check(pAvPair, cbAvPair))
return FALSE;
return ntlm_av_pair_add(pAvPairList, cbAvPairList, ntlm_av_pair_get_id(pAvPair),
ntlm_av_pair_get_value_pointer(pAvPair), ntlm_av_pair_get_len(pAvPair));
if (!ntlm_av_pair_get_id(pAvPair, cbAvPair, &pair))
return FALSE;
if (!ntlm_av_pair_get_len(pAvPair, cbAvPair, &avLen))
return FALSE;
return ntlm_av_pair_add(pAvPairList, cbAvPairList, pair,
ntlm_av_pair_get_value_pointer(pAvPair), avLen);
}
static int ntlm_get_target_computer_name(PUNICODE_STRING pName, COMPUTER_NAME_FORMAT type)
@ -500,32 +565,47 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
if (AvNbDomainName)
{
size_t avLen;
if (!ntlm_av_pair_get_len(AvNbDomainName, cbAvNbDomainName, &avLen))
goto fail;
AvPairsCount++; /* MsvAvNbDomainName */
AvPairsValueLength += ntlm_av_pair_get_len(AvNbDomainName);
AvPairsValueLength += avLen;
}
if (AvNbComputerName)
{
size_t avLen;
if (!ntlm_av_pair_get_len(AvNbComputerName, cbAvNbComputerName, &avLen))
goto fail;
AvPairsCount++; /* MsvAvNbComputerName */
AvPairsValueLength += ntlm_av_pair_get_len(AvNbComputerName);
AvPairsValueLength += avLen;
}
if (AvDnsDomainName)
{
size_t avLen;
if (!ntlm_av_pair_get_len(AvDnsDomainName, cbAvDnsDomainName, &avLen))
goto fail;
AvPairsCount++; /* MsvAvDnsDomainName */
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsDomainName);
AvPairsValueLength += avLen;
}
if (AvDnsComputerName)
{
size_t avLen;
if (!ntlm_av_pair_get_len(AvDnsComputerName, cbAvDnsComputerName, &avLen))
goto fail;
AvPairsCount++; /* MsvAvDnsComputerName */
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsComputerName);
AvPairsValueLength += avLen;
}
if (AvDnsTreeName)
{
size_t avLen;
if (!ntlm_av_pair_get_len(AvDnsTreeName, cbAvDnsTreeName, &avLen))
goto fail;
AvPairsCount++; /* MsvAvDnsTreeName */
AvPairsValueLength += ntlm_av_pair_get_len(AvDnsTreeName);
AvPairsValueLength += avLen;
}
AvPairsCount++; /* MsvAvTimestamp */
@ -572,54 +652,54 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
size += 8; /* unknown 8-byte padding */
if (!sspi_SecBufferAlloc(&context->AuthenticateTargetInfo, size))
return -1;
goto fail;
AuthenticateTargetInfo = (NTLM_AV_PAIR*)context->AuthenticateTargetInfo.pvBuffer;
cbAuthenticateTargetInfo = context->AuthenticateTargetInfo.cbBuffer;
if (!ntlm_av_pair_list_init(AuthenticateTargetInfo, cbAuthenticateTargetInfo))
return -1;
goto fail;
if (AvNbDomainName)
{
if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvNbDomainName,
cbAvNbDomainName))
return -1;
goto fail;
}
if (AvNbComputerName)
{
if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo,
AvNbComputerName, cbAvNbComputerName))
return -1;
goto fail;
}
if (AvDnsDomainName)
{
if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo,
AvDnsDomainName, cbAvDnsDomainName))
return -1;
goto fail;
}
if (AvDnsComputerName)
{
if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo,
AvDnsComputerName, cbAvDnsComputerName))
return -1;
goto fail;
}
if (AvDnsTreeName)
{
if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvDnsTreeName,
cbAvDnsTreeName))
return -1;
goto fail;
}
if (AvTimestamp)
{
if (!ntlm_av_pair_add_copy(AuthenticateTargetInfo, cbAuthenticateTargetInfo, AvTimestamp,
cbAvTimestamp))
return -1;
goto fail;
}
if (context->UseMIC)
@ -629,28 +709,28 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
if (!ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvAvFlags,
(PBYTE)&flags, 4))
return -1;
goto fail;
}
if (context->SendSingleHostData)
{
if (!ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvAvSingleHost,
(PBYTE)&context->SingleHostData, context->SingleHostData.Size))
return -1;
goto fail;
}
if (!context->SuppressExtendedProtection)
{
if (!ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvChannelBindings,
context->ChannelBindingsHash, 16))
return -1;
goto fail;
if (context->ServicePrincipalName.Length > 0)
{
if (!ntlm_av_pair_add(AuthenticateTargetInfo, cbAuthenticateTargetInfo, MsvAvTargetName,
(PBYTE)context->ServicePrincipalName.Buffer,
context->ServicePrincipalName.Length))
return -1;
goto fail;
}
}
@ -660,10 +740,13 @@ int ntlm_construct_authenticate_target_info(NTLM_CONTEXT* context)
AvEOL = ntlm_av_pair_get(ChallengeTargetInfo, cbChallengeTargetInfo, MsvAvEOL, NULL);
if (!AvEOL)
return -1;
goto fail;
ZeroMemory(AvEOL, sizeof(NTLM_AV_PAIR));
}
return 1;
fail:
sspi_SecBufferFree(&context->AuthenticateTargetInfo);
return -1;
}

View File

@ -544,9 +544,9 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
winpr_HexDump(TAG, WLOG_DEBUG, context->Timestamp, 8);
#endif
context->state = NTLM_STATE_AUTHENTICATE;
ntlm_free_message_fields_buffer(&(message->TargetName));
status = SEC_I_CONTINUE_NEEDED;
fail:
ntlm_free_message_fields_buffer(&(message->TargetName));
Stream_Free(s, FALSE);
return status;
}

View File

@ -201,18 +201,23 @@ BOOL LogonUserExW(LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword
BOOL GetUserNameExA(EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
{
size_t length;
char* login;
char login[MAX_PATH];
switch (NameFormat)
{
case NameSamCompatible:
login = getlogin();
#ifndef getlogin_r
strncpy(login, getlogin(), sizeof(login));
#else
if (getlogin_r(login, sizeof(login)) != 0)
return FALSE;
#endif
length = strlen(login);
if (*nSize >= length)
{
CopyMemory(lpNameBuffer, login, length + 1);
return 1;
return TRUE;
}
else
{
@ -235,7 +240,7 @@ BOOL GetUserNameExA(EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG
break;
}
return 0;
return FALSE;
}
BOOL GetUserNameExW(EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)

View File

@ -213,11 +213,12 @@ void GetNativeSystemInfo(LPSYSTEM_INFO lpSystemInfo)
void GetSystemTime(LPSYSTEMTIME lpSystemTime)
{
time_t ct = 0;
struct tm tres;
struct tm* stm = NULL;
WORD wMilliseconds = 0;
ct = time(NULL);
wMilliseconds = (WORD)(GetTickCount() % 1000);
stm = gmtime(&ct);
stm = gmtime_r(&ct, &tres);
ZeroMemory(lpSystemTime, sizeof(SYSTEMTIME));
if (stm)
@ -242,11 +243,12 @@ BOOL SetSystemTime(CONST SYSTEMTIME* lpSystemTime)
VOID GetLocalTime(LPSYSTEMTIME lpSystemTime)
{
time_t ct = 0;
struct tm tres;
struct tm* ltm = NULL;
WORD wMilliseconds = 0;
ct = time(NULL);
wMilliseconds = (WORD)(GetTickCount() % 1000);
ltm = localtime(&ct);
ltm = localtime_r(&ct, &tres);
ZeroMemory(lpSystemTime, sizeof(SYSTEMTIME));
if (ltm)

View File

@ -339,12 +339,16 @@ winpr_get_current_time_zone_rule(const TIME_ZONE_RULE_ENTRY* rules, UINT32 count
DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
{
time_t t;
struct tm tres;
struct tm* local_time;
TIME_ZONE_ENTRY* dtz;
LPTIME_ZONE_INFORMATION tz = lpTimeZoneInformation;
lpTimeZoneInformation->StandardBias = 0;
time(&t);
local_time = localtime(&t);
local_time = localtime_r(&t, &tres);
if (!local_time)
goto out_error;
memset(tz, 0, sizeof(TIME_ZONE_INFORMATION));
#ifdef HAVE_TM_GMTOFF
{

View File

@ -100,12 +100,13 @@ BOOL MessageQueue_Dispatch(wMessageQueue* queue, wMessage* message)
}
CopyMemory(&(queue->array[queue->tail]), message, sizeof(wMessage));
queue->tail = (queue->tail + 1) % queue->capacity;
queue->size++;
message = &(queue->array[queue->tail]);
message->time = GetTickCount64();
queue->tail = (queue->tail + 1) % queue->capacity;
queue->size++;
if (queue->size > 0)
SetEvent(queue->event);

View File

@ -100,24 +100,18 @@ static BOOL readBitmapInfoHeader(wStream* s, WINPR_BITMAP_INFO_HEADER* bi)
return TRUE;
}
/**
* Refer to "Compressed Image File Formats: JPEG, PNG, GIF, XBM, BMP" book
*/
int winpr_bitmap_write(const char* filename, const BYTE* data, int width, int height, int bpp)
BYTE* winpr_bitmap_construct_header(int width, int height, int bpp)
{
FILE* fp;
WINPR_BITMAP_FILE_HEADER bf;
WINPR_BITMAP_INFO_HEADER bi;
wStream* s;
int ret = -1;
fp = fopen(filename, "w+b");
wStream s;
BYTE* buffer = NULL;
if (!fp)
{
WLog_ERR(TAG, "failed to open file %s", filename);
return -1;
}
buffer = malloc(WINPR_IMAGE_BMP_HEADER_LEN);
if (!buffer)
return NULL;
Stream_StaticInit(&s, buffer, WINPR_IMAGE_BMP_HEADER_LEN);
bf.bfType[0] = 'B';
bf.bfType[1] = 'M';
@ -136,27 +130,49 @@ int winpr_bitmap_write(const char* filename, const BYTE* data, int width, int he
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bi.biSize = sizeof(WINPR_BITMAP_INFO_HEADER);
s = Stream_New(NULL, sizeof(WINPR_BITMAP_FILE_HEADER) + sizeof(WINPR_BITMAP_INFO_HEADER));
if (!s)
if (!writeBitmapFileHeader(&s, &bf))
goto fail;
if (!writeBitmapFileHeader(s, &bf))
if (!writeBitmapInfoHeader(&s, &bi))
goto fail;
if (!writeBitmapInfoHeader(s, &bi))
goto fail;
return buffer;
fail:
return NULL;
}
Stream_SealLength(s);
/**
* Refer to "Compressed Image File Formats: JPEG, PNG, GIF, XBM, BMP" book
*/
if (fwrite(Stream_Buffer(s), Stream_Length(s), 1, fp) != 1 ||
fwrite((void*)data, bi.biSizeImage, 1, fp) != 1)
int winpr_bitmap_write(const char* filename, const BYTE* data, int width, int height, int bpp)
{
FILE* fp;
BYTE* bmp_header = NULL;
UINT32 img_size = width * height * (bpp / 8);
int ret = -1;
fp = fopen(filename, "w+b");
if (!fp)
{
WLog_ERR(TAG, "failed to open file %s", filename);
return -1;
}
bmp_header = winpr_bitmap_construct_header(width, height, bpp);
if (!bmp_header)
return -1;
if (fwrite(bmp_header, WINPR_IMAGE_BMP_HEADER_LEN, 1, fp) != 1 ||
fwrite((void*)data, img_size, 1, fp) != 1)
goto fail;
ret = 1;
fail:
fclose(fp);
Stream_Free(s, TRUE);
free(bmp_header);
return ret;
}

View File

@ -2729,7 +2729,7 @@ TRIO_PRIVATE void TrioWriteString TRIO_ARGS5((self, string, flags, width, precis
trio_class_t* self, TRIO_CONST char* string,
trio_flags_t flags, int width, int precision)
{
int length;
int length = 0;
int ch;
assert(VALID(self));
@ -2747,7 +2747,7 @@ TRIO_PRIVATE void TrioWriteString TRIO_ARGS5((self, string, flags, width, precis
}
else
{
if (precision == 0)
if (precision <= 0)
{
length = trio_length(string);
}
@ -4754,7 +4754,7 @@ TRIO_PUBLIC trio_pointer_t trio_register TRIO_ARGS2((callback, name), trio_callb
}
/* Bail out if namespace is too long */
if (trio_length(name) >= MAX_USER_NAME)
if (trio_length_max(name, MAX_USER_NAME) >= MAX_USER_NAME)
return NULL;
/* Bail out if namespace already is registered */

View File

@ -25,6 +25,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include "triodef.h"
#include "triostr.h"
@ -328,7 +329,7 @@ TRIO_PUBLIC_STRING void trio_destroy TRIO_ARGS1((string), char* string)
TRIO_PUBLIC_STRING size_t trio_length TRIO_ARGS1((string), TRIO_CONST char* string)
{
return strlen(string);
return trio_length_max(string, INT_MAX);
}
#endif