diff options
author | Martin Fleisz <martin.fleisz@thincast.com> | 2020-05-20 17:45:43 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-20 17:45:43 +0300 |
commit | 1923e63516c1182bd5e917aeac563431e8c5381a (patch) | |
tree | 5997d6fcac797e2c836c84ac4a7c04aef39cc147 | |
parent | 11b9b1ca6be433f1da5bbf5e152d554d3eb67ac6 (diff) | |
parent | 3c33c6e1a20601da2f47ac8546f5ab6223a66049 (diff) |
Merge pull request #6212 from akallabeth/stable_backport_cve2.1.1
Stable backport cve
89 files changed, 1873 insertions, 1286 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a4d22b31e..1d685b921 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ if ($ENV{BUILD_NUMBER}) endif() set(WITH_LIBRARY_VERSIONING "ON") -set(RAW_VERSION_STRING "2.1.0") +set(RAW_VERSION_STRING "2.1.1") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) @@ -936,10 +936,6 @@ if(MBEDTLS_FOUND) add_definitions("-DWITH_MBEDTLS") endif() -if (TARGET_ARCH MATCHES "sparc") - set(HAVE_ALIGNED_REQUIRED 1) -endif() - if (WITH_X264 OR WITH_OPENH264 OR WITH_MEDIA_FOUNDATION OR WITH_FFMPEG) set(WITH_GFX_H264 ON) else() @@ -1,3 +1,21 @@ +# 2020-05-20 Version 2.1.1 + +Important notes: +* CVE: GHSL-2020-100 OOB Read in ntlm_read_ChallengeMessage +* CVE: GHSL-2020-101 OOB Read in security_fips_decrypt due to uninitialized value +* CVE: GHSL-2020-102 OOB Write in crypto_rsa_common +* Enforce synchronous legacy RDP encryption count (#6156) +* Fixed some leaks and crashes missed in 2.1.0 +* Removed dynamic channel listener limits +* Lots of resource cleanup fixes (clang sanitizers) +* A couple of performance improvements +* Various small annoyances eliminated (typos, prefilled username for windows client, ...) + + +For a complete and detailed change log since the last release candidate run: +git log 2.1.0..2.1.1 + + # 2020-05-05 Version 2.1.0 Important notes: diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 1b14fd3b7..26ac48390 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -100,6 +100,8 @@ struct _AUDIN_PLUGIN FREERDP_DSP_CONTEXT* dsp_context; wLog* log; + + IWTSListener* listener; }; static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args); @@ -687,7 +689,7 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag audin->listener_callback->plugin = pPlugin; audin->listener_callback->channel_mgr = pChannelMgr; return pChannelMgr->CreateListener(pChannelMgr, "AUDIO_INPUT", 0, - (IWTSListenerCallback*)audin->listener_callback, NULL); + &audin->listener_callback->iface, &audin->listener); } /** @@ -704,6 +706,13 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin) return CHANNEL_RC_BAD_CHANNEL_HANDLE; WLog_Print(audin->log, WLOG_TRACE, "..."); + + if (audin->listener_callback) + { + IWTSVirtualChannelManager* mgr = audin->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, audin->listener); + } audio_formats_free(audin->fixed_format, 1); if (audin->device) diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 8541cabcc..b5d119a20 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -594,7 +594,7 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context, wStream* s; WCHAR* wszTempDir = NULL; cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; - s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, 520 * 2); + s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, 260 * sizeof(WCHAR)); if (!s) { @@ -607,11 +607,13 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context, if (length < 0) return ERROR_INTERNAL_ERROR; - if (length > 520) - length = 520; + /* Path must be 260 UTF16 characters with '\0' termination. + * ensure this here */ + if (length >= 260) + length = 259; - Stream_Write(s, wszTempDir, (size_t)length * 2); - Stream_Zero(s, (520 - (size_t)length) * 2); + Stream_Write_UTF16_String(s, wszTempDir, length); + Stream_Zero(s, 520 - (length * sizeof(WCHAR))); free(wszTempDir); WLog_Print(cliprdr->log, WLOG_DEBUG, "TempDirectory: %s", tempDirectory->szTempDir); return cliprdr_packet_send(cliprdr, s); diff --git a/channels/cliprdr/cliprdr_common.c b/channels/cliprdr/cliprdr_common.c index a699852b6..c0fae6e89 100644 --- a/channels/cliprdr/cliprdr_common.c +++ b/channels/cliprdr/cliprdr_common.c @@ -395,7 +395,6 @@ UINT cliprdr_read_file_contents_response(wStream* s, CLIPRDR_FILE_CONTENTS_RESPO UINT cliprdr_read_format_list(wStream* s, CLIPRDR_FORMAT_LIST* formatList, BOOL useLongFormatNames) { UINT32 index; - size_t position; BOOL asciiNames; int formatNameLength; char* szFormatName; diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c index 8854a0fb7..da4ab0b9b 100644 --- a/channels/cliprdr/server/cliprdr_main.c +++ b/channels/cliprdr/server/cliprdr_main.c @@ -553,7 +553,7 @@ static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* con UINT error = CHANNEL_RC_OK; WINPR_UNUSED(header); - if ((slength = Stream_GetRemainingLength(s)) < 520) + if ((slength = Stream_GetRemainingLength(s)) < 260 * sizeof(WCHAR)) { WLog_ERR(TAG, "Stream_GetRemainingLength returned %" PRIuz " but should at least be 520", slength); @@ -562,9 +562,9 @@ static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* con wszTempDir = (WCHAR*)Stream_Pointer(s); - if (wszTempDir[260] != 0) + if (wszTempDir[259] != 0) { - WLog_ERR(TAG, "wszTempDir[260] was not 0"); + WLog_ERR(TAG, "wszTempDir[259] was not 0"); return ERROR_INVALID_DATA; } @@ -578,10 +578,10 @@ static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* con return ERROR_INVALID_DATA; } - length = strnlen(cliprdr->temporaryDirectory, 520); + length = strnlen(cliprdr->temporaryDirectory, 260); - if (length > 519) - length = 519; + if (length >= 260) + length = 259; CopyMemory(tempDirectory.szTempDir, cliprdr->temporaryDirectory, length); tempDirectory.szTempDir[length] = '\0'; diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c index d3e9a22cf..fa92c252a 100644 --- a/channels/disp/client/disp_main.c +++ b/channels/disp/client/disp_main.c @@ -308,8 +308,7 @@ static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage disp->listener_callback->plugin = pPlugin; disp->listener_callback->channel_mgr = pChannelMgr; status = pChannelMgr->CreateListener(pChannelMgr, DISP_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*)disp->listener_callback, - &(disp->listener)); + &disp->listener_callback->iface, &(disp->listener)); disp->listener->pInterface = disp->iface.pInterface; return status; } @@ -322,6 +321,14 @@ static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage static UINT disp_plugin_terminated(IWTSPlugin* pPlugin) { DISP_PLUGIN* disp = (DISP_PLUGIN*)pPlugin; + + if (disp && disp->listener_callback) + { + IWTSVirtualChannelManager* mgr = disp->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, disp->listener); + } + free(disp->listener_callback); free(disp->iface.pInterface); free(pPlugin); diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index fa09cd08f..eb5b418e1 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -30,6 +30,7 @@ #define TAG CHANNELS_TAG("drdynvc.client") +static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr); static void dvcman_channel_free(void* channel); static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data, UINT32 dataSize); @@ -39,6 +40,7 @@ static void dvcman_wtslistener_free(DVCMAN_LISTENER* listener) { if (listener) free(listener->channel_name); + free(listener); } @@ -67,64 +69,50 @@ static UINT dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr, DVCMAN* dvcman = (DVCMAN*)pChannelMgr; DVCMAN_LISTENER* listener; - if (dvcman->num_listeners < MAX_PLUGINS) - { - WLog_DBG(TAG, "create_listener: %d.%s.", dvcman->num_listeners, pszChannelName); - listener = (DVCMAN_LISTENER*)calloc(1, sizeof(DVCMAN_LISTENER)); + WLog_DBG(TAG, "create_listener: %d.%s.", ArrayList_Count(dvcman->listeners) + 1, + pszChannelName); + listener = (DVCMAN_LISTENER*)calloc(1, sizeof(DVCMAN_LISTENER)); - if (!listener) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } + if (!listener) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } - listener->iface.GetConfiguration = dvcman_get_configuration; - listener->iface.pInterface = NULL; - listener->dvcman = dvcman; - listener->channel_name = _strdup(pszChannelName); + listener->iface.GetConfiguration = dvcman_get_configuration; + listener->iface.pInterface = NULL; + listener->dvcman = dvcman; + listener->channel_name = _strdup(pszChannelName); - if (!listener->channel_name) - { - WLog_ERR(TAG, "_strdup failed!"); - dvcman_wtslistener_free(listener); - return CHANNEL_RC_NO_MEMORY; - } + if (!listener->channel_name) + { + WLog_ERR(TAG, "_strdup failed!"); + dvcman_wtslistener_free(listener); + return CHANNEL_RC_NO_MEMORY; + } - listener->flags = ulFlags; - listener->listener_callback = pListenerCallback; + listener->flags = ulFlags; + listener->listener_callback = pListenerCallback; - if (ppListener) - *ppListener = (IWTSListener*)listener; + if (ppListener) + *ppListener = (IWTSListener*)listener; - dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*)listener; - return CHANNEL_RC_OK; - } - else - { - WLog_ERR(TAG, "create_listener: Maximum DVC listener number reached."); + if (ArrayList_Add(dvcman->listeners, listener) < 0) return ERROR_INTERNAL_ERROR; - } + return CHANNEL_RC_OK; } static UINT dvcman_destroy_listener(IWTSVirtualChannelManager* pChannelMgr, IWTSListener* pListener) { - size_t x; DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)pListener; + WINPR_UNUSED(pChannelMgr); + if (listener) { DVCMAN* dvcman = listener->dvcman; - for (x = 0; x < dvcman->num_listeners; x++) - { - if (dvcman->listeners[x] == pListener) - { - size_t rest = (dvcman->num_listeners - x - 1) * sizeof(IWTSListener*); - MoveMemory(&dvcman->listeners[x], &dvcman->listeners[x + 1], rest); - dvcman->num_listeners--; - dvcman_wtslistener_free(listener); - break; - } - } + if (dvcman) + ArrayList_Remove(dvcman->listeners, listener); } return CHANNEL_RC_OK; @@ -140,34 +128,42 @@ static UINT dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const ch { DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman; - if (dvcman->num_plugins < MAX_PLUGINS) - { - dvcman->plugin_names[dvcman->num_plugins] = name; - dvcman->plugins[dvcman->num_plugins++] = pPlugin; - WLog_DBG(TAG, "register_plugin: num_plugins %d", dvcman->num_plugins); - return CHANNEL_RC_OK; - } - else - { - WLog_ERR(TAG, "register_plugin: Maximum DVC plugin number %u reached.", MAX_PLUGINS); + if (ArrayList_Add(dvcman->plugin_names, _strdup(name)) < 0) return ERROR_INTERNAL_ERROR; - } + if (ArrayList_Add(dvcman->plugins, pPlugin) < 0) + return ERROR_INTERNAL_ERROR; + + WLog_DBG(TAG, "register_plugin: num_plugins %d", ArrayList_Count(dvcman->plugins)); + return CHANNEL_RC_OK; } static IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name) { - size_t i; + IWTSPlugin* plugin = NULL; + size_t i, nc, pc; DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman; + if (!dvcman || !pEntryPoints || !name) + return NULL; + + nc = ArrayList_Count(dvcman->plugin_names); + pc = ArrayList_Count(dvcman->plugins); + if (nc != pc) + return NULL; - for (i = 0; i < dvcman->num_plugins; i++) + ArrayList_Lock(dvcman->plugin_names); + ArrayList_Lock(dvcman->plugins); + for (i = 0; i < pc; i++) { - if (dvcman->plugin_names[i] == name || strcmp(dvcman->plugin_names[i], name) == 0) + const char* cur = ArrayList_GetItem(dvcman->plugin_names, i); + if (strcmp(cur, name) == 0) { - return dvcman->plugins[i]; + plugin = ArrayList_GetItem(dvcman->plugins, i); + break; } } - - return NULL; + ArrayList_Unlock(dvcman->plugin_names); + ArrayList_Unlock(dvcman->plugins); + return plugin; } static ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints) @@ -196,38 +192,45 @@ static IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* UINT32 ChannelId) { int index; - BOOL found = FALSE; - DVCMAN_CHANNEL* channel; + IWTSVirtualChannel* channel = NULL; DVCMAN* dvcman = (DVCMAN*)pChannelMgr; ArrayList_Lock(dvcman->channels); - index = 0; - channel = (DVCMAN_CHANNEL*)ArrayList_GetItem(dvcman->channels, index++); - - while (channel) + for (index = 0; index < ArrayList_Count(dvcman->channels); index++) { - if (channel->channel_id == ChannelId) + DVCMAN_CHANNEL* cur = (DVCMAN_CHANNEL*)ArrayList_GetItem(dvcman->channels, index); + if (cur->channel_id == ChannelId) { - found = TRUE; + channel = &cur->iface; break; } - - channel = (DVCMAN_CHANNEL*)ArrayList_GetItem(dvcman->channels, index++); } ArrayList_Unlock(dvcman->channels); - return (found) ? ((IWTSVirtualChannel*)channel) : NULL; + return channel; +} + +static void dvcman_plugin_terminate(void* plugin) +{ + IWTSPlugin* pPlugin = plugin; + + UINT error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Terminated, pPlugin); + if (error != CHANNEL_RC_OK) + WLog_ERR(TAG, "Terminated failed with error %" PRIu32 "!", error); } +static void wts_listener_free(void* arg) +{ + DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)arg; + dvcman_wtslistener_free(listener); +} static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) { + wObject* obj; DVCMAN* dvcman; dvcman = (DVCMAN*)calloc(1, sizeof(DVCMAN)); if (!dvcman) - { - WLog_Print(plugin->log, WLOG_ERROR, "calloc failed!"); return NULL; - } dvcman->iface.CreateListener = dvcman_create_listener; dvcman->iface.DestroyListener = dvcman_destroy_listener; @@ -238,24 +241,36 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) dvcman->channels = ArrayList_New(TRUE); if (!dvcman->channels) - { - WLog_Print(plugin->log, WLOG_ERROR, "ArrayList_New failed!"); - free(dvcman); - return NULL; - } + goto fail; - dvcman->channels->object.fnObjectFree = dvcman_channel_free; - dvcman->pool = StreamPool_New(TRUE, 10); + obj = ArrayList_Object(dvcman->channels); + obj->fnObjectFree = dvcman_channel_free; + dvcman->pool = StreamPool_New(TRUE, 10); if (!dvcman->pool) - { - WLog_Print(plugin->log, WLOG_ERROR, "StreamPool_New failed!"); - ArrayList_Free(dvcman->channels); - free(dvcman); - return NULL; - } - - return (IWTSVirtualChannelManager*)dvcman; + goto fail; + + dvcman->listeners = ArrayList_New(TRUE); + if (!dvcman->listeners) + goto fail; + obj = ArrayList_Object(dvcman->listeners); + obj->fnObjectFree = wts_listener_free; + + dvcman->plugin_names = ArrayList_New(TRUE); + if (!dvcman->plugin_names) + goto fail; + obj = ArrayList_Object(dvcman->plugin_names); + obj->fnObjectFree = free; + + dvcman->plugins = ArrayList_New(TRUE); + if (!dvcman->plugins) + goto fail; + obj = ArrayList_Object(dvcman->plugins); + obj->fnObjectFree = dvcman_plugin_terminate; + return &dvcman->iface; +fail: + dvcman_free(plugin, &dvcman->iface); + return NULL; } /** @@ -304,31 +319,22 @@ static DVCMAN_CHANNEL* dvcman_channel_new(drdynvcPlugin* drdynvc, channel = (DVCMAN_CHANNEL*)calloc(1, sizeof(DVCMAN_CHANNEL)); if (!channel) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "calloc failed!"); - return NULL; - } + goto fail; channel->dvcman = (DVCMAN*)pChannelMgr; channel->channel_id = ChannelId; channel->channel_name = _strdup(ChannelName); if (!channel->channel_name) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "_strdup failed!"); - free(channel); - return NULL; - } + goto fail; if (!InitializeCriticalSectionEx(&(channel->lock), 0, 0)) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "InitializeCriticalSectionEx failed!"); - free(channel->channel_name); - free(channel); - return NULL; - } + goto fail; return channel; +fail: + dvcman_channel_free(channel); + return NULL; } static void dvcman_channel_free(void* arg) @@ -341,6 +347,7 @@ static void dvcman_channel_free(void* arg) if (channel->channel_callback) { IFCALL(channel->channel_callback->OnClose, channel->channel_callback); + channel->channel_callback = NULL; } if (channel->status == CHANNEL_RC_OK) @@ -374,33 +381,29 @@ static void dvcman_channel_free(void* arg) free(channel); } -static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr) +static void dvcman_clear(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr) { - size_t i; - IWTSPlugin* pPlugin; DVCMAN* dvcman = (DVCMAN*)pChannelMgr; - UINT error; - ArrayList_Free(dvcman->channels); - for (i = 0; i < dvcman->num_listeners; i++) - { - DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)dvcman->listeners[i]; - dvcman_wtslistener_free(listener); - } + WINPR_UNUSED(drdynvc); - dvcman->num_listeners = 0; + ArrayList_Clear(dvcman->plugins); + ArrayList_Clear(dvcman->channels); + ArrayList_Clear(dvcman->plugin_names); + ArrayList_Clear(dvcman->listeners); +} - for (i = 0; i < dvcman->num_plugins; i++) - { - pPlugin = dvcman->plugins[i]; +static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr) +{ + DVCMAN* dvcman = (DVCMAN*)pChannelMgr; - if (pPlugin->Terminated) - if ((error = pPlugin->Terminated(pPlugin))) - WLog_Print(drdynvc->log, WLOG_ERROR, "Terminated failed with error %" PRIu32 "!", - error); - } + WINPR_UNUSED(drdynvc); + + ArrayList_Free(dvcman->plugins); + ArrayList_Free(dvcman->channels); + ArrayList_Free(dvcman->plugin_names); + ArrayList_Free(dvcman->listeners); - dvcman->num_plugins = 0; StreamPool_Free(dvcman->pool); free(dvcman); } @@ -413,24 +416,26 @@ static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChan static UINT dvcman_init(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr) { size_t i; - IWTSPlugin* pPlugin; DVCMAN* dvcman = (DVCMAN*)pChannelMgr; - UINT error; + UINT error = CHANNEL_RC_OK; - for (i = 0; i < dvcman->num_plugins; i++) + ArrayList_Lock(dvcman->plugins); + for (i = 0; i < ArrayList_Count(dvcman->plugins); i++) { - pPlugin = dvcman->plugins[i]; + IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i); - if (pPlugin->Initialize) - if ((error = pPlugin->Initialize(pPlugin, pChannelMgr))) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "Initialize failed with error %" PRIu32 "!", - error); - return error; - } + error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Initialize, pPlugin, pChannelMgr); + if (error != CHANNEL_RC_OK) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "Initialize failed with error %" PRIu32 "!", + error); + goto fail; + } } - return CHANNEL_RC_OK; +fail: + ArrayList_Unlock(dvcman->plugins); + return error; } /** @@ -482,7 +487,6 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana BOOL bAccept; DVCMAN_CHANNEL* channel; DrdynvcClientContext* context; - IWTSVirtualChannelCallback* pCallback; DVCMAN* dvcman = (DVCMAN*)pChannelMgr; UINT error; @@ -493,18 +497,20 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana } channel->status = ERROR_NOT_CONNECTED; - ArrayList_Add(dvcman->channels, channel); + if (ArrayList_Add(dvcman->channels, channel) < 0) + return ERROR_INTERNAL_ERROR; - for (i = 0; i < dvcman->num_listeners; i++) + ArrayList_Lock(dvcman->listeners); + for (i = 0; i < ArrayList_Count(dvcman->listeners); i++) { - DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)dvcman->listeners[i]; + DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)ArrayList_GetItem(dvcman->listeners, i); if (strcmp(listener->channel_name, ChannelName) == 0) { + IWTSVirtualChannelCallback* pCallback = NULL; channel->iface.Write = dvcman_write_channel; channel->iface.Close = dvcman_close_channel_iface; bAccept = TRUE; - pCallback = NULL; if ((error = listener->listener_callback->OnNewChannelConnection( listener->listener_callback, &channel->iface, NULL, &bAccept, &pCallback)) == @@ -524,7 +530,7 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana WLog_Print(drdynvc->log, WLOG_ERROR, "context.OnChannelConnected failed with error %" PRIu32 "", error); - return error; + goto fail; } else { @@ -532,19 +538,23 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana { WLog_Print(drdynvc->log, WLOG_ERROR, "OnNewChannelConnection failed with error %" PRIu32 "!", error); - return error; + goto fail; } else { WLog_Print(drdynvc->log, WLOG_ERROR, "OnNewChannelConnection returned with bAccept FALSE!"); - return ERROR_INTERNAL_ERROR; + error = ERROR_INTERNAL_ERROR; + goto fail; } } } } + error = ERROR_INTERNAL_ERROR; +fail: + ArrayList_Unlock(dvcman->listeners); - return ERROR_INTERNAL_ERROR; + return error; } /** @@ -608,10 +618,10 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 if (drdynvc && bSendClosePDU) { - wStream* s = Stream_New(NULL, 5); + wStream* s = StreamPool_Take(dvcman->pool, 5); if (!s) { - WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); error = CHANNEL_RC_NO_MEMORY; } else @@ -689,7 +699,7 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc, if (channel->dvc_data) { /* Fragmented data */ - if (Stream_GetPosition(channel->dvc_data) + dataSize > Stream_Capacity(channel->dvc_data)) + if (Stream_GetPosition(channel->dvc_data) + dataSize > channel->dvc_data_length) { WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!"); Stream_Release(channel->dvc_data); @@ -764,16 +774,16 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s) return CHANNEL_RC_OK; case CHANNEL_RC_NOT_CONNECTED: - Stream_Free(s, TRUE); + Stream_Release(s); return CHANNEL_RC_OK; case CHANNEL_RC_BAD_CHANNEL_HANDLE: - Stream_Free(s, TRUE); + Stream_Release(s); WLog_ERR(TAG, "VirtualChannelWriteEx failed with CHANNEL_RC_BAD_CHANNEL_HANDLE"); return status; default: - Stream_Free(s, TRUE); + Stream_Release(s); WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); @@ -795,17 +805,20 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B UINT8 cbLen; unsigned long chunkLength; UINT status = CHANNEL_RC_BAD_INIT_HANDLE; + DVCMAN* dvcman; if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + dvcman = (DVCMAN*)drdynvc->channel_mgr; + WLog_Print(drdynvc->log, WLOG_DEBUG, "write_data: ChannelId=%" PRIu32 " size=%" PRIu32 "", ChannelId, dataSize); - data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); + data_out = StreamPool_Take(dvcman->pool, CHANNEL_CHUNK_LENGTH); if (!data_out) { - WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -815,7 +828,8 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B if (dataSize == 0) { - status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE); + dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE); + Stream_Release(data_out); } else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos) { @@ -841,11 +855,11 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B while (status == CHANNEL_RC_OK && dataSize > 0) { - data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); + data_out = StreamPool_Take(dvcman->pool, CHANNEL_CHUNK_LENGTH); if (!data_out) { - WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -886,12 +900,14 @@ static UINT drdynvc_send_capability_response(drdynvcPlugin* drdynvc) { UINT status; wStream* s; + DVCMAN* dvcman; if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + dvcman = (DVCMAN*)drdynvc->channel_mgr; WLog_Print(drdynvc->log, WLOG_TRACE, "capability_response"); - s = Stream_New(NULL, 4); + s = StreamPool_Take(dvcman->pool, 4); if (!s) { @@ -1002,11 +1018,13 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int c UINT channel_status; char* name; size_t length; + DVCMAN* dvcman; WINPR_UNUSED(Sp); if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + dvcman = (DVCMAN*)drdynvc->channel_mgr; if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES) { /** @@ -1039,11 +1057,11 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int c WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%" PRIu32 " ChannelName=%s", ChannelId, name); channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, name); - data_out = Stream_New(NULL, pos + 4); + data_out = StreamPool_Take(dvcman->pool, pos + 4); if (!data_out) { - WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1231,22 +1249,23 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, if (dataFlags & CHANNEL_FLAG_FIRST) { + DVCMAN* mgr = (DVCMAN*)drdynvc->channel_mgr; if (drdynvc->data_in) - Stream_Free(drdynvc->data_in, TRUE); + Stream_Release(drdynvc->data_in); - drdynvc->data_in = Stream_New(NULL, totalLength); + drdynvc->data_in = StreamPool_Take(mgr->pool, totalLength); } if (!(data_in = drdynvc->data_in)) { - WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); return CHANNEL_RC_NO_MEMORY; } if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) { WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); - Stream_Free(drdynvc->data_in, TRUE); + Stream_Release(drdynvc->data_in); drdynvc->data_in = NULL; return ERROR_INTERNAL_ERROR; } @@ -1255,7 +1274,9 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, if (dataFlags & CHANNEL_FLAG_LAST) { - if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) + const size_t cap = Stream_Capacity(data_in); + const size_t pos = Stream_GetPosition(data_in); + if (cap < pos) { WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_plugin_process_received: read error"); return ERROR_INVALID_DATA; @@ -1304,7 +1325,7 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam, case CHANNEL_EVENT_WRITE_COMPLETE: { wStream* s = (wStream*)pData; - Stream_Free(s, TRUE); + Stream_Release(s); } break; @@ -1359,7 +1380,7 @@ static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg) "drdynvc_order_recv failed with error %" PRIu32 "!", error); } - Stream_Free(data, TRUE); + Stream_Release(data); } } @@ -1397,7 +1418,41 @@ static void drdynvc_queue_object_free(void* obj) s = (wStream*)msg->wParam; if (s) - Stream_Free(s, TRUE); + Stream_Release(s); +} + +static UINT drdynvc_virtual_channel_event_initialized(drdynvcPlugin* drdynvc, LPVOID pData, + UINT32 dataLength) +{ + UINT error = CHANNEL_RC_OK; + WINPR_UNUSED(pData); + WINPR_UNUSED(dataLength); + + if (!drdynvc) + goto error; + + drdynvc->queue = MessageQueue_New(NULL); + + if (!drdynvc->queue) + { + error = CHANNEL_RC_NO_MEMORY; + WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_New failed!"); + goto error; + } + + drdynvc->queue->object.fnObjectFree = drdynvc_queue_object_free; + drdynvc->channel_mgr = dvcman_new(drdynvc); + + if (!drdynvc->channel_mgr) + { + error = CHANNEL_RC_NO_MEMORY; + WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_new failed!"); + goto error; + } + + return CHANNEL_RC_OK; +error: + return ERROR_INTERNAL_ERROR; } /** @@ -1431,25 +1486,6 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO return status; } - drdynvc->queue = MessageQueue_New(NULL); - - if (!drdynvc->queue) - { - error = CHANNEL_RC_NO_MEMORY; - WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_New failed!"); - goto error; - } - - drdynvc->queue->object.fnObjectFree = drdynvc_queue_object_free; - drdynvc->channel_mgr = dvcman_new(drdynvc); - - if (!drdynvc->channel_mgr) - { - error = CHANNEL_RC_NO_MEMORY; - WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_new failed!"); - goto error; - } - settings = (rdpSettings*)drdynvc->channelEntryPoints.pExtendedData; for (index = 0; index < settings->DynamicChannelCount; index++) @@ -1512,10 +1548,9 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc) return status; } - MessageQueue_Free(drdynvc->queue); CloseHandle(drdynvc->thread); - drdynvc->queue = NULL; drdynvc->thread = NULL; + status = drdynvc->channelEntryPoints.pVirtualChannelCloseEx(drdynvc->InitHandle, drdynvc->OpenHandle); @@ -1525,20 +1560,16 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc) WTSErrorToString(status), status); } + dvcman_clear(drdynvc, drdynvc->channel_mgr); + MessageQueue_Clear(drdynvc->queue); drdynvc->OpenHandle = 0; if (drdynvc->data_in) { - Stream_Free(drdynvc->data_in, TRUE); + Stream_Release(drdynvc->data_in); drdynvc->data_in = NULL; } - if (drdynvc->channel_mgr) - { - dvcman_free(drdynvc, drdynvc->channel_mgr); - drdynvc->channel_mgr = NULL; - } - return status; } @@ -1552,6 +1583,13 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc) if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + 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); @@ -1560,6 +1598,7 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc) static UINT drdynvc_virtual_channel_event_attached(drdynvcPlugin* drdynvc) { + UINT error = CHANNEL_RC_OK; size_t i; DVCMAN* dvcman; @@ -1571,25 +1610,27 @@ static UINT drdynvc_virtual_channel_event_attached(drdynvcPlugin* drdynvc) if (!dvcman) return CHANNEL_RC_BAD_CHANNEL_HANDLE; - for (i = 0; i < dvcman->num_plugins; i++) + ArrayList_Lock(dvcman->plugins); + for (i = 0; i < ArrayList_Count(dvcman->plugins); i++) { - UINT error; - IWTSPlugin* pPlugin = dvcman->plugins[i]; + IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i); - if (pPlugin->Attached) - if ((error = pPlugin->Attached(pPlugin))) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "Attach failed with error %" PRIu32 "!", - error); - return error; - } + error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Attached, pPlugin); + if (error != CHANNEL_RC_OK) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "Attach failed with error %" PRIu32 "!", error); + goto fail; + } } - return CHANNEL_RC_OK; +fail: + ArrayList_Unlock(dvcman->plugins); + return error; } static UINT drdynvc_virtual_channel_event_detached(drdynvcPlugin* drdynvc) { + UINT error = CHANNEL_RC_OK; size_t i; DVCMAN* dvcman; @@ -1601,21 +1642,23 @@ static UINT drdynvc_virtual_channel_event_detached(drdynvcPlugin* drdynvc) if (!dvcman) return CHANNEL_RC_BAD_CHANNEL_HANDLE; - for (i = 0; i < dvcman->num_plugins; i++) + ArrayList_Lock(dvcman->plugins); + for (i = 0; i < ArrayList_Count(dvcman->plugins); i++) { - UINT error; - IWTSPlugin* pPlugin = dvcman->plugins[i]; + IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i); - if (pPlugin->Detached) - if ((error = pPlugin->Detached(pPlugin))) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "Detach failed with error %" PRIu32 "!", - error); - return error; - } + error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Detached, pPlugin); + if (error != CHANNEL_RC_OK) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "Detach failed with error %" PRIu32 "!", error); + goto fail; + } } - return CHANNEL_RC_OK; +fail: + ArrayList_Unlock(dvcman->plugins); + + return error; } static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle, @@ -1633,6 +1676,9 @@ static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam, switch (event) { + case CHANNEL_EVENT_INITIALIZED: + error = drdynvc_virtual_channel_event_initialized(drdynvc, pData, dataLength); + break; case CHANNEL_EVENT_CONNECTED: if ((error = drdynvc_virtual_channel_event_connected(drdynvc, pData, dataLength))) WLog_Print(drdynvc->log, WLOG_ERROR, diff --git a/channels/drdynvc/client/drdynvc_main.h b/channels/drdynvc/client/drdynvc_main.h index f91059988..646c8fdfb 100644 --- a/channels/drdynvc/client/drdynvc_main.h +++ b/channels/drdynvc/client/drdynvc_main.h @@ -37,21 +37,16 @@ typedef struct drdynvc_plugin drdynvcPlugin; -#define MAX_PLUGINS 32 - struct _DVCMAN { IWTSVirtualChannelManager iface; drdynvcPlugin* drdynvc; - size_t num_plugins; - const char* plugin_names[MAX_PLUGINS]; - IWTSPlugin* plugins[MAX_PLUGINS]; - - size_t num_listeners; - IWTSListener* listeners[MAX_PLUGINS]; + wArrayList* plugin_names; + wArrayList* plugins; + wArrayList* listeners; wArrayList* channels; wStreamPool* pool; }; diff --git a/channels/echo/client/echo_main.c b/channels/echo/client/echo_main.c index e830122a7..c8dc4d8a5 100644 --- a/channels/echo/client/echo_main.c +++ b/channels/echo/client/echo_main.c @@ -59,6 +59,7 @@ struct _ECHO_PLUGIN IWTSPlugin iface; ECHO_LISTENER_CALLBACK* listener_callback; + IWTSListener* listener; }; /** @@ -142,8 +143,8 @@ static UINT echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage echo->listener_callback->plugin = pPlugin; echo->listener_callback->channel_mgr = pChannelMgr; - return pChannelMgr->CreateListener(pChannelMgr, "ECHO", 0, - (IWTSListenerCallback*)echo->listener_callback, NULL); + return pChannelMgr->CreateListener(pChannelMgr, "ECHO", 0, &echo->listener_callback->iface, + &echo->listener); } /** @@ -154,7 +155,12 @@ static UINT echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage static UINT echo_plugin_terminated(IWTSPlugin* pPlugin) { ECHO_PLUGIN* echo = (ECHO_PLUGIN*)pPlugin; - + if (echo && echo->listener_callback) + { + IWTSVirtualChannelManager* mgr = echo->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, echo->listener); + } free(echo); return CHANNEL_RC_OK; diff --git a/channels/geometry/client/geometry_main.c b/channels/geometry/client/geometry_main.c index f08b76cf1..eb65b2ca2 100644 --- a/channels/geometry/client/geometry_main.c +++ b/channels/geometry/client/geometry_main.c @@ -410,9 +410,9 @@ static UINT geometry_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMa geometry->listener_callback->iface.OnNewChannelConnection = geometry_on_new_channel_connection; geometry->listener_callback->plugin = pPlugin; geometry->listener_callback->channel_mgr = pChannelMgr; - status = pChannelMgr->CreateListener(pChannelMgr, GEOMETRY_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*)geometry->listener_callback, - &(geometry->listener)); + status = + pChannelMgr->CreateListener(pChannelMgr, GEOMETRY_DVC_CHANNEL_NAME, 0, + &geometry->listener_callback->iface, &(geometry->listener)); geometry->listener->pInterface = geometry->iface.pInterface; return status; } @@ -427,6 +427,13 @@ static UINT geometry_plugin_terminated(IWTSPlugin* pPlugin) GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*)pPlugin; GeometryClientContext* context = (GeometryClientContext*)geometry->iface.pInterface; + if (geometry && geometry->listener_callback) + { + IWTSVirtualChannelManager* mgr = geometry->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, geometry->listener); + } + if (context) HashTable_Free(context->geometries); diff --git a/channels/printer/client/cups/printer_cups.c b/channels/printer/client/cups/printer_cups.c index 8e462c1b1..1f9f07b24 100644 --- a/channels/printer/client/cups/printer_cups.c +++ b/channels/printer/client/cups/printer_cups.c @@ -364,13 +364,15 @@ static void printer_cups_add_ref_driver(rdpPrinterDriver* driver) } /* Singleton */ -static rdpCupsPrinterDriver* cups_driver = NULL; +static rdpCupsPrinterDriver* uniq_cups_driver = NULL; static void printer_cups_release_ref_driver(rdpPrinterDriver* driver) { rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*)driver; if (cups_driver->references <= 1) { + if (uniq_cups_driver == cups_driver) + uniq_cups_driver = NULL; free(cups_driver); cups_driver = NULL; } @@ -384,23 +386,23 @@ rdpPrinterDriver* cups_freerdp_printer_client_subsystem_entry(void) FREERDP_API rdpPrinterDriver* freerdp_printer_client_subsystem_entry(void) #endif { - if (!cups_driver) + if (!uniq_cups_driver) { - cups_driver = (rdpCupsPrinterDriver*)calloc(1, sizeof(rdpCupsPrinterDriver)); + uniq_cups_driver = (rdpCupsPrinterDriver*)calloc(1, sizeof(rdpCupsPrinterDriver)); - if (!cups_driver) + if (!uniq_cups_driver) return NULL; - cups_driver->driver.EnumPrinters = printer_cups_enum_printers; - cups_driver->driver.ReleaseEnumPrinters = printer_cups_release_enum_printers; - cups_driver->driver.GetPrinter = printer_cups_get_printer; + uniq_cups_driver->driver.EnumPrinters = printer_cups_enum_printers; + uniq_cups_driver->driver.ReleaseEnumPrinters = printer_cups_release_enum_printers; + uniq_cups_driver->driver.GetPrinter = printer_cups_get_printer; - cups_driver->driver.AddRef = printer_cups_add_ref_driver; - cups_driver->driver.ReleaseRef = printer_cups_release_ref_driver; + uniq_cups_driver->driver.AddRef = printer_cups_add_ref_driver; + uniq_cups_driver->driver.ReleaseRef = printer_cups_release_ref_driver; - cups_driver->id_sequence = 1; - cups_driver->driver.AddRef(&cups_driver->driver); + uniq_cups_driver->id_sequence = 1; + uniq_cups_driver->driver.AddRef(&uniq_cups_driver->driver); } - return &cups_driver->driver; + return &uniq_cups_driver->driver; } diff --git a/channels/rail/client/rail_orders.c b/channels/rail/client/rail_orders.c index 86a345622..c394a5925 100644 --- a/channels/rail/client/rail_orders.c +++ b/channels/rail/client/rail_orders.c @@ -49,8 +49,7 @@ UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType) rail_write_pdu_header(s, orderType, orderLength); Stream_SetPosition(s, orderLength); WLog_Print(rail->log, WLOG_DEBUG, "Sending %s PDU, length: %" PRIu16 "", - RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], - orderLength); + rail_get_order_type_string(orderType), orderLength); return rail_send_channel_data(rail, s); } @@ -926,8 +925,7 @@ UINT rail_order_recv(railPlugin* rail, wStream* s) } WLog_Print(rail->log, WLOG_DEBUG, "Received %s PDU, length:%" PRIu16 "", - RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], - orderLength); + rail_get_order_type_string(orderType), orderLength); switch (orderType) { diff --git a/channels/rail/rail_common.c b/channels/rail/rail_common.c index 4e1a81df7..902a738c5 100644 --- a/channels/rail/rail_common.c +++ b/channels/rail/rail_common.c @@ -27,29 +27,34 @@ #define TAG CHANNELS_TAG("rail.common") -const char* const RAIL_ORDER_TYPE_STRINGS[] = { "", - "Execute", - "Activate", - "System Parameters Update", - "System Command", - "Handshake", - "Notify Event", - "", - "Window Move", - "Local Move/Size", - "Min Max Info", - "Client Status", - "System Menu", - "Language Bar Info", - "Get Application ID Request", - "Get Application ID Response", - "Execute Result", - "", - "", - "", - "", - "", - "" }; +static const char* const RAIL_ORDER_TYPE_STRINGS[] = { "", + "Execute", + "Activate", + "System Parameters Update", + "System Command", + "Handshake", + "Notify Event", + "", + "Window Move", + "Local Move/Size", + "Min Max Info", + "Client Status", + "System Menu", + "Language Bar Info", + "Get Application ID Request", + "Get Application ID Response", + "Execute Result", + "", + "", + "", + "", + "", + "" }; + +const char* rail_get_order_type_string(BYTE orderType) +{ + return RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)]; +} /** * Function description diff --git a/channels/rail/rail_common.h b/channels/rail/rail_common.h index aa83b8ac4..6d411ebb1 100644 --- a/channels/rail/rail_common.h +++ b/channels/rail/rail_common.h @@ -26,7 +26,7 @@ #include <freerdp/rail.h> -extern const char* const RAIL_ORDER_TYPE_STRINGS[]; +const char* rail_get_order_type_string(BYTE orderType); #define RAIL_PDU_HEADER_LENGTH 4 diff --git a/channels/rail/server/rail_main.c b/channels/rail/server/rail_main.c index 385b0dd9c..18a707242 100644 --- a/channels/rail/server/rail_main.c +++ b/channels/rail/server/rail_main.c @@ -71,8 +71,8 @@ UINT rail_send_pdu(RailServerContext* context, wStream* s, UINT16 orderType) Stream_SetPosition(s, 0); rail_write_pdu_header(s, orderType, orderLength); Stream_SetPosition(s, orderLength); - WLog_DBG(TAG, "Sending %s PDU, length: %" PRIu16 "", - RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength); + WLog_DBG(TAG, "Sending %s PDU, length: %" PRIu16 "", rail_get_order_type_string(orderType), + orderLength); return rail_send(context, s, orderLength); } @@ -1573,8 +1573,8 @@ UINT rail_server_handle_messages(RailServerContext* context) return ERROR_INTERNAL_ERROR; } - WLog_DBG(TAG, "Received %s PDU, length:%" PRIu16 "", - RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength); + WLog_DBG(TAG, "Received %s PDU, length:%" PRIu16 "", rail_get_order_type_string(orderType), + orderLength); switch (orderType) { diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index 7dd65211d..0a0cfefb2 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -571,8 +571,7 @@ static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag rdpei->listener_callback->channel_mgr = pChannelMgr; if ((error = pChannelMgr->CreateListener(pChannelMgr, RDPEI_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*)rdpei->listener_callback, - &(rdpei->listener)))) + &rdpei->listener_callback->iface, &(rdpei->listener)))) { WLog_ERR(TAG, "ChannelMgr->CreateListener failed with error %" PRIu32 "!", error); goto error_out; @@ -598,6 +597,12 @@ static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin) if (!pPlugin) return ERROR_INVALID_PARAMETER; + if (rdpei && rdpei->listener_callback) + { + IWTSVirtualChannelManager* mgr = rdpei->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, rdpei->listener); + } free(rdpei->listener_callback); free(rdpei->context); free(rdpei); diff --git a/channels/rdpei/rdpei_common.c b/channels/rdpei/rdpei_common.c index adf9710d1..f01d4dd78 100644 --- a/channels/rdpei/rdpei_common.c +++ b/channels/rdpei/rdpei_common.c @@ -199,18 +199,18 @@ BOOL rdpei_write_4byte_unsigned(wStream* s, UINT32 value) { BYTE byte; - if (value <= 0x3F) + if (value <= 0x3FUL) { Stream_Write_UINT8(s, value); } - else if (value <= 0x3FFF) + else if (value <= 0x3FFFUL) { byte = (value >> 8) & 0x3F; Stream_Write_UINT8(s, byte | 0x40); byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x3FFFFF) + else if (value <= 0x3FFFFFUL) { byte = (value >> 16) & 0x3F; Stream_Write_UINT8(s, byte | 0x80); @@ -219,7 +219,7 @@ BOOL rdpei_write_4byte_unsigned(wStream* s, UINT32 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x3FFFFF) + else if (value <= 0x3FFFFFFFUL) { byte = (value >> 24) & 0x3F; Stream_Write_UINT8(s, byte | 0xC0); @@ -306,7 +306,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value) value *= -1; } - if (value <= 0x1F) + if (value <= 0x1FUL) { byte = value & 0x1F; @@ -315,7 +315,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value) Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFF) + else if (value <= 0x1FFFUL) { 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 <= 0x1FFFFF) + else if (value <= 0x1FFFFFUL) { 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 <= 0x1FFFFF) + else if (value <= 0x1FFFFFFFUL) { byte = (value >> 24) & 0x1F; @@ -478,12 +478,12 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) { BYTE byte; - if (value <= 0x1F) + if (value <= 0x1FULL) { byte = value & 0x1F; Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFF) + else if (value <= 0x1FFFULL) { byte = (value >> 8) & 0x1F; byte |= (1 << 5); @@ -491,7 +491,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFF) + else if (value <= 0x1FFFFFULL) { byte = (value >> 16) & 0x1F; byte |= (2 << 5); @@ -501,7 +501,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFF) + else if (value <= 0x1FFFFFULL) { byte = (value >> 24) & 0x1F; byte |= (3 << 5); @@ -513,7 +513,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFFF) + else if (value <= 0x1FFFFFFFULL) { byte = (value >> 32) & 0x1F; byte |= (4 << 5); @@ -527,7 +527,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFFFFF) + else if (value <= 0x1FFFFFFFFFULL) { byte = (value >> 40) & 0x1F; byte |= (5 << 5); @@ -543,7 +543,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFFFFFFF) + else if (value <= 0x1FFFFFFFFFFFULL) { byte = (value >> 48) & 0x1F; byte |= (6 << 5); @@ -561,7 +561,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFFFFFFFFF) + else if (value <= 0x1FFFFFFFFFFFFFFFULL) { byte = (value >> 56) & 0x1F; byte |= (7 << 5); diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 7bc25dba9..6ca75bd1d 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -605,7 +605,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wS monitor = &(pdu.monitorDefArray[index]); DEBUG_RDPGFX(gfx->log, "RecvResetGraphicsPdu: monitor left:%" PRIi32 " top:%" PRIi32 " right:%" PRIi32 - " left:%" PRIi32 " flags:0x%" PRIx32 "", + " bottom:%" PRIi32 " flags:0x%" PRIx32 "", monitor->left, monitor->top, monitor->right, monitor->bottom, monitor->flags); } @@ -1826,12 +1826,6 @@ static UINT rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback) free_surfaces(context, gfx->SurfaceTable); evict_cache_slots(context, gfx->MaxCacheSlots, gfx->CacheSlots); - if (gfx->listener_callback) - { - free(gfx->listener_callback); - gfx->listener_callback = NULL; - } - free(callback); gfx->UnacknowledgedFrames = 0; gfx->TotalDecodedFrames = 0; @@ -1896,8 +1890,7 @@ static UINT rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana gfx->listener_callback->plugin = pPlugin; gfx->listener_callback->channel_mgr = pChannelMgr; error = pChannelMgr->CreateListener(pChannelMgr, RDPGFX_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*)gfx->listener_callback, - &(gfx->listener)); + &gfx->listener_callback->iface, &(gfx->listener)); gfx->listener->pInterface = gfx->iface.pInterface; DEBUG_RDPGFX(gfx->log, "Initialize"); return error; @@ -1913,6 +1906,12 @@ static UINT rdpgfx_plugin_terminated(IWTSPlugin* pPlugin) RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)pPlugin; RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; DEBUG_RDPGFX(gfx->log, "Terminated"); + if (gfx && gfx->listener_callback) + { + IWTSVirtualChannelManager* mgr = gfx->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, gfx->listener); + } rdpgfx_client_context_free(context); return CHANNEL_RC_OK; } diff --git a/channels/rdpsnd/client/mac/CMakeLists.txt b/channels/rdpsnd/client/mac/CMakeLists.txt index 19f77e404..8b846561a 100644 --- a/channels/rdpsnd/client/mac/CMakeLists.txt +++ b/channels/rdpsnd/client/mac/CMakeLists.txt @@ -19,6 +19,7 @@ define_channel_client_subsystem("rdpsnd" "mac" "") +find_library(COCOA_LIBRARY Cocoa REQUIRED) FIND_LIBRARY(CORE_FOUNDATION CoreFoundation) FIND_LIBRARY(CORE_AUDIO CoreAudio REQUIRED) FIND_LIBRARY(AUDIO_TOOL AudioToolbox REQUIRED) @@ -38,6 +39,7 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${AUDIO_TOOL} ${AV_FOUNDATION} ${CORE_AUDIO} + ${COCOA_LIBRARY} ${CORE_FOUNDATION}) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp winpr) diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 2526ec55d..9318c95c6 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -1541,8 +1541,7 @@ static UINT rdpsnd_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana rdpsnd->listener_callback->plugin = pPlugin; rdpsnd->listener_callback->channel_mgr = pChannelMgr; status = pChannelMgr->CreateListener(pChannelMgr, RDPSND_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*)rdpsnd->listener_callback, - &(rdpsnd->listener)); + &rdpsnd->listener_callback->iface, &(rdpsnd->listener)); rdpsnd->listener->pInterface = rdpsnd->iface.pInterface; return rdpsnd_virtual_channel_event_initialized(rdpsnd); } @@ -1557,6 +1556,12 @@ static UINT rdpsnd_plugin_terminated(IWTSPlugin* pPlugin) rdpsndPlugin* rdpsnd = (rdpsndPlugin*)pPlugin; if (rdpsnd) { + if (rdpsnd->listener_callback) + { + IWTSVirtualChannelManager* mgr = rdpsnd->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, rdpsnd->listener); + } free(rdpsnd->listener_callback); free(rdpsnd->iface.pInterface); } diff --git a/channels/urbdrc/client/urbdrc_main.c b/channels/urbdrc/client/urbdrc_main.c index 6dbdc5a41..6f383ecb7 100644 --- a/channels/urbdrc/client/urbdrc_main.c +++ b/channels/urbdrc/client/urbdrc_main.c @@ -668,12 +668,13 @@ static UINT urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana { UINT status; URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)pPlugin; - IUDEVMAN* udevman = urbdrc->udevman; + IUDEVMAN* udevman; char channelName[sizeof(URBDRC_CHANNEL_NAME)] = { URBDRC_CHANNEL_NAME }; - if (!urbdrc) + if (!urbdrc || !urbdrc->udevman) return ERROR_INVALID_PARAMETER; + udevman = urbdrc->udevman; urbdrc->listener_callback = (URBDRC_LISTENER_CALLBACK*)calloc(1, sizeof(URBDRC_LISTENER_CALLBACK)); @@ -687,7 +688,7 @@ static UINT urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana /* [MS-RDPEUSB] 2.1 Transport defines the channel name in uppercase letters */ CharUpperA(channelName); status = pChannelMgr->CreateListener(pChannelMgr, channelName, 0, - &urbdrc->listener_callback->iface, NULL); + &urbdrc->listener_callback->iface, &urbdrc->listener); if (status != CHANNEL_RC_OK) return status; @@ -709,7 +710,12 @@ static UINT urbdrc_plugin_terminated(IWTSPlugin* pPlugin) if (!urbdrc) return ERROR_INVALID_DATA; - + if (urbdrc->listener_callback) + { + IWTSVirtualChannelManager* mgr = urbdrc->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, urbdrc->listener); + } udevman = urbdrc->udevman; if (udevman) diff --git a/channels/urbdrc/client/urbdrc_main.h b/channels/urbdrc/client/urbdrc_main.h index 2a750d64d..2b643f7cb 100644 --- a/channels/urbdrc/client/urbdrc_main.h +++ b/channels/urbdrc/client/urbdrc_main.h @@ -84,6 +84,7 @@ struct _URBDRC_PLUGIN char* subsystem; wLog* log; + IWTSListener* listener; }; typedef BOOL (*PREGISTERURBDRCSERVICE)(IWTSPlugin* plugin, IUDEVMAN* udevman); diff --git a/channels/video/client/video_main.c b/channels/video/client/video_main.c index 1efadb399..9a68d92d3 100644 --- a/channels/video/client/video_main.c +++ b/channels/video/client/video_main.c @@ -1048,7 +1048,7 @@ static UINT video_plugin_initialize(IWTSPlugin* plugin, IWTSVirtualChannelManage callback->channel_mgr = channelMgr; status = channelMgr->CreateListener(channelMgr, VIDEO_CONTROL_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*)callback, &(video->controlListener)); + &callback->iface, &(video->controlListener)); if (status != CHANNEL_RC_OK) return status; @@ -1067,7 +1067,7 @@ static UINT video_plugin_initialize(IWTSPlugin* plugin, IWTSVirtualChannelManage callback->channel_mgr = channelMgr; status = channelMgr->CreateListener(channelMgr, VIDEO_DATA_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*)callback, &(video->dataListener)); + &callback->iface, &(video->dataListener)); if (status == CHANNEL_RC_OK) video->dataListener->pInterface = video->wtsPlugin.pInterface; @@ -1084,6 +1084,19 @@ static UINT video_plugin_terminated(IWTSPlugin* pPlugin) { VIDEO_PLUGIN* video = (VIDEO_PLUGIN*)pPlugin; + if (video->control_callback) + { + IWTSVirtualChannelManager* mgr = video->control_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, video->controlListener); + } + if (video->data_callback) + { + IWTSVirtualChannelManager* mgr = video->data_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, video->dataListener); + } + if (video->context) VideoClientContextPriv_free(video->context->priv); diff --git a/client/Android/Studio/build.gradle b/client/Android/Studio/build.gradle index e944b11d3..319280d5e 100644 --- a/client/Android/Studio/build.gradle +++ b/client/Android/Studio/build.gradle @@ -29,7 +29,7 @@ def getVersionName = { -> ext { versionName = properties.get('VERSION_NAME', getVersionName()) - versionCode = properties.get('VERSION_CODE', 16) + versionCode = properties.get('VERSION_CODE', 17) println '----------------- Project configuration -------------------' println 'VERSION_NAME: ' + versionName diff --git a/client/Android/android_freerdp.c b/client/Android/android_freerdp.c index 7d332c731..0b0f27b09 100644 --- a/client/Android/android_freerdp.c +++ b/client/Android/android_freerdp.c @@ -56,7 +56,7 @@ #define TAG CLIENT_TAG("android") /* Defines the JNI version supported by this library. */ -#define FREERDP_JNI_VERSION "2.1.0" +#define FREERDP_JNI_VERSION "2.1.1" static void android_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e) { diff --git a/client/Sample/tf_freerdp.c b/client/Sample/tf_freerdp.c index 4340f1d30..3ba82c783 100644 --- a/client/Sample/tf_freerdp.c +++ b/client/Sample/tf_freerdp.c @@ -342,7 +342,10 @@ int main(int argc, char* argv[]) freerdp_client_settings_command_line_status_print(context->settings, status, argc, argv); if (status) - return 0; + { + rc = 0; + goto fail; + } if (freerdp_client_start(context) != 0) goto fail; diff --git a/client/Windows/wf_client.c b/client/Windows/wf_client.c index 19bca36c9..11667258a 100644 --- a/client/Windows/wf_client.c +++ b/client/Windows/wf_client.c @@ -438,6 +438,8 @@ static BOOL wf_authenticate_raw(freerdp* instance, const char* title, char** use fSave = FALSE; dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES; + if (username && *username) + strncpy(UserName, *username, CREDUI_MAX_USERNAME_LENGTH); if (wfc->isConsole) status = CredUICmdLinePromptForCredentialsA( title, NULL, 0, UserName, CREDUI_MAX_USERNAME_LENGTH + 1, Password, diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 84cd60341..146c7feea 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -223,8 +223,15 @@ BOOL xf_picture_transform_required(xfContext* xfc) } #endif /* WITH_XRENDER defined */ -void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h) +void xf_draw_screen_(xfContext* xfc, int x, int y, int w, int h, const char* fkt, const char* file, + int line) { + if (!xfc) + { + WLog_DBG(TAG, "[%s] called from [%s] xfc=%p", __FUNCTION__, fkt, xfc); + return; + } + if (w == 0 || h == 0) { WLog_WARN(TAG, "invalid width and/or height specified: w=%d h=%d", w, h); diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index 5f4f8297d..e7a889efc 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -185,7 +185,8 @@ BOOL xf_event_action_script_init(xfContext* xfc) while (fgets(buffer, sizeof(buffer), actionScript)) { - strtok(buffer, "\n"); + char* context = NULL; + strtok_s(buffer, "\n", &context); xevent = _strdup(buffer); if (!xevent || ArrayList_Add(xfc->xevents, xevent) < 0) @@ -253,7 +254,8 @@ static BOOL xf_event_execute_action_script(xfContext* xfc, const XEvent* event) while (fgets(buffer, sizeof(buffer), actionScript)) { - strtok(buffer, "\n"); + char* context = NULL; + strtok_s(buffer, "\n", &context); } pclose(actionScript); diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c index 50b259308..794acea0c 100644 --- a/client/X11/xf_keyboard.c +++ b/client/X11/xf_keyboard.c @@ -74,7 +74,8 @@ static BOOL xf_keyboard_action_script_init(xfContext* xfc) while (fgets(buffer, sizeof(buffer), keyScript) != NULL) { - strtok(buffer, "\n"); + char* context = NULL; + strtok_s(buffer, "\n", &context); keyCombination = _strdup(buffer); if (!keyCombination || ArrayList_Add(xfc->keyCombinations, keyCombination) < 0) @@ -433,7 +434,8 @@ static int xf_keyboard_execute_action_script(xfContext* xfc, XF_MODIFIER_KEYS* m while (fgets(buffer, sizeof(buffer), keyScript) != NULL) { - strtok(buffer, "\n"); + char* context = NULL; + strtok_s(buffer, "\n", &context); if (strcmp(buffer, "key-local") == 0) status = 0; diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 3ad3ddc6a..8599d56ec 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -307,7 +307,11 @@ void xf_lock_x11_(xfContext* xfc, const char* fkt); void xf_unlock_x11_(xfContext* xfc, const char* fkt); BOOL xf_picture_transform_required(xfContext* xfc); -void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h); + +#define xf_draw_screen(_xfc, _x, _y, _w, _h) \ + xf_draw_screen_((_xfc), (_x), (_y), (_w), (_h), __FUNCTION__, __FILE__, __LINE__) +void xf_draw_screen_(xfContext* xfc, int x, int y, int w, int h, const char* fkt, const char* file, + int line); FREERDP_API DWORD xf_exit_code_from_disconnect_reason(DWORD reason); diff --git a/client/common/cmdline.c b/client/common/cmdline.c index cdea23de0..bad661987 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -3500,8 +3500,9 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) BOOL success; const char* name = NULL; const char* drive = tok; - char* start = strtok(tok, "("); - char* end = strtok(NULL, ")"); + char* subcontext = NULL; + char* start = strtok_s(tok, "(", &subcontext); + char* end = strtok_s(NULL, ")", &subcontext); if (start && end) name = end; diff --git a/client/common/file.c b/client/common/file.c index 7cac1acab..b9ded2631 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -203,6 +203,7 @@ struct rdp_file DWORD flags; }; +static void freerdp_client_file_string_check_free(LPSTR str); /* * Set an integer in a rdpFile * @@ -841,15 +842,16 @@ BOOL freerdp_client_parse_rdp_file_ex(rdpFile* file, const char* name, rdp_file_ return status; } -#define FILE_POPULATE_STRING(_target, _setting) \ - do \ - { \ - if (_setting) \ - { \ - _target = _strdup(_setting); \ - if (!_target) \ - return FALSE; \ - } \ +#define FILE_POPULATE_STRING(_target, _setting) \ + do \ + { \ + if (_setting) \ + { \ + freerdp_client_file_string_check_free(_target); \ + _target = _strdup(_setting); \ + if (!_target) \ + return FALSE; \ + } \ } while (0) BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSettings* settings) diff --git a/config.h.in b/config.h.in index c2e20d356..cf8f3f601 100644 --- a/config.h.in +++ b/config.h.in @@ -26,7 +26,6 @@ #cmakedefine HAVE_EXECINFO_H /* Features */ -#cmakedefine HAVE_ALIGNED_REQUIRED #cmakedefine SWRESAMPLE_FOUND #cmakedefine AVRESAMPLE_FOUND diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c index 118e09b35..083f1aa97 100644 --- a/libfreerdp/codec/clear.c +++ b/libfreerdp/codec/clear.c @@ -783,7 +783,7 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 if (vBarUpdate) { UINT32 x; - BYTE* pSrcPixel; + BYTE* pSrcPixel = NULL; BYTE* dstBuffer; if (clear->VBarStorageCursor >= CLEARCODEC_VBAR_SIZE) @@ -826,8 +826,9 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 if ((y + count) > vBarPixelCount) count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0; - pSrcPixel = - &vBarShortEntry->pixels[(y - vBarYOn) * GetBytesPerPixel(clear->format)]; + if (count > 0) + pSrcPixel = + &vBarShortEntry->pixels[(y - vBarYOn) * GetBytesPerPixel(clear->format)]; for (x = 0; x < count; x++) { diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index 784937a49..e9f92c700 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -272,11 +272,7 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix) #define WHITE_PIXEL 0xFFFF #define DESTWRITEPIXEL(_buf, _pix) write_pixel_16(_buf, _pix) #define DESTREADPIXEL(_pix, _buf) _pix = ((UINT16*)(_buf))[0] -#ifdef HAVE_ALIGNED_REQUIRED #define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) -#else -#define SRCREADPIXEL(_pix, _buf) _pix = ((UINT16*)(_buf))[0] -#endif #define DESTNEXTPIXEL(_buf) _buf += 2 #define SRCNEXTPIXEL(_buf) _buf += 2 #define WRITEFGBGIMAGE WriteFgBgImage16to16 diff --git a/libfreerdp/codec/mppc.c b/libfreerdp/codec/mppc.c index cdad24863..217fae41d 100644 --- a/libfreerdp/codec/mppc.c +++ b/libfreerdp/codec/mppc.c @@ -772,11 +772,15 @@ void mppc_context_reset(MPPC_CONTEXT* mppc, BOOL flush) ZeroMemory(&(mppc->MatchBuffer), sizeof(mppc->MatchBuffer)); if (flush) + { mppc->HistoryOffset = mppc->HistoryBufferSize + 1; + mppc->HistoryPtr = mppc->HistoryBuffer; + } else + { mppc->HistoryOffset = 0; - mppc->HistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryOffset]); + } } MPPC_CONTEXT* mppc_context_new(DWORD CompressionLevel, BOOL Compressor) diff --git a/libfreerdp/codec/ncrush.c b/libfreerdp/codec/ncrush.c index af503fc7c..3d6a216d3 100644 --- a/libfreerdp/codec/ncrush.c +++ b/libfreerdp/codec/ncrush.c @@ -1926,9 +1926,9 @@ static INLINE UINT16 get_word(const BYTE* data) static INLINE UINT32 get_dword(const BYTE* data) { UINT32 tmp = *data++; - tmp |= *data++ << 8U; - tmp |= *data++ << 16U; - tmp |= *data++ << 24U; + tmp |= (UINT32)*data++ << 8U; + tmp |= (UINT32)*data++ << 16U; + tmp |= (UINT32)*data++ << 24U; return tmp; } diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c index 6c0755217..6627e0b63 100644 --- a/libfreerdp/codec/nsc.c +++ b/libfreerdp/codec/nsc.c @@ -113,14 +113,12 @@ static BOOL nsc_decode(NSC_CONTEXT* context) static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalSize) { - UINT32 len; - UINT32 left; - BYTE value; - left = originalSize; + UINT32 left = originalSize; while (left > 4) { - value = *in++; + const BYTE value = *in++; + UINT32 len = 0; if (left == 5) { @@ -143,8 +141,10 @@ static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalS else { in++; - len = *((UINT32*)in); - in += 4; + len = ((UINT32)(*in++)); + len |= ((UINT32)(*in++)) << 8U; + len |= ((UINT32)(*in++)) << 16U; + len |= ((UINT32)(*in++)) << 24U; } if (outSize < len) diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index b4b1a4cd2..2a0861678 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -1170,7 +1170,6 @@ BYTE* freerdp_bitmap_planar_delta_encode_plane(const BYTE* inPlane, UINT32 width BYTE* outPlane) { char s2c; - INT32 delta; UINT32 y, x; BYTE* outPtr; const BYTE *srcPtr, *prevLinePtr; @@ -1194,9 +1193,9 @@ BYTE* freerdp_bitmap_planar_delta_encode_plane(const BYTE* inPlane, UINT32 width { for (x = 0; x < width; x++, outPtr++, srcPtr++, prevLinePtr++) { - delta = *srcPtr - *prevLinePtr; + INT32 delta = *srcPtr - *prevLinePtr; s2c = (delta >= 0) ? (char)delta : (char)(~((BYTE)(-delta)) + 1); - s2c = (s2c >= 0) ? (s2c << 1) : (char)(((~((BYTE)s2c) + 1) << 1) - 1); + s2c = (s2c >= 0) ? ((UINT32)s2c << 1) : (char)(((UINT32)(~((BYTE)s2c) + 1) << 1) - 1); *outPtr = (BYTE)s2c; } } diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index bfa2dc5da..e2660b19f 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -1183,7 +1183,7 @@ static INLINE int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* s sign[index] = input; } - buffer[index] += (input << shift); + buffer[index] += (INT16)((UINT32)input << shift); } return 1; @@ -1995,7 +1995,7 @@ static INLINE INT32 progressive_wb_read_region_header(PROGRESSIVE_CONTEXT* progr len -= region->tileDataSize; if (len > 0) WLog_Print(progressive->log, WLOG_DEBUG, - "Unused byes detected, %" PRIuz " bytes not processed", len); + "Unused bytes detected, %" PRIuz " bytes not processed", len); return 0; } diff --git a/libfreerdp/codec/rfx_dwt.c b/libfreerdp/codec/rfx_dwt.c index a72d63f4c..4c727cda7 100644 --- a/libfreerdp/codec/rfx_dwt.c +++ b/libfreerdp/codec/rfx_dwt.c @@ -87,26 +87,27 @@ void rfx_dwt_2d_decode_block(INT16* buffer, INT16* idwt, int subband_width) /* Inverse DWT in vertical direction, results are stored in original buffer. */ for (x = 0; x < total_width; x++) { - /* Even coefficients */ - for (n = 0; n < subband_width; n++) - { - y = n << 1; - dst = buffer + y * total_width + x; - l = idwt + n * total_width + x; - h = l + subband_width * total_width; - dst[0] = *l - (((n > 0 ? *(h - total_width) : *h) + (*h) + 1) >> 1); - } + l = idwt + x; + h = idwt + x + subband_width * total_width; + dst = buffer + x; - /* Odd coefficients */ - for (n = 0; n < subband_width; n++) + *dst = *l - ((*h * 2 + 1) >> 1); + + for (n = 1; n < subband_width; n++) { - y = n << 1; - dst = buffer + y * total_width + x; - l = idwt + n * total_width + x; - h = l + subband_width * total_width; - dst[total_width] = - (*h << 1) + ((dst[0] + dst[n < subband_width - 1 ? 2 * total_width : 0]) >> 1); + l += total_width; + h += total_width; + + /* Even coefficients */ + dst[2 * total_width] = *l - ((*(h - total_width) + *h + 1) >> 1); + + /* Odd coefficients */ + dst[total_width] = (*(h - total_width) << 1) + ((*dst + dst[2 * total_width]) >> 1); + + dst += 2 * total_width; } + + dst[total_width] = (*h << 1) + ((*dst * 2) >> 1); } } diff --git a/libfreerdp/codec/rfx_rlgr.c b/libfreerdp/codec/rfx_rlgr.c index 655739244..a0d2c95a7 100644 --- a/libfreerdp/codec/rfx_rlgr.c +++ b/libfreerdp/codec/rfx_rlgr.c @@ -282,7 +282,10 @@ int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* pSrcData, UINT32 SrcSize, INT16* break; bs->mask = ((1 << kr) - 1); - code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask); + if (kr > 0) + code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask); + else + code = 0; BitStream_Shift(bs, kr); /* add (vk << kr) to code */ @@ -390,7 +393,10 @@ int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* pSrcData, UINT32 SrcSize, INT16* break; bs->mask = ((1 << kr) - 1); - code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask); + if (kr > 0) + code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask); + else + code = 0; BitStream_Shift(bs, kr); /* add (vk << kr) to code */ @@ -477,7 +483,10 @@ int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* pSrcData, UINT32 SrcSize, INT16* break; bs->mask = ((1 << nIdx) - 1); - val1 = ((bs->accumulator >> (32 - nIdx)) & bs->mask); + if (nIdx > 0) + val1 = ((bs->accumulator >> (32 - nIdx)) & bs->mask); + else + val1 = 0; BitStream_Shift(bs, nIdx); val2 = code - val1; diff --git a/libfreerdp/common/settings_getters.c b/libfreerdp/common/settings_getters.c index 9ea65070b..2e49b8923 100644 --- a/libfreerdp/common/settings_getters.c +++ b/libfreerdp/common/settings_getters.c @@ -2358,7 +2358,7 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id) } } -BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id, const char* val) +BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char* val, BOOL cleanup) { if (!settings) return FALSE; @@ -2366,332 +2366,398 @@ BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id, const char* v switch (id) { case FreeRDP_AcceptedCert: - free(settings->AcceptedCert); + if (cleanup) + free(settings->AcceptedCert); settings->AcceptedCert = (val ? _strdup(val) : NULL); return (!val || settings->AcceptedCert != NULL); case FreeRDP_AllowedTlsCiphers: - free(settings->AllowedTlsCiphers); + if (cleanup) + free(settings->AllowedTlsCiphers); settings->AllowedTlsCiphers = (val ? _strdup(val) : NULL); return (!val || settings->AllowedTlsCiphers != NULL); case FreeRDP_AlternateShell: - free(settings->AlternateShell); + if (cleanup) + free(settings->AlternateShell); settings->AlternateShell = (val ? _strdup(val) : NULL); return (!val || settings->AlternateShell != NULL); case FreeRDP_AssistanceFile: - free(settings->AssistanceFile); + if (cleanup) + free(settings->AssistanceFile); settings->AssistanceFile = (val ? _strdup(val) : NULL); return (!val || settings->AssistanceFile != NULL); case FreeRDP_AuthenticationServiceClass: - free(settings->AuthenticationServiceClass); + if (cleanup) + free(settings->AuthenticationServiceClass); settings->AuthenticationServiceClass = (val ? _strdup(val) : NULL); return (!val || settings->AuthenticationServiceClass != NULL); case FreeRDP_CertificateAcceptedFingerprints: - free(settings->CertificateAcceptedFingerprints); + if (cleanup) + free(settings->CertificateAcceptedFingerprints); settings->CertificateAcceptedFingerprints = (val ? _strdup(val) : NULL); return (!val || settings->CertificateAcceptedFingerprints != NULL); case FreeRDP_CertificateContent: - free(settings->CertificateContent); + if (cleanup) + free(settings->CertificateContent); settings->CertificateContent = (val ? _strdup(val) : NULL); return (!val || settings->CertificateContent != NULL); case FreeRDP_CertificateFile: - free(settings->CertificateFile); + if (cleanup) + free(settings->CertificateFile); settings->CertificateFile = (val ? _strdup(val) : NULL); return (!val || settings->CertificateFile != NULL); case FreeRDP_CertificateName: - free(settings->CertificateName); + if (cleanup) + free(settings->CertificateName); settings->CertificateName = (val ? _strdup(val) : NULL); return (!val || settings->CertificateName != NULL); case FreeRDP_ClientAddress: - free(settings->ClientAddress); + if (cleanup) + free(settings->ClientAddress); settings->ClientAddress = (val ? _strdup(val) : NULL); return (!val || settings->ClientAddress != NULL); case FreeRDP_ClientDir: - free(settings->ClientDir); + if (cleanup) + free(settings->ClientDir); settings->ClientDir = (val ? _strdup(val) : NULL); return (!val || settings->ClientDir != NULL); case FreeRDP_ClientHostname: - free(settings->ClientHostname); + if (cleanup) + free(settings->ClientHostname); settings->ClientHostname = (val ? _strdup(val) : NULL); return (!val || settings->ClientHostname != NULL); case FreeRDP_ClientProductId: - free(settings->ClientProductId); + if (cleanup) + free(settings->ClientProductId); settings->ClientProductId = (val ? _strdup(val) : NULL); return (!val || settings->ClientProductId != NULL); case FreeRDP_ComputerName: - free(settings->ComputerName); + if (cleanup) + free(settings->ComputerName); settings->ComputerName = (val ? _strdup(val) : NULL); return (!val || settings->ComputerName != NULL); case FreeRDP_ConfigPath: - free(settings->ConfigPath); + if (cleanup) + free(settings->ConfigPath); settings->ConfigPath = (val ? _strdup(val) : NULL); return (!val || settings->ConfigPath != NULL); case FreeRDP_ConnectionFile: - free(settings->ConnectionFile); + if (cleanup) + free(settings->ConnectionFile); settings->ConnectionFile = (val ? _strdup(val) : NULL); return (!val || settings->ConnectionFile != NULL); case FreeRDP_CurrentPath: - free(settings->CurrentPath); + if (cleanup) + free(settings->CurrentPath); settings->CurrentPath = (val ? _strdup(val) : NULL); return (!val || settings->CurrentPath != NULL); case FreeRDP_Domain: - free(settings->Domain); + if (cleanup) + free(settings->Domain); settings->Domain = (val ? _strdup(val) : NULL); return (!val || settings->Domain != NULL); case FreeRDP_DrivesToRedirect: - free(settings->DrivesToRedirect); + if (cleanup) + free(settings->DrivesToRedirect); settings->DrivesToRedirect = (val ? _strdup(val) : NULL); return (!val || settings->DrivesToRedirect != NULL); case FreeRDP_DumpRemoteFxFile: - free(settings->DumpRemoteFxFile); + if (cleanup) + free(settings->DumpRemoteFxFile); settings->DumpRemoteFxFile = (val ? _strdup(val) : NULL); return (!val || settings->DumpRemoteFxFile != NULL); case FreeRDP_DynamicDSTTimeZoneKeyName: - free(settings->DynamicDSTTimeZoneKeyName); + if (cleanup) + free(settings->DynamicDSTTimeZoneKeyName); settings->DynamicDSTTimeZoneKeyName = (val ? _strdup(val) : NULL); return (!val || settings->DynamicDSTTimeZoneKeyName != NULL); case FreeRDP_GatewayAcceptedCert: - free(settings->GatewayAcceptedCert); + if (cleanup) + free(settings->GatewayAcceptedCert); settings->GatewayAcceptedCert = (val ? _strdup(val) : NULL); return (!val || settings->GatewayAcceptedCert != NULL); case FreeRDP_GatewayAccessToken: - free(settings->GatewayAccessToken); + if (cleanup) + free(settings->GatewayAccessToken); settings->GatewayAccessToken = (val ? _strdup(val) : NULL); return (!val || settings->GatewayAccessToken != NULL); case FreeRDP_GatewayDomain: - free(settings->GatewayDomain); + if (cleanup) + free(settings->GatewayDomain); settings->GatewayDomain = (val ? _strdup(val) : NULL); return (!val || settings->GatewayDomain != NULL); case FreeRDP_GatewayHostname: - free(settings->GatewayHostname); + if (cleanup) + free(settings->GatewayHostname); settings->GatewayHostname = (val ? _strdup(val) : NULL); return (!val || settings->GatewayHostname != NULL); case FreeRDP_GatewayPassword: - free(settings->GatewayPassword); + if (cleanup) + free(settings->GatewayPassword); settings->GatewayPassword = (val ? _strdup(val) : NULL); return (!val || settings->GatewayPassword != NULL); case FreeRDP_GatewayUsername: - free(settings->GatewayUsername); + if (cleanup) + free(settings->GatewayUsername); settings->GatewayUsername = (val ? _strdup(val) : NULL); return (!val || settings->GatewayUsername != NULL); case FreeRDP_HomePath: - free(settings->HomePath); + if (cleanup) + free(settings->HomePath); settings->HomePath = (val ? _strdup(val) : NULL); return (!val || settings->HomePath != NULL); case FreeRDP_ImeFileName: - free(settings->ImeFileName); + if (cleanup) + free(settings->ImeFileName); settings->ImeFileName = (val ? _strdup(val) : NULL); return (!val || settings->ImeFileName != NULL); case FreeRDP_KerberosKdc: - free(settings->KerberosKdc); + if (cleanup) + free(settings->KerberosKdc); settings->KerberosKdc = (val ? _strdup(val) : NULL); return (!val || settings->KerberosKdc != NULL); case FreeRDP_KerberosRealm: - free(settings->KerberosRealm); + if (cleanup) + free(settings->KerberosRealm); settings->KerberosRealm = (val ? _strdup(val) : NULL); return (!val || settings->KerberosRealm != NULL); case FreeRDP_NtlmSamFile: - free(settings->NtlmSamFile); + if (cleanup) + free(settings->NtlmSamFile); settings->NtlmSamFile = (val ? _strdup(val) : NULL); return (!val || settings->NtlmSamFile != NULL); case FreeRDP_Password: - free(settings->Password); + if (cleanup) + free(settings->Password); settings->Password = (val ? _strdup(val) : NULL); return (!val || settings->Password != NULL); case FreeRDP_PasswordHash: - free(settings->PasswordHash); + if (cleanup) + free(settings->PasswordHash); settings->PasswordHash = (val ? _strdup(val) : NULL); return (!val || settings->PasswordHash != NULL); case FreeRDP_PlayRemoteFxFile: - free(settings->PlayRemoteFxFile); + if (cleanup) + free(settings->PlayRemoteFxFile); settings->PlayRemoteFxFile = (val ? _strdup(val) : NULL); return (!val || settings->PlayRemoteFxFile != NULL); case FreeRDP_PreconnectionBlob: - free(settings->PreconnectionBlob); + if (cleanup) + free(settings->PreconnectionBlob); settings->PreconnectionBlob = (val ? _strdup(val) : NULL); return (!val || settings->PreconnectionBlob != NULL); case FreeRDP_PrivateKeyContent: - free(settings->PrivateKeyContent); + if (cleanup) + free(settings->PrivateKeyContent); settings->PrivateKeyContent = (val ? _strdup(val) : NULL); return (!val || settings->PrivateKeyContent != NULL); case FreeRDP_PrivateKeyFile: - free(settings->PrivateKeyFile); + if (cleanup) + free(settings->PrivateKeyFile); settings->PrivateKeyFile = (val ? _strdup(val) : NULL); return (!val || settings->PrivateKeyFile != NULL); case FreeRDP_ProxyHostname: - free(settings->ProxyHostname); + if (cleanup) + free(settings->ProxyHostname); settings->ProxyHostname = (val ? _strdup(val) : NULL); return (!val || settings->ProxyHostname != NULL); case FreeRDP_ProxyPassword: - free(settings->ProxyPassword); + if (cleanup) + free(settings->ProxyPassword); settings->ProxyPassword = (val ? _strdup(val) : NULL); return (!val || settings->ProxyPassword != NULL); case FreeRDP_ProxyUsername: - free(settings->ProxyUsername); + if (cleanup) + free(settings->ProxyUsername); settings->ProxyUsername = (val ? _strdup(val) : NULL); return (!val || settings->ProxyUsername != NULL); case FreeRDP_RDP2TCPArgs: - free(settings->RDP2TCPArgs); + if (cleanup) + free(settings->RDP2TCPArgs); settings->RDP2TCPArgs = (val ? _strdup(val) : NULL); return (!val || settings->RDP2TCPArgs != NULL); case FreeRDP_RdpKeyContent: - free(settings->RdpKeyContent); + if (cleanup) + free(settings->RdpKeyContent); settings->RdpKeyContent = (val ? _strdup(val) : NULL); return (!val || settings->RdpKeyContent != NULL); case FreeRDP_RdpKeyFile: - free(settings->RdpKeyFile); + if (cleanup) + free(settings->RdpKeyFile); settings->RdpKeyFile = (val ? _strdup(val) : NULL); return (!val || settings->RdpKeyFile != NULL); case FreeRDP_RedirectionAcceptedCert: - free(settings->RedirectionAcceptedCert); + if (cleanup) + free(settings->RedirectionAcceptedCert); settings->RedirectionAcceptedCert = (val ? _strdup(val) : NULL); return (!val || settings->RedirectionAcceptedCert != NULL); case FreeRDP_RedirectionDomain: - free(settings->RedirectionDomain); + if (cleanup) + free(settings->RedirectionDomain); settings->RedirectionDomain = (val ? _strdup(val) : NULL); return (!val || settings->RedirectionDomain != NULL); case FreeRDP_RedirectionTargetFQDN: - free(settings->RedirectionTargetFQDN); + if (cleanup) + free(settings->RedirectionTargetFQDN); settings->RedirectionTargetFQDN = (val ? _strdup(val) : NULL); return (!val || settings->RedirectionTargetFQDN != NULL); case FreeRDP_RedirectionTargetNetBiosName: - free(settings->RedirectionTargetNetBiosName); + if (cleanup) + free(settings->RedirectionTargetNetBiosName); settings->RedirectionTargetNetBiosName = (val ? _strdup(val) : NULL); return (!val || settings->RedirectionTargetNetBiosName != NULL); case FreeRDP_RedirectionUsername: - free(settings->RedirectionUsername); + if (cleanup) + free(settings->RedirectionUsername); settings->RedirectionUsername = (val ? _strdup(val) : NULL); return (!val || settings->RedirectionUsername != NULL); case FreeRDP_RemoteApplicationCmdLine: - free(settings->RemoteApplicationCmdLine); + if (cleanup) + free(settings->RemoteApplicationCmdLine); settings->RemoteApplicationCmdLine = (val ? _strdup(val) : NULL); return (!val || settings->RemoteApplicationCmdLine != NULL); case FreeRDP_RemoteApplicationFile: - free(settings->RemoteApplicationFile); + if (cleanup) + free(settings->RemoteApplicationFile); settings->RemoteApplicationFile = (val ? _strdup(val) : NULL); return (!val || settings->RemoteApplicationFile != NULL); case FreeRDP_RemoteApplicationGuid: - free(settings->RemoteApplicationGuid); + if (cleanup) + free(settings->RemoteApplicationGuid); settings->RemoteApplicationGuid = (val ? _strdup(val) : NULL); return (!val || settings->RemoteApplicationGuid != NULL); case FreeRDP_RemoteApplicationIcon: - free(settings->RemoteApplicationIcon); + if (cleanup) + free(settings->RemoteApplicationIcon); settings->RemoteApplicationIcon = (val ? _strdup(val) : NULL); return (!val || settings->RemoteApplicationIcon != NULL); case FreeRDP_RemoteApplicationName: - free(settings->RemoteApplicationName); + if (cleanup) + free(settings->RemoteApplicationName); settings->RemoteApplicationName = (val ? _strdup(val) : NULL); return (!val || settings->RemoteApplicationName != NULL); case FreeRDP_RemoteApplicationProgram: - free(settings->RemoteApplicationProgram); + if (cleanup) + free(settings->RemoteApplicationProgram); settings->RemoteApplicationProgram = (val ? _strdup(val) : NULL); return (!val || settings->RemoteApplicationProgram != NULL); case FreeRDP_RemoteApplicationWorkingDir: - free(settings->RemoteApplicationWorkingDir); + if (cleanup) + free(settings->RemoteApplicationWorkingDir); settings->RemoteApplicationWorkingDir = (val ? _strdup(val) : NULL); return (!val || settings->RemoteApplicationWorkingDir != NULL); case FreeRDP_RemoteAssistancePassStub: - free(settings->RemoteAssistancePassStub); + if (cleanup) + free(settings->RemoteAssistancePassStub); settings->RemoteAssistancePassStub = (val ? _strdup(val) : NULL); return (!val || settings->RemoteAssistancePassStub != NULL); case FreeRDP_RemoteAssistancePassword: - free(settings->RemoteAssistancePassword); + if (cleanup) + free(settings->RemoteAssistancePassword); settings->RemoteAssistancePassword = (val ? _strdup(val) : NULL); return (!val || settings->RemoteAssistancePassword != NULL); case FreeRDP_RemoteAssistanceRCTicket: - free(settings->RemoteAssistanceRCTicket); + if (cleanup) + free(settings->RemoteAssistanceRCTicket); settings->RemoteAssistanceRCTicket = (val ? _strdup(val) : NULL); return (!val || settings->RemoteAssistanceRCTicket != NULL); case FreeRDP_RemoteAssistanceSessionId: - free(settings->RemoteAssistanceSessionId); + if (cleanup) + free(settings->RemoteAssistanceSessionId); settings->RemoteAssistanceSessionId = (val ? _strdup(val) : NULL); return (!val || settings->RemoteAssistanceSessionId != NULL); case FreeRDP_ServerHostname: - free(settings->ServerHostname); + if (cleanup) + free(settings->ServerHostname); settings->ServerHostname = (val ? _strdup(val) : NULL); return (!val || settings->ServerHostname != NULL); case FreeRDP_ShellWorkingDirectory: - free(settings->ShellWorkingDirectory); + if (cleanup) + free(settings->ShellWorkingDirectory); settings->ShellWorkingDirectory = (val ? _strdup(val) : NULL); return (!val || settings->ShellWorkingDirectory != NULL); case FreeRDP_TargetNetAddress: - free(settings->TargetNetAddress); + if (cleanup) + free(settings->TargetNetAddress); settings->TargetNetAddress = (val ? _strdup(val) : NULL); return (!val || settings->TargetNetAddress != NULL); case FreeRDP_Username: - free(settings->Username); + if (cleanup) + free(settings->Username); settings->Username = (val ? _strdup(val) : NULL); return (!val || settings->Username != NULL); case FreeRDP_WindowTitle: - free(settings->WindowTitle); + if (cleanup) + free(settings->WindowTitle); settings->WindowTitle = (val ? _strdup(val) : NULL); return (!val || settings->WindowTitle != NULL); case FreeRDP_WmClass: - free(settings->WmClass); + if (cleanup) + free(settings->WmClass); settings->WmClass = (val ? _strdup(val) : NULL); return (!val || settings->WmClass != NULL); @@ -2702,6 +2768,11 @@ BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id, const char* v return TRUE; } +BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id, const char* val) +{ + return freerdp_settings_set_string_(settings, id, val, TRUE); +} + const void* freerdp_settings_get_pointer(const rdpSettings* settings, size_t id) { if (!settings) @@ -2792,3 +2863,121 @@ const void* freerdp_settings_get_pointer(const rdpSettings* settings, size_t id) return FALSE; } } + +BOOL freerdp_settings_set_pointer(rdpSettings* settings, size_t id, const void* val) +{ + if (!settings) + return FALSE; + + switch (id) + { + case FreeRDP_BitmapCacheV2CellInfo: + settings->BitmapCacheV2CellInfo = (void*)val; + break; + + case FreeRDP_ChannelDefArray: + settings->ChannelDefArray = (void*)val; + break; + + case FreeRDP_ClientAutoReconnectCookie: + settings->ClientAutoReconnectCookie = (void*)val; + break; + + case FreeRDP_ClientRandom: + settings->ClientRandom = (void*)val; + break; + + case FreeRDP_ClientTimeZone: + settings->ClientTimeZone = (void*)val; + break; + + case FreeRDP_DeviceArray: + settings->DeviceArray = (void*)val; + break; + + case FreeRDP_DynamicChannelArray: + settings->DynamicChannelArray = (void*)val; + break; + + case FreeRDP_FragCache: + settings->FragCache = (void*)val; + break; + + case FreeRDP_GlyphCache: + settings->GlyphCache = (void*)val; + break; + + case FreeRDP_LoadBalanceInfo: + settings->LoadBalanceInfo = (void*)val; + break; + + case FreeRDP_MonitorDefArray: + settings->MonitorDefArray = (void*)val; + break; + + case FreeRDP_MonitorIds: + settings->MonitorIds = (void*)val; + break; + + case FreeRDP_OrderSupport: + settings->OrderSupport = (void*)val; + break; + + case FreeRDP_Password51: + settings->Password51 = (void*)val; + break; + + case FreeRDP_RdpServerCertificate: + settings->RdpServerCertificate = (void*)val; + break; + + case FreeRDP_RdpServerRsaKey: + settings->RdpServerRsaKey = (void*)val; + break; + + case FreeRDP_ReceivedCapabilities: + settings->ReceivedCapabilities = (void*)val; + break; + + case FreeRDP_RedirectionPassword: + settings->RedirectionPassword = (void*)val; + break; + + case FreeRDP_RedirectionTsvUrl: + settings->RedirectionTsvUrl = (void*)val; + break; + + case FreeRDP_ServerAutoReconnectCookie: + settings->ServerAutoReconnectCookie = (void*)val; + break; + + case FreeRDP_ServerCertificate: + settings->ServerCertificate = (void*)val; + break; + + case FreeRDP_ServerRandom: + settings->ServerRandom = (void*)val; + break; + + case FreeRDP_StaticChannelArray: + settings->StaticChannelArray = (void*)val; + break; + + case FreeRDP_TargetNetAddresses: + settings->TargetNetAddresses = (void*)val; + break; + + case FreeRDP_TargetNetPorts: + settings->TargetNetPorts = (void*)val; + break; + + case FreeRDP_instance: + settings->instance = (void*)val; + break; + + default: + WLog_ERR(TAG, "[%s] Invalid key index %" PRIuz, __FUNCTION__, id); + return FALSE; + } + return TRUE; +} diff --git a/libfreerdp/common/settings_str.c b/libfreerdp/common/settings_str.c index 8ba0b38ae..699c94b2d 100644 --- a/libfreerdp/common/settings_str.c +++ b/libfreerdp/common/settings_str.c @@ -3,6 +3,8 @@ #include <freerdp/settings.h> #include <freerdp/log.h> +#include "../core/settings.h" + #define TAG FREERDP_TAG("common.settings") struct settings_str_entry @@ -385,6 +387,100 @@ static const struct settings_str_entry settings_map[] = { { FreeRDP_instance, 8, "FreeRDP_instance" }, }; +BOOL freerdp_settings_clone_keys(rdpSettings* dst, const rdpSettings* src) +{ + size_t x; + for (x = 0; x < ARRAYSIZE(settings_map); x++) + { + const struct settings_str_entry* cur = &settings_map[x]; + switch (cur->type) + { + case 0: /* bool */ + { + BOOL sval = freerdp_settings_get_bool(src, cur->id); + if (!freerdp_settings_set_bool(dst, cur->id, sval)) + return FALSE; + } + break; + case 1: /* UINT16 */ + { + UINT16 sval = freerdp_settings_get_uint16(src, cur->id); + if (!freerdp_settings_set_uint16(dst, cur->id, sval)) + return FALSE; + } + break; + case 2: /* INT16 */ + { + INT16 sval = freerdp_settings_get_int16(src, cur->id); + if (!freerdp_settings_set_int16(dst, cur->id, sval)) + return FALSE; + } + break; + case 3: /* UINT32 */ + { + UINT32 sval = freerdp_settings_get_uint32(src, cur->id); + if (!freerdp_settings_set_uint32(dst, cur->id, sval)) + return FALSE; + } + break; + case 4: /* INT32 */ + { + INT32 sval = freerdp_settings_get_int32(src, cur->id); + if (!freerdp_settings_set_int32(dst, cur->id, sval)) + return FALSE; + } + break; + case 5: /* UINT64 */ + { + UINT64 sval = freerdp_settings_get_uint64(src, cur->id); + if (!freerdp_settings_set_uint64(dst, cur->id, sval)) + return FALSE; + } + break; + case 6: /* INT64 */ + { + INT64 sval = freerdp_settings_get_int64(src, cur->id); + if (!freerdp_settings_set_int64(dst, cur->id, sval)) + return FALSE; + } + break; + case 7: /* strings */ + { + const char* sval = freerdp_settings_get_string(src, cur->id); + if (!freerdp_settings_set_string_(dst, cur->id, sval, FALSE)) + return FALSE; + } + break; + case 8: /* pointer */ + { + const void* sval = freerdp_settings_get_pointer(src, cur->id); + if (!freerdp_settings_set_pointer(dst, cur->id, sval)) + return FALSE; + } + break; + } + } + return TRUE; +} + +void freerdp_settings_free_keys(rdpSettings* dst, BOOL cleanup) +{ + size_t x; + for (x = 0; x < ARRAYSIZE(settings_map); x++) + { + const struct settings_str_entry* cur = &settings_map[x]; + switch (cur->type) + { + case 7: /* strings */ + freerdp_settings_set_string_(dst, cur->id, NULL, cleanup); + break; + case 8: /* pointer */ + freerdp_settings_set_pointer(dst, cur->id, NULL); + break; + } + } +} + SSIZE_T freerdp_settings_get_key_for_name(const char* value) { size_t x; diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index 31a1f9af3..d91f9078f 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -2702,9 +2702,9 @@ static BOOL rdp_read_bitmap_codec_guid(wStream* s, GUID* guid) if (Stream_GetRemainingLength(s) < 16) return FALSE; Stream_Read(s, g, 16); - guid->Data1 = (g[3] << 24) | (g[2] << 16) | (g[1] << 8) | g[0]; - guid->Data2 = (g[5] << 8) | g[4]; - guid->Data3 = (g[7] << 8) | g[6]; + guid->Data1 = ((UINT32)g[3] << 24U) | ((UINT32)g[2] << 16U) | (g[1] << 8U) | g[0]; + guid->Data2 = (g[5] << 8U) | g[4]; + guid->Data3 = (g[7] << 8U) | g[6]; guid->Data4[0] = g[8]; guid->Data4[1] = g[9]; guid->Data4[2] = g[10]; diff --git a/libfreerdp/core/gateway/http.c b/libfreerdp/core/gateway/http.c index 8d13e8907..848101099 100644 --- a/libfreerdp/core/gateway/http.c +++ b/libfreerdp/core/gateway/http.c @@ -814,6 +814,7 @@ HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength) size_t count = 0; char* buffer = (char*)Stream_Buffer(response->data); char* line = (char*)Stream_Buffer(response->data); + char* context = NULL; while ((line = string_strnstr(line, "\r\n", payloadOffset - (line - buffer) - 2UL))) { @@ -834,12 +835,12 @@ HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength) buffer[payloadOffset - 1] = '\0'; buffer[payloadOffset - 2] = '\0'; count = 0; - line = strtok(buffer, "\r\n"); + line = strtok_s(buffer, "\r\n", &context); while (line && (response->count > count)) { response->lines[count] = line; - line = strtok(NULL, "\r\n"); + line = strtok_s(NULL, "\r\n", &context); count++; } diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c index 91f851f15..7537f18dd 100644 --- a/libfreerdp/core/gateway/tsg.c +++ b/libfreerdp/core/gateway/tsg.c @@ -781,7 +781,7 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu, Stream_Read_UINT32(pdu->s, Pointer); /* TsgCapsPtr (4 bytes) */ Stream_Read_UINT32(pdu->s, versionCaps->numCapabilities); /* NumCapabilities (4 bytes) */ Stream_Read_UINT16(pdu->s, versionCaps->majorVersion); /* MajorVersion (2 bytes) */ - Stream_Read_UINT16(pdu->s, versionCaps->majorVersion); /* MinorVersion (2 bytes) */ + Stream_Read_UINT16(pdu->s, versionCaps->minorVersion); /* MinorVersion (2 bytes) */ Stream_Read_UINT16( pdu->s, versionCaps->quarantineCapabilities); /* QuarantineCapabilities (2 bytes) */ diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index 843693e01..7fd96b934 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -67,6 +67,54 @@ static struct { INFO_HIDEF_RAIL_SUPPORTED, "INFO_HIDEF_RAIL_SUPPORTED" }, }; +static BOOL rdp_read_info_null_string(UINT32 flags, wStream* s, size_t cbLen, CHAR** dst, + size_t max) +{ + CHAR* ret = NULL; + + const BOOL unicode = flags & INFO_UNICODE; + const size_t nullSize = unicode ? sizeof(WCHAR) : sizeof(CHAR); + + if (Stream_GetRemainingLength(s) < (size_t)(cbLen)) + return FALSE; + + if (cbLen > 0) + { + WCHAR domain[512 / sizeof(WCHAR) + sizeof(WCHAR)] = { 0 }; + /* cbDomain is the size in bytes of the character data in the Domain field. + * This size excludes (!) the length of the mandatory null terminator. + * Maximum value including the mandatory null terminator: 512 + */ + if ((cbLen % 2) || (cbLen > (max - nullSize))) + { + WLog_ERR(TAG, "protocol error: invalid value: %" PRIuz "", cbLen); + return FALSE; + } + + Stream_Read(s, domain, cbLen); + + if (unicode) + { + if (ConvertFromUnicode(CP_UTF8, 0, domain, cbLen, &ret, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert Domain string"); + return FALSE; + } + } + else + { + ret = calloc(cbLen + 1, nullSize); + if (!ret) + return FALSE; + memcpy(ret, domain, cbLen); + } + } + + free(*dst); + *dst = ret; + return TRUE; +} + static char* rdp_info_package_flags_description(UINT32 flags) { char* result; @@ -245,10 +293,6 @@ static BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s) UINT16 cbClientDir; UINT16 cbAutoReconnectLen; rdpSettings* settings = rdp->settings; - union { - BYTE* bp; - WCHAR* wp; - } ptrconv; if (Stream_GetRemainingLength(s) < 4) return FALSE; @@ -275,32 +319,9 @@ static BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s) if (Stream_GetRemainingLength(s) < cbClientAddress) return FALSE; - if (settings->ClientAddress) - { - free(settings->ClientAddress); - settings->ClientAddress = NULL; - } - - if (cbClientAddress) - { - ptrconv.bp = Stream_Pointer(s); - - if (ptrconv.wp[cbClientAddress / 2 - 1]) - { - WLog_ERR(TAG, "protocol error: clientAddress must be null terminated"); - return FALSE; - } - - if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->ClientAddress, 0, NULL, - NULL) < 1) - { - WLog_ERR(TAG, "failed to convert client address"); - return FALSE; - } - - Stream_Seek(s, cbClientAddress); - WLog_DBG(TAG, "rdp client address: [%s]", settings->ClientAddress); - } + if (!rdp_read_info_null_string(INFO_UNICODE, s, cbClientAddress, &settings->ClientAddress, + (settings->RdpVersion < RDP_VERSION_10_0) ? 64 : 80)) + return FALSE; if (Stream_GetRemainingLength(s) < 2) return FALSE; @@ -315,41 +336,9 @@ static BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s) * sets cbClientDir to 0. */ - if ((cbClientDir % 2) || cbClientDir > 512) - { - WLog_ERR(TAG, "protocol error: invalid cbClientDir value: %" PRIu16 "", cbClientDir); - return FALSE; - } - - if (Stream_GetRemainingLength(s) < cbClientDir) + if (!rdp_read_info_null_string(INFO_UNICODE, s, cbClientDir, &settings->ClientDir, 512)) return FALSE; - if (settings->ClientDir) - { - free(settings->ClientDir); - settings->ClientDir = NULL; - } - - if (cbClientDir) - { - ptrconv.bp = Stream_Pointer(s); - - if (ptrconv.wp[cbClientDir / 2 - 1]) - { - WLog_ERR(TAG, "protocol error: clientDir must be null terminated"); - return FALSE; - } - - if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->ClientDir, 0, NULL, NULL) < 1) - { - WLog_ERR(TAG, "failed to convert client directory"); - return FALSE; - } - - Stream_Seek(s, cbClientDir); - WLog_DBG(TAG, "rdp client dir: [%s]", settings->ClientDir); - } - /** * down below all fields are optional but if one field is not present, * then all of the subsequent fields also MUST NOT be present. @@ -474,6 +463,68 @@ fail: return ret; } +static BOOL rdp_read_info_string(UINT32 flags, wStream* s, size_t cbLenNonNull, CHAR** dst, + size_t max) +{ + union { + char c; + WCHAR w; + BYTE b[2]; + } terminator; + CHAR* ret = NULL; + + const BOOL unicode = flags & INFO_UNICODE; + const size_t nullSize = unicode ? sizeof(WCHAR) : sizeof(CHAR); + + if (Stream_GetRemainingLength(s) < (size_t)(cbLenNonNull + nullSize)) + return FALSE; + + if (cbLenNonNull > 0) + { + WCHAR domain[512 / sizeof(WCHAR) + sizeof(WCHAR)] = { 0 }; + /* cbDomain is the size in bytes of the character data in the Domain field. + * This size excludes (!) the length of the mandatory null terminator. + * Maximum value including the mandatory null terminator: 512 + */ + if ((cbLenNonNull % 2) || (cbLenNonNull > (max - nullSize))) + { + WLog_ERR(TAG, "protocol error: invalid value: %" PRIuz "", cbLenNonNull); + return FALSE; + } + + Stream_Read(s, domain, cbLenNonNull); + + if (unicode) + { + if (ConvertFromUnicode(CP_UTF8, 0, domain, cbLenNonNull, &ret, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert Domain string"); + return FALSE; + } + } + else + { + ret = calloc(cbLenNonNull + 1, nullSize); + if (!ret) + return FALSE; + memcpy(ret, domain, cbLenNonNull); + } + } + + terminator.w = L'\0'; + Stream_Read(s, terminator.b, nullSize); + + if (terminator.w != L'\0') + { + WLog_ERR(TAG, "protocol error: Domain must be null terminated"); + free(ret); + return FALSE; + } + + *dst = ret; + return TRUE; +} + /** * Read Info Packet (TS_INFO_PACKET).\n * @msdn{cc240475} @@ -483,6 +534,7 @@ fail: static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s, UINT16 tpktlength) { + BOOL smallsize = FALSE; UINT32 flags; UINT16 cbDomain; UINT16 cbUserName; @@ -491,16 +543,12 @@ static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s, UINT16 tpktlength) UINT16 cbWorkingDir; UINT32 CompressionLevel; rdpSettings* settings = rdp->settings; - union { - BYTE* bp; - WCHAR* wp; - } ptrconv; if (Stream_GetRemainingLength(s) < 18) return FALSE; Stream_Read_UINT32(s, settings->KeyboardCodePage); /* CodePage (4 bytes ) */ - Stream_Read_UINT32(s, flags); /* flags (4 bytes) */ + Stream_Read_UINT32(s, flags); /* flags (4 bytes) */ settings->AudioCapture = ((flags & INFO_AUDIOCAPTURE) ? TRUE : FALSE); settings->AudioPlayback = ((flags & INFO_NOAUDIOPLAYBACK) ? FALSE : TRUE); settings->AutoLogonEnabled = ((flags & INFO_AUTOLOGON) ? TRUE : FALSE); @@ -520,11 +568,9 @@ static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s, UINT16 tpktlength) settings->CompressionLevel = CompressionLevel; } - if (!(flags & INFO_UNICODE)) - { - WLog_ERR(TAG, "Client without INFO_UNICODE flag: this is currently not supported"); - return FALSE; - } + /* RDP 4 and 5 have smaller credential limits */ + if (settings->RdpVersion < RDP_VERSION_5_PLUS) + smallsize = TRUE; Stream_Read_UINT16(s, cbDomain); /* cbDomain (2 bytes) */ Stream_Read_UINT16(s, cbUserName); /* cbUserName (2 bytes) */ @@ -532,179 +578,21 @@ static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s, UINT16 tpktlength) Stream_Read_UINT16(s, cbAlternateShell); /* cbAlternateShell (2 bytes) */ Stream_Read_UINT16(s, cbWorkingDir); /* cbWorkingDir (2 bytes) */ - if (Stream_GetRemainingLength(s) < (size_t)(cbDomain + 2)) + if (!rdp_read_info_string(flags, s, cbDomain, &settings->Domain, smallsize ? 52 : 512)) return FALSE; - if (cbDomain > 0) - { - /* cbDomain is the size in bytes of the character data in the Domain field. - * This size excludes (!) the length of the mandatory null terminator. - * Maximum value including the mandatory null terminator: 512 - */ - if ((cbDomain % 2) || cbDomain > 512) - { - WLog_ERR(TAG, "protocol error: invalid cbDomain value: %" PRIu16 "", cbDomain); - return FALSE; - } - - ptrconv.bp = Stream_Pointer(s); - - if (ptrconv.wp[cbDomain / 2]) - { - WLog_ERR(TAG, "protocol error: Domain must be null terminated"); - return FALSE; - } - - if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->Domain, 0, NULL, NULL) < 1) - { - WLog_ERR(TAG, "failed to convert Domain string"); - return FALSE; - } - - Stream_Seek(s, cbDomain); - } - - Stream_Seek(s, 2); - - if (Stream_GetRemainingLength(s) < (size_t)(cbUserName + 2)) + if (!rdp_read_info_string(flags, s, cbUserName, &settings->Username, smallsize ? 44 : 512)) return FALSE; - if (cbUserName > 0) - { - /* cbUserName is the size in bytes of the character data in the UserName field. - * This size excludes (!) the length of the mandatory null terminator. - * Maximum value including the mandatory null terminator: 512 - */ - if ((cbUserName % 2) || cbUserName > 512) - { - WLog_ERR(TAG, "protocol error: invalid cbUserName value: %" PRIu16 "", cbUserName); - return FALSE; - } - - ptrconv.bp = Stream_Pointer(s); - - if (ptrconv.wp[cbUserName / 2]) - { - WLog_ERR(TAG, "protocol error: UserName must be null terminated"); - return FALSE; - } - - if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->Username, 0, NULL, NULL) < 1) - { - WLog_ERR(TAG, "failed to convert UserName string"); - return FALSE; - } - - Stream_Seek(s, cbUserName); - } - - Stream_Seek(s, 2); - - if (Stream_GetRemainingLength(s) < (size_t)(cbPassword + 2)) + if (!rdp_read_info_string(flags, s, cbPassword, &settings->Password, smallsize ? 32 : 512)) return FALSE; - if (cbPassword > 0) - { - /* cbPassword is the size in bytes of the character data in the Password field. - * This size excludes (!) the length of the mandatory null terminator. - * Maximum value including the mandatory null terminator: 512 - */ - if ((cbPassword % 2) || cbPassword > LB_PASSWORD_MAX_LENGTH) - { - WLog_ERR(TAG, "protocol error: invalid cbPassword value: %" PRIu16 "", cbPassword); - return FALSE; - } - - ptrconv.bp = Stream_Pointer(s); - - if (ptrconv.wp[cbPassword / 2]) - { - WLog_ERR(TAG, "protocol error: Password must be null terminated"); - return FALSE; - } - - if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->Password, 0, NULL, NULL) < 1) - { - WLog_ERR(TAG, "failed to convert Password string"); - return FALSE; - } - - Stream_Seek(s, cbPassword); - } - - Stream_Seek(s, 2); - - if (Stream_GetRemainingLength(s) < (size_t)(cbAlternateShell + 2)) + if (!rdp_read_info_string(flags, s, cbAlternateShell, &settings->AlternateShell, 512)) return FALSE; - if (cbAlternateShell > 0) - { - /* cbAlternateShell is the size in bytes of the character data in the AlternateShell field. - * This size excludes (!) the length of the mandatory null terminator. - * Maximum value including the mandatory null terminator: 512 - */ - if ((cbAlternateShell % 2) || cbAlternateShell > 512) - { - WLog_ERR(TAG, "protocol error: invalid cbAlternateShell value: %" PRIu16 "", - cbAlternateShell); - return FALSE; - } - - ptrconv.bp = Stream_Pointer(s); - - if (ptrconv.wp[cbAlternateShell / 2]) - { - WLog_ERR(TAG, "protocol error: AlternateShell must be null terminated"); - return FALSE; - } - - if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->AlternateShell, 0, NULL, - NULL) < 1) - { - WLog_ERR(TAG, "failed to convert AlternateShell string"); - return FALSE; - } - - Stream_Seek(s, cbAlternateShell); - } - - Stream_Seek(s, 2); - - if (Stream_GetRemainingLength(s) < (size_t)(cbWorkingDir + 2)) + if (!rdp_read_info_string(flags, s, cbWorkingDir, &settings->ShellWorkingDirectory, 512)) return FALSE; - if (cbWorkingDir > 0) - { - /* cbWorkingDir is the size in bytes of the character data in the WorkingDir field. - * This size excludes (!) the length of the mandatory null terminator. - * Maximum value including the mandatory null terminator: 512 - */ - if ((cbWorkingDir % 2) || cbWorkingDir > 512) - { - WLog_ERR(TAG, "protocol error: invalid cbWorkingDir value: %" PRIu16 "", cbWorkingDir); - return FALSE; - } - - ptrconv.bp = Stream_Pointer(s); - - if (ptrconv.wp[cbWorkingDir / 2]) - { - WLog_ERR(TAG, "protocol error: WorkingDir must be null terminated"); - return FALSE; - } - - if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->ShellWorkingDirectory, 0, - NULL, NULL) < 1) - { - WLog_ERR(TAG, "failed to convert AlternateShell string"); - return FALSE; - } - - Stream_Seek(s, cbWorkingDir); - } - - Stream_Seek(s, 2); - if (settings->RdpVersion >= RDP_VERSION_5_PLUS) return rdp_read_extended_info_packet(rdp, s); /* extraInfo */ @@ -909,12 +797,12 @@ static BOOL rdp_write_info_packet(rdpRdp* rdp, wStream* s) /* excludes (!) the length of the mandatory null terminator */ cbWorkingDir = cbWorkingDir >= 2 ? cbWorkingDir - 2 : cbWorkingDir; Stream_Write_UINT32(s, settings->KeyboardCodePage); /* CodePage (4 bytes) */ - Stream_Write_UINT32(s, flags); /* flags (4 bytes) */ - Stream_Write_UINT16(s, cbDomain); /* cbDomain (2 bytes) */ - Stream_Write_UINT16(s, cbUserName); /* cbUserName (2 bytes) */ - Stream_Write_UINT16(s, cbPassword); /* cbPassword (2 bytes) */ - Stream_Write_UINT16(s, cbAlternateShell); /* cbAlternateShell (2 bytes) */ - Stream_Write_UINT16(s, cbWorkingDir); /* cbWorkingDir (2 bytes) */ + Stream_Write_UINT32(s, flags); /* flags (4 bytes) */ + Stream_Write_UINT16(s, cbDomain); /* cbDomain (2 bytes) */ + Stream_Write_UINT16(s, cbUserName); /* cbUserName (2 bytes) */ + Stream_Write_UINT16(s, cbPassword); /* cbPassword (2 bytes) */ + Stream_Write_UINT16(s, cbAlternateShell); /* cbAlternateShell (2 bytes) */ + Stream_Write_UINT16(s, cbWorkingDir); /* cbWorkingDir (2 bytes) */ Stream_Write(s, domainW, cbDomain); @@ -1115,10 +1003,6 @@ static BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info* info) UINT32 Size; UINT32 cbDomain; UINT32 cbUserName; - union { - BYTE* bp; - WCHAR* wp; - } ptrconv; WINPR_UNUSED(rdp); ZeroMemory(info, sizeof(*info)); @@ -1141,7 +1025,8 @@ static BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info* info) */ if (cbDomain) { - if ((cbDomain % 2) || cbDomain > 52) + WCHAR domain[26] = { 0 }; + if ((cbDomain % 2) || (cbDomain > 52)) { WLog_ERR(TAG, "protocol error: invalid cbDomain value: %" PRIu32 "", cbDomain); goto fail; @@ -1153,23 +1038,22 @@ static BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info* info) goto fail; } - ptrconv.bp = Stream_Pointer(s); + memcpy(domain, Stream_Pointer(s), cbDomain); + Stream_Seek(s, cbDomain); /* domain */ - if (ptrconv.wp[cbDomain / 2 - 1]) + if (domain[cbDomain / sizeof(WCHAR) - 1]) { WLog_ERR(TAG, "protocol error: Domain field must be null terminated"); goto fail; } - if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &info->domain, 0, NULL, FALSE) < 1) + if (ConvertFromUnicode(CP_UTF8, 0, domain, -1, &info->domain, 0, NULL, FALSE) < 1) { WLog_ERR(TAG, "failed to convert the Domain string"); goto fail; } } - Stream_Seek(s, cbDomain); /* domain */ - /* cbUserName is the size in bytes of the Unicode character data in the UserName field. * The size of the mandatory null terminator is include in this value. * Note: Since MS-RDPBCGR 2.2.10.1.1.2 does not mention any size limits we assume @@ -1178,6 +1062,8 @@ static BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info* info) */ if (cbUserName) { + WCHAR user[256] = { 0 }; + if ((cbUserName % 2) || cbUserName < 2 || cbUserName > 512) { WLog_ERR(TAG, "protocol error: invalid cbUserName value: %" PRIu32 "", cbUserName); @@ -1190,22 +1076,22 @@ static BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info* info) goto fail; } - ptrconv.bp = Stream_Pointer(s); + memcpy(user, Stream_Pointer(s), cbUserName); + Stream_Seek(s, cbUserName); /* userName */ - if (ptrconv.wp[cbUserName / 2 - 1]) + if (user[cbUserName / sizeof(WCHAR) - 1]) { WLog_ERR(TAG, "protocol error: UserName field must be null terminated"); goto fail; } - if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &info->username, 0, NULL, FALSE) < 1) + if (ConvertFromUnicode(CP_UTF8, 0, user, -1, &info->username, 0, NULL, FALSE) < 1) { WLog_ERR(TAG, "failed to convert the Domain string"); goto fail; } } - Stream_Seek(s, cbUserName); /* userName */ WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%08" PRIX32 " UserName: [%s] Domain: [%s]", info->sessionId, info->username, info->domain); return TRUE; diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c index 03efc839a..63d77abf9 100644 --- a/libfreerdp/core/nla.c +++ b/libfreerdp/core/nla.c @@ -1144,6 +1144,7 @@ SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla) const BOOL ntlm = (_tcsncmp(nla->packageName, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0); public_key_length = nla->PublicKey.cbBuffer; + sspi_SecBufferFree(&nla->pubKeyAuth); if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, public_key_length + nla->ContextSizes.cbSecurityTrailer)) return SEC_E_INSUFFICIENT_MEMORY; @@ -1212,6 +1213,7 @@ SECURITY_STATUS nla_encrypt_public_key_hash(rdpNla* nla) const size_t hashSize = nla->server ? sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic); + sspi_SecBufferFree(&nla->pubKeyAuth); if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, auth_data_length)) { status = SEC_E_INSUFFICIENT_MEMORY; @@ -2069,6 +2071,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s) return -1; } + sspi_SecBufferFree(&nla->negoToken); if (!sspi_SecBufferAlloc(&nla->negoToken, length)) return -1; @@ -2097,6 +2100,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s) Stream_GetRemainingLength(s) < length) return -1; + sspi_SecBufferFree(&nla->pubKeyAuth); if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length)) return -1; @@ -2121,6 +2125,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s) Stream_GetRemainingLength(s) < length) return -1; + sspi_SecBufferFree(&nla->ClientNonce); if (!sspi_SecBufferAlloc(&nla->ClientNonce, length)) return -1; @@ -2357,10 +2362,6 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting nla->sendSeqNum = 0; nla->recvSeqNum = 0; nla->version = 6; - ZeroMemory(&nla->ClientNonce, sizeof(SecBuffer)); - ZeroMemory(&nla->negoToken, sizeof(SecBuffer)); - ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer)); - ZeroMemory(&nla->authInfo, sizeof(SecBuffer)); SecInvalidateHandle(&nla->context); if (settings->NtlmSamFile) @@ -2465,6 +2466,7 @@ void nla_free(rdpNla* nla) sspi_SecBufferFree(&nla->tsCredentials); free(nla->ServicePrincipalName); nla_identity_free(nla->identity); + nla_buffer_free(nla); free(nla); } diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index bac9dc113..e053bd480 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -2548,7 +2548,7 @@ 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)) + if (iBitmapFormat >= ARRAYSIZE(BMF_BPP)) goto fail; cache_brush->bpp = BMF_BPP[iBitmapFormat]; diff --git a/libfreerdp/core/proxy.c b/libfreerdp/core/proxy.c index 634dfaabd..a50b7ed47 100644 --- a/libfreerdp/core/proxy.c +++ b/libfreerdp/core/proxy.c @@ -144,6 +144,7 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy) BOOL result = FALSE; char* current; char* copy; + char* context = NULL; size_t host_len; struct sockaddr_in sa4; struct sockaddr_in6 sa6; @@ -164,7 +165,7 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy) if (!copy) return FALSE; - current = strtok(copy, delimiter); + current = strtok_s(copy, delimiter, &context); while (current && !result) { @@ -243,7 +244,7 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy) } } - current = strtok(NULL, delimiter); + current = strtok_s(NULL, delimiter, &context); } free(copy); diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index b9c60c74e..fd771ae3e 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -1751,6 +1751,7 @@ rdpRdp* rdp_new(rdpContext* context) if (!rdp) return NULL; + InitializeCriticalSection(&rdp->critical); rdp->context = context; rdp->instance = context->instance; flags = 0; @@ -1763,7 +1764,7 @@ rdpRdp* rdp_new(rdpContext* context) context->settings = freerdp_settings_new(flags); if (!context->settings) - goto out_free; + goto fail; newSettings = TRUE; } @@ -1784,93 +1785,67 @@ rdpRdp* rdp_new(rdpContext* context) rdp->transport = transport_new(context); if (!rdp->transport) - goto out_free_settings; + goto fail; rdp->license = license_new(rdp); if (!rdp->license) - goto out_free_transport; + goto fail; rdp->input = input_new(rdp); if (!rdp->input) - goto out_free_license; + goto fail; rdp->update = update_new(rdp); if (!rdp->update) - goto out_free_input; + goto fail; rdp->fastpath = fastpath_new(rdp); if (!rdp->fastpath) - goto out_free_update; + goto fail; rdp->nego = nego_new(rdp->transport); if (!rdp->nego) - goto out_free_fastpath; + goto fail; rdp->mcs = mcs_new(rdp->transport); if (!rdp->mcs) - goto out_free_nego; + goto fail; rdp->redirection = redirection_new(); if (!rdp->redirection) - goto out_free_mcs; + goto fail; rdp->autodetect = autodetect_new(); if (!rdp->autodetect) - goto out_free_redirection; + goto fail; rdp->heartbeat = heartbeat_new(); if (!rdp->heartbeat) - goto out_free_autodetect; + goto fail; rdp->multitransport = multitransport_new(); if (!rdp->multitransport) - goto out_free_heartbeat; + goto fail; rdp->bulk = bulk_new(context); if (!rdp->bulk) - goto out_free_multitransport; + goto fail; return rdp; -out_free_multitransport: - multitransport_free(rdp->multitransport); -out_free_heartbeat: - heartbeat_free(rdp->heartbeat); -out_free_autodetect: - autodetect_free(rdp->autodetect); -out_free_redirection: - redirection_free(rdp->redirection); -out_free_mcs: - mcs_free(rdp->mcs); -out_free_nego: - nego_free(rdp->nego); -out_free_fastpath: - fastpath_free(rdp->fastpath); -out_free_update: - update_free(rdp->update); -out_free_input: - input_free(rdp->input); -out_free_license: - license_free(rdp->license); -out_free_transport: - transport_free(rdp->transport); -out_free_settings: - if (newSettings) - freerdp_settings_free(rdp->settings); - -out_free: - free(rdp); +fail: + rdp_free(rdp); return NULL; } @@ -1950,6 +1925,7 @@ void rdp_free(rdpRdp* rdp) { if (rdp) { + DeleteCriticalSection(&rdp->critical); winpr_RC4_Free(rdp->rc4_decrypt_key); winpr_RC4_Free(rdp->rc4_encrypt_key); winpr_Cipher_Free(rdp->fips_encrypt); diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index e728ea357..47281d611 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -179,6 +179,7 @@ struct rdp_rdp UINT64 inPackets; UINT64 outBytes; UINT64 outPackets; + CRITICAL_SECTION critical; }; FREERDP_LOCAL BOOL rdp_read_security_header(wStream* s, UINT16* flags, UINT16* length); diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index 9ef9b1afd..e6571c36d 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -712,26 +712,31 @@ out: BOOL security_encrypt(BYTE* data, size_t length, rdpRdp* rdp) { + BOOL rc = FALSE; + EnterCriticalSection(&rdp->critical); if (rdp->encrypt_use_count >= 4096) { if (!security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len, rdp)) - return FALSE; + goto fail; winpr_RC4_Free(rdp->rc4_encrypt_key); rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len); if (!rdp->rc4_encrypt_key) - return FALSE; + goto fail; rdp->encrypt_use_count = 0; } if (!winpr_RC4_Update(rdp->rc4_encrypt_key, length, data, data)) - return FALSE; + goto fail; rdp->encrypt_use_count++; rdp->encrypt_checksum_use_count++; - return TRUE; + rc = TRUE; +fail: + LeaveCriticalSection(&rdp->critical); + return rc; } BOOL security_decrypt(BYTE* data, size_t length, rdpRdp* rdp) @@ -793,19 +798,27 @@ out: BOOL security_fips_encrypt(BYTE* data, size_t length, rdpRdp* rdp) { + BOOL rc = FALSE; size_t olen; + EnterCriticalSection(&rdp->critical); if (!winpr_Cipher_Update(rdp->fips_encrypt, data, length, data, &olen)) - return FALSE; + goto fail; rdp->encrypt_use_count++; - return TRUE; + rc = TRUE; +fail: + LeaveCriticalSection(&rdp->critical); + return rc; } BOOL security_fips_decrypt(BYTE* data, size_t length, rdpRdp* rdp) { size_t olen; + if (!rdp || !rdp->fips_decrypt) + return FALSE; + if (!winpr_Cipher_Update(rdp->fips_decrypt, data, length, data, &olen)) return FALSE; diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index 15481641b..25d2390c0 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -40,6 +40,8 @@ #include <freerdp/build-config.h> #include <ctype.h> +#include "settings.h" + #ifdef _WIN32 #pragma warning(push) #pragma warning(disable : 4244) @@ -626,39 +628,15 @@ out_fail: static void freerdp_settings_free_internal(rdpSettings* settings) { - free(settings->ServerHostname); - free(settings->Username); - free(settings->Password); - free(settings->Domain); - free(settings->PasswordHash); - free(settings->AcceptedCert); - free(settings->AlternateShell); - free(settings->ShellWorkingDirectory); - free(settings->ComputerName); free(settings->ChannelDefArray); free(settings->MonitorDefArray); free(settings->MonitorIds); - free(settings->ClientAddress); - free(settings->ClientDir); - free(settings->AllowedTlsCiphers); - free(settings->NtlmSamFile); - free(settings->CertificateFile); - free(settings->PrivateKeyFile); - free(settings->ConnectionFile); - free(settings->AssistanceFile); free(settings->ReceivedCapabilities); free(settings->OrderSupport); - free(settings->ClientHostname); - free(settings->ClientProductId); free(settings->ServerRandom); free(settings->ClientRandom); free(settings->ServerCertificate); - free(settings->RdpKeyFile); certificate_free(settings->RdpServerCertificate); - free(settings->CertificateContent); - free(settings->PrivateKeyContent); - free(settings->RdpKeyContent); - free(settings->CertificateAcceptedFingerprints); free(settings->ClientAutoReconnectCookie); free(settings->ServerAutoReconnectCookie); free(settings->ClientTimeZone); @@ -666,52 +644,21 @@ static void freerdp_settings_free_internal(rdpSettings* settings) free(settings->GlyphCache); free(settings->FragCache); key_free(settings->RdpServerRsaKey); - free(settings->ConfigPath); - free(settings->CurrentPath); - free(settings->HomePath); free(settings->LoadBalanceInfo); - free(settings->TargetNetAddress); - free(settings->RedirectionTargetFQDN); - free(settings->RedirectionTargetNetBiosName); - free(settings->RedirectionUsername); - free(settings->RedirectionDomain); free(settings->RedirectionPassword); free(settings->RedirectionTsvUrl); - free(settings->RedirectionAcceptedCert); - free(settings->RemoteAssistanceSessionId); - free(settings->RemoteAssistancePassword); - free(settings->RemoteAssistancePassStub); - free(settings->RemoteAssistanceRCTicket); - free(settings->AuthenticationServiceClass); - free(settings->GatewayHostname); - free(settings->GatewayUsername); - free(settings->GatewayPassword); - free(settings->GatewayDomain); - free(settings->GatewayAccessToken); - free(settings->GatewayAcceptedCert); - free(settings->CertificateName); - free(settings->DynamicDSTTimeZoneKeyName); - free(settings->PreconnectionBlob); - free(settings->KerberosKdc); - free(settings->KerberosRealm); - free(settings->DumpRemoteFxFile); - free(settings->PlayRemoteFxFile); - free(settings->RemoteApplicationName); - free(settings->RemoteApplicationIcon); - free(settings->RemoteApplicationProgram); - free(settings->RemoteApplicationFile); - free(settings->RemoteApplicationGuid); - free(settings->RemoteApplicationCmdLine); - free(settings->ImeFileName); - free(settings->DrivesToRedirect); - free(settings->WindowTitle); - free(settings->WmClass); - free(settings->ActionScript); + freerdp_target_net_addresses_free(settings); freerdp_device_collection_free(settings); freerdp_static_channel_collection_free(settings); freerdp_dynamic_channel_collection_free(settings); - memset(settings, 0, sizeof(rdpSettings)); + + /* Extensions */ + free(settings->ActionScript); + settings->ActionScript = NULL; + + /* Free all strings, set other pointers NULL */ + freerdp_settings_free_keys(settings, TRUE); } void freerdp_settings_free(rdpSettings* settings) @@ -723,79 +670,13 @@ void freerdp_settings_free(rdpSettings* settings) free(settings); } -BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings) +static BOOL freerdp_settings_int_buffer_copy(rdpSettings* _settings, const rdpSettings* settings) { + BOOL rc = FALSE; UINT32 index; - if (!settings || !_settings) + if (!_settings || !settings) return FALSE; - freerdp_settings_free_internal(_settings); - *_settings = *settings; - - /* char* values */ -#define CHECKED_STRDUP(name) \ - if (settings->name && !(_settings->name = _strdup(settings->name))) \ - goto out_fail - CHECKED_STRDUP(ServerHostname); /* 20 */ - CHECKED_STRDUP(Username); /* 21 */ - CHECKED_STRDUP(Password); /* 22 */ - CHECKED_STRDUP(Domain); /* 23 */ - CHECKED_STRDUP(PasswordHash); /* 24 */ - CHECKED_STRDUP(AcceptedCert); /* 27 */ - CHECKED_STRDUP(AlternateShell); /* 640 */ - CHECKED_STRDUP(ShellWorkingDirectory); /* 641 */ - CHECKED_STRDUP(ClientAddress); /* 769 */ - CHECKED_STRDUP(ClientDir); /* 770 */ - CHECKED_STRDUP(DynamicDSTTimeZoneKeyName); /* 897 */ - CHECKED_STRDUP(RemoteAssistanceSessionId); /* 1025 */ - CHECKED_STRDUP(RemoteAssistancePassStub); /* 1026 */ - CHECKED_STRDUP(RemoteAssistancePassword); /* 1027 */ - CHECKED_STRDUP(RemoteAssistanceRCTicket); /* 1028 */ - CHECKED_STRDUP(AuthenticationServiceClass); /* 1098 */ - CHECKED_STRDUP(AllowedTlsCiphers); /* 1101 */ - CHECKED_STRDUP(NtlmSamFile); /* 1103 */ - CHECKED_STRDUP(PreconnectionBlob); /* 1155 */ - CHECKED_STRDUP(TargetNetAddress); /* 1217 */ - CHECKED_STRDUP(RedirectionUsername); /* 1220 */ - CHECKED_STRDUP(RedirectionDomain); /* 1221 */ - CHECKED_STRDUP(RedirectionTargetFQDN); /* 1224 */ - CHECKED_STRDUP(RedirectionTargetNetBiosName); /* 1225 */ - CHECKED_STRDUP(RedirectionAcceptedCert); /* 1231 */ - CHECKED_STRDUP(KerberosKdc); /* 1344 */ - CHECKED_STRDUP(KerberosRealm); /* 1345 */ - CHECKED_STRDUP(CertificateName); /* 1409 */ - CHECKED_STRDUP(CertificateFile); /* 1410 */ - CHECKED_STRDUP(PrivateKeyFile); /* 1411 */ - CHECKED_STRDUP(RdpKeyFile); /* 1412 */ - CHECKED_STRDUP(CertificateContent); /* 1416 */ - CHECKED_STRDUP(PrivateKeyContent); /* 1417 */ - CHECKED_STRDUP(RdpKeyContent); /* 1418 */ - CHECKED_STRDUP(WindowTitle); /* 1542 */ - CHECKED_STRDUP(WmClass); /* 1549 */ - CHECKED_STRDUP(ComputerName); /* 1664 */ - CHECKED_STRDUP(ConnectionFile); /* 1728 */ - CHECKED_STRDUP(AssistanceFile); /* 1729 */ - CHECKED_STRDUP(HomePath); /* 1792 */ - CHECKED_STRDUP(ConfigPath); /* 1793 */ - CHECKED_STRDUP(CurrentPath); /* 1794 */ - CHECKED_STRDUP(DumpRemoteFxFile); /* 1858 */ - CHECKED_STRDUP(PlayRemoteFxFile); /* 1859 */ - CHECKED_STRDUP(GatewayHostname); /* 1986 */ - CHECKED_STRDUP(GatewayUsername); /* 1987 */ - CHECKED_STRDUP(GatewayPassword); /* 1988 */ - CHECKED_STRDUP(GatewayDomain); /* 1989 */ - CHECKED_STRDUP(GatewayAccessToken); /* 1997 */ - CHECKED_STRDUP(GatewayAcceptedCert); /* 1998 */ - CHECKED_STRDUP(ProxyHostname); /* 2016 */ - CHECKED_STRDUP(RemoteApplicationName); /* 2113 */ - CHECKED_STRDUP(RemoteApplicationIcon); /* 2114 */ - CHECKED_STRDUP(RemoteApplicationProgram); /* 2115 */ - CHECKED_STRDUP(RemoteApplicationFile); /* 2116 */ - CHECKED_STRDUP(RemoteApplicationGuid); /* 2117 */ - CHECKED_STRDUP(RemoteApplicationCmdLine); /* 2118 */ - CHECKED_STRDUP(ImeFileName); /* 2628 */ - CHECKED_STRDUP(DrivesToRedirect); /* 4290 */ - CHECKED_STRDUP(ActionScript); if (settings->LoadBalanceInfo && settings->LoadBalanceInfoLength) { @@ -902,15 +783,6 @@ BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings) CopyMemory(_settings->ReceivedCapabilities, settings->ReceivedCapabilities, 32); CopyMemory(_settings->OrderSupport, settings->OrderSupport, 32); - _settings->ClientHostname = _strdup(settings->ClientHostname); - - if (!_settings->ClientHostname) - goto out_fail; - - _settings->ClientProductId = _strdup(settings->ClientProductId); - - if (!_settings->ClientProductId) - goto out_fail; _settings->BitmapCacheV2CellInfo = (BITMAP_CACHE_V2_CELL_INFO*)malloc(sizeof(BITMAP_CACHE_V2_CELL_INFO) * 6); @@ -933,16 +805,6 @@ BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings) CopyMemory(_settings->GlyphCache, settings->GlyphCache, sizeof(GLYPH_CACHE_DEFINITION) * 10); CopyMemory(_settings->FragCache, settings->FragCache, sizeof(GLYPH_CACHE_DEFINITION)); - if (settings->CertificateContent) - _settings->CertificateContent = _strdup(settings->CertificateContent); - if (settings->PrivateKeyContent) - _settings->PrivateKeyContent = _strdup(settings->PrivateKeyContent); - if (settings->RdpKeyContent) - _settings->RdpKeyContent = _strdup(settings->RdpKeyContent); - if (settings->CertificateAcceptedFingerprints) - _settings->CertificateAcceptedFingerprints = - _strdup(settings->CertificateAcceptedFingerprints); - _settings->ClientAutoReconnectCookie = (ARC_CS_PRIVATE_PACKET*)malloc(sizeof(ARC_CS_PRIVATE_PACKET)); @@ -1119,6 +981,55 @@ BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings) goto out_fail; } + if (settings->ActionScript) + _settings->ActionScript = _strdup(settings->ActionScript); + rc = TRUE; +out_fail: + return rc; +} + +BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings) +{ + BOOL rc; + + if (!settings || !_settings) + return FALSE; + + /* This is required to free all non string buffers */ + freerdp_settings_free_internal(_settings); + /* This copies everything except allocated non string buffers. reset all allocated buffers to + * NULL to fix issues during cleanup */ + rc = freerdp_settings_clone_keys(_settings, settings); + + _settings->LoadBalanceInfo = NULL; + _settings->ServerRandom = NULL; + _settings->ClientRandom = NULL; + _settings->RdpServerCertificate = NULL; + _settings->RdpServerRsaKey = NULL; + _settings->ChannelDefArray = NULL; + _settings->MonitorDefArray = NULL; + _settings->MonitorIds = NULL; + _settings->ReceivedCapabilities = NULL; + _settings->OrderSupport = NULL; + _settings->BitmapCacheV2CellInfo = NULL; + _settings->GlyphCache = NULL; + _settings->FragCache = NULL; + _settings->ClientAutoReconnectCookie = NULL; + _settings->ServerAutoReconnectCookie = NULL; + _settings->ClientTimeZone = NULL; + _settings->RedirectionPassword = NULL; + _settings->RedirectionTsvUrl = NULL; + _settings->TargetNetAddresses = NULL; + _settings->DeviceArray = NULL; + _settings->StaticChannelArray = NULL; + _settings->DynamicChannelArray = NULL; + _settings->ActionScript = NULL; + if (!rc) + goto out_fail; + + /* Begin copying */ + if (!freerdp_settings_int_buffer_copy(_settings, settings)) + goto out_fail; return TRUE; out_fail: freerdp_settings_free_internal(_settings); @@ -1134,13 +1045,7 @@ rdpSettings* freerdp_settings_clone(const rdpSettings* settings) return _settings; out_fail: - /* In case any memory allocation failed during clone, some bytes might leak. - * - * freerdp_settings_free can't be reliable used at this point since it could - * free memory of pointers copied by CopyMemory and detecting and freeing - * each allocation separately is quite painful. - */ - free(_settings); + freerdp_settings_free(_settings); return NULL; } #ifdef _WIN32 diff --git a/libfreerdp/core/settings.h b/libfreerdp/core/settings.h index 513cfb66a..d03369fd8 100644 --- a/libfreerdp/core/settings.h +++ b/libfreerdp/core/settings.h @@ -26,5 +26,10 @@ #include <freerdp/api.h> FREERDP_LOCAL BOOL freerdp_settings_set_default_order_support(rdpSettings* settings); +FREERDP_LOCAL BOOL freerdp_settings_set_pointer(rdpSettings* dst, size_t index, const void* ptr); +FREERDP_LOCAL BOOL freerdp_settings_clone_keys(rdpSettings* dst, const rdpSettings* src); +FREERDP_LOCAL void freerdp_settings_free_keys(rdpSettings* dst, BOOL cleanup); +FREERDP_LOCAL BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char* val, + BOOL cleanup); #endif /* FREERDP_LIB_CORE_SETTINGS_H */ diff --git a/libfreerdp/core/test/TestConnect.c b/libfreerdp/core/test/TestConnect.c index 3f79fa03e..7bf196951 100644 --- a/libfreerdp/core/test/TestConnect.c +++ b/libfreerdp/core/test/TestConnect.c @@ -180,6 +180,8 @@ static int testSuccess(int port) path = GetCombinedPath(exe, "Sample"); wpath = GetCombinedPath(wexe, "Sample"); + free(exe); + exe = NULL; if (!path || !wpath) goto fail; @@ -226,6 +228,7 @@ static int testSuccess(int port) fail: free(exe); + free(wexe); free(path); free(wpath); free(commandLine); diff --git a/libfreerdp/core/test/TestSettings.c b/libfreerdp/core/test/TestSettings.c index 6ae9219a3..c9373bd0b 100644 --- a/libfreerdp/core/test/TestSettings.c +++ b/libfreerdp/core/test/TestSettings.c @@ -6,7 +6,8 @@ int TestSettings(int argc, char* argv[]) int rc = -1; size_t x; rdpSettings* settings = NULL; - rdpSettings* cloned; + rdpSettings* cloned = NULL; + rdpSettings* cloned2 = NULL; WINPR_UNUSED(argc); WINPR_UNUSED(argv); settings = freerdp_settings_new(0); @@ -17,24 +18,29 @@ int TestSettings(int argc, char* argv[]) return -1; } - settings->Username = _strdup("abcdefg"); - settings->Password = _strdup("xyz"); + if (!freerdp_settings_set_string(settings, FreeRDP_Username, "abcdefg")) + goto fail; + if (!freerdp_settings_set_string(settings, FreeRDP_Password, "xyz")) + goto fail; + cloned = freerdp_settings_clone(settings); if (!cloned) - { - printf("Problem cloning settings\n"); - freerdp_settings_free(settings); - return -1; - } + goto fail; #if defined(have_bool_list_indices) for (x = 0; x < ARRAYSIZE(bool_list_indices); x++) { const size_t key = bool_list_indices[x]; + const char* name = freerdp_settings_get_name_for_key(key); const BOOL val = freerdp_settings_get_bool(settings, key); - + const BOOL cval = freerdp_settings_get_bool(cloned, key); + if (val != cval) + { + printf("mismatch for key %s: %u -> copy %u\n", name, val, cval); + goto fail; + } if (!freerdp_settings_set_bool(settings, key, val)) goto fail; } @@ -45,8 +51,14 @@ int TestSettings(int argc, char* argv[]) for (x = 0; x < ARRAYSIZE(int16_list_indices); x++) { const size_t key = int16_list_indices[x]; + const char* name = freerdp_settings_get_name_for_key(key); const INT16 val = freerdp_settings_get_int16(settings, key); - + const INT16 cval = freerdp_settings_get_int16(cloned, key); + if (val != cval) + { + printf("mismatch for key %s: %" PRId16 " -> copy %" PRId16 "\n", name, val, cval); + goto fail; + } if (!freerdp_settings_set_int16(settings, key, val)) goto fail; } @@ -57,8 +69,14 @@ int TestSettings(int argc, char* argv[]) for (x = 0; x < ARRAYSIZE(uint16_list_indices); x++) { const size_t key = uint16_list_indices[x]; + const char* name = freerdp_settings_get_name_for_key(key); const UINT16 val = freerdp_settings_get_uint16(settings, key); - + const UINT16 cval = freerdp_settings_get_uint16(cloned, key); + if (val != cval) + { + printf("mismatch for key %s: %" PRIu16 " -> copy %" PRIu16 "\n", name, val, cval); + goto fail; + } if (!freerdp_settings_set_uint16(settings, key, val)) goto fail; } @@ -69,8 +87,14 @@ int TestSettings(int argc, char* argv[]) for (x = 0; x < ARRAYSIZE(uint32_list_indices); x++) { const size_t key = uint32_list_indices[x]; + const char* name = freerdp_settings_get_name_for_key(key); const UINT32 val = freerdp_settings_get_uint32(settings, key); - + const UINT32 cval = freerdp_settings_get_uint32(cloned, key); + if (val != cval) + { + printf("mismatch for key %s: %" PRIu32 " -> copy %" PRIu32 "\n", name, val, cval); + goto fail; + } if (!freerdp_settings_set_uint32(settings, key, val)) goto fail; } @@ -81,8 +105,14 @@ int TestSettings(int argc, char* argv[]) for (x = 0; x < ARRAYSIZE(int32_list_indices); x++) { const size_t key = int32_list_indices[x]; + const char* name = freerdp_settings_get_name_for_key(key); const INT32 val = freerdp_settings_get_int32(settings, key); - + const INT32 cval = freerdp_settings_get_int32(cloned, key); + if (val != cval) + { + printf("mismatch for key %s: %" PRId32 " -> copy %" PRId32 "\n", name, val, cval); + goto fail; + } if (!freerdp_settings_set_int32(settings, key, val)) goto fail; } @@ -93,8 +123,14 @@ int TestSettings(int argc, char* argv[]) for (x = 0; x < ARRAYSIZE(uint64_list_indices); x++) { const size_t key = uint64_list_indices[x]; + const char* name = freerdp_settings_get_name_for_key(key); const UINT64 val = freerdp_settings_get_uint64(settings, key); - + const UINT64 cval = freerdp_settings_get_uint64(cloned, key); + if (val != cval) + { + printf("mismatch for key %s: %" PRIu64 " -> copy %" PRIu64 "\n", name, val, cval); + goto fail; + } if (!freerdp_settings_set_uint64(settings, key, val)) goto fail; } @@ -105,8 +141,14 @@ int TestSettings(int argc, char* argv[]) for (x = 0; x < ARRAYSIZE(int64_list_indices); x++) { const size_t key = int64_list_indices[x]; + const char* name = freerdp_settings_get_name_for_key(key); const INT64 val = freerdp_settings_get_int64(settings, key); - + const INT64 cval = freerdp_settings_get_int64(cloned, key); + if (val != cval) + { + printf("mismatch for key %s: %" PRId64 " -> copy %" PRId64 "\n", name, val, cval); + goto fail; + } if (!freerdp_settings_set_int64(settings, key, val)) goto fail; } @@ -119,7 +161,14 @@ int TestSettings(int argc, char* argv[]) const size_t key = string_list_indices[x]; const char val[] = "test-string"; const char* res; - + const char* name = freerdp_settings_get_name_for_key(key); + const char* oval = freerdp_settings_get_string(settings, key); + const char* cval = freerdp_settings_get_string(cloned, key); + if ((oval != cval) && (strcmp(oval, cval) != 0)) + { + printf("mismatch for key %s: %s -> copy %s\n", name, oval, cval); + goto fail; + } if (!freerdp_settings_set_string(settings, key, val)) goto fail; @@ -136,12 +185,20 @@ int TestSettings(int argc, char* argv[]) { const size_t key = pointer_list_indices[x]; const void* val = freerdp_settings_get_pointer(settings, key); + WINPR_UNUSED(val); } #endif + cloned2 = freerdp_settings_clone(settings); + if (!cloned2) + goto fail; + if (!freerdp_settings_copy(cloned2, cloned)) + goto fail; + rc = 0; fail: freerdp_settings_free(cloned); + freerdp_settings_free(cloned2); freerdp_settings_free(settings); return rc; } diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 534cc6b8c..b20d4a2fe 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -325,6 +325,7 @@ BOOL transport_connect_nla(rdpTransport* transport) if (!settings->Authentication) return TRUE; + nla_free(rdp->nla); rdp->nla = nla_new(instance, transport, settings); if (!rdp->nla) @@ -1214,6 +1215,7 @@ void transport_free(rdpTransport* transport) if (transport->ReceiveBuffer) Stream_Release(transport->ReceiveBuffer); + nla_free(transport->nla); StreamPool_Free(transport->ReceivePool); CloseHandle(transport->connectedEvent); CloseHandle(transport->rereadEvent); diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 0920e356e..841468339 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -96,13 +96,24 @@ exit: static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, int exponent_size, BYTE* output) { - BN_CTX* ctx; + BN_CTX* ctx = NULL; int output_length = -1; - BYTE* input_reverse; - BYTE* modulus_reverse; - BYTE* exponent_reverse; - BIGNUM *mod, *exp, *x, *y; - input_reverse = (BYTE*)malloc(2 * key_length + exponent_size); + BYTE* input_reverse = NULL; + BYTE* modulus_reverse = NULL; + BYTE* exponent_reverse = NULL; + BIGNUM* mod = NULL; + BIGNUM* exp = NULL; + BIGNUM* x = NULL; + BIGNUM* y = NULL; + size_t bufferSize = 2 * key_length + exponent_size; + + if (!input || (length < 0) || (exponent_size < 0) || !modulus || !exponent || !output) + return -1; + + if (length > bufferSize) + bufferSize = length; + + input_reverse = (BYTE*)calloc(bufferSize, 1); if (!input_reverse) return -1; @@ -131,16 +142,24 @@ static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, c if (!(y = BN_new())) goto fail_bn_y; - BN_bin2bn(modulus_reverse, key_length, mod); - BN_bin2bn(exponent_reverse, exponent_size, exp); - BN_bin2bn(input_reverse, length, x); - BN_mod_exp(y, x, exp, mod, ctx); + if (!BN_bin2bn(modulus_reverse, key_length, mod)) + goto fail; + + if (!BN_bin2bn(exponent_reverse, exponent_size, exp)) + goto fail; + if (!BN_bin2bn(input_reverse, length, x)) + goto fail; + if (BN_mod_exp(y, x, exp, mod, ctx) != 1) + goto fail; output_length = BN_bn2bin(y, output); + if (output_length < 0) + goto fail; crypto_reverse(output, output_length); - if (output_length < (int)key_length) + if (output_length < key_length) memset(output + output_length, 0, key_length - output_length); +fail: BN_free(y); fail_bn_y: BN_clear_free(x); @@ -797,6 +816,8 @@ static int verify_cb(int ok, X509_STORE_CTX* csc) BOOL x509_verify_certificate(CryptoCert cert, const char* certificate_store_path) { + size_t i; + const int purposes[3] = { X509_PURPOSE_SSL_SERVER, X509_PURPOSE_SSL_CLIENT, X509_PURPOSE_ANY }; X509_STORE_CTX* csc; BOOL status = FALSE; X509_STORE* cert_ctx = NULL; @@ -831,23 +852,35 @@ BOOL x509_verify_certificate(CryptoCert cert, const char* certificate_store_path X509_LOOKUP_add_dir(lookup, certificate_store_path, X509_FILETYPE_PEM); } - csc = X509_STORE_CTX_new(); - - if (csc == NULL) - goto end; - X509_STORE_set_flags(cert_ctx, 0); - if (!X509_STORE_CTX_init(csc, cert_ctx, cert->px509, cert->px509chain)) - goto end; + for (i = 0; i < ARRAYSIZE(purposes); i++) + { + int err = -1, rc = -1; + int purpose = purposes[i]; + csc = X509_STORE_CTX_new(); + + if (csc == NULL) + goto skip; + if (!X509_STORE_CTX_init(csc, cert_ctx, cert->px509, cert->px509chain)) + goto skip; - X509_STORE_CTX_set_purpose(csc, X509_PURPOSE_ANY); - X509_STORE_CTX_set_verify_cb(csc, verify_cb); + X509_STORE_CTX_set_purpose(csc, purpose); + X509_STORE_CTX_set_verify_cb(csc, verify_cb); - if (X509_verify_cert(csc) == 1) - status = TRUE; + rc = X509_verify_cert(csc); + err = X509_STORE_CTX_get_error(csc); + skip: + X509_STORE_CTX_free(csc); + if (rc == 1) + { + status = TRUE; + break; + } + else if (err != X509_V_ERR_INVALID_PURPOSE) + break; + } - X509_STORE_CTX_free(csc); X509_STORE_free(cert_ctx); end: return status; diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index d7743994e..c94c55534 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -1198,9 +1198,10 @@ static BOOL is_accepted_fingerprint(CryptoCert cert, const char* CertificateAcce char* cur = strtok_s(copy, ",", &context); while (cur) { + char* subcontext = NULL; BOOL equal; char* strhash; - const char* h = strtok(cur, ":"); + const char* h = strtok_s(cur, ":", &subcontext); const char* fp; if (!h) diff --git a/libfreerdp/primitives/prim_colors.c b/libfreerdp/primitives/prim_colors.c index a9d36e39a..54c7ecbc9 100644 --- a/libfreerdp/primitives/prim_colors.c +++ b/libfreerdp/primitives/prim_colors.c @@ -50,13 +50,13 @@ static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_BGRX(const INT16* const pSrc[3] { INT16 R, G, B; const INT32 divisor = 16; - const INT32 Y = ((*pY++) + 4096) << divisor; + const INT32 Y = (INT32)((UINT32)((*pY++) + 4096) << divisor); const INT32 Cb = (*pCb++); const INT32 Cr = (*pCr++); - const INT32 CrR = Cr * (INT32)(1.402525f * (1 << divisor)); - const INT32 CrG = Cr * (INT32)(0.714401f * (1 << divisor)); - const INT32 CbG = Cb * (INT32)(0.343730f * (1 << divisor)); - const INT32 CbB = Cb * (INT32)(1.769905f * (1 << divisor)); + const INT64 CrR = Cr * (INT64)(1.402525f * (1 << divisor)) * 1LL; + const INT64 CrG = Cr * (INT64)(0.714401f * (1 << divisor)) * 1LL; + const INT64 CbG = Cb * (INT64)(0.343730f * (1 << divisor)) * 1LL; + const INT64 CbB = Cb * (INT64)(1.769905f * (1 << divisor)) * 1LL; R = ((INT16)((CrR + Y) >> divisor) >> 5); G = ((INT16)((Y - CbG - CrG) >> divisor) >> 5); B = ((INT16)((CbB + Y) >> divisor) >> 5); @@ -90,18 +90,18 @@ static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_general(const INT16* const pSrc { for (x = 0; x < roi->width; x++) { - INT16 R, G, B; + INT64 R, G, B; const INT32 divisor = 16; - const INT32 Y = ((*pY++) + 4096) << divisor; + const INT32 Y = (INT32)((UINT32)((*pY++) + 4096) << divisor); const INT32 Cb = (*pCb++); const INT32 Cr = (*pCr++); - const INT32 CrR = Cr * (INT32)(1.402525f * (1 << divisor)); - const INT32 CrG = Cr * (INT32)(0.714401f * (1 << divisor)); - const INT32 CbG = Cb * (INT32)(0.343730f * (1 << divisor)); - const INT32 CbB = Cb * (INT32)(1.769905f * (1 << divisor)); - R = ((INT16)((CrR + Y) >> divisor) >> 5); - G = ((INT16)((Y - CbG - CrG) >> divisor) >> 5); - B = ((INT16)((CbB + Y) >> divisor) >> 5); + const INT64 CrR = Cr * (INT64)(1.402525f * (1 << divisor)) * 1LL; + const INT64 CrG = Cr * (INT64)(0.714401f * (1 << divisor)) * 1LL; + const INT64 CbG = Cb * (INT64)(0.343730f * (1 << divisor)) * 1LL; + const INT64 CbB = Cb * (INT64)(1.769905f * (1 << divisor)) * 1LL; + R = (INT64)((CrR + Y) >> (divisor + 5)); + G = (INT64)((Y - CbG - CrG) >> (divisor + 5)); + B = (INT64)((CbB + Y) >> (divisor + 5)); pRGB = (*writePixel)(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0xFF); } @@ -170,7 +170,7 @@ static pstatus_t general_yCbCrToRGB_16s16s_P3P3(const INT16* const pSrc[3], INT3 INT32 y = (INT32)(*yptr++); INT32 cb = (INT32)(*cbptr++); INT32 cr = (INT32)(*crptr++); - INT32 r, g, b; + INT64 r, g, b; /* * This is the slow floating point version kept here for reference. * y = y + 4096; // 128<<5=4096 so that we can scale the sum by>>5 @@ -191,10 +191,10 @@ static pstatus_t general_yCbCrToRGB_16s16s_P3P3(const INT16* const pSrc[3], INT3 * G: 0.344 << 16 = 22544, 0.714 << 16 = 46792 * B: 1.770 << 16 = 115998 */ - y = (y + 4096) << 16; - r = y + cr * 91947; - g = y - cb * 22544 - cr * 46792; - b = y + cb * 115998; + y = (INT32)((UINT32)(y + 4096) << 16); + r = y + cr * 91947LL; + g = y - cb * 22544LL - cr * 46792LL; + b = y + cb * 115998LL; *rptr++ = CLIP(r >> 21); *gptr++ = CLIP(g >> 21); *bptr++ = CLIP(b >> 21); diff --git a/libfreerdp/primitives/prim_shift.c b/libfreerdp/primitives/prim_shift.c index 3fabfe26e..cab9481cc 100644 --- a/libfreerdp/primitives/prim_shift.c +++ b/libfreerdp/primitives/prim_shift.c @@ -26,9 +26,11 @@ static INLINE pstatus_t general_lShiftC_16s(const INT16* pSrc, UINT32 val, INT16 { if (val == 0) return PRIMITIVES_SUCCESS; + if (val >= 16) + return -1; while (len--) - *pDst++ = *pSrc++ << val; + *pDst++ = (INT16)((UINT16)*pSrc++ << val); return PRIMITIVES_SUCCESS; } @@ -38,6 +40,8 @@ static INLINE pstatus_t general_rShiftC_16s(const INT16* pSrc, UINT32 val, INT16 { if (val == 0) return PRIMITIVES_SUCCESS; + if (val >= 16) + return -1; while (len--) *pDst++ = *pSrc++ >> val; @@ -51,9 +55,11 @@ static INLINE pstatus_t general_lShiftC_16u(const UINT16* pSrc, UINT32 val, UINT { if (val == 0) return PRIMITIVES_SUCCESS; + if (val >= 16) + return -1; while (len--) - *pDst++ = *pSrc++ << val; + *pDst++ = (INT16)((UINT16)*pSrc++ << val); return PRIMITIVES_SUCCESS; } @@ -64,6 +70,8 @@ static INLINE pstatus_t general_rShiftC_16u(const UINT16* pSrc, UINT32 val, UINT { if (val == 0) return PRIMITIVES_SUCCESS; + if (val >= 16) + return -1; while (len--) *pDst++ = *pSrc++ >> val; diff --git a/libfreerdp/primitives/prim_shift_opt.c b/libfreerdp/primitives/prim_shift_opt.c index 481363a1b..2515dfbac 100644 --- a/libfreerdp/primitives/prim_shift_opt.c +++ b/libfreerdp/primitives/prim_shift_opt.c @@ -39,13 +39,13 @@ static primitives_t* generic = NULL; #if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS) /* ------------------------------------------------------------------------- */ SSE3_SCD_ROUTINE(sse2_lShiftC_16s, INT16, generic->lShiftC_16s, _mm_slli_epi16, - *dptr++ = *sptr++ << val) + *dptr++ = (INT16)((UINT16)*sptr++ << val)) /* ------------------------------------------------------------------------- */ SSE3_SCD_ROUTINE(sse2_rShiftC_16s, INT16, generic->rShiftC_16s, _mm_srai_epi16, *dptr++ = *sptr++ >> val) /* ------------------------------------------------------------------------- */ SSE3_SCD_ROUTINE(sse2_lShiftC_16u, UINT16, generic->lShiftC_16u, _mm_slli_epi16, - *dptr++ = *sptr++ << val) + *dptr++ = (INT16)((UINT16)*sptr++ << val)) /* ------------------------------------------------------------------------- */ SSE3_SCD_ROUTINE(sse2_rShiftC_16u, UINT16, generic->rShiftC_16u, _mm_srli_epi16, *dptr++ = *sptr++ >> val) diff --git a/libfreerdp/primitives/prim_templates.h b/libfreerdp/primitives/prim_templates.h index 47872651e..46996e2c7 100644 --- a/libfreerdp/primitives/prim_templates.h +++ b/libfreerdp/primitives/prim_templates.h @@ -51,6 +51,10 @@ const _type_* sptr = pSrc; \ _type_* dptr = pDst; \ size_t count; \ + if (val == 0) \ + return PRIMITIVES_SUCCESS; \ + if (val >= 16) \ + return -1; \ if (len < 16) /* pointless if too small */ \ { \ return _fallback_(pSrc, val, pDst, len); \ diff --git a/libfreerdp/primitives/test/TestPrimitivesShift.c b/libfreerdp/primitives/test/TestPrimitivesShift.c index 448c2d1a2..487e188e9 100644 --- a/libfreerdp/primitives/test/TestPrimitivesShift.c +++ b/libfreerdp/primitives/test/TestPrimitivesShift.c @@ -29,7 +29,18 @@ static BOOL test_lShift_16s_func(void) UINT32 val; winpr_RAND((BYTE*)&val, sizeof(val)); winpr_RAND((BYTE*)src, sizeof(src)); - val = (val % (FUNC_TEST_SIZE - 1)) + 1; + val = val % 16; + /* Negative tests */ + status = generic->lShiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + + status = optimized->lShiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + /* Aligned */ status = generic->lShiftC_16s(src + 1, val, d1 + 1, FUNC_TEST_SIZE); @@ -63,7 +74,19 @@ static BOOL test_lShift_16u_func(void) UINT32 val; winpr_RAND((BYTE*)&val, sizeof(val)); winpr_RAND((BYTE*)src, sizeof(src)); - val = (val % (FUNC_TEST_SIZE - 1)) + 1; + val = val % 16; + + /* Negative tests */ + status = generic->lShiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + + status = optimized->lShiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + /* Aligned */ status = generic->lShiftC_16u(src + 1, val, d1 + 1, FUNC_TEST_SIZE); @@ -97,7 +120,19 @@ static BOOL test_rShift_16s_func(void) UINT32 val; winpr_RAND((BYTE*)&val, sizeof(val)); winpr_RAND((BYTE*)src, sizeof(src)); - val = (val % (FUNC_TEST_SIZE - 1)) + 1; + val = val % 16; + + /* Negative Tests */ + status = generic->rShiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + + status = optimized->rShiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + /* Aligned */ status = generic->rShiftC_16s(src + 1, val, d1 + 1, FUNC_TEST_SIZE); @@ -131,7 +166,18 @@ static BOOL test_rShift_16u_func(void) UINT32 val; winpr_RAND((BYTE*)&val, sizeof(val)); winpr_RAND((BYTE*)src, sizeof(src)); - val = (val % (FUNC_TEST_SIZE - 1)) + 1; + val = val % 16; + /* Negative tests */ + status = generic->rShiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + + status = optimized->rShiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + /* Aligned */ status = generic->rShiftC_16u(src + 1, val, d1 + 1, FUNC_TEST_SIZE); @@ -166,7 +212,19 @@ static BOOL test_ShiftWrapper_16s_func(void) INT32 val; winpr_RAND((BYTE*)&tmp, sizeof(tmp)); winpr_RAND((BYTE*)src, sizeof(src)); - val = (tmp % (FUNC_TEST_SIZE - 1)) + 1; + val = tmp % 16; + + /* Negative tests */ + status = generic->shiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + + status = optimized->shiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + /* Aligned */ status = generic->shiftC_16s(src + 1, val, d1 + 1, FUNC_TEST_SIZE); @@ -221,7 +279,18 @@ static BOOL test_ShiftWrapper_16u_func(void) INT32 val; winpr_RAND((BYTE*)&tmp, sizeof(tmp)); winpr_RAND((BYTE*)src, sizeof(src)); - val = (tmp % (FUNC_TEST_SIZE - 1)) + 1; + val = tmp % 16; + + /* Negative */ + status = generic->shiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + if (status == PRIMITIVES_SUCCESS) + return FALSE; + + status = optimized->shiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE); + + if (status == PRIMITIVES_SUCCESS) + return FALSE; + /* Aligned */ status = generic->shiftC_16u(src + 1, val, d1 + 1, FUNC_TEST_SIZE); @@ -275,6 +344,7 @@ static BOOL test_lShift_16s_speed(void) winpr_RAND((BYTE*)src, sizeof(src)); winpr_RAND((BYTE*)&val, sizeof(val)); + val = val % 16; if (!speed_test("lShift_16s", "aligned", g_Iterations, (speed_test_fkt)generic->lShiftC_16s, (speed_test_fkt)optimized->lShiftC_16s, src, val, dst, MAX_TEST_SIZE)) return FALSE; @@ -294,6 +364,7 @@ static BOOL test_lShift_16u_speed(void) winpr_RAND((BYTE*)&val, sizeof(val)); winpr_RAND((BYTE*)src, sizeof(src)); + val = val % 16; if (!speed_test("lShift_16u", "aligned", g_Iterations, (speed_test_fkt)generic->lShiftC_16u, (speed_test_fkt)optimized->lShiftC_16u, src, val, dst, MAX_TEST_SIZE)) return FALSE; @@ -313,6 +384,7 @@ static BOOL test_rShift_16s_speed(void) winpr_RAND((BYTE*)src, sizeof(src)); winpr_RAND((BYTE*)&val, sizeof(val)); + val = val % 16; if (!speed_test("rShift_16s", "aligned", g_Iterations, (speed_test_fkt)generic->rShiftC_16s, (speed_test_fkt)optimized->rShiftC_16s, src, val, dst, MAX_TEST_SIZE)) return FALSE; @@ -332,6 +404,7 @@ static BOOL test_rShift_16u_speed(void) winpr_RAND((BYTE*)&val, sizeof(val)); winpr_RAND((BYTE*)src, sizeof(src)); + val = val % 16; if (!speed_test("rShift_16u", "aligned", g_Iterations, (speed_test_fkt)generic->rShiftC_16u, (speed_test_fkt)optimized->rShiftC_16u, src, val, dst, MAX_TEST_SIZE)) return FALSE; diff --git a/scripts/update-settings-tests b/scripts/update-settings-tests index 25f15714b..48e79d2fc 100755 --- a/scripts/update-settings-tests +++ b/scripts/update-settings-tests @@ -49,6 +49,103 @@ def write_str(f, entry_dict): for val in values: write_str_case(f, entry_types.index(entry_type), val) f.write('};\n\n') + f.write('\n') + f.write('BOOL freerdp_settings_clone_keys(rdpSettings* dst, const rdpSettings* src)\n') + f.write('{\n') + f.write('\tsize_t x;\n') + f.write('\tfor(x=0; x<ARRAYSIZE(settings_map); x++)\n') + f.write('\t{\n') + f.write('\t\tconst struct settings_str_entry* cur = &settings_map[x];\n') + f.write('\t\tswitch(cur->type)\n') + f.write('\t\t{\n') + f.write('\t\t\tcase 0: /* bool */\n') + f.write('\t\t\t{\n') + f.write('\t\t\t\tBOOL sval = freerdp_settings_get_bool(src, cur->id);\n') + f.write('\t\t\t\tif (!freerdp_settings_set_bool(dst, cur->id, sval))\n') + f.write('\t\t\t\t\treturn FALSE;\n') + f.write('\t\t\t}\n') + f.write('\t\t\tbreak;\n') + f.write('\t\t\tcase 1: /* UINT16 */\n') + f.write('\t\t\t{\n') + f.write('\t\t\t\tUINT16 sval = freerdp_settings_get_uint16(src, cur->id);\n') + f.write('\t\t\t\tif (!freerdp_settings_set_uint16(dst, cur->id, sval))\n') + f.write('\t\t\t\t\treturn FALSE;\n') + f.write('\t\t\t}\n') + f.write('\t\t\tbreak;\n') + f.write('\t\t\tcase 2: /* INT16 */\n') + f.write('\t\t\t{\n') + f.write('\t\t\t\tINT16 sval = freerdp_settings_get_int16(src, cur->id);\n') + f.write('\t\t\t\tif (!freerdp_settings_set_int16(dst, cur->id, sval))\n') + f.write('\t\t\t\t\treturn FALSE;\n') + f.write('\t\t\t}\n') + f.write('\t\t\tbreak;\n') + f.write('\t\t\tcase 3: /* UINT32 */\n') + f.write('\t\t\t{\n') + f.write('\t\t\t\tUINT32 sval = freerdp_settings_get_uint32(src, cur->id);\n') + f.write('\t\t\t\tif (!freerdp_settings_set_uint32(dst, cur->id, sval))\n') + f.write('\t\t\t\t\treturn FALSE;\n') + f.write('\t\t\t}\n') + f.write('\t\t\tbreak;\n') + f.write('\t\t\tcase 4: /* INT32 */\n') + f.write('\t\t\t{\n') + f.write('\t\t\t\tINT32 sval = freerdp_settings_get_int32(src, cur->id);\n') + f.write('\t\t\t\tif (!freerdp_settings_set_int32(dst, cur->id, sval))\n') + f.write('\t\t\t\t\treturn FALSE;\n') + f.write('\t\t\t}\n') + f.write('\t\t\tbreak;\n') + f.write('\t\t\tcase 5: /* UINT64 */\n') + f.write('\t\t\t{\n') + f.write('\t\t\t\tUINT64 sval = freerdp_settings_get_uint64(src, cur->id);\n') + f.write('\t\t\t\tif (!freerdp_settings_set_uint64(dst, cur->id, sval))\n') + f.write('\t\t\t\t\treturn FALSE;\n') + f.write('\t\t\t}\n') + f.write('\t\t\tbreak;\n') + f.write('\t\t\tcase 6: /* INT64 */\n') + f.write('\t\t\t{\n') + f.write('\t\t\t\tINT64 sval = freerdp_settings_get_int64(src, cur->id);\n') + f.write('\t\t\t\tif (!freerdp_settings_set_int64(dst, cur->id, sval))\n') + f.write('\t\t\t\t\treturn FALSE;\n') + f.write('\t\t\t}\n') + f.write('\t\t\tbreak;\n') + f.write('\t\t\tcase 7: /* strings */\n') + f.write('\t\t\t{\n') + f.write('\t\t\t\tconst char* sval = freerdp_settings_get_string(src, cur->id);\n') + f.write('\t\t\t\tif (!freerdp_settings_set_string_(dst, cur->id, sval, FALSE))\n') + f.write('\t\t\t\t\treturn FALSE;\n') + f.write('\t\t\t}\n') + f.write('\t\t\tbreak;\n') + f.write('\t\t\tcase 8: /* pointer */\n') + f.write('\t\t\t{\n') + f.write('\t\t\t\tconst void* sval = freerdp_settings_get_pointer(src, cur->id);\n') + f.write('\t\t\t\tif (!freerdp_settings_set_pointer(dst, cur->id, sval))\n') + f.write('\t\t\t\t\treturn FALSE;\n') + f.write('\t\t\t}\n') + f.write('\t\t\tbreak;\n') + + f.write('\t\t}\n') + f.write('\t}\n') + f.write('\treturn TRUE;\n') + f.write('}\n') + f.write('\n') + f.write('void freerdp_settings_free_keys(rdpSettings* dst, BOOL cleanup)\n') + f.write('{\n') + f.write('\tsize_t x;\n') + f.write('\tfor(x=0; x<ARRAYSIZE(settings_map); x++)\n') + f.write('\t{\n') + f.write('\t\tconst struct settings_str_entry* cur = &settings_map[x];\n') + f.write('\t\tswitch(cur->type)\n') + f.write('\t\t{\n') + f.write('\t\t\tcase 7: /* strings */\n') + f.write('\t\t\t\tfreerdp_settings_set_string_(dst, cur->id, NULL, cleanup);\n') + f.write('\t\t\tbreak;\n') + f.write('\t\t\tcase 8: /* pointer */\n') + f.write('\t\t\t\tfreerdp_settings_set_pointer(dst, cur->id, NULL);\n') + f.write('\t\t\tbreak;\n') + f.write('\t\t}\n') + f.write('\t}\n') + f.write('}\n') + f.write('\n') + f.write('SSIZE_T freerdp_settings_get_key_for_name(const char* value)\n') f.write('{\n') f.write('\tsize_t x;\n') @@ -130,11 +227,15 @@ def write_getter(f, entry_dict, entry_type, entry_name): def write_setter_case(f, val, isString, isPointer): f.write('\t\tcase FreeRDP_' + val + ':\n') - if not isString: + if isPointer: + f.write('\t\t\tsettings->' + val + ' = (void*)val;\n') + f.write('\t\t\tbreak;\n\n') + elif not isString: f.write('\t\t\tsettings->' + val + ' = val;\n') f.write('\t\t\tbreak;\n\n') else: - f.write('\t\t\tfree(settings->' + val + ');\n') + f.write('\t\t\tif (cleanup)\n') + f.write('\t\t\t\tfree(settings->' + val + ');\n') f.write('\t\t\tsettings->' + val + ' = (val ? _strdup(val) : NULL);\n') f.write('\t\t\treturn (!val || settings->' + val + ' != NULL);\n\n') @@ -143,13 +244,20 @@ def write_setter(f, entry_dict, entry_type, entry_name): isPointer = 'pointer' in entry_name values = get_values(entry_dict, entry_type) - f.write('BOOL freerdp_settings_set_' + entry_name.lower() + '(rdpSettings* settings, size_t id, ') + f.write('BOOL freerdp_settings_set_' + entry_name.lower()) + if isString: + f.write('_') + f.write('(rdpSettings* settings, size_t id, ') if isString or isPointer: f.write('const ') if not isPointer: - f.write(entry_type + ' val)\n') + f.write(entry_type + ' val') else: - f.write('void* val)\n') + f.write('void* val') + if isString: + f.write(', BOOL cleanup)\n') + else: + f.write(')\n') f.write('{\n') f.write('\tif (!settings)\n') f.write('\t\treturn FALSE;\n\n') @@ -164,6 +272,20 @@ def write_setter(f, entry_dict, entry_type, entry_name): f.write('\t}\n') f.write('\treturn TRUE;\n') f.write('}\n\n') + f.write('\n') + if isString: + f.write('BOOL freerdp_settings_set_' + entry_name.lower() + '(rdpSettings* settings, size_t id, ') + if isString or isPointer: + f.write('const ') + if not isPointer: + f.write(entry_type + ' val') + else: + f.write('void* val') + f.write(')\n') + f.write('{\n') + f.write('\treturn freerdp_settings_set_' + entry_name.lower() + '_(settings, id, val, TRUE);\n') + f.write('}\n') + f.write('\n') name = os.path.dirname(os.path.realpath(__file__)) begin = "WARNING: this data structure is carefully padded for ABI stability!" @@ -230,7 +352,7 @@ try: write_getter(f, getter_list, 'char*', 'string') write_setter(f, setter_list, 'char*', 'string') write_getter(f, getter_list, '*', 'pointer') -# write_setter(f, setter_list, '*', 'pointer') + write_setter(f, setter_list, '*', 'pointer') f.write('\n') @@ -238,6 +360,7 @@ try: f.write('/* Generated by ' + '' + ' */\n\n') f.write('#include <freerdp/settings.h>\n') f.write('#include <freerdp/log.h>\n\n') + f.write('#include "../core/settings.h"\n\n') f.write('#define TAG FREERDP_TAG("common.settings")\n\n') getter_list = dict(type_list) diff --git a/server/proxy/freerdp_proxy.c b/server/proxy/freerdp_proxy.c index 3b348d094..d6888f424 100644 --- a/server/proxy/freerdp_proxy.c +++ b/server/proxy/freerdp_proxy.c @@ -24,6 +24,7 @@ #include "pf_log.h" #include "pf_modules.h" +#include <freerdp/version.h> #include <freerdp/build-config.h> #include <winpr/collections.h> #include <stdlib.h> @@ -85,11 +86,14 @@ int main(int argc, char* argv[]) char* config_path = "config.ini"; int status = -1; + WLog_INFO(TAG, "freerdp-proxy version info:"); + WLog_INFO(TAG, "\tFreeRDP version: %s", FREERDP_VERSION_FULL); + WLog_INFO(TAG, "\tGit commit: %s", GIT_REVISION); + WLog_DBG(TAG, "\tBuild config: %s", freerdp_get_build_config()); + if (argc >= 2) config_path = argv[1]; - pf_server_register_signal_handlers(); - config = pf_server_config_load(config_path); if (!config) goto fail; @@ -107,6 +111,8 @@ int main(int argc, char* argv[]) if (!is_all_required_modules_loaded(config)) goto fail; + pf_server_register_signal_handlers(); + server = pf_server_new(config); if (!server) goto fail; diff --git a/server/proxy/pf_client.c b/server/proxy/pf_client.c index aebba08af..0db33f88a 100644 --- a/server/proxy/pf_client.c +++ b/server/proxy/pf_client.c @@ -72,10 +72,11 @@ static void pf_client_on_error_info(void* ctx, ErrorInfoEventArgs* e) freerdp_send_error_info(ps->context.rdp); } -static BOOL pf_client_load_rdpsnd(pClientContext* pc, proxyConfig* config) +static BOOL pf_client_load_rdpsnd(pClientContext* pc) { rdpContext* context = (rdpContext*)pc; pServerContext* ps = pc->pdata->ps; + proxyConfig* config = pc->pdata->config; /* * if AudioOutput is enabled in proxy and client connected with rdpsnd, use proxy as rdpsnd @@ -98,6 +99,63 @@ static BOOL pf_client_load_rdpsnd(pClientContext* pc, proxyConfig* config) return TRUE; } +static BOOL pf_client_passthrough_channels_init(pClientContext* pc) +{ + pServerContext* ps = pc->pdata->ps; + rdpSettings* settings = pc->context.settings; + proxyConfig* config = pc->pdata->config; + size_t i; + + if (settings->ChannelCount + config->PassthroughCount >= settings->ChannelDefArraySize) + { + LOG_ERR(TAG, pc, "too many channels"); + return FALSE; + } + + for (i = 0; i < config->PassthroughCount; i++) + { + const char* channel_name = config->Passthrough[i]; + CHANNEL_DEF channel = { 0 }; + + /* only connect connect this channel if already joined in peer connection */ + if (!WTSVirtualChannelManagerIsChannelJoined(ps->vcm, channel_name)) + { + LOG_INFO(TAG, ps, "client did not connected with channel %s, skipping passthrough", + channel_name); + + continue; + } + + channel.options = CHANNEL_OPTION_INITIALIZED; /* TODO: Export to config. */ + strncpy(channel.name, channel_name, CHANNEL_NAME_LEN); + + settings->ChannelDefArray[settings->ChannelCount++] = channel; + } + + return TRUE; +} + +static BOOL pf_client_use_peer_load_balance_info(pClientContext* pc) +{ + pServerContext* ps = pc->pdata->ps; + rdpSettings* settings = pc->context.settings; + DWORD lb_info_len; + const char* lb_info = freerdp_nego_get_routing_token(&ps->context, &lb_info_len); + if (!lb_info) + return TRUE; + + free(settings->LoadBalanceInfo); + + settings->LoadBalanceInfoLength = lb_info_len; + settings->LoadBalanceInfo = malloc(settings->LoadBalanceInfoLength); + + if (!settings->LoadBalanceInfo) + return FALSE; + + CopyMemory(settings->LoadBalanceInfo, lb_info, settings->LoadBalanceInfoLength); + return TRUE; +} + /** * Called before a connection is established. * @@ -135,6 +193,7 @@ static BOOL pf_client_pre_connect(freerdp* instance) settings->DynamicResolutionUpdate = config->DisplayControl; settings->AutoReconnectionEnabled = TRUE; + /** * Register the channel listeners. * They are required to set up / tear down channels if they are loaded. @@ -144,45 +203,26 @@ static BOOL pf_client_pre_connect(freerdp* instance) PubSub_SubscribeChannelDisconnected(instance->context->pubSub, pf_channels_on_client_channel_disconnect); PubSub_SubscribeErrorInfo(instance->context->pubSub, pf_client_on_error_info); - /** * Load all required plugins / channels / libraries specified by current * settings. */ LOG_INFO(TAG, pc, "Loading addins"); + if (!config->UseLoadBalanceInfo) { - /* add passthrough channels to channel def array */ - size_t i; + /* if target is static (i.e fetched from config). make sure to use peer's load-balance info, + * in order to support broker redirection. + */ - if (settings->ChannelCount + config->PassthroughCount >= settings->ChannelDefArraySize) - { - LOG_ERR(TAG, pc, "too many channels"); + if (!pf_client_use_peer_load_balance_info(pc)) return FALSE; - } - - for (i = 0; i < config->PassthroughCount; i++) - { - const char* channel_name = config->Passthrough[i]; - CHANNEL_DEF channel = { 0 }; - - /* only connect connect this channel if already joined in peer connection */ - if (!WTSVirtualChannelManagerIsChannelJoined(ps->vcm, channel_name)) - { - LOG_INFO(TAG, ps, "client did not connected with channel %s, skipping passthrough", - channel_name); - - continue; - } - - channel.options = CHANNEL_OPTION_INITIALIZED; /* TODO: Export to config. */ - strncpy(channel.name, channel_name, CHANNEL_NAME_LEN); - - settings->ChannelDefArray[settings->ChannelCount++] = channel; - } } - if (!pf_client_load_rdpsnd(pc, config)) + if (!pf_client_passthrough_channels_init(pc)) + return FALSE; + + if (!pf_client_load_rdpsnd(pc)) { LOG_ERR(TAG, pc, "Failed to load rdpsnd client"); return FALSE; diff --git a/server/shadow/freerdp-shadow-cli.1.in b/server/shadow/freerdp-shadow-cli.1.in index 46f376d52..9c6ffe543 100644 --- a/server/shadow/freerdp-shadow-cli.1.in +++ b/server/shadow/freerdp-shadow-cli.1.in @@ -76,7 +76,7 @@ When run as user within a X session (for example from an xterm) a socket on Successful program execution. .TP .B 1 -Otherweise. +Otherwise. .SH SEE ALSO wlog(7) diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index 650c5910b..a8b66038f 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -51,7 +51,7 @@ if (NOT WIN32) endif() # Soname versioning -set(RAW_VERSION_STRING "2.1.0") +set(RAW_VERSION_STRING "2.1.1") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) diff --git a/winpr/include/winpr/bitstream.h b/winpr/include/winpr/bitstream.h index 29e8ca4de..0771ce958 100644 --- a/winpr/include/winpr/bitstream.h +++ b/winpr/include/winpr/bitstream.h @@ -52,39 +52,39 @@ extern "C" { (_bs->prefetch) = 0; if (((UINT32)(_bs->pointer - _bs->buffer) + 4) < (_bs->capacity)) - (_bs->prefetch) |= (*(_bs->pointer + 4) << 24); + (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 4) << 24); if (((UINT32)(_bs->pointer - _bs->buffer) + 5) < (_bs->capacity)) - (_bs->prefetch) |= (*(_bs->pointer + 5) << 16); + (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 5) << 16); if (((UINT32)(_bs->pointer - _bs->buffer) + 6) < (_bs->capacity)) - (_bs->prefetch) |= (*(_bs->pointer + 6) << 8); + (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 6) << 8); if (((UINT32)(_bs->pointer - _bs->buffer) + 7) < (_bs->capacity)) - (_bs->prefetch) |= (*(_bs->pointer + 7) << 0); + (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 7) << 0); } static INLINE void BitStream_Fetch(wBitStream* _bs) { (_bs->accumulator) = 0; if (((UINT32)(_bs->pointer - _bs->buffer) + 0) < (_bs->capacity)) - (_bs->accumulator) |= (*(_bs->pointer + 0) << 24); + (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 0) << 24); if (((UINT32)(_bs->pointer - _bs->buffer) + 1) < (_bs->capacity)) - (_bs->accumulator) |= (*(_bs->pointer + 1) << 16); + (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 1) << 16); if (((UINT32)(_bs->pointer - _bs->buffer) + 2) < (_bs->capacity)) - (_bs->accumulator) |= (*(_bs->pointer + 2) << 8); + (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 2) << 8); if (((UINT32)(_bs->pointer - _bs->buffer) + 3) < (_bs->capacity)) - (_bs->accumulator) |= (*(_bs->pointer + 3) << 0); + (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 3) << 0); BitStream_Prefetch(_bs); } static INLINE void BitStream_Flush(wBitStream* _bs) { if (((UINT32)(_bs->pointer - _bs->buffer) + 0) < (_bs->capacity)) - *(_bs->pointer + 0) = (_bs->accumulator >> 24); + *(_bs->pointer + 0) = ((UINT32)_bs->accumulator >> 24); if (((UINT32)(_bs->pointer - _bs->buffer) + 1) < (_bs->capacity)) - *(_bs->pointer + 1) = (_bs->accumulator >> 16); + *(_bs->pointer + 1) = ((UINT32)_bs->accumulator >> 16); if (((UINT32)(_bs->pointer - _bs->buffer) + 2) < (_bs->capacity)) - *(_bs->pointer + 2) = (_bs->accumulator >> 8); + *(_bs->pointer + 2) = ((UINT32)_bs->accumulator >> 8); if (((UINT32)(_bs->pointer - _bs->buffer) + 3) < (_bs->capacity)) - *(_bs->pointer + 3) = (_bs->accumulator >> 0); + *(_bs->pointer + 3) = ((UINT32)_bs->accumulator >> 0); } static INLINE void BitStream_Shift(wBitStream* _bs, UINT32 _nbits) @@ -99,13 +99,13 @@ extern "C" _bs->offset += _nbits; if (_bs->offset < 32) { - _bs->mask = ((1 << _nbits) - 1); + _bs->mask = ((1UL << _nbits) - 1); _bs->accumulator |= ((_bs->prefetch >> (32 - _nbits)) & _bs->mask); _bs->prefetch <<= _nbits; } else { - _bs->mask = ((1 << _nbits) - 1); + _bs->mask = ((1UL << _nbits) - 1); _bs->accumulator |= ((_bs->prefetch >> (32 - _nbits)) & _bs->mask); _bs->prefetch <<= _nbits; _bs->offset -= 32; @@ -113,7 +113,7 @@ extern "C" BitStream_Prefetch(_bs); if (_bs->offset) { - _bs->mask = ((1 << _bs->offset) - 1); + _bs->mask = ((1UL << _bs->offset) - 1); _bs->accumulator |= ((_bs->prefetch >> (32 - _bs->offset)) & _bs->mask); _bs->prefetch <<= _bs->offset; } @@ -149,7 +149,7 @@ extern "C" _bs->pointer += 4; if (_bs->offset) { - _bs->mask = ((1 << _bs->offset) - 1); + _bs->mask = ((1UL << _bs->offset) - 1); _bs->accumulator |= ((_bits & _bs->mask) << (32 - _bs->offset)); } } diff --git a/winpr/include/winpr/sam.h b/winpr/include/winpr/sam.h index a11967b12..6d932dfca 100644 --- a/winpr/include/winpr/sam.h +++ b/winpr/include/winpr/sam.h @@ -23,13 +23,6 @@ #include <winpr/winpr.h> #include <winpr/wtypes.h> -struct winpr_sam -{ - FILE* fp; - char* line; - char* buffer; - BOOL readOnly; -}; typedef struct winpr_sam WINPR_SAM; struct winpr_sam_entry diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h index a5f10b03e..f351eaa15 100644 --- a/winpr/include/winpr/stream.h +++ b/winpr/include/winpr/stream.h @@ -74,60 +74,64 @@ extern "C" Stream_Seek(_s, sizeof(_t)); \ } while (0) -#define _stream_read_n16_le(_t, _s, _v, _p) \ - do \ - { \ - (_v) = (_t)(*(_s)->pointer) + (_t)(((_t)(*((_s)->pointer + 1))) << 8); \ - if (_p) \ - Stream_Seek(_s, sizeof(_t)); \ +#define _stream_read_n16_le(_t, _s, _v, _p) \ + do \ + { \ + (_v) = (_t)((*(_s)->pointer) + (((UINT16)(*((_s)->pointer + 1))) << 8)); \ + if (_p) \ + Stream_Seek(_s, sizeof(_t)); \ } while (0) -#define _stream_read_n16_be(_t, _s, _v, _p) \ - do \ - { \ - (_v) = (_t)(((_t)(*(_s)->pointer)) << 8) + (_t)(*((_s)->pointer + 1)); \ - if (_p) \ - Stream_Seek(_s, sizeof(_t)); \ - } while (0) - -#define _stream_read_n32_le(_t, _s, _v, _p) \ - do \ - { \ - (_v) = (_t)(*(_s)->pointer) + (((_t)(*((_s)->pointer + 1))) << 8) + \ - (((_t)(*((_s)->pointer + 2))) << 16) + (((_t)(*((_s)->pointer + 3))) << 24); \ - if (_p) \ - Stream_Seek(_s, sizeof(_t)); \ +#define _stream_read_n16_be(_t, _s, _v, _p) \ + do \ + { \ + (_v) = (_t)((((UINT16)(*(_s)->pointer)) << 8) + (UINT16)(*((_s)->pointer + 1))); \ + if (_p) \ + Stream_Seek(_s, sizeof(_t)); \ } while (0) -#define _stream_read_n32_be(_t, _s, _v, _p) \ +#define _stream_read_n32_le(_t, _s, _v, _p) \ do \ { \ - (_v) = (((_t)(*((_s)->pointer))) << 24) + (((_t)(*((_s)->pointer + 1))) << 16) + \ - (((_t)(*((_s)->pointer + 2))) << 8) + (((_t)(*((_s)->pointer + 3)))); \ + (_v) = (_t)((UINT32)(*(_s)->pointer) + (((UINT32)(*((_s)->pointer + 1))) << 8) + \ + (((UINT32)(*((_s)->pointer + 2))) << 16) + \ + ((((UINT32) * ((_s)->pointer + 3))) << 24)); \ if (_p) \ Stream_Seek(_s, sizeof(_t)); \ } while (0) -#define _stream_read_n64_le(_t, _s, _v, _p) \ - do \ - { \ - (_v) = (_t)(*(_s)->pointer) + (((_t)(*((_s)->pointer + 1))) << 8) + \ - (((_t)(*((_s)->pointer + 2))) << 16) + (((_t)(*((_s)->pointer + 3))) << 24) + \ - (((_t)(*((_s)->pointer + 4))) << 32) + (((_t)(*((_s)->pointer + 5))) << 40) + \ - (((_t)(*((_s)->pointer + 6))) << 48) + (((_t)(*((_s)->pointer + 7))) << 56); \ - if (_p) \ - Stream_Seek(_s, sizeof(_t)); \ +#define _stream_read_n32_be(_t, _s, _v, _p) \ + do \ + { \ + (_v) = (_t)(((((UINT32) * ((_s)->pointer))) << 24) + \ + (((UINT32)(*((_s)->pointer + 1))) << 16) + \ + (((UINT32)(*((_s)->pointer + 2))) << 8) + (((UINT32)(*((_s)->pointer + 3))))); \ + if (_p) \ + Stream_Seek(_s, sizeof(_t)); \ + } while (0) + +#define _stream_read_n64_le(_t, _s, _v, _p) \ + do \ + { \ + (_v) = (_t)( \ + (UINT64)(*(_s)->pointer) + (((UINT64)(*((_s)->pointer + 1))) << 8) + \ + (((UINT64)(*((_s)->pointer + 2))) << 16) + (((UINT64)(*((_s)->pointer + 3))) << 24) + \ + (((UINT64)(*((_s)->pointer + 4))) << 32) + (((UINT64)(*((_s)->pointer + 5))) << 40) + \ + (((UINT64)(*((_s)->pointer + 6))) << 48) + (((UINT64)(*((_s)->pointer + 7))) << 56)); \ + if (_p) \ + Stream_Seek(_s, sizeof(_t)); \ } while (0) -#define _stream_read_n64_be(_t, _s, _v, _p) \ - do \ - { \ - (_v) = (((_t)(*((_s)->pointer))) << 56) + (((_t)(*((_s)->pointer + 1))) << 48) + \ - (((_t)(*((_s)->pointer + 2))) << 40) + (((_t)(*((_s)->pointer + 3))) << 32) + \ - (((_t)(*((_s)->pointer + 4))) << 24) + (((_t)(*((_s)->pointer + 5))) << 16) + \ - (((_t)(*((_s)->pointer + 6))) << 8) + (((_t)(*((_s)->pointer + 7)))); \ - if (_p) \ - Stream_Seek(_s, sizeof(_t)); \ +#define _stream_read_n64_be(_t, _s, _v, _p) \ + do \ + { \ + (_v) = (_t)( \ + (((UINT64)(*((_s)->pointer))) << 56) + (((UINT64)(*((_s)->pointer + 1))) << 48) + \ + (((UINT64)(*((_s)->pointer + 2))) << 40) + (((UINT64)(*((_s)->pointer + 3))) << 32) + \ + (((UINT64)(*((_s)->pointer + 4))) << 24) + (((UINT64)(*((_s)->pointer + 5))) << 16) + \ + (((UINT64)(*((_s)->pointer + 6))) << 8) + (((UINT64)(*((_s)->pointer + 7))))); \ + if (_p) \ + Stream_Seek(_s, sizeof(_t)); \ } while (0) #define Stream_Read_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, TRUE) diff --git a/winpr/libwinpr/crt/test/TestAlignment.c b/winpr/libwinpr/crt/test/TestAlignment.c index 80986478f..0e4595b89 100644 --- a/winpr/libwinpr/crt/test/TestAlignment.c +++ b/winpr/libwinpr/crt/test/TestAlignment.c @@ -12,7 +12,7 @@ int TestAlignment(int argc, char* argv[]) /* Alignment should be 2^N where N is a positive integer */ alignment = 16; - offset = 5; + offset = 8; /* _aligned_malloc */ diff --git a/winpr/libwinpr/crt/utf.c b/winpr/libwinpr/crt/utf.c index 8ab7e39bb..8c8d2a841 100644 --- a/winpr/libwinpr/crt/utf.c +++ b/winpr/libwinpr/crt/utf.c @@ -257,16 +257,24 @@ static const BYTE firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC /* --------------------------------------------------------------------- */ ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sourceEnd, - BYTE** targetStart, BYTE* targetEnd, ConversionFlags flags) + BYTE** targetStart, BYTE* te, ConversionFlags flags) { - BYTE* target; + size_t pos = 0; + size_t end = 0; const WCHAR* source; - BOOL computeLength; - ConversionResult result; - computeLength = (!targetEnd) ? TRUE : FALSE; + const BOOL computeLength = (!te) ? TRUE : FALSE; + ConversionResult result = conversionOK; + + if (targetStart && te) + { + const size_t s = (size_t)*targetStart; + const size_t e = (size_t)te; + if (s > e) + return sourceIllegal; + end = e - s; + } + source = *sourceStart; - target = *targetStart; - result = conversionOK; while (source < sourceEnd) { @@ -345,12 +353,12 @@ ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sour ch = UNI_REPLACEMENT_CHAR; } - target += bytesToWrite; + pos += bytesToWrite; - if ((target > targetEnd) && (!computeLength)) + if ((pos > end) && (!computeLength)) { source = oldSource; /* Back up source pointer! */ - target -= bytesToWrite; + pos -= bytesToWrite; result = targetExhausted; break; } @@ -361,19 +369,19 @@ ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sour { /* note: everything falls through. */ case 4: - *--target = (BYTE)((ch | byteMark) & byteMask); + (*targetStart)[--pos] = (BYTE)((ch | byteMark) & byteMask); ch >>= 6; case 3: - *--target = (BYTE)((ch | byteMark) & byteMask); + (*targetStart)[--pos] = (BYTE)((ch | byteMark) & byteMask); ch >>= 6; case 2: - *--target = (BYTE)((ch | byteMark) & byteMask); + (*targetStart)[--pos] = (BYTE)((ch | byteMark) & byteMask); ch >>= 6; case 1: - *--target = (BYTE)(ch | firstByteMark[bytesToWrite]); + (*targetStart)[--pos] = (BYTE)(ch | firstByteMark[bytesToWrite]); } } else @@ -382,24 +390,27 @@ ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sour { /* note: everything falls through. */ case 4: - --target; + --pos; case 3: - --target; + --pos; case 2: - --target; + --pos; case 1: - --target; + --pos; } } - target += bytesToWrite; + pos += bytesToWrite; } *sourceStart = source; - *targetStart = target; + if (targetStart && *targetStart) + *targetStart = &(*targetStart)[pos]; + else if (targetStart) + *targetStart = (BYTE*)pos; return result; } @@ -503,14 +514,24 @@ BOOL isLegalUTF8Sequence(const BYTE* source, const BYTE* sourceEnd) ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* sourceEnd, WCHAR** targetStart, WCHAR* targetEnd, ConversionFlags flags) { - WCHAR* target; + size_t target = 0; + size_t end = 0; const BYTE* source; BOOL computeLength; ConversionResult result; computeLength = (!targetEnd) ? TRUE : FALSE; result = conversionOK; source = *sourceStart; - target = *targetStart; + + if (targetStart && targetEnd) + { + const size_t s = (size_t)*targetStart; + const size_t e = (size_t)targetEnd; + if (s > e) + return sourceIllegal; + + end = ((size_t)(targetEnd)) - ((size_t)(*targetStart)); + } while (source < sourceEnd) { @@ -561,7 +582,7 @@ ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* source ch -= offsetsFromUTF8[extraBytesToRead]; - if ((target >= targetEnd) && (!computeLength)) + if ((target >= end) && (!computeLength)) { source -= (extraBytesToRead + 1); /* Back up source pointer! */ result = targetExhausted; @@ -583,23 +604,15 @@ ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* source else { if (!computeLength) - { - Data_Write_UINT16(target, UNI_REPLACEMENT_CHAR); - target++; - } - else - target++; + Data_Write_UINT16(&(*targetStart)[target], UNI_REPLACEMENT_CHAR); + target++; } } else { if (!computeLength) - { - Data_Write_UINT16(target, ch); /* normal case */ - target++; - } - else - target++; + Data_Write_UINT16(&(*targetStart)[target], ch); /* normal case */ + target++; } } else if (ch > UNI_MAX_UTF16) @@ -613,18 +626,14 @@ ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* source else { if (!computeLength) - { - Data_Write_UINT16(target, UNI_REPLACEMENT_CHAR); - target++; - } - else - target++; + Data_Write_UINT16(&(*targetStart)[target], UNI_REPLACEMENT_CHAR); + target++; } } else { /* target is a character in range 0xFFFF - 0x10FFFF. */ - if ((target + 1 >= targetEnd) && (!computeLength)) + if ((target + 1 >= end) && (!computeLength)) { source -= (extraBytesToRead + 1); /* Back up source pointer! */ result = targetExhausted; @@ -637,11 +646,9 @@ ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* source { WCHAR wchar; wchar = (ch >> halfShift) + UNI_SUR_HIGH_START; - Data_Write_UINT16(target, wchar); - target++; + Data_Write_UINT16(&(*targetStart)[target++], wchar); wchar = (ch & halfMask) + UNI_SUR_LOW_START; - Data_Write_UINT16(target, wchar); - target++; + Data_Write_UINT16(&(*targetStart)[target++], wchar); } else { @@ -652,7 +659,10 @@ ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* source } *sourceStart = source; - *targetStart = target; + if (targetStart && (*targetStart)) + *targetStart = &(*targetStart)[target]; + else if (targetStart) + *targetStart = (WCHAR*)(target * sizeof(WCHAR)); return result; } diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index f5f33a6b2..36c43af06 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -2930,6 +2930,7 @@ unsigned int determineMacOSXVersion(void) long minorVersion = 0; long patchVersion = 0; int count = 0; + char* context = NULL; mib[0] = CTL_KERN; mib[1] = KERN_OSRELEASE; @@ -2947,7 +2948,7 @@ unsigned int determineMacOSXVersion(void) return 0; } - tok = strtok(kernelVersion, "."); + tok = strtok_s(kernelVersion, ".", &context); errno = 0; while (tok) @@ -2979,7 +2980,7 @@ unsigned int determineMacOSXVersion(void) break; } - tok = strtok(NULL, "."); + tok = strtok_s(NULL, ".", &context); count++; } diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_message.c b/winpr/libwinpr/sspi/NTLM/ntlm_message.c index 5fc6ec73b..314f5c147 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_message.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_message.c @@ -367,12 +367,16 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer) { + SECURITY_STATUS status = SEC_E_INVALID_TOKEN; wStream* s; - int length; - PBYTE StartOffset; - PBYTE PayloadOffset; + size_t length; + size_t StartOffset; + size_t PayloadOffset; NTLM_AV_PAIR* AvTimestamp; NTLM_CHALLENGE_MESSAGE* message; + if (!context || !buffer) + return SEC_E_INTERNAL_ERROR; + ntlm_generate_client_challenge(context); message = &context->CHALLENGE_MESSAGE; ZeroMemory(message, sizeof(NTLM_CHALLENGE_MESSAGE)); @@ -381,77 +385,51 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf if (!s) return SEC_E_INTERNAL_ERROR; - StartOffset = Stream_Pointer(s); + StartOffset = Stream_GetPosition(s); if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*)message) < 0) - { - Stream_Free(s, FALSE); - return SEC_E_INVALID_TOKEN; - } + goto fail; if (message->MessageType != MESSAGE_TYPE_CHALLENGE) - { - Stream_Free(s, FALSE); - return SEC_E_INVALID_TOKEN; - } + goto fail; if (ntlm_read_message_fields(s, &(message->TargetName)) < 0) /* TargetNameFields (8 bytes) */ - { - Stream_Free(s, FALSE); - return SEC_E_INVALID_TOKEN; - } + goto fail; if (Stream_GetRemainingLength(s) < 4) - { - Stream_Free(s, FALSE); - return SEC_E_INVALID_TOKEN; - } + goto fail; Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */ context->NegotiateFlags = message->NegotiateFlags; if (Stream_GetRemainingLength(s) < 8) - { - Stream_Free(s, FALSE); - return SEC_E_INVALID_TOKEN; - } + goto fail; Stream_Read(s, message->ServerChallenge, 8); /* ServerChallenge (8 bytes) */ CopyMemory(context->ServerChallenge, message->ServerChallenge, 8); if (Stream_GetRemainingLength(s) < 8) - { - Stream_Free(s, FALSE); - return SEC_E_INVALID_TOKEN; - } + goto fail; Stream_Read(s, message->Reserved, 8); /* Reserved (8 bytes), should be ignored */ if (ntlm_read_message_fields(s, &(message->TargetInfo)) < 0) /* TargetInfoFields (8 bytes) */ - { - Stream_Free(s, FALSE); - return SEC_E_INVALID_TOKEN; - } + goto fail; if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) { if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */ - { - Stream_Free(s, FALSE); - return SEC_E_INVALID_TOKEN; - } + goto fail; } /* Payload (variable) */ - PayloadOffset = Stream_Pointer(s); + PayloadOffset = Stream_GetPosition(s); + status = SEC_E_INTERNAL_ERROR; if (message->TargetName.Len > 0) { if (ntlm_read_message_fields_buffer(s, &(message->TargetName)) < 0) - { - Stream_Free(s, FALSE); - return SEC_E_INTERNAL_ERROR; - } + goto fail; } if (message->TargetInfo.Len > 0) @@ -459,10 +437,7 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf size_t cbAvTimestamp; if (ntlm_read_message_fields_buffer(s, &(message->TargetInfo)) < 0) - { - Stream_Free(s, FALSE); - return SEC_E_INTERNAL_ERROR; - } + goto fail; context->ChallengeTargetInfo.pvBuffer = message->TargetInfo.Buffer; context->ChallengeTargetInfo.cbBuffer = message->TargetInfo.Len; @@ -474,7 +449,7 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf PBYTE ptr = ntlm_av_pair_get_value_pointer(AvTimestamp); if (!ptr) - return SEC_E_INTERNAL_ERROR; + goto fail; if (context->NTLMv2) context->UseMIC = TRUE; @@ -484,14 +459,14 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf } length = (PayloadOffset - StartOffset) + message->TargetName.Len + message->TargetInfo.Len; + if (length > buffer->cbBuffer) + goto fail; if (!sspi_SecBufferAlloc(&context->ChallengeMessage, length)) - { - Stream_Free(s, FALSE); - return SEC_E_INTERNAL_ERROR; - } + goto fail; - CopyMemory(context->ChallengeMessage.pvBuffer, StartOffset, length); + if (context->ChallengeMessage.pvBuffer) + CopyMemory(context->ChallengeMessage.pvBuffer, Stream_Buffer(s) + StartOffset, length); #ifdef WITH_DEBUG_NTLM WLog_DBG(TAG, "CHALLENGE_MESSAGE (length = %d)", length); winpr_HexDump(TAG, WLOG_DEBUG, context->ChallengeMessage.pvBuffer, @@ -517,10 +492,7 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf if (context->NTLMv2) { if (ntlm_construct_authenticate_target_info(context) < 0) - { - Stream_Free(s, FALSE); - return SEC_E_INTERNAL_ERROR; - } + goto fail; sspi_SecBufferFree(&context->ChallengeTargetInfo); context->ChallengeTargetInfo.pvBuffer = context->AuthenticateTargetInfo.pvBuffer; @@ -530,16 +502,10 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf ntlm_generate_timestamp(context); /* Timestamp */ if (ntlm_compute_lm_v2_response(context) < 0) /* LmChallengeResponse */ - { - Stream_Free(s, FALSE); - return SEC_E_INTERNAL_ERROR; - } + goto fail; if (ntlm_compute_ntlm_v2_response(context) < 0) /* NtChallengeResponse */ - { - Stream_Free(s, FALSE); - return SEC_E_INTERNAL_ERROR; - } + goto fail; ntlm_generate_key_exchange_key(context); /* KeyExchangeKey */ ntlm_generate_random_session_key(context); /* RandomSessionKey */ @@ -579,8 +545,10 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf #endif context->state = NTLM_STATE_AUTHENTICATE; ntlm_free_message_fields_buffer(&(message->TargetName)); + status = SEC_I_CONTINUE_NEEDED; +fail: Stream_Free(s, FALSE); - return SEC_I_CONTINUE_NEEDED; + return status; } SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer) diff --git a/winpr/libwinpr/sspi/sspi_winpr.c b/winpr/libwinpr/sspi/sspi_winpr.c index 5bd897d02..7db9b0e00 100644 --- a/winpr/libwinpr/sspi/sspi_winpr.c +++ b/winpr/libwinpr/sspi/sspi_winpr.c @@ -241,9 +241,12 @@ void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials) passwordLength *= 2; } - memset(credentials->identity.User, 0, userLength); - memset(credentials->identity.Domain, 0, domainLength); - memset(credentials->identity.Password, 0, passwordLength); + if (credentials->identity.User) + memset(credentials->identity.User, 0, userLength); + if (credentials->identity.Domain) + memset(credentials->identity.Domain, 0, domainLength); + if (credentials->identity.Password) + memset(credentials->identity.Password, 0, passwordLength); free(credentials->identity.User); free(credentials->identity.Domain); free(credentials->identity.Password); diff --git a/winpr/libwinpr/sspi/test/TestNTLM.c b/winpr/libwinpr/sspi/test/TestNTLM.c index 83abe70db..82d266fe6 100644 --- a/winpr/libwinpr/sspi/test/TestNTLM.c +++ b/winpr/libwinpr/sspi/test/TestNTLM.c @@ -470,10 +470,15 @@ void test_ntlm_server_free(TEST_NTLM_SERVER* ntlm) int TestNTLM(int argc, char* argv[]) { int status; + int rc = -1; PSecBuffer pSecBuffer; - TEST_NTLM_CLIENT* client; - TEST_NTLM_SERVER* server; + TEST_NTLM_CLIENT* client = NULL; + TEST_NTLM_SERVER* server = NULL; BOOL DynamicTest = TRUE; + + WINPR_UNUSED(argc); + WINPR_UNUSED(argv); + /** * Client Initialization */ @@ -482,7 +487,7 @@ int TestNTLM(int argc, char* argv[]) if (!client) { printf("Memory allocation failed"); - return -1; + goto fail; } status = test_ntlm_client_init(client, TEST_NTLM_USER, TEST_NTLM_DOMAIN, TEST_NTLM_PASSWORD); @@ -490,7 +495,7 @@ int TestNTLM(int argc, char* argv[]) if (status < 0) { printf("test_ntlm_client_init failure\n"); - return -1; + goto fail; } /** @@ -501,7 +506,7 @@ int TestNTLM(int argc, char* argv[]) if (!server) { printf("Memory allocation failed\n"); - return -1; + goto fail; } status = test_ntlm_server_init(server); @@ -509,7 +514,7 @@ int TestNTLM(int argc, char* argv[]) if (status < 0) { printf("test_ntlm_server_init failure\n"); - return -1; + goto fail; } /** @@ -520,7 +525,7 @@ int TestNTLM(int argc, char* argv[]) if (status < 0) { printf("test_ntlm_client_authenticate failure\n"); - return -1; + goto fail; } if (!DynamicTest) @@ -557,7 +562,7 @@ int TestNTLM(int argc, char* argv[]) if (!pSecBuffer->pvBuffer) { printf("Memory allocation failed\n"); - return -1; + goto fail; } CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_NEGOTIATE, pSecBuffer->cbBuffer); @@ -578,7 +583,7 @@ int TestNTLM(int argc, char* argv[]) if (status < 0) { printf("test_ntlm_server_authenticate failure\n"); - return -1; + goto fail; } if (!DynamicTest) @@ -616,7 +621,7 @@ int TestNTLM(int argc, char* argv[]) if (!pSecBuffer->pvBuffer) { printf("Memory allocation failed\n"); - return -1; + goto fail; } CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_CHALLENGE, pSecBuffer->cbBuffer); @@ -643,7 +648,7 @@ int TestNTLM(int argc, char* argv[]) if (status < 0) { printf("test_ntlm_client_authenticate failure\n"); - return -1; + goto fail; } pSecBuffer = &(client->outputBuffer[0]); @@ -656,7 +661,7 @@ int TestNTLM(int argc, char* argv[]) if (!pSecBuffer->pvBuffer) { printf("Memory allocation failed\n"); - return -1; + goto fail; } CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_AUTHENTICATE, pSecBuffer->cbBuffer); @@ -676,13 +681,16 @@ int TestNTLM(int argc, char* argv[]) if (status < 0) { printf("test_ntlm_server_authenticate failure\n"); - return -1; + goto fail; } + rc = 0; + +fail: /** * Cleanup & Termination */ test_ntlm_client_free(client); test_ntlm_server_free(server); - return 0; + return rc; } diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index 80bc51c2a..5475cb67a 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -248,12 +248,14 @@ static BOOL winpr_match_unix_timezone_identifier_with_list(const char* tzid, con { char* p; char* list_copy; + char* context = NULL; + list_copy = _strdup(list); if (!list_copy) return FALSE; - p = strtok(list_copy, " "); + p = strtok_s(list_copy, " ", &context); while (p != NULL) { @@ -263,7 +265,7 @@ static BOOL winpr_match_unix_timezone_identifier_with_list(const char* tzid, con return TRUE; } - p = strtok(NULL, " "); + p = strtok_s(NULL, " ", &context); } free(list_copy); diff --git a/winpr/libwinpr/utils/collections/PubSub.c b/winpr/libwinpr/utils/collections/PubSub.c index f0a19485f..466dde689 100644 --- a/winpr/libwinpr/utils/collections/PubSub.c +++ b/winpr/libwinpr/utils/collections/PubSub.c @@ -112,15 +112,10 @@ int PubSub_Subscribe(wPubSub* pubSub, const char* EventName, pEventHandler Event { status = 0; - if (event->EventHandlerCount <= MAX_EVENT_HANDLERS) - { - event->EventHandlers[event->EventHandlerCount] = EventHandler; - event->EventHandlerCount++; - } + if (event->EventHandlerCount < MAX_EVENT_HANDLERS) + event->EventHandlers[event->EventHandlerCount++] = EventHandler; else - { status = -1; - } } if (pubSub->synchronized) diff --git a/winpr/libwinpr/utils/ini.c b/winpr/libwinpr/utils/ini.c index e1a20e716..656ca6acf 100644 --- a/winpr/libwinpr/utils/ini.c +++ b/winpr/libwinpr/utils/ini.c @@ -206,6 +206,16 @@ static char* IniFile_Load_GetNextLine(wIniFile* ini) return ini->line; } +static void IniFile_Key_Free(wIniFileKey* key) +{ + if (!key) + return; + + free(key->name); + free(key->value); + free(key); +} + static wIniFileKey* IniFile_Key_New(const char* name, const char* value) { wIniFileKey* key; @@ -222,9 +232,7 @@ static wIniFileKey* IniFile_Key_New(const char* name, const char* value) if (!key->name || !key->value) { - free(key->name); - free(key->value); - free(key); + IniFile_Key_Free(key); return NULL; } } @@ -232,16 +240,6 @@ static wIniFileKey* IniFile_Key_New(const char* name, const char* value) return key; } -static void IniFile_Key_Free(wIniFileKey* key) -{ - if (!key) - return; - - free(key->name); - free(key->value); - free(key); -} - static wIniFileSection* IniFile_Section_New(const char* name) { wIniFileSection* section; @@ -821,5 +819,6 @@ void IniFile_Free(wIniFile* ini) IniFile_Section_Free(ini->sections[index]); free(ini->sections); + free(ini->buffer); free(ini); } diff --git a/winpr/libwinpr/utils/lodepng/lodepng.c b/winpr/libwinpr/utils/lodepng/lodepng.c index 227d46906..87f85080e 100644 --- a/winpr/libwinpr/utils/lodepng/lodepng.c +++ b/winpr/libwinpr/utils/lodepng/lodepng.c @@ -327,7 +327,8 @@ static void string_set(char** out, const char* in) static unsigned lodepng_read32bitInt(const unsigned char* buffer) { - return (unsigned)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); + return (unsigned)(((unsigned)buffer[0] << 24) | ((unsigned)buffer[1] << 16) | + ((unsigned)buffer[2] << 8) | buffer[3]); } #if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) diff --git a/winpr/libwinpr/utils/sam.c b/winpr/libwinpr/utils/sam.c index b76302477..b4af5b34b 100644 --- a/winpr/libwinpr/utils/sam.c +++ b/winpr/libwinpr/utils/sam.c @@ -43,6 +43,15 @@ #endif #define TAG WINPR_TAG("utils") +struct winpr_sam +{ + FILE* fp; + char* line; + char* buffer; + char* context; + BOOL readOnly; +}; + WINPR_SAM* SamOpen(const char* filename, BOOL readOnly) { FILE* fp = NULL; @@ -98,6 +107,7 @@ static BOOL SamLookupStart(WINPR_SAM* sam) if (fileSize < 1) return FALSE; + sam->context = NULL; sam->buffer = (char*)malloc(fileSize + 2); if (!sam->buffer) @@ -120,7 +130,7 @@ static BOOL SamLookupStart(WINPR_SAM* sam) sam->buffer[fileSize] = '\n'; sam->buffer[fileSize + 1] = '\0'; - sam->line = strtok(sam->buffer, "\n"); + sam->line = strtok_s(sam->buffer, "\n", &sam->context); return TRUE; } @@ -300,7 +310,7 @@ WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, L } SamResetEntry(entry); - sam->line = strtok(NULL, "\n"); + sam->line = strtok_s(NULL, "\n", &sam->context); } out_fail: @@ -415,7 +425,7 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, } SamResetEntry(entry); - sam->line = strtok(NULL, "\n"); + sam->line = strtok_s(NULL, "\n", &sam->context); } out_fail: diff --git a/winpr/libwinpr/utils/test/TestIni.c b/winpr/libwinpr/utils/test/TestIni.c index 9734072fd..9a07769d7 100644 --- a/winpr/libwinpr/utils/test/TestIni.c +++ b/winpr/libwinpr/utils/test/TestIni.c @@ -38,40 +38,48 @@ const char TEST_INI_03[] = "[FreeRDS]\n" int TestIni(int argc, char* argv[]) { + int rc = -1; int i, j; int nKeys; int nSections; UINT32 iValue; - wIniFile* ini; + wIniFile* ini = NULL; const char* sValue; - char** keyNames; - char** sectionNames; + char** keyNames = NULL; + char** sectionNames = NULL; /* First Sample */ ini = IniFile_New(); - IniFile_ReadBuffer(ini, TEST_INI_01); + if (!ini) + goto fail; + + if (IniFile_ReadBuffer(ini, TEST_INI_01) < 0) + goto fail; + + free(sectionNames); sectionNames = IniFile_GetSectionNames(ini, &nSections); + if (!sectionNames && (nSections > 0)) + goto fail; for (i = 0; i < nSections; i++) { + free(keyNames); keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys); printf("[%s]\n", sectionNames[i]); - + if (!keyNames && (nKeys > 0)) + goto fail; for (j = 0; j < nKeys; j++) { sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]); printf("%s = %s\n", keyNames[j], sValue); } - - free(keyNames); } - free(sectionNames); iValue = IniFile_GetKeyValueInt(ini, "first_section", "one"); if (iValue != 1) { printf("IniFile_GetKeyValueInt failure\n"); - return -1; + goto fail; } iValue = IniFile_GetKeyValueInt(ini, "first_section", "five"); @@ -79,7 +87,7 @@ int TestIni(int argc, char* argv[]) if (iValue != 5) { printf("IniFile_GetKeyValueInt failure\n"); - return -1; + goto fail; } sValue = IniFile_GetKeyValueString(ini, "first_section", "animal"); @@ -87,7 +95,7 @@ int TestIni(int argc, char* argv[]) if (strcmp(sValue, "BIRD") != 0) { printf("IniFile_GetKeyValueString failure\n"); - return -1; + goto fail; } sValue = IniFile_GetKeyValueString(ini, "second_section", "path"); @@ -95,7 +103,7 @@ int TestIni(int argc, char* argv[]) if (strcmp(sValue, "/usr/local/bin") != 0) { printf("IniFile_GetKeyValueString failure\n"); - return -1; + goto fail; } sValue = IniFile_GetKeyValueString(ini, "second_section", "URL"); @@ -103,40 +111,47 @@ int TestIni(int argc, char* argv[]) if (strcmp(sValue, "http://www.example.com/~username") != 0) { printf("IniFile_GetKeyValueString failure\n"); - return -1; + goto fail; } IniFile_Free(ini); /* Second Sample */ ini = IniFile_New(); - IniFile_ReadBuffer(ini, TEST_INI_02); + if (!ini) + goto fail; + if (IniFile_ReadBuffer(ini, TEST_INI_02) < 0) + goto fail; + free(sectionNames); sectionNames = IniFile_GetSectionNames(ini, &nSections); + if (!sectionNames && (nSections > 0)) + goto fail; for (i = 0; i < nSections; i++) { + free(keyNames); keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys); printf("[%s]\n", sectionNames[i]); + if (!keyNames && (nKeys > 0)) + goto fail; for (j = 0; j < nKeys; j++) { sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]); printf("%s = %s\n", keyNames[j], sValue); } - - free(keyNames); } - free(sectionNames); IniFile_Free(ini); /* Third sample - invalid input */ ini = IniFile_New(); if (IniFile_ReadBuffer(ini, TEST_INI_03) != -1) - { - IniFile_Free(ini); - return -1; - } + goto fail; + rc = 0; +fail: + free(keyNames); + free(sectionNames); IniFile_Free(ini); return 0; } diff --git a/winpr/tools/makecert-cli/winpr-makecert.1.in b/winpr/tools/makecert-cli/winpr-makecert.1.in index 57be0ffbb..9478b5212 100644 --- a/winpr/tools/makecert-cli/winpr-makecert.1.in +++ b/winpr/tools/makecert-cli/winpr-makecert.1.in @@ -106,7 +106,7 @@ The certificate has the serial number 22 and is valid for 12 years (144 months). Successful program execution. .TP .B 1 -Otherweise. +Otherwise. .SH SEE ALSO |