24#include <winpr/crypto.h>
25#include <winpr/print.h>
27#include <freerdp/server/proxy/proxy_log.h>
28#include <freerdp/server/proxy/proxy_server.h>
29#include <freerdp/channels/drdynvc.h>
34#include "proxy_modules.h"
36#include <freerdp/server/proxy/proxy_context.h>
38#include "channels/pf_channel_rdpdr.h"
40#define TAG PROXY_TAG("server")
43static UINT32 ChannelId_Hash(
const void* key)
45 const UINT32* v = (
const UINT32*)key;
50static BOOL ChannelId_Compare(
const void* pv1,
const void* pv2)
52 const UINT32* v1 = pv1;
53 const UINT32* v2 = pv2;
60static BOOL dyn_intercept(pServerContext* ps,
const char* name)
62 if (strncmp(DRDYNVC_SVC_CHANNEL_NAME, name,
sizeof(DRDYNVC_SVC_CHANNEL_NAME)) != 0)
66 WINPR_ASSERT(ps->pdata);
68 const proxyConfig* cfg = ps->pdata->config;
72 if (!cfg->AudioOutput)
78 if (!cfg->VideoRedirection)
80 if (!cfg->CameraRedirection)
85pServerStaticChannelContext* StaticChannelContext_new(pServerContext* ps,
const char* name,
88 pServerStaticChannelContext* ret = calloc(1,
sizeof(*ret));
91 PROXY_LOG_ERR(TAG, ps,
"error allocating channel context for '%s'", name);
95 ret->front_channel_id = id;
96 ret->channel_name = _strdup(name);
97 if (!ret->channel_name)
99 PROXY_LOG_ERR(TAG, ps,
"error allocating name in channel context for '%s'", name);
106 if (pf_modules_run_filter(ps->pdata->module, FILTER_TYPE_STATIC_INTERCEPT_LIST, ps->pdata,
109 ret->channelMode = PF_UTILS_CHANNEL_INTERCEPT;
110 else if (dyn_intercept(ps, name))
111 ret->channelMode = PF_UTILS_CHANNEL_INTERCEPT;
113 ret->channelMode = pf_utils_get_channel_mode(ps->pdata->config, name);
117void StaticChannelContext_free(pServerStaticChannelContext* ctx)
122 IFCALL(ctx->contextDtor, ctx->context);
124 free(ctx->channel_name);
128static void HashStaticChannelContext_free(
void* ptr)
130 pServerStaticChannelContext* ctx = (pServerStaticChannelContext*)ptr;
131 StaticChannelContext_free(ctx);
135static void client_to_proxy_context_free(freerdp_peer* client, rdpContext* ctx);
138static BOOL client_to_proxy_context_new(freerdp_peer* client, rdpContext* ctx)
141 pServerContext* context = (pServerContext*)ctx;
143 WINPR_ASSERT(client);
144 WINPR_ASSERT(context);
146 context->dynvcReady =
nullptr;
148 context->vcm = WTSOpenServerA((LPSTR)client->context);
150 if (!context->vcm || context->vcm == INVALID_HANDLE_VALUE)
153 if (!(context->dynvcReady = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
156 context->interceptContextMap = HashTable_New(FALSE);
157 if (!context->interceptContextMap)
159 if (!HashTable_SetupForStringData(context->interceptContextMap, FALSE))
161 obj = HashTable_ValueObject(context->interceptContextMap);
166 context->channelsByFrontId = HashTable_New(FALSE);
167 if (!context->channelsByFrontId)
169 if (!HashTable_SetHashFunction(context->channelsByFrontId, ChannelId_Hash))
172 obj = HashTable_KeyObject(context->channelsByFrontId);
175 obj = HashTable_ValueObject(context->channelsByFrontId);
178 context->channelsByBackId = HashTable_New(FALSE);
179 if (!context->channelsByBackId)
181 if (!HashTable_SetHashFunction(context->channelsByBackId, ChannelId_Hash))
184 obj = HashTable_KeyObject(context->channelsByBackId);
190 client_to_proxy_context_free(client, ctx);
196void client_to_proxy_context_free(freerdp_peer* client, rdpContext* ctx)
198 pServerContext* context = (pServerContext*)ctx;
200 WINPR_UNUSED(client);
205 if (context->dynvcReady)
207 (void)CloseHandle(context->dynvcReady);
208 context->dynvcReady =
nullptr;
211 HashTable_Free(context->interceptContextMap);
212 HashTable_Free(context->channelsByFrontId);
213 HashTable_Free(context->channelsByBackId);
215 if (context->vcm && (context->vcm != INVALID_HANDLE_VALUE))
216 WTSCloseServer(context->vcm);
217 context->vcm =
nullptr;
220BOOL pf_context_init_server_context(freerdp_peer* client)
222 WINPR_ASSERT(client);
224 client->ContextSize =
sizeof(pServerContext);
225 client->ContextNew = client_to_proxy_context_new;
226 client->ContextFree = client_to_proxy_context_free;
228 return freerdp_peer_context_new(client);
232static BOOL pf_context_revert_str_settings(rdpSettings* dst,
const rdpSettings* before,
size_t nr,
233 const FreeRDP_Settings_Keys_String* ids)
236 WINPR_ASSERT(before);
237 WINPR_ASSERT(ids || (nr == 0));
239 for (
size_t x = 0; x < nr; x++)
241 FreeRDP_Settings_Keys_String
id = ids[x];
250void intercept_context_entry_free(
void* obj)
260BOOL pf_context_copy_settings(rdpSettings* dst,
const rdpSettings* src)
263 rdpSettings* before_copy =
nullptr;
264 const FreeRDP_Settings_Keys_String to_revert[] = { FreeRDP_ConfigPath,
265 FreeRDP_CertificateName };
282 if (!pf_context_revert_str_settings(dst, before_copy, ARRAYSIZE(to_revert), to_revert))
308pClientContext* pf_context_create_client_context(
const rdpSettings* clientSettings)
310 RDP_CLIENT_ENTRY_POINTS clientEntryPoints = WINPR_C_ARRAY_INIT;
312 WINPR_ASSERT(clientSettings);
314 RdpClientEntry(&clientEntryPoints);
315 rdpContext* context = freerdp_client_context_new(&clientEntryPoints);
320 pClientContext* pc = (pClientContext*)context;
322 if (!pf_context_copy_settings(context->settings, clientSettings))
327 freerdp_client_context_free(context);
331proxyData* proxy_data_new(
void)
333 BYTE temp[16] = WINPR_C_ARRAY_INIT;
334 proxyData* pdata = calloc(1,
sizeof(proxyData));
338 if (!(pdata->abort_event = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
341 if (!(pdata->gfx_server_ready = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
344 if (winpr_RAND(&temp,
sizeof(temp)) < 0)
348 char* hex = winpr_BinToHexString(temp,
sizeof(temp), FALSE);
352 CopyMemory(pdata->session_id, hex, PROXY_SESSION_ID_LENGTH);
353 pdata->session_id[PROXY_SESSION_ID_LENGTH] =
'\0';
357 if (!(pdata->modules_info = HashTable_New(FALSE)))
361 if (!HashTable_SetupForStringData(pdata->modules_info, FALSE))
366 WINPR_PRAGMA_DIAG_PUSH
367 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
368 proxy_data_free(pdata);
369 WINPR_PRAGMA_DIAG_POP
374void proxy_data_set_client_context(proxyData* pdata, pClientContext* context)
377 WINPR_ASSERT(context);
378 pdata->pc = (rdpContext*)context;
379 context->pdata = pdata;
382pClientContext* proxy_data_get_client_context(proxyData* pdata)
385 return (pClientContext*)pdata->pc;
389void proxy_data_set_server_context(proxyData* pdata, pServerContext* context)
392 WINPR_ASSERT(context);
393 pdata->ps = (rdpContext*)context;
394 context->pdata = pdata;
397pServerContext* proxy_data_get_server_context(proxyData* pdata)
400 return (pServerContext*)pdata->ps;
403void proxy_data_free(proxyData* pdata)
408 if (pdata->abort_event)
409 (void)CloseHandle(pdata->abort_event);
411 if (pdata->client_thread)
412 (void)CloseHandle(pdata->client_thread);
414 if (pdata->gfx_server_ready)
415 (void)CloseHandle(pdata->gfx_server_ready);
417 if (pdata->modules_info)
418 HashTable_Free(pdata->modules_info);
421 freerdp_client_context_free(pdata->pc);
426void proxy_data_abort_connect(proxyData* pdata)
429 WINPR_ASSERT(pdata->abort_event);
430 (void)SetEvent(pdata->abort_event);
432 pClientContext* pc = proxy_data_get_client_context(pdata);
434 freerdp_abort_connect_context(&pc->cctx.context);
437BOOL proxy_data_shall_disconnect(proxyData* pdata)
440 WINPR_ASSERT(pdata->abort_event);
441 return WaitForSingleObject(pdata->abort_event, 0) == WAIT_OBJECT_0;
FREERDP_API rdpSettings * freerdp_settings_clone(const rdpSettings *settings)
Creates a deep copy of settings.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_copy_item(rdpSettings *dst, const rdpSettings *src, SSIZE_T id)
copies one setting identified by id from src to dst
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_copy(rdpSettings *dst, const rdpSettings *src)
Deep copies settings from src to dst.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
FREERDP_API void freerdp_settings_free(rdpSettings *settings)
Free a settings struct with all data in it.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree
WINPR_ATTR_NODISCARD OBJECT_EQUALS_FN fnObjectEquals