Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/libfreerdp/utils/smartcard_operations.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Smartcard Device Service Virtual Channel
4
 *
5
 * Copyright (C) Alexi Volkov <alexi@myrealbox.com> 2006
6
 * Copyright 2011 O.S. Systems Software Ltda.
7
 * Copyright 2011 Anthony Tong <atong@trustedcs.com>
8
 * Copyright 2015 Thincast Technologies GmbH
9
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
10
 * Copyright 2017 Armin Novak <armin.novak@thincast.com>
11
 * Copyright 2017 Thincast Technologies GmbH
12
 *
13
 * Licensed under the Apache License, Version 2.0 (the "License");
14
 * you may not use this file except in compliance with the License.
15
 * You may obtain a copy of the License at
16
 *
17
 *     http://www.apache.org/licenses/LICENSE-2.0
18
 *
19
 * Unless required by applicable law or agreed to in writing, software
20
 * distributed under the License is distributed on an "AS IS" BASIS,
21
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
 * See the License for the specific language governing permissions and
23
 * limitations under the License.
24
 */
25
26
#include <freerdp/config.h>
27
28
#include <winpr/assert.h>
29
30
#include <winpr/crt.h>
31
#include <winpr/print.h>
32
#include <winpr/stream.h>
33
#include <winpr/smartcard.h>
34
35
#include <freerdp/freerdp.h>
36
#include <freerdp/channels/rdpdr.h>
37
#include <freerdp/channels/scard.h>
38
39
#include <freerdp/utils/rdpdr_utils.h>
40
41
#include <freerdp/utils/smartcard_operations.h>
42
#include <freerdp/utils/smartcard_pack.h>
43
44
#include <freerdp/log.h>
45
0
#define TAG FREERDP_TAG("utils.smartcard.ops")
46
47
static LONG smartcard_call_to_operation_handle(SMARTCARD_OPERATION* operation)
48
0
{
49
0
  WINPR_ASSERT(operation);
50
51
0
  operation->hContext =
52
0
      smartcard_scard_context_native_from_redir(&(operation->call.handles.hContext));
53
0
  operation->hCard = smartcard_scard_handle_native_from_redir(&(operation->call.handles.hCard));
54
55
0
  return SCARD_S_SUCCESS;
56
0
}
57
58
static LONG smartcard_EstablishContext_Decode(wStream* s, SMARTCARD_OPERATION* operation)
59
0
{
60
0
  LONG status = 0;
61
62
0
  WINPR_ASSERT(s);
63
0
  WINPR_ASSERT(operation);
64
65
0
  status = smartcard_unpack_establish_context_call(s, &operation->call.establishContext);
66
0
  if (status != SCARD_S_SUCCESS)
67
0
  {
68
0
    return scard_log_status_error(TAG, "smartcard_unpack_establish_context_call", status);
69
0
  }
70
71
0
  return SCARD_S_SUCCESS;
72
0
}
73
74
static LONG smartcard_ReleaseContext_Decode(wStream* s, SMARTCARD_OPERATION* operation)
75
0
{
76
0
  LONG status = 0;
77
78
0
  WINPR_ASSERT(s);
79
0
  WINPR_ASSERT(operation);
80
81
0
  status = smartcard_unpack_context_call(s, &operation->call.context, "ReleaseContext");
82
0
  if (status != SCARD_S_SUCCESS)
83
0
    scard_log_status_error(TAG, "smartcard_unpack_context_call", status);
84
85
0
  return status;
86
0
}
87
88
static LONG smartcard_IsValidContext_Decode(wStream* s, SMARTCARD_OPERATION* operation)
89
0
{
90
0
  LONG status = 0;
91
92
0
  WINPR_ASSERT(s);
93
0
  WINPR_ASSERT(operation);
94
95
0
  status = smartcard_unpack_context_call(s, &operation->call.context, "IsValidContext");
96
97
0
  return status;
98
0
}
99
100
static LONG smartcard_ListReaderGroupsA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
101
0
{
102
0
  LONG status = 0;
103
104
0
  WINPR_ASSERT(s);
105
0
  WINPR_ASSERT(operation);
106
107
0
  status = smartcard_unpack_list_reader_groups_call(s, &operation->call.listReaderGroups, FALSE);
108
109
0
  return status;
110
0
}
111
112
static LONG smartcard_ListReaderGroupsW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
113
0
{
114
0
  LONG status = 0;
115
116
0
  WINPR_ASSERT(s);
117
0
  WINPR_ASSERT(operation);
118
119
0
  status = smartcard_unpack_list_reader_groups_call(s, &operation->call.listReaderGroups, TRUE);
120
121
0
  return status;
122
0
}
123
124
static LONG smartcard_ListReadersA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
125
0
{
126
0
  LONG status = 0;
127
128
0
  WINPR_ASSERT(s);
129
0
  WINPR_ASSERT(operation);
130
131
0
  status = smartcard_unpack_list_readers_call(s, &operation->call.listReaders, FALSE);
132
133
0
  return status;
134
0
}
135
136
static LONG smartcard_ListReadersW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
137
0
{
138
0
  LONG status = 0;
139
140
0
  WINPR_ASSERT(s);
141
0
  WINPR_ASSERT(operation);
142
143
0
  status = smartcard_unpack_list_readers_call(s, &operation->call.listReaders, TRUE);
144
145
0
  return status;
146
0
}
147
148
static LONG smartcard_context_and_two_strings_a_Decode(wStream* s, SMARTCARD_OPERATION* operation)
149
0
{
150
0
  LONG status = 0;
151
152
0
  WINPR_ASSERT(s);
153
0
  WINPR_ASSERT(operation);
154
155
0
  status =
156
0
      smartcard_unpack_context_and_two_strings_a_call(s, &operation->call.contextAndTwoStringA);
157
158
0
  return status;
159
0
}
160
161
static LONG smartcard_context_and_two_strings_w_Decode(wStream* s, SMARTCARD_OPERATION* operation)
162
0
{
163
0
  LONG status = 0;
164
165
0
  WINPR_ASSERT(s);
166
0
  WINPR_ASSERT(operation);
167
168
0
  status =
169
0
      smartcard_unpack_context_and_two_strings_w_call(s, &operation->call.contextAndTwoStringW);
170
171
0
  return status;
172
0
}
173
174
static LONG smartcard_context_and_string_a_Decode(wStream* s, SMARTCARD_OPERATION* operation)
175
0
{
176
0
  LONG status = 0;
177
178
0
  WINPR_ASSERT(s);
179
0
  WINPR_ASSERT(operation);
180
181
0
  status = smartcard_unpack_context_and_string_a_call(s, &operation->call.contextAndStringA);
182
183
0
  return status;
184
0
}
185
186
static LONG smartcard_context_and_string_w_Decode(wStream* s, SMARTCARD_OPERATION* operation)
187
0
{
188
0
  LONG status = 0;
189
190
0
  WINPR_ASSERT(s);
191
0
  WINPR_ASSERT(operation);
192
193
0
  status = smartcard_unpack_context_and_string_w_call(s, &operation->call.contextAndStringW);
194
195
0
  return status;
196
0
}
197
198
static LONG smartcard_LocateCardsA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
199
0
{
200
0
  LONG status = 0;
201
202
0
  WINPR_ASSERT(s);
203
0
  WINPR_ASSERT(operation);
204
205
0
  status = smartcard_unpack_locate_cards_a_call(s, &operation->call.locateCardsA);
206
207
0
  return status;
208
0
}
209
210
static LONG smartcard_LocateCardsW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
211
0
{
212
0
  LONG status = 0;
213
214
0
  WINPR_ASSERT(s);
215
0
  WINPR_ASSERT(operation);
216
217
0
  status = smartcard_unpack_locate_cards_w_call(s, &operation->call.locateCardsW);
218
219
0
  return status;
220
0
}
221
222
static LONG smartcard_GetStatusChangeA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
223
0
{
224
0
  WINPR_ASSERT(s);
225
0
  WINPR_ASSERT(operation);
226
227
0
  return smartcard_unpack_get_status_change_a_call(s, &operation->call.getStatusChangeA);
228
0
}
229
230
static LONG smartcard_GetStatusChangeW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
231
0
{
232
0
  WINPR_ASSERT(s);
233
0
  WINPR_ASSERT(operation);
234
235
0
  return smartcard_unpack_get_status_change_w_call(s, &operation->call.getStatusChangeW);
236
0
}
237
238
static LONG smartcard_Cancel_Decode(wStream* s, SMARTCARD_OPERATION* operation)
239
0
{
240
0
  LONG status = 0;
241
242
0
  WINPR_ASSERT(s);
243
0
  WINPR_ASSERT(operation);
244
245
0
  status = smartcard_unpack_context_call(s, &operation->call.context, "Cancel");
246
247
0
  return status;
248
0
}
249
250
static LONG smartcard_ConnectA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
251
0
{
252
0
  LONG status = 0;
253
254
0
  WINPR_ASSERT(s);
255
0
  WINPR_ASSERT(operation);
256
257
0
  status = smartcard_unpack_connect_a_call(s, &operation->call.connectA);
258
259
0
  return status;
260
0
}
261
262
static LONG smartcard_ConnectW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
263
0
{
264
0
  LONG status = 0;
265
266
0
  WINPR_ASSERT(s);
267
0
  WINPR_ASSERT(operation);
268
269
0
  status = smartcard_unpack_connect_w_call(s, &operation->call.connectW);
270
271
0
  return status;
272
0
}
273
274
static LONG smartcard_Reconnect_Decode(wStream* s, SMARTCARD_OPERATION* operation)
275
0
{
276
0
  LONG status = 0;
277
278
0
  WINPR_ASSERT(s);
279
0
  WINPR_ASSERT(operation);
280
281
0
  status = smartcard_unpack_reconnect_call(s, &operation->call.reconnect);
282
283
0
  return status;
284
0
}
285
286
static LONG smartcard_Disconnect_Decode(wStream* s, SMARTCARD_OPERATION* operation)
287
0
{
288
0
  LONG status = 0;
289
290
0
  WINPR_ASSERT(s);
291
0
  WINPR_ASSERT(operation);
292
293
0
  status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
294
0
                                                       "Disconnect");
295
296
0
  return status;
297
0
}
298
299
static LONG smartcard_BeginTransaction_Decode(wStream* s, SMARTCARD_OPERATION* operation)
300
0
{
301
0
  LONG status = 0;
302
303
0
  WINPR_ASSERT(s);
304
0
  WINPR_ASSERT(operation);
305
306
0
  status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
307
0
                                                       "BeginTransaction");
308
309
0
  return status;
310
0
}
311
312
static LONG smartcard_EndTransaction_Decode(wStream* s, SMARTCARD_OPERATION* operation)
313
0
{
314
0
  LONG status = 0;
315
316
0
  WINPR_ASSERT(s);
317
0
  WINPR_ASSERT(operation);
318
319
0
  status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
320
0
                                                       "EndTransaction");
321
322
0
  return status;
323
0
}
324
325
static LONG smartcard_State_Decode(wStream* s, SMARTCARD_OPERATION* operation)
326
0
{
327
0
  LONG status = 0;
328
329
0
  WINPR_ASSERT(s);
330
0
  WINPR_ASSERT(operation);
331
332
0
  status = smartcard_unpack_state_call(s, &operation->call.state);
333
334
0
  return status;
335
0
}
336
337
static LONG smartcard_StatusA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
338
0
{
339
0
  LONG status = 0;
340
341
0
  WINPR_ASSERT(s);
342
0
  WINPR_ASSERT(operation);
343
344
0
  status = smartcard_unpack_status_call(s, &operation->call.status, FALSE);
345
346
0
  return status;
347
0
}
348
349
static LONG smartcard_StatusW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
350
0
{
351
0
  LONG status = 0;
352
353
0
  WINPR_ASSERT(s);
354
0
  WINPR_ASSERT(operation);
355
356
0
  status = smartcard_unpack_status_call(s, &operation->call.status, TRUE);
357
358
0
  return status;
359
0
}
360
361
static LONG smartcard_Transmit_Decode(wStream* s, SMARTCARD_OPERATION* operation)
362
0
{
363
0
  LONG status = 0;
364
365
0
  WINPR_ASSERT(s);
366
0
  WINPR_ASSERT(operation);
367
368
0
  status = smartcard_unpack_transmit_call(s, &operation->call.transmit);
369
370
0
  return status;
371
0
}
372
373
static LONG smartcard_Control_Decode(wStream* s, SMARTCARD_OPERATION* operation)
374
0
{
375
0
  LONG status = 0;
376
377
0
  WINPR_ASSERT(s);
378
0
  WINPR_ASSERT(operation);
379
380
0
  status = smartcard_unpack_control_call(s, &operation->call.control);
381
382
0
  return status;
383
0
}
384
385
static LONG smartcard_GetAttrib_Decode(wStream* s, SMARTCARD_OPERATION* operation)
386
0
{
387
0
  LONG status = 0;
388
389
0
  WINPR_ASSERT(s);
390
0
  WINPR_ASSERT(operation);
391
392
0
  status = smartcard_unpack_get_attrib_call(s, &operation->call.getAttrib);
393
394
0
  return status;
395
0
}
396
397
static LONG smartcard_SetAttrib_Decode(wStream* s, SMARTCARD_OPERATION* operation)
398
0
{
399
0
  LONG status = 0;
400
401
0
  WINPR_ASSERT(s);
402
0
  WINPR_ASSERT(operation);
403
404
0
  status = smartcard_unpack_set_attrib_call(s, &operation->call.setAttrib);
405
406
0
  return status;
407
0
}
408
409
static LONG smartcard_AccessStartedEvent_Decode(wStream* s, SMARTCARD_OPERATION* operation)
410
0
{
411
0
  WINPR_ASSERT(s);
412
0
  WINPR_ASSERT(operation);
413
414
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
415
0
    return SCARD_F_INTERNAL_ERROR;
416
417
0
  Stream_Read_INT32(s, operation->call.lng.LongValue); /* Unused (4 bytes) */
418
419
0
  return SCARD_S_SUCCESS;
420
0
}
421
422
static LONG smartcard_LocateCardsByATRA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
423
0
{
424
0
  LONG status = 0;
425
426
0
  WINPR_ASSERT(s);
427
0
  WINPR_ASSERT(operation);
428
429
0
  status = smartcard_unpack_locate_cards_by_atr_a_call(s, &operation->call.locateCardsByATRA);
430
431
0
  return status;
432
0
}
433
434
static LONG smartcard_LocateCardsByATRW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
435
0
{
436
0
  LONG status = 0;
437
438
0
  WINPR_ASSERT(s);
439
0
  WINPR_ASSERT(operation);
440
441
0
  status = smartcard_unpack_locate_cards_by_atr_w_call(s, &operation->call.locateCardsByATRW);
442
443
0
  return status;
444
0
}
445
446
static LONG smartcard_ReadCacheA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
447
0
{
448
0
  LONG status = 0;
449
450
0
  WINPR_ASSERT(s);
451
0
  WINPR_ASSERT(operation);
452
453
0
  status = smartcard_unpack_read_cache_a_call(s, &operation->call.readCacheA);
454
455
0
  return status;
456
0
}
457
458
static LONG smartcard_ReadCacheW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
459
0
{
460
0
  LONG status = 0;
461
462
0
  WINPR_ASSERT(s);
463
0
  WINPR_ASSERT(operation);
464
465
0
  status = smartcard_unpack_read_cache_w_call(s, &operation->call.readCacheW);
466
467
0
  return status;
468
0
}
469
470
static LONG smartcard_WriteCacheA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
471
0
{
472
0
  LONG status = 0;
473
474
0
  WINPR_ASSERT(s);
475
0
  WINPR_ASSERT(operation);
476
477
0
  status = smartcard_unpack_write_cache_a_call(s, &operation->call.writeCacheA);
478
479
0
  return status;
480
0
}
481
482
static LONG smartcard_WriteCacheW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
483
0
{
484
0
  LONG status = 0;
485
486
0
  WINPR_ASSERT(s);
487
0
  WINPR_ASSERT(operation);
488
489
0
  status = smartcard_unpack_write_cache_w_call(s, &operation->call.writeCacheW);
490
491
0
  return status;
492
0
}
493
494
static LONG smartcard_GetTransmitCount_Decode(wStream* s, SMARTCARD_OPERATION* operation)
495
0
{
496
0
  LONG status = 0;
497
498
0
  WINPR_ASSERT(s);
499
0
  WINPR_ASSERT(operation);
500
501
0
  status = smartcard_unpack_get_transmit_count_call(s, &operation->call.getTransmitCount);
502
503
0
  return status;
504
0
}
505
506
static LONG smartcard_ReleaseStartedEvent_Decode(wStream* s, SMARTCARD_OPERATION* operation)
507
0
{
508
0
  WINPR_UNUSED(s);
509
0
  WINPR_UNUSED(operation);
510
0
  WLog_WARN(TAG, "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
511
0
                 "SCARD_IOCTL_RELEASETARTEDEVENT is not supported");
512
0
  return SCARD_E_UNSUPPORTED_FEATURE;
513
0
}
514
515
static LONG smartcard_GetReaderIcon_Decode(wStream* s, SMARTCARD_OPERATION* operation)
516
0
{
517
0
  LONG status = 0;
518
519
0
  WINPR_ASSERT(s);
520
0
  WINPR_ASSERT(operation);
521
522
0
  status = smartcard_unpack_get_reader_icon_call(s, &operation->call.getReaderIcon);
523
524
0
  return status;
525
0
}
526
527
static LONG smartcard_GetDeviceTypeId_Decode(wStream* s, SMARTCARD_OPERATION* operation)
528
0
{
529
0
  LONG status = 0;
530
531
0
  WINPR_ASSERT(s);
532
0
  WINPR_ASSERT(operation);
533
534
0
  status = smartcard_unpack_get_device_type_id_call(s, &operation->call.getDeviceTypeId);
535
536
0
  return status;
537
0
}
538
539
LONG smartcard_irp_device_control_decode(wStream* s, UINT32 CompletionId, UINT32 FileId,
540
                                         SMARTCARD_OPERATION* operation)
541
0
{
542
0
  LONG status = 0;
543
0
  UINT32 offset = 0;
544
545
0
  WINPR_ASSERT(s);
546
0
  WINPR_ASSERT(operation);
547
548
  /* Device Control Request */
549
550
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 32))
551
0
    return SCARD_F_INTERNAL_ERROR;
552
553
0
  const UINT32 outputBufferLength = Stream_Get_UINT32(s); /* OutputBufferLength (4 bytes) */
554
0
  const UINT32 inputBufferLength = Stream_Get_UINT32(s);  /* InputBufferLength (4 bytes) */
555
0
  const UINT32 ioControlCode = Stream_Get_UINT32(s);      /* IoControlCode (4 bytes) */
556
0
  Stream_Seek(s, 20);                        /* Padding (20 bytes) */
557
0
  operation->ioControlCode = ioControlCode;
558
0
  operation->ioControlCodeName = scard_get_ioctl_string(ioControlCode, FALSE);
559
0
  operation->outputBufferLength = outputBufferLength;
560
561
0
  if (Stream_Length(s) != (Stream_GetPosition(s) + inputBufferLength))
562
0
  {
563
0
    WLog_WARN(TAG, "InputBufferLength mismatch: Actual: %" PRIuz " Expected: %" PRIuz "",
564
0
              Stream_Length(s), Stream_GetPosition(s) + inputBufferLength);
565
0
    return SCARD_F_INTERNAL_ERROR;
566
0
  }
567
568
0
  WLog_DBG(TAG, "%s (0x%08" PRIX32 ") FileId: %" PRIu32 " CompletionId: %" PRIu32 "",
569
0
           scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, FileId, CompletionId);
570
571
0
  if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
572
0
      (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
573
0
  {
574
0
    status = smartcard_unpack_common_type_header(s);
575
0
    if (status != SCARD_S_SUCCESS)
576
0
      return status;
577
578
0
    status = smartcard_unpack_private_type_header(s);
579
0
    if (status != SCARD_S_SUCCESS)
580
0
      return status;
581
0
  }
582
583
  /* Decode */
584
0
  switch (ioControlCode)
585
0
  {
586
0
    case SCARD_IOCTL_ESTABLISHCONTEXT:
587
0
      status = smartcard_EstablishContext_Decode(s, operation);
588
0
      break;
589
590
0
    case SCARD_IOCTL_RELEASECONTEXT:
591
0
      status = smartcard_ReleaseContext_Decode(s, operation);
592
0
      break;
593
594
0
    case SCARD_IOCTL_ISVALIDCONTEXT:
595
0
      status = smartcard_IsValidContext_Decode(s, operation);
596
0
      break;
597
598
0
    case SCARD_IOCTL_LISTREADERGROUPSA:
599
0
      status = smartcard_ListReaderGroupsA_Decode(s, operation);
600
0
      break;
601
602
0
    case SCARD_IOCTL_LISTREADERGROUPSW:
603
0
      status = smartcard_ListReaderGroupsW_Decode(s, operation);
604
0
      break;
605
606
0
    case SCARD_IOCTL_LISTREADERSA:
607
0
      status = smartcard_ListReadersA_Decode(s, operation);
608
0
      break;
609
610
0
    case SCARD_IOCTL_LISTREADERSW:
611
0
      status = smartcard_ListReadersW_Decode(s, operation);
612
0
      break;
613
614
0
    case SCARD_IOCTL_INTRODUCEREADERGROUPA:
615
0
      status = smartcard_context_and_string_a_Decode(s, operation);
616
0
      break;
617
618
0
    case SCARD_IOCTL_INTRODUCEREADERGROUPW:
619
0
      status = smartcard_context_and_string_w_Decode(s, operation);
620
0
      break;
621
622
0
    case SCARD_IOCTL_FORGETREADERGROUPA:
623
0
      status = smartcard_context_and_string_a_Decode(s, operation);
624
0
      break;
625
626
0
    case SCARD_IOCTL_FORGETREADERGROUPW:
627
0
      status = smartcard_context_and_string_w_Decode(s, operation);
628
0
      break;
629
630
0
    case SCARD_IOCTL_INTRODUCEREADERA:
631
0
      status = smartcard_context_and_two_strings_a_Decode(s, operation);
632
0
      break;
633
634
0
    case SCARD_IOCTL_INTRODUCEREADERW:
635
0
      status = smartcard_context_and_two_strings_w_Decode(s, operation);
636
0
      break;
637
638
0
    case SCARD_IOCTL_FORGETREADERA:
639
0
      status = smartcard_context_and_string_a_Decode(s, operation);
640
0
      break;
641
642
0
    case SCARD_IOCTL_FORGETREADERW:
643
0
      status = smartcard_context_and_string_w_Decode(s, operation);
644
0
      break;
645
646
0
    case SCARD_IOCTL_ADDREADERTOGROUPA:
647
0
      status = smartcard_context_and_two_strings_a_Decode(s, operation);
648
0
      break;
649
650
0
    case SCARD_IOCTL_ADDREADERTOGROUPW:
651
0
      status = smartcard_context_and_two_strings_w_Decode(s, operation);
652
0
      break;
653
654
0
    case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
655
0
      status = smartcard_context_and_two_strings_a_Decode(s, operation);
656
0
      break;
657
658
0
    case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
659
0
      status = smartcard_context_and_two_strings_w_Decode(s, operation);
660
0
      break;
661
662
0
    case SCARD_IOCTL_LOCATECARDSA:
663
0
      status = smartcard_LocateCardsA_Decode(s, operation);
664
0
      break;
665
666
0
    case SCARD_IOCTL_LOCATECARDSW:
667
0
      status = smartcard_LocateCardsW_Decode(s, operation);
668
0
      break;
669
670
0
    case SCARD_IOCTL_GETSTATUSCHANGEA:
671
0
      status = smartcard_GetStatusChangeA_Decode(s, operation);
672
0
      break;
673
674
0
    case SCARD_IOCTL_GETSTATUSCHANGEW:
675
0
      status = smartcard_GetStatusChangeW_Decode(s, operation);
676
0
      break;
677
678
0
    case SCARD_IOCTL_CANCEL:
679
0
      status = smartcard_Cancel_Decode(s, operation);
680
0
      break;
681
682
0
    case SCARD_IOCTL_CONNECTA:
683
0
      status = smartcard_ConnectA_Decode(s, operation);
684
0
      break;
685
686
0
    case SCARD_IOCTL_CONNECTW:
687
0
      status = smartcard_ConnectW_Decode(s, operation);
688
0
      break;
689
690
0
    case SCARD_IOCTL_RECONNECT:
691
0
      status = smartcard_Reconnect_Decode(s, operation);
692
0
      break;
693
694
0
    case SCARD_IOCTL_DISCONNECT:
695
0
      status = smartcard_Disconnect_Decode(s, operation);
696
0
      break;
697
698
0
    case SCARD_IOCTL_BEGINTRANSACTION:
699
0
      status = smartcard_BeginTransaction_Decode(s, operation);
700
0
      break;
701
702
0
    case SCARD_IOCTL_ENDTRANSACTION:
703
0
      status = smartcard_EndTransaction_Decode(s, operation);
704
0
      break;
705
706
0
    case SCARD_IOCTL_STATE:
707
0
      status = smartcard_State_Decode(s, operation);
708
0
      break;
709
710
0
    case SCARD_IOCTL_STATUSA:
711
0
      status = smartcard_StatusA_Decode(s, operation);
712
0
      break;
713
714
0
    case SCARD_IOCTL_STATUSW:
715
0
      status = smartcard_StatusW_Decode(s, operation);
716
0
      break;
717
718
0
    case SCARD_IOCTL_TRANSMIT:
719
0
      status = smartcard_Transmit_Decode(s, operation);
720
0
      break;
721
722
0
    case SCARD_IOCTL_CONTROL:
723
0
      status = smartcard_Control_Decode(s, operation);
724
0
      break;
725
726
0
    case SCARD_IOCTL_GETATTRIB:
727
0
      status = smartcard_GetAttrib_Decode(s, operation);
728
0
      break;
729
730
0
    case SCARD_IOCTL_SETATTRIB:
731
0
      status = smartcard_SetAttrib_Decode(s, operation);
732
0
      break;
733
734
0
    case SCARD_IOCTL_ACCESSSTARTEDEVENT:
735
0
      status = smartcard_AccessStartedEvent_Decode(s, operation);
736
0
      break;
737
738
0
    case SCARD_IOCTL_LOCATECARDSBYATRA:
739
0
      status = smartcard_LocateCardsByATRA_Decode(s, operation);
740
0
      break;
741
742
0
    case SCARD_IOCTL_LOCATECARDSBYATRW:
743
0
      status = smartcard_LocateCardsByATRW_Decode(s, operation);
744
0
      break;
745
746
0
    case SCARD_IOCTL_READCACHEA:
747
0
      status = smartcard_ReadCacheA_Decode(s, operation);
748
0
      break;
749
750
0
    case SCARD_IOCTL_READCACHEW:
751
0
      status = smartcard_ReadCacheW_Decode(s, operation);
752
0
      break;
753
754
0
    case SCARD_IOCTL_WRITECACHEA:
755
0
      status = smartcard_WriteCacheA_Decode(s, operation);
756
0
      break;
757
758
0
    case SCARD_IOCTL_WRITECACHEW:
759
0
      status = smartcard_WriteCacheW_Decode(s, operation);
760
0
      break;
761
762
0
    case SCARD_IOCTL_GETTRANSMITCOUNT:
763
0
      status = smartcard_GetTransmitCount_Decode(s, operation);
764
0
      break;
765
766
0
    case SCARD_IOCTL_RELEASETARTEDEVENT:
767
0
      status = smartcard_ReleaseStartedEvent_Decode(s, operation);
768
0
      break;
769
770
0
    case SCARD_IOCTL_GETREADERICON:
771
0
      status = smartcard_GetReaderIcon_Decode(s, operation);
772
0
      break;
773
774
0
    case SCARD_IOCTL_GETDEVICETYPEID:
775
0
      status = smartcard_GetDeviceTypeId_Decode(s, operation);
776
0
      break;
777
778
0
    default:
779
0
      status = SCARD_F_INTERNAL_ERROR;
780
0
      break;
781
0
  }
782
783
0
  smartcard_call_to_operation_handle(operation);
784
785
0
  if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
786
0
      (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
787
0
  {
788
0
    offset = (RDPDR_DEVICE_IO_REQUEST_LENGTH + RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH);
789
0
    smartcard_unpack_read_size_align(s, Stream_GetPosition(s) - offset, 8);
790
0
  }
791
792
0
  if (Stream_GetPosition(s) < Stream_Length(s))
793
0
  {
794
0
    size_t difference = 0;
795
0
    difference = Stream_Length(s) - Stream_GetPosition(s);
796
0
    WLog_WARN(TAG,
797
0
              "IRP was not fully parsed %s (%s [0x%08" PRIX32 "]): Actual: %" PRIuz
798
0
              ", Expected: %" PRIuz ", Difference: %" PRIuz "",
799
0
              scard_get_ioctl_string(ioControlCode, TRUE),
800
0
              scard_get_ioctl_string(ioControlCode, FALSE), ioControlCode,
801
0
              Stream_GetPosition(s), Stream_Length(s), difference);
802
0
    winpr_HexDump(TAG, WLOG_WARN, Stream_ConstPointer(s), difference);
803
0
  }
804
805
0
  if (Stream_GetPosition(s) > Stream_Length(s))
806
0
  {
807
0
    size_t difference = 0;
808
0
    difference = Stream_GetPosition(s) - Stream_Length(s);
809
0
    WLog_WARN(TAG,
810
0
              "IRP was parsed beyond its end %s (0x%08" PRIX32 "): Actual: %" PRIuz
811
0
              ", Expected: %" PRIuz ", Difference: %" PRIuz "",
812
0
              scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, Stream_GetPosition(s),
813
0
              Stream_Length(s), difference);
814
0
  }
815
816
0
  return status;
817
0
}
818
819
static void free_reader_states_a(LPSCARD_READERSTATEA rgReaderStates, UINT32 cReaders)
820
0
{
821
0
  for (UINT32 x = 0; x < cReaders; x++)
822
0
  {
823
0
    SCARD_READERSTATEA* state = &rgReaderStates[x];
824
0
    free(state->szReader);
825
0
  }
826
827
0
  free(rgReaderStates);
828
0
}
829
830
static void free_reader_states_w(LPSCARD_READERSTATEW rgReaderStates, UINT32 cReaders)
831
0
{
832
0
  for (UINT32 x = 0; x < cReaders; x++)
833
0
  {
834
0
    SCARD_READERSTATEW* state = &rgReaderStates[x];
835
0
    free(state->szReader);
836
0
  }
837
838
0
  free(rgReaderStates);
839
0
}
840
841
void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
842
0
{
843
0
  if (!op)
844
0
    return;
845
0
  switch (op->ioControlCode)
846
0
  {
847
0
    case SCARD_IOCTL_CANCEL:
848
0
    case SCARD_IOCTL_ACCESSSTARTEDEVENT:
849
0
    case SCARD_IOCTL_RELEASETARTEDEVENT:
850
0
    case SCARD_IOCTL_LISTREADERGROUPSA:
851
0
    case SCARD_IOCTL_LISTREADERGROUPSW:
852
0
    case SCARD_IOCTL_RECONNECT:
853
0
    case SCARD_IOCTL_DISCONNECT:
854
0
    case SCARD_IOCTL_BEGINTRANSACTION:
855
0
    case SCARD_IOCTL_ENDTRANSACTION:
856
0
    case SCARD_IOCTL_STATE:
857
0
    case SCARD_IOCTL_STATUSA:
858
0
    case SCARD_IOCTL_STATUSW:
859
0
    case SCARD_IOCTL_ESTABLISHCONTEXT:
860
0
    case SCARD_IOCTL_RELEASECONTEXT:
861
0
    case SCARD_IOCTL_ISVALIDCONTEXT:
862
0
    case SCARD_IOCTL_GETATTRIB:
863
0
    case SCARD_IOCTL_GETTRANSMITCOUNT:
864
0
      break;
865
866
0
    case SCARD_IOCTL_LOCATECARDSA:
867
0
    {
868
0
      LocateCardsA_Call* call = &op->call.locateCardsA;
869
0
      free(call->mszCards);
870
871
0
      free_reader_states_a(call->rgReaderStates, call->cReaders);
872
0
    }
873
0
    break;
874
0
    case SCARD_IOCTL_LOCATECARDSW:
875
0
    {
876
0
      LocateCardsW_Call* call = &op->call.locateCardsW;
877
0
      free(call->mszCards);
878
879
0
      free_reader_states_w(call->rgReaderStates, call->cReaders);
880
0
    }
881
0
    break;
882
883
0
    case SCARD_IOCTL_LOCATECARDSBYATRA:
884
0
    {
885
0
      LocateCardsByATRA_Call* call = &op->call.locateCardsByATRA;
886
887
0
      free_reader_states_a(call->rgReaderStates, call->cReaders);
888
0
    }
889
0
    break;
890
0
    case SCARD_IOCTL_LOCATECARDSBYATRW:
891
0
    {
892
0
      LocateCardsByATRW_Call* call = &op->call.locateCardsByATRW;
893
0
      free_reader_states_w(call->rgReaderStates, call->cReaders);
894
0
    }
895
0
    break;
896
0
    case SCARD_IOCTL_FORGETREADERA:
897
0
    case SCARD_IOCTL_INTRODUCEREADERGROUPA:
898
0
    case SCARD_IOCTL_FORGETREADERGROUPA:
899
0
    {
900
0
      ContextAndStringA_Call* call = &op->call.contextAndStringA;
901
0
      free(call->sz);
902
0
    }
903
0
    break;
904
905
0
    case SCARD_IOCTL_FORGETREADERW:
906
0
    case SCARD_IOCTL_INTRODUCEREADERGROUPW:
907
0
    case SCARD_IOCTL_FORGETREADERGROUPW:
908
0
    {
909
0
      ContextAndStringW_Call* call = &op->call.contextAndStringW;
910
0
      free(call->sz);
911
0
    }
912
0
    break;
913
914
0
    case SCARD_IOCTL_INTRODUCEREADERA:
915
0
    case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
916
0
    case SCARD_IOCTL_ADDREADERTOGROUPA:
917
918
0
    {
919
0
      ContextAndTwoStringA_Call* call = &op->call.contextAndTwoStringA;
920
0
      free(call->sz1);
921
0
      free(call->sz2);
922
0
    }
923
0
    break;
924
925
0
    case SCARD_IOCTL_INTRODUCEREADERW:
926
0
    case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
927
0
    case SCARD_IOCTL_ADDREADERTOGROUPW:
928
929
0
    {
930
0
      ContextAndTwoStringW_Call* call = &op->call.contextAndTwoStringW;
931
0
      free(call->sz1);
932
0
      free(call->sz2);
933
0
    }
934
0
    break;
935
936
0
    case SCARD_IOCTL_LISTREADERSA:
937
0
    case SCARD_IOCTL_LISTREADERSW:
938
0
    {
939
0
      ListReaders_Call* call = &op->call.listReaders;
940
0
      free(call->mszGroups);
941
0
    }
942
0
    break;
943
0
    case SCARD_IOCTL_GETSTATUSCHANGEA:
944
0
    {
945
0
      GetStatusChangeA_Call* call = &op->call.getStatusChangeA;
946
0
      free_reader_states_a(call->rgReaderStates, call->cReaders);
947
0
    }
948
0
    break;
949
950
0
    case SCARD_IOCTL_GETSTATUSCHANGEW:
951
0
    {
952
0
      GetStatusChangeW_Call* call = &op->call.getStatusChangeW;
953
0
      free_reader_states_w(call->rgReaderStates, call->cReaders);
954
0
    }
955
0
    break;
956
0
    case SCARD_IOCTL_GETREADERICON:
957
0
    {
958
0
      GetReaderIcon_Call* call = &op->call.getReaderIcon;
959
0
      free(call->szReaderName);
960
0
    }
961
0
    break;
962
0
    case SCARD_IOCTL_GETDEVICETYPEID:
963
0
    {
964
0
      GetDeviceTypeId_Call* call = &op->call.getDeviceTypeId;
965
0
      free(call->szReaderName);
966
0
    }
967
0
    break;
968
0
    case SCARD_IOCTL_CONNECTA:
969
0
    {
970
0
      ConnectA_Call* call = &op->call.connectA;
971
0
      free(call->szReader);
972
0
    }
973
0
    break;
974
0
    case SCARD_IOCTL_CONNECTW:
975
0
    {
976
0
      ConnectW_Call* call = &op->call.connectW;
977
0
      free(call->szReader);
978
0
    }
979
0
    break;
980
0
    case SCARD_IOCTL_SETATTRIB:
981
0
      free(op->call.setAttrib.pbAttr);
982
0
      break;
983
0
    case SCARD_IOCTL_TRANSMIT:
984
0
    {
985
0
      Transmit_Call* call = &op->call.transmit;
986
0
      free(call->pbSendBuffer);
987
0
      free(call->pioSendPci);
988
0
      free(call->pioRecvPci);
989
0
    }
990
0
    break;
991
0
    case SCARD_IOCTL_CONTROL:
992
0
    {
993
0
      Control_Call* call = &op->call.control;
994
0
      free(call->pvInBuffer);
995
0
    }
996
0
    break;
997
0
    case SCARD_IOCTL_READCACHEA:
998
0
    {
999
0
      ReadCacheA_Call* call = &op->call.readCacheA;
1000
0
      free(call->szLookupName);
1001
0
      free(call->Common.CardIdentifier);
1002
0
    }
1003
0
    break;
1004
0
    case SCARD_IOCTL_READCACHEW:
1005
0
    {
1006
0
      ReadCacheW_Call* call = &op->call.readCacheW;
1007
0
      free(call->szLookupName);
1008
0
      free(call->Common.CardIdentifier);
1009
0
    }
1010
0
    break;
1011
0
    case SCARD_IOCTL_WRITECACHEA:
1012
0
    {
1013
0
      WriteCacheA_Call* call = &op->call.writeCacheA;
1014
0
      free(call->szLookupName);
1015
0
      free(call->Common.CardIdentifier);
1016
0
      free(call->Common.pbData);
1017
0
    }
1018
0
    break;
1019
0
    case SCARD_IOCTL_WRITECACHEW:
1020
0
    {
1021
0
      WriteCacheW_Call* call = &op->call.writeCacheW;
1022
0
      free(call->szLookupName);
1023
0
      free(call->Common.CardIdentifier);
1024
0
      free(call->Common.pbData);
1025
0
    }
1026
0
    break;
1027
0
    default:
1028
0
      break;
1029
0
  }
1030
1031
0
  {
1032
0
    SMARTCARD_OPERATION empty = { 0 };
1033
0
    *op = empty;
1034
0
  }
1035
1036
0
  if (allocated)
1037
0
    free(op);
1038
0
}