20#include <freerdp/config.h>
24#include <winpr/wtypes.h>
25#include <winpr/collections.h>
26#include <winpr/string.h>
28#include <winpr/crypto.h>
29#include <winpr/print.h>
30#include <winpr/windows.h>
32#include <winpr/file.h>
34#include <freerdp/log.h>
35#include <freerdp/client/file.h>
36#include <freerdp/client/cmdline.h>
38#include <freerdp/assistance.h>
40#include "../core/settings.h"
42#define TAG FREERDP_TAG("common")
44struct rdp_assistance_file
55 BOOL RCTicketEncrypted;
57 char* ConnectionString1;
58 char* ConnectionString2;
60 BYTE* EncryptedPassStub;
61 size_t EncryptedPassStubLength;
63 BYTE* EncryptedLHTicket;
64 size_t EncryptedLHTicketLength;
66 wArrayList* MachineAddresses;
67 wArrayList* MachinePorts;
68 wArrayList* MachineUris;
71 char* RASpecificParams;
72 char* RASpecificParams2;
78static const char* strrstr(
const char* haystack,
size_t len,
const char* needle)
83 char* result =
nullptr;
86 char* p = strstr(haystack, needle);
89 if (p > haystack + len)
99static BOOL update_option(
char** opt,
const char* val,
size_t len)
105 if (!val && (len != 0))
107 else if (!val && (len == 0))
109 *opt = strndup(val, len);
110 return *opt !=
nullptr;
113static BOOL update_name(rdpAssistanceFile* file,
const char* name)
119 WLog_ERR(TAG,
"ASSISTANCE file %s invalid name", name);
123 free(file->filename);
124 file->filename = _strdup(name);
125 return file->filename !=
nullptr;
128static BOOL update_password(rdpAssistanceFile* file,
const char* password)
131 free(file->password);
132 file->password =
nullptr;
135 file->password = _strdup(password);
136 return file->password !=
nullptr;
139static BOOL update_connectionstring2_nocopy(rdpAssistanceFile* file,
char* str)
142 free(file->ConnectionString2);
143 file->ConnectionString2 =
nullptr;
146 file->ConnectionString2 = str;
147 return file->ConnectionString2 !=
nullptr;
150static BOOL update_connectionstring2(rdpAssistanceFile* file,
const char* str,
size_t len)
152 char* strc =
nullptr;
153 if (!str && (len != 0))
156 if (str && (len > 0))
158 strc = strndup(str, len);
162 return update_connectionstring2_nocopy(file, strc);
165static BOOL update_connectionstring2_wchar(rdpAssistanceFile* file,
const WCHAR* str,
size_t len)
167 char* strc =
nullptr;
169 if (!str && (len != 0))
172 if (str && (len > 0))
174 strc = ConvertWCharNToUtf8Alloc(str, len,
nullptr);
178 return update_connectionstring2_nocopy(file, strc);
217static BOOL freerdp_assistance_crypt_derive_key_sha1(
const BYTE* hash,
size_t hashLength, BYTE* key,
221 BYTE pad1[64] = WINPR_C_ARRAY_INIT;
222 BYTE pad2[64] = WINPR_C_ARRAY_INIT;
227 memset(pad1, 0x36,
sizeof(pad1));
228 memset(pad2, 0x5C,
sizeof(pad2));
230 for (
size_t i = 0; i < hashLength; i++)
236 BYTE* buffer = (BYTE*)calloc(hashLength, 2);
241 if (!winpr_Digest(WINPR_MD_SHA1, pad1, 64, buffer, hashLength))
244 if (!winpr_Digest(WINPR_MD_SHA1, pad2, 64, &buffer[hashLength], hashLength))
247 CopyMemory(key, buffer, keyLength);
254static BOOL append_address_to_list(wArrayList* MachineAddresses,
const char* str,
size_t len)
256 char* copy =
nullptr;
258 copy = strndup(str, len);
262 const BOOL rc = ArrayList_Append(MachineAddresses, copy);
269static BOOL append_address(rdpAssistanceFile* file,
const char* host,
const char* port)
274 unsigned long p = strtoul(port,
nullptr, 0);
276 if ((errno != 0) || (p == 0) || (p > UINT16_MAX))
278 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: ConnectionString2 invalid port value %s",
283 if (!append_address_to_list(file->MachineAddresses, host, host ? strlen(host) : 0))
285 return ArrayList_Append(file->MachinePorts, (
void*)(uintptr_t)p);
288static BOOL freerdp_assistance_parse_address_list(rdpAssistanceFile* file,
char* list)
292 WLog_DBG(TAG,
"freerdp_assistance_parse_address_list list=%s", list);
303 char* saveptr =
nullptr;
304 char* token = strtok_s(strp, s, &saveptr);
307 while (token !=
nullptr)
309 char* port = strchr(token,
':');
315 if (!append_address(file, token, port))
318 token = strtok_s(
nullptr, s, &saveptr);
325static BOOL freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file)
327 char* tokens[8] = WINPR_C_ARRAY_INIT;
339 char* str = _strdup(file->RCTicket);
345 const size_t length = strlen(str);
349 for (
size_t i = 0; i < length; i++)
361 tokens[count++] = str;
363 for (
size_t i = 0; i < length; i++)
368 tokens[count++] = &str[i + 1];
374 if (strcmp(tokens[0],
"65538") != 0)
377 if (strcmp(tokens[1],
"1") != 0)
380 if (strcmp(tokens[3],
"*") != 0)
383 if (strcmp(tokens[5],
"*") != 0)
386 if (strcmp(tokens[6],
"*") != 0)
389 file->RASessionId = _strdup(tokens[4]);
391 if (!file->RASessionId)
394 file->RASpecificParams = _strdup(tokens[7]);
396 if (!file->RASpecificParams)
399 if (!freerdp_assistance_parse_address_list(file, tokens[2]))
421static BOOL freerdp_assistance_parse_attr(
const char** opt,
size_t* plength,
const char* key,
425 WINPR_ASSERT(plength);
433 char bkey[128] = WINPR_C_ARRAY_INIT;
434 const int rc = _snprintf(bkey,
sizeof(bkey),
"%s=\"", key);
435 WINPR_ASSERT(rc > 0);
436 WINPR_ASSERT((
size_t)rc <
sizeof(bkey));
437 if ((rc <= 0) || ((
size_t)rc >=
sizeof(bkey)))
440 char* p = strstr(tag, bkey);
445 char* q = strchr(p,
'"');
449 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: ConnectionString2 invalid field '%s=%s'",
457 "Failed to parse ASSISTANCE file: ConnectionString2 invalid field "
462 const size_t length = WINPR_ASSERTING_INT_CAST(
size_t, q - p);
469static BOOL freerdp_assistance_parse_attr_str(
char** opt,
const char* key,
const char* tag)
471 const char* copt =
nullptr;
473 if (!freerdp_assistance_parse_attr(&copt, &size, key, tag))
475 return update_option(opt, copt, size);
478static BOOL freerdp_assistance_parse_attr_bool(BOOL* opt,
const char* key,
const char* tag)
480 const char* copt =
nullptr;
486 if (!freerdp_assistance_parse_attr(&copt, &size, key, tag))
491 *opt = (copt[0] ==
'1');
495static BOOL freerdp_assistance_parse_attr_uint32(UINT32* opt,
const char* key,
const char* tag)
497 const char* copt =
nullptr;
503 if (!freerdp_assistance_parse_attr(&copt, &size, key, tag))
506 char buffer[64] = WINPR_C_ARRAY_INIT;
507 if ((!copt && (size > 0)) || (size >=
sizeof(buffer)))
509 WLog_WARN(TAG,
"Invalid UINT32 string '%s' [%" PRIuz
"]", copt, size);
514 strncpy(buffer, copt, size);
517 unsigned long val = strtoul(buffer,
nullptr, 0);
519 if ((errno != 0) || (val > UINT32_MAX))
521 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: Invalid value %s", buffer);
530static char* freerdp_assistance_contains_element(
char* input,
size_t ilen,
const char* key,
531 size_t* plen,
char** pdata,
size_t* pdlen)
537 char bkey[128] = WINPR_C_ARRAY_INIT;
538 const int rc = _snprintf(bkey,
sizeof(bkey),
"<%s", key);
539 WINPR_ASSERT(rc > 0);
540 WINPR_ASSERT((
size_t)rc <
sizeof(bkey));
541 if ((rc < 0) || ((
size_t)rc >=
sizeof(bkey)))
544 char* tag = strstr(input, bkey);
545 if (!tag || (tag > input + ilen))
548 char* data = tag + strnlen(bkey,
sizeof(bkey));
560 "Failed to parse ASSISTANCE file: ConnectionString2 missing delimiter after "
566 char* start = strstr(tag,
">");
568 if (!start || (start > input + ilen))
570 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: ConnectionString2 missing field %s", bkey);
574 const char* end = start;
575 const char* dend = start - 1;
578 char ekey[128] = WINPR_C_ARRAY_INIT;
579 const int erc = _snprintf(ekey,
sizeof(ekey),
"</%s>", key);
580 WINPR_ASSERT(erc > 0);
581 WINPR_ASSERT((
size_t)erc <
sizeof(ekey));
582 if ((erc <= 0) || ((
size_t)erc >=
sizeof(ekey)))
584 const size_t offset = WINPR_ASSERTING_INT_CAST(
size_t, start - tag);
585 dend = end = strrstr(start, ilen - offset, ekey);
587 end += strnlen(ekey,
sizeof(ekey));
593 "Failed to parse ASSISTANCE file: ConnectionString2 missing end tag for field %s",
598 *plen = WINPR_ASSERTING_INT_CAST(
size_t, end - tag);
603 *pdlen = WINPR_ASSERTING_INT_CAST(
size_t, dend - data);
612static BOOL freerdp_assistance_consume_input_and_get_element(
char* input,
const char* key,
613 char** element,
size_t* elen)
617 WINPR_ASSERT(element);
622 char* data =
nullptr;
623 char* tag = freerdp_assistance_contains_element(input, strlen(input), key, &len, &data, &dlen);
627 char* end = data + dlen;
635static BOOL freerdp_assistance_get_element(
char* input,
size_t ilen,
const char* key,
636 char** element,
size_t* elen)
640 WINPR_ASSERT(element);
645 char* data =
nullptr;
646 char* tag = freerdp_assistance_contains_element(input, ilen, key, &len, &data, &dlen);
650 if (tag + len > input + ilen)
653 char* end = tag + len;
655 *elen = WINPR_ASSERTING_INT_CAST(
size_t, end - data + 1);
659static BOOL freerdp_assistance_parse_all_elements_of(rdpAssistanceFile* file,
char* data,
660 size_t len,
const char* key,
661 BOOL (*fkt)(rdpAssistanceFile* file,
662 char* data,
size_t len))
667 while (freerdp_assistance_get_element(data, len, key, &val, &vlen))
670 len = strnlen(data, len);
673 val[vlen - 1] =
'\0';
675 if (!fkt(file, val, vlen))
683static BOOL freerdp_assistance_parse_all_elements_of_l(rdpAssistanceFile* file,
char* data,
684 WINPR_ATTR_UNUSED
size_t len)
687 const char* n =
nullptr;
688 const char* u =
nullptr;
691 if (!freerdp_assistance_parse_attr_uint32(&p,
"P", data))
693 if (!freerdp_assistance_parse_attr(&n, &nlen,
"N", data))
695 if (!freerdp_assistance_parse_attr(&u, &ulen,
"U", data))
700 if (!append_address_to_list(file->MachineAddresses, n, nlen))
702 if (!ArrayList_Append(file->MachinePorts, (
void*)(uintptr_t)p))
707 if (!append_address_to_list(file->MachineAddresses, u, ulen))
709 if (!ArrayList_Append(file->MachinePorts, (
void*)(uintptr_t)p))
715static BOOL freerdp_assistance_parse_all_elements_of_t(rdpAssistanceFile* file,
char* data,
720 if (!freerdp_assistance_parse_attr_uint32(&
id,
"ID", data))
722 if (!freerdp_assistance_parse_attr_uint32(&sid,
"SID", data))
724 WLog_DBG(TAG,
"transport id=%" PRIu32
", sid=%" PRIu32,
id, sid);
725 return freerdp_assistance_parse_all_elements_of(file, data, len,
"L",
726 freerdp_assistance_parse_all_elements_of_l);
729static BOOL freerdp_assistance_parse_all_elements_of_c(rdpAssistanceFile* file,
char* data,
732 return freerdp_assistance_parse_all_elements_of(file, data, len,
"T",
733 freerdp_assistance_parse_all_elements_of_t);
736static BOOL freerdp_assistance_parse_find_elements_of_c(rdpAssistanceFile* file,
char* data,
739 return freerdp_assistance_parse_all_elements_of(file, data, len,
"C",
740 freerdp_assistance_parse_all_elements_of_c);
743static BOOL freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file)
749 if (!file->ConnectionString2)
752 char* str = _strdup(file->ConnectionString2);
759 if (!freerdp_assistance_consume_input_and_get_element(str,
"E", &e, &elen))
762 if (!e || (elen == 0))
767 if (!freerdp_assistance_get_element(e, elen,
"A", &a, &alen))
770 if (!a || (alen == 0))
773 if (!freerdp_assistance_parse_find_elements_of_c(file, e, elen))
781 if (!freerdp_assistance_parse_attr_str(&file->RASpecificParams,
"KH", a))
784 if (!freerdp_assistance_parse_attr_str(&file->RASpecificParams2,
"KH2", a))
787 if (!freerdp_assistance_parse_attr_str(&file->RASessionId,
"ID", a))
797char* freerdp_assistance_construct_expert_blob(
const char* name,
const char* pass)
802 const size_t nameLength = strlen(name) + strlen(
"NAME=");
803 const size_t passLength = strlen(pass) + strlen(
"PASS=");
804 const size_t size = nameLength + passLength + 64;
805 char* ExpertBlob = (
char*)calloc(1, size);
810 (void)sprintf_s(ExpertBlob, size,
"%" PRIuz
";NAME=%s%" PRIuz
";PASS=%s", nameLength, name,
815char* freerdp_assistance_generate_pass_stub(WINPR_ATTR_UNUSED DWORD flags)
817 UINT32 nums[14] = WINPR_C_ARRAY_INIT;
818 const char set1[64] = {
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
819 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
820 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
821 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
822 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'*',
'_' };
823 const char set2[12] = {
'!',
'@',
'#',
'$',
'&',
'^',
'*',
'(',
')',
'-',
'+',
'=' };
824 const char set3[10] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9' };
825 const char set4[26] = {
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
826 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z' };
827 const char set5[26] = {
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
828 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z' };
829 char* passStub = calloc(15,
sizeof(
char));
845 if (winpr_RAND(nums,
sizeof(nums)) < 0)
851 passStub[0] = set1[nums[0] %
sizeof(set1)];
852 passStub[1] = set2[nums[1] %
sizeof(set2)];
853 passStub[2] = set3[nums[2] %
sizeof(set3)];
854 passStub[3] = set4[nums[3] %
sizeof(set4)];
855 passStub[4] = set5[nums[4] %
sizeof(set5)];
857 for (
size_t x = 5; x < ARRAYSIZE(nums); x++)
858 passStub[x] = set1[nums[x] %
sizeof(set1)];
862BYTE* freerdp_assistance_encrypt_pass_stub(
const char* password,
const char* passStub,
863 size_t* pEncryptedSize)
866 size_t cbPasswordW = 0;
867 size_t cbPassStubW = 0;
868 BYTE PasswordHash[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
869 WINPR_RC4_CTX* rc4Ctx =
nullptr;
870 BYTE* pbIn =
nullptr;
871 BYTE* pbOut =
nullptr;
873 WCHAR* PasswordW = ConvertUtf8ToWCharAlloc(password, &cbPasswordW);
874 WCHAR* PassStubW = ConvertUtf8ToWCharAlloc(passStub, &cbPassStubW);
876 cbPasswordW = cbPasswordW *
sizeof(WCHAR);
877 cbPassStubW = cbPassStubW *
sizeof(WCHAR);
878 const size_t EncryptedSize = cbPassStubW + 4;
880 if (!PasswordW || !PassStubW)
883 if (!winpr_Digest(WINPR_MD_MD5, (BYTE*)PasswordW, cbPasswordW, (BYTE*)PasswordHash,
884 sizeof(PasswordHash)))
887 pbIn = (BYTE*)calloc(1, EncryptedSize);
888 pbOut = (BYTE*)calloc(1, EncryptedSize);
893 WINPR_ASSERT(cbPasswordW <= UINT32_MAX);
894 winpr_Data_Write_UINT32(pbIn, (UINT32)cbPassStubW);
895 CopyMemory(&pbIn[4], PassStubW, cbPassStubW);
896 rc4Ctx = winpr_RC4_New(PasswordHash,
sizeof(PasswordHash));
900 WLog_ERR(TAG,
"winpr_Cipher_New failure");
904 rc = winpr_RC4_Update(rc4Ctx, EncryptedSize, pbIn, pbOut);
908 WLog_ERR(TAG,
"winpr_Cipher_Update failure");
913 winpr_RC4_Free(rc4Ctx);
920 *pEncryptedSize = EncryptedSize;
924static BOOL freerdp_assistance_decrypt2(rdpAssistanceFile* file)
928 size_t cbPasswordW = 0;
930 WINPR_CIPHER_CTX* aesDec =
nullptr;
931 WCHAR* PasswordW =
nullptr;
932 BYTE* pbIn =
nullptr;
933 BYTE* pbOut =
nullptr;
937 BYTE DerivedKey[WINPR_AES_BLOCK_SIZE] = WINPR_C_ARRAY_INIT;
938 BYTE InitializationVector[WINPR_AES_BLOCK_SIZE] = WINPR_C_ARRAY_INIT;
939 BYTE PasswordHash[WINPR_SHA1_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
946 PasswordW = ConvertUtf8ToWCharAlloc(file->password, &cbPasswordW);
949 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: Conversion from UCS2 to UTF8 failed");
953 cbPasswordW = cbPasswordW *
sizeof(WCHAR);
955 if (!winpr_Digest(WINPR_MD_SHA1, (BYTE*)PasswordW, cbPasswordW, PasswordHash,
956 sizeof(PasswordHash)))
959 if (!freerdp_assistance_crypt_derive_key_sha1(PasswordHash,
sizeof(PasswordHash), DerivedKey,
964 winpr_Cipher_NewEx(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, DerivedKey,
sizeof(DerivedKey),
965 InitializationVector,
sizeof(InitializationVector));
971 cbIn = file->EncryptedLHTicketLength;
972 pbIn = file->EncryptedLHTicket;
973 pbOut = (BYTE*)calloc(1, cbIn + WINPR_AES_BLOCK_SIZE + 2);
978 if (!winpr_Cipher_Update(aesDec, pbIn, cbIn, pbOut, &cbOut))
981 if (!winpr_Cipher_Final(aesDec, pbOut + cbOut, &cbFinal))
983 WLog_ERR(TAG,
"winpr_Cipher_Final failure");
997 cchOutW = cbOut /
sizeof(WCHAR);
999 if (!update_connectionstring2_wchar(file, cnv.wc, cchOutW))
1001 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: Conversion from UCS2 to UTF8 failed");
1005 if (!freerdp_assistance_parse_connection_string2(file))
1010 winpr_Cipher_Free(aesDec);
1013 WLog_DBG(TAG,
"freerdp_assistance_parse_connection_string2: %d", status);
1017BYTE* freerdp_assistance_hex_string_to_bin(
const void* str,
size_t* size)
1019 BYTE* buffer =
nullptr;
1023 const size_t length = strlen(str);
1024 buffer = calloc(length,
sizeof(BYTE));
1027 const size_t rc = winpr_HexStringToBinBuffer(str, length, buffer, length);
1037char* freerdp_assistance_bin_to_hex_string(
const void* data,
size_t size)
1039 return winpr_BinToHexString(data, size, FALSE);
1042static int freerdp_assistance_parse_uploadinfo(rdpAssistanceFile* file,
char* uploadinfo,
1043 size_t uploadinfosize)
1045 const char escalated[9] = {
'E',
's',
'c',
'a',
'l',
'a',
't',
'e',
'd' };
1046 const size_t esclen =
sizeof(escalated);
1047 const char* typestr =
nullptr;
1050 if (!uploadinfo || (uploadinfosize == 0))
1053 if (strnlen(uploadinfo, uploadinfosize) == uploadinfosize)
1055 WLog_WARN(TAG,
"UPLOADINFOR string is not '\\0' terminated");
1059 if (!freerdp_assistance_parse_attr(&typestr, &typelen,
"TYPE", uploadinfo))
1062 if ((typelen != esclen) || (strncmp(typestr, escalated, esclen) != 0))
1065 "Failed to parse ASSISTANCE file: Missing or invalid UPLOADINFO TYPE '%s' [%" PRIuz
1071 char* uploaddata =
nullptr;
1072 size_t uploaddatasize = 0;
1073 if (!freerdp_assistance_consume_input_and_get_element(uploadinfo,
"UPLOADDATA", &uploaddata,
1078 if (!freerdp_assistance_parse_attr_str(&file->Username,
"USERNAME", uploaddata))
1082 if (!freerdp_assistance_parse_attr_str(&file->LHTicket,
"LHTICKET", uploaddata))
1086 if (!freerdp_assistance_parse_attr_str(&file->RCTicket,
"RCTICKET", uploaddata))
1090 if (!freerdp_assistance_parse_attr_bool(&file->RCTicketEncrypted,
"RCTICKETENCRYPTED",
1095 if (!freerdp_assistance_parse_attr_str(&file->PassStub,
"PassStub", uploaddata))
1100 const char* amp =
"&";
1101 char* passtub = strstr(file->PassStub, amp);
1104 const char* end = passtub + 5;
1105 const size_t len = strlen(end);
1106 memmove(&passtub[1], end, len + 1);
1107 passtub = strstr(passtub, amp);
1112 if (!freerdp_assistance_parse_attr_uint32(&file->DtStart,
"DtStart", uploaddata))
1116 if (!freerdp_assistance_parse_attr_uint32(&file->DtLength,
"DtLength", uploaddata))
1120 if (!freerdp_assistance_parse_attr_bool(&file->LowSpeed,
"L", uploaddata))
1123 file->Type = (file->LHTicket) ? 2 : 1;
1130 file->EncryptedLHTicket = freerdp_assistance_hex_string_to_bin(
1131 file->LHTicket, &file->EncryptedLHTicketLength);
1133 if (!freerdp_assistance_decrypt2(file))
1140 if (!freerdp_assistance_parse_connection_string1(file))
1151 WLog_ERR(TAG,
"freerdp_assistance_parse_connection_string1 failure: %d", status);
1155 file->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(file->password, file->PassStub,
1156 &file->EncryptedPassStubLength);
1158 if (!file->EncryptedPassStub)
1164static int freerdp_assistance_parse_file_buffer_int(rdpAssistanceFile* file,
char* buffer,
1165 size_t size,
const char* password)
1168 WINPR_ASSERT(buffer);
1169 WINPR_ASSERT(size > 0);
1171 if (!update_password(file, password))
1174 char* uploadinfo =
nullptr;
1175 size_t uploadinfosize = 0;
1176 if (freerdp_assistance_consume_input_and_get_element(buffer,
"UPLOADINFO", &uploadinfo,
1178 return freerdp_assistance_parse_uploadinfo(file, uploadinfo, uploadinfosize);
1182 freerdp_assistance_contains_element(buffer, size,
"E", &elen,
nullptr,
nullptr);
1183 if (!estr || (elen == 0))
1185 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: Neither UPLOADINFO nor <E> found");
1188 if (!update_connectionstring2(file, estr, elen))
1191 if (!freerdp_assistance_parse_connection_string2(file))
1197int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file,
const char* cbuffer,
size_t size,
1198 const char* password)
1203 WLog_WARN(TAG,
"empty password supplied");
1206 if (!cbuffer || (size == 0))
1208 WLog_WARN(TAG,
"no data supplied [%p, %" PRIuz
"]",
1209 WINPR_CXX_COMPAT_CAST(
const void*, cbuffer), size);
1213 char* abuffer = strndup(cbuffer, size);
1214 const size_t len = strnlen(cbuffer, size);
1216 WLog_WARN(TAG,
"Input data not '\\0' terminated");
1221 const int rc = freerdp_assistance_parse_file_buffer_int(file, abuffer, len + 1, password);
1226int freerdp_assistance_parse_file(rdpAssistanceFile* file,
const char* name,
const char* password)
1229 BYTE* buffer =
nullptr;
1231 size_t readSize = 0;
1238 if (!update_name(file, name))
1241 fp = winpr_fopen(name,
"r");
1245 WLog_ERR(TAG,
"Failed to open ASSISTANCE file %s ", name);
1249 (void)_fseeki64(fp, 0, SEEK_END);
1250 fileSize.i64 = _ftelli64(fp);
1251 (void)_fseeki64(fp, 0, SEEK_SET);
1253 if (fileSize.i64 < 1)
1255 WLog_ERR(TAG,
"Failed to read ASSISTANCE file %s ", name);
1260 buffer = (BYTE*)malloc(fileSize.s + 2);
1268 readSize = fread(buffer, fileSize.s, 1, fp);
1273 readSize = fileSize.s;
1280 WLog_ERR(TAG,
"Failed to read ASSISTANCE file %s ", name);
1286 buffer[fileSize.s] =
'\0';
1287 buffer[fileSize.s + 1] =
'\0';
1288 status = freerdp_assistance_parse_file_buffer(file, (
char*)buffer, fileSize.s, password);
1293BOOL freerdp_assistance_populate_settings_from_assistance_file(rdpAssistanceFile* file,
1294 rdpSettings* settings)
1299 if (!file->RASessionId || !file->MachineAddresses)
1315 file->ConnectionString2))
1326 if (ArrayList_Count(file->MachineAddresses) < 1)
1329 const char* addr = ArrayList_GetItem(file->MachineAddresses, 0);
1348 const size_t ports = ArrayList_Count(file->MachinePorts);
1349 const size_t addresses = ArrayList_Count(file->MachineAddresses);
1352 if (ports != addresses)
1360 cnv.data = ArrayList_GetItem(file->MachinePorts, 0);
1361 WINPR_ASSERT(cnv.port <= UINT32_MAX);
1365 if (!freerdp_target_net_adresses_reset(settings, ports))
1368 for (
size_t x = 0; x < ports; x++)
1370 cnv.data = ArrayList_GetItem(file->MachinePorts, x);
1371 WINPR_ASSERT(cnv.port <= UINT32_MAX);
1372 const UINT32 port = (UINT32)cnv.port;
1373 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_TargetNetPorts, x, &port))
1376 for (
size_t i = 0; i < addresses; i++)
1378 const char* maddr = ArrayList_GetItem(file->MachineAddresses, i);
1379 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_TargetNetAddresses, i, maddr))
1386static BOOL setup_string(wArrayList* list)
1390 wObject* obj = ArrayList_Object(list);
1398rdpAssistanceFile* freerdp_assistance_file_new(
void)
1400 winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
1401 rdpAssistanceFile* file = calloc(1,
sizeof(rdpAssistanceFile));
1405 file->MachineAddresses = ArrayList_New(FALSE);
1406 file->MachinePorts = ArrayList_New(FALSE);
1407 file->MachineUris = ArrayList_New(FALSE);
1409 if (!file->MachineAddresses || !file->MachinePorts || !file->MachineUris)
1412 if (!setup_string(file->MachineAddresses) || !setup_string(file->MachineUris))
1418 WINPR_PRAGMA_DIAG_PUSH
1419 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1420 freerdp_assistance_file_free(file);
1421 WINPR_PRAGMA_DIAG_POP
1425void freerdp_assistance_file_free(rdpAssistanceFile* file)
1430 update_password(file,
nullptr);
1431 update_connectionstring2(file,
nullptr, 0);
1432 free(file->filename);
1433 free(file->Username);
1434 free(file->LHTicket);
1435 free(file->RCTicket);
1436 free(file->PassStub);
1437 free(file->ConnectionString1);
1438 free(file->EncryptedLHTicket);
1439 free(file->RASessionId);
1440 free(file->RASpecificParams);
1441 free(file->RASpecificParams2);
1442 free(file->EncryptedPassStub);
1444 ArrayList_Free(file->MachineAddresses);
1445 ArrayList_Free(file->MachinePorts);
1446 ArrayList_Free(file->MachineUris);
1450void freerdp_assistance_print_file(rdpAssistanceFile* file, wLog* log, DWORD level)
1454 WLog_Print(log, level,
"Username: %s", file->Username);
1455 WLog_Print(log, level,
"LHTicket: %s", file->LHTicket);
1456 WLog_Print(log, level,
"RCTicket: %s", file->RCTicket);
1457 WLog_Print(log, level,
"RCTicketEncrypted: %" PRId32, file->RCTicketEncrypted);
1458 WLog_Print(log, level,
"PassStub: %s", file->PassStub);
1459 WLog_Print(log, level,
"DtStart: %" PRIu32, file->DtStart);
1460 WLog_Print(log, level,
"DtLength: %" PRIu32, file->DtLength);
1461 WLog_Print(log, level,
"LowSpeed: %" PRId32, file->LowSpeed);
1462 WLog_Print(log, level,
"RASessionId: %s", file->RASessionId);
1463 WLog_Print(log, level,
"RASpecificParams: %s", file->RASpecificParams);
1464 WLog_Print(log, level,
"RASpecificParams2: %s", file->RASpecificParams2);
1466 for (
size_t x = 0; x < ArrayList_Count(file->MachineAddresses); x++)
1469 const char* uri =
nullptr;
1470 const char* addr = ArrayList_GetItem(file->MachineAddresses, x);
1471 if (x < ArrayList_Count(file->MachinePorts))
1478 cnv.data = ArrayList_GetItem(file->MachinePorts, x);
1479 WINPR_ASSERT(cnv.port <= UINT32_MAX);
1480 port = (UINT32)cnv.port;
1482 if (x < ArrayList_Count(file->MachineUris))
1483 uri = ArrayList_GetItem(file->MachineUris, x);
1485 WLog_Print(log, level,
"MachineAddress [%" PRIuz
": %s", x, addr);
1486 WLog_Print(log, level,
"MachinePort [%" PRIuz
": %" PRIu32, x, port);
1487 WLog_Print(log, level,
"MachineURI [%" PRIuz
": %s", x, uri);
1491BOOL freerdp_assistance_get_encrypted_pass_stub(rdpAssistanceFile* file,
const char** pwd,
1494 if (!file || !pwd || !size)
1497 *pwd = (
const char*)file->EncryptedPassStub;
1498 *size = file->EncryptedPassStubLength;
1502int freerdp_assistance_set_connection_string2(rdpAssistanceFile* file,
const char*
string,
1503 const char* password)
1505 if (!file || !
string || !password)
1508 char* str = _strdup(
string);
1512 if (!update_connectionstring2_nocopy(file, str))
1514 if (!update_password(file, password))
1516 return freerdp_assistance_parse_connection_string2(file);
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree