/[rdesktop]/sourceforge.net/trunk/rdesktop/scard.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/scard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1373 - (show annotations)
Mon Jan 8 12:38:34 2007 UTC (17 years, 4 months ago) by stargo
File MIME type: text/plain
File size: 70142 byte(s)
some more RD_BOOL

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 Smart Card support
4 Copyright (C) Alexi Volkov <alexi@myrealbox.com> 2006
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <strings.h>
25 #include <sys/types.h>
26 #include <time.h>
27 #ifndef MAKE_PROTO
28 #ifdef PCSC_OSX
29 #include <PCSC/wintypes.h>
30 #include <PCSC/pcsclite.h>
31 #include <PCSC/winscard.h>
32 #else
33 #include <wintypes.h>
34 #include <pcsclite.h>
35 #include <winscard.h>
36 #endif /* PCSC_OSX */
37 #include "rdesktop.h"
38 #include "scard.h"
39
40 /* variable segment */
41
42 #define SCARD_MAX_MEM 102400
43 #define SCARD_AUTOALLOCATE -1
44 #define OUT_STREAM_SIZE 4096
45 #define STREAM_COUNT 8
46
47 static struct stream out[STREAM_COUNT];
48 static int cur_stream_id = 0;
49 static pthread_mutex_t **scard_mutex = NULL;
50
51 static uint32 curDevice = 0, curId = 0, curBytesOut = 0;
52 static PSCNameMapRec nameMapList = NULL;
53 static int nameMapCount = 0;
54
55 static pthread_t queueHandler;
56 static pthread_mutex_t queueAccess;
57 static pthread_mutex_t queueEmpty;
58 static pthread_mutex_t hcardAccess;
59
60 static PMEM_HANDLE threadListHandle = NULL;
61 static PThreadListElement threadList = NULL;
62
63
64 static PSCThreadData queueFirst = NULL, queueLast = NULL;
65 static int threadCount = 0;
66
67 static PSCHCardRec hcardFirst = NULL;
68
69 static void *queue_handler_function(void *data);
70
71 /* code segment */
72
73 #endif /* MAKE_PROTO */
74 void
75 scardSetInfo(uint32 device, uint32 id, uint32 bytes_out)
76 {
77 curDevice = device;
78 curId = id;
79 curBytesOut = bytes_out;
80 }
81
82 #ifndef MAKE_PROTO
83
84 static RD_NTSTATUS
85 scard_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
86 uint32 flags_and_attributes, char *filename, RD_NTHANDLE * phandle)
87 {
88 return RD_STATUS_SUCCESS;
89 }
90
91 static RD_NTSTATUS
92 scard_close(RD_NTHANDLE handle)
93 {
94 return RD_STATUS_SUCCESS;
95 }
96
97 static RD_NTSTATUS
98 scard_read(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
99 {
100 return RD_STATUS_SUCCESS;
101 }
102
103 static RD_NTSTATUS
104 scard_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
105 {
106 return RD_STATUS_SUCCESS;
107 }
108 #endif /* MAKE_PROTO */
109
110 /* Enumeration of devices from rdesktop.c */
111 /* returns numer of units found and initialized. */
112 /* optarg looks like ':"ReaderName=ReaderAlias"' */
113 /* when it arrives to this function. */
114
115 int
116 scard_enum_devices(uint32 * id, char *optarg)
117 {
118 char *name = optarg + 1;
119 char *alias;
120 int count = 0;
121 PSCNameMapRec tmpMap;
122
123 MYPCSC_DWORD rv;
124 SCARDCONTEXT hContext;
125
126 /* code segment */
127 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
128 if (rv != SCARD_S_SUCCESS)
129 {
130 error("[SMART CARD: PCSC service not available]\n");
131 return 0;
132 }
133 else
134 rv = SCardReleaseContext(hContext);
135
136 count = 0;
137
138 if (0 != pthread_mutex_init(&queueAccess, NULL))
139 {
140 error("[SMART CARD: Can't initialize queue access mutex]\n");
141 return 0;
142 }
143
144 if (0 != pthread_mutex_init(&queueEmpty, NULL))
145 {
146 error("[SMART CARD: Can't initialize queue control mutex]\n");
147 return 0;
148 }
149
150 if (0 != pthread_mutex_init(&hcardAccess, NULL))
151 {
152 error("[SMART CARD: Can't initialize hcard list access mutex]\n");
153 return 0;
154 }
155
156 if (0 !=
157 pthread_create(&queueHandler, NULL, (void *(*)(void *)) queue_handler_function, NULL))
158 {
159 error("[SMART CARD: Can't create queue handling Thread]\n");
160 return 0;
161 }
162
163 strncpy(g_rdpdr_device[*id].name, "SCARD\0\0\0", 8);
164 toupper_str(g_rdpdr_device[*id].name);
165 g_rdpdr_device[*id].local_path = "/dev/scard";
166 g_rdpdr_device[*id].pdevice_data = NULL;
167 g_rdpdr_device[*id].handle = 0;
168 g_rdpdr_device[*id].device_type = DEVICE_TYPE_SCARD;
169 count++;
170 (*id)++;
171
172 if (*optarg == ':')
173 {
174 while ((optarg = next_arg(name, ',')) && *id < RDPDR_MAX_DEVICES)
175 {
176 int len;
177 char *vendor = NULL;
178 alias = next_arg(name, '=');
179 vendor = next_arg(alias, ';');
180
181 if (strlen(name) > 0)
182 {
183 if (!strlen(alias))
184 {
185 alias = name;
186 vendor = "\0";
187 }
188
189 printf("Static/aliased Device:\n");
190 printf(" Lin name: [%s]\n", name);
191 printf(" Win name: [%s]\n", alias);
192 printf(" Vendor : [%s]\n", vendor);
193 nameMapCount++;
194
195 if (nameMapList == NULL)
196 nameMapList = xmalloc(nameMapCount * sizeof(TSCNameMapRec));
197 else
198 nameMapList =
199 xrealloc(nameMapList,
200 nameMapCount * sizeof(TSCNameMapRec));
201
202 tmpMap = nameMapList + nameMapCount - 1;
203
204 len = strlen(alias);
205 strncpy(tmpMap->alias, alias, (len > 127) ? (127) : (len));
206 len = strlen(name);
207 strncpy(tmpMap->name, name, (len > 127) ? (127) : (len));
208
209 if (vendor)
210 {
211 len = strlen(vendor);
212 if (len > 0)
213 {
214 memset(tmpMap->vendor, 0, 128);
215 strncpy(tmpMap->vendor, vendor,
216 (len > 127) ? (127) : (len));
217 }
218 else
219 tmpMap->vendor[0] = '\0';
220 }
221 else
222 tmpMap->vendor[0] = '\0';
223 }
224 name = optarg;
225 }
226 }
227
228 return count;
229 }
230
231 #ifndef MAKE_PROTO
232 /* ---------------------------------- */
233
234 /* These two functions depend heavily on the actual implementation of the smart
235 * card handle in PC/SC Lite 1.3.1. Here are the salient bits:
236 *
237 * From winscard.c:331, in SCardConnect:
238 * *phCard = RFCreateReaderHandle(rContext);
239 *
240 * RFCreateReaderHandle (readerfactory.c:1161) creates a random short (16-bit
241 * integer) and makes sure it's unique. Then it adds it to
242 * rContext->dwIdentity.
243 *
244 * From readerfactory.c:173, in RFAddReader:
245 * (sReadersContexts[dwContext])->dwIdentity =
246 * (dwContext + 1) << (sizeof(DWORD) / 2) * 8;
247 *
248 * dwContext must be less than PCSCLITE_MAX_READERS_CONTEXTS, which is defined
249 * to be 16 in the 1.3.1 release.
250 *
251 * The use of "(sizeof(DWORD) / 2) * 8" is what makes conversion necessary in
252 * order to use 64-bit card handles when talking to PC/SC Lite, and 32-bit card
253 * handles when talking with the server, without losing any data: a card handle
254 * made by a 32-bit PC/SC Lite looks like 0x00014d32, where the 4d32 is the
255 * random 16 bits, 01 is the reader context index + 1, and it's left-shifted by
256 * 16 bits (sizeof(DWORD) == 4, divided by 2 is 2, times 8 is 16.) But a 64-bit
257 * PC/SC Lite makes a card handle that looks like 0x0000000100004d32. The
258 * reader context index+1 is left-shifted 32 bits because sizeof(DWORD) is 8,
259 * not 4. This means the handle won't fit in 32 bits. (The multiplication by 8
260 * is because sizeofs are in bytes, but saying how many places to left-shift is
261 * speaking in bits.)
262 *
263 * So then. Maximum value of dwContext+1 is 17; we'll say this fits in a byte
264 * to be loose and have plenty of room. This is then left-shifted by
265 * sizeof(DWORD) / 2 * 8 - which in this file is sizeof(MYPCSC_DWORD) / 2 * 8.
266 *
267 * At any rate, if we take the handle as passed from PC/SC Lite, right-shift by
268 * sizeof(MYPCSC_DWORD) / 2, left-shift by sizeof(SERVER_DWORD) / 2, and add
269 * the lower two bytes of the value (the random number), we can fit all the
270 * information into 32 bits without losing any. Of course, any time we want to
271 * hand that back to PC/SC Lite, we'll have to expand it again. (And if
272 * sizeof(MYPCSC_DWORD) == sizeof(SERVER_DWORD), we're essentially doing
273 * nothing, which will not break anything.)
274 *
275 *
276 * - jared.jennings@eglin.af.mil, 2 Aug 2006
277 */
278
279
280 static MYPCSC_SCARDHANDLE
281 scHandleToMyPCSC(SERVER_SCARDHANDLE server)
282 {
283 return (((MYPCSC_SCARDHANDLE) server >> (sizeof(SERVER_DWORD) * 8 / 2) & 0xffff)
284 << (sizeof(MYPCSC_DWORD) * 8 / 2)) + (server & 0xffff);
285 }
286
287 static SERVER_SCARDHANDLE
288 scHandleToServer(MYPCSC_SCARDHANDLE mypcsc)
289 {
290 return ((mypcsc >> (sizeof(MYPCSC_DWORD) * 8 / 2) & 0xffff)
291 << (sizeof(SERVER_DWORD) * 8 / 2)) + (mypcsc & 0xffff);
292 }
293
294 /* ---------------------------------- */
295
296 static void *
297 SC_xmalloc(PMEM_HANDLE * memHandle, unsigned int size)
298 {
299 PMEM_HANDLE handle = NULL;
300 if (size > 0 && memHandle)
301 {
302 handle = xmalloc(size + sizeof(MEM_HANDLE));
303 if (handle)
304 {
305 handle->prevHandle = NULL;
306 handle->nextHandle = NULL;
307 handle->dataSize = size;
308 if (*memHandle)
309 {
310 handle->prevHandle = *memHandle;
311 (*memHandle)->nextHandle = handle;
312 }
313 *memHandle = handle;
314 return handle + 1;
315 }
316 else
317 return NULL;
318 }
319 else
320 return NULL;
321 }
322
323 static void
324 SC_xfree(PMEM_HANDLE * handle, void *memptr)
325 {
326 if (memptr != NULL)
327 {
328 PMEM_HANDLE lcHandle = (PMEM_HANDLE) memptr - 1;
329 if (lcHandle->dataSize > 0)
330 {
331 memset(memptr, 0, lcHandle->dataSize);
332 if (lcHandle->nextHandle)
333 lcHandle->nextHandle->prevHandle = lcHandle->prevHandle;
334 if (lcHandle->prevHandle)
335 lcHandle->prevHandle->nextHandle = lcHandle->nextHandle;
336 if (*handle == lcHandle)
337 {
338 if (lcHandle->prevHandle)
339 *handle = lcHandle->prevHandle;
340 else
341 *handle = lcHandle->nextHandle;
342 }
343 xfree(lcHandle);
344 }
345 }
346 }
347
348 static void
349 SC_xfreeallmemory(PMEM_HANDLE * handle)
350 {
351 if (handle && (*handle))
352 {
353 if ((*handle)->prevHandle)
354 {
355 (*handle)->prevHandle->nextHandle = NULL;
356 SC_xfreeallmemory(&((*handle)->prevHandle));
357 }
358 if ((*handle)->nextHandle)
359 {
360 (*handle)->nextHandle->prevHandle = NULL;
361 SC_xfreeallmemory(&((*handle)->nextHandle));
362 }
363 memset(*handle, 0, (*handle)->dataSize + sizeof(MEM_HANDLE));
364 xfree(*handle);
365 *handle = NULL;
366 }
367 }
368
369 /* ---------------------------------- */
370
371 static char *
372 getName(char *alias)
373 {
374 int i;
375 PSCNameMapRec tmpMap;
376 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
377 {
378 if (strcmp(tmpMap->alias, alias) == 0)
379 return tmpMap->name;
380 }
381 return alias;
382 }
383
384 static char *
385 getVendor(char *name)
386 {
387 int i;
388 PSCNameMapRec tmpMap;
389 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
390 {
391 if (strcmp(tmpMap->name, name) == 0)
392 return tmpMap->vendor;
393 }
394 return NULL;
395 }
396
397
398 static char *
399 getAlias(char *name)
400 {
401 int i;
402 PSCNameMapRec tmpMap;
403 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
404 {
405 if (strcmp(tmpMap->name, name) == 0)
406 return tmpMap->alias;
407 }
408 return name;
409 }
410
411 static int
412 hasAlias(char *name)
413 {
414 int i;
415 PSCNameMapRec tmpMap;
416 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
417 {
418 if (strcmp(tmpMap->name, name) == 0)
419 return 1;
420 }
421 return 0;
422 }
423
424 static void
425 inRepos(STREAM in, unsigned int read)
426 {
427 SERVER_DWORD add = 4 - read % 4;
428 if (add < 4 && add > 0)
429 {
430 in_uint8s(in, add);
431 }
432 }
433
434 static void
435 outRepos(STREAM out, unsigned int written)
436 {
437 SERVER_DWORD add = (4 - written % 4) % 4;
438 if (add > 0)
439 {
440 out_uint8s(out, add);
441 }
442 }
443
444
445 static void
446 outBufferStartWithLimit(STREAM out, int length, int highLimit)
447 {
448 int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
449 out_uint32_le(out, header);
450 out_uint32_le(out, 0x00000001); /* Magic DWORD - any non zero */
451 }
452
453
454 static void
455 outBufferStart(STREAM out, int length)
456 {
457 outBufferStartWithLimit(out, length, 0x7FFFFFFF);
458 }
459
460 static void
461 outBufferFinishWithLimit(STREAM out, char *buffer, unsigned int length, unsigned int highLimit)
462 {
463 int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
464 out_uint32_le(out, header);
465
466 if (length <= 0)
467 {
468 out_uint32_le(out, 0x00000000);
469 }
470 else
471 {
472 if (header < length)
473 length = header;
474 out_uint8p(out, buffer, length);
475 outRepos(out, length);
476 }
477 }
478
479 static void
480 outBufferFinish(STREAM out, char *buffer, unsigned int length)
481 {
482 outBufferFinishWithLimit(out, buffer, length, 0x7FFFFFFF);
483 }
484
485 static void
486 outForceAlignment(STREAM out, unsigned int seed)
487 {
488 SERVER_DWORD add = (seed - (out->p - out->data) % seed) % seed;
489 if (add > 0)
490 out_uint8s(out, add);
491 }
492
493 static unsigned int
494 inString(PMEM_HANDLE * handle, STREAM in, char **destination, SERVER_DWORD dataLength, RD_BOOL wide)
495 {
496 unsigned int Result = (wide) ? (2 * dataLength) : (dataLength);
497 PMEM_HANDLE lcHandle = NULL;
498 char *buffer = SC_xmalloc(&lcHandle, Result + 2);
499 char *reader;
500
501 /* code segment */
502
503 if (wide)
504 {
505 int i;
506 in_uint8a(in, buffer, 2 * dataLength);
507 for (i = 0; i < dataLength; i++)
508 if ((buffer[2 * i] < 0) || (buffer[2 * i + 1] != 0))
509 buffer[i] = '?';
510 else
511 buffer[i] = buffer[2 * i];
512 }
513 else
514 {
515 in_uint8a(in, buffer, dataLength);
516 }
517
518 buffer[dataLength] = '\0';
519 reader = getName(buffer);
520 *destination = SC_xmalloc(handle, strlen(reader) + 1);
521 strcpy(*destination, reader);
522
523 SC_xfreeallmemory(&lcHandle);
524 return Result;
525 }
526
527 static unsigned int
528 outString(STREAM out, char *source, RD_BOOL wide)
529 {
530 PMEM_HANDLE lcHandle = NULL;
531 char *reader = getAlias(source);
532 unsigned int dataLength = strlen(reader) + 1;
533 unsigned int Result = (wide) ? (2 * dataLength) : (dataLength);
534
535 /* code segment */
536
537 if (wide)
538 {
539 int i;
540 char *buffer = SC_xmalloc(&lcHandle, Result);
541
542 for (i = 0; i < dataLength; i++)
543 {
544 if (source[i] < 0)
545 buffer[2 * i] = '?';
546 else
547 buffer[2 * i] = reader[i];
548 buffer[2 * i + 1] = '\0';
549 }
550 out_uint8p(out, buffer, 2 * dataLength);
551 }
552 else
553 {
554 out_uint8p(out, reader, dataLength);
555 }
556
557 SC_xfreeallmemory(&lcHandle);
558 return Result;
559 }
560
561 static void
562 inReaderName(PMEM_HANDLE * handle, STREAM in, char **destination, RD_BOOL wide)
563 {
564 SERVER_DWORD dataLength;
565 in->p += 0x08;
566 in_uint32_le(in, dataLength);
567 inRepos(in, inString(handle, in, destination, dataLength, wide));
568 }
569
570 static void
571 inSkipLinked(STREAM in)
572 {
573 SERVER_DWORD len;
574 in_uint32_le(in, len);
575 if (len > 0)
576 {
577 in_uint8s(in, len);
578 inRepos(in, len);
579 }
580 }
581
582 /* ---------------------------------- */
583 /* Smart Card processing functions: */
584 /* ---------------------------------- */
585
586 static MYPCSC_DWORD
587 SC_returnCode(MYPCSC_DWORD rc, PMEM_HANDLE * handle, STREAM in, STREAM out)
588 {
589 SC_xfreeallmemory(handle);
590 out_uint8s(out, 256);
591 return rc;
592 }
593
594 static MYPCSC_DWORD
595 SC_returnNoMemoryError(PMEM_HANDLE * handle, STREAM in, STREAM out)
596 {
597 return SC_returnCode(SCARD_E_NO_MEMORY, handle, in, out);
598 }
599
600 static MYPCSC_DWORD
601 TS_SCardEstablishContext(STREAM in, STREAM out)
602 {
603 MYPCSC_DWORD rv;
604 MYPCSC_SCARDCONTEXT hContext;
605 /* code segment */
606
607 DEBUG_SCARD(("Establishing PC/SC Context... \n"));
608 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
609 if (rv)
610 {
611 DEBUG_SCARD(("<--ERROR SCardEstablishContext Code=0x%.8x, %s]-->\n",
612 (unsigned int) rv, pcsc_stringify_error(rv)));
613 }
614 else
615 {
616 DEBUG_SCARD(("<--SUCCESS SCardEstablishContext-->\n"));
617 }
618
619 out_uint32_le(out, 0x00000004);
620 out_uint32_le(out, (SERVER_DWORD) hContext); /* must not be 0 (Seems to be pointer), don't know what is this (I use hContext as value) */
621 /* i hope it's not a pointer because i just downcasted it - jlj */
622 out_uint32_le(out, 0x00000004);
623 out_uint32_le(out, (SERVER_DWORD) hContext);
624 return rv;
625 }
626
627 static MYPCSC_DWORD
628 TS_SCardReleaseContext(STREAM in, STREAM out)
629 {
630 MYPCSC_DWORD rv;
631 SERVER_SCARDCONTEXT hContext;
632
633 in->p += 0x1C;
634 in_uint32_le(in, hContext);
635 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
636 DEBUG_SCARD(("Releasing context... \n"));
637 rv = SCardReleaseContext((MYPCSC_SCARDCONTEXT) hContext);
638
639 if (rv)
640 {
641 DEBUG_SCARD(("<--ERROR SCardReleaseContext Code=0x%.8x, %s-->\n", (unsigned int) rv,
642 pcsc_stringify_error(rv)));
643 }
644 else
645 {
646 DEBUG_SCARD(("<--SUCCESS SCardReleaseContext-->\n"));
647 }
648
649 return rv;
650 }
651
652 static MYPCSC_DWORD
653 TS_SCardIsValidContext(STREAM in, STREAM out)
654 {
655 MYPCSC_DWORD rv;
656 SERVER_SCARDCONTEXT hContext;
657 char *readers;
658 DWORD readerCount = 1024;
659 PMEM_HANDLE lcHandle = NULL;
660
661 in->p += 0x1C;
662 in_uint32_le(in, hContext);
663 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
664 DEBUG_SCARD(("Checking... \n"));
665 /* There is no realization of SCardIsValidContext in PC/SC Lite so we call SCardListReaders */
666
667 readers = SC_xmalloc(&lcHandle, 1024);
668 if (!readers)
669 return SC_returnNoMemoryError(&lcHandle, in, out);
670
671 rv = SCardListReaders((MYPCSC_SCARDCONTEXT) hContext, NULL, readers, &readerCount);
672
673 if (rv)
674 {
675 DEBUG_SCARD(("<--ERROR SCardListReaders (no SCardIsValidContext) Code=0x%.8x, %s-->\n", (unsigned int) rv, pcsc_stringify_error(rv)));
676 rv = SCARD_E_INVALID_HANDLE;
677 }
678 else
679 {
680 DEBUG_SCARD(("<--SUCCESS SCardListReaders (no SCardIsValidContext)-->\n"));
681 }
682
683 outForceAlignment(out, 8);
684 SC_xfreeallmemory(&lcHandle);
685 return rv;
686 }
687
688
689 static MYPCSC_DWORD
690 TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide)
691 {
692 #define readerArraySize 1024
693 MYPCSC_DWORD rv;
694 SERVER_SCARDCONTEXT hContext;
695 SERVER_DWORD dataLength;
696 MYPCSC_DWORD cchReaders = readerArraySize;
697 unsigned char *plen1, *plen2, *pend;
698 char *readers, *cur;
699 PMEM_HANDLE lcHandle = NULL;
700
701 in->p += 0x2C;
702 in_uint32_le(in, hContext);
703 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
704 plen1 = out->p;
705 out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
706 out_uint32_le(out, 0x01760650);
707 plen2 = out->p;
708 out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
709
710 dataLength = 0;
711 readers = SC_xmalloc(&lcHandle, readerArraySize);
712 if (!readers)
713 return SC_returnNoMemoryError(&lcHandle, in, out);
714
715
716 readers[0] = '\0';
717 readers[1] = '\0';
718 rv = SCardListReaders((MYPCSC_SCARDCONTEXT) hContext, NULL, readers, &cchReaders);
719 cur = readers;
720 if (!rv)
721 {
722 int i;
723 PSCNameMapRec tmpMap;
724 #ifdef WITH_DEBUG_SCARD
725 DEBUG_SCARD(("[CALL RESULT of SCardListReaders 0x%.8x]\n", (unsigned int) rv));
726 hexdump((void *) readers, cchReaders);
727 #endif
728 for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
729 {
730 dataLength += outString(out, tmpMap->alias, wide);
731 }
732
733 int lenSC = strlen(cur);
734 if (lenSC == 0)
735 dataLength += outString(out, "\0", wide);
736 else
737 while (lenSC > 0)
738 {
739 if (!hasAlias(cur))
740 dataLength += outString(out, cur, wide);
741 cur = (void *) ((unsigned char *) cur + lenSC + 1);
742 lenSC = strlen(cur);
743 }
744 }
745
746 dataLength += outString(out, "\0", wide);
747 outRepos(out, dataLength);
748
749 pend = out->p;
750 out->p = plen1;
751 out_uint32_le(out, dataLength);
752 out->p = plen2;
753 out_uint32_le(out, dataLength);
754 out->p = pend;
755
756 outForceAlignment(out, 8);
757 SC_xfreeallmemory(&lcHandle);
758 return rv;
759 }
760
761
762 static MYPCSC_DWORD
763 TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide)
764 {
765 MYPCSC_DWORD rv;
766 SCARDCONTEXT hContext;
767 char *szReader;
768 SERVER_DWORD dwShareMode;
769 SERVER_DWORD dwPreferredProtocol;
770 MYPCSC_SCARDHANDLE myHCard;
771 SERVER_SCARDHANDLE hCard;
772
773 MYPCSC_DWORD dwActiveProtocol;
774 PMEM_HANDLE lcHandle = NULL;
775
776 in->p += 0x1C;
777 in_uint32_le(in, dwShareMode);
778 in_uint32_le(in, dwPreferredProtocol);
779 DEBUG_SCARD(("[SHARE %8x]\n", (unsigned int) dwShareMode));
780 DEBUG_SCARD(("[PROTO %8x]\n", (unsigned int) dwPreferredProtocol));
781 inReaderName(&lcHandle, in, &szReader, wide);
782 DEBUG_SCARD(("[CONNECT TO READER \"%s\"\n", (szReader != NULL) ? (szReader) : ("NULL")));
783 in->p += 0x04;
784 in_uint32_le(in, hContext);
785 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
786 rv = SCardConnect(hContext, szReader, (MYPCSC_DWORD) dwShareMode,
787 (MYPCSC_DWORD) dwPreferredProtocol, &myHCard, &dwActiveProtocol);
788 hCard = scHandleToServer(myHCard);
789 DEBUG_SCARD(("[RECEIVED HCARD 0x%016lx]\n", (unsigned long) myHCard));
790 DEBUG_SCARD(("[MANGLED HCARD 0x%08x]\n", hCard));
791 if (rv != SCARD_S_SUCCESS)
792 {
793 DEBUG_SCARD(("<--ERROR SCardConnect Code=0x%.8x, %s-->\n", (unsigned int) rv,
794 pcsc_stringify_error(rv)));
795 }
796 else
797 {
798 char *szVendor = getVendor(szReader);
799 DEBUG_SCARD(("<--SUCCESS ScardConnect-->\n"));
800 if (szVendor && (strlen(szVendor) > 0))
801 {
802 DEBUG_SCARD(("Set Attribute ATTR_VENDOR_NAME\n"));
803 pthread_mutex_lock(&hcardAccess);
804 PSCHCardRec hcard = xmalloc(sizeof(TSCHCardRec));
805 if (hcard)
806 {
807 hcard->hCard = hCard;
808 hcard->vendor = szVendor;
809 hcard->next = NULL;
810 hcard->prev = NULL;
811
812 if (hcardFirst)
813 {
814 hcardFirst->prev = hcard;
815 hcard->next = hcardFirst;
816 }
817 hcardFirst = hcard;
818 }
819 pthread_mutex_unlock(&hcardAccess);
820 }
821 }
822
823 out_uint32_le(out, 0x00000000);
824 out_uint32_le(out, 0x00000000);
825 out_uint32_le(out, 0x00000004);
826 out_uint32_le(out, 0x016Cff34);
827 /* if the active protocol > 4 billion, this is trouble. odds are low */
828 out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
829 out_uint32_le(out, 0x00000004);
830 out_uint32_le(out, hCard);
831
832 outForceAlignment(out, 8);
833 SC_xfreeallmemory(&lcHandle);
834 return rv;
835 }
836
837 static MYPCSC_DWORD
838 TS_SCardReconnect(STREAM in, STREAM out)
839 {
840 MYPCSC_DWORD rv;
841 SCARDCONTEXT hContext;
842 SERVER_SCARDHANDLE hCard;
843 MYPCSC_SCARDHANDLE myHCard;
844 SERVER_DWORD dwShareMode;
845 SERVER_DWORD dwPreferredProtocol;
846 SERVER_DWORD dwInitialization;
847 MYPCSC_DWORD dwActiveProtocol;
848
849 in->p += 0x20;
850 in_uint32_le(in, dwShareMode);
851 in_uint32_le(in, dwPreferredProtocol);
852 in_uint32_le(in, dwInitialization);
853 in->p += 0x04;
854 in_uint32_le(in, hContext);
855 in->p += 0x04;
856 in_uint32_le(in, hCard);
857 myHCard = scHandleToMyPCSC(hCard);
858 DEBUG_SCARD(("[SHARE = 0x%.8x]\n", (unsigned int) dwShareMode));
859 DEBUG_SCARD(("[PROTO = 0x%.8x]\n", (unsigned int) dwPreferredProtocol));
860 DEBUG_SCARD(("[INIT = 0x%.8x]\n", (unsigned int) dwInitialization));
861 DEBUG_SCARD(("[hContext = 0x%.8x]\n", (unsigned int) hContext));
862 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
863 DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
864 rv = SCardReconnect(myHCard, (MYPCSC_DWORD) dwShareMode, (MYPCSC_DWORD) dwPreferredProtocol,
865 (MYPCSC_DWORD) dwInitialization, &dwActiveProtocol);
866 if (rv != SCARD_S_SUCCESS)
867 {
868 DEBUG_SCARD(("<--ERROR SCardReconnect Code=0x%.8x, %s-->\n", (unsigned int) rv,
869 pcsc_stringify_error(rv)));
870 }
871 else
872 {
873 DEBUG_SCARD(("<--SUCCESS SCardReconnect-->\n"));
874 }
875
876 outForceAlignment(out, 8);
877 out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
878 return rv;
879 }
880
881 static MYPCSC_DWORD
882 TS_SCardDisconnect(STREAM in, STREAM out)
883 {
884 MYPCSC_DWORD rv;
885 SERVER_SCARDCONTEXT hContext;
886 SERVER_SCARDHANDLE hCard;
887 MYPCSC_SCARDHANDLE myHCard;
888 SERVER_DWORD dwDisposition;
889
890 in->p += 0x20;
891 in_uint32_le(in, dwDisposition);
892 in->p += 0x04;
893 in_uint32_le(in, hContext);
894 in->p += 0x04;
895 in_uint32_le(in, hCard);
896
897 DEBUG_SCARD(("[hContext = 0x%.8x]\n", (unsigned int) hContext));
898 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
899 DEBUG_SCARD(("[dwDisposition = 0x%.8x]\n", (unsigned int) dwDisposition));
900
901 pthread_mutex_lock(&hcardAccess);
902 PSCHCardRec hcard = hcardFirst;
903 while (hcard)
904 {
905 if (hcard->hCard == hCard)
906 {
907 if (hcard->prev)
908 hcard->prev->next = hcard->next;
909 if (hcard->next)
910 hcard->next->prev = hcard->prev;
911 if (hcardFirst == hcard)
912 hcardFirst = hcard->next;
913 xfree(hcard);
914 break;
915 }
916 hcard = hcard->next;
917 }
918 pthread_mutex_unlock(&hcardAccess);
919
920 myHCard = scHandleToMyPCSC(hCard);
921 rv = SCardDisconnect(myHCard, (MYPCSC_DWORD) dwDisposition);
922
923 if (rv != SCARD_S_SUCCESS)
924 {
925 DEBUG_SCARD(("<--ERROR SCardDisconnect Code=0x%.8x, %s-->\n", (unsigned int) rv,
926 pcsc_stringify_error(rv)));
927 }
928 else
929 {
930 DEBUG_SCARD(("<--SUCCESS SCardDisconnect-->\n"));
931 }
932
933 outForceAlignment(out, 8);
934 return rv;
935 }
936
937 static int
938 needStatusRecheck(MYPCSC_DWORD rv, MYPCSC_LPSCARD_READERSTATE_A rsArray, SERVER_DWORD dwCount)
939 {
940 int i, recall = 0;
941 if (rv == SCARD_S_SUCCESS)
942 {
943 MYPCSC_LPSCARD_READERSTATE_A cur;
944 for (i = 0, cur = rsArray; i < dwCount; i++, cur++)
945 {
946 if (cur->dwEventState & SCARD_STATE_UNKNOWN)
947 {
948 cur->dwCurrentState = cur->dwEventState;
949 recall++;
950 }
951 }
952 }
953 return recall;
954 }
955
956 static RD_BOOL
957 mappedStatus(MYPCSC_DWORD code)
958 {
959 code >>= 16;
960 code &= 0x0000FFFF;
961 return (code % 2);
962 }
963
964 static MYPCSC_DWORD
965 incStatus(MYPCSC_DWORD code, RD_BOOL mapped)
966 {
967 if (mapped || (code & SCARD_STATE_CHANGED))
968 {
969 MYPCSC_DWORD count = (code >> 16) & 0x0000FFFF;
970 count++;
971 if (mapped && !(count % 2))
972 count++;
973 return (code & 0x0000FFFF) | (count << 16);
974 }
975 else
976 return code;
977 }
978
979 static void
980 copyReaderState_MyPCSCToServer(MYPCSC_LPSCARD_READERSTATE_A src, SERVER_LPSCARD_READERSTATE_A dst,
981 MYPCSC_DWORD readerCount)
982 {
983 MYPCSC_LPSCARD_READERSTATE_A srcIter;
984 SERVER_LPSCARD_READERSTATE_A dstIter;
985 MYPCSC_DWORD i;
986
987 for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
988 {
989 dstIter->szReader = srcIter->szReader;
990 dstIter->pvUserData = srcIter->pvUserData;
991 dstIter->dwCurrentState = srcIter->dwCurrentState;
992 dstIter->dwEventState = srcIter->dwEventState;
993 dstIter->cbAtr = srcIter->cbAtr;
994 memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
995 }
996 }
997
998 static void
999 copyReaderState_ServerToMyPCSC(SERVER_LPSCARD_READERSTATE_A src, MYPCSC_LPSCARD_READERSTATE_A dst,
1000 SERVER_DWORD readerCount)
1001 {
1002 SERVER_LPSCARD_READERSTATE_A srcIter;
1003 MYPCSC_LPSCARD_READERSTATE_A dstIter;
1004 SERVER_DWORD i;
1005
1006 for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
1007 {
1008 dstIter->szReader = srcIter->szReader;
1009 dstIter->pvUserData = srcIter->pvUserData;
1010 dstIter->dwCurrentState = srcIter->dwCurrentState;
1011 dstIter->dwEventState = srcIter->dwEventState;
1012 dstIter->cbAtr = srcIter->cbAtr;
1013 memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
1014 }
1015 }
1016
1017
1018 static MYPCSC_DWORD
1019 TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
1020 {
1021 MYPCSC_DWORD rv;
1022 SERVER_SCARDCONTEXT hContext;
1023 SERVER_DWORD dwTimeout;
1024 SERVER_DWORD dwCount;
1025 SERVER_LPSCARD_READERSTATE_A rsArray, cur;
1026 SERVER_DWORD *stateArray = NULL, *curState;
1027 MYPCSC_LPSCARD_READERSTATE_A myRsArray;
1028 long i;
1029 PMEM_HANDLE lcHandle = NULL;
1030 #if 0
1031 RD_BOOL mapped = False;
1032 #endif
1033
1034 in->p += 0x18;
1035 in_uint32_le(in, dwTimeout);
1036 in_uint32_le(in, dwCount);
1037 in->p += 0x08;
1038 in_uint32_le(in, hContext);
1039 in->p += 0x04;
1040
1041 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
1042 DEBUG_SCARD(("[dwTimeout 0x%.8x]\n", (unsigned int) dwTimeout));
1043 DEBUG_SCARD(("[COUNT %d]\n", (unsigned int) dwCount));
1044 DEBUG_SCARD(("[TYPE SIZE %d]\n", (unsigned int) sizeof(SERVER_SCARD_READERSTATE_A)));
1045
1046 if (dwCount > 0)
1047 {
1048 rsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1049 if (!rsArray)
1050 return SC_returnNoMemoryError(&lcHandle, in, out);
1051 memset(rsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1052 stateArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_DWORD));
1053 if (!stateArray)
1054 return SC_returnNoMemoryError(&lcHandle, in, out);
1055 /* skip two pointers at beginning of struct */
1056 for (i = 0, cur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
1057 i < dwCount; i++, cur++)
1058 {
1059 in->p += 0x04;
1060 in_uint8a(in, cur, SERVER_SCARDSTATESIZE);
1061 }
1062 #ifdef WITH_DEBUG_SCARD
1063 DEBUG_SCARD(("[READERS DUMP 1]------------------\n"));
1064 hexdump((void *) rsArray, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1065 #endif
1066
1067
1068 for (i = 0, cur = rsArray, curState = stateArray;
1069 i < dwCount; i++, cur++, curState++)
1070 {
1071 SERVER_DWORD dataLength;
1072
1073 /* reset Current state hign bytes; */
1074 *curState = cur->dwCurrentState;
1075 cur->dwCurrentState &= 0x0000FFFF;
1076 cur->dwEventState &= 0x0000FFFF;
1077
1078 #if 0
1079 if (cur->dwCurrentState == (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT))
1080 {
1081 cur->dwCurrentState = 0x00000000;
1082 mapped = True;
1083 }
1084
1085 if (mappedStatus(*curState))
1086 {
1087 cur->dwCurrentState &= ~SCARD_STATE_INUSE;
1088 cur->dwEventState &= ~SCARD_STATE_INUSE;
1089
1090 if (cur->dwCurrentState & SCARD_STATE_EMPTY)
1091 {
1092 cur->dwCurrentState &= ~SCARD_STATE_EMPTY;
1093 cur->dwCurrentState |= SCARD_STATE_UNKNOWN;
1094 }
1095 }
1096 #endif
1097
1098 in->p += 0x08;
1099 in_uint32_le(in, dataLength);
1100 DEBUG_SCARD(("[%d] Data Length %d]\n", (unsigned int) i, dataLength));
1101 inRepos(in,
1102 inString(&lcHandle, in, (char **) &(cur->szReader), dataLength,
1103 wide));
1104
1105 if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0)
1106 cur->dwCurrentState |= SCARD_STATE_IGNORE;
1107 }
1108 #ifdef WITH_DEBUG_SCARD
1109 DEBUG_SCARD(("[READERS DUMP 2]------------------\n"));
1110 hexdump((void *) rsArray, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1111 #endif
1112 }
1113 else
1114 {
1115 rsArray = NULL;
1116 stateArray = NULL;
1117 }
1118
1119 DEBUG_SCARD(("\nCalling SCardGetStatusChange...\n"));
1120
1121
1122 myRsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
1123 if (!rsArray)
1124 return SC_returnNoMemoryError(&lcHandle, in, out);
1125 memset(myRsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1126 copyReaderState_ServerToMyPCSC(rsArray, myRsArray, (SERVER_DWORD) dwCount);
1127 #ifdef WITH_DEBUG_SCARD
1128 DEBUG_SCARD(("[TRANSLATION OF READERS]--------------------\n"));
1129 hexdump((void *) myRsArray, dwCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
1130 #endif
1131
1132 rv = SCardGetStatusChange((MYPCSC_SCARDCONTEXT) hContext, (MYPCSC_DWORD) dwTimeout,
1133 myRsArray, (MYPCSC_DWORD) dwCount);
1134 copyReaderState_MyPCSCToServer(myRsArray, rsArray, (MYPCSC_DWORD) dwCount);
1135
1136 if (rv != SCARD_S_SUCCESS)
1137 {
1138 DEBUG_SCARD(("<--ERROR SCardGetStatusChange Code=0x%.8x, %s-->\n",
1139 (unsigned int) rv, pcsc_stringify_error(rv)));
1140 }
1141 else
1142 {
1143 DEBUG_SCARD(("<--SUCCESS SCardGetStatusChange-->\n"));
1144 }
1145
1146 #ifdef WITH_DEBUG_SCARD
1147 if (dwCount > 0)
1148 {
1149 DEBUG_SCARD(("[READERS DUMP]------------------\n"));
1150 hexdump((void *) rsArray, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
1151 }
1152 #endif
1153
1154 out_uint32_le(out, dwCount);
1155 out_uint32_le(out, 0x00084dd8);
1156 out_uint32_le(out, dwCount);
1157
1158 for (i = 0, cur = rsArray, curState = stateArray; i < dwCount; i++, cur++, curState++)
1159 {
1160
1161 cur->dwCurrentState = (*curState);
1162 cur->dwEventState |= (*curState) & 0xFFFF0000;
1163
1164 #if 0
1165 if (mapped && (cur->dwCurrentState & SCARD_STATE_PRESENT)
1166 && (cur->dwCurrentState & SCARD_STATE_CHANGED)
1167 && (cur->dwEventState & SCARD_STATE_PRESENT)
1168 && (cur->dwEventState & SCARD_STATE_CHANGED))
1169 {
1170 cur->dwEventState |= SCARD_STATE_INUSE;
1171 }
1172 else if (cur->dwEventState & SCARD_STATE_UNKNOWN)
1173 {
1174 cur->dwEventState &= ~SCARD_STATE_UNKNOWN;
1175 cur->dwEventState |= SCARD_STATE_EMPTY;
1176 mapped = True;
1177 }
1178 else if ((!mapped) && (cur->dwEventState & SCARD_STATE_INUSE))
1179 {
1180 mapped = True;
1181 cur->dwEventState &= ~SCARD_STATE_INUSE;
1182 }
1183
1184 cur->dwEventState = incStatus(cur->dwEventState, mapped);
1185 #endif
1186 cur->dwEventState = incStatus(cur->dwEventState, False);
1187
1188 out_uint8p(out, (void *) ((unsigned char **) cur + 2),
1189 sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
1190 }
1191 outForceAlignment(out, 8);
1192 SC_xfreeallmemory(&lcHandle);
1193 return rv;
1194 }
1195
1196 static MYPCSC_DWORD
1197 TS_SCardCancel(STREAM in, STREAM out)
1198 {
1199 MYPCSC_DWORD rv;
1200 SERVER_SCARDCONTEXT hContext;
1201
1202 in->p += 0x1C;
1203 in_uint32_le(in, hContext);
1204 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
1205 DEBUG_SCARD(("Canceling... \n"));
1206 rv = SCardCancel((MYPCSC_SCARDCONTEXT) hContext);
1207 if (rv != SCARD_S_SUCCESS)
1208 {
1209 DEBUG_SCARD(("<--ERROR SCardCancel Code=0x%.8x, %s-->\n", (unsigned int) rv,
1210 pcsc_stringify_error(rv)));
1211 }
1212 else
1213 {
1214 DEBUG_SCARD(("<--SUCCESS SCardCancel-->\n"));
1215 }
1216 outForceAlignment(out, 8);
1217 return rv;
1218 }
1219
1220 static MYPCSC_DWORD
1221 TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
1222 {
1223 int i, j, k;
1224 MYPCSC_DWORD rv;
1225 SERVER_SCARDCONTEXT hContext;
1226 /* The SCARD_ATRMASK_L struct doesn't contain any longs or DWORDs -
1227 no need to split into SERVER_ and MYPCSC_ */
1228 LPSCARD_ATRMASK_L pAtrMasks, cur;
1229 SERVER_DWORD atrMaskCount = 0;
1230 SERVER_DWORD readerCount = 0;
1231 SERVER_LPSCARD_READERSTATE_A rsArray, ResArray, rsCur;
1232 MYPCSC_LPSCARD_READERSTATE_A myRsArray;
1233 PMEM_HANDLE lcHandle = NULL;
1234
1235 in->p += 0x2C;
1236 in_uint32_le(in, hContext);
1237 DEBUG_SCARD(("[CONTEXT 0x%.8x]\n", (unsigned int) hContext));
1238 in_uint32_le(in, atrMaskCount);
1239 pAtrMasks = SC_xmalloc(&lcHandle, atrMaskCount * sizeof(SCARD_ATRMASK_L));
1240 if (!pAtrMasks)
1241 return SC_returnNoMemoryError(&lcHandle, in, out);
1242 in_uint8a(in, pAtrMasks, atrMaskCount * sizeof(SCARD_ATRMASK_L));
1243
1244 in_uint32_le(in, readerCount);
1245 rsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SCARD_READERSTATE_A));
1246 if (!rsArray)
1247 return SC_returnNoMemoryError(&lcHandle, in, out);
1248 memset(rsArray, 0, readerCount * sizeof(SCARD_READERSTATE_A));
1249
1250 for (i = 0, rsCur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
1251 i < readerCount; i++, rsCur++)
1252 {
1253 in_uint8s(in, 4);
1254 in_uint8a(in, rsCur, SERVER_SCARDSTATESIZE);
1255 }
1256
1257 ResArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
1258 if (!ResArray)
1259 return SC_returnNoMemoryError(&lcHandle, in, out);
1260 memcpy(ResArray, rsArray, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
1261
1262 for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
1263 {
1264 inReaderName(&lcHandle, in, (char **) &rsCur->szReader, wide);
1265 DEBUG_SCARD(("[CHECK READER %s]\n",
1266 (rsCur->szReader) ? (rsCur->szReader) : ("NULL")));
1267 }
1268
1269 DEBUG_SCARD(("[CALL subfunction \"SCardGetStatusChange\"]\n"));
1270 /* FIXME segfault here. */
1271 myRsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
1272 if (!myRsArray)
1273 return SC_returnNoMemoryError(&lcHandle, in, out);
1274 rv = SCardGetStatusChange((MYPCSC_SCARDCONTEXT) hContext, 0x00000001, myRsArray,
1275 readerCount);
1276 copyReaderState_MyPCSCToServer(myRsArray, rsArray, readerCount);
1277 if (rv != SCARD_S_SUCCESS)
1278 {
1279 DEBUG_SCARD(("<--ERROR SCardGetStatusChange (no SCardLocateCardsByATR) Code=0x%.8x, %s-->\n", (unsigned int) rv, pcsc_stringify_error(rv)));
1280 }
1281 else
1282 {
1283 DEBUG_SCARD(("<--SUCCESS SCardGetStatusChange (no SCardLocateCardsByATR)-->\n"));
1284 cur = pAtrMasks;
1285 for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++)
1286 {
1287 for (j = 0, rsCur = rsArray; j < readerCount; j++, rsCur++)
1288 {
1289 RD_BOOL equal = 1;
1290 for (k = 0; k < cur->cbAtr; k++)
1291 {
1292 /* This line check if them equal */
1293 if (cur->rgbAtr[k] != rsCur->rgbAtr[k])
1294 /* Next Line was make to search with mask (some strange behavours with applications which use eToken SmartCards) */
1295 /* if((cur->rgbAtr[k]&cur->rgbMask[k])!=(rsCur->rgbAtr[k]&cur->rgbMask[k])){ */
1296 {
1297 equal = 0;
1298 break;
1299 }
1300 }
1301 if (equal)
1302 {
1303 DEBUG_SCARD(("[FOUND]\n"));
1304 rsCur->dwEventState |= 0x00000040; /* SCARD_STATE_ATRMATCH 0x00000040 */
1305 memcpy(ResArray + j, rsCur, sizeof(SCARD_READERSTATE_A));
1306 }
1307 }
1308 }
1309 }
1310
1311 out_uint32_le(out, readerCount);
1312 out_uint32_le(out, 0x00084dd8);
1313 out_uint32_le(out, readerCount);
1314
1315 for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
1316 {
1317 out_uint8p(out, (void *) ((unsigned char **) rsCur + 2),
1318 sizeof(SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
1319 }
1320
1321 outForceAlignment(out, 8);
1322 SC_xfreeallmemory(&lcHandle);
1323 return rv;
1324 }
1325
1326 static DWORD
1327 TS_SCardBeginTransaction(STREAM in, STREAM out)
1328 {
1329 MYPCSC_DWORD rv;
1330 SERVER_SCARDCONTEXT hCard;
1331 MYPCSC_SCARDCONTEXT myHCard;
1332
1333 in->p += 0x30;
1334 in_uint32_le(in, hCard);
1335 myHCard = scHandleToMyPCSC(hCard);
1336 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
1337 DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
1338 rv = SCardBeginTransaction(myHCard);
1339 if (rv != SCARD_S_SUCCESS)
1340 {
1341 DEBUG_SCARD(("<--ERROR SCardBeginTransaction Code=0x%.8x, %s-->\n",
1342 (unsigned int) rv, pcsc_stringify_error(rv)));
1343 }
1344 else
1345 {
1346 DEBUG_SCARD(("<--SUCCESS SCardBeginTransaction-->\n"));
1347 }
1348 outForceAlignment(out, 8);
1349 return rv;
1350 }
1351
1352 static DWORD
1353 TS_SCardEndTransaction(STREAM in, STREAM out)
1354 {
1355 MYPCSC_DWORD rv;
1356 SERVER_SCARDCONTEXT hCard;
1357 MYPCSC_SCARDCONTEXT myHCard;
1358 SERVER_DWORD dwDisposition = 0;
1359
1360 in->p += 0x20;
1361 in_uint32_le(in, dwDisposition);
1362 in->p += 0x0C;
1363 in_uint32_le(in, hCard);
1364 myHCard = scHandleToMyPCSC(hCard);
1365
1366 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
1367 DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
1368 DEBUG_SCARD(("[dwDisposition = 0x%.8x]\n", (unsigned int) dwDisposition));
1369
1370 rv = SCardEndTransaction(myHCard, (MYPCSC_DWORD) dwDisposition);
1371 if (rv != SCARD_S_SUCCESS)
1372 {
1373 DEBUG_SCARD(("<--ERROR SCardEndTransaction Code=0x%.8x, %s-->\n", (unsigned int) rv,
1374 pcsc_stringify_error(rv)));
1375 }
1376 else
1377 {
1378 DEBUG_SCARD(("<--SUCCESS SCardEndTransaction-->\n"));
1379 }
1380 outForceAlignment(out, 8);
1381 return rv;
1382 }
1383
1384
1385 static void
1386 copyIORequest_MyPCSCToServer(MYPCSC_LPSCARD_IO_REQUEST src, SERVER_LPSCARD_IO_REQUEST dst)
1387 {
1388 unsigned char *srcBytes, *dstBytes;
1389 size_t bytesToCopy = src->cbPciLength - sizeof(MYPCSC_SCARD_IO_REQUEST);
1390 srcBytes = ((unsigned char *) src + sizeof(MYPCSC_SCARD_IO_REQUEST));
1391 dstBytes = ((unsigned char *) dst + sizeof(SERVER_SCARD_IO_REQUEST));
1392 dst->dwProtocol = src->dwProtocol;
1393 dst->cbPciLength = src->cbPciLength
1394 - sizeof(MYPCSC_SCARD_IO_REQUEST) + sizeof(SERVER_SCARD_IO_REQUEST);
1395 memcpy(dstBytes, srcBytes, bytesToCopy);
1396 }
1397
1398 static void
1399 copyIORequest_ServerToMyPCSC(SERVER_LPSCARD_IO_REQUEST src, MYPCSC_LPSCARD_IO_REQUEST dst)
1400 {
1401 unsigned char *srcBytes, *dstBytes;
1402 size_t bytesToCopy = src->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST);
1403 srcBytes = ((unsigned char *) src + sizeof(SERVER_SCARD_IO_REQUEST));
1404 dstBytes = ((unsigned char *) dst + sizeof(MYPCSC_SCARD_IO_REQUEST));
1405 dst->dwProtocol = src->dwProtocol;
1406 dst->cbPciLength = src->cbPciLength
1407 - sizeof(SERVER_SCARD_IO_REQUEST) + sizeof(MYPCSC_SCARD_IO_REQUEST);
1408 memcpy(dstBytes, srcBytes, bytesToCopy);
1409 }
1410
1411
1412 static DWORD
1413 TS_SCardTransmit(STREAM in, STREAM out)
1414 {
1415 MYPCSC_DWORD rv;
1416 SERVER_DWORD map[7], linkedLen;
1417 void *tmp;
1418 SERVER_SCARDCONTEXT hCard;
1419 MYPCSC_SCARDCONTEXT myHCard;
1420 SERVER_LPSCARD_IO_REQUEST pioSendPci, pioRecvPci;
1421 MYPCSC_LPSCARD_IO_REQUEST myPioSendPci, myPioRecvPci;
1422 unsigned char *sendBuf = NULL, *recvBuf = NULL;
1423 SERVER_DWORD cbSendLength, cbRecvLength;
1424 MYPCSC_DWORD myCbRecvLength;
1425 PMEM_HANDLE lcHandle = NULL;
1426
1427 in->p += 0x14;
1428 in_uint32_le(in, map[0]);
1429 in->p += 0x04;
1430 in_uint32_le(in, map[1]);
1431 pioSendPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
1432 if (!pioSendPci)
1433 return SC_returnNoMemoryError(&lcHandle, in, out);
1434 in_uint8a(in, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
1435 in_uint32_le(in, map[2]);
1436 in_uint32_le(in, cbSendLength);
1437 in_uint32_le(in, map[3]);
1438 in_uint32_le(in, map[4]);
1439 in_uint32_le(in, map[5]);
1440 in_uint32_le(in, cbRecvLength);
1441 if (map[0] & INPUT_LINKED)
1442 inSkipLinked(in);
1443
1444 in->p += 0x04;
1445 in_uint32_le(in, hCard);
1446 myHCard = scHandleToMyPCSC(hCard);
1447
1448 if (map[2] & INPUT_LINKED)
1449 {
1450 in_uint32_le(in, linkedLen);
1451 pioSendPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
1452 tmp = SC_xmalloc(&lcHandle, pioSendPci->cbPciLength);
1453 if (!tmp)
1454 return SC_returnNoMemoryError(&lcHandle, in, out);
1455 in_uint8a(in, (void *) ((unsigned char *) tmp + sizeof(SERVER_SCARD_IO_REQUEST)),
1456 linkedLen);
1457 memcpy(tmp, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
1458 SC_xfree(&lcHandle, pioSendPci);
1459 pioSendPci = tmp;
1460 tmp = NULL;
1461 }
1462 else
1463 pioSendPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
1464
1465 if (map[3] & INPUT_LINKED)
1466 {
1467 in_uint32_le(in, linkedLen);
1468 sendBuf = SC_xmalloc(&lcHandle, linkedLen);
1469 if (!sendBuf)
1470 return SC_returnNoMemoryError(&lcHandle, in, out);
1471 in_uint8a(in, sendBuf, linkedLen);
1472 inRepos(in, linkedLen);
1473 }
1474 else
1475 sendBuf = NULL;
1476
1477 if (cbRecvLength)
1478 {
1479 recvBuf = SC_xmalloc(&lcHandle, cbRecvLength);
1480 if (!recvBuf)
1481 return SC_returnNoMemoryError(&lcHandle, in, out);
1482 }
1483
1484 if (map[4] & INPUT_LINKED)
1485 {
1486 pioRecvPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
1487 if (!pioRecvPci)
1488 return SC_returnNoMemoryError(&lcHandle, in, out);
1489 in_uint8a(in, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
1490 in_uint32_le(in, map[6]);
1491 if (map[6] & INPUT_LINKED)
1492 {
1493 in_uint32_le(in, linkedLen);
1494 pioRecvPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
1495 tmp = SC_xmalloc(&lcHandle, pioRecvPci->cbPciLength);
1496 if (!tmp)
1497 return SC_returnNoMemoryError(&lcHandle, in, out);
1498 in_uint8a(in,
1499 (void *) ((unsigned char *) tmp +
1500 sizeof(SERVER_SCARD_IO_REQUEST)), linkedLen);
1501 memcpy(tmp, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
1502 SC_xfree(&lcHandle, pioRecvPci);
1503 pioRecvPci = tmp;
1504 tmp = NULL;
1505 }
1506 else
1507 pioRecvPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
1508 }
1509 else
1510 pioRecvPci = NULL;
1511
1512 #ifdef WITH_DEBUG_SCARD
1513 DEBUG_SCARD(("++++++++++\n"));
1514 DEBUG_SCARD(("[SEND LEN = %d]\n", (unsigned int) cbSendLength));
1515 DEBUG_SCARD(("[RECV LEN = %d]\n", (unsigned int) cbRecvLength));
1516 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
1517 DEBUG_SCARD(("[myHCard = 0x%016lx]\n", (unsigned long) myHCard));
1518 DEBUG_SCARD(("[pioSendPci]\n"));
1519 if (pioSendPci == NULL)
1520 {
1521 DEBUG_SCARD(("NULL\n"));
1522 }
1523 else
1524 {
1525 hexdump((void *) pioSendPci, pioSendPci->cbPciLength);
1526 }
1527
1528 DEBUG_SCARD(("[pioRecvPci]\n"));
1529 if (pioRecvPci == NULL)
1530 {
1531 DEBUG_SCARD(("NULL\n"));
1532 }
1533 else
1534 {
1535 hexdump((void *) pioRecvPci, pioRecvPci->cbPciLength);
1536 }
1537 DEBUG_SCARD(("[sendBuf]\n"));
1538 hexdump(sendBuf, cbSendLength);
1539 DEBUG_SCARD(("++++++++++\n"));
1540 #endif
1541
1542 myCbRecvLength = cbRecvLength;
1543 myPioSendPci = SC_xmalloc(&lcHandle,
1544 sizeof(MYPCSC_SCARD_IO_REQUEST)
1545 + pioSendPci->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST));
1546 if (!myPioSendPci)
1547 return SC_returnNoMemoryError(&lcHandle, in, out);
1548 copyIORequest_ServerToMyPCSC(pioSendPci, myPioSendPci);
1549 /* always a send, not always a recv */
1550 if (pioRecvPci)
1551 {
1552 myPioRecvPci = SC_xmalloc(&lcHandle,
1553 sizeof(MYPCSC_SCARD_IO_REQUEST)
1554 + pioRecvPci->cbPciLength
1555 - sizeof(SERVER_SCARD_IO_REQUEST));
1556 if (!myPioRecvPci)
1557 return SC_returnNoMemoryError(&lcHandle, in, out);
1558 copyIORequest_ServerToMyPCSC(pioRecvPci, myPioRecvPci);
1559 }
1560 else
1561 {
1562 myPioRecvPci = NULL;
1563 }
1564 rv = SCardTransmit(myHCard, myPioSendPci, sendBuf, (MYPCSC_DWORD) cbSendLength,
1565 myPioRecvPci, recvBuf, &myCbRecvLength);
1566 cbRecvLength = myCbRecvLength;
1567
1568 /* FIXME: handle responses with length > 448 bytes */
1569 if (cbRecvLength > 448)
1570 {
1571 warning("Card response limited from %d to 448 bytes!\n", cbRecvLength);
1572 DEBUG_SCARD(("[RECV LEN %d -> %d]\n", (unsigned int) cbRecvLength, 400));
1573 cbRecvLength = 448;
1574 }
1575
1576 if (pioRecvPci)
1577 {
1578 copyIORequest_MyPCSCToServer(myPioRecvPci, pioRecvPci);
1579 }
1580
1581 if (rv != SCARD_S_SUCCESS)
1582 {
1583 DEBUG_SCARD(("<--ERROR SCardTransmit Code=0x%.8x, %s-->\n", (unsigned int) rv,
1584 pcsc_stringify_error(rv)));
1585 }
1586 else
1587 {
1588 #ifdef WITH_DEBUG_SCARD
1589 DEBUG_SCARD(("<--SUCCESS SCardTransmit-->\n"));
1590 DEBUG_SCARD(("RESULT %d\n", (unsigned int) cbRecvLength));
1591 hexdump(recvBuf, cbRecvLength);
1592 if (myPioRecvPci)
1593 {
1594 DEBUG_SCARD(("--- myPioRecvPci ---\n"));
1595 hexdump((void *) myPioRecvPci, myPioRecvPci->cbPciLength);
1596 }
1597 DEBUG_SCARD(("------------------\n"));
1598 #endif
1599 #if 0
1600 if ((pioRecvPci != NULL) && (pioRecvPci->cbPciLength > 0))
1601 {
1602 out_uint32_le(out, (DWORD) pioRecvPci); /* if not NULL, this 4 bytes indicates that pioRecvPci is present */
1603 }
1604 else
1605 #endif
1606 out_uint32_le(out, 0); /* pioRecvPci 0x00; */
1607
1608 outBufferStart(out, cbRecvLength); /* start of recvBuf output */
1609
1610 #if 0
1611 if ((pioRecvPci) && (pioRecvPci->cbPciLength > 0))
1612 {
1613 out_uint32_le(out, pioRecvPci->dwProtocol);
1614 int len = pioRecvPci->cbPciLength - sizeof(pioRecvPci);
1615 outBufferStartWithLimit(out, len, 12);
1616 outBufferFinishWithLimit(out,
1617 (char *) ((DWORD) pioRecvPci + sizeof(pioRecvPci)),
1618 len, 12);
1619 }
1620 #endif
1621
1622 outBufferFinish(out, (char *) recvBuf, cbRecvLength);
1623 }
1624 outForceAlignment(out, 8);
1625 SC_xfreeallmemory(&lcHandle);
1626 return rv;
1627 }
1628
1629 static MYPCSC_DWORD
1630 TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
1631 {
1632 MYPCSC_DWORD rv;
1633 SERVER_SCARDCONTEXT hCard;
1634 MYPCSC_SCARDCONTEXT myHCard;
1635 SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
1636 MYPCSC_DWORD state, protocol, readerLen, atrLen;
1637 SERVER_DWORD dataLength;
1638 PMEM_HANDLE lcHandle = NULL;
1639 char *readerName;
1640 unsigned char *atr;
1641
1642 in->p += 0x24;
1643 in_uint32_le(in, dwReaderLen);
1644 in_uint32_le(in, dwAtrLen);
1645 in->p += 0x0C;
1646 in_uint32_le(in, hCard);
1647 in->p += 0x04;
1648 myHCard = scHandleToMyPCSC(hCard);
1649
1650 DEBUG_SCARD(("[hCard 0x%.8x]\n", (unsigned int) hCard));
1651 DEBUG_SCARD(("[myHCard 0x%016lx]\n", (unsigned long) myHCard));
1652 DEBUG_SCARD(("[dwReaderLen %d]\n", (unsigned int) dwReaderLen));
1653 DEBUG_SCARD(("[dwAtrLen %d]\n", (unsigned int) dwAtrLen));
1654
1655 if (dwReaderLen <= 0 || dwReaderLen == SCARD_AUTOALLOCATE || dwReaderLen > SCARD_MAX_MEM)
1656 dwReaderLen = SCARD_MAX_MEM;
1657 if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
1658 dwAtrLen = SCARD_MAX_MEM;
1659
1660 readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
1661 if (!readerName)
1662 return SC_returnNoMemoryError(&lcHandle, in, out);
1663
1664 atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
1665 if (!atr)
1666 return SC_returnNoMemoryError(&lcHandle, in, out);
1667
1668 state = dwState;
1669 protocol = dwProtocol;
1670 readerLen = dwReaderLen;
1671 atrLen = dwAtrLen;
1672 rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
1673 dwAtrLen = atrLen;
1674 dwReaderLen = readerLen;
1675 dwProtocol = protocol;
1676 dwState = state;
1677
1678
1679 if (rv != SCARD_S_SUCCESS)
1680 {
1681 DEBUG_SCARD(("<--ERROR SCardStatus Code=0x%.8x, %s-->\n", (unsigned int) rv,
1682 pcsc_stringify_error(rv)));
1683 return SC_returnCode(rv, &lcHandle, in, out);
1684 }
1685 else
1686 {
1687 #ifdef WITH_DEBUG_SCARD
1688 DEBUG_SCARD(("<--SUCCESS SCardStatus-->\n"));
1689 DEBUG_SCARD(("[dwState 0x%.8x]\n", (unsigned int) dwState));
1690 DEBUG_SCARD(("[dwProtocol 0x%.8x]\n", (unsigned int) dwProtocol));
1691 DEBUG_SCARD(("[Reader Name]\n"));
1692 hexdump((unsigned char *) readerName, dwReaderLen);
1693 DEBUG_SCARD(("[Atr]\n"));
1694 hexdump(atr, dwAtrLen);
1695 #endif
1696 if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
1697 dwState = 0x00000006;
1698 else
1699 #if 0
1700 if (dwState & SCARD_SPECIFIC)
1701 dwState = 0x00000006;
1702 else if (dwState & SCARD_NEGOTIABLE)
1703 dwState = 0x00000005;
1704 else
1705 #endif
1706 if (dwState & SCARD_POWERED)
1707 dwState = 0x00000004;
1708 else if (dwState & SCARD_SWALLOWED)
1709 dwState = 0x00000003;
1710 else if (dwState & SCARD_PRESENT)
1711 dwState = 0x00000002;
1712 else if (dwState & SCARD_ABSENT)
1713 dwState = 0x00000001;
1714 else
1715 dwState = 0x00000000;
1716
1717 void *p_len1 = out->p;
1718 out_uint32_le(out, dwReaderLen);
1719 out_uint32_le(out, 0x00020000);
1720 out_uint32_le(out, dwState);
1721 out_uint32_le(out, dwProtocol);
1722 out_uint8p(out, atr, dwAtrLen);
1723 if (dwAtrLen < 32)
1724 {
1725 out_uint8s(out, 32 - dwAtrLen);
1726 }
1727 out_uint32_le(out, dwAtrLen);
1728
1729 void *p_len2 = out->p;
1730 out_uint32_le(out, dwReaderLen);
1731 dataLength = outString(out, readerName, wide);
1732 dataLength += outString(out, "\0", wide);
1733 outRepos(out, dataLength);
1734 void *psave = out->p;
1735 out->p = p_len1;
1736 out_uint32_le(out, dataLength);
1737 out->p = p_len2;
1738 out_uint32_le(out, dataLength);
1739 out->p = psave;
1740 }
1741 outForceAlignment(out, 8);
1742 SC_xfreeallmemory(&lcHandle);
1743 return rv;
1744 }
1745
1746 static MYPCSC_DWORD
1747 TS_SCardState(STREAM in, STREAM out)
1748 {
1749 MYPCSC_DWORD rv;
1750 SERVER_SCARDCONTEXT hCard;
1751 MYPCSC_SCARDCONTEXT myHCard;
1752 SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
1753 MYPCSC_DWORD state, protocol, readerLen, atrLen;
1754 PMEM_HANDLE lcHandle = NULL;
1755 char *readerName;
1756 unsigned char *atr;
1757
1758 in->p += 0x24;
1759 in_uint32_le(in, dwAtrLen);
1760 in->p += 0x0C;
1761 in_uint32_le(in, hCard);
1762 in->p += 0x04;
1763 myHCard = scHandleToMyPCSC(hCard);
1764
1765 DEBUG_SCARD(("[hCard 0x%.8x]\n", (unsigned int) hCard));
1766 DEBUG_SCARD(("[myHCard 0x%.8x]\n", (unsigned int) myHCard));
1767 DEBUG_SCARD(("[dwAtrLen %d]\n", (unsigned int) dwAtrLen));
1768
1769 dwReaderLen = SCARD_MAX_MEM;
1770 if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
1771 dwAtrLen = SCARD_MAX_MEM;
1772
1773 readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
1774 if (!readerName)
1775 return SC_returnNoMemoryError(&lcHandle, in, out);
1776
1777 atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
1778 if (!atr)
1779 return SC_returnNoMemoryError(&lcHandle, in, out);
1780
1781 state = dwState;
1782 protocol = dwProtocol;
1783 readerLen = dwReaderLen;
1784 atrLen = dwAtrLen;
1785 rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
1786 dwAtrLen = atrLen;
1787 dwReaderLen = readerLen;
1788 dwProtocol = protocol;
1789 dwState = state;
1790
1791 if (rv != SCARD_S_SUCCESS)
1792 {
1793 DEBUG_SCARD(("<--ERROR SCardStatus (no ScardState) Code=0x%.8x, %s-->\n",
1794 (unsigned int) rv, pcsc_stringify_error(rv)));
1795 return SC_returnCode(rv, &lcHandle, in, out);
1796 }
1797 else
1798 {
1799 #ifdef WITH_DEBUG_SCARD
1800 DEBUG_SCARD(("<--SUCCESS SCardStatus (no ScardState)-->\n"));
1801 DEBUG_SCARD(("[dwState 0x%.8x]\n", (unsigned int) dwState));
1802 DEBUG_SCARD(("[dwProtocol 0x%.8x]\n", (unsigned int) dwProtocol));
1803 DEBUG_SCARD(("[Atr]\n"));
1804 hexdump(atr, dwAtrLen);
1805 #endif
1806 if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
1807 dwState = 0x00000006;
1808 else
1809 #if 0
1810 if (dwState & SCARD_SPECIFIC)
1811 dwState = 0x00000006;
1812 else if (dwState & SCARD_NEGOTIABLE)
1813 dwState = 0x00000005;
1814 else
1815 #endif
1816 if (dwState & SCARD_POWERED)
1817 dwState = 0x00000004;
1818 else if (dwState & SCARD_SWALLOWED)
1819 dwState = 0x00000003;
1820 else if (dwState & SCARD_PRESENT)
1821 dwState = 0x00000002;
1822 else if (dwState & SCARD_ABSENT)
1823 dwState = 0x00000001;
1824 else
1825 dwState = 0x00000000;
1826
1827 out_uint32_le(out, dwState);
1828 out_uint32_le(out, dwProtocol);
1829 out_uint32_le(out, dwAtrLen);
1830 out_uint32_le(out, 0x00000001);
1831 out_uint32_le(out, dwAtrLen);
1832 out_uint8p(out, atr, dwAtrLen);
1833 outRepos(out, dwAtrLen);
1834 }
1835 outForceAlignment(out, 8);
1836 SC_xfreeallmemory(&lcHandle);
1837 return rv;
1838 }
1839
1840
1841
1842 #ifndef WITH_PCSC120
1843
1844 static MYPCSC_DWORD
1845 TS_SCardListReaderGroups(STREAM in, STREAM out)
1846 {
1847 MYPCSC_DWORD rv;
1848 SERVER_SCARDCONTEXT hContext;
1849 SERVER_DWORD dwGroups;
1850 MYPCSC_DWORD groups;
1851 char *szGroups;
1852 PMEM_HANDLE lcHandle = NULL;
1853
1854 in->p += 0x20;
1855 in_uint32_le(in, dwGroups);
1856 in->p += 0x04;
1857 in_uint32_le(in, hContext);
1858
1859 if (dwGroups <= 0 || dwGroups == SCARD_AUTOALLOCATE || dwGroups > SCARD_MAX_MEM)
1860 dwGroups = SCARD_MAX_MEM;
1861
1862 szGroups = SC_xmalloc(&lcHandle, dwGroups);
1863 if (!szGroups)
1864 return SC_returnNoMemoryError(&lcHandle, in, out);
1865
1866 groups = dwGroups;
1867 rv = SCardListReaderGroups((MYPCSC_SCARDCONTEXT) hContext, szGroups, &groups);
1868 dwGroups = groups;
1869
1870 if (rv)
1871 {
1872 DEBUG_SCARD(("<--ERROR SCardListReaderGroups Code=0x%.8x, %s-->\n",
1873 (unsigned int) rv, pcsc_stringify_error(rv)));
1874 return SC_returnCode(rv, &lcHandle, in, out);
1875 }
1876 else
1877 {
1878 DEBUG_SCARD(("<--SUCCESS SCardListReaderGroups-->\n"));
1879 }
1880
1881
1882 out_uint32_le(out, dwGroups);
1883 out_uint32_le(out, 0x00200000);
1884 out_uint32_le(out, dwGroups);
1885 out_uint8a(out, szGroups, dwGroups);
1886 outRepos(out, dwGroups);
1887 out_uint32_le(out, 0x00000000);
1888
1889 outForceAlignment(out, 8);
1890 SC_xfreeallmemory(&lcHandle);
1891 return rv;
1892 }
1893
1894 static MYPCSC_DWORD
1895 TS_SCardGetAttrib(STREAM in, STREAM out)
1896 {
1897 MYPCSC_DWORD rv;
1898 SERVER_SCARDCONTEXT hCard;
1899 MYPCSC_SCARDCONTEXT myHCard;
1900 SERVER_DWORD dwAttrId, dwAttrLen;
1901 MYPCSC_DWORD attrLen;
1902 unsigned char *pbAttr;
1903 PMEM_HANDLE lcHandle = NULL;
1904
1905 in->p += 0x20;
1906 in_uint32_le(in, dwAttrId);
1907 in->p += 0x04;
1908 in_uint32_le(in, dwAttrLen);
1909 in->p += 0x0C;
1910 in_uint32_le(in, hCard);
1911 myHCard = scHandleToMyPCSC(hCard);
1912
1913 dwAttrId = dwAttrId & 0x0000FFFF;
1914
1915 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
1916 DEBUG_SCARD(("[myHCard 0x%.8x]\n", (unsigned int) myHCard));
1917 DEBUG_SCARD(("[dwAttrId = 0x%.8x]\n", (unsigned int) dwAttrId));
1918 DEBUG_SCARD(("[dwAttrLen = 0x%.8x]\n", (unsigned int) dwAttrLen));
1919
1920 if (dwAttrLen > MAX_BUFFER_SIZE)
1921 dwAttrLen = MAX_BUFFER_SIZE;
1922
1923
1924 if (dwAttrLen > SCARD_AUTOALLOCATE)
1925 pbAttr = NULL;
1926 else if ((dwAttrLen < 0) || (dwAttrLen > SCARD_MAX_MEM))
1927 {
1928 dwAttrLen = SCARD_AUTOALLOCATE;
1929 pbAttr = NULL;
1930 }
1931 else
1932 {
1933 pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
1934 if (!pbAttr)
1935 return SC_returnNoMemoryError(&lcHandle, in, out);
1936 }
1937
1938 attrLen = dwAttrLen;
1939 rv = SCardGetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, &attrLen);
1940 dwAttrLen = attrLen;
1941
1942 if (dwAttrId == 0x00000100 && rv != SCARD_S_SUCCESS)
1943 {
1944 DEBUG_SCARD(("Get Attribute ATTR_VENDOR_NAME\n"));
1945 pthread_mutex_lock(&hcardAccess);
1946 PSCHCardRec hcard = hcardFirst;
1947 while (hcard)
1948 {
1949 if (hcard->hCard == hCard)
1950 {
1951 dwAttrLen = strlen(hcard->vendor);
1952 memcpy(pbAttr, hcard->vendor, dwAttrLen);
1953 rv = SCARD_S_SUCCESS;
1954 break;
1955 }
1956 hcard = hcard->next;
1957 }
1958 pthread_mutex_unlock(&hcardAccess);
1959 DEBUG_SCARD(("[0x%.8x]\n", (unsigned int) rv));
1960 }
1961
1962 if (rv != SCARD_S_SUCCESS)
1963 {
1964 DEBUG_SCARD(("<--ERROR SCardGetAttrib Code=0x%.8x, %s-->\n", (unsigned int) rv,
1965 pcsc_stringify_error(rv)));
1966 return SC_returnCode(rv, &lcHandle, in, out);
1967 }
1968 else
1969 {
1970 #ifdef WITH_DEBUG_SCARD
1971 DEBUG_SCARD(("<--SUCCESS SCardGetAttrib-->\n"));
1972 DEBUG_SCARD(("[LENGTH %d]\n", (unsigned int) dwAttrLen));
1973 DEBUG_SCARD(("+++++++++++++++++++++\n"));
1974 hexdump(pbAttr, dwAttrLen);
1975 DEBUG_SCARD(("+++++++++++++++++++++\n"));
1976 #endif
1977 out_uint32_le(out, dwAttrLen);
1978 out_uint32_le(out, 0x00000200);
1979 out_uint32_le(out, dwAttrLen);
1980 if (!pbAttr)
1981 {
1982 out_uint8s(out, dwAttrLen);
1983 }
1984 else
1985 {
1986 out_uint8p(out, pbAttr, dwAttrLen);
1987 }
1988 outRepos(out, dwAttrLen);
1989 out_uint32_le(out, 0x00000000);
1990 }
1991 outForceAlignment(out, 8);
1992 return rv;
1993 }
1994
1995 static MYPCSC_DWORD
1996 TS_SCardSetAttrib(STREAM in, STREAM out)
1997 {
1998 MYPCSC_DWORD rv;
1999 SERVER_SCARDCONTEXT hCard;
2000 MYPCSC_SCARDCONTEXT myHCard;
2001 SERVER_DWORD dwAttrId;
2002 SERVER_DWORD dwAttrLen;
2003 unsigned char *pbAttr;
2004 PMEM_HANDLE lcHandle = NULL;
2005
2006 in->p += 0x20;
2007 in_uint32_le(in, dwAttrId);
2008 in->p += 0x04;
2009 in_uint32_le(in, dwAttrLen);
2010 in->p += 0x0C;
2011 in_uint32_le(in, hCard);
2012 myHCard = scHandleToMyPCSC(hCard);
2013
2014 dwAttrId = dwAttrId & 0x0000FFFF;
2015
2016 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
2017 DEBUG_SCARD(("[myHCard 0x%.8x]\n", (unsigned int) myHCard));
2018 DEBUG_SCARD(("[dwAttrId = 0x%.8x]\n", (unsigned int) dwAttrId));
2019 DEBUG_SCARD(("[dwAttrLen = 0x%.8x]\n", (unsigned int) dwAttrLen));
2020
2021 if (dwAttrLen > MAX_BUFFER_SIZE)
2022 dwAttrLen = MAX_BUFFER_SIZE;
2023
2024 pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
2025 if (!pbAttr)
2026 return SC_returnNoMemoryError(&lcHandle, in, out);
2027
2028 in_uint8a(in, pbAttr, dwAttrLen);
2029 rv = SCardSetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, (MYPCSC_DWORD) dwAttrLen);
2030
2031 if (rv)
2032 {
2033 DEBUG_SCARD(("<--ERROR SCardSetAttrib Code=0x%.8x, %s-->\n", (unsigned int) rv,
2034 pcsc_stringify_error(rv)));
2035 }
2036 else
2037 {
2038 DEBUG_SCARD(("<--SUCCESS SCardSetAttrib-->\n"));
2039 }
2040
2041 out_uint32_le(out, 0x00000000);
2042 out_uint32_le(out, 0x00000200);
2043 out_uint32_le(out, 0x00000000);
2044 out_uint32_le(out, 0x00000000);
2045 outForceAlignment(out, 8);
2046 SC_xfreeallmemory(&lcHandle);
2047 return rv;
2048 }
2049
2050 #endif
2051
2052 static MYPCSC_DWORD
2053 TS_SCardControl(STREAM in, STREAM out)
2054 {
2055 MYPCSC_DWORD rv;
2056 SERVER_SCARDCONTEXT hContext;
2057 SERVER_SCARDHANDLE hCard;
2058 MYPCSC_SCARDHANDLE myHCard;
2059 SERVER_DWORD map[3];
2060 SERVER_DWORD dwControlCode;
2061 unsigned char *pInBuffer, *pOutBuffer;
2062 SERVER_DWORD nInBufferSize, nOutBufferSize, nOutBufferRealSize, nBytesReturned;
2063 MYPCSC_DWORD sc_nBytesReturned;
2064 PMEM_HANDLE lcHandle = NULL;
2065
2066 pInBuffer = NULL;
2067 pOutBuffer = NULL;
2068
2069 in->p += 0x14;
2070 in_uint32_le(in, map[0]);
2071 in->p += 0x04;
2072 in_uint32_le(in, map[1]);
2073 in_uint32_le(in, dwControlCode);
2074 in_uint32_le(in, nInBufferSize);
2075 in_uint32_le(in, map[2]);
2076 in->p += 0x04;
2077 in_uint32_le(in, nOutBufferSize);
2078 in->p += 0x04;
2079 in_uint32_le(in, hContext);
2080 in->p += 0x04;
2081 in_uint32_le(in, hCard);
2082 if (map[2] & INPUT_LINKED)
2083 {
2084 /* read real input size */
2085 in_uint32_le(in, nInBufferSize);
2086 pInBuffer = SC_xmalloc(&lcHandle, nInBufferSize);
2087 if (!pInBuffer)
2088 return SC_returnNoMemoryError(&lcHandle, in, out);
2089 in_uint8a(in, pInBuffer, nInBufferSize);
2090 }
2091
2092 #if 0
2093 if (nOutBufferSize > 0)
2094 {
2095 nOutBufferRealSize = nOutBufferSize;
2096 }
2097 else
2098 #endif
2099 nOutBufferRealSize = 1024;
2100
2101 nBytesReturned = nOutBufferRealSize;
2102
2103 nBytesReturned = nOutBufferRealSize;
2104 pOutBuffer = SC_xmalloc(&lcHandle, nOutBufferRealSize);
2105 if (!pOutBuffer)
2106 return SC_returnNoMemoryError(&lcHandle, in, out);
2107
2108 #ifdef WITH_DEBUG_SCARD
2109 DEBUG_SCARD(("[hContext = 0x%.8x]\n", (unsigned int) hContext));
2110 DEBUG_SCARD(("[hCard = 0x%.8x]\n", (unsigned int) hCard));
2111 DEBUG_SCARD(("[dwControlCode = 0x%.8x]\n", (unsigned int) dwControlCode));
2112 DEBUG_SCARD(("[nInBufferSize = %d]\n", (unsigned int) nInBufferSize));
2113 DEBUG_SCARD(("[nOutBufferSize = %d]\n", (unsigned int) nOutBufferSize));
2114 if (nInBufferSize > 0)
2115 {
2116 DEBUG_SCARD(("[In buffer]\n"));
2117 hexdump((unsigned char *) pInBuffer, nInBufferSize);
2118 }
2119 DEBUG_SCARD(("---> Calling SCardControl\n"));
2120 #endif
2121
2122 sc_nBytesReturned = nBytesReturned;
2123 myHCard = scHandleToMyPCSC(hCard);
2124 #ifdef WITH_PCSC120
2125 rv = SCardControl(myHCard, pInBuffer, (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
2126 &sc_nBytesReturned);
2127 #else
2128 rv = SCardControl(myHCard, (MYPCSC_DWORD) dwControlCode, pInBuffer,
2129 (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
2130 (MYPCSC_DWORD) nOutBufferRealSize, &sc_nBytesReturned);
2131 #endif
2132 nBytesReturned = sc_nBytesReturned;
2133
2134 #ifdef WITH_DEBUG_SCARD
2135 if (rv != SCARD_S_SUCCESS)
2136 {
2137 DEBUG_SCARD(("<--ERROR SCardControl Code=0x%.8x, %s-->\n", (unsigned int) rv,
2138 pcsc_stringify_error(rv)));
2139 }
2140 else
2141 {
2142 DEBUG_SCARD(("<--SUCCESS SCardControl-->\n"));
2143 DEBUG_SCARD(("[LENGTH %d]\n", (unsigned int) nBytesReturned));
2144 DEBUG_SCARD(("+++++++++++++++++++++\n"));
2145 hexdump((unsigned char *) pOutBuffer, nBytesReturned);
2146 DEBUG_SCARD(("+++++++++++++++++++++\n"));
2147 }
2148 #endif
2149
2150 out_uint32_le(out, nBytesReturned);
2151 out_uint32_le(out, 0x00000004);
2152 out_uint32_le(out, nBytesReturned);
2153 if (nBytesReturned > 0)
2154 {
2155 out_uint8p(out, pOutBuffer, nBytesReturned);
2156 outRepos(out, nBytesReturned);
2157 }
2158
2159 outForceAlignment(out, 8);
2160 SC_xfreeallmemory(&lcHandle);
2161 return rv;
2162 }
2163
2164 static MYPCSC_DWORD
2165 TS_SCardAccessStartedEvent(STREAM in, STREAM out)
2166 {
2167 out_uint8s(out, 8);
2168 return SCARD_S_SUCCESS;
2169 }
2170
2171
2172 static RD_NTSTATUS
2173 scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2174 {
2175 SERVER_DWORD Result = 0x00000000;
2176 unsigned char *psize, *pend, *pStatusCode;
2177 SERVER_DWORD addToEnd = 0;
2178 #ifdef WITH_DEBUG_SCARD
2179 unsigned char *pbeg = out->p;
2180
2181 DEBUG_SCARD(("--------------------------------\n"));
2182 DEBUG_SCARD(("[NTHANDLE %08X]\n", handle));
2183 DEBUG_SCARD(("[REQUEST %08X]\n", request));
2184 DEBUG_SCARD(("[INPUT DUMP]--------------------\n"));
2185 hexdump(in->p, in->end - in->p);
2186 #endif
2187 /* Processing request */
2188
2189 out_uint32_le(out, 0x00081001); /* Header lines */
2190 out_uint32_le(out, 0xCCCCCCCC);
2191 psize = out->p;
2192 out_uint32_le(out, 0x00000000); /* Size of data portion */
2193 out_uint32_le(out, 0x00000000); /* Zero bytes (may be usefull) */
2194 pStatusCode = out->p;
2195 out_uint32_le(out, 0x00000000); /* Status Code */
2196
2197 switch (request)
2198 {
2199 /* SCardEstablishContext */
2200 case SC_ESTABLISH_CONTEXT:
2201 {
2202 DEBUG_SCARD(("<---SCardEstablishContext--->\n"));
2203 Result = (SERVER_DWORD) TS_SCardEstablishContext(in, out);
2204 break;
2205 }
2206 /* SCardReleaseContext */
2207 case SC_RELEASE_CONTEXT:
2208 {
2209 DEBUG_SCARD(("<---SCardReleaseContext--->\n"));
2210 Result = (SERVER_DWORD) TS_SCardReleaseContext(in, out);
2211 break;
2212 }
2213 /* SCardIsValidContext */
2214 case SC_IS_VALID_CONTEXT:
2215 {
2216 DEBUG_SCARD(("<---SCardIsValidContext--->\n"));
2217 Result = (SERVER_DWORD) TS_SCardIsValidContext(in, out);
2218 break;
2219 }
2220 /* SCardListReaders */
2221 case SC_LIST_READERS: /* SCardListReadersA */
2222 case SC_LIST_READERS + 4: /* SCardListReadersW */
2223 {
2224 RD_BOOL wide = request != SC_LIST_READERS;
2225 DEBUG_SCARD(("<---SCardListReaders---> (%s)\n",
2226 (wide) ? ("WIDE") : ("ASCII")));
2227 Result = (SERVER_DWORD) TS_SCardListReaders(in, out, wide);
2228 break;
2229 }
2230 /* ScardConnect */
2231 case SC_CONNECT: /* ScardConnectA */
2232 case SC_CONNECT + 4: /* SCardConnectW */
2233 {
2234 RD_BOOL wide = request != SC_CONNECT;
2235 DEBUG_SCARD(("<---SCardConnect---> (%s)\n",
2236 (wide) ? ("WIDE") : ("ASCII")));
2237 Result = (SERVER_DWORD) TS_SCardConnect(in, out, wide);
2238 break;
2239 }
2240 /* ScardReconnect */
2241 case SC_RECONNECT:
2242 {
2243 DEBUG_SCARD(("<---SCardReconnect--->\n"));
2244 Result = (SERVER_DWORD) TS_SCardReconnect(in, out);
2245 break;
2246 }
2247 /* ScardDisconnect */
2248 case SC_DISCONNECT:
2249 {
2250 DEBUG_SCARD(("<---SCardDisconnect--->\n"));
2251 Result = (SERVER_DWORD) TS_SCardDisconnect(in, out);
2252 break;
2253 }
2254 /* ScardGetStatusChange */
2255 case SC_GET_STATUS_CHANGE: /* SCardGetStatusChangeA */
2256 case SC_GET_STATUS_CHANGE + 4: /* SCardGetStatusChangeW */
2257 {
2258 RD_BOOL wide = request != SC_GET_STATUS_CHANGE;
2259 DEBUG_SCARD(("<---SCardGetStatusChange---> (%s)\n",
2260 (wide) ? ("WIDE") : ("ASCII")));
2261 Result = (SERVER_DWORD) TS_SCardGetStatusChange(in, out, wide);
2262 break;
2263 }
2264 /* SCardCancel */
2265 case SC_CANCEL:
2266 {
2267 DEBUG_SCARD(("<---SCardCancel--->\n"));
2268 Result = (SERVER_DWORD) TS_SCardCancel(in, out);
2269 break;
2270 }
2271 /* SCardLocateCardsByATR */
2272 case SC_LOCATE_CARDS_BY_ATR: /* SCardLocateCardsByATRA */
2273 case SC_LOCATE_CARDS_BY_ATR + 4: /* SCardLocateCardsByATRW */
2274 {
2275 RD_BOOL wide = request != SC_LOCATE_CARDS_BY_ATR;
2276 DEBUG_SCARD(("<---SCardLocateCardsByATR---> (%s)\n",
2277 (wide) ? ("WIDE") : ("ASCII")));
2278 Result = (SERVER_DWORD) TS_SCardLocateCardsByATR(in, out, wide);
2279 break;
2280 }
2281 /* SCardBeginTransaction */
2282 case SC_BEGIN_TRANSACTION:
2283 {
2284 DEBUG_SCARD(("<---SCardBeginTransaction--->\n"));
2285 Result = (SERVER_DWORD) TS_SCardBeginTransaction(in, out);
2286 break;
2287 }
2288 /* SCardBeginTransaction */
2289 case SC_END_TRANSACTION:
2290 {
2291 DEBUG_SCARD(("<---SCardEndTransaction--->\n"));
2292 Result = (SERVER_DWORD) TS_SCardEndTransaction(in, out);
2293 break;
2294 }
2295 /* ScardTransmit */
2296 case SC_TRANSMIT:
2297 {
2298 DEBUG_SCARD(("<---SCardTransmit--->\n"));
2299 Result = (SERVER_DWORD) TS_SCardTransmit(in, out);
2300 break;
2301 }
2302 /* SCardControl */
2303 case SC_CONTROL:
2304 {
2305 DEBUG_SCARD(("<---SCardControl--->\n"));
2306 Result = (SERVER_DWORD) TS_SCardControl(in, out);
2307 break;
2308 }
2309 /* SCardGetAttrib */
2310 #ifndef WITH_PCSC120
2311 case SC_GETATTRIB:
2312 {
2313 DEBUG_SCARD(("<---SCardGetAttrib--->\n"));
2314 Result = (SERVER_DWORD) TS_SCardGetAttrib(in, out);
2315 break;
2316 }
2317 #endif
2318 case SC_ACCESS_STARTED_EVENT:
2319 {
2320 DEBUG_SCARD(("<---SCardAccessStartedEvent-->\n"));
2321 Result = (SERVER_DWORD) TS_SCardAccessStartedEvent(in, out);
2322 break;
2323 }
2324 case SC_STATUS: /* SCardStatusA */
2325 case SC_STATUS + 4: /* SCardStatusW */
2326 {
2327 RD_BOOL wide = request != SC_STATUS;
2328 DEBUG_SCARD(("<---SCardStatus---> (%s)\n",
2329 (wide) ? ("WIDE") : ("ASCII")));
2330 Result = (SERVER_DWORD) TS_SCardStatus(in, out, wide);
2331 break;
2332 }
2333 case SC_STATE: /* SCardState */
2334 {
2335 DEBUG_SCARD(("<---SCardState--->"));
2336 Result = (SERVER_DWORD) TS_SCardState(in, out);
2337 break;
2338 }
2339 default:
2340 {
2341 DEBUG_SCARD(("<---UNSUPPORTED-FUNC--->\n"));
2342 Result = 0x80100014;
2343 out_uint8s(out, 256);
2344 break;
2345 }
2346 }
2347
2348 #if 0
2349 out_uint32_le(out, 0x00000000);
2350 #endif
2351 /* Setting modified variables */
2352 pend = out->p;
2353 /* setting data size */
2354 out->p = psize;
2355 out_uint32_le(out, pend - psize - 16);
2356 /* setting status code */
2357 out->p = pStatusCode;
2358 out_uint32_le(out, Result);
2359 /* finish */
2360 out->p = pend;
2361
2362 addToEnd = (pend - pStatusCode) % 16;
2363 if (addToEnd < 16 && addToEnd > 0)
2364 {
2365 out_uint8s(out, addToEnd);
2366 }
2367
2368 #ifdef WITH_DEBUG_SCARD
2369 DEBUG_SCARD(("[OUTPUT DUMP]-------------------\n"));
2370 hexdump(pbeg, (size_t) (out->p) - (size_t) pbeg);
2371 DEBUG_SCARD(("--------------------------------\n"));
2372 #endif
2373 return RD_STATUS_SUCCESS;
2374 }
2375
2376 /* Thread functions */
2377
2378 static STREAM
2379 duplicateStream(PMEM_HANDLE * handle, STREAM s, uint32 buffer_size, RD_BOOL isInputStream)
2380 {
2381 STREAM d = SC_xmalloc(handle, sizeof(struct stream));
2382 if (d != NULL)
2383 {
2384 if (isInputStream)
2385 d->size = (size_t) (s->end) - (size_t) (s->data);
2386 else if (buffer_size < s->size)
2387 d->size = s->size;
2388 else
2389 d->size = buffer_size;
2390
2391 d->data = SC_xmalloc(handle, d->size);
2392
2393 d->end = (void *) ((size_t) (d->data) + (size_t) (s->end) - (size_t) (s->data));
2394 d->p = (void *) ((size_t) (d->data) + (size_t) (s->p) - (size_t) (s->data));
2395 d->iso_hdr =
2396 (void *) ((size_t) (d->data) + (size_t) (s->iso_hdr) - (size_t) (s->data));
2397 d->mcs_hdr =
2398 (void *) ((size_t) (d->data) + (size_t) (s->mcs_hdr) - (size_t) (s->data));
2399 d->sec_hdr =
2400 (void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
2401 d->sec_hdr =
2402 (void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
2403 d->rdp_hdr =
2404 (void *) ((size_t) (d->data) + (size_t) (s->rdp_hdr) - (size_t) (s->data));
2405 d->channel_hdr =
2406 (void *) ((size_t) (d->data) + (size_t) (s->channel_hdr) -
2407 (size_t) (s->data));
2408 if (isInputStream)
2409 memcpy(d->data, s->data, (size_t) (s->end) - (size_t) (s->data));
2410 else
2411 memcpy(d->data, s->data, (size_t) (s->p) - (size_t) (s->data));
2412 }
2413 return d;
2414 }
2415
2416 static void
2417 freeStream(PMEM_HANDLE * handle, STREAM s)
2418 {
2419 if (s != NULL)
2420 {
2421 if (s->data != NULL)
2422 SC_xfree(handle, s->data);
2423 SC_xfree(handle, s);
2424 }
2425 }
2426
2427 static PSCThreadData
2428 SC_addToQueue(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2429 {
2430 PMEM_HANDLE lcHandle = NULL;
2431 PSCThreadData data = SC_xmalloc(&lcHandle, sizeof(TSCThreadData));
2432
2433 if (!data)
2434 return NULL;
2435 else
2436 {
2437 data->memHandle = lcHandle;
2438 data->device = curDevice;
2439 data->id = curId;
2440 data->handle = handle;
2441 data->request = request;
2442 data->in = duplicateStream(&(data->memHandle), in, 0, SC_TRUE);
2443 if (data->in == NULL)
2444 {
2445 SC_xfreeallmemory(&(data->memHandle));
2446 return NULL;
2447 }
2448 data->out =
2449 duplicateStream(&(data->memHandle), out, OUT_STREAM_SIZE + curBytesOut,
2450 SC_FALSE);
2451 if (data->out == NULL)
2452 {
2453 SC_xfreeallmemory(&(data->memHandle));
2454 return NULL;
2455 }
2456 data->next = NULL;
2457
2458 pthread_mutex_lock(&queueAccess);
2459
2460 if (queueLast)
2461 queueLast->next = data;
2462 queueLast = data;
2463 if (!queueFirst)
2464 queueFirst = data;
2465
2466 pthread_mutex_unlock(&queueEmpty);
2467 pthread_mutex_unlock(&queueAccess);
2468 }
2469 return data;
2470 }
2471
2472 static void
2473 SC_destroyThreadData(PSCThreadData data)
2474 {
2475 if (data)
2476 {
2477 PMEM_HANDLE handle = data->memHandle;
2478 SC_xfreeallmemory(&handle);
2479 }
2480 }
2481
2482 static PSCThreadData
2483 SC_getNextInQueue()
2484 {
2485 PSCThreadData Result = NULL;
2486 pthread_mutex_lock(&queueAccess);
2487 if (queueFirst != NULL)
2488 {
2489 Result = queueFirst;
2490 queueFirst = queueFirst->next;
2491 if (!queueFirst)
2492 {
2493 queueLast = NULL;
2494 pthread_mutex_trylock(&queueEmpty);
2495 }
2496 Result->next = NULL;
2497 }
2498 pthread_mutex_unlock(&queueAccess);
2499 return Result;
2500 }
2501
2502 static void
2503 SC_deviceControl(PSCThreadData data)
2504 {
2505 size_t buffer_len = 0;
2506 scard_device_control(data->handle, data->request, data->in, data->out);
2507 buffer_len = (size_t) data->out->p - (size_t) data->out->data;
2508 rdpdr_send_completion(data->device, data->id, 0, buffer_len, data->out->data, buffer_len);
2509 SC_destroyThreadData(data);
2510 }
2511
2512
2513 static void *
2514 thread_function(PThreadListElement listElement)
2515 {
2516 #ifdef WITH_DEBUG_SCARD
2517 long sTime = 0;
2518 #endif
2519 if ((listElement != NULL) && (listElement->data != NULL))
2520 {
2521 while (1)
2522 {
2523 #ifdef WITH_DEBUG_SCARD
2524 sTime = time(NULL);
2525 #endif
2526 pthread_mutex_lock(&listElement->nodata);
2527 SC_deviceControl(listElement->data);
2528 listElement->data = NULL;
2529 DEBUG_SCARD(("[HANDLING TIME %d]\n", (int) (time(NULL) - sTime)));
2530 pthread_mutex_unlock(&listElement->busy);
2531 }
2532 }
2533 pthread_exit(NULL);
2534 return NULL;
2535 }
2536
2537 static void
2538 SC_handleRequest(PSCThreadData data)
2539 {
2540 int Result = 0;
2541 PThreadListElement cur = threadList, last = threadList;
2542
2543 DEBUG_SCARD(("[THREAD COUNT %d]\n", threadCount));
2544
2545 while (cur)
2546 {
2547 if (0 == pthread_mutex_trylock(&cur->busy))
2548 {
2549 cur->data = data;
2550 pthread_mutex_unlock(&cur->nodata);
2551 return;
2552 }
2553 else
2554 {
2555 last = cur;
2556 cur = cur->next;
2557 }
2558 }
2559
2560 cur = SC_xmalloc(&threadListHandle, sizeof(TThreadListElement));
2561 if (!cur)
2562 return;
2563
2564 threadCount++;
2565
2566 cur->next = NULL;
2567 pthread_mutex_init(&cur->busy, NULL);
2568 pthread_mutex_init(&cur->nodata, NULL);
2569 pthread_mutex_trylock(&cur->busy);
2570 cur->data = data;
2571 pthread_mutex_unlock(&cur->nodata);
2572
2573 Result = pthread_create(&cur->thread, NULL, (void *(*)(void *)) thread_function, cur);
2574 if (0 != Result)
2575 {
2576 error("[THREAD CREATE ERROR 0x%.8x]\n", Result);
2577 SC_xfree(&threadListHandle, cur);
2578 SC_destroyThreadData(data);
2579 data = NULL;
2580 }
2581 else if (last)
2582 last->next = cur;
2583 else
2584 threadList = cur;
2585 }
2586
2587 static void *
2588 queue_handler_function(void *data)
2589 {
2590 PSCThreadData cur_data = NULL;
2591 while (1)
2592 {
2593 cur_data = SC_getNextInQueue();
2594 if (cur_data != NULL)
2595 {
2596 switch (cur_data->request)
2597 {
2598 case SC_ESTABLISH_CONTEXT:
2599 case SC_RELEASE_CONTEXT:
2600 {
2601 SC_deviceControl(cur_data);
2602 break;
2603 }
2604 default:
2605 {
2606 SC_handleRequest(cur_data);
2607 break;
2608 }
2609 }
2610 cur_data = NULL;
2611 }
2612 else
2613 pthread_mutex_lock(&queueEmpty);
2614 }
2615 return NULL;
2616 }
2617
2618 static RD_NTSTATUS
2619 thread_wrapper(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
2620 {
2621 if (SC_addToQueue(handle, request, in, out))
2622 return RD_STATUS_PENDING | 0xC0000000;
2623 else
2624 return RD_STATUS_NO_SUCH_FILE;
2625 }
2626
2627 DEVICE_FNS scard_fns = {
2628 scard_create,
2629 scard_close,
2630 scard_read,
2631 scard_write,
2632 thread_wrapper
2633 };
2634 #endif /* MAKE_PROTO */
2635
2636 void
2637 scard_lock(int lock)
2638 {
2639 if (!scard_mutex)
2640 {
2641 int i;
2642
2643 scard_mutex =
2644 (pthread_mutex_t **) xmalloc(sizeof(pthread_mutex_t *) * SCARD_LOCK_LAST);
2645
2646 for (i = 0; i < SCARD_LOCK_LAST; i++)
2647 {
2648 scard_mutex[i] = NULL;
2649 }
2650 }
2651
2652 if (!scard_mutex[lock])
2653 {
2654 scard_mutex[lock] = (pthread_mutex_t *) xmalloc(sizeof(pthread_mutex_t));
2655 pthread_mutex_init(scard_mutex[lock], NULL);
2656 }
2657
2658 pthread_mutex_lock(scard_mutex[lock]);
2659 }
2660
2661 void
2662 scard_unlock(int lock)
2663 {
2664 pthread_mutex_unlock(scard_mutex[lock]);
2665 }
2666
2667 STREAM
2668 scard_tcp_init(void)
2669 {
2670 STREAM result = NULL;
2671
2672 result = &out[cur_stream_id];
2673 cur_stream_id = (cur_stream_id + 1) % STREAM_COUNT;
2674
2675 return result;
2676 }
2677
2678 void
2679 scard_tcp_connect(void)
2680 {
2681 int i;
2682
2683 for (i = 0; i < STREAM_COUNT; i++)
2684 {
2685 out[i].size = 4096;
2686 out[i].data = (uint8 *) xmalloc(out[i].size);
2687 }
2688 }
2689
2690 void
2691 scard_tcp_reset_state(void)
2692 {
2693 int i;
2694 struct stream *p;
2695
2696 for (i = 0, p = out; i < STREAM_COUNT; i++, p++)
2697 {
2698 if (p->data != NULL)
2699 xfree(p->data);
2700 p->p = NULL;
2701 p->end = NULL;
2702 p->data = NULL;
2703 p->size = 0;
2704 p->iso_hdr = NULL;
2705 p->mcs_hdr = NULL;
2706 p->sec_hdr = NULL;
2707 p->rdp_hdr = NULL;
2708 p->channel_hdr = NULL;
2709 }
2710 }

  ViewVC Help
Powered by ViewVC 1.1.26