2
* NSS utility functions
4
* The contents of this file are subject to the Mozilla Public
5
* License Version 1.1 (the "License"); you may not use this file
6
* except in compliance with the License. You may obtain a copy of
7
* the License at http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS
10
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11
* implied. See the License for the specific language governing
12
* rights and limitations under the License.
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is Netscape
17
* Communications Corporation. Portions created by Netscape are
18
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
23
* Alternatively, the contents of this file may be used under the
24
* terms of the GNU General Public License Version 2 or later (the
25
* "GPL"), in which case the provisions of the GPL are applicable
26
* instead of those above. If you wish to allow use of your
27
* version of this file only under the terms of the GPL and not to
28
* allow others to use your version of this file under the MPL,
29
* indicate your decision by deleting the provisions above and
30
* replace them with the notice and other provisions required by
31
* the GPL. If you do not delete the provisions above, a recipient
32
* may use your version of this file under either the MPL or the
35
# $Id: nssinit.c,v 1.64.22.1 2004/10/15 21:13:54 wchang0222%aol.com Exp $
59
* On Windows nss3.dll needs to export the symbol 'mktemp' to be
60
* fully backward compatible with the nss3.dll in NSS 3.2.x and
61
* 3.3.x. This symbol was unintentionally exported and its
62
* definition (in DBM) was moved from nss3.dll to softokn3.dll
63
* in NSS 3.4. See bug 142575.
65
#ifdef WIN32_NSS3_DLL_COMPAT
68
/* exported as 'mktemp' */
70
nss_mktemp(char *path)
76
#define NSS_MAX_FLAG_SIZE sizeof("readOnly")+sizeof("noCertDB")+ \
77
sizeof("noModDB")+sizeof("forceOpen")+sizeof("passwordRequired")+ \
78
sizeof ("optimizeSpace")
79
#define NSS_DEFAULT_MOD_NAME "NSS Internal Module"
82
nss_makeFlags(PRBool readOnly, PRBool noCertDB,
83
PRBool noModDB, PRBool forceOpen,
84
PRBool passwordRequired, PRBool optimizeSpace)
86
char *flags = (char *)PORT_Alloc(NSS_MAX_FLAG_SIZE);
87
PRBool first = PR_TRUE;
89
PORT_Memset(flags,0,NSS_MAX_FLAG_SIZE);
91
PORT_Strcat(flags,"readOnly");
95
if (!first) PORT_Strcat(flags,",");
96
PORT_Strcat(flags,"noCertDB");
100
if (!first) PORT_Strcat(flags,",");
101
PORT_Strcat(flags,"noModDB");
105
if (!first) PORT_Strcat(flags,",");
106
PORT_Strcat(flags,"forceOpen");
109
if (passwordRequired) {
110
if (!first) PORT_Strcat(flags,",");
111
PORT_Strcat(flags,"passwordRequired");
115
if (!first) PORT_Strcat(flags,",");
116
PORT_Strcat(flags,"optimizeSpace");
123
* statics to remember the PKCS11_ConfigurePKCS11()
126
static char * pk11_config_strings = NULL;
127
static char * pk11_config_name = NULL;
128
static PRBool pk11_password_required = PR_FALSE;
131
* this is a legacy configuration function which used to be part of
132
* the PKCS #11 internal token.
135
PK11_ConfigurePKCS11(const char *man, const char *libdes, const char *tokdes,
136
const char *ptokdes, const char *slotdes, const char *pslotdes,
137
const char *fslotdes, const char *fpslotdes, int minPwd, int pwRequired)
139
char *strings = NULL;
142
/* make sure the internationalization was done correctly... */
143
strings = PR_smprintf("");
144
if (strings == NULL) return;
147
newStrings = PR_smprintf("%s manufacturerID='%s'",strings,man);
148
PR_smprintf_free(strings);
149
strings = newStrings;
151
if (strings == NULL) return;
154
newStrings = PR_smprintf("%s libraryDescription='%s'",strings,libdes);
155
PR_smprintf_free(strings);
156
strings = newStrings;
157
if (pk11_config_name != NULL) {
158
PORT_Free(pk11_config_name);
160
pk11_config_name = PORT_Strdup(libdes);
162
if (strings == NULL) return;
165
newStrings = PR_smprintf("%s cryptoTokenDescription='%s'",strings,
167
PR_smprintf_free(strings);
168
strings = newStrings;
170
if (strings == NULL) return;
173
newStrings = PR_smprintf("%s dbTokenDescription='%s'",strings,ptokdes);
174
PR_smprintf_free(strings);
175
strings = newStrings;
177
if (strings == NULL) return;
180
newStrings = PR_smprintf("%s cryptoSlotDescription='%s'",strings,
182
PR_smprintf_free(strings);
183
strings = newStrings;
185
if (strings == NULL) return;
188
newStrings = PR_smprintf("%s dbSlotDescription='%s'",strings,pslotdes);
189
PR_smprintf_free(strings);
190
strings = newStrings;
192
if (strings == NULL) return;
195
newStrings = PR_smprintf("%s FIPSSlotDescription='%s'",
197
PR_smprintf_free(strings);
198
strings = newStrings;
200
if (strings == NULL) return;
203
newStrings = PR_smprintf("%s FIPSTokenDescription='%s'",
205
PR_smprintf_free(strings);
206
strings = newStrings;
208
if (strings == NULL) return;
210
newStrings = PR_smprintf("%s minPS=%d", strings, minPwd);
211
PR_smprintf_free(strings);
212
strings = newStrings;
213
if (strings == NULL) return;
215
if (pk11_config_strings != NULL) {
216
PR_smprintf_free(pk11_config_strings);
218
pk11_config_strings = strings;
219
pk11_password_required = pwRequired;
225
nss_addEscape(const char *string, char quote)
228
int escapes = 0, size = 0;
232
for (src=string; *src ; src++) {
233
if ((*src == quote) || (*src == '\\')) escapes++;
237
newString = PORT_ZAlloc(escapes+size+1);
238
if (newString == NULL) {
242
for (src=string, dest=newString; *src; src++,dest++) {
243
if ((*src == '\\') || (*src == quote)) {
253
nss_doubleEscape(const char *string)
256
char *retValue = NULL;
257
if (string == NULL) {
260
round1 = nss_addEscape(string,'\'');
262
retValue = nss_addEscape(round1,'"');
267
if (retValue == NULL) {
268
retValue = PORT_Strdup("");
276
* The following code is an attempt to automagically find the external root
277
* module. NOTE: This code should be checked out on the MAC! There must be
278
* some cross platform support out there to help out with this?
279
* Note: Keep the #if-defined chunks in order. HPUX must select before UNIX.
282
static const char *dllname =
283
#if defined(XP_WIN32) || defined(XP_OS2)
287
#elif defined(DARWIN)
289
#elif defined(XP_UNIX) || defined(XP_BEOS)
291
#elif defined(XP_MAC)
292
"NSS Builtin Root Certs";
294
#error "Uh! Oh! I don't know about this platform."
297
/* Should we have platform ifdefs here??? */
300
static void nss_FindExternalRootPaths(const char *dbpath, const char* secmodprefix,
301
char** retoldpath, char** retnewpath)
303
char *path, *oldpath = NULL, *lastsep;
304
int len, path_len, secmod_len, dll_len;
306
path_len = PORT_Strlen(dbpath);
307
secmod_len = PORT_Strlen(secmodprefix);
308
dll_len = PORT_Strlen(dllname);
309
len = path_len + secmod_len + dll_len + 2; /* FILE_SEP + NULL */
311
path = PORT_Alloc(len);
312
if (path == NULL) return;
314
/* back up to the top of the directory */
315
PORT_Memcpy(path,dbpath,path_len);
316
if (path[path_len-1] != FILE_SEP) {
317
path[path_len++] = FILE_SEP;
319
PORT_Strcpy(&path[path_len],dllname);
321
lastsep = PORT_Strrchr(secmodprefix, FILE_SEP);
323
int secmoddir_len = lastsep-secmodprefix+1; /* FILE_SEP */
324
oldpath = PORT_Alloc(len);
325
if (oldpath == NULL) {
329
PORT_Memcpy(oldpath,path,path_len);
330
PORT_Memcpy(&oldpath[path_len],secmodprefix,secmoddir_len);
331
PORT_Strcpy(&oldpath[path_len+secmoddir_len],dllname);
334
*retoldpath = oldpath;
339
static void nss_FreeExternalRootPaths(char* oldpath, char* path)
350
nss_FindExternalRoot(const char *dbpath, const char* secmodprefix)
353
char *oldpath = NULL;
354
PRBool hasrootcerts = PR_FALSE;
357
* 'oldpath' is the external root path in NSS 3.3.x or older.
358
* For backward compatibility we try to load the root certs
359
* module with the old path first.
361
nss_FindExternalRootPaths(dbpath, secmodprefix, &oldpath, &path);
363
(void) SECMOD_AddNewModule("Root Certs",oldpath, 0, 0);
364
hasrootcerts = SECMOD_HasRootCerts();
366
if (path && !hasrootcerts) {
367
(void) SECMOD_AddNewModule("Root Certs",path, 0, 0);
369
nss_FreeExternalRootPaths(oldpath, path);
375
* OK there are now lots of options here, lets go through them all:
377
* configdir - base directory where all the cert, key, and module datbases live.
378
* certPrefix - prefix added to the beginning of the cert database example: "
380
* keyPrefix - prefix added to the beginning of the key database example: "
382
* secmodName - name of the security module database (usually "secmod.db").
383
* readOnly - Boolean: true if the databases are to be openned read only.
384
* nocertdb - Don't open the cert DB and key DB's, just initialize the
386
* nomoddb - Don't open the security module DB, just initialize the
388
* forceOpen - Continue to force initializations even if the databases cannot
392
static PRBool nss_IsInitted = PR_FALSE;
394
extern SECStatus secoid_Init(void);
397
nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
398
const char *secmodName, PRBool readOnly, PRBool noCertDB,
399
PRBool noModDB, PRBool forceOpen, PRBool noRootInit,
400
PRBool optimizeSpace)
402
char *moduleSpec = NULL;
404
SECStatus rv = SECFailure;
405
char *lconfigdir = NULL;
406
char *lcertPrefix = NULL;
407
char *lkeyPrefix = NULL;
408
char *lsecmodName = NULL;
414
if (SECSuccess != InitCRLCache()) {
418
flags = nss_makeFlags(readOnly,noCertDB,noModDB,forceOpen,
419
pk11_password_required, optimizeSpace);
420
if (flags == NULL) return rv;
423
* configdir is double nested, and Windows uses the same character
424
* for file seps as we use for escapes! (sigh).
426
lconfigdir = nss_doubleEscape(configdir);
427
if (lconfigdir == NULL) {
430
lcertPrefix = nss_doubleEscape(certPrefix);
431
if (lcertPrefix == NULL) {
434
lkeyPrefix = nss_doubleEscape(keyPrefix);
435
if (lkeyPrefix == NULL) {
438
lsecmodName = nss_doubleEscape(secmodName);
439
if (lsecmodName == NULL) {
443
moduleSpec = PR_smprintf("name=\"%s\" parameters=\"configdir='%s' certPrefix='%s' keyPrefix='%s' secmod='%s' flags=%s %s\" NSS=\"flags=internal,moduleDB,moduleDBOnly,critical\"",
444
pk11_config_name ? pk11_config_name : NSS_DEFAULT_MOD_NAME,
445
lconfigdir,lcertPrefix,lkeyPrefix,lsecmodName,flags,
446
pk11_config_strings ? pk11_config_strings : "");
450
if (lconfigdir) PORT_Free(lconfigdir);
451
if (lcertPrefix) PORT_Free(lcertPrefix);
452
if (lkeyPrefix) PORT_Free(lkeyPrefix);
453
if (lsecmodName) PORT_Free(lsecmodName);
456
SECMODModule *module = SECMOD_LoadModule(moduleSpec,NULL,PR_TRUE);
457
PR_smprintf_free(moduleSpec);
459
if (module->loaded) rv=SECSuccess;
460
SECMOD_DestroyModule(module);
464
if (rv == SECSuccess) {
465
if (secoid_Init() != SECSuccess) {
468
if (STAN_LoadDefaultNSS3TrustDomain() != PR_SUCCESS) {
471
CERT_SetDefaultCertDB((CERTCertDBHandle *)
472
STAN_GetDefaultTrustDomain());
474
/* only servers need this. We currently do not have a mac server */
475
if ((!noModDB) && (!noCertDB) && (!noRootInit)) {
476
if (!SECMOD_HasRootCerts()) {
477
nss_FindExternalRoot(configdir, secmodName);
482
cert_CreateSubjectKeyIDHashTable();
483
nss_IsInitted = PR_TRUE;
490
NSS_Init(const char *configdir)
492
return nss_Init(configdir, "", "", SECMOD_DB, PR_TRUE,
493
PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_TRUE);
497
NSS_InitReadWrite(const char *configdir)
499
return nss_Init(configdir, "", "", SECMOD_DB, PR_FALSE,
500
PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_TRUE);
504
* OK there are now lots of options here, lets go through them all:
506
* configdir - base directory where all the cert, key, and module datbases live.
507
* certPrefix - prefix added to the beginning of the cert database example: "
509
* keyPrefix - prefix added to the beginning of the key database example: "
511
* secmodName - name of the security module database (usually "secmod.db").
512
* flags - change the open options of NSS_Initialize as follows:
513
* NSS_INIT_READONLY - Open the databases read only.
514
* NSS_INIT_NOCERTDB - Don't open the cert DB and key DB's, just
515
* initialize the volatile certdb.
516
* NSS_INIT_NOMODDB - Don't open the security module DB, just
517
* initialize the PKCS #11 module.
518
* NSS_INIT_FORCEOPEN - Continue to force initializations even if the
519
* databases cannot be opened.
522
NSS_Initialize(const char *configdir, const char *certPrefix,
523
const char *keyPrefix, const char *secmodName, PRUint32 flags)
525
return nss_Init(configdir, certPrefix, keyPrefix, secmodName,
526
((flags & NSS_INIT_READONLY) == NSS_INIT_READONLY),
527
((flags & NSS_INIT_NOCERTDB) == NSS_INIT_NOCERTDB),
528
((flags & NSS_INIT_NOMODDB) == NSS_INIT_NOMODDB),
529
((flags & NSS_INIT_FORCEOPEN) == NSS_INIT_FORCEOPEN),
530
((flags & NSS_INIT_NOROOTINIT) == NSS_INIT_NOROOTINIT),
531
((flags & NSS_INIT_OPTIMIZESPACE) == NSS_INIT_OPTIMIZESPACE));
535
* initialize NSS without a creating cert db's, key db's, or secmod db's.
538
NSS_NoDB_Init(const char * configdir)
540
return nss_Init("","","","",
541
PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE);
544
extern const NSSError NSS_ERROR_BUSY;
554
status = STAN_Shutdown();
555
cert_DestroySubjectKeyIDHashTable();
556
rv = SECMOD_Shutdown();
558
if (status == PR_FAILURE) {
559
if (NSS_GetError() == NSS_ERROR_BUSY) {
560
PORT_SetError(SEC_ERROR_BUSY);
564
nss_IsInitted = PR_FALSE;
570
extern const char __nss_base_rcsid[];
572
NSS_IsInitialized(void)
574
return nss_IsInitted;
576
extern const char __nss_base_sccsid[];
579
NSS_VersionCheck(const char *importedVersion)
582
* This is the secret handshake algorithm.
584
* This release has a simple version compatibility
585
* check algorithm. This release is not backward
586
* compatible with previous major releases. It is
587
* not compatible with future major, minor, or
590
int vmajor = 0, vminor = 0, vpatch = 0;
591
const char *ptr = importedVersion;
592
volatile char c; /* force a reference that won't get optimized away */
594
c = __nss_base_rcsid[0] + __nss_base_sccsid[0];
596
while (isdigit(*ptr)) {
597
vmajor = 10 * vmajor + *ptr - '0';
602
while (isdigit(*ptr)) {
603
vminor = 10 * vminor + *ptr - '0';
608
while (isdigit(*ptr)) {
609
vpatch = 10 * vpatch + *ptr - '0';
615
if (vmajor != NSS_VMAJOR) {
618
if (vmajor == NSS_VMAJOR && vminor > NSS_VMINOR) {
621
if (vmajor == NSS_VMAJOR && vminor == NSS_VMINOR && vpatch > NSS_VPATCH) {
624
/* Check dependent libraries */
625
if (PR_VersionCheck(PR_VERSION) == PR_FALSE) {