Exemplo n.º 1
0
Arquivo: rfx.c Projeto: C4rt/FreeRDP
RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length)
{
	int pos;
	UINT32 blockLen;
	UINT32 blockType;
	RFX_MESSAGE* message = NULL;
	wStream* s = NULL;
	BOOL ok = TRUE;
	UINT16 expectedDataBlockType = WBT_FRAME_BEGIN;

	if (!context || !data || !length)
		goto fail;

	if (!(s = Stream_New(data, length)))
		goto fail;

	if (!(message = (RFX_MESSAGE*) calloc(1, sizeof(RFX_MESSAGE))))
		goto fail;

	message->freeRects = TRUE;

	while (ok && Stream_GetRemainingLength(s) > 6)
	{
		/* RFX_BLOCKT */
		Stream_Read_UINT16(s, blockType); /* blockType (2 bytes) */
		Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */

		WLog_Print(context->priv->log, WLOG_DEBUG, "blockType 0x%X blockLen %d", blockType, blockLen);

		if (blockLen == 0)
		{
			WLog_ERR(TAG, "zero blockLen");
			goto fail;
		}

		if (Stream_GetRemainingLength(s) < blockLen - 6)
		{
			WLog_ERR(TAG, "%s: packet too small for blocklen=%d", __FUNCTION__, blockLen);
			goto fail;
		}

		pos = Stream_GetPosition(s) - 6 + blockLen;

		if (blockType > WBT_CONTEXT && context->decodedHeaderBlocks != _RFX_DECODED_HEADERS)
		{
			WLog_ERR(TAG, "%s: incomplete header blocks processing", __FUNCTION__);
			goto fail;
		}

		if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION)
		{
			/* RFX_CODEC_CHANNELT */
			UINT8 codecId;
			UINT8 channelId;

			if (Stream_GetRemainingLength(s) < 2)
				goto fail;

			Stream_Read_UINT8(s, codecId); /* codecId (1 byte) must be set to 0x01 */
			Stream_Read_UINT8(s, channelId); /* channelId (1 byte) 0xFF or 0x00, see below */

			if (codecId != 0x01)
			{
				WLog_ERR(TAG, "%s: invalid codecId 0x%02X", __FUNCTION__, codecId);
				goto fail;
			}

			if (blockType == WBT_CONTEXT)
			{
				/* If the blockType is set to WBT_CONTEXT, then channelId MUST be set to 0xFF.*/
				if (channelId != 0xFF)
				{
					WLog_ERR(TAG, "%s: invalid channelId 0x%02X for blockType 0x%04X", __FUNCTION__, channelId, blockType);
					goto fail;
				}
			}
			else
			{
				/* For all other values of blockType, channelId MUST be set to 0x00. */
				if (channelId != 0x00)
				{
					WLog_ERR(TAG, "%s: invalid channelId 0x%02X for blockType WBT_CONTEXT", __FUNCTION__, channelId);
					goto fail;
				}
			}
		}


		switch (blockType)
		{
			/* Header messages:
			 * The stream MUST start with the header messages and any of these headers can appear
			 * in the stream at a later stage. The header messages can be repeated.
			 */

			case WBT_SYNC:
				ok = rfx_process_message_sync(context, s);
				break;

			case WBT_CONTEXT:
				ok = rfx_process_message_context(context, s);
				break;

			case WBT_CODEC_VERSIONS:
				ok = rfx_process_message_codec_versions(context, s);
				break;

			case WBT_CHANNELS:
				ok = rfx_process_message_channels(context, s);
				break;

			/* Data messages:
			 * The data associated with each encoded frame or image is always bracketed by the
			 * TS_RFX_FRAME_BEGIN (section 2.2.2.3.1) and TS_RFX_FRAME_END (section 2.2.2.3.2) messages.
			 * There MUST only be one TS_RFX_REGION (section 2.2.2.3.3) message per frame and one TS_RFX_TILESET
			 * (section 2.2.2.3.4) message per TS_RFX_REGION.
			 */

			case WBT_FRAME_BEGIN:
				ok = rfx_process_message_frame_begin(context, message, s, &expectedDataBlockType);
				break;

			case WBT_REGION:
				ok = rfx_process_message_region(context, message, s, &expectedDataBlockType);
				break;

			case WBT_EXTENSION:
				ok = rfx_process_message_tileset(context, message, s, &expectedDataBlockType);
				break;

			case WBT_FRAME_END:
				ok = rfx_process_message_frame_end(context, message, s, &expectedDataBlockType);
				break;

			default:
				WLog_ERR(TAG, "%s: unknown blockType 0x%X", __FUNCTION__, blockType);
				goto fail;
		}

		Stream_SetPosition(s, pos);
	}

	if (ok)
	{
		Stream_Free(s, FALSE);
		return message;
	}

fail:
	Stream_Free(s, FALSE);
	rfx_message_free(context, message);

	return NULL;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
int remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
{
	int status = 1;
	UINT32 msgType = 0;
	UINT32 result = 0;

	if (Stream_GetRemainingLength(s) < 4)
		return -1;

	Stream_Read_UINT32(s, msgType); /* msgType (4 bytes) */

	//printf("msgType: %d\n", msgType);

	switch (msgType)
	{
		case REMDESK_CTL_REMOTE_CONTROL_DESKTOP:
			break;

		case REMDESK_CTL_RESULT:
			status = remdesk_recv_result_pdu(remdesk, s, header, &result);
			break;

		case REMDESK_CTL_AUTHENTICATE:
			break;

		case REMDESK_CTL_SERVER_ANNOUNCE:
			status = remdesk_recv_ctl_server_announce_pdu(remdesk, s, header);
			break;

		case REMDESK_CTL_DISCONNECT:
			break;

		case REMDESK_CTL_VERSIONINFO:
			status = remdesk_recv_ctl_version_info_pdu(remdesk, s, header);

			if (remdesk->Version == 1)
			{
				if (status >= 0)
					status = remdesk_send_ctl_version_info_pdu(remdesk);

				if (status >= 0)
					status = remdesk_send_ctl_authenticate_pdu(remdesk);

				if (status >= 0)
					status = remdesk_send_ctl_remote_control_desktop_pdu(remdesk);
			}
			else if (remdesk->Version == 2)
			{
				if (status >= 0)
					status = remdesk_send_ctl_expert_on_vista_pdu(remdesk);

				if (status >= 0)
					status = remdesk_send_ctl_verify_password_pdu(remdesk);
			}

			break;

		case REMDESK_CTL_ISCONNECTED:
			break;

		case REMDESK_CTL_VERIFY_PASSWORD:
			break;

		case REMDESK_CTL_EXPERT_ON_VISTA:
			break;

		case REMDESK_CTL_RANOVICE_NAME:
			break;

		case REMDESK_CTL_RAEXPERT_NAME:
			break;

		case REMDESK_CTL_TOKEN:
			break;

		default:
			fprintf(stderr, "remdesk_recv_control_pdu: unknown msgType: %d\n", msgType);
			status = -1;
			break;
	}

	return status;
}
Exemplo n.º 4
0
static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
{
	int i, num_known_format = 0;
	UINT32 flags, vol, pitch;
	UINT16 udpPort, version;
	BYTE lastblock;

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

	Stream_Read_UINT32(s, flags); /* dwFlags */
	Stream_Read_UINT32(s, vol); /* dwVolume */
	Stream_Read_UINT32(s, pitch); /* dwPitch */
	Stream_Read_UINT16(s, udpPort); /* wDGramPort */
	Stream_Read_UINT16(s, context->num_client_formats); /* wNumberOfFormats */
	Stream_Read_UINT8(s, lastblock); /* cLastBlockConfirmed */
	Stream_Read_UINT16(s, version); /* wVersion */
	Stream_Seek_UINT8(s); /* bPad */

	/* this check is only a guess as cbSize can influence the size of a format record */
	if (Stream_GetRemainingLength(s) < context->num_client_formats * 18)
		return FALSE;

	if (!context->num_client_formats)
	{
		fprintf(stderr, "%s: client doesn't support any format!\n", __FUNCTION__);
		return FALSE;
	}

	context->client_formats = (AUDIO_FORMAT *)calloc(context->num_client_formats, sizeof(AUDIO_FORMAT));
	if (!context->client_formats)
		return FALSE;

	for (i = 0; i < context->num_client_formats; i++)
	{
		if (Stream_GetRemainingLength(s) < 18)
			goto out_free;

		Stream_Read_UINT16(s, context->client_formats[i].wFormatTag);
		Stream_Read_UINT16(s, context->client_formats[i].nChannels);
		Stream_Read_UINT32(s, context->client_formats[i].nSamplesPerSec);
		Stream_Read_UINT32(s, context->client_formats[i].nAvgBytesPerSec);
		Stream_Read_UINT16(s, context->client_formats[i].nBlockAlign);
		Stream_Read_UINT16(s, context->client_formats[i].wBitsPerSample);
		Stream_Read_UINT16(s, context->client_formats[i].cbSize);

		if (context->client_formats[i].cbSize > 0)
		{
			if (!Stream_SafeSeek(s, context->client_formats[i].cbSize))
				goto out_free;
		}

		if (context->client_formats[i].wFormatTag != 0)
		{
			//lets call this a known format
			//TODO: actually look through our own list of known formats
			num_known_format++;
		}
	}

	if (!context->num_client_formats)
	{
		fprintf(stderr, "%s: client doesn't support any known format!\n", __FUNCTION__);
		goto out_free;
	}

	return TRUE;

out_free:
	free(context->client_formats);
	return FALSE;
}
Exemplo n.º 5
0
BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, 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;
	UINT32 desktopPhysicalWidth = 0;
	UINT32 desktopPhysicalHeight = 0;
	UINT16 desktopOrientation = 0;
	UINT32 desktopScaleFactor = 0;
	UINT32 deviceScaleFactor = 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) */

	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, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
		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, settings->PerformanceFlags); /* 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 (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;
}
Exemplo n.º 6
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT audin_server_recv_formats(audin_server* audin, wStream* s,
                                      UINT32 length)
{
	int i;
	UINT success = CHANNEL_RC_OK;

	if (length < 8)
	{
		WLog_ERR(TAG, "error parsing rec formats: expected at least 8 bytes, got %"PRIu32"",
		         length);
		return ERROR_INVALID_DATA;
	}

	Stream_Read_UINT32(s,
	                   audin->context.num_client_formats); /* NumFormats (4 bytes) */
	Stream_Seek_UINT32(s); /* cbSizeFormatsPacket (4 bytes) */
	length -= 8;

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

	audin->context.client_formats = calloc(audin->context.num_client_formats,
	                                       sizeof(AUDIO_FORMAT));

	if (!audin->context.client_formats)
		return ERROR_NOT_ENOUGH_MEMORY;

	for (i = 0; i < audin->context.num_client_formats; i++)
	{
		if (length < 18)
		{
			free(audin->context.client_formats);
			audin->context.client_formats = NULL;
			WLog_ERR(TAG, "expected length at least 18, but got %"PRIu32"", length);
			return ERROR_INVALID_DATA;
		}

		Stream_Read_UINT16(s, audin->context.client_formats[i].wFormatTag);
		Stream_Read_UINT16(s, audin->context.client_formats[i].nChannels);
		Stream_Read_UINT32(s, audin->context.client_formats[i].nSamplesPerSec);
		Stream_Seek_UINT32(s); /* nAvgBytesPerSec */
		Stream_Read_UINT16(s, audin->context.client_formats[i].nBlockAlign);
		Stream_Read_UINT16(s, audin->context.client_formats[i].wBitsPerSample);
		Stream_Read_UINT16(s, audin->context.client_formats[i].cbSize);

		if (audin->context.client_formats[i].cbSize > 0)
		{
			Stream_Seek(s, audin->context.client_formats[i].cbSize);
		}
	}

	IFCALLRET(audin->context.Opening, success, &audin->context);

	if (success)
		WLog_ERR(TAG, "context.Opening failed with error %"PRIu32"", success);

	return success;
}
Exemplo n.º 7
0
BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
{
    BYTE* client_random = NULL;
    BYTE* crypt_client_random = NULL;
    UINT32 rand_len, key_len;
    UINT16 channel_id, length, sec_flags;
    BYTE* mod;
    BYTE* priv_exp;
    BOOL ret = FALSE;

    if (!rdp->settings->UseRdpSecurityLayer)
    {
        /* No RDP Security. */
        return TRUE;
    }

    if (!rdp_read_header(rdp, s, &length, &channel_id))
    {
        WLog_ERR(TAG, "invalid RDP header");
        return FALSE;
    }

    if (!rdp_read_security_header(s, &sec_flags))
    {
        WLog_ERR(TAG, "invalid security header");
        return FALSE;
    }

    if ((sec_flags & SEC_EXCHANGE_PKT) == 0)
    {
        WLog_ERR(TAG, "missing SEC_EXCHANGE_PKT in security header");
        return FALSE;
    }

    rdp->do_crypt_license = (sec_flags & SEC_LICENSE_ENCRYPT_SC) != 0 ? TRUE : FALSE;

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

    Stream_Read_UINT32(s, rand_len);

    /* rand_len already includes 8 bytes of padding */
    if (Stream_GetRemainingLength(s) < rand_len)
        return FALSE;

    key_len = rdp->settings->RdpServerRsaKey->ModulusLength;
    client_random = malloc(key_len);
    if (!client_random)
        return FALSE;

    if (rand_len != key_len + 8)
    {
        WLog_ERR(TAG, "invalid encrypted client random length");
        goto end2;
    }

    crypt_client_random = calloc(1, rand_len);
    if (!crypt_client_random)
        goto end2;
    Stream_Read(s, crypt_client_random, rand_len);

    mod = rdp->settings->RdpServerRsaKey->Modulus;
    priv_exp = rdp->settings->RdpServerRsaKey->PrivateExponent;
    crypto_rsa_private_decrypt(crypt_client_random, rand_len - 8, key_len, mod, priv_exp, client_random);

    /* now calculate encrypt / decrypt and update keys */
    if (!security_establish_keys(client_random, rdp))
    {
        goto end;
    }

    rdp->do_crypt = TRUE;

    if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
    {
        rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec);
        if (!rdp->fips_encrypt)
        {
            WLog_ERR(TAG, "unable to allocate des3 encrypt key");
            goto end;
        }

        rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec);
        if (!rdp->fips_decrypt)
        {
            WLog_ERR(TAG, "unable to allocate des3 decrypt key");
            goto end;
        }

        rdp->fips_hmac = crypto_hmac_new();
        if (!rdp->fips_hmac)
        {
            WLog_ERR(TAG, "unable to allocate fips hmac");
            goto end;
        }
        ret = TRUE;
        goto end;
    }

    rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len);
    if (!rdp->rc4_decrypt_key)
    {
        WLog_ERR(TAG, "unable to allocate rc4 decrypt key");
        goto end;
    }

    rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len);
    if (!rdp->rc4_encrypt_key)
    {
        WLog_ERR(TAG, "unable to allocate rc4 encrypt key");
        goto end;
    }
    ret = TRUE;
end:
    if (crypt_client_random)
        free(crypt_client_random);
end2:
    if (client_random)
        free(client_random);

    return ret;
}
Exemplo n.º 8
0
static void 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);

	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;
		ListDictionary_Add(drive->files, key, file);

		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);

	irp->Complete(irp);
}
Exemplo n.º 9
0
static void drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp)
{
	UINT32 FsInformationClass;
	wStream* output = irp->output;
	struct STATVFS svfst;
	struct STAT st;
	char* volumeLabel = {"FREERDP"};
	char* diskType = {"FAT32"};
	WCHAR* outStr = NULL;
	int length;

	Stream_Read_UINT32(irp->input, FsInformationClass);

	STATVFS(drive->path, &svfst);
	STAT(drive->path, &st);

	switch (FsInformationClass)
	{
		case FileFsVolumeInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232108.aspx */
			length = ConvertToUnicode(sys_code_page, 0, volumeLabel, -1, &outStr, 0) * 2;
			Stream_Write_UINT32(output, 17 + length); /* Length */
			Stream_EnsureRemainingCapacity(output, 17 + length);
			Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* VolumeCreationTime */
#ifdef ANDROID
			Stream_Write_UINT32(output, svfst.f_fsid.__val[0]); /* VolumeSerialNumber */
#else
			Stream_Write_UINT32(output, svfst.f_fsid); /* VolumeSerialNumber */
#endif
			Stream_Write_UINT32(output, length); /* VolumeLabelLength */
			Stream_Write_UINT8(output, 0); /* SupportsObjects */
			/* Reserved(1), MUST NOT be added! */
			Stream_Write(output, outStr, length); /* VolumeLabel (Unicode) */
			free(outStr);
			break;

		case FileFsSizeInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232107.aspx */
			Stream_Write_UINT32(output, 24); /* Length */
			Stream_EnsureRemainingCapacity(output, 24);
			Stream_Write_UINT64(output, svfst.f_blocks); /* TotalAllocationUnits */
			Stream_Write_UINT64(output, svfst.f_bavail); /* AvailableAllocationUnits */
			Stream_Write_UINT32(output, 1); /* SectorsPerAllocationUnit */
			Stream_Write_UINT32(output, svfst.f_bsize); /* BytesPerSector */
			break;

		case FileFsAttributeInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232101.aspx */
			length = ConvertToUnicode(sys_code_page, 0, diskType, -1, &outStr, 0) * 2;
			Stream_Write_UINT32(output, 12 + length); /* Length */
			Stream_EnsureRemainingCapacity(output, 12 + length);
			Stream_Write_UINT32(output,
				FILE_CASE_SENSITIVE_SEARCH |
				FILE_CASE_PRESERVED_NAMES |
				FILE_UNICODE_ON_DISK); /* FileSystemAttributes */
#ifdef ANDROID
			Stream_Write_UINT32(output, 255); /* MaximumComponentNameLength */
#else
			Stream_Write_UINT32(output, svfst.f_namemax/*510*/); /* MaximumComponentNameLength */
#endif
			Stream_Write_UINT32(output, length); /* FileSystemNameLength */
			Stream_Write(output, outStr, length); /* FileSystemName (Unicode) */
			free(outStr);
			break;

		case FileFsFullSizeInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232104.aspx */
			Stream_Write_UINT32(output, 32); /* Length */
			Stream_EnsureRemainingCapacity(output, 32);
			Stream_Write_UINT64(output, svfst.f_blocks); /* TotalAllocationUnits */
			Stream_Write_UINT64(output, svfst.f_bavail); /* CallerAvailableAllocationUnits */
			Stream_Write_UINT64(output, svfst.f_bfree); /* AvailableAllocationUnits */
			Stream_Write_UINT32(output, 1); /* SectorsPerAllocationUnit */
			Stream_Write_UINT32(output, svfst.f_bsize); /* BytesPerSector */
			break;

		case FileFsDeviceInformation:
			/* http://msdn.microsoft.com/en-us/library/cc232109.aspx */
			Stream_Write_UINT32(output, 8); /* Length */
			Stream_EnsureRemainingCapacity(output, 8);
			Stream_Write_UINT32(output, FILE_DEVICE_DISK); /* DeviceType */
			Stream_Write_UINT32(output, 0); /* Characteristics */
			break;

		default:
			irp->IoStatus = STATUS_UNSUCCESSFUL;
			Stream_Write_UINT32(output, 0); /* Length */
			break;
	}

	irp->Complete(irp);
}
Exemplo n.º 10
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
{
	UINT error = CHANNEL_RC_OK;
	UINT32 msgType = 0;
	UINT32 result = 0;

	if (Stream_GetRemainingLength(s) < 4)
	{
		WLog_ERR(TAG, "Not enought data!");
		return ERROR_INVALID_DATA;
	}

	Stream_Read_UINT32(s, msgType); /* msgType (4 bytes) */

	//WLog_DBG(TAG, "msgType: %d", msgType);

	switch (msgType)
	{
		case REMDESK_CTL_REMOTE_CONTROL_DESKTOP:
			break;

		case REMDESK_CTL_RESULT:
			if ((error = remdesk_recv_ctl_result_pdu(remdesk, s, header, &result)))
				WLog_ERR(TAG, "remdesk_recv_ctl_result_pdu failed with error %lu", error);
			break;

		case REMDESK_CTL_AUTHENTICATE:
			break;

		case REMDESK_CTL_SERVER_ANNOUNCE:
			if ((error = remdesk_recv_ctl_server_announce_pdu(remdesk, s, header)))
				WLog_ERR(TAG, "remdesk_recv_ctl_server_announce_pdu failed with error %lu", error);
			break;

		case REMDESK_CTL_DISCONNECT:
			break;

		case REMDESK_CTL_VERSIONINFO:
			if ((error = remdesk_recv_ctl_version_info_pdu(remdesk, s, header)))
			{
				WLog_ERR(TAG, "remdesk_recv_ctl_version_info_pdu failed with error %lu", error);
				break;
			}

			if (remdesk->Version == 1)
			{
				if ((error = remdesk_send_ctl_version_info_pdu(remdesk)))
				{
					WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu", error);
					break;
				}

				if ((error = remdesk_send_ctl_authenticate_pdu(remdesk)))
				{
					WLog_ERR(TAG, "remdesk_send_ctl_authenticate_pdu failed with error %lu", error);
					break;
				}

				if ((error = remdesk_send_ctl_remote_control_desktop_pdu(remdesk)))
				{
					WLog_ERR(TAG, "remdesk_send_ctl_remote_control_desktop_pdu failed with error %lu", error);
					break;
				}
			}
			else if (remdesk->Version == 2)
			{
				if ((error = remdesk_send_ctl_expert_on_vista_pdu(remdesk)))
				{
					WLog_ERR(TAG, "remdesk_send_ctl_expert_on_vista_pdu failed with error %lu", error);
					break;
				}

				if ((error = remdesk_send_ctl_verify_password_pdu(remdesk)))
				{
					WLog_ERR(TAG, "remdesk_send_ctl_verify_password_pdu failed with error %lu", error);
					break;
				}
			}

			break;

		case REMDESK_CTL_ISCONNECTED:
			break;

		case REMDESK_CTL_VERIFY_PASSWORD:
			break;

		case REMDESK_CTL_EXPERT_ON_VISTA:
			break;

		case REMDESK_CTL_RANOVICE_NAME:
			break;

		case REMDESK_CTL_RAEXPERT_NAME:
			break;

		case REMDESK_CTL_TOKEN:
			break;

		default:
			WLog_ERR(TAG,  "unknown msgType: %d", msgType);
			error = ERROR_INVALID_DATA;
			break;
	}

	return error;
}
Exemplo n.º 11
0
UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, wStream* output, UINT32* abort_io)
{
	int purge_mask;
	UINT32 result;
	UINT32 modemstate;
	BYTE immediate;
	UINT32 ret = STATUS_SUCCESS;
	UINT32 length = 0;
	UINT32 pos;

	DEBUG_SVC("in");

	Stream_Seek(output, sizeof(UINT32));

	switch (IoControlCode)
	{
		case IOCTL_SERIAL_SET_BAUD_RATE:
			Stream_Read_UINT32(input, tty->baud_rate);
			tty_set_termios(tty);
			DEBUG_SVC("SERIAL_SET_BAUD_RATE %d", tty->baud_rate);
			break;

		case IOCTL_SERIAL_GET_BAUD_RATE:
			length = 4;
			Stream_Write_UINT32(output, tty->baud_rate);
			DEBUG_SVC("SERIAL_GET_BAUD_RATE %d", tty->baud_rate);
			break;

		case IOCTL_SERIAL_SET_QUEUE_SIZE:
			Stream_Read_UINT32(input, tty->queue_in_size);
			Stream_Read_UINT32(input, tty->queue_out_size);
			DEBUG_SVC("SERIAL_SET_QUEUE_SIZE in %d out %d", tty->queue_in_size, tty->queue_out_size);
			break;

		case IOCTL_SERIAL_SET_LINE_CONTROL:
			Stream_Read_UINT8(input, tty->stop_bits);
			Stream_Read_UINT8(input, tty->parity);
			Stream_Read_UINT8(input, tty->word_length);
			tty_set_termios(tty);
			DEBUG_SVC("SERIAL_SET_LINE_CONTROL stop %d parity %d word %d",
				tty->stop_bits, tty->parity, tty->word_length);
			break;

		case IOCTL_SERIAL_GET_LINE_CONTROL:
			DEBUG_SVC("SERIAL_GET_LINE_CONTROL");
			length = 3;
			Stream_Write_UINT8(output, tty->stop_bits);
			Stream_Write_UINT8(output, tty->parity);
			Stream_Write_UINT8(output, tty->word_length);
			break;

		case IOCTL_SERIAL_IMMEDIATE_CHAR:
			DEBUG_SVC("SERIAL_IMMEDIATE_CHAR");
			Stream_Read_UINT8(input, immediate);
			tty_write_data(tty, &immediate, 1);
			break;

		case IOCTL_SERIAL_CONFIG_SIZE:
			DEBUG_SVC("SERIAL_CONFIG_SIZE");
			length = 4;
			Stream_Write_UINT32(output, 0);
			break;

		case IOCTL_SERIAL_GET_CHARS:
			DEBUG_SVC("SERIAL_GET_CHARS");
			length = 6;
			Stream_Write(output, tty->chars, 6);
			break;

		case IOCTL_SERIAL_SET_CHARS:
			DEBUG_SVC("SERIAL_SET_CHARS");
			Stream_Read(input, tty->chars, 6);
			tty_set_termios(tty);
			break;

		case IOCTL_SERIAL_GET_HANDFLOW:
			length = 16;
			tty_get_termios(tty);
			Stream_Write_UINT32(output, tty->control);
			Stream_Write_UINT32(output, tty->xonoff);
			Stream_Write_UINT32(output, tty->onlimit);
			Stream_Write_UINT32(output, tty->offlimit);
			DEBUG_SVC("IOCTL_SERIAL_GET_HANDFLOW %X %X %X %X",
				tty->control, tty->xonoff, tty->onlimit, tty->offlimit);
			break;

		case IOCTL_SERIAL_SET_HANDFLOW:
			Stream_Read_UINT32(input, tty->control);
			Stream_Read_UINT32(input, tty->xonoff);
			Stream_Read_UINT32(input, tty->onlimit);
			Stream_Read_UINT32(input, tty->offlimit);
			DEBUG_SVC("IOCTL_SERIAL_SET_HANDFLOW %X %X %X %X",
				tty->control, tty->xonoff, tty->onlimit, tty->offlimit);
			tty_set_termios(tty);
			break;

		case IOCTL_SERIAL_SET_TIMEOUTS:
			Stream_Read_UINT32(input, tty->read_interval_timeout);
			Stream_Read_UINT32(input, tty->read_total_timeout_multiplier);
			Stream_Read_UINT32(input, tty->read_total_timeout_constant);
			Stream_Read_UINT32(input, tty->write_total_timeout_multiplier);
			Stream_Read_UINT32(input, tty->write_total_timeout_constant);

			/* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section
				http://msdn.microsoft.com/en-us/library/ms885171.aspx */
			if (tty->read_interval_timeout == SERIAL_TIMEOUT_MAX)
			{
				tty->read_interval_timeout = 0;
				tty->read_total_timeout_multiplier = 0;
			}

			DEBUG_SVC("SERIAL_SET_TIMEOUTS read timeout %d %d %d",
				tty->read_interval_timeout,
				tty->read_total_timeout_multiplier,
				tty->read_total_timeout_constant);
			break;

		case IOCTL_SERIAL_GET_TIMEOUTS:
			DEBUG_SVC("SERIAL_GET_TIMEOUTS read timeout %d %d %d",
				tty->read_interval_timeout,
				tty->read_total_timeout_multiplier,
				tty->read_total_timeout_constant);
			length = 20;
			Stream_Write_UINT32(output, tty->read_interval_timeout);
			Stream_Write_UINT32(output, tty->read_total_timeout_multiplier);
			Stream_Write_UINT32(output, tty->read_total_timeout_constant);
			Stream_Write_UINT32(output, tty->write_total_timeout_multiplier);
			Stream_Write_UINT32(output, tty->write_total_timeout_constant);
			break;

		case IOCTL_SERIAL_GET_WAIT_MASK:
			DEBUG_SVC("SERIAL_GET_WAIT_MASK %X", tty->wait_mask);
			length = 4;
			Stream_Write_UINT32(output, tty->wait_mask);
			break;

		case IOCTL_SERIAL_SET_WAIT_MASK:
			Stream_Read_UINT32(input, tty->wait_mask);
			DEBUG_SVC("SERIAL_SET_WAIT_MASK %X", tty->wait_mask);
			break;

		case IOCTL_SERIAL_SET_DTR:
			DEBUG_SVC("SERIAL_SET_DTR");
			ioctl(tty->fd, TIOCMGET, &result);
			result |= TIOCM_DTR;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->dtr = 1;
			break;

		case IOCTL_SERIAL_CLR_DTR:
			DEBUG_SVC("SERIAL_CLR_DTR");
			ioctl(tty->fd, TIOCMGET, &result);
			result &= ~TIOCM_DTR;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->dtr = 0;
			break;

		case IOCTL_SERIAL_SET_RTS:
			DEBUG_SVC("SERIAL_SET_RTS");
			ioctl(tty->fd, TIOCMGET, &result);
			result |= TIOCM_RTS;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->rts = 1;
			break;

		case IOCTL_SERIAL_CLR_RTS:
			DEBUG_SVC("SERIAL_CLR_RTS");
			ioctl(tty->fd, TIOCMGET, &result);
			result &= ~TIOCM_RTS;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->rts = 0;
			break;

		case IOCTL_SERIAL_GET_MODEMSTATUS:
			modemstate = 0;
#ifdef TIOCMGET
			ioctl(tty->fd, TIOCMGET, &result);
			if (result & TIOCM_CTS)
				modemstate |= SERIAL_MS_CTS;
			if (result & TIOCM_DSR)
				modemstate |= SERIAL_MS_DSR;
			if (result & TIOCM_RNG)
				modemstate |= SERIAL_MS_RNG;
			if (result & TIOCM_CAR)
				modemstate |= SERIAL_MS_CAR;
			if (result & TIOCM_DTR)
				modemstate |= SERIAL_MS_DTR;
			if (result & TIOCM_RTS)
				modemstate |= SERIAL_MS_RTS;
#endif
			DEBUG_SVC("SERIAL_GET_MODEMSTATUS %X", modemstate);
			length = 4;
			Stream_Write_UINT32(output, modemstate);
			break;

		case IOCTL_SERIAL_GET_COMMSTATUS:
			length = 18;
			Stream_Write_UINT32(output, 0);	/* Errors */
			Stream_Write_UINT32(output, 0);	/* Hold reasons */

			result = 0;
#ifdef TIOCINQ
			ioctl(tty->fd, TIOCINQ, &result);
#endif
			Stream_Write_UINT32(output, result); /* Amount in in queue */
			if (result)
				DEBUG_SVC("SERIAL_GET_COMMSTATUS in queue %d", result);

			result = 0;
#ifdef TIOCOUTQ
			ioctl(tty->fd, TIOCOUTQ, &result);
#endif
			Stream_Write_UINT32(output, result);	/* Amount in out queue */
			DEBUG_SVC("SERIAL_GET_COMMSTATUS out queue %d", result);

			Stream_Write_UINT8(output, 0); /* EofReceived */
			Stream_Write_UINT8(output, 0); /* WaitForImmediate */
			break;

		case IOCTL_SERIAL_PURGE:
			Stream_Read_UINT32(input, purge_mask);
			DEBUG_SVC("SERIAL_PURGE purge_mask %X", purge_mask);

		/*	See http://msdn.microsoft.com/en-us/library/ms901431.aspx
			PURGE_TXCLEAR 	Clears the output buffer, if the driver has one.
			PURGE_RXCLEAR 	Clears the input buffer, if the driver has one.

			It clearly states to clear the *driver* buffer, not the port buffer
		*/

#ifdef DEBUG_SVC
			if (purge_mask & SERIAL_PURGE_TXCLEAR)
				DEBUG_SVC("Ignoring SERIAL_PURGE_TXCLEAR");
			if (purge_mask & SERIAL_PURGE_RXCLEAR)
				DEBUG_SVC("Ignoring SERIAL_PURGE_RXCLEAR");
#endif

			if (purge_mask & SERIAL_PURGE_TXABORT)
				*abort_io |= SERIAL_ABORT_IO_WRITE;
			if (purge_mask & SERIAL_PURGE_RXABORT)
				*abort_io |= SERIAL_ABORT_IO_READ;
			break;
		case IOCTL_SERIAL_WAIT_ON_MASK:
			DEBUG_SVC("SERIAL_WAIT_ON_MASK %X", tty->wait_mask);
			tty->event_pending = 1;
			length = 4;
			if (serial_tty_get_event(tty, &result))
			{
				DEBUG_SVC("WAIT end  event = %X", result);
				Stream_Write_UINT32(output, result);
				break;
			}
			ret = STATUS_PENDING;
			break;

		case IOCTL_SERIAL_SET_BREAK_ON:
			DEBUG_SVC("SERIAL_SET_BREAK_ON");
			tcsendbreak(tty->fd, 0);
			break;

		case IOCTL_SERIAL_RESET_DEVICE:
			DEBUG_SVC("SERIAL_RESET_DEVICE");
			break;

		case IOCTL_SERIAL_SET_BREAK_OFF:
			DEBUG_SVC("SERIAL_SET_BREAK_OFF");
			break;

		case IOCTL_SERIAL_SET_XOFF:
			DEBUG_SVC("SERIAL_SET_XOFF");
			break;

		case IOCTL_SERIAL_SET_XON:
			DEBUG_SVC("SERIAL_SET_XON");
			tcflow(tty->fd, TCION);
			break;

		default:
			DEBUG_SVC("NOT FOUND IoControlCode SERIAL IOCTL %d", IoControlCode);
			return STATUS_INVALID_PARAMETER;
	}

	/* Write OutputBufferLength */
	pos = Stream_GetPosition(output);
	Stream_SetPosition(output, 16);
	Stream_Write_UINT32(output, length);
	Stream_SetPosition(output, pos);

	return ret;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
UINT cliprdr_server_read(CliprdrServerContext* context)
{
	wStream* s;
	int position;
	DWORD BytesToRead;
	DWORD BytesReturned;
	CLIPRDR_HEADER header;
	CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle;
	UINT error;
    DWORD status;

	s = cliprdr->s;

	if (Stream_GetPosition(s) < CLIPRDR_HEADER_LENGTH)
	{
		BytesReturned = 0;
		BytesToRead = CLIPRDR_HEADER_LENGTH - Stream_GetPosition(s);

        status = WaitForSingleObject(cliprdr->ChannelEvent, 0);

		if (status == WAIT_FAILED)
        {
            error = GetLastError();
            WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
            return error;
        }

        if (status == WAIT_TIMEOUT)
            return CHANNEL_RC_OK;

		if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0,
			(PCHAR) Stream_Pointer(s), BytesToRead, &BytesReturned))
		{
			WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
			return ERROR_INTERNAL_ERROR;
		}

		Stream_Seek(s, BytesReturned);
	}

	if (Stream_GetPosition(s) >= CLIPRDR_HEADER_LENGTH)
	{
		position = Stream_GetPosition(s);
		Stream_SetPosition(s, 0);

		Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */
		Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
		Stream_Read_UINT32(s, header.dataLen); /* dataLen (4 bytes) */

		if (!Stream_EnsureCapacity(s, (header.dataLen + CLIPRDR_HEADER_LENGTH)))
		{
			WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
			return CHANNEL_RC_NO_MEMORY;
		}

		Stream_SetPosition(s, position);

		if (Stream_GetPosition(s) < (header.dataLen + CLIPRDR_HEADER_LENGTH))
		{
			BytesReturned = 0;
			BytesToRead = (header.dataLen + CLIPRDR_HEADER_LENGTH) - Stream_GetPosition(s);

            status = WaitForSingleObject(cliprdr->ChannelEvent, 0);

            if (status == WAIT_FAILED)
            {
                error = GetLastError();
                WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
                return error;
            }

            if (status == WAIT_TIMEOUT)
                return CHANNEL_RC_OK;

			if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0,
				(PCHAR) Stream_Pointer(s), BytesToRead, &BytesReturned))
			{
				WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
				return ERROR_INTERNAL_ERROR;
			}

			Stream_Seek(s, BytesReturned);
		}

		if (Stream_GetPosition(s) >= (header.dataLen + CLIPRDR_HEADER_LENGTH))
		{
			Stream_SetPosition(s, (header.dataLen + CLIPRDR_HEADER_LENGTH));
			Stream_SealLength(s);
			Stream_SetPosition(s, CLIPRDR_HEADER_LENGTH);

			if ((error = cliprdr_server_receive_pdu(context, s, &header)))
			{
				WLog_ERR(TAG, "cliprdr_server_receive_pdu failed with error code %lu!", error);
				return error;
			}

			Stream_SetPosition(s, 0);

			/* check for trailing zero bytes */

            status = WaitForSingleObject(cliprdr->ChannelEvent, 0);

            if (status == WAIT_FAILED)
            {
                error = GetLastError();
                WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
                return error;
            }

            if (status == WAIT_TIMEOUT)
                return CHANNEL_RC_OK;

			BytesReturned = 0;
			BytesToRead = 4;

			if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0,
				(PCHAR) Stream_Pointer(s), BytesToRead, &BytesReturned))
			{
				WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
				return ERROR_INTERNAL_ERROR;
			}

			if (BytesReturned == 4)
			{
				Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */
				Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */

				if (!header.msgType)
				{
					/* ignore trailing bytes */
					Stream_SetPosition(s, 0);
				}
			}
			else
			{
				Stream_Seek(s, BytesReturned);
			}
		}
	}

	return CHANNEL_RC_OK;
}
Exemplo n.º 14
0
void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd,
        wStream* input_stream, guac_rdpsnd_pdu_header* header) {

    int server_format_count;
    int server_version;
    int i;

    wStream* output_stream;
    int output_body_size;
    unsigned char* output_stream_end;

    /* Get associated client data */
    guac_client* client = rdpsnd->client;
    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;

    /* Get audio stream from client data */
    guac_audio_stream* audio = rdp_client->audio;

    /* Format header */
    Stream_Seek(input_stream, 14);
    Stream_Read_UINT16(input_stream, server_format_count);
    Stream_Seek_UINT8(input_stream);
    Stream_Read_UINT16(input_stream, server_version);
    Stream_Seek_UINT8(input_stream);

    /* Initialize Client Audio Formats and Version PDU */
    output_stream = Stream_New(NULL, 24);
    Stream_Write_UINT8(output_stream,  SNDC_FORMATS);
    Stream_Write_UINT8(output_stream,  0);

    /* Fill in body size later */
    Stream_Seek_UINT16(output_stream); /* offset = 0x02 */

    /* Flags, volume, and pitch */
    Stream_Write_UINT32(output_stream, TSSNDCAPS_ALIVE);
    Stream_Write_UINT32(output_stream, 0);
    Stream_Write_UINT32(output_stream, 0);

    /* Datagram port (UDP) */
    Stream_Write_UINT16(output_stream, 0);

    /* Fill in format count later */
    Stream_Seek_UINT16(output_stream); /* offset = 0x12 */

    /* Version and padding */
    Stream_Write_UINT8(output_stream,  0);
    Stream_Write_UINT16(output_stream, 6);
    Stream_Write_UINT8(output_stream,  0);

    /* Check each server format, respond if supported and audio is enabled */
    if (audio != NULL) {
        for (i=0; i < server_format_count; i++) {

            unsigned char* format_start;

            int format_tag;
            int channels;
            int rate;
            int bps;
            int body_size;

            /* Remember position in stream */
            Stream_GetPointer(input_stream, format_start);

            /* Read format */
            Stream_Read_UINT16(input_stream, format_tag);
            Stream_Read_UINT16(input_stream, channels);
            Stream_Read_UINT32(input_stream, rate);
            Stream_Seek_UINT32(input_stream);
            Stream_Seek_UINT16(input_stream);
            Stream_Read_UINT16(input_stream, bps);

            /* Skip past extra data */
            Stream_Read_UINT16(input_stream, body_size);
            Stream_Seek(input_stream, body_size);

            /* If PCM, accept */
            if (format_tag == WAVE_FORMAT_PCM) {

                /* If can fit another format, accept it */
                if (rdpsnd->format_count < GUAC_RDP_MAX_FORMATS) {

                    /* Add channel */
                    int current = rdpsnd->format_count++;
                    rdpsnd->formats[current].rate     = rate;
                    rdpsnd->formats[current].channels = channels;
                    rdpsnd->formats[current].bps      = bps;

                    /* Log format */
                    guac_client_log(client, GUAC_LOG_INFO,
                            "Accepted format: %i-bit PCM with %i channels at "
                            "%i Hz",
                            bps, channels, rate);

                    /* Ensure audio stream is configured to use accepted
                     * format */
                    guac_audio_stream_reset(audio, NULL, rate, channels, bps);

                    /* Queue format for sending as accepted */
                    Stream_EnsureRemainingCapacity(output_stream,
                            18 + body_size);
                    Stream_Write(output_stream, format_start, 18 + body_size);

                    /*
                     * BEWARE that using Stream_EnsureRemainingCapacity means
                     * that any pointers returned via Stream_GetPointer on
                     * output_stream are invalid.
                     */

                }

                /* Otherwise, log that we dropped one */
                else
                    guac_client_log(client, GUAC_LOG_INFO,
                            "Dropped valid format: %i-bit PCM with %i "
                            "channels at %i Hz",
                            bps, channels, rate);

            }

        }
    }

    /* Otherwise, ignore all supported formats as we do not intend to actually
     * receive audio */
    else
        guac_client_log(client, GUAC_LOG_DEBUG,
                "Audio explicitly disabled. Ignoring supported formats.");

    /* Calculate size of PDU */
    output_body_size = Stream_GetPosition(output_stream) - 4;
    Stream_GetPointer(output_stream, output_stream_end);

    /* Set body size */
    Stream_SetPosition(output_stream, 0x02);
    Stream_Write_UINT16(output_stream, output_body_size);

    /* Set format count */
    Stream_SetPosition(output_stream, 0x12);
    Stream_Write_UINT16(output_stream, rdpsnd->format_count);

    /* Reposition cursor at end (necessary for message send) */
    Stream_SetPointer(output_stream, output_stream_end);

    /* Send accepted formats */
    pthread_mutex_lock(&(rdp_client->rdp_lock));
    svc_plugin_send((rdpSvcPlugin*)rdpsnd, output_stream);

    /* If version greater than 6, must send Quality Mode PDU */
    if (server_version >= 6) {

        /* Always send High Quality for now */
        output_stream = Stream_New(NULL, 8);
        Stream_Write_UINT8(output_stream, SNDC_QUALITYMODE);
        Stream_Write_UINT8(output_stream, 0);
        Stream_Write_UINT16(output_stream, 4);
        Stream_Write_UINT16(output_stream, HIGH_QUALITY);
        Stream_Write_UINT16(output_stream, 0);

        svc_plugin_send((rdpSvcPlugin*)rdpsnd, output_stream);
    }

    pthread_mutex_unlock(&(rdp_client->rdp_lock));

}
Exemplo n.º 15
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;
}
Exemplo n.º 16
0
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);
	}
}
Exemplo n.º 17
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;
}
Exemplo n.º 18
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;
}
Exemplo n.º 19
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;
}
Exemplo n.º 20
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;
}
Exemplo n.º 21
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;
}
Exemplo n.º 22
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s,
				       RDPGFX_H264_METABLOCK* meta)
{
	UINT32 index;
	RECTANGLE_16* regionRect;
	RDPGFX_H264_QUANT_QUALITY* quantQualityVal;
	UINT error = ERROR_INVALID_DATA;

	meta->regionRects = NULL;
	meta->quantQualityVals = NULL;

	if (Stream_GetRemainingLength(s) < 4)
	{
		WLog_ERR(TAG, "not enough data!");
		goto error_out;
	}

	Stream_Read_UINT32(s, meta->numRegionRects); /* numRegionRects (4 bytes) */

	if (Stream_GetRemainingLength(s) < (meta->numRegionRects * 8))
	{
		WLog_ERR(TAG, "not enough data!");
		goto error_out;
	}

	meta->regionRects = (RECTANGLE_16*) malloc(meta->numRegionRects * sizeof(RECTANGLE_16));

	if (!meta->regionRects)
	{
		WLog_ERR(TAG, "malloc failed!");
		error = CHANNEL_RC_NO_MEMORY;
		goto error_out;
	}

	meta->quantQualityVals = (RDPGFX_H264_QUANT_QUALITY*) malloc(meta->numRegionRects * sizeof(RDPGFX_H264_QUANT_QUALITY));

	if (!meta->quantQualityVals)
	{
		WLog_ERR(TAG, "malloc failed!");
		error = CHANNEL_RC_NO_MEMORY;
		goto error_out;
	}

	WLog_DBG(TAG, "H264_METABLOCK: numRegionRects: %"PRIu32"", meta->numRegionRects);

	for (index = 0; index < meta->numRegionRects; index++)
	{
		regionRect = &(meta->regionRects[index]);
		if ((error = rdpgfx_read_rect16(s, regionRect)))
		{
			WLog_ERR(TAG, "rdpgfx_read_rect16 failed with error %"PRIu32"!", error);
			goto error_out;
		}
		WLog_DBG(TAG, "regionRects[%"PRIu32"]: left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16"",
				 index, regionRect->left, regionRect->top, regionRect->right, regionRect->bottom);
	}

	if (Stream_GetRemainingLength(s) < (meta->numRegionRects * 2))
	{
		WLog_ERR(TAG, "not enough data!");
		error = ERROR_INVALID_DATA;
		goto error_out;
	}

	for (index = 0; index < meta->numRegionRects; index++)
	{
		quantQualityVal = &(meta->quantQualityVals[index]);
		Stream_Read_UINT8(s, quantQualityVal->qpVal); /* qpVal (1 byte) */
		Stream_Read_UINT8(s, quantQualityVal->qualityVal); /* qualityVal (1 byte) */

		quantQualityVal->qp = quantQualityVal->qpVal & 0x3F;
		quantQualityVal->r = (quantQualityVal->qpVal >> 6) & 1;
		quantQualityVal->p = (quantQualityVal->qpVal >> 7) & 1;
		WLog_DBG(TAG, "quantQualityVals[%"PRIu32"]: qp: %"PRIu8" r: %"PRIu8" p: %"PRIu8" qualityVal: %"PRIu8"",
				 index, quantQualityVal->qp, quantQualityVal->r, quantQualityVal->p, quantQualityVal->qualityVal);
	}

	return CHANNEL_RC_OK;
error_out:
	free(meta->regionRects);
	meta->regionRects = NULL;
	free(meta->quantQualityVals);
	meta->quantQualityVals = NULL;
	return error;
}
Exemplo n.º 23
0
static BOOL peer_recv_data_pdu(freerdp_peer* client, wStream* s)
{
	BYTE type;
	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 FALSE;

#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_SYNCHRONIZE:
			if (!rdp_recv_client_synchronize_pdu(client->context->rdp, s))
				return FALSE;
			break;

		case DATA_PDU_TYPE_CONTROL:
			if (!rdp_server_accept_client_control_pdu(client->context->rdp, s))
				return FALSE;
			break;

		case DATA_PDU_TYPE_INPUT:
			if (!input_recv(client->context->rdp->input, s))
				return FALSE;
			break;

		case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST:
			/* TODO: notify server bitmap cache data */
			break;

		case DATA_PDU_TYPE_FONT_LIST:

			if (!rdp_server_accept_client_font_list_pdu(client->context->rdp, s))
				return FALSE;

			break;

		case DATA_PDU_TYPE_SHUTDOWN_REQUEST:
			mcs_send_disconnect_provider_ultimatum(client->context->rdp->mcs);
			return FALSE;

		case DATA_PDU_TYPE_FRAME_ACKNOWLEDGE:
			if (Stream_GetRemainingLength(s) < 4)
				return FALSE;
			Stream_Read_UINT32(s, client->ack_frame_id);
			IFCALL(client->update->SurfaceFrameAcknowledge, client->update->context, client->ack_frame_id);
			break;

		case DATA_PDU_TYPE_REFRESH_RECT:
			if (!update_read_refresh_rect(client->update, s))
				return FALSE;
			break;

		case DATA_PDU_TYPE_SUPPRESS_OUTPUT:
			if (!update_read_suppress_output(client->update, s))
				return FALSE;
			break;

		default:
			DEBUG_WARN( "Data PDU type %d\n", type);
			break;
	}

	return TRUE;
}
Exemplo n.º 24
0
static UINT serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
{
	DWORD DesiredAccess;
	DWORD SharedAccess;
	DWORD CreateDisposition;
	UINT32 PathLength;

	if (Stream_GetRemainingLength(irp->input) < 32)
		return ERROR_INVALID_DATA;

	Stream_Read_UINT32(irp->input, DesiredAccess);		/* DesiredAccess (4 bytes) */
	Stream_Seek_UINT64(irp->input);				/* AllocationSize (8 bytes) */
	Stream_Seek_UINT32(irp->input);				/* FileAttributes (4 bytes) */
	Stream_Read_UINT32(irp->input, SharedAccess);		/* SharedAccess (4 bytes) */
	Stream_Read_UINT32(irp->input, CreateDisposition);	/* CreateDisposition (4 bytes) */
	Stream_Seek_UINT32(irp->input); 			/* CreateOptions (4 bytes) */
	Stream_Read_UINT32(irp->input, PathLength);		/* PathLength (4 bytes) */

	if (Stream_GetRemainingLength(irp->input) < PathLength)
		return ERROR_INVALID_DATA;

	Stream_Seek(irp->input, PathLength);			/* Path (variable) */
	assert(PathLength == 0); /* MS-RDPESP 2.2.2.2 */
#ifndef _WIN32
	/* Windows 2012 server sends on a first call :
	 *     DesiredAccess     = 0x00100080: SYNCHRONIZE | FILE_READ_ATTRIBUTES
	 *     SharedAccess      = 0x00000007: FILE_SHARE_DELETE | FILE_SHARE_WRITE | FILE_SHARE_READ
	 *     CreateDisposition = 0x00000001: CREATE_NEW
	 *
	 * then Windows 2012 sends :
	 *     DesiredAccess     = 0x00120089: SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA
	 *     SharedAccess      = 0x00000007: FILE_SHARE_DELETE | FILE_SHARE_WRITE | FILE_SHARE_READ
	 *     CreateDisposition = 0x00000001: CREATE_NEW
	 *
	 * assert(DesiredAccess == (GENERIC_READ | GENERIC_WRITE));
	 * assert(SharedAccess == 0);
	 * assert(CreateDisposition == OPEN_EXISTING);
	 *
	 */
	WLog_Print(serial->log, WLOG_DEBUG,
	           "DesiredAccess: 0x%"PRIX32", SharedAccess: 0x%"PRIX32", CreateDisposition: 0x%"PRIX32"",
	           DesiredAccess, SharedAccess, CreateDisposition);
	/* FIXME: As of today only the flags below are supported by CommCreateFileA: */
	DesiredAccess     = GENERIC_READ | GENERIC_WRITE;
	SharedAccess      = 0;
	CreateDisposition = OPEN_EXISTING;
#endif
	serial->hComm = CreateFile(serial->device.name,
	                           DesiredAccess,
	                           SharedAccess,
	                           NULL,			/* SecurityAttributes */
	                           CreateDisposition,
	                           0,			/* FlagsAndAttributes */
	                           NULL);			/* TemplateFile */

	if (!serial->hComm || (serial->hComm == INVALID_HANDLE_VALUE))
	{
		WLog_Print(serial->log, WLOG_WARN, "CreateFile failure: %s last-error: 0x%08"PRIX32"",
		           serial->device.name, GetLastError());
		irp->IoStatus = STATUS_UNSUCCESSFUL;
		goto error_handle;
	}

	_comm_setServerSerialDriver(serial->hComm, serial->ServerSerialDriverId);
	_comm_set_permissive(serial->hComm, serial->permissive);
	/* NOTE: binary mode/raw mode required for the redirection. On
	 * Linux, CommCreateFileA forces this setting.
	 */
	/* ZeroMemory(&dcb, sizeof(DCB)); */
	/* dcb.DCBlength = sizeof(DCB); */
	/* GetCommState(serial->hComm, &dcb); */
	/* dcb.fBinary = TRUE; */
	/* SetCommState(serial->hComm, &dcb); */
	assert(irp->FileId == 0);
	irp->FileId = irp->devman->id_sequence++; /* FIXME: why not ((WINPR_COMM*)hComm)->fd? */
	irp->IoStatus = STATUS_SUCCESS;
	WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %"PRIu32", FileId: %"PRIu32") created.",
	           serial->device.name, irp->device->id, irp->FileId);
error_handle:
	Stream_Write_UINT32(irp->output, irp->FileId);	/* FileId (4 bytes) */
	Stream_Write_UINT8(irp->output, 0);		/* Information (1 byte) */
	return CHANNEL_RC_OK;
}
Exemplo n.º 25
0
BOOL gcc_read_server_security_data(wStream* s, rdpMcs* mcs)
{
	BYTE* data;
	UINT32 length;
	rdpSettings* settings = mcs->settings;

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

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

	if (settings->EncryptionMethods == 0 && settings->EncryptionLevel == 0)
	{
		/* serverRandom and serverRandom must not be present */
		settings->DisableEncryption = FALSE;
		settings->EncryptionMethods = ENCRYPTION_METHOD_NONE;
		settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
		return TRUE;
	}

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

	Stream_Read_UINT32(s, settings->ServerRandomLength); /* serverRandomLen */
	Stream_Read_UINT32(s, settings->ServerCertificateLength); /* serverCertLen */

	if (Stream_GetRemainingLength(s) < settings->ServerRandomLength + settings->ServerCertificateLength)
		return FALSE;

	if (settings->ServerRandomLength > 0)
	{
		/* serverRandom */
		settings->ServerRandom = (BYTE*) malloc(settings->ServerRandomLength);
		Stream_Read(s, settings->ServerRandom, settings->ServerRandomLength);
	}
	else
	{
		return FALSE;
	}

	if (settings->ServerCertificateLength > 0)
	{
		/* serverCertificate */
		settings->ServerCertificate = (BYTE*) malloc(settings->ServerCertificateLength);
		Stream_Read(s, settings->ServerCertificate, settings->ServerCertificateLength);

		certificate_free(settings->RdpServerCertificate);
		settings->RdpServerCertificate = certificate_new();
		data = settings->ServerCertificate;
		length = settings->ServerCertificateLength;

		if (certificate_read_server_certificate(settings->RdpServerCertificate, data, length) < 1)
			return FALSE;
	}
	else
	{
		return FALSE;
	}

	return TRUE;
}
Exemplo n.º 26
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
{
	UINT32 IoControlCode;
	UINT32 InputBufferLength;
	BYTE*  InputBuffer = NULL;
	UINT32 OutputBufferLength;
	BYTE*  OutputBuffer = NULL;
	DWORD  BytesReturned = 0;

	if (Stream_GetRemainingLength(irp->input) < 32)
		return ERROR_INVALID_DATA;

	Stream_Read_UINT32(irp->input, OutputBufferLength); /* OutputBufferLength (4 bytes) */
	Stream_Read_UINT32(irp->input, InputBufferLength); /* InputBufferLength (4 bytes) */

	Stream_Read_UINT32(irp->input, IoControlCode); /* IoControlCode (4 bytes) */
	Stream_Seek(irp->input, 20); /* Padding (20 bytes) */

	if (Stream_GetRemainingLength(irp->input) < InputBufferLength)
		return ERROR_INVALID_DATA;

	OutputBuffer = (BYTE*)calloc(OutputBufferLength, sizeof(BYTE));
	if (OutputBuffer == NULL)
	{
		irp->IoStatus = STATUS_NO_MEMORY;
		goto error_handle;
	}

	InputBuffer = (BYTE*)calloc(InputBufferLength, sizeof(BYTE));
	if (InputBuffer == NULL)
	{
		irp->IoStatus = STATUS_NO_MEMORY;
		goto error_handle;
	}

	Stream_Read(irp->input, InputBuffer, InputBufferLength);
	WLog_Print(serial->log, WLOG_DEBUG,
	           "CommDeviceIoControl: CompletionId=%"PRIu32", IoControlCode=[0x%"PRIX32"] %s",
	           irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode));

	/* FIXME: CommDeviceIoControl to be replaced by DeviceIoControl() */
	if (CommDeviceIoControl(serial->hComm, IoControlCode, InputBuffer,
	                        InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned, NULL))
	{
		/* WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl: CompletionId=%"PRIu32", IoControlCode=[0x%"PRIX32"] %s done", irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode)); */
		irp->IoStatus = STATUS_SUCCESS;
	}
	else
	{
		WLog_Print(serial->log, WLOG_DEBUG,
		           "CommDeviceIoControl failure: IoControlCode=[0x%"PRIX32"] %s, last-error: 0x%08"PRIX32"",
		           IoControlCode, _comm_serial_ioctl_name(IoControlCode), GetLastError());
		irp->IoStatus = _GetLastErrorToIoStatus(serial);
	}

error_handle:
	/* FIXME: find out whether it's required or not to get
	 * BytesReturned == OutputBufferLength when
	 * CommDeviceIoControl returns FALSE */
	assert(OutputBufferLength == BytesReturned);
	Stream_Write_UINT32(irp->output, BytesReturned); /* OutputBufferLength (4 bytes) */

	if (BytesReturned > 0)
	{
		if (!Stream_EnsureRemainingCapacity(irp->output, BytesReturned))
		{
			WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
			free(InputBuffer);
			free(OutputBuffer);
			return CHANNEL_RC_NO_MEMORY;
		}

		Stream_Write(irp->output, OutputBuffer, BytesReturned); /* OutputBuffer */
	}

	/* FIXME: Why at least Windows 2008R2 gets lost with this
	 * extra byte and likely on a IOCTL_SERIAL_SET_BAUD_RATE? The
	 * extra byte is well required according MS-RDPEFS
	 * 2.2.1.5.5 */
	/* else */
	/* { */
	/* 	Stream_Write_UINT8(irp->output, 0); /\* Padding (1 byte) *\/ */
	/* } */
	free(InputBuffer);
	free(OutputBuffer);
	return CHANNEL_RC_OK;
}
Exemplo n.º 27
0
void remmina_rdp_cliprdr_process_data_response(RemminaProtocolWidget* gp, RDP_CB_DATA_RESPONSE_EVENT* event)
{
	UINT8* data;
	size_t size;
	rfContext* rfi = GET_DATA(gp);
	GdkPixbufLoader *pixbuf;
	gpointer output = NULL;

	data = event->data;
	size = event->size;

	if (size > 0)
	{
		switch (rfi->format)
		{
			case CB_FORMAT_UNICODETEXT:
			{
				size = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)data, size / 2, (CHAR**)&data, 0, NULL, NULL);
				crlf2lf(data, &size);
				output = data;
				break;
			}

			case CB_FORMAT_TEXT:
			case CB_FORMAT_HTML:
			{
				crlf2lf(data, &size);
				output = data;
				break;
			}

			case CB_FORMAT_DIB:
			{
				wStream* s;
				UINT16 bpp;
				UINT32 offset;
				UINT32 ncolors;

				s = Stream_New(data, size);
				Stream_Seek(s, 14);
				Stream_Read_UINT16(s, bpp);
				Stream_Read_UINT32(s, ncolors);
				offset = 14 + 40 + (bpp <= 8 ? (ncolors == 0 ? (1 << bpp) : ncolors) * 4 : 0);
				Stream_Free(s, TRUE);

				s = Stream_New(NULL, 14 + size);
				Stream_Write_UINT8(s, 'B');
				Stream_Write_UINT8(s, 'M');
				Stream_Write_UINT32(s, 14 + size);
				Stream_Write_UINT32(s, 0);
				Stream_Write_UINT32(s, offset);
				Stream_Write(s, data, size);

				data = Stream_Buffer(s);
				size = Stream_Length(s);

				pixbuf = gdk_pixbuf_loader_new();
				gdk_pixbuf_loader_write(pixbuf, data, size, NULL);
				gdk_pixbuf_loader_close(pixbuf, NULL);
				Stream_Free(s, TRUE);
				output = g_object_ref(gdk_pixbuf_loader_get_pixbuf(pixbuf));
				g_object_unref(pixbuf);
				break;
			}

			case CB_FORMAT_PNG:
			case CB_FORMAT_JPEG:
			{
				pixbuf = gdk_pixbuf_loader_new();
				gdk_pixbuf_loader_write(pixbuf, data, size, NULL);
				output = g_object_ref(gdk_pixbuf_loader_get_pixbuf(pixbuf));
				gdk_pixbuf_loader_close(pixbuf, NULL);
				g_object_unref(pixbuf);
				break;
			}
		}
	}
	g_async_queue_push(rfi->clipboard_queue, output);
}
Exemplo n.º 28
0
BOOL update_read_window_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState)
{
	int i;
	int size;

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER)
	{
		if (Stream_GetRemainingLength(s) < 4)
			return FALSE;

		Stream_Read_UINT32(s, windowState->ownerWindowId); /* ownerWindowId (4 bytes) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE)
	{
		if (Stream_GetRemainingLength(s) < 8)
			return FALSE;

		Stream_Read_UINT32(s, windowState->style); /* style (4 bytes) */
		Stream_Read_UINT32(s, windowState->extendedStyle); /* extendedStyle (4 bytes) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW)
	{
		if (Stream_GetRemainingLength(s) < 1)
			return FALSE;

		Stream_Read_UINT8(s, windowState->showState); /* showState (1 byte) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE)
	{
		if (!rail_read_unicode_string(s, &windowState->titleInfo)) /* titleInfo */
			return FALSE;
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
	{
		if (Stream_GetRemainingLength(s) < 4)
			return FALSE;

		Stream_Read_UINT32(s, windowState->clientOffsetX); /* clientOffsetX (4 bytes) */
		Stream_Read_UINT32(s, windowState->clientOffsetY); /* clientOffsetY (4 bytes) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
	{
		if (Stream_GetRemainingLength(s) < 4)
			return FALSE;

		Stream_Read_UINT32(s, windowState->clientAreaWidth); /* clientAreaWidth (4 bytes) */
		Stream_Read_UINT32(s, windowState->clientAreaHeight); /* clientAreaHeight (4 bytes) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT)
	{
		if (Stream_GetRemainingLength(s) < 1)
			return FALSE;

		Stream_Read_UINT8(s, windowState->RPContent); /* RPContent (1 byte) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT)
	{
		if (Stream_GetRemainingLength(s) < 4)
			return FALSE;

		Stream_Read_UINT32(s, windowState->rootParentHandle);/* rootParentHandle (4 bytes) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
	{
		if (Stream_GetRemainingLength(s) < 8)
			return FALSE;

		Stream_Read_UINT32(s, windowState->windowOffsetX); /* windowOffsetX (4 bytes) */
		Stream_Read_UINT32(s, windowState->windowOffsetY); /* windowOffsetY (4 bytes) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
	{
		if (Stream_GetRemainingLength(s) < 8)
			return FALSE;

		Stream_Read_UINT32(s, windowState->windowClientDeltaX); /* windowClientDeltaX (4 bytes) */
		Stream_Read_UINT32(s, windowState->windowClientDeltaY); /* windowClientDeltaY (4 bytes) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
	{
		if (Stream_GetRemainingLength(s) < 8)
			return FALSE;

		Stream_Read_UINT32(s, windowState->windowWidth); /* windowWidth (4 bytes) */
		Stream_Read_UINT32(s, windowState->windowHeight); /* windowHeight (4 bytes) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
	{
		if (Stream_GetRemainingLength(s) < 2)
			return FALSE;

		Stream_Read_UINT16(s, windowState->numWindowRects); /* numWindowRects (2 bytes) */

		size = sizeof(RECTANGLE_16) * windowState->numWindowRects;
		windowState->windowRects = (RECTANGLE_16*) malloc(size);

		if (Stream_GetRemainingLength(s) < 8 * windowState->numWindowRects)
			return FALSE;

		/* windowRects */
		for (i = 0; i < (int) windowState->numWindowRects; i++)
		{
			Stream_Read_UINT16(s, windowState->windowRects[i].left); /* left (2 bytes) */
			Stream_Read_UINT16(s, windowState->windowRects[i].top); /* top (2 bytes) */
			Stream_Read_UINT16(s, windowState->windowRects[i].right); /* right (2 bytes) */
			Stream_Read_UINT16(s, windowState->windowRects[i].bottom); /* bottom (2 bytes) */
		}
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
	{
		if (Stream_GetRemainingLength(s) < 4)
			return FALSE;

		Stream_Read_UINT32(s, windowState->visibleOffsetX); /* visibleOffsetX (4 bytes) */
		Stream_Read_UINT32(s, windowState->visibleOffsetY); /* visibleOffsetY (4 bytes) */
	}

	if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
	{
		if (Stream_GetRemainingLength(s) < 2)
			return FALSE;

		Stream_Read_UINT16(s, windowState->numVisibilityRects); /* numVisibilityRects (2 bytes) */

		size = sizeof(RECTANGLE_16) * windowState->numVisibilityRects;
		windowState->visibilityRects = (RECTANGLE_16*) malloc(size);

		if (Stream_GetRemainingLength(s) < windowState->numVisibilityRects * 8)
			return FALSE;

		/* visibilityRects */
		for (i = 0; i < (int) windowState->numVisibilityRects; i++)
		{
			Stream_Read_UINT16(s, windowState->visibilityRects[i].left); /* left (2 bytes) */
			Stream_Read_UINT16(s, windowState->visibilityRects[i].top); /* top (2 bytes) */
			Stream_Read_UINT16(s, windowState->visibilityRects[i].right); /* right (2 bytes) */
			Stream_Read_UINT16(s, windowState->visibilityRects[i].bottom); /* bottom (2 bytes) */
		}
	}
	return TRUE;
}
Exemplo n.º 29
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;
}
Exemplo n.º 30
0
Arquivo: rfx.c Projeto: C4rt/FreeRDP
static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s, UINT16* pExpecedBlockType)
{
	BOOL rc;
	int i, close_cnt;
	int pos;
	BYTE quant;
	RFX_TILE* tile;
	UINT32* quants;
	UINT16 subtype;
	UINT32 blockLen;
	UINT32 blockType;
	UINT32 tilesDataSize;
	PTP_WORK* work_objects = NULL;
	RFX_TILE_PROCESS_WORK_PARAM* params = NULL;
	void *pmem;

	if (*pExpecedBlockType != WBT_EXTENSION)
	{
		WLog_ERR(TAG, "%s: message unexpeced", __FUNCTION__);
		return FALSE;
	}
	*pExpecedBlockType = WBT_FRAME_END;

	if (Stream_GetRemainingLength(s) < 14)
	{
		WLog_ERR(TAG, "RfxMessageTileSet packet too small");
		return FALSE;
	}

	Stream_Read_UINT16(s, subtype); /* subtype (2 bytes) must be set to CBT_TILESET (0xCAC2) */

	if (subtype != CBT_TILESET)
	{
		WLog_ERR(TAG, "invalid subtype, expected CBT_TILESET.");
		return FALSE;
	}

	Stream_Seek_UINT16(s); /* idx (2 bytes), must be set to 0x0000 */
	Stream_Seek_UINT16(s); /* properties (2 bytes) */

	Stream_Read_UINT8(s, context->numQuant); /* numQuant (1 byte) */
	Stream_Seek_UINT8(s); /* tileSize (1 byte), must be set to 0x40 */

	if (context->numQuant < 1)
	{
		WLog_ERR(TAG, "no quantization value.");
		return FALSE;
	}

	Stream_Read_UINT16(s, message->numTiles); /* numTiles (2 bytes) */

	if (message->numTiles < 1)
	{
		WLog_ERR(TAG, "no tiles.");
		return FALSE;
	}

	Stream_Read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */

	if (!(pmem = realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32))))
		return FALSE;

	quants = context->quants = (UINT32*) pmem;

	/* quantVals */
	if (Stream_GetRemainingLength(s) < (size_t) (context->numQuant * 5))
	{
		WLog_ERR(TAG, "RfxMessageTileSet packet too small for num_quants=%d", context->numQuant);
		return FALSE;
	}

	for (i = 0; i < context->numQuant; i++)
	{
		/* RFX_CODEC_QUANT */
		Stream_Read_UINT8(s, quant);
		*quants++ = (quant & 0x0F);
		*quants++ = (quant >> 4);
		Stream_Read_UINT8(s, quant);
		*quants++ = (quant & 0x0F);
		*quants++ = (quant >> 4);
		Stream_Read_UINT8(s, quant);
		*quants++ = (quant & 0x0F);
		*quants++ = (quant >> 4);
		Stream_Read_UINT8(s, quant);
		*quants++ = (quant & 0x0F);
		*quants++ = (quant >> 4);
		Stream_Read_UINT8(s, quant);
		*quants++ = (quant & 0x0F);
		*quants++ = (quant >> 4);

		WLog_Print(context->priv->log, WLOG_DEBUG, "quant %d (%d %d %d %d %d %d %d %d %d %d).",
			i, context->quants[i * 10], context->quants[i * 10 + 1],
			context->quants[i * 10 + 2], context->quants[i * 10 + 3],
			context->quants[i * 10 + 4], context->quants[i * 10 + 5],
			context->quants[i * 10 + 6], context->quants[i * 10 + 7],
			context->quants[i * 10 + 8], context->quants[i * 10 + 9]);
	}

	if (!(message->tiles = (RFX_TILE**) calloc(message->numTiles, sizeof(RFX_TILE*))))
	{
		message->numTiles = 0;
		return FALSE;
	}

	if (context->priv->UseThreads)
	{
		work_objects = (PTP_WORK*) calloc(message->numTiles, sizeof(PTP_WORK));
		params = (RFX_TILE_PROCESS_WORK_PARAM*) calloc(message->numTiles, sizeof(RFX_TILE_PROCESS_WORK_PARAM));

		if (!work_objects)
		{
			free(params);
			return FALSE;
		}

		if (!params)
		{
			free(work_objects);
			return FALSE;
		}
	}

	/* tiles */
	close_cnt = 0;
	rc = TRUE;
	for (i = 0; i < message->numTiles; i++)
	{
		if (!(tile = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool)))
		{
			WLog_ERR(TAG, "RfxMessageTileSet failed to get tile from object pool");
			rc = FALSE;
			break;
		}

		message->tiles[i] = tile;

		/* RFX_TILE */
		if (Stream_GetRemainingLength(s) < 6)
		{
			WLog_ERR(TAG, "RfxMessageTileSet packet too small to read tile %d/%d", i, message->numTiles);
			rc = FALSE;
			break;
		}

		Stream_Read_UINT16(s, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */
		Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */

		if (Stream_GetRemainingLength(s) < blockLen - 6)
		{
			WLog_ERR(TAG, "RfxMessageTileSet not enough bytes to read tile %d/%d with blocklen=%d",
					 i, message->numTiles, blockLen);
			rc = FALSE;
			break;
		}

		pos = Stream_GetPosition(s) - 6 + blockLen;

		if (blockType != CBT_TILE)
		{
			WLog_ERR(TAG, "unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType);
			rc = FALSE;
			break;
		}

		Stream_Read_UINT8(s, tile->quantIdxY); /* quantIdxY (1 byte) */
		Stream_Read_UINT8(s, tile->quantIdxCb); /* quantIdxCb (1 byte) */
		Stream_Read_UINT8(s, tile->quantIdxCr); /* quantIdxCr (1 byte) */
		Stream_Read_UINT16(s, tile->xIdx); /* xIdx (2 bytes) */
		Stream_Read_UINT16(s, tile->yIdx); /* yIdx (2 bytes) */
		Stream_Read_UINT16(s, tile->YLen); /* YLen (2 bytes) */
		Stream_Read_UINT16(s, tile->CbLen); /* CbLen (2 bytes) */
		Stream_Read_UINT16(s, tile->CrLen); /* CrLen (2 bytes) */

		Stream_GetPointer(s, tile->YData);
		Stream_Seek(s, tile->YLen);
		Stream_GetPointer(s, tile->CbData);
		Stream_Seek(s, tile->CbLen);
		Stream_GetPointer(s, tile->CrData);
		Stream_Seek(s, tile->CrLen);

		tile->x = tile->xIdx * 64;
		tile->y = tile->yIdx * 64;

		if (context->priv->UseThreads)
		{
			assert(params);

			params[i].context = context;
			params[i].tile = message->tiles[i];

			if (!(work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_process_message_tile_work_callback,
					(void*) &params[i], &context->priv->ThreadPoolEnv)))
			{
				WLog_ERR(TAG, "CreateThreadpoolWork failed.");
				rc = FALSE;
				break;
			}

			SubmitThreadpoolWork(work_objects[i]);
			close_cnt = i + 1;
		}
		else
		{
			rfx_decode_rgb(context, tile, tile->data, 64 * 4);
		}

		Stream_SetPosition(s, pos);
	}

	if (context->priv->UseThreads)
	{
		for (i = 0; i < close_cnt; i++)
		{
			WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE);
			CloseThreadpoolWork(work_objects[i]);
		}

		free(work_objects);
		free(params);
	}

	for (i = 0; i < message->numTiles; i++)
	{
		if (!(tile = message->tiles[i]))
			continue;
		tile->YLen = tile->CbLen = tile->CrLen = 0;
		tile->YData = tile->CbData = tile->CrData = NULL;
	}

	return rc;
}