Exemple #1
0
BOOL http_proxy_connect(BIO* bufferedBio, const char* hostname, UINT16 port)
{
	int status;
	wStream* s;
	char port_str[10], recv_buf[256], *eol;
	int resultsize;
	_itoa_s(port, port_str, sizeof(port_str), 10);
	s = Stream_New(NULL, 200);
	Stream_Write(s, "CONNECT ", 8);
	Stream_Write(s, hostname, strlen(hostname));
	Stream_Write_UINT8(s, ':');
	Stream_Write(s, port_str, strlen(port_str));
	Stream_Write(s, " HTTP/1.1" CRLF "Host: ", 17);
	Stream_Write(s, hostname, strlen(hostname));
	Stream_Write_UINT8(s, ':');
	Stream_Write(s, port_str, strlen(port_str));
	Stream_Write(s, CRLF CRLF, 4);
	status = BIO_write(bufferedBio, Stream_Buffer(s), Stream_GetPosition(s));

	if (status != Stream_GetPosition(s))
	{
		WLog_ERR(TAG, "HTTP proxy: failed to write CONNECT request");
		return FALSE;
	}

	Stream_Free(s, TRUE);
	s = NULL;
	/* Read result until CR-LF-CR-LF.
	 * Keep recv_buf a null-terminated string. */
	memset(recv_buf, '\0', sizeof(recv_buf));
	resultsize = 0;

	while (strstr(recv_buf, CRLF CRLF) == NULL)
	{
		if (resultsize >= sizeof(recv_buf) - 1)
		{
			WLog_ERR(TAG, "HTTP Reply headers too long.");
			return FALSE;
		}

		status = BIO_read(bufferedBio, (BYTE*)recv_buf + resultsize, sizeof(recv_buf) - resultsize - 1);

		if (status < 0)
		{
			/* Error? */
			if (BIO_should_retry(bufferedBio))
			{
				USleep(100);
				continue;
			}

			WLog_ERR(TAG, "Failed reading reply from HTTP proxy (Status %d)", status);
			return FALSE;
		}
		else if (status == 0)
		{
			/* Error? */
			WLog_ERR(TAG, "Failed reading reply from HTTP proxy (BIO_read returned zero)");
			return FALSE;
		}

		resultsize += status;
	}

	/* Extract HTTP status line */
	eol = strchr(recv_buf, '\r');

	if (!eol)
	{
		/* should never happen */
		return FALSE;
	}

	*eol = '\0';
	WLog_INFO(TAG, "HTTP Proxy: %s", recv_buf);

	if (strlen(recv_buf) < 12)
	{
		return FALSE;
	}

	recv_buf[7] = 'X';

	if (strncmp(recv_buf, "HTTP/1.X 200", 12))
		return FALSE;

	return TRUE;
}
Exemple #2
0
BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten)
{
	wStream* s;
	int cbLen;
	int cbChId;
	int first;
	BYTE* buffer;
	UINT32 length;
	UINT32 written;
	rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
	BOOL ret = TRUE;

	if (!channel)
		return FALSE;

	if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
	{
		length = Length;
		buffer = (BYTE *)malloc(length);
		if (!buffer)
		{
			SetLastError(E_OUTOFMEMORY);
			return FALSE;
		}
		CopyMemory(buffer, Buffer, length);

		ret = wts_queue_send_item(channel, buffer, length);
	}
	else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY))
	{
		DEBUG_DVC("drdynvc not ready");
		return FALSE;
	}
	else
	{
		first = TRUE;

		while (Length > 0)
		{
			s = Stream_New(NULL, channel->client->settings->VirtualChannelChunkSize);
			if (!s)
			{
				WLog_ERR(TAG, "Stream_New failed!");
				SetLastError(E_OUTOFMEMORY);
				return FALSE;
			}

			buffer = Stream_Buffer(s);

			Stream_Seek_UINT8(s);
			cbChId = wts_write_variable_uint(s, channel->channelId);

			if (first && (Length > (UINT32) Stream_GetRemainingLength(s)))
			{
				cbLen = wts_write_variable_uint(s, Length);
				buffer[0] = (DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId;
			}
			else
			{
				buffer[0] = (DATA_PDU << 4) | cbChId;
			}

			first = FALSE;
			written = Stream_GetRemainingLength(s);

			if (written > Length)
				written = Length;

			Stream_Write(s, Buffer, written);
			length = Stream_GetPosition(s);
			Stream_Free(s, FALSE);

			Length -= written;
			Buffer += written;

			ret = wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, length);
		}
	}

	if (pBytesWritten)
		*pBytesWritten = Length;

	return ret;
}
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk)
{
	int status;
	UINT error;
	wStream* s = NULL;
	int cbExpertBlobW = 0;
	WCHAR* expertBlobW = NULL;
	int cbRaConnectionStringW = 0;
	WCHAR* raConnectionStringW = NULL;
	REMDESK_CTL_AUTHENTICATE_PDU pdu;

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

	pdu.expertBlob = remdesk->ExpertBlob;
	pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;

	status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1, &raConnectionStringW, 0);

	if (status <= 0)
	{
		WLog_ERR(TAG, "ConvertToUnicode failed!");
		return ERROR_INTERNAL_ERROR;
	}

	cbRaConnectionStringW = status * 2;

	status = ConvertToUnicode(CP_UTF8, 0, pdu.expertBlob, -1, &expertBlobW, 0);

	if (status <= 0)
	{
		WLog_ERR(TAG, "ConvertToUnicode failed!");
		error = ERROR_INTERNAL_ERROR;
		goto out;
	}

	cbExpertBlobW = status * 2;

	remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_AUTHENTICATE,
			cbRaConnectionStringW + cbExpertBlobW);

	s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
	if (!s)
	{
		WLog_ERR(TAG, "Stream_New failed!");
		error = CHANNEL_RC_NO_MEMORY;
		goto out;
	}

	remdesk_write_ctl_header(s, &(pdu.ctlHeader));

	Stream_Write(s, (BYTE*) raConnectionStringW, cbRaConnectionStringW);
	Stream_Write(s, (BYTE*) expertBlobW, cbExpertBlobW);

	Stream_SealLength(s);

	if ((error = remdesk_virtual_channel_write(remdesk, s)))
		WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error);

out:
	free(raConnectionStringW);
	free(expertBlobW);
	if (error != CHANNEL_RC_OK)
		Stream_Free(s, TRUE);

	return error;
}
Exemple #4
0
static BOOL rdp_client_establish_keys(rdpRdp* rdp)
{
	BYTE* mod;
	BYTE* exp;
	wStream* s;
	UINT32 length;
	UINT32 key_len;
	BYTE *crypt_client_random = NULL;
	BOOL ret = FALSE;
	int status = 0;

	if (!rdp->settings->DisableEncryption)
	{
		/* no RDP encryption */
		return TRUE;
	}

	/* encrypt client random */

	if (rdp->settings->ClientRandom)
		free(rdp->settings->ClientRandom);

	rdp->settings->ClientRandom = malloc(CLIENT_RANDOM_LENGTH);

	if (!rdp->settings->ClientRandom)
		return FALSE;


	crypto_nonce(rdp->settings->ClientRandom, CLIENT_RANDOM_LENGTH);
	key_len = rdp->settings->RdpServerCertificate->cert_info.ModulusLength;
	mod = rdp->settings->RdpServerCertificate->cert_info.Modulus;
	exp = rdp->settings->RdpServerCertificate->cert_info.exponent;
	/*
	 * client random must be (bitlen / 8) + 8 - see [MS-RDPBCGR] 5.3.4.1
	 * for details
	 */
	crypt_client_random = calloc(1,key_len+8);
	if (!crypt_client_random)
		return FALSE;
	crypto_rsa_public_encrypt(rdp->settings->ClientRandom, CLIENT_RANDOM_LENGTH, key_len, mod, exp, crypt_client_random);

	/* send crypt client random to server */
	length = RDP_PACKET_HEADER_MAX_LENGTH + RDP_SECURITY_HEADER_LENGTH + 4 + key_len + 8;
	s = Stream_New(NULL, length);

	rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
	rdp_write_security_header(s, SEC_EXCHANGE_PKT | SEC_LICENSE_ENCRYPT_SC);
	length = key_len + 8;

	Stream_Write_UINT32(s, length);
	Stream_Write(s, crypt_client_random, length);
	Stream_SealLength(s);

	status = transport_write(rdp->mcs->transport, s);
	Stream_Free(s, TRUE);

	if (status < 0)
		goto end;

	/* now calculate encrypt / decrypt and update keys */
	if (!security_establish_keys(rdp->settings->ClientRandom, rdp))
		goto end;

	rdp->do_crypt = TRUE;

	if (rdp->settings->SaltedChecksum)
		rdp->do_secure_checksum = 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)
		{
			DEBUG_WARN( "%s: unable to allocate des3 encrypt key\n", __FUNCTION__);
			goto end;
		}
		rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec);
		if (!rdp->fips_decrypt)
		{
			DEBUG_WARN( "%s: unable to allocate des3 decrypt key\n", __FUNCTION__);
			goto end;
		}

		rdp->fips_hmac = crypto_hmac_new();
		if (!rdp->fips_hmac)
		{
			DEBUG_WARN( "%s: unable to allocate fips hmac\n", __FUNCTION__);
			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)
	{
		DEBUG_WARN( "%s: unable to allocate rc4 decrypt key\n", __FUNCTION__);
		goto end;
	}

	rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len);
	if (!rdp->rc4_encrypt_key)
	{
		DEBUG_WARN( "%s: unable to allocate rc4 encrypt key\n", __FUNCTION__);
		goto end;
	}
	ret = TRUE;
end:
	if (crypt_client_random)
		free(crypt_client_random);
	return ret;
}
Exemple #5
0
static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg)
{
	wStream* data;
	wMessage message;
	UINT error = CHANNEL_RC_OK;
	drdynvcPlugin* drdynvc = (drdynvcPlugin*) arg;

	if (!drdynvc)
	{
		ExitThread((DWORD) CHANNEL_RC_BAD_CHANNEL_HANDLE);
		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
	}

	while (1)
	{
		if (!MessageQueue_Wait(drdynvc->queue))
		{
			WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_Wait failed!");
			error = ERROR_INTERNAL_ERROR;
			break;
		}

		if (!MessageQueue_Peek(drdynvc->queue, &message, TRUE))
		{
			WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_Peek failed!");
			error = ERROR_INTERNAL_ERROR;
			break;
		}

		if (message.id == WMQ_QUIT)
			break;

		if (message.id == 0)
		{
			data = (wStream*) message.wParam;

			if ((error = drdynvc_order_recv(drdynvc, data)))
			{
				Stream_Free(data, TRUE);
				WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_order_recv failed with error %"PRIu32"!", error);
				break;
			}

			Stream_Free(data, TRUE);
		}
	}

	{
		/* Disconnect remaining dynamic channels that the server did not.
		* This is required to properly shut down channels by calling the appropriate
		* event handlers. */
		DVCMAN* drdynvcMgr = (DVCMAN*)drdynvc->channel_mgr;

		while (ArrayList_Count(drdynvcMgr->channels) > 0)
		{
			IWTSVirtualChannel* channel = (IWTSVirtualChannel*)
			                              ArrayList_GetItem(drdynvcMgr->channels, 0);
			const UINT32 ChannelId = drdynvc->channel_mgr->GetChannelId(channel);
			dvcman_close_channel(drdynvc->channel_mgr, ChannelId);
		}
	}

	if (error && drdynvc->rdpcontext)
		setChannelError(drdynvc->rdpcontext, error,
		                "drdynvc_virtual_channel_client_thread reported an error");

	ExitThread((DWORD) error);
	return error;
}
Exemple #6
0
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;
}
Exemple #7
0
static void rpc_pdu_free(RPC_PDU* pdu)
{
	Stream_Free(pdu->s, TRUE);
	free(pdu);
}
Exemple #8
0
static void* echo_server_thread_func(void* arg)
{
	wStream* s;
	void* buffer;
	DWORD nCount;
	HANDLE events[8];
	BOOL ready = FALSE;
	HANDLE ChannelEvent;
	DWORD BytesReturned = 0;
	echo_server* echo = (echo_server*) arg;
	UINT error;
    DWORD status;

	if ((error = echo_server_open_channel(echo)))
	{
		IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
		WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error);
		goto out;
	}

	buffer = NULL;
	BytesReturned = 0;
	ChannelEvent = NULL;

	if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
	{
		if (BytesReturned == sizeof(HANDLE))
			CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));

		WTSFreeMemory(buffer);
	}

	nCount = 0;
	events[nCount++] = echo->stopEvent;
	events[nCount++] = ChannelEvent;

	/* Wait for the client to confirm that the Graphics Pipeline dynamic channel is ready */

	while (1)
	{
        status = WaitForMultipleObjects(nCount, events, FALSE, 100);

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

		if (status == WAIT_OBJECT_0)
		{
			IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_CLOSED);
			if (error)
				WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
			break;
		}

		if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE)
		{
			IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_ERROR);
			if (error)
				WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
			break;
		}

		ready = *((BOOL*) buffer);

		WTSFreeMemory(buffer);

		if (ready)
		{
			IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_OK);
			if (error)
				WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
			break;
		}
	}

	s = Stream_New(NULL, 4096);
	if (!s)
	{
		WLog_ERR(TAG, "Stream_New failed!");
		WTSVirtualChannelClose(echo->echo_channel);
		ExitThread((DWORD)ERROR_NOT_ENOUGH_MEMORY);
		return NULL;
	}

	while (ready)
	{
        status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);

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

        if (status == WAIT_OBJECT_0)
			break;

		Stream_SetPosition(s, 0);

		WTSVirtualChannelRead(echo->echo_channel, 0, NULL, 0, &BytesReturned);
		if (BytesReturned < 1)
			continue;
		if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
		{
			WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
			error = CHANNEL_RC_NO_MEMORY;
			break;
		}

		if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR) Stream_Buffer(s),
			(ULONG) Stream_Capacity(s), &BytesReturned) == FALSE)
		{
			WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
			error = ERROR_INTERNAL_ERROR;
			break;
		}

		IFCALLRET(echo->context.Response, error, &echo->context, (BYTE *) Stream_Buffer(s), BytesReturned);
		if (error)
		{
			WLog_ERR(TAG, "Response failed with error %lu!", error);
			break;
		}
	}
	Stream_Free(s, TRUE);
	WTSVirtualChannelClose(echo->echo_channel);
	echo->echo_channel = NULL;
out:
	if (error && echo->context.rdpcontext)
		setChannelError(echo->context.rdpcontext, error, "echo_server_thread_func reported an error");

	ExitThread((DWORD)error);
	return NULL;
}
Exemple #9
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
{
	UINT error;
	wStream* s;
	UINT16 index;
	RDPGFX_PLUGIN* gfx;
	RDPGFX_HEADER header;
	RDPGFX_CAPSET* capsSet;
	RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS];
	RDPGFX_CAPS_ADVERTISE_PDU pdu;
	gfx = (RDPGFX_PLUGIN*) callback->plugin;
	header.flags = 0;
	header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;
	pdu.capsSetCount = 0;
	pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
	capsSet = &capsSets[pdu.capsSetCount++];
	capsSet->version = RDPGFX_CAPVERSION_8;
	capsSet->flags = 0;

	if (gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;

	/* in CAPVERSION_8 the spec says that we should not have both
	 * thinclient and smallcache (and thinclient implies a small cache)
	 */
	if (gfx->SmallCache && !gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

	capsSet = &capsSets[pdu.capsSetCount++];
	capsSet->version = RDPGFX_CAPVERSION_81;
	capsSet->flags = 0;

	if (gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;

	if (gfx->SmallCache)
		capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

#ifdef WITH_GFX_H264
	if (gfx->H264)
		capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED;
#endif

	if (!gfx->H264 || gfx->AVC444)
	{
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_10;
		capsSet->flags = 0;

		if (gfx->SmallCache)
			capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

#ifdef WITH_GFX_H264
		if (!gfx->AVC444)
			capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
#else
		capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
#endif

		capsSets[pdu.capsSetCount] = *capsSet;
		capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102;
		capsSets[pdu.capsSetCount] = *capsSet;
		capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_103;
	}

	header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE);
	WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu %"PRIu16"", pdu.capsSetCount);
	s = Stream_New(NULL, header.pduLength);

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

	if ((error = rdpgfx_write_header(s, &header)))
		goto fail;

	/* RDPGFX_CAPS_ADVERTISE_PDU */
	Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */

	for (index = 0; index < pdu.capsSetCount; index++)
	{
		capsSet = &(pdu.capsSets[index]);
		Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */
		Stream_Write_UINT32(s, 4); /* capsDataLength (4 bytes) */
		Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */
	}

	Stream_SealLength(s);
	error = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s),
	                                 Stream_Buffer(s), NULL);
fail:
	Stream_Free(s, TRUE);
	return error;
}
Exemple #10
0
static UINT remmina_rdp_cliprdr_server_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
	TRACE_CALL(__func__);

	UINT8* data;
	size_t size;
	rfContext* rfi;
	RemminaProtocolWidget* gp;
	rfClipboard* clipboard;
	GdkPixbufLoader *pixbuf;
	gpointer output = NULL;
	RemminaPluginRdpUiObject *ui;

	clipboard = (rfClipboard*)context->custom;
	gp = clipboard->rfi->protocol_widget;
	rfi = GET_PLUGIN_DATA(gp);

	data = formatDataResponse->requestedFormatData;
	size = formatDataResponse->dataLen;

	// formatDataResponse->requestedFormatData is allocated
	//  by freerdp and freed after returning from this callback function.
	//  So we must make a copy if we need to preserve it

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

		case CF_TEXT:
		case CB_FORMAT_HTML:
		{
			output = (gpointer)calloc(1, size + 1);
			if (output) {
				memcpy(output, data, size);
				crlf2lf(output, &size);
			}
			break;
		}

		case CF_DIBV5:
		case CF_DIB:
		{
			wStream* s;
			UINT32 offset;
			GError *perr;
			BITMAPINFOHEADER* pbi;
			BITMAPV5HEADER* pbi5;

			pbi = (BITMAPINFOHEADER*)data;

			// offset calculation inspired by http://downloads.poolelan.com/MSDN/MSDNLibrary6/Disk1/Samples/VC/OS/WindowsXP/GetImage/BitmapUtil.cpp
			offset = 14 + pbi->biSize;
			if (pbi->biClrUsed != 0)
				offset += sizeof(RGBQUAD) * pbi->biClrUsed;
			else if (pbi->biBitCount <= 8)
				offset += sizeof(RGBQUAD) * (1 << pbi->biBitCount);
			if (pbi->biSize == sizeof(BITMAPINFOHEADER)) {
				if (pbi->biCompression == 3)         // BI_BITFIELDS is 3
					offset += 12;
			} else if (pbi->biSize >= sizeof(BITMAPV5HEADER)) {
				pbi5 = (BITMAPV5HEADER*)pbi;
				if (pbi5->bV5ProfileData <= offset)
					offset += pbi5->bV5ProfileSize;
			}
			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();
			perr = NULL;
			if ( !gdk_pixbuf_loader_write(pixbuf, data, size, &perr) ) {
				remmina_plugin_service->log_printf("[RDP] rdp_cliprdr: gdk_pixbuf_loader_write() returned error %s\n", perr->message);
			}else  {
				if ( !gdk_pixbuf_loader_close(pixbuf, &perr) ) {
					remmina_plugin_service->log_printf("[RDP] rdp_cliprdr: gdk_pixbuf_loader_close() returned error %s\n", perr->message);
					perr = 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;
		}
		}
	}

	pthread_mutex_lock(&clipboard->transfer_clip_mutex);
	pthread_cond_signal(&clipboard->transfer_clip_cond);
	if ( clipboard->srv_clip_data_wait == SCDW_BUSY_WAIT ) {
		clipboard->srv_data = output;
	}else  {
		// Clipboard data arrived from server when we are not busywaiting.
		// Just put it on the local clipboard

		ui = g_new0(RemminaPluginRdpUiObject, 1);
		ui->type = REMMINA_RDP_UI_CLIPBOARD;
		ui->clipboard.clipboard = clipboard;
		ui->clipboard.type = REMMINA_RDP_UI_CLIPBOARD_SET_CONTENT;
		ui->clipboard.data = output;
		ui->clipboard.format = clipboard->format;
		remmina_rdp_event_queue_ui_sync_retint(gp, ui);

		clipboard->srv_clip_data_wait = SCDW_NONE;

	}
	pthread_mutex_unlock(&clipboard->transfer_clip_mutex);

	return CHANNEL_RC_OK;
}
Exemple #11
0
wStream* http_request_write(HttpContext* context, HttpRequest* request)
{
	wStream* s;

	if (!context || !request)
		return NULL;

	s = Stream_New(NULL, 1024);

	if (!s)
		return NULL;

	if (!http_encode_header_line(s, request->Method, request->URI) ||
	    !http_encode_body_line(s, "Cache-Control", context->CacheControl) ||
	    !http_encode_body_line(s, "Connection", context->Connection) ||
	    !http_encode_body_line(s, "Pragma", context->Pragma) ||
	    !http_encode_body_line(s, "Accept", context->Accept) ||
	    !http_encode_body_line(s, "User-Agent", context->UserAgent) ||
	    !http_encode_body_line(s, "Host", context->Host))
		goto fail;

	if (context->RdgConnectionId)
	{
		if (!http_encode_body_line(s, "RDG-Connection-Id", context->RdgConnectionId))
			goto fail;
	}

	if (context->RdgAuthScheme)
	{
		if (!http_encode_body_line(s, "RDG-Auth-Scheme", context->RdgAuthScheme))
			goto fail;
	}

	if (request->TransferEncoding)
	{
		if (!http_encode_body_line(s, "Transfer-Encoding", request->TransferEncoding))
			goto fail;
	}
	else
	{
		if (!http_encode_content_length_line(s, request->ContentLength))
			goto fail;
	}

	if (request->Authorization)
	{
		if (!http_encode_body_line(s, "Authorization", request->Authorization))
			goto fail;
	}
	else if (request->AuthScheme && request->AuthParam)
	{
		if (!http_encode_authorization_line(s, request->AuthScheme, request->AuthParam))
			goto fail;
	}

	Stream_Write(s, "\r\n", 2);
	Stream_SealLength(s);
	return s;
fail:
	Stream_Free(s, TRUE);
	return NULL;
}
Exemple #12
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
{
	UINT error;
	wStream* s;
	UINT16 index;
	RDPGFX_PLUGIN* gfx;
	RDPGFX_HEADER header;
	RDPGFX_CAPSET* capsSet;
	RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS];
	RDPGFX_CAPS_ADVERTISE_PDU pdu;
	gfx = (RDPGFX_PLUGIN*) callback->plugin;
	header.flags = 0;
	header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;
	pdu.capsSetCount = 0;
	pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
	capsSet = &capsSets[pdu.capsSetCount++];
	capsSet->version = RDPGFX_CAPVERSION_8;
	capsSet->flags = 0;

	if (gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;

	if (gfx->SmallCache)
		capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

	capsSet = &capsSets[pdu.capsSetCount++];
	capsSet->version = RDPGFX_CAPVERSION_81;
	capsSet->flags = 0;

	if (gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;

	if (gfx->SmallCache)
		capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

	if (gfx->H264)
		capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED;

	if (gfx->AVC444)
	{
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_10;
		capsSet->flags = 0;

		if (gfx->SmallCache)
			capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

		if (!gfx->H264)
			capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;

		capsSets[pdu.capsSetCount] = *capsSet;
		capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102;
	}

	header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount *
	                   RDPGFX_CAPSET_SIZE);
	WLog_DBG(TAG, "SendCapsAdvertisePdu %d", pdu.capsSetCount);
	s = Stream_New(NULL, header.pduLength);

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

	if ((error = rdpgfx_write_header(s, &header)))
	{
		WLog_ERR(TAG, "rdpgfx_write_header failed with error %u!", error);
		return error;
	}

	/* RDPGFX_CAPS_ADVERTISE_PDU */
	Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */

	for (index = 0; index < pdu.capsSetCount; index++)
	{
		capsSet = &(pdu.capsSets[index]);
		Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */
		Stream_Write_UINT32(s, 4); /* capsDataLength (4 bytes) */
		Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */
	}

	Stream_SealLength(s);
	error = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s),
	                                 Stream_Buffer(s), NULL);
	Stream_Free(s, TRUE);
	return error;
}
Exemple #13
0
static void* remdesk_server_thread(void* arg)
{
	wStream* s;
	DWORD status;
	DWORD nCount;
	void* buffer;
	UINT32* pHeader;
	UINT32 PduLength;
	HANDLE events[8];
	HANDLE ChannelEvent;
	DWORD BytesReturned;
	RemdeskServerContext* context;
	UINT error;
	context = (RemdeskServerContext*) arg;

	buffer = NULL;
	BytesReturned = 0;
	ChannelEvent = NULL;
	s = Stream_New(NULL, 4096);

	if (!s)
	{
		WLog_ERR(TAG, "Stream_New failed!");
		error = CHANNEL_RC_NO_MEMORY;
		goto out;
	}

	if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
	                           &buffer, &BytesReturned) == TRUE)
	{
		if (BytesReturned == sizeof(HANDLE))
			CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));

		WTSFreeMemory(buffer);
	}
	else
	{
		WLog_ERR(TAG, "WTSVirtualChannelQuery failed!");
		error = ERROR_INTERNAL_ERROR;
		goto out;
	}

	nCount = 0;
	events[nCount++] = ChannelEvent;
	events[nCount++] = context->priv->StopEvent;

	if ((error = remdesk_send_ctl_version_info_pdu(context)))
	{
		WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %"PRIu32"!",
		         error);
		goto out;
	}

	while (1)
	{
		status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);

		if (status == WAIT_FAILED)
		{
			error = GetLastError();
			WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error);
			break;
		}

		status = WaitForSingleObject(context->priv->StopEvent, 0);

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

		if (status == WAIT_OBJECT_0)
		{
			break;
		}

		if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
		                          (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
		{
			if (BytesReturned)
				Stream_Seek(s, BytesReturned);
		}
		else
		{
			if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
			{
				WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
				error = CHANNEL_RC_NO_MEMORY;
				break;
			}
		}

		if (Stream_GetPosition(s) >= 8)
		{
			pHeader = (UINT32*) Stream_Buffer(s);
			PduLength = pHeader[0] + pHeader[1] + 8;

			if (PduLength >= Stream_GetPosition(s))
			{
				Stream_SealLength(s);
				Stream_SetPosition(s, 0);

				if ((error = remdesk_server_receive_pdu(context, s)))
				{
					WLog_ERR(TAG, "remdesk_server_receive_pdu failed with error %"PRIu32"!", error);
					break;
				}

				Stream_SetPosition(s, 0);
			}
		}
	}

	Stream_Free(s, TRUE);
out:

	if (error && context->rdpcontext)
		setChannelError(context->rdpcontext, error,
		                "remdesk_server_thread reported an error");

	ExitThread((DWORD)error);
	return NULL;
}
Exemple #14
0
static CLIPRDR_FORMAT* xf_cliprdr_parse_server_format_list(BYTE* data,
        size_t length, UINT32* numFormats)
{
	UINT32 i;
	wStream* s = NULL;
	CLIPRDR_FORMAT* formats = NULL;

	if (!(s = Stream_New(data, length)))
	{
		WLog_ERR(TAG, "failed to allocate stream for parsing serialized format list");
		goto error;
	}

	if (Stream_GetRemainingLength(s) < sizeof(UINT32))
	{
		WLog_ERR(TAG, "too short serialized format list");
		goto error;
	}

	Stream_Read_UINT32(s, *numFormats);

	if (*numFormats > MAX_CLIPBOARD_FORMATS)
	{
		WLog_ERR(TAG, "unexpectedly large number of formats: %"PRIu32"", *numFormats);
		goto error;
	}

	if (!(formats = (CLIPRDR_FORMAT*) calloc(*numFormats, sizeof(CLIPRDR_FORMAT))))
	{
		WLog_ERR(TAG, "failed to allocate format list");
		goto error;
	}

	for (i = 0; i < *numFormats; i++)
	{
		const char* formatName = NULL;
		size_t formatNameLength = 0;

		if (Stream_GetRemainingLength(s) < sizeof(UINT32))
		{
			WLog_ERR(TAG, "unexpected end of serialized format list");
			goto error;
		}

		Stream_Read_UINT32(s, formats[i].formatId);
		formatName = (const char*) Stream_Pointer(s);
		formatNameLength = strnlen(formatName, Stream_GetRemainingLength(s));

		if (formatNameLength == Stream_GetRemainingLength(s))
		{
			WLog_ERR(TAG, "missing terminating null byte, %"PRIuz" bytes left to read",
			         formatNameLength);
			goto error;
		}

		formats[i].formatName = strndup(formatName, formatNameLength);
		Stream_Seek(s, formatNameLength + 1);
	}

	Stream_Free(s, FALSE);
	return formats;
error:
	Stream_Free(s, FALSE);
	free(formats);
	*numFormats = 0;
	return NULL;
}
Exemple #15
0
BOOL nego_send_negotiation_response(rdpNego* nego)
{
	int length;
	int bm, em;
	BOOL status;
	wStream* s;
	BYTE flags;
	rdpSettings* settings;

	status = TRUE;
	settings = nego->transport->settings;

	s = Stream_New(NULL, 512);
	if (!s)
		return FALSE;

	length = TPDU_CONNECTION_CONFIRM_LENGTH;
	bm = Stream_GetPosition(s);
	Stream_Seek(s, length);

	if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)
	{
		UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO);
		flags = 0;

		Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE);
		Stream_Write_UINT8(s, flags); /* flags */
		Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */

		Stream_Write_UINT32(s, errorCode);
		length += 8;
		status = FALSE;
	}
	else
	{
		flags = EXTENDED_CLIENT_DATA_SUPPORTED;

		if (settings->SupportGraphicsPipeline)
			flags |= DYNVC_GFX_PROTOCOL_SUPPORTED;

		/* RDP_NEG_DATA must be present for TLS, NLA, and RDP */
		Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
		Stream_Write_UINT8(s, flags); /* flags */
		Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
		Stream_Write_UINT32(s, nego->SelectedProtocol); /* selectedProtocol */
		length += 8;
	}

	em = Stream_GetPosition(s);
	Stream_SetPosition(s, bm);
	tpkt_write_header(s, length);
	tpdu_write_connection_confirm(s, length - 5);
	Stream_SetPosition(s, em);

	Stream_SealLength(s);

	if (transport_write(nego->transport, s) < 0)
	{
		Stream_Free(s, TRUE);
		return FALSE;
	}

	Stream_Free(s, TRUE);

	if (status)
	{
		/* update settings with negotiated protocol security */
		settings->RequestedProtocols = nego->RequestedProtocols;
		settings->SelectedProtocol = nego->SelectedProtocol;

		if (settings->SelectedProtocol == PROTOCOL_RDP)
		{
			settings->TlsSecurity = FALSE;
			settings->NlaSecurity = FALSE;
			settings->RdpSecurity = TRUE;
			settings->UseRdpSecurityLayer = TRUE;

			if (settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE)
			{
				/**
				 * If the server implementation did not explicitely set a
				 * encryption level we default to client compatible
				 */
				settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
			}

			if (settings->LocalConnection)
			{
				/**
				 * Note: This hack was firstly introduced in commit 95f5e115 to
				 * disable the unnecessary encryption with peers connecting to
				 * 127.0.0.1 or local unix sockets.
				 * This also affects connections via port tunnels! (e.g. ssh -L)
				 */
				WLog_INFO(TAG, "Turning off encryption for local peer with standard rdp security");
				settings->UseRdpSecurityLayer = FALSE;
				settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
			}

			if (!settings->RdpServerRsaKey && !settings->RdpKeyFile)
			{
				WLog_ERR(TAG, "Missing server certificate");
				return FALSE;
			}
		}
		else if (settings->SelectedProtocol == PROTOCOL_TLS)
		{
			settings->TlsSecurity = TRUE;
			settings->NlaSecurity = FALSE;
			settings->RdpSecurity = FALSE;
			settings->UseRdpSecurityLayer = FALSE;
			settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
		}
		else if (settings->SelectedProtocol == PROTOCOL_NLA)
		{
			settings->TlsSecurity = TRUE;
			settings->NlaSecurity = TRUE;
			settings->RdpSecurity = FALSE;
			settings->UseRdpSecurityLayer = FALSE;
			settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
		}
	}

	return status;
}
Exemple #16
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
{
	char* name;
	char* path;
	int i;
	size_t length;
	RDPDR_PARALLEL* device;
	PARALLEL_DEVICE* parallel;
	UINT error;
	device = (RDPDR_PARALLEL*) pEntryPoints->device;
	name = device->Name;
	path = device->Path;

	if (!name || (name[0] == '*'))
	{
		/* TODO: implement auto detection of parallel ports */
		return CHANNEL_RC_OK;
	}

	if (name[0] && path[0])
	{
		parallel = (PARALLEL_DEVICE*) calloc(1, sizeof(PARALLEL_DEVICE));

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

		parallel->device.type = RDPDR_DTYP_PARALLEL;
		parallel->device.name = name;
		parallel->device.IRPRequest = parallel_irp_request;
		parallel->device.Free = parallel_free;
		parallel->rdpcontext = pEntryPoints->rdpcontext;
		length = strlen(name);
		parallel->device.data = Stream_New(NULL, length + 1);

		if (!parallel->device.data)
		{
			WLog_ERR(TAG, "Stream_New failed!");
			error = CHANNEL_RC_NO_MEMORY;
			goto error_out;
		}

		for (i = 0; i <= length; i++)
			Stream_Write_UINT8(parallel->device.data, name[i] < 0 ? '_' : name[i]);

		parallel->path = path;
		parallel->queue = MessageQueue_New(NULL);

		if (!parallel->queue)
		{
			WLog_ERR(TAG, "MessageQueue_New failed!");
			error = CHANNEL_RC_NO_MEMORY;
			goto error_out;
		}

		if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
		             (DEVICE*) parallel)))
		{
			WLog_ERR(TAG, "RegisterDevice failed with error %u!", error);
			goto error_out;
		}

		if (!(parallel->thread = CreateThread(NULL, 0,
		                                      (LPTHREAD_START_ROUTINE) parallel_thread_func, (void*) parallel, 0, NULL)))
		{
			WLog_ERR(TAG, "CreateThread failed!");
			error = ERROR_INTERNAL_ERROR;
			goto error_out;
		}
	}

	return CHANNEL_RC_OK;
error_out:
	MessageQueue_Free(parallel->queue);
	Stream_Free(parallel->device.data, TRUE);
	free(parallel);
	return error;
}
Exemple #17
0
static void rail_process_receive(rdpSvcPlugin* plugin, wStream* s)
{
	railPlugin* rail = (railPlugin*) plugin;
	rail_order_recv(rail->rail_order, s);
	Stream_Free(s, TRUE);
}
Exemple #18
0
static DWORD WINAPI audin_server_thread_func(LPVOID arg)
{
	wStream* s;
	void* buffer;
	DWORD nCount;
	BYTE MessageId;
	HANDLE events[8];
	BOOL ready = FALSE;
	HANDLE ChannelEvent;
	DWORD BytesReturned = 0;
	audin_server* audin = (audin_server*) arg;
	UINT error = CHANNEL_RC_OK;
	DWORD status;
	buffer = NULL;
	BytesReturned = 0;
	ChannelEvent = NULL;

	if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualEventHandle, &buffer,
	                           &BytesReturned) == TRUE)
	{
		if (BytesReturned == sizeof(HANDLE))
			CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));

		WTSFreeMemory(buffer);
	}
	else
	{
		WLog_ERR(TAG, "WTSVirtualChannelQuery failed");
		error = ERROR_INTERNAL_ERROR;
		goto out;
	}

	nCount = 0;
	events[nCount++] = audin->stopEvent;
	events[nCount++] = ChannelEvent;

	/* Wait for the client to confirm that the Audio Input dynamic channel is ready */

	while (1)
	{
		if ((status = WaitForMultipleObjects(nCount, events, FALSE,
		                                     100)) == WAIT_OBJECT_0)
			goto out;

		if (status == WAIT_FAILED)
		{
			error = GetLastError();
			WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error);
			goto out;
		}

		if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady,
		                           &buffer, &BytesReturned) == FALSE)
		{
			WLog_ERR(TAG, "WTSVirtualChannelQuery failed");
			error = ERROR_INTERNAL_ERROR;
			goto out;
		}

		ready = *((BOOL*) buffer);
		WTSFreeMemory(buffer);

		if (ready)
			break;
	}

	s = Stream_New(NULL, 4096);

	if (!s)
	{
		WLog_ERR(TAG, "Stream_New failed!");
		error = CHANNEL_RC_NO_MEMORY;
		goto out;
	}

	if (ready)
	{
		if ((error = audin_server_send_version(audin, s)))
		{
			WLog_ERR(TAG, "audin_server_send_version failed with error %"PRIu32"!", error);
			goto out_capacity;
		}
	}

	while (ready)
	{
		if ((status = WaitForMultipleObjects(nCount, events, FALSE,
		                                     INFINITE)) == WAIT_OBJECT_0)
			break;

		if (status == WAIT_FAILED)
		{
			error = GetLastError();
			WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error);
			goto out;
		}

		Stream_SetPosition(s, 0);

		if (!WTSVirtualChannelRead(audin->audin_channel, 0, NULL, 0, &BytesReturned))
		{
			WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
			error = ERROR_INTERNAL_ERROR;
			break;
		}

		if (BytesReturned < 1)
			continue;

		if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
			break;

		if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
		                          Stream_Capacity(s), &BytesReturned) == FALSE)
		{
			WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
			error = ERROR_INTERNAL_ERROR;
			break;
		}

		Stream_Read_UINT8(s, MessageId);
		BytesReturned--;

		switch (MessageId)
		{
			case MSG_SNDIN_VERSION:
				if ((error = audin_server_recv_version(audin, s, BytesReturned)))
				{
					WLog_ERR(TAG, "audin_server_recv_version failed with error %"PRIu32"!", error);
					goto out_capacity;
				}

				if ((error = audin_server_send_formats(audin, s)))
				{
					WLog_ERR(TAG, "audin_server_send_formats failed with error %"PRIu32"!", error);
					goto out_capacity;
				}

				break;

			case MSG_SNDIN_FORMATS:
				if ((error = audin_server_recv_formats(audin, s, BytesReturned)))
				{
					WLog_ERR(TAG, "audin_server_recv_formats failed with error %"PRIu32"!", error);
					goto out_capacity;
				}

				if ((error = audin_server_send_open(audin, s)))
				{
					WLog_ERR(TAG, "audin_server_send_open failed with error %"PRIu32"!", error);
					goto out_capacity;
				}

				break;

			case MSG_SNDIN_OPEN_REPLY:
				if ((error = audin_server_recv_open_reply(audin, s, BytesReturned)))
				{
					WLog_ERR(TAG, "audin_server_recv_open_reply failed with error %"PRIu32"!", error);
					goto out_capacity;
				}

				break;

			case MSG_SNDIN_DATA_INCOMING:
				break;

			case MSG_SNDIN_DATA:
				if ((error = audin_server_recv_data(audin, s, BytesReturned)))
				{
					WLog_ERR(TAG, "audin_server_recv_data failed with error %"PRIu32"!", error);
					goto out_capacity;
				};

				break;

			case MSG_SNDIN_FORMATCHANGE:
				break;

			default:
				WLog_ERR(TAG, "audin_server_thread_func: unknown MessageId %"PRIu8"", MessageId);
				break;
		}
	}

out_capacity:
	Stream_Free(s, TRUE);
out:
	WTSVirtualChannelClose(audin->audin_channel);
	audin->audin_channel = NULL;

	if (error && audin->context.rdpcontext)
		setChannelError(audin->context.rdpcontext, error,
		                "audin_server_thread_func reported an error");

	ExitThread(error);
	return error;
}
Exemple #19
0
static void* encomsp_server_thread(void* arg)
{
	wStream* s;
	DWORD nCount;
	void* buffer;
	HANDLE events[8];
	HANDLE ChannelEvent;
	DWORD BytesReturned;
	ENCOMSP_ORDER_HEADER* header;
	EncomspServerContext* context;
	UINT error = CHANNEL_RC_OK;
	DWORD status;
	context = (EncomspServerContext*) arg;
	freerdp_channel_init_thread_context(context->rdpcontext);
	buffer = NULL;
	BytesReturned = 0;
	ChannelEvent = NULL;
	s = Stream_New(NULL, 4096);

	if (!s)
	{
		WLog_ERR(TAG, "Stream_New failed!");
		error = CHANNEL_RC_NO_MEMORY;
		goto out;
	}

	if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
	                           &buffer, &BytesReturned) == TRUE)
	{
		if (BytesReturned == sizeof(HANDLE))
			CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));

		WTSFreeMemory(buffer);
	}

	nCount = 0;
	events[nCount++] = ChannelEvent;
	events[nCount++] = context->priv->StopEvent;

	while (1)
	{
		status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);

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

		status = WaitForSingleObject(context->priv->StopEvent, 0);

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

		if (status == WAIT_OBJECT_0)
		{
			break;
		}

		WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned);

		if (BytesReturned < 1)
			continue;

		if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
		{
			WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
			error = CHANNEL_RC_NO_MEMORY;
			break;
		}

		if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
		                           (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
		{
			WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
			error = ERROR_INTERNAL_ERROR;
			break;
		}

		if (Stream_GetPosition(s) >= ENCOMSP_ORDER_HEADER_SIZE)
		{
			header = (ENCOMSP_ORDER_HEADER*) Stream_Buffer(s);

			if (header->Length >= Stream_GetPosition(s))
			{
				Stream_SealLength(s);
				Stream_SetPosition(s, 0);

				if ((error = encomsp_server_receive_pdu(context, s)))
				{
					WLog_ERR(TAG, "encomsp_server_receive_pdu failed with error %lu!", error);
					break;
				}

				Stream_SetPosition(s, 0);
			}
		}
	}

	Stream_Free(s, TRUE);
out:

	if (error && context->rdpcontext)
		setChannelError(context->rdpcontext, error,
		                "encomsp_server_thread reported an error");

	ExitThread((DWORD)error);
	return NULL;
}
Exemple #20
0
int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors)
{
	int status;
	wStream* s;
	UINT32 type;
	UINT32 index;
	UINT32 length;
	DISP_PLUGIN* disp;
	UINT32 MonitorLayoutSize;

	disp = (DISP_PLUGIN*) callback->plugin;

	MonitorLayoutSize = 40;

	length = 8 + 8 + (NumMonitors * MonitorLayoutSize);

	type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT;

	s = Stream_New(NULL, length);

	Stream_Write_UINT32(s, type); /* Type (4 bytes) */
	Stream_Write_UINT32(s, length); /* Length (4 bytes) */

	if (NumMonitors > disp->MaxNumMonitors)
		NumMonitors = disp->MaxNumMonitors;

	Stream_Write_UINT32(s, MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */

	Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */

	//WLog_ERR(TAG,  "NumMonitors: %d\n", NumMonitors);

	for (index = 0; index < NumMonitors; index++)
	{
		Monitors[index].Width -= (Monitors[index].Width % 2);

		if (Monitors[index].Width < 200)
			Monitors[index].Width = 200;

		if (Monitors[index].Width > 8192)
			Monitors[index].Width = 8192;

		if (Monitors[index].Width % 2)
			Monitors[index].Width++;

		if (Monitors[index].Height < 200)
			Monitors[index].Height = 200;

		if (Monitors[index].Height > 8192)
			Monitors[index].Height = 8192;

		Stream_Write_UINT32(s, Monitors[index].Flags); /* Flags (4 bytes) */
		Stream_Write_UINT32(s, Monitors[index].Left); /* Left (4 bytes) */
		Stream_Write_UINT32(s, Monitors[index].Top); /* Top (4 bytes) */
		Stream_Write_UINT32(s, Monitors[index].Width); /* Width (4 bytes) */
		Stream_Write_UINT32(s, Monitors[index].Height); /* Height (4 bytes) */
		Stream_Write_UINT32(s, Monitors[index].PhysicalWidth); /* PhysicalWidth (4 bytes) */
		Stream_Write_UINT32(s, Monitors[index].PhysicalHeight); /* PhysicalHeight (4 bytes) */
		Stream_Write_UINT32(s, Monitors[index].Orientation); /* Orientation (4 bytes) */
		Stream_Write_UINT32(s, Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */
		Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */

#if 0
		WLog_DBG(TAG,  "\t: Flags: 0x%04X\n", Monitors[index].Flags);
		WLog_DBG(TAG,  "\t: Left: %d\n", Monitors[index].Left);
		WLog_DBG(TAG,  "\t: Top: %d\n", Monitors[index].Top);
		WLog_DBG(TAG,  "\t: Width: %d\n", Monitors[index].Width);
		WLog_DBG(TAG,  "\t: Height: %d\n", Monitors[index].Height);
		WLog_DBG(TAG,  "\t: PhysicalWidth: %d\n", Monitors[index].PhysicalWidth);
		WLog_DBG(TAG,  "\t: PhysicalHeight: %d\n", Monitors[index].PhysicalHeight);
		WLog_DBG(TAG,  "\t: Orientation: %d\n", Monitors[index].Orientation);
#endif
	}

	Stream_SealLength(s);

	status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL);

	Stream_Free(s, TRUE);

	return status;
}int disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s)
Exemple #21
0
static void rpc_fragment_free(wStream* fragment)
{
	Stream_Free(fragment, TRUE);
}
Exemple #22
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
{
	char* name;
	char* path;
	char* driver;
	RDPDR_SERIAL* device;
#if defined __linux__ && !defined ANDROID
	int i, len;
	SERIAL_DEVICE* serial;
#endif /* __linux__ */
	UINT error = CHANNEL_RC_OK;
	device = (RDPDR_SERIAL*) pEntryPoints->device;
	name = device->Name;
	path = device->Path;
	driver = device->Driver;

	if (!name || (name[0] == '*'))
	{
		/* TODO: implement auto detection of serial ports */
		return CHANNEL_RC_OK;
	}

	if ((name && name[0]) && (path && path[0]))
	{
		wLog* log;
		log = WLog_Get("com.freerdp.channel.serial.client");
		WLog_Print(log, WLOG_DEBUG, "initializing");
#ifndef __linux__ /* to be removed */
		WLog_Print(log, WLOG_WARN,
		           "Serial ports redirection not supported on this platform.");
		return CHANNEL_RC_INITIALIZATION_ERROR;
#else /* __linux __ */
		WLog_Print(log, WLOG_DEBUG, "Defining %s as %s", name, path);

		if (!DefineCommDevice(name /* eg: COM1 */, path /* eg: /dev/ttyS0 */))
		{
			DWORD status = GetLastError();
			WLog_ERR(TAG, "DefineCommDevice failed with %08"PRIx32, status);
			return ERROR_INTERNAL_ERROR;
		}

		serial = (SERIAL_DEVICE*) calloc(1, sizeof(SERIAL_DEVICE));

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

		serial->log = log;
		serial->device.type = RDPDR_DTYP_SERIAL;
		serial->device.name = name;
		serial->device.IRPRequest = serial_irp_request;
		serial->device.Free = serial_free;
		serial->rdpcontext = pEntryPoints->rdpcontext;
		len = strlen(name);
		serial->device.data = Stream_New(NULL, len + 1);

		if (!serial->device.data)
		{
			WLog_ERR(TAG, "calloc failed!");
			error = CHANNEL_RC_NO_MEMORY;
			goto error_out;
		}

		for (i = 0; i <= len; i++)
			Stream_Write_UINT8(serial->device.data, name[i] < 0 ? '_' : name[i]);

		if (driver != NULL)
		{
			if (_stricmp(driver, "Serial") == 0)
				serial->ServerSerialDriverId = SerialDriverSerialSys;
			else if (_stricmp(driver, "SerCx") == 0)
				serial->ServerSerialDriverId = SerialDriverSerCxSys;
			else if (_stricmp(driver, "SerCx2") == 0)
				serial->ServerSerialDriverId = SerialDriverSerCx2Sys;
			else
			{
				assert(FALSE);
				WLog_Print(serial->log, WLOG_DEBUG,
				           "Unknown server's serial driver: %s. SerCx2 will be used", driver);
				serial->ServerSerialDriverId = SerialDriverSerialSys;
			}
		}
		else
		{
			/* default driver */
			serial->ServerSerialDriverId = SerialDriverSerialSys;
		}

		if (device->Permissive != NULL)
		{
			if (_stricmp(device->Permissive, "permissive") == 0)
			{
				serial->permissive = TRUE;
			}
			else
			{
				WLog_Print(serial->log, WLOG_DEBUG, "Unknown flag: %s", device->Permissive);
				assert(FALSE);
			}
		}

		WLog_Print(serial->log, WLOG_DEBUG, "Server's serial driver: %s (id: %d)",
		           driver, serial->ServerSerialDriverId);
		/* TODO: implement auto detection of the server's serial driver */
		serial->MainIrpQueue = MessageQueue_New(NULL);

		if (!serial->MainIrpQueue)
		{
			WLog_ERR(TAG, "MessageQueue_New failed!");
			error = CHANNEL_RC_NO_MEMORY;
			goto error_out;
		}

		/* IrpThreads content only modified by create_irp_thread() */
		serial->IrpThreads = ListDictionary_New(FALSE);

		if (!serial->IrpThreads)
		{
			WLog_ERR(TAG, "ListDictionary_New failed!");
			error = CHANNEL_RC_NO_MEMORY;
			goto error_out;
		}

		serial->IrpThreadToBeTerminatedCount = 0;
		InitializeCriticalSection(&serial->TerminatingIrpThreadsLock);

		if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
		             (DEVICE*) serial)))
		{
			WLog_ERR(TAG, "EntryPoints->RegisterDevice failed with error %"PRIu32"!", error);
			goto error_out;
		}

		if (!(serial->MainThread = CreateThread(NULL,
		                                        0,
		                                        serial_thread_func,
		                                        (void*) serial,
		                                        0,
		                                        NULL)))
		{
			WLog_ERR(TAG, "CreateThread failed!");
			error = ERROR_INTERNAL_ERROR;
			goto error_out;
		}

#endif /* __linux __ */
	}

	return error;
error_out:
#ifdef __linux__ /* to be removed */
	ListDictionary_Free(serial->IrpThreads);
	MessageQueue_Free(serial->MainIrpQueue);
	Stream_Free(serial->device.data, TRUE);
	free(serial);
#endif /* __linux __ */
	return error;
}
Exemple #23
0
static void* audin_server_thread_func(void* arg)
{
	wStream* s;
	void* buffer;
	DWORD nCount;
	BYTE MessageId;
	HANDLE events[8];
	BOOL ready = FALSE;
	HANDLE ChannelEvent;
	DWORD BytesReturned = 0;
	audin_server* audin = (audin_server*) arg;

	buffer = NULL;
	BytesReturned = 0;
	ChannelEvent = NULL;

	if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
	{
		if (BytesReturned == sizeof(HANDLE))
			CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));

		WTSFreeMemory(buffer);
	}

	nCount = 0;
	events[nCount++] = audin->stopEvent;
	events[nCount++] = ChannelEvent;

	/* Wait for the client to confirm that the Audio Input dynamic channel is ready */

	while (1)
	{
		if (WaitForMultipleObjects(nCount, events, FALSE, 100) == WAIT_OBJECT_0)
			break;

		if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE)
			break;

		ready = *((BOOL*) buffer);

		WTSFreeMemory(buffer);

		if (ready)
			break;
	}

	s = Stream_New(NULL, 4096);
	if (!s)
		goto out;

	if (ready)
	{
		audin_server_send_version(audin, s);
	}

	while (ready)
	{
		if (WaitForMultipleObjects(nCount, events, FALSE, INFINITE) == WAIT_OBJECT_0)
			break;

		Stream_SetPosition(s, 0);

		if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
			Stream_Capacity(s), &BytesReturned) == FALSE)
		{
			if (BytesReturned == 0)
				break;
			
			Stream_EnsureRemainingCapacity(s, BytesReturned);

			if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
				Stream_Capacity(s), &BytesReturned) == FALSE)
			{
				break;
			}
		}

		if (BytesReturned < 1)
			continue;

		Stream_Read_UINT8(s, MessageId);
		BytesReturned--;

		switch (MessageId)
		{
			case MSG_SNDIN_VERSION:
				if (audin_server_recv_version(audin, s, BytesReturned))
					audin_server_send_formats(audin, s);
				break;

			case MSG_SNDIN_FORMATS:
				if (audin_server_recv_formats(audin, s, BytesReturned))
					audin_server_send_open(audin, s);
				break;

			case MSG_SNDIN_OPEN_REPLY:
				audin_server_recv_open_reply(audin, s, BytesReturned);
				break;

			case MSG_SNDIN_DATA_INCOMING:
				break;

			case MSG_SNDIN_DATA:
				audin_server_recv_data(audin, s, BytesReturned);
				break;

			case MSG_SNDIN_FORMATCHANGE:
				break;

			default:
				fprintf(stderr, "audin_server_thread_func: unknown MessageId %d\n", MessageId);
				break;
		}
	}

	Stream_Free(s, TRUE);

out:
	WTSVirtualChannelClose(audin->audin_channel);
	audin->audin_channel = NULL;

	return NULL;
}
Exemple #24
0
DWORD TsProxySendToServer(handle_t IDL_handle, byte pRpcMessage[], UINT32 count, UINT32* lengths)
{
	wStream* s;
	int status;
	rdpTsg* tsg;
	BYTE* buffer;
	UINT32 length;
	byte* buffer1 = NULL;
	byte* buffer2 = NULL;
	byte* buffer3 = NULL;
	UINT32 buffer1Length;
	UINT32 buffer2Length;
	UINT32 buffer3Length;
	UINT32 numBuffers = 0;
	UINT32 totalDataBytes = 0;

	tsg = (rdpTsg*) IDL_handle;
	buffer1Length = buffer2Length = buffer3Length = 0;

	if (count > 0)
	{
		numBuffers++;
		buffer1 = &pRpcMessage[0];
		buffer1Length = lengths[0];
		totalDataBytes += lengths[0] + 4;
	}

	if (count > 1)
	{
		numBuffers++;
		buffer2 = &pRpcMessage[1];
		buffer2Length = lengths[1];
		totalDataBytes += lengths[1] + 4;
	}

	if (count > 2)
	{
		numBuffers++;
		buffer3 = &pRpcMessage[2];
		buffer3Length = lengths[2];
		totalDataBytes += lengths[2] + 4;
	}

	length = 28 + totalDataBytes;
	buffer = (BYTE*) malloc(length);

	s = Stream_New(buffer, length);

	/* PCHANNEL_CONTEXT_HANDLE_NOSERIALIZE_NR (20 bytes) */
	Stream_Write(s, &tsg->ChannelContext.ContextType, 4); /* ContextType (4 bytes) */
	Stream_Write(s, tsg->ChannelContext.ContextUuid, 16); /* ContextUuid (16 bytes) */

	Stream_Write_UINT32_BE(s, totalDataBytes); /* totalDataBytes (4 bytes) */
	Stream_Write_UINT32_BE(s, numBuffers); /* numBuffers (4 bytes) */

	if (buffer1Length > 0)
		Stream_Write_UINT32_BE(s, buffer1Length); /* buffer1Length (4 bytes) */
	if (buffer2Length > 0)
		Stream_Write_UINT32_BE(s, buffer2Length); /* buffer2Length (4 bytes) */
	if (buffer3Length > 0)
		Stream_Write_UINT32_BE(s, buffer3Length); /* buffer3Length (4 bytes) */

	if (buffer1Length > 0)
		Stream_Write(s, buffer1, buffer1Length); /* buffer1 (variable) */
	if (buffer2Length > 0)
		Stream_Write(s, buffer2, buffer2Length); /* buffer2 (variable) */
	if (buffer3Length > 0)
		Stream_Write(s, buffer3, buffer3Length); /* buffer3 (variable) */

	Stream_Length(s) = Stream_GetPosition(s);

	status = rpc_write(tsg->rpc, Stream_Buffer(s), Stream_Length(s), TsProxySendToServerOpnum);

	Stream_Free(s, TRUE);

	if (status <= 0)
	{
		fprintf(stderr, "rpc_write failed!\n");
		return -1;
	}

	return length;
}
Exemple #25
0
HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
{
	UINT32 index;
	wStream* s;
	rdpMcs* mcs;
	BOOL joined = FALSE;
	freerdp_peer* client;
	rdpPeerChannel* channel;
	ULONG written;
	WTSVirtualChannelManager* vcm;

	if (SessionId == WTS_CURRENT_SESSION)
		return NULL;

	vcm = (WTSVirtualChannelManager*) HashTable_GetItemValue(g_ServerHandles, (void*) (UINT_PTR) SessionId);

	if (!vcm)
		return NULL;

	if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC))
	{
		return FreeRDP_WTSVirtualChannelOpen((HANDLE) vcm, SessionId, pVirtualName);
	}

	client = vcm->client;
	mcs = client->context->rdp->mcs;

	for (index = 0; index < mcs->channelCount; index++)
	{
		if (mcs->channels[index].joined && (strncmp(mcs->channels[index].Name, "drdynvc", 7) == 0))
		{
			joined = TRUE;
			break;
		}
	}

	if (!joined)
	{
		SetLastError(ERROR_NOT_FOUND);
		return NULL;
	}

	if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY))
	{
		SetLastError(ERROR_NOT_READY);
		return NULL;
	}

	channel = (rdpPeerChannel*) calloc(1, sizeof(rdpPeerChannel));
	if (!channel)
	{
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return NULL;
	}

	channel->vcm = vcm;
	channel->client = client;
	channel->channelType = RDP_PEER_CHANNEL_TYPE_DVC;
	channel->receiveData = Stream_New(NULL, client->settings->VirtualChannelChunkSize);

	if (!channel->receiveData)
	{
		WLog_ERR(TAG, "Stream_New failed!");
		goto error_receiveData;
	}

	channel->queue = MessageQueue_New(NULL);
	if (!channel->queue)
		goto error_queue;

	channel->channelId = InterlockedIncrement(&vcm->dvc_channel_id_seq);
	if (ArrayList_Add(vcm->dynamicVirtualChannels, channel) < 0)
		goto error_add;

	s = Stream_New(NULL, 64);
	if (!s)
		goto error_s;
	if (!wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName))
		goto error_create;
	if (!WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written))
		goto error_create;
	Stream_Free(s, TRUE);

	return channel;

error_create:
	Stream_Free(s, TRUE);
error_s:
	ArrayList_Remove(vcm->dynamicVirtualChannels, channel);
error_add:
	MessageQueue_Free(channel->queue);
error_queue:
	Stream_Free(channel->receiveData, TRUE);
error_receiveData:
	free(channel);
	SetLastError(ERROR_NOT_ENOUGH_MEMORY);
	return NULL;
}
int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
{
	int status;
	wStream* s;
	UINT16 index;
	RDPGFX_PLUGIN* gfx;
	RDPGFX_HEADER header;
	RDPGFX_CAPSET* capsSet;
	RDPGFX_CAPSET capsSets[2];
	RDPGFX_CAPS_ADVERTISE_PDU pdu;

	gfx = (RDPGFX_PLUGIN*) callback->plugin;

	header.flags = 0;
	header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;

	pdu.capsSetCount = 0;
	pdu.capsSets = (RDPGFX_CAPSET*) capsSets;

	capsSet = &capsSets[pdu.capsSetCount++];
	capsSet->version = RDPGFX_CAPVERSION_8;
	capsSet->flags = 0;

	if (gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;

	if (gfx->SmallCache)
		capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

	capsSet = &capsSets[pdu.capsSetCount++];
	capsSet->version = RDPGFX_CAPVERSION_81;
	capsSet->flags = 0;

	if (gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;

	if (gfx->SmallCache)
		capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

	if (gfx->H264)
		capsSet->flags |= RDPGFX_CAPS_FLAG_H264ENABLED;

	header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE);

	WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu");

	s = Stream_New(NULL, header.pduLength);

	rdpgfx_write_header(s, &header);

	/* RDPGFX_CAPS_ADVERTISE_PDU */

	Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */

	for (index = 0; index < pdu.capsSetCount; index++)
	{
		capsSet = &(pdu.capsSets[index]);
		Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */
		Stream_Write_UINT32(s, 4); /* capsDataLength (4 bytes) */
		Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */
	}

	Stream_SealLength(s);

	status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL);

	Stream_Free(s, TRUE);

	return status;
}
Exemple #27
0
HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
{
	int length;
	UINT32 index;
	rdpMcs* mcs;
	BOOL joined = FALSE;
	freerdp_peer* client;
	rdpPeerChannel* channel;
	WTSVirtualChannelManager* vcm;
	HANDLE hChannelHandle = NULL;

	vcm = (WTSVirtualChannelManager*) hServer;
	if (!vcm)
	{
		SetLastError(ERROR_INVALID_DATA);
		return NULL;
	}

	client = vcm->client;
	mcs = client->context->rdp->mcs;

	length = strlen(pVirtualName);
	if (length > 8)
	{
		SetLastError(ERROR_NOT_FOUND);
		return NULL;
	}

	for (index = 0; index < mcs->channelCount; index++)
	{
		if (mcs->channels[index].joined && (strncmp(mcs->channels[index].Name, pVirtualName, length) == 0))
		{
			joined = TRUE;
			break;
		}
	}

	if (!joined)
	{
		SetLastError(ERROR_NOT_FOUND);
		return NULL;
	}

	channel = (rdpPeerChannel*) mcs->channels[index].handle;
	if (!channel)
	{
		channel = (rdpPeerChannel*) calloc(1, sizeof(rdpPeerChannel));
		if (!channel)
			goto error_channel_alloc;

		channel->vcm = vcm;
		channel->client = client;
		channel->channelId = mcs->channels[index].ChannelId;
		channel->index = index;
		channel->channelType = RDP_PEER_CHANNEL_TYPE_SVC;
		channel->receiveData = Stream_New(NULL, client->settings->VirtualChannelChunkSize);
		if (!channel->receiveData)
		{
			WLog_ERR(TAG, "Stream_New failed!");
			goto error_receiveData;
		}
		channel->queue = MessageQueue_New(NULL);
		if (!channel->queue)
			goto error_queue;

		mcs->channels[index].handle = channel;
	}

	hChannelHandle = (HANDLE) channel;
	return hChannelHandle;

error_queue:
	Stream_Free(channel->receiveData, TRUE);
error_receiveData:
	free(channel);
error_channel_alloc:
	SetLastError(ERROR_NOT_ENOUGH_MEMORY);
	return NULL;
}
Exemple #28
0
BOOL nego_send_negotiation_request(rdpNego* nego)
{
	wStream* s;
	int length;
	int bm, em;
	BYTE flags = 0;
	int cookie_length;

	s = Stream_New(NULL, 512);

	length = TPDU_CONNECTION_REQUEST_LENGTH;
	bm = Stream_GetPosition(s);
	Stream_Seek(s, length);

	if (nego->RoutingToken)
	{
		Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength);

		/* Ensure Routing Token is correctly terminated - may already be present in string */

		if ((nego->RoutingTokenLength > 2) &&
				(nego->RoutingToken[nego->RoutingTokenLength - 2] == 0x0D) &&
				(nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A))
		{
			WLog_DBG(TAG, "Routing token looks correctly terminated - use verbatim");
			length +=nego->RoutingTokenLength;
		}
		else
		{
			WLog_DBG(TAG, "Adding terminating CRLF to routing token");
			Stream_Write_UINT8(s, 0x0D); /* CR */
			Stream_Write_UINT8(s, 0x0A); /* LF */
			length += nego->RoutingTokenLength + 2;
		}
	}
	else if (nego->cookie)
	{
		cookie_length = strlen(nego->cookie);

		if (cookie_length > (int) nego->CookieMaxLength)
			cookie_length = nego->CookieMaxLength;

		Stream_Write(s, "Cookie: mstshash=", 17);
		Stream_Write(s, (BYTE*) nego->cookie, cookie_length);
		Stream_Write_UINT8(s, 0x0D); /* CR */
		Stream_Write_UINT8(s, 0x0A); /* LF */
		length += cookie_length + 19;
	}

	WLog_DBG(TAG, "RequestedProtocols: %d", nego->RequestedProtocols);

	if ((nego->RequestedProtocols > PROTOCOL_RDP) || (nego->sendNegoData))
	{
		/* RDP_NEG_DATA must be present for TLS and NLA */

		if (nego->RestrictedAdminModeRequired)
			flags |= RESTRICTED_ADMIN_MODE_REQUIRED;

		Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
		Stream_Write_UINT8(s, flags);
		Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
		Stream_Write_UINT32(s, nego->RequestedProtocols); /* requestedProtocols */
		length += 8;
	}

	em = Stream_GetPosition(s);
	Stream_SetPosition(s, bm);
	tpkt_write_header(s, length);
	tpdu_write_connection_request(s, length - 5);
	Stream_SetPosition(s, em);

	Stream_SealLength(s);

	if (transport_write(nego->transport, s) < 0)
	{
		Stream_Free(s, TRUE);
		return FALSE;
	}

	Stream_Free(s, TRUE);

	return TRUE;
}
Exemple #29
0
static BOOL TestStream_Create(int count, BOOL selfAlloc)
{
	int i, len, cap, pos;
	wStream *s = NULL;
	void* buffer = NULL;

	for (i = 0; i < count; i++)
	{
		len = cap = i+1;
		pos = 0;

		if (selfAlloc)
		{
			if (!(buffer = malloc(cap)))
			{
				printf("%s: failed to allocate buffer of size %d\n", __FUNCTION__, cap);
				goto fail;
			}
		}

		if (!(s = Stream_New(selfAlloc ? buffer : NULL, len)))
		{
			printf("%s: Stream_New failed for stream #%d\n", __FUNCTION__, i);
			goto fail;
		}

		if (!TestStream_Verify(s, cap, len, pos))
		{
			goto fail;
		}

		for (pos = 0; pos < len; pos++)
		{
			Stream_SetPosition(s, pos);
			Stream_SealLength(s);
			if (!TestStream_Verify(s, cap, pos, pos))
			{
				goto fail;
			}
		}

		if (selfAlloc)
		{
			memset(buffer, i%256, cap);
			if (memcmp(buffer, Stream_Buffer(s), cap))
			{
				printf("%s: buffer memory corruption\n", __FUNCTION__);
				goto fail;
			}
		}

		Stream_Free(s, buffer ? FALSE : TRUE);
		free(buffer);
	}

	return TRUE;

fail:
	free(buffer);
	if (s)
	{
		Stream_Free(s, buffer ? FALSE : TRUE);
	}

	return FALSE;
}
Exemple #30
0
static BOOL rdp_client_establish_keys(rdpRdp* rdp)
{
	BYTE* mod;
	BYTE* exp;
	wStream* s;
	UINT32 length;
	UINT32 key_len;
	int status = 0;
	BOOL ret = FALSE;
	rdpSettings* settings;
	BYTE* crypt_client_random = NULL;

	settings = rdp->settings;

	if (!settings->UseRdpSecurityLayer)
	{
		/* no RDP encryption */
		return TRUE;
	}

	/* encrypt client random */

	free(settings->ClientRandom);

	settings->ClientRandomLength = CLIENT_RANDOM_LENGTH;
	settings->ClientRandom = malloc(settings->ClientRandomLength);

	if (!settings->ClientRandom)
		return FALSE;

	winpr_RAND(settings->ClientRandom, settings->ClientRandomLength);
	key_len = settings->RdpServerCertificate->cert_info.ModulusLength;
	mod = settings->RdpServerCertificate->cert_info.Modulus;
	exp = settings->RdpServerCertificate->cert_info.exponent;

	/*
	 * client random must be (bitlen / 8) + 8 - see [MS-RDPBCGR] 5.3.4.1
	 * for details
	 */
	crypt_client_random = calloc(key_len + 8, 1);

	if (!crypt_client_random)
		return FALSE;

	crypto_rsa_public_encrypt(settings->ClientRandom, settings->ClientRandomLength, key_len, mod, exp, crypt_client_random);

	/* send crypt client random to server */
	length = RDP_PACKET_HEADER_MAX_LENGTH + RDP_SECURITY_HEADER_LENGTH + 4 + key_len + 8;
	s = Stream_New(NULL, length);

	if (!s)
	{
		WLog_ERR(TAG, "Stream_New failed!");
		goto end;
	}

	rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
	rdp_write_security_header(s, SEC_EXCHANGE_PKT | SEC_LICENSE_ENCRYPT_SC);
	length = key_len + 8;

	Stream_Write_UINT32(s, length);
	Stream_Write(s, crypt_client_random, length);
	Stream_SealLength(s);

	status = transport_write(rdp->mcs->transport, s);
	Stream_Free(s, TRUE);

	if (status < 0)
		goto end;

	rdp->do_crypt_license = TRUE;

	/* now calculate encrypt / decrypt and update keys */
	if (!security_establish_keys(settings->ClientRandom, rdp))
		goto end;

	rdp->do_crypt = TRUE;

	if (settings->SaltedChecksum)
		rdp->do_secure_checksum = TRUE;

	if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
	{
		rdp->fips_encrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC,
		                                     WINPR_ENCRYPT,
		                                     rdp->fips_encrypt_key,
		                                     fips_ivec);
		if (!rdp->fips_encrypt)
		{
			WLog_ERR(TAG, "unable to allocate des3 encrypt key");
			goto end;
		}
		rdp->fips_decrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC,
		                                     WINPR_DECRYPT,
		                                     rdp->fips_decrypt_key,
		                                     fips_ivec);
		if (!rdp->fips_decrypt)
		{
			WLog_ERR(TAG, "unable to allocate des3 decrypt key");
			goto end;
		}

		ret = TRUE;
		goto end;
	}

	rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len);
	rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len);
	if (!rdp->rc4_decrypt_key || !rdp->rc4_encrypt_key)
		goto end;

	ret = TRUE;
end:
	free(crypt_client_random);
	if (!ret)
	{
		winpr_Cipher_Free(rdp->fips_decrypt);
		winpr_Cipher_Free(rdp->fips_encrypt);
		winpr_RC4_Free(rdp->rc4_decrypt_key);
		winpr_RC4_Free(rdp->rc4_encrypt_key);

		rdp->fips_decrypt = NULL;
		rdp->fips_encrypt = NULL;
		rdp->rc4_decrypt_key = NULL;
		rdp->rc4_encrypt_key = NULL;
	}

	return ret;
}