Blame libfreerdp/core/channels.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * Virtual Channels
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2011 Vic Lee
Packit 1fb8d4
 * Copyright 2015 Copyright 2015 Thincast Technologies GmbH
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <stdio.h>
Packit 1fb8d4
#include <stdlib.h>
Packit 1fb8d4
#include <string.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/stream.h>
Packit 1fb8d4
#include <winpr/wtsapi.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/freerdp.h>
Packit 1fb8d4
#include <freerdp/constants.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
#include <freerdp/svc.h>
Packit 1fb8d4
#include <freerdp/peer.h>
Packit 1fb8d4
#include <freerdp/addin.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/client/channels.h>
Packit 1fb8d4
#include <freerdp/client/drdynvc.h>
Packit 1fb8d4
#include <freerdp/channels/channels.h>
Packit 1fb8d4
Packit 1fb8d4
#include "rdp.h"
Packit 1fb8d4
#include "client.h"
Packit 1fb8d4
#include "server.h"
Packit 1fb8d4
#include "channels.h"
Packit 1fb8d4
Packit 1fb8d4
#define TAG FREERDP_TAG("core.channels")
Packit 1fb8d4
Packit Service 5a9772
BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size_t size)
Packit 1fb8d4
{
Packit 1fb8d4
	DWORD i;
Packit Service 5a9772
	size_t left;
Packit 1fb8d4
	wStream* s;
Packit 1fb8d4
	UINT32 flags;
Packit Service 5a9772
	size_t chunkSize;
Packit 1fb8d4
	rdpMcs* mcs = rdp->mcs;
Packit 1fb8d4
	rdpMcsChannel* channel = NULL;
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < mcs->channelCount; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (mcs->channels[i].ChannelId == channelId)
Packit 1fb8d4
		{
Packit 1fb8d4
			channel = &mcs->channels[i];
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!channel)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "freerdp_channel_send: unknown channelId %" PRIu16 "", channelId);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	flags = CHANNEL_FLAG_FIRST;
Packit 1fb8d4
	left = size;
Packit 1fb8d4
Packit 1fb8d4
	while (left > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		s = rdp_send_stream_init(rdp);
Packit 1fb8d4
Packit 1fb8d4
		if (!s)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit Service 5a9772
		if (left > rdp->settings->VirtualChannelChunkSize)
Packit 1fb8d4
		{
Packit 1fb8d4
			chunkSize = rdp->settings->VirtualChannelChunkSize;
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			chunkSize = left;
Packit 1fb8d4
			flags |= CHANNEL_FLAG_LAST;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit Service 5a9772
		if (!rdp->settings->ServerMode && (channel->options & CHANNEL_OPTION_SHOW_PROTOCOL))
Packit 1fb8d4
		{
Packit 1fb8d4
			flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		Stream_Write_UINT32(s, size);
Packit 1fb8d4
		Stream_Write_UINT32(s, flags);
Packit 1fb8d4
Packit 1fb8d4
		if (!Stream_EnsureCapacity(s, chunkSize))
Packit 1fb8d4
		{
Packit 1fb8d4
			Stream_Release(s);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		Stream_Write(s, data, chunkSize);
Packit 1fb8d4
Packit 1fb8d4
		/* WLog_DBG(TAG, "%s: sending data (flags=0x%x size=%d)", __FUNCTION__, flags, size); */
Packit 1fb8d4
		if (!rdp_send(rdp, s, channelId))
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		data += chunkSize;
Packit 1fb8d4
		left -= chunkSize;
Packit 1fb8d4
		flags = 0;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId, size_t packetLength)
Packit 1fb8d4
{
Packit Service 5a9772
	BOOL rc = FALSE;
Packit 1fb8d4
	UINT32 length;
Packit 1fb8d4
	UINT32 flags;
Packit Service 5a9772
	size_t chunkLength;
Packit Service 5a9772
Packit Service 5a9772
	if (packetLength < 8)
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Header length %" PRIdz " bytes promised, none available", packetLength);
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
	}
Packit Service 5a9772
	packetLength -= 8;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 8)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	/* [MS-RDPBCGR] 3.1.5.2.2 Processing of Virtual Channel PDU
Packit Service 5a9772
	 * chunked data. Length is the total size of the combined data,
Packit Service 5a9772
	 * chunkLength is the actual data received.
Packit Service 5a9772
	 * check chunkLength against packetLength, which is the TPKT header size.
Packit Service 5a9772
	 */
Packit 1fb8d4
	Stream_Read_UINT32(s, length);
Packit 1fb8d4
	Stream_Read_UINT32(s, flags);
Packit 1fb8d4
	chunkLength = Stream_GetRemainingLength(s);
Packit Service 5a9772
	if (packetLength != chunkLength)
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Header length %" PRIdz " != actual length %" PRIdz, packetLength,
Packit Service 5a9772
		         chunkLength);
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
	}
Packit Service 5a9772
	if (length < chunkLength)
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_ERR(TAG, "Expected %" PRIu32 " bytes, but have %" PRIdz, length, chunkLength);
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
	}
Packit Service 5a9772
	IFCALLRET(instance->ReceiveChannelData, rc, instance, channelId, Stream_Pointer(s), chunkLength,
Packit Service 5a9772
	          flags, length);
Packit Service 5a9772
	if (!rc)
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_WARN(TAG, "ReceiveChannelData returned %d", rc);
Packit Service 5a9772
		return FALSE;
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	return Stream_SafeSeek(s, chunkLength);
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 length;
Packit 1fb8d4
	UINT32 flags;
Packit Service 5a9772
	size_t chunkLength;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 8)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT32(s, length);
Packit 1fb8d4
	Stream_Read_UINT32(s, flags);
Packit 1fb8d4
	chunkLength = Stream_GetRemainingLength(s);
Packit 1fb8d4
Packit 1fb8d4
	if (client->VirtualChannelRead)
Packit 1fb8d4
	{
Packit Service 5a9772
		int rc;
Packit 1fb8d4
		UINT32 index;
Packit 1fb8d4
		BOOL found = FALSE;
Packit 1fb8d4
		HANDLE hChannel = 0;
Packit 1fb8d4
		rdpContext* context = client->context;
Packit 1fb8d4
		rdpMcs* mcs = context->rdp->mcs;
Packit 1fb8d4
		rdpMcsChannel* mcsChannel = NULL;
Packit 1fb8d4
Packit 1fb8d4
		for (index = 0; index < mcs->channelCount; index++)
Packit 1fb8d4
		{
Packit 1fb8d4
			mcsChannel = &(mcs->channels[index]);
Packit 1fb8d4
Packit 1fb8d4
			if (mcsChannel->ChannelId == channelId)
Packit 1fb8d4
			{
Packit Service 5a9772
				hChannel = (HANDLE)mcsChannel->handle;
Packit 1fb8d4
				found = TRUE;
Packit 1fb8d4
				break;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!found)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit Service 5a9772
		rc = client->VirtualChannelRead(client, hChannel, Stream_Pointer(s), chunkLength);
Packit Service 5a9772
		if (rc < 0)
Packit Service 5a9772
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (client->ReceiveChannelData)
Packit 1fb8d4
	{
Packit Service 5a9772
		BOOL rc = client->ReceiveChannelData(client, channelId, Stream_Pointer(s), chunkLength,
Packit Service 5a9772
		                                     flags, length);
Packit Service 5a9772
		if (!rc)
Packit Service 5a9772
			return FALSE;
Packit 1fb8d4
	}
Packit Service 5a9772
	return Stream_SafeSeek(s, chunkLength);
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static const WtsApiFunctionTable FreeRDP_WtsApiFunctionTable = {
Packit 1fb8d4
	0, /* dwVersion */
Packit 1fb8d4
	0, /* dwFlags */
Packit 1fb8d4
Packit Service 5a9772
	FreeRDP_WTSStopRemoteControlSession,        /* StopRemoteControlSession */
Packit Service 5a9772
	FreeRDP_WTSStartRemoteControlSessionW,      /* StartRemoteControlSessionW */
Packit Service 5a9772
	FreeRDP_WTSStartRemoteControlSessionA,      /* StartRemoteControlSessionA */
Packit Service 5a9772
	FreeRDP_WTSConnectSessionW,                 /* ConnectSessionW */
Packit Service 5a9772
	FreeRDP_WTSConnectSessionA,                 /* ConnectSessionA */
Packit Service 5a9772
	FreeRDP_WTSEnumerateServersW,               /* EnumerateServersW */
Packit Service 5a9772
	FreeRDP_WTSEnumerateServersA,               /* EnumerateServersA */
Packit Service 5a9772
	FreeRDP_WTSOpenServerW,                     /* OpenServerW */
Packit Service 5a9772
	FreeRDP_WTSOpenServerA,                     /* OpenServerA */
Packit Service 5a9772
	FreeRDP_WTSOpenServerExW,                   /* OpenServerExW */
Packit Service 5a9772
	FreeRDP_WTSOpenServerExA,                   /* OpenServerExA */
Packit Service 5a9772
	FreeRDP_WTSCloseServer,                     /* CloseServer */
Packit Service 5a9772
	FreeRDP_WTSEnumerateSessionsW,              /* EnumerateSessionsW */
Packit Service 5a9772
	FreeRDP_WTSEnumerateSessionsA,              /* EnumerateSessionsA */
Packit Service 5a9772
	FreeRDP_WTSEnumerateSessionsExW,            /* EnumerateSessionsExW */
Packit Service 5a9772
	FreeRDP_WTSEnumerateSessionsExA,            /* EnumerateSessionsExA */
Packit Service 5a9772
	FreeRDP_WTSEnumerateProcessesW,             /* EnumerateProcessesW */
Packit Service 5a9772
	FreeRDP_WTSEnumerateProcessesA,             /* EnumerateProcessesA */
Packit Service 5a9772
	FreeRDP_WTSTerminateProcess,                /* TerminateProcess */
Packit Service 5a9772
	FreeRDP_WTSQuerySessionInformationW,        /* QuerySessionInformationW */
Packit Service 5a9772
	FreeRDP_WTSQuerySessionInformationA,        /* QuerySessionInformationA */
Packit Service 5a9772
	FreeRDP_WTSQueryUserConfigW,                /* QueryUserConfigW */
Packit Service 5a9772
	FreeRDP_WTSQueryUserConfigA,                /* QueryUserConfigA */
Packit Service 5a9772
	FreeRDP_WTSSetUserConfigW,                  /* SetUserConfigW */
Packit Service 5a9772
	FreeRDP_WTSSetUserConfigA,                  /* SetUserConfigA */
Packit Service 5a9772
	FreeRDP_WTSSendMessageW,                    /* SendMessageW */
Packit Service 5a9772
	FreeRDP_WTSSendMessageA,                    /* SendMessageA */
Packit Service 5a9772
	FreeRDP_WTSDisconnectSession,               /* DisconnectSession */
Packit Service 5a9772
	FreeRDP_WTSLogoffSession,                   /* LogoffSession */
Packit Service 5a9772
	FreeRDP_WTSShutdownSystem,                  /* ShutdownSystem */
Packit Service 5a9772
	FreeRDP_WTSWaitSystemEvent,                 /* WaitSystemEvent */
Packit Service 5a9772
	FreeRDP_WTSVirtualChannelOpen,              /* VirtualChannelOpen */
Packit Service 5a9772
	FreeRDP_WTSVirtualChannelOpenEx,            /* VirtualChannelOpenEx */
Packit Service 5a9772
	FreeRDP_WTSVirtualChannelClose,             /* VirtualChannelClose */
Packit Service 5a9772
	FreeRDP_WTSVirtualChannelRead,              /* VirtualChannelRead */
Packit Service 5a9772
	FreeRDP_WTSVirtualChannelWrite,             /* VirtualChannelWrite */
Packit Service 5a9772
	FreeRDP_WTSVirtualChannelPurgeInput,        /* VirtualChannelPurgeInput */
Packit Service 5a9772
	FreeRDP_WTSVirtualChannelPurgeOutput,       /* VirtualChannelPurgeOutput */
Packit Service 5a9772
	FreeRDP_WTSVirtualChannelQuery,             /* VirtualChannelQuery */
Packit Service 5a9772
	FreeRDP_WTSFreeMemory,                      /* FreeMemory */
Packit Service 5a9772
	FreeRDP_WTSRegisterSessionNotification,     /* RegisterSessionNotification */
Packit Service 5a9772
	FreeRDP_WTSUnRegisterSessionNotification,   /* UnRegisterSessionNotification */
Packit Service 5a9772
	FreeRDP_WTSRegisterSessionNotificationEx,   /* RegisterSessionNotificationEx */
Packit 1fb8d4
	FreeRDP_WTSUnRegisterSessionNotificationEx, /* UnRegisterSessionNotificationEx */
Packit Service 5a9772
	FreeRDP_WTSQueryUserToken,                  /* QueryUserToken */
Packit Service 5a9772
	FreeRDP_WTSFreeMemoryExW,                   /* FreeMemoryExW */
Packit Service 5a9772
	FreeRDP_WTSFreeMemoryExA,                   /* FreeMemoryExA */
Packit Service 5a9772
	FreeRDP_WTSEnumerateProcessesExW,           /* EnumerateProcessesExW */
Packit Service 5a9772
	FreeRDP_WTSEnumerateProcessesExA,           /* EnumerateProcessesExA */
Packit Service 5a9772
	FreeRDP_WTSEnumerateListenersW,             /* EnumerateListenersW */
Packit Service 5a9772
	FreeRDP_WTSEnumerateListenersA,             /* EnumerateListenersA */
Packit Service 5a9772
	FreeRDP_WTSQueryListenerConfigW,            /* QueryListenerConfigW */
Packit Service 5a9772
	FreeRDP_WTSQueryListenerConfigA,            /* QueryListenerConfigA */
Packit Service 5a9772
	FreeRDP_WTSCreateListenerW,                 /* CreateListenerW */
Packit Service 5a9772
	FreeRDP_WTSCreateListenerA,                 /* CreateListenerA */
Packit Service 5a9772
	FreeRDP_WTSSetListenerSecurityW,            /* SetListenerSecurityW */
Packit Service 5a9772
	FreeRDP_WTSSetListenerSecurityA,            /* SetListenerSecurityA */
Packit Service 5a9772
	FreeRDP_WTSGetListenerSecurityW,            /* GetListenerSecurityW */
Packit Service 5a9772
	FreeRDP_WTSGetListenerSecurityA,            /* GetListenerSecurityA */
Packit Service 5a9772
	FreeRDP_WTSEnableChildSessions,             /* EnableChildSessions */
Packit Service 5a9772
	FreeRDP_WTSIsChildSessionsEnabled,          /* IsChildSessionsEnabled */
Packit Service 5a9772
	FreeRDP_WTSGetChildSessionId,               /* GetChildSessionId */
Packit Service 5a9772
	FreeRDP_WTSGetActiveConsoleSessionId,       /* GetActiveConsoleSessionId */
Packit 1fb8d4
	FreeRDP_WTSLogonUser,
Packit 1fb8d4
	FreeRDP_WTSLogoffUser,
Packit 1fb8d4
	FreeRDP_WTSStartRemoteControlSessionExW,
Packit 1fb8d4
	FreeRDP_WTSStartRemoteControlSessionExA
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
PWtsApiFunctionTable FreeRDP_InitWtsApi(void)
Packit 1fb8d4
{
Packit 1fb8d4
	return (PWtsApiFunctionTable)&FreeRDP_WtsApiFunctionTable;
Packit 1fb8d4
}