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