FreeRDP
libfreerdp/core/channels.c
1 
21 #include <freerdp/config.h>
22 
23 #include "settings.h"
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include <winpr/crt.h>
30 #include <winpr/assert.h>
31 #include <winpr/stream.h>
32 #include <winpr/wtsapi.h>
33 
34 #include <freerdp/freerdp.h>
35 #include <freerdp/constants.h>
36 
37 #include <freerdp/log.h>
38 #include <freerdp/svc.h>
39 #include <freerdp/peer.h>
40 #include <freerdp/addin.h>
41 
42 #include <freerdp/client/channels.h>
43 #include <freerdp/client/drdynvc.h>
44 #include <freerdp/channels/channels.h>
45 
46 #include "rdp.h"
47 #include "client.h"
48 #include "server.h"
49 #include "channels.h"
50 
51 #define TAG FREERDP_TAG("core.channels")
52 
53 BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size_t size)
54 {
55  size_t left = 0;
56  UINT32 flags = 0;
57  size_t chunkSize = 0;
58  rdpMcs* mcs = NULL;
59  const rdpMcsChannel* channel = NULL;
60 
61  WINPR_ASSERT(rdp);
62  WINPR_ASSERT(data || (size == 0));
63 
64  mcs = rdp->mcs;
65  WINPR_ASSERT(mcs);
66  for (UINT32 i = 0; i < mcs->channelCount; i++)
67  {
68  const rdpMcsChannel* cur = &mcs->channels[i];
69  if (cur->ChannelId == channelId)
70  {
71  channel = cur;
72  break;
73  }
74  }
75 
76  if (!channel)
77  {
78  WLog_ERR(TAG, "freerdp_channel_send: unknown channelId %" PRIu16 "", channelId);
79  return FALSE;
80  }
81 
82  flags = CHANNEL_FLAG_FIRST;
83  left = size;
84 
85  while (left > 0)
86  {
87  if (left > rdp->settings->VCChunkSize)
88  {
89  chunkSize = rdp->settings->VCChunkSize;
90  }
91  else
92  {
93  chunkSize = left;
94  flags |= CHANNEL_FLAG_LAST;
95  }
96 
97  if (!rdp->settings->ServerMode && (channel->options & CHANNEL_OPTION_SHOW_PROTOCOL))
98  {
99  flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
100  }
101 
102  if (!freerdp_channel_send_packet(rdp, channelId, size, flags, data, chunkSize))
103  return FALSE;
104 
105  data += chunkSize;
106  left -= chunkSize;
107  flags = 0;
108  }
109 
110  return TRUE;
111 }
112 
113 BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId, size_t packetLength)
114 {
115  BOOL rc = FALSE;
116  UINT32 length = 0;
117  UINT32 flags = 0;
118  size_t chunkLength = 0;
119 
120  WINPR_ASSERT(instance);
121 
122  if (packetLength < 8)
123  {
124  WLog_ERR(TAG, "Header length %" PRIdz " bytes promised, none available", packetLength);
125  return FALSE;
126  }
127  packetLength -= 8;
128 
129  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
130  return FALSE;
131 
132  /* [MS-RDPBCGR] 3.1.5.2.2 Processing of Virtual Channel PDU
133  * chunked data. Length is the total size of the combined data,
134  * chunkLength is the actual data received.
135  * check chunkLength against packetLength, which is the TPKT header size.
136  */
137  Stream_Read_UINT32(s, length);
138  Stream_Read_UINT32(s, flags);
139  chunkLength = Stream_GetRemainingLength(s);
140  if (packetLength != chunkLength)
141  {
142  WLog_ERR(TAG, "Header length %" PRIdz " != actual length %" PRIdz, packetLength,
143  chunkLength);
144  return FALSE;
145  }
146 
147  IFCALLRET(instance->ReceiveChannelData, rc, instance, channelId, Stream_Pointer(s), chunkLength,
148  flags, length);
149  if (!rc)
150  {
151  WLog_WARN(TAG, "ReceiveChannelData returned %d", rc);
152  return FALSE;
153  }
154 
155  return Stream_SafeSeek(s, chunkLength);
156 }
157 
158 BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId)
159 {
160  UINT32 length = 0;
161  UINT32 flags = 0;
162 
163  WINPR_ASSERT(client);
164  WINPR_ASSERT(s);
165 
166  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
167  return FALSE;
168 
169  Stream_Read_UINT32(s, length);
170  Stream_Read_UINT32(s, flags);
171  const size_t chunkLength = Stream_GetRemainingLength(s);
172  if (chunkLength > UINT32_MAX)
173  return FALSE;
174 
175  if (client->VirtualChannelRead)
176  {
177  int rc = 0;
178  BOOL found = FALSE;
179  HANDLE hChannel = 0;
180  rdpContext* context = client->context;
181  rdpMcs* mcs = context->rdp->mcs;
182 
183  for (UINT32 index = 0; index < mcs->channelCount; index++)
184  {
185  const rdpMcsChannel* mcsChannel = &(mcs->channels[index]);
186 
187  if (mcsChannel->ChannelId == channelId)
188  {
189  hChannel = (HANDLE)mcsChannel->handle;
190  found = TRUE;
191  break;
192  }
193  }
194 
195  if (!found)
196  return FALSE;
197 
198  rc = client->VirtualChannelRead(client, hChannel, Stream_Pointer(s), (UINT32)chunkLength);
199  if (rc < 0)
200  return FALSE;
201  }
202  else if (client->ReceiveChannelData)
203  {
204  BOOL rc = client->ReceiveChannelData(client, channelId, Stream_Pointer(s),
205  (UINT32)chunkLength, flags, length);
206  if (!rc)
207  return FALSE;
208  }
209  if (!Stream_SafeSeek(s, chunkLength))
210  {
211  WLog_WARN(TAG, "Short PDU, need %" PRIuz " bytes, got %" PRIuz, chunkLength,
212  Stream_GetRemainingLength(s));
213  return FALSE;
214  }
215  return TRUE;
216 }
217 
218 static const WtsApiFunctionTable FreeRDP_WtsApiFunctionTable = {
219  0, /* dwVersion */
220  0, /* dwFlags */
221 
222  FreeRDP_WTSStopRemoteControlSession, /* StopRemoteControlSession */
223  FreeRDP_WTSStartRemoteControlSessionW, /* StartRemoteControlSessionW */
224  FreeRDP_WTSStartRemoteControlSessionA, /* StartRemoteControlSessionA */
225  FreeRDP_WTSConnectSessionW, /* ConnectSessionW */
226  FreeRDP_WTSConnectSessionA, /* ConnectSessionA */
227  FreeRDP_WTSEnumerateServersW, /* EnumerateServersW */
228  FreeRDP_WTSEnumerateServersA, /* EnumerateServersA */
229  FreeRDP_WTSOpenServerW, /* OpenServerW */
230  FreeRDP_WTSOpenServerA, /* OpenServerA */
231  FreeRDP_WTSOpenServerExW, /* OpenServerExW */
232  FreeRDP_WTSOpenServerExA, /* OpenServerExA */
233  FreeRDP_WTSCloseServer, /* CloseServer */
234  FreeRDP_WTSEnumerateSessionsW, /* EnumerateSessionsW */
235  FreeRDP_WTSEnumerateSessionsA, /* EnumerateSessionsA */
236  FreeRDP_WTSEnumerateSessionsExW, /* EnumerateSessionsExW */
237  FreeRDP_WTSEnumerateSessionsExA, /* EnumerateSessionsExA */
238  FreeRDP_WTSEnumerateProcessesW, /* EnumerateProcessesW */
239  FreeRDP_WTSEnumerateProcessesA, /* EnumerateProcessesA */
240  FreeRDP_WTSTerminateProcess, /* TerminateProcess */
241  FreeRDP_WTSQuerySessionInformationW, /* QuerySessionInformationW */
242  FreeRDP_WTSQuerySessionInformationA, /* QuerySessionInformationA */
243  FreeRDP_WTSQueryUserConfigW, /* QueryUserConfigW */
244  FreeRDP_WTSQueryUserConfigA, /* QueryUserConfigA */
245  FreeRDP_WTSSetUserConfigW, /* SetUserConfigW */
246  FreeRDP_WTSSetUserConfigA, /* SetUserConfigA */
247  FreeRDP_WTSSendMessageW, /* SendMessageW */
248  FreeRDP_WTSSendMessageA, /* SendMessageA */
249  FreeRDP_WTSDisconnectSession, /* DisconnectSession */
250  FreeRDP_WTSLogoffSession, /* LogoffSession */
251  FreeRDP_WTSShutdownSystem, /* ShutdownSystem */
252  FreeRDP_WTSWaitSystemEvent, /* WaitSystemEvent */
253  FreeRDP_WTSVirtualChannelOpen, /* VirtualChannelOpen */
254  FreeRDP_WTSVirtualChannelOpenEx, /* VirtualChannelOpenEx */
255  FreeRDP_WTSVirtualChannelClose, /* VirtualChannelClose */
256  FreeRDP_WTSVirtualChannelRead, /* VirtualChannelRead */
257  FreeRDP_WTSVirtualChannelWrite, /* VirtualChannelWrite */
258  FreeRDP_WTSVirtualChannelPurgeInput, /* VirtualChannelPurgeInput */
259  FreeRDP_WTSVirtualChannelPurgeOutput, /* VirtualChannelPurgeOutput */
260  FreeRDP_WTSVirtualChannelQuery, /* VirtualChannelQuery */
261  FreeRDP_WTSFreeMemory, /* FreeMemory */
262  FreeRDP_WTSRegisterSessionNotification, /* RegisterSessionNotification */
263  FreeRDP_WTSUnRegisterSessionNotification, /* UnRegisterSessionNotification */
264  FreeRDP_WTSRegisterSessionNotificationEx, /* RegisterSessionNotificationEx */
265  FreeRDP_WTSUnRegisterSessionNotificationEx, /* UnRegisterSessionNotificationEx */
266  FreeRDP_WTSQueryUserToken, /* QueryUserToken */
267  FreeRDP_WTSFreeMemoryExW, /* FreeMemoryExW */
268  FreeRDP_WTSFreeMemoryExA, /* FreeMemoryExA */
269  FreeRDP_WTSEnumerateProcessesExW, /* EnumerateProcessesExW */
270  FreeRDP_WTSEnumerateProcessesExA, /* EnumerateProcessesExA */
271  FreeRDP_WTSEnumerateListenersW, /* EnumerateListenersW */
272  FreeRDP_WTSEnumerateListenersA, /* EnumerateListenersA */
273  FreeRDP_WTSQueryListenerConfigW, /* QueryListenerConfigW */
274  FreeRDP_WTSQueryListenerConfigA, /* QueryListenerConfigA */
275  FreeRDP_WTSCreateListenerW, /* CreateListenerW */
276  FreeRDP_WTSCreateListenerA, /* CreateListenerA */
277  FreeRDP_WTSSetListenerSecurityW, /* SetListenerSecurityW */
278  FreeRDP_WTSSetListenerSecurityA, /* SetListenerSecurityA */
279  FreeRDP_WTSGetListenerSecurityW, /* GetListenerSecurityW */
280  FreeRDP_WTSGetListenerSecurityA, /* GetListenerSecurityA */
281  FreeRDP_WTSEnableChildSessions, /* EnableChildSessions */
282  FreeRDP_WTSIsChildSessionsEnabled, /* IsChildSessionsEnabled */
283  FreeRDP_WTSGetChildSessionId, /* GetChildSessionId */
284  FreeRDP_WTSGetActiveConsoleSessionId, /* GetActiveConsoleSessionId */
285  FreeRDP_WTSLogonUser,
286  FreeRDP_WTSLogoffUser,
287  FreeRDP_WTSStartRemoteControlSessionExW,
288  FreeRDP_WTSStartRemoteControlSessionExA
289 };
290 
291 const WtsApiFunctionTable* FreeRDP_InitWtsApi(void)
292 {
293  return &FreeRDP_WtsApiFunctionTable;
294 }
295 
296 BOOL freerdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize, UINT32 flags,
297  const BYTE* data, size_t chunkSize)
298 {
299  if (totalSize > UINT32_MAX)
300  return FALSE;
301 
302  wStream* s = rdp_send_stream_init(rdp);
303 
304  if (!s)
305  return FALSE;
306 
307  Stream_Write_UINT32(s, (UINT32)totalSize);
308  Stream_Write_UINT32(s, flags);
309 
310  if (!Stream_EnsureCapacity(s, chunkSize))
311  {
312  Stream_Release(s);
313  return FALSE;
314  }
315 
316  Stream_Write(s, data, chunkSize);
317 
318  /* WLog_DBG(TAG, "sending data (flags=0x%x size=%d)", flags, size); */
319  return rdp_send(rdp, s, channelId);
320 }