FreeRDP
Loading...
Searching...
No Matches
assistance.c
1
20#include <freerdp/config.h>
21
22#include <errno.h>
23
24#include <winpr/wtypes.h>
25#include <winpr/collections.h>
26#include <winpr/string.h>
27#include <winpr/crt.h>
28#include <winpr/crypto.h>
29#include <winpr/print.h>
30#include <winpr/windows.h>
31#include <winpr/ssl.h>
32#include <winpr/file.h>
33
34#include <freerdp/log.h>
35#include <freerdp/client/file.h>
36#include <freerdp/client/cmdline.h>
37
38#include <freerdp/assistance.h>
39
40#include "../core/settings.h"
41
42#define TAG FREERDP_TAG("common")
43
44struct rdp_assistance_file
45{
46 UINT32 Type;
47
48 char* Username;
49 char* LHTicket;
50 char* RCTicket;
51 char* PassStub;
52 UINT32 DtStart;
53 UINT32 DtLength;
54 BOOL LowSpeed;
55 BOOL RCTicketEncrypted;
56
57 char* ConnectionString1;
58 char* ConnectionString2;
59
60 BYTE* EncryptedPassStub;
61 size_t EncryptedPassStubLength;
62
63 BYTE* EncryptedLHTicket;
64 size_t EncryptedLHTicketLength;
65
66 wArrayList* MachineAddresses;
67 wArrayList* MachinePorts;
68 wArrayList* MachineUris;
69
70 char* RASessionId;
71 char* RASpecificParams;
72 char* RASpecificParams2;
73
74 char* filename;
75 char* password;
76};
77
78WINPR_ATTR_NODISCARD
79static const char* strrstr(const char* haystack, size_t len, const char* needle)
80{
81 if (*needle == '\0')
82 return haystack;
83
84 const char* result = nullptr;
85 for (;;)
86 {
87 const char* p = strstr(haystack, needle);
88 if (p == nullptr)
89 break;
90 if (p > haystack + len)
91 return nullptr;
92
93 result = p;
94 haystack = p + 1;
95 }
96
97 return result;
98}
99
100WINPR_ATTR_NODISCARD
101static BOOL update_option(char** opt, const char* val, size_t len)
102{
103 WINPR_ASSERT(opt);
104 free(*opt);
105 *opt = nullptr;
106
107 if (!val && (len != 0))
108 return FALSE;
109 else if (!val && (len == 0))
110 return TRUE;
111 *opt = strndup(val, len);
112 return *opt != nullptr;
113}
114
115WINPR_ATTR_NODISCARD
116static BOOL update_name(rdpAssistanceFile* file, const char* name)
117{
118 WINPR_ASSERT(file);
119
120 if (!name)
121 {
122 WLog_ERR(TAG, "ASSISTANCE file %s invalid name", name);
123 return FALSE;
124 }
125
126 free(file->filename);
127 file->filename = _strdup(name);
128 return file->filename != nullptr;
129}
130
131WINPR_ATTR_NODISCARD
132static BOOL update_password(rdpAssistanceFile* file, const char* password)
133{
134 WINPR_ASSERT(file);
135 free(file->password);
136 file->password = nullptr;
137 if (!password)
138 return TRUE;
139 file->password = _strdup(password);
140 return file->password != nullptr;
141}
142
143WINPR_ATTR_NODISCARD
144static BOOL update_connectionstring2_nocopy(rdpAssistanceFile* file, char* str)
145{
146 WINPR_ASSERT(file);
147 free(file->ConnectionString2);
148 file->ConnectionString2 = nullptr;
149 if (!str)
150 return TRUE;
151 file->ConnectionString2 = str;
152 return file->ConnectionString2 != nullptr;
153}
154
155WINPR_ATTR_NODISCARD
156static BOOL update_connectionstring2(rdpAssistanceFile* file, const char* str, size_t len)
157{
158 char* strc = nullptr;
159 if (!str && (len != 0))
160 return FALSE;
161
162 if (str && (len > 0))
163 {
164 strc = strndup(str, len);
165 if (!strc)
166 return FALSE;
167 }
168 return update_connectionstring2_nocopy(file, strc);
169}
170
171WINPR_ATTR_NODISCARD
172static BOOL update_connectionstring2_wchar(rdpAssistanceFile* file, const WCHAR* str, size_t len)
173{
174 char* strc = nullptr;
175
176 if (!str && (len != 0))
177 return FALSE;
178
179 if (str && (len > 0))
180 {
181 strc = ConvertWCharNToUtf8Alloc(str, len, nullptr);
182 if (!strc)
183 return FALSE;
184 }
185 return update_connectionstring2_nocopy(file, strc);
186}
187
223WINPR_ATTR_NODISCARD
224static BOOL freerdp_assistance_crypt_derive_key_sha1(const BYTE* hash, size_t hashLength, BYTE* key,
225 size_t keyLength)
226{
227 BOOL rc = FALSE;
228 BYTE pad1[64] = WINPR_C_ARRAY_INIT;
229 BYTE pad2[64] = WINPR_C_ARRAY_INIT;
230
231 if (hashLength == 0)
232 return FALSE;
233
234 memset(pad1, 0x36, sizeof(pad1));
235 memset(pad2, 0x5C, sizeof(pad2));
236
237 for (size_t i = 0; i < hashLength; i++)
238 {
239 pad1[i] ^= hash[i];
240 pad2[i] ^= hash[i];
241 }
242
243 BYTE* buffer = (BYTE*)calloc(hashLength, 2);
244
245 if (!buffer)
246 goto fail;
247
248 if (!winpr_Digest(WINPR_MD_SHA1, pad1, 64, buffer, hashLength))
249 goto fail;
250
251 if (!winpr_Digest(WINPR_MD_SHA1, pad2, 64, &buffer[hashLength], hashLength))
252 goto fail;
253
254 CopyMemory(key, buffer, keyLength);
255 rc = TRUE;
256fail:
257 free(buffer);
258 return rc;
259}
260
261WINPR_ATTR_NODISCARD
262static BOOL append_address_to_list(wArrayList* MachineAddresses, const char* str, size_t len)
263{
264 char* copy = nullptr;
265 if (len > 0)
266 copy = strndup(str, len);
267 if (!copy)
268 return FALSE;
269
270 const BOOL rc = ArrayList_Append(MachineAddresses, copy);
271 if (!rc)
272 free(copy);
273 // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): ArrayList_Append takes ownership of copy
274 return rc;
275}
276
277WINPR_ATTR_NODISCARD
278static BOOL append_address(rdpAssistanceFile* file, const char* host, const char* port)
279{
280 WINPR_ASSERT(file);
281
282 errno = 0;
283 unsigned long p = strtoul(port, nullptr, 0);
284
285 if ((errno != 0) || (p == 0) || (p > UINT16_MAX))
286 {
287 WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 invalid port value %s",
288 port);
289 return FALSE;
290 }
291
292 if (!append_address_to_list(file->MachineAddresses, host, host ? strlen(host) : 0))
293 return FALSE;
294 return ArrayList_Append(file->MachinePorts, (void*)(uintptr_t)p);
295}
296
297WINPR_ATTR_NODISCARD
298static BOOL freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list)
299{
300 WINPR_ASSERT(file);
301
302 WLog_DBG(TAG, "freerdp_assistance_parse_address_list list=%s", list);
303
304 BOOL rc = FALSE;
305
306 if (!list)
307 return FALSE;
308
309 char* strp = list;
310 char* s = ";";
311
312 // get the first token
313 char* saveptr = nullptr;
314 char* token = strtok_s(strp, s, &saveptr);
315
316 // walk through other tokens
317 while (token != nullptr)
318 {
319 char* port = strchr(token, ':');
320 if (!port)
321 goto out;
322 *port = '\0';
323 port++;
324
325 if (!append_address(file, token, port))
326 goto out;
327
328 token = strtok_s(nullptr, s, &saveptr);
329 }
330 rc = TRUE;
331out:
332 return rc;
333}
334
335WINPR_ATTR_NODISCARD
336static BOOL freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file)
337{
338 char* tokens[8] = WINPR_C_ARRAY_INIT;
339 BOOL rc = FALSE;
340
341 WINPR_ASSERT(file);
342
343 if (!file->RCTicket)
344 return FALSE;
345
350 char* str = _strdup(file->RCTicket);
351
352 if (!str)
353 goto error;
354
355 {
356 const size_t length = strlen(str);
357
358 {
359 int count = 1;
360 for (size_t i = 0; i < length; i++)
361 {
362 if (str[i] == ',')
363 count++;
364 }
365
366 if (count != 8)
367 goto error;
368 }
369
370 {
371 size_t count = 0;
372 tokens[count++] = str;
373
374 for (size_t i = 0; i < length; i++)
375 {
376 if (str[i] == ',')
377 {
378 str[i] = '\0';
379 tokens[count++] = &str[i + 1];
380 }
381 }
382 }
383 }
384
385 if (strcmp(tokens[0], "65538") != 0)
386 goto error;
387
388 if (strcmp(tokens[1], "1") != 0)
389 goto error;
390
391 if (strcmp(tokens[3], "*") != 0)
392 goto error;
393
394 if (strcmp(tokens[5], "*") != 0)
395 goto error;
396
397 if (strcmp(tokens[6], "*") != 0)
398 goto error;
399
400 file->RASessionId = _strdup(tokens[4]);
401
402 if (!file->RASessionId)
403 goto error;
404
405 file->RASpecificParams = _strdup(tokens[7]);
406
407 if (!file->RASpecificParams)
408 goto error;
409
410 if (!freerdp_assistance_parse_address_list(file, tokens[2]))
411 goto error;
412
413 rc = TRUE;
414error:
415 free(str);
416 return rc;
417}
418
431WINPR_ATTR_NODISCARD
432static BOOL freerdp_assistance_parse_attr(const char** opt, size_t* plength, const char* key,
433 const char* tag)
434{
435 WINPR_ASSERT(opt);
436 WINPR_ASSERT(plength);
437 WINPR_ASSERT(key);
438
439 *opt = nullptr;
440 *plength = 0;
441 if (!tag)
442 return FALSE;
443
444 char bkey[128] = WINPR_C_ARRAY_INIT;
445 const int rc = _snprintf(bkey, sizeof(bkey), "%s=\"", key);
446 WINPR_ASSERT(rc > 0);
447 WINPR_ASSERT((size_t)rc < sizeof(bkey));
448 if ((rc <= 0) || ((size_t)rc >= sizeof(bkey)))
449 return FALSE;
450
451 const char* p = strstr(tag, bkey);
452 if (!p)
453 return TRUE;
454
455 p += strlen(bkey);
456 const char* q = strchr(p, '"');
457
458 if (!q)
459 {
460 WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 invalid field '%s=%s'",
461 key, p);
462 return FALSE;
463 }
464
465 if (p > q)
466 {
467 WLog_ERR(TAG,
468 "Failed to parse ASSISTANCE file: ConnectionString2 invalid field "
469 "order for '%s'",
470 key);
471 return FALSE;
472 }
473 const size_t length = WINPR_ASSERTING_INT_CAST(size_t, q - p);
474 *opt = p;
475 *plength = length;
476
477 return TRUE;
478}
479
480WINPR_ATTR_NODISCARD
481static BOOL freerdp_assistance_parse_attr_str(char** opt, const char* key, const char* tag)
482{
483 const char* copt = nullptr;
484 size_t size = 0;
485 if (!freerdp_assistance_parse_attr(&copt, &size, key, tag))
486 return FALSE;
487 return update_option(opt, copt, size);
488}
489
490WINPR_ATTR_NODISCARD
491static BOOL freerdp_assistance_parse_attr_bool(BOOL* opt, const char* key, const char* tag)
492{
493 const char* copt = nullptr;
494 size_t size = 0;
495
496 WINPR_ASSERT(opt);
497 *opt = FALSE;
498
499 if (!freerdp_assistance_parse_attr(&copt, &size, key, tag))
500 return FALSE;
501 if (size != 1)
502 return TRUE;
503
504 *opt = (copt[0] == '1');
505 return TRUE;
506}
507
508WINPR_ATTR_NODISCARD
509static BOOL freerdp_assistance_parse_attr_uint32(UINT32* opt, const char* key, const char* tag)
510{
511 const char* copt = nullptr;
512 size_t size = 0;
513
514 WINPR_ASSERT(opt);
515 *opt = 0;
516
517 if (!freerdp_assistance_parse_attr(&copt, &size, key, tag))
518 return FALSE;
519
520 char buffer[64] = WINPR_C_ARRAY_INIT;
521 if ((!copt && (size > 0)) || (size >= sizeof(buffer)))
522 {
523 WLog_WARN(TAG, "Invalid UINT32 string '%s' [%" PRIuz "]", copt, size);
524 return FALSE;
525 }
526
527 if (size > 0)
528 strncpy(buffer, copt, size);
529
530 errno = 0;
531 unsigned long val = strtoul(buffer, nullptr, 0);
532
533 if ((errno != 0) || (val > UINT32_MAX))
534 {
535 WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid value %s", buffer);
536 return FALSE;
537 }
538
539 *opt = (UINT32)val;
540
541 return TRUE;
542}
543
544WINPR_ATTR_NODISCARD
545static char* freerdp_assistance_contains_element(char* input, size_t ilen, const char* key,
546 size_t* plen, char** pdata, size_t* pdlen)
547{
548 WINPR_ASSERT(input);
549 WINPR_ASSERT(key);
550 WINPR_ASSERT(plen);
551
552 char bkey[128] = WINPR_C_ARRAY_INIT;
553 const int rc = _snprintf(bkey, sizeof(bkey), "<%s", key);
554 WINPR_ASSERT(rc > 0);
555 WINPR_ASSERT((size_t)rc < sizeof(bkey));
556 if ((rc < 0) || ((size_t)rc >= sizeof(bkey)))
557 return nullptr;
558
559 char* tag = winpr_strnstr(input, bkey, ilen);
560 if (!tag)
561 return nullptr;
562
563 const intptr_t tdiff = (tag - input);
564 WINPR_ASSERT(tdiff >= 0);
565 const size_t utdiff = WINPR_ASSERTING_INT_CAST(size_t, tdiff);
566 WINPR_ASSERT(utdiff <= ilen);
567 const size_t tlen = ilen - utdiff;
568 const size_t texpect = strnlen(bkey, sizeof(bkey));
569 if (tlen <= texpect)
570 return nullptr;
571
572 char* data = tag + texpect;
573
574 /* Ensure there is a valid delimiter following our token */
575 switch (data[0])
576 {
577 case '>':
578 case '/':
579 case ' ':
580 case '\t':
581 break;
582 default:
583 WLog_ERR(TAG,
584 "Failed to parse ASSISTANCE file: ConnectionString2 missing delimiter after "
585 "field %s",
586 bkey);
587 return nullptr;
588 }
589
590 const char* start = winpr_strnstr(tag, ">", tlen);
591
592 if (!start || (start > input + ilen))
593 {
594 WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 missing field %s", bkey);
595 return nullptr;
596 }
597
598 const char* end = start;
599 const char* dend = start - 1;
600 if (*dend != '/')
601 {
602 char ekey[128] = WINPR_C_ARRAY_INIT;
603 const int erc = _snprintf(ekey, sizeof(ekey), "</%s>", key);
604 WINPR_ASSERT(erc > 0);
605 WINPR_ASSERT((size_t)erc < sizeof(ekey));
606 if ((erc <= 0) || ((size_t)erc >= sizeof(ekey)))
607 return nullptr;
608 const size_t offset = WINPR_ASSERTING_INT_CAST(size_t, start - tag);
609 dend = end = strrstr(start, ilen - offset, ekey);
610 if (end)
611 end += strnlen(ekey, sizeof(ekey));
612 }
613
614 if (!end)
615 {
616 WLog_ERR(TAG,
617 "Failed to parse ASSISTANCE file: ConnectionString2 missing end tag for field %s",
618 key);
619 return nullptr;
620 }
621 if (plen)
622 *plen = WINPR_ASSERTING_INT_CAST(size_t, end - tag);
623
624 if (pdata)
625 *pdata = data;
626 if (pdlen)
627 *pdlen = WINPR_ASSERTING_INT_CAST(size_t, dend - data);
628 return tag;
629}
630
636WINPR_ATTR_NODISCARD
637static BOOL freerdp_assistance_consume_input_and_get_element(char* input, size_t ilen,
638 const char* key, char** element,
639 size_t* elen)
640{
641 WINPR_ASSERT(input);
642 WINPR_ASSERT(key);
643 WINPR_ASSERT(element);
644 WINPR_ASSERT(elen);
645
646 size_t len = 0;
647 size_t dlen = 0;
648 char* data = nullptr;
649 char* tag = freerdp_assistance_contains_element(input, ilen, key, &len, &data, &dlen);
650 if (!tag)
651 return FALSE;
652
653 char* end = data + dlen;
654 *tag = '\0';
655 *end = '\0';
656 *element = data;
657 *elen = dlen + 1;
658 return TRUE;
659}
660
661WINPR_ATTR_NODISCARD
662static BOOL freerdp_assistance_get_element(char* input, size_t ilen, const char* key,
663 char** element, size_t* elen)
664{
665 WINPR_ASSERT(input);
666 WINPR_ASSERT(key);
667 WINPR_ASSERT(element);
668 WINPR_ASSERT(elen);
669
670 size_t len = 0;
671 size_t dlen = 0;
672 char* data = nullptr;
673 char* tag = freerdp_assistance_contains_element(input, ilen, key, &len, &data, &dlen);
674 if (!tag)
675 return FALSE;
676
677 if (tag + len > input + ilen)
678 return FALSE;
679
680 char* end = tag + len;
681 *element = data;
682 *elen = WINPR_ASSERTING_INT_CAST(size_t, end - data + 1);
683 return TRUE;
684}
685
686WINPR_ATTR_NODISCARD
687static BOOL freerdp_assistance_parse_all_elements_of(rdpAssistanceFile* file, char* data,
688 size_t len, const char* key,
689 BOOL (*fkt)(rdpAssistanceFile* file,
690 char* data, size_t len))
691{
692 char* val = nullptr;
693 size_t vlen = 0;
694
695 while (freerdp_assistance_get_element(data, len, key, &val, &vlen))
696 {
697 if (vlen > len)
698 return FALSE;
699 data = val + vlen;
700 len = strnlen(data, len - vlen);
701 if (vlen > 0)
702 {
703 val[vlen - 1] = '\0';
704
705 if (!fkt(file, val, vlen))
706 return FALSE;
707 }
708 }
709
710 return TRUE;
711}
712
713WINPR_ATTR_NODISCARD
714static BOOL freerdp_assistance_parse_all_elements_of_l(rdpAssistanceFile* file, char* data,
715 WINPR_ATTR_UNUSED size_t len)
716{
717 UINT32 p = 0;
718 const char* n = nullptr;
719 const char* u = nullptr;
720 size_t nlen = 0;
721 size_t ulen = 0;
722 if (!freerdp_assistance_parse_attr_uint32(&p, "P", data))
723 return FALSE;
724 if (!freerdp_assistance_parse_attr(&n, &nlen, "N", data))
725 return FALSE;
726 if (!freerdp_assistance_parse_attr(&u, &ulen, "U", data))
727 return FALSE;
728
729 if (n && (nlen > 0))
730 {
731 if (!append_address_to_list(file->MachineAddresses, n, nlen))
732 return FALSE;
733 if (!ArrayList_Append(file->MachinePorts, (void*)(uintptr_t)p))
734 return FALSE;
735 }
736 if (u && (ulen > 0))
737 {
738 if (!append_address_to_list(file->MachineAddresses, u, ulen))
739 return FALSE;
740 if (!ArrayList_Append(file->MachinePorts, (void*)(uintptr_t)p))
741 return FALSE;
742 }
743 return TRUE;
744}
745
746WINPR_ATTR_NODISCARD
747static BOOL freerdp_assistance_parse_all_elements_of_t(rdpAssistanceFile* file, char* data,
748 size_t len)
749{
750 UINT32 id = 0;
751 UINT32 sid = 0;
752 if (!freerdp_assistance_parse_attr_uint32(&id, "ID", data))
753 return FALSE;
754 if (!freerdp_assistance_parse_attr_uint32(&sid, "SID", data))
755 return FALSE;
756 WLog_DBG(TAG, "transport id=%" PRIu32 ", sid=%" PRIu32, id, sid);
757 return freerdp_assistance_parse_all_elements_of(file, data, len, "L",
758 freerdp_assistance_parse_all_elements_of_l);
759}
760
761WINPR_ATTR_NODISCARD
762static BOOL freerdp_assistance_parse_all_elements_of_c(rdpAssistanceFile* file, char* data,
763 size_t len)
764{
765 return freerdp_assistance_parse_all_elements_of(file, data, len, "T",
766 freerdp_assistance_parse_all_elements_of_t);
767}
768
769WINPR_ATTR_NODISCARD
770static BOOL freerdp_assistance_parse_find_elements_of_c(rdpAssistanceFile* file, char* data,
771 size_t len)
772{
773 return freerdp_assistance_parse_all_elements_of(file, data, len, "C",
774 freerdp_assistance_parse_all_elements_of_c);
775}
776
777WINPR_ATTR_NODISCARD
778static BOOL freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file)
779{
780 BOOL rc = FALSE;
781
782 WINPR_ASSERT(file);
783
784 if (!file->ConnectionString2)
785 return FALSE;
786
787 char* str = _strdup(file->ConnectionString2);
788 if (!str)
789 goto out_fail;
790 const size_t slen = strlen(str);
791
792 {
793 char* e = nullptr;
794 size_t elen = 0;
795 if (!freerdp_assistance_consume_input_and_get_element(str, slen, "E", &e, &elen))
796 goto out_fail;
797
798 if (!e || (elen == 0))
799 goto out_fail;
800 {
801 char* a = nullptr;
802 size_t alen = 0;
803 if (!freerdp_assistance_get_element(e, elen, "A", &a, &alen))
804 goto out_fail;
805
806 if (!a || (alen == 0))
807 goto out_fail;
808
809 if (!freerdp_assistance_parse_find_elements_of_c(file, e, elen))
810 goto out_fail;
811
812 /* '\0' terminate the detected XML elements so
813 * the parser can continue with terminated strings
814 */
815 a[alen] = '\0';
816
817 if (!freerdp_assistance_parse_attr_str(&file->RASpecificParams, "KH", a))
818 goto out_fail;
819
820 if (!freerdp_assistance_parse_attr_str(&file->RASpecificParams2, "KH2", a))
821 goto out_fail;
822
823 if (!freerdp_assistance_parse_attr_str(&file->RASessionId, "ID", a))
824 goto out_fail;
825 }
826 }
827 rc = TRUE;
828out_fail:
829 free(str);
830 return rc;
831}
832
833char* freerdp_assistance_construct_expert_blob(const char* name, const char* pass)
834{
835 if (!name || !pass)
836 return nullptr;
837
838 const size_t nameLength = strlen(name) + strlen("NAME=");
839 const size_t passLength = strlen(pass) + strlen("PASS=");
840 const size_t size = nameLength + passLength + 64;
841 char* ExpertBlob = (char*)calloc(1, size);
842
843 if (!ExpertBlob)
844 return nullptr;
845
846 (void)sprintf_s(ExpertBlob, size, "%" PRIuz ";NAME=%s%" PRIuz ";PASS=%s", nameLength, name,
847 passLength, pass);
848 return ExpertBlob;
849}
850
851char* freerdp_assistance_generate_pass_stub(WINPR_ATTR_UNUSED DWORD flags)
852{
853 UINT32 nums[14] = WINPR_C_ARRAY_INIT;
854 const char set1[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
855 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
856 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
857 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
858 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '_' };
859 const char set2[12] = { '!', '@', '#', '$', '&', '^', '*', '(', ')', '-', '+', '=' };
860 const char set3[10] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
861 const char set4[26] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
862 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
863 const char set5[26] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
864 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
865 char* passStub = calloc(15, sizeof(char));
866
867 if (!passStub)
868 return nullptr;
869
881 if (winpr_RAND(nums, sizeof(nums)) < 0)
882 {
883 free(passStub);
884 return nullptr;
885 }
886
887 passStub[0] = set1[nums[0] % sizeof(set1)]; /* character 0 */
888 passStub[1] = set2[nums[1] % sizeof(set2)]; /* character 1 */
889 passStub[2] = set3[nums[2] % sizeof(set3)]; /* character 2 */
890 passStub[3] = set4[nums[3] % sizeof(set4)]; /* character 3 */
891 passStub[4] = set5[nums[4] % sizeof(set5)]; /* character 4 */
892
893 for (size_t x = 5; x < ARRAYSIZE(nums); x++)
894 passStub[x] = set1[nums[x] % sizeof(set1)]; /* character 5 - 13 */
895 return passStub;
896}
897
898BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub,
899 size_t* pEncryptedSize)
900{
901 BOOL rc = 0;
902 size_t cbPasswordW = 0;
903 size_t cbPassStubW = 0;
904 BYTE PasswordHash[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
905 WINPR_RC4_CTX* rc4Ctx = nullptr;
906 BYTE* pbIn = nullptr;
907 BYTE* pbOut = nullptr;
908 BYTE* res = nullptr;
909 WCHAR* PasswordW = ConvertUtf8ToWCharAlloc(password, &cbPasswordW);
910 WCHAR* PassStubW = ConvertUtf8ToWCharAlloc(passStub, &cbPassStubW);
911
912 cbPasswordW = cbPasswordW * sizeof(WCHAR);
913 cbPassStubW = cbPassStubW * sizeof(WCHAR);
914 const size_t EncryptedSize = cbPassStubW + 4;
915
916 if (!PasswordW || !PassStubW)
917 goto fail;
918
919 if (!winpr_Digest(WINPR_MD_MD5, (BYTE*)PasswordW, cbPasswordW, (BYTE*)PasswordHash,
920 sizeof(PasswordHash)))
921 goto fail;
922
923 pbIn = (BYTE*)calloc(1, EncryptedSize);
924 pbOut = (BYTE*)calloc(1, EncryptedSize);
925
926 if (!pbIn || !pbOut)
927 goto fail;
928
929 WINPR_ASSERT(cbPasswordW <= UINT32_MAX);
930 winpr_Data_Write_UINT32(pbIn, (UINT32)cbPassStubW);
931 CopyMemory(&pbIn[4], PassStubW, cbPassStubW);
932 rc4Ctx = winpr_RC4_New(PasswordHash, sizeof(PasswordHash));
933
934 if (!rc4Ctx)
935 {
936 WLog_ERR(TAG, "winpr_Cipher_New failure");
937 goto fail;
938 }
939
940 rc = winpr_RC4_Update(rc4Ctx, EncryptedSize, pbIn, pbOut);
941
942 if (!rc)
943 {
944 WLog_ERR(TAG, "winpr_Cipher_Update failure");
945 goto fail;
946 }
947 res = pbOut;
948fail:
949 winpr_RC4_Free(rc4Ctx);
950 free(PasswordW);
951 free(PassStubW);
952 free(pbIn);
953 if (!res)
954 free(pbOut);
955 else
956 *pEncryptedSize = EncryptedSize;
957 return res;
958}
959
960WINPR_ATTR_NODISCARD
961static BOOL freerdp_assistance_decrypt2(rdpAssistanceFile* file)
962{
963 BOOL rc = FALSE;
964 int status = 0;
965 size_t cbPasswordW = 0;
966 size_t cchOutW = 0;
967 WINPR_CIPHER_CTX* aesDec = nullptr;
968 WCHAR* PasswordW = nullptr;
969 BYTE* pbIn = nullptr;
970 BYTE* pbOut = nullptr;
971 size_t cbOut = 0;
972 size_t cbIn = 0;
973 size_t cbFinal = 0;
974 BYTE DerivedKey[WINPR_AES_BLOCK_SIZE] = WINPR_C_ARRAY_INIT;
975 BYTE InitializationVector[WINPR_AES_BLOCK_SIZE] = WINPR_C_ARRAY_INIT;
976 BYTE PasswordHash[WINPR_SHA1_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
977
978 WINPR_ASSERT(file);
979
980 if (!file->password)
981 return FALSE;
982
983 PasswordW = ConvertUtf8ToWCharAlloc(file->password, &cbPasswordW);
984 if (!PasswordW)
985 {
986 WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Conversion from UCS2 to UTF8 failed");
987 return FALSE;
988 }
989
990 cbPasswordW = cbPasswordW * sizeof(WCHAR);
991
992 if (!winpr_Digest(WINPR_MD_SHA1, (BYTE*)PasswordW, cbPasswordW, PasswordHash,
993 sizeof(PasswordHash)))
994 goto fail;
995
996 if (!freerdp_assistance_crypt_derive_key_sha1(PasswordHash, sizeof(PasswordHash), DerivedKey,
997 sizeof(DerivedKey)))
998 goto fail;
999
1000 aesDec =
1001 winpr_Cipher_NewEx(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, DerivedKey, sizeof(DerivedKey),
1002 InitializationVector, sizeof(InitializationVector));
1003
1004 if (!aesDec)
1005 goto fail;
1006
1007 cbOut = cbFinal = 0;
1008 cbIn = file->EncryptedLHTicketLength;
1009 pbIn = file->EncryptedLHTicket;
1010 pbOut = (BYTE*)calloc(1, cbIn + WINPR_AES_BLOCK_SIZE + 2);
1011
1012 if (!pbOut)
1013 goto fail;
1014
1015 if (!winpr_Cipher_Update(aesDec, pbIn, cbIn, pbOut, &cbOut))
1016 goto fail;
1017
1018 if (!winpr_Cipher_Final(aesDec, pbOut + cbOut, &cbFinal))
1019 {
1020 WLog_ERR(TAG, "winpr_Cipher_Final failure");
1021 goto fail;
1022 }
1023
1024 cbOut += cbFinal;
1025 cbFinal = 0;
1026
1027 union
1028 {
1029 const WCHAR* wc;
1030 const BYTE* b;
1031 } cnv;
1032
1033 cnv.b = pbOut;
1034 cchOutW = cbOut / sizeof(WCHAR);
1035
1036 if (!update_connectionstring2_wchar(file, cnv.wc, cchOutW))
1037 {
1038 WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Conversion from UCS2 to UTF8 failed");
1039 goto fail;
1040 }
1041
1042 if (!freerdp_assistance_parse_connection_string2(file))
1043 goto fail;
1044
1045 rc = TRUE;
1046fail:
1047 winpr_Cipher_Free(aesDec);
1048 free(PasswordW);
1049 free(pbOut);
1050 WLog_DBG(TAG, "freerdp_assistance_parse_connection_string2: %d", status);
1051 return rc;
1052}
1053
1054BYTE* freerdp_assistance_hex_string_to_bin(const void* str, size_t* size)
1055{
1056 BYTE* buffer = nullptr;
1057 if (!str || !size)
1058 return nullptr;
1059 *size = 0;
1060 const size_t length = strlen(str);
1061 buffer = calloc(length, sizeof(BYTE));
1062 if (!buffer)
1063 return nullptr;
1064 const size_t rc = winpr_HexStringToBinBuffer(str, length, buffer, length);
1065 if (rc == 0)
1066 {
1067 free(buffer);
1068 return nullptr;
1069 }
1070 *size = rc;
1071 return buffer;
1072}
1073
1074char* freerdp_assistance_bin_to_hex_string(const void* data, size_t size)
1075{
1076 return winpr_BinToHexString(data, size, FALSE);
1077}
1078
1079WINPR_ATTR_NODISCARD
1080static int freerdp_assistance_parse_uploadinfo(rdpAssistanceFile* file, char* uploadinfo,
1081 size_t uploadinfosize)
1082{
1083 const char escalated[9] = { 'E', 's', 'c', 'a', 'l', 'a', 't', 'e', 'd' };
1084 const size_t esclen = sizeof(escalated);
1085 const char* typestr = nullptr;
1086 size_t typelen = 0;
1087
1088 if (!uploadinfo || (uploadinfosize == 0))
1089 return -1;
1090
1091 const size_t ulen = strnlen(uploadinfo, uploadinfosize);
1092 if (ulen == uploadinfosize)
1093 {
1094 WLog_WARN(TAG, "UPLOADINFOR string is not '\\0' terminated");
1095 return -1;
1096 }
1097
1098 if (!freerdp_assistance_parse_attr(&typestr, &typelen, "TYPE", uploadinfo))
1099 return -1;
1100
1101 if ((typelen != esclen) || (strncmp(typestr, escalated, esclen) != 0))
1102 {
1103 WLog_ERR(TAG,
1104 "Failed to parse ASSISTANCE file: Missing or invalid UPLOADINFO TYPE '%s' [%" PRIuz
1105 "]",
1106 typestr, typelen);
1107 return -1;
1108 }
1109
1110 char* uploaddata = nullptr;
1111 size_t uploaddatasize = 0;
1112 if (!freerdp_assistance_consume_input_and_get_element(uploadinfo, ulen, "UPLOADDATA",
1113 &uploaddata, &uploaddatasize))
1114 return -1;
1115
1116 /* Parse USERNAME */
1117 if (!freerdp_assistance_parse_attr_str(&file->Username, "USERNAME", uploaddata))
1118 return -1;
1119
1120 /* Parse LHTICKET */
1121 if (!freerdp_assistance_parse_attr_str(&file->LHTicket, "LHTICKET", uploaddata))
1122 return -1;
1123
1124 /* Parse RCTICKET */
1125 if (!freerdp_assistance_parse_attr_str(&file->RCTicket, "RCTICKET", uploaddata))
1126 return -1;
1127
1128 /* Parse RCTICKETENCRYPTED */
1129 if (!freerdp_assistance_parse_attr_bool(&file->RCTicketEncrypted, "RCTICKETENCRYPTED",
1130 uploaddata))
1131 return -1;
1132
1133 /* Parse PassStub */
1134 if (!freerdp_assistance_parse_attr_str(&file->PassStub, "PassStub", uploaddata))
1135 return -1;
1136
1137 if (file->PassStub)
1138 {
1139 const char* amp = "&amp;";
1140 char* passtub = strstr(file->PassStub, amp);
1141 while (passtub)
1142 {
1143 const char* end = passtub + 5;
1144 const size_t len = strlen(end);
1145 memmove(&passtub[1], end, len + 1);
1146 passtub = strstr(passtub, amp);
1147 }
1148 }
1149
1150 /* Parse DtStart */
1151 if (!freerdp_assistance_parse_attr_uint32(&file->DtStart, "DtStart", uploaddata))
1152 return -1;
1153
1154 /* Parse DtLength */
1155 if (!freerdp_assistance_parse_attr_uint32(&file->DtLength, "DtLength", uploaddata))
1156 return -1;
1157
1158 /* Parse L (LowSpeed) */
1159 if (!freerdp_assistance_parse_attr_bool(&file->LowSpeed, "L", uploaddata))
1160 return -1;
1161
1162 file->Type = (file->LHTicket) ? 2 : 1;
1163 int status = 0;
1164
1165 switch (file->Type)
1166 {
1167 case 2:
1168 {
1169 file->EncryptedLHTicket = freerdp_assistance_hex_string_to_bin(
1170 file->LHTicket, &file->EncryptedLHTicketLength);
1171
1172 if (!freerdp_assistance_decrypt2(file))
1173 status = -1;
1174 }
1175 break;
1176
1177 case 1:
1178 {
1179 if (!freerdp_assistance_parse_connection_string1(file))
1180 status = -1;
1181 }
1182 break;
1183
1184 default:
1185 return -1;
1186 }
1187
1188 if (status < 0)
1189 {
1190 WLog_ERR(TAG, "freerdp_assistance_parse_connection_string1 failure: %d", status);
1191 return -1;
1192 }
1193
1194 file->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(file->password, file->PassStub,
1195 &file->EncryptedPassStubLength);
1196
1197 if (!file->EncryptedPassStub)
1198 return -1;
1199
1200 return 1;
1201}
1202
1203WINPR_ATTR_NODISCARD
1204static int freerdp_assistance_parse_file_buffer_int(rdpAssistanceFile* file, char* buffer,
1205 size_t size, const char* password)
1206{
1207 WINPR_ASSERT(file);
1208 WINPR_ASSERT(buffer);
1209 WINPR_ASSERT(size > 0);
1210
1211 if (!update_password(file, password))
1212 return -1;
1213
1214 char* uploadinfo = nullptr;
1215 size_t uploadinfosize = 0;
1216 if (freerdp_assistance_consume_input_and_get_element(buffer, size, "UPLOADINFO", &uploadinfo,
1217 &uploadinfosize))
1218 return freerdp_assistance_parse_uploadinfo(file, uploadinfo, uploadinfosize);
1219
1220 size_t elen = 0;
1221 const char* estr =
1222 freerdp_assistance_contains_element(buffer, size, "E", &elen, nullptr, nullptr);
1223 if (!estr || (elen == 0))
1224 {
1225 WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Neither UPLOADINFO nor <E> found");
1226 return -1;
1227 }
1228 if (!update_connectionstring2(file, estr, elen))
1229 return -1;
1230
1231 if (!freerdp_assistance_parse_connection_string2(file))
1232 return -1;
1233
1234 return 1;
1235}
1236
1237int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* cbuffer, size_t size,
1238 const char* password)
1239{
1240 WINPR_ASSERT(file);
1241 if (!password)
1242 {
1243 WLog_WARN(TAG, "empty password supplied");
1244 }
1245
1246 if (!cbuffer || (size == 0))
1247 {
1248 WLog_WARN(TAG, "no data supplied [%p, %" PRIuz "]",
1249 WINPR_CXX_COMPAT_CAST(const void*, cbuffer), size);
1250 return -1;
1251 }
1252
1253 char* abuffer = strndup(cbuffer, size);
1254 const size_t len = strnlen(cbuffer, size);
1255 if (len == size)
1256 WLog_WARN(TAG, "Input data not '\\0' terminated");
1257
1258 if (!abuffer)
1259 return -1;
1260
1261 const int rc = freerdp_assistance_parse_file_buffer_int(file, abuffer, len + 1, password);
1262 free(abuffer);
1263 return rc;
1264}
1265
1266int freerdp_assistance_parse_file(rdpAssistanceFile* file, const char* name, const char* password)
1267{
1268 int status = -1;
1269 BYTE* buffer = nullptr;
1270 size_t readSize = 0;
1271 union
1272 {
1273 INT64 i64;
1274 size_t s;
1275 } fileSize;
1276
1277 if (!update_name(file, name))
1278 return -1;
1279
1280 FILE* fp = winpr_fopen(name, "r");
1281
1282 if (!fp)
1283 {
1284 WLog_ERR(TAG, "Failed to open ASSISTANCE file %s ", name);
1285 return -1;
1286 }
1287
1288 if (_fseeki64(fp, 0, SEEK_END) < 0)
1289 goto fail;
1290 fileSize.i64 = _ftelli64(fp);
1291 if (_fseeki64(fp, 0, SEEK_SET) < 0)
1292 goto fail;
1293
1294 if (fileSize.i64 < 1)
1295 {
1296 WLog_ERR(TAG, "Failed to read ASSISTANCE file %s ", name);
1297 goto fail;
1298 }
1299
1300 buffer = (BYTE*)malloc(fileSize.s + 2);
1301
1302 if (!buffer)
1303 goto fail;
1304
1305 readSize = fread(buffer, fileSize.s, 1, fp);
1306
1307 if (!readSize)
1308 {
1309 if (!ferror(fp))
1310 readSize = fileSize.s;
1311 }
1312
1313 if (readSize < 1)
1314 {
1315 WLog_ERR(TAG, "Failed to read ASSISTANCE file %s ", name);
1316 goto fail;
1317 }
1318
1319 buffer[fileSize.s] = '\0';
1320 buffer[fileSize.s + 1] = '\0';
1321 status = freerdp_assistance_parse_file_buffer(file, (char*)buffer, fileSize.s, password);
1322
1323fail:
1324 (void)fclose(fp);
1325 free(buffer);
1326 return status;
1327}
1328
1329BOOL freerdp_assistance_populate_settings_from_assistance_file(rdpAssistanceFile* file,
1330 rdpSettings* settings)
1331{
1332 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteAssistanceMode, TRUE))
1333 return FALSE;
1334
1335 if (!file->RASessionId || !file->MachineAddresses)
1336 return FALSE;
1337
1338 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteAssistanceSessionId,
1339 file->RASessionId))
1340 return FALSE;
1341
1342 if (file->RCTicket)
1343 {
1344 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteAssistanceRCTicket,
1345 file->RCTicket))
1346 return FALSE;
1347 }
1348 else
1349 {
1350 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteAssistanceRCTicket,
1351 file->ConnectionString2))
1352 return FALSE;
1353 }
1354
1355 if (file->PassStub)
1356 {
1357 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteAssistancePassStub,
1358 file->PassStub))
1359 return FALSE;
1360 }
1361
1362 if (ArrayList_Count(file->MachineAddresses) < 1)
1363 return FALSE;
1364
1365 const char* addr = ArrayList_GetItem(file->MachineAddresses, 0);
1366 if (!freerdp_settings_set_string(settings, FreeRDP_ServerHostname, addr))
1367 return FALSE;
1368
1369 if (!freerdp_settings_set_string(settings, FreeRDP_AssistanceFile, file->filename))
1370 return FALSE;
1371
1372 if (!freerdp_settings_set_string(settings, FreeRDP_RemoteAssistancePassword, file->password))
1373 return FALSE;
1374
1375 if (file->Username)
1376 {
1377 if (!freerdp_settings_set_string(settings, FreeRDP_Username, file->Username))
1378 return FALSE;
1379 }
1380
1381 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteAssistanceMode, TRUE))
1382 return FALSE;
1383
1384 const size_t ports = ArrayList_Count(file->MachinePorts);
1385 const size_t addresses = ArrayList_Count(file->MachineAddresses);
1386 if (ports < 1)
1387 return FALSE;
1388 if (ports != addresses)
1389 return FALSE;
1390
1391 union
1392 {
1393 uintptr_t port;
1394 void* data;
1395 } cnv;
1396 cnv.data = ArrayList_GetItem(file->MachinePorts, 0);
1397 WINPR_ASSERT(cnv.port <= UINT32_MAX);
1398 if (!freerdp_settings_set_uint32(settings, FreeRDP_ServerPort, (UINT32)cnv.port))
1399 return FALSE;
1400
1401 if (!freerdp_target_net_adresses_reset(settings, ports))
1402 return FALSE;
1403
1404 for (size_t x = 0; x < ports; x++)
1405 {
1406 cnv.data = ArrayList_GetItem(file->MachinePorts, x);
1407 WINPR_ASSERT(cnv.port <= UINT32_MAX);
1408 const UINT32 port = (UINT32)cnv.port;
1409 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_TargetNetPorts, x, &port))
1410 return FALSE;
1411 }
1412 for (size_t i = 0; i < addresses; i++)
1413 {
1414 const char* maddr = ArrayList_GetItem(file->MachineAddresses, i);
1415 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_TargetNetAddresses, i, maddr))
1416 return FALSE;
1417 }
1418
1419 return TRUE;
1420}
1421
1422WINPR_ATTR_NODISCARD
1423static BOOL setup_string(wArrayList* list)
1424{
1425 WINPR_ASSERT(list);
1426
1427 wObject* obj = ArrayList_Object(list);
1428 if (!obj)
1429 return FALSE;
1430 obj->fnObjectFree = free;
1431 // obj->fnObjectNew = wwinpr_ObjectStringClone;
1432 return TRUE;
1433}
1434
1435rdpAssistanceFile* freerdp_assistance_file_new(void)
1436{
1437 if (!winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT))
1438 return nullptr;
1439
1440 rdpAssistanceFile* file = calloc(1, sizeof(rdpAssistanceFile));
1441 if (!file)
1442 return nullptr;
1443
1444 file->MachineAddresses = ArrayList_New(FALSE);
1445 file->MachinePorts = ArrayList_New(FALSE);
1446 file->MachineUris = ArrayList_New(FALSE);
1447
1448 if (!file->MachineAddresses || !file->MachinePorts || !file->MachineUris)
1449 goto fail;
1450
1451 if (!setup_string(file->MachineAddresses) || !setup_string(file->MachineUris))
1452 goto fail;
1453
1454 return file;
1455
1456fail:
1457 WINPR_PRAGMA_DIAG_PUSH
1458 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1459 freerdp_assistance_file_free(file);
1460 WINPR_PRAGMA_DIAG_POP
1461 return nullptr;
1462}
1463
1464void freerdp_assistance_file_free(rdpAssistanceFile* file)
1465{
1466 if (!file)
1467 return;
1468
1469 free(file->password);
1470 free(file->ConnectionString2);
1471 free(file->filename);
1472 free(file->Username);
1473 free(file->LHTicket);
1474 free(file->RCTicket);
1475 free(file->PassStub);
1476 free(file->ConnectionString1);
1477 free(file->EncryptedLHTicket);
1478 free(file->RASessionId);
1479 free(file->RASpecificParams);
1480 free(file->RASpecificParams2);
1481 free(file->EncryptedPassStub);
1482
1483 ArrayList_Free(file->MachineAddresses);
1484 ArrayList_Free(file->MachinePorts);
1485 ArrayList_Free(file->MachineUris);
1486 free(file);
1487}
1488
1489void freerdp_assistance_print_file(rdpAssistanceFile* file, wLog* log, DWORD level)
1490{
1491 WINPR_ASSERT(file);
1492
1493 WLog_Print(log, level, "Username: %s", file->Username);
1494 WLog_Print(log, level, "LHTicket: %s", file->LHTicket);
1495 WLog_Print(log, level, "RCTicket: %s", file->RCTicket);
1496 WLog_Print(log, level, "RCTicketEncrypted: %" PRId32, file->RCTicketEncrypted);
1497 WLog_Print(log, level, "PassStub: %s", file->PassStub);
1498 WLog_Print(log, level, "DtStart: %" PRIu32, file->DtStart);
1499 WLog_Print(log, level, "DtLength: %" PRIu32, file->DtLength);
1500 WLog_Print(log, level, "LowSpeed: %" PRId32, file->LowSpeed);
1501 WLog_Print(log, level, "RASessionId: %s", file->RASessionId);
1502 WLog_Print(log, level, "RASpecificParams: %s", file->RASpecificParams);
1503 WLog_Print(log, level, "RASpecificParams2: %s", file->RASpecificParams2);
1504
1505 for (size_t x = 0; x < ArrayList_Count(file->MachineAddresses); x++)
1506 {
1507 UINT32 port = 0;
1508 const char* uri = nullptr;
1509 const char* addr = ArrayList_GetItem(file->MachineAddresses, x);
1510 if (x < ArrayList_Count(file->MachinePorts))
1511 {
1512 union
1513 {
1514 uintptr_t port;
1515 void* data;
1516 } cnv;
1517 cnv.data = ArrayList_GetItem(file->MachinePorts, x);
1518 WINPR_ASSERT(cnv.port <= UINT32_MAX);
1519 port = (UINT32)cnv.port;
1520 }
1521 if (x < ArrayList_Count(file->MachineUris))
1522 uri = ArrayList_GetItem(file->MachineUris, x);
1523
1524 WLog_Print(log, level, "MachineAddress [%" PRIuz ": %s", x, addr);
1525 WLog_Print(log, level, "MachinePort [%" PRIuz ": %" PRIu32, x, port);
1526 WLog_Print(log, level, "MachineURI [%" PRIuz ": %s", x, uri);
1527 }
1528}
1529
1530BOOL freerdp_assistance_get_encrypted_pass_stub(rdpAssistanceFile* file, const char** pwd,
1531 size_t* size)
1532{
1533 if (!file || !pwd || !size)
1534 return FALSE;
1535
1536 *pwd = (const char*)file->EncryptedPassStub;
1537 *size = file->EncryptedPassStubLength;
1538 return TRUE;
1539}
1540
1541int freerdp_assistance_set_connection_string2(rdpAssistanceFile* file, const char* string,
1542 const char* password)
1543{
1544 if (!file || !string || !password)
1545 return -1;
1546
1547 char* str = _strdup(string);
1548 if (!str)
1549 return -1;
1550
1551 if (!update_connectionstring2_nocopy(file, str))
1552 return -1;
1553 if (!update_password(file, password))
1554 return -1;
1555 return freerdp_assistance_parse_connection_string2(file);
1556}
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.
This struct contains function pointer to initialize/free objects.
Definition collections.h:52
OBJECT_FREE_FN fnObjectFree
Definition collections.h:59