Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/libfreerdp/core/channels.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Virtual Channels
4
 *
5
 * Copyright 2011 Vic Lee
6
 * Copyright 2015 Copyright 2015 Thincast Technologies GmbH
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
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
0
{
55
0
  size_t left = 0;
56
0
  UINT32 flags = 0;
57
0
  size_t chunkSize = 0;
58
0
  rdpMcs* mcs = NULL;
59
0
  const rdpMcsChannel* channel = NULL;
60
61
0
  WINPR_ASSERT(rdp);
62
0
  WINPR_ASSERT(data || (size == 0));
63
64
0
  mcs = rdp->mcs;
65
0
  WINPR_ASSERT(mcs);
66
0
  for (UINT32 i = 0; i < mcs->channelCount; i++)
67
0
  {
68
0
    const rdpMcsChannel* cur = &mcs->channels[i];
69
0
    if (cur->ChannelId == channelId)
70
0
    {
71
0
      channel = cur;
72
0
      break;
73
0
    }
74
0
  }
75
76
0
  if (!channel)
77
0
  {
78
0
    WLog_ERR(TAG, "freerdp_channel_send: unknown channelId %" PRIu16 "", channelId);
79
0
    return FALSE;
80
0
  }
81
82
0
  flags = CHANNEL_FLAG_FIRST;
83
0
  left = size;
84
85
0
  while (left > 0)
86
0
  {
87
0
    if (left > rdp->settings->VCChunkSize)
88
0
    {
89
0
      chunkSize = rdp->settings->VCChunkSize;
90
0
    }
91
0
    else
92
0
    {
93
0
      chunkSize = left;
94
0
      flags |= CHANNEL_FLAG_LAST;
95
0
    }
96
97
0
    if (!rdp->settings->ServerMode && (channel->options & CHANNEL_OPTION_SHOW_PROTOCOL))
98
0
    {
99
0
      flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
100
0
    }
101
102
0
    if (!freerdp_channel_send_packet(rdp, channelId, size, flags, data, chunkSize))
103
0
      return FALSE;
104
105
0
    data += chunkSize;
106
0
    left -= chunkSize;
107
0
    flags = 0;
108
0
  }
109
110
0
  return TRUE;
111
0
}
112
113
BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId, size_t packetLength)
114
0
{
115
0
  BOOL rc = FALSE;
116
0
  UINT32 length = 0;
117
0
  UINT32 flags = 0;
118
0
  size_t chunkLength = 0;
119
120
0
  WINPR_ASSERT(instance);
121
122
0
  if (packetLength < 8)
123
0
  {
124
0
    WLog_ERR(TAG, "Header length %" PRIdz " bytes promised, none available", packetLength);
125
0
    return FALSE;
126
0
  }
127
0
  packetLength -= 8;
128
129
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
130
0
    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
0
  Stream_Read_UINT32(s, length);
138
0
  Stream_Read_UINT32(s, flags);
139
0
  chunkLength = Stream_GetRemainingLength(s);
140
0
  if (packetLength != chunkLength)
141
0
  {
142
0
    WLog_ERR(TAG, "Header length %" PRIdz " != actual length %" PRIdz, packetLength,
143
0
             chunkLength);
144
0
    return FALSE;
145
0
  }
146
147
0
  IFCALLRET(instance->ReceiveChannelData, rc, instance, channelId, Stream_Pointer(s), chunkLength,
148
0
            flags, length);
149
0
  if (!rc)
150
0
  {
151
0
    WLog_WARN(TAG, "ReceiveChannelData returned %d", rc);
152
0
    return FALSE;
153
0
  }
154
155
0
  return Stream_SafeSeek(s, chunkLength);
156
0
}
157
158
BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId)
159
0
{
160
0
  UINT32 length = 0;
161
0
  UINT32 flags = 0;
162
0
  size_t chunkLength = 0;
163
164
0
  WINPR_ASSERT(client);
165
0
  WINPR_ASSERT(s);
166
167
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
168
0
    return FALSE;
169
170
0
  Stream_Read_UINT32(s, length);
171
0
  Stream_Read_UINT32(s, flags);
172
0
  chunkLength = Stream_GetRemainingLength(s);
173
174
0
  if (client->VirtualChannelRead)
175
0
  {
176
0
    int rc = 0;
177
0
    BOOL found = FALSE;
178
0
    HANDLE hChannel = 0;
179
0
    rdpContext* context = client->context;
180
0
    rdpMcs* mcs = context->rdp->mcs;
181
182
0
    for (UINT32 index = 0; index < mcs->channelCount; index++)
183
0
    {
184
0
      const rdpMcsChannel* mcsChannel = &(mcs->channels[index]);
185
186
0
      if (mcsChannel->ChannelId == channelId)
187
0
      {
188
0
        hChannel = (HANDLE)mcsChannel->handle;
189
0
        found = TRUE;
190
0
        break;
191
0
      }
192
0
    }
193
194
0
    if (!found)
195
0
      return FALSE;
196
197
0
    rc = client->VirtualChannelRead(client, hChannel, Stream_Pointer(s), chunkLength);
198
0
    if (rc < 0)
199
0
      return FALSE;
200
0
  }
201
0
  else if (client->ReceiveChannelData)
202
0
  {
203
0
    BOOL rc = client->ReceiveChannelData(client, channelId, Stream_Pointer(s), chunkLength,
204
0
                                         flags, length);
205
0
    if (!rc)
206
0
      return FALSE;
207
0
  }
208
0
  if (!Stream_SafeSeek(s, chunkLength))
209
0
  {
210
0
    WLog_WARN(TAG, "Short PDU, need %" PRIuz " bytes, got %" PRIuz, chunkLength,
211
0
              Stream_GetRemainingLength(s));
212
0
    return FALSE;
213
0
  }
214
0
  return TRUE;
215
0
}
216
217
static const WtsApiFunctionTable FreeRDP_WtsApiFunctionTable = {
218
  0, /* dwVersion */
219
  0, /* dwFlags */
220
221
  FreeRDP_WTSStopRemoteControlSession,        /* StopRemoteControlSession */
222
  FreeRDP_WTSStartRemoteControlSessionW,      /* StartRemoteControlSessionW */
223
  FreeRDP_WTSStartRemoteControlSessionA,      /* StartRemoteControlSessionA */
224
  FreeRDP_WTSConnectSessionW,                 /* ConnectSessionW */
225
  FreeRDP_WTSConnectSessionA,                 /* ConnectSessionA */
226
  FreeRDP_WTSEnumerateServersW,               /* EnumerateServersW */
227
  FreeRDP_WTSEnumerateServersA,               /* EnumerateServersA */
228
  FreeRDP_WTSOpenServerW,                     /* OpenServerW */
229
  FreeRDP_WTSOpenServerA,                     /* OpenServerA */
230
  FreeRDP_WTSOpenServerExW,                   /* OpenServerExW */
231
  FreeRDP_WTSOpenServerExA,                   /* OpenServerExA */
232
  FreeRDP_WTSCloseServer,                     /* CloseServer */
233
  FreeRDP_WTSEnumerateSessionsW,              /* EnumerateSessionsW */
234
  FreeRDP_WTSEnumerateSessionsA,              /* EnumerateSessionsA */
235
  FreeRDP_WTSEnumerateSessionsExW,            /* EnumerateSessionsExW */
236
  FreeRDP_WTSEnumerateSessionsExA,            /* EnumerateSessionsExA */
237
  FreeRDP_WTSEnumerateProcessesW,             /* EnumerateProcessesW */
238
  FreeRDP_WTSEnumerateProcessesA,             /* EnumerateProcessesA */
239
  FreeRDP_WTSTerminateProcess,                /* TerminateProcess */
240
  FreeRDP_WTSQuerySessionInformationW,        /* QuerySessionInformationW */
241
  FreeRDP_WTSQuerySessionInformationA,        /* QuerySessionInformationA */
242
  FreeRDP_WTSQueryUserConfigW,                /* QueryUserConfigW */
243
  FreeRDP_WTSQueryUserConfigA,                /* QueryUserConfigA */
244
  FreeRDP_WTSSetUserConfigW,                  /* SetUserConfigW */
245
  FreeRDP_WTSSetUserConfigA,                  /* SetUserConfigA */
246
  FreeRDP_WTSSendMessageW,                    /* SendMessageW */
247
  FreeRDP_WTSSendMessageA,                    /* SendMessageA */
248
  FreeRDP_WTSDisconnectSession,               /* DisconnectSession */
249
  FreeRDP_WTSLogoffSession,                   /* LogoffSession */
250
  FreeRDP_WTSShutdownSystem,                  /* ShutdownSystem */
251
  FreeRDP_WTSWaitSystemEvent,                 /* WaitSystemEvent */
252
  FreeRDP_WTSVirtualChannelOpen,              /* VirtualChannelOpen */
253
  FreeRDP_WTSVirtualChannelOpenEx,            /* VirtualChannelOpenEx */
254
  FreeRDP_WTSVirtualChannelClose,             /* VirtualChannelClose */
255
  FreeRDP_WTSVirtualChannelRead,              /* VirtualChannelRead */
256
  FreeRDP_WTSVirtualChannelWrite,             /* VirtualChannelWrite */
257
  FreeRDP_WTSVirtualChannelPurgeInput,        /* VirtualChannelPurgeInput */
258
  FreeRDP_WTSVirtualChannelPurgeOutput,       /* VirtualChannelPurgeOutput */
259
  FreeRDP_WTSVirtualChannelQuery,             /* VirtualChannelQuery */
260
  FreeRDP_WTSFreeMemory,                      /* FreeMemory */
261
  FreeRDP_WTSRegisterSessionNotification,     /* RegisterSessionNotification */
262
  FreeRDP_WTSUnRegisterSessionNotification,   /* UnRegisterSessionNotification */
263
  FreeRDP_WTSRegisterSessionNotificationEx,   /* RegisterSessionNotificationEx */
264
  FreeRDP_WTSUnRegisterSessionNotificationEx, /* UnRegisterSessionNotificationEx */
265
  FreeRDP_WTSQueryUserToken,                  /* QueryUserToken */
266
  FreeRDP_WTSFreeMemoryExW,                   /* FreeMemoryExW */
267
  FreeRDP_WTSFreeMemoryExA,                   /* FreeMemoryExA */
268
  FreeRDP_WTSEnumerateProcessesExW,           /* EnumerateProcessesExW */
269
  FreeRDP_WTSEnumerateProcessesExA,           /* EnumerateProcessesExA */
270
  FreeRDP_WTSEnumerateListenersW,             /* EnumerateListenersW */
271
  FreeRDP_WTSEnumerateListenersA,             /* EnumerateListenersA */
272
  FreeRDP_WTSQueryListenerConfigW,            /* QueryListenerConfigW */
273
  FreeRDP_WTSQueryListenerConfigA,            /* QueryListenerConfigA */
274
  FreeRDP_WTSCreateListenerW,                 /* CreateListenerW */
275
  FreeRDP_WTSCreateListenerA,                 /* CreateListenerA */
276
  FreeRDP_WTSSetListenerSecurityW,            /* SetListenerSecurityW */
277
  FreeRDP_WTSSetListenerSecurityA,            /* SetListenerSecurityA */
278
  FreeRDP_WTSGetListenerSecurityW,            /* GetListenerSecurityW */
279
  FreeRDP_WTSGetListenerSecurityA,            /* GetListenerSecurityA */
280
  FreeRDP_WTSEnableChildSessions,             /* EnableChildSessions */
281
  FreeRDP_WTSIsChildSessionsEnabled,          /* IsChildSessionsEnabled */
282
  FreeRDP_WTSGetChildSessionId,               /* GetChildSessionId */
283
  FreeRDP_WTSGetActiveConsoleSessionId,       /* GetActiveConsoleSessionId */
284
  FreeRDP_WTSLogonUser,
285
  FreeRDP_WTSLogoffUser,
286
  FreeRDP_WTSStartRemoteControlSessionExW,
287
  FreeRDP_WTSStartRemoteControlSessionExA
288
};
289
290
const WtsApiFunctionTable* FreeRDP_InitWtsApi(void)
291
0
{
292
0
  return &FreeRDP_WtsApiFunctionTable;
293
0
}
294
295
BOOL freerdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize, UINT32 flags,
296
                                 const BYTE* data, size_t chunkSize)
297
0
{
298
0
  wStream* s = rdp_send_stream_init(rdp);
299
300
0
  if (!s)
301
0
    return FALSE;
302
303
0
  Stream_Write_UINT32(s, totalSize);
304
0
  Stream_Write_UINT32(s, flags);
305
306
0
  if (!Stream_EnsureCapacity(s, chunkSize))
307
0
  {
308
0
    Stream_Release(s);
309
0
    return FALSE;
310
0
  }
311
312
0
  Stream_Write(s, data, chunkSize);
313
314
  /* WLog_DBG(TAG, "sending data (flags=0x%x size=%d)",  flags, size); */
315
0
  return rdp_send(rdp, s, channelId);
316
0
}