~ubuntu-branches/ubuntu/raring/nss/raring-security

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/nss/nssinit.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2010-03-25 13:46:06 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20100325134606-bl6liuok2w9l7snv
Tags: 3.12.6-0ubuntu1
* New upstream release 3.12.6 RTM (NSS_3_12_6_RTM)
  - fixes CVE-2009-3555 aka US-CERT VU#120541
* Adjust patches to changed upstream code base
  - update debian/patches/38_kbsd.patch
  - update debian/patches/38_mips64_build.patch
  - update debian/patches/85_security_load.patch
* Remove patches that are merged upstream
  - delete debian/patches/91_nonexec_stack.patch
  - update debian/patches/series
* Bump nspr dependency to 4.8
  - update debian/control
* Add new symbols for 3.12.6
  - update debian/libnss3-1d.symbols

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
 * the terms of any one of the MPL, the GPL or the LGPL.
37
37
 *
38
38
 * ***** END LICENSE BLOCK ***** */
39
 
/* $Id: nssinit.c,v 1.97 2008/08/22 01:33:03 wtc%google.com Exp $ */
 
39
/* $Id: nssinit.c,v 1.105 2010/01/22 02:10:54 wtc%google.com Exp $ */
40
40
 
41
41
#include <ctype.h>
 
42
#include <string.h>
42
43
#include "seccomon.h"
43
44
#include "prinit.h"
44
45
#include "prprf.h"
45
46
#include "prmem.h"
46
47
#include "cert.h"
47
48
#include "key.h"
48
 
#include "ssl.h"
49
 
#include "sslproto.h"
50
49
#include "secmod.h"
51
50
#include "secoid.h"
52
51
#include "nss.h"
127
126
    return flags;
128
127
}
129
128
 
 
129
 
 
130
/*
 
131
 * build config string from individual internationalized strings
 
132
 */
 
133
char *
 
134
nss_MkConfigString(const char *man, const char *libdesc, const char *tokdesc,
 
135
        const char *ptokdesc, const char *slotdesc, const char *pslotdesc, 
 
136
        const char *fslotdesc, const char *fpslotdesc, int minPwd)
 
137
{
 
138
    char *strings = NULL;
 
139
    char *newStrings;
 
140
 
 
141
    /* make sure the internationalization was done correctly... */
 
142
    strings = PR_smprintf("");
 
143
    if (strings == NULL) return NULL;
 
144
 
 
145
    if (man) {
 
146
        newStrings = PR_smprintf("%s manufacturerID='%s'",strings,man);
 
147
        PR_smprintf_free(strings);
 
148
        strings = newStrings;
 
149
    }
 
150
    if (strings == NULL) return NULL;
 
151
 
 
152
    if (libdesc) {
 
153
        newStrings = PR_smprintf("%s libraryDescription='%s'",strings,libdesc);
 
154
        PR_smprintf_free(strings);
 
155
        strings = newStrings;
 
156
    }
 
157
    if (strings == NULL) return NULL;
 
158
 
 
159
    if (tokdesc) {
 
160
        newStrings = PR_smprintf("%s cryptoTokenDescription='%s'",strings,
 
161
                                                                tokdesc);
 
162
        PR_smprintf_free(strings);
 
163
        strings = newStrings;
 
164
    }
 
165
    if (strings == NULL) return NULL;
 
166
 
 
167
    if (ptokdesc) {
 
168
        newStrings = PR_smprintf("%s dbTokenDescription='%s'",strings,ptokdesc);
 
169
        PR_smprintf_free(strings);
 
170
        strings = newStrings;
 
171
    }
 
172
    if (strings == NULL) return NULL;
 
173
 
 
174
    if (slotdesc) {
 
175
        newStrings = PR_smprintf("%s cryptoSlotDescription='%s'",strings,
 
176
                                                                slotdesc);
 
177
        PR_smprintf_free(strings);
 
178
        strings = newStrings;
 
179
    }
 
180
    if (strings == NULL) return NULL;
 
181
 
 
182
    if (pslotdesc) {
 
183
        newStrings = PR_smprintf("%s dbSlotDescription='%s'",strings,pslotdesc);
 
184
        PR_smprintf_free(strings);
 
185
        strings = newStrings;
 
186
    }
 
187
    if (strings == NULL) return NULL;
 
188
 
 
189
    if (fslotdesc) {
 
190
        newStrings = PR_smprintf("%s FIPSSlotDescription='%s'",
 
191
                                                        strings,fslotdesc);
 
192
        PR_smprintf_free(strings);
 
193
        strings = newStrings;
 
194
    }
 
195
    if (strings == NULL) return NULL;
 
196
 
 
197
    if (fpslotdesc) {
 
198
        newStrings = PR_smprintf("%s FIPSTokenDescription='%s'",
 
199
                                                        strings,fpslotdesc);
 
200
        PR_smprintf_free(strings);
 
201
        strings = newStrings;
 
202
    }
 
203
    if (strings == NULL) return NULL;
 
204
 
 
205
    newStrings = PR_smprintf("%s minPS=%d", strings, minPwd);
 
206
    PR_smprintf_free(strings);
 
207
    strings = newStrings;
 
208
 
 
209
    return(strings);
 
210
}
 
211
 
130
212
/*
131
213
 * statics to remember the PK11_ConfigurePKCS11()
132
214
 * info.
140
222
 * the PKCS #11 internal token.
141
223
 */
142
224
void
143
 
PK11_ConfigurePKCS11(const char *man, const char *libdes, const char *tokdes,
144
 
        const char *ptokdes, const char *slotdes, const char *pslotdes, 
145
 
        const char *fslotdes, const char *fpslotdes, int minPwd, int pwRequired)
 
225
PK11_ConfigurePKCS11(const char *man, const char *libdesc, const char *tokdesc,
 
226
        const char *ptokdesc, const char *slotdesc, const char *pslotdesc, 
 
227
        const char *fslotdesc, const char *fpslotdesc, int minPwd, 
 
228
        int pwRequired)
146
229
{
147
 
   char *strings = NULL;
148
 
   char *newStrings;
149
 
 
150
 
   /* make sure the internationalization was done correctly... */
151
 
   strings = PR_smprintf("");
152
 
   if (strings == NULL) return;
153
 
 
154
 
    if (man) {
155
 
        newStrings = PR_smprintf("%s manufacturerID='%s'",strings,man);
156
 
        PR_smprintf_free(strings);
157
 
        strings = newStrings;
 
230
    char * strings;
 
231
 
 
232
    strings = nss_MkConfigString(man,libdesc,tokdesc,ptokdesc,slotdesc,
 
233
        pslotdesc,fslotdesc,fpslotdesc,minPwd);
 
234
    if (strings == NULL) {
 
235
        return;
158
236
    }
159
 
   if (strings == NULL) return;
160
237
 
161
 
    if (libdes) {
162
 
        newStrings = PR_smprintf("%s libraryDescription='%s'",strings,libdes);
163
 
        PR_smprintf_free(strings);
164
 
        strings = newStrings;
 
238
    if (libdesc) {
165
239
        if (pk11_config_name != NULL) {
166
240
            PORT_Free(pk11_config_name);
167
241
        }
168
 
        pk11_config_name = PORT_Strdup(libdes);
169
 
    }
170
 
   if (strings == NULL) return;
171
 
 
172
 
    if (tokdes) {
173
 
        newStrings = PR_smprintf("%s cryptoTokenDescription='%s'",strings,
174
 
                                                                tokdes);
175
 
        PR_smprintf_free(strings);
176
 
        strings = newStrings;
177
 
    }
178
 
   if (strings == NULL) return;
179
 
 
180
 
    if (ptokdes) {
181
 
        newStrings = PR_smprintf("%s dbTokenDescription='%s'",strings,ptokdes);
182
 
        PR_smprintf_free(strings);
183
 
        strings = newStrings;
184
 
    }
185
 
   if (strings == NULL) return;
186
 
 
187
 
    if (slotdes) {
188
 
        newStrings = PR_smprintf("%s cryptoSlotDescription='%s'",strings,
189
 
                                                                slotdes);
190
 
        PR_smprintf_free(strings);
191
 
        strings = newStrings;
192
 
    }
193
 
   if (strings == NULL) return;
194
 
 
195
 
    if (pslotdes) {
196
 
        newStrings = PR_smprintf("%s dbSlotDescription='%s'",strings,pslotdes);
197
 
        PR_smprintf_free(strings);
198
 
        strings = newStrings;
199
 
    }
200
 
   if (strings == NULL) return;
201
 
 
202
 
    if (fslotdes) {
203
 
        newStrings = PR_smprintf("%s FIPSSlotDescription='%s'",
204
 
                                                        strings,fslotdes);
205
 
        PR_smprintf_free(strings);
206
 
        strings = newStrings;
207
 
    }
208
 
   if (strings == NULL) return;
209
 
 
210
 
    if (fpslotdes) {
211
 
        newStrings = PR_smprintf("%s FIPSTokenDescription='%s'",
212
 
                                                        strings,fpslotdes);
213
 
        PR_smprintf_free(strings);
214
 
        strings = newStrings;
215
 
    }
216
 
   if (strings == NULL) return;
217
 
 
218
 
    newStrings = PR_smprintf("%s minPS=%d", strings, minPwd);
219
 
    PR_smprintf_free(strings);
220
 
    strings = newStrings;
221
 
   if (strings == NULL) return;
 
242
        pk11_config_name = PORT_Strdup(libdesc);
 
243
    }
222
244
 
223
245
    if (pk11_config_strings != NULL) {
224
246
        PR_smprintf_free(pk11_config_strings);
241
263
    }
242
264
}
243
265
 
244
 
static char *
245
 
nss_addEscape(const char *string, char quote)
246
 
{
247
 
    char *newString = 0;
248
 
    int escapes = 0, size = 0;
249
 
    const char *src;
250
 
    char *dest;
251
 
 
252
 
    for (src=string; *src ; src++) {
253
 
        if ((*src == quote) || (*src == '\\')) escapes++;
254
 
        size++;
255
 
    }
256
 
 
257
 
    newString = PORT_ZAlloc(escapes+size+1); 
258
 
    if (newString == NULL) {
259
 
        return NULL;
260
 
    }
261
 
 
262
 
    for (src=string, dest=newString; *src; src++,dest++) {
263
 
        if ((*src == '\\') || (*src == quote)) {
264
 
            *dest++ = '\\';
265
 
        }
266
 
        *dest = *src;
267
 
    }
268
 
 
269
 
    return newString;
270
 
}
271
 
 
272
 
static char *
273
 
nss_doubleEscape(const char *string)
274
 
{
275
 
    char *round1 = NULL;
276
 
    char *retValue = NULL;
277
 
    if (string == NULL) {
278
 
        goto done;
279
 
    }
280
 
    round1 = nss_addEscape(string,'\'');
281
 
    if (round1) {
282
 
        retValue = nss_addEscape(round1,'"');
283
 
        PORT_Free(round1);
284
 
    }
285
 
 
286
 
done:
287
 
    if (retValue == NULL) {
288
 
        retValue = PORT_Strdup("");
289
 
    }
290
 
    return retValue;
291
 
}
292
 
 
293
 
 
294
266
/*
295
267
 * The following code is an attempt to automagically find the external root
296
268
 * module.
388
360
}
389
361
 
390
362
/*
391
 
 * OK there are now lots of options here, lets go through them all:
 
363
 * see nss_Init for definitions of the various options.
392
364
 *
393
 
 * configdir - base directory where all the cert, key, and module datbases live.
394
 
 * certPrefix - prefix added to the beginning of the cert database example: "
395
 
 *                      "https-server1-"
396
 
 * keyPrefix - prefix added to the beginning of the key database example: "
397
 
 *                      "https-server1-"
398
 
 * secmodName - name of the security module database (usually "secmod.db").
399
 
 * readOnly - Boolean: true if the databases are to be opened read only.
400
 
 * nocertdb - Don't open the cert DB and key DB's, just initialize the 
401
 
 *                      Volatile certdb.
402
 
 * nomoddb - Don't open the security module DB, just initialize the 
403
 
 *                      PKCS #11 module.
404
 
 * forceOpen - Continue to force initializations even if the databases cannot
405
 
 *                      be opened.
 
365
 * this function builds a moduleSpec string from the options and previously
 
366
 * set statics (from PKCS11_Configure, for instance), and uses it to kick off
 
367
 * the loading of the various PKCS #11 modules.
406
368
 */
407
 
 
408
 
static PRBool nss_IsInitted = PR_FALSE;
409
 
static void* plContext = NULL;
410
 
 
411
 
static SECStatus nss_InitShutdownList(void);
412
 
 
413
 
#ifdef DEBUG
414
 
static CERTCertificate dummyCert;
415
 
#endif
416
 
 
417
369
static SECStatus
418
 
nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
419
 
                 const char *secmodName, const char *updateDir, 
420
 
                 const char *updCertPrefix, const char *updKeyPrefix,
421
 
                 const char *updateID, const char *updateName,
422
 
                        PRBool readOnly, PRBool noCertDB, 
423
 
                        PRBool noModDB, PRBool forceOpen, PRBool noRootInit,
424
 
                        PRBool optimizeSpace, PRBool noSingleThreadedModules,
425
 
                        PRBool allowAlreadyInitializedModules,
426
 
                        PRBool dontFinalizeModules)
 
370
nss_InitModules(const char *configdir, const char *certPrefix, 
 
371
                const char *keyPrefix, const char *secmodName, 
 
372
                const char *updateDir, const char *updCertPrefix, 
 
373
                const char *updKeyPrefix, const char *updateID, 
 
374
                const char *updateName, char *configName, char *configStrings,
 
375
                PRBool pwRequired, PRBool readOnly, PRBool noCertDB,
 
376
                PRBool noModDB, PRBool forceOpen, PRBool optimizeSpace,
 
377
                PRBool isContextInit)
427
378
{
 
379
    SECStatus rv = SECFailure;
428
380
    char *moduleSpec = NULL;
429
381
    char *flags = NULL;
430
 
    SECStatus rv = SECFailure;
431
382
    char *lconfigdir = NULL;
432
383
    char *lcertPrefix = NULL;
433
384
    char *lkeyPrefix = NULL;
437
388
    char *lupdKeyPrefix = NULL;
438
389
    char *lupdateID = NULL;
439
390
    char *lupdateName = NULL;
440
 
    PKIX_UInt32 actualMinorVersion = 0;
441
 
    PKIX_Error *pkixError = NULL;;
442
 
 
443
 
    if (nss_IsInitted) {
444
 
        return SECSuccess;
445
 
    }
446
 
 
447
 
    /* New option bits must not change the size of CERTCertificate. */
448
 
    PORT_Assert(sizeof(dummyCert.options) == sizeof(void *));
449
 
 
450
 
    if (SECSuccess != cert_InitLocks()) {
451
 
        return SECFailure;
452
 
    }
453
 
 
454
 
    if (SECSuccess != InitCRLCache()) {
455
 
        return SECFailure;
456
 
    }
457
 
    
458
 
    if (SECSuccess != OCSP_InitGlobal()) {
459
 
        return SECFailure;
460
 
    }
461
391
 
462
392
    flags = nss_makeFlags(readOnly,noCertDB,noModDB,forceOpen,
463
 
                                        pk11_password_required, optimizeSpace);
 
393
                                        pwRequired, optimizeSpace);
464
394
    if (flags == NULL) return rv;
465
395
 
466
396
    /*
467
397
     * configdir is double nested, and Windows uses the same character
468
398
     * for file seps as we use for escapes! (sigh).
469
399
     */
470
 
    lconfigdir = nss_doubleEscape(configdir);
 
400
    lconfigdir = secmod_DoubleEscape(configdir, '\'', '\"');
471
401
    if (lconfigdir == NULL) {
472
402
        goto loser;
473
403
    }
474
 
    lcertPrefix = nss_doubleEscape(certPrefix);
 
404
    lcertPrefix = secmod_DoubleEscape(certPrefix, '\'', '\"');
475
405
    if (lcertPrefix == NULL) {
476
406
        goto loser;
477
407
    }
478
 
    lkeyPrefix = nss_doubleEscape(keyPrefix);
 
408
    lkeyPrefix = secmod_DoubleEscape(keyPrefix, '\'', '\"');
479
409
    if (lkeyPrefix == NULL) {
480
410
        goto loser;
481
411
    }
482
 
    lsecmodName = nss_doubleEscape(secmodName);
 
412
    lsecmodName = secmod_DoubleEscape(secmodName, '\'', '\"');
483
413
    if (lsecmodName == NULL) {
484
414
        goto loser;
485
415
    }
486
 
    lupdateDir = nss_doubleEscape(updateDir);
 
416
    lupdateDir = secmod_DoubleEscape(updateDir, '\'', '\"');
487
417
    if (lupdateDir == NULL) {
488
418
        goto loser;
489
419
    }
490
 
    lupdCertPrefix = nss_doubleEscape(updCertPrefix);
 
420
    lupdCertPrefix = secmod_DoubleEscape(updCertPrefix, '\'', '\"');
491
421
    if (lupdCertPrefix == NULL) {
492
422
        goto loser;
493
423
    }
494
 
    lupdKeyPrefix = nss_doubleEscape(updKeyPrefix);
 
424
    lupdKeyPrefix = secmod_DoubleEscape(updKeyPrefix, '\'', '\"');
495
425
    if (lupdKeyPrefix == NULL) {
496
426
        goto loser;
497
427
    }
498
 
    lupdateID = nss_doubleEscape(updateID);
 
428
    lupdateID = secmod_DoubleEscape(updateID, '\'', '\"');
499
429
    if (lupdateID == NULL) {
500
430
        goto loser;
501
431
    }
502
 
    lupdateName = nss_doubleEscape(updateName);
 
432
    lupdateName = secmod_DoubleEscape(updateName, '\'', '\"');
503
433
    if (lupdateName == NULL) {
504
434
        goto loser;
505
435
    }
506
 
    if (noSingleThreadedModules || allowAlreadyInitializedModules ||
507
 
        dontFinalizeModules) {
508
 
        pk11_setGlobalOptions(noSingleThreadedModules,
509
 
                              allowAlreadyInitializedModules,
510
 
                              dontFinalizeModules);
511
 
    }
512
436
 
513
437
    moduleSpec = PR_smprintf(
514
438
     "name=\"%s\" parameters=\"configdir='%s' certPrefix='%s' keyPrefix='%s' "
515
439
     "secmod='%s' flags=%s updatedir='%s' updateCertPrefix='%s' "
516
440
     "updateKeyPrefix='%s' updateid='%s' updateTokenDescription='%s' %s\" "
517
 
     "NSS=\"flags=internal,moduleDB,moduleDBOnly,critical\"",
518
 
                pk11_config_name ? pk11_config_name : NSS_DEFAULT_MOD_NAME,
 
441
     "NSS=\"flags=internal,moduleDB,moduleDBOnly,critical%s\"",
 
442
                configName ? configName : NSS_DEFAULT_MOD_NAME,
519
443
                lconfigdir,lcertPrefix,lkeyPrefix,lsecmodName,flags,
520
444
                lupdateDir, lupdCertPrefix, lupdKeyPrefix, lupdateID, 
521
 
                lupdateName, pk11_config_strings ? pk11_config_strings : "");
 
445
                lupdateName, configStrings ? configStrings : "",
 
446
                isContextInit ? "" : ",defaultModDB,internalKeySlot");
522
447
 
523
448
loser:
524
449
    PORT_Free(flags);
540
465
            SECMOD_DestroyModule(module);
541
466
        }
542
467
    }
543
 
 
544
 
    if (rv == SECSuccess) {
 
468
    return rv;
 
469
}
 
470
 
 
471
/*
 
472
 * OK there are now lots of options here, lets go through them all:
 
473
 *
 
474
 * configdir - base directory where all the cert, key, and module datbases live.
 
475
 * certPrefix - prefix added to the beginning of the cert database example: "
 
476
 *                      "https-server1-"
 
477
 * keyPrefix - prefix added to the beginning of the key database example: "
 
478
 *                      "https-server1-"
 
479
 * secmodName - name of the security module database (usually "secmod.db").
 
480
 * updateDir - used in initMerge, old directory to update from.
 
481
 * updateID - used in initMerge, unique ID to represent the updated directory.
 
482
 * updateName - used in initMerge, token name when updating.
 
483
 * initContextPtr -  used in initContext, pointer to return a unique context
 
484
 *            value.
 
485
 * readOnly - Boolean: true if the databases are to be opened read only.
 
486
 * nocertdb - Don't open the cert DB and key DB's, just initialize the 
 
487
 *                      Volatile certdb.
 
488
 * nomoddb - Don't open the security module DB, just initialize the 
 
489
 *                      PKCS #11 module.
 
490
 * forceOpen - Continue to force initializations even if the databases cannot
 
491
 *                      be opened.
 
492
 * noRootInit - don't try to automatically load the root cert store if one is
 
493
 *           not found.
 
494
 * optimizeSpace - tell NSS to use fewer hash table buckets.
 
495
 *
 
496
 * The next three options are used in an attempt to share PKCS #11 modules
 
497
 * with other loaded, running libraries. PKCS #11 was not designed with this
 
498
 * sort of sharing in mind, so use of these options may lead to questionable
 
499
 * results. These options are may be incompatible with NSS_LoadContext() calls.
 
500
 *
 
501
 * noSingleThreadedModules - don't load modules that are not thread safe (many
 
502
 *           smart card tokens will not work).
 
503
 * allowAlreadyInitializedModules - if a module has already been loaded and
 
504
 *           initialize try to use it.
 
505
 * don'tFinalizeModules -  dont shutdown modules we may have loaded.
 
506
 */
 
507
 
 
508
static PRBool          nssIsInitted = PR_FALSE;
 
509
static NSSInitContext *nssInitContextList = NULL;
 
510
static void*           plContext = NULL;
 
511
 
 
512
struct NSSInitContextStr {
 
513
    NSSInitContext *next;
 
514
    PRUint32 magic;
 
515
};
 
516
 
 
517
#define NSS_INIT_MAGIC 0x1413A91C
 
518
static SECStatus nss_InitShutdownList(void);
 
519
 
 
520
#ifdef DEBUG
 
521
static CERTCertificate dummyCert;
 
522
#endif
 
523
 
 
524
static SECStatus
 
525
nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
 
526
                 const char *secmodName, const char *updateDir, 
 
527
                 const char *updCertPrefix, const char *updKeyPrefix,
 
528
                 const char *updateID, const char *updateName,
 
529
                 NSSInitContext ** initContextPtr,
 
530
                 NSSInitParameters *initParams,
 
531
                 PRBool readOnly, PRBool noCertDB, 
 
532
                 PRBool noModDB, PRBool forceOpen, PRBool noRootInit,
 
533
                 PRBool optimizeSpace, PRBool noSingleThreadedModules,
 
534
                 PRBool allowAlreadyInitializedModules,
 
535
                 PRBool dontFinalizeModules)
 
536
{
 
537
    SECStatus rv = SECFailure;
 
538
    PKIX_UInt32 actualMinorVersion = 0;
 
539
    PKIX_Error *pkixError = NULL;
 
540
    PRBool isReallyInitted;
 
541
    char *configStrings = NULL;
 
542
    char *configName = NULL;
 
543
    PRBool passwordRequired = PR_FALSE;
 
544
 
 
545
    /* if we are trying to init with a traditional NSS_Init call, maintain
 
546
     * the traditional idempotent behavior. */
 
547
    if (!initContextPtr && nssIsInitted) {
 
548
        return SECSuccess;
 
549
    }
 
550
 
 
551
    /* this tells us whether or not some library has already initialized us.
 
552
     * if so, we don't want to double call some of the basic initialization
 
553
     * functions */
 
554
    isReallyInitted = NSS_IsInitialized();
 
555
 
 
556
    if (!isReallyInitted) {
 
557
        /* New option bits must not change the size of CERTCertificate. */
 
558
        PORT_Assert(sizeof(dummyCert.options) == sizeof(void *));
 
559
 
 
560
        if (SECSuccess != cert_InitLocks()) {
 
561
            return SECFailure;
 
562
        }
 
563
 
 
564
        if (SECSuccess != InitCRLCache()) {
 
565
            return SECFailure;
 
566
        }
 
567
    
 
568
        if (SECSuccess != OCSP_InitGlobal()) {
 
569
            return SECFailure;
 
570
        }
 
571
    }
 
572
 
 
573
    if (noSingleThreadedModules || allowAlreadyInitializedModules ||
 
574
        dontFinalizeModules) {
 
575
        pk11_setGlobalOptions(noSingleThreadedModules,
 
576
                              allowAlreadyInitializedModules,
 
577
                              dontFinalizeModules);
 
578
    }
 
579
 
 
580
    if (initContextPtr) {
 
581
        *initContextPtr = PORT_ZNew(NSSInitContext);
 
582
        if (*initContextPtr == NULL) {
 
583
            return SECFailure;
 
584
        }
 
585
        /*
 
586
         * For traditional NSS_Init, we used the PK11_Configure() call to set
 
587
         * globals. with InitContext, we pass those strings in as parameters.
 
588
         *
 
589
         * This allows old NSS_Init calls to work as before, while at the same
 
590
         * time new calls and old calls will not interfere with each other.
 
591
         */
 
592
        if (initParams) {
 
593
            if (initParams->length < sizeof(NSSInitParameters)) {
 
594
                PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
595
                return SECFailure;
 
596
            }
 
597
            configStrings = nss_MkConfigString(initParams->manufactureID,
 
598
                initParams->libraryDescription,
 
599
                initParams->cryptoTokenDescription,
 
600
                initParams->dbTokenDescription,
 
601
                initParams->cryptoSlotDescription,
 
602
                initParams->dbSlotDescription,
 
603
                initParams->FIPSSlotDescription,
 
604
                initParams->FIPSTokenDescription,
 
605
                initParams->minPWLen);
 
606
            if (configStrings == NULL) {
 
607
                PORT_SetError(SEC_ERROR_NO_MEMORY);
 
608
                return SECFailure;
 
609
            }
 
610
            configName = initParams->libraryDescription;
 
611
            passwordRequired = initParams->passwordRequired;
 
612
        }
 
613
    } else {
 
614
        configStrings = pk11_config_strings;
 
615
        configName = pk11_config_name;
 
616
        passwordRequired = pk11_password_required;
 
617
    }
 
618
 
 
619
    /* we always try to initialize the modules */
 
620
    rv = nss_InitModules(configdir, certPrefix, keyPrefix, secmodName, 
 
621
                updateDir, updCertPrefix, updKeyPrefix, updateID, 
 
622
                updateName, configName, configStrings, passwordRequired,
 
623
                readOnly, noCertDB, noModDB, forceOpen, optimizeSpace, 
 
624
                (initContextPtr != NULL));
 
625
 
 
626
    if (rv != SECSuccess) {
 
627
        goto loser;
 
628
    }
 
629
 
 
630
 
 
631
    /* finish up initialization */
 
632
    if (!isReallyInitted) {
545
633
        if (SECOID_Init() != SECSuccess) {
546
 
            return SECFailure;
 
634
            goto loser;
547
635
        }
548
636
        if (STAN_LoadDefaultNSS3TrustDomain() != PR_SUCCESS) {
549
 
            return SECFailure;
 
637
            goto loser;
550
638
        }
551
639
        if (nss_InitShutdownList() != SECSuccess) {
552
 
            return SECFailure;
 
640
            goto loser;
553
641
        }
554
642
        CERT_SetDefaultCertDB((CERTCertDBHandle *)
555
643
                                STAN_GetDefaultTrustDomain());
556
644
        if ((!noModDB) && (!noCertDB) && (!noRootInit)) {
557
645
            if (!SECMOD_HasRootCerts()) {
558
 
                nss_FindExternalRoot(configdir, secmodName);
 
646
                const char *dbpath = configdir;
 
647
                /* handle supported database modifiers */
 
648
                if (strncmp(dbpath, "sql:", 4) == 0) {
 
649
                    dbpath += 4;
 
650
                } else if(strncmp(dbpath, "dbm:", 4) == 0) {
 
651
                    dbpath += 4;
 
652
                } else if(strncmp(dbpath, "extern:", 7) == 0) {
 
653
                    dbpath += 7;
 
654
                } else if(strncmp(dbpath, "rdb:", 4) == 0) {
 
655
                    /* if rdb: is specified, the configdir isn't really a 
 
656
                     * path. Skip it */
 
657
                    dbpath = NULL;
 
658
                }
 
659
                if (dbpath) {
 
660
                    nss_FindExternalRoot(dbpath, secmodName);
 
661
                }
559
662
            }
560
663
        }
 
664
 
561
665
        pk11sdr_Init();
562
666
        cert_CreateSubjectKeyIDHashTable();
563
 
        nss_IsInitted = PR_TRUE;
564
 
    }
565
667
 
566
 
    if (SECSuccess == rv) {
567
668
        pkixError = PKIX_Initialize
568
669
            (PKIX_FALSE, PKIX_MAJOR_VERSION, PKIX_MINOR_VERSION,
569
670
            PKIX_MINOR_VERSION, &actualMinorVersion, &plContext);
570
671
 
571
672
        if (pkixError != NULL) {
572
 
            rv = SECFailure;
 
673
            goto loser;
573
674
        } else {
574
675
            char *ev = getenv("NSS_ENABLE_PKIX_VERIFY");
575
676
            if (ev && ev[0]) {
576
677
                CERT_SetUsePKIXForValidation(PR_TRUE);
577
678
            }
578
679
        }
579
 
    }
580
 
 
581
 
    return rv;
 
680
 
 
681
 
 
682
    }
 
683
 
 
684
    /*
 
685
     * Now mark the appropriate init state. If initContextPtr was passed
 
686
     * in, then return the new context pointer and add it to the
 
687
     * nssInitContextList. Otherwise set the global nss_isInitted flag
 
688
     */
 
689
    if (!initContextPtr) {
 
690
        nssIsInitted = PR_TRUE;
 
691
    } else {
 
692
        (*initContextPtr)->magic = NSS_INIT_MAGIC;
 
693
        (*initContextPtr)->next = nssInitContextList;
 
694
        nssInitContextList = (*initContextPtr);
 
695
    }
 
696
 
 
697
    return SECSuccess;
 
698
 
 
699
loser:
 
700
    if (initContextPtr && *initContextPtr) {
 
701
        PORT_Free(*initContextPtr);
 
702
        *initContextPtr = NULL;
 
703
        if (configStrings) {
 
704
           PR_smprintf_free(configStrings);
 
705
        }
 
706
    }
 
707
    return SECFailure;
582
708
}
583
709
 
584
710
 
585
711
SECStatus
586
712
NSS_Init(const char *configdir)
587
713
{
588
 
    return nss_Init(configdir, "", "", SECMOD_DB, "", "", "", "", "",
589
 
                PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, 
 
714
    return nss_Init(configdir, "", "", SECMOD_DB, "", "", "", "", "", NULL,
 
715
                NULL, PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, 
590
716
                PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE);
591
717
}
592
718
 
593
719
SECStatus
594
720
NSS_InitReadWrite(const char *configdir)
595
721
{
596
 
    return nss_Init(configdir, "", "", SECMOD_DB, "", "", "", "", "",
597
 
                PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, 
 
722
    return nss_Init(configdir, "", "", SECMOD_DB, "", "", "", "", "", NULL,
 
723
                NULL, PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, 
598
724
                PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE);
599
725
}
600
726
 
651
777
        const char *keyPrefix, const char *secmodName, PRUint32 flags)
652
778
{
653
779
    return nss_Init(configdir, certPrefix, keyPrefix, secmodName,
654
 
        "", "", "", "", "",
 
780
        "", "", "", "", "", NULL, NULL,
655
781
        ((flags & NSS_INIT_READONLY) == NSS_INIT_READONLY),
656
782
        ((flags & NSS_INIT_NOCERTDB) == NSS_INIT_NOCERTDB),
657
783
        ((flags & NSS_INIT_NOMODDB) == NSS_INIT_NOMODDB),
663
789
        ((flags & NSS_INIT_NOPK11FINALIZE) == NSS_INIT_NOPK11FINALIZE));
664
790
}
665
791
 
 
792
NSSInitContext *
 
793
NSS_InitContext(const char *configdir, const char *certPrefix, 
 
794
        const char *keyPrefix, const char *secmodName, 
 
795
        NSSInitParameters *initParams, PRUint32 flags)
 
796
{
 
797
    SECStatus rv;
 
798
    NSSInitContext *context;
 
799
 
 
800
    rv = nss_Init(configdir, certPrefix, keyPrefix, secmodName,
 
801
        "", "", "", "", "", &context, initParams,
 
802
        ((flags & NSS_INIT_READONLY) == NSS_INIT_READONLY),
 
803
        ((flags & NSS_INIT_NOCERTDB) == NSS_INIT_NOCERTDB),
 
804
        ((flags & NSS_INIT_NOMODDB) == NSS_INIT_NOMODDB),
 
805
        ((flags & NSS_INIT_FORCEOPEN) == NSS_INIT_FORCEOPEN), PR_TRUE,
 
806
        ((flags & NSS_INIT_OPTIMIZESPACE) == NSS_INIT_OPTIMIZESPACE),
 
807
        ((flags & NSS_INIT_PK11THREADSAFE) == NSS_INIT_PK11THREADSAFE),
 
808
        ((flags & NSS_INIT_PK11RELOAD) == NSS_INIT_PK11RELOAD),
 
809
        ((flags & NSS_INIT_NOPK11FINALIZE) == NSS_INIT_NOPK11FINALIZE));
 
810
    return (rv == SECSuccess) ? context : NULL;
 
811
}
 
812
 
666
813
SECStatus
667
814
NSS_InitWithMerge(const char *configdir, const char *certPrefix, 
668
815
        const char *keyPrefix, const char *secmodName, 
671
818
        const char *updateName, PRUint32 flags)
672
819
{
673
820
    return nss_Init(configdir, certPrefix, keyPrefix, secmodName,
674
 
        updateDir, updCertPrefix, updKeyPrefix, updateID, updateName,
 
821
        updateDir, updCertPrefix, updKeyPrefix, updateID, updateName, 
 
822
        NULL, NULL,
675
823
        ((flags & NSS_INIT_READONLY) == NSS_INIT_READONLY),
676
824
        ((flags & NSS_INIT_NOCERTDB) == NSS_INIT_NOCERTDB),
677
825
        ((flags & NSS_INIT_NOMODDB) == NSS_INIT_NOMODDB),
689
837
SECStatus
690
838
NSS_NoDB_Init(const char * configdir)
691
839
{
692
 
      return nss_Init("","","","", "", "", "", "", "",
 
840
      return nss_Init("","","","", "", "", "", "", "", NULL, NULL,
693
841
                        PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,
694
842
                        PR_FALSE,PR_FALSE,PR_FALSE);
695
843
}
717
865
{
718
866
    int count, i;
719
867
    count = nssShutdownList.peakFuncs;
720
 
    /* expect the list to be short, just do a linear search */
 
868
 
721
869
    for (i=0; i < count; i++) {
722
870
        if ((nssShutdownList.funcs[i].func == sFunc) &&
723
871
            (nssShutdownList.funcs[i].appData == appData)){
735
883
{
736
884
    int i;
737
885
 
738
 
    if (!nss_IsInitted) {
739
 
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
886
    if (!NSS_IsInitialized()) {
 
887
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
740
888
        return SECFailure;
741
889
    }
742
890
    if (sFunc == NULL) {
769
917
                (nssShutdownList.allocatedFuncs + NSS_SHUTDOWN_STEP) 
770
918
                *sizeof(struct NSSShutdownFuncPair));
771
919
        if (!funcs) {
 
920
            PZ_Unlock(nssShutdownList.lock);
772
921
            return SECFailure;
773
922
        }
774
923
        nssShutdownList.funcs = funcs;
788
937
NSS_UnregisterShutdown(NSS_ShutdownFunc sFunc, void *appData)
789
938
{
790
939
    int i;
791
 
    if (!nss_IsInitted) {
792
 
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
940
    if (!NSS_IsInitialized()) {
 
941
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
793
942
        return SECFailure;
794
943
    }
795
944
 
815
964
static SECStatus
816
965
nss_InitShutdownList(void)
817
966
{
 
967
    if (nssShutdownList.lock != NULL) {
 
968
        return SECSuccess;
 
969
    }
818
970
    nssShutdownList.lock = PZ_NewLock(nssILockOther);
819
971
    if (nssShutdownList.lock == NULL) {
820
972
        return SECFailure;
863
1015
extern const NSSError NSS_ERROR_BUSY;
864
1016
 
865
1017
SECStatus
866
 
NSS_Shutdown(void)
 
1018
nss_Shutdown(void)
867
1019
{
868
1020
    SECStatus shutdownRV = SECSuccess;
869
1021
    SECStatus rv;
870
1022
    PRStatus status;
871
 
 
872
 
    if (!nss_IsInitted) {
873
 
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
874
 
        return SECFailure;
875
 
    }
 
1023
    NSSInitContext *temp;
876
1024
 
877
1025
    rv = nss_ShutdownShutdownList();
878
1026
    if (rv != SECSuccess) {
885
1033
    SECOID_Shutdown();
886
1034
    status = STAN_Shutdown();
887
1035
    cert_DestroySubjectKeyIDHashTable();
 
1036
    pk11_SetInternalKeySlot(NULL);
888
1037
    rv = SECMOD_Shutdown();
889
1038
    if (rv != SECSuccess) {
890
1039
        shutdownRV = SECFailure;
905
1054
        }
906
1055
        shutdownRV = SECFailure;
907
1056
    }
908
 
    nss_IsInitted = PR_FALSE;
 
1057
    nssIsInitted = PR_FALSE;
 
1058
    temp = nssInitContextList;
 
1059
    nssInitContextList = NULL;
 
1060
    /* free the old list. This is necessary when we are called from
 
1061
     * NSS_Shutdown(). */
 
1062
    while (temp) {
 
1063
        NSSInitContext *next = temp->next;
 
1064
        temp->magic = 0;
 
1065
        PORT_Free(temp);
 
1066
        temp = next;
 
1067
    }
909
1068
    return shutdownRV;
910
1069
}
911
1070
 
 
1071
SECStatus
 
1072
NSS_Shutdown(void)
 
1073
{
 
1074
    if (!nssIsInitted) {
 
1075
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
1076
        return SECFailure;
 
1077
    }
 
1078
 
 
1079
    return nss_Shutdown();
 
1080
}
 
1081
 
 
1082
/*
 
1083
 * remove the context from a list. return true if found, false if not
 
1084
 */
 
1085
PRBool
 
1086
nss_RemoveList(NSSInitContext *context) {
 
1087
    NSSInitContext *this = nssInitContextList;
 
1088
    NSSInitContext **last = &nssInitContextList;
 
1089
 
 
1090
    while (this) {
 
1091
        if (this == context) {
 
1092
            *last = this->next;
 
1093
            this->magic = 0;
 
1094
            PORT_Free(this);
 
1095
            return PR_TRUE;
 
1096
        }
 
1097
        last = &this->next;
 
1098
        this=this->next;
 
1099
    }
 
1100
    return PR_FALSE;
 
1101
}
 
1102
 
 
1103
/*
 
1104
 * This form of shutdown is safe in the case where we may have multiple 
 
1105
 * entities using NSS in a single process. Each entity calls shutdown with
 
1106
 * it's own context. The application (which doesn't get a context), calls
 
1107
 * shutdown with NULL. Once all users have 'checked in' NSS will shutdown.
 
1108
 * This is different than NSS_Shutdown, where calling it will shutdown NSS
 
1109
 * irreguardless of who else may have NSS open.
 
1110
 */
 
1111
SECStatus
 
1112
NSS_ShutdownContext(NSSInitContext *context)
 
1113
{
 
1114
   if (!context) {
 
1115
        if (!nssIsInitted) {
 
1116
            PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
1117
            return SECFailure;
 
1118
        }
 
1119
        nssIsInitted = 0;
 
1120
    } else if (! nss_RemoveList(context)) {
 
1121
        /* context was already freed or wasn't valid */
 
1122
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
 
1123
        return SECFailure;
 
1124
    }
 
1125
    if ((nssIsInitted == 0) && (nssInitContextList == NULL)) {
 
1126
        return nss_Shutdown();
 
1127
    }
 
1128
    return SECSuccess;
 
1129
}
 
1130
        
 
1131
        
 
1132
 
 
1133
 
912
1134
PRBool
913
1135
NSS_IsInitialized(void)
914
1136
{
915
 
    return nss_IsInitted;
 
1137
    return (nssIsInitted) || (nssInitContextList != NULL);
916
1138
}
917
1139
 
918
1140
 
929
1151
     * check algorithm.  This release is not backward
930
1152
     * compatible with previous major releases.  It is
931
1153
     * not compatible with future major, minor, or
932
 
     * patch releases.
 
1154
     * patch releases or builds.
933
1155
     */
934
 
    int vmajor = 0, vminor = 0, vpatch = 0;
 
1156
    int vmajor = 0, vminor = 0, vpatch = 0, vbuild = 0;
935
1157
    const char *ptr = importedVersion;
936
1158
    volatile char c; /* force a reference that won't get optimized away */
937
1159
 
953
1175
                vpatch = 10 * vpatch + *ptr - '0';
954
1176
                ptr++;
955
1177
            }
 
1178
            if (*ptr == '.') {
 
1179
                ptr++;
 
1180
                while (isdigit(*ptr)) {
 
1181
                    vbuild = 10 * vbuild + *ptr - '0';
 
1182
                    ptr++;
 
1183
                }
 
1184
            }
956
1185
        }
957
1186
    }
958
1187
 
965
1194
    if (vmajor == NSS_VMAJOR && vminor == NSS_VMINOR && vpatch > NSS_VPATCH) {
966
1195
        return PR_FALSE;
967
1196
    }
 
1197
    if (vmajor == NSS_VMAJOR && vminor == NSS_VMINOR &&
 
1198
        vpatch == NSS_VPATCH && vbuild > NSS_VBUILD) {
 
1199
        return PR_FALSE;
 
1200
    }
968
1201
    /* Check dependent libraries */
969
1202
    if (PR_VersionCheck(PR_VERSION) == PR_FALSE) {
970
1203
        return PR_FALSE;