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