Пример #1
0
wStream* transport_send_stream_init(rdpTransport* transport, int size)
{
	wStream* s = transport->SendStream;
	Stream_EnsureCapacity(s, size);
	Stream_SetPosition(s, 0);
	return s;
}
Пример #2
0
int rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version)
{
	ULONG written;
	RdpeiServerPrivate *priv = context->priv;

	if (priv->automataState != STATE_INITIAL)
	{
		fprintf(stderr, "%s: called from unexpected state %d\n", __FUNCTION__, priv->automataState);
		return -1;
	}

	Stream_SetPosition(priv->outputStream, 0);
	Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4);

	Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY);
	Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4);
	Stream_Write_UINT32(priv->outputStream, version);

	if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream),
			Stream_GetPosition(priv->outputStream), &written))
	{
		fprintf(stderr, "%s: error writing ready message\n", __FUNCTION__);
		return -1;
	}

	priv->automataState = STATE_WAITING_CLIENT_READY;
	return 0;
}
Пример #3
0
wStream* transport_recv_stream_init(rdpTransport* transport, int size)
{
	wStream* s = transport->ReceiveStream;
	Stream_EnsureCapacity(s, size);
	Stream_SetPosition(s, 0);
	return s;
}
Пример #4
0
static wStream* rdg_receive_packet(rdpRdg* rdg)
{
	wStream* s;
	size_t packetLength;
	s = Stream_New(NULL, 1024);

	if (!s)
		return NULL;

	if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s), sizeof(RdgPacketHeader)))
	{
		Stream_Free(s, TRUE);
		return NULL;
	}

	Stream_Seek(s, 4);
	Stream_Read_UINT32(s, packetLength);

	if (!Stream_EnsureCapacity(s, packetLength))
	{
		Stream_Free(s, TRUE);
		return NULL;
	}

	if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s) + sizeof(RdgPacketHeader),
	                  packetLength - sizeof(RdgPacketHeader)))
	{
		Stream_Free(s, TRUE);
		return NULL;
	}

	Stream_SetLength(s, packetLength);
	return s;
}
Пример #5
0
int rdpei_server_resume(RdpeiServerContext *context)
{
	ULONG written;
	RdpeiServerPrivate *priv = context->priv;

	switch (priv->automataState)
	{
	case STATE_WAITING_FRAME:
		fprintf(stderr, "%s: not suspended\n", __FUNCTION__);
		return 0;
	case STATE_SUSPENDED:
		break;
	default:
		fprintf(stderr, "%s: called from unexpected state %d\n", __FUNCTION__, priv->automataState);
		return -1;
	}

	Stream_SetPosition(priv->outputStream, 0);
	Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH);

	Stream_Write_UINT16(priv->outputStream, EVENTID_RESUME_TOUCH);
	Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH);

	if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream),
			Stream_GetPosition(priv->outputStream), &written))
	{
		fprintf(stderr, "%s: error writing resumeTouch message\n", __FUNCTION__);
		return -1;
	}

	priv->automataState = STATE_WAITING_FRAME;
	return 0;
}
Пример #6
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
UINT rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version)
{
	ULONG written;
	RdpeiServerPrivate *priv = context->priv;

	if (priv->automataState != STATE_INITIAL)
	{
		WLog_ERR(TAG, "called from unexpected state %d", (int)priv->automataState);
		return ERROR_INVALID_STATE;
	}

	Stream_SetPosition(priv->outputStream, 0);

	if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4))
	{
		WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
		return CHANNEL_RC_NO_MEMORY;
	}

	Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY);
	Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4);
	Stream_Write_UINT32(priv->outputStream, version);

	if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream),
			Stream_GetPosition(priv->outputStream), &written))
	{
		WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
		return ERROR_INTERNAL_ERROR;
	}

	priv->automataState = STATE_WAITING_CLIENT_READY;
	return CHANNEL_RC_OK;
}
Пример #7
0
wStream* transport_send_stream_init(rdpTransport* transport, int size)
{
	wStream* s;
	s = StreamPool_Take(transport->ReceivePool, size);
	Stream_EnsureCapacity(s, size);
	Stream_SetPosition(s, 0);
	return s;
}
Пример #8
0
wStream* rdg_receive_packet(rdpRdg* rdg)
{
	int status;
	wStream* s;
	RdgPacketHeader* packet;
	UINT32 readCount = 0;

	s = Stream_New(NULL, 1024);

	if (!s)
		return NULL;

	packet = (RdgPacketHeader*) Stream_Buffer(s);

	while (readCount < sizeof(RdgPacketHeader))
	{
		status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount);

		if (status < 0)
		{
			continue;
		}

		readCount += status;
		Stream_Seek(s, readCount);
	}

	if (Stream_Capacity(s) < packet->packetLength)
	{
		if (!Stream_EnsureCapacity(s, packet->packetLength))
		{
			Stream_Free(s, TRUE);
			return NULL;
		}
		packet = (RdgPacketHeader*) Stream_Buffer(s);
	}

	while (readCount < packet->packetLength)
	{
		status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), packet->packetLength - readCount);

		if (status < 0)
		{
			continue;
		}

		readCount += status;
		Stream_Seek(s, readCount);
	}

	Stream_SealLength(s);

	return s;
}
Пример #9
0
wStream* transport_send_stream_init(rdpTransport* transport, int size)
{
	wStream* s;
	if (!(s = StreamPool_Take(transport->ReceivePool, size)))
		return NULL;
	if (!Stream_EnsureCapacity(s, size))
	{
		Stream_Release(s);
		return NULL;
	}
	Stream_SetPosition(s, 0);
	return s;
}
Пример #10
0
static int transport_read_nonblocking(rdpTransport* transport)
{
	int status;

	Stream_EnsureCapacity(transport->ReceiveBuffer, 32 * 1024);
	status = transport_read(transport, transport->ReceiveBuffer);

	if (status <= 0)
		return status;

	Stream_Seek(transport->ReceiveBuffer, status);

	return status;
}
Пример #11
0
BOOL tf_peer_dump_rfx(freerdp_peer* client)
{
	wStream* s;
	UINT32 prev_seconds;
	UINT32 prev_useconds;
	rdpUpdate* update;
	rdpPcap* pcap_rfx;
	pcap_record record;
	s = Stream_New(NULL, 512);

	if (!s)
		return FALSE;

	update = client->update;

	if (!(pcap_rfx = pcap_open(test_pcap_file, FALSE)))
		return FALSE;

	prev_seconds = prev_useconds = 0;

	while (pcap_has_next_record(pcap_rfx))
	{
		if (!pcap_get_next_record_header(pcap_rfx, &record))
			break;

		if (!Stream_EnsureCapacity(s, record.length))
			break;

		record.data = Stream_Buffer(s);
		pcap_get_next_record_content(pcap_rfx, &record);
		Stream_SetPointer(s, Stream_Buffer(s) + Stream_Capacity(s));

		if (test_dump_rfx_realtime
		    && test_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec,
		                         record.header.ts_usec) == FALSE)
			break;

		update->SurfaceCommand(update->context, s);

		if (client->CheckFileDescriptor(client) != TRUE)
			break;
	}

	Stream_Free(s, TRUE);
	pcap_close(pcap_rfx);
	return TRUE;
}
Пример #12
0
wStream* StreamPool_Take(wStreamPool* pool, size_t size)
{
	int index;
	int foundIndex;
	wStream* s = NULL;
	BOOL found = FALSE;

	if (pool->synchronized)
		WaitForSingleObject(pool->mutex, INFINITE);

	if (size == 0)
		size = pool->defaultSize;

	for (index = 0; index < pool->aSize; index++)
	{
		s = pool->aArray[index];

		if (Stream_Capacity(s) >= size)
		{
			foundIndex = index;
			found = TRUE;
			break;
		}
	}

	if (!found)
	{
		s = Stream_New(NULL, size);
	}
	else
	{
		StreamPool_ShiftAvailable(pool, foundIndex, -1);

		Stream_EnsureCapacity(s, size);
		Stream_Pointer(s) = Stream_Buffer(s);
	}

	s->pool = pool;
	s->count = 1;

	StreamPool_AddUsed(pool, s);

	if (pool->synchronized)
		ReleaseMutex(pool->mutex);

	return s;
}
Пример #13
0
wStream* StreamPool_Take(wStreamPool* pool, size_t size)
{
	int index;
	int foundIndex;
	wStream* s = NULL;
	BOOL found = FALSE;

	if (pool->synchronized)
		EnterCriticalSection(&pool->lock);

	if (size == 0)
		size = pool->defaultSize;

	for (index = 0; index < pool->aSize; index++)
	{
		s = pool->aArray[index];

		if (Stream_Capacity(s) >= size)
		{
			foundIndex = index;
			found = TRUE;
			break;
		}
	}

	if (!found)
	{
		s = Stream_New(NULL, size);
	}
	else
	{
		StreamPool_ShiftAvailable(pool, foundIndex, -1);

		Stream_EnsureCapacity(s, size);
		Stream_Pointer(s) = Stream_Buffer(s);
	}

	s->pool = pool;
	s->count = 1;

	StreamPool_AddUsed(pool, s);

	if (pool->synchronized)
		LeaveCriticalSection(&pool->lock);

	return s;
}
Пример #14
0
static BOOL TestStream_Extent(UINT32 maxSize)
{
	UINT32 i;
	wStream *s = NULL;
	BOOL result = FALSE;

	if (!(s = Stream_New(NULL, 1)))
	{
		printf("%s: Stream_New failed\n", __FUNCTION__);
		return FALSE;
	}

	for (i = 1; i < maxSize; i++)
	{
		if (i % 2)
		{
			if (!Stream_EnsureRemainingCapacity(s, i))
				goto fail;
		}
		else
		{
			if (!Stream_EnsureCapacity(s, i))
				goto fail;
		}

		Stream_SetPosition(s, i);
		Stream_SealLength(s);

		if (!TestStream_Verify(s, i, i, i))
		{
			printf("%s: failed to verify stream in iteration %"PRIu32"\n", __FUNCTION__, i);
			goto fail;
		}
	}

	result = TRUE;

fail:
	if (s)
	{
		Stream_Free(s, TRUE);
	}

	return result;
}
Пример #15
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
UINT rdpei_server_resume(RdpeiServerContext *context)
{
	ULONG written;
	RdpeiServerPrivate *priv = context->priv;

	switch (priv->automataState)
	{
	case STATE_WAITING_FRAME:
		WLog_ERR(TAG, "not suspended");
		return CHANNEL_RC_OK;
	case STATE_SUSPENDED:
		break;
	default:
		WLog_ERR(TAG, "called from unexpected state %d", (int)priv->automataState);
		return ERROR_INVALID_STATE;
	}

	Stream_SetPosition(priv->outputStream, 0);
	if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH))
	{
		WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
		return CHANNEL_RC_NO_MEMORY;
	}

	Stream_Write_UINT16(priv->outputStream, EVENTID_RESUME_TOUCH);
	Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH);

	if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream),
			Stream_GetPosition(priv->outputStream), &written))
	{
		WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
		return ERROR_INTERNAL_ERROR;
	}

	priv->automataState = STATE_WAITING_FRAME;
	return CHANNEL_RC_OK;
}
Пример #16
0
void Stream_EnsureRemainingCapacity(wStream* s, size_t size)
{
	if (Stream_GetPosition(s) + size > Stream_Capacity(s))
		Stream_EnsureCapacity(s, Stream_Capacity(s) + size);
}
Пример #17
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
{
	DWORD bytesReturned;
	UINT ret = CHANNEL_RC_OK;

	RdpsndServerPrivate *priv = context->priv;
	wStream *s = priv->input_stream;

	if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned))
	{
		if (GetLastError() == ERROR_NO_DATA)
			return ERROR_NO_DATA;

		WLog_ERR(TAG,  "channel connection closed");
		return ERROR_INTERNAL_ERROR;
	}
	priv->expectedBytes -= bytesReturned;
	Stream_Seek(s, bytesReturned);

	if (priv->expectedBytes)
		return CHANNEL_RC_OK;

	Stream_SealLength(s);
	Stream_SetPosition(s, 0);
	if (priv->waitingHeader)
	{
		/* header case */
		Stream_Read_UINT8(s, priv->msgType);
		Stream_Seek_UINT8(s); /* bPad */
		Stream_Read_UINT16(s, priv->expectedBytes);

		priv->waitingHeader = FALSE;
		Stream_SetPosition(s, 0);
		if (priv->expectedBytes)
		{
			if (!Stream_EnsureCapacity(s, priv->expectedBytes))
			{
				WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
				return CHANNEL_RC_NO_MEMORY;
			}
			return CHANNEL_RC_OK;
		}
	}

	/* when here we have the header + the body */
#ifdef WITH_DEBUG_SND
	WLog_DBG(TAG,  "message type %d", priv->msgType);
#endif
	priv->expectedBytes = 4;
	priv->waitingHeader = TRUE;

	switch (priv->msgType)
	{
		case SNDC_WAVECONFIRM:
			ret = rdpsnd_server_recv_waveconfirm(context, s);
			break;

		case SNDC_FORMATS:
			ret = rdpsnd_server_recv_formats(context, s);

			if ((ret == CHANNEL_RC_OK) && (context->clientVersion < 6))
				IFCALL(context->Activated, context);

			break;

		case SNDC_QUALITYMODE:
			ret = rdpsnd_server_recv_quality_mode(context, s);
			Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */

			if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= 6))
				IFCALL(context->Activated, context);
			break;

		default:
			WLog_ERR(TAG,  "UNKOWN MESSAGE TYPE!! (%#0X)", priv->msgType);
			ret = ERROR_INVALID_DATA;
			break;
	}
	Stream_SetPosition(s, 0);

	return ret;
}
Пример #18
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;
}
Пример #19
0
/**
 * @brief Try to read a complete PDU (NLA, fast-path or tpkt) from the underlying transport.
 *
 * If possible a complete PDU is read, in case of non blocking transport this might not succeed.
 * Except in case of an error the passed stream will point to the last byte read (correct
 * position). When the pdu read is completed the stream is sealed and the pointer set to 0
 *
 * @param[in] transport rdpTransport
 * @param[in] s wStream
 * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 number of
 * bytes of the *complete* pdu read
 */
int transport_read_pdu(rdpTransport* transport, wStream* s)
{
	int status;
	int position;
	int pduLength;
	BYTE* header;

	position = 0;
	pduLength = 0;

	if (!transport)
		return -1;

	if (!s)
		return -1;

	position = Stream_GetPosition(s);
	/* Make sure there is enough space for the longest header within the stream */
	if (!Stream_EnsureCapacity(s, 4))
		return -1;

	/* Make sure at least two bytes are read for further processing */
	if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1)
	{
		/* No data available at the moment */
		return status;
	}

	/* update position value for further checks */
	position = Stream_GetPosition(s);
	header = Stream_Buffer(s);

	if (transport->NlaMode)
	{
		/*
		 * In case NlaMode is set TSRequest package(s) are expected
		 * 0x30 = DER encoded data with these bits set:
		 * bit 6 P/C constructed
		 * bit 5 tag number - sequence
		 */
		if (header[0] == 0x30)
		{
			/* TSRequest (NLA) */
			if (header[1] & 0x80)
			{
				if ((header[1] & ~(0x80)) == 1)
				{
					/* check for header bytes already was readed in previous calls */
					if (position < 3
							&& (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1)
						return status;

					pduLength = header[2];
					pduLength += 3;
				}
				else if ((header[1] & ~(0x80)) == 2)
				{
					/* check for header bytes already was readed in previous calls */
					if (position < 4
							&& (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1)
						return status;

					pduLength = (header[2] << 8) | header[3];
					pduLength += 4;
				}
				else
				{
					WLog_ERR(TAG, "Error reading TSRequest!");
					return -1;
				}
			}
			else
			{
				pduLength = header[1];
				pduLength += 2;
			}
		}
	}
	else
	{
		if (header[0] == 0x03)
		{
			/* TPKT header */
			/* check for header bytes already was readed in previous calls */
			if (position < 4
					&& (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1)
				return status;

			pduLength = (header[2] << 8) | header[3];

			/* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */
			if (pduLength < 7 || pduLength > 0xFFFF)
			{
				WLog_ERR(TAG, "tpkt - invalid pduLength: %d", pduLength);
				return -1;
			}
		}
		else
		{
			/* Fast-Path Header */
			if (header[1] & 0x80)
			{
				/* check for header bytes already was readed in previous calls */
				if (position < 3
						&& (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1)
					return status;

				pduLength = ((header[1] & 0x7F) << 8) | header[2];
			}
			else
				pduLength = header[1];

			/*
			 * fast-path has 7 bits for length so the maximum size, including headers is 0x8000
			 * The theoretical minimum fast-path PDU consists only of two header bytes plus one
			 * byte for data (e.g. fast-path input synchronize pdu)
			 */
			if (pduLength < 3 || pduLength > 0x8000)
			{
				WLog_ERR(TAG, "fast path - invalid pduLength: %d", pduLength);
				return -1;
			}
		}
	}

	if (!Stream_EnsureCapacity(s, Stream_GetPosition(s) + pduLength))
		return -1;
	status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s));

	if (status != 1)
		return status;

	if (Stream_GetPosition(s) >= pduLength)
		WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);

	Stream_SealLength(s);
	Stream_SetPosition(s, 0);
	return Stream_Length(s);
}
Пример #20
0
BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size)
{
	DWORD i;
	int left;
	wStream* s;
	UINT32 flags;
	int chunkSize;
	rdpMcs* mcs = rdp->mcs;
	rdpMcsChannel* channel = NULL;

	for (i = 0; i < mcs->channelCount; i++)
	{
		if (mcs->channels[i].ChannelId == channelId)
		{
			channel = &mcs->channels[i];
			break;
		}
	}

	if (!channel)
	{
		DEBUG_WARN( "freerdp_channel_send: unknown channelId %d\n", channelId);
		return FALSE;
	}

	flags = CHANNEL_FLAG_FIRST;
	left = size;

	while (left > 0)
	{
		s = rdp_send_stream_init(rdp);

		if (left > (int) rdp->settings->VirtualChannelChunkSize)
		{
			chunkSize = rdp->settings->VirtualChannelChunkSize;
		}
		else
		{
			chunkSize = left;
			flags |= CHANNEL_FLAG_LAST;
		}

		if ((channel->options & CHANNEL_OPTION_SHOW_PROTOCOL))
		{
			flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
		}

		Stream_Write_UINT32(s, size);
		Stream_Write_UINT32(s, flags);
		Stream_EnsureCapacity(s, chunkSize);
		Stream_Write(s, data, chunkSize);

		rdp_send(rdp, s, channelId);

		data += chunkSize;
		left -= chunkSize;
		flags = 0;
	}

	return TRUE;
}
Пример #21
0
/**
 * @brief Try to read a complete PDU (NLA, fast-path or tpkt) from the underlying transport.
 *
 * If possible a complete PDU is read, in case of non blocking transport this might not succeed.
 * Except in case of an error the passed stream will point to the last byte read (correct
 * position). When the pdu read is completed the stream is sealed and the pointer set to 0
 *
 * @param[in] transport rdpTransport
 * @param[in] s wStream
 * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 number of
 * bytes of the *complete* pdu read
 */
int transport_read_pdu(rdpTransport* transport, wStream* s)
{
	int status;
	int position;
	int pduLength;
	BYTE *header;

	position = 0;
	pduLength = 0;

	if (!transport)
		return -1;

	if (!s)
		return -1;

	position = Stream_GetPosition(s);

	/* Make sure there is enough space for the longest header within the stream */
	Stream_EnsureCapacity(s, 4);

	/* Make sure at least two bytes are read for futher processing */
	if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1)
	{
		/* No data available at the moment */
		return status;
	}

	header = Stream_Buffer(s);

	if (transport->NlaMode)
	{
		/*
		 * In case NlaMode is set TSRequest package(s) are expected
		 * 0x30 = DER encoded data with these bits set:
		 * bit 6 P/C constructed
		 * bit 5 tag number - sequence
		 */
		if (header[0] == 0x30)
		{
			/* TSRequest (NLA) */
			if (header[1] & 0x80)
			{
				if ((header[1] & ~(0x80)) == 1)
				{
					if ((status = transport_read_layer_bytes(transport, s, 1)) != 1)
						return status;
					pduLength = header[2];
					pduLength += 3;
				}
				else if ((header[1] & ~(0x80)) == 2)
				{
					if ((status = transport_read_layer_bytes(transport, s, 2)) != 1)
						return status;
					pduLength = (header[2] << 8) | header[3];
					pduLength += 4;
				}
				else
				{
					fprintf(stderr, "Error reading TSRequest!\n");
					return -1;
				}
			}
			else
			{
				pduLength = header[1];
				pduLength += 2;
			}
		}
	}
	else
	{
		if (header[0] == 0x03)
		{
			/* TPKT header */
			if ((status = transport_read_layer_bytes(transport, s, 2)) != 1)
				return status;

			pduLength = (header[2] << 8) | header[3];

			/* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */
			if (pduLength < 7 || pduLength > 0xFFFF)
			{
				fprintf(stderr, "%s: tpkt - invalid pduLength: %d\n", __FUNCTION__, pduLength);
				return -1;
			}
		}
		else
		{
			/* Fast-Path Header */
			if (header[1] & 0x80)
			{
				if ((status = transport_read_layer_bytes(transport, s, 1)) != 1)
					return status;
				pduLength = ((header[1] & 0x7F) << 8) | header[2];
			}
			else
				pduLength = header[1];

			/*
			 * fast-path has 7 bits for length so the maximum size, including headers is 0x8000
			 * The theoretical minimum fast-path PDU consists only of two header bytes plus one
			 * byte for data (e.g. fast-path input synchronize pdu)
			 */
			if (pduLength < 3 || pduLength > 0x8000)
			{
				fprintf(stderr, "%s: fast path - invalid pduLength: %d\n", __FUNCTION__, pduLength);
				return -1;
			}
		}
	}


	Stream_EnsureCapacity(s, Stream_GetPosition(s) + pduLength);

	status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s));

	if (status != 1)
		return status;

#ifdef WITH_DEBUG_TRANSPORT
	/* dump when whole PDU is read */
	if (Stream_GetPosition(s) >= pduLength)
	{
		fprintf(stderr, "Local < Remote\n");
		winpr_HexDump(Stream_Buffer(s), pduLength);
	}
#endif

	if (Stream_GetPosition(s) >= pduLength)
		WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);

	Stream_SealLength(s);
	Stream_SetPosition(s, 0);
	return Stream_Length(s);
}
Пример #22
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
UINT rdpei_server_handle_messages(RdpeiServerContext *context) {
	DWORD bytesReturned;
	RdpeiServerPrivate *priv = context->priv;
	wStream *s = priv->inputStream;
	UINT error = CHANNEL_RC_OK;

	if (!WTSVirtualChannelRead(priv->channelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned))
	{
		if (GetLastError() == ERROR_NO_DATA)
			return ERROR_READ_FAULT;

		WLog_DBG(TAG, "channel connection closed");
		return CHANNEL_RC_OK;
	}
	priv->expectedBytes -= bytesReturned;
	Stream_Seek(s, bytesReturned);

	if (priv->expectedBytes)
		return CHANNEL_RC_OK;

	Stream_SealLength(s);
	Stream_SetPosition(s, 0);

	if (priv->waitingHeaders)
	{
		UINT32 pduLen;

		/* header case */
		Stream_Read_UINT16(s, priv->currentMsgType);
		Stream_Read_UINT16(s, pduLen);

		if (pduLen < RDPINPUT_HEADER_LENGTH)
		{
			WLog_ERR(TAG, "invalid pduLength %d", pduLen);
			return ERROR_INVALID_DATA;
		}
		priv->expectedBytes = pduLen - RDPINPUT_HEADER_LENGTH;
		priv->waitingHeaders = FALSE;
		Stream_SetPosition(s, 0);
		if (priv->expectedBytes)
		{
			if (!Stream_EnsureCapacity(s, priv->expectedBytes))
			{
				WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
				return CHANNEL_RC_NO_MEMORY;
			}
			return CHANNEL_RC_OK;
		}
	}

	/* when here we have the header + the body */
	switch (priv->currentMsgType)
	{
	case EVENTID_CS_READY:
		if (priv->automataState != STATE_WAITING_CLIENT_READY)
		{
			WLog_ERR(TAG, "not expecting a CS_READY packet in this state(%d)", (int)priv->automataState);
			return ERROR_INVALID_STATE;
		}

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

	case EVENTID_TOUCH:
		if ((error = read_touch_event(context, s)))
		{
			WLog_ERR(TAG, "read_touch_event failed with error %lu", error);
			return error;
		}
		break;
	case EVENTID_DISMISS_HOVERING_CONTACT:
		if ((error = read_dismiss_hovering_contact(context, s)))
		{
			WLog_ERR(TAG, "read_dismiss_hovering_contact failed with error %lu", error);
			return error;
		}
		break;
	default:
		WLog_ERR(TAG, "unexpected message type 0x%x", priv->currentMsgType);
	}

	Stream_SetPosition(s, 0);
	priv->waitingHeaders = TRUE;
	priv->expectedBytes = RDPINPUT_HEADER_LENGTH;
	return error;
}
Пример #23
0
BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size)
{
	DWORD i;
	int left;
	wStream* s;
	UINT32 flags;
	int chunkSize;
	rdpMcs* mcs = rdp->mcs;
	rdpMcsChannel* channel = NULL;

	for (i = 0; i < mcs->channelCount; i++)
	{
		if (mcs->channels[i].ChannelId == channelId)
		{
			channel = &mcs->channels[i];
			break;
		}
	}

	if (!channel)
	{
		WLog_ERR(TAG,  "freerdp_channel_send: unknown channelId %"PRIu16"", channelId);
		return FALSE;
	}

	flags = CHANNEL_FLAG_FIRST;
	left = size;

	while (left > 0)
	{
		s = rdp_send_stream_init(rdp);

		if (!s)
			return FALSE;

		if (left > (int) rdp->settings->VirtualChannelChunkSize)
		{
			chunkSize = rdp->settings->VirtualChannelChunkSize;
		}
		else
		{
			chunkSize = left;
			flags |= CHANNEL_FLAG_LAST;
		}

		if ((channel->options & CHANNEL_OPTION_SHOW_PROTOCOL))
		{
			flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
		}

		Stream_Write_UINT32(s, size);
		Stream_Write_UINT32(s, flags);

		if (!Stream_EnsureCapacity(s, chunkSize))
		{
			Stream_Release(s);
			return FALSE;
		}

		Stream_Write(s, data, chunkSize);

		/* WLog_DBG(TAG, "%s: sending data (flags=0x%x size=%d)", __FUNCTION__, flags, size); */
		if (!rdp_send(rdp, s, channelId))
		{
			Stream_Release(s);
			return FALSE;
		}

		data += chunkSize;
		left -= chunkSize;
		flags = 0;
	}

	return TRUE;
}
Пример #24
0
BOOL rdpsnd_server_handle_messages(RdpsndServerContext *context)
{
	DWORD bytesReturned;
	BOOL ret;

	RdpsndServerPrivate *priv = context->priv;
	wStream *s = priv->input_stream;

	if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned))
	{
		if (GetLastError() == ERROR_NO_DATA)
			return TRUE;

		CLOG_ERR( "%s: channel connection closed\n", __FUNCTION__);
		return FALSE;
	}
	priv->expectedBytes -= bytesReturned;
	Stream_Seek(s, bytesReturned);

	if (priv->expectedBytes)
		return TRUE;

	Stream_SetPosition(s, 0);
	if (priv->waitingHeader)
	{
		/* header case */
		Stream_Read_UINT8(s, priv->msgType);
		Stream_Seek_UINT8(s); /* bPad */
		Stream_Read_UINT16(s, priv->expectedBytes);

		priv->waitingHeader = FALSE;
		Stream_SetPosition(s, 0);
		if (priv->expectedBytes)
		{
			Stream_EnsureCapacity(s, priv->expectedBytes);
			return TRUE;
		}
	}

	/* when here we have the header + the body */
#ifdef WITH_DEBUG_SND
	CLOG_ERR( "%s: message type %d\n", __FUNCTION__, priv->msgType);
#endif
	priv->expectedBytes = 4;
	priv->waitingHeader = TRUE;

	switch (priv->msgType)
	{
		case SNDC_WAVECONFIRM:
			ret = rdpsnd_server_recv_waveconfirm(context, s);
			break;

		case SNDC_FORMATS:
			ret = rdpsnd_server_recv_formats(context, s);
			break;

		case SNDC_QUALITYMODE:
			ret = rdpsnd_server_recv_quality_mode(context, s);
			Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */

			if (ret)
			{
				IFCALL(context->Activated, context);
			}
			break;

		default:
			CLOG_ERR( "%s: UNKOWN MESSAGE TYPE!! (%#0X)\n\n", __FUNCTION__, priv->msgType);
			ret = FALSE;
			break;
	}
	Stream_SetPosition(s, 0);

	return ret;
}
Пример #25
0
int rpc_client_on_fragment_received_event(rdpRpc* rpc)
{
	BYTE* buffer;
	UINT32 StubOffset;
	UINT32 StubLength;
	wStream* fragment;
	rpcconn_hdr_t* header;
	freerdp* instance;

	instance = (freerdp*) rpc->transport->settings->instance;

	if (!rpc->client->pdu)
		rpc->client->pdu = rpc_client_receive_pool_take(rpc);

	fragment = Queue_Dequeue(rpc->client->FragmentQueue);

	buffer = (BYTE*) Stream_Buffer(fragment);
	header = (rpcconn_hdr_t*) Stream_Buffer(fragment);

	if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
	{
		rpc->client->pdu->Flags = 0;
		rpc->client->pdu->CallId = header->common.call_id;

		Stream_EnsureCapacity(rpc->client->pdu->s, Stream_Length(fragment));
		Stream_Write(rpc->client->pdu->s, buffer, Stream_Length(fragment));
		Stream_Length(rpc->client->pdu->s) = Stream_GetPosition(rpc->client->pdu->s);

		rpc_client_fragment_pool_return(rpc, fragment);

		Queue_Enqueue(rpc->client->ReceiveQueue, rpc->client->pdu);
		SetEvent(rpc->transport->ReceiveEvent);
		rpc->client->pdu = NULL;

		return 0;
	}

	if (header->common.ptype == PTYPE_RTS)
	{
		if (rpc->VirtualConnection->State >= VIRTUAL_CONNECTION_STATE_OPENED)
		{
			//fprintf(stderr, "Receiving Out-of-Sequence RTS PDU\n");
			rts_recv_out_of_sequence_pdu(rpc, buffer, header->common.frag_length);

			rpc_client_fragment_pool_return(rpc, fragment);
		}
		else
		{
			fprintf(stderr, "warning: unhandled RTS PDU\n");
		}

		return 0;
	}
	else if (header->common.ptype == PTYPE_FAULT)
	{
		rpc_recv_fault_pdu(header);
		return -1;
	}

	if (header->common.ptype != PTYPE_RESPONSE)
	{
		fprintf(stderr, "Unexpected RPC PDU type: %d\n", header->common.ptype);
		return -1;
	}

	rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length;
	rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header->common.frag_length;

	if (!rpc_get_stub_data_info(rpc, buffer, &StubOffset, &StubLength))
	{
		fprintf(stderr, "rpc_recv_pdu_fragment: expected stub\n");
		return -1;
	}

	if (StubLength == 4)
	{
		//fprintf(stderr, "Ignoring TsProxySendToServer Response\n");
		printf("Got stub length 4 with flags %d and callid %d\n", header->common.pfc_flags, header->common.call_id);

		/* received a disconnect request from the server? */
		if ((header->common.call_id == rpc->PipeCallId) && (header->common.pfc_flags & PFC_LAST_FRAG))
		{
			TerminateEventArgs e;

			instance->context->rdp->disconnect = TRUE;
			rpc->transport->tsg->state = TSG_STATE_TUNNEL_CLOSE_PENDING;

			EventArgsInit(&e, "freerdp");
			e.code = 0;
			PubSub_OnTerminate(instance->context->pubSub, instance->context, &e);
		}

		rpc_client_fragment_pool_return(rpc, fragment);
		return 0;
	}

	Stream_EnsureCapacity(rpc->client->pdu->s, header->response.alloc_hint);
	buffer = (BYTE*) Stream_Buffer(fragment);
	header = (rpcconn_hdr_t*) Stream_Buffer(fragment);

	if (rpc->StubFragCount == 0)
		rpc->StubCallId = header->common.call_id;

	if (rpc->StubCallId != header->common.call_id)
	{
		fprintf(stderr, "invalid call_id: actual: %d, expected: %d, frag_count: %d\n",
				rpc->StubCallId, header->common.call_id, rpc->StubFragCount);
	}

	Stream_Write(rpc->client->pdu->s, &buffer[StubOffset], StubLength);
	rpc->StubFragCount++;

	rpc_client_fragment_pool_return(rpc, fragment);

	if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < (rpc->ReceiveWindow / 2))
	{
		//fprintf(stderr, "Sending Flow Control Ack PDU\n");
		rts_send_flow_control_ack_pdu(rpc);
	}

	/**
	 * If alloc_hint is set to a nonzero value and a request or a response is fragmented into multiple
	 * PDUs, implementations of these extensions SHOULD set the alloc_hint field in every PDU to be the
	 * combined stub data length of all remaining fragment PDUs.
	 */

	if (header->response.alloc_hint == StubLength)
	{
		rpc->client->pdu->Flags = RPC_PDU_FLAG_STUB;
		rpc->client->pdu->CallId = rpc->StubCallId;

		Stream_Length(rpc->client->pdu->s) = Stream_GetPosition(rpc->client->pdu->s);

		rpc->StubFragCount = 0;
		rpc->StubCallId = 0;

		Queue_Enqueue(rpc->client->ReceiveQueue, rpc->client->pdu);

		rpc->client->pdu = NULL;

		return 0;
	}

	return 0;
}
Пример #26
0
int rpc_client_on_fragment_received_event(rdpRpc* rpc)
{
	BYTE* buffer;
	UINT32 StubOffset;
	UINT32 StubLength;
	wStream* fragment;
	rpcconn_hdr_t* header;

	if (!rpc->client->pdu)
		rpc->client->pdu = rpc_client_receive_pool_take(rpc);

	fragment = Queue_Dequeue(rpc->client->FragmentQueue);

	buffer = (BYTE*) Stream_Buffer(fragment);
	header = (rpcconn_hdr_t*) Stream_Buffer(fragment);

	if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
	{
		rpc->client->pdu->Flags = 0;
		rpc->client->pdu->CallId = header->common.call_id;

		Stream_EnsureCapacity(rpc->client->pdu->s, Stream_Length(fragment));
		Stream_Write(rpc->client->pdu->s, buffer, Stream_Length(fragment));
		Stream_Length(rpc->client->pdu->s) = Stream_Position(rpc->client->pdu->s);

		rpc_client_fragment_pool_return(rpc, fragment);

		Queue_Enqueue(rpc->client->ReceiveQueue, rpc->client->pdu);
		SetEvent(rpc->transport->ReceiveEvent);
		rpc->client->pdu = NULL;

		return 0;
	}

	if (header->common.ptype == PTYPE_RTS)
	{
		if (rpc->VirtualConnection->State >= VIRTUAL_CONNECTION_STATE_OPENED)
		{
			//printf("Receiving Out-of-Sequence RTS PDU\n");
			rts_recv_out_of_sequence_pdu(rpc, buffer, header->common.frag_length);

			rpc_client_fragment_pool_return(rpc, fragment);
		}
		else
		{
			printf("warning: unhandled RTS PDU\n");
		}

		return 0;
	}
	else if (header->common.ptype == PTYPE_FAULT)
	{
		rpc_recv_fault_pdu(header);
		return -1;
	}

	if (header->common.ptype != PTYPE_RESPONSE)
	{
		printf("Unexpected RPC PDU type: %d\n", header->common.ptype);
		return -1;
	}

	rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length;
	rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header->common.frag_length;

	if (!rpc_get_stub_data_info(rpc, buffer, &StubOffset, &StubLength))
	{
		printf("rpc_recv_pdu_fragment: expected stub\n");
		return -1;
	}

	if (StubLength == 4)
	{
		//printf("Ignoring TsProxySendToServer Response\n");
		rpc_client_fragment_pool_return(rpc, fragment);
		return 0;
	}

	Stream_EnsureCapacity(rpc->client->pdu->s, header->response.alloc_hint);
	buffer = (BYTE*) Stream_Buffer(fragment);
	header = (rpcconn_hdr_t*) Stream_Buffer(fragment);

	if (rpc->StubFragCount == 0)
		rpc->StubCallId = header->common.call_id;

	if (rpc->StubCallId != header->common.call_id)
	{
		printf("invalid call_id: actual: %d, expected: %d, frag_count: %d\n",
				rpc->StubCallId, header->common.call_id, rpc->StubFragCount);
	}

	Stream_Write(rpc->client->pdu->s, &buffer[StubOffset], StubLength);
	rpc->StubFragCount++;

	rpc_client_fragment_pool_return(rpc, fragment);

	if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < (rpc->ReceiveWindow / 2))
	{
		//printf("Sending Flow Control Ack PDU\n");
		rts_send_flow_control_ack_pdu(rpc);
	}

	/**
	 * If alloc_hint is set to a nonzero value and a request or a response is fragmented into multiple
	 * PDUs, implementations of these extensions SHOULD set the alloc_hint field in every PDU to be the
	 * combined stub data length of all remaining fragment PDUs.
	 */

	if (header->response.alloc_hint == StubLength)
	{
		rpc->client->pdu->Flags = RPC_PDU_FLAG_STUB;
		rpc->client->pdu->CallId = rpc->StubCallId;

		Stream_Length(rpc->client->pdu->s) = Stream_Position(rpc->client->pdu->s);

		rpc->StubFragCount = 0;
		rpc->StubCallId = 0;

		Queue_Enqueue(rpc->client->ReceiveQueue, rpc->client->pdu);

		rpc->client->pdu = NULL;

		return 0;
	}

	return 0;
}
Пример #27
0
BOOL rts_connect(rdpRpc* rpc)
{
	RPC_PDU* pdu;
	rpcconn_rts_hdr_t* rts;
	HttpResponse* http_response;
	freerdp* instance = (freerdp*) rpc->settings->instance;
	rdpContext* context = instance->context;

	/**
	 * Connection Opening
	 *
	 * When opening a virtual connection to the server, an implementation of this protocol MUST perform
	 * the following sequence of steps:
	 *
	 * 1. Send an IN channel request as specified in section 2.1.2.1.1, containing the connection timeout,
	 *    ResourceType UUID, and Session UUID values, if any, supplied by the higher-layer protocol or application.
	 *
	 * 2. Send an OUT channel request as specified in section 2.1.2.1.2.
	 *
	 * 3. Send a CONN/A1 RTS PDU as specified in section 2.2.4.2
	 *
	 * 4. Send a CONN/B1 RTS PDU as specified in section 2.2.4.5
	 *
	 * 5. Wait for the connection establishment protocol sequence as specified in 3.2.1.5.3.1 to complete
	 *
	 * An implementation MAY execute steps 1 and 2 in parallel. An implementation SHOULD execute steps
	 * 3 and 4 in parallel. An implementation MUST execute step 3 after completion of step 1 and execute
	 * step 4 after completion of step 2.
	 *
	 */

	rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
	WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_INITIAL");

	rpc->client->SynchronousSend = TRUE;
	rpc->client->SynchronousReceive = TRUE;

	if (!rpc_ntlm_http_out_connect(rpc))
	{
		WLog_ERR(TAG, "rpc_out_connect_http error!");
		return FALSE;
	}

	if (rts_send_CONN_A1_pdu(rpc) != 0)
	{
		WLog_ERR(TAG, "rpc_send_CONN_A1_pdu error!");
		return FALSE;
	}

	if (!rpc_ntlm_http_in_connect(rpc))
	{
		WLog_ERR(TAG, "rpc_in_connect_http error!");
		return FALSE;
	}

	if (rts_send_CONN_B1_pdu(rpc) < 0)
	{
		WLog_ERR(TAG, "rpc_send_CONN_B1_pdu error!");
		return FALSE;
	}

	rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT;
	WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT");

	/**
	 * Receive OUT Channel Response
	 *
	 * A client implementation MUST NOT accept the OUT channel HTTP response in any state other than
	 * Out Channel Wait. If received in any other state, this HTTP response is a protocol error. Therefore,
	 * the client MUST consider the virtual connection opening a failure and indicate this to higher layers
	 * in an implementation-specific way. The Microsoft Windows® implementation returns
	 * RPC_S_PROTOCOL_ERROR, as specified in [MS-ERREF], to higher-layer protocols.
	 *
	 * If this HTTP response is received in Out Channel Wait state, the client MUST process the fields of
	 * this response as defined in this section.
	 *
	 * First, the client MUST determine whether the response indicates a success or a failure. If the status
	 * code is set to 200, the client MUST interpret this as a success, and it MUST do the following:
	 *
	 * 1. Ignore the values of all other header fields.
	 *
	 * 2. Transition to Wait_A3W state.
	 *
	 * 3. Wait for network events.
	 *
	 * 4. Skip the rest of the processing in this section.
	 *
	 * If the status code is not set to 200, the client MUST interpret this as a failure and follow the same
	 * processing rules as specified in section 3.2.2.5.6.
	 *
	 */

	http_response = http_response_recv(rpc->TlsOut);
	if (!http_response)
	{
		WLog_ERR(TAG, "unable to retrieve OUT Channel Response!");
		return FALSE;
	}

	if (http_response->StatusCode != HTTP_STATUS_OK)
	{
		WLog_ERR(TAG, "error! Status Code: %d", http_response->StatusCode);
		http_response_print(http_response);
		http_response_free(http_response);

		if (http_response->StatusCode == HTTP_STATUS_DENIED)
		{
			if (!connectErrorCode)
			{
				connectErrorCode = AUTHENTICATIONERROR;
			}

			if (!freerdp_get_last_error(context))
			{
				freerdp_set_last_error(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
			}
		}

		return FALSE;
	}

	if (http_response->bodyLen)
	{
		/* inject bytes we have read in the body as a received packet for the RPC client */
		rpc->client->RecvFrag = rpc_client_fragment_pool_take(rpc);
		Stream_EnsureCapacity(rpc->client->RecvFrag, http_response->bodyLen);
		CopyMemory(rpc->client->RecvFrag, http_response->BodyContent,  http_response->bodyLen);
	}

	//http_response_print(http_response);
	http_response_free(http_response);

	rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_A3W;
	WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_WAIT_A3W");

	/**
	 * Receive CONN_A3 RTS PDU
	 *
	 * A client implementation MUST NOT accept the CONN/A3 RTS PDU in any state other than
	 * Wait_A3W. If received in any other state, this PDU is a protocol error and the client
	 * MUST consider the virtual connection opening a failure and indicate this to higher
	 * layers in an implementation-specific way.
	 *
	 * Set the ConnectionTimeout in the Ping Originator of the Client's IN Channel to the
	 * ConnectionTimeout in the CONN/A3 PDU.
	 *
	 * If this RTS PDU is received in Wait_A3W state, the client MUST transition the state
	 * machine to Wait_C2 state and wait for network events.
	 *
	 */

	rpc_client_start(rpc);

	pdu = rpc_recv_dequeue_pdu(rpc);

	if (!pdu)
		return FALSE;

	rts = (rpcconn_rts_hdr_t*) Stream_Buffer(pdu->s);

	if (!rts_match_pdu_signature(rpc, &RTS_PDU_CONN_A3_SIGNATURE, rts))
	{
		WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/A3");
		return FALSE;
	}

	rts_recv_CONN_A3_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s));

	rpc_client_receive_pool_return(rpc, pdu);

	rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_C2;
	WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_WAIT_C2");

	/**
	 * Receive CONN_C2 RTS PDU
	 *
	 * A client implementation MUST NOT accept the CONN/C2 RTS PDU in any state other than Wait_C2.
	 * If received in any other state, this PDU is a protocol error and the client MUST consider the virtual
	 * connection opening a failure and indicate this to higher layers in an implementation-specific way.
	 *
	 * If this RTS PDU is received in Wait_C2 state, the client implementation MUST do the following:
	 *
	 * 1. Transition the state machine to opened state.
	 *
	 * 2. Set the connection time-out protocol variable to the value of the ConnectionTimeout field from
	 *    the CONN/C2 RTS PDU.
	 *
	 * 3. Set the PeerReceiveWindow value in the SendingChannel of the Client IN Channel to the
	 *    ReceiveWindowSize value in the CONN/C2 PDU.
	 *
	 * 4. Indicate to higher-layer protocols that the virtual connection opening is a success.
	 *
	 */

	pdu = rpc_recv_dequeue_pdu(rpc);
	if (!pdu)
		return FALSE;

	rts = (rpcconn_rts_hdr_t*) Stream_Buffer(pdu->s);

	if (!rts_match_pdu_signature(rpc, &RTS_PDU_CONN_C2_SIGNATURE, rts))
	{
		WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/C2");
		return FALSE;
	}

	rts_recv_CONN_C2_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s));

	rpc_client_receive_pool_return(rpc, pdu);

	rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_OPENED;
	WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_OPENED");

	rpc->client->SynchronousSend = TRUE;
	rpc->client->SynchronousReceive = TRUE;

	return TRUE;
}
Пример #28
0
int rdpei_server_handle_messages(RdpeiServerContext *context) {
	DWORD bytesReturned;
	RdpeiServerPrivate *priv = context->priv;
	wStream *s = priv->inputStream;

	if (!WTSVirtualChannelRead(priv->channelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned))
	{
		if (GetLastError() == ERROR_NO_DATA)
			return -1;

		fprintf(stderr, "%s: channel connection closed\n", __FUNCTION__);
		return 0;
	}
	priv->expectedBytes -= bytesReturned;
	Stream_Seek(s, bytesReturned);

	if (priv->expectedBytes)
		return 1;

	Stream_SealLength(s);
	Stream_SetPosition(s, 0);

	if (priv->waitingHeaders)
	{
		UINT32 pduLen;

		/* header case */
		Stream_Read_UINT16(s, priv->currentMsgType);
		Stream_Read_UINT16(s, pduLen);

		if (pduLen < RDPINPUT_HEADER_LENGTH)
		{
			fprintf(stderr, "%s: invalid pduLength %d\n", __FUNCTION__, pduLen);
			return -1;
		}
		priv->expectedBytes = pduLen - RDPINPUT_HEADER_LENGTH;
		priv->waitingHeaders = FALSE;
		Stream_SetPosition(s, 0);
		if (priv->expectedBytes)
		{
			Stream_EnsureCapacity(s, priv->expectedBytes);
			return 1;
		}
	}

	/* when here we have the header + the body */
	switch (priv->currentMsgType)
	{
	case EVENTID_CS_READY:
		if (priv->automataState != STATE_WAITING_CLIENT_READY)
		{
			fprintf(stderr, "%s: not expecting a CS_READY packet in this state(%d)\n", __FUNCTION__, (int)priv->automataState);
			return 0;
		}

		if (read_cs_ready_message(context, s) < 0)
			return 0;
		break;

	case EVENTID_TOUCH:
		if (read_touch_event(context, s) < 0)
		{
			fprintf(stderr, "%s: error in touch event packet\n", __FUNCTION__);
			return 0;
		}
		break;
	case EVENTID_DISMISS_HOVERING_CONTACT:
		if (read_dismiss_hovering_contact(context, s) < 0)
		{
			fprintf(stderr, "%s: error reading read_dismiss_hovering_contact\n", __FUNCTION__);
			return 0;
		}
		break;
	default:
		fprintf(stderr, "%s: unexpected message type 0x%x\n", __FUNCTION__, priv->currentMsgType);
	}

	Stream_SetPosition(s, 0);
	priv->waitingHeaders = TRUE;
	priv->expectedBytes = RDPINPUT_HEADER_LENGTH;
	return 1;
}