Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/libfreerdp/utils/rdpdr_utils.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * SCard utility functions
4
 *
5
 * Copyright 2021 Armin Novak <armin.novak@thincast.com>
6
 * Copyright 2021 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 <winpr/wlog.h>
22
#include <winpr/print.h>
23
#include <winpr/smartcard.h>
24
25
#include <freerdp/utils/rdpdr_utils.h>
26
#include <freerdp/channels/scard.h>
27
#include <freerdp/channels/rdpdr.h>
28
29
#include <freerdp/log.h>
30
#define TAG FREERDP_TAG("utils.scard")
31
32
LONG scard_log_status_error(const char* tag, const char* what, LONG status)
33
0
{
34
0
  if (status != SCARD_S_SUCCESS)
35
0
  {
36
0
    DWORD level = WLOG_ERROR;
37
0
    switch (status)
38
0
    {
39
0
      case SCARD_E_TIMEOUT:
40
0
        level = WLOG_DEBUG;
41
0
        break;
42
0
      case SCARD_E_NO_READERS_AVAILABLE:
43
0
        level = WLOG_INFO;
44
0
        break;
45
0
      default:
46
0
        break;
47
0
    }
48
0
    WLog_Print(WLog_Get(tag), level, "%s failed with error %s [%" PRId32 "]", what,
49
0
               SCardGetErrorString(status), status);
50
0
  }
51
0
  return status;
52
0
}
53
54
const char* scard_get_ioctl_string(UINT32 ioControlCode, BOOL funcName)
55
0
{
56
0
  switch (ioControlCode)
57
0
  {
58
0
    case SCARD_IOCTL_ESTABLISHCONTEXT:
59
0
      return funcName ? "SCardEstablishContext" : "SCARD_IOCTL_ESTABLISHCONTEXT";
60
61
0
    case SCARD_IOCTL_RELEASECONTEXT:
62
0
      return funcName ? "SCardReleaseContext" : "SCARD_IOCTL_RELEASECONTEXT";
63
64
0
    case SCARD_IOCTL_ISVALIDCONTEXT:
65
0
      return funcName ? "SCardIsValidContext" : "SCARD_IOCTL_ISVALIDCONTEXT";
66
67
0
    case SCARD_IOCTL_LISTREADERGROUPSA:
68
0
      return funcName ? "SCardListReaderGroupsA" : "SCARD_IOCTL_LISTREADERGROUPSA";
69
70
0
    case SCARD_IOCTL_LISTREADERGROUPSW:
71
0
      return funcName ? "SCardListReaderGroupsW" : "SCARD_IOCTL_LISTREADERGROUPSW";
72
73
0
    case SCARD_IOCTL_LISTREADERSA:
74
0
      return funcName ? "SCardListReadersA" : "SCARD_IOCTL_LISTREADERSA";
75
76
0
    case SCARD_IOCTL_LISTREADERSW:
77
0
      return funcName ? "SCardListReadersW" : "SCARD_IOCTL_LISTREADERSW";
78
79
0
    case SCARD_IOCTL_INTRODUCEREADERGROUPA:
80
0
      return funcName ? "SCardIntroduceReaderGroupA" : "SCARD_IOCTL_INTRODUCEREADERGROUPA";
81
82
0
    case SCARD_IOCTL_INTRODUCEREADERGROUPW:
83
0
      return funcName ? "SCardIntroduceReaderGroupW" : "SCARD_IOCTL_INTRODUCEREADERGROUPW";
84
85
0
    case SCARD_IOCTL_FORGETREADERGROUPA:
86
0
      return funcName ? "SCardForgetReaderGroupA" : "SCARD_IOCTL_FORGETREADERGROUPA";
87
88
0
    case SCARD_IOCTL_FORGETREADERGROUPW:
89
0
      return funcName ? "SCardForgetReaderGroupW" : "SCARD_IOCTL_FORGETREADERGROUPW";
90
91
0
    case SCARD_IOCTL_INTRODUCEREADERA:
92
0
      return funcName ? "SCardIntroduceReaderA" : "SCARD_IOCTL_INTRODUCEREADERA";
93
94
0
    case SCARD_IOCTL_INTRODUCEREADERW:
95
0
      return funcName ? "SCardIntroduceReaderW" : "SCARD_IOCTL_INTRODUCEREADERW";
96
97
0
    case SCARD_IOCTL_FORGETREADERA:
98
0
      return funcName ? "SCardForgetReaderA" : "SCARD_IOCTL_FORGETREADERA";
99
100
0
    case SCARD_IOCTL_FORGETREADERW:
101
0
      return funcName ? "SCardForgetReaderW" : "SCARD_IOCTL_FORGETREADERW";
102
103
0
    case SCARD_IOCTL_ADDREADERTOGROUPA:
104
0
      return funcName ? "SCardAddReaderToGroupA" : "SCARD_IOCTL_ADDREADERTOGROUPA";
105
106
0
    case SCARD_IOCTL_ADDREADERTOGROUPW:
107
0
      return funcName ? "SCardAddReaderToGroupW" : "SCARD_IOCTL_ADDREADERTOGROUPW";
108
109
0
    case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
110
0
      return funcName ? "SCardRemoveReaderFromGroupA" : "SCARD_IOCTL_REMOVEREADERFROMGROUPA";
111
112
0
    case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
113
0
      return funcName ? "SCardRemoveReaderFromGroupW" : "SCARD_IOCTL_REMOVEREADERFROMGROUPW";
114
115
0
    case SCARD_IOCTL_LOCATECARDSA:
116
0
      return funcName ? "SCardLocateCardsA" : "SCARD_IOCTL_LOCATECARDSA";
117
118
0
    case SCARD_IOCTL_LOCATECARDSW:
119
0
      return funcName ? "SCardLocateCardsW" : "SCARD_IOCTL_LOCATECARDSW";
120
121
0
    case SCARD_IOCTL_GETSTATUSCHANGEA:
122
0
      return funcName ? "SCardGetStatusChangeA" : "SCARD_IOCTL_GETSTATUSCHANGEA";
123
124
0
    case SCARD_IOCTL_GETSTATUSCHANGEW:
125
0
      return funcName ? "SCardGetStatusChangeW" : "SCARD_IOCTL_GETSTATUSCHANGEW";
126
127
0
    case SCARD_IOCTL_CANCEL:
128
0
      return funcName ? "SCardCancel" : "SCARD_IOCTL_CANCEL";
129
130
0
    case SCARD_IOCTL_CONNECTA:
131
0
      return funcName ? "SCardConnectA" : "SCARD_IOCTL_CONNECTA";
132
133
0
    case SCARD_IOCTL_CONNECTW:
134
0
      return funcName ? "SCardConnectW" : "SCARD_IOCTL_CONNECTW";
135
136
0
    case SCARD_IOCTL_RECONNECT:
137
0
      return funcName ? "SCardReconnect" : "SCARD_IOCTL_RECONNECT";
138
139
0
    case SCARD_IOCTL_DISCONNECT:
140
0
      return funcName ? "SCardDisconnect" : "SCARD_IOCTL_DISCONNECT";
141
142
0
    case SCARD_IOCTL_BEGINTRANSACTION:
143
0
      return funcName ? "SCardBeginTransaction" : "SCARD_IOCTL_BEGINTRANSACTION";
144
145
0
    case SCARD_IOCTL_ENDTRANSACTION:
146
0
      return funcName ? "SCardEndTransaction" : "SCARD_IOCTL_ENDTRANSACTION";
147
148
0
    case SCARD_IOCTL_STATE:
149
0
      return funcName ? "SCardState" : "SCARD_IOCTL_STATE";
150
151
0
    case SCARD_IOCTL_STATUSA:
152
0
      return funcName ? "SCardStatusA" : "SCARD_IOCTL_STATUSA";
153
154
0
    case SCARD_IOCTL_STATUSW:
155
0
      return funcName ? "SCardStatusW" : "SCARD_IOCTL_STATUSW";
156
157
0
    case SCARD_IOCTL_TRANSMIT:
158
0
      return funcName ? "SCardTransmit" : "SCARD_IOCTL_TRANSMIT";
159
160
0
    case SCARD_IOCTL_CONTROL:
161
0
      return funcName ? "SCardControl" : "SCARD_IOCTL_CONTROL";
162
163
0
    case SCARD_IOCTL_GETATTRIB:
164
0
      return funcName ? "SCardGetAttrib" : "SCARD_IOCTL_GETATTRIB";
165
166
0
    case SCARD_IOCTL_SETATTRIB:
167
0
      return funcName ? "SCardSetAttrib" : "SCARD_IOCTL_SETATTRIB";
168
169
0
    case SCARD_IOCTL_ACCESSSTARTEDEVENT:
170
0
      return funcName ? "SCardAccessStartedEvent" : "SCARD_IOCTL_ACCESSSTARTEDEVENT";
171
172
0
    case SCARD_IOCTL_LOCATECARDSBYATRA:
173
0
      return funcName ? "SCardLocateCardsByATRA" : "SCARD_IOCTL_LOCATECARDSBYATRA";
174
175
0
    case SCARD_IOCTL_LOCATECARDSBYATRW:
176
0
      return funcName ? "SCardLocateCardsByATRB" : "SCARD_IOCTL_LOCATECARDSBYATRW";
177
178
0
    case SCARD_IOCTL_READCACHEA:
179
0
      return funcName ? "SCardReadCacheA" : "SCARD_IOCTL_READCACHEA";
180
181
0
    case SCARD_IOCTL_READCACHEW:
182
0
      return funcName ? "SCardReadCacheW" : "SCARD_IOCTL_READCACHEW";
183
184
0
    case SCARD_IOCTL_WRITECACHEA:
185
0
      return funcName ? "SCardWriteCacheA" : "SCARD_IOCTL_WRITECACHEA";
186
187
0
    case SCARD_IOCTL_WRITECACHEW:
188
0
      return funcName ? "SCardWriteCacheW" : "SCARD_IOCTL_WRITECACHEW";
189
190
0
    case SCARD_IOCTL_GETTRANSMITCOUNT:
191
0
      return funcName ? "SCardGetTransmitCount" : "SCARD_IOCTL_GETTRANSMITCOUNT";
192
193
0
    case SCARD_IOCTL_RELEASETARTEDEVENT:
194
0
      return funcName ? "SCardReleaseStartedEvent" : "SCARD_IOCTL_RELEASETARTEDEVENT";
195
196
0
    case SCARD_IOCTL_GETREADERICON:
197
0
      return funcName ? "SCardGetReaderIcon" : "SCARD_IOCTL_GETREADERICON";
198
199
0
    case SCARD_IOCTL_GETDEVICETYPEID:
200
0
      return funcName ? "SCardGetDeviceTypeId" : "SCARD_IOCTL_GETDEVICETYPEID";
201
202
0
    default:
203
0
      return funcName ? "SCardUnknown" : "SCARD_IOCTL_UNKNOWN";
204
0
  }
205
0
}
206
207
const char* rdpdr_component_string(UINT16 component)
208
0
{
209
0
  switch (component)
210
0
  {
211
0
    case RDPDR_CTYP_PRN:
212
0
      return "RDPDR_CTYP_PRN";
213
0
    case RDPDR_CTYP_CORE:
214
0
      return "RDPDR_CTYP_CORE";
215
0
    default:
216
0
      return "UNKNOWN";
217
0
  }
218
0
}
219
220
const char* rdpdr_packetid_string(UINT16 packetid)
221
0
{
222
0
  switch (packetid)
223
0
  {
224
0
    case PAKID_CORE_SERVER_ANNOUNCE:
225
0
      return "PAKID_CORE_SERVER_ANNOUNCE";
226
0
    case PAKID_CORE_CLIENTID_CONFIRM:
227
0
      return "PAKID_CORE_CLIENTID_CONFIRM";
228
0
    case PAKID_CORE_CLIENT_NAME:
229
0
      return "PAKID_CORE_CLIENT_NAME";
230
0
    case PAKID_CORE_DEVICELIST_ANNOUNCE:
231
0
      return "PAKID_CORE_DEVICELIST_ANNOUNCE";
232
0
    case PAKID_CORE_DEVICE_REPLY:
233
0
      return "PAKID_CORE_DEVICE_REPLY";
234
0
    case PAKID_CORE_DEVICE_IOREQUEST:
235
0
      return "PAKID_CORE_DEVICE_IOREQUEST";
236
0
    case PAKID_CORE_DEVICE_IOCOMPLETION:
237
0
      return "PAKID_CORE_DEVICE_IOCOMPLETION";
238
0
    case PAKID_CORE_SERVER_CAPABILITY:
239
0
      return "PAKID_CORE_SERVER_CAPABILITY";
240
0
    case PAKID_CORE_CLIENT_CAPABILITY:
241
0
      return "PAKID_CORE_CLIENT_CAPABILITY";
242
0
    case PAKID_CORE_DEVICELIST_REMOVE:
243
0
      return "PAKID_CORE_DEVICELIST_REMOVE";
244
0
    case PAKID_CORE_USER_LOGGEDON:
245
0
      return "PAKID_CORE_USER_LOGGEDON";
246
0
    case PAKID_PRN_CACHE_DATA:
247
0
      return "PAKID_PRN_CACHE_DATA";
248
0
    case PAKID_PRN_USING_XPS:
249
0
      return "PAKID_PRN_USING_XPS";
250
0
    default:
251
0
      return "UNKNOWN";
252
0
  }
253
0
}
254
255
BOOL rdpdr_write_iocompletion_header(wStream* out, UINT32 DeviceId, UINT32 CompletionId,
256
                                     UINT32 ioStatus)
257
0
{
258
0
  WINPR_ASSERT(out);
259
0
  Stream_SetPosition(out, 0);
260
0
  if (!Stream_EnsureRemainingCapacity(out, 16))
261
0
    return FALSE;
262
0
  Stream_Write_UINT16(out, RDPDR_CTYP_CORE);                /* Component (2 bytes) */
263
0
  Stream_Write_UINT16(out, PAKID_CORE_DEVICE_IOCOMPLETION); /* PacketId (2 bytes) */
264
0
  Stream_Write_UINT32(out, DeviceId);                       /* DeviceId (4 bytes) */
265
0
  Stream_Write_UINT32(out, CompletionId);                   /* CompletionId (4 bytes) */
266
0
  Stream_Write_UINT32(out, ioStatus);                       /* IoStatus (4 bytes) */
267
268
0
  return TRUE;
269
0
}
270
271
static void rdpdr_dump_packet(wLog* log, DWORD lvl, wStream* s, const char* custom, BOOL send)
272
0
{
273
0
  if (!WLog_IsLevelActive(log, lvl))
274
0
    return;
275
276
0
  const size_t gpos = Stream_GetPosition(s);
277
0
  const size_t pos = send ? Stream_GetPosition(s) : Stream_Length(s);
278
279
0
  UINT16 component = 0;
280
0
  UINT16 packetid = 0;
281
282
0
  Stream_SetPosition(s, 0);
283
284
0
  if (pos >= 2)
285
0
    Stream_Read_UINT16(s, component);
286
0
  if (pos >= 4)
287
0
    Stream_Read_UINT16(s, packetid);
288
289
0
  switch (packetid)
290
0
  {
291
0
    case PAKID_CORE_SERVER_ANNOUNCE:
292
0
    case PAKID_CORE_CLIENTID_CONFIRM:
293
0
    {
294
0
      UINT16 versionMajor = 0;
295
0
      UINT16 versionMinor = 0;
296
0
      UINT32 clientID = 0;
297
298
0
      if (pos >= 6)
299
0
        Stream_Read_UINT16(s, versionMajor);
300
0
      if (pos >= 8)
301
0
        Stream_Read_UINT16(s, versionMinor);
302
0
      if (pos >= 12)
303
0
        Stream_Read_UINT32(s, clientID);
304
0
      WLog_Print(log, lvl,
305
0
                 "%s [%s | %s] [version:%" PRIu16 ".%" PRIu16 "][id:0x%08" PRIx32
306
0
                 "] -> %" PRIuz,
307
0
                 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
308
0
                 versionMajor, versionMinor, clientID, pos);
309
0
    }
310
0
    break;
311
0
    case PAKID_CORE_CLIENT_NAME:
312
0
    {
313
0
      char name[256] = { 0 };
314
0
      UINT32 unicodeFlag = 0;
315
0
      UINT32 codePage = 0;
316
0
      UINT32 computerNameLen = 0;
317
0
      if (pos >= 8)
318
0
        Stream_Read_UINT32(s, unicodeFlag);
319
0
      if (pos >= 12)
320
0
        Stream_Read_UINT32(s, codePage);
321
0
      if (pos >= 16)
322
0
        Stream_Read_UINT32(s, computerNameLen);
323
0
      if (pos >= 16 + computerNameLen)
324
0
      {
325
0
        if (unicodeFlag == 0)
326
0
          Stream_Read(s, name, MIN(sizeof(name), computerNameLen));
327
0
        else
328
0
          ConvertWCharNToUtf8(Stream_ConstPointer(s), computerNameLen / sizeof(WCHAR),
329
0
                              name, sizeof(name));
330
0
      }
331
0
      WLog_Print(log, lvl,
332
0
                 "%s [%s | %s] [ucs:%" PRIu32 "|cp:%" PRIu32 "][len:0x%08" PRIx32
333
0
                 "] '%s' -> %" PRIuz,
334
0
                 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
335
0
                 unicodeFlag, codePage, computerNameLen, name, pos);
336
0
    }
337
0
    break;
338
339
0
    case PAKID_CORE_DEVICE_IOREQUEST:
340
0
    {
341
0
      UINT32 CompletionId = 0;
342
0
      UINT32 deviceID = 0;
343
0
      UINT32 FileId = 0;
344
0
      UINT32 MajorFunction = 0;
345
0
      UINT32 MinorFunction = 0;
346
347
0
      if (pos >= 8)
348
0
        Stream_Read_UINT32(s, deviceID);
349
0
      if (pos >= 12)
350
0
        Stream_Read_UINT32(s, FileId);
351
0
      if (pos >= 16)
352
0
        Stream_Read_UINT32(s, CompletionId);
353
0
      if (pos >= 20)
354
0
        Stream_Read_UINT32(s, MajorFunction);
355
0
      if (pos >= 24)
356
0
        Stream_Read_UINT32(s, MinorFunction);
357
0
      WLog_Print(log, lvl,
358
0
                 "%s [%s | %s] [0x%08" PRIx32 "] FileId=0x%08" PRIx32
359
0
                 ", CompletionId=0x%08" PRIx32 ", MajorFunction=0x%08" PRIx32
360
0
                 ", MinorFunction=0x%08" PRIx32 " -> %" PRIuz,
361
0
                 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
362
0
                 deviceID, FileId, CompletionId, MajorFunction, MinorFunction, pos);
363
0
    }
364
0
    break;
365
0
    case PAKID_CORE_DEVICE_IOCOMPLETION:
366
0
    {
367
0
      UINT32 completionID = 0;
368
0
      UINT32 ioStatus = 0;
369
0
      UINT32 deviceID = 0;
370
0
      if (pos >= 8)
371
0
        Stream_Read_UINT32(s, deviceID);
372
0
      if (pos >= 12)
373
0
        Stream_Read_UINT32(s, completionID);
374
0
      if (pos >= 16)
375
0
        Stream_Read_UINT32(s, ioStatus);
376
377
0
      WLog_Print(log, lvl,
378
0
                 "%s [%s | %s] [0x%08" PRIx32 "] completionID=0x%08" PRIx32
379
0
                 ", ioStatus=0x%08" PRIx32 " -> %" PRIuz,
380
0
                 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
381
0
                 deviceID, completionID, ioStatus, pos);
382
0
    }
383
0
    break;
384
0
    case PAKID_CORE_DEVICE_REPLY:
385
0
    {
386
0
      UINT32 deviceID = 0;
387
0
      UINT32 status = 0;
388
389
0
      if (pos >= 8)
390
0
        Stream_Read_UINT32(s, deviceID);
391
0
      if (pos >= 12)
392
0
        Stream_Read_UINT32(s, status);
393
0
      WLog_Print(log, lvl,
394
0
                 "%s [%s | %s] [id:0x%08" PRIx32 ",status=0x%08" PRIx32 "] -> %" PRIuz,
395
0
                 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
396
0
                 deviceID, status, pos);
397
0
    }
398
0
    break;
399
0
    case PAKID_CORE_CLIENT_CAPABILITY:
400
0
    case PAKID_CORE_SERVER_CAPABILITY:
401
0
    {
402
0
      UINT16 numCapabilities = 0;
403
0
      if (pos >= 6)
404
0
        Stream_Read_UINT16(s, numCapabilities);
405
0
      if (pos >= 8)
406
0
        Stream_Seek_UINT16(s); /* padding */
407
0
      WLog_Print(log, lvl, "%s [%s | %s] [caps:%" PRIu16 "] -> %" PRIuz, custom,
408
0
                 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
409
0
                 numCapabilities, pos);
410
0
      for (UINT16 x = 0; x < numCapabilities; x++)
411
0
      {
412
0
        RDPDR_CAPABILITY_HEADER header = { 0 };
413
0
        const UINT error = rdpdr_read_capset_header(log, s, &header);
414
0
        if (error == CHANNEL_RC_OK)
415
0
          Stream_Seek(s, header.CapabilityLength);
416
0
      }
417
0
    }
418
0
    break;
419
0
    case PAKID_CORE_DEVICELIST_ANNOUNCE:
420
0
    {
421
0
      size_t offset = 8;
422
0
      UINT32 count = 0;
423
424
0
      if (pos >= offset)
425
0
        Stream_Read_UINT32(s, count);
426
427
0
      WLog_Print(log, lvl, "%s [%s | %s] [%" PRIu32 "] -> %" PRIuz, custom,
428
0
                 rdpdr_component_string(component), rdpdr_packetid_string(packetid), count,
429
0
                 pos);
430
431
0
      for (UINT32 x = 0; x < count; x++)
432
0
      {
433
0
        RdpdrDevice device = { 0 };
434
435
0
        offset += 20;
436
0
        if (pos >= offset)
437
0
        {
438
0
          Stream_Read_UINT32(s, device.DeviceType);       /* DeviceType (4 bytes) */
439
0
          Stream_Read_UINT32(s, device.DeviceId);         /* DeviceId (4 bytes) */
440
0
          Stream_Read(s, device.PreferredDosName, 8);     /* PreferredDosName (8 bytes) */
441
0
          Stream_Read_UINT32(s, device.DeviceDataLength); /* DeviceDataLength (4 bytes) */
442
0
          device.DeviceData = Stream_Pointer(s);
443
0
        }
444
0
        offset += device.DeviceDataLength;
445
446
0
        WLog_Print(log, lvl,
447
0
                   "%s [announce][%" PRIu32 "] %s [0x%08" PRIx32
448
0
                   "] '%s' [DeviceDataLength=%" PRIu32 "]",
449
0
                   custom, x, freerdp_rdpdr_dtyp_string(device.DeviceType), device.DeviceId,
450
0
                   device.PreferredDosName, device.DeviceDataLength);
451
0
      }
452
0
    }
453
0
    break;
454
0
    case PAKID_CORE_DEVICELIST_REMOVE:
455
0
    {
456
0
      size_t offset = 8;
457
0
      UINT32 count = 0;
458
459
0
      if (pos >= offset)
460
0
        Stream_Read_UINT32(s, count);
461
462
0
      WLog_Print(log, lvl, "%s [%s | %s] [%" PRIu32 "] -> %" PRIuz, custom,
463
0
                 rdpdr_component_string(component), rdpdr_packetid_string(packetid), count,
464
0
                 pos);
465
466
0
      for (UINT32 x = 0; x < count; x++)
467
0
      {
468
0
        UINT32 id = 0;
469
470
0
        offset += 4;
471
0
        if (pos >= offset)
472
0
          Stream_Read_UINT32(s, id);
473
474
0
        WLog_Print(log, lvl, "%s [remove][%" PRIu32 "] id=%" PRIu32, custom, x, id);
475
0
      }
476
0
    }
477
0
    break;
478
0
    case PAKID_CORE_USER_LOGGEDON:
479
0
      WLog_Print(log, lvl, "%s [%s | %s] -> %" PRIuz, custom,
480
0
                 rdpdr_component_string(component), rdpdr_packetid_string(packetid), pos);
481
0
      break;
482
0
    default:
483
0
    {
484
0
      WLog_Print(log, lvl, "%s [%s | %s] -> %" PRIuz, custom,
485
0
                 rdpdr_component_string(component), rdpdr_packetid_string(packetid), pos);
486
0
    }
487
0
    break;
488
0
  }
489
490
  // winpr_HexLogDump(log, lvl, Stream_Buffer(s), pos);
491
0
  Stream_SetPosition(s, gpos);
492
0
}
493
494
void rdpdr_dump_received_packet(wLog* log, DWORD lvl, wStream* s, const char* custom)
495
0
{
496
0
  rdpdr_dump_packet(log, lvl, s, custom, FALSE);
497
0
}
498
499
void rdpdr_dump_send_packet(wLog* log, DWORD lvl, wStream* s, const char* custom)
500
0
{
501
0
  rdpdr_dump_packet(log, lvl, s, custom, TRUE);
502
0
}
503
504
const char* rdpdr_irp_string(UINT32 major)
505
0
{
506
0
  switch (major)
507
0
  {
508
0
    case IRP_MJ_CREATE:
509
0
      return "IRP_MJ_CREATE";
510
0
    case IRP_MJ_CLOSE:
511
0
      return "IRP_MJ_CLOSE";
512
0
    case IRP_MJ_READ:
513
0
      return "IRP_MJ_READ";
514
0
    case IRP_MJ_WRITE:
515
0
      return "IRP_MJ_WRITE";
516
0
    case IRP_MJ_DEVICE_CONTROL:
517
0
      return "IRP_MJ_DEVICE_CONTROL";
518
0
    case IRP_MJ_QUERY_VOLUME_INFORMATION:
519
0
      return "IRP_MJ_QUERY_VOLUME_INFORMATION";
520
0
    case IRP_MJ_SET_VOLUME_INFORMATION:
521
0
      return "IRP_MJ_SET_VOLUME_INFORMATION";
522
0
    case IRP_MJ_QUERY_INFORMATION:
523
0
      return "IRP_MJ_QUERY_INFORMATION";
524
0
    case IRP_MJ_SET_INFORMATION:
525
0
      return "IRP_MJ_SET_INFORMATION";
526
0
    case IRP_MJ_DIRECTORY_CONTROL:
527
0
      return "IRP_MJ_DIRECTORY_CONTROL";
528
0
    case IRP_MJ_LOCK_CONTROL:
529
0
      return "IRP_MJ_LOCK_CONTROL";
530
0
    default:
531
0
      return "IRP_UNKNOWN";
532
0
  }
533
0
}
534
535
const char* rdpdr_cap_type_string(UINT16 capability)
536
0
{
537
0
  switch (capability)
538
0
  {
539
0
    case CAP_GENERAL_TYPE:
540
0
      return "CAP_GENERAL_TYPE";
541
0
    case CAP_PRINTER_TYPE:
542
0
      return "CAP_PRINTER_TYPE";
543
0
    case CAP_PORT_TYPE:
544
0
      return "CAP_PORT_TYPE";
545
0
    case CAP_DRIVE_TYPE:
546
0
      return "CAP_DRIVE_TYPE";
547
0
    case CAP_SMARTCARD_TYPE:
548
0
      return "CAP_SMARTCARD_TYPE";
549
0
    default:
550
0
      return "CAP_UNKNOWN";
551
0
  }
552
0
}
553
554
UINT rdpdr_read_capset_header(wLog* log, wStream* s, RDPDR_CAPABILITY_HEADER* header)
555
0
{
556
0
  WINPR_ASSERT(header);
557
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
558
0
    return ERROR_INVALID_DATA;
559
560
0
  Stream_Read_UINT16(s, header->CapabilityType);   /* CapabilityType (2 bytes) */
561
0
  Stream_Read_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */
562
0
  Stream_Read_UINT32(s, header->Version);          /* Version (4 bytes) */
563
564
0
  WLog_Print(log, WLOG_TRACE,
565
0
             "capability %s [0x%04" PRIx16 "] got version %" PRIu32 ", length %" PRIu16,
566
0
             rdpdr_cap_type_string(header->CapabilityType), header->CapabilityType,
567
0
             header->Version, header->CapabilityLength);
568
0
  if (header->CapabilityLength < 8)
569
0
  {
570
0
    WLog_Print(log, WLOG_ERROR, "capability %s got short length %" PRIu32,
571
0
               rdpdr_cap_type_string(header->CapabilityType), header->CapabilityLength);
572
0
    return ERROR_INVALID_DATA;
573
0
  }
574
0
  header->CapabilityLength -= 8;
575
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, header->CapabilityLength))
576
0
    return ERROR_INVALID_DATA;
577
0
  return CHANNEL_RC_OK;
578
0
}
579
580
UINT rdpdr_write_capset_header(wLog* log, wStream* s, const RDPDR_CAPABILITY_HEADER* header)
581
0
{
582
0
  WINPR_ASSERT(header);
583
0
  WINPR_ASSERT(header->CapabilityLength >= 8);
584
585
0
  if (!Stream_EnsureRemainingCapacity(s, header->CapabilityLength))
586
0
  {
587
0
    WLog_Print(log, WLOG_ERROR, "not enough data in stream!");
588
0
    return ERROR_INVALID_DATA;
589
0
  }
590
591
0
  WLog_Print(log, WLOG_TRACE, "writing capability %s version %" PRIu32 ", length %" PRIu16,
592
0
             rdpdr_cap_type_string(header->CapabilityType), header->Version,
593
0
             header->CapabilityLength);
594
0
  Stream_Write_UINT16(s, header->CapabilityType);   /* CapabilityType (2 bytes) */
595
0
  Stream_Write_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */
596
0
  Stream_Write_UINT32(s, header->Version);          /* Version (4 bytes) */
597
0
  return CHANNEL_RC_OK;
598
0
}