Exemple #1
0
static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
{
	TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
	int len;
	int frame_size;
	UINT32 src_size;
	const BYTE *src;
	BYTE *dst;
	int dst_offset;
#if 0
	WLog_DBG(TAG, ("tsmf_ffmpeg_decode_audio: data_size %d", data_size));
	int i;
	for(i = 0; i < data_size; i++)
	{
		WLog_DBG(TAG, ("%02X ", data[i]));
		if (i % 16 == 15)
			WLog_DBG(TAG, ("\n"));
	}
#endif
	if (mdecoder->decoded_size_max == 0)
		mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16;

	mdecoder->decoded_data = calloc(1, mdecoder->decoded_size_max);
	if (!mdecoder->decoded_data)
		return FALSE;

	/* align the memory for SSE2 needs */
	dst = (BYTE *)(((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F);
	dst_offset = dst - mdecoder->decoded_data;
	src = data;
	src_size = data_size;
	while(src_size > 0)
	{
		/* Ensure enough space for decoding */
		if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE)
		{
			BYTE *tmp_data;

			tmp_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max * 2 + 16);
			if (!tmp_data)
				return FALSE;
			mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16;
			mdecoder->decoded_data = tmp_data;

			dst = (BYTE *)(((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
			if (dst - mdecoder->decoded_data != dst_offset)
			{
				/* re-align the memory if the alignment has changed after realloc */
				memmove(dst, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
				dst_offset = dst - mdecoder->decoded_data;
			}
			dst += mdecoder->decoded_size;
		}
		frame_size = mdecoder->decoded_size_max - mdecoder->decoded_size;
#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
		len = avcodec_decode_audio2(mdecoder->codec_context,
									(int16_t *) dst, &frame_size, src, src_size);
#else
		{
			AVFrame *decoded_frame = avcodec_alloc_frame();
			int got_frame = 0;
			AVPacket pkt;
			av_init_packet(&pkt);
			pkt.data = (BYTE *) src;
			pkt.size = src_size;
			len = avcodec_decode_audio4(mdecoder->codec_context, decoded_frame, &got_frame, &pkt);
			if (len >= 0 && got_frame)
			{
				frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels,
														decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1);
				memcpy(dst, decoded_frame->data[0], frame_size);
			}
			av_free(decoded_frame);
		}
#endif
		if (len <= 0 || frame_size <= 0)
		{
			WLog_ERR(TAG, "error decoding");
			break;
		}
		src += len;
		src_size -= len;
		mdecoder->decoded_size += frame_size;
		dst += frame_size;
	}
	if (mdecoder->decoded_size == 0)
	{
		free(mdecoder->decoded_data);
		mdecoder->decoded_data = NULL;
	}
	else
		if (dst_offset)
		{
			/* move the aligned decoded data to original place */
			memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
		}
	DEBUG_TSMF("data_size %d decoded_size %d",
			   data_size, mdecoder->decoded_size);
	return TRUE;
}
Exemple #2
0
void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
{
	WLog_DBG(TAG, "Enabling RDP security: %s", enable_rdp ? "TRUE" : "FALSE");
	nego->EnabledProtocols[PROTOCOL_RDP] = enable_rdp;
}
Exemple #3
0
void nego_enable_nla(rdpNego* nego, BOOL enable_nla)
{
	WLog_DBG(TAG, "Enabling NLA security: %s", enable_nla ? "TRUE" : "FALSE");
	nego->EnabledProtocols[PROTOCOL_NLA] = enable_nla;
}
Exemple #4
0
static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
{
	int i;
	void* sin_addr;
	int peer_sockfd;
	freerdp_peer* client = NULL;
	socklen_t peer_addr_size;
	struct sockaddr_storage peer_addr;
	rdpListener* listener = (rdpListener*) instance->listener;
	static const BYTE localhost6_bytes[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };

	if (listener->num_sockfds < 1)
		return FALSE;

	for (i = 0; i < listener->num_sockfds; i++)
	{
		peer_addr_size = sizeof(peer_addr);
		peer_sockfd = accept(listener->sockfds[i], (struct sockaddr*) &peer_addr, &peer_addr_size);

		if (peer_sockfd == -1)
		{
#ifdef _WIN32
			int wsa_error = WSAGetLastError();

			/* No data available */
			if (wsa_error == WSAEWOULDBLOCK)
				continue;
#else
			if (errno == EAGAIN || errno == EWOULDBLOCK)
				continue;
#endif
			WLog_DBG(TAG, "accept");

			if (client)
				free(client);
			return FALSE;
		}

		client = freerdp_peer_new(peer_sockfd);

		sin_addr = NULL;
		if (peer_addr.ss_family == AF_INET)
		{
			sin_addr = &(((struct sockaddr_in*) &peer_addr)->sin_addr);
			if ((*(UINT32*) sin_addr) == 0x0100007f)
				client->local = TRUE;
		}
		else if (peer_addr.ss_family == AF_INET6)
		{
			sin_addr = &(((struct sockaddr_in6*) &peer_addr)->sin6_addr);
			if (memcmp(sin_addr, localhost6_bytes, 16) == 0)
				client->local = TRUE;
		}
#ifndef _WIN32
		else if (peer_addr.ss_family == AF_UNIX)
			client->local = TRUE;
#endif

		if (sin_addr)
			inet_ntop(peer_addr.ss_family, sin_addr, client->hostname, sizeof(client->hostname));

		IFCALL(instance->PeerAccepted, instance, client);
	}

	return TRUE;
}
Exemple #5
0
void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer)
{
	WLog_DBG(TAG, "Enabling security layer negotiation: %s", NegotiateSecurityLayer ? "TRUE" : "FALSE");
	nego->NegotiateSecurityLayer = NegotiateSecurityLayer;
}
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
{
	int pad;
	UINT32 index;
	MONITOR_DEF* monitor;
	RDPGFX_RESET_GRAPHICS_PDU pdu;
	RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
	RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
	UINT error = CHANNEL_RC_OK;

	if (Stream_GetRemainingLength(s) < 12)
	{
		WLog_ERR(TAG, "not enough data!");
		return ERROR_INVALID_DATA;
	}

	Stream_Read_UINT32(s, pdu.width); /* width (4 bytes) */
	Stream_Read_UINT32(s, pdu.height); /* height (4 bytes) */
	Stream_Read_UINT32(s, pdu.monitorCount); /* monitorCount (4 bytes) */

	if (Stream_GetRemainingLength(s) < (pdu.monitorCount * 20))
	{
		WLog_ERR(TAG, "not enough data!");
		return ERROR_INVALID_DATA;
	}

	pdu.monitorDefArray = (MONITOR_DEF*) calloc(pdu.monitorCount, sizeof(MONITOR_DEF));

	if (!pdu.monitorDefArray)
	{
		WLog_ERR(TAG, "calloc failed!");
		return CHANNEL_RC_NO_MEMORY;
	}

	for (index = 0; index < pdu.monitorCount; index++)
	{
		monitor = &(pdu.monitorDefArray[index]);
		Stream_Read_UINT32(s, monitor->left); /* left (4 bytes) */
		Stream_Read_UINT32(s, monitor->top); /* top (4 bytes) */
		Stream_Read_UINT32(s, monitor->right); /* right (4 bytes) */
		Stream_Read_UINT32(s, monitor->bottom); /* bottom (4 bytes) */
		Stream_Read_UINT32(s, monitor->flags); /* flags (4 bytes) */
	}

	pad = 340 - (RDPGFX_HEADER_SIZE + 12 + (pdu.monitorCount * 20));

	if (Stream_GetRemainingLength(s) < (size_t) pad)
	{
		WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
		free(pdu.monitorDefArray);
		return CHANNEL_RC_NO_MEMORY;
	}

	Stream_Seek(s, pad); /* pad (total size is 340 bytes) */

	WLog_DBG(TAG, "RecvResetGraphicsPdu: width: %d height: %d count: %d",
			pdu.width, pdu.height, pdu.monitorCount);

	if (context)
	{
		IFCALLRET(context->ResetGraphics, error, context, &pdu);
		if (error)
			WLog_ERR(TAG, "context->ResetGraphics failed with error %lu", error);
	}

	free(pdu.monitorDefArray);

	return error;
}
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
{
	UINT16 index;
	RECTANGLE_16* fillRect;
	RDPGFX_SOLID_FILL_PDU pdu;
	RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
	RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
	UINT error;

	if (Stream_GetRemainingLength(s) < 8)
	{
		WLog_ERR(TAG, "not enough data!");
		return ERROR_INVALID_DATA;
	}

	Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */
	if ((error = rdpgfx_read_color32(s, &(pdu.fillPixel)))) /* fillPixel (4 bytes) */
	{
		WLog_ERR(TAG, "rdpgfx_read_color32 failed with error %lu!", error);
		return error;
	}
	Stream_Read_UINT16(s, pdu.fillRectCount); /* fillRectCount (2 bytes) */

	if (Stream_GetRemainingLength(s) < (size_t) (pdu.fillRectCount * 8))
	{
		WLog_ERR(TAG, "not enough data!");
		return ERROR_INVALID_DATA;
	}

	pdu.fillRects = (RECTANGLE_16*) calloc(pdu.fillRectCount, sizeof(RECTANGLE_16));

	if (!pdu.fillRects)
	{
		WLog_ERR(TAG, "calloc failed!");
		return CHANNEL_RC_NO_MEMORY;
	}

	for (index = 0; index < pdu.fillRectCount; index++)
	{
		fillRect = &(pdu.fillRects[index]);
		if ((error = rdpgfx_read_rect16(s, fillRect)))
		{
			WLog_ERR(TAG, "rdpgfx_read_rect16 failed with error %lu!", error);
			free(pdu.fillRects);
			return error;
		}
	}

	WLog_DBG(TAG, "RecvSolidFillPdu: surfaceId: %d fillRectCount: %d",
			pdu.surfaceId, pdu.fillRectCount);

	if (context)
	{
		IFCALLRET(context->SolidFill, error, context, &pdu);
		if (error)
			WLog_ERR(TAG, "context->SolidFill failed with error %lu", error);
	}

	free(pdu.fillRects);

	return error;
}
Exemple #8
0
BOOL tf_peer_post_connect(freerdp_peer* client)
{
	testPeerContext* context = (testPeerContext*) client->context;

	/**
	 * This callback is called when the entire connection sequence is done, i.e. we've received the
	 * Font List PDU from the client and sent out the Font Map PDU.
	 * The server may start sending graphics output and receiving keyboard/mouse input after this
	 * callback returns.
	 */
	WLog_DBG(TAG, "Client %s is activated (osMajorType %d osMinorType %d)", client->local ? "(local)" : client->hostname,
			 client->settings->OsMajorType, client->settings->OsMinorType);

	if (client->settings->AutoLogonEnabled)
	{
		WLog_DBG(TAG, " and wants to login automatically as %s\\%s",
				 client->settings->Domain ? client->settings->Domain : "",
				 client->settings->Username);
		/* A real server may perform OS login here if NLA is not executed previously. */
	}

	WLog_DBG(TAG, "");
	WLog_DBG(TAG, "Client requested desktop: %dx%dx%d",
			 client->settings->DesktopWidth, client->settings->DesktopHeight, client->settings->ColorDepth);
#if (SAMPLE_SERVER_USE_CLIENT_RESOLUTION == 1)
	context->rfx_context->width = client->settings->DesktopWidth;
	context->rfx_context->height = client->settings->DesktopHeight;
	WLog_DBG(TAG, "Using resolution requested by client.");
#else
	client->settings->DesktopWidth = context->rfx_context->width;
	client->settings->DesktopHeight = context->rfx_context->height;
	WLog_DBG(TAG, "Resizing client to %dx%d", client->settings->DesktopWidth, client->settings->DesktopHeight);
	client->update->DesktopResize(client->update->context);
#endif

	/* A real server should tag the peer as activated here and start sending updates in main loop. */
	test_peer_load_icon(client);

	if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpdbg"))
	{
		context->debug_channel = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpdbg");

		if (context->debug_channel != NULL)
		{
			WLog_DBG(TAG, "Open channel rdpdbg.");
			if (!(context->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
			{
				WLog_ERR(TAG, "Failed to create stop event");
				return FALSE;
			}

			if (!(context->debug_channel_thread = CreateThread(NULL, 0,
					(LPTHREAD_START_ROUTINE) tf_debug_channel_thread_func, (void*) context, 0, NULL)))
			{
				WLog_ERR(TAG, "Failed to create debug channel thread");
				CloseHandle(context->stopEvent);
				context->stopEvent = NULL;
				return FALSE;
			}
		}
	}

	if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpsnd"))
	{
		sf_peer_rdpsnd_init(context); /* Audio Output */
	}

	if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "encomsp"))
	{
		sf_peer_encomsp_init(context); /* Lync Multiparty */
	}

	/* Dynamic Virtual Channels */

	sf_peer_audin_init(context); /* Audio Input */

	/* Return FALSE here would stop the execution of the peer main loop. */

	return TRUE;
}
Exemple #9
0
BOOL tf_peer_synchronize_event(rdpInput* input, UINT32 flags)
{
	WLog_DBG(TAG, "Client sent a synchronize event (flags:0x%X)", flags);
	return TRUE;
}
Exemple #10
0
/*
 * Handle rpdsnd messages - server side
 *
 * @param Server side context
 *
 * @return -1 if no data could be read,
 *          0 on error (like connection close),
 *          1 on succsess (also if further bytes need to be read)
 */
int 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 -1;

		WLog_ERR(TAG,  "%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->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 1;
		}
	}

	/* 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 && 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 && context->clientVersion >= 6)
				IFCALL(context->Activated, context);
			break;

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

	if (ret)
		return 1;
	else
		return 0;
}
Exemple #11
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s)
{
	int beg, end;
	RDPGFX_HEADER header;
	UINT error = CHANNEL_RC_OK;
	beg = Stream_GetPosition(s);

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

	WLog_DBG(TAG, "cmdId: %s (0x%04"PRIX16") flags: 0x%04"PRIX16" pduLength: %"PRIu32"",
	         rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId,
	         header.flags, header.pduLength);

	switch (header.cmdId)
	{
		case RDPGFX_CMDID_FRAMEACKNOWLEDGE:
			if ((error = rdpgfx_recv_frame_acknowledge_pdu(context, s)))
				WLog_ERR(TAG, "rdpgfx_recv_frame_acknowledge_pdu "
						"failed with error %"PRIu32"!", error);

			break;

		case RDPGFX_CMDID_CACHEIMPORTOFFER:
			if ((error = rdpgfx_recv_cache_import_offer_pdu(context, s)))
				WLog_ERR(TAG, "rdpgfx_recv_cache_import_offer_pdu "
						"failed with error %"PRIu32"!", error);

			break;

		case RDPGFX_CMDID_CAPSADVERTISE:
			if ((error = rdpgfx_recv_caps_advertise_pdu(context, s)))
				WLog_ERR(TAG, "rdpgfx_recv_caps_advertise_pdu "
						"failed with error %"PRIu32"!", error);

			break;

		case RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE:
			if ((error = rdpgfx_recv_qoe_frame_acknowledge_pdu(context, s)))
				WLog_ERR(TAG, "rdpgfx_recv_qoe_frame_acknowledge_pdu "
						"failed with error %"PRIu32"!", error);

			break;

		default:
			error = CHANNEL_RC_BAD_PROC;
			break;
	}

	if (error)
	{
		WLog_ERR(TAG,  "Error while parsing GFX cmdId: %s (0x%04"PRIX16")",
		         rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId);
		return error;
	}

	end = Stream_GetPosition(s);

	if (end != (beg + header.pduLength))
	{
		WLog_ERR(TAG,  "Unexpected gfx pdu end: Actual: %d, Expected: %"PRIu32"",
		         end, (beg + header.pduLength));
		Stream_SetPosition(s, (beg + header.pduLength));
	}

	return error;
}
Exemple #12
0
int transport_write(rdpTransport* transport, wStream* s)
{
	int length;
	int status = -1;
	EnterCriticalSection(&(transport->WriteLock));
	length = Stream_GetPosition(s);
	Stream_SetPosition(s, 0);
#ifdef WITH_DEBUG_TRANSPORT

	if (length > 0)
	{
		WLog_DBG(TAG,  "Local > Remote");
		winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), length);
	}

#endif

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

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

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

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

			if (transport_wait_for_write(transport) < 0)
			{
				WLog_ERR(TAG, "error when selecting for write");
				return -1;
			}

			continue;
		}

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

			while (out->writeBlocked)
			{
				if (transport_wait_for_write(transport) < 0)
				{
					WLog_ERR(TAG, "error when selecting for write");
					return -1;
				}

				if (!transport_bio_buffered_drain(out->bufferedBio))
				{
					WLog_ERR(TAG, "error when draining outputBuffer");
					return -1;
				}
			}
		}

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

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

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

	LeaveCriticalSection(&(transport->WriteLock));
	return status;
}
Exemple #13
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
				{
					WLog_ERR(TAG,  "Error reading TSRequest!");
					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)
			{
				WLog_ERR(TAG, "tpkt - invalid pduLength: %d", 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)
			{
				WLog_ERR(TAG, "fast path - invalid pduLength: %d", 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)
	{
		WLog_DBG(TAG,  "Local < Remote");
		winpr_HexDump(TAG, WLOG_DEBUG, 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);
}
Exemple #14
0
int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
{
	UINT32 index;
	int rectSize = 2;
	RDPINPUT_CONTACT_DATA* contact;

#ifdef WITH_DEBUG_RDPEI
	WLog_DBG(TAG, "contactCount: %d", frame->contactCount);
	WLog_DBG(TAG, "frameOffset: 0x%08X", (UINT32) frame->frameOffset);
#endif

	rdpei_write_2byte_unsigned(s, frame->contactCount); /* contactCount (TWO_BYTE_UNSIGNED_INTEGER) */

	/**
	 * the time offset from the previous frame (in microseconds).
	 * If this is the first frame being transmitted then this field MUST be set to zero.
	 */
	rdpei_write_8byte_unsigned(s, frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */

	Stream_EnsureRemainingCapacity(s, (size_t) frame->contactCount * 64);

	for (index = 0; index < frame->contactCount; index++)
	{
		contact = &frame->contacts[index];

		contact->fieldsPresent |= CONTACT_DATA_CONTACTRECT_PRESENT;
		contact->contactRectLeft = contact->x - rectSize;
		contact->contactRectTop = contact->y - rectSize;
		contact->contactRectRight = contact->x + rectSize;
		contact->contactRectBottom = contact->y + rectSize;

#ifdef WITH_DEBUG_RDPEI
		WLog_DBG(TAG, "contact[%d].contactId: %d", index, contact->contactId);
		WLog_DBG(TAG, "contact[%d].fieldsPresent: %d", index, contact->fieldsPresent);
		WLog_DBG(TAG, "contact[%d].x: %d", index, contact->x);
		WLog_DBG(TAG, "contact[%d].y: %d", index, contact->y);
		WLog_DBG(TAG, "contact[%d].contactFlags: 0x%04X", index, contact->contactFlags);
		rdpei_print_contact_flags(contact->contactFlags);
#endif

		Stream_Write_UINT8(s, contact->contactId); /* contactId (1 byte) */

		/* fieldsPresent (TWO_BYTE_UNSIGNED_INTEGER) */
		rdpei_write_2byte_unsigned(s, contact->fieldsPresent);

		rdpei_write_4byte_signed(s, contact->x); /* x (FOUR_BYTE_SIGNED_INTEGER) */
		rdpei_write_4byte_signed(s, contact->y); /* y (FOUR_BYTE_SIGNED_INTEGER) */

		/* contactFlags (FOUR_BYTE_UNSIGNED_INTEGER) */
		rdpei_write_4byte_unsigned(s, contact->contactFlags);

		if (contact->fieldsPresent & CONTACT_DATA_CONTACTRECT_PRESENT)
		{
			/* contactRectLeft (TWO_BYTE_SIGNED_INTEGER) */
			rdpei_write_2byte_signed(s, contact->contactRectLeft);
			/* contactRectTop (TWO_BYTE_SIGNED_INTEGER) */
			rdpei_write_2byte_signed(s, contact->contactRectTop);
			/* contactRectRight (TWO_BYTE_SIGNED_INTEGER) */
			rdpei_write_2byte_signed(s, contact->contactRectRight);
			/* contactRectBottom (TWO_BYTE_SIGNED_INTEGER) */
			rdpei_write_2byte_signed(s, contact->contactRectBottom);
		}

		if (contact->fieldsPresent & CONTACT_DATA_ORIENTATION_PRESENT)
		{
			/* orientation (FOUR_BYTE_UNSIGNED_INTEGER) */
			rdpei_write_4byte_unsigned(s, contact->orientation);
		}

		if (contact->fieldsPresent & CONTACT_DATA_PRESSURE_PRESENT)
		{
			/* pressure (FOUR_BYTE_UNSIGNED_INTEGER) */
			rdpei_write_4byte_unsigned(s, contact->pressure);
		}
	}

	return 0;
}
Exemple #15
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
{
	int beg, end;
	RDPGFX_HEADER header;
	UINT error;

	beg = Stream_GetPosition(s);

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

#if 1
	WLog_DBG(TAG, "cmdId: %s (0x%04X) flags: 0x%04X pduLength: %d",
			rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags, header.pduLength);
#endif

	switch (header.cmdId)
	{
		case RDPGFX_CMDID_WIRETOSURFACE_1:
			if ((error = rdpgfx_recv_wire_to_surface_1_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_wire_to_surface_1_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_WIRETOSURFACE_2:
			if ((error = rdpgfx_recv_wire_to_surface_2_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_wire_to_surface_2_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_DELETEENCODINGCONTEXT:
			if ((error = rdpgfx_recv_delete_encoding_context_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_delete_encoding_context_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_SOLIDFILL:
			if ((error = rdpgfx_recv_solid_fill_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_solid_fill_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_SURFACETOSURFACE:
			if ((error = rdpgfx_recv_surface_to_surface_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_surface_to_surface_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_SURFACETOCACHE:
			if ((error = rdpgfx_recv_surface_to_cache_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_surface_to_cache_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_CACHETOSURFACE:
			if ((error = rdpgfx_recv_cache_to_surface_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_cache_to_surface_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_EVICTCACHEENTRY:
			if ((error = rdpgfx_recv_evict_cache_entry_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_evict_cache_entry_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_CREATESURFACE:
			if ((error = rdpgfx_recv_create_surface_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_create_surface_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_DELETESURFACE:
			if ((error = rdpgfx_recv_delete_surface_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_delete_surface_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_STARTFRAME:
			if ((error = rdpgfx_recv_start_frame_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_start_frame_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_ENDFRAME:
			if ((error = rdpgfx_recv_end_frame_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_end_frame_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_RESETGRAPHICS:
			if ((error = rdpgfx_recv_reset_graphics_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_reset_graphics_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_MAPSURFACETOOUTPUT:
			if ((error = rdpgfx_recv_map_surface_to_output_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_map_surface_to_output_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_CACHEIMPORTREPLY:
			if ((error = rdpgfx_recv_cache_import_reply_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_cache_import_reply_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_CAPSCONFIRM:
			if ((error = rdpgfx_recv_caps_confirm_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_caps_confirm_pdu failed with error %lu!", error);
			break;

		case RDPGFX_CMDID_MAPSURFACETOWINDOW:
			if ((error = rdpgfx_recv_map_surface_to_window_pdu(callback, s)))
				WLog_ERR(TAG, "rdpgfx_recv_map_surface_to_window_pdu failed with error %lu!", error);
			break;

		default:
			error = CHANNEL_RC_BAD_PROC;
			break;
	}

	if (error)
	{
		WLog_ERR(TAG,  "Error while parsing GFX cmdId: %s (0x%04X)",
				 rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId);
		return error;
	}

	end = Stream_GetPosition(s);

	if (end != (beg + header.pduLength))
	{
		WLog_ERR(TAG,  "Unexpected gfx pdu end: Actual: %d, Expected: %d",
				 end, (beg + header.pduLength));
		Stream_SetPosition(s, (beg + header.pduLength));
	}

	return error;
}
Exemple #16
0
BOOL tf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{
	WLog_DBG(TAG, "Client sent a unicode keyboard event (flags:0x%X code:0x%X)", flags, code);
	return TRUE;
}
Exemple #17
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_plugin_terminated(IWTSPlugin* pPlugin)
{
	int count;
	int index;
	ULONG_PTR* pKeys = NULL;
	RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin;
	RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
	UINT error = CHANNEL_RC_OK;

	WLog_DBG(TAG, "Terminated");

	if (gfx->listener_callback)
	{
		free(gfx->listener_callback);
		gfx->listener_callback = NULL;
	}

	if (gfx->zgfx)
	{
		zgfx_context_free(gfx->zgfx);
		gfx->zgfx = NULL;
	}

	count = HashTable_GetKeys(gfx->SurfaceTable, &pKeys);

	for (index = 0; index < count; index++)
	{
		RDPGFX_DELETE_SURFACE_PDU pdu;

		pdu.surfaceId = ((UINT16) pKeys[index]) - 1;

		if (context)
		{
			IFCALLRET(context->DeleteSurface, error, context, &pdu);
			if (error)
			{
				WLog_ERR(TAG, "context->DeleteSurface failed with error %lu", error);
				free(pKeys);
				free(context);
				free(gfx);
				return error;
			}
		}
	}

	free(pKeys);

	HashTable_Free(gfx->SurfaceTable);

	for (index = 0; index < gfx->MaxCacheSlot; index++)
	{
		if (gfx->CacheSlots[index])
		{
			RDPGFX_EVICT_CACHE_ENTRY_PDU pdu;

			pdu.cacheSlot = (UINT16) index;

			if (context)
			{
				IFCALLRET(context->EvictCacheEntry, error, context, &pdu);
				if (error)
				{
					WLog_ERR(TAG, "context->EvictCacheEntry failed with error %lu", error);
					free(context);
					free(gfx);
					return error;
				}
			}

			gfx->CacheSlots[index] = NULL;
		}
	}

	free(context);

	free(gfx);

	return CHANNEL_RC_OK;
}
Exemple #18
0
int xcrush_compress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags)
{
	int status = 0;
	UINT32 DstSize = 0;
	BYTE* pDstData = NULL;
	BYTE* CompressedData = NULL;
	UINT32 CompressedDataSize = 0;
	BYTE* OriginalData = NULL;
	UINT32 OriginalDataSize = 0;
	UINT32 Level1ComprFlags = 0;
	UINT32 Level2ComprFlags = 0;
	UINT32 CompressionLevel = 3;

	if (SrcSize > 16384)
		return -1001;

	if ((SrcSize + 2) > *pDstSize)
		return -1002;

	OriginalData = *ppDstData;
	OriginalDataSize = SrcSize;

	pDstData = xcrush->BlockBuffer;
	CompressedDataSize = SrcSize;

	status = xcrush_compress_l1(xcrush, pSrcData, SrcSize, &pDstData, &CompressedDataSize, &Level1ComprFlags);

	if (status < 0)
		return status;

	if (Level1ComprFlags & L1_COMPRESSED)
	{
		CompressedData = pDstData;

		if (CompressedDataSize > SrcSize)
			return -1003;
	}
	else
	{
		CompressedData = pSrcData;

		if (CompressedDataSize != SrcSize)
			return -1004;
	}

	status = 0;

	pDstData = &OriginalData[2];
	DstSize = OriginalDataSize - 2;

	if (CompressedDataSize > 50)
	{
		status = mppc_compress(xcrush->mppc, CompressedData, CompressedDataSize, &pDstData, &DstSize, &Level2ComprFlags);
	}

	if (status < 0)
		return status;

	if (!status || (Level2ComprFlags & PACKET_FLUSHED))
	{
		if (CompressedDataSize > DstSize)
		{
			xcrush_context_reset(xcrush, TRUE);
			*ppDstData = pSrcData;
			*pDstSize = SrcSize;
			*pFlags = 0;
			return 1;
		}

		DstSize = CompressedDataSize;
		CopyMemory(&OriginalData[2], CompressedData, CompressedDataSize);
	}

	if (Level2ComprFlags & PACKET_COMPRESSED)
	{
		Level2ComprFlags |= xcrush->CompressionFlags;
		xcrush->CompressionFlags = 0;
	}
	else if (Level2ComprFlags & PACKET_FLUSHED)
	{
		xcrush->CompressionFlags = PACKET_FLUSHED;
	}

	Level1ComprFlags |= L1_INNER_COMPRESSION;

	OriginalData[0] = (BYTE) Level1ComprFlags;
	OriginalData[1] = (BYTE) Level2ComprFlags;

#if 0
	WLog_DBG(TAG, "XCrushCompress: Level1ComprFlags: %s Level2ComprFlags: %s",
			xcrush_get_level_1_compression_flags_string(Level1ComprFlags),
			xcrush_get_level_2_compression_flags_string(Level2ComprFlags));
#endif

	if (*pDstSize < (DstSize + 2))
		return -1006;

	*pDstSize = DstSize + 2;
	*pFlags = PACKET_COMPRESSED | CompressionLevel;

	return 1;
}
Exemple #19
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[3];
	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;
	}

	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 %lu!", 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 #20
0
BOOL NamedPipeWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
                    LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
{
	int io_status;
	WINPR_NAMED_PIPE* pipe;
	BOOL status = TRUE;

	if (lpOverlapped)
	{
		WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
		SetLastError(ERROR_NOT_SUPPORTED);
		return FALSE;
	}

	pipe = (WINPR_NAMED_PIPE*) Object;

	if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
	{
		if (pipe->clientfd == -1)
			return FALSE;

		do
		{
			io_status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite);
		}
		while ((io_status < 0) && (errno == EINTR));

		if (io_status < 0)
		{
			*lpNumberOfBytesWritten = 0;

			switch (errno)
			{
				case EWOULDBLOCK:
					io_status = 0;
					status = TRUE;
					break;

				default:
					status = FALSE;
			}
		}

		*lpNumberOfBytesWritten = io_status;
		return status;
	}
	else
	{
		/* Overlapped I/O */
		if (!lpOverlapped)
			return FALSE;

		if (pipe->clientfd == -1)
			return FALSE;

		pipe->lpOverlapped = lpOverlapped;
#ifdef HAVE_AIO_H
		{
			struct aiocb cb;
			ZeroMemory(&cb, sizeof(struct aiocb));
			cb.aio_fildes = pipe->clientfd;
			cb.aio_buf = (void*) lpBuffer;
			cb.aio_nbytes = nNumberOfBytesToWrite;
			cb.aio_offset = lpOverlapped->Offset;
			cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
			cb.aio_sigevent.sigev_signo = SIGIO;
			cb.aio_sigevent.sigev_value.sival_ptr = (void*) lpOverlapped;
			InstallAioSignalHandler();
			io_status = aio_write(&cb);
			WLog_DBG("aio_write status: %d", io_status);

			if (io_status < 0)
				status = FALSE;

			return status;
		}
#else
		/* synchronous behavior */
		lpOverlapped->Internal = 1;
		lpOverlapped->InternalHigh = (ULONG_PTR) nNumberOfBytesToWrite;
		lpOverlapped->Pointer = (PVOID) lpBuffer;
		SetEvent(lpOverlapped->hEvent);
#endif
	}

	return TRUE;
}
Exemple #21
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
{
	UINT16 index;
	RDPGFX_POINT16* destPt;
	RDPGFX_SURFACE_TO_SURFACE_PDU pdu;
	RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
	RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
	UINT error;

	if (Stream_GetRemainingLength(s) < 14)
	{
		WLog_ERR(TAG, "not enough data!");
		return ERROR_INVALID_DATA;
	}

	Stream_Read_UINT16(s, pdu.surfaceIdSrc); /* surfaceIdSrc (2 bytes) */
	Stream_Read_UINT16(s, pdu.surfaceIdDest); /* surfaceIdDest (2 bytes) */
	if ((error = rdpgfx_read_rect16(s, &(pdu.rectSrc)))) /* rectSrc (8 bytes ) */
	{
		WLog_ERR(TAG, "rdpgfx_read_rect16 failed with error %lu!", error);
		return error;
	}

	Stream_Read_UINT16(s, pdu.destPtsCount); /* destPtsCount (2 bytes) */

	if (Stream_GetRemainingLength(s) < (size_t) (pdu.destPtsCount * 4))
	{
		WLog_ERR(TAG, "not enough data!");
		return ERROR_INVALID_DATA;
	}

	pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16));

	if (!pdu.destPts)
	{
		WLog_ERR(TAG, "calloc failed!");
		return CHANNEL_RC_NO_MEMORY;
	}

	for (index = 0; index < pdu.destPtsCount; index++)
	{
		destPt = &(pdu.destPts[index]);
		if ((error = rdpgfx_read_point16(s, destPt)))
		{
			WLog_ERR(TAG, "rdpgfx_read_point16 failed with error %lu!", error);
			free(pdu.destPts);
			return error;
		}
	}

	WLog_DBG(TAG, "RecvSurfaceToSurfacePdu: surfaceIdSrc: %d surfaceIdDest: %d "
			"left: %d top: %d right: %d bottom: %d destPtsCount: %d",
			pdu.surfaceIdSrc, pdu.surfaceIdDest,
			pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom,
			pdu.destPtsCount);

	if (context)
	{
		IFCALLRET(context->SurfaceToSurface, error, context, &pdu);
		if (error)
			WLog_ERR(TAG, "context->SurfaceToSurface failed with error %lu", error);
	}

	free(pdu.destPts);

	return error;
}
Exemple #22
0
int nla_client_begin(rdpNla* nla)
{
	if (nla_client_init(nla) < 1)
		return -1;

	if (nla->state != NLA_STATE_INITIAL)
		return -1;

	nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
	nla->outputBufferDesc.cBuffers = 1;
	nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
	nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
	nla->outputBuffer.cbBuffer = nla->cbMaxToken;
	nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);

	if (!nla->outputBuffer.pvBuffer)
		return -1;

	nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
			NULL, nla->ServicePrincipalName, nla->fContextReq, 0,
			SECURITY_NATIVE_DREP, NULL, 0, &nla->context,
			&nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);

	WLog_VRB(TAG, " InitializeSecurityContext status %s [%08X]",
		   GetSecurityStatusString(nla->status), nla->status);

	if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
	{
		if (nla->table->CompleteAuthToken)
		{
			SECURITY_STATUS status;

			status = nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
			if (status != SEC_E_OK)
			{
				WLog_WARN(TAG, "CompleteAuthToken status %s [%08X]",
					  GetSecurityStatusString(status), status);
				return -1;
			}
		}

		if (nla->status == SEC_I_COMPLETE_NEEDED)
			nla->status = SEC_E_OK;
		else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
			nla->status = SEC_I_CONTINUE_NEEDED;
	}

	if (nla->status != SEC_I_CONTINUE_NEEDED)
		return -1;

	if (nla->outputBuffer.cbBuffer < 1)
		return -1;

	nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
	nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;

	WLog_DBG(TAG, "Sending Authentication Token");
	winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);

	if (!nla_send(nla))
	{
		nla_buffer_free(nla);
		return -1;
	}

	nla_buffer_free(nla);

	nla->state = NLA_STATE_NEGO_TOKEN;

	return 1;
}
Exemple #23
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;
	}

	switch (header->common.ptype)
	{
		case PTYPE_RTS:

			if (rpc->VirtualConnection->State < VIRTUAL_CONNECTION_STATE_OPENED)
			{
				WLog_ERR(TAG, "warning: unhandled RTS PDU");
				return 0;
			}

			WLog_DBG(TAG, "Receiving Out-of-Sequence RTS PDU");
			rts_recv_out_of_sequence_pdu(rpc, buffer, header->common.frag_length);
			rpc_client_fragment_pool_return(rpc, fragment);
			return 0;
		case PTYPE_FAULT:
			rpc_recv_fault_pdu(header);
			Queue_Enqueue(rpc->client->ReceiveQueue, NULL);
			return -1;
		case PTYPE_RESPONSE:
			break;
		default:
			WLog_ERR(TAG, "unexpected RPC PDU type %d", header->common.ptype);
			Queue_Enqueue(rpc->client->ReceiveQueue, NULL);
			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))
	{
		WLog_ERR(TAG, "expected stub");
		Queue_Enqueue(rpc->client->ReceiveQueue, NULL);
		return -1;
	}

	if (StubLength == 4)
	{
		//WLog_ERR(TAG,  "Ignoring TsProxySendToServer Response");
		//WLog_DBG(TAG, "Got stub length 4 with flags %d and callid %d", 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)
	{
		WLog_ERR(TAG, "invalid call_id: actual: %d, expected: %d, frag_count: %d",
				 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))
	{
		//WLog_ERR(TAG,  "Sending Flow Control Ack PDU");
		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;
}
Exemple #24
0
int nla_client_recv(rdpNla* nla)
{
	int status = -1;

	if (nla->state == NLA_STATE_NEGO_TOKEN)
	{
		nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
		nla->inputBufferDesc.cBuffers = 1;
		nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
		nla->inputBuffer.BufferType = SECBUFFER_TOKEN;
		nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
		nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;

		nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
		nla->outputBufferDesc.cBuffers = 1;
		nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
		nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
		nla->outputBuffer.cbBuffer = nla->cbMaxToken;
		nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);

		if (!nla->outputBuffer.pvBuffer)
			return -1;

		nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
				&nla->context, nla->ServicePrincipalName, nla->fContextReq, 0,
				SECURITY_NATIVE_DREP, &nla->inputBufferDesc,
				0, &nla->context, &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);

		WLog_VRB(TAG, "InitializeSecurityContext  %s [%08X]",
			   GetSecurityStatusString(nla->status), nla->status);

		free(nla->inputBuffer.pvBuffer);
		nla->inputBuffer.pvBuffer = NULL;

		if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
		{
			if (nla->table->CompleteAuthToken)
			{
				SECURITY_STATUS status;
				status = nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
				if (status != SEC_E_OK)
				{
					WLog_WARN(TAG, "CompleteAuthToken status %s [%08X]",
						  GetSecurityStatusString(status), status);
					return -1;
				}
			}

			if (nla->status == SEC_I_COMPLETE_NEEDED)
				nla->status = SEC_E_OK;
			else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
				nla->status = SEC_I_CONTINUE_NEEDED;
		}

		if (nla->status == SEC_E_OK)
		{
			nla->havePubKeyAuth = TRUE;

			nla->status = nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES, &nla->ContextSizes);
			if (nla->status != SEC_E_OK)
			{
				WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure %s [%08X]",
					 GetSecurityStatusString(nla->status), nla->status);
				return -1;
			}

			nla->status = nla_encrypt_public_key_echo(nla);
			if (nla->status != SEC_E_OK)
				return -1;
		}

		nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
		nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;

		WLog_DBG(TAG, "Sending Authentication Token");
		winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer);

		if (!nla_send(nla))
		{
			nla_buffer_free(nla);
			return -1;
		}
		nla_buffer_free(nla);

		if (nla->status == SEC_E_OK)
			nla->state = NLA_STATE_PUB_KEY_AUTH;
		status = 1;
	}
	else if (nla->state == NLA_STATE_PUB_KEY_AUTH)
	{
		/* Verify Server Public Key Echo */
		nla->status = nla_decrypt_public_key_echo(nla);
		nla_buffer_free(nla);

		if (nla->status != SEC_E_OK)
		{
			WLog_ERR(TAG, "Could not verify public key echo %s [%08X]",
				 GetSecurityStatusString(nla->status), nla->status);
			return -1;
		}

		/* Send encrypted credentials */
		nla->status = nla_encrypt_ts_credentials(nla);

		if (nla->status != SEC_E_OK)
		{
			WLog_ERR(TAG, "nla_encrypt_ts_credentials status %s [%08X]",
				 GetSecurityStatusString(nla->status), nla->status);
			return -1;
		}

		if (!nla_send(nla))
		{
			nla_buffer_free(nla);
			return -1;
		}
		nla_buffer_free(nla);

		nla->table->FreeCredentialsHandle(&nla->credentials);
		if (nla->status != SEC_E_OK)
		{
			WLog_ERR(TAG, "FreeCredentialsHandle status %s [%08X]",
				  GetSecurityStatusString(nla->status), nla->status);
		}

		nla->status = nla->table->FreeContextBuffer(nla->pPackageInfo);
		if (nla->status != SEC_E_OK)
		{
			WLog_ERR(TAG, "FreeContextBuffer status %s [%08X]",
				  GetSecurityStatusString(nla->status), nla->status);
		}

		if (nla->status != SEC_E_OK)
			return -1;

		nla->state = NLA_STATE_AUTH_INFO;
		status = 1;
	}

	return status;
}
Exemple #25
0
void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired)
{
	WLog_DBG(TAG, "Enabling restricted admin mode: %s", RestrictedAdminModeRequired ? "TRUE" : "FALSE");
	nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
}
Exemple #26
0
int nla_server_authenticate(rdpNla* nla)
{
	if (nla_server_init(nla) < 1)
		return -1;

	while (TRUE)
	{
		/* receive authentication token */
		nla->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
		nla->inputBufferDesc.cBuffers = 1;
		nla->inputBufferDesc.pBuffers = &nla->inputBuffer;
		nla->inputBuffer.BufferType = SECBUFFER_TOKEN;

		if (nla_recv(nla) < 0)
			return -1;

		WLog_DBG(TAG, "Receiving Authentication Token");
		nla_buffer_print(nla);

		nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer;
		nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer;

		if (nla->negoToken.cbBuffer < 1)
		{
			WLog_ERR(TAG, "CredSSP: invalid negoToken!");
			return -1;
		}

		nla->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
		nla->outputBufferDesc.cBuffers = 1;
		nla->outputBufferDesc.pBuffers = &nla->outputBuffer;
		nla->outputBuffer.BufferType = SECBUFFER_TOKEN;
		nla->outputBuffer.cbBuffer = nla->cbMaxToken;
		nla->outputBuffer.pvBuffer = malloc(nla->outputBuffer.cbBuffer);

		if (!nla->outputBuffer.pvBuffer)
			return -1;

		nla->status = nla->table->AcceptSecurityContext(&nla->credentials,
				nla-> haveContext? &nla->context: NULL,
				 &nla->inputBufferDesc, nla->fContextReq, SECURITY_NATIVE_DREP, &nla->context,
				 &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);

		WLog_VRB(TAG, "AcceptSecurityContext status %s [%08X]",
			   GetSecurityStatusString(nla->status), nla->status);
		nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer;
		nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer;

		if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
		{
			if (nla->table->CompleteAuthToken)
			{
				SECURITY_STATUS status;
				status = nla->table->CompleteAuthToken(&nla->context, &nla->outputBufferDesc);
				if (status != SEC_E_OK)
				{
					WLog_WARN(TAG, "CompleteAuthToken status %s [%08X]",
						  GetSecurityStatusString(status), status);
					return -1;
				}
			}
			if (nla->status == SEC_I_COMPLETE_NEEDED)
				nla->status = SEC_E_OK;
			else if (nla->status == SEC_I_COMPLETE_AND_CONTINUE)
				nla->status = SEC_I_CONTINUE_NEEDED;
		}

		if (nla->status == SEC_E_OK)
		{
			if (nla->outputBuffer.cbBuffer != 0)
			{
				if (!nla_send(nla))
				{
					nla_buffer_free(nla);
					return -1;
				}

				if (nla_recv(nla) < 0)
					return -1;

				WLog_DBG(TAG, "Receiving pubkey Token");
				nla_buffer_print(nla);
			}

			nla->havePubKeyAuth = TRUE;

			nla->status  = nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES, &nla->ContextSizes);
			if (nla->status != SEC_E_OK)
			{
				WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure %s [%08X]",
					 GetSecurityStatusString(nla->status), nla->status);
				return -1;
			}

			nla->status = nla_decrypt_public_key_echo(nla);
			if (nla->status != SEC_E_OK)
			{
				WLog_ERR(TAG, "Error: could not verify client's public key echo %s [%08X]",
					 GetSecurityStatusString(nla->status), nla->status);
				return -1;
			}

			sspi_SecBufferFree(&nla->negoToken);
			nla->negoToken.pvBuffer = NULL;
			nla->negoToken.cbBuffer = 0;
			nla->status = nla_encrypt_public_key_echo(nla);
			if (nla->status != SEC_E_OK)
				return -1;
		}

		if ((nla->status != SEC_E_OK) && (nla->status != SEC_I_CONTINUE_NEEDED))
		{
			/* Special handling of these specific error codes as NTSTATUS_FROM_WIN32
			   unfortunately does not map directly to the corresponding NTSTATUS values
			 */
			switch (GetLastError())
			{
				case ERROR_PASSWORD_MUST_CHANGE:
					nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
					break;
				case ERROR_PASSWORD_EXPIRED:
					nla->errorCode = STATUS_PASSWORD_EXPIRED;
					break;
				case ERROR_ACCOUNT_DISABLED:
					nla->errorCode = STATUS_ACCOUNT_DISABLED;
					break;
				default:
					nla->errorCode = NTSTATUS_FROM_WIN32(GetLastError());
					break;
			}

			WLog_ERR(TAG, "AcceptSecurityContext status %s [%08X]",
				 GetSecurityStatusString(nla->status), nla->status);
			nla_send(nla);
			return -1; /* Access Denied */
		}

		/* send authentication token */

		WLog_DBG(TAG, "Sending Authentication Token");
		nla_buffer_print(nla);

		if (!nla_send(nla))
		{
			nla_buffer_free(nla);
			return -1;
		}
		nla_buffer_free(nla);

		if (nla->status != SEC_I_CONTINUE_NEEDED)
			break;

		nla->haveContext = TRUE;
	}

	/* Receive encrypted credentials */

	if (nla_recv(nla) < 0)
		return -1;

	nla->status = nla_decrypt_ts_credentials(nla);
	if (nla->status != SEC_E_OK)
	{
		WLog_ERR(TAG, "Could not decrypt TSCredentials status %s [%08X]",
			 GetSecurityStatusString(nla->status), nla->status);
		return -1;
	}

	nla->status = nla->table->ImpersonateSecurityContext(&nla->context);

	if (nla->status != SEC_E_OK)
	{
		WLog_ERR(TAG, "ImpersonateSecurityContext status %s [%08X]",
			 GetSecurityStatusString(nla->status), nla->status);
		return -1;
	}
	else
	{
		nla->status = nla->table->RevertSecurityContext(&nla->context);

		if (nla->status != SEC_E_OK)
		{
			WLog_ERR(TAG, "RevertSecurityContext status %s [%08X]",
				 GetSecurityStatusString(nla->status), nla->status);
			return -1;
		}
	}

	nla->status = nla->table->FreeContextBuffer(nla->pPackageInfo);
	if (nla->status != SEC_E_OK)
	{
		WLog_ERR(TAG, "DeleteSecurityContext status %s [%08X]",
			  GetSecurityStatusString(nla->status), nla->status);
		return -1;
	}

	return 1;
}
Exemple #27
0
void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
{
	WLog_DBG(TAG, "Enabling TLS security: %s", enable_tls ? "TRUE" : "FALSE");
	nego->EnabledProtocols[PROTOCOL_TLS] = enable_tls;
}
Exemple #28
0
BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* length)
{
	UINT32 alloc_hint = 0;
	rpcconn_hdr_t* header;
	UINT32 frag_length;
	UINT32 auth_length;
	UINT32 auth_pad_length;
	UINT32 sec_trailer_offset;
	rpc_sec_trailer* sec_trailer;
	*offset = RPC_COMMON_FIELDS_LENGTH;
	header = ((rpcconn_hdr_t*) buffer);

	switch (header->common.ptype)
	{
		case PTYPE_RESPONSE:
			*offset += 8;
			rpc_offset_align(offset, 8);
			alloc_hint = header->response.alloc_hint;
			break;

		case PTYPE_REQUEST:
			*offset += 4;
			rpc_offset_align(offset, 8);
			alloc_hint = header->request.alloc_hint;
			break;

		case PTYPE_RTS:
			*offset += 4;
			break;

		default:
			WLog_ERR(TAG, "Unknown PTYPE: 0x%02"PRIX8"", header->common.ptype);
			return FALSE;
	}

	if (!length)
		return TRUE;

	if (header->common.ptype == PTYPE_REQUEST)
	{
		UINT32 sec_trailer_offset;
		sec_trailer_offset = header->common.frag_length - header->common.auth_length - 8;
		*length = sec_trailer_offset - *offset;
		return TRUE;
	}

	frag_length = header->common.frag_length;
	auth_length = header->common.auth_length;
	sec_trailer_offset = frag_length - auth_length - 8;
	sec_trailer = (rpc_sec_trailer*) &buffer[sec_trailer_offset];
	auth_pad_length = sec_trailer->auth_pad_length;
#if 0
	WLog_DBG(TAG,
	         "sec_trailer: type: %"PRIu8" level: %"PRIu8" pad_length: %"PRIu8" reserved: %"PRIu8" context_id: %"PRIu32"",
	         sec_trailer->auth_type, sec_trailer->auth_level,
	         sec_trailer->auth_pad_length, sec_trailer->auth_reserved,
	         sec_trailer->auth_context_id);
#endif

	/**
	 * According to [MS-RPCE], auth_pad_length is the number of padding
	 * octets used to 4-byte align the security trailer, but in practice
	 * we get values up to 15, which indicates 16-byte alignment.
	 */

	if ((frag_length - (sec_trailer_offset + 8)) != auth_length)
	{
		WLog_ERR(TAG, "invalid auth_length: actual: %"PRIu32", expected: %"PRIu32"", auth_length,
		         (frag_length - (sec_trailer_offset + 8)));
	}

	*length = frag_length - auth_length - 24 - 8 - auth_pad_length;
	return TRUE;
}
Exemple #29
0
void nego_enable_ext(rdpNego* nego, BOOL enable_ext)
{
	WLog_DBG(TAG, "Enabling NLA extended security: %s", enable_ext ? "TRUE" : "FALSE");
	nego->EnabledProtocols[PROTOCOL_EXT] = enable_ext;
}
Exemple #30
0
DWORD WINAPI wf_client_thread(LPVOID lpParam)
{
	MSG msg;
	int width;
	int height;
	BOOL msg_ret;
	int quit_msg;
	DWORD nCount;
	HANDLE handles[64];
	wfContext* wfc;
	freerdp* instance;
	rdpContext* context;
	rdpChannels* channels;
	rdpSettings* settings;
	BOOL async_input;
	BOOL async_transport;
	HANDLE input_thread;

	instance = (freerdp*) lpParam;
	context = instance->context;
	wfc = (wfContext*) instance->context;

	if (!freerdp_connect(instance))
		return 0;

	channels = instance->context->channels;
	settings = instance->context->settings;

	async_input = settings->AsyncInput;
	async_transport = settings->AsyncTransport;

	if (async_input)
	{
		input_thread = CreateThread(NULL, 0,
				(LPTHREAD_START_ROUTINE) wf_input_thread,
				instance, 0, NULL);
	}

	while (1)
	{
		nCount = 0;

		if (freerdp_focus_required(instance))
		{
			wf_event_focus_in(wfc);
			wf_event_focus_in(wfc);
		}

		if (!async_transport)
		{
			DWORD tmp = freerdp_get_event_handles(context, &handles[nCount], 64 - nCount);

			if (tmp == 0)
			{
				WLog_ERR(TAG, "freerdp_get_event_handles failed");
				break;
			}

			nCount += tmp;
		}

		if (MsgWaitForMultipleObjects(nCount, handles, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED)
		{
			WLog_ERR(TAG, "wfreerdp_run: WaitForMultipleObjects failed: 0x%04X", GetLastError());
			break;
		}

		if (!async_transport)
		{
			if (!freerdp_check_event_handles(context))
			{
				if (wf_auto_reconnect(instance))
					continue;

				WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
				break;
			}
		}

		if (freerdp_shall_disconnect(instance))
			break;

		quit_msg = FALSE;

		while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
		{
			msg_ret = GetMessage(&msg, NULL, 0, 0);

			if (instance->settings->EmbeddedWindow)
			{
				if ((msg.message == WM_SETFOCUS) && (msg.lParam == 1))
				{
					PostMessage(wfc->hwnd, WM_SETFOCUS, 0, 0);
				}
				else if ((msg.message == WM_KILLFOCUS) && (msg.lParam == 1))
				{
					PostMessage(wfc->hwnd, WM_KILLFOCUS, 0, 0);
				}
			}

			if (msg.message == WM_SIZE)
			{
				width = LOWORD(msg.lParam);
				height = HIWORD(msg.lParam);

				SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED);
			}

			if ((msg_ret == 0) || (msg_ret == -1))
			{
				quit_msg = TRUE;
				break;
			}

			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		if (quit_msg)
			break;
	}

	/* cleanup */
	freerdp_channels_disconnect(channels, instance);

	if (async_input)
	{
		wMessageQueue* input_queue;
		input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
		MessageQueue_PostQuit(input_queue, 0);
		WaitForSingleObject(input_thread, INFINITE);
		CloseHandle(input_thread);
	}

	freerdp_disconnect(instance);
	WLog_DBG(TAG, "Main thread exited.");

	ExitThread(0);
	return 0;
}