Exemple #1
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
	UINT32 index;
	UINT32 dataLen;
	UINT32 position;
	BOOL asciiNames;
	int formatNameLength;
	char* szFormatName;
	WCHAR* wszFormatName;
	CLIPRDR_FORMAT* formats = NULL;
	CLIPRDR_FORMAT_LIST formatList;
	CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle;
	UINT error = CHANNEL_RC_OK;

	dataLen = header->dataLen;
	asciiNames = (header->msgFlags & CB_ASCII_NAMES) ? TRUE : FALSE;

	formatList.msgType = CB_FORMAT_LIST;
	formatList.msgFlags = header->msgFlags;
	formatList.dataLen = header->dataLen;

	index = 0;
	formatList.numFormats = 0;
	position = Stream_GetPosition(s);

	if (!header->dataLen)
	{
		/* empty format list */
		formatList.formats = NULL;
		formatList.numFormats = 0;
	}
	else if (!cliprdr->useLongFormatNames)
	{
		formatList.numFormats = (dataLen / 36);

		if ((formatList.numFormats * 36) != dataLen)
		{
			WLog_ERR(TAG, "Invalid short format list length: %d", dataLen);
			return ERROR_INVALID_PARAMETER;
		}

		if (formatList.numFormats)
			formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, sizeof(CLIPRDR_FORMAT));

		if (!formats)
		{
			WLog_ERR(TAG, "calloc failed!");
			return CHANNEL_RC_NO_MEMORY;
		}

		formatList.formats = formats;

		while (dataLen)
		{
			Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */
			dataLen -= 4;

			formats[index].formatName = NULL;

			if (asciiNames)
			{
				szFormatName = (char*) Stream_Pointer(s);

				if (szFormatName[0])
				{
					formats[index].formatName = (char*) malloc(32 + 1);
					CopyMemory(formats[index].formatName, szFormatName, 32);
					formats[index].formatName[32] = '\0';
				}
			}
			else
			{
				wszFormatName = (WCHAR*) Stream_Pointer(s);

				if (wszFormatName[0])
				{
					ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
						16, &(formats[index].formatName), 0, NULL, NULL);
				}
			}

			Stream_Seek(s, 32);
			dataLen -= 32;
			index++;
		}
	}
	else
	{
		while (dataLen)
		{
			Stream_Seek(s, 4); /* formatId (4 bytes) */
			dataLen -= 4;

			wszFormatName = (WCHAR*) Stream_Pointer(s);

			if (!wszFormatName[0])
				formatNameLength = 0;
			else
				formatNameLength = _wcslen(wszFormatName);

			Stream_Seek(s, (formatNameLength + 1) * 2);
			dataLen -= ((formatNameLength + 1) * 2);

			formatList.numFormats++;
		}

		dataLen = formatList.dataLen;
		Stream_SetPosition(s, position);

		if (formatList.numFormats)
			formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, sizeof(CLIPRDR_FORMAT));

		if (!formats)
		{
			WLog_ERR(TAG, "calloc failed!");
			return CHANNEL_RC_NO_MEMORY;
		}

		formatList.formats = formats;

		while (dataLen)
		{
			Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */
			dataLen -= 4;

			formats[index].formatName = NULL;

			wszFormatName = (WCHAR*) Stream_Pointer(s);

			if (!wszFormatName[0])
				formatNameLength = 0;
			else
				formatNameLength = _wcslen(wszFormatName);

			if (formatNameLength)
			{
				ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
					-1, &(formats[index].formatName), 0, NULL, NULL);
			}

			Stream_Seek(s, (formatNameLength + 1) * 2);
			dataLen -= ((formatNameLength + 1) * 2);

			index++;
		}
	}

	WLog_DBG(TAG, "ClientFormatList: numFormats: %d",
			formatList.numFormats);

	IFCALLRET(context->ClientFormatList, error, context, &formatList);
	if (error)
		WLog_ERR(TAG, "ClientFormatList failed with error %lu!", error);

	for (index = 0; index < formatList.numFormats; index++)
	{
		free(formatList.formats[index].formatName);
	}

	free(formatList.formats);

	return error;
}
Exemple #2
0
BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
{
	char* str = NULL;
	UINT32 version;
	BYTE connectionType = 0;
	UINT32 clientColorDepth;
	UINT16 colorDepth = 0;
	UINT16 postBeta2ColorDepth = 0;
	UINT16 highColorDepth = 0;
	UINT16 supportedColorDepths = 0;
	UINT32 serverSelectedProtocol = 0;
	UINT32 desktopPhysicalWidth = 0;
	UINT32 desktopPhysicalHeight = 0;
	UINT16 desktopOrientation = 0;
	UINT32 desktopScaleFactor = 0;
	UINT32 deviceScaleFactor = 0;
	UINT16 earlyCapabilityFlags = 0;
	rdpSettings* settings = mcs->settings;

	/* Length of all required fields, until imeFileName */
	if (blockLength < 128)
		return FALSE;

	Stream_Read_UINT32(s, version); /* version (4 bytes) */
	settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7);

	Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth (2 bytes) */
	Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight (2 bytes) */
	Stream_Read_UINT16(s, colorDepth); /* ColorDepth (2 bytes) */
	Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) (2 bytes) */
	Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout (4 bytes) */
	Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild (4 bytes) */

	/* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
	ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL);
	Stream_Seek(s, 32);
	sprintf_s(settings->ClientHostname, 31, "%s", str);
	settings->ClientHostname[31] = 0;
	free(str);
	str = NULL;

	Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType (4 bytes) */
	Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType (4 bytes) */
	Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey (4 bytes) */

	WLog_DBG(TAG, "KeyboardLayout=%x, KeyboardType=%x, KeyboardSubType=%x, KeyboardFunctionKey=%x",
		settings->KeyboardLayout, settings->KeyboardType, settings->KeyboardSubType, settings->KeyboardFunctionKey);

	Stream_Seek(s, 64); /* imeFileName (64 bytes) */

	blockLength -= 128;

	/**
	 * The following fields are all optional. If one field is present, all of the preceding
	 * fields MUST also be present. If one field is not present, all of the subsequent fields
	 * MUST NOT be present.
	 * We must check the bytes left before reading each field.
	 */

	do
	{
		if (blockLength < 2)
			break;
		Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth (2 bytes) */
		blockLength -= 2;

		if (blockLength < 2)
			break;
		Stream_Seek_UINT16(s); /* clientProductID (2 bytes) */
		blockLength -= 2;

		if (blockLength < 4)
			break;
		Stream_Seek_UINT32(s); /* serialNumber (4 bytes) */
		blockLength -= 4;

		if (blockLength < 2)
			break;
		Stream_Read_UINT16(s, highColorDepth); /* highColorDepth (2 bytes) */
		blockLength -= 2;

		if (blockLength < 2)
			break;
		Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths (2 bytes) */
		blockLength -= 2;

		if (blockLength < 2)
			break;
		Stream_Read_UINT16(s, earlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
		settings->EarlyCapabilityFlags = (UINT32) earlyCapabilityFlags;
		blockLength -= 2;

		if (blockLength < 64)
			break;

		ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL);
		Stream_Seek(s, 64); /* clientDigProductId (64 bytes) */
		sprintf_s(settings->ClientProductId, 32, "%s", str);
		free(str);
		blockLength -= 64;

		if (blockLength < 1)
			break;
		Stream_Read_UINT8(s, connectionType); /* connectionType (1 byte) */
		blockLength -= 1;

		if (blockLength < 1)
			break;
		Stream_Seek_UINT8(s); /* pad1octet (1 byte) */
		blockLength -= 1;

		if (blockLength < 4)
			break;
		Stream_Read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol (4 bytes) */
		blockLength -= 4;

		if (blockLength < 4)
			break;
		Stream_Read_UINT32(s, desktopPhysicalWidth); /* desktopPhysicalWidth (4 bytes) */
		blockLength -= 4;

		if (blockLength < 4)
			break;
		Stream_Read_UINT32(s, desktopPhysicalHeight); /* desktopPhysicalHeight (4 bytes) */
		blockLength -= 4;

		if (blockLength < 2)
			break;
		Stream_Read_UINT16(s, desktopOrientation); /* desktopOrientation (2 bytes) */
		blockLength -= 2;

		if (blockLength < 4)
			break;
		Stream_Read_UINT32(s, desktopScaleFactor); /* desktopScaleFactor (4 bytes) */
		blockLength -= 4;

		if (blockLength < 4)
			break;
		Stream_Read_UINT32(s, deviceScaleFactor); /* deviceScaleFactor (4 bytes) */
		blockLength -= 4;

		if (settings->SelectedProtocol != serverSelectedProtocol)
			return FALSE;
	} while (0);

	if (highColorDepth > 0)
	{
		if (earlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION)
			clientColorDepth = 32;
		else
			clientColorDepth = highColorDepth;
	}
	else if (postBeta2ColorDepth > 0)
	{
		switch (postBeta2ColorDepth)
		{
			case RNS_UD_COLOR_4BPP:
				clientColorDepth = 4;
				break;
			case RNS_UD_COLOR_8BPP:
				clientColorDepth = 8;
				break;
			case RNS_UD_COLOR_16BPP_555:
				clientColorDepth = 15;
				break;
			case RNS_UD_COLOR_16BPP_565:
				clientColorDepth = 16;
				break;
			case RNS_UD_COLOR_24BPP:
				clientColorDepth = 24;
				break;
			default:
				return FALSE;
		}
	}
	else
	{
		switch (colorDepth)
		{
			case RNS_UD_COLOR_4BPP:
				clientColorDepth = 4;
				break;
			case RNS_UD_COLOR_8BPP:
				clientColorDepth = 8;
				break;
			default:
				return FALSE;
		}
	}

	/*
	 * If we are in server mode, accept client's color depth only if
	 * it is smaller than ours. This is what Windows server does.
	 */
	if ((clientColorDepth < settings->ColorDepth) || !settings->ServerMode)
		settings->ColorDepth = clientColorDepth;

	if (settings->NetworkAutoDetect)
		settings->NetworkAutoDetect = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT) ? TRUE : FALSE;

	if (settings->SupportHeartbeatPdu)
		settings->SupportHeartbeatPdu = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU) ? TRUE : FALSE;

	if (settings->SupportGraphicsPipeline)
		settings->SupportGraphicsPipeline = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL) ? TRUE : FALSE;

	if (settings->SupportDynamicTimeZone)
		settings->SupportDynamicTimeZone = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE) ? TRUE : FALSE;

	if (!(earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE))
		connectionType = 0;

	settings->SupportErrorInfoPdu = earlyCapabilityFlags & RNS_UD_CS_SUPPORT_ERRINFO_PDU;

	settings->ConnectionType = connectionType;

	return TRUE;
}
Exemple #3
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
{
	int status;
	void* key;
	UINT32 FileId;
	DRIVE_FILE* file;
	BYTE Information;
	UINT32 DesiredAccess;
	UINT32 CreateDisposition;
	UINT32 CreateOptions;
	UINT32 PathLength;
	char* path = NULL;
	Stream_Read_UINT32(irp->input, DesiredAccess);
	Stream_Seek(irp->input,
	            16); /* AllocationSize(8), FileAttributes(4), SharedAccess(4) */
	Stream_Read_UINT32(irp->input, CreateDisposition);
	Stream_Read_UINT32(irp->input, CreateOptions);
	Stream_Read_UINT32(irp->input, PathLength);
	status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input),
	                            PathLength / 2, &path, 0, NULL, NULL);

	if (status < 1)
	{
		path = (char*) calloc(1, 1);

		if (!path)
		{
			WLog_ERR(TAG, "calloc failed!");
			return CHANNEL_RC_NO_MEMORY;
		}
	}

	FileId = irp->devman->id_sequence++;
	file = drive_file_new(drive->path, path, FileId,
	                      DesiredAccess, CreateDisposition, CreateOptions);

	if (!file)
	{
		irp->IoStatus = STATUS_UNSUCCESSFUL;
		FileId = 0;
		Information = 0;
	}
	else if (file->err)
	{
		FileId = 0;
		Information = 0;
		/* map errno to windows result */
		irp->IoStatus = drive_map_posix_err(file->err);
		drive_file_free(file);
	}
	else
	{
		key = (void*)(size_t) file->id;

		if (!ListDictionary_Add(drive->files, key, file))
		{
			WLog_ERR(TAG, "ListDictionary_Add failed!");
			free(path);
			return ERROR_INTERNAL_ERROR;
		}

		switch (CreateDisposition)
		{
			case FILE_SUPERSEDE:
			case FILE_OPEN:
			case FILE_CREATE:
			case FILE_OVERWRITE:
				Information = FILE_SUPERSEDED;
				break;

			case FILE_OPEN_IF:
				Information = FILE_OPENED;
				break;

			case FILE_OVERWRITE_IF:
				Information = FILE_OVERWRITTEN;
				break;

			default:
				Information = 0;
				break;
		}
	}

	Stream_Write_UINT32(irp->output, FileId);
	Stream_Write_UINT8(irp->output, Information);
	free(path);
	return irp->Complete(irp);
}
Exemple #4
0
BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags)
{
    BYTE cmac[8];
    BYTE wmac[8];

    if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
    {
        UINT16 len;
        BYTE version, pad;
        BYTE* sig;

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

        Stream_Read_UINT16(s, len); /* 0x10 */
        Stream_Read_UINT8(s, version); /* 0x1 */
        Stream_Read_UINT8(s, pad);

        sig = Stream_Pointer(s);
        Stream_Seek(s, 8);	/* signature */

        length -= 12;

        if (!security_fips_decrypt(Stream_Pointer(s), length, rdp))
        {
            DEBUG_WARN( "FATAL: cannot decrypt\n");
            return FALSE; /* TODO */
        }

        if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, rdp))
        {
            DEBUG_WARN( "FATAL: invalid packet signature\n");
            return FALSE; /* TODO */
        }

        Stream_Length(s) -= pad;
        return TRUE;
    }

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

    Stream_Read(s, wmac, sizeof(wmac));
    length -= sizeof(wmac);

    if (!security_decrypt(Stream_Pointer(s), length, rdp))
        return FALSE;

    if (securityFlags & SEC_SECURE_CHECKSUM)
        security_salted_mac_signature(rdp, Stream_Pointer(s), length, FALSE, cmac);
    else
        security_mac_signature(rdp, Stream_Pointer(s), length, cmac);

    if (memcmp(wmac, cmac, sizeof(wmac)) != 0)
    {
        DEBUG_WARN( "WARNING: invalid packet signature\n");
        /*
         * Because Standard RDP Security is totally broken,
         * and cannot protect against MITM, don't treat signature
         * verification failure as critical. This at least enables
         * us to work with broken RDP clients and servers that
         * generate invalid signatures.
         */
        //return FALSE;
    }

    return TRUE;
}
Exemple #5
0
void gcc_write_server_security_data(wStream* s, rdpMcs* mcs)
{
	CryptoMd5 md5;
	BYTE* sigData;
	int expLen, keyLen, sigDataLen;
	BYTE encryptedSignature[TSSK_KEY_LENGTH];
	BYTE signature[sizeof(initial_signature)];
	UINT32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen;
	rdpSettings* settings = mcs->settings;

	/**
	 * Re: settings->EncryptionLevel:
	 * This is configured/set by the server implementation and serves the same
	 * purpose as the "Encryption Level" setting in the RDP-Tcp configuration
	 * dialog of Microsoft's Remote Desktop Session Host Configuration.
	 * Re: settings->EncryptionMethods:
	 * at this point this setting contains the client's supported encryption
	 * methods we've received in gcc_read_client_security_data()
	 */

	if (!settings->UseRdpSecurityLayer)
	{
		/* TLS/NLA is used: disable rdp style encryption */
		settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
	}

	/* verify server encryption level value */
	switch (settings->EncryptionLevel)
	{
		case ENCRYPTION_LEVEL_NONE:
			WLog_INFO(TAG, "Active rdp encryption level: NONE");
			break;
		case ENCRYPTION_LEVEL_FIPS:
			WLog_INFO(TAG, "Active rdp encryption level: FIPS Compliant");
			break;
		case ENCRYPTION_LEVEL_HIGH:
			WLog_INFO(TAG, "Active rdp encryption level: HIGH");
			break;
		case ENCRYPTION_LEVEL_LOW:
			WLog_INFO(TAG, "Active rdp encryption level: LOW");
			break;
		case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
			WLog_INFO(TAG, "Active rdp encryption level: CLIENT-COMPATIBLE");
			break;
		default:
			WLog_ERR(TAG, "Invalid server encryption level 0x%08X", settings->EncryptionLevel);
			WLog_ERR(TAG, "Switching to encryption level CLIENT-COMPATIBLE");
			settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
	}

	/* choose rdp encryption method based on server level and client methods */
	switch (settings->EncryptionLevel)
	{
		case ENCRYPTION_LEVEL_NONE:
			/* The only valid method is NONE in this case */
			settings->EncryptionMethods = ENCRYPTION_METHOD_NONE;
			break;
		case ENCRYPTION_LEVEL_FIPS:
			/* The only valid method is FIPS in this case */
			if (!(settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS))
			{
				WLog_WARN(TAG, "client does not support FIPS as required by server configuration");
			}
			settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS;
			break;
		case ENCRYPTION_LEVEL_HIGH:
			/* Maximum key strength supported by the server must be used (128 bit)*/
			if (!(settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT))
			{
				WLog_WARN(TAG, "client does not support 128 bit encryption method as required by server configuration");
			}
			settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
			break;
		case ENCRYPTION_LEVEL_LOW:
		case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
			/* Maximum key strength supported by the client must be used */
			if (settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT)
				settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
			else if (settings->EncryptionMethods & ENCRYPTION_METHOD_56BIT)
				settings->EncryptionMethods = ENCRYPTION_METHOD_56BIT;
			else if (settings->EncryptionMethods & ENCRYPTION_METHOD_40BIT)
				settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT;
			else if (settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS)
				settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS;
			else
			{
				WLog_WARN(TAG, "client has not announced any supported encryption methods");
				settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
			}
			break;
		default:
			WLog_ERR(TAG, "internal error: unknown encryption level");
	}

	/* log selected encryption method */
	switch (settings->EncryptionMethods)
	{
		case ENCRYPTION_METHOD_NONE:
			WLog_INFO(TAG, "Selected rdp encryption method: NONE");
			break;
		case ENCRYPTION_METHOD_40BIT:
			WLog_INFO(TAG, "Selected rdp encryption method: 40BIT");
			break;
		case ENCRYPTION_METHOD_56BIT:
			WLog_INFO(TAG, "Selected rdp encryption method: 56BIT");
			break;
		case ENCRYPTION_METHOD_128BIT:
			WLog_INFO(TAG, "Selected rdp encryption method: 128BIT");
			break;
		case ENCRYPTION_METHOD_FIPS:
			WLog_INFO(TAG, "Selected rdp encryption method: FIPS");
			break;
		default:
			WLog_ERR(TAG, "internal error: unknown encryption method");
	}

	headerLen = 12;
	keyLen = 0;
	wPublicKeyBlobLen = 0;
	serverRandomLen = 0;
	serverCertLen = 0;

	if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE)
	{
		serverRandomLen = 32;

		keyLen = settings->RdpServerRsaKey->ModulusLength;
		expLen = sizeof(settings->RdpServerRsaKey->exponent);
		wPublicKeyBlobLen = 4; /* magic (RSA1) */
		wPublicKeyBlobLen += 4; /* keylen */
		wPublicKeyBlobLen += 4; /* bitlen */
		wPublicKeyBlobLen += 4; /* datalen */
		wPublicKeyBlobLen += expLen;
		wPublicKeyBlobLen += keyLen;
		wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */

		serverCertLen = 4; /* dwVersion */
		serverCertLen += 4; /* dwSigAlgId */
		serverCertLen += 4; /* dwKeyAlgId */
		serverCertLen += 2; /* wPublicKeyBlobType */
		serverCertLen += 2; /* wPublicKeyBlobLen */
		serverCertLen += wPublicKeyBlobLen;
		serverCertLen += 2; /* wSignatureBlobType */
		serverCertLen += 2; /* wSignatureBlobLen */
		serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */
		serverCertLen += 8; /* 8 bytes of zero padding */

		headerLen += sizeof(serverRandomLen);
		headerLen += sizeof(serverCertLen);
		headerLen += serverRandomLen;
		headerLen += serverCertLen;
	}

	gcc_write_user_data_header(s, SC_SECURITY, headerLen);

	Stream_Write_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */
	Stream_Write_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */

	if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
	{
		return;
	}

	Stream_Write_UINT32(s, serverRandomLen); /* serverRandomLen */
	Stream_Write_UINT32(s, serverCertLen); /* serverCertLen */

	settings->ServerRandomLength = serverRandomLen;
	settings->ServerRandom = (BYTE*) malloc(serverRandomLen);
	crypto_nonce(settings->ServerRandom, serverRandomLen);
	Stream_Write(s, settings->ServerRandom, serverRandomLen);

	sigData = Stream_Pointer(s);

	Stream_Write_UINT32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */
	Stream_Write_UINT32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */
	Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */
	Stream_Write_UINT16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */

	Stream_Write_UINT16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */
	Stream_Write(s, "RSA1", 4); /* magic */
	Stream_Write_UINT32(s, keyLen + 8); /* keylen */
	Stream_Write_UINT32(s, keyLen * 8); /* bitlen */
	Stream_Write_UINT32(s, keyLen - 1); /* datalen */

	Stream_Write(s, settings->RdpServerRsaKey->exponent, expLen);
	Stream_Write(s, settings->RdpServerRsaKey->Modulus, keyLen);
	Stream_Zero(s, 8);

	sigDataLen = Stream_Pointer(s) - sigData;

	Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */
	Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */

	memcpy(signature, initial_signature, sizeof(initial_signature));

	md5 = crypto_md5_init();
	if (!md5)
	{
		WLog_ERR(TAG,  "unable to allocate a md5");
		return;
	}

	crypto_md5_update(md5, sigData, sigDataLen);
	crypto_md5_final(md5, signature);

	crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH,
		tssk_modulus, tssk_privateExponent, encryptedSignature);

	Stream_Write(s, encryptedSignature, sizeof(encryptedSignature));
	Stream_Zero(s, 8);
}
Exemple #6
0
BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate, wStream* s)
{
	UINT32 dwSigAlgId;
	UINT32 dwKeyAlgId;
	UINT32 wPublicKeyBlobType;
	UINT32 wPublicKeyBlobLen;
	UINT32 wSignatureBlobType;
	UINT32 wSignatureBlobLen;
	BYTE* sigdata;
	int sigdatalen;

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

	/* -4, because we need to include dwVersion */
	sigdata = Stream_Pointer(s) - 4;
	Stream_Read_UINT32(s, dwSigAlgId);
	Stream_Read_UINT32(s, dwKeyAlgId);

	if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
	{
		WLog_ERR(TAG, "unsupported signature or key algorithm, dwSigAlgId=%d dwKeyAlgId=%d",
				 dwSigAlgId, dwKeyAlgId);
		return FALSE;
	}

	Stream_Read_UINT16(s, wPublicKeyBlobType);

	if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
	{
		WLog_ERR(TAG, "unsupported public key blob type %d", wPublicKeyBlobType);
		return FALSE;
	}

	Stream_Read_UINT16(s, wPublicKeyBlobLen);

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

	if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
	{
		WLog_ERR(TAG, "error in server public key");
		return FALSE;
	}

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

	sigdatalen = Stream_Pointer(s) - sigdata;
	Stream_Read_UINT16(s, wSignatureBlobType);

	if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
	{
		WLog_ERR(TAG, "unsupported blob signature %d", wSignatureBlobType);
		return FALSE;
	}

	Stream_Read_UINT16(s, wSignatureBlobLen);

	if (Stream_GetRemainingLength(s) < wSignatureBlobLen)
	{
		WLog_ERR(TAG, "not enought bytes for signature(len=%d)", wSignatureBlobLen);
		return FALSE;
	}

	if (wSignatureBlobLen != 72)
	{
		WLog_ERR(TAG, "invalid signature length (got %d, expected %d)", wSignatureBlobLen, 64);
		return FALSE;
	}

	if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s, wSignatureBlobLen))
	{
		WLog_ERR(TAG, "unable to parse server public signature");
		return FALSE;
	}

	return TRUE;
}
Exemple #7
0
int transport_write(rdpTransport* transport, wStream* s)
{
	int length;
	int status = -1;

	EnterCriticalSection(&(transport->WriteLock));

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

#ifdef WITH_DEBUG_TRANSPORT
	if (length > 0)
	{
		fprintf(stderr, "Local > Remote\n");
		winpr_HexDump(Stream_Buffer(s), length);
	}
#endif

	if (length > 0)
	{
		WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
	}

	while (length > 0)
	{
		status = BIO_write(transport->frontBio, Stream_Pointer(s), length);

		if (status <= 0)
		{
			/* the buffered BIO that is at the end of the chain always says OK for writing,
			 * so a retry means that for any reason we need to read. The most probable
			 * is a SSL or TSG BIO in the chain.
			 */
			if (!BIO_should_retry(transport->frontBio))
				return status;

			/* non-blocking can live with blocked IOs */
			if (!transport->blocking)
				return status;

			if (transport_wait_for_write(transport) < 0)
			{
				fprintf(stderr, "%s: error when selecting for write\n", __FUNCTION__);
				return -1;
			}
			continue;
		}

		if (transport->blocking || transport->settings->WaitForOutputBufferFlush)
		{
			/* blocking transport, we must ensure the write buffer is really empty */
			rdpTcp *out = transport->TcpOut;

			while (out->writeBlocked)
			{
				if (transport_wait_for_write(transport) < 0)
				{
					fprintf(stderr, "%s: error when selecting for write\n", __FUNCTION__);
					return -1;
				}

				if (!transport_bio_buffered_drain(out->bufferedBio))
				{
					fprintf(stderr, "%s: error when draining outputBuffer\n", __FUNCTION__);
					return -1;
				}
			}
		}

		length -= status;
		Stream_Seek(s, status);
	}

	if (status < 0)
	{
		/* A write error indicates that the peer has dropped the connection */
		transport->layer = TRANSPORT_LAYER_CLOSED;
	}

	if (s->pool)
		Stream_Release(s);

	LeaveCriticalSection(&(transport->WriteLock));

	return status;
}
Exemple #8
0
int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
{
	TSMF_PRESENTATION* presentation;
	UINT32 numGeometryInfo;
	UINT32 Left;
	UINT32 Top;
	UINT32 Width;
	UINT32 Height;
	UINT32 cbVisibleRect;
	RDP_RECT* rects = NULL;
	int num_rects = 0;
	int error = 0;
	int i;
	int pos;

	presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
	Stream_Seek(ifman->input, 16);

	Stream_Read_UINT32(ifman->input, numGeometryInfo);
	pos = Stream_GetPosition(ifman->input);

	Stream_Seek(ifman->input, 12); /* VideoWindowId (8 bytes), VideoWindowState (4 bytes) */
	Stream_Read_UINT32(ifman->input, Width);
	Stream_Read_UINT32(ifman->input, Height);
	Stream_Read_UINT32(ifman->input, Left);
	Stream_Read_UINT32(ifman->input, Top);

	Stream_SetPosition(ifman->input, pos + numGeometryInfo);
	Stream_Read_UINT32(ifman->input, cbVisibleRect);
	num_rects = cbVisibleRect / 16;

	DEBUG_DVC("numGeometryInfo %d Width %d Height %d Left %d Top %d cbVisibleRect %d num_rects %d",
		numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);

	if (presentation == NULL)
	{
		error = 1;
	}
	else
	{
		if (num_rects > 0)
		{
			rects = (RDP_RECT*) malloc(sizeof(RDP_RECT) * num_rects);
			ZeroMemory(rects, sizeof(RDP_RECT) * num_rects);

			for (i = 0; i < num_rects; i++)
			{
				Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */
				Stream_Seek_UINT16(ifman->input);
				Stream_Read_UINT16(ifman->input, rects[i].x); /* Left */
				Stream_Seek_UINT16(ifman->input);
				Stream_Read_UINT16(ifman->input, rects[i].height); /* Bottom */
				Stream_Seek_UINT16(ifman->input);
				Stream_Read_UINT16(ifman->input, rects[i].width); /* Right */
				Stream_Seek_UINT16(ifman->input);
				rects[i].width -= rects[i].x;
				rects[i].height -= rects[i].y;

				DEBUG_DVC("rect %d: %d %d %d %d", i,
					rects[i].x, rects[i].y, rects[i].width, rects[i].height);
			}
		}
		tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects);
	}
	
	ifman->output_pending = TRUE;

	return error;
}
Exemple #9
0
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, wStream* input)
{
	char* s = NULL;
	mode_t m;
	UINT64 size;
	int status;
	char* fullpath;
	struct STAT st;
#if defined(__linux__) && !defined(ANDROID) || defined(sun)
	struct timespec tv[2];
#else
	struct timeval tv[2];
#endif
	UINT64 LastWriteTime;
	UINT32 FileAttributes;
	UINT32 FileNameLength;

	m = 0;

	switch (FsInformationClass)
	{
		case FileBasicInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
			Stream_Seek_UINT64(input); /* CreationTime */
			Stream_Seek_UINT64(input); /* LastAccessTime */
			Stream_Read_UINT64(input, LastWriteTime);
			Stream_Seek_UINT64(input); /* ChangeTime */
			Stream_Read_UINT32(input, FileAttributes);

			if (FSTAT(file->fd, &st) != 0)
				return FALSE;

			tv[0].tv_sec = st.st_atime;
			tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime);
#ifndef WIN32
			/* TODO on win32 */
#ifdef ANDROID
			tv[0].tv_usec = 0;
			tv[1].tv_usec = 0;
			utimes(file->fullpath, tv);
#elif defined (__linux__) || defined (sun)
			tv[0].tv_nsec = 0;
			tv[1].tv_nsec = 0;			
			futimens(file->fd, tv);
#else
			tv[0].tv_usec = 0;
			tv[1].tv_usec = 0;
			futimes(file->fd, tv);
#endif

			if (FileAttributes > 0)
			{
				m = st.st_mode;
				if ((FileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
					m |= S_IWUSR;
				else
					m &= ~S_IWUSR;
				if (m != st.st_mode)
					fchmod(file->fd, st.st_mode);
			}
#endif
			break;

		case FileEndOfFileInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232067.aspx */
		case FileAllocationInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
			Stream_Read_UINT64(input, size);
#ifndef _WIN32
			if (ftruncate(file->fd, size) != 0)
				return FALSE;
#endif
			break;

		case FileDispositionInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232098.aspx */
			/* http://msdn.microsoft.com/en-us/library/cc241371.aspx */
			if (file->is_dir && !dir_empty(file->fullpath))
				break;

			if (Length)
				Stream_Read_UINT8(input, file->delete_pending);
			else
				file->delete_pending = 1;
			break;

		case FileRenameInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232085.aspx */
			Stream_Seek_UINT8(input); /* ReplaceIfExists */
			Stream_Seek_UINT8(input); /* RootDirectory */
			Stream_Read_UINT32(input, FileNameLength);

			status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(input),
					FileNameLength / 2, &s, 0, NULL, NULL);

			if (status < 1)
				if (!(s = (char*) calloc(1, 1)))
				{
					WLog_ERR(TAG, "calloc failed!");
					return FALSE;
				}

			fullpath = drive_file_combine_fullpath(file->basepath, s);
			if (!fullpath)
			{
				WLog_ERR(TAG, "drive_file_combine_fullpath failed!");
				free (s);
				return FALSE;
			}
			free(s);

#ifdef _WIN32
			if (file->fd)
				close(file->fd);
#endif
			if (rename(file->fullpath, fullpath) == 0)
			{
				drive_file_set_fullpath(file, fullpath);
#ifdef _WIN32
				file->fd = OPEN(fullpath, O_RDWR | O_BINARY);
#endif
			}
			else
			{
				free(fullpath);
				return FALSE;
			}

			break;

		default:
			return FALSE;
	}

	return TRUE;
}
Exemple #10
0
static int remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header)
{
	int status;
	int cchStringW;
	WCHAR* pStringW;
	UINT32 msgLength;
	int cbExpertBlobW = 0;
	WCHAR* expertBlobW = NULL;
	int cbRaConnectionStringW = 0;
	WCHAR* raConnectionStringW = NULL;
	REMDESK_CTL_AUTHENTICATE_PDU pdu;

	msgLength = header->DataLength - 4;

	pStringW = (WCHAR*) Stream_Pointer(s);
	raConnectionStringW = pStringW;
	cchStringW = 0;

	while ((msgLength > 0) && pStringW[cchStringW])
	{
		msgLength -= 2;
		cchStringW++;
	}

	if (pStringW[cchStringW] || !cchStringW)
		return -1;

	cchStringW++;
	cbRaConnectionStringW = cchStringW * 2;

	pStringW += cchStringW;
	expertBlobW = pStringW;
	cchStringW = 0;

	while ((msgLength > 0) && pStringW[cchStringW])
	{
		msgLength -= 2;
		cchStringW++;
	}

	if (pStringW[cchStringW] || !cchStringW)
		return -1;

	cchStringW++;
	cbExpertBlobW = cchStringW * 2;

	pdu.raConnectionString = NULL;

	status = ConvertFromUnicode(CP_UTF8, 0, raConnectionStringW,
			cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL);

	if (status <= 0)
		return -1;

	pdu.expertBlob = NULL;

	status = ConvertFromUnicode(CP_UTF8, 0, expertBlobW,
			cbExpertBlobW / 2, &pdu.expertBlob, 0, NULL, NULL);

	if (status <= 0)
		return -1;

	printf("RaConnectionString: %s ExpertBlob: %s\n",
			pdu.raConnectionString, pdu.expertBlob);

	free(pdu.raConnectionString);
	free(pdu.expertBlob);

	return 1;
}
Exemple #11
0
static BOOL nego_read_request_token_or_cookie(rdpNego* nego, wStream* s)
{
	/* routingToken and cookie are optional and mutually exclusive!
	 *
	 * routingToken (variable): An optional and variable-length routing
	 * token (used for load balancing) terminated by a 0x0D0A two-byte
	 * sequence: (check [MSFT-SDLBTS] for details!)
	 * Cookie:[space]msts=[ip address].[port].[reserved][\x0D\x0A]
	 *
	 * cookie (variable): An optional and variable-length ANSI character
	 * string terminated by a 0x0D0A two-byte sequence:
	 * Cookie:[space]mstshash=[ANSISTRING][\x0D\x0A]
	 */
	BYTE* str = NULL;
	UINT16 crlf = 0;
	size_t pos, len;
	BOOL result = FALSE;
	BOOL isToken = FALSE;
	str = Stream_Pointer(s);
	pos = Stream_GetPosition(s);

	/* minimum length for token is 15 */
	if (Stream_GetRemainingLength(s) < 15)
		return TRUE;

	if (memcmp(Stream_Pointer(s), "Cookie: mstshash=", 17) != 0)
	{
		isToken = TRUE;
	}
	else
	{
		/* not a token, minimum length for cookie is 19 */
		if (Stream_GetRemainingLength(s) < 19)
			return TRUE;

		Stream_Seek(s, 17);
	}

	while (Stream_GetRemainingLength(s) >= 2)
	{
		Stream_Read_UINT16(s, crlf);

		if (crlf == 0x0A0D)
			break;

		Stream_Rewind(s, 1);
	}

	if (crlf == 0x0A0D)
	{
		Stream_Rewind(s, 2);
		len = Stream_GetPosition(s) - pos;
		Stream_Write_UINT16(s, 0);

		if (strlen((char*)str) == len)
		{
			if (isToken)
				result = nego_set_routing_token(nego, str, len);
			else
				result = nego_set_cookie(nego, (char*)str);
		}
	}

	if (!result)
	{
		Stream_SetPosition(s, pos);
		WLog_ERR(TAG, "invalid %s received",
		         isToken ? "routing token" : "cookie");
	}
	else
	{
		WLog_DBG(TAG, "received %s [%s]",
		         isToken ? "routing token" : "cookie", str);
	}

	return result;
}
Exemple #12
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
	UINT error;
	UINT32 tmp;
	size_t pos1, pos2;
	wStream* s;
	RDPGFX_AVC444_BITMAP_STREAM h264;
	RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;

	s = Stream_New(cmd->data, cmd->length);

	if (!s)
	{
		WLog_ERR(TAG, "Stream_New failed!");
		return CHANNEL_RC_NO_MEMORY;
	}

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

	Stream_Read_UINT32(s, tmp);
	h264.cbAvc420EncodedBitstream1 = tmp & 0x3FFFFFFFUL;
	h264.LC = (tmp >> 30UL) & 0x03UL;

	if (h264.LC == 0x03)
		return ERROR_INVALID_DATA;

	pos1 = Stream_GetPosition(s);
	if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[0].meta))))
	{
		WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %"PRIu32"!", error);
		return error;
	}
	pos2 = Stream_GetPosition(s);

	h264.bitstream[0].data = Stream_Pointer(s);

	if (h264.LC == 0)
	{
		tmp = h264.cbAvc420EncodedBitstream1 - pos2 + pos1;
		if (Stream_GetRemainingLength(s) < tmp)
			return ERROR_INVALID_DATA;

		h264.bitstream[0].length = tmp;
		Stream_Seek(s, tmp);

		if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[1].meta))))
		{
			WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %"PRIu32"!", error);
			return error;
		}

		h264.bitstream[1].data = Stream_Pointer(s);
		h264.bitstream[1].length = Stream_GetRemainingLength(s);
	}
	else
	{
		h264.bitstream[0].length = Stream_GetRemainingLength(s);
		memset(&h264.bitstream[1], 0, sizeof(h264.bitstream[1]));
	}

	Stream_Free(s, FALSE);

	cmd->extra = (void*) &h264;

	if (context)
	{
		IFCALLRET(context->SurfaceCommand, error, context, cmd);
		if (error)
			WLog_ERR(TAG, "context->SurfaceCommand failed with error %"PRIu32"", error);
	}

	free(h264.bitstream[0].meta.regionRects);
	free(h264.bitstream[0].meta.quantQualityVals);
	free(h264.bitstream[1].meta.regionRects);
	free(h264.bitstream[1].meta.quantQualityVals);

	return error;
}
Exemple #13
0
BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings)
{
	UINT32 flags;
	UINT16 cbDomain;
	UINT16 cbUserName;
	UINT16 cbPassword;
	UINT16 cbAlternateShell;
	UINT16 cbWorkingDir;

	if (Stream_GetRemainingLength(s) < 18) // invalid packet
		return FALSE;

	Stream_Seek_UINT32(s); /* CodePage */
	Stream_Read_UINT32(s, flags); /* flags */

	settings->AudioCapture = ((flags & RNS_INFO_AUDIOCAPTURE) ? TRUE : FALSE);
	settings->AudioPlayback = ((flags & INFO_NOAUDIOPLAYBACK) ? FALSE : TRUE);
	settings->AutoLogonEnabled = ((flags & INFO_AUTOLOGON) ? TRUE : FALSE);
	settings->RemoteApplicationMode = ((flags & INFO_RAIL) ? TRUE : FALSE);
	settings->RemoteConsoleAudio = ((flags & INFO_REMOTECONSOLEAUDIO) ? TRUE : FALSE);
	settings->CompressionEnabled = ((flags & INFO_COMPRESSION) ? TRUE : FALSE);

	Stream_Read_UINT16(s, cbDomain); /* cbDomain */
	Stream_Read_UINT16(s, cbUserName); /* cbUserName */
	Stream_Read_UINT16(s, cbPassword); /* cbPassword */
	Stream_Read_UINT16(s, cbAlternateShell); /* cbAlternateShell */
	Stream_Read_UINT16(s, cbWorkingDir); /* cbWorkingDir */

	if (Stream_GetRemainingLength(s) < cbDomain + 2)
		return FALSE;

	if (cbDomain > 0)
	{
		ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain / 2, &settings->Domain, 0, NULL, NULL);
		Stream_Seek(s, cbDomain);
	}
	Stream_Seek(s, 2);

	if (Stream_GetRemainingLength(s) < cbUserName + 2)
		return FALSE;

	if (cbUserName > 0)
	{
		ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName / 2, &settings->Username, 0, NULL, NULL);
		Stream_Seek(s, cbUserName);
	}
	Stream_Seek(s, 2);

	if (Stream_GetRemainingLength(s) < cbPassword + 2)
		return FALSE;

	if (cbPassword > 0)
	{
		ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbPassword / 2, &settings->Password, 0, NULL, NULL);
		Stream_Seek(s, cbPassword);
	}
	Stream_Seek(s, 2);

	if (Stream_GetRemainingLength(s) < cbAlternateShell + 2)
		return FALSE;

	if (cbAlternateShell > 0)
	{
		ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbAlternateShell / 2, &settings->AlternateShell, 0, NULL, NULL);
		Stream_Seek(s, cbAlternateShell);
	}
	Stream_Seek(s, 2);

	if (Stream_GetRemainingLength(s) < cbWorkingDir + 2)
		return FALSE;

	if (cbWorkingDir > 0)
	{
		ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbWorkingDir / 2, &settings->ShellWorkingDirectory, 0, NULL, NULL);
		Stream_Seek(s, cbWorkingDir);
	}
	Stream_Seek(s, 2);

	if (settings->RdpVersion >= 5)
		return rdp_read_extended_info_packet(s, settings); /* extraInfo */

	return TRUE;
}
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
{
	CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);

	if (context->custom)
	{
		UINT32 index;
		int formatNameLength;
		CLIPRDR_FORMAT* formats;
		CLIPRDR_FORMAT_LIST formatList;

		formatList.msgType = CB_FORMAT_LIST;
		formatList.msgFlags = msgFlags;
		formatList.dataLen = dataLen;

		formatList.cFormats = 0;

		while (dataLen)
		{
			Stream_Seek(s, 4); /* formatId */
			dataLen -= 4;

			formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s));
			Stream_Seek(s, (formatNameLength + 1) * 2);
			dataLen -= ((formatNameLength + 1) * 2);
			formatList.cFormats++;
		}

		index = 0;
		dataLen = formatList.dataLen;
		Stream_Rewind(s, dataLen);

		formats = (CLIPRDR_FORMAT*) malloc(sizeof(CLIPRDR_FORMAT) * formatList.cFormats);
		formatList.formats = formats;

		while (dataLen)
		{
			Stream_Read_UINT32(s, formats[index].formatId); /* formatId */
			dataLen -= 4;

			formats[index].formatName = NULL;
			formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s));

			if (formatNameLength)
			{
				formatNameLength = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
					-1, &(formats[index].formatName), 0, NULL, NULL);

				Stream_Seek(s, formatNameLength * 2);
				dataLen -= (formatNameLength * 2);
			}
			else
			{
				Stream_Seek(s, 2);
				dataLen -= 2;
			}

			index++;
		}

		if (context->ServerFormatList)
			context->ServerFormatList(context, &formatList);

		for (index = 0; index < formatList.cFormats; index++)
			free(formats[index].formatName);

		free(formats);
	}
	else
	{
		int i;
		UINT32 format;
		BOOL supported;
		CLIPRDR_FORMAT_NAME* format_name;
		RDP_CB_FORMAT_LIST_EVENT* cb_event;

		cb_event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
				CliprdrChannel_FormatList, NULL, NULL);

		if (dataLen > 0)
		{
			cb_event->raw_format_data = (BYTE*) malloc(dataLen);
			memcpy(cb_event->raw_format_data, Stream_Pointer(s), dataLen);
			cb_event->raw_format_data_size = dataLen;
			cb_event->raw_format_unicode = (msgFlags & CB_ASCII_NAMES) ? FALSE : TRUE;
		}

		if (cliprdr->use_long_format_names)
			cliprdr_process_long_format_names(cliprdr, s, dataLen, msgFlags);
		else
			cliprdr_process_short_format_names(cliprdr, s, dataLen, msgFlags);

		if (cliprdr->num_format_names > 0)
			cb_event->formats = (UINT32*) malloc(sizeof(UINT32) * cliprdr->num_format_names);

		cb_event->num_formats = 0;

		for (i = 0; i < cliprdr->num_format_names; i++)
		{
			supported = TRUE;
			format_name = &cliprdr->format_names[i];
			format = format_name->id;

			switch (format)
			{
				case CB_FORMAT_TEXT:
				case CB_FORMAT_DIB:
				case CB_FORMAT_UNICODETEXT:
					break;

				default:

					if (format_name->length > 0)
					{
						DEBUG_CLIPRDR("format: %s", format_name->name);

						if (strcmp(format_name->name, "HTML Format") == 0)
						{
							format = CB_FORMAT_HTML;
							break;
						}
						if (strcmp(format_name->name, "PNG") == 0)
						{
							format = CB_FORMAT_PNG;
							break;
						}
						if (strcmp(format_name->name, "JFIF") == 0)
						{
							format = CB_FORMAT_JPEG;
							break;
						}
						if (strcmp(format_name->name, "GIF") == 0)
						{
							format = CB_FORMAT_GIF;
							break;
						}
					}
					else
					{
						supported = FALSE;
					}

					break;
			}

			if (supported)
				cb_event->formats[cb_event->num_formats++] = format;

			if (format_name->length > 0)
				free(format_name->name);
		}

		free(cliprdr->format_names);
		cliprdr->format_names = NULL;

		cliprdr->num_format_names = 0;

		svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
		cliprdr_send_format_list_response(cliprdr);
	}
}
Exemple #15
0
static BOOL TestStream_Verify(wStream* s, int mincap, int len, size_t pos)
{
	if (Stream_Buffer(s) == NULL)
	{
		printf("stream buffer is null\n");
		return FALSE;
	}
	if (Stream_Pointer(s) == NULL)
	{
		printf("stream pointer is null\n");
		return FALSE;
	}
	if (Stream_Pointer(s) < Stream_Buffer(s))
	{
		printf("stream pointer (%p) or buffer (%p) is invalid\n",
			(void*) Stream_Pointer(s), (void*) Stream_Buffer(s));
		return FALSE;
	}
	if (Stream_Capacity(s) < mincap) {
		printf("stream capacity is %"PRIuz" but minimum expected value is %d\n",
			Stream_Capacity(s), mincap);
		return FALSE;
	}
	if (Stream_Length(s) != len) {
		printf("stream has unexpected length (%"PRIuz" instead of %d)\n",
			Stream_Length(s), len);
		return FALSE;
	}
	if (Stream_GetPosition(s) != pos)
	{
		printf("stream has unexpected position (%"PRIuz" instead of %d)\n",
			Stream_GetPosition(s), pos);
		return FALSE;
	}
	if (Stream_GetPosition(s) > Stream_Length(s))
	{
		printf("stream position (%"PRIuz") exceeds length (%"PRIuz")\n",
			Stream_GetPosition(s), Stream_Length(s));
		return FALSE;
	}
	if (Stream_GetPosition(s) > Stream_Capacity(s))
	{
		printf("stream position (%"PRIuz") exceeds capacity (%"PRIuz")\n",
			Stream_GetPosition(s), Stream_Capacity(s));
		return FALSE;
	}
	if (Stream_Length(s) > Stream_Capacity(s))
	{
		printf("stream length (%"PRIuz") exceeds capacity (%"PRIuz")\n",
			Stream_Length(s), Stream_Capacity(s));
		return FALSE;
	}
	if (Stream_GetRemainingLength(s) != len - pos)
	{
		printf("stream remaining length (%"PRIuz" instead of %d)\n",
			Stream_GetRemainingLength(s), len - pos);
		return FALSE;
	}

	return TRUE;
}
Exemple #16
0
BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
{
	UINT16 clientAddressFamily;
	UINT16 cbClientAddress;
	UINT16 cbClientDir;
	UINT16 cbAutoReconnectLen;
	rdpSettings* settings = rdp->settings;
	WCHAR* wstr;

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

	Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily (2 bytes) */
	Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress (2 bytes) */

	/* cbClientAddress is the size in bytes of the character data in the clientAddress field.
	 * This size includes the length of the mandatory null terminator.
	 * The maximum allowed value is 80 bytes
	 * Note: Although according to [MS-RDPBCGR 2.2.1.11.1.1.1] the null terminator
	 * is mandatory, connections via Microsoft's TS Gateway set cbClientAddress to 0.
	 */

	if ((cbClientAddress % 2) || cbClientAddress > 80)
	{
		WLog_ERR(TAG, "protocol error: invalid cbClientAddress value: %u", cbClientAddress);
		return FALSE;
	}

	settings->IPv6Enabled = (clientAddressFamily == ADDRESS_FAMILY_INET6 ? TRUE : FALSE);

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

	if (settings->ClientAddress)
	{
		free(settings->ClientAddress);
		settings->ClientAddress = NULL;
	}

	if (cbClientAddress)
	{
		wstr = (WCHAR*) Stream_Pointer(s);
		if (wstr[cbClientAddress / 2 - 1])
		{
			WLog_ERR(TAG, "protocol error: clientAddress must be null terminated");
			return FALSE;
		}
		if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->ClientAddress, 0, NULL, NULL) < 1)
		{
			WLog_ERR(TAG, "failed to convert client address");
			return FALSE;
		}
		Stream_Seek(s, cbClientAddress);
		WLog_DBG(TAG, "rdp client address: [%s]", settings->ClientAddress);
	}

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

	Stream_Read_UINT16(s, cbClientDir); /* cbClientDir (2 bytes) */

	/* cbClientDir is the size in bytes of the character data in the clientDir field.
	 * This size includes the length of the mandatory null terminator.
	 * The maximum allowed value is 512 bytes.
	 * Note: Although according to [MS-RDPBCGR 2.2.1.11.1.1.1] the null terminator
	 * is mandatory the Microsoft Android client (starting with version 8.1.31.44)
	 * sets cbClientDir to 0.
	 */

	if ((cbClientDir % 2) || cbClientDir > 512)
	{
		WLog_ERR(TAG, "protocol error: invalid cbClientDir value: %u", cbClientDir);
		return FALSE;
	}

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

	if (settings->ClientDir)
	{
		free(settings->ClientDir);
		settings->ClientDir = NULL;
	}

	if (cbClientDir)
	{
		wstr = (WCHAR*) Stream_Pointer(s);
		if (wstr[cbClientDir / 2 - 1])
		{
			WLog_ERR(TAG, "protocol error: clientDir must be null terminated");
			return FALSE;
		}
		if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1, &settings->ClientDir, 0, NULL, NULL) < 1)
		{
			WLog_ERR(TAG, "failed to convert client directory");
			return FALSE;
		}
		Stream_Seek(s, cbClientDir);
		WLog_DBG(TAG, "rdp client dir: [%s]", settings->ClientDir);
	}

	/**
	 * down below all fields are optional but if one field is not present,
	 * then all of the subsequent fields also MUST NOT be present.
	 */

	/* optional: clientTimeZone (172 bytes) */
	if (Stream_GetRemainingLength(s) == 0)
		return TRUE;
	if (!rdp_read_client_time_zone(s, settings))
		return FALSE;

	/* optional: clientSessionId (4 bytes), should be set to 0 */
	if (Stream_GetRemainingLength(s) == 0)
		return TRUE;
	if (Stream_GetRemainingLength(s) < 4)
		return FALSE;
	Stream_Seek_UINT32(s);

	/* optional: performanceFlags (4 bytes) */
	if (Stream_GetRemainingLength(s) == 0)
		return TRUE;
	if (Stream_GetRemainingLength(s) < 4)
		return FALSE;
	Stream_Read_UINT32(s, settings->PerformanceFlags);
	freerdp_performance_flags_split(settings);

	/* optional: cbAutoReconnectLen (2 bytes) */
	if (Stream_GetRemainingLength(s) == 0)
		return TRUE;
	if (Stream_GetRemainingLength(s) < 2)
		return FALSE;
	Stream_Read_UINT16(s, cbAutoReconnectLen);

	/* optional: autoReconnectCookie (28 bytes) */
	/* must be present if cbAutoReconnectLen is > 0 */
	if (cbAutoReconnectLen > 0)
		return rdp_read_client_auto_reconnect_cookie(rdp, s);

	/* TODO */

	/* reserved1 (2 bytes) */
	/* reserved2 (2 bytes) */
	/* cbDynamicDSTTimeZoneKeyName (2 bytes) */
	/* dynamicDSTTimeZoneKeyName (variable) */
	/* dynamicDaylightTimeDisabled (2 bytes) */

	return TRUE;
}
Exemple #17
0
int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
{
	BYTE type;
	UINT32 roff;
	UINT32 rlen;
	wStream* cs;
	BYTE* buffer;
	UINT16 length;
	UINT32 share_id;
	BYTE compressed_type;
	UINT16 compressed_len;

	if (!rdp_read_share_data_header(s, &length, &type, &share_id, &compressed_type, &compressed_len))
		return -1;

	cs = s;

	if (compressed_type & PACKET_COMPRESSED)
	{
		if (Stream_GetRemainingLength(s) < compressed_len - 18)
		{
			fprintf(stderr, "decompress_rdp: not enough bytes for compressed_len=%d\n", compressed_len);
			return -1;	
		}

		if (decompress_rdp(rdp->mppc_dec, Stream_Pointer(s), compressed_len - 18, compressed_type, &roff, &rlen))
		{
			buffer = rdp->mppc_dec->history_buf + roff;
			cs = StreamPool_Take(rdp->transport->ReceivePool, rlen);

			Stream_SetPosition(cs, 0);
			Stream_Write(cs, buffer, rlen);
			Stream_SealLength(cs);
			Stream_SetPosition(cs, 0);
		}
		else
		{
			fprintf(stderr, "decompress_rdp() failed\n");
			return -1;
		}

		Stream_Seek(s, compressed_len - 18);
	}

#ifdef WITH_DEBUG_RDP
	/* if (type != DATA_PDU_TYPE_UPDATE) */
		DEBUG_RDP("recv %s Data PDU (0x%02X), length:%d",
				type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
#endif

	switch (type)
	{
		case DATA_PDU_TYPE_UPDATE:
			if (!update_recv(rdp->update, cs))
				return -1;
			break;

		case DATA_PDU_TYPE_CONTROL:
			if (!rdp_recv_server_control_pdu(rdp, cs))
				return -1;
			break;

		case DATA_PDU_TYPE_POINTER:
			if (!update_recv_pointer(rdp->update, cs))
				return -1;
			break;

		case DATA_PDU_TYPE_INPUT:
			break;

		case DATA_PDU_TYPE_SYNCHRONIZE:
			if (!rdp_recv_synchronize_pdu(rdp, cs))
				return -1;
			break;

		case DATA_PDU_TYPE_REFRESH_RECT:
			break;

		case DATA_PDU_TYPE_PLAY_SOUND:
			if (!update_recv_play_sound(rdp->update, cs))
				return -1;
			break;

		case DATA_PDU_TYPE_SUPPRESS_OUTPUT:
			break;

		case DATA_PDU_TYPE_SHUTDOWN_REQUEST:
			break;

		case DATA_PDU_TYPE_SHUTDOWN_DENIED:
			break;

		case DATA_PDU_TYPE_SAVE_SESSION_INFO:
			if (!rdp_recv_save_session_info(rdp, cs))
				return -1;
			break;

		case DATA_PDU_TYPE_FONT_LIST:
			break;

		case DATA_PDU_TYPE_FONT_MAP:
			if (!rdp_recv_font_map_pdu(rdp, cs))
				return -1;
			break;

		case DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS:
			break;

		case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST:
			break;

		case DATA_PDU_TYPE_BITMAP_CACHE_ERROR:
			break;

		case DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS:
			break;

		case DATA_PDU_TYPE_OFFSCREEN_CACHE_ERROR:
			break;

		case DATA_PDU_TYPE_SET_ERROR_INFO:
			if (!rdp_recv_set_error_info_data_pdu(rdp, cs))
				return -1;
			break;

		case DATA_PDU_TYPE_DRAW_NINEGRID_ERROR:
			break;

		case DATA_PDU_TYPE_DRAW_GDIPLUS_ERROR:
			break;

		case DATA_PDU_TYPE_ARC_STATUS:
			break;

		case DATA_PDU_TYPE_STATUS_INFO:
			break;

		case DATA_PDU_TYPE_MONITOR_LAYOUT:
			break;

		default:
			break;
	}

	if (cs != s)
		Stream_Release(cs);

	return 0;
}
Exemple #18
0
HttpResponse* http_response_recv(rdpTls* tls)
{
	wStream* s;
	int size;
	int count;
	int status;
	int position;
	char* line;
	char* buffer;
	char* header;
	char* payload;
	int bodyLength;
	int payloadOffset;
	HttpResponse* response;

	size = 1024;
	payload = NULL;
	payloadOffset = 0;

	s = Stream_New(NULL, size);

	if (!s)
		goto out_free;

	buffer = (char*) Stream_Buffer(s);

	response = http_response_new();

	if (!response)
		goto out_free;

	response->ContentLength = 0;

	while (TRUE)
	{
		while (!payloadOffset)
		{
			status = BIO_read(tls->bio, Stream_Pointer(s), Stream_Capacity(s) - Stream_GetPosition(s));

			if (status <= 0)
			{
				if (!BIO_should_retry(tls->bio))
					goto out_error;

				USleep(100);
				continue;
			}

#ifdef HAVE_VALGRIND_MEMCHECK_H
			VALGRIND_MAKE_MEM_DEFINED(Stream_Pointer(s), status);
#endif

			Stream_Seek(s, status);

			if (Stream_GetRemainingLength(s) < 1024)
			{
				Stream_EnsureRemainingCapacity(s, 1024);
				buffer = (char*) Stream_Buffer(s);
				payload = &buffer[payloadOffset];
			}

			position = Stream_GetPosition(s);

			if (position >= 4)
			{
				line = string_strnstr(buffer, "\r\n\r\n", position);

				if (line)
				{
					payloadOffset = (line - buffer) + 4;
					payload = &buffer[payloadOffset];
				}
			}
		}

		if (payloadOffset)
		{
			count = 0;
			line = buffer;

			position = Stream_GetPosition(s);

			while ((line = string_strnstr(line, "\r\n", payloadOffset - (line - buffer) - 2)))
			{
				line += 2;
				count++;
			}

			response->count = count;

			if (count)
			{
				response->lines = (char**) calloc(response->count, sizeof(char*));

				if (!response->lines)
					goto out_error;
			}

			header = (char*) malloc(payloadOffset);

			if (!header)
				goto out_error;

			CopyMemory(header, buffer, payloadOffset);
			header[payloadOffset - 1] = '\0';
			header[payloadOffset - 2] = '\0';

			count = 0;
			line = strtok(header, "\r\n");

			while (line && response->lines)
			{
				response->lines[count] = _strdup(line);

				if (!response->lines[count])
					goto out_error;

				line = strtok(NULL, "\r\n");
				count++;
			}

			free(header);

			if (!http_response_parse_header(response))
				goto out_error;

			response->BodyLength = Stream_GetPosition(s) - payloadOffset;

			if (response->BodyLength > 0)
			{
				response->BodyContent = (BYTE*) malloc(response->BodyLength);

				if (!response->BodyContent)
					goto out_error;

				CopyMemory(response->BodyContent, payload, response->BodyLength);
			}

			bodyLength = 0; /* expected body length */

			if (response->ContentType)
			{
				if (_stricmp(response->ContentType, "text/plain") == 0)
				{
					bodyLength = response->ContentLength;
				}
			}

			if (bodyLength != response->BodyLength)
			{
				WLog_WARN(TAG, "http_response_recv: %s unexpected body length: actual: %d, expected: %d",
						response->ContentType, response->ContentLength, response->BodyLength);
			}

			break;
		}

		if (Stream_GetRemainingLength(s) < 1024)
		{
			Stream_EnsureRemainingCapacity(s, 1024);
			buffer = (char*) Stream_Buffer(s);
			payload = &buffer[payloadOffset];
		}
	}

	Stream_Free(s, TRUE);
	return response;
out_error:
	http_response_free(response);
out_free:
	Stream_Free(s, TRUE);
	return NULL;
}
Exemple #19
0
BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
{
	UINT16 clientAddressFamily;
	UINT16 cbClientAddress;
	UINT16 cbClientDir;
	UINT16 cbAutoReconnectLen;
	rdpSettings* settings = rdp->settings;

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

	Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily (2 bytes) */
	Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress (2 bytes) */

	settings->IPv6Enabled = (clientAddressFamily == ADDRESS_FAMILY_INET6 ? TRUE : FALSE);

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

	if (settings->ClientAddress)
	{
		free(settings->ClientAddress);
		settings->ClientAddress = NULL;
	}

	ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbClientAddress / 2, &settings->ClientAddress, 0, NULL, NULL);
	Stream_Seek(s, cbClientAddress);

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

	Stream_Read_UINT16(s, cbClientDir); /* cbClientDir (2 bytes) */

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

	if (settings->ClientDir)
	{
		free(settings->ClientDir);
		settings->ClientDir = NULL;
	}

	ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbClientDir / 2, &settings->ClientDir, 0, NULL, NULL);
	Stream_Seek(s, cbClientDir);

	if (!rdp_read_client_time_zone(s, settings))
		return FALSE;

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

	Stream_Seek_UINT32(s); /* clientSessionId (4 bytes), should be set to 0 */
	Stream_Read_UINT32(s, settings->PerformanceFlags); /* performanceFlags (4 bytes) */
	freerdp_performance_flags_split(settings);

	Stream_Read_UINT16(s, cbAutoReconnectLen); /* cbAutoReconnectLen (2 bytes) */

	if (cbAutoReconnectLen > 0)
		return rdp_read_client_auto_reconnect_cookie(rdp, s); /* autoReconnectCookie */

	/* reserved1 (2 bytes) */
	/* reserved2 (2 bytes) */

	return TRUE;
}
Exemple #20
0
BOOL gcc_read_client_core_data(wStream* s, rdpSettings* settings, UINT16 blockLength)
{
	char* str = NULL;
	UINT32 version;
	UINT32 color_depth;
	UINT16 colorDepth = 0;
	UINT16 postBeta2ColorDepth = 0;
	UINT16 highColorDepth = 0;
	UINT16 supportedColorDepths = 0;
	UINT32 serverSelectedProtocol = 0;

	/* Length of all required fields, until imeFileName */
	if (blockLength < 128)
		return FALSE;

	Stream_Read_UINT32(s, version); /* version */
	settings->RdpVersion = (version == RDP_VERSION_4 ? 4 : 7);

	Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth */
	Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight */
	Stream_Read_UINT16(s, colorDepth); /* ColorDepth */
	Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) */
	Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout */
	Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild */

	/* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
	ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL);
	Stream_Seek(s, 32);
	sprintf_s(settings->ClientHostname, 31, "%s", str);
	settings->ClientHostname[31] = 0;
	free(str);
	str = NULL;

	Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType */
	Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */
	Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey */

	Stream_Seek(s, 64); /* imeFileName */

	blockLength -= 128;

	/**
	 * The following fields are all optional. If one field is present, all of the preceding
	 * fields MUST also be present. If one field is not present, all of the subsequent fields
	 * MUST NOT be present.
	 * We must check the bytes left before reading each field.
	 */

	do
	{
		if (blockLength < 2)
			break;
		Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */
		blockLength -= 2;

		if (blockLength < 2)
			break;
		Stream_Seek_UINT16(s); /* clientProductID */
		blockLength -= 2;

		if (blockLength < 4)
			break;
		Stream_Seek_UINT32(s); /* serialNumber */
		blockLength -= 4;

		if (blockLength < 2)
			break;
		Stream_Read_UINT16(s, highColorDepth); /* highColorDepth */
		blockLength -= 2;

		if (blockLength < 2)
			break;
		Stream_Read_UINT16(s, supportedColorDepths); /* supportedColorDepths */
		blockLength -= 2;

		if (blockLength < 2)
			break;
		Stream_Read_UINT16(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags */
		blockLength -= 2;

		if (blockLength < 64)
			break;

		ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL);
		Stream_Seek(s, 64);
		sprintf_s(settings->ClientProductId, 32, "%s", str);
		free(str);
		blockLength -= 64;

		if (blockLength < 1)
			break;
		Stream_Read_UINT8(s, settings->PerformanceFlags); /* connectionType */
		blockLength -= 1;

		if (blockLength < 1)
			break;
		Stream_Seek_UINT8(s); /* pad1octet */
		blockLength -= 1;

		if (blockLength < 4)
			break;
		Stream_Read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol */
		blockLength -= 4;

		if (settings->SelectedProtocol != serverSelectedProtocol)
			return FALSE;
	} while (0);

	if (highColorDepth > 0)
	{
		if (settings->EarlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION)
			color_depth = 32;
		else
			color_depth = highColorDepth;
	}
	else if (postBeta2ColorDepth > 0)
	{
		switch (postBeta2ColorDepth)
		{
			case RNS_UD_COLOR_4BPP:
				color_depth = 4;
				break;
			case RNS_UD_COLOR_8BPP:
				color_depth = 8;
				break;
			case RNS_UD_COLOR_16BPP_555:
				color_depth = 15;
				break;
			case RNS_UD_COLOR_16BPP_565:
				color_depth = 16;
				break;
			case RNS_UD_COLOR_24BPP:
				color_depth = 24;
				break;
			default:
				return FALSE;
		}
	}
	else
	{
		switch (colorDepth)
		{
			case RNS_UD_COLOR_4BPP:
				color_depth = 4;
				break;
			case RNS_UD_COLOR_8BPP:
				color_depth = 8;
				break;
			default:
				return FALSE;
		}
	}

	/*
	 * If we are in server mode, accept client's color depth only if
	 * it is smaller than ours. This is what Windows server does.
	 */
	if ((color_depth < settings->ColorDepth) || !settings->ServerMode)
		settings->ColorDepth = color_depth;

	return TRUE;
}
Exemple #21
0
int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
{
    BYTE type;
    wStream* cs;
    UINT16 length;
    UINT32 shareId;
    BYTE compressedType;
    UINT16 compressedLength;

    if (!rdp_read_share_data_header(s, &length, &type, &shareId, &compressedType, &compressedLength))
        return -1;

    cs = s;

    if (compressedType & PACKET_COMPRESSED)
    {
        UINT32 DstSize = 0;
        BYTE* pDstData = NULL;
        UINT32 SrcSize = compressedLength - 18;

        if (Stream_GetRemainingLength(s) < (size_t) SrcSize)
        {
            DEBUG_WARN( "bulk_decompress: not enough bytes for compressedLength %d\n", compressedLength);
            return -1;
        }

        if (bulk_decompress(rdp->bulk, Stream_Pointer(s), SrcSize, &pDstData, &DstSize, compressedType))
        {
            cs = StreamPool_Take(rdp->transport->ReceivePool, DstSize);

            Stream_SetPosition(cs, 0);
            Stream_Write(cs, pDstData, DstSize);
            Stream_SealLength(cs);
            Stream_SetPosition(cs, 0);
        }
        else
        {
            DEBUG_WARN( "bulk_decompress() failed\n");
            return -1;
        }

        Stream_Seek(s, SrcSize);
    }

#ifdef WITH_DEBUG_RDP
    DEBUG_MSG("recv %s Data PDU (0x%02X), length: %d\n",
              type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
#endif

    switch (type)
    {
    case DATA_PDU_TYPE_UPDATE:
        if (!update_recv(rdp->update, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_CONTROL:
        if (!rdp_recv_server_control_pdu(rdp, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_POINTER:
        if (!update_recv_pointer(rdp->update, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_SYNCHRONIZE:
        if (!rdp_recv_synchronize_pdu(rdp, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_PLAY_SOUND:
        if (!update_recv_play_sound(rdp->update, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_SHUTDOWN_DENIED:
        if (!rdp_recv_server_shutdown_denied_pdu(rdp, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_SAVE_SESSION_INFO:
        if (!rdp_recv_save_session_info(rdp, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_FONT_MAP:
        if (!rdp_recv_font_map_pdu(rdp, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS:
        if (!rdp_recv_server_set_keyboard_indicators_pdu(rdp, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS:
        if (!rdp_recv_server_set_keyboard_ime_status_pdu(rdp, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_SET_ERROR_INFO:
        if (!rdp_recv_set_error_info_data_pdu(rdp, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_ARC_STATUS:
        if (!rdp_recv_server_auto_reconnect_status_pdu(rdp, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_STATUS_INFO:
        if (!rdp_recv_server_status_info_pdu(rdp, cs))
            return -1;
        break;

    case DATA_PDU_TYPE_MONITOR_LAYOUT:
        if (!rdp_recv_monitor_layout_pdu(rdp, cs))
            return -1;
        break;

    default:
        break;
    }

    if (cs != s)
        Stream_Release(cs);

    return 0;
}
Exemple #22
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
{
	UINT32 index;
	UINT32 position;
	BOOL asciiNames;
	int formatNameLength;
	char* szFormatName;
	WCHAR* wszFormatName;
	CLIPRDR_FORMAT* formats = NULL;
	CLIPRDR_FORMAT_LIST formatList;
	CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
	UINT error = CHANNEL_RC_OK;

	if (!context->custom)
	{
		WLog_ERR(TAG, "context->custom not set!");
		return ERROR_INTERNAL_ERROR;
	}

	asciiNames = (msgFlags & CB_ASCII_NAMES) ? TRUE : FALSE;

	formatList.msgType = CB_FORMAT_LIST;
	formatList.msgFlags = msgFlags;
	formatList.dataLen = dataLen;

	index = 0;
	formatList.numFormats = 0;
	position = Stream_GetPosition(s);

	if (!formatList.dataLen)
	{
		/* empty format list */
		formatList.formats = NULL;
		formatList.numFormats = 0;
	}
	else if (!cliprdr->useLongFormatNames)
	{
		formatList.numFormats = (dataLen / 36);

		if ((formatList.numFormats * 36) != dataLen)
		{
			WLog_ERR(TAG, "Invalid short format list length: %d", dataLen);
			return ERROR_INTERNAL_ERROR;
		}

		if (formatList.numFormats)
			formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, sizeof(CLIPRDR_FORMAT));

		if (!formats)
		{
			WLog_ERR(TAG, "calloc failed!");
			return CHANNEL_RC_NO_MEMORY;
		}

		formatList.formats = formats;

		while (dataLen)
		{
			Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */
			dataLen -= 4;

			formats[index].formatName = NULL;

			if (asciiNames)
			{
				szFormatName = (char*) Stream_Pointer(s);

				if (szFormatName[0])
				{
					formats[index].formatName = (char*) malloc(32 + 1);
					if (!formats[index].formatName)
					{
						WLog_ERR(TAG, "calloc failed!");
						error = CHANNEL_RC_NO_MEMORY;
						goto error_out;
					}
					CopyMemory(formats[index].formatName, szFormatName, 32);
					formats[index].formatName[32] = '\0';
				}
			}
			else
			{
				wszFormatName = (WCHAR*) Stream_Pointer(s);

				if (wszFormatName[0])
				{
					ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
						16, &(formats[index].formatName), 0, NULL, NULL);
				}
			}

			Stream_Seek(s, 32);
			dataLen -= 32;
			index++;
		}
	}
	else
	{
		while (dataLen)
		{
			Stream_Seek(s, 4); /* formatId (4 bytes) */
			dataLen -= 4;

			wszFormatName = (WCHAR*) Stream_Pointer(s);

			if (!wszFormatName[0])
				formatNameLength = 0;
			else
				formatNameLength = _wcslen(wszFormatName);

			Stream_Seek(s, (formatNameLength + 1) * 2);
			dataLen -= ((formatNameLength + 1) * 2);

			formatList.numFormats++;
		}

		dataLen = formatList.dataLen;
		Stream_SetPosition(s, position);

		if (formatList.numFormats)
			formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, sizeof(CLIPRDR_FORMAT));

		if (!formats)
		{
			WLog_ERR(TAG, "calloc failed!");
			return CHANNEL_RC_NO_MEMORY;
		}

		formatList.formats = formats;

		while (dataLen)
		{
			Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */
			dataLen -= 4;

			formats[index].formatName = NULL;

			wszFormatName = (WCHAR*) Stream_Pointer(s);

			if (!wszFormatName[0])
				formatNameLength = 0;
			else
				formatNameLength = _wcslen(wszFormatName);

			if (formatNameLength)
			{
				ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
					-1, &(formats[index].formatName), 0, NULL, NULL);
			}

			Stream_Seek(s, (formatNameLength + 1) * 2);
			dataLen -= ((formatNameLength + 1) * 2);

			index++;
		}
	}

	WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatList: numFormats: %d",
			formatList.numFormats);

	if (context->ServerFormatList)
	{
		if ((error = context->ServerFormatList(context, &formatList)))
			WLog_ERR(TAG, "ServerFormatList failed with error %d", error);
	}

error_out:
	if (formats)
	{
		for (index = 0; index < formatList.numFormats; index++)
		{
			free(formats[index].formatName);
		}

		free(formats);
	}
	return error;
}
Exemple #23
0
BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s)
{
	int length;

	if (!nla->identity)
	{
		WLog_ERR(TAG, "nla->identity is NULL!");
		return FALSE;
	}

	/* TSPasswordCreds (SEQUENCE)
	 * Initialise to default values. */
	nla->identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

	nla->identity->UserLength = (UINT32) 0;
	nla->identity->User = NULL;

	nla->identity->DomainLength = (UINT32) 0;
	nla->identity->Domain = NULL;

	nla->identity->Password = NULL;
	nla->identity->PasswordLength = (UINT32) 0;

	if (!ber_read_sequence_tag(s, &length))
		return FALSE;

	/* The sequence is empty, return early,
	 * TSPasswordCreds (SEQUENCE) is optional. */
	if (length == 0)
		return TRUE;

	/* [0] domainName (OCTET STRING) */
	if (!ber_read_contextual_tag(s, 0, &length, TRUE) ||
		!ber_read_octet_string_tag(s, &length))
	{
		return FALSE;
	}

	nla->identity->DomainLength = (UINT32) length;
	if (nla->identity->DomainLength > 0)
	{
		nla->identity->Domain = (UINT16*) malloc(length);
		if (!nla->identity->Domain)
			return FALSE;
		CopyMemory(nla->identity->Domain, Stream_Pointer(s), nla->identity->DomainLength);
		Stream_Seek(s, nla->identity->DomainLength);
		nla->identity->DomainLength /= 2;
	}

	/* [1] userName (OCTET STRING) */
	if (!ber_read_contextual_tag(s, 1, &length, TRUE) ||
		!ber_read_octet_string_tag(s, &length))
	{
		return FALSE;
	}

	nla->identity->UserLength = (UINT32) length;
	if (nla->identity->UserLength > 0)
	{
		nla->identity->User = (UINT16 *) malloc(length);
		if (!nla->identity->User)
			return FALSE;
		CopyMemory(nla->identity->User, Stream_Pointer(s), nla->identity->UserLength);
		Stream_Seek(s, nla->identity->UserLength);
		nla->identity->UserLength /= 2;
	}

	/* [2] password (OCTET STRING) */
	if (!ber_read_contextual_tag(s, 2, &length, TRUE) ||
		!ber_read_octet_string_tag(s, &length))
	{
		return FALSE;
	}

	nla->identity->PasswordLength = (UINT32) length;
	if (nla->identity->PasswordLength > 0)
	{
		nla->identity->Password = (UINT16 *) malloc(length);
		if (!nla->identity->Password)
			return FALSE;
		CopyMemory(nla->identity->Password, Stream_Pointer(s), nla->identity->PasswordLength);
		Stream_Seek(s, nla->identity->PasswordLength);
		nla->identity->PasswordLength /= 2;
	}

	return TRUE;
}
Exemple #24
0
int transport_write(rdpTransport* transport, wStream* s)
{
	int length;
	int status = -1;
	int writtenlength = 0;

	EnterCriticalSection(&(transport->WriteLock));

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

	if (length > 0)
	{
		WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
	}

	while (length > 0)
	{
		status = BIO_write(transport->frontBio, Stream_Pointer(s), length);

		if (status <= 0)
		{
			/* the buffered BIO that is at the end of the chain always says OK for writing,
			 * so a retry means that for any reason we need to read. The most probable
			 * is a SSL or TSG BIO in the chain.
			 */
			if (!BIO_should_retry(transport->frontBio))
			{
				WLog_ERR_BIO(TAG, "BIO_should_retry", transport->frontBio);
				goto out_cleanup;
			}

			/* non-blocking can live with blocked IOs */
			if (!transport->blocking)
			{
				WLog_ERR_BIO(TAG, "BIO_write", transport->frontBio);
				goto out_cleanup;
			}

			if (BIO_wait_write(transport->frontBio, 100) < 0)
			{
				WLog_ERR_BIO(TAG, "BIO_wait_write", transport->frontBio);
				status = -1;
				goto out_cleanup;
			}

			continue;
		}

		if (transport->blocking || transport->settings->WaitForOutputBufferFlush)
		{
			while (BIO_write_blocked(transport->frontBio))
			{
				if (BIO_wait_write(transport->frontBio, 100) < 0)
				{
					WLog_ERR(TAG, "error when selecting for write");
					status = -1;
					goto out_cleanup;
				}

				if (BIO_flush(transport->frontBio) < 1)
				{
					WLog_ERR(TAG, "error when flushing outputBuffer");
					status = -1;
					goto out_cleanup;
				}
			}
		}

		length -= status;
		Stream_Seek(s, status);
	}
	transport->written += writtenlength;

out_cleanup:

	if (status < 0)
	{
		/* A write error indicates that the peer has dropped the connection */
		transport->layer = TRANSPORT_LAYER_CLOSED;
	}

	if (s->pool)
		Stream_Release(s);

	LeaveCriticalSection(&(transport->WriteLock));
	return status;
}
Exemple #25
0
BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
{
	UINT16 type;
	UINT16 offset = 0;
	UINT16 blockLength;
	BYTE* holdp;

	while (offset < length)
	{
		holdp = Stream_Pointer(s);

		if (!gcc_read_user_data_header(s, &type, &blockLength))
		{
			WLog_ERR(TAG,  "gcc_read_server_data_blocks: gcc_read_user_data_header failed");
			return FALSE;
		}

		switch (type)
		{
			case SC_CORE:
				if (!gcc_read_server_core_data(s, mcs))
				{
					WLog_ERR(TAG,  "gcc_read_server_data_blocks: gcc_read_server_core_data failed");
					return FALSE;
				}
				break;

			case SC_SECURITY:
				if (!gcc_read_server_security_data(s, mcs))
				{
					WLog_ERR(TAG,  "gcc_read_server_data_blocks: gcc_read_server_security_data failed");
					return FALSE;
				}
				break;

			case SC_NET:
				if (!gcc_read_server_network_data(s, mcs))
				{
					WLog_ERR(TAG,  "gcc_read_server_data_blocks: gcc_read_server_network_data failed");
					return FALSE;
				}
				break;

			case SC_MCS_MSGCHANNEL:
				if (!gcc_read_server_message_channel_data(s, mcs))
				{
					WLog_ERR(TAG,  "gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed");
					return FALSE;
				}
				break;

			case SC_MULTITRANSPORT:
				if (!gcc_read_server_multitransport_channel_data(s, mcs))
				{
					WLog_ERR(TAG,  "gcc_read_server_data_blocks: gcc_read_server_multitransport_channel_data failed");
					return FALSE;
				}
				break;

			default:
				WLog_ERR(TAG,  "gcc_read_server_data_blocks: ignoring type=%hu", type);
				break;
		}
		offset += blockLength;
		Stream_Pointer(s) = holdp + blockLength;
	}

	return TRUE;
}
Exemple #26
0
void gcc_write_server_security_data(wStream* s, rdpMcs* mcs)
{
	CryptoMd5 md5;
	BYTE* sigData;
	int expLen, keyLen, sigDataLen;
	BYTE encryptedSignature[TSSK_KEY_LENGTH];
	BYTE signature[sizeof(initial_signature)];
	UINT32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen;
	rdpSettings* settings = mcs->settings;

	if (!settings->DisableEncryption)
	{
		settings->EncryptionMethods = ENCRYPTION_METHOD_NONE;
		settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
	}
	else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS) != 0)
	{
		settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS;
	}
	else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT) != 0)
	{
		settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
	}
	else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_40BIT) != 0)
	{
		settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT;
	}

	if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE)
		settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;

	headerLen = 12;
	keyLen = 0;
	wPublicKeyBlobLen = 0;
	serverRandomLen = 0;
	serverCertLen = 0;

	if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE ||
	    settings->EncryptionLevel != ENCRYPTION_LEVEL_NONE)
	{
		serverRandomLen = 32;

		keyLen = settings->RdpServerRsaKey->ModulusLength;
		expLen = sizeof(settings->RdpServerRsaKey->exponent);
		wPublicKeyBlobLen = 4; /* magic (RSA1) */
		wPublicKeyBlobLen += 4; /* keylen */
		wPublicKeyBlobLen += 4; /* bitlen */
		wPublicKeyBlobLen += 4; /* datalen */
		wPublicKeyBlobLen += expLen;
		wPublicKeyBlobLen += keyLen;
		wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */

		serverCertLen = 4; /* dwVersion */
		serverCertLen += 4; /* dwSigAlgId */
		serverCertLen += 4; /* dwKeyAlgId */
		serverCertLen += 2; /* wPublicKeyBlobType */
		serverCertLen += 2; /* wPublicKeyBlobLen */
		serverCertLen += wPublicKeyBlobLen;
		serverCertLen += 2; /* wSignatureBlobType */
		serverCertLen += 2; /* wSignatureBlobLen */
		serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */
		serverCertLen += 8; /* 8 bytes of zero padding */

		headerLen += sizeof(serverRandomLen);
		headerLen += sizeof(serverCertLen);
		headerLen += serverRandomLen;
		headerLen += serverCertLen;
	}

	gcc_write_user_data_header(s, SC_SECURITY, headerLen);

	Stream_Write_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */
	Stream_Write_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */

	if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE &&
	    settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE)
	{
		return;
	}

	Stream_Write_UINT32(s, serverRandomLen); /* serverRandomLen */
	Stream_Write_UINT32(s, serverCertLen); /* serverCertLen */

	settings->ServerRandomLength = serverRandomLen;
	settings->ServerRandom = (BYTE*) malloc(serverRandomLen);
	crypto_nonce(settings->ServerRandom, serverRandomLen);
	Stream_Write(s, settings->ServerRandom, serverRandomLen);

	sigData = Stream_Pointer(s);

	Stream_Write_UINT32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */
	Stream_Write_UINT32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */
	Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */
	Stream_Write_UINT16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */

	Stream_Write_UINT16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */
	Stream_Write(s, "RSA1", 4); /* magic */
	Stream_Write_UINT32(s, keyLen + 8); /* keylen */
	Stream_Write_UINT32(s, keyLen * 8); /* bitlen */
	Stream_Write_UINT32(s, keyLen - 1); /* datalen */

	Stream_Write(s, settings->RdpServerRsaKey->exponent, expLen);
	Stream_Write(s, settings->RdpServerRsaKey->Modulus, keyLen);
	Stream_Zero(s, 8);

	sigDataLen = Stream_Pointer(s) - sigData;

	Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */
	Stream_Write_UINT16(s, keyLen + 8); /* wSignatureBlobLen */

	memcpy(signature, initial_signature, sizeof(initial_signature));

	md5 = crypto_md5_init();
	crypto_md5_update(md5, sigData, sigDataLen);
	crypto_md5_final(md5, signature);

	crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH,
		tssk_modulus, tssk_privateExponent, encryptedSignature);

	Stream_Write(s, encryptedSignature, sizeof(encryptedSignature));
	Stream_Zero(s, 8);
}
Exemple #27
0
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, wStream* input)
{
	char* s = NULL;
        mode_t m;
	UINT64 size;
	int status;
	char* fullpath;
	struct STAT st;
	struct timeval tv[2];
	UINT64 LastWriteTime;
	UINT32 FileAttributes;
	UINT32 FileNameLength;

	m = 0;

	switch (FsInformationClass)
	{
		case FileBasicInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
			Stream_Seek_UINT64(input); /* CreationTime */
			Stream_Seek_UINT64(input); /* LastAccessTime */
			Stream_Read_UINT64(input, LastWriteTime);
			Stream_Seek_UINT64(input); /* ChangeTime */
			Stream_Read_UINT32(input, FileAttributes);

			if (FSTAT(file->fd, &st) != 0)
				return FALSE;

			tv[0].tv_sec = st.st_atime;
			tv[0].tv_usec = 0;
			tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime);
			tv[1].tv_usec = 0;
#ifndef WIN32
/* TODO on win32 */                        
#ifdef ANDROID
			utimes(file->fullpath, tv);
#else
			futimes(file->fd, tv);
#endif

			if (FileAttributes > 0)
			{
				m = st.st_mode;
				if ((FileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
					m |= S_IWUSR;
				else
					m &= ~S_IWUSR;
				if (m != st.st_mode)
					fchmod(file->fd, m);
			}
#endif
                        break;

		case FileEndOfFileInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232067.aspx */
		case FileAllocationInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
			Stream_Read_UINT64(input, size);
			if (ftruncate(file->fd, size) != 0)
				return FALSE;
			break;

		case FileDispositionInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232098.aspx */
			/* http://msdn.microsoft.com/en-us/library/cc241371.aspx */
			if (Length)
				Stream_Read_UINT8(input, file->delete_pending);
			else
				file->delete_pending = 1;
			if (file->delete_pending && file->is_dir)
			{
				/* mstsc causes this to FAIL if the directory is not empty,
				 * and that's what the server is expecting.  If we wait for
				 * the close to flag a failure, cut and paste of a folder
				 * will lose the folder's contents.
				 */
				int status;
				status = rmdir(file->fullpath);
				if (status == 0)
				{
					/* Put it back so the normal pending delete will work. */
					mkdir(file->fullpath, 0755);
				}
				else
				{
					return FALSE;
				}
			}
			break;

		case FileRenameInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232085.aspx */
			Stream_Seek_UINT8(input); /* ReplaceIfExists */
			Stream_Seek_UINT8(input); /* RootDirectory */
			Stream_Read_UINT32(input, FileNameLength);

			status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(input),
					FileNameLength / 2, &s, 0, NULL, NULL);

			if (status < 1)
				s = (char*) calloc(1, 1);

			fullpath = drive_file_combine_fullpath(file->basepath, s);
			free(s);

			/* TODO rename does not work on win32 */
                        if (rename(file->fullpath, fullpath) == 0)
			{
				DEBUG_SVC("renamed %s to %s", file->fullpath, fullpath);
				drive_file_set_fullpath(file, fullpath);
			}
			else
			{
				DEBUG_WARN("rename %s to %s failed, errno = %d", file->fullpath, fullpath, errno);
				free(fullpath);
				return FALSE;
			}

			break;

		default:
			DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass);
			return FALSE;
	}

	return TRUE;
}
Exemple #28
0
BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
{
    int i;
    UINT32 cbFormat;
    BOOL ret = TRUE;

    memset(mediatype, 0, sizeof(TS_AM_MEDIA_TYPE));

    /* MajorType */
    DEBUG_DVC("MajorType:");
    tsmf_print_guid(Stream_Pointer(s));
    for (i = 0; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++)
    {
        if (memcmp(tsmf_major_type_map[i].guid, Stream_Pointer(s), 16) == 0)
            break;
    }
    mediatype->MajorType = tsmf_major_type_map[i].type;
    if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
        ret = FALSE;
    DEBUG_DVC("MajorType %s", tsmf_major_type_map[i].name);
    Stream_Seek(s, 16);

    /* SubType */
    DEBUG_DVC("SubType:");
    tsmf_print_guid(Stream_Pointer(s));
    for (i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++)
    {
        if (memcmp(tsmf_sub_type_map[i].guid, Stream_Pointer(s), 16) == 0)
            break;
    }
    mediatype->SubType = tsmf_sub_type_map[i].type;
    if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
        ret = FALSE;
    DEBUG_DVC("SubType %s", tsmf_sub_type_map[i].name);
    Stream_Seek(s, 16);

    /* bFixedSizeSamples, bTemporalCompression, SampleSize */
    Stream_Seek(s, 12);

    /* FormatType */
    DEBUG_DVC("FormatType:");
    tsmf_print_guid(Stream_Pointer(s));
    for (i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++)
    {
        if (memcmp(tsmf_format_type_map[i].guid, Stream_Pointer(s), 16) == 0)
            break;
    }
    mediatype->FormatType = tsmf_format_type_map[i].type;
    if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
        ret = FALSE;
    DEBUG_DVC("FormatType %s", tsmf_format_type_map[i].name);
    Stream_Seek(s, 16);

    /* cbFormat */
    Stream_Read_UINT32(s, cbFormat);
    DEBUG_DVC("cbFormat %d", cbFormat);

#ifdef WITH_DEBUG_DVC
    winpr_HexDump(Stream_Pointer(s), cbFormat);
#endif

    switch (mediatype->FormatType)
    {
    case TSMF_FORMAT_TYPE_MFVIDEOFORMAT:
        /* http://msdn.microsoft.com/en-us/library/aa473808.aspx */

        Stream_Seek(s, 8); /* dwSize and ? */
        Stream_Read_UINT32(s, mediatype->Width); /* videoInfo.dwWidth */
        Stream_Read_UINT32(s, mediatype->Height); /* videoInfo.dwHeight */
        Stream_Seek(s, 32);
        /* videoInfo.FramesPerSecond */
        Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator);
        Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Denominator);
        Stream_Seek(s, 80);
        Stream_Read_UINT32(s, mediatype->BitRate); /* compressedInfo.AvgBitrate */
        Stream_Seek(s, 36);

        if (cbFormat > 176)
        {
            mediatype->ExtraDataSize = cbFormat - 176;
            mediatype->ExtraData = Stream_Pointer(s);
        }
        break;

    case TSMF_FORMAT_TYPE_WAVEFORMATEX:
        /* http://msdn.microsoft.com/en-us/library/dd757720.aspx */

        Stream_Seek_UINT16(s);
        Stream_Read_UINT16(s, mediatype->Channels);
        Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator);
        mediatype->SamplesPerSecond.Denominator = 1;
        Stream_Read_UINT32(s, mediatype->BitRate);
        mediatype->BitRate *= 8;
        Stream_Read_UINT16(s, mediatype->BlockAlign);
        Stream_Read_UINT16(s, mediatype->BitsPerSample);
        Stream_Read_UINT16(s, mediatype->ExtraDataSize);
        if (mediatype->ExtraDataSize > 0)
            mediatype->ExtraData = Stream_Pointer(s);

        break;

    case TSMF_FORMAT_TYPE_MPEG1VIDEOINFO:
        /* http://msdn.microsoft.com/en-us/library/dd390700.aspx */

        i = tsmf_codec_parse_VIDEOINFOHEADER(mediatype, s);
        i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
        if (cbFormat > i)
        {
            mediatype->ExtraDataSize = cbFormat - i;
            mediatype->ExtraData = Stream_Pointer(s);
        }
        break;

    case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO:
        /* http://msdn.microsoft.com/en-us/library/dd390707.aspx */

        i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
        i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
        if (cbFormat > i)
        {
            mediatype->ExtraDataSize = cbFormat - i;
            mediatype->ExtraData = Stream_Pointer(s);
        }
        break;

    case TSMF_FORMAT_TYPE_VIDEOINFO2:
        i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
        i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, FALSE);
        if (cbFormat > i)
        {
            mediatype->ExtraDataSize = cbFormat - i;
            mediatype->ExtraData = Stream_Pointer(s);
        }
        break;

    default:
        break;
    }

    if (mediatype->SamplesPerSecond.Numerator == 0)
        mediatype->SamplesPerSecond.Numerator = 1;
    if (mediatype->SamplesPerSecond.Denominator == 0)
        mediatype->SamplesPerSecond.Denominator = 1;

    return ret;
}
Exemple #29
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT audin_server_recv_data(audin_server* audin, wStream* s,
                                   UINT32 length)
{
	AUDIO_FORMAT* format;
	int sbytes_per_sample;
	int sbytes_per_frame;
	BYTE* src;
	int size;
	int frames;
	UINT success = CHANNEL_RC_OK;

	if (audin->context.selected_client_format < 0)
	{
		WLog_ERR(TAG, "audin->context.selected_client_format = %d",
		         audin->context.selected_client_format);
		return ERROR_INVALID_DATA;
	}

	format = &audin->context.client_formats[audin->context.selected_client_format];

	if (format->wFormatTag == WAVE_FORMAT_ADPCM)
	{
		audin->dsp_context->decode_ms_adpcm(audin->dsp_context,
		                                    Stream_Pointer(s), length, format->nChannels, format->nBlockAlign);
		size = audin->dsp_context->adpcm_size;
		src = audin->dsp_context->adpcm_buffer;
		sbytes_per_sample = 2;
		sbytes_per_frame = format->nChannels * 2;
	}
	else if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
	{
		audin->dsp_context->decode_ima_adpcm(audin->dsp_context,
		                                     Stream_Pointer(s), length, format->nChannels, format->nBlockAlign);
		size = audin->dsp_context->adpcm_size;
		src = audin->dsp_context->adpcm_buffer;
		sbytes_per_sample = 2;
		sbytes_per_frame = format->nChannels * 2;
	}
	else
	{
		size = length;
		src = Stream_Pointer(s);
		sbytes_per_sample = format->wBitsPerSample / 8;
		sbytes_per_frame = format->nChannels * sbytes_per_sample;
	}

	if (format->nSamplesPerSec == audin->context.dst_format.nSamplesPerSec
	    && format->nChannels == audin->context.dst_format.nChannels)
	{
		frames = size / sbytes_per_frame;
	}
	else
	{
		audin->dsp_context->resample(audin->dsp_context, src, sbytes_per_sample,
		                             format->nChannels, format->nSamplesPerSec, size / sbytes_per_frame,
		                             audin->context.dst_format.nChannels, audin->context.dst_format.nSamplesPerSec);
		frames = audin->dsp_context->resampled_frames;
		src = audin->dsp_context->resampled_buffer;
	}

	IFCALLRET(audin->context.ReceiveSamples, success, &audin->context, src, frames);

	if (success)
		WLog_ERR(TAG, "context.ReceiveSamples failed with error %lu", success);

	return success;
}
Exemple #30
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT cliprdr_server_format_list(CliprdrServerContext* context, CLIPRDR_FORMAT_LIST* formatList)
{
	wStream* s;
	UINT32 index;
	int length = 0;
	int cchWideChar;
	LPWSTR lpWideCharStr;
	int formatNameSize;
	int formatNameLength;
	char* szFormatName;
	WCHAR* wszFormatName;
	BOOL asciiNames = FALSE;
	CLIPRDR_FORMAT* format;
	CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle;

	if (!cliprdr->useLongFormatNames)
	{
		length = formatList->numFormats * 36;

		s = cliprdr_server_packet_new(CB_FORMAT_LIST, 0, length);
		if (!s)
		{
			WLog_ERR(TAG, "cliprdr_server_packet_new failed!");
			return ERROR_INTERNAL_ERROR;
		}

		for (index = 0; index < formatList->numFormats; index++)
		{
			format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);

			Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */

			formatNameSize = 0;
			formatNameLength = 0;

			szFormatName = format->formatName;

			if (asciiNames)
			{
				if (szFormatName)
					formatNameLength = strlen(szFormatName);

				if (formatNameLength > 31)
					formatNameLength = 31;

				Stream_Write(s, szFormatName, formatNameLength);
				Stream_Zero(s, 32 - formatNameLength);
			}
			else
			{
				wszFormatName = NULL;

				if (szFormatName)
					formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName, 0);

				if (formatNameSize > 15)
					formatNameSize = 15;

				if (wszFormatName)
					Stream_Write(s, wszFormatName, formatNameSize * 2);

				Stream_Zero(s, 32 - (formatNameSize * 2));

				free(wszFormatName);
			}
		}
	}
	else
	{
		for (index = 0; index < formatList->numFormats; index++)
		{
			format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
			length += 4;
			formatNameSize = 2;

			if (format->formatName)
				formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, 0) * 2;

			length += formatNameSize;
		}

		s = cliprdr_server_packet_new(CB_FORMAT_LIST, 0, length);

		if (!s)
		{
			WLog_ERR(TAG, "cliprdr_server_packet_new failed!");
			return ERROR_INTERNAL_ERROR;
		}

		for (index = 0; index < formatList->numFormats; index++)
		{
			format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
			Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */

			if (format->formatName)
			{
				lpWideCharStr = (LPWSTR) Stream_Pointer(s);
				cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2;
				formatNameSize = MultiByteToWideChar(CP_UTF8, 0,
					format->formatName, -1, lpWideCharStr, cchWideChar) * 2;
				Stream_Seek(s, formatNameSize);
			}
			else
			{
				Stream_Write_UINT16(s, 0);
			}
		}
	}

	WLog_DBG(TAG, "ServerFormatList: numFormats: %d",
			formatList->numFormats);

	return cliprdr_server_packet_send(cliprdr, s);
}