2 FreeRDP: A Remote Desktop Protocol client.
3 Redirected Smart Card Device Service
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>
9 Licensed under the Apache License, Version 2.0 (the "License");
10 you may not use this file except in compliance with the License.
11 You may obtain a copy of the License at
13 http://www.apache.org/licenses/LICENSE-2.0
15 Unless required by applicable law or agreed to in writing, software
16 distributed under the License is distributed on an "AS IS" BASIS,
17 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 See the License for the specific language governing permissions and
19 limitations under the License.
29 #include <semaphore.h>
32 #include <PCSC/pcsclite.h>
33 #include <PCSC/reader.h>
34 #include <PCSC/winscard.h>
36 #include <freerdp/freerdp.h>
37 #include <freerdp/utils/hexdump.h>
38 #include <freerdp/utils/memory.h>
39 #include <freerdp/utils/stream.h>
40 #include <freerdp/utils/svc_plugin.h>
41 #include <freerdp/utils/semaphore.h>
42 #include <freerdp/utils/thread.h>
44 #include "rdpdr_types.h"
45 #include "rdpdr_constants.h"
47 #include "scard_main.h"
49 /* [MS-RDPESC] 3.1.4 */
50 #define SCARD_IOCTL_ESTABLISH_CONTEXT 0x00090014 /* EstablishContext */
51 #define SCARD_IOCTL_RELEASE_CONTEXT 0x00090018 /* ReleaseContext */
52 #define SCARD_IOCTL_IS_VALID_CONTEXT 0x0009001C /* IsValidContext */
53 #define SCARD_IOCTL_LIST_READER_GROUPS 0x00090020 /* ListReaderGroups */
54 #define SCARD_IOCTL_LIST_READERS 0x00090028 /* ListReadersA */
55 #define SCARD_IOCTL_INTRODUCE_READER_GROUP 0x00090050 /* IntroduceReaderGroup */
56 #define SCARD_IOCTL_FORGET_READER_GROUP 0x00090058 /* ForgetReader */
57 #define SCARD_IOCTL_INTRODUCE_READER 0x00090060 /* IntroduceReader */
58 #define SCARD_IOCTL_FORGET_READER 0x00090068 /* IntroduceReader */
59 #define SCARD_IOCTL_ADD_READER_TO_GROUP 0x00090070 /* AddReaderToGroup */
60 #define SCARD_IOCTL_REMOVE_READER_FROM_GROUP 0x00090078 /* RemoveReaderFromGroup */
61 #define SCARD_IOCTL_GET_STATUS_CHANGE 0x000900A0 /* GetStatusChangeA */
62 #define SCARD_IOCTL_CANCEL 0x000900A8 /* Cancel */
63 #define SCARD_IOCTL_CONNECT 0x000900AC /* ConnectA */
64 #define SCARD_IOCTL_RECONNECT 0x000900B4 /* Reconnect */
65 #define SCARD_IOCTL_DISCONNECT 0x000900B8 /* Disconnect */
66 #define SCARD_IOCTL_BEGIN_TRANSACTION 0x000900BC /* BeginTransaction */
67 #define SCARD_IOCTL_END_TRANSACTION 0x000900C0 /* EndTransaction */
68 #define SCARD_IOCTL_STATE 0x000900C4 /* State */
69 #define SCARD_IOCTL_STATUS 0x000900C8 /* StatusA */
70 #define SCARD_IOCTL_TRANSMIT 0x000900D0 /* Transmit */
71 #define SCARD_IOCTL_CONTROL 0x000900D4 /* Control */
72 #define SCARD_IOCTL_GETATTRIB 0x000900D8 /* GetAttrib */
73 #define SCARD_IOCTL_SETATTRIB 0x000900DC /* SetAttrib */
74 #define SCARD_IOCTL_ACCESS_STARTED_EVENT 0x000900E0 /* SCardAccessStartedEvent */
75 #define SCARD_IOCTL_LOCATE_CARDS_BY_ATR 0x000900E8 /* LocateCardsByATR */
77 #define SCARD_INPUT_LINKED 0xFFFFFFFF
79 /* Decode Win CTL_CODE values */
80 #define WIN_CTL_FUNCTION(ctl_code) ((ctl_code & 0x3FFC) >> 2)
81 #define WIN_CTL_DEVICE_TYPE(ctl_code) (ctl_code >> 16)
83 #define WIN_FILE_DEVICE_SMARTCARD 0x00000031
86 static uint32 sc_output_string(IRP* irp, char *src, boolean wide)
91 p = stream_get_tail(irp->output);
92 len = strlen(src) + 1;
98 for (i = 0; i < len; i++ )
100 p[2 * i] = src[i] < 0 ? '?' : src[i];
111 stream_seek(irp->output, len);
115 static void sc_output_alignment(IRP *irp, uint32 seed)
117 uint32 size = stream_get_length(irp->output) - 20;
118 uint32 add = (seed - (size % seed)) % seed;
121 stream_write_zero(irp->output, add);
124 static void sc_output_repos(IRP* irp, uint32 written)
126 uint32 add = (4 - (written % 4)) % 4;
129 stream_write_zero(irp->output, add);
132 static uint32 sc_output_return(IRP* irp, uint32 rv)
134 stream_write_zero(irp->output, 256);
138 static void sc_output_buffer_limit(IRP* irp, char *buffer, unsigned int length, unsigned int highLimit)
140 int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
142 stream_write_uint32(irp->output, header);
146 stream_write_uint32(irp->output, 0);
153 stream_write(irp->output, buffer, length);
154 sc_output_repos(irp, length);
158 static void sc_output_buffer(IRP* irp, char *buffer, unsigned int length)
160 sc_output_buffer_limit(irp, buffer, length, 0x7FFFFFFF);
163 static void sc_output_buffer_start_limit(IRP *irp, int length, int highLimit)
165 int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
167 stream_write_uint32(irp->output, header);
168 stream_write_uint32(irp->output, 0x00000001); /* Magic DWORD - any non zero */
171 static void sc_output_buffer_start(IRP *irp, int length)
173 sc_output_buffer_start_limit(irp, length, 0x7FFFFFFF);
176 static uint32 sc_input_string(IRP* irp, char **dest, uint32 dataLength, boolean wide)
181 bufferSize = wide ? (2 * dataLength) : dataLength;
182 buffer = xmalloc(bufferSize + 2); /* reserve 2 bytes for the '\0' */
184 stream_read(irp->input, buffer, bufferSize);
188 for (i = 0; i < dataLength; i++)
190 if ((buffer[2 * i] < 0) || (buffer[2 * i + 1] != 0))
193 buffer[i] = buffer[2 * i];
197 buffer[dataLength] = '\0';
203 static void sc_input_repos(IRP* irp, uint32 read)
205 uint32 add = 4 - (read % 4);
207 if (add < 4 && add > 0)
208 stream_seek(irp->input, add);
211 static void sc_input_reader_name(IRP* irp, char **dest, boolean wide)
215 stream_seek(irp->input, 8);
216 stream_read_uint32(irp->input, dataLength);
218 DEBUG_SCARD("datalength %d", dataLength);
219 sc_input_repos(irp, sc_input_string(irp, dest, dataLength, wide));
222 static void sc_input_skip_linked(IRP* irp)
225 stream_read_uint32(irp->input, len);
229 stream_seek(irp->input, len);
230 sc_input_repos(irp, len);
234 static uint32 sc_map_state(uint32 state)
236 /* is this mapping still needed? */
238 if (state & SCARD_SPECIFIC)
240 else if (state & SCARD_NEGOTIABLE)
242 else if (state & SCARD_POWERED)
244 else if (state & SCARD_SWALLOWED)
246 else if (state & SCARD_PRESENT)
248 else if (state & SCARD_ABSENT)
256 static uint32 handle_EstablishContext(IRP* irp)
260 SCARDCONTEXT hContext = -1;
262 stream_seek(irp->input, 8);
263 stream_read_uint32(irp->input, len);
266 return SCARD_F_INTERNAL_ERROR;
268 stream_seek_uint32(irp->input);
269 stream_read_uint32(irp->input, scope);
271 rv = SCardEstablishContext(scope, NULL, NULL, &hContext);
273 stream_write_uint32(irp->output, 4); // ?
274 stream_write_uint32(irp->output, -1); // ?
276 stream_write_uint32(irp->output, 4);
277 stream_write_uint32(irp->output, hContext);
279 /* TODO: store hContext in allowed context list */
281 return SCARD_S_SUCCESS;
284 static uint32 handle_ReleaseContext(IRP* irp)
287 SCARDCONTEXT hContext = -1;
289 stream_seek(irp->input, 8);
290 stream_read_uint32(irp->input, len);
292 stream_seek(irp->input, 0x10);
293 stream_read_uint32(irp->input, hContext);
295 rv = SCardReleaseContext(hContext);
297 DEBUG_SCARD("%s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
299 DEBUG_SCARD("success 0x%08lx", hContext);
304 static uint32 handle_IsValidContext(IRP* irp)
307 SCARDCONTEXT hContext;
309 stream_seek(irp->input, 0x1C);
310 stream_read_uint32(irp->input, hContext);
312 rv = SCardIsValidContext(hContext);
315 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
317 DEBUG_SCARD("Success context: 0x%08x", (unsigned) hContext);
319 stream_write_uint32(irp->output, rv);
324 static uint32 handle_ListReaders(IRP* irp, boolean wide)
327 SCARDCONTEXT hContext;
329 char *readerList = NULL, *walker;
330 int elemLength, dataLength;
331 int pos, poslen1, poslen2;
333 stream_seek(irp->input, 8);
334 stream_read_uint32(irp->input, len);
336 stream_seek(irp->input, 0x1c);
337 stream_read_uint32(irp->input, len);
340 return SCARD_F_INTERNAL_ERROR;
342 stream_read_uint32(irp->input, hContext);
344 /* ignore rest of [MS-RDPESC] 2.2.2.4 ListReaders_Call */
346 rv = SCARD_S_SUCCESS;
347 #ifdef SCARD_AUTOALLOCATE
348 dwReaders = SCARD_AUTOALLOCATE;
349 rv = SCardListReaders(hContext, NULL, (LPSTR) &readerList, &dwReaders);
351 rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
353 readerList = xmalloc(dwReaders);
354 rv = SCardListReaders(hContext, NULL, readerList, &dwReaders);
356 if (rv != SCARD_S_SUCCESS)
358 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
362 /* DEBUG_SCARD("Success 0x%08x %d %d", (unsigned) hContext, (unsigned) cchReaders, (int) strlen(readerList));*/
364 poslen1 = stream_get_pos(irp->output);
365 stream_seek_uint32(irp->output);
367 stream_write_uint32(irp->output, 0x01760650);
369 poslen2 = stream_get_pos(irp->output);
370 stream_seek_uint32(irp->output);
377 elemLength = strlen(walker);
381 dataLength += sc_output_string(irp, walker, wide);
382 walker += elemLength + 1;
383 elemLength = strlen(walker);
386 dataLength += sc_output_string(irp, "\0", wide);
388 pos = stream_get_pos(irp->output);
390 stream_set_pos(irp->output, poslen1);
391 stream_write_uint32(irp->output, dataLength);
392 stream_set_pos(irp->output, poslen2);
393 stream_write_uint32(irp->output, dataLength);
395 stream_set_pos(irp->output, pos);
397 sc_output_repos(irp, dataLength);
398 sc_output_alignment(irp, 8);
400 #ifdef SCARD_AUTOALLOCATE
401 SCardFreeMemory(hContext, readerList);
409 static uint32 handle_GetStatusChange(IRP* irp, boolean wide)
412 SCARDCONTEXT hContext;
414 DWORD readerCount = 0;
415 SCARD_READERSTATE *readerStates, *cur;
418 stream_seek(irp->input, 0x18);
419 stream_read_uint32(irp->input, dwTimeout);
420 stream_read_uint32(irp->input, readerCount);
422 stream_seek(irp->input, 8);
424 stream_read_uint32(irp->input, hContext);
426 stream_seek(irp->input, 4);
428 DEBUG_SCARD("context: 0x%08x, timeout: 0x%08x, count: %d",
429 (unsigned) hContext, (unsigned) dwTimeout, (int) readerCount);
432 readerStates = xzalloc(readerCount * sizeof(SCARD_READERSTATE));
434 return sc_output_return(irp, SCARD_E_NO_MEMORY);
437 for (i = 0; i < readerCount; i++)
439 cur = &readerStates[i];
441 stream_seek(irp->input, 4);
444 * TODO: on-wire is little endian; need to either
445 * convert to host endian or fix the headers to
446 * request the order we want
448 stream_read_uint32(irp->input, cur->dwCurrentState);
449 stream_read_uint32(irp->input, cur->dwEventState);
450 stream_read_uint32(irp->input, cur->cbAtr);
451 stream_read(irp->input, cur->rgbAtr, 32);
453 stream_seek(irp->input, 4);
455 /* reset high bytes? */
456 cur->dwCurrentState &= 0x0000FFFF;
457 cur->dwEventState &= 0x0000FFFF;
458 cur->dwEventState = 0;
461 for (i = 0; i < readerCount; i++)
463 cur = &readerStates[i];
466 stream_seek(irp->input, 8);
467 stream_read_uint32(irp->input, dataLength);
468 sc_input_repos(irp, sc_input_string(irp, (char **) &cur->szReader, dataLength, wide));
470 DEBUG_SCARD(" \"%s\"", cur->szReader ? cur->szReader : "NULL");
471 DEBUG_SCARD(" user: 0x%08x, state: 0x%08x, event: 0x%08x",
472 (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
473 (unsigned) cur->dwEventState);
475 if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0)
476 cur->dwCurrentState |= SCARD_STATE_IGNORE;
484 rv = SCardGetStatusChange(hContext, (DWORD) dwTimeout, readerStates, (DWORD) readerCount);
486 if (rv != SCARD_S_SUCCESS)
487 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
489 DEBUG_SCARD("Success");
491 stream_write_uint32(irp->output, readerCount);
492 stream_write_uint32(irp->output, 0x00084dd8);
493 stream_write_uint32(irp->output, readerCount);
495 for (i = 0; i < readerCount; i++)
497 cur = &readerStates[i];
499 DEBUG_SCARD(" \"%s\"", cur->szReader ? cur->szReader : "NULL");
500 DEBUG_SCARD(" user: 0x%08x, state: 0x%08x, event: 0x%08x\n",
501 (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
502 (unsigned) cur->dwEventState);
504 /* TODO: do byte conversions if necessary */
505 stream_write_uint32(irp->output, cur->dwCurrentState);
506 stream_write_uint32(irp->output, cur->dwEventState);
507 stream_write_uint32(irp->output, cur->cbAtr);
508 stream_write(irp->output, cur->rgbAtr, 32);
510 stream_write_zero(irp->output, 4);
512 xfree((void *)cur->szReader);
515 sc_output_alignment(irp, 8);
521 static uint32 handle_Cancel(IRP *irp)
524 SCARDCONTEXT hContext;
526 stream_seek(irp->input, 0x1C);
527 stream_read_uint32(irp->input, hContext);
529 rv = SCardCancel(hContext);
531 if (rv != SCARD_S_SUCCESS)
532 DEBUG_SCARD("Failure: %s (0x%08x)\n", pcsc_stringify_error(rv), (unsigned) rv);
534 DEBUG_SCARD("Success context: 0x%08x %s\n", (unsigned) hContext, pcsc_stringify_error(rv));
536 sc_output_alignment(irp, 8);
541 static uint32 handle_Connect(IRP* irp, boolean wide)
544 SCARDCONTEXT hContext;
545 char *readerName = NULL;
546 DWORD dwShareMode = 0;
547 DWORD dwPreferredProtocol = 0;
548 DWORD dwActiveProtocol = 0;
551 stream_seek(irp->input, 0x1c);
552 stream_read_uint32(irp->input, dwShareMode);
553 stream_read_uint32(irp->input, dwPreferredProtocol);
555 sc_input_reader_name(irp, &readerName, wide);
557 stream_seek(irp->input, 4);
558 stream_read_uint32(irp->input, hContext);
560 DEBUG_SCARD("(context: 0x%08x, share: 0x%08x, proto: 0x%08x, reader: \"%s\")",
561 (unsigned) hContext, (unsigned) dwShareMode,
562 (unsigned) dwPreferredProtocol, readerName ? readerName : "NULL");
564 rv = SCardConnect(hContext, readerName, (DWORD) dwShareMode,
565 (DWORD) dwPreferredProtocol, &hCard, (DWORD *) &dwActiveProtocol);
567 if (rv != SCARD_S_SUCCESS)
568 DEBUG_SCARD("Failure: %s 0x%08x", pcsc_stringify_error(rv), (unsigned) rv);
570 DEBUG_SCARD("Success 0x%08x", (unsigned) hCard);
572 stream_write_uint32(irp->output, 0x00000000);
573 stream_write_uint32(irp->output, 0x00000000);
574 stream_write_uint32(irp->output, 0x00000004);
575 stream_write_uint32(irp->output, 0x016Cff34);
576 stream_write_uint32(irp->output, dwActiveProtocol);
577 stream_write_uint32(irp->output, 0x00000004);
578 stream_write_uint32(irp->output, hCard);
579 stream_seek(irp->output, 28);
581 sc_output_alignment(irp, 8);
587 static uint32 handle_Reconnect(IRP* irp)
590 SCARDCONTEXT hContext;
592 DWORD dwShareMode = 0;
593 DWORD dwPreferredProtocol = 0;
594 DWORD dwInitialization = 0;
595 DWORD dwActiveProtocol = 0;
597 stream_seek(irp->input, 0x20);
598 stream_read_uint32(irp->input, dwShareMode);
599 stream_read_uint32(irp->input, dwPreferredProtocol);
600 stream_read_uint32(irp->input, dwInitialization);
602 stream_seek(irp->input, 0x4);
603 stream_read_uint32(irp->input, hContext);
604 stream_seek(irp->input, 0x4);
605 stream_read_uint32(irp->input, hCard);
607 DEBUG_SCARD("(context: 0x%08x, hcard: 0x%08x, share: 0x%08x, proto: 0x%08x, init: 0x%08x)",
608 (unsigned) hContext, (unsigned) hCard,
609 (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, (unsigned) dwInitialization);
611 rv = SCardReconnect(hCard, (DWORD) dwShareMode, (DWORD) dwPreferredProtocol,
612 (DWORD) dwInitialization, (LPDWORD) &dwActiveProtocol);
614 if (rv != SCARD_S_SUCCESS)
615 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
617 DEBUG_SCARD("Success (proto: 0x%08x)", (unsigned) dwActiveProtocol);
619 sc_output_alignment(irp, 8);
620 stream_write_uint32(irp->output, dwActiveProtocol); /* reversed? */
625 static uint32 handle_Disconnect(IRP* irp)
628 SCARDCONTEXT hContext;
630 DWORD dwDisposition = 0;
632 stream_seek(irp->input, 0x20);
633 stream_read_uint32(irp->input, dwDisposition);
634 stream_seek(irp->input, 4);
635 stream_read_uint32(irp->input, hContext);
636 stream_seek(irp->input, 4);
637 stream_read_uint32(irp->input, hCard);
639 DEBUG_SCARD("(context: 0x%08x, hcard: 0x%08x, disposition: 0x%08x)",
640 (unsigned) hContext, (unsigned) hCard, (unsigned) dwDisposition);
642 rv = SCardDisconnect(hCard, (DWORD) dwDisposition);
644 if (rv != SCARD_S_SUCCESS)
645 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
647 DEBUG_SCARD("Success");
649 sc_output_alignment(irp, 8);
654 static uint32 handle_BeginTransaction(IRP* irp)
659 stream_seek(irp->input, 0x30);
660 stream_read_uint32(irp->input, hCard);
662 rv = SCardBeginTransaction(hCard);
664 if (rv != SCARD_S_SUCCESS)
665 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
667 DEBUG_SCARD("Success hcard: 0x%08x", (unsigned) hCard);
669 sc_output_alignment(irp, 8);
674 static uint32 handle_EndTransaction(IRP* irp)
678 DWORD dwDisposition = 0;
680 stream_seek(irp->input, 0x20);
681 stream_read_uint32(irp->input, dwDisposition);
683 stream_seek(irp->input, 0x0C);
684 stream_read_uint32(irp->input, hCard);
686 rv = SCardEndTransaction(hCard, dwDisposition);
688 if (rv != SCARD_S_SUCCESS)
689 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
691 DEBUG_SCARD("Success hcard: 0x%08x", (unsigned) hCard);
693 sc_output_alignment(irp, 8);
698 static uint32 handle_State(IRP* irp)
702 DWORD state = 0, protocol = 0;
704 DWORD atrLen = MAX_ATR_SIZE;
706 BYTE pbAtr[MAX_ATR_SIZE];
708 #ifdef WITH_DEBUG_SCARD
712 stream_seek(irp->input, 0x24);
713 stream_seek_uint32(irp->input); /* atrLen */
715 stream_seek(irp->input, 0x0c);
716 stream_read_uint32(irp->input, hCard);
717 stream_seek(irp->input, 0x04);
719 #ifdef SCARD_AUTOALLOCATE
720 readerLen = SCARD_AUTOALLOCATE;
722 rv = SCardStatus(hCard, (LPSTR) &readerName, &readerLen, &state, &protocol, pbAtr, &atrLen);
725 readerName = xmalloc(readerLen);
727 rv = SCardStatus(hCard, (LPSTR) readerName, &readerLen, &state, &protocol, pbAtr, &atrLen);
730 if (rv != SCARD_S_SUCCESS)
732 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
733 return sc_output_return(irp, rv);
736 DEBUG_SCARD("Success (hcard: 0x%08x len: %d state: 0x%08x, proto: 0x%08x)",
737 (unsigned) hCard, (int) atrLen, (unsigned) state, (unsigned) protocol);
739 #ifdef WITH_DEBUG_SCARD
741 for (i = 0; i < atrLen; i++)
742 printf("%02x%c", pbAtr[i], (i == atrLen - 1) ? ' ' : ':');
746 state = sc_map_state(state);
748 stream_write_uint32(irp->output, state);
749 stream_write_uint32(irp->output, protocol);
750 stream_write_uint32(irp->output, atrLen);
751 stream_write_uint32(irp->output, 0x00000001);
752 stream_write_uint32(irp->output, atrLen);
753 stream_write(irp->output, pbAtr, atrLen);
755 sc_output_repos(irp, atrLen);
756 sc_output_alignment(irp, 8);
758 #ifdef SCARD_AUTOALLOCATE
767 static DWORD handle_Status(IRP *irp, boolean wide)
771 DWORD state, protocol;
775 BYTE pbAtr[MAX_ATR_SIZE];
777 int pos, poslen1, poslen2;
779 #ifdef WITH_DEBUG_SCARD
783 stream_seek(irp->input, 0x24);
784 stream_read_uint32(irp->input, readerLen);
785 stream_read_uint32(irp->input, atrLen);
786 stream_seek(irp->input, 0x0c);
787 stream_read_uint32(irp->input, hCard);
788 stream_seek(irp->input, 0x4);
790 atrLen = MAX_ATR_SIZE;
792 #ifdef SCARD_AUTOALLOCATE
793 readerLen = SCARD_AUTOALLOCATE;
795 rv = SCardStatus(hCard, (LPSTR) &readerName, &readerLen, &state, &protocol, pbAtr, &atrLen);
798 readerName = xmalloc(readerLen);
800 rv = SCardStatus(hCard, (LPSTR) readerName, &readerLen, &state, &protocol, pbAtr, &atrLen);
803 if (rv != SCARD_S_SUCCESS)
805 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
806 return sc_output_return(irp, rv);
809 DEBUG_SCARD("Success (state: 0x%08x, proto: 0x%08x)", (unsigned) state, (unsigned) protocol);
810 DEBUG_SCARD(" Reader: \"%s\"", readerName ? readerName : "NULL");
812 #ifdef WITH_DEBUG_SCARD
814 for (i = 0; i < atrLen; i++)
815 printf("%02x%c", pbAtr[i], (i == atrLen - 1) ? ' ' : ':');
819 state = sc_map_state(state);
821 poslen1 = stream_get_pos(irp->output);
822 stream_write_uint32(irp->output, readerLen);
823 stream_write_uint32(irp->output, 0x00020000);
824 stream_write_uint32(irp->output, state);
825 stream_write_uint32(irp->output, protocol);
826 stream_write(irp->output, pbAtr, atrLen);
829 stream_write_zero(irp->output, 32 - atrLen);
830 stream_write_uint32(irp->output, atrLen);
832 poslen2 = stream_get_pos(irp->output);
833 stream_write_uint32(irp->output, readerLen);
835 dataLength = sc_output_string(irp, readerName, wide);
836 dataLength += sc_output_string(irp, "\0", wide);
837 sc_output_repos(irp, dataLength);
839 pos = stream_get_pos(irp->output);
840 stream_set_pos(irp->output, poslen1);
841 stream_write_uint32(irp->output,dataLength);
842 stream_set_pos(irp->output, poslen2);
843 stream_write_uint32(irp->output,dataLength);
844 stream_set_pos(irp->output, pos);
846 sc_output_alignment(irp, 8);
848 #ifdef SCARD_AUTOALLOCATE
849 /* SCardFreeMemory(NULL, readerName); */
858 static uint32 handle_Transmit(IRP* irp)
862 uint32 map[7], linkedLen;
863 SCARD_IO_REQUEST pioSendPci, pioRecvPci, *pPioRecvPci;
864 DWORD cbSendLength = 0, cbRecvLength = 0;
865 BYTE *sendBuf = NULL, *recvBuf = NULL;
867 stream_seek(irp->input, 0x14);
868 stream_read_uint32(irp->input, map[0]);
869 stream_seek(irp->input, 0x4);
870 stream_read_uint32(irp->input, map[1]);
872 stream_read_uint32(irp->input, pioSendPci.dwProtocol);
873 stream_read_uint32(irp->input, pioSendPci.cbPciLength);
875 stream_read_uint32(irp->input, map[2]);
876 stream_read_uint32(irp->input, cbSendLength);
877 stream_read_uint32(irp->input, map[3]);
878 stream_read_uint32(irp->input, map[4]);
879 stream_read_uint32(irp->input, map[5]);
880 stream_read_uint32(irp->input, cbRecvLength);
882 if (map[0] & SCARD_INPUT_LINKED)
883 sc_input_skip_linked(irp);
885 stream_seek(irp->input, 4);
886 stream_read_uint32(irp->input, hCard);
888 if (map[2] & SCARD_INPUT_LINKED)
891 stream_read_uint32(irp->input, linkedLen);
893 stream_read_uint32(irp->input, pioSendPci.dwProtocol);
894 stream_seek(irp->input, linkedLen - 4);
896 sc_input_repos(irp, linkedLen);
898 pioSendPci.cbPciLength = sizeof(SCARD_IO_REQUEST);
900 if (map[3] & SCARD_INPUT_LINKED)
903 stream_read_uint32(irp->input, linkedLen);
905 sendBuf = xmalloc(linkedLen);
906 stream_read(irp->input, sendBuf, linkedLen);
907 sc_input_repos(irp, linkedLen);
911 recvBuf = xmalloc(cbRecvLength);
913 if (map[4] & SCARD_INPUT_LINKED)
916 stream_read_uint32(irp->input, linkedLen);
918 stream_read_uint32(irp->input, pioRecvPci.dwProtocol);
919 stream_seek(irp->input, linkedLen - 4);
921 sc_input_repos(irp, linkedLen);
923 stream_read_uint32(irp->input, map[6]);
924 if (map[6] & SCARD_INPUT_LINKED)
926 /* not sure what this is */
927 stream_read_uint32(irp->input, linkedLen);
928 stream_seek(irp->input, linkedLen);
930 sc_input_repos(irp, linkedLen);
932 pioRecvPci.cbPciLength = sizeof(SCARD_IO_REQUEST);
933 pPioRecvPci = &pioRecvPci;
941 DEBUG_SCARD("SCardTransmit(hcard: 0x%08lx, send: %d bytes, recv: %d bytes)",
942 (long unsigned) hCard, (int) cbSendLength, (int) cbRecvLength);
944 rv = SCardTransmit(hCard, &pioSendPci, sendBuf, cbSendLength,
945 pPioRecvPci, recvBuf, &cbRecvLength);
947 if (rv != SCARD_S_SUCCESS)
949 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
953 DEBUG_SCARD("Success (%d bytes)", (int) cbRecvLength);
955 stream_write_uint32(irp->output, 0); /* pioRecvPci 0x00; */
957 sc_output_buffer_start(irp, cbRecvLength); /* start of recvBuf output */
959 sc_output_buffer(irp, (char *) recvBuf, cbRecvLength);
962 sc_output_alignment(irp, 8);
970 static uint32 handle_Control(IRP* irp)
973 SCARDCONTEXT hContext;
977 uint32 controlFunction;
978 BYTE *recvBuffer = NULL, *sendBuffer = NULL;
980 DWORD nBytesReturned;
983 stream_seek(irp->input, 0x14);
984 stream_read_uint32(irp->input, map[0]);
985 stream_seek(irp->input, 0x4);
986 stream_read_uint32(irp->input, map[1]);
987 stream_read_uint32(irp->input, controlCode);
988 stream_read_uint32(irp->input, recvLength);
989 stream_read_uint32(irp->input, map[2]);
990 stream_seek(irp->input, 0x4);
991 stream_read_uint32(irp->input, outBufferSize);
992 stream_seek(irp->input, 0x4);
993 stream_read_uint32(irp->input, hContext);
994 stream_seek(irp->input, 0x4);
995 stream_read_uint32(irp->input, hCard);
997 /* Translate Windows SCARD_CTL_CODE's to corresponding local code */
998 if (WIN_CTL_DEVICE_TYPE(controlCode) == WIN_FILE_DEVICE_SMARTCARD)
1000 controlFunction = WIN_CTL_FUNCTION(controlCode);
1001 controlCode = SCARD_CTL_CODE(controlFunction);
1003 DEBUG_SCARD("controlCode: 0x%08x", (unsigned) controlCode);
1005 if (map[2] & SCARD_INPUT_LINKED)
1007 /* read real input size */
1008 stream_read_uint32(irp->input, recvLength);
1010 recvBuffer = xmalloc(recvLength);
1013 return sc_output_return(irp, SCARD_E_NO_MEMORY);
1015 stream_read(irp->input, recvBuffer, recvLength);
1018 nBytesReturned = outBufferSize;
1019 sendBuffer = xmalloc(outBufferSize);
1022 return sc_output_return(irp, SCARD_E_NO_MEMORY);
1024 rv = SCardControl(hCard, (DWORD) controlCode, recvBuffer, (DWORD) recvLength,
1025 sendBuffer, (DWORD) outBufferSize, &nBytesReturned);
1027 if (rv != SCARD_S_SUCCESS)
1028 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
1030 DEBUG_SCARD("Success (out: %u bytes)", (unsigned) nBytesReturned);
1032 stream_write_uint32(irp->output, (uint32) nBytesReturned);
1033 stream_write_uint32(irp->output, 0x00000004);
1034 stream_write_uint32(irp->output, nBytesReturned);
1036 if (nBytesReturned > 0)
1038 stream_write(irp->output, sendBuffer, nBytesReturned);
1039 sc_output_repos(irp, nBytesReturned);
1042 sc_output_alignment(irp, 8);
1050 static uint32 handle_GetAttrib(IRP* irp)
1054 DWORD dwAttrId = 0, dwAttrLen = 0;
1056 uint8* pbAttr = NULL;
1058 stream_seek(irp->input, 0x20);
1059 stream_read_uint32(irp->input, dwAttrId);
1060 stream_seek(irp->input, 0x4);
1061 stream_read_uint32(irp->input, dwAttrLen);
1062 stream_seek(irp->input, 0xC);
1063 stream_read_uint32(irp->input, hCard);
1065 DEBUG_SCARD("hcard: 0x%08x, attrib: 0x%08x (%d bytes)\n",
1066 (unsigned) hCard, (unsigned) dwAttrId, (int) dwAttrLen);
1068 #ifdef SCARD_AUTOALLOCATE
1075 attrLen = SCARD_AUTOALLOCATE;
1079 rv = SCardGetAttrib(hCard, dwAttrId, attrLen == 0 ? NULL : (uint8*) &pbAttr, &attrLen);
1080 if( rv != SCARD_S_SUCCESS ) {
1081 #ifdef SCARD_AUTOALLOCATE
1088 attrLen = SCARD_AUTOALLOCATE;
1093 if(dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A && rv == SCARD_E_UNSUPPORTED_FEATURE)
1095 rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W,
1096 attrLen == 0 ? NULL : (uint8*) &pbAttr, &attrLen);
1097 if( rv != SCARD_S_SUCCESS ) {
1098 #ifdef SCARD_AUTOALLOCATE
1105 attrLen = SCARD_AUTOALLOCATE;
1110 if(dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W && rv == SCARD_E_UNSUPPORTED_FEATURE)
1112 rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A,
1113 attrLen == 0 ? NULL : (uint8*) &pbAttr, &attrLen);
1114 if( rv != SCARD_S_SUCCESS ) {
1115 #ifdef SCARD_AUTOALLOCATE
1122 attrLen = SCARD_AUTOALLOCATE;
1127 if(attrLen > dwAttrLen && pbAttr != NULL)
1129 rv = SCARD_E_INSUFFICIENT_BUFFER;
1131 dwAttrLen = attrLen;
1133 if (rv != SCARD_S_SUCCESS)
1135 DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned int) rv);
1137 return sc_output_return(irp, rv);
1141 DEBUG_SCARD("Success (%d bytes)", (int) dwAttrLen);
1143 stream_write_uint32(irp->output, dwAttrLen);
1144 stream_write_uint32(irp->output, 0x00000200);
1145 stream_write_uint32(irp->output, dwAttrLen);
1149 stream_write_zero(irp->output, dwAttrLen);
1153 stream_write(irp->output, pbAttr, dwAttrLen);
1155 sc_output_repos(irp, dwAttrLen);
1156 /* align to multiple of 4 */
1157 stream_write_uint32(irp->output, 0);
1159 sc_output_alignment(irp, 8);
1166 static uint32 handle_AccessStartedEvent(IRP* irp)
1168 stream_write_zero(irp->output, 8);
1169 return SCARD_S_SUCCESS;
1172 void scard_error(SCARD_DEVICE* scard, IRP* irp, uint32 ntstatus)
1174 /* [MS-RDPESC] 3.1.4.4 */
1175 printf("scard processing error %x\n", ntstatus);
1177 stream_set_pos(irp->output, 0); /* CHECKME */
1178 irp->IoStatus = ntstatus;
1182 /* http://msdn.microsoft.com/en-gb/library/ms938473.aspx */
1183 typedef struct _SERVER_SCARD_ATRMASK
1189 SERVER_SCARD_ATRMASK;
1191 static uint32 handle_LocateCardsByATR(IRP* irp, boolean wide)
1195 SCARDCONTEXT hContext;
1196 uint32 atrMaskCount = 0;
1197 uint32 readerCount = 0;
1198 SCARD_READERSTATE* cur = NULL;
1199 SCARD_READERSTATE* rsCur = NULL;
1200 SCARD_READERSTATE* readerStates = NULL;
1201 SERVER_SCARD_ATRMASK* curAtr = NULL;
1202 SERVER_SCARD_ATRMASK* pAtrMasks = NULL;
1204 stream_seek(irp->input, 0x2C);
1205 stream_read_uint32(irp->input, hContext);
1206 stream_read_uint32(irp->input, atrMaskCount);
1208 pAtrMasks = xmalloc(atrMaskCount * sizeof(SERVER_SCARD_ATRMASK));
1211 return sc_output_return(irp, SCARD_E_NO_MEMORY);
1213 for (i = 0; i < atrMaskCount; i++)
1215 stream_read_uint32(irp->input, pAtrMasks[i].cbAtr);
1216 stream_read(irp->input, pAtrMasks[i].rgbAtr, 36);
1217 stream_read(irp->input, pAtrMasks[i].rgbMask, 36);
1220 stream_read_uint32(irp->input, readerCount);
1222 readerStates = xzalloc(readerCount * sizeof(SCARD_READERSTATE));
1225 return sc_output_return(irp, SCARD_E_NO_MEMORY);
1227 for (i = 0; i < readerCount; i++)
1229 cur = &readerStates[i];
1231 stream_seek(irp->input, 4);
1234 * TODO: on-wire is little endian; need to either
1235 * convert to host endian or fix the headers to
1236 * request the order we want
1238 stream_read_uint32(irp->input, cur->dwCurrentState);
1239 stream_read_uint32(irp->input, cur->dwEventState);
1240 stream_read_uint32(irp->input, cur->cbAtr);
1241 stream_read(irp->input, cur->rgbAtr, 32);
1243 stream_seek(irp->input, 4);
1245 /* reset high bytes? */
1246 cur->dwCurrentState &= 0x0000FFFF;
1247 cur->dwEventState &= 0x0000FFFF;
1248 cur->dwEventState = 0;
1251 for (i = 0; i < readerCount; i++)
1253 cur = &readerStates[i];
1256 stream_seek(irp->input, 8);
1257 stream_read_uint32(irp->input, dataLength);
1258 sc_input_repos(irp, sc_input_string(irp, (char **) &cur->szReader, dataLength, wide));
1260 DEBUG_SCARD(" \"%s\"", cur->szReader ? cur->szReader : "NULL");
1261 DEBUG_SCARD(" user: 0x%08x, state: 0x%08x, event: 0x%08x",
1262 (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
1263 (unsigned) cur->dwEventState);
1265 if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0)
1266 cur->dwCurrentState |= SCARD_STATE_IGNORE;
1269 rv = SCardGetStatusChange(hContext, 0x00000001, readerStates, readerCount);
1270 if (rv != SCARD_S_SUCCESS)
1272 DEBUG_SCARD("Failure: %s (0x%08x)",
1273 pcsc_stringify_error(rv), (unsigned) rv);
1275 return sc_output_return(irp, rv);
1278 DEBUG_SCARD("Success");
1279 for (i = 0, curAtr = pAtrMasks; i < atrMaskCount; i++, curAtr++)
1281 for (j = 0, rsCur = readerStates; j < readerCount; j++, rsCur++)
1284 for (k = 0; k < cur->cbAtr; k++)
1286 if ((curAtr->rgbAtr[k] & curAtr->rgbMask[k]) !=
1287 (rsCur->rgbAtr[k] & curAtr->rgbMask[k]))
1295 rsCur->dwEventState |= 0x00000040; /* SCARD_STATE_ATRMATCH 0x00000040 */
1300 stream_write_uint32(irp->output, readerCount);
1301 stream_write_uint32(irp->output, 0x00084dd8);
1302 stream_write_uint32(irp->output, readerCount);
1304 for (i = 0, rsCur = readerStates; i < readerCount; i++, rsCur++)
1306 stream_write_uint32(irp->output, cur->dwCurrentState);
1307 stream_write_uint32(irp->output, cur->dwEventState);
1308 stream_write_uint32(irp->output, cur->cbAtr);
1309 stream_write(irp->output, cur->rgbAtr, 32);
1311 stream_write_zero(irp->output, 4);
1313 xfree((void*) cur->szReader);
1316 sc_output_alignment(irp, 8);
1323 boolean scard_async_op(IRP* irp)
1328 stream_seek(irp->input, 8);
1329 stream_read_uint32(irp->input, ioctl_code);
1330 stream_rewind(irp->input, 12);
1334 /* non-blocking events */
1335 case SCARD_IOCTL_ACCESS_STARTED_EVENT:
1337 case SCARD_IOCTL_ESTABLISH_CONTEXT:
1338 case SCARD_IOCTL_RELEASE_CONTEXT:
1339 case SCARD_IOCTL_IS_VALID_CONTEXT:
1345 case SCARD_IOCTL_GET_STATUS_CHANGE:
1346 case SCARD_IOCTL_GET_STATUS_CHANGE + 4:
1348 case SCARD_IOCTL_TRANSMIT:
1350 case SCARD_IOCTL_STATUS:
1351 case SCARD_IOCTL_STATUS + 4:
1359 /* default to async */
1363 void scard_device_control(SCARD_DEVICE* scard, IRP* irp)
1365 uint32 output_len, input_len, ioctl_code;
1366 uint32 stream_len, result;
1367 uint32 pos, pad_len;
1369 uint32 irp_result_pos, output_len_pos, result_pos;
1371 stream_read_uint32(irp->input, output_len);
1372 stream_read_uint32(irp->input, input_len);
1373 stream_read_uint32(irp->input, ioctl_code);
1375 stream_seek(irp->input, 20); /* padding */
1377 // stream_seek(irp->input, 4); /* TODO: parse len, le, v1 */
1378 // stream_seek(irp->input, 4); /* 0xcccccccc */
1379 // stream_seek(irp->input, 4); /* rpce len */
1381 /* [MS-RDPESC] 3.2.5.1 Sending Outgoing Messages */
1382 stream_extend(irp->output, 2048);
1384 irp_result_pos = stream_get_pos(irp->output);
1386 stream_write_uint32(irp->output, 0x00081001); /* len 8, LE, v1 */
1388 /* [MS-RPCE] 2.2.6.1 */
1389 stream_write_uint32(irp->output, 0x00081001); /* len 8, LE, v1 */
1390 stream_write_uint32(irp->output, 0xcccccccc); /* filler */
1392 output_len_pos = stream_get_pos(irp->output);
1393 stream_seek(irp->output, 4); /* size */
1395 stream_write_uint32(irp->output, 0x0); /* filler */
1397 result_pos = stream_get_pos(irp->output);
1398 stream_seek(irp->output, 4); /* result */
1403 case SCARD_IOCTL_ESTABLISH_CONTEXT:
1404 result = handle_EstablishContext(irp);
1407 case SCARD_IOCTL_IS_VALID_CONTEXT:
1408 result = handle_IsValidContext(irp);
1411 case SCARD_IOCTL_RELEASE_CONTEXT:
1412 result = handle_ReleaseContext(irp);
1415 case SCARD_IOCTL_LIST_READERS:
1416 result = handle_ListReaders(irp, 0);
1418 case SCARD_IOCTL_LIST_READERS + 4:
1419 result = handle_ListReaders(irp, 1);
1422 case SCARD_IOCTL_LIST_READER_GROUPS:
1423 case SCARD_IOCTL_LIST_READER_GROUPS + 4:
1424 /* typically not used unless list_readers fail */
1425 result = SCARD_F_INTERNAL_ERROR;
1428 case SCARD_IOCTL_GET_STATUS_CHANGE:
1429 result = handle_GetStatusChange(irp, 0);
1431 case SCARD_IOCTL_GET_STATUS_CHANGE + 4:
1432 result = handle_GetStatusChange(irp, 1);
1435 case SCARD_IOCTL_CANCEL:
1436 result = handle_Cancel(irp);
1439 case SCARD_IOCTL_CONNECT:
1440 result = handle_Connect(irp, 0);
1442 case SCARD_IOCTL_CONNECT + 4:
1443 result = handle_Connect(irp, 1);
1446 case SCARD_IOCTL_RECONNECT:
1447 result = handle_Reconnect(irp);
1450 case SCARD_IOCTL_DISCONNECT:
1451 result = handle_Disconnect(irp);
1454 case SCARD_IOCTL_BEGIN_TRANSACTION:
1455 result = handle_BeginTransaction(irp);
1458 case SCARD_IOCTL_END_TRANSACTION:
1459 result = handle_EndTransaction(irp);
1462 case SCARD_IOCTL_STATE:
1463 result = handle_State(irp);
1466 case SCARD_IOCTL_STATUS:
1467 result = handle_Status(irp, 0);
1469 case SCARD_IOCTL_STATUS + 4:
1470 result = handle_Status(irp, 1);
1473 case SCARD_IOCTL_TRANSMIT:
1474 result = handle_Transmit(irp);
1477 case SCARD_IOCTL_CONTROL:
1478 result = handle_Control(irp);
1481 case SCARD_IOCTL_GETATTRIB:
1482 result = handle_GetAttrib(irp);
1485 case SCARD_IOCTL_ACCESS_STARTED_EVENT:
1486 result = handle_AccessStartedEvent(irp);
1489 case SCARD_IOCTL_LOCATE_CARDS_BY_ATR:
1490 result = handle_LocateCardsByATR(irp, 0);
1492 case SCARD_IOCTL_LOCATE_CARDS_BY_ATR + 4:
1493 result = handle_LocateCardsByATR(irp, 1);
1497 result = 0xc0000001;
1498 printf("scard unknown ioctl 0x%x\n", ioctl_code);
1502 /* look for NTSTATUS errors */
1503 if ((result & 0xc0000000) == 0xc0000000)
1504 return scard_error(scard, irp, result);
1506 /* per Ludovic Rousseau, map different usage of this particular
1507 * error code between pcsc-lite & windows */
1508 if (result == 0x8010001F)
1509 result = 0x80100022;
1511 /* handle response packet */
1512 pos = stream_get_pos(irp->output);
1513 stream_len = pos - irp_result_pos - 4;
1515 stream_set_pos(irp->output, output_len_pos);
1516 stream_write_uint32(irp->output, stream_len - 24);
1518 stream_set_pos(irp->output, result_pos);
1519 stream_write_uint32(irp->output, result);
1521 stream_set_pos(irp->output, pos);
1523 /* pad stream to 16 byte align */
1524 pad_len = stream_len % 16;
1525 stream_write_zero(irp->output, pad_len);
1526 pos = stream_get_pos(irp->output);
1527 irp_len = stream_len + pad_len;
1529 stream_set_pos(irp->output, irp_result_pos);
1530 stream_write_uint32(irp->output, irp_len);
1531 stream_set_pos(irp->output, pos);
1533 #ifdef WITH_DEBUG_SCARD
1534 freerdp_hexdump(stream_get_data(irp->output), stream_get_length(irp->output));