~ubuntu-branches/ubuntu/precise/nss/precise-security

« back to all changes in this revision

Viewing changes to nss/lib/pk11wrap/pk11util.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2013-11-14 14:58:07 UTC
  • mfrom: (1.1.19)
  • Revision ID: package-import@ubuntu.com-20131114145807-ay302kimn72ovt88
Tags: 3.15.3-0ubuntu0.12.04.1
* SECURITY UPDATE: New upstream release to fix multiple security issues
  and add TLSv1.2 support.
  - CVE-2013-1739
  - CVE-2013-1741
  - CVE-2013-5605
  - CVE-2013-5606
* Adjusted packaging for 3.15.3:
  - debian/patches/*: refreshed.
  - debian/patches/lower-dhe-priority.patch: removed, no longer needed,
    was a workaround for an old version of firefox.
  - debian/libnss3.symbols: added new symbols.
  - debian/rules: updated for new source layout.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This Source Code Form is subject to the terms of the Mozilla Public
 
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
4
/*
 
5
 * Initialize the PCKS 11 subsystem
 
6
 */
 
7
#include "seccomon.h"
 
8
#include "secmod.h"
 
9
#include "nssilock.h"
 
10
#include "secmodi.h"
 
11
#include "secmodti.h"
 
12
#include "pk11func.h"
 
13
#include "pki3hack.h"
 
14
#include "secerr.h"
 
15
#include "dev.h"
 
16
#include "utilpars.h"
 
17
 
 
18
/* these are for displaying error messages */
 
19
 
 
20
static  SECMODModuleList *modules = NULL;
 
21
static  SECMODModuleList *modulesDB = NULL;
 
22
static  SECMODModuleList *modulesUnload = NULL;
 
23
static  SECMODModule *internalModule = NULL;
 
24
static  SECMODModule *defaultDBModule = NULL;
 
25
static  SECMODModule *pendingModule = NULL;
 
26
static SECMODListLock *moduleLock = NULL;
 
27
 
 
28
int secmod_PrivateModuleCount = 0;
 
29
 
 
30
extern PK11DefaultArrayEntry PK11_DefaultArray[];
 
31
extern int num_pk11_default_mechanisms;
 
32
 
 
33
 
 
34
void
 
35
SECMOD_Init() 
 
36
{
 
37
    /* don't initialize twice */
 
38
    if (moduleLock) return;
 
39
 
 
40
    moduleLock = SECMOD_NewListLock();
 
41
    PK11_InitSlotLists();
 
42
}
 
43
 
 
44
 
 
45
SECStatus
 
46
SECMOD_Shutdown() 
 
47
{
 
48
    /* destroy the lock */
 
49
    if (moduleLock) {
 
50
        SECMOD_DestroyListLock(moduleLock);
 
51
        moduleLock = NULL;
 
52
    }
 
53
    /* free the internal module */
 
54
    if (internalModule) {
 
55
        SECMOD_DestroyModule(internalModule);
 
56
        internalModule = NULL;
 
57
    }
 
58
 
 
59
    /* free the default database module */
 
60
    if (defaultDBModule) {
 
61
        SECMOD_DestroyModule(defaultDBModule);
 
62
        defaultDBModule = NULL;
 
63
    }
 
64
        
 
65
    /* destroy the list */
 
66
    if (modules) {
 
67
        SECMOD_DestroyModuleList(modules);
 
68
        modules = NULL;
 
69
    }
 
70
   
 
71
    if (modulesDB) {
 
72
        SECMOD_DestroyModuleList(modulesDB);
 
73
        modulesDB = NULL;
 
74
    }
 
75
 
 
76
    if (modulesUnload) {
 
77
        SECMOD_DestroyModuleList(modulesUnload);
 
78
        modulesUnload = NULL;
 
79
    }
 
80
 
 
81
    /* make all the slots and the lists go away */
 
82
    PK11_DestroySlotLists();
 
83
 
 
84
    nss_DumpModuleLog();
 
85
 
 
86
#ifdef DEBUG
 
87
    if (PR_GetEnv("NSS_STRICT_SHUTDOWN")) {
 
88
        PORT_Assert(secmod_PrivateModuleCount == 0);
 
89
    }
 
90
#endif
 
91
    if (secmod_PrivateModuleCount) {
 
92
        PORT_SetError(SEC_ERROR_BUSY);
 
93
        return SECFailure;
 
94
    }
 
95
    return SECSuccess;
 
96
}
 
97
 
 
98
 
 
99
/*
 
100
 * retrieve the internal module
 
101
 */
 
102
SECMODModule *
 
103
SECMOD_GetInternalModule(void)
 
104
{
 
105
   return internalModule;
 
106
}
 
107
 
 
108
 
 
109
SECStatus
 
110
secmod_AddModuleToList(SECMODModuleList **moduleList,SECMODModule *newModule)
 
111
{
 
112
    SECMODModuleList *mlp, *newListElement, *last = NULL;
 
113
 
 
114
    newListElement = SECMOD_NewModuleListElement();
 
115
    if (newListElement == NULL) {
 
116
        return SECFailure;
 
117
    }
 
118
 
 
119
    newListElement->module = SECMOD_ReferenceModule(newModule);
 
120
 
 
121
    SECMOD_GetWriteLock(moduleLock);
 
122
    /* Added it to the end (This is very inefficient, but Adding a module
 
123
     * on the fly should happen maybe 2-3 times through the life this program
 
124
     * on a given computer, and this list should be *SHORT*. */
 
125
    for(mlp = *moduleList; mlp != NULL; mlp = mlp->next) {
 
126
        last = mlp;
 
127
    }
 
128
 
 
129
    if (last == NULL) {
 
130
        *moduleList = newListElement;
 
131
    } else {
 
132
        SECMOD_AddList(last,newListElement,NULL);
 
133
    }
 
134
    SECMOD_ReleaseWriteLock(moduleLock);
 
135
    return SECSuccess;
 
136
}
 
137
 
 
138
SECStatus
 
139
SECMOD_AddModuleToList(SECMODModule *newModule)
 
140
{
 
141
    if (newModule->internal && !internalModule) {
 
142
        internalModule = SECMOD_ReferenceModule(newModule);
 
143
    }
 
144
    return secmod_AddModuleToList(&modules,newModule);
 
145
}
 
146
 
 
147
SECStatus
 
148
SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule)
 
149
{
 
150
    if (defaultDBModule && SECMOD_GetDefaultModDBFlag(newModule)) {
 
151
        SECMOD_DestroyModule(defaultDBModule);
 
152
        defaultDBModule = SECMOD_ReferenceModule(newModule);
 
153
    } else if (defaultDBModule == NULL) {
 
154
        defaultDBModule = SECMOD_ReferenceModule(newModule);
 
155
    }
 
156
    return secmod_AddModuleToList(&modulesDB,newModule);
 
157
}
 
158
 
 
159
SECStatus
 
160
SECMOD_AddModuleToUnloadList(SECMODModule *newModule)
 
161
{
 
162
    return secmod_AddModuleToList(&modulesUnload,newModule);
 
163
}
 
164
 
 
165
/*
 
166
 * get the list of PKCS11 modules that are available.
 
167
 */
 
168
SECMODModuleList * SECMOD_GetDefaultModuleList() { return modules; }
 
169
SECMODModuleList *SECMOD_GetDeadModuleList() { return modulesUnload; }
 
170
SECMODModuleList *SECMOD_GetDBModuleList() { return modulesDB; }
 
171
 
 
172
/*
 
173
 * This lock protects the global module lists.
 
174
 * it also protects changes to the slot array (module->slots[]) and slot count 
 
175
 * (module->slotCount) in each module. It is a read/write lock with multiple 
 
176
 * readers or one writer. Writes are uncommon. 
 
177
 * Because of legacy considerations protection of the slot array and count is 
 
178
 * only necessary in applications if the application calls 
 
179
 * SECMOD_UpdateSlotList() or SECMOD_WaitForAnyTokenEvent(), though all new
 
180
 * applications are encouraged to acquire this lock when reading the
 
181
 * slot array information directly.
 
182
 */
 
183
SECMODListLock *SECMOD_GetDefaultModuleListLock() { return moduleLock; }
 
184
 
 
185
 
 
186
 
 
187
/*
 
188
 * find a module by name, and add a reference to it.
 
189
 * return that module.
 
190
 */
 
191
SECMODModule *
 
192
SECMOD_FindModule(const char *name)
 
193
{
 
194
    SECMODModuleList *mlp;
 
195
    SECMODModule *module = NULL;
 
196
 
 
197
    if (!moduleLock) {
 
198
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
199
        return module;
 
200
    }
 
201
    SECMOD_GetReadLock(moduleLock);
 
202
    for(mlp = modules; mlp != NULL; mlp = mlp->next) {
 
203
        if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
 
204
            module = mlp->module;
 
205
            SECMOD_ReferenceModule(module);
 
206
            break;
 
207
        }
 
208
    }
 
209
    if (module) {
 
210
        goto found;
 
211
    }
 
212
    for(mlp = modulesUnload; mlp != NULL; mlp = mlp->next) {
 
213
        if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
 
214
            module = mlp->module;
 
215
            SECMOD_ReferenceModule(module);
 
216
            break;
 
217
        }
 
218
    }
 
219
 
 
220
found:
 
221
    SECMOD_ReleaseReadLock(moduleLock);
 
222
 
 
223
    return module;
 
224
}
 
225
 
 
226
/*
 
227
 * find a module by ID, and add a reference to it.
 
228
 * return that module.
 
229
 */
 
230
SECMODModule *
 
231
SECMOD_FindModuleByID(SECMODModuleID id) 
 
232
{
 
233
    SECMODModuleList *mlp;
 
234
    SECMODModule *module = NULL;
 
235
 
 
236
    if (!moduleLock) {
 
237
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
238
        return module;
 
239
    }
 
240
    SECMOD_GetReadLock(moduleLock);
 
241
    for(mlp = modules; mlp != NULL; mlp = mlp->next) {
 
242
        if (id == mlp->module->moduleID) {
 
243
            module = mlp->module;
 
244
            SECMOD_ReferenceModule(module);
 
245
            break;
 
246
        }
 
247
    }
 
248
    SECMOD_ReleaseReadLock(moduleLock);
 
249
    if (module == NULL) {
 
250
        PORT_SetError(SEC_ERROR_NO_MODULE);
 
251
    }
 
252
    return module;
 
253
}
 
254
 
 
255
/*
 
256
 * find the function pointer.
 
257
 */
 
258
SECMODModule *
 
259
secmod_FindModuleByFuncPtr(void *funcPtr) 
 
260
{
 
261
    SECMODModuleList *mlp;
 
262
    SECMODModule *module = NULL;
 
263
 
 
264
    SECMOD_GetReadLock(moduleLock);
 
265
    for(mlp = modules; mlp != NULL; mlp = mlp->next) {
 
266
        /* paranoia, shouldn't ever happen */
 
267
        if (!mlp->module) {
 
268
            continue;
 
269
        }
 
270
        if (funcPtr == mlp->module->functionList) {
 
271
            module = mlp->module;
 
272
            SECMOD_ReferenceModule(module);
 
273
            break;
 
274
        }
 
275
    }
 
276
    SECMOD_ReleaseReadLock(moduleLock);
 
277
    if (module == NULL) {
 
278
        PORT_SetError(SEC_ERROR_NO_MODULE);
 
279
    }
 
280
    return module;
 
281
}
 
282
 
 
283
/*
 
284
 * Find the Slot based on ID and the module.
 
285
 */
 
286
PK11SlotInfo *
 
287
SECMOD_FindSlotByID(SECMODModule *module, CK_SLOT_ID slotID)
 
288
{
 
289
    int i;
 
290
    PK11SlotInfo *slot = NULL;
 
291
 
 
292
    if (!moduleLock) {
 
293
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
294
        return slot;
 
295
    }
 
296
    SECMOD_GetReadLock(moduleLock);
 
297
    for (i=0; i < module->slotCount; i++) {
 
298
        PK11SlotInfo *cSlot = module->slots[i];
 
299
 
 
300
        if (cSlot->slotID == slotID) {
 
301
            slot = PK11_ReferenceSlot(cSlot);
 
302
            break;
 
303
        }
 
304
    }
 
305
    SECMOD_ReleaseReadLock(moduleLock);
 
306
 
 
307
    if (slot == NULL) {
 
308
        PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
 
309
    }
 
310
    return slot;
 
311
}
 
312
 
 
313
/*
 
314
 * lookup the Slot module based on it's module ID and slot ID.
 
315
 */
 
316
PK11SlotInfo *
 
317
SECMOD_LookupSlot(SECMODModuleID moduleID,CK_SLOT_ID slotID) 
 
318
{
 
319
    SECMODModule *module;
 
320
    PK11SlotInfo *slot;
 
321
 
 
322
    module = SECMOD_FindModuleByID(moduleID);
 
323
    if (module == NULL) return NULL;
 
324
 
 
325
    slot = SECMOD_FindSlotByID(module, slotID);
 
326
    SECMOD_DestroyModule(module);
 
327
    return slot;
 
328
}
 
329
 
 
330
 
 
331
/*
 
332
 * find a module by name or module pointer and delete it off the module list.
 
333
 * optionally remove it from secmod.db.
 
334
 */
 
335
SECStatus
 
336
SECMOD_DeleteModuleEx(const char *name, SECMODModule *mod, 
 
337
                                                int *type, PRBool permdb) 
 
338
{
 
339
    SECMODModuleList *mlp;
 
340
    SECMODModuleList **mlpp;
 
341
    SECStatus rv = SECFailure;
 
342
 
 
343
    if (!moduleLock) {
 
344
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
345
        return rv;
 
346
    }
 
347
 
 
348
    *type = SECMOD_EXTERNAL;
 
349
 
 
350
    SECMOD_GetWriteLock(moduleLock);
 
351
    for (mlpp = &modules,mlp = modules; 
 
352
                                mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
 
353
        if ((name && (PORT_Strcmp(name,mlp->module->commonName) == 0)) ||
 
354
                                                        mod == mlp->module) {
 
355
            /* don't delete the internal module */
 
356
            if (!mlp->module->internal) {
 
357
                SECMOD_RemoveList(mlpp,mlp);
 
358
                /* delete it after we release the lock */
 
359
                rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module);
 
360
            } else if (mlp->module->isFIPS) {
 
361
                *type = SECMOD_FIPS;
 
362
            } else {
 
363
                *type = SECMOD_INTERNAL;
 
364
            }
 
365
            break;
 
366
        }
 
367
    }
 
368
    if (mlp) {
 
369
        goto found;
 
370
    }
 
371
    /* not on the internal list, check the unload list */
 
372
    for (mlpp = &modulesUnload,mlp = modulesUnload; 
 
373
                                mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
 
374
        if ((name && (PORT_Strcmp(name,mlp->module->commonName) == 0)) ||
 
375
                                                        mod == mlp->module) {
 
376
            /* don't delete the internal module */
 
377
            if (!mlp->module->internal) {
 
378
                SECMOD_RemoveList(mlpp,mlp);
 
379
                rv = SECSuccess;
 
380
            } else if (mlp->module->isFIPS) {
 
381
                *type = SECMOD_FIPS;
 
382
            } else {
 
383
                *type = SECMOD_INTERNAL;
 
384
            }
 
385
            break;
 
386
        }
 
387
    }
 
388
found:
 
389
    SECMOD_ReleaseWriteLock(moduleLock);
 
390
 
 
391
 
 
392
    if (rv == SECSuccess) {
 
393
        if (permdb) {
 
394
            SECMOD_DeletePermDB(mlp->module);
 
395
        }
 
396
        SECMOD_DestroyModuleListElement(mlp);
 
397
    }
 
398
    return rv;
 
399
}
 
400
 
 
401
/*
 
402
 * find a module by name and delete it off the module list
 
403
 */
 
404
SECStatus
 
405
SECMOD_DeleteModule(const char *name, int *type) 
 
406
{
 
407
    return SECMOD_DeleteModuleEx(name, NULL, type, PR_TRUE);
 
408
}
 
409
 
 
410
/*
 
411
 * find a module by name and delete it off the module list
 
412
 */
 
413
SECStatus
 
414
SECMOD_DeleteInternalModule(const char *name) 
 
415
{
 
416
    SECMODModuleList *mlp;
 
417
    SECMODModuleList **mlpp;
 
418
    SECStatus rv = SECFailure;
 
419
 
 
420
    if (pendingModule) {
 
421
        PORT_SetError(SEC_ERROR_MODULE_STUCK);
 
422
        return rv;
 
423
    }
 
424
    if (!moduleLock) {
 
425
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
426
        return rv;
 
427
    }
 
428
 
 
429
    SECMOD_GetWriteLock(moduleLock);
 
430
    for(mlpp = &modules,mlp = modules; 
 
431
                                mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
 
432
        if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
 
433
            /* don't delete the internal module */
 
434
            if (mlp->module->internal) {
 
435
                SECMOD_RemoveList(mlpp,mlp);
 
436
                rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module);
 
437
            } 
 
438
            break;
 
439
        }
 
440
    }
 
441
    SECMOD_ReleaseWriteLock(moduleLock);
 
442
 
 
443
    if (rv == SECSuccess) {
 
444
        SECMODModule *newModule,*oldModule;
 
445
 
 
446
        if (mlp->module->isFIPS) {
 
447
            newModule = SECMOD_CreateModule(NULL, SECMOD_INT_NAME,
 
448
                                NULL, SECMOD_INT_FLAGS);
 
449
        } else {
 
450
            newModule = SECMOD_CreateModule(NULL, SECMOD_FIPS_NAME,
 
451
                                NULL, SECMOD_FIPS_FLAGS);
 
452
        }
 
453
        if (newModule) {
 
454
            PK11SlotInfo *slot;
 
455
            newModule->libraryParams = 
 
456
             PORT_ArenaStrdup(newModule->arena,mlp->module->libraryParams);
 
457
            /* if an explicit internal key slot has been set, reset it */
 
458
            slot = pk11_SwapInternalKeySlot(NULL);
 
459
            if (slot) {
 
460
                secmod_SetInternalKeySlotFlag(newModule, PR_TRUE);
 
461
            }
 
462
            rv = SECMOD_AddModule(newModule);
 
463
            if (rv != SECSuccess) {
 
464
                /* load failed, restore the internal key slot */
 
465
                pk11_SetInternalKeySlot(slot);
 
466
                SECMOD_DestroyModule(newModule);
 
467
                newModule = NULL;
 
468
            }
 
469
            /* free the old explicit internal key slot, we now have a new one */
 
470
            if (slot) {
 
471
                PK11_FreeSlot(slot);
 
472
            }
 
473
        }
 
474
        if (newModule == NULL) {
 
475
            SECMODModuleList *last = NULL,*mlp2;
 
476
           /* we're in pretty deep trouble if this happens...Security
 
477
            * not going to work well... try to put the old module back on
 
478
            * the list */
 
479
           SECMOD_GetWriteLock(moduleLock);
 
480
           for(mlp2 = modules; mlp2 != NULL; mlp2 = mlp->next) {
 
481
                last = mlp2;
 
482
           }
 
483
 
 
484
           if (last == NULL) {
 
485
                modules = mlp;
 
486
           } else {
 
487
                SECMOD_AddList(last,mlp,NULL);
 
488
           }
 
489
           SECMOD_ReleaseWriteLock(moduleLock);
 
490
           return SECFailure; 
 
491
        }
 
492
        pendingModule = oldModule = internalModule;
 
493
        internalModule = NULL;
 
494
        SECMOD_DestroyModule(oldModule);
 
495
        SECMOD_DeletePermDB(mlp->module);
 
496
        SECMOD_DestroyModuleListElement(mlp);
 
497
        internalModule = newModule; /* adopt the module */
 
498
    }
 
499
    return rv;
 
500
}
 
501
 
 
502
SECStatus
 
503
SECMOD_AddModule(SECMODModule *newModule) 
 
504
{
 
505
    SECStatus rv;
 
506
    SECMODModule *oldModule;
 
507
 
 
508
    /* Test if a module w/ the same name already exists */
 
509
    /* and return SECWouldBlock if so. */
 
510
    /* We should probably add a new return value such as */
 
511
    /* SECDublicateModule, but to minimize ripples, I'll */
 
512
    /* give SECWouldBlock a new meaning */
 
513
    if ((oldModule = SECMOD_FindModule(newModule->commonName)) != NULL) {
 
514
        SECMOD_DestroyModule(oldModule);
 
515
        return SECWouldBlock;
 
516
        /* module already exists. */
 
517
    }
 
518
 
 
519
    rv = secmod_LoadPKCS11Module(newModule, NULL);
 
520
    if (rv != SECSuccess) {
 
521
        return rv;
 
522
    }
 
523
 
 
524
    if (newModule->parent == NULL) {
 
525
        newModule->parent = SECMOD_ReferenceModule(defaultDBModule);
 
526
    }
 
527
 
 
528
    SECMOD_AddPermDB(newModule);
 
529
    SECMOD_AddModuleToList(newModule);
 
530
 
 
531
    rv = STAN_AddModuleToDefaultTrustDomain(newModule);
 
532
 
 
533
    return rv;
 
534
}
 
535
 
 
536
PK11SlotInfo *
 
537
SECMOD_FindSlot(SECMODModule *module,const char *name) 
 
538
{
 
539
    int i;
 
540
    char *string;
 
541
    PK11SlotInfo *retSlot = NULL;
 
542
 
 
543
    if (!moduleLock) {
 
544
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
545
        return retSlot;
 
546
    }
 
547
    SECMOD_GetReadLock(moduleLock);
 
548
    for (i=0; i < module->slotCount; i++) {
 
549
        PK11SlotInfo *slot = module->slots[i];
 
550
 
 
551
        if (PK11_IsPresent(slot)) {
 
552
            string = PK11_GetTokenName(slot);
 
553
        } else {
 
554
            string = PK11_GetSlotName(slot);
 
555
        }
 
556
        if (PORT_Strcmp(name,string) == 0) {
 
557
            retSlot = PK11_ReferenceSlot(slot);
 
558
            break;
 
559
        }
 
560
    }
 
561
    SECMOD_ReleaseReadLock(moduleLock);
 
562
 
 
563
    if (retSlot == NULL) {
 
564
        PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
 
565
    }
 
566
    return retSlot;
 
567
}
 
568
 
 
569
SECStatus
 
570
PK11_GetModInfo(SECMODModule *mod,CK_INFO *info)
 
571
{
 
572
    CK_RV crv;
 
573
 
 
574
    if (mod->functionList == NULL) return SECFailure;
 
575
    crv = PK11_GETTAB(mod)->C_GetInfo(info);
 
576
    if (crv != CKR_OK) {
 
577
        PORT_SetError(PK11_MapError(crv));
 
578
    }   
 
579
    return (crv == CKR_OK) ? SECSuccess : SECFailure;
 
580
}
 
581
 
 
582
/* Determine if we have the FIP's module loaded as the default
 
583
 * module to trigger other bogus FIPS requirements in PKCS #12 and
 
584
 * SSL
 
585
 */
 
586
PRBool
 
587
PK11_IsFIPS(void)
 
588
{
 
589
    SECMODModule *mod = SECMOD_GetInternalModule();
 
590
 
 
591
    if (mod && mod->internal) {
 
592
        return mod->isFIPS;
 
593
    }
 
594
 
 
595
    return PR_FALSE;
 
596
}
 
597
 
 
598
/* combines NewModule() & AddModule */
 
599
/* give a string for the module name & the full-path for the dll, */
 
600
/* installs the PKCS11 module & update registry */
 
601
SECStatus 
 
602
SECMOD_AddNewModuleEx(const char* moduleName, const char* dllPath,
 
603
                              unsigned long defaultMechanismFlags,
 
604
                              unsigned long cipherEnableFlags,
 
605
                              char* modparms, char* nssparms)
 
606
{
 
607
    SECMODModule *module;
 
608
    SECStatus result = SECFailure;
 
609
    int s,i;
 
610
    PK11SlotInfo* slot;
 
611
 
 
612
    PR_SetErrorText(0, NULL);
 
613
    if (!moduleLock) {
 
614
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
615
        return result;
 
616
    }
 
617
 
 
618
    module = SECMOD_CreateModule(dllPath, moduleName, modparms, nssparms);
 
619
 
 
620
    if (module == NULL) {
 
621
        return result;
 
622
    }
 
623
 
 
624
    if (module->dllName != NULL) {
 
625
        if (module->dllName[0] != 0) {
 
626
            result = SECMOD_AddModule(module);
 
627
            if (result == SECSuccess) {
 
628
                /* turn on SSL cipher enable flags */
 
629
                module->ssl[0] = cipherEnableFlags;
 
630
 
 
631
                SECMOD_GetReadLock(moduleLock);
 
632
                /* check each slot to turn on appropriate mechanisms */
 
633
                for (s = 0; s < module->slotCount; s++) {
 
634
                    slot = (module->slots)[s];
 
635
                    /* for each possible mechanism */
 
636
                    for (i=0; i < num_pk11_default_mechanisms; i++) {
 
637
                        /* we are told to turn it on by default ? */
 
638
                        PRBool add = 
 
639
                         (PK11_DefaultArray[i].flag & defaultMechanismFlags) ?
 
640
                                                PR_TRUE: PR_FALSE;
 
641
                        result = PK11_UpdateSlotAttribute(slot, 
 
642
                                        &(PK11_DefaultArray[i]),  add);
 
643
                    } /* for each mechanism */
 
644
                    /* disable each slot if the defaultFlags say so */
 
645
                    if (defaultMechanismFlags & PK11_DISABLE_FLAG) {
 
646
                        PK11_UserDisableSlot(slot);
 
647
                    }
 
648
                } /* for each slot of this module */
 
649
                SECMOD_ReleaseReadLock(moduleLock);
 
650
 
 
651
                /* delete and re-add module in order to save changes 
 
652
                 * to the module */
 
653
                result = SECMOD_UpdateModule(module);
 
654
            }
 
655
        }
 
656
    }
 
657
    SECMOD_DestroyModule(module);
 
658
    return result;
 
659
}
 
660
 
 
661
SECStatus 
 
662
SECMOD_AddNewModule(const char* moduleName, const char* dllPath,
 
663
                              unsigned long defaultMechanismFlags,
 
664
                              unsigned long cipherEnableFlags)
 
665
{
 
666
    return SECMOD_AddNewModuleEx(moduleName, dllPath, defaultMechanismFlags,
 
667
                  cipherEnableFlags, 
 
668
                  NULL, NULL); /* don't pass module or nss params */
 
669
}
 
670
 
 
671
SECStatus 
 
672
SECMOD_UpdateModule(SECMODModule *module)
 
673
{
 
674
    SECStatus result;
 
675
 
 
676
    result = SECMOD_DeletePermDB(module);
 
677
                
 
678
    if (result == SECSuccess) {          
 
679
        result = SECMOD_AddPermDB(module);
 
680
    }
 
681
    return result;
 
682
}
 
683
 
 
684
/* Public & Internal(Security Library)  representation of
 
685
 * encryption mechanism flags conversion */
 
686
 
 
687
/* Currently, the only difference is that internal representation 
 
688
 * puts RANDOM_FLAG at bit 31 (Most-significant bit), but
 
689
 * public representation puts this bit at bit 28
 
690
 */
 
691
unsigned long 
 
692
SECMOD_PubMechFlagstoInternal(unsigned long publicFlags)
 
693
{
 
694
    unsigned long internalFlags = publicFlags;
 
695
 
 
696
    if (publicFlags & PUBLIC_MECH_RANDOM_FLAG) {
 
697
        internalFlags &= ~PUBLIC_MECH_RANDOM_FLAG;
 
698
        internalFlags |= SECMOD_RANDOM_FLAG;
 
699
    }
 
700
    return internalFlags;
 
701
}
 
702
 
 
703
unsigned long 
 
704
SECMOD_InternaltoPubMechFlags(unsigned long internalFlags) 
 
705
{
 
706
    unsigned long publicFlags = internalFlags;
 
707
 
 
708
    if (internalFlags & SECMOD_RANDOM_FLAG) {
 
709
        publicFlags &= ~SECMOD_RANDOM_FLAG;
 
710
        publicFlags |= PUBLIC_MECH_RANDOM_FLAG;
 
711
    }
 
712
    return publicFlags;
 
713
}
 
714
 
 
715
 
 
716
/* Public & Internal(Security Library)  representation of */
 
717
/* cipher flags conversion */
 
718
/* Note: currently they are just stubs */
 
719
unsigned long 
 
720
SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags) 
 
721
{
 
722
    return publicFlags;
 
723
}
 
724
 
 
725
unsigned long 
 
726
SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags) 
 
727
{
 
728
    return internalFlags;
 
729
}
 
730
 
 
731
/* Funtion reports true if module of modType is installed/configured */
 
732
PRBool 
 
733
SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags )
 
734
{
 
735
    PRBool result = PR_FALSE;
 
736
    SECMODModuleList *mods;
 
737
 
 
738
    if (!moduleLock) {
 
739
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
740
        return result;
 
741
    }
 
742
    SECMOD_GetReadLock(moduleLock);
 
743
    mods = SECMOD_GetDefaultModuleList();
 
744
    for ( ; mods != NULL; mods = mods->next) {
 
745
        if (mods->module->ssl[0] & 
 
746
                SECMOD_PubCipherFlagstoInternal(pubCipherEnableFlags)) {
 
747
            result = PR_TRUE;
 
748
        }
 
749
    }
 
750
 
 
751
    SECMOD_ReleaseReadLock(moduleLock);
 
752
    return result;
 
753
}
 
754
 
 
755
/* create a new ModuleListElement */
 
756
SECMODModuleList *SECMOD_NewModuleListElement(void) 
 
757
{
 
758
    SECMODModuleList *newModList;
 
759
 
 
760
    newModList= (SECMODModuleList *) PORT_Alloc(sizeof(SECMODModuleList));
 
761
    if (newModList) {
 
762
        newModList->next = NULL;
 
763
        newModList->module = NULL;
 
764
    }
 
765
    return newModList;
 
766
}
 
767
 
 
768
/*
 
769
 * make a new reference to a module so It doesn't go away on us
 
770
 */
 
771
SECMODModule *
 
772
SECMOD_ReferenceModule(SECMODModule *module) 
 
773
{
 
774
    PZ_Lock(module->refLock);
 
775
    PORT_Assert(module->refCount > 0);
 
776
 
 
777
    module->refCount++;
 
778
    PZ_Unlock(module->refLock);
 
779
    return module;
 
780
}
 
781
 
 
782
 
 
783
/* destroy an existing module */
 
784
void
 
785
SECMOD_DestroyModule(SECMODModule *module) 
 
786
{
 
787
    PRBool willfree = PR_FALSE;
 
788
    int slotCount;
 
789
    int i;
 
790
 
 
791
    PZ_Lock(module->refLock);
 
792
    if (module->refCount-- == 1) {
 
793
        willfree = PR_TRUE;
 
794
    }
 
795
    PORT_Assert(willfree || (module->refCount > 0));
 
796
    PZ_Unlock(module->refLock);
 
797
 
 
798
    if (!willfree) {
 
799
        return;
 
800
    }
 
801
   
 
802
    if (module->parent != NULL) {
 
803
        SECMODModule *parent = module->parent;
 
804
        /* paranoia, don't loop forever if the modules are looped */
 
805
        module->parent = NULL;
 
806
        SECMOD_DestroyModule(parent);
 
807
    }
 
808
 
 
809
    /* slots can't really disappear until our module starts freeing them,
 
810
     * so this check is safe */
 
811
    slotCount = module->slotCount;
 
812
    if (slotCount == 0) {
 
813
        SECMOD_SlotDestroyModule(module,PR_FALSE);
 
814
        return;
 
815
    }
 
816
 
 
817
    /* now free all out slots, when they are done, they will cause the
 
818
     * module to disappear altogether */
 
819
    for (i=0 ; i < slotCount; i++) {
 
820
        if (!module->slots[i]->disabled) {
 
821
                PK11_ClearSlotList(module->slots[i]);
 
822
        }
 
823
        PK11_FreeSlot(module->slots[i]);
 
824
    }
 
825
    /* WARNING: once the last slot has been freed is it possible (even likely)
 
826
     * that module is no more... touching it now is a good way to go south */
 
827
}
 
828
 
 
829
 
 
830
/* we can only get here if we've destroyed the module, or some one has
 
831
 * erroneously freed a slot that wasn't referenced. */
 
832
void
 
833
SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot) 
 
834
{
 
835
    PRBool willfree = PR_FALSE;
 
836
    if (fromSlot) {
 
837
        PORT_Assert(module->refCount == 0);
 
838
        PZ_Lock(module->refLock);
 
839
        if (module->slotCount-- == 1) {
 
840
            willfree = PR_TRUE;
 
841
        }
 
842
        PORT_Assert(willfree || (module->slotCount > 0));
 
843
        PZ_Unlock(module->refLock);
 
844
        if (!willfree) return;
 
845
    }
 
846
 
 
847
    if (module == pendingModule) {
 
848
        pendingModule = NULL;
 
849
    }
 
850
 
 
851
    if (module->loaded) {
 
852
        SECMOD_UnloadModule(module);
 
853
    }
 
854
    PZ_DestroyLock(module->refLock);
 
855
    PORT_FreeArena(module->arena,PR_FALSE);
 
856
    secmod_PrivateModuleCount--;
 
857
}
 
858
 
 
859
/* destroy a list element
 
860
 * this destroys a single element, and returns the next element
 
861
 * on the chain. It makes it easy to implement for loops to delete
 
862
 * the chain. It also make deleting a single element easy */
 
863
SECMODModuleList *
 
864
SECMOD_DestroyModuleListElement(SECMODModuleList *element) 
 
865
{
 
866
    SECMODModuleList *next = element->next;
 
867
 
 
868
    if (element->module) {
 
869
        SECMOD_DestroyModule(element->module);
 
870
        element->module = NULL;
 
871
    }
 
872
    PORT_Free(element);
 
873
    return next;
 
874
}
 
875
 
 
876
 
 
877
/*
 
878
 * Destroy an entire module list
 
879
 */
 
880
void
 
881
SECMOD_DestroyModuleList(SECMODModuleList *list) 
 
882
{
 
883
    SECMODModuleList *lp;
 
884
 
 
885
    for ( lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) ;
 
886
}
 
887
 
 
888
PRBool
 
889
SECMOD_CanDeleteInternalModule(void)
 
890
{
 
891
    return (PRBool) (pendingModule == NULL);
 
892
}
 
893
 
 
894
/*
 
895
 * check to see if the module has added new slots. PKCS 11 v2.20 allows for
 
896
 * modules to add new slots, but never remove them. Slots cannot be added 
 
897
 * between a call to C_GetSlotLlist(Flag, NULL, &count) and the subsequent
 
898
 * C_GetSlotList(flag, &data, &count) so that the array doesn't accidently
 
899
 * grow on the caller. It is permissible for the slots to increase between
 
900
 * successive calls with NULL to get the size.
 
901
 */
 
902
SECStatus
 
903
SECMOD_UpdateSlotList(SECMODModule *mod)
 
904
{
 
905
    CK_RV crv;
 
906
    CK_ULONG count;
 
907
    CK_ULONG i, oldCount;
 
908
    PRBool freeRef = PR_FALSE;
 
909
    void *mark = NULL;
 
910
    CK_ULONG *slotIDs = NULL;
 
911
    PK11SlotInfo **newSlots = NULL;
 
912
    PK11SlotInfo **oldSlots = NULL;
 
913
 
 
914
    if (!moduleLock) {
 
915
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
916
        return SECFailure;
 
917
    }
 
918
 
 
919
    /* C_GetSlotList is not a session function, make sure 
 
920
     * calls are serialized */
 
921
    PZ_Lock(mod->refLock);
 
922
    freeRef = PR_TRUE;
 
923
    /* see if the number of slots have changed */
 
924
    crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, NULL, &count);
 
925
    if (crv != CKR_OK) {
 
926
        PORT_SetError(PK11_MapError(crv));
 
927
        goto loser;
 
928
    }
 
929
    /* nothing new, blow out early, we want this function to be quick
 
930
     * and cheap in the normal case  */
 
931
    if (count == mod->slotCount) {
 
932
        PZ_Unlock(mod->refLock);
 
933
        return SECSuccess;
 
934
    }
 
935
    if (count < (CK_ULONG)mod->slotCount) {
 
936
        /* shouldn't happen with a properly functioning PKCS #11 module */
 
937
        PORT_SetError( SEC_ERROR_INCOMPATIBLE_PKCS11 );
 
938
        goto loser;
 
939
    }
 
940
 
 
941
    /* get the new slot list */
 
942
    slotIDs = PORT_NewArray(CK_SLOT_ID, count);
 
943
    if (slotIDs == NULL) {
 
944
        goto loser;
 
945
    }
 
946
 
 
947
    crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, slotIDs, &count);
 
948
    if (crv != CKR_OK) {
 
949
        PORT_SetError(PK11_MapError(crv));
 
950
        goto loser;
 
951
    }
 
952
    freeRef = PR_FALSE;
 
953
    PZ_Unlock(mod->refLock);
 
954
    mark = PORT_ArenaMark(mod->arena);
 
955
    if (mark == NULL) {
 
956
        goto loser;
 
957
    }
 
958
    newSlots = PORT_ArenaZNewArray(mod->arena,PK11SlotInfo *,count);
 
959
 
 
960
    /* walk down the new slot ID list returned from the module. We keep
 
961
     * the old slots which match a returned ID, and we initialize the new 
 
962
     * slots. */
 
963
    for (i=0; i < count; i++) {
 
964
        PK11SlotInfo *slot = SECMOD_FindSlotByID(mod,slotIDs[i]);
 
965
 
 
966
        if (!slot) {
 
967
            /* we have a new slot create a new slot data structure */
 
968
            slot = PK11_NewSlotInfo(mod);
 
969
            if (!slot) {
 
970
                goto loser;
 
971
            }
 
972
            PK11_InitSlot(mod, slotIDs[i], slot);
 
973
            STAN_InitTokenForSlotInfo(NULL, slot);
 
974
        }
 
975
        newSlots[i] = slot;
 
976
    }
 
977
    STAN_ResetTokenInterator(NULL);
 
978
    PORT_Free(slotIDs);
 
979
    slotIDs = NULL;
 
980
    PORT_ArenaUnmark(mod->arena, mark);
 
981
 
 
982
    /* until this point we're still using the old slot list. Now we update
 
983
     * module slot list. We update the slots (array) first then the count, 
 
984
     * since we've already guarrenteed that count has increased (just in case 
 
985
     * someone is looking at the slots field of  module without holding the 
 
986
     * moduleLock */
 
987
    SECMOD_GetWriteLock(moduleLock);
 
988
    oldCount =mod->slotCount;
 
989
    oldSlots = mod->slots;
 
990
    mod->slots = newSlots; /* typical arena 'leak'... old mod->slots is
 
991
                            * allocated out of the module arena and won't
 
992
                            * be freed until the module is freed */
 
993
    mod->slotCount = count;
 
994
    SECMOD_ReleaseWriteLock(moduleLock);
 
995
    /* free our old references before forgetting about oldSlot*/
 
996
    for (i=0; i < oldCount; i++) {
 
997
        PK11_FreeSlot(oldSlots[i]);
 
998
    }
 
999
    return SECSuccess;
 
1000
 
 
1001
loser:
 
1002
    if (freeRef) {
 
1003
        PZ_Unlock(mod->refLock);
 
1004
    }
 
1005
    if (slotIDs) {
 
1006
        PORT_Free(slotIDs);
 
1007
    }
 
1008
    /* free all the slots we allocated. newSlots are part of the
 
1009
     * mod arena. NOTE: the newSlots array contain both new and old
 
1010
     * slots, but we kept a reference to the old slots when we built the new
 
1011
     * array, so we need to free all the slots in newSlots array. */
 
1012
    if (newSlots) {
 
1013
        for (i=0; i < count; i++) {
 
1014
            if (newSlots[i] == NULL) {
 
1015
                break; /* hit the last one */
 
1016
            }
 
1017
            PK11_FreeSlot(newSlots[i]);
 
1018
        }
 
1019
    }
 
1020
    /* must come after freeing newSlots */
 
1021
    if (mark) {
 
1022
        PORT_ArenaRelease(mod->arena, mark);
 
1023
    }
 
1024
    return SECFailure;
 
1025
}
 
1026
 
 
1027
/*
 
1028
 * this handles modules that do not support C_WaitForSlotEvent().
 
1029
 * The internal flags are stored. Note that C_WaitForSlotEvent() does not
 
1030
 * have a timeout, so we don't have one for handleWaitForSlotEvent() either.
 
1031
 */
 
1032
PK11SlotInfo *
 
1033
secmod_HandleWaitForSlotEvent(SECMODModule *mod,  unsigned long flags,
 
1034
                                                PRIntervalTime latency)
 
1035
{
 
1036
    PRBool removableSlotsFound = PR_FALSE;
 
1037
    int i;
 
1038
    int error = SEC_ERROR_NO_EVENT;
 
1039
 
 
1040
    if (!moduleLock) {
 
1041
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
1042
        return NULL;
 
1043
    }
 
1044
    PZ_Lock(mod->refLock);
 
1045
    if (mod->evControlMask & SECMOD_END_WAIT) {
 
1046
        mod->evControlMask &= ~SECMOD_END_WAIT;
 
1047
        PZ_Unlock(mod->refLock);
 
1048
        PORT_SetError(SEC_ERROR_NO_EVENT);
 
1049
        return NULL;
 
1050
    }
 
1051
    mod->evControlMask |= SECMOD_WAIT_SIMULATED_EVENT;
 
1052
    while (mod->evControlMask & SECMOD_WAIT_SIMULATED_EVENT) {
 
1053
        PZ_Unlock(mod->refLock);
 
1054
        /* now is a good time to see if new slots have been added */
 
1055
        SECMOD_UpdateSlotList(mod);
 
1056
 
 
1057
        /* loop through all the slots on a module */
 
1058
        SECMOD_GetReadLock(moduleLock);
 
1059
        for (i=0; i < mod->slotCount; i++) {
 
1060
            PK11SlotInfo *slot = mod->slots[i];
 
1061
            PRUint16 series;
 
1062
            PRBool present;
 
1063
 
 
1064
            /* perm modules do not change */
 
1065
            if (slot->isPerm) {
 
1066
                continue;
 
1067
            }
 
1068
            removableSlotsFound = PR_TRUE;
 
1069
            /* simulate the PKCS #11 module flags. are the flags different
 
1070
             * from the last time we called? */
 
1071
            series = slot->series;
 
1072
            present = PK11_IsPresent(slot);
 
1073
            if ((slot->flagSeries != series) || (slot->flagState != present)) {
 
1074
                slot->flagState = present;
 
1075
                slot->flagSeries = series;
 
1076
                SECMOD_ReleaseReadLock(moduleLock);
 
1077
                PZ_Lock(mod->refLock);
 
1078
                mod->evControlMask &= ~SECMOD_END_WAIT;
 
1079
                PZ_Unlock(mod->refLock);
 
1080
                return PK11_ReferenceSlot(slot);
 
1081
            }
 
1082
        }
 
1083
        SECMOD_ReleaseReadLock(moduleLock);
 
1084
        /* if everything was perm modules, don't lock up forever */
 
1085
        if ((mod->slotCount !=0) && !removableSlotsFound) {
 
1086
            error =SEC_ERROR_NO_SLOT_SELECTED;
 
1087
            PZ_Lock(mod->refLock);
 
1088
            break;
 
1089
        }
 
1090
        if (flags & CKF_DONT_BLOCK) {
 
1091
            PZ_Lock(mod->refLock);
 
1092
            break;
 
1093
        }
 
1094
        PR_Sleep(latency);
 
1095
        PZ_Lock(mod->refLock);
 
1096
    }
 
1097
    mod->evControlMask &= ~SECMOD_END_WAIT;
 
1098
    PZ_Unlock(mod->refLock);
 
1099
    PORT_SetError(error);
 
1100
    return NULL;
 
1101
}
 
1102
 
 
1103
/*
 
1104
 * this function waits for a token event on any slot of a given module
 
1105
 * This function should not be called from more than one thread of the
 
1106
 * same process (though other threads can make other library calls
 
1107
 * on this module while this call is blocked).
 
1108
 */
 
1109
PK11SlotInfo *
 
1110
SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags,
 
1111
                                                 PRIntervalTime latency)
 
1112
{
 
1113
    CK_SLOT_ID id;
 
1114
    CK_RV crv;
 
1115
    PK11SlotInfo *slot;
 
1116
 
 
1117
    if (!pk11_getFinalizeModulesOption() ||
 
1118
        ((mod->cryptokiVersion.major == 2) &&
 
1119
         (mod->cryptokiVersion.minor < 1))) { 
 
1120
        /* if we are sharing the module with other software in our
 
1121
         * address space, we can't reliably use C_WaitForSlotEvent(),
 
1122
         * and if the module is version 2.0, C_WaitForSlotEvent() doesn't
 
1123
         * exist */
 
1124
        return secmod_HandleWaitForSlotEvent(mod, flags, latency);
 
1125
    }
 
1126
    /* first the the PKCS #11 call */
 
1127
    PZ_Lock(mod->refLock);
 
1128
    if (mod->evControlMask & SECMOD_END_WAIT) {
 
1129
        goto end_wait;
 
1130
    }
 
1131
    mod->evControlMask |= SECMOD_WAIT_PKCS11_EVENT;
 
1132
    PZ_Unlock(mod->refLock);
 
1133
    crv = PK11_GETTAB(mod)->C_WaitForSlotEvent(flags, &id, NULL);
 
1134
    PZ_Lock(mod->refLock);
 
1135
    mod->evControlMask &= ~SECMOD_WAIT_PKCS11_EVENT;
 
1136
    /* if we are in end wait, short circuit now, don't even risk
 
1137
     * going into secmod_HandleWaitForSlotEvent */
 
1138
    if (mod->evControlMask & SECMOD_END_WAIT) {
 
1139
        goto end_wait;
 
1140
    }
 
1141
    PZ_Unlock(mod->refLock);
 
1142
    if (crv == CKR_FUNCTION_NOT_SUPPORTED) {
 
1143
        /* module doesn't support that call, simulate it */
 
1144
        return secmod_HandleWaitForSlotEvent(mod, flags, latency);
 
1145
    }
 
1146
    if (crv != CKR_OK) {
 
1147
        /* we can get this error if finalize was called while we were
 
1148
         * still running. This is the only way to force a C_WaitForSlotEvent()
 
1149
         * to return in PKCS #11. In this case, just return that there
 
1150
         * was no event. */
 
1151
        if (crv == CKR_CRYPTOKI_NOT_INITIALIZED) {
 
1152
            PORT_SetError(SEC_ERROR_NO_EVENT);
 
1153
        } else {
 
1154
            PORT_SetError(PK11_MapError(crv));
 
1155
        }
 
1156
        return NULL;
 
1157
    }
 
1158
    slot = SECMOD_FindSlotByID(mod, id);
 
1159
    if (slot == NULL) {
 
1160
        /* possibly a new slot that was added? */
 
1161
        SECMOD_UpdateSlotList(mod);
 
1162
        slot = SECMOD_FindSlotByID(mod, id);
 
1163
    }
 
1164
    /* if we are in the delay period for the "isPresent" call, reset
 
1165
     * the delay since we know things have probably changed... */
 
1166
    if (slot && slot->nssToken && slot->nssToken->slot) {
 
1167
        nssSlot_ResetDelay(slot->nssToken->slot);
 
1168
    }
 
1169
    return slot;
 
1170
 
 
1171
    /* must be called with the lock on. */
 
1172
end_wait:
 
1173
    mod->evControlMask &= ~SECMOD_END_WAIT;
 
1174
    PZ_Unlock(mod->refLock);
 
1175
    PORT_SetError(SEC_ERROR_NO_EVENT);
 
1176
    return NULL;
 
1177
}
 
1178
 
 
1179
/*
 
1180
 * This function "wakes up" WaitForAnyTokenEvent. It's a pretty drastic
 
1181
 * function, possibly bringing down the pkcs #11 module in question. This
 
1182
 * should be OK because 1) it does reinitialize, and 2) it should only be
 
1183
 * called when we are on our way to tear the whole system down anyway.
 
1184
 */
 
1185
SECStatus
 
1186
SECMOD_CancelWait(SECMODModule *mod)
 
1187
{
 
1188
    unsigned long controlMask = mod->evControlMask;
 
1189
    SECStatus rv = SECSuccess;
 
1190
    CK_RV crv;
 
1191
 
 
1192
    PZ_Lock(mod->refLock);
 
1193
    mod->evControlMask |= SECMOD_END_WAIT;
 
1194
    controlMask = mod->evControlMask;
 
1195
    if (controlMask & SECMOD_WAIT_PKCS11_EVENT) {
 
1196
        if (!pk11_getFinalizeModulesOption()) {
 
1197
            /* can't get here unless pk11_getFinalizeModulesOption is set */
 
1198
            PORT_Assert(0);
 
1199
            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
1200
            rv = SECFailure;
 
1201
            goto loser;
 
1202
        }
 
1203
        /* NOTE: this call will drop all transient keys, in progress
 
1204
         * operations, and any authentication. This is the only documented
 
1205
         * way to get WaitForSlotEvent to return. Also note: for non-thread
 
1206
         * safe tokens, we need to hold the module lock, this is not yet at
 
1207
         * system shutdown/startup time, so we need to protect these calls */
 
1208
        crv = PK11_GETTAB(mod)->C_Finalize(NULL);
 
1209
        /* ok, we slammed the module down, now we need to reinit it in case
 
1210
         * we intend to use it again */
 
1211
        if (CKR_OK == crv) {
 
1212
            PRBool alreadyLoaded;
 
1213
            secmod_ModuleInit(mod, NULL, &alreadyLoaded);
 
1214
        } else {
 
1215
            /* Finalized failed for some reason,  notify the application
 
1216
             * so maybe it has a prayer of recovering... */
 
1217
            PORT_SetError(PK11_MapError(crv));
 
1218
            rv = SECFailure;
 
1219
        }
 
1220
    } else if (controlMask & SECMOD_WAIT_SIMULATED_EVENT) {
 
1221
        mod->evControlMask &= ~SECMOD_WAIT_SIMULATED_EVENT; 
 
1222
                                /* Simulated events will eventually timeout
 
1223
                                 * and wake up in the loop */
 
1224
    }
 
1225
loser:
 
1226
    PZ_Unlock(mod->refLock);
 
1227
    return rv;
 
1228
}
 
1229
 
 
1230
/*
 
1231
 * check to see if the module has removable slots that we may need to
 
1232
 * watch for.
 
1233
 */
 
1234
PRBool
 
1235
SECMOD_HasRemovableSlots(SECMODModule *mod)
 
1236
{
 
1237
    int i;
 
1238
    PRBool ret = PR_FALSE;
 
1239
 
 
1240
    if (!moduleLock) {
 
1241
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
1242
        return ret;
 
1243
    }
 
1244
    SECMOD_GetReadLock(moduleLock);
 
1245
    for (i=0; i < mod->slotCount; i++) {
 
1246
        PK11SlotInfo *slot = mod->slots[i];
 
1247
        /* perm modules are not inserted or removed */
 
1248
        if (slot->isPerm) {
 
1249
            continue;
 
1250
        }
 
1251
        ret = PR_TRUE;
 
1252
        break;
 
1253
    }
 
1254
    if (mod->slotCount == 0 ) {
 
1255
        ret = PR_TRUE;
 
1256
    }
 
1257
    SECMOD_ReleaseReadLock(moduleLock);
 
1258
    return ret;
 
1259
}
 
1260
 
 
1261
/*
 
1262
 * helper function to actually create and destroy user defined slots
 
1263
 */
 
1264
static SECStatus
 
1265
secmod_UserDBOp(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass, 
 
1266
                const char *sendSpec)
 
1267
{
 
1268
    CK_OBJECT_HANDLE dummy;
 
1269
    CK_ATTRIBUTE template[2] ;
 
1270
    CK_ATTRIBUTE *attrs = template;
 
1271
    CK_RV crv;
 
1272
 
 
1273
    PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); attrs++;
 
1274
    PK11_SETATTRS(attrs, CKA_NETSCAPE_MODULE_SPEC , (unsigned char *)sendSpec,
 
1275
                                         strlen(sendSpec)+1); attrs++;
 
1276
 
 
1277
    PORT_Assert(attrs-template <= 2);
 
1278
 
 
1279
 
 
1280
    PK11_EnterSlotMonitor(slot);
 
1281
    crv = PK11_CreateNewObject(slot, slot->session,
 
1282
        template, attrs-template, PR_FALSE, &dummy);
 
1283
    PK11_ExitSlotMonitor(slot);
 
1284
 
 
1285
    if (crv != CKR_OK) {
 
1286
        PORT_SetError(PK11_MapError(crv));
 
1287
        return SECFailure;
 
1288
    }
 
1289
    return SECMOD_UpdateSlotList(slot->module);
 
1290
}
 
1291
 
 
1292
/*
 
1293
 * return true if the selected slot ID is not present or doesn't exist
 
1294
 */
 
1295
static PRBool
 
1296
secmod_SlotIsEmpty(SECMODModule *mod,  CK_SLOT_ID slotID)
 
1297
{
 
1298
    PK11SlotInfo *slot = SECMOD_LookupSlot(mod->moduleID, slotID);
 
1299
    if (slot) {
 
1300
        PRBool present = PK11_IsPresent(slot);
 
1301
        PK11_FreeSlot(slot);
 
1302
        if (present) {
 
1303
            return PR_FALSE;
 
1304
        }
 
1305
    }
 
1306
    /* it doesn't exist or isn't present, it's available */
 
1307
    return PR_TRUE;
 
1308
}
 
1309
 
 
1310
/*
 
1311
 * Find an unused slot id in module.
 
1312
 */
 
1313
static CK_SLOT_ID
 
1314
secmod_FindFreeSlot(SECMODModule *mod)
 
1315
{
 
1316
    CK_SLOT_ID i, minSlotID, maxSlotID;
 
1317
 
 
1318
    /* look for a free slot id on the internal module */
 
1319
    if (mod->internal && mod->isFIPS) {
 
1320
        minSlotID = SFTK_MIN_FIPS_USER_SLOT_ID;
 
1321
        maxSlotID = SFTK_MAX_FIPS_USER_SLOT_ID;
 
1322
    } else {
 
1323
        minSlotID = SFTK_MIN_USER_SLOT_ID;
 
1324
        maxSlotID = SFTK_MAX_USER_SLOT_ID;
 
1325
    }
 
1326
    for (i=minSlotID; i < maxSlotID; i++) {
 
1327
        if (secmod_SlotIsEmpty(mod,i)) {
 
1328
            return i;
 
1329
        }
 
1330
    }
 
1331
    PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED);
 
1332
    return (CK_SLOT_ID) -1;
 
1333
}
 
1334
 
 
1335
/*
 
1336
 * Attempt to open a new slot.
 
1337
 *
 
1338
 * This works the same os OpenUserDB except it can be called against
 
1339
 * any module that understands the softoken protocol for opening new
 
1340
 * slots, not just the softoken itself. If the selected module does not
 
1341
 * understand the protocol, C_CreateObject will fail with 
 
1342
 * CKR_INVALID_ATTRIBUTE, and SECMOD_OpenNewSlot will return NULL and set
 
1343
 * SEC_ERROR_BAD_DATA.
 
1344
 * 
 
1345
 * NewSlots can be closed with SECMOD_CloseUserDB();
 
1346
 *
 
1347
 * Modulespec is module dependent.
 
1348
 */
 
1349
PK11SlotInfo *
 
1350
SECMOD_OpenNewSlot(SECMODModule *mod, const char *moduleSpec)
 
1351
{
 
1352
    CK_SLOT_ID slotID = 0;
 
1353
    PK11SlotInfo *slot;
 
1354
    char *escSpec;
 
1355
    char *sendSpec;
 
1356
    SECStatus rv;
 
1357
 
 
1358
    slotID = secmod_FindFreeSlot(mod);
 
1359
    if (slotID == (CK_SLOT_ID) -1) {
 
1360
        return NULL;
 
1361
    }
 
1362
 
 
1363
    if (mod->slotCount == 0) {
 
1364
        return NULL;
 
1365
    }
 
1366
 
 
1367
    /* just grab the first slot in the module, any present slot should work */
 
1368
    slot = PK11_ReferenceSlot(mod->slots[0]);
 
1369
    if (slot == NULL) {
 
1370
        return NULL;
 
1371
    }
 
1372
 
 
1373
    /* we've found the slot, now build the moduleSpec */
 
1374
    escSpec = NSSUTIL_DoubleEscape(moduleSpec, '>', ']');
 
1375
    if (escSpec == NULL) {
 
1376
        PK11_FreeSlot(slot);
 
1377
        return NULL;
 
1378
    }
 
1379
    sendSpec = PR_smprintf("tokens=[0x%x=<%s>]", slotID, escSpec);
 
1380
    PORT_Free(escSpec);
 
1381
 
 
1382
    if (sendSpec == NULL) {
 
1383
        /* PR_smprintf does not set SEC_ERROR_NO_MEMORY on failure. */
 
1384
        PK11_FreeSlot(slot);
 
1385
        PORT_SetError(SEC_ERROR_NO_MEMORY);
 
1386
        return NULL;
 
1387
    }
 
1388
    rv = secmod_UserDBOp(slot, CKO_NETSCAPE_NEWSLOT, sendSpec);
 
1389
    PR_smprintf_free(sendSpec);
 
1390
    PK11_FreeSlot(slot);
 
1391
    if (rv != SECSuccess) {
 
1392
        return NULL;
 
1393
    }
 
1394
 
 
1395
    slot = SECMOD_FindSlotByID(mod, slotID);
 
1396
    if (slot) {
 
1397
        /* if we are in the delay period for the "isPresent" call, reset
 
1398
         * the delay since we know things have probably changed... */
 
1399
        if (slot->nssToken && slot->nssToken->slot) {
 
1400
            nssSlot_ResetDelay(slot->nssToken->slot);
 
1401
        }
 
1402
        /* force the slot info structures to properly reset */
 
1403
        (void)PK11_IsPresent(slot);
 
1404
    }
 
1405
    return slot;
 
1406
}
 
1407
 
 
1408
/*
 
1409
 * Open a new database using the softoken. The caller is responsible for making
 
1410
 * sure the module spec is correct and usable. The caller should ask for one
 
1411
 * new database per call if the caller wants to get meaningful information 
 
1412
 * about the new database.
 
1413
 *
 
1414
 * moduleSpec is the same data that you would pass to softoken at 
 
1415
 * initialization time under the 'tokens' options. For example, if you were
 
1416
 * to specify tokens=<0x4=[configdir='./mybackup' tokenDescription='Backup']>
 
1417
 * You would specify "configdir='./mybackup' tokenDescription='Backup'" as your
 
1418
 * module spec here. The slot ID will be calculated for you by 
 
1419
 * SECMOD_OpenUserDB().
 
1420
 *
 
1421
 * Typical parameters here are configdir, tokenDescription and flags.
 
1422
 *
 
1423
 * a Full list is below:
 
1424
 *
 
1425
 *
 
1426
 *  configDir - The location of the databases for this token. If configDir is 
 
1427
 *         not specified, and noCertDB and noKeyDB is not specified, the load
 
1428
 *         will fail.
 
1429
 *   certPrefix - Cert prefix for this token.
 
1430
 *   keyPrefix - Prefix for the key database for this token. (if not specified,
 
1431
 *         certPrefix will be used).
 
1432
 *   tokenDescription - The label value for this token returned in the 
 
1433
 *         CK_TOKEN_INFO structure with an internationalize string (UTF8). 
 
1434
 *         This value will be truncated at 32 bytes (no NULL, partial UTF8 
 
1435
 *         characters dropped). You should specify a user friendly name here
 
1436
 *         as this is the value the token will be referred to in most 
 
1437
 *         application UI's. You should make sure tokenDescription is unique.
 
1438
 *   slotDescription - The slotDescription value for this token returned 
 
1439
 *         in the CK_SLOT_INFO structure with an internationalize string 
 
1440
 *         (UTF8). This value will be truncated at 64 bytes (no NULL, partial 
 
1441
 *         UTF8 characters dropped). This name will not change after the 
 
1442
 *         database is closed. It should have some number to make this unique.
 
1443
 *   minPWLen - minimum password length for this token.
 
1444
 *   flags - comma separated list of flag values, parsed case-insensitive.
 
1445
 *         Valid flags are:
 
1446
 *              readOnly - Databases should be opened read only.
 
1447
 *              noCertDB - Don't try to open a certificate database.
 
1448
 *              noKeyDB - Don't try to open a key database.
 
1449
 *              forceOpen - Don't fail to initialize the token if the 
 
1450
 *                databases could not be opened.
 
1451
 *              passwordRequired - zero length passwords are not acceptable 
 
1452
 *                (valid only if there is a keyDB).
 
1453
 *              optimizeSpace - allocate smaller hash tables and lock tables.
 
1454
 *                When this flag is not specified, Softoken will allocate 
 
1455
 *                large tables to prevent lock contention. 
 
1456
 */
 
1457
PK11SlotInfo *
 
1458
SECMOD_OpenUserDB(const char *moduleSpec)
 
1459
{
 
1460
    SECMODModule *mod;
 
1461
 
 
1462
    if (moduleSpec == NULL) {
 
1463
        return NULL;
 
1464
    }
 
1465
 
 
1466
    /* NOTE: unlike most PK11 function, this does not return a reference
 
1467
     * to the module */
 
1468
    mod = SECMOD_GetInternalModule();
 
1469
    if (!mod) {
 
1470
        /* shouldn't happen */
 
1471
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
1472
        return NULL;
 
1473
    }
 
1474
    return SECMOD_OpenNewSlot(mod, moduleSpec);
 
1475
}
 
1476
 
 
1477
 
 
1478
/*
 
1479
 * close an already opened user database. NOTE: the database must be
 
1480
 * in the internal token, and must be one created with SECMOD_OpenUserDB().
 
1481
 * Once the database is closed, the slot will remain as an empty slot
 
1482
 * until it's used again with SECMOD_OpenUserDB() or SECMOD_OpenNewSlot().
 
1483
 */
 
1484
SECStatus
 
1485
SECMOD_CloseUserDB(PK11SlotInfo *slot)
 
1486
{
 
1487
    SECStatus rv;
 
1488
    char *sendSpec;
 
1489
    
 
1490
    sendSpec = PR_smprintf("tokens=[0x%x=<>]", slot->slotID);
 
1491
    if (sendSpec == NULL) {
 
1492
        /* PR_smprintf does not set no memory error */
 
1493
        PORT_SetError(SEC_ERROR_NO_MEMORY);
 
1494
        return SECFailure;
 
1495
    }
 
1496
    rv = secmod_UserDBOp(slot, CKO_NETSCAPE_DELSLOT, sendSpec);
 
1497
    PR_smprintf_free(sendSpec);
 
1498
    /* if we are in the delay period for the "isPresent" call, reset
 
1499
     * the delay since we know things have probably changed... */
 
1500
    if (slot->nssToken && slot->nssToken->slot) {
 
1501
        nssSlot_ResetDelay(slot->nssToken->slot);
 
1502
        /* force the slot info structures to properly reset */
 
1503
        (void)PK11_IsPresent(slot);
 
1504
    }
 
1505
    return rv;
 
1506
}
 
1507
 
 
1508
/*
 
1509
 * Restart PKCS #11 modules after a fork(). See secmod.h for more information.
 
1510
 */
 
1511
SECStatus
 
1512
SECMOD_RestartModules(PRBool force)
 
1513
{
 
1514
    SECMODModuleList *mlp;
 
1515
    SECStatus rrv = SECSuccess;
 
1516
    int lastError = 0;
 
1517
 
 
1518
    if (!moduleLock) {
 
1519
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
1520
        return SECFailure;
 
1521
    }
 
1522
 
 
1523
    /* Only need to restart the PKCS #11 modules that were initialized */
 
1524
    SECMOD_GetReadLock(moduleLock);
 
1525
    for (mlp = modules; mlp != NULL; mlp = mlp->next) {
 
1526
        SECMODModule *mod = mlp->module;
 
1527
        CK_ULONG count;
 
1528
        SECStatus rv;
 
1529
        int i;
 
1530
 
 
1531
        /* If the module needs to be reset, do so */
 
1532
        if (force  || (PK11_GETTAB(mod)->
 
1533
                        C_GetSlotList(CK_FALSE, NULL, &count) != CKR_OK)) {
 
1534
            PRBool alreadyLoaded;
 
1535
            /* first call Finalize. This is not required by PKCS #11, but some
 
1536
             * older modules require it, and it doesn't hurt (compliant modules
 
1537
             * will return CKR_NOT_INITIALIZED */
 
1538
            (void) PK11_GETTAB(mod)->C_Finalize(NULL);
 
1539
            /* now initialize the module, this function reinitializes
 
1540
             * a module in place, preserving existing slots (even if they
 
1541
             * no longer exist) */
 
1542
            rv = secmod_ModuleInit(mod, NULL, &alreadyLoaded);
 
1543
            if (rv != SECSuccess) {
 
1544
                /* save the last error code */
 
1545
                lastError = PORT_GetError();
 
1546
                rrv = rv;
 
1547
                /* couldn't reinit the module, disable all its slots */
 
1548
                for (i=0; i < mod->slotCount; i++) {
 
1549
                    mod->slots[i]->disabled = PR_TRUE;
 
1550
                    mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
 
1551
                }
 
1552
                continue;
 
1553
            }
 
1554
            for (i=0; i < mod->slotCount; i++) {
 
1555
                /* get new token sessions, bump the series up so that
 
1556
                 * we refresh other old sessions. This will tell much of
 
1557
                 * NSS to flush cached handles it may hold as well */
 
1558
                rv = PK11_InitToken(mod->slots[i],PR_TRUE);
 
1559
                /* PK11_InitToken could fail if the slot isn't present.
 
1560
                 * If it is present, though, something is wrong and we should
 
1561
                 * disable the slot and let the caller know. */
 
1562
                if (rv != SECSuccess && PK11_IsPresent(mod->slots[i])) {
 
1563
                    /* save the last error code */
 
1564
                    lastError = PORT_GetError();
 
1565
                    rrv = rv;
 
1566
                    /* disable the token */
 
1567
                    mod->slots[i]->disabled = PR_TRUE;
 
1568
                    mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
 
1569
                }
 
1570
            }
 
1571
        }
 
1572
    }
 
1573
    SECMOD_ReleaseReadLock(moduleLock);
 
1574
 
 
1575
    /*
 
1576
     * on multiple failures, we are only returning the lastError. The caller
 
1577
     * can determine which slots are bad by calling PK11_IsDisabled().
 
1578
     */
 
1579
    if (rrv != SECSuccess) {
 
1580
        /* restore the last error code */
 
1581
        PORT_SetError(lastError);
 
1582
    }
 
1583
 
 
1584
    return rrv;
 
1585
}