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_ext = "ServerExtSecurity";
116static const char* key_security_server_tls = "ServerTlsSecurity";
117static const char* key_security_server_rdp = "ServerRdpSecurity";
118static const char* key_security_client_nla = "ClientNlaSecurity";
119static const char* key_security_client_ext = "ClientExtSecurity";
120static const char* key_security_client_tls = "ClientTlsSecurity";
121static const char* key_security_client_rdp = "ClientRdpSecurity";
122static const char* key_security_client_fallback = "ClientAllowFallbackToTls";
123
124static const char* section_certificates = "Certificates";
125static const char* key_private_key_file = "PrivateKeyFile";
126static const char* key_private_key_content = "PrivateKeyContent";
127static const char* key_cert_file = "CertificateFile";
128static const char* key_cert_content = "CertificateContent";
129
130WINPR_ATTR_MALLOC(free, 1)
131static char* pf_config_decode_base64(const char* data, const char* name, size_t* pLength);
132
133WINPR_ATTR_MALLOC(CommandLineParserFree, 1)
134WINPR_ATTR_NODISCARD
135static char** pf_config_parse_comma_separated_list(const char* list, size_t* count)
136{
137 if (!list || !count)
138 return nullptr;
139
140 if (strlen(list) == 0)
141 {
142 *count = 0;
143 return nullptr;
144 }
145
146 return CommandLineParseCommaSeparatedValues(list, count);
147}
148
149WINPR_ATTR_NODISCARD
150static BOOL pf_config_get_uint16(wIniFile* ini, const char* section, const char* key,
151 UINT16* result, BOOL required)
152{
153 int val = 0;
154 const char* strval = nullptr;
155
156 WINPR_ASSERT(result);
157
158 strval = IniFile_GetKeyValueString(ini, section, key);
159 if (!strval && required)
160 {
161 WLog_ERR(TAG, "key '%s.%s' does not exist.", section, key);
162 return FALSE;
163 }
164 else if (!strval)
165 goto out;
166
167 val = IniFile_GetKeyValueInt(ini, section, key);
168 if ((val <= 0) || (val > UINT16_MAX))
169 {
170 WLog_ERR(TAG, "invalid value %d for key '%s.%s'.", val, section, key);
171 return FALSE;
172 }
173
174out:
175 *result = (UINT16)val;
176 return TRUE;
177}
178
179WINPR_ATTR_NODISCARD
180static BOOL pf_config_get_uint32(wIniFile* ini, const char* section, const char* key,
181 UINT32* result, BOOL required)
182{
183 WINPR_ASSERT(result);
184
185 const char* strval = IniFile_GetKeyValueString(ini, section, key);
186 if (!strval)
187 {
188 if (required)
189 WLog_ERR(TAG, "key '%s.%s' does not exist.", section, key);
190 return !required;
191 }
192
193 const int val = IniFile_GetKeyValueInt(ini, section, key);
194 if (val < 0)
195 {
196 WLog_ERR(TAG, "invalid value %d for key '%s.%s'.", val, section, key);
197 return FALSE;
198 }
199
200 *result = (UINT32)val;
201 return TRUE;
202}
203
204WINPR_ATTR_NODISCARD
205static BOOL pf_config_get_bool(wIniFile* ini, const char* section, const char* key, BOOL fallback)
206{
207 int num_value = 0;
208 const char* str_value = nullptr;
209
210 str_value = IniFile_GetKeyValueString(ini, section, key);
211 if (!str_value)
212 {
213 WLog_WARN(TAG, "key '%s.%s' not found, value defaults to %s.", section, key,
214 fallback ? bool_str_true : bool_str_false);
215 return fallback;
216 }
217
218 if (_stricmp(str_value, bool_str_true) == 0)
219 return TRUE;
220 if (_stricmp(str_value, bool_str_false) == 0)
221 return FALSE;
222
223 num_value = IniFile_GetKeyValueInt(ini, section, key);
224
225 return (num_value != 0);
226}
227
228WINPR_ATTR_NODISCARD
229static const char* pf_config_get_str(wIniFile* ini, const char* section, const char* key,
230 BOOL required)
231{
232 const char* value = IniFile_GetKeyValueString(ini, section, key);
233
234 if (!value)
235 {
236 if (required)
237 WLog_ERR(TAG, "key '%s.%s' not found.", section, key);
238 return nullptr;
239 }
240
241 return value;
242}
243
244WINPR_ATTR_NODISCARD
245static BOOL pf_config_copy_string(char** dst, const char* src)
246{
247 WINPR_ASSERT(dst);
248 *dst = nullptr;
249 if (src)
250 *dst = _strdup(src);
251 return TRUE;
252}
253
254WINPR_ATTR_NODISCARD
255static BOOL pf_config_free_and_copy_string(char** dst, const char* src)
256{
257 WINPR_ASSERT(dst);
258 winpr_zfree(*dst);
259 return pf_config_copy_string(dst, src);
260}
261
262WINPR_ATTR_NODISCARD
263static BOOL pf_config_load_server(wIniFile* ini, proxyConfig* config)
264{
265 WINPR_ASSERT(config);
266 const char* host = pf_config_get_str(ini, section_server, key_host, FALSE);
267
268 if (host)
269 {
270 if (!pf_config_free_and_copy_string(&config->Host, host))
271 return FALSE;
272 }
273
274 if (!pf_config_get_uint16(ini, section_server, key_port, &config->Port, FALSE))
275 return FALSE;
276
277 const char* sam = pf_config_get_str(ini, section_server, key_sam_file, FALSE);
278 if (sam)
279 {
280 if (!pf_config_free_and_copy_string(&config->SamFile, sam))
281 return FALSE;
282 }
283
284 return TRUE;
285}
286
287WINPR_ATTR_NODISCARD
288static BOOL pf_config_load_target(wIniFile* ini, proxyConfig* config)
289{
290 const char* target_value = nullptr;
291
292 WINPR_ASSERT(config);
293 config->FixedTarget = pf_config_get_bool(ini, section_target, key_target_fixed, FALSE);
294
295 if (!pf_config_get_uint32(ini, section_target, key_target_tls_seclevel,
296 &config->TargetTlsSecLevel, FALSE))
297 return FALSE;
298
299 if (config->FixedTarget)
300 {
301 if (!pf_config_get_uint16(ini, section_target, key_port, &config->TargetPort, FALSE))
302 return FALSE;
303
304 target_value = pf_config_get_str(ini, section_target, key_host, FALSE);
305 if (target_value)
306 {
307 if (!pf_config_free_and_copy_string(&config->TargetHost, target_value))
308 return FALSE;
309 }
310 }
311
312 target_value = pf_config_get_str(ini, section_target, key_target_user, FALSE);
313 if (target_value)
314 {
315 if (!pf_config_free_and_copy_string(&config->TargetUser, target_value))
316 return FALSE;
317 }
318
319 target_value = pf_config_get_str(ini, section_target, key_target_pwd, FALSE);
320 if (target_value)
321 {
322 if (!pf_config_free_and_copy_string(&config->TargetPassword, target_value))
323 return FALSE;
324 }
325
326 target_value = pf_config_get_str(ini, section_target, key_target_domain, FALSE);
327 if (target_value)
328 {
329 if (!pf_config_free_and_copy_string(&config->TargetDomain, target_value))
330 return FALSE;
331 }
332
333 config->TargetSmartcardAuth =
334 pf_config_get_bool(ini, section_target, key_target_scard_auth, FALSE);
335
336 target_value = pf_config_get_str(ini, section_target, key_target_scard_cert, FALSE);
337 if (target_value)
338 {
339 size_t len = 0;
340 char* pem = crypto_read_pem(target_value, &len);
341 if (!pem)
342 return FALSE;
343 winpr_znfree(config->TargetSmartcardCert, config->TargetSmartcardCertLength);
344 config->TargetSmartcardCert = pem;
345 config->TargetSmartcardCertLength = len;
346 }
347
348 {
349 const char* pem_value =
350 pf_config_get_str(ini, section_target, key_target_scard_pem_cert, FALSE);
351 if (pem_value)
352 {
353 if (target_value)
354 WLog_WARN(TAG, "In section [%s] both, '%s' and '%s' are provided. Ignoring %s",
355 section_target, key_target_scard_cert, key_target_scard_pem_cert,
356 key_target_scard_cert);
357 winpr_znfree(config->TargetSmartcardCert, config->TargetSmartcardCertLength);
358 size_t len = 0;
359 config->TargetSmartcardCert =
360 pf_config_decode_base64(pem_value, key_target_scard_pem_cert, &len);
361 if (!config->TargetSmartcardCert)
362 return FALSE;
363 config->TargetSmartcardCertLength = len;
364 }
365 }
366
367 target_value = pf_config_get_str(ini, section_target, key_target_scard_key, FALSE);
368 if (target_value)
369 {
370 size_t len = 0;
371 char* pem = crypto_read_pem(target_value, &len);
372 if (!pem)
373 return FALSE;
374 winpr_znfree(config->TargetSmartcardKey, config->TargetSmartcardKeyLength);
375 config->TargetSmartcardKey = pem;
376 config->TargetSmartcardKeyLength = len;
377 }
378
379 {
380 const char* pem_value =
381 pf_config_get_str(ini, section_target, key_target_scard_pem_key, FALSE);
382 if (pem_value)
383 {
384 if (target_value)
385 WLog_WARN(TAG, "In section [%s] both, '%s' and '%s' are provided. Ignoring %s",
386 section_target, key_target_scard_key, key_target_scard_pem_key,
387 key_target_scard_key);
388 winpr_znfree(config->TargetSmartcardKey, config->TargetSmartcardKeyLength);
389
390 size_t len = 0;
391 config->TargetSmartcardKey =
392 pf_config_decode_base64(pem_value, key_target_scard_pem_key, &len);
393 if (!config->TargetSmartcardKey)
394 return FALSE;
395 config->TargetSmartcardKeyLength = len;
396 }
397 }
398
399 return TRUE;
400}
401
402WINPR_ATTR_NODISCARD
403static BOOL pf_config_load_codecs(wIniFile* ini, proxyConfig* config)
404{
405 WINPR_ASSERT(config);
406 config->RFX = pf_config_get_bool(ini, section_codecs, key_codecs_rfx, TRUE);
407 config->NSC = pf_config_get_bool(ini, section_codecs, key_codecs_nsc, TRUE);
408 return TRUE;
409}
410
411WINPR_ATTR_NODISCARD
412static BOOL pf_config_load_channels(wIniFile* ini, proxyConfig* config)
413{
414 WINPR_ASSERT(config);
415 config->GFX = pf_config_get_bool(ini, section_channels, key_channels_gfx, TRUE);
416 config->DisplayControl = pf_config_get_bool(ini, section_channels, key_channels_disp, TRUE);
417 config->Clipboard = pf_config_get_bool(ini, section_channels, key_channels_clip, FALSE);
418 config->AudioOutput = pf_config_get_bool(ini, section_channels, key_channels_sound, TRUE);
419 config->AudioInput = pf_config_get_bool(ini, section_channels, key_channels_mic, TRUE);
420 config->DeviceRedirection = pf_config_get_bool(ini, section_channels, key_channels_rdpdr, TRUE);
421 config->VideoRedirection = pf_config_get_bool(ini, section_channels, key_channels_video, TRUE);
422 config->CameraRedirection =
423 pf_config_get_bool(ini, section_channels, key_channels_camera, TRUE);
424 config->RemoteApp = pf_config_get_bool(ini, section_channels, key_channels_rails, FALSE);
425 config->PassthroughIsBlacklist =
426 pf_config_get_bool(ini, section_channels, key_channels_blacklist, FALSE);
427 config->Passthrough = pf_config_parse_comma_separated_list(
428 pf_config_get_str(ini, section_channels, key_channels_pass, FALSE),
429 &config->PassthroughCount);
430 config->Intercept = pf_config_parse_comma_separated_list(
431 pf_config_get_str(ini, section_channels, key_channels_intercept, FALSE),
432 &config->InterceptCount);
433
434 return TRUE;
435}
436
437WINPR_ATTR_NODISCARD
438static BOOL pf_config_load_input(wIniFile* ini, proxyConfig* config)
439{
440 WINPR_ASSERT(config);
441 config->Keyboard = pf_config_get_bool(ini, section_input, key_input_kbd, TRUE);
442 config->Mouse = pf_config_get_bool(ini, section_input, key_input_mouse, TRUE);
443 config->Multitouch = pf_config_get_bool(ini, section_input, key_input_multitouch, TRUE);
444 return TRUE;
445}
446
447WINPR_ATTR_NODISCARD
448static BOOL pf_config_load_security(wIniFile* ini, proxyConfig* config)
449{
450 WINPR_ASSERT(config);
451 config->ServerTlsSecurity =
452 pf_config_get_bool(ini, section_security, key_security_server_tls, TRUE);
453 config->ServerNlaSecurity =
454 pf_config_get_bool(ini, section_security, key_security_server_nla, FALSE);
455 config->ServerExtSecurity =
456 pf_config_get_bool(ini, section_security, key_security_server_ext, FALSE);
457 config->ServerRdpSecurity =
458 pf_config_get_bool(ini, section_security, key_security_server_rdp, TRUE);
459
460 config->ClientTlsSecurity =
461 pf_config_get_bool(ini, section_security, key_security_client_tls, TRUE);
462 config->ClientNlaSecurity =
463 pf_config_get_bool(ini, section_security, key_security_client_nla, TRUE);
464 config->ClientExtSecurity =
465 pf_config_get_bool(ini, section_security, key_security_client_ext, 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 winpr_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_ext, bool_str_false) <
817 0)
818 goto fail;
819 if (IniFile_SetKeyValueString(ini, section_security, key_security_server_rdp, bool_str_true) <
820 0)
821 goto fail;
822
823 if (IniFile_SetKeyValueString(ini, section_security, key_security_client_tls, bool_str_true) <
824 0)
825 goto fail;
826 if (IniFile_SetKeyValueString(ini, section_security, key_security_client_nla, bool_str_true) <
827 0)
828 goto fail;
829 if (IniFile_SetKeyValueString(ini, section_security, key_security_client_ext, bool_str_true) <
830 0)
831 goto fail;
832 if (IniFile_SetKeyValueString(ini, section_security, key_security_client_rdp, bool_str_true) <
833 0)
834 goto fail;
835 if (IniFile_SetKeyValueString(ini, section_security, key_security_client_fallback,
836 bool_str_true) < 0)
837 goto fail;
838
839 /* Module configuration */
840 if (IniFile_SetKeyValueString(ini, section_plugins, key_plugins_modules,
841 "module1,module2,...") < 0)
842 goto fail;
843 if (IniFile_SetKeyValueString(ini, section_plugins, key_plugins_required,
844 "module1,module2,...") < 0)
845 goto fail;
846
847 /* Certificate configuration */
848 if (IniFile_SetKeyValueString(ini, section_certificates, key_cert_file,
849 "<absolute path to some certificate file> OR") < 0)
850 goto fail;
851 if (IniFile_SetKeyValueString(ini, section_certificates, key_cert_content,
852 "<base64 encoded PEM>") < 0)
853 goto fail;
854
855 if (IniFile_SetKeyValueString(ini, section_certificates, key_private_key_file,
856 "<absolute path to some private key file> OR") < 0)
857 goto fail;
858 if (IniFile_SetKeyValueString(ini, section_certificates, key_private_key_content,
859 "<base64 encoded PEM>") < 0)
860 goto fail;
861
862 if ((strcmp("stdout", file) == 0) || (strcmp("stderr", file) == 0))
863 {
864 char* buffer = IniFile_WriteBuffer(ini);
865 if (!buffer)
866 goto fail;
867 FILE* fp = stderr;
868 if (strcmp("stdout", file) == 0)
869 fp = stdout;
870 (void)fprintf(fp, "%s", buffer);
871 winpr_zfree(buffer);
872 }
873 else
874 {
875 /* store configuration */
876 if (IniFile_WriteFile(ini, file) < 0)
877 goto fail;
878 }
879
880 rc = TRUE;
881
882fail:
883 IniFile_Free(ini);
884 return rc;
885}
886
887proxyConfig* pf_server_config_load_buffer(const char* buffer)
888{
889 proxyConfig* config = nullptr;
890 wIniFile* ini = nullptr;
891
892 ini = IniFile_New();
893
894 if (!ini)
895 {
896 WLog_ERR(TAG, "IniFile_New() failed!");
897 return nullptr;
898 }
899
900 if (IniFile_ReadBuffer(ini, buffer) < 0)
901 {
902 WLog_ERR(TAG, "failed to parse ini: '%s'", buffer);
903 goto out;
904 }
905
906 config = server_config_load_ini(ini);
907out:
908 IniFile_Free(ini);
909 return config;
910}
911
912proxyConfig* pf_server_config_load_file(const char* path)
913{
914 proxyConfig* config = nullptr;
915 wIniFile* ini = IniFile_New();
916
917 if (!ini)
918 {
919 WLog_ERR(TAG, "IniFile_New() failed!");
920 return nullptr;
921 }
922
923 if (IniFile_ReadFile(ini, path) < 0)
924 {
925 WLog_ERR(TAG, "failed to parse ini file: '%s'", path);
926 goto out;
927 }
928
929 config = server_config_load_ini(ini);
930out:
931 IniFile_Free(ini);
932 return config;
933}
934
935static void pf_server_config_print_list(char** list, size_t count)
936{
937 WINPR_ASSERT(list);
938 for (size_t i = 0; i < count; i++)
939 WLog_INFO(TAG, "\t\t- %s", list[i]);
940}
941
942void pf_server_config_print(const proxyConfig* config)
943{
944 WINPR_ASSERT(config);
945 WLog_INFO(TAG, "Proxy configuration:");
946
947 CONFIG_PRINT_SECTION(section_server);
948 CONFIG_PRINT_STR(config, Host);
949 CONFIG_PRINT_STR(config, SamFile);
950 CONFIG_PRINT_UINT16(config, Port);
951
952 if (config->FixedTarget)
953 {
954 CONFIG_PRINT_SECTION(section_target);
955 CONFIG_PRINT_STR(config, TargetHost);
956 CONFIG_PRINT_UINT16(config, TargetPort);
957 CONFIG_PRINT_UINT32(config, TargetTlsSecLevel);
958
959 CONFIG_PRINT_STR(config, TargetUser);
960 CONFIG_PRINT_STR(config, TargetDomain);
961 CONFIG_PRINT_SECRET_STR(config, TargetPassword);
962
963 CONFIG_PRINT_BOOL(config, TargetSmartcardAuth);
964 CONFIG_PRINT_SECRET_STR(config, TargetSmartcardCert);
965 CONFIG_PRINT_SECRET_STR(config, TargetSmartcardKey);
966 }
967
968 CONFIG_PRINT_SECTION(section_input);
969 CONFIG_PRINT_BOOL(config, Keyboard);
970 CONFIG_PRINT_BOOL(config, Mouse);
971 CONFIG_PRINT_BOOL(config, Multitouch);
972
973 CONFIG_PRINT_SECTION(section_security);
974 CONFIG_PRINT_BOOL(config, ServerNlaSecurity);
975 CONFIG_PRINT_BOOL(config, ServerExtSecurity);
976 CONFIG_PRINT_BOOL(config, ServerTlsSecurity);
977 CONFIG_PRINT_BOOL(config, ServerRdpSecurity);
978 CONFIG_PRINT_BOOL(config, ClientNlaSecurity);
979 CONFIG_PRINT_BOOL(config, ClientExtSecurity);
980 CONFIG_PRINT_BOOL(config, ClientTlsSecurity);
981 CONFIG_PRINT_BOOL(config, ClientRdpSecurity);
982 CONFIG_PRINT_BOOL(config, ClientAllowFallbackToTls);
983
984 CONFIG_PRINT_SECTION(section_codecs);
985 CONFIG_PRINT_BOOL(config, RFX);
986 CONFIG_PRINT_BOOL(config, NSC);
987
988 CONFIG_PRINT_SECTION(section_channels);
989 CONFIG_PRINT_BOOL(config, GFX);
990 CONFIG_PRINT_BOOL(config, DisplayControl);
991 CONFIG_PRINT_BOOL(config, Clipboard);
992 CONFIG_PRINT_BOOL(config, AudioOutput);
993 CONFIG_PRINT_BOOL(config, AudioInput);
994 CONFIG_PRINT_BOOL(config, DeviceRedirection);
995 CONFIG_PRINT_BOOL(config, VideoRedirection);
996 CONFIG_PRINT_BOOL(config, CameraRedirection);
997 CONFIG_PRINT_BOOL(config, RemoteApp);
998 CONFIG_PRINT_BOOL(config, PassthroughIsBlacklist);
999
1000 if (config->PassthroughCount)
1001 {
1002 WLog_INFO(TAG, "\tStatic Channels Proxy:");
1003 pf_server_config_print_list(config->Passthrough, config->PassthroughCount);
1004 }
1005
1006 if (config->InterceptCount)
1007 {
1008 WLog_INFO(TAG, "\tStatic Channels Proxy-Intercept:");
1009 pf_server_config_print_list(config->Intercept, config->InterceptCount);
1010 }
1011
1012 /* modules */
1013 CONFIG_PRINT_SECTION_KEY(section_plugins, key_plugins_modules);
1014 for (size_t x = 0; x < config->ModulesCount; x++)
1015 CONFIG_PRINT_STR(config, Modules[x]);
1016
1017 /* Required plugins */
1018 CONFIG_PRINT_SECTION_KEY(section_plugins, key_plugins_required);
1019 for (size_t x = 0; x < config->RequiredPluginsCount; x++)
1020 CONFIG_PRINT_STR(config, RequiredPlugins[x]);
1021
1022 CONFIG_PRINT_SECTION(section_certificates);
1023 CONFIG_PRINT_STR(config, CertificateFile);
1024 CONFIG_PRINT_SECRET_STR(config, CertificateContent);
1025 CONFIG_PRINT_STR(config, PrivateKeyFile);
1026 CONFIG_PRINT_SECRET_STR(config, PrivateKeyContent);
1027}
1028
1029void pf_server_config_free(proxyConfig* config)
1030{
1031 if (config == nullptr)
1032 return;
1033
1034 winpr_zfree(config->Host);
1035 winpr_zfree(config->SamFile);
1036 winpr_zfree(config->TargetHost);
1037 winpr_zfree(config->TargetUser);
1038 winpr_zfree(config->TargetDomain);
1039 winpr_zfree(config->TargetPassword);
1040 winpr_znfree(config->TargetSmartcardCert, config->TargetSmartcardCertLength);
1041 winpr_znfree(config->TargetSmartcardKey, config->TargetSmartcardKeyLength);
1042
1043 CommandLineParserFree(config->Passthrough);
1044 CommandLineParserFree(config->Intercept);
1045 CommandLineParserFree(config->Modules);
1046 CommandLineParserFree(config->RequiredPlugins);
1047
1048 winpr_zfree(config->CertificateFile);
1049 winpr_zfree(config->CertificateContent);
1050 winpr_znfree(config->CertificatePEM, config->CertificatePEMLength);
1051 winpr_zfree(config->PrivateKeyFile);
1052 winpr_zfree(config->PrivateKeyContent);
1053 winpr_znfree(config->PrivateKeyPEM, config->PrivateKeyPEMLength);
1054 IniFile_Free(config->ini);
1055 free(config);
1056}
1057
1058size_t pf_config_required_plugins_count(const proxyConfig* config)
1059{
1060 WINPR_ASSERT(config);
1061 return config->RequiredPluginsCount;
1062}
1063
1064const char* pf_config_required_plugin(const proxyConfig* config, size_t index)
1065{
1066 WINPR_ASSERT(config);
1067 if (index >= config->RequiredPluginsCount)
1068 return nullptr;
1069
1070 return config->RequiredPlugins[index];
1071}
1072
1073size_t pf_config_modules_count(const proxyConfig* config)
1074{
1075 WINPR_ASSERT(config);
1076 return config->ModulesCount;
1077}
1078
1079const char** pf_config_modules(const proxyConfig* config)
1080{
1081 union
1082 {
1083 char** ppc;
1084 const char** cppc;
1085 } cnv;
1086
1087 WINPR_ASSERT(config);
1088
1089 cnv.ppc = config->Modules;
1090 return cnv.cppc;
1091}
1092
1093WINPR_ATTR_NODISCARD
1094static BOOL pf_config_copy_string_n(char** dst, const char* src, size_t size)
1095{
1096 *dst = nullptr;
1097
1098 if (src && (size > 0))
1099 {
1100 WINPR_ASSERT(strnlen(src, size) == size - 1);
1101 *dst = calloc(size, sizeof(char));
1102 if (!*dst)
1103 return FALSE;
1104 memcpy(*dst, src, size);
1105 }
1106
1107 return TRUE;
1108}
1109
1110WINPR_ATTR_NODISCARD
1111static BOOL pf_config_copy_string_list(char*** dst, size_t* size, char** src, size_t srcSize)
1112{
1113 WINPR_ASSERT(dst);
1114 WINPR_ASSERT(size);
1115 WINPR_ASSERT(src || (srcSize == 0));
1116
1117 *dst = nullptr;
1118 *size = 0;
1119 if (srcSize > INT32_MAX)
1120 return FALSE;
1121
1122 if (srcSize != 0)
1123 {
1124 char* csv = CommandLineToCommaSeparatedValues((INT32)srcSize, src);
1125 *dst = CommandLineParseCommaSeparatedValues(csv, size);
1126 winpr_zfree(csv);
1127 }
1128
1129 return TRUE;
1130}
1131
1132BOOL pf_config_clone(proxyConfig** dst, const proxyConfig* config)
1133{
1134 proxyConfig* tmp = calloc(1, sizeof(proxyConfig));
1135
1136 WINPR_ASSERT(dst);
1137 WINPR_ASSERT(config);
1138
1139 if (!tmp)
1140 return FALSE;
1141
1142 *tmp = *config;
1143
1144 if (!pf_config_copy_string(&tmp->Host, config->Host))
1145 goto fail;
1146 if (!pf_config_copy_string(&tmp->SamFile, config->SamFile))
1147 goto fail;
1148 if (!pf_config_copy_string(&tmp->TargetHost, config->TargetHost))
1149 goto fail;
1150 if (!pf_config_copy_string(&tmp->TargetUser, config->TargetUser))
1151 goto fail;
1152 if (!pf_config_copy_string(&tmp->TargetDomain, config->TargetDomain))
1153 goto fail;
1154 if (!pf_config_copy_string(&tmp->TargetPassword, config->TargetPassword))
1155 goto fail;
1156 if (!pf_config_copy_string_n(&tmp->TargetSmartcardCert, config->TargetSmartcardCert,
1157 config->TargetSmartcardCertLength))
1158 goto fail;
1159 if (!pf_config_copy_string_n(&tmp->TargetSmartcardKey, config->TargetSmartcardKey,
1160 config->TargetSmartcardKeyLength))
1161 goto fail;
1162 if (!pf_config_copy_string_list(&tmp->Passthrough, &tmp->PassthroughCount, config->Passthrough,
1163 config->PassthroughCount))
1164 goto fail;
1165 if (!pf_config_copy_string_list(&tmp->Intercept, &tmp->InterceptCount, config->Intercept,
1166 config->InterceptCount))
1167 goto fail;
1168 if (!pf_config_copy_string_list(&tmp->Modules, &tmp->ModulesCount, config->Modules,
1169 config->ModulesCount))
1170 goto fail;
1171 if (!pf_config_copy_string_list(&tmp->RequiredPlugins, &tmp->RequiredPluginsCount,
1172 config->RequiredPlugins, config->RequiredPluginsCount))
1173 goto fail;
1174 if (!pf_config_copy_string(&tmp->CertificateFile, config->CertificateFile))
1175 goto fail;
1176 if (!pf_config_copy_string(&tmp->CertificateContent, config->CertificateContent))
1177 goto fail;
1178 if (!pf_config_copy_string_n(&tmp->CertificatePEM, config->CertificatePEM,
1179 config->CertificatePEMLength))
1180 goto fail;
1181 if (!pf_config_copy_string(&tmp->PrivateKeyFile, config->PrivateKeyFile))
1182 goto fail;
1183 if (!pf_config_copy_string(&tmp->PrivateKeyContent, config->PrivateKeyContent))
1184 goto fail;
1185 if (!pf_config_copy_string_n(&tmp->PrivateKeyPEM, config->PrivateKeyPEM,
1186 config->PrivateKeyPEMLength))
1187 goto fail;
1188
1189 tmp->ini = IniFile_Clone(config->ini);
1190 if (!tmp->ini)
1191 goto fail;
1192
1193 *dst = tmp;
1194 return TRUE;
1195
1196fail:
1197 WINPR_PRAGMA_DIAG_PUSH
1198 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1200 WINPR_PRAGMA_DIAG_POP
1201 return FALSE;
1202}
1203
1204struct config_plugin_data
1205{
1206 proxyPluginsManager* mgr;
1207 const proxyConfig* config;
1208};
1209
1210static const char config_plugin_name[] = "config";
1211static const char config_plugin_desc[] =
1212 "A plugin filtering according to proxy configuration file rules";
1213
1214WINPR_ATTR_NODISCARD
1215static BOOL config_plugin_unload(proxyPlugin* plugin)
1216{
1217 WINPR_ASSERT(plugin);
1218
1219 /* Here we have to free up our custom data storage. */
1220 if (plugin)
1221 {
1222 free(plugin->custom);
1223 plugin->custom = nullptr;
1224 }
1225
1226 return TRUE;
1227}
1228
1229WINPR_ATTR_NODISCARD
1230static BOOL config_plugin_keyboard_event(proxyPlugin* plugin, WINPR_ATTR_UNUSED proxyData* pdata,
1231 void* param)
1232{
1233 BOOL rc = 0;
1234 const struct config_plugin_data* custom = nullptr;
1235 const proxyConfig* cfg = nullptr;
1236 const proxyKeyboardEventInfo* event_data = (const proxyKeyboardEventInfo*)(param);
1237
1238 WINPR_ASSERT(plugin);
1239 WINPR_ASSERT(pdata);
1240 WINPR_ASSERT(event_data);
1241
1242 WINPR_UNUSED(event_data);
1243
1244 custom = plugin->custom;
1245 WINPR_ASSERT(custom);
1246
1247 cfg = custom->config;
1248 WINPR_ASSERT(cfg);
1249
1250 rc = cfg->Keyboard;
1251 WLog_DBG(TAG, "%s", boolstr(rc));
1252 return rc;
1253}
1254
1255WINPR_ATTR_NODISCARD
1256static BOOL config_plugin_unicode_event(proxyPlugin* plugin, WINPR_ATTR_UNUSED proxyData* pdata,
1257 void* param)
1258{
1259 BOOL rc = 0;
1260 const struct config_plugin_data* custom = nullptr;
1261 const proxyConfig* cfg = nullptr;
1262 const proxyUnicodeEventInfo* event_data = (const proxyUnicodeEventInfo*)(param);
1263
1264 WINPR_ASSERT(plugin);
1265 WINPR_ASSERT(pdata);
1266 WINPR_ASSERT(event_data);
1267
1268 WINPR_UNUSED(event_data);
1269
1270 custom = plugin->custom;
1271 WINPR_ASSERT(custom);
1272
1273 cfg = custom->config;
1274 WINPR_ASSERT(cfg);
1275
1276 rc = cfg->Keyboard;
1277 WLog_DBG(TAG, "%s", boolstr(rc));
1278 return rc;
1279}
1280
1281WINPR_ATTR_NODISCARD
1282static BOOL config_plugin_mouse_event(proxyPlugin* plugin, WINPR_ATTR_UNUSED proxyData* pdata,
1283 void* param)
1284{
1285 BOOL rc = 0;
1286 const struct config_plugin_data* custom = nullptr;
1287 const proxyConfig* cfg = nullptr;
1288 const proxyMouseEventInfo* event_data = (const proxyMouseEventInfo*)(param);
1289
1290 WINPR_ASSERT(plugin);
1291 WINPR_ASSERT(pdata);
1292 WINPR_ASSERT(event_data);
1293
1294 WINPR_UNUSED(event_data);
1295
1296 custom = plugin->custom;
1297 WINPR_ASSERT(custom);
1298
1299 cfg = custom->config;
1300 WINPR_ASSERT(cfg);
1301
1302 rc = cfg->Mouse;
1303 return rc;
1304}
1305
1306WINPR_ATTR_NODISCARD
1307static BOOL config_plugin_mouse_ex_event(proxyPlugin* plugin, WINPR_ATTR_UNUSED proxyData* pdata,
1308 void* param)
1309{
1310 BOOL rc = 0;
1311 const struct config_plugin_data* custom = nullptr;
1312 const proxyConfig* cfg = nullptr;
1313 const proxyMouseExEventInfo* event_data = (const proxyMouseExEventInfo*)(param);
1314
1315 WINPR_ASSERT(plugin);
1316 WINPR_ASSERT(pdata);
1317 WINPR_ASSERT(event_data);
1318
1319 WINPR_UNUSED(event_data);
1320
1321 custom = plugin->custom;
1322 WINPR_ASSERT(custom);
1323
1324 cfg = custom->config;
1325 WINPR_ASSERT(cfg);
1326
1327 rc = cfg->Mouse;
1328 return rc;
1329}
1330
1331WINPR_ATTR_NODISCARD
1332static BOOL config_plugin_client_channel_data(WINPR_ATTR_UNUSED proxyPlugin* plugin,
1333 WINPR_ATTR_UNUSED proxyData* pdata, void* param)
1334{
1335 const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param);
1336
1337 WINPR_ASSERT(plugin);
1338 WINPR_ASSERT(pdata);
1339 WINPR_ASSERT(channel);
1340
1341 WLog_DBG(TAG, "%s [0x%04" PRIx16 "] got %" PRIuz, channel->channel_name, channel->channel_id,
1342 channel->data_len);
1343 return TRUE;
1344}
1345
1346WINPR_ATTR_NODISCARD
1347static BOOL config_plugin_server_channel_data(WINPR_ATTR_UNUSED proxyPlugin* plugin,
1348 WINPR_ATTR_UNUSED proxyData* pdata, void* param)
1349{
1350 const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param);
1351
1352 WINPR_ASSERT(plugin);
1353 WINPR_ASSERT(pdata);
1354 WINPR_ASSERT(channel);
1355
1356 WLog_DBG(TAG, "%s [0x%04" PRIx16 "] got %" PRIuz, channel->channel_name, channel->channel_id,
1357 channel->data_len);
1358 return TRUE;
1359}
1360
1361WINPR_ATTR_NODISCARD
1362static BOOL config_plugin_dynamic_channel_create(proxyPlugin* plugin,
1363 WINPR_ATTR_UNUSED proxyData* pdata, void* param)
1364{
1365 BOOL accept = 0;
1366 const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param);
1367
1368 WINPR_ASSERT(plugin);
1369 WINPR_ASSERT(pdata);
1370 WINPR_ASSERT(channel);
1371
1372 const struct config_plugin_data* custom = plugin->custom;
1373 WINPR_ASSERT(custom);
1374
1375 const proxyConfig* cfg = custom->config;
1376 WINPR_ASSERT(cfg);
1377
1378 pf_utils_channel_mode rc = pf_utils_get_channel_mode(cfg, channel->channel_name);
1379 switch (rc)
1380 {
1381
1382 case PF_UTILS_CHANNEL_INTERCEPT:
1383 case PF_UTILS_CHANNEL_PASSTHROUGH:
1384 accept = TRUE;
1385 break;
1386 case PF_UTILS_CHANNEL_BLOCK:
1387 default:
1388 accept = FALSE;
1389 break;
1390 }
1391
1392 if (accept)
1393 {
1394 if (strncmp(RDPGFX_DVC_CHANNEL_NAME, channel->channel_name,
1395 sizeof(RDPGFX_DVC_CHANNEL_NAME)) == 0)
1396 accept = cfg->GFX;
1397 else if (strncmp(RDPSND_DVC_CHANNEL_NAME, channel->channel_name,
1398 sizeof(RDPSND_DVC_CHANNEL_NAME)) == 0)
1399 accept = cfg->AudioOutput;
1400 else if (strncmp(RDPSND_LOSSY_DVC_CHANNEL_NAME, channel->channel_name,
1401 sizeof(RDPSND_LOSSY_DVC_CHANNEL_NAME)) == 0)
1402 accept = cfg->AudioOutput;
1403 else if (strncmp(AUDIN_DVC_CHANNEL_NAME, channel->channel_name,
1404 sizeof(AUDIN_DVC_CHANNEL_NAME)) == 0)
1405 accept = cfg->AudioInput;
1406 else if (strncmp(RDPEI_DVC_CHANNEL_NAME, channel->channel_name,
1407 sizeof(RDPEI_DVC_CHANNEL_NAME)) == 0)
1408 accept = cfg->Multitouch;
1409 else if (strncmp(TSMF_DVC_CHANNEL_NAME, channel->channel_name,
1410 sizeof(TSMF_DVC_CHANNEL_NAME)) == 0)
1411 accept = cfg->VideoRedirection;
1412 else if (strncmp(VIDEO_CONTROL_DVC_CHANNEL_NAME, channel->channel_name,
1413 sizeof(VIDEO_CONTROL_DVC_CHANNEL_NAME)) == 0)
1414 accept = cfg->VideoRedirection;
1415 else if (strncmp(VIDEO_DATA_DVC_CHANNEL_NAME, channel->channel_name,
1416 sizeof(VIDEO_DATA_DVC_CHANNEL_NAME)) == 0)
1417 accept = cfg->VideoRedirection;
1418 else if (strncmp(RDPECAM_DVC_CHANNEL_NAME, channel->channel_name,
1419 sizeof(RDPECAM_DVC_CHANNEL_NAME)) == 0)
1420 accept = cfg->CameraRedirection;
1421 }
1422
1423 WLog_DBG(TAG, "%s [0x%04" PRIx16 "]: %s", channel->channel_name, channel->channel_id,
1424 boolstr(accept));
1425 return accept;
1426}
1427
1428WINPR_ATTR_NODISCARD
1429static BOOL config_plugin_channel_create(proxyPlugin* plugin, WINPR_ATTR_UNUSED proxyData* pdata,
1430 void* param)
1431{
1432 BOOL accept = 0;
1433 const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param);
1434
1435 WINPR_ASSERT(plugin);
1436 WINPR_ASSERT(pdata);
1437 WINPR_ASSERT(channel);
1438
1439 const struct config_plugin_data* custom = plugin->custom;
1440 WINPR_ASSERT(custom);
1441
1442 const proxyConfig* cfg = custom->config;
1443 WINPR_ASSERT(cfg);
1444
1445 pf_utils_channel_mode rc = pf_utils_get_channel_mode(cfg, channel->channel_name);
1446 switch (rc)
1447 {
1448 case PF_UTILS_CHANNEL_INTERCEPT:
1449 case PF_UTILS_CHANNEL_PASSTHROUGH:
1450 accept = TRUE;
1451 break;
1452 case PF_UTILS_CHANNEL_BLOCK:
1453 default:
1454 accept = FALSE;
1455 break;
1456 }
1457 if (accept)
1458 {
1459 if (strncmp(CLIPRDR_SVC_CHANNEL_NAME, channel->channel_name,
1460 sizeof(CLIPRDR_SVC_CHANNEL_NAME)) == 0)
1461 accept = cfg->Clipboard;
1462 else if (strncmp(RDPSND_CHANNEL_NAME, channel->channel_name, sizeof(RDPSND_CHANNEL_NAME)) ==
1463 0)
1464 accept = cfg->AudioOutput;
1465 else if (strncmp(RDPDR_SVC_CHANNEL_NAME, channel->channel_name,
1466 sizeof(RDPDR_SVC_CHANNEL_NAME)) == 0)
1467 accept = cfg->DeviceRedirection;
1468 else if (strncmp(DISP_DVC_CHANNEL_NAME, channel->channel_name,
1469 sizeof(DISP_DVC_CHANNEL_NAME)) == 0)
1470 accept = cfg->DisplayControl;
1471 else if (strncmp(RAIL_SVC_CHANNEL_NAME, channel->channel_name,
1472 sizeof(RAIL_SVC_CHANNEL_NAME)) == 0)
1473 accept = cfg->RemoteApp;
1474 }
1475
1476 WLog_DBG(TAG, "%s [static]: %s", channel->channel_name, boolstr(accept));
1477 return accept;
1478}
1479
1480BOOL pf_config_plugin(proxyPluginsManager* plugins_manager, void* userdata)
1481{
1482 struct config_plugin_data* custom = nullptr;
1483 proxyPlugin plugin = WINPR_C_ARRAY_INIT;
1484
1485 plugin.name = config_plugin_name;
1486 plugin.description = config_plugin_desc;
1487 plugin.PluginUnload = config_plugin_unload;
1488
1489 plugin.KeyboardEvent = config_plugin_keyboard_event;
1490 plugin.UnicodeEvent = config_plugin_unicode_event;
1491 plugin.MouseEvent = config_plugin_mouse_event;
1492 plugin.MouseExEvent = config_plugin_mouse_ex_event;
1493 plugin.ClientChannelData = config_plugin_client_channel_data;
1494 plugin.ServerChannelData = config_plugin_server_channel_data;
1495 plugin.ChannelCreate = config_plugin_channel_create;
1496 plugin.DynamicChannelCreate = config_plugin_dynamic_channel_create;
1497 plugin.userdata = userdata;
1498
1499 custom = calloc(1, sizeof(struct config_plugin_data));
1500 if (!custom)
1501 return FALSE;
1502
1503 custom->mgr = plugins_manager;
1504 custom->config = userdata;
1505
1506 plugin.custom = custom;
1507 plugin.userdata = userdata;
1508
1509 return plugins_manager->RegisterPlugin(plugins_manager, &plugin);
1510}
1511
1512const char* pf_config_get(const proxyConfig* config, const char* section, const char* key)
1513{
1514 WINPR_ASSERT(config);
1515 WINPR_ASSERT(config->ini);
1516 WINPR_ASSERT(section);
1517 WINPR_ASSERT(key);
1518
1519 return IniFile_GetKeyValueString(config->ini, section, key);
1520}
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:887
void pf_server_config_free(proxyConfig *config)
pf_server_config_free Releases all resources associated with proxyConfig
Definition pf_config.c:1029
void pf_server_config_print(const proxyConfig *config)
pf_server_config_print Print the configuration to stdout
Definition pf_config.c:942
const char ** pf_config_modules(const proxyConfig *config)
pf_config_modules
Definition pf_config.c:1079
const char * pf_config_required_plugin(const proxyConfig *config, size_t index)
pf_config_required_plugin
Definition pf_config.c:1064
size_t pf_config_modules_count(const proxyConfig *config)
pf_config_modules_count
Definition pf_config.c:1073
BOOL pf_config_clone(proxyConfig **dst, const proxyConfig *config)
pf_config_clone Create a copy of the configuration
Definition pf_config.c:1132
size_t pf_config_required_plugins_count(const proxyConfig *config)
pf_config_required_plugins_count
Definition pf_config.c:1058
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
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:912
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:1480
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:1512