FreeRDP
Loading...
Searching...
No Matches
pf_config.c
1
23#include <stdio.h>
24#include <string.h>
25#include <winpr/crt.h>
26#include <winpr/path.h>
27#include <winpr/collections.h>
28#include <winpr/cmdline.h>
29
30#include "pf_server.h"
31#include <freerdp/server/proxy/proxy_config.h>
32
33#include <freerdp/server/proxy/proxy_log.h>
34
35#include <freerdp/crypto/crypto.h>
36#include <freerdp/channels/cliprdr.h>
37#include <freerdp/channels/rdpsnd.h>
38#include <freerdp/channels/audin.h>
39#include <freerdp/channels/rdpdr.h>
40#include <freerdp/channels/disp.h>
41#include <freerdp/channels/rail.h>
42#include <freerdp/channels/rdpei.h>
43#include <freerdp/channels/tsmf.h>
44#include <freerdp/channels/video.h>
45#include <freerdp/channels/rdpecam.h>
46
47#include "pf_utils.h"
48
49#define TAG PROXY_TAG("config")
50
51#define CONFIG_PRINT_SECTION(section) WLog_INFO(TAG, "\t%s:", section)
52#define CONFIG_PRINT_SECTION_KEY(section, key) WLog_INFO(TAG, "\t%s/%s:", section, key)
53#define CONFIG_PRINT_STR(config, key) WLog_INFO(TAG, "\t\t%s: %s", #key, (config)->key)
54#define CONFIG_PRINT_SECRET_STR(config, key) \
55 WLog_INFO(TAG, "\t\t%s: %s", #key, (config)->key ? "********" : nullptr)
56#define CONFIG_PRINT_BOOL(config, key) WLog_INFO(TAG, "\t\t%s: %s", #key, boolstr((config)->key))
57#define CONFIG_PRINT_UINT16(config, key) WLog_INFO(TAG, "\t\t%s: %" PRIu16 "", #key, (config)->key)
58#define CONFIG_PRINT_UINT32(config, key) WLog_INFO(TAG, "\t\t%s: %" PRIu32 "", #key, (config)->key)
59
60static const char* bool_str_true = "true";
61static const char* bool_str_false = "false";
62
63WINPR_ATTR_NODISCARD
64static const char* boolstr(BOOL rc)
65{
66 return rc ? bool_str_true : bool_str_false;
67}
68
69static const char* section_server = "Server";
70static const char* key_host = "Host";
71static const char* key_port = "Port";
72static const char* key_sam_file = "SamFile";
73
74static const char* section_target = "Target";
75static const char* key_target_fixed = "FixedTarget";
76static const char* key_target_user = "User";
77static const char* key_target_pwd = "Password";
78static const char* key_target_domain = "Domain";
79static const char* key_target_tls_seclevel = "TlsSecLevel";
80static const char* key_target_scard_auth = "SmartcardAuth";
81static const char* key_target_scard_cert = "SmartcardCert";
82static const char* key_target_scard_key = "SmartcardKey";
83static const char* key_target_scard_pem_cert = "SmartcardCertPEMContent";
84static const char* key_target_scard_pem_key = "SmartcardKeyPEMContent";
85
86static const char* section_plugins = "Plugins";
87static const char* key_plugins_modules = "Modules";
88static const char* key_plugins_required = "Required";
89
90static const char* section_codecs = "Codecs";
91static const char* key_codecs_rfx = "RFX";
92static const char* key_codecs_nsc = "NSC";
93
94static const char* section_channels = "Channels";
95static const char* key_channels_gfx = "GFX";
96static const char* key_channels_disp = "DisplayControl";
97static const char* key_channels_clip = "Clipboard";
98static const char* key_channels_mic = "AudioInput";
99static const char* key_channels_sound = "AudioOutput";
100static const char* key_channels_rdpdr = "DeviceRedirection";
101static const char* key_channels_video = "VideoRedirection";
102static const char* key_channels_camera = "CameraRedirection";
103static const char* key_channels_rails = "RemoteApp";
104static const char* key_channels_blacklist = "PassthroughIsBlacklist";
105static const char* key_channels_pass = "Passthrough";
106static const char* key_channels_intercept = "Intercept";
107
108static const char* section_input = "Input";
109static const char* key_input_kbd = "Keyboard";
110static const char* key_input_mouse = "Mouse";
111static const char* key_input_multitouch = "Multitouch";
112
113static const char* section_security = "Security";
114static const char* key_security_server_nla = "ServerNlaSecurity";
115static const char* key_security_server_tls = "ServerTlsSecurity";
116static const char* key_security_server_rdp = "ServerRdpSecurity";
117static const char* key_security_client_nla = "ClientNlaSecurity";
118static const char* key_security_client_tls = "ClientTlsSecurity";
119static const char* key_security_client_rdp = "ClientRdpSecurity";
120static const char* key_security_client_fallback = "ClientAllowFallbackToTls";
121
122static const char* section_certificates = "Certificates";
123static const char* key_private_key_file = "PrivateKeyFile";
124static const char* key_private_key_content = "PrivateKeyContent";
125static const char* key_cert_file = "CertificateFile";
126static const char* key_cert_content = "CertificateContent";
127
128WINPR_ATTR_MALLOC(free, 1)
129static char* pf_config_decode_base64(const char* data, const char* name, size_t* pLength);
130
131WINPR_ATTR_MALLOC(CommandLineParserFree, 1)
132WINPR_ATTR_NODISCARD
133static char** pf_config_parse_comma_separated_list(const char* list, size_t* count)
134{
135 if (!list || !count)
136 return nullptr;
137
138 if (strlen(list) == 0)
139 {
140 *count = 0;
141 return nullptr;
142 }
143
144 return CommandLineParseCommaSeparatedValues(list, count);
145}
146
147WINPR_ATTR_NODISCARD
148static BOOL pf_config_get_uint16(wIniFile* ini, const char* section, const char* key,
149 UINT16* result, BOOL required)
150{
151 int val = 0;
152 const char* strval = nullptr;
153
154 WINPR_ASSERT(result);
155
156 strval = IniFile_GetKeyValueString(ini, section, key);
157 if (!strval && required)
158 {
159 WLog_ERR(TAG, "key '%s.%s' does not exist.", section, key);
160 return FALSE;
161 }
162 val = IniFile_GetKeyValueInt(ini, section, key);
163 if ((val <= 0) || (val > UINT16_MAX))
164 {
165 WLog_ERR(TAG, "invalid value %d for key '%s.%s'.", val, section, key);
166 return FALSE;
167 }
168
169 *result = (UINT16)val;
170 return TRUE;
171}
172
173WINPR_ATTR_NODISCARD
174static BOOL pf_config_get_uint32(wIniFile* ini, const char* section, const char* key,
175 UINT32* result, BOOL required)
176{
177 WINPR_ASSERT(result);
178
179 const char* strval = IniFile_GetKeyValueString(ini, section, key);
180 if (!strval)
181 {
182 if (required)
183 WLog_ERR(TAG, "key '%s.%s' does not exist.", section, key);
184 return !required;
185 }
186
187 const int val = IniFile_GetKeyValueInt(ini, section, key);
188 if (val < 0)
189 {
190 WLog_ERR(TAG, "invalid value %d for key '%s.%s'.", val, section, key);
191 return FALSE;
192 }
193
194 *result = (UINT32)val;
195 return TRUE;
196}
197
198WINPR_ATTR_NODISCARD
199static BOOL pf_config_get_bool(wIniFile* ini, const char* section, const char* key, BOOL fallback)
200{
201 int num_value = 0;
202 const char* str_value = nullptr;
203
204 str_value = IniFile_GetKeyValueString(ini, section, key);
205 if (!str_value)
206 {
207 WLog_WARN(TAG, "key '%s.%s' not found, value defaults to %s.", section, key,
208 fallback ? bool_str_true : bool_str_false);
209 return fallback;
210 }
211
212 if (_stricmp(str_value, bool_str_true) == 0)
213 return TRUE;
214 if (_stricmp(str_value, bool_str_false) == 0)
215 return FALSE;
216
217 num_value = IniFile_GetKeyValueInt(ini, section, key);
218
219 return (num_value != 0);
220}
221
222WINPR_ATTR_NODISCARD
223static const char* pf_config_get_str(wIniFile* ini, const char* section, const char* key,
224 BOOL required)
225{
226 const char* value = IniFile_GetKeyValueString(ini, section, key);
227
228 if (!value)
229 {
230 if (required)
231 WLog_ERR(TAG, "key '%s.%s' not found.", section, key);
232 return nullptr;
233 }
234
235 return value;
236}
237
238static void zfree(char* str)
239{
240 if (!str)
241 return;
242 const size_t len = strlen(str);
243 memset(str, 0, len);
244 free(str);
245}
246
247static void znfree(char* str, size_t len)
248{
249 if (!str)
250 return;
251 memset(str, 0, len);
252 free(str);
253}
254
255WINPR_ATTR_NODISCARD
256static BOOL pf_config_copy_string(char** dst, const char* src)
257{
258 WINPR_ASSERT(dst);
259 *dst = nullptr;
260 if (src)
261 *dst = _strdup(src);
262 return TRUE;
263}
264
265WINPR_ATTR_NODISCARD
266static BOOL pf_config_free_and_copy_string(char** dst, const char* src)
267{
268 WINPR_ASSERT(dst);
269 zfree(*dst);
270 return pf_config_copy_string(dst, src);
271}
272
273WINPR_ATTR_NODISCARD
274static BOOL pf_config_load_server(wIniFile* ini, proxyConfig* config)
275{
276 WINPR_ASSERT(config);
277 const char* host = pf_config_get_str(ini, section_server, key_host, FALSE);
278
279 if (host)
280 {
281 if (!pf_config_free_and_copy_string(&config->Host, host))
282 return FALSE;
283 }
284
285 if (!pf_config_get_uint16(ini, section_server, key_port, &config->Port, TRUE))
286 return FALSE;
287
288 const char* sam = pf_config_get_str(ini, section_server, key_sam_file, FALSE);
289 if (sam)
290 {
291 if (!pf_config_free_and_copy_string(&config->SamFile, sam))
292 return FALSE;
293 }
294
295 return TRUE;
296}
297
298WINPR_ATTR_NODISCARD
299static BOOL pf_config_load_target(wIniFile* ini, proxyConfig* config)
300{
301 const char* target_value = nullptr;
302
303 WINPR_ASSERT(config);
304 config->FixedTarget = pf_config_get_bool(ini, section_target, key_target_fixed, FALSE);
305
306 if (!pf_config_get_uint16(ini, section_target, key_port, &config->TargetPort,
307 config->FixedTarget))
308 return FALSE;
309
310 if (!pf_config_get_uint32(ini, section_target, key_target_tls_seclevel,
311 &config->TargetTlsSecLevel, FALSE))
312 return FALSE;
313
314 if (config->FixedTarget)
315 {
316 target_value = pf_config_get_str(ini, section_target, key_host, TRUE);
317 if (!target_value)
318 return FALSE;
319
320 if (!pf_config_free_and_copy_string(&config->TargetHost, target_value))
321 return FALSE;
322 }
323
324 target_value = pf_config_get_str(ini, section_target, key_target_user, FALSE);
325 if (target_value)
326 {
327 if (!pf_config_free_and_copy_string(&config->TargetUser, target_value))
328 return FALSE;
329 }
330
331 target_value = pf_config_get_str(ini, section_target, key_target_pwd, FALSE);
332 if (target_value)
333 {
334 if (!pf_config_free_and_copy_string(&config->TargetPassword, target_value))
335 return FALSE;
336 }
337
338 target_value = pf_config_get_str(ini, section_target, key_target_domain, FALSE);
339 if (target_value)
340 {
341 if (!pf_config_free_and_copy_string(&config->TargetDomain, target_value))
342 return FALSE;
343 }
344
345 config->TargetSmartcardAuth =
346 pf_config_get_bool(ini, section_target, key_target_scard_auth, FALSE);
347
348 target_value = pf_config_get_str(ini, section_target, key_target_scard_cert, FALSE);
349 if (target_value)
350 {
351 char* pem = crypto_read_pem(target_value, nullptr);
352 if (!pem)
353 return FALSE;
354 free(config->TargetSmartcardCert);
355 config->TargetSmartcardCert = pem;
356 }
357
358 {
359 const char* pem_value =
360 pf_config_get_str(ini, section_target, key_target_scard_pem_cert, FALSE);
361 if (pem_value)
362 {
363 if (target_value)
364 WLog_WARN(TAG, "In section [%s] both, '%s' and '%s' are provided. Ignoring %s",
365 section_target, key_target_scard_cert, key_target_scard_pem_cert,
366 key_target_scard_cert);
367 free(config->TargetSmartcardCert);
368 size_t len = 0;
369 config->TargetSmartcardCert =
370 pf_config_decode_base64(pem_value, key_target_scard_pem_cert, &len);
371 if (!config->TargetSmartcardCert)
372 return FALSE;
373 }
374 }
375
376 target_value = pf_config_get_str(ini, section_target, key_target_scard_key, FALSE);
377 if (target_value)
378 {
379 char* pem = crypto_read_pem(target_value, nullptr);
380 free(config->TargetSmartcardKey);
381 config->TargetSmartcardKey = pem;
382 }
383
384 {
385 const char* pem_value =
386 pf_config_get_str(ini, section_target, key_target_scard_pem_key, FALSE);
387 if (pem_value)
388 {
389 if (target_value)
390 WLog_WARN(TAG, "In section [%s] both, '%s' and '%s' are provided. Ignoring %s",
391 section_target, key_target_scard_key, key_target_scard_pem_key,
392 key_target_scard_key);
393 free(config->TargetSmartcardKey);
394
395 size_t len = 0;
396 config->TargetSmartcardKey =
397 pf_config_decode_base64(pem_value, key_target_scard_pem_key, &len);
398 if (!config->TargetSmartcardKey)
399 return FALSE;
400 }
401 }
402
403 return TRUE;
404}
405
406WINPR_ATTR_NODISCARD
407static BOOL pf_config_load_codecs(wIniFile* ini, proxyConfig* config)
408{
409 WINPR_ASSERT(config);
410 config->RFX = pf_config_get_bool(ini, section_codecs, key_codecs_rfx, TRUE);
411 config->NSC = pf_config_get_bool(ini, section_codecs, key_codecs_nsc, TRUE);
412 return TRUE;
413}
414
415WINPR_ATTR_NODISCARD
416static BOOL pf_config_load_channels(wIniFile* ini, proxyConfig* config)
417{
418 WINPR_ASSERT(config);
419 config->GFX = pf_config_get_bool(ini, section_channels, key_channels_gfx, TRUE);
420 config->DisplayControl = pf_config_get_bool(ini, section_channels, key_channels_disp, TRUE);
421 config->Clipboard = pf_config_get_bool(ini, section_channels, key_channels_clip, FALSE);
422 config->AudioOutput = pf_config_get_bool(ini, section_channels, key_channels_mic, TRUE);
423 config->AudioInput = pf_config_get_bool(ini, section_channels, key_channels_sound, TRUE);
424 config->DeviceRedirection = pf_config_get_bool(ini, section_channels, key_channels_rdpdr, TRUE);
425 config->VideoRedirection = pf_config_get_bool(ini, section_channels, key_channels_video, TRUE);
426 config->CameraRedirection =
427 pf_config_get_bool(ini, section_channels, key_channels_camera, TRUE);
428 config->RemoteApp = pf_config_get_bool(ini, section_channels, key_channels_rails, FALSE);
429 config->PassthroughIsBlacklist =
430 pf_config_get_bool(ini, section_channels, key_channels_blacklist, FALSE);
431 config->Passthrough = pf_config_parse_comma_separated_list(
432 pf_config_get_str(ini, section_channels, key_channels_pass, FALSE),
433 &config->PassthroughCount);
434 config->Intercept = pf_config_parse_comma_separated_list(
435 pf_config_get_str(ini, section_channels, key_channels_intercept, FALSE),
436 &config->InterceptCount);
437
438 return TRUE;
439}
440
441WINPR_ATTR_NODISCARD
442static BOOL pf_config_load_input(wIniFile* ini, proxyConfig* config)
443{
444 WINPR_ASSERT(config);
445 config->Keyboard = pf_config_get_bool(ini, section_input, key_input_kbd, TRUE);
446 config->Mouse = pf_config_get_bool(ini, section_input, key_input_mouse, TRUE);
447 config->Multitouch = pf_config_get_bool(ini, section_input, key_input_multitouch, TRUE);
448 return TRUE;
449}
450
451WINPR_ATTR_NODISCARD
452static BOOL pf_config_load_security(wIniFile* ini, proxyConfig* config)
453{
454 WINPR_ASSERT(config);
455 config->ServerTlsSecurity =
456 pf_config_get_bool(ini, section_security, key_security_server_tls, TRUE);
457 config->ServerNlaSecurity =
458 pf_config_get_bool(ini, section_security, key_security_server_nla, FALSE);
459 config->ServerRdpSecurity =
460 pf_config_get_bool(ini, section_security, key_security_server_rdp, TRUE);
461
462 config->ClientTlsSecurity =
463 pf_config_get_bool(ini, section_security, key_security_client_tls, TRUE);
464 config->ClientNlaSecurity =
465 pf_config_get_bool(ini, section_security, key_security_client_nla, TRUE);
466 config->ClientRdpSecurity =
467 pf_config_get_bool(ini, section_security, key_security_client_rdp, TRUE);
468 config->ClientAllowFallbackToTls =
469 pf_config_get_bool(ini, section_security, key_security_client_fallback, TRUE);
470 return TRUE;
471}
472
473WINPR_ATTR_NODISCARD
474static BOOL pf_config_load_modules(wIniFile* ini, proxyConfig* config)
475{
476 const char* modules_to_load = nullptr;
477 const char* required_modules = nullptr;
478
479 modules_to_load = pf_config_get_str(ini, section_plugins, key_plugins_modules, FALSE);
480 required_modules = pf_config_get_str(ini, section_plugins, key_plugins_required, FALSE);
481
482 WINPR_ASSERT(config);
483 config->Modules = pf_config_parse_comma_separated_list(modules_to_load, &config->ModulesCount);
484
485 config->RequiredPlugins =
486 pf_config_parse_comma_separated_list(required_modules, &config->RequiredPluginsCount);
487 return TRUE;
488}
489
490char* pf_config_decode_base64(const char* data, const char* name, size_t* pLength)
491{
492 const char* headers[] = { "-----BEGIN PUBLIC KEY-----", "-----BEGIN RSA PUBLIC KEY-----",
493 "-----BEGIN CERTIFICATE-----", "-----BEGIN PRIVATE KEY-----",
494 "-----BEGIN RSA PRIVATE KEY-----" };
495
496 size_t decoded_length = 0;
497 char* decoded = nullptr;
498 if (!data)
499 {
500 WLog_ERR(TAG, "Invalid base64 data [nullptr] for %s", name);
501 return nullptr;
502 }
503
504 WINPR_ASSERT(name);
505 WINPR_ASSERT(pLength);
506
507 const size_t length = strlen(data);
508
509 if (strncmp(data, "-----", 5) == 0)
510 {
511 BOOL expected = FALSE;
512 for (size_t x = 0; x < ARRAYSIZE(headers); x++)
513 {
514 const char* header = headers[x];
515
516 if (strncmp(data, header, strlen(header)) == 0)
517 expected = TRUE;
518 }
519
520 if (!expected)
521 {
522 /* Extract header for log message
523 * expected format is '----- SOMETEXT -----'
524 */
525 char hdr[128] = WINPR_C_ARRAY_INIT;
526 const char* end = strchr(&data[5], '-');
527 if (end)
528 {
529 while (*end == '-')
530 end++;
531
532 const size_t s = MIN(ARRAYSIZE(hdr) - 1ULL, (size_t)(end - data));
533 memcpy(hdr, data, s);
534 }
535
536 WLog_WARN(TAG, "PEM has unexpected header '%s'. Known supported headers are:", hdr);
537 for (size_t x = 0; x < ARRAYSIZE(headers); x++)
538 {
539 const char* header = headers[x];
540 WLog_WARN(TAG, "%s", header);
541 }
542 }
543
544 *pLength = length + 1;
545 return _strdup(data);
546 }
547
548 crypto_base64_decode(data, length, (BYTE**)&decoded, &decoded_length);
549 if (!decoded || decoded_length == 0)
550 {
551 WLog_ERR(TAG, "Failed to decode base64 data of length %" PRIuz " for %s", length, name);
552 zfree(decoded);
553 return nullptr;
554 }
555
556 *pLength = strnlen(decoded, decoded_length) + 1;
557 return decoded;
558}
559
560WINPR_ATTR_NODISCARD
561static BOOL pf_config_load_certificates(wIniFile* ini, proxyConfig* config)
562{
563 const char* tmp1 = nullptr;
564 const char* tmp2 = nullptr;
565
566 WINPR_ASSERT(ini);
567 WINPR_ASSERT(config);
568
569 tmp1 = pf_config_get_str(ini, section_certificates, key_cert_file, FALSE);
570 if (tmp1)
571 {
572 if (!winpr_PathFileExists(tmp1))
573 {
574 WLog_ERR(TAG, "%s/%s file %s does not exist", section_certificates, key_cert_file,
575 tmp1);
576 return FALSE;
577 }
578 config->CertificateFile = _strdup(tmp1);
579 config->CertificatePEM =
580 crypto_read_pem(config->CertificateFile, &config->CertificatePEMLength);
581 if (!config->CertificatePEM)
582 return FALSE;
583 config->CertificatePEMLength += 1;
584 }
585 tmp2 = pf_config_get_str(ini, section_certificates, key_cert_content, FALSE);
586 if (tmp2)
587 {
588 if (strlen(tmp2) < 1)
589 {
590 WLog_ERR(TAG, "%s/%s has invalid empty value", section_certificates, key_cert_content);
591 return FALSE;
592 }
593 config->CertificateContent = _strdup(tmp2);
594 config->CertificatePEM = pf_config_decode_base64(
595 config->CertificateContent, "CertificateContent", &config->CertificatePEMLength);
596 if (!config->CertificatePEM)
597 return FALSE;
598 }
599 if (tmp1 && tmp2)
600 {
601 WLog_ERR(TAG,
602 "%s/%s and %s/%s are "
603 "mutually exclusive options",
604 section_certificates, key_cert_file, section_certificates, key_cert_content);
605 return FALSE;
606 }
607 else if (!tmp1 && !tmp2)
608 {
609 WLog_ERR(TAG,
610 "%s/%s or %s/%s are "
611 "required settings",
612 section_certificates, key_cert_file, section_certificates, key_cert_content);
613 return FALSE;
614 }
615
616 tmp1 = pf_config_get_str(ini, section_certificates, key_private_key_file, FALSE);
617 if (tmp1)
618 {
619 if (!winpr_PathFileExists(tmp1))
620 {
621 WLog_ERR(TAG, "%s/%s file %s does not exist", section_certificates,
622 key_private_key_file, tmp1);
623 return FALSE;
624 }
625 config->PrivateKeyFile = _strdup(tmp1);
626 config->PrivateKeyPEM =
627 crypto_read_pem(config->PrivateKeyFile, &config->PrivateKeyPEMLength);
628 if (!config->PrivateKeyPEM)
629 return FALSE;
630 config->PrivateKeyPEMLength += 1;
631 }
632 tmp2 = pf_config_get_str(ini, section_certificates, key_private_key_content, FALSE);
633 if (tmp2)
634 {
635 if (strlen(tmp2) < 1)
636 {
637 WLog_ERR(TAG, "%s/%s has invalid empty value", section_certificates,
638 key_private_key_content);
639 return FALSE;
640 }
641 config->PrivateKeyContent = _strdup(tmp2);
642 config->PrivateKeyPEM = pf_config_decode_base64(
643 config->PrivateKeyContent, "PrivateKeyContent", &config->PrivateKeyPEMLength);
644 if (!config->PrivateKeyPEM)
645 return FALSE;
646 }
647
648 if (tmp1 && tmp2)
649 {
650 WLog_ERR(TAG,
651 "%s/%s and %s/%s are "
652 "mutually exclusive options",
653 section_certificates, key_private_key_file, section_certificates,
654 key_private_key_content);
655 return FALSE;
656 }
657 else if (!tmp1 && !tmp2)
658 {
659 WLog_ERR(TAG,
660 "%s/%s or %s/%s are "
661 "are required settings",
662 section_certificates, key_private_key_file, section_certificates,
663 key_private_key_content);
664 return FALSE;
665 }
666
667 return TRUE;
668}
669
670proxyConfig* server_config_load_ini(wIniFile* ini)
671{
672 proxyConfig* config = nullptr;
673
674 WINPR_ASSERT(ini);
675
676 config = calloc(1, sizeof(proxyConfig));
677 if (config)
678 {
679 /* Set default values != 0 */
680 config->TargetTlsSecLevel = 1;
681
682 /* Load from ini */
683 if (!pf_config_load_server(ini, config))
684 goto out;
685
686 if (!pf_config_load_target(ini, config))
687 goto out;
688
689 if (!pf_config_load_codecs(ini, config))
690 goto out;
691
692 if (!pf_config_load_channels(ini, config))
693 goto out;
694
695 if (!pf_config_load_input(ini, config))
696 goto out;
697
698 if (!pf_config_load_security(ini, config))
699 goto out;
700
701 if (!pf_config_load_modules(ini, config))
702 goto out;
703
704 if (!pf_config_load_certificates(ini, config))
705 goto out;
706 config->ini = IniFile_Clone(ini);
707 if (!config->ini)
708 goto out;
709 }
710 return config;
711out:
712 WINPR_PRAGMA_DIAG_PUSH
713 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
714 pf_server_config_free(config);
715 WINPR_PRAGMA_DIAG_POP
716
717 return nullptr;
718}
719
720BOOL pf_server_config_dump(const char* file)
721{
722 BOOL rc = FALSE;
723 wIniFile* ini = IniFile_New();
724 if (!ini)
725 return FALSE;
726
727 /* Proxy server configuration */
728 if (IniFile_SetKeyValueString(ini, section_server, key_host, "0.0.0.0") < 0)
729 goto fail;
730 if (IniFile_SetKeyValueInt(ini, section_server, key_port, 3389) < 0)
731 goto fail;
732 if (IniFile_SetKeyValueString(ini, section_server, key_sam_file,
733 "optional/path/some/file.sam") < 0)
734 goto fail;
735
736 /* Target configuration */
737 if (IniFile_SetKeyValueString(ini, section_target, key_host, "somehost.example.com") < 0)
738 goto fail;
739 if (IniFile_SetKeyValueInt(ini, section_target, key_port, 3389) < 0)
740 goto fail;
741 if (IniFile_SetKeyValueString(ini, section_target, key_target_fixed, bool_str_true) < 0)
742 goto fail;
743 if (IniFile_SetKeyValueInt(ini, section_target, key_target_tls_seclevel, 1) < 0)
744 goto fail;
745 if (IniFile_SetKeyValueString(ini, section_target, key_target_user, "optionaltargetuser") < 0)
746 goto fail;
747 if (IniFile_SetKeyValueString(ini, section_target, key_target_domain, "optionaltargetdomain") <
748 0)
749 goto fail;
750 if (IniFile_SetKeyValueString(ini, section_target, key_target_pwd, "optionaltargetpassword") <
751 0)
752 goto fail;
753 if (IniFile_SetKeyValueString(ini, section_target, key_target_scard_auth, bool_str_false) < 0)
754 goto fail;
755 if (IniFile_SetKeyValueString(ini, section_target, key_target_scard_cert,
756 "optional/path/some/file.pem.crt") < 0)
757 goto fail;
758 if (IniFile_SetKeyValueString(ini, section_target, key_target_scard_pem_cert,
759 "<base64 encoded PEM>") < 0)
760 goto fail;
761 if (IniFile_SetKeyValueString(ini, section_target, key_target_scard_key,
762 "optional/path/some/file.pem.key") < 0)
763 goto fail;
764
765 if (IniFile_SetKeyValueString(ini, section_target, key_target_scard_pem_key,
766 "<base64 encoded PEM>") < 0)
767 goto fail;
768 /* Codec configuration */
769 if (IniFile_SetKeyValueString(ini, section_codecs, key_codecs_rfx, bool_str_true) < 0)
770 goto fail;
771 if (IniFile_SetKeyValueString(ini, section_codecs, key_codecs_nsc, bool_str_true) < 0)
772 goto fail;
773
774 /* Channel configuration */
775 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_gfx, bool_str_true) < 0)
776 goto fail;
777 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_disp, bool_str_true) < 0)
778 goto fail;
779 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_clip, bool_str_true) < 0)
780 goto fail;
781 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_mic, bool_str_true) < 0)
782 goto fail;
783 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_sound, bool_str_true) < 0)
784 goto fail;
785 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_rdpdr, bool_str_true) < 0)
786 goto fail;
787 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_video, bool_str_true) < 0)
788 goto fail;
789 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_camera, bool_str_true) < 0)
790 goto fail;
791 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_rails, bool_str_false) < 0)
792 goto fail;
793
794 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_blacklist, bool_str_true) < 0)
795 goto fail;
796 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_pass, "") < 0)
797 goto fail;
798 if (IniFile_SetKeyValueString(ini, section_channels, key_channels_intercept, "") < 0)
799 goto fail;
800
801 /* Input configuration */
802 if (IniFile_SetKeyValueString(ini, section_input, key_input_kbd, bool_str_true) < 0)
803 goto fail;
804 if (IniFile_SetKeyValueString(ini, section_input, key_input_mouse, bool_str_true) < 0)
805 goto fail;
806 if (IniFile_SetKeyValueString(ini, section_input, key_input_multitouch, bool_str_true) < 0)
807 goto fail;
808
809 /* Security settings */
810 if (IniFile_SetKeyValueString(ini, section_security, key_security_server_tls, bool_str_true) <
811 0)
812 goto fail;
813 if (IniFile_SetKeyValueString(ini, section_security, key_security_server_nla, bool_str_false) <
814 0)
815 goto fail;
816 if (IniFile_SetKeyValueString(ini, section_security, key_security_server_rdp, bool_str_true) <
817 0)
818 goto fail;
819
820 if (IniFile_SetKeyValueString(ini, section_security, key_security_client_tls, bool_str_true) <
821 0)
822 goto fail;
823 if (IniFile_SetKeyValueString(ini, section_security, key_security_client_nla, bool_str_true) <
824 0)
825 goto fail;
826 if (IniFile_SetKeyValueString(ini, section_security, key_security_client_rdp, bool_str_true) <
827 0)
828 goto fail;
829 if (IniFile_SetKeyValueString(ini, section_security, key_security_client_fallback,
830 bool_str_true) < 0)
831 goto fail;
832
833 /* Module configuration */
834 if (IniFile_SetKeyValueString(ini, section_plugins, key_plugins_modules,
835 "module1,module2,...") < 0)
836 goto fail;
837 if (IniFile_SetKeyValueString(ini, section_plugins, key_plugins_required,
838 "module1,module2,...") < 0)
839 goto fail;
840
841 /* Certificate configuration */
842 if (IniFile_SetKeyValueString(ini, section_certificates, key_cert_file,
843 "<absolute path to some certificate file> OR") < 0)
844 goto fail;
845 if (IniFile_SetKeyValueString(ini, section_certificates, key_cert_content,
846 "<base64 encoded PEM>") < 0)
847 goto fail;
848
849 if (IniFile_SetKeyValueString(ini, section_certificates, key_private_key_file,
850 "<absolute path to some private key file> OR") < 0)
851 goto fail;
852 if (IniFile_SetKeyValueString(ini, section_certificates, key_private_key_content,
853 "<base64 encoded PEM>") < 0)
854 goto fail;
855
856 if ((strcmp("stdout", file) == 0) || (strcmp("stderr", file) == 0))
857 {
858 char* buffer = IniFile_WriteBuffer(ini);
859 if (!buffer)
860 goto fail;
861 FILE* fp = stderr;
862 if (strcmp("stdout", file) == 0)
863 fp = stdout;
864 (void)fprintf(fp, "%s", buffer);
865 zfree(buffer);
866 }
867 else
868 {
869 /* store configuration */
870 if (IniFile_WriteFile(ini, file) < 0)
871 goto fail;
872 }
873
874 rc = TRUE;
875
876fail:
877 IniFile_Free(ini);
878 return rc;
879}
880
881proxyConfig* pf_server_config_load_buffer(const char* buffer)
882{
883 proxyConfig* config = nullptr;
884 wIniFile* ini = nullptr;
885
886 ini = IniFile_New();
887
888 if (!ini)
889 {
890 WLog_ERR(TAG, "IniFile_New() failed!");
891 return nullptr;
892 }
893
894 if (IniFile_ReadBuffer(ini, buffer) < 0)
895 {
896 WLog_ERR(TAG, "failed to parse ini: '%s'", buffer);
897 goto out;
898 }
899
900 config = server_config_load_ini(ini);
901out:
902 IniFile_Free(ini);
903 return config;
904}
905
906proxyConfig* pf_server_config_load_file(const char* path)
907{
908 proxyConfig* config = nullptr;
909 wIniFile* ini = IniFile_New();
910
911 if (!ini)
912 {
913 WLog_ERR(TAG, "IniFile_New() failed!");
914 return nullptr;
915 }
916
917 if (IniFile_ReadFile(ini, path) < 0)
918 {
919 WLog_ERR(TAG, "failed to parse ini file: '%s'", path);
920 goto out;
921 }
922
923 config = server_config_load_ini(ini);
924out:
925 IniFile_Free(ini);
926 return config;
927}
928
929static void pf_server_config_print_list(char** list, size_t count)
930{
931 WINPR_ASSERT(list);
932 for (size_t i = 0; i < count; i++)
933 WLog_INFO(TAG, "\t\t- %s", list[i]);
934}
935
936void pf_server_config_print(const proxyConfig* config)
937{
938 WINPR_ASSERT(config);
939 WLog_INFO(TAG, "Proxy configuration:");
940
941 CONFIG_PRINT_SECTION(section_server);
942 CONFIG_PRINT_STR(config, Host);
943 CONFIG_PRINT_STR(config, SamFile);
944 CONFIG_PRINT_UINT16(config, Port);
945
946 if (config->FixedTarget)
947 {
948 CONFIG_PRINT_SECTION(section_target);
949 CONFIG_PRINT_STR(config, TargetHost);
950 CONFIG_PRINT_UINT16(config, TargetPort);
951 CONFIG_PRINT_UINT32(config, TargetTlsSecLevel);
952
953 CONFIG_PRINT_STR(config, TargetUser);
954 CONFIG_PRINT_STR(config, TargetDomain);
955 CONFIG_PRINT_SECRET_STR(config, TargetPassword);
956
957 CONFIG_PRINT_BOOL(config, TargetSmartcardAuth);
958 CONFIG_PRINT_SECRET_STR(config, TargetSmartcardCert);
959 CONFIG_PRINT_SECRET_STR(config, TargetSmartcardKey);
960 }
961
962 CONFIG_PRINT_SECTION(section_input);
963 CONFIG_PRINT_BOOL(config, Keyboard);
964 CONFIG_PRINT_BOOL(config, Mouse);
965 CONFIG_PRINT_BOOL(config, Multitouch);
966
967 CONFIG_PRINT_SECTION(section_security);
968 CONFIG_PRINT_BOOL(config, ServerNlaSecurity);
969 CONFIG_PRINT_BOOL(config, ServerTlsSecurity);
970 CONFIG_PRINT_BOOL(config, ServerRdpSecurity);
971 CONFIG_PRINT_BOOL(config, ClientNlaSecurity);
972 CONFIG_PRINT_BOOL(config, ClientTlsSecurity);
973 CONFIG_PRINT_BOOL(config, ClientRdpSecurity);
974 CONFIG_PRINT_BOOL(config, ClientAllowFallbackToTls);
975
976 CONFIG_PRINT_SECTION(section_codecs);
977 CONFIG_PRINT_BOOL(config, RFX);
978 CONFIG_PRINT_BOOL(config, NSC);
979
980 CONFIG_PRINT_SECTION(section_channels);
981 CONFIG_PRINT_BOOL(config, GFX);
982 CONFIG_PRINT_BOOL(config, DisplayControl);
983 CONFIG_PRINT_BOOL(config, Clipboard);
984 CONFIG_PRINT_BOOL(config, AudioOutput);
985 CONFIG_PRINT_BOOL(config, AudioInput);
986 CONFIG_PRINT_BOOL(config, DeviceRedirection);
987 CONFIG_PRINT_BOOL(config, VideoRedirection);
988 CONFIG_PRINT_BOOL(config, CameraRedirection);
989 CONFIG_PRINT_BOOL(config, RemoteApp);
990 CONFIG_PRINT_BOOL(config, PassthroughIsBlacklist);
991
992 if (config->PassthroughCount)
993 {
994 WLog_INFO(TAG, "\tStatic Channels Proxy:");
995 pf_server_config_print_list(config->Passthrough, config->PassthroughCount);
996 }
997
998 if (config->InterceptCount)
999 {
1000 WLog_INFO(TAG, "\tStatic Channels Proxy-Intercept:");
1001 pf_server_config_print_list(config->Intercept, config->InterceptCount);
1002 }
1003
1004 /* modules */
1005 CONFIG_PRINT_SECTION_KEY(section_plugins, key_plugins_modules);
1006 for (size_t x = 0; x < config->ModulesCount; x++)
1007 CONFIG_PRINT_STR(config, Modules[x]);
1008
1009 /* Required plugins */
1010 CONFIG_PRINT_SECTION_KEY(section_plugins, key_plugins_required);
1011 for (size_t x = 0; x < config->RequiredPluginsCount; x++)
1012 CONFIG_PRINT_STR(config, RequiredPlugins[x]);
1013
1014 CONFIG_PRINT_SECTION(section_certificates);
1015 CONFIG_PRINT_STR(config, CertificateFile);
1016 CONFIG_PRINT_SECRET_STR(config, CertificateContent);
1017 CONFIG_PRINT_STR(config, PrivateKeyFile);
1018 CONFIG_PRINT_SECRET_STR(config, PrivateKeyContent);
1019}
1020
1021void pf_server_config_free(proxyConfig* config)
1022{
1023 if (config == nullptr)
1024 return;
1025
1026 zfree(config->Host);
1027 zfree(config->SamFile);
1028 zfree(config->TargetHost);
1029 zfree(config->TargetUser);
1030 zfree(config->TargetDomain);
1031 zfree(config->TargetPassword);
1032 zfree(config->TargetSmartcardCert);
1033 zfree(config->TargetSmartcardKey);
1034
1035 CommandLineParserFree(config->Passthrough);
1036 CommandLineParserFree(config->Intercept);
1037 CommandLineParserFree(config->Modules);
1038 CommandLineParserFree(config->RequiredPlugins);
1039
1040 zfree(config->CertificateFile);
1041 zfree(config->CertificateContent);
1042 znfree(config->CertificatePEM, config->CertificatePEMLength);
1043 zfree(config->PrivateKeyFile);
1044 zfree(config->PrivateKeyContent);
1045 znfree(config->PrivateKeyPEM, config->PrivateKeyPEMLength);
1046 IniFile_Free(config->ini);
1047 free(config);
1048}
1049
1050size_t pf_config_required_plugins_count(const proxyConfig* config)
1051{
1052 WINPR_ASSERT(config);
1053 return config->RequiredPluginsCount;
1054}
1055
1056const char* pf_config_required_plugin(const proxyConfig* config, size_t index)
1057{
1058 WINPR_ASSERT(config);
1059 if (index >= config->RequiredPluginsCount)
1060 return nullptr;
1061
1062 return config->RequiredPlugins[index];
1063}
1064
1065size_t pf_config_modules_count(const proxyConfig* config)
1066{
1067 WINPR_ASSERT(config);
1068 return config->ModulesCount;
1069}
1070
1071const char** pf_config_modules(const proxyConfig* config)
1072{
1073 union
1074 {
1075 char** ppc;
1076 const char** cppc;
1077 } cnv;
1078
1079 WINPR_ASSERT(config);
1080
1081 cnv.ppc = config->Modules;
1082 return cnv.cppc;
1083}
1084
1085WINPR_ATTR_NODISCARD
1086static BOOL pf_config_copy_string_n(char** dst, const char* src, size_t size)
1087{
1088 *dst = nullptr;
1089
1090 if (src && (size > 0))
1091 {
1092 WINPR_ASSERT(strnlen(src, size) == size - 1);
1093 *dst = calloc(size, sizeof(char));
1094 if (!*dst)
1095 return FALSE;
1096 memcpy(*dst, src, size);
1097 }
1098
1099 return TRUE;
1100}
1101
1102WINPR_ATTR_NODISCARD
1103static BOOL pf_config_copy_string_list(char*** dst, size_t* size, char** src, size_t srcSize)
1104{
1105 WINPR_ASSERT(dst);
1106 WINPR_ASSERT(size);
1107 WINPR_ASSERT(src || (srcSize == 0));
1108
1109 *dst = nullptr;
1110 *size = 0;
1111 if (srcSize > INT32_MAX)
1112 return FALSE;
1113
1114 if (srcSize != 0)
1115 {
1116 char* csv = CommandLineToCommaSeparatedValues((INT32)srcSize, src);
1117 *dst = CommandLineParseCommaSeparatedValues(csv, size);
1118 zfree(csv);
1119 }
1120
1121 return TRUE;
1122}
1123
1124BOOL pf_config_clone(proxyConfig** dst, const proxyConfig* config)
1125{
1126 proxyConfig* tmp = calloc(1, sizeof(proxyConfig));
1127
1128 WINPR_ASSERT(dst);
1129 WINPR_ASSERT(config);
1130
1131 if (!tmp)
1132 return FALSE;
1133
1134 *tmp = *config;
1135
1136 if (!pf_config_copy_string(&tmp->Host, config->Host))
1137 goto fail;
1138 if (!pf_config_copy_string(&tmp->SamFile, config->SamFile))
1139 goto fail;
1140 if (!pf_config_copy_string(&tmp->TargetHost, config->TargetHost))
1141 goto fail;
1142 if (!pf_config_copy_string(&tmp->TargetUser, config->TargetUser))
1143 goto fail;
1144 if (!pf_config_copy_string(&tmp->TargetDomain, config->TargetDomain))
1145 goto fail;
1146 if (!pf_config_copy_string(&tmp->TargetPassword, config->TargetPassword))
1147 goto fail;
1148 if (!pf_config_copy_string(&tmp->TargetSmartcardCert, config->TargetSmartcardCert))
1149 goto fail;
1150 if (!pf_config_copy_string(&tmp->TargetSmartcardKey, config->TargetSmartcardKey))
1151 goto fail;
1152 if (!pf_config_copy_string_list(&tmp->Passthrough, &tmp->PassthroughCount, config->Passthrough,
1153 config->PassthroughCount))
1154 goto fail;
1155 if (!pf_config_copy_string_list(&tmp->Intercept, &tmp->InterceptCount, config->Intercept,
1156 config->InterceptCount))
1157 goto fail;
1158 if (!pf_config_copy_string_list(&tmp->Modules, &tmp->ModulesCount, config->Modules,
1159 config->ModulesCount))
1160 goto fail;
1161 if (!pf_config_copy_string_list(&tmp->RequiredPlugins, &tmp->RequiredPluginsCount,
1162 config->RequiredPlugins, config->RequiredPluginsCount))
1163 goto fail;
1164 if (!pf_config_copy_string(&tmp->CertificateFile, config->CertificateFile))
1165 goto fail;
1166 if (!pf_config_copy_string(&tmp->CertificateContent, config->CertificateContent))
1167 goto fail;
1168 if (!pf_config_copy_string_n(&tmp->CertificatePEM, config->CertificatePEM,
1169 config->CertificatePEMLength))
1170 goto fail;
1171 if (!pf_config_copy_string(&tmp->PrivateKeyFile, config->PrivateKeyFile))
1172 goto fail;
1173 if (!pf_config_copy_string(&tmp->PrivateKeyContent, config->PrivateKeyContent))
1174 goto fail;
1175 if (!pf_config_copy_string_n(&tmp->PrivateKeyPEM, config->PrivateKeyPEM,
1176 config->PrivateKeyPEMLength))
1177 goto fail;
1178
1179 tmp->ini = IniFile_Clone(config->ini);
1180 if (!tmp->ini)
1181 goto fail;
1182
1183 *dst = tmp;
1184 return TRUE;
1185
1186fail:
1187 WINPR_PRAGMA_DIAG_PUSH
1188 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1190 WINPR_PRAGMA_DIAG_POP
1191 return FALSE;
1192}
1193
1194struct config_plugin_data
1195{
1196 proxyPluginsManager* mgr;
1197 const proxyConfig* config;
1198};
1199
1200static const char config_plugin_name[] = "config";
1201static const char config_plugin_desc[] =
1202 "A plugin filtering according to proxy configuration file rules";
1203
1204WINPR_ATTR_NODISCARD
1205static BOOL config_plugin_unload(proxyPlugin* plugin)
1206{
1207 WINPR_ASSERT(plugin);
1208
1209 /* Here we have to free up our custom data storage. */
1210 if (plugin)
1211 {
1212 free(plugin->custom);
1213 plugin->custom = nullptr;
1214 }
1215
1216 return TRUE;
1217}
1218
1219WINPR_ATTR_NODISCARD
1220static BOOL config_plugin_keyboard_event(proxyPlugin* plugin, WINPR_ATTR_UNUSED proxyData* pdata,
1221 void* param)
1222{
1223 BOOL rc = 0;
1224 const struct config_plugin_data* custom = nullptr;
1225 const proxyConfig* cfg = nullptr;
1226 const proxyKeyboardEventInfo* event_data = (const proxyKeyboardEventInfo*)(param);
1227
1228 WINPR_ASSERT(plugin);
1229 WINPR_ASSERT(pdata);
1230 WINPR_ASSERT(event_data);
1231
1232 WINPR_UNUSED(event_data);
1233
1234 custom = plugin->custom;
1235 WINPR_ASSERT(custom);
1236
1237 cfg = custom->config;
1238 WINPR_ASSERT(cfg);
1239
1240 rc = cfg->Keyboard;
1241 WLog_DBG(TAG, "%s", boolstr(rc));
1242 return rc;
1243}
1244
1245WINPR_ATTR_NODISCARD
1246static BOOL config_plugin_unicode_event(proxyPlugin* plugin, WINPR_ATTR_UNUSED proxyData* pdata,
1247 void* param)
1248{
1249 BOOL rc = 0;
1250 const struct config_plugin_data* custom = nullptr;
1251 const proxyConfig* cfg = nullptr;
1252 const proxyUnicodeEventInfo* event_data = (const proxyUnicodeEventInfo*)(param);
1253
1254 WINPR_ASSERT(plugin);
1255 WINPR_ASSERT(pdata);
1256 WINPR_ASSERT(event_data);
1257
1258 WINPR_UNUSED(event_data);
1259
1260 custom = plugin->custom;
1261 WINPR_ASSERT(custom);
1262
1263 cfg = custom->config;
1264 WINPR_ASSERT(cfg);
1265
1266 rc = cfg->Keyboard;
1267 WLog_DBG(TAG, "%s", boolstr(rc));
1268 return rc;
1269}
1270
1271WINPR_ATTR_NODISCARD
1272static BOOL config_plugin_mouse_event(proxyPlugin* plugin, WINPR_ATTR_UNUSED proxyData* pdata,
1273 void* param)
1274{
1275 BOOL rc = 0;
1276 const struct config_plugin_data* custom = nullptr;
1277 const proxyConfig* cfg = nullptr;
1278 const proxyMouseEventInfo* event_data = (const proxyMouseEventInfo*)(param);
1279
1280 WINPR_ASSERT(plugin);
1281 WINPR_ASSERT(pdata);
1282 WINPR_ASSERT(event_data);
1283
1284 WINPR_UNUSED(event_data);
1285
1286 custom = plugin->custom;
1287 WINPR_ASSERT(custom);
1288
1289 cfg = custom->config;
1290 WINPR_ASSERT(cfg);
1291
1292 rc = cfg->Mouse;
1293 return rc;
1294}
1295
1296WINPR_ATTR_NODISCARD
1297static BOOL config_plugin_mouse_ex_event(proxyPlugin* plugin, WINPR_ATTR_UNUSED proxyData* pdata,
1298 void* param)
1299{
1300 BOOL rc = 0;
1301 const struct config_plugin_data* custom = nullptr;
1302 const proxyConfig* cfg = nullptr;
1303 const proxyMouseExEventInfo* event_data = (const proxyMouseExEventInfo*)(param);
1304
1305 WINPR_ASSERT(plugin);
1306 WINPR_ASSERT(pdata);
1307 WINPR_ASSERT(event_data);
1308
1309 WINPR_UNUSED(event_data);
1310
1311 custom = plugin->custom;
1312 WINPR_ASSERT(custom);
1313
1314 cfg = custom->config;
1315 WINPR_ASSERT(cfg);
1316
1317 rc = cfg->Mouse;
1318 return rc;
1319}
1320
1321WINPR_ATTR_NODISCARD
1322static BOOL config_plugin_client_channel_data(WINPR_ATTR_UNUSED proxyPlugin* plugin,
1323 WINPR_ATTR_UNUSED proxyData* pdata, void* param)
1324{
1325 const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param);
1326
1327 WINPR_ASSERT(plugin);
1328 WINPR_ASSERT(pdata);
1329 WINPR_ASSERT(channel);
1330
1331 WLog_DBG(TAG, "%s [0x%04" PRIx16 "] got %" PRIuz, channel->channel_name, channel->channel_id,
1332 channel->data_len);
1333 return TRUE;
1334}
1335
1336WINPR_ATTR_NODISCARD
1337static BOOL config_plugin_server_channel_data(WINPR_ATTR_UNUSED proxyPlugin* plugin,
1338 WINPR_ATTR_UNUSED proxyData* pdata, void* param)
1339{
1340 const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param);
1341
1342 WINPR_ASSERT(plugin);
1343 WINPR_ASSERT(pdata);
1344 WINPR_ASSERT(channel);
1345
1346 WLog_DBG(TAG, "%s [0x%04" PRIx16 "] got %" PRIuz, channel->channel_name, channel->channel_id,
1347 channel->data_len);
1348 return TRUE;
1349}
1350
1351WINPR_ATTR_NODISCARD
1352static BOOL config_plugin_dynamic_channel_create(proxyPlugin* plugin,
1353 WINPR_ATTR_UNUSED proxyData* pdata, void* param)
1354{
1355 BOOL accept = 0;
1356 const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param);
1357
1358 WINPR_ASSERT(plugin);
1359 WINPR_ASSERT(pdata);
1360 WINPR_ASSERT(channel);
1361
1362 const struct config_plugin_data* custom = plugin->custom;
1363 WINPR_ASSERT(custom);
1364
1365 const proxyConfig* cfg = custom->config;
1366 WINPR_ASSERT(cfg);
1367
1368 pf_utils_channel_mode rc = pf_utils_get_channel_mode(cfg, channel->channel_name);
1369 switch (rc)
1370 {
1371
1372 case PF_UTILS_CHANNEL_INTERCEPT:
1373 case PF_UTILS_CHANNEL_PASSTHROUGH:
1374 accept = TRUE;
1375 break;
1376 case PF_UTILS_CHANNEL_BLOCK:
1377 default:
1378 accept = FALSE;
1379 break;
1380 }
1381
1382 if (accept)
1383 {
1384 if (strncmp(RDPGFX_DVC_CHANNEL_NAME, channel->channel_name,
1385 sizeof(RDPGFX_DVC_CHANNEL_NAME)) == 0)
1386 accept = cfg->GFX;
1387 else if (strncmp(RDPSND_DVC_CHANNEL_NAME, channel->channel_name,
1388 sizeof(RDPSND_DVC_CHANNEL_NAME)) == 0)
1389 accept = cfg->AudioOutput;
1390 else if (strncmp(RDPSND_LOSSY_DVC_CHANNEL_NAME, channel->channel_name,
1391 sizeof(RDPSND_LOSSY_DVC_CHANNEL_NAME)) == 0)
1392 accept = cfg->AudioOutput;
1393 else if (strncmp(AUDIN_DVC_CHANNEL_NAME, channel->channel_name,
1394 sizeof(AUDIN_DVC_CHANNEL_NAME)) == 0)
1395 accept = cfg->AudioInput;
1396 else if (strncmp(RDPEI_DVC_CHANNEL_NAME, channel->channel_name,
1397 sizeof(RDPEI_DVC_CHANNEL_NAME)) == 0)
1398 accept = cfg->Multitouch;
1399 else if (strncmp(TSMF_DVC_CHANNEL_NAME, channel->channel_name,
1400 sizeof(TSMF_DVC_CHANNEL_NAME)) == 0)
1401 accept = cfg->VideoRedirection;
1402 else if (strncmp(VIDEO_CONTROL_DVC_CHANNEL_NAME, channel->channel_name,
1403 sizeof(VIDEO_CONTROL_DVC_CHANNEL_NAME)) == 0)
1404 accept = cfg->VideoRedirection;
1405 else if (strncmp(VIDEO_DATA_DVC_CHANNEL_NAME, channel->channel_name,
1406 sizeof(VIDEO_DATA_DVC_CHANNEL_NAME)) == 0)
1407 accept = cfg->VideoRedirection;
1408 else if (strncmp(RDPECAM_DVC_CHANNEL_NAME, channel->channel_name,
1409 sizeof(RDPECAM_DVC_CHANNEL_NAME)) == 0)
1410 accept = cfg->CameraRedirection;
1411 }
1412
1413 WLog_DBG(TAG, "%s [0x%04" PRIx16 "]: %s", channel->channel_name, channel->channel_id,
1414 boolstr(accept));
1415 return accept;
1416}
1417
1418WINPR_ATTR_NODISCARD
1419static BOOL config_plugin_channel_create(proxyPlugin* plugin, WINPR_ATTR_UNUSED proxyData* pdata,
1420 void* param)
1421{
1422 BOOL accept = 0;
1423 const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param);
1424
1425 WINPR_ASSERT(plugin);
1426 WINPR_ASSERT(pdata);
1427 WINPR_ASSERT(channel);
1428
1429 const struct config_plugin_data* custom = plugin->custom;
1430 WINPR_ASSERT(custom);
1431
1432 const proxyConfig* cfg = custom->config;
1433 WINPR_ASSERT(cfg);
1434
1435 pf_utils_channel_mode rc = pf_utils_get_channel_mode(cfg, channel->channel_name);
1436 switch (rc)
1437 {
1438 case PF_UTILS_CHANNEL_INTERCEPT:
1439 case PF_UTILS_CHANNEL_PASSTHROUGH:
1440 accept = TRUE;
1441 break;
1442 case PF_UTILS_CHANNEL_BLOCK:
1443 default:
1444 accept = FALSE;
1445 break;
1446 }
1447 if (accept)
1448 {
1449 if (strncmp(CLIPRDR_SVC_CHANNEL_NAME, channel->channel_name,
1450 sizeof(CLIPRDR_SVC_CHANNEL_NAME)) == 0)
1451 accept = cfg->Clipboard;
1452 else if (strncmp(RDPSND_CHANNEL_NAME, channel->channel_name, sizeof(RDPSND_CHANNEL_NAME)) ==
1453 0)
1454 accept = cfg->AudioOutput;
1455 else if (strncmp(RDPDR_SVC_CHANNEL_NAME, channel->channel_name,
1456 sizeof(RDPDR_SVC_CHANNEL_NAME)) == 0)
1457 accept = cfg->DeviceRedirection;
1458 else if (strncmp(DISP_DVC_CHANNEL_NAME, channel->channel_name,
1459 sizeof(DISP_DVC_CHANNEL_NAME)) == 0)
1460 accept = cfg->DisplayControl;
1461 else if (strncmp(RAIL_SVC_CHANNEL_NAME, channel->channel_name,
1462 sizeof(RAIL_SVC_CHANNEL_NAME)) == 0)
1463 accept = cfg->RemoteApp;
1464 }
1465
1466 WLog_DBG(TAG, "%s [static]: %s", channel->channel_name, boolstr(accept));
1467 return accept;
1468}
1469
1470BOOL pf_config_plugin(proxyPluginsManager* plugins_manager, void* userdata)
1471{
1472 struct config_plugin_data* custom = nullptr;
1473 proxyPlugin plugin = WINPR_C_ARRAY_INIT;
1474
1475 plugin.name = config_plugin_name;
1476 plugin.description = config_plugin_desc;
1477 plugin.PluginUnload = config_plugin_unload;
1478
1479 plugin.KeyboardEvent = config_plugin_keyboard_event;
1480 plugin.UnicodeEvent = config_plugin_unicode_event;
1481 plugin.MouseEvent = config_plugin_mouse_event;
1482 plugin.MouseExEvent = config_plugin_mouse_ex_event;
1483 plugin.ClientChannelData = config_plugin_client_channel_data;
1484 plugin.ServerChannelData = config_plugin_server_channel_data;
1485 plugin.ChannelCreate = config_plugin_channel_create;
1486 plugin.DynamicChannelCreate = config_plugin_dynamic_channel_create;
1487 plugin.userdata = userdata;
1488
1489 custom = calloc(1, sizeof(struct config_plugin_data));
1490 if (!custom)
1491 return FALSE;
1492
1493 custom->mgr = plugins_manager;
1494 custom->config = userdata;
1495
1496 plugin.custom = custom;
1497 plugin.userdata = userdata;
1498
1499 return plugins_manager->RegisterPlugin(plugins_manager, &plugin);
1500}
1501
1502const char* pf_config_get(const proxyConfig* config, const char* section, const char* key)
1503{
1504 WINPR_ASSERT(config);
1505 WINPR_ASSERT(config->ini);
1506 WINPR_ASSERT(section);
1507 WINPR_ASSERT(key);
1508
1509 return IniFile_GetKeyValueString(config->ini, section, key);
1510}
void pf_server_config_free(proxyConfig *config)
pf_server_config_free Releases all resources associated with proxyConfig
Definition pf_config.c:1021
proxyConfig * pf_server_config_load_file(const char *path)
pf_server_config_load_file Create a proxyConfig from a INI file found at path.
Definition pf_config.c:906
void pf_server_config_print(const proxyConfig *config)
pf_server_config_print Print the configuration to stdout
Definition pf_config.c:936
const char ** pf_config_modules(const proxyConfig *config)
pf_config_modules
Definition pf_config.c:1071
const char * pf_config_required_plugin(const proxyConfig *config, size_t index)
pf_config_required_plugin
Definition pf_config.c:1056
proxyConfig * pf_server_config_load_buffer(const char *buffer)
pf_server_config_load_buffer Create a proxyConfig from a memory string buffer in INI file format
Definition pf_config.c:881
size_t pf_config_modules_count(const proxyConfig *config)
pf_config_modules_count
Definition pf_config.c:1065
BOOL pf_config_clone(proxyConfig **dst, const proxyConfig *config)
pf_config_clone Create a copy of the configuration
Definition pf_config.c:1124
proxyConfig * server_config_load_ini(wIniFile *ini)
server_config_load_ini Create a proxyConfig from a already loaded INI file.
Definition pf_config.c:670
size_t pf_config_required_plugins_count(const proxyConfig *config)
pf_config_required_plugins_count
Definition pf_config.c:1050
BOOL pf_server_config_dump(const char *file)
pf_server_config_dump Dumps a default INI configuration file
Definition pf_config.c:720
BOOL pf_config_plugin(proxyPluginsManager *plugins_manager, void *userdata)
pf_config_plugin Register a proxy plugin handling event filtering defined in the configuration.
Definition pf_config.c:1470
const char * pf_config_get(const proxyConfig *config, const char *section, const char *key)
pf_config_get get a value for a section/key
Definition pf_config.c:1502