commit
ed3d9526b2
@ -283,6 +283,8 @@ void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
|
|||||||
free(listener);
|
free(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dvcman->num_listeners = 0;
|
||||||
|
|
||||||
for (i = 0; i < dvcman->num_plugins; i++)
|
for (i = 0; i < dvcman->num_plugins; i++)
|
||||||
{
|
{
|
||||||
pPlugin = dvcman->plugins[i];
|
pPlugin = dvcman->plugins[i];
|
||||||
@ -291,7 +293,10 @@ void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
|
|||||||
pPlugin->Terminated(pPlugin);
|
pPlugin->Terminated(pPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dvcman->num_plugins = 0;
|
||||||
|
|
||||||
StreamPool_Free(dvcman->pool);
|
StreamPool_Free(dvcman->pool);
|
||||||
|
|
||||||
free(dvcman);
|
free(dvcman);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,7 +553,7 @@ int drdynvc_send(drdynvcPlugin* drdynvc, wStream* s)
|
|||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,7 +643,7 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
|
|||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
drdynvc->channel_error = status;
|
drdynvc->channel_error = status;
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -659,7 +664,7 @@ static int drdynvc_send_capability_response(drdynvcPlugin* drdynvc)
|
|||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -766,7 +771,7 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb
|
|||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -830,7 +835,7 @@ static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbC
|
|||||||
|
|
||||||
if (error != CHANNEL_RC_OK)
|
if (error != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||||
WTSErrorToString(error), error);
|
WTSErrorToString(error), error);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -968,7 +973,7 @@ static void drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
|
|||||||
{
|
{
|
||||||
if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
|
if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "drdynvc_plugin_process_received: read error");
|
WLog_ERR(TAG, "drdynvc_plugin_process_received: read error");
|
||||||
}
|
}
|
||||||
|
|
||||||
drdynvc->data_in = NULL;
|
drdynvc->data_in = NULL;
|
||||||
@ -988,7 +993,7 @@ static VOID VCAPITYPE drdynvc_virtual_channel_open_event(DWORD openHandle, UINT
|
|||||||
|
|
||||||
if (!drdynvc)
|
if (!drdynvc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match");
|
WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1050,7 +1055,7 @@ static void drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO
|
|||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
||||||
WTSErrorToString(status), status);
|
WTSErrorToString(status), status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1078,7 +1083,7 @@ static void drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO
|
|||||||
|
|
||||||
static void drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
|
static void drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
|
||||||
{
|
{
|
||||||
UINT rc;
|
UINT status;
|
||||||
|
|
||||||
MessageQueue_PostQuit(drdynvc->queue, 0);
|
MessageQueue_PostQuit(drdynvc->queue, 0);
|
||||||
WaitForSingleObject(drdynvc->thread, INFINITE);
|
WaitForSingleObject(drdynvc->thread, INFINITE);
|
||||||
@ -1089,11 +1094,12 @@ static void drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
|
|||||||
drdynvc->queue = NULL;
|
drdynvc->queue = NULL;
|
||||||
drdynvc->thread = NULL;
|
drdynvc->thread = NULL;
|
||||||
|
|
||||||
rc = drdynvc->channelEntryPoints.pVirtualChannelClose(drdynvc->OpenHandle);
|
status = drdynvc->channelEntryPoints.pVirtualChannelClose(drdynvc->OpenHandle);
|
||||||
if (CHANNEL_RC_OK != rc)
|
|
||||||
|
if (status != CHANNEL_RC_OK)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
||||||
WTSErrorToString(rc), rc);
|
WTSErrorToString(status), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drdynvc->data_in)
|
if (drdynvc->data_in)
|
||||||
@ -1125,7 +1131,7 @@ static VOID VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle, UIN
|
|||||||
|
|
||||||
if (!drdynvc)
|
if (!drdynvc)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "drdynvc_virtual_channel_init_event: error no match");
|
WLog_ERR(TAG, "drdynvc_virtual_channel_init_event: error no match");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,9 +22,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
#include <winpr/wlog.h>
|
#include <winpr/wlog.h>
|
||||||
@ -955,9 +952,16 @@ static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin)
|
|||||||
WLog_Print(gfx->log, WLOG_DEBUG, "Terminated");
|
WLog_Print(gfx->log, WLOG_DEBUG, "Terminated");
|
||||||
|
|
||||||
if (gfx->listener_callback)
|
if (gfx->listener_callback)
|
||||||
|
{
|
||||||
free(gfx->listener_callback);
|
free(gfx->listener_callback);
|
||||||
|
gfx->listener_callback = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
zgfx_context_free(gfx->zgfx);
|
if (gfx->zgfx)
|
||||||
|
{
|
||||||
|
zgfx_context_free(gfx->zgfx);
|
||||||
|
gfx->zgfx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
count = HashTable_GetKeys(gfx->SurfaceTable, &pKeys);
|
count = HashTable_GetKeys(gfx->SurfaceTable, &pKeys);
|
||||||
|
|
||||||
@ -1124,8 +1128,8 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
|||||||
|
|
||||||
if (!gfx->zgfx)
|
if (!gfx->zgfx)
|
||||||
{
|
{
|
||||||
free (gfx);
|
free(gfx);
|
||||||
free (context);
|
free(context);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,6 @@ int main(int argc, char* argv[])
|
|||||||
thread = freerdp_client_get_thread(context);
|
thread = freerdp_client_get_thread(context);
|
||||||
|
|
||||||
WaitForSingleObject(thread, INFINITE);
|
WaitForSingleObject(thread, INFINITE);
|
||||||
|
|
||||||
GetExitCodeThread(thread, &dwExitCode);
|
GetExitCodeThread(thread, &dwExitCode);
|
||||||
|
|
||||||
freerdp_client_stop(context);
|
freerdp_client_stop(context);
|
||||||
|
@ -203,7 +203,7 @@ void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h)
|
|||||||
{
|
{
|
||||||
if (w == 0 || h == 0)
|
if (w == 0 || h == 0)
|
||||||
{
|
{
|
||||||
WLog_WARN(TAG, "invalid width and/or height specified: w=%d h=%d", w, h);
|
WLog_WARN(TAG, "invalid width and/or height specified: w=%d h=%d", w, h);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -788,7 +788,6 @@ int _xf_error_handler(Display* d, XErrorEvent* ev)
|
|||||||
static void xf_post_disconnect(freerdp* instance)
|
static void xf_post_disconnect(freerdp* instance)
|
||||||
{
|
{
|
||||||
xfContext* xfc;
|
xfContext* xfc;
|
||||||
rdpChannels* channels = channels = instance->context->channels;
|
|
||||||
|
|
||||||
if (!instance || !instance->context || !instance->settings)
|
if (!instance || !instance->context || !instance->settings)
|
||||||
return;
|
return;
|
||||||
@ -895,7 +894,7 @@ BOOL xf_pre_connect(freerdp* instance)
|
|||||||
{
|
{
|
||||||
if (!XInitThreads())
|
if (!XInitThreads())
|
||||||
{
|
{
|
||||||
WLog_WARN(TAG, "XInitThreads() failure");
|
WLog_WARN(TAG, "XInitThreads() failure");
|
||||||
xfc->UseXThreads = FALSE;
|
xfc->UseXThreads = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -911,7 +910,7 @@ BOOL xf_pre_connect(freerdp* instance)
|
|||||||
|
|
||||||
if (xfc->debug)
|
if (xfc->debug)
|
||||||
{
|
{
|
||||||
WLog_INFO(TAG, "Enabling X11 debug mode.");
|
WLog_INFO(TAG, "Enabling X11 debug mode.");
|
||||||
XSynchronize(xfc->display, TRUE);
|
XSynchronize(xfc->display, TRUE);
|
||||||
_def_error_handler = XSetErrorHandler(_xf_error_handler);
|
_def_error_handler = XSetErrorHandler(_xf_error_handler);
|
||||||
}
|
}
|
||||||
@ -1127,6 +1126,7 @@ BOOL xf_post_connect(freerdp *instance)
|
|||||||
palette_cache_register_callbacks(instance->update);
|
palette_cache_register_callbacks(instance->update);
|
||||||
instance->update->BitmapUpdate = xf_gdi_bitmap_update;
|
instance->update->BitmapUpdate = xf_gdi_bitmap_update;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->update->PlaySound = xf_play_sound;
|
instance->update->PlaySound = xf_play_sound;
|
||||||
instance->update->SetKeyboardIndicators = xf_keyboard_set_indicators;
|
instance->update->SetKeyboardIndicators = xf_keyboard_set_indicators;
|
||||||
|
|
||||||
@ -1360,39 +1360,44 @@ void* xf_input_thread(void *arg)
|
|||||||
|
|
||||||
BOOL xf_auto_reconnect(freerdp* instance)
|
BOOL xf_auto_reconnect(freerdp* instance)
|
||||||
{
|
{
|
||||||
|
UINT32 maxRetries;
|
||||||
|
UINT32 numRetries = 0;
|
||||||
xfContext* xfc = (xfContext*) instance->context;
|
xfContext* xfc = (xfContext*) instance->context;
|
||||||
UINT32 num_retries = 0;
|
rdpSettings* settings = xfc->settings;
|
||||||
UINT32 max_retries = instance->settings->AutoReconnectMaxRetries;
|
|
||||||
|
maxRetries = settings->AutoReconnectMaxRetries;
|
||||||
|
|
||||||
/* Only auto reconnect on network disconnects. */
|
/* Only auto reconnect on network disconnects. */
|
||||||
if (freerdp_error_info(instance) != 0)
|
if (freerdp_error_info(instance) != 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* A network disconnect was detected */
|
/* A network disconnect was detected */
|
||||||
WLog_INFO(TAG, "Network disconnect!");
|
WLog_INFO(TAG, "Network disconnect!");
|
||||||
|
|
||||||
if (!instance->settings->AutoReconnectionEnabled)
|
if (!settings->AutoReconnectionEnabled)
|
||||||
{
|
{
|
||||||
/* No auto-reconnect - just quit */
|
/* No auto-reconnect - just quit */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform an auto-reconnect. */
|
/* Perform an auto-reconnect. */
|
||||||
for (;;)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
/* Quit retrying if max retries has been exceeded */
|
/* Quit retrying if max retries has been exceeded */
|
||||||
if (num_retries++ >= max_retries)
|
if (numRetries++ >= maxRetries)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempt the next reconnect */
|
/* Attempt the next reconnect */
|
||||||
WLog_INFO(TAG, "Attempting reconnect (%u of %u)", num_retries, max_retries);
|
WLog_INFO(TAG, "Attempting reconnect (%u of %u)", numRetries, maxRetries);
|
||||||
|
|
||||||
if (freerdp_reconnect(instance))
|
if (freerdp_reconnect(instance))
|
||||||
{
|
{
|
||||||
xfc->disconnect = FALSE;
|
xfc->disconnect = FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(5);
|
sleep(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1487,7 +1492,7 @@ void* xf_client_thread(void *param)
|
|||||||
nCount += freerdp_get_event_handles(context, &handles[nCount]);
|
nCount += freerdp_get_event_handles(context, &handles[nCount]);
|
||||||
}
|
}
|
||||||
|
|
||||||
waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
|
waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, 100);
|
||||||
|
|
||||||
if (!settings->AsyncTransport)
|
if (!settings->AsyncTransport)
|
||||||
{
|
{
|
||||||
@ -1642,9 +1647,13 @@ static int xfreerdp_client_start(rdpContext* context)
|
|||||||
WLog_ERR(TAG, "error: server hostname was not specified with /v:<server>[:port]");
|
WLog_ERR(TAG, "error: server hostname was not specified with /v:<server>[:port]");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfc->disconnect = FALSE;
|
xfc->disconnect = FALSE;
|
||||||
xfc->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_client_thread,
|
|
||||||
context->instance, 0, NULL);
|
xfc->thread = CreateThread(NULL, 0,
|
||||||
|
(LPTHREAD_START_ROUTINE) xf_client_thread,
|
||||||
|
context->instance, 0, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1654,8 +1663,10 @@ static int xfreerdp_client_stop(rdpContext* context)
|
|||||||
|
|
||||||
if (context->settings->AsyncInput)
|
if (context->settings->AsyncInput)
|
||||||
{
|
{
|
||||||
wMessageQueue *queue;
|
wMessageQueue* queue;
|
||||||
|
|
||||||
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
|
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
|
||||||
|
|
||||||
if (queue)
|
if (queue)
|
||||||
MessageQueue_PostQuit(queue, 0);
|
MessageQueue_PostQuit(queue, 0);
|
||||||
}
|
}
|
||||||
@ -1666,6 +1677,7 @@ static int xfreerdp_client_stop(rdpContext* context)
|
|||||||
|
|
||||||
if (xfc->thread)
|
if (xfc->thread)
|
||||||
{
|
{
|
||||||
|
WaitForSingleObject(xfc->thread, INFINITE);
|
||||||
CloseHandle(xfc->thread);
|
CloseHandle(xfc->thread);
|
||||||
xfc->thread = NULL;
|
xfc->thread = NULL;
|
||||||
}
|
}
|
||||||
@ -1706,26 +1718,45 @@ static void xfreerdp_client_free(freerdp* instance, rdpContext* context)
|
|||||||
{
|
{
|
||||||
xfContext* xfc = (xfContext*) context;
|
xfContext* xfc = (xfContext*) context;
|
||||||
|
|
||||||
if (context)
|
if (!context)
|
||||||
|
return;
|
||||||
|
|
||||||
|
xf_window_free(xfc);
|
||||||
|
|
||||||
|
if (xfc->bitmap_buffer)
|
||||||
{
|
{
|
||||||
xf_window_free(xfc);
|
_aligned_free(xfc->bitmap_buffer);
|
||||||
|
xfc->bitmap_buffer = NULL;
|
||||||
if (xfc->bitmap_buffer)
|
|
||||||
_aligned_free(xfc->bitmap_buffer);
|
|
||||||
|
|
||||||
if (xfc->display)
|
|
||||||
XCloseDisplay(xfc->display);
|
|
||||||
|
|
||||||
if (xfc->x11event)
|
|
||||||
CloseHandle(xfc->x11event);
|
|
||||||
|
|
||||||
if (context->channels)
|
|
||||||
{
|
|
||||||
freerdp_channels_close(context->channels, instance);
|
|
||||||
freerdp_channels_free(context->channels);
|
|
||||||
context->channels = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xfc->display)
|
||||||
|
{
|
||||||
|
XCloseDisplay(xfc->display);
|
||||||
|
xfc->display = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xfc->x11event)
|
||||||
|
{
|
||||||
|
CloseHandle(xfc->x11event);
|
||||||
|
xfc->x11event = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->channels)
|
||||||
|
{
|
||||||
|
freerdp_channels_close(context->channels, instance);
|
||||||
|
freerdp_channels_free(context->channels);
|
||||||
|
context->channels = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xfc->mutex)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(xfc->mutex, INFINITE);
|
||||||
|
CloseHandle(xfc->mutex);
|
||||||
|
xfc->mutex = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
xf_monitors_free(xfc, instance->settings);
|
||||||
|
gdi_free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
|
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
|
||||||
|
@ -26,58 +26,87 @@
|
|||||||
|
|
||||||
#define TAG CLIENT_TAG("x11")
|
#define TAG CLIENT_TAG("x11")
|
||||||
|
|
||||||
|
static int xf_call_for_each_surface(xfContext* xfc, wArrayList* surfaceList, int (*processSurface)(xfContext*, xfGfxSurface*, void*), void* param)
|
||||||
|
{
|
||||||
|
int status = 1;
|
||||||
|
int surfaceIndex;
|
||||||
|
RdpgfxClientContext* context = xfc->gfx;
|
||||||
|
|
||||||
|
/* Iterating backwards to be able to remove surfaces from the list */
|
||||||
|
surfaceIndex = ArrayList_Count(surfaceList) - 1;
|
||||||
|
|
||||||
|
for (; surfaceIndex >= 0; surfaceIndex--)
|
||||||
|
{
|
||||||
|
UINT32 surfaceId;
|
||||||
|
xfGfxSurface* surface;
|
||||||
|
|
||||||
|
surfaceId = (UINT32) (ULONG_PTR) ArrayList_GetItem(xfc->gfxMappedSurfaceIds, surfaceIndex);
|
||||||
|
surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceId);
|
||||||
|
|
||||||
|
if (!surface)
|
||||||
|
{
|
||||||
|
ArrayList_RemoveAt(surfaceList, surfaceIndex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processSurface(xfc, surface, param) < 0)
|
||||||
|
status = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_clearInvalidRegion(xfContext* xfc, xfGfxSurface* surface, void* param)
|
||||||
|
{
|
||||||
|
region16_clear(&surface->invalidRegion);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
|
int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
|
||||||
{
|
{
|
||||||
xfContext* xfc = (xfContext*) context->custom;
|
xfContext* xfc = (xfContext*) context->custom;
|
||||||
|
|
||||||
freerdp_client_codecs_reset(xfc->codecs, FREERDP_CODEC_ALL);
|
freerdp_client_codecs_reset(xfc->codecs, FREERDP_CODEC_ALL);
|
||||||
|
|
||||||
region16_uninit(&(xfc->invalidRegion));
|
xf_call_for_each_surface(xfc, xfc->gfxMappedSurfaceIds, do_clearInvalidRegion, NULL);
|
||||||
region16_init(&(xfc->invalidRegion));
|
|
||||||
|
|
||||||
xfc->graphicsReset = TRUE;
|
xfc->graphicsReset = TRUE;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xf_OutputUpdate(xfContext* xfc)
|
int xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
|
||||||
{
|
{
|
||||||
UINT16 width, height;
|
UINT16 width, height;
|
||||||
xfGfxSurface* surface;
|
UINT32 surfaceX, surfaceY;
|
||||||
RECTANGLE_16 surfaceRect;
|
RECTANGLE_16 surfaceRect;
|
||||||
const RECTANGLE_16* extents;
|
const RECTANGLE_16* extents;
|
||||||
|
|
||||||
if (!xfc->graphicsReset)
|
surfaceX = surface->mapping.output.originX;
|
||||||
return 1;
|
surfaceY = surface->mapping.output.originY;
|
||||||
|
|
||||||
surface = (xfGfxSurface*) xfc->gfx->GetSurfaceData(xfc->gfx, xfc->outputSurfaceId);
|
surfaceRect.left = surfaceX;
|
||||||
|
surfaceRect.top = surfaceY;
|
||||||
if (!surface)
|
surfaceRect.right = surfaceX + surface->width;
|
||||||
return -1;
|
surfaceRect.bottom = surfaceY + surface->height;
|
||||||
|
|
||||||
surfaceRect.left = 0;
|
|
||||||
surfaceRect.top = 0;
|
|
||||||
surfaceRect.right = xfc->width;
|
|
||||||
surfaceRect.bottom = xfc->height;
|
|
||||||
|
|
||||||
region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect);
|
|
||||||
|
|
||||||
XSetClipMask(xfc->display, xfc->gc, None);
|
XSetClipMask(xfc->display, xfc->gc, None);
|
||||||
XSetFunction(xfc->display, xfc->gc, GXcopy);
|
XSetFunction(xfc->display, xfc->gc, GXcopy);
|
||||||
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
|
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
|
||||||
|
|
||||||
if (!region16_is_empty(&(xfc->invalidRegion)))
|
if (!region16_is_empty(&surface->invalidRegion))
|
||||||
{
|
{
|
||||||
extents = region16_extents(&(xfc->invalidRegion));
|
extents = region16_extents(&surface->invalidRegion);
|
||||||
|
|
||||||
width = extents->right - extents->left;
|
width = extents->right - extents->left;
|
||||||
height = extents->bottom - extents->top;
|
height = extents->bottom - extents->top;
|
||||||
|
|
||||||
if (width > xfc->width)
|
if (width > surface->width)
|
||||||
width = xfc->width;
|
width = surface->width;
|
||||||
|
|
||||||
if (height > xfc->height)
|
if (height > surface->height)
|
||||||
height = xfc->height;
|
height = surface->height;
|
||||||
|
|
||||||
if (surface->stage)
|
if (surface->stage)
|
||||||
{
|
{
|
||||||
@ -89,7 +118,7 @@ int xf_OutputUpdate(xfContext* xfc)
|
|||||||
if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures)
|
if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures)
|
||||||
{
|
{
|
||||||
XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image,
|
XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image,
|
||||||
extents->left, extents->top, extents->left, extents->top, width, height);
|
extents->left, extents->top, extents->left + surfaceX, extents->top + surfaceY, width, height);
|
||||||
|
|
||||||
xf_draw_screen(xfc, extents->left, extents->top, width, height);
|
xf_draw_screen(xfc, extents->left, extents->top, width, height);
|
||||||
}
|
}
|
||||||
@ -97,11 +126,11 @@ int xf_OutputUpdate(xfContext* xfc)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image,
|
XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image,
|
||||||
extents->left, extents->top, extents->left, extents->top, width, height);
|
extents->left, extents->top, extents->left + surfaceX, extents->top + surfaceY, width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
region16_clear(&(xfc->invalidRegion));
|
region16_clear(&surface->invalidRegion);
|
||||||
|
|
||||||
XSetClipMask(xfc->display, xfc->gc, None);
|
XSetClipMask(xfc->display, xfc->gc, None);
|
||||||
XSync(xfc->display, True);
|
XSync(xfc->display, True);
|
||||||
@ -109,8 +138,78 @@ int xf_OutputUpdate(xfContext* xfc)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xf_UpdateSurface(xfContext* xfc, xfGfxSurface* surface, void* param)
|
||||||
|
{
|
||||||
|
int status = 1;
|
||||||
|
|
||||||
|
switch (surface->mapping.mode)
|
||||||
|
{
|
||||||
|
case GFX_MAP_OUTPUT:
|
||||||
|
status = xf_OutputUpdate(xfc, surface);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GFX_MAP_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xf_UpdateSurfaces(xfContext* xfc)
|
||||||
|
{
|
||||||
|
if (!xfc->graphicsReset)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return xf_call_for_each_surface(xfc, xfc->gfxMappedSurfaceIds, xf_UpdateSurface, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL xf_MappedSurfaceRect(xfContext* xfc, xfGfxSurface* surface, RECTANGLE_16* rect)
|
||||||
|
{
|
||||||
|
BOOL mapped = FALSE;
|
||||||
|
|
||||||
|
switch (surface->mapping.mode)
|
||||||
|
{
|
||||||
|
case GFX_MAP_OUTPUT:
|
||||||
|
mapped = TRUE;
|
||||||
|
rect->left = surface->mapping.output.originX;
|
||||||
|
rect->top = surface->mapping.output.originY;
|
||||||
|
rect->right = surface->mapping.output.originX + surface->width;
|
||||||
|
rect->bottom = surface->mapping.output.originY + surface->height;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GFX_MAP_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_OutputExpose(xfContext* xfc, xfGfxSurface* surface, void* param)
|
||||||
|
{
|
||||||
|
RECTANGLE_16 surfaceRect;
|
||||||
|
RECTANGLE_16 intersection;
|
||||||
|
RECTANGLE_16* invalidRect = param;
|
||||||
|
|
||||||
|
if (!xf_MappedSurfaceRect(xfc, surface, &surfaceRect))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (rectangles_intersection(invalidRect, &surfaceRect, &intersection))
|
||||||
|
{
|
||||||
|
/* Invalid rects are specified relative to surface origin */
|
||||||
|
intersection.left -= surfaceRect.left;
|
||||||
|
intersection.top -= surfaceRect.top;
|
||||||
|
intersection.right -= surfaceRect.left;
|
||||||
|
intersection.bottom -= surfaceRect.top;
|
||||||
|
|
||||||
|
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &intersection);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height)
|
int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
|
int status = 1;
|
||||||
RECTANGLE_16 invalidRect;
|
RECTANGLE_16 invalidRect;
|
||||||
|
|
||||||
invalidRect.left = x;
|
invalidRect.left = x;
|
||||||
@ -118,11 +217,13 @@ int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height)
|
|||||||
invalidRect.right = x + width;
|
invalidRect.right = x + width;
|
||||||
invalidRect.bottom = y + height;
|
invalidRect.bottom = y + height;
|
||||||
|
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
if (xf_call_for_each_surface(xfc, xfc->gfxMappedSurfaceIds, do_OutputExpose, &invalidRect) < 0)
|
||||||
|
status = -1;
|
||||||
|
|
||||||
xf_OutputUpdate(xfc);
|
if (xf_UpdateSurfaces(xfc) < 0)
|
||||||
|
status = -1;
|
||||||
|
|
||||||
return 1;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame)
|
int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame)
|
||||||
@ -138,7 +239,7 @@ int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame)
|
|||||||
{
|
{
|
||||||
xfContext* xfc = (xfContext*) context->custom;
|
xfContext* xfc = (xfContext*) context->custom;
|
||||||
|
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
xfc->inGfxFrame = FALSE;
|
xfc->inGfxFrame = FALSE;
|
||||||
|
|
||||||
@ -163,10 +264,10 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context,
|
|||||||
invalidRect.right = cmd->right;
|
invalidRect.right = cmd->right;
|
||||||
invalidRect.bottom = cmd->bottom;
|
invalidRect.bottom = cmd->bottom;
|
||||||
|
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
|
||||||
|
|
||||||
if (!xfc->inGfxFrame)
|
if (!xfc->inGfxFrame)
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -238,7 +339,7 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
|
|||||||
nXDst, nYDst, nWidth, nHeight,
|
nXDst, nYDst, nWidth, nHeight,
|
||||||
tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0, NULL);
|
tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0, NULL);
|
||||||
|
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]);
|
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &updateRects[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
region16_uninit(&updateRegion);
|
region16_uninit(&updateRegion);
|
||||||
@ -249,7 +350,7 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
|
|||||||
region16_uninit(&clippingRects);
|
region16_uninit(&clippingRects);
|
||||||
|
|
||||||
if (!xfc->inGfxFrame)
|
if (!xfc->inGfxFrame)
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -284,10 +385,10 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R
|
|||||||
invalidRect.right = cmd->right;
|
invalidRect.right = cmd->right;
|
||||||
invalidRect.bottom = cmd->bottom;
|
invalidRect.bottom = cmd->bottom;
|
||||||
|
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
|
||||||
|
|
||||||
if (!xfc->inGfxFrame)
|
if (!xfc->inGfxFrame)
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -316,10 +417,10 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF
|
|||||||
invalidRect.right = cmd->right;
|
invalidRect.right = cmd->right;
|
||||||
invalidRect.bottom = cmd->bottom;
|
invalidRect.bottom = cmd->bottom;
|
||||||
|
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
|
||||||
|
|
||||||
if (!xfc->inGfxFrame)
|
if (!xfc->inGfxFrame)
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -364,11 +465,11 @@ int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_
|
|||||||
|
|
||||||
for (i = 0; i < meta->numRegionRects; i++)
|
for (i = 0; i < meta->numRegionRects; i++)
|
||||||
{
|
{
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), (RECTANGLE_16*) &(meta->regionRects[i]));
|
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, (RECTANGLE_16*) &(meta->regionRects[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!xfc->inGfxFrame)
|
if (!xfc->inGfxFrame)
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -397,10 +498,10 @@ int xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context, RDPGFX
|
|||||||
invalidRect.right = cmd->right;
|
invalidRect.right = cmd->right;
|
||||||
invalidRect.bottom = cmd->bottom;
|
invalidRect.bottom = cmd->bottom;
|
||||||
|
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
|
||||||
|
|
||||||
if (!xfc->inGfxFrame)
|
if (!xfc->inGfxFrame)
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -487,7 +588,7 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context,
|
|||||||
surface->scanline, nXDst, nYDst, nWidth, nHeight,
|
surface->scanline, nXDst, nYDst, nWidth, nHeight,
|
||||||
tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc, NULL);
|
tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc, NULL);
|
||||||
|
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]);
|
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &updateRects[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
region16_uninit(&updateRegion);
|
region16_uninit(&updateRegion);
|
||||||
@ -496,7 +597,7 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context,
|
|||||||
region16_uninit(&clippingRects);
|
region16_uninit(&clippingRects);
|
||||||
|
|
||||||
if (!xfc->inGfxFrame)
|
if (!xfc->inGfxFrame)
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -607,6 +708,10 @@ int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* cr
|
|||||||
(char*) surface->stage, surface->width, surface->height, xfc->scanline_pad, surface->stageStep);
|
(char*) surface->stage, surface->width, surface->height, xfc->scanline_pad, surface->stageStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
surface->mapping.mode = GFX_MAP_NONE;
|
||||||
|
|
||||||
|
region16_init(&surface->invalidRegion);
|
||||||
|
|
||||||
context->SetSurfaceData(context, surface->surfaceId, (void*) surface);
|
context->SetSurfaceData(context, surface->surfaceId, (void*) surface);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -624,9 +729,11 @@ int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* de
|
|||||||
XFree(surface->image);
|
XFree(surface->image);
|
||||||
_aligned_free(surface->data);
|
_aligned_free(surface->data);
|
||||||
_aligned_free(surface->stage);
|
_aligned_free(surface->stage);
|
||||||
|
region16_uninit(&surface->invalidRegion);
|
||||||
free(surface);
|
free(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayList_Remove(xfc->gfxMappedSurfaceIds, (void*) (ULONG_PTR) deleteSurface->surfaceId);
|
||||||
context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
|
context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
|
||||||
|
|
||||||
if (xfc->codecs->progressive)
|
if (xfc->codecs->progressive)
|
||||||
@ -673,11 +780,11 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill)
|
|||||||
freerdp_image_fill(surface->data, surface->format, surface->scanline,
|
freerdp_image_fill(surface->data, surface->format, surface->scanline,
|
||||||
rect->left, rect->top, nWidth, nHeight, color);
|
rect->left, rect->top, nWidth, nHeight, color);
|
||||||
|
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!xfc->inGfxFrame)
|
if (!xfc->inGfxFrame)
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -733,11 +840,11 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_
|
|||||||
invalidRect.right = destPt->x + rectSrc->right;
|
invalidRect.right = destPt->x + rectSrc->right;
|
||||||
invalidRect.bottom = destPt->y + rectSrc->bottom;
|
invalidRect.bottom = destPt->y + rectSrc->bottom;
|
||||||
|
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
region16_union_rect(&surfaceDst->invalidRegion, &surfaceDst->invalidRegion, &invalidRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!xfc->inGfxFrame)
|
if (!xfc->inGfxFrame)
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -818,11 +925,11 @@ int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU*
|
|||||||
invalidRect.right = destPt->x + cacheEntry->width - 1;
|
invalidRect.right = destPt->x + cacheEntry->width - 1;
|
||||||
invalidRect.bottom = destPt->y + cacheEntry->height - 1;
|
invalidRect.bottom = destPt->y + cacheEntry->height - 1;
|
||||||
|
|
||||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!xfc->inGfxFrame)
|
if (!xfc->inGfxFrame)
|
||||||
xf_OutputUpdate(xfc);
|
xf_UpdateSurfaces(xfc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -851,9 +958,18 @@ int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PD
|
|||||||
|
|
||||||
int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput)
|
int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput)
|
||||||
{
|
{
|
||||||
|
xfGfxSurface* surface;
|
||||||
xfContext* xfc = (xfContext*) context->custom;
|
xfContext* xfc = (xfContext*) context->custom;
|
||||||
|
|
||||||
xfc->outputSurfaceId = surfaceToOutput->surfaceId;
|
surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToOutput->surfaceId);
|
||||||
|
|
||||||
|
surface->mapping.mode = GFX_MAP_OUTPUT;
|
||||||
|
surface->mapping.output.originX = surfaceToOutput->outputOriginX;
|
||||||
|
surface->mapping.output.originY = surfaceToOutput->outputOriginY;
|
||||||
|
|
||||||
|
region16_clear(&surface->invalidRegion);
|
||||||
|
|
||||||
|
ArrayList_Add(xfc->gfxMappedSurfaceIds, (void*) (ULONG_PTR) surfaceToOutput->surfaceId);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -884,13 +1000,14 @@ void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx)
|
|||||||
gfx->MapSurfaceToOutput = xf_MapSurfaceToOutput;
|
gfx->MapSurfaceToOutput = xf_MapSurfaceToOutput;
|
||||||
gfx->MapSurfaceToWindow = xf_MapSurfaceToWindow;
|
gfx->MapSurfaceToWindow = xf_MapSurfaceToWindow;
|
||||||
|
|
||||||
region16_init(&(xfc->invalidRegion));
|
xfc->gfxMappedSurfaceIds = ArrayList_New(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx)
|
void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx)
|
||||||
{
|
{
|
||||||
region16_uninit(&(xfc->invalidRegion));
|
if (xfc->gfxMappedSurfaceIds)
|
||||||
|
{
|
||||||
gfx->custom = NULL;
|
ArrayList_Free(xfc->gfxMappedSurfaceIds);
|
||||||
xfc->gfx = NULL;
|
xfc->gfxMappedSurfaceIds = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,13 @@
|
|||||||
|
|
||||||
#include <freerdp/gdi/gfx.h>
|
#include <freerdp/gdi/gfx.h>
|
||||||
|
|
||||||
|
enum xf_gfx_mapping_mode
|
||||||
|
{
|
||||||
|
GFX_MAP_NONE,
|
||||||
|
GFX_MAP_OUTPUT
|
||||||
|
};
|
||||||
|
typedef enum xf_gfx_mapping_mode xfGfxMappingMode;
|
||||||
|
|
||||||
struct xf_gfx_surface
|
struct xf_gfx_surface
|
||||||
{
|
{
|
||||||
UINT16 surfaceId;
|
UINT16 surfaceId;
|
||||||
@ -37,6 +44,19 @@ struct xf_gfx_surface
|
|||||||
int scanline;
|
int scanline;
|
||||||
int stageStep;
|
int stageStep;
|
||||||
UINT32 format;
|
UINT32 format;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
xfGfxMappingMode mode;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UINT32 originX;
|
||||||
|
UINT32 originY;
|
||||||
|
} output;
|
||||||
|
};
|
||||||
|
} mapping;
|
||||||
|
REGION16 invalidRegion;
|
||||||
};
|
};
|
||||||
typedef struct xf_gfx_surface xfGfxSurface;
|
typedef struct xf_gfx_surface xfGfxSurface;
|
||||||
|
|
||||||
|
@ -122,10 +122,9 @@ struct xf_context
|
|||||||
UINT32 bitmap_size;
|
UINT32 bitmap_size;
|
||||||
BYTE* bitmap_buffer;
|
BYTE* bitmap_buffer;
|
||||||
BYTE* primary_buffer;
|
BYTE* primary_buffer;
|
||||||
REGION16 invalidRegion;
|
|
||||||
BOOL inGfxFrame;
|
BOOL inGfxFrame;
|
||||||
BOOL graphicsReset;
|
BOOL graphicsReset;
|
||||||
UINT16 outputSurfaceId;
|
wArrayList* gfxMappedSurfaceIds;
|
||||||
|
|
||||||
BOOL frame_begin;
|
BOOL frame_begin;
|
||||||
UINT16 frame_x1;
|
UINT16 frame_x1;
|
||||||
|
@ -132,8 +132,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
|||||||
{ "sec-tls", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "tls protocol security" },
|
{ "sec-tls", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "tls protocol security" },
|
||||||
{ "sec-nla", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "nla protocol security" },
|
{ "sec-nla", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "nla protocol security" },
|
||||||
{ "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "nla extended protocol security" },
|
{ "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "nla extended protocol security" },
|
||||||
{ "tls-ciphers", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "List of permitted openssl ciphers - see ciphers(1)" },
|
{ "tls-ciphers", COMMAND_LINE_VALUE_REQUIRED, "<netmon|ma|ciphers>", NULL, NULL, -1, NULL, "Allowed TLS ciphers" },
|
||||||
{ "tls-ciphers-netmon", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Use tls ciphers that netmon can parse" },
|
|
||||||
{ "cert-name", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "certificate name" },
|
{ "cert-name", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "certificate name" },
|
||||||
{ "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "ignore certificate" },
|
{ "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "ignore certificate" },
|
||||||
{ "pcb", COMMAND_LINE_VALUE_REQUIRED, "<blob>", NULL, NULL, -1, NULL, "Preconnection Blob" },
|
{ "pcb", COMMAND_LINE_VALUE_REQUIRED, "<blob>", NULL, NULL, -1, NULL, "Preconnection Blob" },
|
||||||
@ -1810,11 +1809,18 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
|||||||
}
|
}
|
||||||
CommandLineSwitchCase(arg, "tls-ciphers")
|
CommandLineSwitchCase(arg, "tls-ciphers")
|
||||||
{
|
{
|
||||||
settings->PermittedTLSCiphers = _strdup(arg->Value);
|
if (strcmp(arg->Value, "netmon") == 0)
|
||||||
}
|
{
|
||||||
CommandLineSwitchCase(arg, "tls-ciphers-netmon")
|
settings->AllowedTlsCiphers = _strdup("ALL:!ECDH");
|
||||||
{
|
}
|
||||||
settings->PermittedTLSCiphers = arg->Value ? _strdup("ALL:!ECDH") : NULL;
|
else if (strcmp(arg->Value, "ma") == 0)
|
||||||
|
{
|
||||||
|
settings->AllowedTlsCiphers = _strdup("AES128-SHA");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
settings->AllowedTlsCiphers = _strdup(arg->Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CommandLineSwitchCase(arg, "cert-name")
|
CommandLineSwitchCase(arg, "cert-name")
|
||||||
{
|
{
|
||||||
|
@ -615,6 +615,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
|
|||||||
#define FreeRDP_AuthenticationServiceClass 1098
|
#define FreeRDP_AuthenticationServiceClass 1098
|
||||||
#define FreeRDP_DisableCredentialsDelegation 1099
|
#define FreeRDP_DisableCredentialsDelegation 1099
|
||||||
#define FreeRDP_AuthenticationLevel 1100
|
#define FreeRDP_AuthenticationLevel 1100
|
||||||
|
#define FreeRDP_AllowedTlsCiphers 1101
|
||||||
#define FreeRDP_MstscCookieMode 1152
|
#define FreeRDP_MstscCookieMode 1152
|
||||||
#define FreeRDP_CookieMaxLength 1153
|
#define FreeRDP_CookieMaxLength 1153
|
||||||
#define FreeRDP_PreconnectionId 1154
|
#define FreeRDP_PreconnectionId 1154
|
||||||
@ -998,7 +999,7 @@ struct rdp_settings
|
|||||||
ALIGN64 char* AuthenticationServiceClass; /* 1098 */
|
ALIGN64 char* AuthenticationServiceClass; /* 1098 */
|
||||||
ALIGN64 BOOL DisableCredentialsDelegation; /* 1099 */
|
ALIGN64 BOOL DisableCredentialsDelegation; /* 1099 */
|
||||||
ALIGN64 BOOL AuthenticationLevel; /* 1100 */
|
ALIGN64 BOOL AuthenticationLevel; /* 1100 */
|
||||||
ALIGN64 char* PermittedTLSCiphers; /* 1101 */
|
ALIGN64 char* AllowedTlsCiphers; /* 1101 */
|
||||||
UINT64 padding1152[1152 - 1102]; /* 1102 */
|
UINT64 padding1152[1152 - 1102]; /* 1102 */
|
||||||
|
|
||||||
/* Connection Cookie */
|
/* Connection Cookie */
|
||||||
|
@ -798,10 +798,12 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE
|
|||||||
void region16_uninit(REGION16 *region)
|
void region16_uninit(REGION16 *region)
|
||||||
{
|
{
|
||||||
assert(region);
|
assert(region);
|
||||||
assert(region->data);
|
|
||||||
|
|
||||||
if (region->data->size)
|
if (region->data)
|
||||||
free(region->data);
|
{
|
||||||
|
if (region->data->size)
|
||||||
|
free(region->data);
|
||||||
|
|
||||||
region->data = NULL;
|
region->data = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -503,17 +503,20 @@ ADDIN_ARGV* freerdp_dynamic_channel_clone(ADDIN_ARGV* channel)
|
|||||||
ADDIN_ARGV* _channel = NULL;
|
ADDIN_ARGV* _channel = NULL;
|
||||||
|
|
||||||
_channel = (ADDIN_ARGV*) malloc(sizeof(ADDIN_ARGV));
|
_channel = (ADDIN_ARGV*) malloc(sizeof(ADDIN_ARGV));
|
||||||
|
|
||||||
if (!_channel)
|
if (!_channel)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
_channel->argc = channel->argc;
|
_channel->argc = channel->argc;
|
||||||
_channel->argv = (char**) malloc(sizeof(char*) * channel->argc);
|
_channel->argv = (char**) malloc(sizeof(char*) * channel->argc);
|
||||||
|
|
||||||
if (!_channel->argv)
|
if (!_channel->argv)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
for (index = 0; index < _channel->argc; index++)
|
for (index = 0; index < _channel->argc; index++)
|
||||||
{
|
{
|
||||||
_channel->argv[index] = _strdup(channel->argv[index]);
|
_channel->argv[index] = _strdup(channel->argv[index]);
|
||||||
|
|
||||||
if (!_channel->argv[index])
|
if (!_channel->argv[index])
|
||||||
goto out_release_args;
|
goto out_release_args;
|
||||||
}
|
}
|
||||||
|
@ -773,6 +773,49 @@ void key_free(rdpRsaKey* key)
|
|||||||
free(key);
|
free(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rdpCertificate* certificate_clone(rdpCertificate* certificate)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
rdpCertificate* _certificate = (rdpCertificate*) calloc(1, sizeof(rdpCertificate));
|
||||||
|
|
||||||
|
if (!_certificate)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
CopyMemory(_certificate, certificate, sizeof(rdpCertificate));
|
||||||
|
|
||||||
|
if (certificate->cert_info.ModulusLength)
|
||||||
|
{
|
||||||
|
_certificate->cert_info.Modulus = (BYTE*) malloc(certificate->cert_info.ModulusLength);
|
||||||
|
CopyMemory(_certificate->cert_info.Modulus, certificate->cert_info.Modulus, certificate->cert_info.ModulusLength);
|
||||||
|
_certificate->cert_info.ModulusLength = certificate->cert_info.ModulusLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certificate->x509_cert_chain)
|
||||||
|
{
|
||||||
|
_certificate->x509_cert_chain = (rdpX509CertChain*) malloc(sizeof(rdpX509CertChain));
|
||||||
|
CopyMemory(_certificate->x509_cert_chain, certificate->x509_cert_chain, sizeof(rdpX509CertChain));
|
||||||
|
|
||||||
|
if (certificate->x509_cert_chain->count)
|
||||||
|
{
|
||||||
|
_certificate->x509_cert_chain->array = (rdpCertBlob*) calloc(certificate->x509_cert_chain->count, sizeof(rdpCertBlob));
|
||||||
|
|
||||||
|
for (index = 0; index < certificate->x509_cert_chain->count; index++)
|
||||||
|
{
|
||||||
|
_certificate->x509_cert_chain->array[index].length = certificate->x509_cert_chain->array[index].length;
|
||||||
|
|
||||||
|
if (certificate->x509_cert_chain->array[index].length)
|
||||||
|
{
|
||||||
|
_certificate->x509_cert_chain->array[index].data = (BYTE*) malloc(certificate->x509_cert_chain->array[index].length);
|
||||||
|
CopyMemory(_certificate->x509_cert_chain->array[index].data, certificate->x509_cert_chain->array[index].data,
|
||||||
|
_certificate->x509_cert_chain->array[index].length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _certificate;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate new certificate module.\n
|
* Instantiate new certificate module.\n
|
||||||
* @param rdp RDP module
|
* @param rdp RDP module
|
||||||
|
@ -53,6 +53,8 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate
|
|||||||
BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, wStream* s);
|
BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, wStream* s);
|
||||||
BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert, int length);
|
BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert, int length);
|
||||||
|
|
||||||
|
rdpCertificate* certificate_clone(rdpCertificate* certificate);
|
||||||
|
|
||||||
rdpCertificate* certificate_new(void);
|
rdpCertificate* certificate_new(void);
|
||||||
void certificate_free(rdpCertificate* certificate);
|
void certificate_free(rdpCertificate* certificate);
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
|
|||||||
int hostnameLength;
|
int hostnameLength;
|
||||||
CHANNEL_CLIENT_DATA* pChannelClientData;
|
CHANNEL_CLIENT_DATA* pChannelClientData;
|
||||||
|
|
||||||
channels->is_connected = 1;
|
channels->connected = 1;
|
||||||
hostname = instance->settings->ServerHostname;
|
hostname = instance->settings->ServerHostname;
|
||||||
hostnameLength = (int) strlen(hostname);
|
hostnameLength = (int) strlen(hostname);
|
||||||
|
|
||||||
@ -413,7 +413,10 @@ int freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance)
|
|||||||
CHANNEL_OPEN_DATA* pChannelOpenData;
|
CHANNEL_OPEN_DATA* pChannelOpenData;
|
||||||
CHANNEL_CLIENT_DATA* pChannelClientData;
|
CHANNEL_CLIENT_DATA* pChannelClientData;
|
||||||
|
|
||||||
channels->is_connected = 0;
|
if (!channels->connected)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
channels->connected = 0;
|
||||||
freerdp_channels_check_fds(channels, instance);
|
freerdp_channels_check_fds(channels, instance);
|
||||||
|
|
||||||
/* tell all libraries we are shutting down */
|
/* tell all libraries we are shutting down */
|
||||||
@ -498,7 +501,7 @@ UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle, PCHANNEL_DEF pCh
|
|||||||
if (!pChannel)
|
if (!pChannel)
|
||||||
return CHANNEL_RC_BAD_CHANNEL;
|
return CHANNEL_RC_BAD_CHANNEL;
|
||||||
|
|
||||||
if (channels->is_connected)
|
if (channels->connected)
|
||||||
return CHANNEL_RC_ALREADY_CONNECTED;
|
return CHANNEL_RC_ALREADY_CONNECTED;
|
||||||
|
|
||||||
if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000)
|
if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000)
|
||||||
@ -571,7 +574,7 @@ UINT VCAPITYPE FreeRDP_VirtualChannelOpen(LPVOID pInitHandle, LPDWORD pOpenHandl
|
|||||||
if (!pChannelOpenEventProc)
|
if (!pChannelOpenEventProc)
|
||||||
return CHANNEL_RC_BAD_PROC;
|
return CHANNEL_RC_BAD_PROC;
|
||||||
|
|
||||||
if (!channels->is_connected)
|
if (!channels->connected)
|
||||||
return CHANNEL_RC_NOT_CONNECTED;
|
return CHANNEL_RC_NOT_CONNECTED;
|
||||||
|
|
||||||
pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName);
|
pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName);
|
||||||
@ -623,7 +626,7 @@ UINT VCAPITYPE FreeRDP_VirtualChannelWrite(DWORD openHandle, LPVOID pData, ULONG
|
|||||||
if (!channels)
|
if (!channels)
|
||||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
|
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
|
||||||
|
|
||||||
if (!channels->is_connected)
|
if (!channels->connected)
|
||||||
return CHANNEL_RC_NOT_CONNECTED;
|
return CHANNEL_RC_NOT_CONNECTED;
|
||||||
|
|
||||||
if (!pData)
|
if (!pData)
|
||||||
|
@ -96,7 +96,7 @@ struct rdp_channels
|
|||||||
rdpSettings* settings;
|
rdpSettings* settings;
|
||||||
|
|
||||||
/* true once freerdp_channels_post_connect is called */
|
/* true once freerdp_channels_post_connect is called */
|
||||||
int is_connected;
|
BOOL connected;
|
||||||
|
|
||||||
/* used for locating the channels for a given instance */
|
/* used for locating the channels for a given instance */
|
||||||
freerdp* instance;
|
freerdp* instance;
|
||||||
|
@ -172,7 +172,7 @@
|
|||||||
|
|
||||||
BOOL rdp_client_connect(rdpRdp* rdp)
|
BOOL rdp_client_connect(rdpRdp* rdp)
|
||||||
{
|
{
|
||||||
BOOL ret;
|
BOOL status;
|
||||||
rdpSettings* settings = rdp->settings;
|
rdpSettings* settings = rdp->settings;
|
||||||
|
|
||||||
if (rdp->settingsCopy)
|
if (rdp->settingsCopy)
|
||||||
@ -213,6 +213,7 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
|||||||
|
|
||||||
cookie_length = domain_length + 1 + user_length;
|
cookie_length = domain_length + 1 + user_length;
|
||||||
cookie = (char*) malloc(cookie_length + 1);
|
cookie = (char*) malloc(cookie_length + 1);
|
||||||
|
|
||||||
if (!cookie)
|
if (!cookie)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -225,15 +226,15 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
|||||||
|
|
||||||
cookie[cookie_length] = '\0';
|
cookie[cookie_length] = '\0';
|
||||||
|
|
||||||
ret = nego_set_cookie(rdp->nego, cookie);
|
status = nego_set_cookie(rdp->nego, cookie);
|
||||||
free(cookie);
|
free(cookie);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = nego_set_cookie(rdp->nego, settings->Username);
|
status = nego_set_cookie(rdp->nego, settings->Username);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret)
|
if (!status)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
nego_set_send_preconnection_pdu(rdp->nego, settings->SendPreconnectionPdu);
|
nego_set_send_preconnection_pdu(rdp->nego, settings->SendPreconnectionPdu);
|
||||||
@ -269,7 +270,7 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
|||||||
freerdp_set_last_error(rdp->context, FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED);
|
freerdp_set_last_error(rdp->context, FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
WLog_ERR(TAG, "Error: protocol security negotiation or connection failure");
|
WLog_ERR(TAG, "Error: protocol security negotiation or connection failure");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +298,7 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
|||||||
freerdp_set_last_error(rdp->context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
|
freerdp_set_last_error(rdp->context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
WLog_ERR(TAG, "Error: unable to send MCS Connect Initial");
|
WLog_ERR(TAG, "Error: unable to send MCS Connect Initial");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +320,7 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
|||||||
|
|
||||||
BOOL rdp_client_disconnect(rdpRdp* rdp)
|
BOOL rdp_client_disconnect(rdpRdp* rdp)
|
||||||
{
|
{
|
||||||
BOOL rc;
|
BOOL status;
|
||||||
|
|
||||||
if (rdp->settingsCopy)
|
if (rdp->settingsCopy)
|
||||||
{
|
{
|
||||||
@ -327,10 +328,13 @@ BOOL rdp_client_disconnect(rdpRdp* rdp)
|
|||||||
rdp->settingsCopy = NULL;
|
rdp->settingsCopy = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = nego_disconnect(rdp->nego);
|
status = nego_disconnect(rdp->nego);
|
||||||
|
|
||||||
rdp_reset(rdp);
|
rdp_reset(rdp);
|
||||||
|
|
||||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_INITIAL);
|
rdp_client_transition_to_state(rdp, CONNECTION_STATE_INITIAL);
|
||||||
return rc;
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL rdp_client_redirect(rdpRdp* rdp)
|
BOOL rdp_client_redirect(rdpRdp* rdp)
|
||||||
@ -381,6 +385,23 @@ BOOL rdp_client_redirect(rdpRdp* rdp)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL rdp_client_reconnect(rdpRdp* rdp)
|
||||||
|
{
|
||||||
|
BOOL status;
|
||||||
|
rdpContext* context = rdp->context;
|
||||||
|
rdpChannels* channels = context->channels;
|
||||||
|
|
||||||
|
freerdp_channels_disconnect(channels, context->instance);
|
||||||
|
rdp_client_disconnect(rdp);
|
||||||
|
|
||||||
|
status = rdp_client_connect(rdp);
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
freerdp_channels_post_connect(channels, context->instance);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static BYTE fips_ivec[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
|
static BYTE fips_ivec[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
|
||||||
|
|
||||||
static BOOL rdp_client_establish_keys(rdpRdp* rdp)
|
static BOOL rdp_client_establish_keys(rdpRdp* rdp)
|
||||||
@ -631,7 +652,7 @@ BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s)
|
|||||||
{
|
{
|
||||||
if (!mcs_recv_connect_response(rdp->mcs, s))
|
if (!mcs_recv_connect_response(rdp->mcs, s))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdp_client_connect_mcs_connect_response: mcs_recv_connect_response failed");
|
WLog_ERR(TAG, "rdp_client_connect_mcs_connect_response: mcs_recv_connect_response failed");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -795,7 +816,7 @@ int rdp_client_connect_license(rdpRdp* rdp, wStream* s)
|
|||||||
|
|
||||||
if (rdp->license->state == LICENSE_STATE_ABORTED)
|
if (rdp->license->state == LICENSE_STATE_ABORTED)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "license connection sequence aborted.");
|
WLog_ERR(TAG, "license connection sequence aborted.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -974,12 +995,12 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
nego->SelectedProtocol = 0;
|
nego->SelectedProtocol = 0;
|
||||||
WLog_INFO(TAG, "Client Security: NLA:%d TLS:%d RDP:%d",
|
WLog_INFO(TAG, "Client Security: NLA:%d TLS:%d RDP:%d",
|
||||||
(nego->RequestedProtocols & PROTOCOL_NLA) ? 1 : 0,
|
(nego->RequestedProtocols & PROTOCOL_NLA) ? 1 : 0,
|
||||||
(nego->RequestedProtocols & PROTOCOL_TLS) ? 1 : 0,
|
(nego->RequestedProtocols & PROTOCOL_TLS) ? 1 : 0,
|
||||||
(nego->RequestedProtocols == PROTOCOL_RDP) ? 1 : 0
|
(nego->RequestedProtocols == PROTOCOL_RDP) ? 1 : 0
|
||||||
);
|
);
|
||||||
WLog_INFO(TAG, "Server Security: NLA:%d TLS:%d RDP:%d",
|
WLog_INFO(TAG, "Server Security: NLA:%d TLS:%d RDP:%d",
|
||||||
settings->NlaSecurity, settings->TlsSecurity, settings->RdpSecurity);
|
settings->NlaSecurity, settings->TlsSecurity, settings->RdpSecurity);
|
||||||
|
|
||||||
if ((settings->NlaSecurity) && (nego->RequestedProtocols & PROTOCOL_NLA))
|
if ((settings->NlaSecurity) && (nego->RequestedProtocols & PROTOCOL_NLA))
|
||||||
@ -996,10 +1017,10 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Protocol security negotiation failure");
|
WLog_ERR(TAG, "Protocol security negotiation failure");
|
||||||
}
|
}
|
||||||
|
|
||||||
WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d",
|
WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d",
|
||||||
(nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0,
|
(nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0,
|
||||||
(nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0,
|
(nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0,
|
||||||
(nego->SelectedProtocol == PROTOCOL_RDP) ? 1: 0
|
(nego->SelectedProtocol == PROTOCOL_RDP) ? 1: 0
|
||||||
@ -1035,12 +1056,12 @@ BOOL rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, wStream* s)
|
|||||||
if (!mcs_recv_connect_initial(mcs, s))
|
if (!mcs_recv_connect_initial(mcs, s))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
WLog_INFO(TAG, "Accepted client: %s", rdp->settings->ClientHostname);
|
WLog_INFO(TAG, "Accepted client: %s", rdp->settings->ClientHostname);
|
||||||
WLog_INFO(TAG, "Accepted channels:");
|
WLog_INFO(TAG, "Accepted channels:");
|
||||||
|
|
||||||
for (i = 0; i < mcs->channelCount; i++)
|
for (i = 0; i < mcs->channelCount; i++)
|
||||||
{
|
{
|
||||||
WLog_INFO(TAG, " %s", mcs->channels[i].Name);
|
WLog_INFO(TAG, " %s", mcs->channels[i].Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mcs_send_connect_response(mcs))
|
if (!mcs_send_connect_response(mcs))
|
||||||
|
@ -49,6 +49,7 @@ enum CONNECTION_STATE
|
|||||||
|
|
||||||
BOOL rdp_client_connect(rdpRdp* rdp);
|
BOOL rdp_client_connect(rdpRdp* rdp);
|
||||||
BOOL rdp_client_disconnect(rdpRdp* rdp);
|
BOOL rdp_client_disconnect(rdpRdp* rdp);
|
||||||
|
BOOL rdp_client_reconnect(rdpRdp* rdp);
|
||||||
BOOL rdp_client_redirect(rdpRdp* rdp);
|
BOOL rdp_client_redirect(rdpRdp* rdp);
|
||||||
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s);
|
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s);
|
||||||
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s);
|
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s);
|
||||||
|
@ -62,8 +62,8 @@
|
|||||||
BOOL freerdp_connect(freerdp* instance)
|
BOOL freerdp_connect(freerdp* instance)
|
||||||
{
|
{
|
||||||
rdpRdp* rdp;
|
rdpRdp* rdp;
|
||||||
|
BOOL status = TRUE;
|
||||||
rdpSettings* settings;
|
rdpSettings* settings;
|
||||||
BOOL status = FALSE;
|
|
||||||
ConnectionResultEventArgs e;
|
ConnectionResultEventArgs e;
|
||||||
|
|
||||||
/* We always set the return code to 0 before we start the connect sequence*/
|
/* We always set the return code to 0 before we start the connect sequence*/
|
||||||
@ -117,6 +117,7 @@ BOOL freerdp_connect(freerdp* instance)
|
|||||||
}
|
}
|
||||||
|
|
||||||
IFCALLRET(instance->PostConnect, status, instance);
|
IFCALLRET(instance->PostConnect, status, instance);
|
||||||
|
|
||||||
update_post_connect(instance->update);
|
update_post_connect(instance->update);
|
||||||
|
|
||||||
if (!status)
|
if (!status)
|
||||||
@ -345,8 +346,10 @@ BOOL freerdp_disconnect(freerdp* instance)
|
|||||||
rdpRdp* rdp;
|
rdpRdp* rdp;
|
||||||
|
|
||||||
rdp = instance->context->rdp;
|
rdp = instance->context->rdp;
|
||||||
|
|
||||||
rdp_client_disconnect(rdp);
|
rdp_client_disconnect(rdp);
|
||||||
update_post_disconnect(instance->update);
|
update_post_disconnect(instance->update);
|
||||||
|
|
||||||
IFCALL(instance->PostDisconnect, instance);
|
IFCALL(instance->PostDisconnect, instance);
|
||||||
|
|
||||||
if (instance->update->pcap_rfx)
|
if (instance->update->pcap_rfx)
|
||||||
@ -361,8 +364,12 @@ BOOL freerdp_disconnect(freerdp* instance)
|
|||||||
|
|
||||||
BOOL freerdp_reconnect(freerdp* instance)
|
BOOL freerdp_reconnect(freerdp* instance)
|
||||||
{
|
{
|
||||||
freerdp_disconnect(instance);
|
BOOL status;
|
||||||
return freerdp_connect(instance);
|
rdpRdp* rdp = instance->context->rdp;
|
||||||
|
|
||||||
|
status = rdp_client_reconnect(rdp);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL freerdp_shall_disconnect(freerdp* instance)
|
BOOL freerdp_shall_disconnect(freerdp* instance)
|
||||||
|
@ -30,22 +30,55 @@
|
|||||||
|
|
||||||
#include "info.h"
|
#include "info.h"
|
||||||
|
|
||||||
#define TAG FREERDP_TAG("core")
|
#define TAG FREERDP_TAG("core.info")
|
||||||
|
|
||||||
#define INFO_TYPE_LOGON 0x00000000
|
static const char* const INFO_TYPE_LOGON_STRINGS[4] =
|
||||||
#define INFO_TYPE_LOGON_LONG 0x00000001
|
|
||||||
#define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002
|
|
||||||
#define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003
|
|
||||||
|
|
||||||
/*
|
|
||||||
static const char* const INFO_TYPE_LOGON_STRINGS[] =
|
|
||||||
{
|
{
|
||||||
"Logon Info V1",
|
"Logon Info V1",
|
||||||
"Logon Info V2",
|
"Logon Info V2",
|
||||||
"Logon Plain Notify",
|
"Logon Plain Notify",
|
||||||
"Logon Extended Info"
|
"Logon Extended Info"
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
|
BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp)
|
||||||
|
{
|
||||||
|
CryptoHmac hmac;
|
||||||
|
BYTE ClientRandom[32];
|
||||||
|
BYTE AutoReconnectRandom[32];
|
||||||
|
ARC_SC_PRIVATE_PACKET* serverCookie;
|
||||||
|
ARC_CS_PRIVATE_PACKET* clientCookie;
|
||||||
|
rdpSettings* settings = rdp->settings;
|
||||||
|
|
||||||
|
serverCookie = settings->ServerAutoReconnectCookie;
|
||||||
|
clientCookie = settings->ClientAutoReconnectCookie;
|
||||||
|
|
||||||
|
clientCookie->cbLen = 28;
|
||||||
|
clientCookie->version = serverCookie->version;
|
||||||
|
clientCookie->logonId = serverCookie->logonId;
|
||||||
|
ZeroMemory(clientCookie->securityVerifier, 16);
|
||||||
|
|
||||||
|
ZeroMemory(AutoReconnectRandom, sizeof(AutoReconnectRandom));
|
||||||
|
CopyMemory(AutoReconnectRandom, serverCookie->arcRandomBits, 16);
|
||||||
|
|
||||||
|
ZeroMemory(ClientRandom, sizeof(ClientRandom));
|
||||||
|
|
||||||
|
if (settings->SelectedProtocol == PROTOCOL_RDP)
|
||||||
|
CopyMemory(ClientRandom, settings->ClientRandom, settings->ClientRandomLength);
|
||||||
|
|
||||||
|
hmac = crypto_hmac_new();
|
||||||
|
|
||||||
|
if (!hmac)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* SecurityVerifier = HMAC_MD5(AutoReconnectRandom, ClientRandom) */
|
||||||
|
|
||||||
|
crypto_hmac_md5_init(hmac, AutoReconnectRandom, 16);
|
||||||
|
crypto_hmac_update(hmac, ClientRandom, 32);
|
||||||
|
crypto_hmac_final(hmac, clientCookie->securityVerifier, 16);
|
||||||
|
crypto_hmac_free(hmac);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read Server Auto Reconnect Cookie (ARC_SC_PRIVATE_PACKET).\n
|
* Read Server Auto Reconnect Cookie (ARC_SC_PRIVATE_PACKET).\n
|
||||||
@ -54,25 +87,44 @@ static const char* const INFO_TYPE_LOGON_STRINGS[] =
|
|||||||
* @param settings settings
|
* @param settings settings
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL rdp_read_server_auto_reconnect_cookie(wStream* s, rdpSettings* settings)
|
BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
|
BYTE* p;
|
||||||
ARC_SC_PRIVATE_PACKET* autoReconnectCookie;
|
ARC_SC_PRIVATE_PACKET* autoReconnectCookie;
|
||||||
|
rdpSettings* settings = rdp->settings;
|
||||||
|
|
||||||
autoReconnectCookie = settings->ServerAutoReconnectCookie;
|
autoReconnectCookie = settings->ServerAutoReconnectCookie;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < 4+4+4+16)
|
if (Stream_GetRemainingLength(s) < 28)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */
|
Stream_Read_UINT32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */
|
||||||
Stream_Read_UINT32(s, autoReconnectCookie->version); /* version (4 bytes) */
|
Stream_Read_UINT32(s, autoReconnectCookie->version); /* Version (4 bytes) */
|
||||||
Stream_Read_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */
|
Stream_Read_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */
|
||||||
Stream_Read(s, autoReconnectCookie->arcRandomBits, 16); /* arcRandomBits (16 bytes) */
|
Stream_Read(s, autoReconnectCookie->arcRandomBits, 16); /* ArcRandomBits (16 bytes) */
|
||||||
|
|
||||||
|
if (autoReconnectCookie->cbLen != 28)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "ServerAutoReconnectCookie.cbLen != 28");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = autoReconnectCookie->arcRandomBits;
|
||||||
|
|
||||||
|
WLog_DBG(TAG, "ServerAutoReconnectCookie: Version: %d LogonId: %d SecurityVerifier: "
|
||||||
|
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
|
autoReconnectCookie->version, autoReconnectCookie->logonId,
|
||||||
|
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
|
||||||
|
p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
|
||||||
|
|
||||||
if ((settings->PrintReconnectCookie) && (autoReconnectCookie->cbLen > 0))
|
if ((settings->PrintReconnectCookie) && (autoReconnectCookie->cbLen > 0))
|
||||||
{
|
{
|
||||||
char *base64;
|
char* base64;
|
||||||
base64 = crypto_base64_encode((BYTE *) autoReconnectCookie,
|
base64 = crypto_base64_encode((BYTE*) autoReconnectCookie, sizeof(ARC_SC_PRIVATE_PACKET));
|
||||||
sizeof(ARC_SC_PRIVATE_PACKET));
|
WLog_INFO(TAG, "Reconnect-cookie: %s", base64);
|
||||||
WLog_INFO(TAG, "Reconnect-cookie: %s", base64);
|
|
||||||
free(base64);
|
free(base64);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,9 +135,11 @@ BOOL rdp_read_server_auto_reconnect_cookie(wStream* s, rdpSettings* settings)
|
|||||||
* @param settings settings
|
* @param settings settings
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL rdp_read_client_auto_reconnect_cookie(wStream* s, rdpSettings* settings)
|
BOOL rdp_read_client_auto_reconnect_cookie(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
ARC_CS_PRIVATE_PACKET* autoReconnectCookie;
|
ARC_CS_PRIVATE_PACKET* autoReconnectCookie;
|
||||||
|
rdpSettings* settings = rdp->settings;
|
||||||
|
|
||||||
autoReconnectCookie = settings->ClientAutoReconnectCookie;
|
autoReconnectCookie = settings->ClientAutoReconnectCookie;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < 28)
|
if (Stream_GetRemainingLength(s) < 28)
|
||||||
@ -106,33 +160,26 @@ BOOL rdp_read_client_auto_reconnect_cookie(wStream* s, rdpSettings* settings)
|
|||||||
* @param settings settings
|
* @param settings settings
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void rdp_write_client_auto_reconnect_cookie(wStream* s, rdpSettings* settings)
|
void rdp_write_client_auto_reconnect_cookie(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
CryptoHmac hmac;
|
BYTE* p;
|
||||||
BYTE nullRandom[32];
|
|
||||||
BYTE cryptSecurityVerifier[16];
|
|
||||||
ARC_CS_PRIVATE_PACKET* autoReconnectCookie;
|
ARC_CS_PRIVATE_PACKET* autoReconnectCookie;
|
||||||
|
rdpSettings* settings = rdp->settings;
|
||||||
|
|
||||||
autoReconnectCookie = settings->ClientAutoReconnectCookie;
|
autoReconnectCookie = settings->ClientAutoReconnectCookie;
|
||||||
|
|
||||||
/* SecurityVerifier = HMAC(AutoReconnectRandom, ClientRandom) */
|
p = autoReconnectCookie->securityVerifier;
|
||||||
|
|
||||||
hmac = crypto_hmac_new();
|
WLog_DBG(TAG, "ClientAutoReconnectCookie: Version: %d LogonId: %d ArcRandomBits: "
|
||||||
ZeroMemory(nullRandom, sizeof(nullRandom));
|
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
|
autoReconnectCookie->version, autoReconnectCookie->logonId,
|
||||||
crypto_hmac_md5_init(hmac, autoReconnectCookie->securityVerifier, 16);
|
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
|
||||||
|
p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
|
||||||
if (settings->ClientRandomLength > 0)
|
|
||||||
crypto_hmac_update(hmac, settings->ClientRandom, settings->ClientRandomLength);
|
|
||||||
else
|
|
||||||
crypto_hmac_update(hmac, nullRandom, sizeof(nullRandom));
|
|
||||||
|
|
||||||
crypto_hmac_final(hmac, cryptSecurityVerifier, 16);
|
|
||||||
crypto_hmac_free(hmac);
|
|
||||||
|
|
||||||
Stream_Write_UINT32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */
|
Stream_Write_UINT32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */
|
||||||
Stream_Write_UINT32(s, autoReconnectCookie->version); /* version (4 bytes) */
|
Stream_Write_UINT32(s, autoReconnectCookie->version); /* version (4 bytes) */
|
||||||
Stream_Write_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */
|
Stream_Write_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */
|
||||||
Stream_Write(s, cryptSecurityVerifier, 16); /* SecurityVerifier */
|
Stream_Write(s, autoReconnectCookie->securityVerifier, 16); /* SecurityVerifier (16 bytes) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -142,18 +189,19 @@ void rdp_write_client_auto_reconnect_cookie(wStream* s, rdpSettings* settings)
|
|||||||
* @param settings settings
|
* @param settings settings
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings)
|
BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
UINT16 clientAddressFamily;
|
UINT16 clientAddressFamily;
|
||||||
UINT16 cbClientAddress;
|
UINT16 cbClientAddress;
|
||||||
UINT16 cbClientDir;
|
UINT16 cbClientDir;
|
||||||
UINT16 cbAutoReconnectLen;
|
UINT16 cbAutoReconnectLen;
|
||||||
|
rdpSettings* settings = rdp->settings;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < 4)
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily */
|
Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily (2 bytes) */
|
||||||
Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress */
|
Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress (2 bytes) */
|
||||||
|
|
||||||
settings->IPv6Enabled = (clientAddressFamily == ADDRESS_FAMILY_INET6 ? TRUE : FALSE);
|
settings->IPv6Enabled = (clientAddressFamily == ADDRESS_FAMILY_INET6 ? TRUE : FALSE);
|
||||||
|
|
||||||
@ -172,7 +220,7 @@ BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
if (Stream_GetRemainingLength(s) < 2)
|
if (Stream_GetRemainingLength(s) < 2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT16(s, cbClientDir); /* cbClientDir */
|
Stream_Read_UINT16(s, cbClientDir); /* cbClientDir (2 bytes) */
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < cbClientDir)
|
if (Stream_GetRemainingLength(s) < cbClientDir)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -192,14 +240,14 @@ BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
if (Stream_GetRemainingLength(s) < 10)
|
if (Stream_GetRemainingLength(s) < 10)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Seek_UINT32(s); /* clientSessionId, should be set to 0 */
|
Stream_Seek_UINT32(s); /* clientSessionId (4 bytes), should be set to 0 */
|
||||||
Stream_Read_UINT32(s, settings->PerformanceFlags); /* performanceFlags */
|
Stream_Read_UINT32(s, settings->PerformanceFlags); /* performanceFlags (4 bytes) */
|
||||||
freerdp_performance_flags_split(settings);
|
freerdp_performance_flags_split(settings);
|
||||||
|
|
||||||
Stream_Read_UINT16(s, cbAutoReconnectLen); /* cbAutoReconnectLen */
|
Stream_Read_UINT16(s, cbAutoReconnectLen); /* cbAutoReconnectLen (2 bytes) */
|
||||||
|
|
||||||
if (cbAutoReconnectLen > 0)
|
if (cbAutoReconnectLen > 0)
|
||||||
return rdp_read_client_auto_reconnect_cookie(s, settings); /* autoReconnectCookie */
|
return rdp_read_client_auto_reconnect_cookie(rdp, s); /* autoReconnectCookie */
|
||||||
|
|
||||||
/* reserved1 (2 bytes) */
|
/* reserved1 (2 bytes) */
|
||||||
/* reserved2 (2 bytes) */
|
/* reserved2 (2 bytes) */
|
||||||
@ -214,14 +262,15 @@ BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
* @param settings settings
|
* @param settings settings
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void rdp_write_extended_info_packet(wStream* s, rdpSettings* settings)
|
void rdp_write_extended_info_packet(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
int clientAddressFamily;
|
int clientAddressFamily;
|
||||||
WCHAR* clientAddress = NULL;
|
WCHAR* clientAddress = NULL;
|
||||||
int cbClientAddress;
|
int cbClientAddress;
|
||||||
WCHAR* clientDir = NULL;
|
WCHAR* clientDir = NULL;
|
||||||
int cbClientDir;
|
int cbClientDir;
|
||||||
int cbAutoReconnectLen;
|
int cbAutoReconnectCookie;
|
||||||
|
rdpSettings* settings = rdp->settings;
|
||||||
|
|
||||||
clientAddressFamily = settings->IPv6Enabled ? ADDRESS_FAMILY_INET6 : ADDRESS_FAMILY_INET;
|
clientAddressFamily = settings->IPv6Enabled ? ADDRESS_FAMILY_INET6 : ADDRESS_FAMILY_INET;
|
||||||
|
|
||||||
@ -229,78 +278,41 @@ void rdp_write_extended_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
|
|
||||||
cbClientDir = ConvertToUnicode(CP_UTF8, 0, settings->ClientDir, -1, &clientDir, 0) * 2;
|
cbClientDir = ConvertToUnicode(CP_UTF8, 0, settings->ClientDir, -1, &clientDir, 0) * 2;
|
||||||
|
|
||||||
cbAutoReconnectLen = (int) settings->ServerAutoReconnectCookie->cbLen;
|
cbAutoReconnectCookie = (int) settings->ServerAutoReconnectCookie->cbLen;
|
||||||
|
|
||||||
Stream_Write_UINT16(s, clientAddressFamily); /* clientAddressFamily */
|
Stream_Write_UINT16(s, clientAddressFamily); /* clientAddressFamily (2 bytes) */
|
||||||
|
|
||||||
Stream_Write_UINT16(s, cbClientAddress + 2); /* cbClientAddress */
|
Stream_Write_UINT16(s, cbClientAddress + 2); /* cbClientAddress (2 bytes) */
|
||||||
|
|
||||||
if (cbClientAddress > 0)
|
if (cbClientAddress > 0)
|
||||||
Stream_Write(s, clientAddress, cbClientAddress); /* clientAddress */
|
Stream_Write(s, clientAddress, cbClientAddress); /* clientAddress */
|
||||||
Stream_Write_UINT16(s, 0);
|
Stream_Write_UINT16(s, 0);
|
||||||
|
|
||||||
Stream_Write_UINT16(s, cbClientDir + 2); /* cbClientDir */
|
Stream_Write_UINT16(s, cbClientDir + 2); /* cbClientDir (2 bytes) */
|
||||||
|
|
||||||
if (cbClientDir > 0)
|
if (cbClientDir > 0)
|
||||||
Stream_Write(s, clientDir, cbClientDir); /* clientDir */
|
Stream_Write(s, clientDir, cbClientDir); /* clientDir */
|
||||||
Stream_Write_UINT16(s, 0);
|
Stream_Write_UINT16(s, 0);
|
||||||
|
|
||||||
rdp_write_client_time_zone(s, settings); /* clientTimeZone */
|
rdp_write_client_time_zone(s, settings); /* clientTimeZone (172 bytes) */
|
||||||
|
|
||||||
Stream_Write_UINT32(s, 0); /* clientSessionId, should be set to 0 */
|
Stream_Write_UINT32(s, 0); /* clientSessionId (4 bytes), should be set to 0 */
|
||||||
|
|
||||||
freerdp_performance_flags_make(settings);
|
freerdp_performance_flags_make(settings);
|
||||||
Stream_Write_UINT32(s, settings->PerformanceFlags); /* performanceFlags */
|
Stream_Write_UINT32(s, settings->PerformanceFlags); /* performanceFlags (4 bytes) */
|
||||||
|
|
||||||
Stream_Write_UINT16(s, cbAutoReconnectLen); /* cbAutoReconnectLen */
|
Stream_Write_UINT16(s, cbAutoReconnectCookie); /* cbAutoReconnectCookie (2 bytes) */
|
||||||
|
|
||||||
if (cbAutoReconnectLen > 0)
|
if (cbAutoReconnectCookie > 0)
|
||||||
{
|
{
|
||||||
CryptoHmac hmac;
|
rdp_compute_client_auto_reconnect_cookie(rdp);
|
||||||
ARC_SC_PRIVATE_PACKET* serverCookie;
|
|
||||||
ARC_CS_PRIVATE_PACKET* clientCookie;
|
|
||||||
WLog_DBG(TAG, "Sending auto reconnect");
|
|
||||||
serverCookie = settings->ServerAutoReconnectCookie;
|
|
||||||
clientCookie = settings->ClientAutoReconnectCookie;
|
|
||||||
|
|
||||||
clientCookie->cbLen = serverCookie->cbLen;
|
rdp_write_client_auto_reconnect_cookie(rdp, s); /* autoReconnectCookie */
|
||||||
clientCookie->version = serverCookie->version;
|
|
||||||
clientCookie->logonId = serverCookie->logonId;
|
|
||||||
|
|
||||||
hmac = crypto_hmac_new();
|
Stream_Write_UINT16(s, 0); /* reserved1 (2 bytes) */
|
||||||
if (!hmac)
|
Stream_Write_UINT16(s, 0); /* reserved2 (2 bytes) */
|
||||||
{
|
|
||||||
WLog_ERR(TAG, "unable to allocate hmac");
|
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_hmac_md5_init(hmac, serverCookie->arcRandomBits, 16);
|
|
||||||
|
|
||||||
if (settings->SelectedProtocol == PROTOCOL_RDP)
|
|
||||||
{
|
|
||||||
crypto_hmac_update(hmac, (BYTE*) (settings->ClientRandom), 32);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Anthony Tong's version had 16 zeroes here; I'm not sure why.
|
|
||||||
* I do know that 16 did not reconnect correctly vs Win2008RDVH,
|
|
||||||
* and 32 did.
|
|
||||||
*/
|
|
||||||
const BYTE zeros[32] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
|
|
||||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
|
|
||||||
crypto_hmac_update(hmac, zeros, 32);
|
|
||||||
}
|
|
||||||
crypto_hmac_final(hmac, clientCookie->securityVerifier, 16);
|
|
||||||
|
|
||||||
rdp_write_client_auto_reconnect_cookie(s, settings); /* autoReconnectCookie */
|
|
||||||
/* mark as used */
|
|
||||||
settings->ServerAutoReconnectCookie->cbLen = 0;
|
|
||||||
crypto_hmac_free(hmac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reserved1 (2 bytes) */
|
|
||||||
/* reserved2 (2 bytes) */
|
|
||||||
out_free:
|
|
||||||
free(clientAddress);
|
free(clientAddress);
|
||||||
free(clientDir);
|
free(clientDir);
|
||||||
}
|
}
|
||||||
@ -312,7 +324,7 @@ out_free:
|
|||||||
* @param settings settings
|
* @param settings settings
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings)
|
BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
UINT32 flags;
|
UINT32 flags;
|
||||||
UINT16 cbDomain;
|
UINT16 cbDomain;
|
||||||
@ -321,12 +333,13 @@ BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
UINT16 cbAlternateShell;
|
UINT16 cbAlternateShell;
|
||||||
UINT16 cbWorkingDir;
|
UINT16 cbWorkingDir;
|
||||||
UINT32 CompressionLevel;
|
UINT32 CompressionLevel;
|
||||||
|
rdpSettings* settings = rdp->settings;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < 18)
|
if (Stream_GetRemainingLength(s) < 18)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Seek_UINT32(s); /* CodePage */
|
Stream_Seek_UINT32(s); /* CodePage (4 bytes ) */
|
||||||
Stream_Read_UINT32(s, flags); /* flags */
|
Stream_Read_UINT32(s, flags); /* flags (4 bytes) */
|
||||||
|
|
||||||
settings->AudioCapture = ((flags & INFO_AUDIOCAPTURE) ? TRUE : FALSE);
|
settings->AudioCapture = ((flags & INFO_AUDIOCAPTURE) ? TRUE : FALSE);
|
||||||
settings->AudioPlayback = ((flags & INFO_NOAUDIOPLAYBACK) ? FALSE : TRUE);
|
settings->AudioPlayback = ((flags & INFO_NOAUDIOPLAYBACK) ? FALSE : TRUE);
|
||||||
@ -341,11 +354,11 @@ BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
settings->CompressionLevel = CompressionLevel;
|
settings->CompressionLevel = CompressionLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream_Read_UINT16(s, cbDomain); /* cbDomain */
|
Stream_Read_UINT16(s, cbDomain); /* cbDomain (2 bytes) */
|
||||||
Stream_Read_UINT16(s, cbUserName); /* cbUserName */
|
Stream_Read_UINT16(s, cbUserName); /* cbUserName (2 bytes) */
|
||||||
Stream_Read_UINT16(s, cbPassword); /* cbPassword */
|
Stream_Read_UINT16(s, cbPassword); /* cbPassword (2 bytes) */
|
||||||
Stream_Read_UINT16(s, cbAlternateShell); /* cbAlternateShell */
|
Stream_Read_UINT16(s, cbAlternateShell); /* cbAlternateShell (2 bytes) */
|
||||||
Stream_Read_UINT16(s, cbWorkingDir); /* cbWorkingDir */
|
Stream_Read_UINT16(s, cbWorkingDir); /* cbWorkingDir (2 bytes) */
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < (size_t) (cbDomain + 2))
|
if (Stream_GetRemainingLength(s) < (size_t) (cbDomain + 2))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -398,7 +411,7 @@ BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
Stream_Seek(s, 2);
|
Stream_Seek(s, 2);
|
||||||
|
|
||||||
if (settings->RdpVersion >= 5)
|
if (settings->RdpVersion >= 5)
|
||||||
return rdp_read_extended_info_packet(s, settings); /* extraInfo */
|
return rdp_read_extended_info_packet(rdp, s); /* extraInfo */
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -410,7 +423,7 @@ BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
* @param settings settings
|
* @param settings settings
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void rdp_write_info_packet(wStream* s, rdpSettings* settings)
|
void rdp_write_info_packet(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
UINT32 flags;
|
UINT32 flags;
|
||||||
WCHAR* domainW = NULL;
|
WCHAR* domainW = NULL;
|
||||||
@ -424,6 +437,7 @@ void rdp_write_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
WCHAR* workingDirW = NULL;
|
WCHAR* workingDirW = NULL;
|
||||||
int cbWorkingDir = 0;
|
int cbWorkingDir = 0;
|
||||||
BOOL usedPasswordCookie = FALSE;
|
BOOL usedPasswordCookie = FALSE;
|
||||||
|
rdpSettings* settings = rdp->settings;
|
||||||
|
|
||||||
flags = INFO_MOUSE |
|
flags = INFO_MOUSE |
|
||||||
INFO_UNICODE |
|
INFO_UNICODE |
|
||||||
@ -527,14 +541,14 @@ void rdp_write_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
cbWorkingDir = ConvertToUnicode(CP_UTF8, 0, settings->RemoteAssistanceSessionId, -1, &workingDirW, 0) * 2;
|
cbWorkingDir = ConvertToUnicode(CP_UTF8, 0, settings->RemoteAssistanceSessionId, -1, &workingDirW, 0) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream_Write_UINT32(s, 0); /* CodePage */
|
Stream_Write_UINT32(s, 0); /* CodePage (4 bytes) */
|
||||||
Stream_Write_UINT32(s, flags); /* flags */
|
Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
|
||||||
|
|
||||||
Stream_Write_UINT16(s, cbDomain); /* cbDomain */
|
Stream_Write_UINT16(s, cbDomain); /* cbDomain (2 bytes) */
|
||||||
Stream_Write_UINT16(s, cbUserName); /* cbUserName */
|
Stream_Write_UINT16(s, cbUserName); /* cbUserName (2 bytes) */
|
||||||
Stream_Write_UINT16(s, cbPassword); /* cbPassword */
|
Stream_Write_UINT16(s, cbPassword); /* cbPassword (2 bytes) */
|
||||||
Stream_Write_UINT16(s, cbAlternateShell); /* cbAlternateShell */
|
Stream_Write_UINT16(s, cbAlternateShell); /* cbAlternateShell (2 bytes) */
|
||||||
Stream_Write_UINT16(s, cbWorkingDir); /* cbWorkingDir */
|
Stream_Write_UINT16(s, cbWorkingDir); /* cbWorkingDir (2 bytes) */
|
||||||
|
|
||||||
if (cbDomain > 0)
|
if (cbDomain > 0)
|
||||||
Stream_Write(s, domainW, cbDomain);
|
Stream_Write(s, domainW, cbDomain);
|
||||||
@ -565,7 +579,7 @@ void rdp_write_info_packet(wStream* s, rdpSettings* settings)
|
|||||||
free(passwordW);
|
free(passwordW);
|
||||||
|
|
||||||
if (settings->RdpVersion >= 5)
|
if (settings->RdpVersion >= 5)
|
||||||
rdp_write_extended_info_packet(s, settings); /* extraInfo */
|
rdp_write_extended_info_packet(rdp, s); /* extraInfo */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -594,7 +608,7 @@ BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s)
|
|||||||
{
|
{
|
||||||
if (securityFlags & SEC_REDIRECTION_PKT)
|
if (securityFlags & SEC_REDIRECTION_PKT)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Error: SEC_REDIRECTION_PKT unsupported");
|
WLog_ERR(TAG, "Error: SEC_REDIRECTION_PKT unsupported");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,13 +616,13 @@ BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s)
|
|||||||
{
|
{
|
||||||
if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
|
if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "rdp_decrypt failed");
|
WLog_ERR(TAG, "rdp_decrypt failed");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rdp_read_info_packet(s, rdp->settings);
|
return rdp_read_info_packet(rdp, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -627,7 +641,7 @@ BOOL rdp_send_client_info(rdpRdp* rdp)
|
|||||||
s = Stream_New(NULL, 2048);
|
s = Stream_New(NULL, 2048);
|
||||||
rdp_init_stream(rdp, s);
|
rdp_init_stream(rdp, s);
|
||||||
|
|
||||||
rdp_write_info_packet(s, rdp->settings);
|
rdp_write_info_packet(rdp, s);
|
||||||
|
|
||||||
status = rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
|
status = rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
|
||||||
|
|
||||||
@ -640,40 +654,48 @@ BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s)
|
|||||||
{
|
{
|
||||||
UINT32 cbDomain;
|
UINT32 cbDomain;
|
||||||
UINT32 cbUserName;
|
UINT32 cbUserName;
|
||||||
|
UINT32 SessionId;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < (4 + 52 + 4 + 512 + 4))
|
if (Stream_GetRemainingLength(s) < 576)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */
|
Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */
|
||||||
Stream_Seek(s, 52); /* domain (52 bytes) */
|
Stream_Seek(s, 52); /* domain (52 bytes) */
|
||||||
Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */
|
Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */
|
||||||
Stream_Seek(s, 512); /* userName (512 bytes) */
|
Stream_Seek(s, 512); /* userName (512 bytes) */
|
||||||
Stream_Seek_UINT32(s); /* sessionId (4 bytes) */
|
Stream_Read_UINT32(s, SessionId); /* SessionId (4 bytes) */
|
||||||
|
|
||||||
|
WLog_DBG(TAG, "LogonInfoV1: SessionId: 0x%04X", SessionId);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s)
|
BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
|
UINT16 Version;
|
||||||
|
UINT32 Size;
|
||||||
|
UINT32 SessionId;
|
||||||
UINT32 cbDomain;
|
UINT32 cbDomain;
|
||||||
UINT32 cbUserName;
|
UINT32 cbUserName;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < (2 + 4 + 4 + 4 + 4 + 558))
|
if (Stream_GetRemainingLength(s) < 576)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Seek_UINT16(s); /* version (2 bytes) */
|
Stream_Read_UINT16(s, Version); /* Version (2 bytes) */
|
||||||
Stream_Seek_UINT32(s); /* size (4 bytes) */
|
Stream_Read_UINT32(s, Size); /* Size (4 bytes) */
|
||||||
Stream_Seek_UINT32(s); /* sessionId (4 bytes) */
|
Stream_Read_UINT32(s, SessionId); /* SessionId (4 bytes) */
|
||||||
Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */
|
Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */
|
||||||
Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */
|
Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */
|
||||||
Stream_Seek(s, 558); /* pad */
|
Stream_Seek(s, 558); /* pad (558 bytes) */
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < cbDomain+cbUserName)
|
if (Stream_GetRemainingLength(s) < (cbDomain + cbUserName))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Seek(s, cbDomain); /* domain */
|
Stream_Seek(s, cbDomain); /* domain */
|
||||||
Stream_Seek(s, cbUserName); /* userName */
|
Stream_Seek(s, cbUserName); /* userName */
|
||||||
|
|
||||||
|
WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X", SessionId);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,7 +704,9 @@ BOOL rdp_recv_logon_plain_notify(rdpRdp* rdp, wStream* s)
|
|||||||
if (Stream_GetRemainingLength(s) < 576)
|
if (Stream_GetRemainingLength(s) < 576)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Seek(s, 576); /* pad */
|
Stream_Seek(s, 576); /* pad (576 bytes) */
|
||||||
|
|
||||||
|
WLog_DBG(TAG, "LogonPlainNotify");
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -698,6 +722,9 @@ BOOL rdp_recv_logon_error_info(rdpRdp* rdp, wStream* s)
|
|||||||
Stream_Read_UINT32(s, errorNotificationData); /* errorNotificationData (4 bytes) */
|
Stream_Read_UINT32(s, errorNotificationData); /* errorNotificationData (4 bytes) */
|
||||||
Stream_Read_UINT32(s, errorNotificationType); /* errorNotificationType (4 bytes) */
|
Stream_Read_UINT32(s, errorNotificationType); /* errorNotificationType (4 bytes) */
|
||||||
|
|
||||||
|
WLog_DBG(TAG, "LogonErrorInfo: Data: 0x%04X Type: 0x%04X",
|
||||||
|
errorNotificationData, errorNotificationType);
|
||||||
|
|
||||||
IFCALL(rdp->instance->LogonErrorInfo, rdp->instance, errorNotificationData, errorNotificationType);
|
IFCALL(rdp->instance->LogonErrorInfo, rdp->instance, errorNotificationData, errorNotificationType);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -712,9 +739,14 @@ BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s)
|
|||||||
if (Stream_GetRemainingLength(s) < 6)
|
if (Stream_GetRemainingLength(s) < 6)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT16(s, Length); /* The total size in bytes of this structure */
|
Stream_Read_UINT16(s, Length); /* Length (2 bytes) */
|
||||||
Stream_Read_UINT32(s, fieldsPresent); /* fieldsPresent (4 bytes) */
|
Stream_Read_UINT32(s, fieldsPresent); /* fieldsPresent (4 bytes) */
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < (Length - 6))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
WLog_DBG(TAG, "LogonInfoExtended: fieldsPresent: 0x%04X", fieldsPresent);
|
||||||
|
|
||||||
/* logonFields */
|
/* logonFields */
|
||||||
|
|
||||||
if (fieldsPresent & LOGON_EX_AUTORECONNECTCOOKIE)
|
if (fieldsPresent & LOGON_EX_AUTORECONNECTCOOKIE)
|
||||||
@ -724,7 +756,7 @@ BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s)
|
|||||||
|
|
||||||
Stream_Read_UINT32(s, cbFieldData); /* cbFieldData (4 bytes) */
|
Stream_Read_UINT32(s, cbFieldData); /* cbFieldData (4 bytes) */
|
||||||
|
|
||||||
if (rdp_read_server_auto_reconnect_cookie(s, rdp->settings) == FALSE)
|
if (!rdp_read_server_auto_reconnect_cookie(rdp, s))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,14 +767,14 @@ BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s)
|
|||||||
|
|
||||||
Stream_Read_UINT32(s, cbFieldData); /* cbFieldData (4 bytes) */
|
Stream_Read_UINT32(s, cbFieldData); /* cbFieldData (4 bytes) */
|
||||||
|
|
||||||
if (rdp_recv_logon_error_info(rdp, s) == FALSE)
|
if (!rdp_recv_logon_error_info(rdp, s))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < 570)
|
if (Stream_GetRemainingLength(s) < 570)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Seek(s, 570); /* pad */
|
Stream_Seek(s, 570); /* pad (570 bytes) */
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -750,31 +782,41 @@ BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s)
|
|||||||
BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s)
|
BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
UINT32 infoType;
|
UINT32 infoType;
|
||||||
|
BOOL status = FALSE;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < 4)
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
Stream_Read_UINT32(s, infoType); /* infoType (4 bytes) */
|
|
||||||
|
|
||||||
//WLog_ERR(TAG, "%s", INFO_TYPE_LOGON_STRINGS[infoType]);
|
Stream_Read_UINT32(s, infoType); /* infoType (4 bytes) */
|
||||||
|
|
||||||
switch (infoType)
|
switch (infoType)
|
||||||
{
|
{
|
||||||
case INFO_TYPE_LOGON:
|
case INFO_TYPE_LOGON:
|
||||||
return rdp_recv_logon_info_v1(rdp, s);
|
status = rdp_recv_logon_info_v1(rdp, s);
|
||||||
|
break;
|
||||||
|
|
||||||
case INFO_TYPE_LOGON_LONG:
|
case INFO_TYPE_LOGON_LONG:
|
||||||
return rdp_recv_logon_info_v2(rdp, s);
|
status = rdp_recv_logon_info_v2(rdp, s);
|
||||||
|
break;
|
||||||
|
|
||||||
case INFO_TYPE_LOGON_PLAIN_NOTIFY:
|
case INFO_TYPE_LOGON_PLAIN_NOTIFY:
|
||||||
return rdp_recv_logon_plain_notify(rdp, s);
|
status = rdp_recv_logon_plain_notify(rdp, s);
|
||||||
|
break;
|
||||||
|
|
||||||
case INFO_TYPE_LOGON_EXTENDED_INF:
|
case INFO_TYPE_LOGON_EXTENDED_INF:
|
||||||
return rdp_recv_logon_info_extended(rdp, s);
|
status = rdp_recv_logon_info_extended(rdp, s);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
if (!status)
|
||||||
|
{
|
||||||
|
WLog_DBG(TAG, "SaveSessionInfo error: infoType: %s (%d)",
|
||||||
|
infoType < 4 ? INFO_TYPE_LOGON_STRINGS[infoType % 4] : "Unknown", infoType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,11 @@
|
|||||||
|
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
|
|
||||||
|
#define INFO_TYPE_LOGON 0x00000000
|
||||||
|
#define INFO_TYPE_LOGON_LONG 0x00000001
|
||||||
|
#define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002
|
||||||
|
#define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003
|
||||||
|
|
||||||
/* Client Address Family */
|
/* Client Address Family */
|
||||||
#define ADDRESS_FAMILY_INET 0x0002
|
#define ADDRESS_FAMILY_INET 0x0002
|
||||||
#define ADDRESS_FAMILY_INET6 0x0017
|
#define ADDRESS_FAMILY_INET6 0x0017
|
||||||
@ -67,19 +72,14 @@
|
|||||||
#define LOGON_FAILED_OTHER 0x00000002
|
#define LOGON_FAILED_OTHER 0x00000002
|
||||||
#define LOGON_WARNING 0x00000003
|
#define LOGON_WARNING 0x00000003
|
||||||
|
|
||||||
void rdp_read_system_time(wStream* s, SYSTEM_TIME* system_time);
|
BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s);
|
||||||
void rdp_write_system_time(wStream* s, SYSTEM_TIME* system_time);
|
BOOL rdp_read_client_auto_reconnect_cookie(rdpRdp* rdp, wStream* s);
|
||||||
void rdp_get_client_time_zone(wStream* s, rdpSettings* settings);
|
void rdp_write_client_auto_reconnect_cookie(rdpRdp* rdp, wStream* s);
|
||||||
BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings);
|
void rdp_write_auto_reconnect_cookie(rdpRdp* rdp, wStream* s);
|
||||||
void rdp_write_client_time_zone(wStream* s, rdpSettings* settings);
|
BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s);
|
||||||
BOOL rdp_read_server_auto_reconnect_cookie(wStream* s, rdpSettings* settings);
|
void rdp_write_extended_info_packet(rdpRdp* rdp, wStream* s);
|
||||||
BOOL rdp_read_client_auto_reconnect_cookie(wStream* s, rdpSettings* settings);
|
BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s);
|
||||||
void rdp_write_client_auto_reconnect_cookie(wStream* s, rdpSettings* settings);
|
void rdp_write_info_packet(rdpRdp* rdp, wStream* s);
|
||||||
void rdp_write_auto_reconnect_cookie(wStream* s, rdpSettings* settings);
|
|
||||||
BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings);
|
|
||||||
void rdp_write_extended_info_packet(wStream* s, rdpSettings* settings);
|
|
||||||
BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings);
|
|
||||||
void rdp_write_info_packet(wStream* s, rdpSettings* settings);
|
|
||||||
BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s);
|
BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s);
|
||||||
BOOL rdp_send_client_info(rdpRdp* rdp);
|
BOOL rdp_send_client_info(rdpRdp* rdp);
|
||||||
BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s);
|
BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s);
|
||||||
|
@ -654,6 +654,9 @@ BOOL rdp_recv_server_auto_reconnect_status_pdu(rdpRdp* rdp, wStream* s)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT32(s, arcStatus); /* arcStatus (4 bytes) */
|
Stream_Read_UINT32(s, arcStatus); /* arcStatus (4 bytes) */
|
||||||
|
|
||||||
|
WLog_WARN(TAG, "AutoReconnectStatus: 0x%04X", arcStatus);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1424,29 +1427,60 @@ void rdp_reset(rdpRdp* rdp)
|
|||||||
|
|
||||||
bulk_reset(rdp->bulk);
|
bulk_reset(rdp->bulk);
|
||||||
|
|
||||||
crypto_rc4_free(rdp->rc4_decrypt_key);
|
if (rdp->rc4_decrypt_key)
|
||||||
rdp->rc4_decrypt_key = NULL;
|
{
|
||||||
crypto_rc4_free(rdp->rc4_encrypt_key);
|
crypto_rc4_free(rdp->rc4_decrypt_key);
|
||||||
rdp->rc4_encrypt_key = NULL;
|
rdp->rc4_decrypt_key = NULL;
|
||||||
crypto_des3_free(rdp->fips_encrypt);
|
}
|
||||||
rdp->fips_encrypt = NULL;
|
|
||||||
crypto_des3_free(rdp->fips_decrypt);
|
if (rdp->rc4_encrypt_key)
|
||||||
rdp->fips_decrypt = NULL;
|
{
|
||||||
crypto_hmac_free(rdp->fips_hmac);
|
crypto_rc4_free(rdp->rc4_encrypt_key);
|
||||||
rdp->fips_hmac = NULL;
|
rdp->rc4_encrypt_key = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rdp->fips_encrypt)
|
||||||
|
{
|
||||||
|
crypto_des3_free(rdp->fips_encrypt);
|
||||||
|
rdp->fips_encrypt = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rdp->fips_decrypt)
|
||||||
|
{
|
||||||
|
crypto_des3_free(rdp->fips_decrypt);
|
||||||
|
rdp->fips_decrypt = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rdp->fips_hmac)
|
||||||
|
{
|
||||||
|
crypto_hmac_free(rdp->fips_hmac);
|
||||||
|
rdp->fips_hmac = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->ServerRandom)
|
||||||
|
{
|
||||||
|
free(settings->ServerRandom);
|
||||||
|
settings->ServerRandom = NULL;
|
||||||
|
settings->ServerRandomLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->ServerCertificate)
|
||||||
|
{
|
||||||
|
free(settings->ServerCertificate);
|
||||||
|
settings->ServerCertificate = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->ClientAddress)
|
||||||
|
{
|
||||||
|
free(settings->ClientAddress);
|
||||||
|
settings->ClientAddress = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
mcs_free(rdp->mcs);
|
mcs_free(rdp->mcs);
|
||||||
nego_free(rdp->nego);
|
nego_free(rdp->nego);
|
||||||
license_free(rdp->license);
|
license_free(rdp->license);
|
||||||
transport_free(rdp->transport);
|
transport_free(rdp->transport);
|
||||||
|
|
||||||
free(settings->ServerRandom);
|
|
||||||
settings->ServerRandom = NULL;
|
|
||||||
free(settings->ServerCertificate);
|
|
||||||
settings->ServerCertificate = NULL;
|
|
||||||
free(settings->ClientAddress);
|
|
||||||
settings->ClientAddress = NULL;
|
|
||||||
|
|
||||||
rdp->transport = transport_new(context);
|
rdp->transport = transport_new(context);
|
||||||
rdp->transport->rdp = rdp;
|
rdp->transport->rdp = rdp;
|
||||||
rdp->license = license_new(rdp);
|
rdp->license = license_new(rdp);
|
||||||
|
@ -483,6 +483,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
|||||||
_settings->RemoteAssistancePassword = _strdup(settings->RemoteAssistancePassword); /* 1027 */
|
_settings->RemoteAssistancePassword = _strdup(settings->RemoteAssistancePassword); /* 1027 */
|
||||||
_settings->RemoteAssistanceRCTicket = _strdup(settings->RemoteAssistanceRCTicket); /* 1028 */
|
_settings->RemoteAssistanceRCTicket = _strdup(settings->RemoteAssistanceRCTicket); /* 1028 */
|
||||||
_settings->AuthenticationServiceClass = _strdup(settings->AuthenticationServiceClass); /* 1098 */
|
_settings->AuthenticationServiceClass = _strdup(settings->AuthenticationServiceClass); /* 1098 */
|
||||||
|
_settings->AllowedTlsCiphers = _strdup(settings->AllowedTlsCiphers); /* 1101 */
|
||||||
_settings->PreconnectionBlob = _strdup(settings->PreconnectionBlob); /* 1155 */
|
_settings->PreconnectionBlob = _strdup(settings->PreconnectionBlob); /* 1155 */
|
||||||
_settings->KerberosKdc = _strdup(settings->KerberosKdc); /* 1344 */
|
_settings->KerberosKdc = _strdup(settings->KerberosKdc); /* 1344 */
|
||||||
_settings->KerberosRealm = _strdup(settings->KerberosRealm); /* 1345 */
|
_settings->KerberosRealm = _strdup(settings->KerberosRealm); /* 1345 */
|
||||||
@ -542,12 +543,19 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
|||||||
{
|
{
|
||||||
_settings->ServerRandom = (BYTE*) malloc(_settings->ServerRandomLength);
|
_settings->ServerRandom = (BYTE*) malloc(_settings->ServerRandomLength);
|
||||||
CopyMemory(_settings->ServerRandom, settings->ServerRandom, _settings->ServerRandomLength);
|
CopyMemory(_settings->ServerRandom, settings->ServerRandom, _settings->ServerRandomLength);
|
||||||
|
_settings->ServerRandomLength = settings->ServerRandomLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_settings->ClientRandomLength)
|
if (_settings->ClientRandomLength)
|
||||||
{
|
{
|
||||||
_settings->ClientRandom = (BYTE*) malloc(_settings->ClientRandomLength);
|
_settings->ClientRandom = (BYTE*) malloc(_settings->ClientRandomLength);
|
||||||
CopyMemory(_settings->ClientRandom, settings->ClientRandom, _settings->ClientRandomLength);
|
CopyMemory(_settings->ClientRandom, settings->ClientRandom, _settings->ClientRandomLength);
|
||||||
|
_settings->ClientRandomLength = settings->ClientRandomLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->RdpServerCertificate)
|
||||||
|
{
|
||||||
|
_settings->RdpServerCertificate = certificate_clone(settings->RdpServerCertificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
_settings->ChannelCount = settings->ChannelCount;
|
_settings->ChannelCount = settings->ChannelCount;
|
||||||
@ -608,9 +616,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
|||||||
|
|
||||||
_settings->StaticChannelCount = settings->StaticChannelCount;
|
_settings->StaticChannelCount = settings->StaticChannelCount;
|
||||||
_settings->StaticChannelArraySize = settings->StaticChannelArraySize;
|
_settings->StaticChannelArraySize = settings->StaticChannelArraySize;
|
||||||
_settings->StaticChannelArray = (ADDIN_ARGV**)
|
_settings->StaticChannelArray = (ADDIN_ARGV**) calloc(_settings->StaticChannelArraySize, sizeof(ADDIN_ARGV*));
|
||||||
malloc(sizeof(ADDIN_ARGV*) * _settings->StaticChannelArraySize);
|
|
||||||
ZeroMemory(_settings->StaticChannelArray, sizeof(ADDIN_ARGV*) * _settings->StaticChannelArraySize);
|
|
||||||
|
|
||||||
for (index = 0; index < _settings->StaticChannelCount; index++)
|
for (index = 0; index < _settings->StaticChannelCount; index++)
|
||||||
{
|
{
|
||||||
@ -619,9 +625,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
|||||||
|
|
||||||
_settings->DynamicChannelCount = settings->DynamicChannelCount;
|
_settings->DynamicChannelCount = settings->DynamicChannelCount;
|
||||||
_settings->DynamicChannelArraySize = settings->DynamicChannelArraySize;
|
_settings->DynamicChannelArraySize = settings->DynamicChannelArraySize;
|
||||||
_settings->DynamicChannelArray = (ADDIN_ARGV**)
|
_settings->DynamicChannelArray = (ADDIN_ARGV**) calloc(_settings->DynamicChannelArraySize, sizeof(ADDIN_ARGV*));
|
||||||
malloc(sizeof(ADDIN_ARGV*) * _settings->DynamicChannelArraySize);
|
|
||||||
ZeroMemory(_settings->DynamicChannelArray, sizeof(ADDIN_ARGV*) * _settings->DynamicChannelArraySize);
|
|
||||||
|
|
||||||
for (index = 0; index < _settings->DynamicChannelCount; index++)
|
for (index = 0; index < _settings->DynamicChannelCount; index++)
|
||||||
{
|
{
|
||||||
@ -651,7 +655,7 @@ void freerdp_settings_free(rdpSettings* settings)
|
|||||||
free(settings->MonitorDefArray);
|
free(settings->MonitorDefArray);
|
||||||
free(settings->ClientAddress);
|
free(settings->ClientAddress);
|
||||||
free(settings->ClientDir);
|
free(settings->ClientDir);
|
||||||
free(settings->PermittedTLSCiphers);
|
free(settings->AllowedTlsCiphers);
|
||||||
free(settings->CertificateFile);
|
free(settings->CertificateFile);
|
||||||
free(settings->PrivateKeyFile);
|
free(settings->PrivateKeyFile);
|
||||||
free(settings->ConnectionFile);
|
free(settings->ConnectionFile);
|
||||||
|
@ -511,7 +511,7 @@ static CryptoCert tls_get_certificate(rdpTls* tls, BOOL peer)
|
|||||||
|
|
||||||
if (!remote_cert)
|
if (!remote_cert)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "failed to get the server TLS certificate");
|
WLog_ERR(TAG, "failed to get the server TLS certificate");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,10 +581,13 @@ BOOL tls_prepare(rdpTls* tls, BIO *underlying, SSL_METHOD *method, int options,
|
|||||||
BOOL tls_prepare(rdpTls* tls, BIO *underlying, const SSL_METHOD *method, int options, BOOL clientMode)
|
BOOL tls_prepare(rdpTls* tls, BIO *underlying, const SSL_METHOD *method, int options, BOOL clientMode)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
rdpSettings* settings = tls->settings;
|
||||||
|
|
||||||
tls->ctx = SSL_CTX_new(method);
|
tls->ctx = SSL_CTX_new(method);
|
||||||
|
|
||||||
if (!tls->ctx)
|
if (!tls->ctx)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "SSL_CTX_new failed");
|
WLog_ERR(TAG, "SSL_CTX_new failed");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,9 +596,11 @@ BOOL tls_prepare(rdpTls* tls, BIO *underlying, const SSL_METHOD *method, int opt
|
|||||||
SSL_CTX_set_options(tls->ctx, options);
|
SSL_CTX_set_options(tls->ctx, options);
|
||||||
SSL_CTX_set_read_ahead(tls->ctx, 1);
|
SSL_CTX_set_read_ahead(tls->ctx, 1);
|
||||||
|
|
||||||
if (tls->settings->PermittedTLSCiphers) {
|
if (settings->AllowedTlsCiphers)
|
||||||
if(!SSL_CTX_set_cipher_list(tls->ctx, tls->settings->PermittedTLSCiphers)) {
|
{
|
||||||
WLog_ERR(TAG, "SSL_CTX_set_cipher_list %s failed", tls->settings->PermittedTLSCiphers);
|
if (!SSL_CTX_set_cipher_list(tls->ctx, settings->AllowedTlsCiphers))
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "SSL_CTX_set_cipher_list %s failed", settings->AllowedTlsCiphers);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -604,7 +609,7 @@ BOOL tls_prepare(rdpTls* tls, BIO *underlying, const SSL_METHOD *method, int opt
|
|||||||
|
|
||||||
if (BIO_get_ssl(tls->bio, &tls->ssl) < 0)
|
if (BIO_get_ssl(tls->bio, &tls->ssl) < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "unable to retrieve the SSL of the connection");
|
WLog_ERR(TAG, "unable to retrieve the SSL of the connection");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,7 +647,7 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
|
|||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "unable to retrieve BIO fd");
|
WLog_ERR(TAG, "unable to retrieve BIO fd");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,7 +671,7 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
|
|||||||
#endif
|
#endif
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "error during select()");
|
WLog_ERR(TAG, "error during select()");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -675,21 +680,21 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
|
|||||||
cert = tls_get_certificate(tls, clientMode);
|
cert = tls_get_certificate(tls, clientMode);
|
||||||
if (!cert)
|
if (!cert)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "tls_get_certificate failed to return the server certificate.");
|
WLog_ERR(TAG, "tls_get_certificate failed to return the server certificate.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls->Bindings = tls_get_channel_bindings(cert->px509);
|
tls->Bindings = tls_get_channel_bindings(cert->px509);
|
||||||
if (!tls->Bindings)
|
if (!tls->Bindings)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "unable to retrieve bindings");
|
WLog_ERR(TAG, "unable to retrieve bindings");
|
||||||
verify_status = -1;
|
verify_status = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
|
if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "crypto_cert_get_public_key failed to return the server public key.");
|
WLog_ERR(TAG, "crypto_cert_get_public_key failed to return the server public key.");
|
||||||
verify_status = -1;
|
verify_status = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -704,7 +709,7 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
|
|||||||
|
|
||||||
if (verify_status < 1)
|
if (verify_status < 1)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "certificate not trusted, aborting.");
|
WLog_ERR(TAG, "certificate not trusted, aborting.");
|
||||||
tls_disconnect(tls);
|
tls_disconnect(tls);
|
||||||
verify_status = 0;
|
verify_status = 0;
|
||||||
}
|
}
|
||||||
@ -755,8 +760,6 @@ int tls_connect(rdpTls* tls, BIO *underlying)
|
|||||||
return tls_do_handshake(tls, TRUE);
|
return tls_do_handshake(tls, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOL tls_accept(rdpTls* tls, BIO *underlying, const char* cert_file, const char* privatekey_file)
|
BOOL tls_accept(rdpTls* tls, BIO *underlying, const char* cert_file, const char* privatekey_file)
|
||||||
{
|
{
|
||||||
long options = 0;
|
long options = 0;
|
||||||
@ -803,14 +806,14 @@ BOOL tls_accept(rdpTls* tls, BIO *underlying, const char* cert_file, const char*
|
|||||||
|
|
||||||
if (SSL_use_RSAPrivateKey_file(tls->ssl, privatekey_file, SSL_FILETYPE_PEM) <= 0)
|
if (SSL_use_RSAPrivateKey_file(tls->ssl, privatekey_file, SSL_FILETYPE_PEM) <= 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed");
|
WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed");
|
||||||
WLog_ERR(TAG, "PrivateKeyFile: %s", privatekey_file);
|
WLog_ERR(TAG, "PrivateKeyFile: %s", privatekey_file);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0)
|
if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "SSL_use_certificate_file failed");
|
WLog_ERR(TAG, "SSL_use_certificate_file failed");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1096,7 +1099,7 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por
|
|||||||
|
|
||||||
if (!bio)
|
if (!bio)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "BIO_new() failure");
|
WLog_ERR(TAG, "BIO_new() failure");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1104,7 +1107,7 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por
|
|||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
|
WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1116,7 +1119,7 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por
|
|||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "failed to read certificate");
|
WLog_ERR(TAG, "failed to read certificate");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1137,7 +1140,7 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por
|
|||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "failed to read certificate");
|
WLog_ERR(TAG, "failed to read certificate");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1151,7 +1154,7 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por
|
|||||||
status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, tls->isGatewayTransport);
|
status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, tls->isGatewayTransport);
|
||||||
}
|
}
|
||||||
|
|
||||||
WLog_ERR(TAG, "(length = %d) status: %d%s", length, status, pemCert);
|
WLog_ERR(TAG, "(length = %d) status: %d%s", length, status, pemCert);
|
||||||
|
|
||||||
free(pemCert);
|
free(pemCert);
|
||||||
BIO_free(bio);
|
BIO_free(bio);
|
||||||
@ -1311,18 +1314,18 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por
|
|||||||
|
|
||||||
void tls_print_certificate_error(char* hostname, char* fingerprint, char *hosts_file)
|
void tls_print_certificate_error(char* hostname, char* fingerprint, char *hosts_file)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "The host key for %s has changed", hostname);
|
WLog_ERR(TAG, "The host key for %s has changed", hostname);
|
||||||
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
WLog_ERR(TAG, "@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
|
WLog_ERR(TAG, "@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
|
||||||
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
WLog_ERR(TAG, "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
|
WLog_ERR(TAG, "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
|
||||||
WLog_ERR(TAG, "Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
|
WLog_ERR(TAG, "Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
|
||||||
WLog_ERR(TAG, "It is also possible that a host key has just been changed.");
|
WLog_ERR(TAG, "It is also possible that a host key has just been changed.");
|
||||||
WLog_ERR(TAG, "The fingerprint for the host key sent by the remote host is%s", fingerprint);
|
WLog_ERR(TAG, "The fingerprint for the host key sent by the remote host is%s", fingerprint);
|
||||||
WLog_ERR(TAG, "Please contact your system administrator.");
|
WLog_ERR(TAG, "Please contact your system administrator.");
|
||||||
WLog_ERR(TAG, "Add correct host key in %s to get rid of this message.", hosts_file);
|
WLog_ERR(TAG, "Add correct host key in %s to get rid of this message.", hosts_file);
|
||||||
WLog_ERR(TAG, "Host key for %s has changed and you have requested strict checking.", hostname);
|
WLog_ERR(TAG, "Host key for %s has changed and you have requested strict checking.", hostname);
|
||||||
WLog_ERR(TAG, "Host key verification failed.");
|
WLog_ERR(TAG, "Host key verification failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count)
|
void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count)
|
||||||
@ -1330,24 +1333,24 @@ void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name
|
|||||||
int index;
|
int index;
|
||||||
|
|
||||||
assert(NULL != hostname);
|
assert(NULL != hostname);
|
||||||
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
WLog_ERR(TAG, "@ WARNING: CERTIFICATE NAME MISMATCH! @");
|
WLog_ERR(TAG, "@ WARNING: CERTIFICATE NAME MISMATCH! @");
|
||||||
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
WLog_ERR(TAG, "The hostname used for this connection (%s) ", hostname);
|
WLog_ERR(TAG, "The hostname used for this connection (%s) ", hostname);
|
||||||
WLog_ERR(TAG, "does not match %s given in the certificate:", alt_names_count < 1 ? "the name" : "any of the names");
|
WLog_ERR(TAG, "does not match %s given in the certificate:", alt_names_count < 1 ? "the name" : "any of the names");
|
||||||
WLog_ERR(TAG, "Common Name (CN):");
|
WLog_ERR(TAG, "Common Name (CN):");
|
||||||
WLog_ERR(TAG, "\t%s", common_name ? common_name : "no CN found in certificate");
|
WLog_ERR(TAG, "\t%s", common_name ? common_name : "no CN found in certificate");
|
||||||
if (alt_names_count > 0)
|
if (alt_names_count > 0)
|
||||||
{
|
{
|
||||||
assert(NULL != alt_names);
|
assert(NULL != alt_names);
|
||||||
WLog_ERR(TAG, "Alternative names:");
|
WLog_ERR(TAG, "Alternative names:");
|
||||||
for (index = 0; index < alt_names_count; index++)
|
for (index = 0; index < alt_names_count; index++)
|
||||||
{
|
{
|
||||||
assert(alt_names[index]);
|
assert(alt_names[index]);
|
||||||
WLog_ERR(TAG, "\t %s", alt_names[index]);
|
WLog_ERR(TAG, "\t %s", alt_names[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WLog_ERR(TAG, "A valid certificate for the wrong name should NOT be trusted!");
|
WLog_ERR(TAG, "A valid certificate for the wrong name should NOT be trusted!");
|
||||||
}
|
}
|
||||||
|
|
||||||
rdpTls* tls_new(rdpSettings* settings)
|
rdpTls* tls_new(rdpSettings* settings)
|
||||||
@ -1392,6 +1395,12 @@ void tls_free(rdpTls* tls)
|
|||||||
tls->ctx = NULL;
|
tls->ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tls->bio)
|
||||||
|
{
|
||||||
|
BIO_free(tls->bio);
|
||||||
|
tls->bio = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (tls->PublicKey)
|
if (tls->PublicKey)
|
||||||
{
|
{
|
||||||
free(tls->PublicKey);
|
free(tls->PublicKey);
|
||||||
|
Loading…
Reference in New Issue
Block a user