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