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>
33#include "proxy_modules.h"
35#include <freerdp/server/proxy/proxy_context.h>
37#include "channels/pf_channel_rdpdr.h"
39#define TAG PROXY_TAG("server")
42static UINT32 ChannelId_Hash(
const void* key)
44 const UINT32* v = (
const UINT32*)key;
49static BOOL ChannelId_Compare(
const void* pv1,
const void* pv2)
51 const UINT32* v1 = pv1;
52 const UINT32* v2 = pv2;
59static BOOL dyn_intercept(pServerContext* ps,
const char* name)
61 if (strncmp(DRDYNVC_SVC_CHANNEL_NAME, name,
sizeof(DRDYNVC_SVC_CHANNEL_NAME)) != 0)
65 WINPR_ASSERT(ps->pdata);
67 const proxyConfig* cfg = ps->pdata->config;
71 if (!cfg->AudioOutput)
77 if (!cfg->VideoRedirection)
79 if (!cfg->CameraRedirection)
84pServerStaticChannelContext* StaticChannelContext_new(pServerContext* ps,
const char* name,
87 pServerStaticChannelContext* ret = calloc(1,
sizeof(*ret));
90 PROXY_LOG_ERR(TAG, ps,
"error allocating channel context for '%s'", name);
94 ret->front_channel_id = id;
95 ret->channel_name = _strdup(name);
96 if (!ret->channel_name)
98 PROXY_LOG_ERR(TAG, ps,
"error allocating name in channel context for '%s'", name);
105 if (pf_modules_run_filter(ps->pdata->module, FILTER_TYPE_STATIC_INTERCEPT_LIST, ps->pdata,
108 ret->channelMode = PF_UTILS_CHANNEL_INTERCEPT;
109 else if (dyn_intercept(ps, name))
110 ret->channelMode = PF_UTILS_CHANNEL_INTERCEPT;
112 ret->channelMode = pf_utils_get_channel_mode(ps->pdata->config, name);
116void StaticChannelContext_free(pServerStaticChannelContext* ctx)
121 IFCALL(ctx->contextDtor, ctx->context);
123 free(ctx->channel_name);
127static void HashStaticChannelContext_free(
void* ptr)
129 pServerStaticChannelContext* ctx = (pServerStaticChannelContext*)ptr;
130 StaticChannelContext_free(ctx);
134static void client_to_proxy_context_free(freerdp_peer* client, rdpContext* ctx);
137static BOOL client_to_proxy_context_new(freerdp_peer* client, rdpContext* ctx)
140 pServerContext* context = (pServerContext*)ctx;
142 WINPR_ASSERT(client);
143 WINPR_ASSERT(context);
145 context->dynvcReady =
nullptr;
147 context->vcm = WTSOpenServerA((LPSTR)client->context);
149 if (!context->vcm || context->vcm == INVALID_HANDLE_VALUE)
152 if (!(context->dynvcReady = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
155 context->interceptContextMap = HashTable_New(FALSE);
156 if (!context->interceptContextMap)
158 if (!HashTable_SetupForStringData(context->interceptContextMap, FALSE))
160 obj = HashTable_ValueObject(context->interceptContextMap);
165 context->channelsByFrontId = HashTable_New(FALSE);
166 if (!context->channelsByFrontId)
168 if (!HashTable_SetHashFunction(context->channelsByFrontId, ChannelId_Hash))
171 obj = HashTable_KeyObject(context->channelsByFrontId);
174 obj = HashTable_ValueObject(context->channelsByFrontId);
177 context->channelsByBackId = HashTable_New(FALSE);
178 if (!context->channelsByBackId)
180 if (!HashTable_SetHashFunction(context->channelsByBackId, ChannelId_Hash))
183 obj = HashTable_KeyObject(context->channelsByBackId);
189 client_to_proxy_context_free(client, ctx);
195void client_to_proxy_context_free(freerdp_peer* client, rdpContext* ctx)
197 pServerContext* context = (pServerContext*)ctx;
199 WINPR_UNUSED(client);
204 if (context->dynvcReady)
206 (void)CloseHandle(context->dynvcReady);
207 context->dynvcReady =
nullptr;
210 HashTable_Free(context->interceptContextMap);
211 HashTable_Free(context->channelsByFrontId);
212 HashTable_Free(context->channelsByBackId);
214 if (context->vcm && (context->vcm != INVALID_HANDLE_VALUE))
215 WTSCloseServer(context->vcm);
216 context->vcm =
nullptr;
219BOOL pf_context_init_server_context(freerdp_peer* client)
221 WINPR_ASSERT(client);
223 client->ContextSize =
sizeof(pServerContext);
224 client->ContextNew = client_to_proxy_context_new;
225 client->ContextFree = client_to_proxy_context_free;
227 return freerdp_peer_context_new(client);
231static BOOL pf_context_revert_str_settings(rdpSettings* dst,
const rdpSettings* before,
size_t nr,
232 const FreeRDP_Settings_Keys_String* ids)
235 WINPR_ASSERT(before);
236 WINPR_ASSERT(ids || (nr == 0));
238 for (
size_t x = 0; x < nr; x++)
240 FreeRDP_Settings_Keys_String
id = ids[x];
249void intercept_context_entry_free(
void* obj)
259BOOL pf_context_copy_settings(rdpSettings* dst,
const rdpSettings* src)
262 rdpSettings* before_copy =
nullptr;
263 const FreeRDP_Settings_Keys_String to_revert[] = { FreeRDP_ConfigPath,
264 FreeRDP_CertificateName };
281 if (!pf_context_revert_str_settings(dst, before_copy, ARRAYSIZE(to_revert), to_revert))
307pClientContext* pf_context_create_client_context(
const rdpSettings* clientSettings)
309 RDP_CLIENT_ENTRY_POINTS clientEntryPoints = WINPR_C_ARRAY_INIT;
311 WINPR_ASSERT(clientSettings);
313 RdpClientEntry(&clientEntryPoints);
314 rdpContext* context = freerdp_client_context_new(&clientEntryPoints);
319 pClientContext* pc = (pClientContext*)context;
321 if (!pf_context_copy_settings(context->settings, clientSettings))
326 freerdp_client_context_free(context);
330proxyData* proxy_data_new(
void)
334 proxyData* pdata =
nullptr;
336 pdata = calloc(1,
sizeof(proxyData));
340 if (!(pdata->abort_event = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
343 if (!(pdata->gfx_server_ready = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
346 if (winpr_RAND(&temp, 16) < 0)
348 hex = winpr_BinToHexString(temp, 16, FALSE);
352 CopyMemory(pdata->session_id, hex, PROXY_SESSION_ID_LENGTH);
353 pdata->session_id[PROXY_SESSION_ID_LENGTH] =
'\0';
356 if (!(pdata->modules_info = HashTable_New(FALSE)))
360 if (!HashTable_SetupForStringData(pdata->modules_info, FALSE))
365 WINPR_PRAGMA_DIAG_PUSH
366 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
367 proxy_data_free(pdata);
368 WINPR_PRAGMA_DIAG_POP
373void proxy_data_set_client_context(proxyData* pdata, pClientContext* context)
376 WINPR_ASSERT(context);
378 context->pdata = pdata;
382void proxy_data_set_server_context(proxyData* pdata, pServerContext* context)
385 WINPR_ASSERT(context);
387 context->pdata = pdata;
390void proxy_data_free(proxyData* pdata)
395 if (pdata->abort_event)
396 (void)CloseHandle(pdata->abort_event);
398 if (pdata->client_thread)
399 (void)CloseHandle(pdata->client_thread);
401 if (pdata->gfx_server_ready)
402 (void)CloseHandle(pdata->gfx_server_ready);
404 if (pdata->modules_info)
405 HashTable_Free(pdata->modules_info);
408 freerdp_client_context_free(&pdata->pc->context);
413void proxy_data_abort_connect(proxyData* pdata)
416 WINPR_ASSERT(pdata->abort_event);
417 (void)SetEvent(pdata->abort_event);
419 freerdp_abort_connect_context(&pdata->pc->context);
422BOOL proxy_data_shall_disconnect(proxyData* pdata)
425 WINPR_ASSERT(pdata->abort_event);
426 return WaitForSingleObject(pdata->abort_event, 0) == WAIT_OBJECT_0;
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 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 rdpSettings * freerdp_settings_clone(const rdpSettings *settings)
Creates a deep copy of settings.
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
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.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_copy(rdpSettings *dst, const rdpSettings *src)
Deep copies settings from src to dst.
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_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
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.
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree
OBJECT_EQUALS_FN fnObjectEquals