Blame libfreerdp/common/assistance.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * Remote Assistance
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <errno.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/wtypes.h>
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/crypto.h>
Packit 1fb8d4
#include <winpr/print.h>
Packit 1fb8d4
#include <winpr/windows.h>
Packit Service 5a9772
#include <winpr/ssl.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
#include <freerdp/client/file.h>
Packit 1fb8d4
#include <freerdp/client/cmdline.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/assistance.h>
Packit 1fb8d4
Packit 1fb8d4
#define TAG FREERDP_TAG("common")
Packit 1fb8d4
Packit Service 5a9772
struct rdp_assistance_file
Packit Service 5a9772
{
Packit Service 5a9772
	UINT32 Type;
Packit Service 5a9772
Packit Service 5a9772
	char* Username;
Packit Service 5a9772
	char* LHTicket;
Packit Service 5a9772
	char* RCTicket;
Packit Service 5a9772
	char* PassStub;
Packit Service 5a9772
	UINT32 DtStart;
Packit Service 5a9772
	UINT32 DtLength;
Packit Service 5a9772
	BOOL LowSpeed;
Packit Service 5a9772
	BOOL RCTicketEncrypted;
Packit Service 5a9772
Packit Service 5a9772
	char* ConnectionString1;
Packit Service 5a9772
	char* ConnectionString2;
Packit Service 5a9772
Packit Service 5a9772
	BYTE* EncryptedPassStub;
Packit Service 5a9772
	size_t EncryptedPassStubLength;
Packit Service 5a9772
Packit Service 5a9772
	BYTE* EncryptedLHTicket;
Packit Service 5a9772
	size_t EncryptedLHTicketLength;
Packit Service 5a9772
Packit Service 5a9772
	UINT32 MachineCount;
Packit Service 5a9772
	char** MachineAddresses;
Packit Service 5a9772
	UINT32* MachinePorts;
Packit Service 5a9772
Packit Service 5a9772
	char* RASessionId;
Packit Service 5a9772
	char* RASpecificParams;
Packit Service 5a9772
Packit Service 5a9772
	char* filename;
Packit Service 5a9772
	char* password;
Packit Service 5a9772
};
Packit Service 5a9772
Packit 1fb8d4
/**
Packit 1fb8d4
 * Password encryption in establishing a remote assistance session of type 1:
Packit 1fb8d4
 * http://blogs.msdn.com/b/openspecification/archive/2011/10/31/password-encryption-in-establishing-a-remote-assistance-session-of-type-1.aspx
Packit 1fb8d4
 *
Packit 1fb8d4
 * Creation of PassStub for the Remote Assistance Ticket:
Packit 1fb8d4
 * http://social.msdn.microsoft.com/Forums/en-US/6316c3f4-ea09-4343-a4a1-9cca46d70d28/creation-of-passstub-for-the-remote-assistance-ticket?forum=os_windowsprotocols
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * CryptDeriveKey Function:
Packit 1fb8d4
 * http://msdn.microsoft.com/en-us/library/windows/desktop/aa379916/
Packit 1fb8d4
 *
Packit 1fb8d4
 * Let n be the required derived key length, in bytes.
Packit 1fb8d4
 * The derived key is the first n bytes of the hash value after the hash computation
Packit 1fb8d4
 * has been completed by CryptDeriveKey. If the hash is not a member of the SHA-2
Packit 1fb8d4
 * family and the required key is for either 3DES or AES, the key is derived as follows:
Packit 1fb8d4
 *
Packit 1fb8d4
 * Form a 64-byte buffer by repeating the constant 0x36 64 times.
Packit 1fb8d4
 * Let k be the length of the hash value that is represented by the input parameter hBaseData.
Packit 1fb8d4
 * Set the first k bytes of the buffer to the result of an XOR operation of the first k bytes
Packit 1fb8d4
 * of the buffer with the hash value that is represented by the input parameter hBaseData.
Packit 1fb8d4
 *
Packit 1fb8d4
 * Form a 64-byte buffer by repeating the constant 0x5C 64 times.
Packit 1fb8d4
 * Set the first k bytes of the buffer to the result of an XOR operation of the first k bytes
Packit 1fb8d4
 * of the buffer with the hash value that is represented by the input parameter hBaseData.
Packit 1fb8d4
 *
Packit 1fb8d4
 * Hash the result of step 1 by using the same hash algorithm as that used to compute the hash
Packit 1fb8d4
 * value that is represented by the hBaseData parameter.
Packit 1fb8d4
 *
Packit 1fb8d4
 * Hash the result of step 2 by using the same hash algorithm as that used to compute the hash
Packit 1fb8d4
 * value that is represented by the hBaseData parameter.
Packit 1fb8d4
 *
Packit 1fb8d4
 * Concatenate the result of step 3 with the result of step 4.
Packit 1fb8d4
 * Use the first n bytes of the result of step 5 as the derived key.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit Service 5a9772
static BOOL freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, size_t hashLength, BYTE* key,
Packit Service 5a9772
                                                     size_t keyLength)
Packit 1fb8d4
{
Packit Service 5a9772
	BOOL rc = FALSE;
Packit Service 5a9772
	size_t i;
Packit 1fb8d4
	BYTE* buffer;
Packit 1fb8d4
	BYTE pad1[64];
Packit 1fb8d4
	BYTE pad2[64];
Packit 1fb8d4
	memset(pad1, 0x36, 64);
Packit 1fb8d4
	memset(pad2, 0x5C, 64);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < hashLength; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		pad1[i] ^= hash[i];
Packit 1fb8d4
		pad2[i] ^= hash[i];
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	buffer = (BYTE*)calloc(hashLength, 2);
Packit 1fb8d4
Packit 1fb8d4
	if (!buffer)
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Digest(WINPR_MD_SHA1, pad1, 64, buffer, hashLength))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Digest(WINPR_MD_SHA1, pad2, 64, &buffer[hashLength], hashLength))
Packit 1fb8d4
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(key, buffer, keyLength);
Packit Service 5a9772
	rc = TRUE;
Packit 1fb8d4
fail:
Packit 1fb8d4
	free(buffer);
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL reallocate(rdpAssistanceFile* file, const char* host, UINT32 port)
Packit 1fb8d4
{
Packit Service 5a9772
	void *tmp1, *tmp2;
Packit Service 5a9772
	file->MachineCount++;
Packit Service 5a9772
	tmp1 = realloc(file->MachinePorts, sizeof(UINT32) * file->MachineCount);
Packit Service 5a9772
	tmp2 = realloc(file->MachineAddresses, sizeof(char*) * file->MachineCount);
Packit 1fb8d4
Packit Service 5a9772
	if (!tmp1 || !tmp2)
Packit 1fb8d4
	{
Packit Service 5a9772
		free(tmp1);
Packit Service 5a9772
		free(tmp2);
Packit Service 5a9772
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	file->MachinePorts = tmp1;
Packit Service 5a9772
	file->MachineAddresses = tmp2;
Packit Service 5a9772
	file->MachinePorts[file->MachineCount - 1] = port;
Packit Service 5a9772
	file->MachineAddresses[file->MachineCount - 1] = _strdup(host);
Packit Service 5a9772
	return TRUE;
Packit Service 5a9772
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL append_address(rdpAssistanceFile* file, const char* host, const char* port)
Packit Service 5a9772
{
Packit Service 5a9772
	unsigned long p;
Packit Service 5a9772
	errno = 0;
Packit Service 5a9772
	p = strtoul(port, NULL, 0);
Packit 1fb8d4
Packit Service 5a9772
	if ((errno != 0) || (p == 0) || (p > UINT16_MAX))
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 invalid port value %s",
Packit Service 5a9772
		         port);
Packit Service 5a9772
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	return reallocate(file, host, (UINT16)p);
Packit Service 5a9772
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list)
Packit Service 5a9772
{
Packit Service 5a9772
	BOOL rc = FALSE;
Packit Service 5a9772
	char* p;
Packit 1fb8d4
Packit Service 5a9772
	if (!file || !list)
Packit Service 5a9772
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	p = list;
Packit 1fb8d4
Packit Service 5a9772
	while ((p = strchr(p, ';')) != NULL)
Packit 1fb8d4
	{
Packit Service 5a9772
		char* q = strchr(p, ':');
Packit 1fb8d4
Packit 1fb8d4
		if (!q)
Packit 1fb8d4
			goto out;
Packit 1fb8d4
Packit Service 5a9772
		*q = '\0';
Packit 1fb8d4
		q++;
Packit 1fb8d4
Packit Service 5a9772
		if (!append_address(file, p, q))
Packit 1fb8d4
			goto out;
Packit 1fb8d4
Packit Service 5a9772
		p = q;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	rc = TRUE;
Packit 1fb8d4
out:
Packit Service 5a9772
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file)
Packit 1fb8d4
{
Packit Service 5a9772
	size_t i;
Packit 1fb8d4
	char* str;
Packit 1fb8d4
	int count;
Packit Service 5a9772
	size_t length;
Packit 1fb8d4
	char* tokens[8];
Packit Service 5a9772
	BOOL rc = FALSE;
Packit Service 5a9772
Packit Service 5a9772
	if (!file || !file->RCTicket)
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * <ProtocolVersion>,<protocolType>,<machineAddressList>,<assistantAccountPwd>,
Packit 1fb8d4
	 * <RASessionID>,<RASessionName>,<RASessionPwd>,<protocolSpecificParms>
Packit 1fb8d4
	 */
Packit 1fb8d4
	count = 1;
Packit 1fb8d4
	str = _strdup(file->RCTicket);
Packit 1fb8d4
Packit 1fb8d4
	if (!str)
Packit Service 5a9772
		goto error;
Packit 1fb8d4
Packit 1fb8d4
	length = strlen(str);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < length; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (str[i] == ',')
Packit 1fb8d4
			count++;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (count != 8)
Packit 1fb8d4
		goto error;
Packit 1fb8d4
Packit 1fb8d4
	count = 0;
Packit 1fb8d4
	tokens[count++] = str;
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < length; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (str[i] == ',')
Packit 1fb8d4
		{
Packit 1fb8d4
			str[i] = '\0';
Packit 1fb8d4
			tokens[count++] = &str[i + 1];
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (strcmp(tokens[0], "65538") != 0)
Packit 1fb8d4
		goto error;
Packit 1fb8d4
Packit 1fb8d4
	if (strcmp(tokens[1], "1") != 0)
Packit 1fb8d4
		goto error;
Packit 1fb8d4
Packit 1fb8d4
	if (strcmp(tokens[3], "*") != 0)
Packit 1fb8d4
		goto error;
Packit 1fb8d4
Packit 1fb8d4
	if (strcmp(tokens[5], "*") != 0)
Packit 1fb8d4
		goto error;
Packit 1fb8d4
Packit 1fb8d4
	if (strcmp(tokens[6], "*") != 0)
Packit 1fb8d4
		goto error;
Packit 1fb8d4
Packit 1fb8d4
	file->RASessionId = _strdup(tokens[4]);
Packit 1fb8d4
Packit 1fb8d4
	if (!file->RASessionId)
Packit 1fb8d4
		goto error;
Packit 1fb8d4
Packit 1fb8d4
	file->RASpecificParams = _strdup(tokens[7]);
Packit 1fb8d4
Packit 1fb8d4
	if (!file->RASpecificParams)
Packit 1fb8d4
		goto error;
Packit 1fb8d4
Packit Service 5a9772
	if (!freerdp_assistance_parse_address_list(file, tokens[2]))
Packit Service 5a9772
		goto error;
Packit Service 5a9772
Packit Service 5a9772
	rc = TRUE;
Packit 1fb8d4
error:
Packit 1fb8d4
	free(str);
Packit Service 5a9772
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Decrypted Connection String 2:
Packit 1fb8d4
 *
Packit 1fb8d4
 * <E>
Packit Service 5a9772
 * 
Packit Service 5a9772
 * ID="+ULZ6ifjoCa6cGPMLQiGHRPwkg6VyJqGwxMnO6GcelwUh9a6/FBq3It5ADSndmLL"/> <C> <T ID="1" SID="0"> 
Packit Service 5a9772
 * P="49228" N="fe80::1032:53d9:5a01:909b%3"/> <L P="49229" N="fe80::3d8f:9b2d:6b4e:6aa%6"/> 
Packit Service 5a9772
 * P="49230" N="192.168.1.200"/> <L P="49231" N="169.254.6.170"/>
Packit 1fb8d4
 * </T>
Packit 1fb8d4
 * </C>
Packit 1fb8d4
 * </E>
Packit 1fb8d4
 */
Packit 1fb8d4
Packit Service 5a9772
static BOOL freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file)
Packit 1fb8d4
{
Packit 1fb8d4
	char* str;
Packit 1fb8d4
	char* tag;
Packit 1fb8d4
	char* end;
Packit 1fb8d4
	char* p;
Packit Service 5a9772
	BOOL rc = FALSE;
Packit Service 5a9772
Packit Service 5a9772
	if (!file || !file->ConnectionString2)
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
Packit 1fb8d4
	str = file->ConnectionString2;
Packit 1fb8d4
Packit 1fb8d4
	if (!strstr(str, "<E>"))
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 missing field <E>");
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!strstr(str, "<C>"))
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 missing field <C>");
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
	}
Packit 1fb8d4
Packit 1fb8d4
	str = _strdup(file->ConnectionString2);
Packit 1fb8d4
Packit 1fb8d4
	if (!str)
Packit Service 5a9772
		goto out_fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!(tag = strstr(str, "
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 missing field 
Packit 1fb8d4
		goto out_fail;
Packit Service 5a9772
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Parse Auth String Node () */
Packit 1fb8d4
	end = strstr(tag, "/>");
Packit 1fb8d4
Packit 1fb8d4
	if (!end)
Packit 1fb8d4
		goto out_fail;
Packit 1fb8d4
Packit 1fb8d4
	*end = '\0';
Packit 1fb8d4
	p = strstr(tag, "KH=\"");
Packit 1fb8d4
Packit 1fb8d4
	if (p)
Packit 1fb8d4
	{
Packit 1fb8d4
		char* q;
Packit 1fb8d4
		size_t length;
Packit 1fb8d4
		p += sizeof("KH=\"") - 1;
Packit 1fb8d4
		q = strchr(p, '"');
Packit 1fb8d4
Packit 1fb8d4
		if (!q)
Packit Service 5a9772
		{
Packit Service 5a9772
			WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 invalid field KH=%s",
Packit Service 5a9772
			         q);
Packit 1fb8d4
			goto out_fail;
Packit Service 5a9772
		}
Packit 1fb8d4
Packit 1fb8d4
		length = q - p;
Packit 1fb8d4
		free(file->RASpecificParams);
Packit Service 5a9772
		file->RASpecificParams = (char*)malloc(length + 1);
Packit 1fb8d4
Packit 1fb8d4
		if (!file->RASpecificParams)
Packit 1fb8d4
			goto out_fail;
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(file->RASpecificParams, p, length);
Packit 1fb8d4
		file->RASpecificParams[length] = '\0';
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	p = strstr(tag, "ID=\"");
Packit 1fb8d4
Packit 1fb8d4
	if (p)
Packit 1fb8d4
	{
Packit 1fb8d4
		char* q;
Packit 1fb8d4
		size_t length;
Packit 1fb8d4
		p += sizeof("ID=\"") - 1;
Packit 1fb8d4
		q = strchr(p, '"');
Packit 1fb8d4
Packit 1fb8d4
		if (!q)
Packit Service 5a9772
		{
Packit Service 5a9772
			WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 invalid field ID=%s",
Packit Service 5a9772
			         q);
Packit 1fb8d4
			goto out_fail;
Packit Service 5a9772
		}
Packit 1fb8d4
Packit 1fb8d4
		length = q - p;
Packit 1fb8d4
		free(file->RASessionId);
Packit Service 5a9772
		file->RASessionId = (char*)malloc(length + 1);
Packit 1fb8d4
Packit 1fb8d4
		if (!file->RASessionId)
Packit 1fb8d4
			goto out_fail;
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(file->RASessionId, p, length);
Packit 1fb8d4
		file->RASessionId[length] = '\0';
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	*end = '/';
Packit 1fb8d4
	/* Parse 
Packit 1fb8d4
	p = strstr(str, "
Packit 1fb8d4
Packit 1fb8d4
	while (p)
Packit 1fb8d4
	{
Packit Service 5a9772
		char* port;
Packit 1fb8d4
		char* q;
Packit 1fb8d4
		size_t length;
Packit 1fb8d4
		p += sizeof("
Packit 1fb8d4
		q = strchr(p, '"');
Packit 1fb8d4
Packit 1fb8d4
		if (!q)
Packit Service 5a9772
		{
Packit Service 5a9772
			WLog_ERR(TAG,
Packit Service 5a9772
			         "Failed to parse ASSISTANCE file: ConnectionString2 invalid field 
Packit 1fb8d4
			goto out_fail;
Packit Service 5a9772
		}
Packit 1fb8d4
Packit 1fb8d4
		q[0] = '\0';
Packit 1fb8d4
		q++;
Packit Service 5a9772
		port = p;
Packit 1fb8d4
		p = strstr(q, " N=\"");
Packit 1fb8d4
Packit 1fb8d4
		if (!p)
Packit Service 5a9772
		{
Packit Service 5a9772
			WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 invalid field N=%s",
Packit Service 5a9772
			         p);
Packit 1fb8d4
			goto out_fail;
Packit Service 5a9772
		}
Packit 1fb8d4
Packit 1fb8d4
		p += sizeof(" N=\"") - 1;
Packit 1fb8d4
		q = strchr(p, '"');
Packit 1fb8d4
Packit 1fb8d4
		if (!q)
Packit Service 5a9772
		{
Packit Service 5a9772
			WLog_ERR(TAG, "Failed to parse ASSISTANCE file: ConnectionString2 invalid field N=%s",
Packit Service 5a9772
			         q);
Packit 1fb8d4
			goto out_fail;
Packit Service 5a9772
		}
Packit 1fb8d4
Packit 1fb8d4
		q[0] = '\0';
Packit 1fb8d4
		q++;
Packit 1fb8d4
		length = strlen(p);
Packit 1fb8d4
Packit 1fb8d4
		if (length > 8)
Packit 1fb8d4
		{
Packit Service 5a9772
			if (!append_address(file, p, port))
Packit Service 5a9772
				goto out_fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		p = strstr(q, "
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	rc = TRUE;
Packit 1fb8d4
out_fail:
Packit 1fb8d4
	free(str);
Packit Service 5a9772
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
char* freerdp_assistance_construct_expert_blob(const char* name, const char* pass)
Packit 1fb8d4
{
Packit Service 5a9772
	size_t size;
Packit Service 5a9772
	size_t nameLength;
Packit Service 5a9772
	size_t passLength;
Packit 1fb8d4
	char* ExpertBlob = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!name || !pass)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	nameLength = strlen(name) + strlen("NAME=");
Packit 1fb8d4
	passLength = strlen(pass) + strlen("PASS=");
Packit 1fb8d4
	size = nameLength + passLength + 64;
Packit Service 5a9772
	ExpertBlob = (char*)calloc(1, size);
Packit 1fb8d4
Packit 1fb8d4
	if (!ExpertBlob)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit Service 5a9772
	sprintf_s(ExpertBlob, size, "%" PRIdz ";NAME=%s%" PRIdz ";PASS=%s", nameLength, name,
Packit Service 5a9772
	          passLength, pass);
Packit 1fb8d4
	return ExpertBlob;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
char* freerdp_assistance_generate_pass_stub(DWORD flags)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 nums[14];
Packit 1fb8d4
	char* passStub = NULL;
Packit 1fb8d4
	char set1[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*_";
Packit 1fb8d4
	char set2[12] = "!@#$&^*()-+=";
Packit 1fb8d4
	char set3[10] = "0123456789";
Packit 1fb8d4
	char set4[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Packit 1fb8d4
	char set5[26] = "abcdefghijklmnopqrstuvwxyz";
Packit Service 5a9772
	passStub = (char*)malloc(15);
Packit 1fb8d4
Packit 1fb8d4
	if (!passStub)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * PassStub generation:
Packit 1fb8d4
	 *
Packit 1fb8d4
	 * Characters 0 and 5-13 are from the set A-Z a-z 0-9 * _
Packit 1fb8d4
	 * Character 1 is from the set !@#$&^*()-+=
Packit 1fb8d4
	 * Character 2 is from the set 0-9
Packit 1fb8d4
	 * Character 3 is from the set A-Z
Packit 1fb8d4
	 * Character 4 is from the set a-z
Packit 1fb8d4
	 *
Packit 1fb8d4
	 * Example: WB^6HsrIaFmEpi
Packit 1fb8d4
	 */
Packit Service 5a9772
	winpr_RAND((BYTE*)nums, sizeof(nums));
Packit Service 5a9772
	passStub[0] = set1[nums[0] % sizeof(set1)];   /* character 0 */
Packit Service 5a9772
	passStub[1] = set2[nums[1] % sizeof(set2)];   /* character 1 */
Packit Service 5a9772
	passStub[2] = set3[nums[2] % sizeof(set3)];   /* character 2 */
Packit Service 5a9772
	passStub[3] = set4[nums[3] % sizeof(set4)];   /* character 3 */
Packit Service 5a9772
	passStub[4] = set5[nums[4] % sizeof(set5)];   /* character 4 */
Packit Service 5a9772
	passStub[5] = set1[nums[5] % sizeof(set1)];   /* character 5 */
Packit Service 5a9772
	passStub[6] = set1[nums[6] % sizeof(set1)];   /* character 6 */
Packit Service 5a9772
	passStub[7] = set1[nums[7] % sizeof(set1)];   /* character 7 */
Packit Service 5a9772
	passStub[8] = set1[nums[8] % sizeof(set1)];   /* character 8 */
Packit Service 5a9772
	passStub[9] = set1[nums[9] % sizeof(set1)];   /* character 9 */
Packit 1fb8d4
	passStub[10] = set1[nums[10] % sizeof(set1)]; /* character 10 */
Packit 1fb8d4
	passStub[11] = set1[nums[11] % sizeof(set1)]; /* character 11 */
Packit 1fb8d4
	passStub[12] = set1[nums[12] % sizeof(set1)]; /* character 12 */
Packit 1fb8d4
	passStub[13] = set1[nums[13] % sizeof(set1)]; /* character 13 */
Packit 1fb8d4
	passStub[14] = '\0';
Packit 1fb8d4
	return passStub;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub,
Packit Service 5a9772
                                           size_t* pEncryptedSize)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL rc;
Packit 1fb8d4
	int status;
Packit Service 5a9772
	size_t cbPasswordW;
Packit Service 5a9772
	size_t cbPassStubW;
Packit Service 5a9772
	size_t EncryptedSize;
Packit 1fb8d4
	BYTE PasswordHash[WINPR_MD5_DIGEST_LENGTH];
Packit Service 5a9772
	WINPR_CIPHER_CTX* rc4Ctx = NULL;
Packit Service 5a9772
	BYTE* pbIn = NULL;
Packit Service 5a9772
	BYTE* pbOut = NULL;
Packit 1fb8d4
	size_t cbOut, cbIn, cbFinal;
Packit 1fb8d4
	WCHAR* PasswordW = NULL;
Packit 1fb8d4
	WCHAR* PassStubW = NULL;
Packit 1fb8d4
	status = ConvertToUnicode(CP_UTF8, 0, password, -1, &PasswordW, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (status <= 0)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit Service 5a9772
	cbPasswordW = (size_t)(status - 1) * 2UL;
Packit 1fb8d4
Packit Service 5a9772
	if (!winpr_Digest(WINPR_MD_MD5, (BYTE*)PasswordW, cbPasswordW, (BYTE*)PasswordHash,
Packit 1fb8d4
	                  sizeof(PasswordHash)))
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	status = ConvertToUnicode(CP_UTF8, 0, passStub, -1, &PassStubW, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (status <= 0)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	cbPassStubW = (size_t)(status - 1) * 2UL;
Packit 1fb8d4
	EncryptedSize = cbPassStubW + 4;
Packit Service 5a9772
	pbIn = (BYTE*)calloc(1, EncryptedSize);
Packit Service 5a9772
	pbOut = (BYTE*)calloc(1, EncryptedSize);
Packit 1fb8d4
Packit 1fb8d4
	if (!pbIn || !pbOut)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	*((UINT32*)pbIn) = (UINT32)cbPassStubW;
Packit 1fb8d4
	CopyMemory(&pbIn[4], PassStubW, cbPassStubW);
Packit Service 5a9772
	rc4Ctx = winpr_Cipher_New(WINPR_CIPHER_ARC4_128, WINPR_ENCRYPT, PasswordHash, NULL);
Packit 1fb8d4
Packit 1fb8d4
	if (!rc4Ctx)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "winpr_Cipher_New failure");
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	cbOut = cbFinal = 0;
Packit 1fb8d4
	cbIn = EncryptedSize;
Packit 1fb8d4
	rc = winpr_Cipher_Update(rc4Ctx, pbIn, cbIn, pbOut, &cbOut);
Packit 1fb8d4
Packit 1fb8d4
	if (!rc)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "winpr_Cipher_Update failure");
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Cipher_Final(rc4Ctx, pbOut + cbOut, &cbFinal))
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "winpr_Cipher_Final failure");
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	winpr_Cipher_Free(rc4Ctx);
Packit Service 5a9772
	free(pbIn);
Packit Service 5a9772
	free(PasswordW);
Packit Service 5a9772
	free(PassStubW);
Packit 1fb8d4
	*pEncryptedSize = EncryptedSize;
Packit 1fb8d4
	return pbOut;
Packit Service 5a9772
fail:
Packit Service 5a9772
	winpr_Cipher_Free(rc4Ctx);
Packit Service 5a9772
	free(PasswordW);
Packit Service 5a9772
	free(PassStubW);
Packit Service 5a9772
	free(pbIn);
Packit Service 5a9772
	free(pbOut);
Packit Service 5a9772
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password)
Packit 1fb8d4
{
Packit Service 5a9772
	BOOL rc = FALSE;
Packit Service 5a9772
	int status = 0;
Packit Service 5a9772
	size_t cbPasswordW;
Packit 1fb8d4
	int cchOutW = 0;
Packit 1fb8d4
	WCHAR* pbOutW = NULL;
Packit Service 5a9772
	WINPR_CIPHER_CTX* aesDec = NULL;
Packit 1fb8d4
	WCHAR* PasswordW = NULL;
Packit Service 5a9772
	BYTE* pbIn = NULL;
Packit Service 5a9772
	BYTE* pbOut = NULL;
Packit 1fb8d4
	size_t cbOut, cbIn, cbFinal;
Packit 1fb8d4
	BYTE DerivedKey[WINPR_AES_BLOCK_SIZE];
Packit 1fb8d4
	BYTE InitializationVector[WINPR_AES_BLOCK_SIZE];
Packit 1fb8d4
	BYTE PasswordHash[WINPR_SHA1_DIGEST_LENGTH];
Packit 1fb8d4
Packit Service 5a9772
	if (!file || !password)
Packit Service 5a9772
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	status = ConvertToUnicode(CP_UTF8, 0, password, -1, &PasswordW, 0);
Packit 1fb8d4
Packit Service 5a9772
	if (status <= 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Conversion from UCS2 to UTF8 failed");
Packit Service 5a9772
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	cbPasswordW = (size_t)(status - 1) * 2UL;
Packit 1fb8d4
Packit Service 5a9772
	if (!winpr_Digest(WINPR_MD_SHA1, (BYTE*)PasswordW, cbPasswordW, PasswordHash,
Packit Service 5a9772
	                  sizeof(PasswordHash)))
Packit Service 5a9772
		goto fail;
Packit Service 5a9772
Packit Service 5a9772
	if (!freerdp_assistance_crypt_derive_key_sha1(PasswordHash, sizeof(PasswordHash), DerivedKey,
Packit Service 5a9772
	                                              sizeof(DerivedKey)))
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	ZeroMemory(InitializationVector, sizeof(InitializationVector));
Packit Service 5a9772
	aesDec =
Packit Service 5a9772
	    winpr_Cipher_New(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, DerivedKey, InitializationVector);
Packit 1fb8d4
Packit 1fb8d4
	if (!aesDec)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	cbOut = cbFinal = 0;
Packit Service 5a9772
	cbIn = (size_t)file->EncryptedLHTicketLength;
Packit Service 5a9772
	pbIn = (BYTE*)file->EncryptedLHTicket;
Packit Service 5a9772
	pbOut = (BYTE*)calloc(1, cbIn + WINPR_AES_BLOCK_SIZE + 2);
Packit 1fb8d4
Packit 1fb8d4
	if (!pbOut)
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Cipher_Update(aesDec, pbIn, cbIn, pbOut, &cbOut))
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Cipher_Final(aesDec, pbOut + cbOut, &cbFinal))
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "winpr_Cipher_Final failure");
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	cbOut += cbFinal;
Packit 1fb8d4
	cbFinal = 0;
Packit Service 5a9772
	pbOutW = (WCHAR*)pbOut;
Packit Service 5a9772
Packit Service 5a9772
	if (cbOut > INT_MAX / 2)
Packit Service 5a9772
		goto fail;
Packit Service 5a9772
Packit Service 5a9772
	cchOutW = (int)cbOut / 2;
Packit 1fb8d4
	file->ConnectionString2 = NULL;
Packit Service 5a9772
	status =
Packit Service 5a9772
	    ConvertFromUnicode(CP_UTF8, 0, pbOutW, cchOutW, &file->ConnectionString2, 0, NULL, NULL);
Packit 1fb8d4
Packit 1fb8d4
	if (status <= 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Conversion from UCS2 to UTF8 failed");
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	if (!freerdp_assistance_parse_connection_string2(file))
Packit Service 5a9772
		goto fail;
Packit 1fb8d4
Packit Service 5a9772
	rc = TRUE;
Packit Service 5a9772
fail:
Packit Service 5a9772
	winpr_Cipher_Free(aesDec);
Packit Service 5a9772
	free(PasswordW);
Packit Service 5a9772
	free(pbOut);
Packit Service 5a9772
	WLog_DBG(TAG, "freerdp_assistance_parse_connection_string2: %d", status);
Packit Service 5a9772
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BYTE* freerdp_assistance_hex_string_to_bin(const void* raw, size_t* size)
Packit 1fb8d4
{
Packit Service 5a9772
	size_t length;
Packit 1fb8d4
	BYTE* buffer;
Packit Service 5a9772
	size_t i;
Packit Service 5a9772
	const char* str = (const char*)raw;
Packit 1fb8d4
	length = strlen(str);
Packit 1fb8d4
Packit 1fb8d4
	if ((length % 2) != 0)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	length /= 2;
Packit 1fb8d4
	*size = length;
Packit Service 5a9772
	buffer = (BYTE*)malloc(length);
Packit 1fb8d4
Packit 1fb8d4
	if (!buffer)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < length; i++)
Packit 1fb8d4
	{
Packit Service 5a9772
		int hn, ln;
Packit Service 5a9772
		char c;
Packit 1fb8d4
		hn = ln = 0;
Packit 1fb8d4
		c = str[(i * 2) + 0];
Packit 1fb8d4
Packit 1fb8d4
		if ((c >= '0') && (c <= '9'))
Packit 1fb8d4
			hn = c - '0';
Packit 1fb8d4
		else if ((c >= 'a') && (c <= 'f'))
Packit 1fb8d4
			hn = (c - 'a') + 10;
Packit 1fb8d4
		else if ((c >= 'A') && (c <= 'F'))
Packit 1fb8d4
			hn = (c - 'A') + 10;
Packit 1fb8d4
Packit 1fb8d4
		c = str[(i * 2) + 1];
Packit 1fb8d4
Packit 1fb8d4
		if ((c >= '0') && (c <= '9'))
Packit 1fb8d4
			ln = c - '0';
Packit 1fb8d4
		else if ((c >= 'a') && (c <= 'f'))
Packit 1fb8d4
			ln = (c - 'a') + 10;
Packit 1fb8d4
		else if ((c >= 'A') && (c <= 'F'))
Packit 1fb8d4
			ln = (c - 'A') + 10;
Packit 1fb8d4
Packit Service 5a9772
		buffer[i] = ((hn << 4) | ln) & 0xFF;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return buffer;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
char* freerdp_assistance_bin_to_hex_string(const void* raw, size_t size)
Packit 1fb8d4
{
Packit Service 5a9772
	size_t i;
Packit 1fb8d4
	char* p;
Packit 1fb8d4
	int ln, hn;
Packit Service 5a9772
	const char* data = (const char*)raw;
Packit 1fb8d4
	char bin2hex[] = "0123456789ABCDEF";
Packit Service 5a9772
	p = (char*)calloc((size + 1), 2);
Packit 1fb8d4
Packit 1fb8d4
	if (!p)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < size; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		ln = data[i] & 0xF;
Packit 1fb8d4
		hn = (data[i] >> 4) & 0xF;
Packit 1fb8d4
		p[i * 2] = bin2hex[hn];
Packit 1fb8d4
		p[(i * 2) + 1] = bin2hex[ln];
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	p[size * 2] = '\0';
Packit 1fb8d4
	return p;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* buffer, size_t size,
Packit Service 5a9772
                                         const char* password)
Packit 1fb8d4
{
Packit 1fb8d4
	char* p;
Packit 1fb8d4
	char* q;
Packit 1fb8d4
	char* r;
Packit 1fb8d4
	int status;
Packit 1fb8d4
	size_t length;
Packit 1fb8d4
	p = strstr(buffer, "UPLOADINFO");
Packit 1fb8d4
Packit Service 5a9772
	if (p)
Packit Service 5a9772
	{
Packit Service 5a9772
		p = strstr(p + sizeof("UPLOADINFO") - 1, "TYPE=\"");
Packit 1fb8d4
Packit Service 5a9772
		if (!p)
Packit Service 5a9772
		{
Packit Service 5a9772
			WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Missing UPLOADINFO TYPE");
Packit Service 5a9772
			return -1;
Packit Service 5a9772
		}
Packit 1fb8d4
Packit Service 5a9772
		p = strstr(buffer, "UPLOADDATA");
Packit 1fb8d4
Packit Service 5a9772
		if (!p)
Packit Service 5a9772
		{
Packit Service 5a9772
			WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Missing UPLOADDATA");
Packit Service 5a9772
			return -1;
Packit Service 5a9772
		}
Packit 1fb8d4
Packit Service 5a9772
		/* Parse USERNAME */
Packit Service 5a9772
		p = strstr(buffer, "USERNAME=\"");
Packit 1fb8d4
Packit Service 5a9772
		if (p)
Packit Service 5a9772
		{
Packit Service 5a9772
			p += sizeof("USERNAME=\"") - 1;
Packit Service 5a9772
			q = strchr(p, '"');
Packit 1fb8d4
Packit Service 5a9772
			if (!q)
Packit Service 5a9772
			{
Packit Service 5a9772
				WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid USERNAME=%s", p);
Packit Service 5a9772
				return -1;
Packit Service 5a9772
			}
Packit 1fb8d4
Packit Service 5a9772
			length = q - p;
Packit Service 5a9772
			file->Username = (char*)malloc(length + 1);
Packit 1fb8d4
Packit Service 5a9772
			if (!file->Username)
Packit Service 5a9772
				return -1;
Packit 1fb8d4
Packit Service 5a9772
			CopyMemory(file->Username, p, length);
Packit Service 5a9772
			file->Username[length] = '\0';
Packit Service 5a9772
		}
Packit 1fb8d4
Packit Service 5a9772
		/* Parse LHTICKET */
Packit Service 5a9772
		p = strstr(buffer, "LHTICKET=\"");
Packit 1fb8d4
Packit Service 5a9772
		if (p)
Packit Service 5a9772
		{
Packit Service 5a9772
			p += sizeof("LHTICKET=\"") - 1;
Packit Service 5a9772
			q = strchr(p, '"');
Packit 1fb8d4
Packit Service 5a9772
			if (!q)
Packit Service 5a9772
			{
Packit Service 5a9772
				WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid LHTICKET=%s", p);
Packit Service 5a9772
				return -1;
Packit Service 5a9772
			}
Packit 1fb8d4
Packit Service 5a9772
			length = q - p;
Packit Service 5a9772
			file->LHTicket = (char*)malloc(length + 1);
Packit 1fb8d4
Packit Service 5a9772
			if (!file->LHTicket)
Packit Service 5a9772
				return -1;
Packit 1fb8d4
Packit Service 5a9772
			CopyMemory(file->LHTicket, p, length);
Packit Service 5a9772
			file->LHTicket[length] = '\0';
Packit Service 5a9772
		}
Packit 1fb8d4
Packit Service 5a9772
		/* Parse RCTICKET */
Packit Service 5a9772
		p = strstr(buffer, "RCTICKET=\"");
Packit 1fb8d4
Packit Service 5a9772
		if (p)
Packit Service 5a9772
		{
Packit Service 5a9772
			p += sizeof("RCTICKET=\"") - 1;
Packit Service 5a9772
			q = strchr(p, '"');
Packit 1fb8d4
Packit Service 5a9772
			if (!q)
Packit Service 5a9772
			{
Packit Service 5a9772
				WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid RCTICKET=%s", p);
Packit Service 5a9772
				return -1;
Packit Service 5a9772
			}
Packit 1fb8d4
Packit Service 5a9772
			length = q - p;
Packit Service 5a9772
			file->RCTicket = (char*)malloc(length + 1);
Packit 1fb8d4
Packit Service 5a9772
			if (!file->RCTicket)
Packit Service 5a9772
				return -1;
Packit 1fb8d4
Packit Service 5a9772
			CopyMemory(file->RCTicket, p, length);
Packit Service 5a9772
			file->RCTicket[length] = '\0';
Packit Service 5a9772
		}
Packit 1fb8d4
Packit Service 5a9772
		/* Parse RCTICKETENCRYPTED */
Packit Service 5a9772
		p = strstr(buffer, "RCTICKETENCRYPTED=\"");
Packit 1fb8d4
Packit Service 5a9772
		if (p)
Packit Service 5a9772
		{
Packit Service 5a9772
			p += sizeof("RCTICKETENCRYPTED=\"") - 1;
Packit Service 5a9772
			q = strchr(p, '"');
Packit 1fb8d4
Packit Service 5a9772
			if (!q)
Packit Service 5a9772
			{
Packit Service 5a9772
				WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid RCTICKETENCRYPTED=%s", p);
Packit Service 5a9772
				return -1;
Packit Service 5a9772
			}
Packit 1fb8d4
Packit Service 5a9772
			length = q - p;
Packit 1fb8d4
Packit Service 5a9772
			if ((length == 1) && (p[0] == '1'))
Packit Service 5a9772
				file->RCTicketEncrypted = TRUE;
Packit Service 5a9772
		}
Packit 1fb8d4
Packit Service 5a9772
		/* Parse PassStub */
Packit Service 5a9772
		p = strstr(buffer, "PassStub=\"");
Packit 1fb8d4
Packit Service 5a9772
		if (p)
Packit Service 5a9772
		{
Packit Service 5a9772
			p += sizeof("PassStub=\"") - 1;
Packit Service 5a9772
			q = strchr(p, '"');
Packit 1fb8d4
Packit Service 5a9772
			if (!q)
Packit Service 5a9772
			{
Packit Service 5a9772
				WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid PassStub=%s", p);
Packit Service 5a9772
				return -1;
Packit Service 5a9772
			}
Packit 1fb8d4
Packit Service 5a9772
			length = q - p;
Packit Service 5a9772
			file->PassStub = (char*)malloc(length + 1);
Packit 1fb8d4
Packit Service 5a9772
			if (!file->PassStub)
Packit Service 5a9772
				return -1;
Packit 1fb8d4
Packit Service 5a9772
			CopyMemory(file->PassStub, p, length);
Packit Service 5a9772
			file->PassStub[length] = '\0';
Packit Service 5a9772
		}
Packit 1fb8d4
Packit Service 5a9772
		/* Parse DtStart */
Packit Service 5a9772
		p = strstr(buffer, "DtStart=\"");
Packit 1fb8d4
Packit Service 5a9772
		if (p)
Packit Service 5a9772
		{
Packit Service 5a9772
			p += sizeof("DtStart=\"") - 1;
Packit Service 5a9772
			q = strchr(p, '"');
Packit 1fb8d4
Packit Service 5a9772
			if (!q)
Packit Service 5a9772
			{
Packit Service 5a9772
				WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid DtStart=%s", p);
Packit Service 5a9772
				return -1;
Packit Service 5a9772
			}
Packit 1fb8d4
Packit Service 5a9772
			length = q - p;
Packit Service 5a9772
			r = (char*)malloc(length + 1);
Packit 1fb8d4
Packit Service 5a9772
			if (!r)
Packit Service 5a9772
				return -1;
Packit 1fb8d4
Packit Service 5a9772
			CopyMemory(r, p, length);
Packit Service 5a9772
			r[length] = '\0';
Packit Service 5a9772
			errno = 0;
Packit Service 5a9772
			{
Packit Service 5a9772
				unsigned long val = strtoul(r, NULL, 0);
Packit 1fb8d4
Packit Service 5a9772
				if ((errno != 0) || (val > UINT32_MAX))
Packit Service 5a9772
				{
Packit Service 5a9772
					WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid DtStart value %s", r);
Packit Service 5a9772
					free(r);
Packit Service 5a9772
					return -1;
Packit Service 5a9772
				}
Packit Service 5a9772
Packit Service 5a9772
				free(r);
Packit Service 5a9772
				file->DtStart = val;
Packit Service 5a9772
			}
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		/* Parse DtLength */
Packit Service 5a9772
		p = strstr(buffer, "DtLength=\"");
Packit Service 5a9772
Packit Service 5a9772
		if (p)
Packit 1fb8d4
		{
Packit Service 5a9772
			p += sizeof("DtLength=\"") - 1;
Packit Service 5a9772
			q = strchr(p, '"');
Packit 1fb8d4
Packit Service 5a9772
			if (!q)
Packit Service 5a9772
			{
Packit Service 5a9772
				WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid DtLength=%s", p);
Packit 1fb8d4
				return -1;
Packit Service 5a9772
			}
Packit Service 5a9772
Packit Service 5a9772
			length = q - p;
Packit Service 5a9772
			r = (char*)malloc(length + 1);
Packit Service 5a9772
Packit Service 5a9772
			if (!r)
Packit Service 5a9772
				return -1;
Packit Service 5a9772
Packit Service 5a9772
			CopyMemory(r, p, length);
Packit Service 5a9772
			r[length] = '\0';
Packit Service 5a9772
			errno = 0;
Packit Service 5a9772
			{
Packit Service 5a9772
				unsigned long val = strtoul(r, NULL, 0);
Packit 1fb8d4
Packit Service 5a9772
				if ((errno != 0) || (val > UINT32_MAX))
Packit Service 5a9772
				{
Packit Service 5a9772
					WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid DtLength value %s", r);
Packit Service 5a9772
					free(r);
Packit Service 5a9772
					return -1;
Packit Service 5a9772
				}
Packit Service 5a9772
Packit Service 5a9772
				free(r);
Packit Service 5a9772
				file->DtLength = val;
Packit Service 5a9772
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit Service 5a9772
		/* Parse L (LowSpeed) */
Packit Service 5a9772
		p = strstr(buffer, " L=\"");
Packit 1fb8d4
Packit Service 5a9772
		if (p)
Packit Service 5a9772
		{
Packit Service 5a9772
			p += sizeof(" L=\"") - 1;
Packit Service 5a9772
			q = strchr(p, '"');
Packit 1fb8d4
Packit Service 5a9772
			if (!q)
Packit Service 5a9772
			{
Packit Service 5a9772
				WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Invalid L=%s", p);
Packit Service 5a9772
				return -1;
Packit Service 5a9772
			}
Packit 1fb8d4
Packit Service 5a9772
			length = q - p;
Packit 1fb8d4
Packit Service 5a9772
			if ((length == 1) && (p[0] == '1'))
Packit Service 5a9772
				file->LowSpeed = TRUE;
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		file->Type = (file->LHTicket) ? 2 : 1;
Packit Service 5a9772
		status = 0;
Packit 1fb8d4
Packit Service 5a9772
		switch (file->Type)
Packit 1fb8d4
		{
Packit Service 5a9772
			case 2:
Packit Service 5a9772
			{
Packit Service 5a9772
				file->EncryptedLHTicket = freerdp_assistance_hex_string_to_bin(
Packit Service 5a9772
				    file->LHTicket, &file->EncryptedLHTicketLength);
Packit Service 5a9772
Packit Service 5a9772
				if (!freerdp_assistance_decrypt2(file, password))
Packit Service 5a9772
					status = -1;
Packit Service 5a9772
			}
Packit Service 5a9772
			break;
Packit 1fb8d4
Packit Service 5a9772
			case 1:
Packit Service 5a9772
			{
Packit Service 5a9772
				if (!freerdp_assistance_parse_connection_string1(file))
Packit Service 5a9772
					status = -1;
Packit Service 5a9772
			}
Packit Service 5a9772
			break;
Packit Service 5a9772
Packit Service 5a9772
			default:
Packit 1fb8d4
				return -1;
Packit Service 5a9772
		}
Packit 1fb8d4
Packit Service 5a9772
		if (status < 0)
Packit Service 5a9772
		{
Packit Service 5a9772
			WLog_ERR(TAG, "freerdp_assistance_parse_connection_string1 failure: %d", status);
Packit Service 5a9772
			return -1;
Packit 1fb8d4
		}
Packit Service 5a9772
Packit Service 5a9772
		file->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(
Packit Service 5a9772
		    password, file->PassStub, &file->EncryptedPassStubLength);
Packit Service 5a9772
Packit Service 5a9772
		if (!file->EncryptedPassStub)
Packit Service 5a9772
			return -1;
Packit Service 5a9772
Packit Service 5a9772
		return 1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	p = strstr(buffer, "<E>");
Packit 1fb8d4
Packit 1fb8d4
	if (p)
Packit 1fb8d4
	{
Packit Service 5a9772
		q = strstr(buffer, "</E>");
Packit 1fb8d4
Packit 1fb8d4
		if (!q)
Packit Service 5a9772
		{
Packit Service 5a9772
			WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Missing </E> tag");
Packit 1fb8d4
			return -1;
Packit Service 5a9772
		}
Packit 1fb8d4
Packit Service 5a9772
		q += sizeof("</E>") - 1;
Packit 1fb8d4
		length = q - p;
Packit Service 5a9772
		file->ConnectionString2 = (char*)malloc(length + 1);
Packit 1fb8d4
Packit Service 5a9772
		if (!file->ConnectionString2)
Packit Service 5a9772
			return -1;
Packit 1fb8d4
Packit Service 5a9772
		CopyMemory(file->ConnectionString2, p, length);
Packit Service 5a9772
		file->ConnectionString2[length] = '\0';
Packit 1fb8d4
Packit Service 5a9772
		if (!freerdp_assistance_parse_connection_string2(file))
Packit Service 5a9772
			return -1;
Packit 1fb8d4
Packit Service 5a9772
		return 1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	WLog_ERR(TAG, "Failed to parse ASSISTANCE file: Neither UPLOADINFO nor <E> found");
Packit Service 5a9772
	return -1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
int freerdp_assistance_parse_file(rdpAssistanceFile* file, const char* name, const char* password)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
	BYTE* buffer;
Packit 1fb8d4
	FILE* fp = NULL;
Packit 1fb8d4
	size_t readSize;
Packit 1fb8d4
	INT64 fileSize;
Packit 1fb8d4
Packit 1fb8d4
	if (!name)
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_ERR(TAG, "ASSISTANCE file %s invalid name", name);
Packit 1fb8d4
		return -1;
Packit Service 5a9772
	}
Packit 1fb8d4
Packit Service 5a9772
	free(file->filename);
Packit Service 5a9772
	free(file->password);
Packit Service 5a9772
	file->filename = _strdup(name);
Packit Service 5a9772
	file->password = _strdup(password);
Packit 1fb8d4
	fp = fopen(name, "r");
Packit 1fb8d4
Packit 1fb8d4
	if (!fp)
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Failed to open ASSISTANCE file %s ", name);
Packit 1fb8d4
		return -1;
Packit Service 5a9772
	}
Packit 1fb8d4
Packit 1fb8d4
	_fseeki64(fp, 0, SEEK_END);
Packit 1fb8d4
	fileSize = _ftelli64(fp);
Packit 1fb8d4
	_fseeki64(fp, 0, SEEK_SET);
Packit 1fb8d4
Packit 1fb8d4
	if (fileSize < 1)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Failed to read ASSISTANCE file %s ", name);
Packit 1fb8d4
		fclose(fp);
Packit 1fb8d4
		return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	buffer = (BYTE*)malloc(fileSize + 2);
Packit 1fb8d4
Packit 1fb8d4
	if (!buffer)
Packit 1fb8d4
	{
Packit 1fb8d4
		fclose(fp);
Packit 1fb8d4
		return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	readSize = fread(buffer, fileSize, 1, fp);
Packit 1fb8d4
Packit 1fb8d4
	if (!readSize)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!ferror(fp))
Packit 1fb8d4
			readSize = fileSize;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	fclose(fp);
Packit 1fb8d4
Packit 1fb8d4
	if (readSize < 1)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Failed to read ASSISTANCE file %s ", name);
Packit 1fb8d4
		free(buffer);
Packit 1fb8d4
		buffer = NULL;
Packit 1fb8d4
		return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	buffer[fileSize] = '\0';
Packit 1fb8d4
	buffer[fileSize + 1] = '\0';
Packit Service 5a9772
	status = freerdp_assistance_parse_file_buffer(file, (char*)buffer, fileSize, password);
Packit 1fb8d4
	free(buffer);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL freerdp_assistance_populate_settings_from_assistance_file(rdpAssistanceFile* file,
Packit Service 5a9772
                                                               rdpSettings* settings)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 i;
Packit 1fb8d4
Packit Service 5a9772
	if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteAssistanceMode, TRUE))
Packit Service 5a9772
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	if (!file->RASessionId || !file->MachineAddresses)
Packit Service 5a9772
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	if (!freerdp_settings_set_string(settings, FreeRDP_RemoteAssistanceSessionId,
Packit Service 5a9772
	                                 file->RASessionId))
Packit Service 5a9772
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	if (file->RCTicket)
Packit Service 5a9772
	{
Packit Service 5a9772
		if (!freerdp_settings_set_string(settings, FreeRDP_RemoteAssistanceRCTicket,
Packit Service 5a9772
		                                 file->RCTicket))
Packit Service 5a9772
			return FALSE;
Packit Service 5a9772
	}
Packit Service 5a9772
	else
Packit Service 5a9772
	{
Packit Service 5a9772
		if (!freerdp_settings_set_string(settings, FreeRDP_RemoteAssistanceRCTicket,
Packit Service 5a9772
		                                 file->ConnectionString2))
Packit Service 5a9772
			return FALSE;
Packit Service 5a9772
	}
Packit 1fb8d4
Packit Service 5a9772
	if (file->PassStub)
Packit Service 5a9772
	{
Packit Service 5a9772
		if (!freerdp_settings_set_string(settings, FreeRDP_RemoteAssistancePassStub,
Packit Service 5a9772
		                                 file->PassStub))
Packit Service 5a9772
			return FALSE;
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	if (!freerdp_settings_set_string(settings, FreeRDP_ServerHostname, file->MachineAddresses[0]))
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
Packit Service 5a9772
	if (!freerdp_settings_set_string(settings, FreeRDP_AssistanceFile, file->filename))
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
Packit Service 5a9772
	if (!freerdp_settings_set_string(settings, FreeRDP_RemoteAssistancePassword, file->password))
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
Packit Service 5a9772
	if (file->Username)
Packit Service 5a9772
	{
Packit Service 5a9772
		if (!freerdp_settings_set_string(settings, FreeRDP_Username, file->Username))
Packit Service 5a9772
			return FALSE;
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	settings->RemoteAssistanceMode = TRUE;
Packit Service 5a9772
Packit Service 5a9772
	if (!freerdp_settings_set_uint32(settings, FreeRDP_ServerPort, file->MachinePorts[0]))
Packit Service 5a9772
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	freerdp_target_net_addresses_free(settings);
Packit 1fb8d4
	settings->TargetNetAddressCount = file->MachineCount;
Packit 1fb8d4
Packit 1fb8d4
	if (settings->TargetNetAddressCount)
Packit 1fb8d4
	{
Packit Service 5a9772
		settings->TargetNetAddresses = (char**)calloc(file->MachineCount, sizeof(char*));
Packit Service 5a9772
		settings->TargetNetPorts = (UINT32*)calloc(file->MachineCount, sizeof(UINT32));
Packit 1fb8d4
Packit 1fb8d4
		if (!settings->TargetNetAddresses || !settings->TargetNetPorts)
Packit Service 5a9772
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		for (i = 0; i < settings->TargetNetAddressCount; i++)
Packit 1fb8d4
		{
Packit 1fb8d4
			settings->TargetNetAddresses[i] = _strdup(file->MachineAddresses[i]);
Packit 1fb8d4
			settings->TargetNetPorts[i] = file->MachinePorts[i];
Packit 1fb8d4
Packit 1fb8d4
			if (!settings->TargetNetAddresses[i])
Packit Service 5a9772
				return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
rdpAssistanceFile* freerdp_assistance_file_new(void)
Packit 1fb8d4
{
Packit Service 5a9772
	winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
Packit Service 5a9772
	return (rdpAssistanceFile*)calloc(1, sizeof(rdpAssistanceFile));
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void freerdp_assistance_file_free(rdpAssistanceFile* file)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 i;
Packit 1fb8d4
Packit 1fb8d4
	if (!file)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit Service 5a9772
	free(file->filename);
Packit Service 5a9772
	free(file->password);
Packit 1fb8d4
	free(file->Username);
Packit 1fb8d4
	free(file->LHTicket);
Packit 1fb8d4
	free(file->RCTicket);
Packit 1fb8d4
	free(file->PassStub);
Packit 1fb8d4
	free(file->ConnectionString1);
Packit 1fb8d4
	free(file->ConnectionString2);
Packit 1fb8d4
	free(file->EncryptedLHTicket);
Packit 1fb8d4
	free(file->RASessionId);
Packit 1fb8d4
	free(file->RASpecificParams);
Packit 1fb8d4
	free(file->EncryptedPassStub);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < file->MachineCount; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		free(file->MachineAddresses[i]);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(file->MachineAddresses);
Packit 1fb8d4
	free(file->MachinePorts);
Packit 1fb8d4
	free(file);
Packit 1fb8d4
}
Packit Service 5a9772
Packit Service 5a9772
void freerdp_assistance_print_file(rdpAssistanceFile* file, wLog* log, DWORD level)
Packit Service 5a9772
{
Packit Service 5a9772
	size_t x;
Packit Service 5a9772
	WLog_Print(log, level, "Username: %s", file->Username);
Packit Service 5a9772
	WLog_Print(log, level, "LHTicket: %s", file->LHTicket);
Packit Service 5a9772
	WLog_Print(log, level, "RCTicket: %s", file->RCTicket);
Packit Service 5a9772
	WLog_Print(log, level, "RCTicketEncrypted: %" PRId32, file->RCTicketEncrypted);
Packit Service 5a9772
	WLog_Print(log, level, "PassStub: %s", file->PassStub);
Packit Service 5a9772
	WLog_Print(log, level, "DtStart: %" PRIu32, file->DtStart);
Packit Service 5a9772
	WLog_Print(log, level, "DtLength: %" PRIu32, file->DtLength);
Packit Service 5a9772
	WLog_Print(log, level, "LowSpeed: %" PRId32, file->LowSpeed);
Packit Service 5a9772
	WLog_Print(log, level, "RASessionId: %s", file->RASessionId);
Packit Service 5a9772
	WLog_Print(log, level, "RASpecificParams: %s", file->RASpecificParams);
Packit Service 5a9772
Packit Service 5a9772
	for (x = 0; x < file->MachineCount; x++)
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_Print(log, level, "MachineAddress [%" PRIdz ": %s", x, file->MachineAddresses[x]);
Packit Service 5a9772
		WLog_Print(log, level, "MachinePort    [%" PRIdz ": %" PRIu32, x, file->MachinePorts[x]);
Packit Service 5a9772
	}
Packit Service 5a9772
}
Packit Service 5a9772
Packit Service 5a9772
BOOL freerdp_assistance_get_encrypted_pass_stub(rdpAssistanceFile* file, const char** pwd,
Packit Service 5a9772
                                                size_t* size)
Packit Service 5a9772
{
Packit Service 5a9772
	if (!file || !pwd || !size)
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
Packit Service 5a9772
	*pwd = (const char*)file->EncryptedPassStub;
Packit Service 5a9772
	*size = file->EncryptedPassStubLength;
Packit Service 5a9772
	return TRUE;
Packit Service 5a9772
}
Packit Service 5a9772
Packit Service 5a9772
int freerdp_assistance_set_connection_string2(rdpAssistanceFile* file, const char* string,
Packit Service 5a9772
                                              const char* password)
Packit Service 5a9772
{
Packit Service 5a9772
	if (!file || !string || !password)
Packit Service 5a9772
		return -1;
Packit Service 5a9772
Packit Service 5a9772
	free(file->ConnectionString2);
Packit Service 5a9772
	free(file->password);
Packit Service 5a9772
	file->ConnectionString2 = _strdup(string);
Packit Service 5a9772
	file->password = _strdup(password);
Packit Service 5a9772
	return freerdp_assistance_parse_connection_string2(file);
Packit Service 5a9772
}