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

« back to all changes in this revision

Viewing changes to src/winscard_svc.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) 2001-2004
 
5
 *  David Corcoran <corcoran@linuxnet.com>
 
6
 *  Damien Sauveron <damien.sauveron@labri.fr>
 
7
 *  Ludovic Rousseau <ludovic.rousseau@free.fr>
 
8
 *
 
9
 * $Id: winscard_svc.c 1695 2005-10-29 16:27:33Z rousseau $
 
10
 */
 
11
 
 
12
/**
 
13
 * @file
 
14
 * @brief This demarshalls functions over the message queue and keeps
 
15
 * track of clients and their handles.
 
16
 *
 
17
 * Each Client message is deald by creating a thread (\c CreateContextThread).
 
18
 * The thread establishes reands and demarshalls the message and calls the
 
19
 * appropriate function to threat it.
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
#include <time.h>
 
24
#include <stdio.h>
 
25
#include <string.h>
 
26
 
 
27
#include "pcsclite.h"
 
28
#include "winscard.h"
 
29
#include "debuglog.h"
 
30
#include "winscard_msg.h"
 
31
#include "winscard_svc.h"
 
32
#include "sys_generic.h"
 
33
#include "thread_generic.h"
 
34
 
 
35
/**
 
36
 * @brief Represents the an Application Context on the Server side.
 
37
 *
 
38
 * An Application Context contains Channels (\c hCard).
 
39
 */
 
40
static struct _psContext
 
41
{
 
42
        SCARDCONTEXT hContext;
 
43
        SCARDHANDLE hCard[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
 
44
        DWORD dwClientID;                       /* Connection ID used to reference the Client. */
 
45
        PCSCLITE_THREAD_T pthThread;            /* Event polling thread's ID */
 
46
        sharedSegmentMsg msgStruct;             /* Msg sent by the Client */
 
47
        int protocol_major, protocol_minor;     /* Protocol number agreed between client and server*/
 
48
} psContext[PCSCLITE_MAX_APPLICATIONS_CONTEXTS];
 
49
 
 
50
/**
 
51
 * @brief Index of an avaiable Application Context slot in \c psContext.
 
52
 */
 
53
static DWORD dwNextContextIndex;
 
54
 
 
55
LONG MSGCheckHandleAssociation(SCARDHANDLE, DWORD);
 
56
LONG MSGFunctionDemarshall(psharedSegmentMsg, DWORD);
 
57
LONG MSGAddContext(SCARDCONTEXT, DWORD);
 
58
LONG MSGRemoveContext(SCARDCONTEXT, DWORD);
 
59
LONG MSGAddHandle(SCARDCONTEXT, SCARDHANDLE, DWORD);
 
60
LONG MSGRemoveHandle(SCARDHANDLE, DWORD);
 
61
LONG MSGCleanupClient(DWORD);
 
62
 
 
63
static void ContextThread(DWORD* pdwIndex);
 
64
 
 
65
LONG ContextsInitialize(void)
 
66
{
 
67
        memset(psContext, 0, sizeof(struct _psContext)*PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
 
68
        return 1;
 
69
}
 
70
 
 
71
/**
 
72
 * @brief Creates threads to handle messages received from Clients.
 
73
 *
 
74
 * @param[in] pdwClientID Connection ID used to reference the Client.
 
75
 *
 
76
 * @return Error code.
 
77
 * @retval SCARD_S_SUCCESS Success.
 
78
 * @retval SCARD_F_INTERNAL_ERROR Exceded the maximum number of simultaneous Application Contexts.
 
79
 * @retval SCARD_E_NO_MEMORY Error creating the Context Thread.
 
80
 */
 
81
LONG CreateContextThread(PDWORD pdwClientID)
 
82
{
 
83
        int i;
 
84
 
 
85
        for (i = 0; i < PCSCLITE_MAX_APPLICATIONS_CONTEXTS; i++)
 
86
        {
 
87
                if (psContext[i].dwClientID == 0)
 
88
                {
 
89
                        psContext[i].dwClientID = *pdwClientID;
 
90
                        *pdwClientID = 0;
 
91
                        break;
 
92
                }
 
93
        }
 
94
 
 
95
        if (i == PCSCLITE_MAX_APPLICATIONS_CONTEXTS)
 
96
        {
 
97
                SYS_CloseFile(psContext[i].dwClientID);
 
98
                psContext[i].dwClientID = 0; 
 
99
                return SCARD_F_INTERNAL_ERROR;
 
100
        }
 
101
        
 
102
        dwNextContextIndex = i;
 
103
 
 
104
        if (SYS_ThreadCreate(&psContext[i].pthThread, THREAD_ATTR_DETACHED,
 
105
                (PCSCLITE_THREAD_FUNCTION( )) ContextThread,
 
106
                (LPVOID) &dwNextContextIndex) != 1)
 
107
        {
 
108
                SYS_CloseFile(psContext[i].dwClientID);
 
109
                psContext[i].dwClientID = 0; 
 
110
                return SCARD_E_NO_MEMORY;
 
111
        }
 
112
 
 
113
        return SCARD_S_SUCCESS;
 
114
}
 
115
 
 
116
/*
 
117
 * A list of local functions used to keep track of clients and their
 
118
 * connections 
 
119
 */
 
120
 
 
121
/**
 
122
 * @brief Handles messages received from Clients.
 
123
 *
 
124
 * For each Client message a new instance of this thread is created.
 
125
 *
 
126
 * @param[in] pdwIndex Index of an avaiable Application Context slot in 
 
127
 * \c psContext.
 
128
 */
 
129
static void ContextThread(DWORD* pdwIndex)
 
130
{
 
131
        LONG rv;
 
132
        sharedSegmentMsg msgStruct;
 
133
        DWORD dwContextIndex = *pdwIndex;
 
134
 
 
135
        Log2(PCSC_LOG_DEBUG, "Thread is started: %d",
 
136
                psContext[dwContextIndex].dwClientID);
 
137
        
 
138
        while (1)
 
139
        {
 
140
                switch (rv = SHMProcessEventsContext(&psContext[dwContextIndex].dwClientID, &msgStruct, 0))
 
141
                {
 
142
                case 0:
 
143
                        if (msgStruct.mtype == CMD_CLIENT_DIED)
 
144
                        {
 
145
                                /*
 
146
                                 * Clean up the dead client
 
147
                                 */
 
148
                                Log2(PCSC_LOG_DEBUG, "Client die: %d",
 
149
                                        psContext[dwContextIndex].dwClientID);
 
150
                                MSGCleanupClient(dwContextIndex);
 
151
                                SYS_ThreadExit((LPVOID) NULL);
 
152
                        } 
 
153
                        break;
 
154
 
 
155
                case 1:
 
156
                        if (msgStruct.mtype == CMD_FUNCTION)
 
157
                        {
 
158
                                /*
 
159
                                 * Command must be found
 
160
                                 */
 
161
                                MSGFunctionDemarshall(&msgStruct, dwContextIndex);
 
162
                                rv = SHMMessageSend(&msgStruct, psContext[dwContextIndex].dwClientID,
 
163
                                                    PCSCLITE_SERVER_ATTEMPTS);
 
164
                        }
 
165
                        else
 
166
                                /* pcsc-lite client/server protocol version */
 
167
                                if (msgStruct.mtype == CMD_VERSION)
 
168
                                {
 
169
                                        version_struct *veStr;
 
170
                                        veStr = (version_struct *) msgStruct.data;
 
171
 
 
172
                                        /* get the client protocol version */
 
173
                                        psContext[dwContextIndex].protocol_major = veStr->major;
 
174
                                        psContext[dwContextIndex].protocol_minor = veStr->minor;
 
175
 
 
176
                                        Log3(PCSC_LOG_DEBUG,
 
177
                                                "Client is protocol version %d:%d",
 
178
                                                veStr->major, veStr->minor);
 
179
 
 
180
                                        /* set the server protocol version */
 
181
                                        veStr->major = PROTOCOL_VERSION_MAJOR;
 
182
                                        veStr->minor = PROTOCOL_VERSION_MINOR;
 
183
                                        veStr->rv = SCARD_S_SUCCESS;
 
184
 
 
185
                                        /* send back the response */
 
186
                                        rv = SHMMessageSend(&msgStruct,
 
187
                                                psContext[dwContextIndex].dwClientID,
 
188
                                            PCSCLITE_SERVER_ATTEMPTS);
 
189
                                }
 
190
                                else
 
191
                                        continue;
 
192
 
 
193
                        break;
 
194
 
 
195
                case 2:
 
196
                        /*
 
197
                         * timeout in SHMProcessEventsContext(): do nothing
 
198
                         * this is used to catch the Ctrl-C signal at some time when
 
199
                         * nothing else happens
 
200
                         */
 
201
                        break;
 
202
                        
 
203
                case -1:
 
204
                        Log1(PCSC_LOG_ERROR, "Error in SHMProcessEventsContext");
 
205
                        break;
 
206
                        
 
207
                default:
 
208
                        Log2(PCSC_LOG_ERROR,
 
209
                                "SHMProcessEventsContext unknown retval: %d", rv);
 
210
                        break;
 
211
                }
 
212
        }
 
213
}
 
214
 
 
215
/**
 
216
 * @brief Find out which message was sent by the Client and execute the right task.
 
217
 *
 
218
 * According to the command type sent by the client (\c pcsc_msg_commands),
 
219
 * cast the message data to the correct struct so that is can be demarshalled.
 
220
 * Then call the appropriate function to handle the request.
 
221
 *
 
222
 * Possible structs are: \c establish_struct \c release_struct 
 
223
 * \c connect_struct \c reconnect_struct \c disconnect_struct \c begin_struct
 
224
 * \c cancel_struct \c end_struct \c status_struct \c transmit_struct
 
225
 * \c control_struct \c getset_struct.
 
226
 *
 
227
 * @param[in] msgStruct Message to be demarshalled and executed.
 
228
 * @param[in] dwContextIndex 
 
229
 */
 
230
LONG MSGFunctionDemarshall(psharedSegmentMsg msgStruct, DWORD dwContextIndex)
 
231
{
 
232
        LONG rv;
 
233
        establish_struct *esStr;
 
234
        release_struct *reStr;
 
235
        connect_struct *coStr;
 
236
        reconnect_struct *rcStr;
 
237
        disconnect_struct *diStr;
 
238
        begin_struct *beStr;
 
239
        cancel_struct *caStr;
 
240
        end_struct *enStr;
 
241
        status_struct *stStr;
 
242
        transmit_struct *trStr;
 
243
        control_struct *ctStr;
 
244
        getset_struct *gsStr;
 
245
 
 
246
        /*
 
247
         * Zero out everything 
 
248
         */
 
249
        rv = 0;
 
250
        switch (msgStruct->command)
 
251
        {
 
252
 
 
253
        case SCARD_ESTABLISH_CONTEXT:
 
254
                esStr = ((establish_struct *) msgStruct->data);
 
255
                esStr->rv = SCardEstablishContext(esStr->dwScope, 0, 0,
 
256
                        &esStr->phContext);
 
257
 
 
258
                if (esStr->rv == SCARD_S_SUCCESS)
 
259
                        esStr->rv =
 
260
                                MSGAddContext(esStr->phContext, dwContextIndex);
 
261
                break;
 
262
 
 
263
        case SCARD_RELEASE_CONTEXT:
 
264
                reStr = ((release_struct *) msgStruct->data);
 
265
                reStr->rv = SCardReleaseContext(reStr->hContext);
 
266
 
 
267
                if (reStr->rv == SCARD_S_SUCCESS)
 
268
                        reStr->rv =
 
269
                                MSGRemoveContext(reStr->hContext, dwContextIndex);
 
270
 
 
271
                break;
 
272
 
 
273
        case SCARD_CONNECT:
 
274
                coStr = ((connect_struct *) msgStruct->data);
 
275
                coStr->rv = SCardConnect(coStr->hContext, coStr->szReader,
 
276
                        coStr->dwShareMode, coStr->dwPreferredProtocols,
 
277
                        &coStr->phCard, &coStr->pdwActiveProtocol);
 
278
 
 
279
                if (coStr->rv == SCARD_S_SUCCESS)
 
280
                        coStr->rv =
 
281
                                MSGAddHandle(coStr->hContext, coStr->phCard, dwContextIndex);
 
282
 
 
283
                break;
 
284
 
 
285
        case SCARD_RECONNECT:
 
286
                rcStr = ((reconnect_struct *) msgStruct->data);
 
287
                rv = MSGCheckHandleAssociation(rcStr->hCard, dwContextIndex);
 
288
                if (rv != 0) return rv;
 
289
 
 
290
                rcStr->rv = SCardReconnect(rcStr->hCard, rcStr->dwShareMode,
 
291
                        rcStr->dwPreferredProtocols,
 
292
                        rcStr->dwInitialization, &rcStr->pdwActiveProtocol);
 
293
                break;
 
294
 
 
295
        case SCARD_DISCONNECT:
 
296
                diStr = ((disconnect_struct *) msgStruct->data);
 
297
                rv = MSGCheckHandleAssociation(diStr->hCard, dwContextIndex);
 
298
                if (rv != 0) return rv;
 
299
                diStr->rv = SCardDisconnect(diStr->hCard, diStr->dwDisposition);
 
300
 
 
301
                if (diStr->rv == SCARD_S_SUCCESS)
 
302
                        diStr->rv =
 
303
                                MSGRemoveHandle(diStr->hCard, dwContextIndex);
 
304
                break;
 
305
 
 
306
        case SCARD_BEGIN_TRANSACTION:
 
307
                beStr = ((begin_struct *) msgStruct->data);
 
308
                rv = MSGCheckHandleAssociation(beStr->hCard, dwContextIndex);
 
309
                if (rv != 0) return rv;
 
310
                beStr->rv = SCardBeginTransaction(beStr->hCard);
 
311
                break;
 
312
 
 
313
        case SCARD_END_TRANSACTION:
 
314
                enStr = ((end_struct *) msgStruct->data);
 
315
                rv = MSGCheckHandleAssociation(enStr->hCard, dwContextIndex);
 
316
                if (rv != 0) return rv;
 
317
                enStr->rv =
 
318
                        SCardEndTransaction(enStr->hCard, enStr->dwDisposition);
 
319
                break;
 
320
 
 
321
        case SCARD_CANCEL_TRANSACTION:
 
322
                caStr = ((cancel_struct *) msgStruct->data);
 
323
                rv = MSGCheckHandleAssociation(caStr->hCard, dwContextIndex);
 
324
                if (rv != 0) return rv;
 
325
                caStr->rv = SCardCancelTransaction(caStr->hCard);
 
326
                break;
 
327
 
 
328
        case SCARD_STATUS:
 
329
                stStr = ((status_struct *) msgStruct->data);
 
330
                rv = MSGCheckHandleAssociation(stStr->hCard, dwContextIndex);
 
331
                if (rv != 0) return rv;
 
332
                stStr->rv = SCardStatus(stStr->hCard, stStr->mszReaderNames,
 
333
                        &stStr->pcchReaderLen, &stStr->pdwState,
 
334
                        &stStr->pdwProtocol, stStr->pbAtr, &stStr->pcbAtrLen);
 
335
                break;
 
336
 
 
337
        case SCARD_TRANSMIT:
 
338
                trStr = ((transmit_struct *) msgStruct->data);
 
339
                rv = MSGCheckHandleAssociation(trStr->hCard, dwContextIndex);
 
340
                if (rv != 0) return rv;
 
341
                trStr->rv = SCardTransmit(trStr->hCard, &trStr->pioSendPci,
 
342
                        trStr->pbSendBuffer, trStr->cbSendLength,
 
343
                        &trStr->pioRecvPci, trStr->pbRecvBuffer,
 
344
                        &trStr->pcbRecvLength);
 
345
                break;
 
346
 
 
347
        case SCARD_CONTROL:
 
348
                ctStr = ((control_struct *) msgStruct->data);
 
349
                rv = MSGCheckHandleAssociation(ctStr->hCard, dwContextIndex);
 
350
                if (rv != 0) return rv;
 
351
                ctStr->rv = SCardControl(ctStr->hCard, ctStr->dwControlCode,
 
352
                        ctStr->pbSendBuffer, ctStr->cbSendLength,
 
353
                        ctStr->pbRecvBuffer, ctStr->cbRecvLength,
 
354
                        &ctStr->dwBytesReturned);
 
355
                break;
 
356
 
 
357
        case SCARD_GET_ATTRIB:
 
358
                gsStr = ((getset_struct *) msgStruct->data);
 
359
                rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
 
360
                if (rv != 0) return rv;
 
361
                gsStr->rv = SCardGetAttrib(gsStr->hCard, gsStr->dwAttrId,
 
362
                        gsStr->pbAttr, &gsStr->cbAttrLen);
 
363
                break;
 
364
 
 
365
        case SCARD_SET_ATTRIB:
 
366
                gsStr = ((getset_struct *) msgStruct->data);
 
367
                rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
 
368
                if (rv != 0) return rv;
 
369
                gsStr->rv = SCardSetAttrib(gsStr->hCard, gsStr->dwAttrId,
 
370
                        gsStr->pbAttr, gsStr->cbAttrLen);
 
371
                break;
 
372
 
 
373
        default:
 
374
                return -1;
 
375
        }
 
376
 
 
377
        return 0;
 
378
}
 
379
 
 
380
LONG MSGAddContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
 
381
{
 
382
        psContext[dwContextIndex].hContext = hContext;
 
383
        return SCARD_S_SUCCESS;
 
384
}
 
385
 
 
386
LONG MSGRemoveContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
 
387
{
 
388
        int i;
 
389
        LONG rv;
 
390
 
 
391
        if (psContext[dwContextIndex].hContext == hContext)
 
392
        {
 
393
 
 
394
                for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
 
395
                {
 
396
                        /*
 
397
                         * Disconnect each of these just in case 
 
398
                         */
 
399
                        
 
400
                        if (psContext[dwContextIndex].hCard[i] != 0)
 
401
                        {
 
402
                                
 
403
                                /*
 
404
                                 * We will use SCardStatus to see if the card has been 
 
405
                                 * reset there is no need to reset each time
 
406
                                 * Disconnect is called 
 
407
                                 */
 
408
                                
 
409
                                rv = SCardStatus(psContext[dwContextIndex].hCard[i], 0, 0, 0, 0, 0, 0);
 
410
                                
 
411
                                if (rv == SCARD_W_RESET_CARD
 
412
                                    || rv == SCARD_W_REMOVED_CARD)
 
413
                                {
 
414
                                        SCardDisconnect(psContext[dwContextIndex].hCard[i], SCARD_LEAVE_CARD);
 
415
                                } else
 
416
                                {
 
417
                                        SCardDisconnect(psContext[dwContextIndex].hCard[i], SCARD_RESET_CARD);
 
418
                                }
 
419
 
 
420
                                psContext[dwContextIndex].hCard[i] = 0;
 
421
                        }
 
422
 
 
423
                }
 
424
 
 
425
                psContext[dwContextIndex].hContext = 0;
 
426
                return SCARD_S_SUCCESS;
 
427
        } 
 
428
 
 
429
        return SCARD_E_INVALID_VALUE;
 
430
}
 
431
 
 
432
LONG MSGAddHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard, DWORD dwContextIndex)
 
433
{
 
434
        int i;
 
435
 
 
436
        if (psContext[dwContextIndex].hContext == hContext)
 
437
        {
 
438
                
 
439
                /*
 
440
                 * Find an empty spot to put the hCard value 
 
441
                 */
 
442
                for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
 
443
                {
 
444
                        if (psContext[dwContextIndex].hCard[i] == 0)
 
445
                        {
 
446
                                psContext[dwContextIndex].hCard[i] = hCard;
 
447
                                break;
 
448
                        }
 
449
                }
 
450
                
 
451
                if (i == PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS)
 
452
                {
 
453
                        return SCARD_F_INTERNAL_ERROR;
 
454
                } else
 
455
                {
 
456
                        return SCARD_S_SUCCESS;
 
457
                }
 
458
 
 
459
        }
 
460
        
 
461
        return SCARD_E_INVALID_VALUE;
 
462
}
 
463
 
 
464
LONG MSGRemoveHandle(SCARDHANDLE hCard, DWORD dwContextIndex)
 
465
{
 
466
        int i;
 
467
 
 
468
        for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
 
469
        {
 
470
                if (psContext[dwContextIndex].hCard[i] == hCard)
 
471
                {
 
472
                        psContext[dwContextIndex].hCard[i] = 0;
 
473
                        return SCARD_S_SUCCESS;
 
474
                }
 
475
        }
 
476
 
 
477
        return SCARD_E_INVALID_VALUE;
 
478
}
 
479
 
 
480
 
 
481
LONG MSGCheckHandleAssociation(SCARDHANDLE hCard, DWORD dwContextIndex)
 
482
{
 
483
        int i;
 
484
 
 
485
        for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
 
486
        {
 
487
                if (psContext[dwContextIndex].hCard[i] == hCard)
 
488
                {
 
489
                        return 0;
 
490
                }
 
491
        }
 
492
        
 
493
        /* Must be a rogue client, debug log and sleep a couple of seconds */
 
494
        Log1(PCSC_LOG_ERROR, "Client failed to authenticate");
 
495
        SYS_Sleep(2);
 
496
 
 
497
        return -1;
 
498
}
 
499
 
 
500
LONG MSGCleanupClient(DWORD dwContextIndex)
 
501
{
 
502
        if (psContext[dwContextIndex].hContext != 0)
 
503
        {
 
504
                SCardReleaseContext(psContext[dwContextIndex].hContext);        
 
505
                MSGRemoveContext(psContext[dwContextIndex].hContext, dwContextIndex);
 
506
        }
 
507
 
 
508
        psContext[dwContextIndex].dwClientID = 0;
 
509
        psContext[dwContextIndex].protocol_major = 0;
 
510
        psContext[dwContextIndex].protocol_minor = 0;
 
511
        
 
512
        return 0;
 
513
}