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;
79static const char* strrstr(
const char* haystack,
size_t len,
const char* needle)
84 const char* result =
nullptr;
87 const char* p = strstr(haystack, needle);
90 if (p > haystack + len)
101static BOOL update_option(
char** opt,
const char* val,
size_t len)
107 if (!val && (len != 0))
109 else if (!val && (len == 0))
111 *opt = strndup(val, len);
112 return *opt !=
nullptr;
116static BOOL update_name(rdpAssistanceFile* file,
const char* name)
122 WLog_ERR(TAG,
"ASSISTANCE file %s invalid name", name);
126 free(file->filename);
127 file->filename = _strdup(name);
128 return file->filename !=
nullptr;
132static BOOL update_password(rdpAssistanceFile* file,
const char* password)
135 free(file->password);
136 file->password =
nullptr;
139 file->password = _strdup(password);
140 return file->password !=
nullptr;
144static BOOL update_connectionstring2_nocopy(rdpAssistanceFile* file,
char* str)
147 free(file->ConnectionString2);
148 file->ConnectionString2 =
nullptr;
151 file->ConnectionString2 = str;
152 return file->ConnectionString2 !=
nullptr;
156static BOOL update_connectionstring2(rdpAssistanceFile* file,
const char* str,
size_t len)
158 char* strc =
nullptr;
159 if (!str && (len != 0))
162 if (str && (len > 0))
164 strc = strndup(str, len);
168 return update_connectionstring2_nocopy(file, strc);
172static BOOL update_connectionstring2_wchar(rdpAssistanceFile* file,
const WCHAR* str,
size_t len)
174 char* strc =
nullptr;
176 if (!str && (len != 0))
179 if (str && (len > 0))
181 strc = ConvertWCharNToUtf8Alloc(str, len,
nullptr);
185 return update_connectionstring2_nocopy(file, strc);
224static BOOL freerdp_assistance_crypt_derive_key_sha1(
const BYTE* hash,
size_t hashLength, BYTE* key,
228 BYTE pad1[64] = WINPR_C_ARRAY_INIT;
229 BYTE pad2[64] = WINPR_C_ARRAY_INIT;
234 memset(pad1, 0x36,
sizeof(pad1));
235 memset(pad2, 0x5C,
sizeof(pad2));
237 for (
size_t i = 0; i < hashLength; i++)
243 BYTE* buffer = (BYTE*)calloc(hashLength, 2);
248 if (!winpr_Digest(WINPR_MD_SHA1, pad1, 64, buffer, hashLength))
251 if (!winpr_Digest(WINPR_MD_SHA1, pad2, 64, &buffer[hashLength], hashLength))
254 CopyMemory(key, buffer, keyLength);
262static BOOL append_address_to_list(wArrayList* MachineAddresses,
const char* str,
size_t len)
264 char* copy =
nullptr;
266 copy = strndup(str, len);
270 const BOOL rc = ArrayList_Append(MachineAddresses, copy);
278static BOOL append_address(rdpAssistanceFile* file,
const char* host,
const char* port)
283 unsigned long p = strtoul(port,
nullptr, 0);
285 if ((errno != 0) || (p == 0) || (p > UINT16_MAX))
287 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: ConnectionString2 invalid port value %s",
292 if (!append_address_to_list(file->MachineAddresses, host, host ? strlen(host) : 0))
294 return ArrayList_Append(file->MachinePorts, (
void*)(uintptr_t)p);
298static BOOL freerdp_assistance_parse_address_list(rdpAssistanceFile* file,
char* list)
302 WLog_DBG(TAG,
"freerdp_assistance_parse_address_list list=%s", list);
313 char* saveptr =
nullptr;
314 char* token = strtok_s(strp, s, &saveptr);
317 while (token !=
nullptr)
319 char* port = strchr(token,
':');
325 if (!append_address(file, token, port))
328 token = strtok_s(
nullptr, s, &saveptr);
336static BOOL freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file)
338 char* tokens[8] = WINPR_C_ARRAY_INIT;
350 char* str = _strdup(file->RCTicket);
356 const size_t length = strlen(str);
360 for (
size_t i = 0; i < length; i++)
372 tokens[count++] = str;
374 for (
size_t i = 0; i < length; i++)
379 tokens[count++] = &str[i + 1];
385 if (strcmp(tokens[0],
"65538") != 0)
388 if (strcmp(tokens[1],
"1") != 0)
391 if (strcmp(tokens[3],
"*") != 0)
394 if (strcmp(tokens[5],
"*") != 0)
397 if (strcmp(tokens[6],
"*") != 0)
400 file->RASessionId = _strdup(tokens[4]);
402 if (!file->RASessionId)
405 file->RASpecificParams = _strdup(tokens[7]);
407 if (!file->RASpecificParams)
410 if (!freerdp_assistance_parse_address_list(file, tokens[2]))
432static BOOL freerdp_assistance_parse_attr(
const char** opt,
size_t* plength,
const char* key,
436 WINPR_ASSERT(plength);
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)))
451 const char* p = strstr(tag, bkey);
456 const char* q = strchr(p,
'"');
460 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: ConnectionString2 invalid field '%s=%s'",
468 "Failed to parse ASSISTANCE file: ConnectionString2 invalid field "
473 const size_t length = WINPR_ASSERTING_INT_CAST(
size_t, q - p);
481static BOOL freerdp_assistance_parse_attr_str(
char** opt,
const char* key,
const char* tag)
483 const char* copt =
nullptr;
485 if (!freerdp_assistance_parse_attr(&copt, &size, key, tag))
487 return update_option(opt, copt, size);
491static BOOL freerdp_assistance_parse_attr_bool(BOOL* opt,
const char* key,
const char* tag)
493 const char* copt =
nullptr;
499 if (!freerdp_assistance_parse_attr(&copt, &size, key, tag))
504 *opt = (copt[0] ==
'1');
509static BOOL freerdp_assistance_parse_attr_uint32(UINT32* opt,
const char* key,
const char* tag)
511 const char* copt =
nullptr;
517 if (!freerdp_assistance_parse_attr(&copt, &size, key, tag))
520 char buffer[64] = WINPR_C_ARRAY_INIT;
521 if ((!copt && (size > 0)) || (size >=
sizeof(buffer)))
523 WLog_WARN(TAG,
"Invalid UINT32 string '%s' [%" PRIuz
"]", copt, size);
528 strncpy(buffer, copt, size);
531 unsigned long val = strtoul(buffer,
nullptr, 0);
533 if ((errno != 0) || (val > UINT32_MAX))
535 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: Invalid value %s", buffer);
545static char* freerdp_assistance_contains_element(
char* input,
size_t ilen,
const char* key,
546 size_t* plen,
char** pdata,
size_t* pdlen)
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)))
559 char* tag = winpr_strnstr(input, bkey, ilen);
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));
572 char* data = tag + texpect;
584 "Failed to parse ASSISTANCE file: ConnectionString2 missing delimiter after "
590 const char* start = winpr_strnstr(tag,
">", tlen);
592 if (!start || (start > input + ilen))
594 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: ConnectionString2 missing field %s", bkey);
598 const char* end = start;
599 const char* dend = start - 1;
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)))
608 const size_t offset = WINPR_ASSERTING_INT_CAST(
size_t, start - tag);
609 dend = end = strrstr(start, ilen - offset, ekey);
611 end += strnlen(ekey,
sizeof(ekey));
617 "Failed to parse ASSISTANCE file: ConnectionString2 missing end tag for field %s",
622 *plen = WINPR_ASSERTING_INT_CAST(
size_t, end - tag);
627 *pdlen = WINPR_ASSERTING_INT_CAST(
size_t, dend - data);
637static BOOL freerdp_assistance_consume_input_and_get_element(
char* input,
size_t ilen,
638 const char* key,
char** element,
643 WINPR_ASSERT(element);
648 char* data =
nullptr;
649 char* tag = freerdp_assistance_contains_element(input, ilen, key, &len, &data, &dlen);
653 char* end = data + dlen;
662static BOOL freerdp_assistance_get_element(
char* input,
size_t ilen,
const char* key,
663 char** element,
size_t* elen)
667 WINPR_ASSERT(element);
672 char* data =
nullptr;
673 char* tag = freerdp_assistance_contains_element(input, ilen, key, &len, &data, &dlen);
677 if (tag + len > input + ilen)
680 char* end = tag + len;
682 *elen = WINPR_ASSERTING_INT_CAST(
size_t, end - data + 1);
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))
695 while (freerdp_assistance_get_element(data, len, key, &val, &vlen))
700 len = strnlen(data, len - vlen);
703 val[vlen - 1] =
'\0';
705 if (!fkt(file, val, vlen))
714static BOOL freerdp_assistance_parse_all_elements_of_l(rdpAssistanceFile* file,
char* data,
715 WINPR_ATTR_UNUSED
size_t len)
718 const char* n =
nullptr;
719 const char* u =
nullptr;
722 if (!freerdp_assistance_parse_attr_uint32(&p,
"P", data))
724 if (!freerdp_assistance_parse_attr(&n, &nlen,
"N", data))
726 if (!freerdp_assistance_parse_attr(&u, &ulen,
"U", data))
731 if (!append_address_to_list(file->MachineAddresses, n, nlen))
733 if (!ArrayList_Append(file->MachinePorts, (
void*)(uintptr_t)p))
738 if (!append_address_to_list(file->MachineAddresses, u, ulen))
740 if (!ArrayList_Append(file->MachinePorts, (
void*)(uintptr_t)p))
747static BOOL freerdp_assistance_parse_all_elements_of_t(rdpAssistanceFile* file,
char* data,
752 if (!freerdp_assistance_parse_attr_uint32(&
id,
"ID", data))
754 if (!freerdp_assistance_parse_attr_uint32(&sid,
"SID", data))
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);
762static BOOL freerdp_assistance_parse_all_elements_of_c(rdpAssistanceFile* file,
char* data,
765 return freerdp_assistance_parse_all_elements_of(file, data, len,
"T",
766 freerdp_assistance_parse_all_elements_of_t);
770static BOOL freerdp_assistance_parse_find_elements_of_c(rdpAssistanceFile* file,
char* data,
773 return freerdp_assistance_parse_all_elements_of(file, data, len,
"C",
774 freerdp_assistance_parse_all_elements_of_c);
778static BOOL freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file)
784 if (!file->ConnectionString2)
787 char* str = _strdup(file->ConnectionString2);
790 const size_t slen = strlen(str);
795 if (!freerdp_assistance_consume_input_and_get_element(str, slen,
"E", &e, &elen))
798 if (!e || (elen == 0))
803 if (!freerdp_assistance_get_element(e, elen,
"A", &a, &alen))
806 if (!a || (alen == 0))
809 if (!freerdp_assistance_parse_find_elements_of_c(file, e, elen))
817 if (!freerdp_assistance_parse_attr_str(&file->RASpecificParams,
"KH", a))
820 if (!freerdp_assistance_parse_attr_str(&file->RASpecificParams2,
"KH2", a))
823 if (!freerdp_assistance_parse_attr_str(&file->RASessionId,
"ID", a))
833char* freerdp_assistance_construct_expert_blob(
const char* name,
const char* pass)
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);
846 (void)sprintf_s(ExpertBlob, size,
"%" PRIuz
";NAME=%s%" PRIuz
";PASS=%s", nameLength, name,
851char* freerdp_assistance_generate_pass_stub(WINPR_ATTR_UNUSED DWORD flags)
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));
881 if (winpr_RAND(nums,
sizeof(nums)) < 0)
887 passStub[0] = set1[nums[0] %
sizeof(set1)];
888 passStub[1] = set2[nums[1] %
sizeof(set2)];
889 passStub[2] = set3[nums[2] %
sizeof(set3)];
890 passStub[3] = set4[nums[3] %
sizeof(set4)];
891 passStub[4] = set5[nums[4] %
sizeof(set5)];
893 for (
size_t x = 5; x < ARRAYSIZE(nums); x++)
894 passStub[x] = set1[nums[x] %
sizeof(set1)];
898BYTE* freerdp_assistance_encrypt_pass_stub(
const char* password,
const char* passStub,
899 size_t* pEncryptedSize)
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;
909 WCHAR* PasswordW = ConvertUtf8ToWCharAlloc(password, &cbPasswordW);
910 WCHAR* PassStubW = ConvertUtf8ToWCharAlloc(passStub, &cbPassStubW);
912 cbPasswordW = cbPasswordW *
sizeof(WCHAR);
913 cbPassStubW = cbPassStubW *
sizeof(WCHAR);
914 const size_t EncryptedSize = cbPassStubW + 4;
916 if (!PasswordW || !PassStubW)
919 if (!winpr_Digest(WINPR_MD_MD5, (BYTE*)PasswordW, cbPasswordW, (BYTE*)PasswordHash,
920 sizeof(PasswordHash)))
923 pbIn = (BYTE*)calloc(1, EncryptedSize);
924 pbOut = (BYTE*)calloc(1, EncryptedSize);
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));
936 WLog_ERR(TAG,
"winpr_Cipher_New failure");
940 rc = winpr_RC4_Update(rc4Ctx, EncryptedSize, pbIn, pbOut);
944 WLog_ERR(TAG,
"winpr_Cipher_Update failure");
949 winpr_RC4_Free(rc4Ctx);
956 *pEncryptedSize = EncryptedSize;
961static BOOL freerdp_assistance_decrypt2(rdpAssistanceFile* file)
965 size_t cbPasswordW = 0;
967 WINPR_CIPHER_CTX* aesDec =
nullptr;
968 WCHAR* PasswordW =
nullptr;
969 BYTE* pbIn =
nullptr;
970 BYTE* pbOut =
nullptr;
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;
983 PasswordW = ConvertUtf8ToWCharAlloc(file->password, &cbPasswordW);
986 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: Conversion from UCS2 to UTF8 failed");
990 cbPasswordW = cbPasswordW *
sizeof(WCHAR);
992 if (!winpr_Digest(WINPR_MD_SHA1, (BYTE*)PasswordW, cbPasswordW, PasswordHash,
993 sizeof(PasswordHash)))
996 if (!freerdp_assistance_crypt_derive_key_sha1(PasswordHash,
sizeof(PasswordHash), DerivedKey,
1001 winpr_Cipher_NewEx(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, DerivedKey,
sizeof(DerivedKey),
1002 InitializationVector,
sizeof(InitializationVector));
1007 cbOut = cbFinal = 0;
1008 cbIn = file->EncryptedLHTicketLength;
1009 pbIn = file->EncryptedLHTicket;
1010 pbOut = (BYTE*)calloc(1, cbIn + WINPR_AES_BLOCK_SIZE + 2);
1015 if (!winpr_Cipher_Update(aesDec, pbIn, cbIn, pbOut, &cbOut))
1018 if (!winpr_Cipher_Final(aesDec, pbOut + cbOut, &cbFinal))
1020 WLog_ERR(TAG,
"winpr_Cipher_Final failure");
1034 cchOutW = cbOut /
sizeof(WCHAR);
1036 if (!update_connectionstring2_wchar(file, cnv.wc, cchOutW))
1038 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: Conversion from UCS2 to UTF8 failed");
1042 if (!freerdp_assistance_parse_connection_string2(file))
1047 winpr_Cipher_Free(aesDec);
1050 WLog_DBG(TAG,
"freerdp_assistance_parse_connection_string2: %d", status);
1054BYTE* freerdp_assistance_hex_string_to_bin(
const void* str,
size_t* size)
1056 BYTE* buffer =
nullptr;
1060 const size_t length = strlen(str);
1061 buffer = calloc(length,
sizeof(BYTE));
1064 const size_t rc = winpr_HexStringToBinBuffer(str, length, buffer, length);
1074char* freerdp_assistance_bin_to_hex_string(
const void* data,
size_t size)
1076 return winpr_BinToHexString(data, size, FALSE);
1080static int freerdp_assistance_parse_uploadinfo(rdpAssistanceFile* file,
char* uploadinfo,
1081 size_t uploadinfosize)
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;
1088 if (!uploadinfo || (uploadinfosize == 0))
1091 const size_t ulen = strnlen(uploadinfo, uploadinfosize);
1092 if (ulen == uploadinfosize)
1094 WLog_WARN(TAG,
"UPLOADINFOR string is not '\\0' terminated");
1098 if (!freerdp_assistance_parse_attr(&typestr, &typelen,
"TYPE", uploadinfo))
1101 if ((typelen != esclen) || (strncmp(typestr, escalated, esclen) != 0))
1104 "Failed to parse ASSISTANCE file: Missing or invalid UPLOADINFO TYPE '%s' [%" PRIuz
1110 char* uploaddata =
nullptr;
1111 size_t uploaddatasize = 0;
1112 if (!freerdp_assistance_consume_input_and_get_element(uploadinfo, ulen,
"UPLOADDATA",
1113 &uploaddata, &uploaddatasize))
1117 if (!freerdp_assistance_parse_attr_str(&file->Username,
"USERNAME", uploaddata))
1121 if (!freerdp_assistance_parse_attr_str(&file->LHTicket,
"LHTICKET", uploaddata))
1125 if (!freerdp_assistance_parse_attr_str(&file->RCTicket,
"RCTICKET", uploaddata))
1129 if (!freerdp_assistance_parse_attr_bool(&file->RCTicketEncrypted,
"RCTICKETENCRYPTED",
1134 if (!freerdp_assistance_parse_attr_str(&file->PassStub,
"PassStub", uploaddata))
1139 const char* amp =
"&";
1140 char* passtub = strstr(file->PassStub, amp);
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);
1151 if (!freerdp_assistance_parse_attr_uint32(&file->DtStart,
"DtStart", uploaddata))
1155 if (!freerdp_assistance_parse_attr_uint32(&file->DtLength,
"DtLength", uploaddata))
1159 if (!freerdp_assistance_parse_attr_bool(&file->LowSpeed,
"L", uploaddata))
1162 file->Type = (file->LHTicket) ? 2 : 1;
1169 file->EncryptedLHTicket = freerdp_assistance_hex_string_to_bin(
1170 file->LHTicket, &file->EncryptedLHTicketLength);
1172 if (!freerdp_assistance_decrypt2(file))
1179 if (!freerdp_assistance_parse_connection_string1(file))
1190 WLog_ERR(TAG,
"freerdp_assistance_parse_connection_string1 failure: %d", status);
1194 file->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(file->password, file->PassStub,
1195 &file->EncryptedPassStubLength);
1197 if (!file->EncryptedPassStub)
1204static int freerdp_assistance_parse_file_buffer_int(rdpAssistanceFile* file,
char* buffer,
1205 size_t size,
const char* password)
1208 WINPR_ASSERT(buffer);
1209 WINPR_ASSERT(size > 0);
1211 if (!update_password(file, password))
1214 char* uploadinfo =
nullptr;
1215 size_t uploadinfosize = 0;
1216 if (freerdp_assistance_consume_input_and_get_element(buffer, size,
"UPLOADINFO", &uploadinfo,
1218 return freerdp_assistance_parse_uploadinfo(file, uploadinfo, uploadinfosize);
1222 freerdp_assistance_contains_element(buffer, size,
"E", &elen,
nullptr,
nullptr);
1223 if (!estr || (elen == 0))
1225 WLog_ERR(TAG,
"Failed to parse ASSISTANCE file: Neither UPLOADINFO nor <E> found");
1228 if (!update_connectionstring2(file, estr, elen))
1231 if (!freerdp_assistance_parse_connection_string2(file))
1237int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file,
const char* cbuffer,
size_t size,
1238 const char* password)
1243 WLog_WARN(TAG,
"empty password supplied");
1246 if (!cbuffer || (size == 0))
1248 WLog_WARN(TAG,
"no data supplied [%p, %" PRIuz
"]",
1249 WINPR_CXX_COMPAT_CAST(
const void*, cbuffer), size);
1253 char* abuffer = strndup(cbuffer, size);
1254 const size_t len = strnlen(cbuffer, size);
1256 WLog_WARN(TAG,
"Input data not '\\0' terminated");
1261 const int rc = freerdp_assistance_parse_file_buffer_int(file, abuffer, len + 1, password);
1266int freerdp_assistance_parse_file(rdpAssistanceFile* file,
const char* name,
const char* password)
1269 BYTE* buffer =
nullptr;
1270 size_t readSize = 0;
1277 if (!update_name(file, name))
1280 FILE* fp = winpr_fopen(name,
"r");
1284 WLog_ERR(TAG,
"Failed to open ASSISTANCE file %s ", name);
1288 if (_fseeki64(fp, 0, SEEK_END) < 0)
1290 fileSize.i64 = _ftelli64(fp);
1291 if (_fseeki64(fp, 0, SEEK_SET) < 0)
1294 if (fileSize.i64 < 1)
1296 WLog_ERR(TAG,
"Failed to read ASSISTANCE file %s ", name);
1300 buffer = (BYTE*)malloc(fileSize.s + 2);
1305 readSize = fread(buffer, fileSize.s, 1, fp);
1310 readSize = fileSize.s;
1315 WLog_ERR(TAG,
"Failed to read ASSISTANCE file %s ", name);
1319 buffer[fileSize.s] =
'\0';
1320 buffer[fileSize.s + 1] =
'\0';
1321 status = freerdp_assistance_parse_file_buffer(file, (
char*)buffer, fileSize.s, password);
1329BOOL freerdp_assistance_populate_settings_from_assistance_file(rdpAssistanceFile* file,
1330 rdpSettings* settings)
1335 if (!file->RASessionId || !file->MachineAddresses)
1351 file->ConnectionString2))
1362 if (ArrayList_Count(file->MachineAddresses) < 1)
1365 const char* addr = ArrayList_GetItem(file->MachineAddresses, 0);
1384 const size_t ports = ArrayList_Count(file->MachinePorts);
1385 const size_t addresses = ArrayList_Count(file->MachineAddresses);
1388 if (ports != addresses)
1396 cnv.data = ArrayList_GetItem(file->MachinePorts, 0);
1397 WINPR_ASSERT(cnv.port <= UINT32_MAX);
1401 if (!freerdp_target_net_adresses_reset(settings, ports))
1404 for (
size_t x = 0; x < ports; x++)
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))
1412 for (
size_t i = 0; i < addresses; i++)
1414 const char* maddr = ArrayList_GetItem(file->MachineAddresses, i);
1415 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_TargetNetAddresses, i, maddr))
1423static BOOL setup_string(wArrayList* list)
1427 wObject* obj = ArrayList_Object(list);
1435rdpAssistanceFile* freerdp_assistance_file_new(
void)
1437 if (!winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT))
1440 rdpAssistanceFile* file = calloc(1,
sizeof(rdpAssistanceFile));
1444 file->MachineAddresses = ArrayList_New(FALSE);
1445 file->MachinePorts = ArrayList_New(FALSE);
1446 file->MachineUris = ArrayList_New(FALSE);
1448 if (!file->MachineAddresses || !file->MachinePorts || !file->MachineUris)
1451 if (!setup_string(file->MachineAddresses) || !setup_string(file->MachineUris))
1457 WINPR_PRAGMA_DIAG_PUSH
1458 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1459 freerdp_assistance_file_free(file);
1460 WINPR_PRAGMA_DIAG_POP
1464void freerdp_assistance_file_free(rdpAssistanceFile* file)
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);
1483 ArrayList_Free(file->MachineAddresses);
1484 ArrayList_Free(file->MachinePorts);
1485 ArrayList_Free(file->MachineUris);
1489void freerdp_assistance_print_file(rdpAssistanceFile* file, wLog* log, DWORD level)
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);
1505 for (
size_t x = 0; x < ArrayList_Count(file->MachineAddresses); x++)
1508 const char* uri =
nullptr;
1509 const char* addr = ArrayList_GetItem(file->MachineAddresses, x);
1510 if (x < ArrayList_Count(file->MachinePorts))
1517 cnv.data = ArrayList_GetItem(file->MachinePorts, x);
1518 WINPR_ASSERT(cnv.port <= UINT32_MAX);
1519 port = (UINT32)cnv.port;
1521 if (x < ArrayList_Count(file->MachineUris))
1522 uri = ArrayList_GetItem(file->MachineUris, x);
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);
1530BOOL freerdp_assistance_get_encrypted_pass_stub(rdpAssistanceFile* file,
const char** pwd,
1533 if (!file || !pwd || !size)
1536 *pwd = (
const char*)file->EncryptedPassStub;
1537 *size = file->EncryptedPassStubLength;
1541int freerdp_assistance_set_connection_string2(rdpAssistanceFile* file,
const char*
string,
1542 const char* password)
1544 if (!file || !
string || !password)
1547 char* str = _strdup(
string);
1551 if (!update_connectionstring2_nocopy(file, str))
1553 if (!update_password(file, password))
1555 return freerdp_assistance_parse_connection_string2(file);
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.
OBJECT_FREE_FN fnObjectFree