~ubuntu-branches/ubuntu/jaunty/pcsc-lite/jaunty-security

« back to all changes in this revision

Viewing changes to pcsc-lite/src/eventhandler.c

  • Committer: Bazaar Package Importer
  • Author(s): Ludovic Rousseau
  • Date: 2005-11-27 18:04:59 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051127180459-qrex2gzpq9d8jexd
Tags: 1.2.9-beta9-1
* New upstream version
* debian/compat: change from 3 to 4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * This keeps track of card insertion/removal events
3
 
 * and updates ATR, protocol, and status information.
4
 
 *
5
 
 * MUSCLE SmartCard Development ( http://www.linuxnet.com )
6
 
 *
7
 
 * Copyright (C) 2000
8
 
 *  David Corcoran <corcoran@linuxnet.com>
9
 
 * Copyright (C) 2004
10
 
 *  Ludovic Rousseau <ludovic.rousseau@free.fr>
11
 
 *
12
 
 * $Id: eventhandler.c,v 1.31 2005/02/22 14:40:26 rousseau Exp $
13
 
 */
14
 
 
15
 
#include "config.h"
16
 
#include <sys/types.h>
17
 
#include <sys/stat.h>
18
 
#include <errno.h>
19
 
#include <fcntl.h>
20
 
#include <string.h>
21
 
#include <stdlib.h>
22
 
 
23
 
#include "pcsclite.h"
24
 
#include "ifdhandler.h"
25
 
#include "debuglog.h"
26
 
#include "thread_generic.h"
27
 
#include "readerfactory.h"
28
 
#include "eventhandler.h"
29
 
#include "dyn_generic.h"
30
 
#include "sys_generic.h"
31
 
#include "ifdwrapper.h"
32
 
#include "prothandler.h"
33
 
#include "strlcpycat.h"
34
 
 
35
 
static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
36
 
 
37
 
void EHStatusHandlerThread(PREADER_CONTEXT);
38
 
 
39
 
LONG EHInitializeEventStructures(void)
40
 
{
41
 
        int fd, i, pageSize;
42
 
 
43
 
        fd = 0;
44
 
        i = 0;
45
 
        pageSize = 0;
46
 
 
47
 
        SYS_RemoveFile(PCSCLITE_PUBSHM_FILE);
48
 
 
49
 
        fd = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDWR | O_CREAT, 00644);
50
 
        if (fd < 0)
51
 
        {
52
 
                Log3(PCSC_LOG_CRITICAL, "Cannot create public shared file %s: %s",
53
 
                        PCSCLITE_PUBSHM_FILE, strerror(errno));
54
 
                exit(1);
55
 
        }
56
 
 
57
 
        SYS_Chmod(PCSCLITE_PUBSHM_FILE,
58
 
                S_IRGRP | S_IREAD | S_IWRITE | S_IROTH);
59
 
 
60
 
        pageSize = SYS_GetPageSize();
61
 
 
62
 
        /*
63
 
         * Jump to end of file space and allocate zero's 
64
 
         */
65
 
        SYS_SeekFile(fd, pageSize * PCSCLITE_MAX_READERS_CONTEXTS);
66
 
        SYS_WriteFile(fd, "", 1);
67
 
 
68
 
        /*
69
 
         * Allocate each reader structure 
70
 
         */
71
 
        for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
72
 
        {
73
 
                readerStates[i] = (PREADER_STATE)
74
 
                        SYS_MemoryMap(sizeof(READER_STATE), fd, (i * pageSize));
75
 
                if (readerStates[i] == 0)
76
 
                {
77
 
                        Log3(PCSC_LOG_CRITICAL, "Cannot memory map public shared file %s: %s",
78
 
                                PCSCLITE_PUBSHM_FILE, strerror(errno));
79
 
                        exit(1);
80
 
                }
81
 
 
82
 
                /*
83
 
                 * Zero out each value in the struct 
84
 
                 */
85
 
                memset((readerStates[i])->readerName, 0, MAX_READERNAME);
86
 
                memset((readerStates[i])->cardAtr, 0, MAX_ATR_SIZE);
87
 
                (readerStates[i])->readerID = 0;
88
 
                (readerStates[i])->readerState = 0;
89
 
                (readerStates[i])->lockState = 0;
90
 
                (readerStates[i])->readerSharing = 0;
91
 
                (readerStates[i])->cardAtrLength = 0;
92
 
                (readerStates[i])->cardProtocol = SCARD_PROTOCOL_UNSET;
93
 
        }
94
 
 
95
 
        return SCARD_S_SUCCESS;
96
 
}
97
 
 
98
 
LONG EHDestroyEventHandler(PREADER_CONTEXT rContext)
99
 
{
100
 
        if (NULL == rContext->readerState)
101
 
        {
102
 
                Log1(PCSC_LOG_ERROR, "Thread never started (reader init failed?)");
103
 
                return SCARD_S_SUCCESS;
104
 
        }
105
 
 
106
 
        if ('\0' == rContext->readerState->readerName[0])
107
 
        {
108
 
                Log1(PCSC_LOG_INFO, "Thread already stomped.");
109
 
                return SCARD_S_SUCCESS;
110
 
        }
111
 
 
112
 
        /*
113
 
         * Set the thread to 0 to exit thread 
114
 
         */
115
 
        rContext->dwLockId = 0xFFFF;
116
 
 
117
 
        Log1(PCSC_LOG_INFO, "Stomping thread.");
118
 
 
119
 
        do
120
 
        {
121
 
                /*
122
 
                 * Wait 0.05 seconds for the child to respond 
123
 
                 */
124
 
                SYS_USleep(50000);
125
 
        }
126
 
        while (rContext->dwLockId == 0xFFFF);
127
 
        /*
128
 
         * Zero out the public status struct to allow it to be recycled and
129
 
         * used again 
130
 
         */
131
 
 
132
 
        memset(rContext->readerState->readerName, 0,
133
 
                sizeof(rContext->readerState->readerName));
134
 
        memset(rContext->readerState->cardAtr, 0,
135
 
                sizeof(rContext->readerState->cardAtr));
136
 
        rContext->readerState->readerID = 0;
137
 
        rContext->readerState->readerState = 0;
138
 
        rContext->readerState->lockState = 0;
139
 
        rContext->readerState->readerSharing = 0;
140
 
        rContext->readerState->cardAtrLength = 0;
141
 
        rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
142
 
 
143
 
        /* Zero the thread */
144
 
        rContext->pthThread = 0;
145
 
 
146
 
        Log1(PCSC_LOG_INFO, "Thread stomped.");
147
 
 
148
 
        return SCARD_S_SUCCESS;
149
 
}
150
 
 
151
 
LONG EHSpawnEventHandler(PREADER_CONTEXT rContext)
152
 
{
153
 
        LONG rv;
154
 
        DWORD dwStatus = 0;
155
 
        int i;
156
 
        UCHAR ucAtr[MAX_ATR_SIZE];
157
 
        DWORD dwAtrLen = 0;
158
 
 
159
 
        rv = IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen);
160
 
        if (rv != SCARD_S_SUCCESS)
161
 
        {
162
 
                Log2(PCSC_LOG_ERROR, "Initial Check Failed on %s", rContext->lpcReader);
163
 
                return SCARD_F_UNKNOWN_ERROR;
164
 
        }
165
 
 
166
 
        /*
167
 
         * Find an empty reader slot and insert the new reader 
168
 
         */
169
 
        for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
170
 
        {
171
 
                if ((readerStates[i])->readerID == 0)
172
 
                        break;
173
 
        }
174
 
 
175
 
        if (i == PCSCLITE_MAX_READERS_CONTEXTS)
176
 
                return SCARD_F_INTERNAL_ERROR;
177
 
 
178
 
        /*
179
 
         * Set all the attributes to this reader 
180
 
         */
181
 
        rContext->readerState = readerStates[i];
182
 
        strlcpy(rContext->readerState->readerName, rContext->lpcReader,
183
 
                sizeof(rContext->readerState->readerName));
184
 
        memcpy(rContext->readerState->cardAtr, ucAtr, dwAtrLen);
185
 
        rContext->readerState->readerID = i + 100;
186
 
        rContext->readerState->readerState = dwStatus;
187
 
        rContext->readerState->readerSharing = rContext->dwContexts;
188
 
        rContext->readerState->cardAtrLength = dwAtrLen;
189
 
        rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
190
 
 
191
 
        rv = SYS_ThreadCreate(&rContext->pthThread, THREAD_ATTR_DETACHED,
192
 
                (PCSCLITE_THREAD_FUNCTION( ))EHStatusHandlerThread, (LPVOID) rContext);
193
 
        if (rv == 1)
194
 
                return SCARD_S_SUCCESS;
195
 
        else
196
 
                return SCARD_E_NO_MEMORY;
197
 
}
198
 
 
199
 
void EHStatusHandlerThread(PREADER_CONTEXT rContext)
200
 
{
201
 
        LONG rv;
202
 
        LPCTSTR lpcReader;
203
 
        DWORD dwStatus, dwReaderSharing;
204
 
        DWORD dwCurrentState;
205
 
        int pageSize;
206
 
 
207
 
        /*
208
 
         * Zero out everything 
209
 
         */
210
 
        dwStatus = 0;
211
 
        dwReaderSharing = 0;
212
 
        dwCurrentState = 0;
213
 
 
214
 
        lpcReader = rContext->lpcReader;
215
 
 
216
 
        pageSize = SYS_GetPageSize();
217
 
 
218
 
        rv = IFDStatusICC(rContext, &dwStatus, rContext->readerState->cardAtr,
219
 
                        &rContext->readerState->cardAtrLength);
220
 
        if (dwStatus & SCARD_PRESENT)
221
 
        {
222
 
                rv = IFDPowerICC(rContext, IFD_POWER_UP,
223
 
                        rContext->readerState->cardAtr,
224
 
                        &rContext->readerState->cardAtrLength);
225
 
 
226
 
                /* the protocol is unset after a power on */
227
 
                rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
228
 
 
229
 
                if (rv == IFD_SUCCESS)
230
 
                {
231
 
                        dwStatus |= SCARD_PRESENT;
232
 
                        dwStatus &= ~SCARD_ABSENT;
233
 
                        dwStatus |= SCARD_POWERED;
234
 
                        dwStatus |= SCARD_NEGOTIABLE;
235
 
                        dwStatus &= ~SCARD_SPECIFIC;
236
 
                        dwStatus &= ~SCARD_SWALLOWED;
237
 
                        dwStatus &= ~SCARD_UNKNOWN;
238
 
 
239
 
                        if (rContext->readerState->cardAtrLength > 0)
240
 
                        {
241
 
                                LogXxd(PCSC_LOG_INFO, "Card ATR: ",
242
 
                                        rContext->readerState->cardAtr,
243
 
                                        rContext->readerState->cardAtrLength);
244
 
                        }
245
 
                        else
246
 
                                Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
247
 
                }
248
 
                else
249
 
                {
250
 
                        dwStatus |= SCARD_PRESENT;
251
 
                        dwStatus &= ~SCARD_ABSENT;
252
 
                        dwStatus |= SCARD_SWALLOWED;
253
 
                        dwStatus &= ~SCARD_POWERED;
254
 
                        dwStatus &= ~SCARD_NEGOTIABLE;
255
 
                        dwStatus &= ~SCARD_SPECIFIC;
256
 
                        dwStatus &= ~SCARD_UNKNOWN;
257
 
                        Log1(PCSC_LOG_ERROR, "Error powering up card.");
258
 
                }
259
 
 
260
 
                dwCurrentState = SCARD_PRESENT;
261
 
        }
262
 
        else
263
 
        {
264
 
                dwStatus |= SCARD_ABSENT;
265
 
                dwStatus &= ~SCARD_PRESENT;
266
 
                dwStatus &= ~SCARD_POWERED;
267
 
                dwStatus &= ~SCARD_NEGOTIABLE;
268
 
                dwStatus &= ~SCARD_SPECIFIC;
269
 
                dwStatus &= ~SCARD_SWALLOWED;
270
 
                dwStatus &= ~SCARD_UNKNOWN;
271
 
                rContext->readerState->cardAtrLength = 0;
272
 
                rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
273
 
 
274
 
                dwCurrentState = SCARD_ABSENT;
275
 
        }
276
 
 
277
 
        /*
278
 
         * Set all the public attributes to this reader 
279
 
         */
280
 
        rContext->readerState->readerState = dwStatus;
281
 
        rContext->readerState->readerSharing = dwReaderSharing =
282
 
                rContext->dwContexts;
283
 
 
284
 
        SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
285
 
 
286
 
        while (1)
287
 
        {
288
 
                dwStatus = 0;
289
 
 
290
 
                rv = IFDStatusICC(rContext, &dwStatus,
291
 
                        rContext->readerState->cardAtr,
292
 
                        &rContext->readerState->cardAtrLength);
293
 
 
294
 
                if (rv != SCARD_S_SUCCESS)
295
 
                {
296
 
                        Log2(PCSC_LOG_ERROR, "Error communicating to: %s", lpcReader);
297
 
 
298
 
                        /*
299
 
                         * Set error status on this reader while errors occur 
300
 
                         */
301
 
 
302
 
                        rContext->readerState->readerState &= ~SCARD_ABSENT;
303
 
                        rContext->readerState->readerState &= ~SCARD_PRESENT;
304
 
                        rContext->readerState->readerState &= ~SCARD_POWERED;
305
 
                        rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
306
 
                        rContext->readerState->readerState &= ~SCARD_SPECIFIC;
307
 
                        rContext->readerState->readerState &= ~SCARD_SWALLOWED;
308
 
                        rContext->readerState->readerState |= SCARD_UNKNOWN;
309
 
                        rContext->readerState->cardAtrLength = 0;
310
 
                        rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
311
 
 
312
 
                        dwCurrentState = SCARD_UNKNOWN;
313
 
 
314
 
                        SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
315
 
 
316
 
                        /*
317
 
                         * This code causes race conditions on G4's with USB
318
 
                         * insertion 
319
 
                         */
320
 
                        /*
321
 
                         * dwErrorCount += 1; SYS_Sleep(1); 
322
 
                         */
323
 
                        /*
324
 
                         * After 10 seconds of errors, try to reinitialize the reader
325
 
                         * This sometimes helps bring readers out of *crazy* states. 
326
 
                         */
327
 
                        /*
328
 
                         * if ( dwErrorCount == 10 ) { RFUnInitializeReader( rContext
329
 
                         * ); RFInitializeReader( rContext ); dwErrorCount = 0; } 
330
 
                         */
331
 
 
332
 
                        /*
333
 
                         * End of race condition code block 
334
 
                         */
335
 
                }
336
 
 
337
 
                if (dwStatus & SCARD_ABSENT)
338
 
                {
339
 
                        if (dwCurrentState == SCARD_PRESENT ||
340
 
                                dwCurrentState == SCARD_UNKNOWN)
341
 
                        {
342
 
                                /*
343
 
                                 * Change the status structure 
344
 
                                 */
345
 
                                Log2(PCSC_LOG_INFO, "Card Removed From %s", lpcReader);
346
 
                                /*
347
 
                                 * Notify the card has been removed 
348
 
                                 */
349
 
                                RFSetReaderEventState(rContext, SCARD_REMOVED);
350
 
 
351
 
                                rContext->readerState->cardAtrLength = 0;
352
 
                                rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
353
 
                                rContext->readerState->readerState |= SCARD_ABSENT;
354
 
                                rContext->readerState->readerState &= ~SCARD_UNKNOWN;
355
 
                                rContext->readerState->readerState &= ~SCARD_PRESENT;
356
 
                                rContext->readerState->readerState &= ~SCARD_POWERED;
357
 
                                rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
358
 
                                rContext->readerState->readerState &= ~SCARD_SWALLOWED;
359
 
                                rContext->readerState->readerState &= ~SCARD_SPECIFIC;
360
 
                                dwCurrentState = SCARD_ABSENT;
361
 
 
362
 
                                SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
363
 
                        }
364
 
 
365
 
                }
366
 
                else if (dwStatus & SCARD_PRESENT)
367
 
                {
368
 
                        if (dwCurrentState == SCARD_ABSENT ||
369
 
                                dwCurrentState == SCARD_UNKNOWN)
370
 
                        {
371
 
                                /*
372
 
                                 * Power and reset the card 
373
 
                                 */
374
 
                                SYS_USleep(PCSCLITE_STATUS_WAIT);
375
 
                                rv = IFDPowerICC(rContext, IFD_POWER_UP,
376
 
                                        rContext->readerState->cardAtr,
377
 
                                        &rContext->readerState->cardAtrLength);
378
 
 
379
 
                                /* the protocol is unset after a power on */
380
 
                                rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
381
 
 
382
 
                                if (rv == IFD_SUCCESS)
383
 
                                {
384
 
                                        rContext->readerState->readerState |= SCARD_PRESENT;
385
 
                                        rContext->readerState->readerState &= ~SCARD_ABSENT;
386
 
                                        rContext->readerState->readerState |= SCARD_POWERED;
387
 
                                        rContext->readerState->readerState |= SCARD_NEGOTIABLE;
388
 
                                        rContext->readerState->readerState &= ~SCARD_SPECIFIC;
389
 
                                        rContext->readerState->readerState &= ~SCARD_UNKNOWN;
390
 
                                        rContext->readerState->readerState &= ~SCARD_SWALLOWED;
391
 
 
392
 
                                        /*
393
 
                                         * Notify the card has been reset 
394
 
                                         */
395
 
                                        RFSetReaderEventState(rContext, SCARD_RESET); 
396
 
                                }
397
 
                                else
398
 
                                {
399
 
                                        rContext->readerState->readerState |= SCARD_PRESENT;
400
 
                                        rContext->readerState->readerState &= ~SCARD_ABSENT;
401
 
                                        rContext->readerState->readerState |= SCARD_SWALLOWED;
402
 
                                        rContext->readerState->readerState &= ~SCARD_POWERED;
403
 
                                        rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
404
 
                                        rContext->readerState->readerState &= ~SCARD_SPECIFIC;
405
 
                                        rContext->readerState->readerState &= ~SCARD_UNKNOWN;
406
 
                                        rContext->readerState->cardAtrLength = 0;
407
 
                                }
408
 
 
409
 
                                dwCurrentState = SCARD_PRESENT;
410
 
 
411
 
                                SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
412
 
 
413
 
                                Log2(PCSC_LOG_INFO, "Card inserted into %s", lpcReader);
414
 
 
415
 
                                if (rv == IFD_SUCCESS)
416
 
                                {
417
 
                                        if (rContext->readerState->cardAtrLength > 0)
418
 
                                        {
419
 
                                                LogXxd(PCSC_LOG_INFO, "Card ATR: ",
420
 
                                                        rContext->readerState->cardAtr,
421
 
                                                        rContext->readerState->cardAtrLength);
422
 
                                        }
423
 
                                        else
424
 
                                                Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
425
 
                                }
426
 
                                else
427
 
                                        Log1(PCSC_LOG_ERROR,"Error powering up card.");
428
 
                        }
429
 
                }
430
 
 
431
 
                if (rContext->dwLockId == 0xFFFF)
432
 
                {
433
 
                        /*
434
 
                         * Exit and notify the caller 
435
 
                         */
436
 
                        rContext->dwLockId = 0;
437
 
                        SYS_ThreadDetach(rContext->pthThread);
438
 
                        SYS_ThreadExit(0);
439
 
                }
440
 
 
441
 
                /*
442
 
                 * Sharing may change w/o an event pass it on 
443
 
                 */
444
 
 
445
 
                if (dwReaderSharing != rContext->dwContexts)
446
 
                {
447
 
                        dwReaderSharing = rContext->dwContexts;
448
 
                        rContext->readerState->readerSharing = dwReaderSharing;
449
 
                        SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
450
 
                }
451
 
 
452
 
                SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
453
 
        }
454
 
}
455
 
 
456
 
void EHSetSharingEvent(PREADER_CONTEXT rContext, DWORD dwValue)
457
 
{
458
 
        rContext->readerState->lockState = dwValue;
459
 
}