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

« back to all changes in this revision

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