Commit message: Fix CVE-2014-0791

This patch fixes CVE-2014-0791, the remaining length in the stream is checked
before doing some malloc().
CVE: CVE-2014-0791
CWE: CWE-189
Vulnerability description: Integer overflow in the license_read_scope_list function in libfreerdp/core/license.c in FreeRDP through 1.0.2 allows remote RDP servers to cause a denial of service (application crash) or possibly have unspecified other impact via a large ScopeCount value in a Scope List in a Server License Request packet.

Project: FreeRDP

void license_send_new_license_request_packet(rdpLicense* license)
{
	wStream* s;
	char* username;

	DEBUG_LICENSE("Sending New License Packet");

	s = license_send_stream_init(license);

	if (license->rdp->settings->Username != NULL)
		username = license->rdp->settings->Username;
	else
		username = "username";

	license->ClientUserName->data = (BYTE*) username;
	license->ClientUserName->length = strlen(username) + 1;

	license->ClientMachineName->data = (BYTE*) license->rdp->settings->ClientHostname;
	license->ClientMachineName->length = strlen(license->rdp->settings->ClientHostname) + 1;

	license_write_new_license_request_packet(license, s);

	license_send(license, s, NEW_LICENSE_REQUEST);

	license->ClientUserName->data = NULL;
	license->ClientUserName->length = 0;

	license->ClientMachineName->data = NULL;
	license->ClientMachineName->length = 0;
}

Project: FreeRDP

void license_read_new_license_packet(rdpLicense* license, wStream* s)
{
	DEBUG_LICENSE("Receiving New License Packet");
	license->state = LICENSE_STATE_COMPLETED;
}

Project: FreeRDP

BOOL license_read_preamble(wStream* s, BYTE* bMsgType, BYTE* flags, UINT16* wMsgSize)
{
	/* preamble (4 bytes) */
	if (Stream_GetRemainingLength(s) < 4)
		return FALSE;

	Stream_Read_UINT8(s, *bMsgType); /* bMsgType (1 byte) */
	Stream_Read_UINT8(s, *flags); /* flags (1 byte) */
	Stream_Read_UINT16(s, *wMsgSize); /* wMsgSize (2 bytes) */

	return TRUE;
}

Project: FreeRDP

void license_generate_randoms(rdpLicense* license)
{
	ZeroMemory(license->ClientRandom, CLIENT_RANDOM_LENGTH); /* ClientRandom */
	ZeroMemory(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */

#ifndef LICENSE_NULL_CLIENT_RANDOM
	crypto_nonce(license->ClientRandom, CLIENT_RANDOM_LENGTH); /* ClientRandom */
#endif

#ifndef LICENSE_NULL_PREMASTER_SECRET
	crypto_nonce(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */
#endif
}

Project: FreeRDP

SCOPE_LIST* license_new_scope_list()
{
	SCOPE_LIST* scopeList;

	scopeList = (SCOPE_LIST*) malloc(sizeof(SCOPE_LIST));
	scopeList->count = 0;
	scopeList->array = NULL;

	return scopeList;
}

Project: FreeRDP

void license_print_scope_list(SCOPE_LIST* scopeList)
{
	int index;
	LICENSE_BLOB* scope;

	fprintf(stderr, "ScopeList (%d):\n", scopeList->count);

	for (index = 0; index < scopeList->count; index++)
	{
		scope = &scopeList->array[index];
		fprintf(stderr, "\t%s\n", (char*) scope->data);
	}
}

Project: FreeRDP

void license_free(rdpLicense* license)
{
	if (license)
	{
		free(license->Modulus);
		certificate_free(license->certificate);
		license_free_product_info(license->ProductInfo);
		license_free_binary_blob(license->ErrorInfo);
		license_free_binary_blob(license->KeyExchangeList);
		license_free_binary_blob(license->ServerCertificate);
		license_free_binary_blob(license->ClientUserName);
		license_free_binary_blob(license->ClientMachineName);
		license_free_binary_blob(license->PlatformChallenge);
		license_free_binary_blob(license->EncryptedPlatformChallenge);
		license_free_binary_blob(license->EncryptedPremasterSecret);
		license_free_binary_blob(license->EncryptedHardwareId);
		license_free_scope_list(license->ScopeList);
		free(license);
	}
}

Project: FreeRDP

void license_generate_keys(rdpLicense* license)
{
	security_master_secret(license->PremasterSecret, license->ClientRandom,
			license->ServerRandom, license->MasterSecret); /* MasterSecret */

	security_session_key_blob(license->MasterSecret, license->ClientRandom,
			license->ServerRandom, license->SessionKeyBlob); /* SessionKeyBlob */

	security_mac_salt_key(license->SessionKeyBlob, license->ClientRandom,
			license->ServerRandom, license->MacSaltKey); /* MacSaltKey */

	security_licensing_encryption_key(license->SessionKeyBlob, license->ClientRandom,
			license->ServerRandom, license->LicensingEncryptionKey); /* LicensingEncryptionKey */

#ifdef WITH_DEBUG_LICENSE
	fprintf(stderr, "ClientRandom:\n");
	winpr_HexDump(license->ClientRandom, CLIENT_RANDOM_LENGTH);
	fprintf(stderr, "\n");

	fprintf(stderr, "ServerRandom:\n");
	winpr_HexDump(license->ServerRandom, SERVER_RANDOM_LENGTH);
	fprintf(stderr, "\n");

	fprintf(stderr, "PremasterSecret:\n");
	winpr_HexDump(license->PremasterSecret, PREMASTER_SECRET_LENGTH);
	fprintf(stderr, "\n");

	fprintf(stderr, "MasterSecret:\n");
	winpr_HexDump(license->MasterSecret, MASTER_SECRET_LENGTH);
	fprintf(stderr, "\n");

	fprintf(stderr, "SessionKeyBlob:\n");
	winpr_HexDump(license->SessionKeyBlob, SESSION_KEY_BLOB_LENGTH);
	fprintf(stderr, "\n");

	fprintf(stderr, "MacSaltKey:\n");
	winpr_HexDump(license->MacSaltKey, MAC_SALT_KEY_LENGTH);
	fprintf(stderr, "\n");

	fprintf(stderr, "LicensingEncryptionKey:\n");
	winpr_HexDump(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH);
	fprintf(stderr, "\n");
#endif
}

Project: FreeRDP

void license_write_encrypted_premaster_secret_blob(wStream* s, LICENSE_BLOB* blob, UINT32 ModulusLength)
{
	UINT32 length;

	length = ModulusLength + 8;

	if (blob->length > ModulusLength)
	{
		fprintf(stderr, "license_write_encrypted_premaster_secret_blob: invalid blob\n");
		return;
	}

	Stream_EnsureRemainingCapacity(s, length + 4);

	Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
	Stream_Write_UINT16(s, length); /* wBlobLen (2 bytes) */

	if (blob->length > 0)
		Stream_Write(s, blob->data, blob->length); /* blobData */

	Stream_Zero(s, length - blob->length);
}

Project: FreeRDP

void license_generate_hwid(rdpLicense* license)
{
	CryptoMd5 md5;
	BYTE* mac_address;

	ZeroMemory(license->HardwareId, HWID_LENGTH);
	mac_address = license->rdp->transport->TcpIn->mac_address;

	md5 = crypto_md5_init();
	crypto_md5_update(md5, mac_address, 6);
	crypto_md5_final(md5, &license->HardwareId[HWID_PLATFORM_ID_LENGTH]);
}

Project: FreeRDP

void license_print_product_info(PRODUCT_INFO* productInfo)
{
	char* CompanyName = NULL;
	char* ProductId = NULL;

	ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) productInfo->pbCompanyName,
			productInfo->cbCompanyName / 2, &CompanyName, 0, NULL, NULL);

	ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) productInfo->pbProductId,
			productInfo->cbProductId / 2, &ProductId, 0, NULL, NULL);

	fprintf(stderr, "ProductInfo:\n");
	fprintf(stderr, "\tdwVersion: 0x%08X\n", productInfo->dwVersion);
	fprintf(stderr, "\tCompanyName: %s\n", CompanyName);
	fprintf(stderr, "\tProductId: %s\n", ProductId);

	free(CompanyName);
	free(ProductId);
}

Project: FreeRDP

void license_write_binary_blob(wStream* s, LICENSE_BLOB* blob)
{
	Stream_EnsureRemainingCapacity(s, blob->length +  4);

	Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
	Stream_Write_UINT16(s, blob->length); /* wBlobLen (2 bytes) */

	if (blob->length > 0)
		Stream_Write(s, blob->data, blob->length); /* blobData */
}

Project: FreeRDP

int license_recv(rdpLicense* license, wStream* s)
{
	BYTE flags;
	BYTE bMsgType;
	UINT16 wMsgSize;
	UINT16 length;
	UINT16 channelId;
	UINT16 securityFlags;

	if (!rdp_read_header(license->rdp, s, &length, &channelId))
	{
		fprintf(stderr, "Incorrect RDP header.\n");
		return -1;
	}

	if (!rdp_read_security_header(s, &securityFlags))
		return -1;

	if (securityFlags & SEC_ENCRYPT)
	{
		if (!rdp_decrypt(license->rdp, s, length - 4, securityFlags))
		{
			fprintf(stderr, "rdp_decrypt failed\n");
			return -1;
		}
	}

	if (!(securityFlags & SEC_LICENSE_PKT))
	{
		int status;

		if (!(securityFlags & SEC_ENCRYPT))
			Stream_Rewind(s, RDP_SECURITY_HEADER_LENGTH);

		status = rdp_recv_out_of_sequence_pdu(license->rdp, s);

		if (status < 0)
		{
			fprintf(stderr, "Unexpected license packet.\n");
			return status;
		}

		return 0;
	}

	if (!license_read_preamble(s, &bMsgType, &flags, &wMsgSize)) /* preamble (4 bytes) */
		return -1;

	DEBUG_LICENSE("Receiving %s Packet", LICENSE_MESSAGE_STRINGS[bMsgType & 0x1F]);

	switch (bMsgType)
	{
		case LICENSE_REQUEST:
			if (!license_read_license_request_packet(license, s))
				return -1;
			license_send_new_license_request_packet(license);
			break;

		case PLATFORM_CHALLENGE:
			if (!license_read_platform_challenge_packet(license, s))
				return -1;
			license_send_platform_challenge_response_packet(license);
			break;

		case NEW_LICENSE:
			license_read_new_license_packet(license, s);
			break;

		case UPGRADE_LICENSE:
			license_read_upgrade_license_packet(license, s);
			break;

		case ERROR_ALERT:
			if (!license_read_error_alert_packet(license, s))
				return -1;
			break;

		default:
			fprintf(stderr, "invalid bMsgType:%d\n", bMsgType);
			return FALSE;
	}

	return 0;
}

Project: FreeRDP

BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
{
	int length;
	BYTE flags;
	UINT16 wMsgSize;
	UINT16 sec_flags;

	DEBUG_LICENSE("Sending %s Packet", LICENSE_MESSAGE_STRINGS[type & 0x1F]);

	length = Stream_GetPosition(s);
	Stream_SetPosition(s, 0);

	sec_flags = SEC_LICENSE_PKT;
	wMsgSize = length - LICENSE_PACKET_HEADER_MAX_LENGTH + 4;

	flags = PREAMBLE_VERSION_3_0;

	/**
	 * Using EXTENDED_ERROR_MSG_SUPPORTED here would cause mstsc to crash when
	 * running in server mode! This flag seems to be incorrectly documented.
	 */

	if (!license->rdp->settings->ServerMode)
		flags |= EXTENDED_ERROR_MSG_SUPPORTED;

	rdp_write_header(license->rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
	rdp_write_security_header(s, sec_flags);
	license_write_preamble(s, type, flags, wMsgSize);

#ifdef WITH_DEBUG_LICENSE
	fprintf(stderr, "Sending %s Packet, length %d\n", LICENSE_MESSAGE_STRINGS[type & 0x1F], wMsgSize);
	winpr_HexDump(Stream_Pointer(s) - 4, wMsgSize);
#endif

	Stream_SetPosition(s, length);
	Stream_SealLength(s);

	if (transport_write(license->rdp->transport, s) < 0)
		return FALSE;

	Stream_Free(s, TRUE);

	return TRUE;
}

Project: FreeRDP

void license_read_upgrade_license_packet(rdpLicense* license, wStream* s)
{
	DEBUG_LICENSE("Receiving Upgrade License Packet");
	license->state = LICENSE_STATE_COMPLETED;
}

Project: FreeRDP

LICENSE_BLOB* license_new_binary_blob(UINT16 type)
{
	LICENSE_BLOB* blob;

	blob = (LICENSE_BLOB*) malloc(sizeof(LICENSE_BLOB));
	blob->type = type;
	blob->length = 0;
	blob->data = NULL;

	return blob;
}

Project: FreeRDP

wStream* license_send_stream_init(rdpLicense* license)
{
	wStream* s;

	s = Stream_New(NULL, 4096);
	Stream_Seek(s, LICENSE_PACKET_HEADER_MAX_LENGTH);

	return s;
}

Project: FreeRDP

void license_get_server_rsa_public_key(rdpLicense* license)
{
	BYTE* Exponent;
	BYTE* Modulus;
	int ModulusLength;

	if (license->ServerCertificate->length < 1)
	{
		certificate_read_server_certificate(license->certificate,
				license->rdp->settings->ServerCertificate,
				license->rdp->settings->ServerCertificateLength);
	}

	Exponent = license->certificate->cert_info.exponent;
	Modulus = license->certificate->cert_info.Modulus;
	ModulusLength = license->certificate->cert_info.ModulusLength;

	CopyMemory(license->Exponent, Exponent, 4);

	license->ModulusLength = ModulusLength;
	license->Modulus = (BYTE*) malloc(ModulusLength);
	memcpy(license->Modulus, Modulus, ModulusLength);
}

Project: FreeRDP

BOOL license_read_license_request_packet(rdpLicense* license, wStream* s)
{
	/* ServerRandom (32 bytes) */
	if (Stream_GetRemainingLength(s) < 32)
		return FALSE;

	Stream_Read(s, license->ServerRandom, 32);

	/* ProductInfo */
	if (!license_read_product_info(s, license->ProductInfo))
		return FALSE;

	/* KeyExchangeList */
	if (!license_read_binary_blob(s, license->KeyExchangeList))
		return FALSE;

	/* ServerCertificate */
	if (!license_read_binary_blob(s, license->ServerCertificate))
		return FALSE;

	/* ScopeList */
	if (!license_read_scope_list(s, license->ScopeList))
		return FALSE;

	/* Parse Server Certificate */
	if (!certificate_read_server_certificate(license->certificate,
			license->ServerCertificate->data, license->ServerCertificate->length) < 0)
		return FALSE;

	license_generate_keys(license);
	license_generate_hwid(license);
	license_encrypt_premaster_secret(license);

#ifdef WITH_DEBUG_LICENSE
	fprintf(stderr, "ServerRandom:\n");
	winpr_HexDump(license->ServerRandom, 32);
	fprintf(stderr, "\n");

	license_print_product_info(license->ProductInfo);
	fprintf(stderr, "\n");

	license_print_scope_list(license->ScopeList);
	fprintf(stderr, "\n");
#endif

	return TRUE;
}

Project: FreeRDP

void license_write_platform_challenge_response_packet(rdpLicense* license, wStream* s, BYTE* macData)
{
	license_write_binary_blob(s, license->EncryptedPlatformChallenge); /* EncryptedPlatformChallengeResponse */
	license_write_binary_blob(s, license->EncryptedHardwareId); /* EncryptedHWID */

	Stream_EnsureRemainingCapacity(s, 16);
	Stream_Write(s, macData, 16); /* MACData */
}

Project: FreeRDP

void license_write_preamble(wStream* s, BYTE bMsgType, BYTE flags, UINT16 wMsgSize)
{
	/* preamble (4 bytes) */
	Stream_Write_UINT8(s, bMsgType); /* bMsgType (1 byte) */
	Stream_Write_UINT8(s, flags); /* flags (1 byte) */
	Stream_Write_UINT16(s, wMsgSize); /* wMsgSize (2 bytes) */
}

Project: FreeRDP

PRODUCT_INFO* license_new_product_info()
{
	PRODUCT_INFO* productInfo;

	productInfo = (PRODUCT_INFO*) malloc(sizeof(PRODUCT_INFO));

	productInfo->dwVersion = 0;
	productInfo->cbCompanyName = 0;
	productInfo->pbCompanyName = NULL;
	productInfo->cbProductId = 0;
	productInfo->pbProductId = NULL;

	return productInfo;
}

Project: FreeRDP

void license_send_platform_challenge_response_packet(rdpLicense* license)
{
	wStream* s;
	int length;
	BYTE* buffer;
	CryptoRc4 rc4;
	BYTE mac_data[16];

	DEBUG_LICENSE("Sending Platform Challenge Response Packet");

	s = license_send_stream_init(license);

	license->EncryptedPlatformChallenge->type = BB_DATA_BLOB;
	length = license->PlatformChallenge->length + HWID_LENGTH;

	buffer = (BYTE*) malloc(length);
	CopyMemory(buffer, license->PlatformChallenge->data, license->PlatformChallenge->length);
	CopyMemory(&buffer[license->PlatformChallenge->length], license->HardwareId, HWID_LENGTH);
	security_mac_data(license->MacSaltKey, buffer, length, mac_data);
	free(buffer);

	buffer = (BYTE*) malloc(HWID_LENGTH);
	rc4 = crypto_rc4_init(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH);
	crypto_rc4(rc4, HWID_LENGTH, license->HardwareId, buffer);
	crypto_rc4_free(rc4);

	license->EncryptedHardwareId->type = BB_DATA_BLOB;
	license->EncryptedHardwareId->data = buffer;
	license->EncryptedHardwareId->length = HWID_LENGTH;

#ifdef WITH_DEBUG_LICENSE
	fprintf(stderr, "LicensingEncryptionKey:\n");
	winpr_HexDump(license->LicensingEncryptionKey, 16);
	fprintf(stderr, "\n");

	fprintf(stderr, "HardwareId:\n");
	winpr_HexDump(license->HardwareId, HWID_LENGTH);
	fprintf(stderr, "\n");

	fprintf(stderr, "EncryptedHardwareId:\n");
	winpr_HexDump(license->EncryptedHardwareId->data, HWID_LENGTH);
	fprintf(stderr, "\n");
#endif

	license_write_platform_challenge_response_packet(license, s, mac_data);

	license_send(license, s, PLATFORM_CHALLENGE_RESPONSE);
}

Project: FreeRDP

rdpLicense* license_new(rdpRdp* rdp)
{
	rdpLicense* license;

	license = (rdpLicense*) malloc(sizeof(rdpLicense));

	if (license != NULL)
	{
		ZeroMemory(license, sizeof(rdpLicense));

		license->rdp = rdp;
		license->state = LICENSE_STATE_AWAIT;
		license->certificate = certificate_new();
		license->ProductInfo = license_new_product_info();
		license->ErrorInfo = license_new_binary_blob(BB_ERROR_BLOB);
		license->KeyExchangeList = license_new_binary_blob(BB_KEY_EXCHG_ALG_BLOB);
		license->ServerCertificate = license_new_binary_blob(BB_CERTIFICATE_BLOB);
		license->ClientUserName = license_new_binary_blob(BB_CLIENT_USER_NAME_BLOB);
		license->ClientMachineName = license_new_binary_blob(BB_CLIENT_MACHINE_NAME_BLOB);
		license->PlatformChallenge = license_new_binary_blob(BB_ANY_BLOB);
		license->EncryptedPlatformChallenge = license_new_binary_blob(BB_ANY_BLOB);
		license->EncryptedPremasterSecret = license_new_binary_blob(BB_ANY_BLOB);
		license->EncryptedHardwareId = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB);
		license->ScopeList = license_new_scope_list();
		license_generate_randoms(license);
	}

	return license;
}

Project: FreeRDP

void license_free_binary_blob(LICENSE_BLOB* blob)
{
	if (blob->data != NULL)
		free(blob->data);

	free(blob);
}

Project: FreeRDP

BOOL license_read_product_info(wStream* s, PRODUCT_INFO* productInfo)
{
	if (Stream_GetRemainingLength(s) < 8)
		return FALSE;

	Stream_Read_UINT32(s, productInfo->dwVersion); /* dwVersion (4 bytes) */

	Stream_Read_UINT32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */

	if (Stream_GetRemainingLength(s) < productInfo->cbCompanyName + 4)
		return FALSE;

	productInfo->pbCompanyName = (BYTE*) malloc(productInfo->cbCompanyName);
	Stream_Read(s, productInfo->pbCompanyName, productInfo->cbCompanyName);

	Stream_Read_UINT32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */

	if (Stream_GetRemainingLength(s) < productInfo->cbProductId)
	{
		free(productInfo->pbCompanyName);
		productInfo->pbCompanyName = NULL;
		return FALSE;
	}

	productInfo->pbProductId = (BYTE*) malloc(productInfo->cbProductId);
	Stream_Read(s, productInfo->pbProductId, productInfo->cbProductId);

	return TRUE;
}

Project: FreeRDP

void license_free_product_info(PRODUCT_INFO* productInfo)
{
	if (productInfo->pbCompanyName != NULL)
		free(productInfo->pbCompanyName);

	if (productInfo->pbProductId != NULL)
		free(productInfo->pbProductId);

	free(productInfo);
}

Project: FreeRDP

BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList)
{
	UINT32 i;
	UINT32 scopeCount;

	if (Stream_GetRemainingLength(s) < 4)
		return FALSE;

	Stream_Read_UINT32(s, scopeCount); /* ScopeCount (4 bytes) */
	if (scopeCount > Stream_GetRemainingLength(s) / 4)  /* every blob is at least 4 bytes */
		return FALSE;

	scopeList->count = scopeCount;
	scopeList->array = (LICENSE_BLOB*) malloc(sizeof(LICENSE_BLOB) * scopeCount);

	/* ScopeArray */
	for (i = 0; i < scopeCount; i++)
	{
		scopeList->array[i].type = BB_SCOPE_BLOB;

		if (!license_read_binary_blob(s, &scopeList->array[i]))
			return FALSE;
	}

	return TRUE;
}

Project: FreeRDP

BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob)
{
	UINT16 wBlobType;

	if (Stream_GetRemainingLength(s) < 4)
		return FALSE;

	Stream_Read_UINT16(s, wBlobType); /* wBlobType (2 bytes) */
	Stream_Read_UINT16(s, blob->length); /* wBlobLen (2 bytes) */

	if (Stream_GetRemainingLength(s) < blob->length)
		return FALSE;

	/*
 	 * Server can choose to not send data by setting length to 0.
 	 * If so, it may not bother to set the type, so shortcut the warning
 	 */
	if ((blob->type != BB_ANY_BLOB) && (blob->length == 0))
		return TRUE;

	if ((blob->type != wBlobType) && (blob->type != BB_ANY_BLOB))
	{
		fprintf(stderr, "license binary blob type (%x) does not match expected type (%x).\n", wBlobType, blob->type);
	}

	blob->type = wBlobType;
	blob->data = (BYTE*) malloc(blob->length);

	Stream_Read(s, blob->data, blob->length); /* blobData */
	return TRUE;
}

Project: FreeRDP

BOOL license_send_valid_client_error_packet(rdpLicense* license)
{
	wStream* s;

	s = license_send_stream_init(license);

	DEBUG_LICENSE("Sending Error Alert Packet");

	Stream_Write_UINT32(s, STATUS_VALID_CLIENT); /* dwErrorCode */
	Stream_Write_UINT32(s, ST_NO_TRANSITION); /* dwStateTransition */

	license_write_binary_blob(s, license->ErrorInfo);

	return license_send(license, s, ERROR_ALERT);
}

Project: FreeRDP

BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s)
{
	UINT32 dwErrorCode;
	UINT32 dwStateTransition;

	if (Stream_GetRemainingLength(s) < 8)
		return FALSE;

	Stream_Read_UINT32(s, dwErrorCode); /* dwErrorCode (4 bytes) */
	Stream_Read_UINT32(s, dwStateTransition); /* dwStateTransition (4 bytes) */

	if (!license_read_binary_blob(s, license->ErrorInfo)) /* bbErrorInfo */
		return FALSE;

#ifdef WITH_DEBUG_LICENSE
	fprintf(stderr, "dwErrorCode: %s, dwStateTransition: %s\n",
			error_codes[dwErrorCode], state_transitions[dwStateTransition]);
#endif

	if (dwErrorCode == STATUS_VALID_CLIENT)
	{
		license->state = LICENSE_STATE_COMPLETED;
		return TRUE;
	}

	switch (dwStateTransition)
	{
		case ST_TOTAL_ABORT:
			license->state = LICENSE_STATE_ABORTED;
			break;

		case ST_NO_TRANSITION:
			license->state = LICENSE_STATE_COMPLETED;
			break;

		case ST_RESET_PHASE_TO_START:
			license->state = LICENSE_STATE_AWAIT;
			break;

		case ST_RESEND_LAST_MESSAGE:
			break;

		default:
			break;
	}

	return TRUE;
}

Project: FreeRDP

void license_free_scope_list(SCOPE_LIST* scopeList)
{
	UINT32 i;

	/*
	 * We must NOT call license_free_binary_blob() on each scopelist->array[i] element,
	 * because scopelist->array was allocated at once, by a single call to malloc. The elements
	 * it contains cannot be deallocated separately then.
	 * To make things clean, we must deallocate each scopelist->array[].data,
	 * and finish by deallocating scopelist->array with a single call to free().
	 */
	for (i = 0; i < scopeList->count; i++)
	{
		free(scopeList->array[i].data);
	}

	free(scopeList->array);
	free(scopeList);
}

Project: FreeRDP

BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s)
{
	BYTE MacData[16];
	UINT32 ConnectFlags = 0;

	DEBUG_LICENSE("Receiving Platform Challenge Packet");

	if (Stream_GetRemainingLength(s) < 4)
		return FALSE;

	Stream_Read_UINT32(s, ConnectFlags); /* ConnectFlags, Reserved (4 bytes) */

	/* EncryptedPlatformChallenge */
	license->EncryptedPlatformChallenge->type = BB_ANY_BLOB;
	license_read_binary_blob(s, license->EncryptedPlatformChallenge);
	license->EncryptedPlatformChallenge->type = BB_ENCRYPTED_DATA_BLOB;

	if (Stream_GetRemainingLength(s) < 16)
		return FALSE;

	Stream_Read(s, MacData, 16); /* MACData (16 bytes) */

	license_decrypt_platform_challenge(license);

#ifdef WITH_DEBUG_LICENSE
	fprintf(stderr, "ConnectFlags: 0x%08X\n", ConnectFlags);
	fprintf(stderr, "\n");

	fprintf(stderr, "EncryptedPlatformChallenge:\n");
	winpr_HexDump(license->EncryptedPlatformChallenge->data, license->EncryptedPlatformChallenge->length);
	fprintf(stderr, "\n");

	fprintf(stderr, "PlatformChallenge:\n");
	winpr_HexDump(license->PlatformChallenge->data, license->PlatformChallenge->length);
	fprintf(stderr, "\n");

	fprintf(stderr, "MacData:\n");
	winpr_HexDump(MacData, 16);
	fprintf(stderr, "\n");
#endif

	return TRUE;
}

Project: FreeRDP

void license_encrypt_premaster_secret(rdpLicense* license)
{
	BYTE* EncryptedPremasterSecret;

	license_get_server_rsa_public_key(license);

#ifdef WITH_DEBUG_LICENSE
	fprintf(stderr, "Modulus (%d bits):\n", license->ModulusLength * 8);
	winpr_HexDump(license->Modulus, license->ModulusLength);
	fprintf(stderr, "\n");

	fprintf(stderr, "Exponent:\n");
	winpr_HexDump(license->Exponent, 4);
	fprintf(stderr, "\n");
#endif

	EncryptedPremasterSecret = (BYTE*) malloc(license->ModulusLength);
	ZeroMemory(EncryptedPremasterSecret, license->ModulusLength);
	license->EncryptedPremasterSecret->type = BB_RANDOM_BLOB;
	license->EncryptedPremasterSecret->length = PREMASTER_SECRET_LENGTH;

#ifndef LICENSE_NULL_PREMASTER_SECRET
	license->EncryptedPremasterSecret->length =
		crypto_rsa_public_encrypt(license->PremasterSecret, PREMASTER_SECRET_LENGTH,
			license->ModulusLength, license->Modulus, license->Exponent, EncryptedPremasterSecret);
#endif

	license->EncryptedPremasterSecret->data = EncryptedPremasterSecret;
}

Project: FreeRDP

void license_decrypt_platform_challenge(rdpLicense* license)
{
	CryptoRc4 rc4;

	license->PlatformChallenge->data = (BYTE*) malloc(license->EncryptedPlatformChallenge->length);
	license->PlatformChallenge->length = license->EncryptedPlatformChallenge->length;

	rc4 = crypto_rc4_init(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH);

	crypto_rc4(rc4, license->EncryptedPlatformChallenge->length,
			license->EncryptedPlatformChallenge->data,
			license->PlatformChallenge->data);

	crypto_rc4_free(rc4);
}

Project: FreeRDP

void license_write_new_license_request_packet(rdpLicense* license, wStream* s)
{
	UINT32 PlatformId;
	UINT32 PreferredKeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;

	PlatformId = CLIENT_OS_ID_WINNT_POST_52 | CLIENT_IMAGE_ID_MICROSOFT;

	Stream_Write_UINT32(s, PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
	Stream_Write_UINT32(s, PlatformId); /* PlatformId (4 bytes) */
	Stream_Write(s, license->ClientRandom, 32); /* ClientRandom (32 bytes) */
	license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret, license->ModulusLength); /* EncryptedPremasterSecret */
	license_write_binary_blob(s, license->ClientUserName); /* ClientUserName */
	license_write_binary_blob(s, license->ClientMachineName); /* ClientMachineName */

#ifdef WITH_DEBUG_LICENSE
	fprintf(stderr, "PreferredKeyExchangeAlg: 0x%08X\n", PreferredKeyExchangeAlg);
	fprintf(stderr, "\n");

	fprintf(stderr, "ClientRandom:\n");
	winpr_HexDump(license->ClientRandom, 32);
	fprintf(stderr, "\n");

	fprintf(stderr, "EncryptedPremasterSecret\n");
	winpr_HexDump(license->EncryptedPremasterSecret->data, license->EncryptedPremasterSecret->length);
	fprintf(stderr, "\n");

	fprintf(stderr, "ClientUserName (%d): %s\n", license->ClientUserName->length, (char*) license->ClientUserName->data);
	fprintf(stderr, "\n");

	fprintf(stderr, "ClientMachineName (%d): %s\n", license->ClientMachineName->length, (char*) license->ClientMachineName->data);
	fprintf(stderr, "\n");
#endif
}