Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(797)

Side by Side Diff: nss/lib/nss/nssinit.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/nss/nss.h ('k') | nss/lib/nss/nssoptions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * NSS utility functions
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #include <ctype.h>
9 #include <string.h>
10 #include "seccomon.h"
11 #include "prinit.h"
12 #include "prprf.h"
13 #include "prmem.h"
14 #include "cert.h"
15 #include "key.h"
16 #include "secmod.h"
17 #include "secoid.h"
18 #include "nss.h"
19 #include "pk11func.h"
20 #include "secerr.h"
21 #include "nssbase.h"
22 #include "nssutil.h"
23 #ifndef NSS_DISABLE_LIBPKIX
24 #include "pkixt.h"
25 #include "pkix.h"
26 #include "pkix_tools.h"
27 #endif /* NSS_DISABLE_LIBPKIX */
28
29 #include "pki3hack.h"
30 #include "certi.h"
31 #include "secmodi.h"
32 #include "ocspti.h"
33 #include "ocspi.h"
34 #include "utilpars.h"
35
36 /*
37 * On Windows nss3.dll needs to export the symbol 'mktemp' to be
38 * fully backward compatible with the nss3.dll in NSS 3.2.x and
39 * 3.3.x. This symbol was unintentionally exported and its
40 * definition (in DBM) was moved from nss3.dll to softokn3.dll
41 * in NSS 3.4. See bug 142575.
42 */
43 #ifdef WIN32_NSS3_DLL_COMPAT
44 #include <io.h>
45
46 /* exported as 'mktemp' */
47 char *
48 nss_mktemp(char *path)
49 {
50 return _mktemp(path);
51 }
52 #endif
53
54 #define NSS_MAX_FLAG_SIZE sizeof("readOnly")+sizeof("noCertDB")+ \
55 sizeof("noModDB")+sizeof("forceOpen")+sizeof("passwordRequired")+ \
56 sizeof ("optimizeSpace")
57 #define NSS_DEFAULT_MOD_NAME "NSS Internal Module"
58
59 static char *
60 nss_makeFlags(PRBool readOnly, PRBool noCertDB,
61 PRBool noModDB, PRBool forceOpen,
62 PRBool passwordRequired, PRBool optimizeSpace)
63 {
64 char *flags = (char *)PORT_Alloc(NSS_MAX_FLAG_SIZE);
65 PRBool first = PR_TRUE;
66
67 PORT_Memset(flags,0,NSS_MAX_FLAG_SIZE);
68 if (readOnly) {
69 PORT_Strcat(flags,"readOnly");
70 first = PR_FALSE;
71 }
72 if (noCertDB) {
73 if (!first) PORT_Strcat(flags,",");
74 PORT_Strcat(flags,"noCertDB");
75 first = PR_FALSE;
76 }
77 if (noModDB) {
78 if (!first) PORT_Strcat(flags,",");
79 PORT_Strcat(flags,"noModDB");
80 first = PR_FALSE;
81 }
82 if (forceOpen) {
83 if (!first) PORT_Strcat(flags,",");
84 PORT_Strcat(flags,"forceOpen");
85 first = PR_FALSE;
86 }
87 if (passwordRequired) {
88 if (!first) PORT_Strcat(flags,",");
89 PORT_Strcat(flags,"passwordRequired");
90 first = PR_FALSE;
91 }
92 if (optimizeSpace) {
93 if (!first) PORT_Strcat(flags,",");
94 PORT_Strcat(flags,"optimizeSpace");
95 first = PR_FALSE;
96 }
97 return flags;
98 }
99
100
101 /*
102 * build config string from individual internationalized strings
103 */
104 char *
105 nss_MkConfigString(const char *man, const char *libdesc, const char *tokdesc,
106 const char *ptokdesc, const char *slotdesc, const char *pslotdesc,
107 const char *fslotdesc, const char *fpslotdesc, int minPwd)
108 {
109 char *strings = NULL;
110 char *newStrings;
111
112 /* make sure the internationalization was done correctly... */
113 strings = PR_smprintf("");
114 if (strings == NULL) return NULL;
115
116 if (man) {
117 newStrings = PR_smprintf("%s manufacturerID='%s'",strings,man);
118 PR_smprintf_free(strings);
119 strings = newStrings;
120 }
121 if (strings == NULL) return NULL;
122
123 if (libdesc) {
124 newStrings = PR_smprintf("%s libraryDescription='%s'",strings,libdesc);
125 PR_smprintf_free(strings);
126 strings = newStrings;
127 }
128 if (strings == NULL) return NULL;
129
130 if (tokdesc) {
131 newStrings = PR_smprintf("%s cryptoTokenDescription='%s'",strings,
132 tokdesc);
133 PR_smprintf_free(strings);
134 strings = newStrings;
135 }
136 if (strings == NULL) return NULL;
137
138 if (ptokdesc) {
139 newStrings = PR_smprintf("%s dbTokenDescription='%s'",strings,ptokdesc);
140 PR_smprintf_free(strings);
141 strings = newStrings;
142 }
143 if (strings == NULL) return NULL;
144
145 if (slotdesc) {
146 newStrings = PR_smprintf("%s cryptoSlotDescription='%s'",strings,
147 slotdesc);
148 PR_smprintf_free(strings);
149 strings = newStrings;
150 }
151 if (strings == NULL) return NULL;
152
153 if (pslotdesc) {
154 newStrings = PR_smprintf("%s dbSlotDescription='%s'",strings,pslotdesc);
155 PR_smprintf_free(strings);
156 strings = newStrings;
157 }
158 if (strings == NULL) return NULL;
159
160 if (fslotdesc) {
161 newStrings = PR_smprintf("%s FIPSSlotDescription='%s'",
162 strings,fslotdesc);
163 PR_smprintf_free(strings);
164 strings = newStrings;
165 }
166 if (strings == NULL) return NULL;
167
168 if (fpslotdesc) {
169 newStrings = PR_smprintf("%s FIPSTokenDescription='%s'",
170 strings,fpslotdesc);
171 PR_smprintf_free(strings);
172 strings = newStrings;
173 }
174 if (strings == NULL) return NULL;
175
176 newStrings = PR_smprintf("%s minPS=%d", strings, minPwd);
177 PR_smprintf_free(strings);
178 strings = newStrings;
179
180 return(strings);
181 }
182
183 /*
184 * statics to remember the PK11_ConfigurePKCS11()
185 * info.
186 */
187 static char * pk11_config_strings = NULL;
188 static char * pk11_config_name = NULL;
189 static PRBool pk11_password_required = PR_FALSE;
190
191 /*
192 * this is a legacy configuration function which used to be part of
193 * the PKCS #11 internal token.
194 */
195 void
196 PK11_ConfigurePKCS11(const char *man, const char *libdesc, const char *tokdesc,
197 const char *ptokdesc, const char *slotdesc, const char *pslotdesc,
198 const char *fslotdesc, const char *fpslotdesc, int minPwd,
199 int pwRequired)
200 {
201 char * strings;
202
203 strings = nss_MkConfigString(man,libdesc,tokdesc,ptokdesc,slotdesc,
204 pslotdesc,fslotdesc,fpslotdesc,minPwd);
205 if (strings == NULL) {
206 return;
207 }
208
209 if (libdesc) {
210 if (pk11_config_name != NULL) {
211 PORT_Free(pk11_config_name);
212 }
213 pk11_config_name = PORT_Strdup(libdesc);
214 }
215
216 if (pk11_config_strings != NULL) {
217 PR_smprintf_free(pk11_config_strings);
218 }
219 pk11_config_strings = strings;
220 pk11_password_required = pwRequired;
221
222 return;
223 }
224
225 void PK11_UnconfigurePKCS11(void)
226 {
227 if (pk11_config_strings != NULL) {
228 PR_smprintf_free(pk11_config_strings);
229 pk11_config_strings = NULL;
230 }
231 if (pk11_config_name) {
232 PORT_Free(pk11_config_name);
233 pk11_config_name = NULL;
234 }
235 }
236
237 /*
238 * The following code is an attempt to automagically find the external root
239 * module.
240 * Note: Keep the #if-defined chunks in order. HPUX must select before UNIX.
241 */
242
243 static const char *dllname =
244 #if defined(XP_WIN32) || defined(XP_OS2)
245 "nssckbi.dll";
246 #elif defined(HPUX) && !defined(__ia64) /* HP-UX PA-RISC */
247 "libnssckbi.sl";
248 #elif defined(DARWIN)
249 "libnssckbi.dylib";
250 #elif defined(XP_UNIX) || defined(XP_BEOS)
251 "libnssckbi.so";
252 #else
253 #error "Uh! Oh! I don't know about this platform."
254 #endif
255
256 /* Should we have platform ifdefs here??? */
257 #define FILE_SEP '/'
258
259 static void nss_FindExternalRootPaths(const char *dbpath,
260 const char* secmodprefix,
261 char** retoldpath, char** retnewpath)
262 {
263 char *path, *oldpath = NULL, *lastsep;
264 int len, path_len, secmod_len, dll_len;
265
266 path_len = PORT_Strlen(dbpath);
267 secmod_len = secmodprefix ? PORT_Strlen(secmodprefix) : 0;
268 dll_len = PORT_Strlen(dllname);
269 len = path_len + secmod_len + dll_len + 2; /* FILE_SEP + NULL */
270
271 path = PORT_Alloc(len);
272 if (path == NULL) return;
273
274 /* back up to the top of the directory */
275 PORT_Memcpy(path,dbpath,path_len);
276 if (path[path_len-1] != FILE_SEP) {
277 path[path_len++] = FILE_SEP;
278 }
279 PORT_Strcpy(&path[path_len],dllname);
280 if (secmod_len > 0) {
281 lastsep = PORT_Strrchr(secmodprefix, FILE_SEP);
282 if (lastsep) {
283 int secmoddir_len = lastsep-secmodprefix+1; /* FILE_SEP */
284 oldpath = PORT_Alloc(len);
285 if (oldpath == NULL) {
286 PORT_Free(path);
287 return;
288 }
289 PORT_Memcpy(oldpath,path,path_len);
290 PORT_Memcpy(&oldpath[path_len],secmodprefix,secmoddir_len);
291 PORT_Strcpy(&oldpath[path_len+secmoddir_len],dllname);
292 }
293 }
294 *retoldpath = oldpath;
295 *retnewpath = path;
296 return;
297 }
298
299 static void nss_FreeExternalRootPaths(char* oldpath, char* path)
300 {
301 if (path) {
302 PORT_Free(path);
303 }
304 if (oldpath) {
305 PORT_Free(oldpath);
306 }
307 }
308
309 static void
310 nss_FindExternalRoot(const char *dbpath, const char* secmodprefix)
311 {
312 char *path = NULL;
313 char *oldpath = NULL;
314 PRBool hasrootcerts = PR_FALSE;
315
316 /*
317 * 'oldpath' is the external root path in NSS 3.3.x or older.
318 * For backward compatibility we try to load the root certs
319 * module with the old path first.
320 */
321 nss_FindExternalRootPaths(dbpath, secmodprefix, &oldpath, &path);
322 if (oldpath) {
323 (void) SECMOD_AddNewModule("Root Certs",oldpath, 0, 0);
324 hasrootcerts = SECMOD_HasRootCerts();
325 }
326 if (path && !hasrootcerts) {
327 (void) SECMOD_AddNewModule("Root Certs",path, 0, 0);
328 }
329 nss_FreeExternalRootPaths(oldpath, path);
330 return;
331 }
332
333 /*
334 * see nss_Init for definitions of the various options.
335 *
336 * this function builds a moduleSpec string from the options and previously
337 * set statics (from PKCS11_Configure, for instance), and uses it to kick off
338 * the loading of the various PKCS #11 modules.
339 */
340 static SECStatus
341 nss_InitModules(const char *configdir, const char *certPrefix,
342 const char *keyPrefix, const char *secmodName,
343 const char *updateDir, const char *updCertPrefix,
344 const char *updKeyPrefix, const char *updateID,
345 const char *updateName, char *configName, char *configStrings,
346 PRBool pwRequired, PRBool readOnly, PRBool noCertDB,
347 PRBool noModDB, PRBool forceOpen, PRBool optimizeSpace,
348 PRBool isContextInit)
349 {
350 SECStatus rv = SECFailure;
351 char *moduleSpec = NULL;
352 char *flags = NULL;
353 char *lconfigdir = NULL;
354 char *lcertPrefix = NULL;
355 char *lkeyPrefix = NULL;
356 char *lsecmodName = NULL;
357 char *lupdateDir = NULL;
358 char *lupdCertPrefix = NULL;
359 char *lupdKeyPrefix = NULL;
360 char *lupdateID = NULL;
361 char *lupdateName = NULL;
362
363 if (NSS_InitializePRErrorTable() != SECSuccess) {
364 PORT_SetError(SEC_ERROR_NO_MEMORY);
365 return rv;
366 }
367
368 flags = nss_makeFlags(readOnly,noCertDB,noModDB,forceOpen,
369 pwRequired, optimizeSpace);
370 if (flags == NULL) return rv;
371
372 /*
373 * configdir is double nested, and Windows uses the same character
374 * for file seps as we use for escapes! (sigh).
375 */
376 lconfigdir = NSSUTIL_DoubleEscape(configdir, '\'', '\"');
377 if (lconfigdir == NULL) {
378 goto loser;
379 }
380 lcertPrefix = NSSUTIL_DoubleEscape(certPrefix, '\'', '\"');
381 if (lcertPrefix == NULL) {
382 goto loser;
383 }
384 lkeyPrefix = NSSUTIL_DoubleEscape(keyPrefix, '\'', '\"');
385 if (lkeyPrefix == NULL) {
386 goto loser;
387 }
388 lsecmodName = NSSUTIL_DoubleEscape(secmodName, '\'', '\"');
389 if (lsecmodName == NULL) {
390 goto loser;
391 }
392 lupdateDir = NSSUTIL_DoubleEscape(updateDir, '\'', '\"');
393 if (lupdateDir == NULL) {
394 goto loser;
395 }
396 lupdCertPrefix = NSSUTIL_DoubleEscape(updCertPrefix, '\'', '\"');
397 if (lupdCertPrefix == NULL) {
398 goto loser;
399 }
400 lupdKeyPrefix = NSSUTIL_DoubleEscape(updKeyPrefix, '\'', '\"');
401 if (lupdKeyPrefix == NULL) {
402 goto loser;
403 }
404 lupdateID = NSSUTIL_DoubleEscape(updateID, '\'', '\"');
405 if (lupdateID == NULL) {
406 goto loser;
407 }
408 lupdateName = NSSUTIL_DoubleEscape(updateName, '\'', '\"');
409 if (lupdateName == NULL) {
410 goto loser;
411 }
412
413 moduleSpec = PR_smprintf(
414 "name=\"%s\" parameters=\"configdir='%s' certPrefix='%s' keyPrefix='%s' "
415 "secmod='%s' flags=%s updatedir='%s' updateCertPrefix='%s' "
416 "updateKeyPrefix='%s' updateid='%s' updateTokenDescription='%s' %s\" "
417 "NSS=\"flags=internal,moduleDB,moduleDBOnly,critical%s\"",
418 configName ? configName : NSS_DEFAULT_MOD_NAME,
419 lconfigdir,lcertPrefix,lkeyPrefix,lsecmodName,flags,
420 lupdateDir, lupdCertPrefix, lupdKeyPrefix, lupdateID,
421 lupdateName, configStrings ? configStrings : "",
422 isContextInit ? "" : ",defaultModDB,internalKeySlot");
423
424 loser:
425 PORT_Free(flags);
426 if (lconfigdir) PORT_Free(lconfigdir);
427 if (lcertPrefix) PORT_Free(lcertPrefix);
428 if (lkeyPrefix) PORT_Free(lkeyPrefix);
429 if (lsecmodName) PORT_Free(lsecmodName);
430 if (lupdateDir) PORT_Free(lupdateDir);
431 if (lupdCertPrefix) PORT_Free(lupdCertPrefix);
432 if (lupdKeyPrefix) PORT_Free(lupdKeyPrefix);
433 if (lupdateID) PORT_Free(lupdateID);
434 if (lupdateName) PORT_Free(lupdateName);
435
436 if (moduleSpec) {
437 SECMODModule *module = SECMOD_LoadModule(moduleSpec,NULL,PR_TRUE);
438 PR_smprintf_free(moduleSpec);
439 if (module) {
440 if (module->loaded) rv=SECSuccess;
441 SECMOD_DestroyModule(module);
442 }
443 }
444 return rv;
445 }
446
447 /*
448 * OK there are now lots of options here, lets go through them all:
449 *
450 * configdir - base directory where all the cert, key, and module datbases live.
451 * certPrefix - prefix added to the beginning of the cert database example: "
452 * "https-server1-"
453 * keyPrefix - prefix added to the beginning of the key database example: "
454 * "https-server1-"
455 * secmodName - name of the security module database (usually "secmod.db").
456 * updateDir - used in initMerge, old directory to update from.
457 * updateID - used in initMerge, unique ID to represent the updated directory.
458 * updateName - used in initMerge, token name when updating.
459 * initContextPtr - used in initContext, pointer to return a unique context
460 * value.
461 * readOnly - Boolean: true if the databases are to be opened read only.
462 * nocertdb - Don't open the cert DB and key DB's, just initialize the
463 * Volatile certdb.
464 * nomoddb - Don't open the security module DB, just initialize the
465 * PKCS #11 module.
466 * forceOpen - Continue to force initializations even if the databases cannot
467 * be opened.
468 * noRootInit - don't try to automatically load the root cert store if one is
469 * not found.
470 * optimizeSpace - tell NSS to use fewer hash table buckets.
471 *
472 * The next three options are used in an attempt to share PKCS #11 modules
473 * with other loaded, running libraries. PKCS #11 was not designed with this
474 * sort of sharing in mind, so use of these options may lead to questionable
475 * results. These options are may be incompatible with NSS_LoadContext() calls.
476 *
477 * noSingleThreadedModules - don't load modules that are not thread safe (many
478 * smart card tokens will not work).
479 * allowAlreadyInitializedModules - if a module has already been loaded and
480 * initialize try to use it.
481 * don'tFinalizeModules - dont shutdown modules we may have loaded.
482 */
483
484 static PRBool nssIsInitted = PR_FALSE;
485 static NSSInitContext *nssInitContextList = NULL;
486 static void* plContext = NULL;
487
488 struct NSSInitContextStr {
489 NSSInitContext *next;
490 PRUint32 magic;
491 };
492
493 #define NSS_INIT_MAGIC 0x1413A91C
494 static SECStatus nss_InitShutdownList(void);
495
496 /* All initialized to zero in BSS */
497 static PRCallOnceType nssInitOnce;
498 static PZLock *nssInitLock;
499 static PZCondVar *nssInitCondition;
500 static int nssIsInInit;
501
502 static PRStatus
503 nss_doLockInit(void)
504 {
505 nssInitLock = PZ_NewLock(nssILockOther);
506 if (nssInitLock == NULL) {
507 return PR_FAILURE;
508 }
509 nssInitCondition = PZ_NewCondVar(nssInitLock);
510 if (nssInitCondition == NULL) {
511 return PR_FAILURE;
512 }
513 return PR_SUCCESS;
514 }
515
516
517 static SECStatus
518 nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
519 const char *secmodName, const char *updateDir,
520 const char *updCertPrefix, const char *updKeyPrefix,
521 const char *updateID, const char *updateName,
522 NSSInitContext ** initContextPtr,
523 NSSInitParameters *initParams,
524 PRBool readOnly, PRBool noCertDB,
525 PRBool noModDB, PRBool forceOpen, PRBool noRootInit,
526 PRBool optimizeSpace, PRBool noSingleThreadedModules,
527 PRBool allowAlreadyInitializedModules,
528 PRBool dontFinalizeModules)
529 {
530 SECStatus rv = SECFailure;
531 #ifndef NSS_DISABLE_LIBPKIX
532 PKIX_UInt32 actualMinorVersion = 0;
533 PKIX_Error *pkixError = NULL;
534 #endif
535 PRBool isReallyInitted;
536 char *configStrings = NULL;
537 char *configName = NULL;
538 PRBool passwordRequired = PR_FALSE;
539
540 /* if we are trying to init with a traditional NSS_Init call, maintain
541 * the traditional idempotent behavior. */
542 if (!initContextPtr && nssIsInitted) {
543 return SECSuccess;
544 }
545
546 /* make sure our lock and condition variable are initialized one and only
547 * one time */
548 if (PR_CallOnce(&nssInitOnce, nss_doLockInit) != PR_SUCCESS) {
549 return SECFailure;
550 }
551
552 /*
553 * if we haven't done basic initialization, single thread the
554 * initializations.
555 */
556 PZ_Lock(nssInitLock);
557 isReallyInitted = NSS_IsInitialized();
558 if (!isReallyInitted) {
559 while (!isReallyInitted && nssIsInInit) {
560 PZ_WaitCondVar(nssInitCondition,PR_INTERVAL_NO_TIMEOUT);
561 isReallyInitted = NSS_IsInitialized();
562 }
563 /* once we've completed basic initialization, we can allow more than
564 * one process initialize NSS at a time. */
565 }
566 nssIsInInit++;
567 PZ_Unlock(nssInitLock);
568
569 /* this tells us whether or not some library has already initialized us.
570 * if so, we don't want to double call some of the basic initialization
571 * functions */
572
573 if (!isReallyInitted) {
574 #ifdef DEBUG
575 CERTCertificate dummyCert;
576 /* New option bits must not change the size of CERTCertificate. */
577 PORT_Assert(sizeof(dummyCert.options) == sizeof(void *));
578 #endif
579
580 if (SECSuccess != cert_InitLocks()) {
581 goto loser;
582 }
583
584 if (SECSuccess != InitCRLCache()) {
585 goto loser;
586 }
587
588 if (SECSuccess != OCSP_InitGlobal()) {
589 goto loser;
590 }
591 }
592
593 if (noSingleThreadedModules || allowAlreadyInitializedModules ||
594 dontFinalizeModules) {
595 pk11_setGlobalOptions(noSingleThreadedModules,
596 allowAlreadyInitializedModules,
597 dontFinalizeModules);
598 }
599
600 if (initContextPtr) {
601 *initContextPtr = PORT_ZNew(NSSInitContext);
602 if (*initContextPtr == NULL) {
603 goto loser;
604 }
605 /*
606 * For traditional NSS_Init, we used the PK11_Configure() call to set
607 * globals. with InitContext, we pass those strings in as parameters.
608 *
609 * This allows old NSS_Init calls to work as before, while at the same
610 * time new calls and old calls will not interfere with each other.
611 */
612 if (initParams) {
613 if (initParams->length < sizeof(NSSInitParameters)) {
614 PORT_SetError(SEC_ERROR_INVALID_ARGS);
615 goto loser;
616 }
617 configStrings = nss_MkConfigString(initParams->manufactureID,
618 initParams->libraryDescription,
619 initParams->cryptoTokenDescription,
620 initParams->dbTokenDescription,
621 initParams->cryptoSlotDescription,
622 initParams->dbSlotDescription,
623 initParams->FIPSSlotDescription,
624 initParams->FIPSTokenDescription,
625 initParams->minPWLen);
626 if (configStrings == NULL) {
627 PORT_SetError(SEC_ERROR_NO_MEMORY);
628 goto loser;
629 }
630 configName = initParams->libraryDescription;
631 passwordRequired = initParams->passwordRequired;
632 }
633 } else {
634 configStrings = pk11_config_strings;
635 configName = pk11_config_name;
636 passwordRequired = pk11_password_required;
637 }
638
639 /* Skip the module init if we are already initted and we are trying
640 * to init with noCertDB and noModDB */
641 if (!(isReallyInitted && noCertDB && noModDB)) {
642 rv = nss_InitModules(configdir, certPrefix, keyPrefix, secmodName,
643 updateDir, updCertPrefix, updKeyPrefix, updateID,
644 updateName, configName, configStrings, passwordRequired,
645 readOnly, noCertDB, noModDB, forceOpen, optimizeSpace,
646 (initContextPtr != NULL));
647
648 if (rv != SECSuccess) {
649 goto loser;
650 }
651 }
652
653
654 /* finish up initialization */
655 if (!isReallyInitted) {
656 if (SECOID_Init() != SECSuccess) {
657 goto loser;
658 }
659 if (STAN_LoadDefaultNSS3TrustDomain() != PR_SUCCESS) {
660 goto loser;
661 }
662 if (nss_InitShutdownList() != SECSuccess) {
663 goto loser;
664 }
665 CERT_SetDefaultCertDB((CERTCertDBHandle *)
666 STAN_GetDefaultTrustDomain());
667 if ((!noModDB) && (!noCertDB) && (!noRootInit)) {
668 if (!SECMOD_HasRootCerts()) {
669 const char *dbpath = configdir;
670 /* handle supported database modifiers */
671 if (strncmp(dbpath, "sql:", 4) == 0) {
672 dbpath += 4;
673 } else if(strncmp(dbpath, "dbm:", 4) == 0) {
674 dbpath += 4;
675 } else if(strncmp(dbpath, "extern:", 7) == 0) {
676 dbpath += 7;
677 } else if(strncmp(dbpath, "rdb:", 4) == 0) {
678 /* if rdb: is specified, the configdir isn't really a
679 * path. Skip it */
680 dbpath = NULL;
681 }
682 if (dbpath) {
683 nss_FindExternalRoot(dbpath, secmodName);
684 }
685 }
686 }
687
688 pk11sdr_Init();
689 cert_CreateSubjectKeyIDHashTable();
690
691 #ifndef NSS_DISABLE_LIBPKIX
692 pkixError = PKIX_Initialize
693 (PKIX_FALSE, PKIX_MAJOR_VERSION, PKIX_MINOR_VERSION,
694 PKIX_MINOR_VERSION, &actualMinorVersion, &plContext);
695
696 if (pkixError != NULL) {
697 goto loser;
698 } else {
699 char *ev = PR_GetEnvSecure("NSS_ENABLE_PKIX_VERIFY");
700 if (ev && ev[0]) {
701 CERT_SetUsePKIXForValidation(PR_TRUE);
702 }
703 }
704 #endif /* NSS_DISABLE_LIBPKIX */
705
706
707 }
708
709 /*
710 * Now mark the appropriate init state. If initContextPtr was passed
711 * in, then return the new context pointer and add it to the
712 * nssInitContextList. Otherwise set the global nss_isInitted flag
713 */
714 PZ_Lock(nssInitLock);
715 if (!initContextPtr) {
716 nssIsInitted = PR_TRUE;
717 } else {
718 (*initContextPtr)->magic = NSS_INIT_MAGIC;
719 (*initContextPtr)->next = nssInitContextList;
720 nssInitContextList = (*initContextPtr);
721 }
722 nssIsInInit--;
723 /* now that we are inited, all waiters can move forward */
724 PZ_NotifyAllCondVar(nssInitCondition);
725 PZ_Unlock(nssInitLock);
726
727 if (initContextPtr && configStrings) {
728 PR_smprintf_free(configStrings);
729 }
730
731 return SECSuccess;
732
733 loser:
734 if (initContextPtr && *initContextPtr) {
735 PORT_Free(*initContextPtr);
736 *initContextPtr = NULL;
737 if (configStrings) {
738 PR_smprintf_free(configStrings);
739 }
740 }
741 PZ_Lock(nssInitLock);
742 nssIsInInit--;
743 /* We failed to init, allow one to move forward */
744 PZ_NotifyCondVar(nssInitCondition);
745 PZ_Unlock(nssInitLock);
746 return SECFailure;
747 }
748
749
750 SECStatus
751 NSS_Init(const char *configdir)
752 {
753 return nss_Init(configdir, "", "", SECMOD_DB, "", "", "", "", "", NULL,
754 NULL, PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE,
755 PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE);
756 }
757
758 SECStatus
759 NSS_InitReadWrite(const char *configdir)
760 {
761 return nss_Init(configdir, "", "", SECMOD_DB, "", "", "", "", "", NULL,
762 NULL, PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE,
763 PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE);
764 }
765
766 /*
767 * OK there are now lots of options here, lets go through them all:
768 *
769 * configdir - base directory where all the cert, key, and module datbases live.
770 * certPrefix - prefix added to the beginning of the cert database example: "
771 * "https-server1-"
772 * keyPrefix - prefix added to the beginning of the key database example: "
773 * "https-server1-"
774 * secmodName - name of the security module database (usually "secmod.db").
775 * flags - change the open options of NSS_Initialize as follows:
776 * NSS_INIT_READONLY - Open the databases read only.
777 * NSS_INIT_NOCERTDB - Don't open the cert DB and key DB's, just
778 * initialize the volatile certdb.
779 * NSS_INIT_NOMODDB - Don't open the security module DB, just
780 * initialize the PKCS #11 module.
781 * NSS_INIT_FORCEOPEN - Continue to force initializations even if the
782 * databases cannot be opened.
783 * NSS_INIT_PK11THREADSAFE - only load PKCS#11 modules that are
784 * thread-safe, ie. that support locking - either OS
785 * locking or NSS-provided locks . If a PKCS#11
786 * module isn't thread-safe, don't serialize its
787 * calls; just don't load it instead. This is necessary
788 * if another piece of code is using the same PKCS#11
789 * modules that NSS is accessing without going through
790 * NSS, for example the Java SunPKCS11 provider.
791 * NSS_INIT_PK11RELOAD - ignore the CKR_CRYPTOKI_ALREADY_INITIALIZED
792 * error when loading PKCS#11 modules. This is necessary
793 * if another piece of code is using the same PKCS#11
794 * modules that NSS is accessing without going through
795 * NSS, for example Java SunPKCS11 provider.
796 * NSS_INIT_NOPK11FINALIZE - never call C_Finalize on any
797 * PKCS#11 module. This may be necessary in order to
798 * ensure continuous operation and proper shutdown
799 * sequence if another piece of code is using the same
800 * PKCS#11 modules that NSS is accessing without going
801 * through NSS, for example Java SunPKCS11 provider.
802 * The following limitation applies when this is set :
803 * SECMOD_WaitForAnyTokenEvent will not use
804 * C_WaitForSlotEvent, in order to prevent the need for
805 * C_Finalize. This call will be emulated instead.
806 * NSS_INIT_RESERVED - Currently has no effect, but may be used in the
807 * future to trigger better cooperation between PKCS#11
808 * modules used by both NSS and the Java SunPKCS11
809 * provider. This should occur after a new flag is defined
810 * for C_Initialize by the PKCS#11 working group.
811 * NSS_INIT_COOPERATE - Sets 4 recommended options for applications that
812 * use both NSS and the Java SunPKCS11 provider.
813 */
814 SECStatus
815 NSS_Initialize(const char *configdir, const char *certPrefix,
816 const char *keyPrefix, const char *secmodName, PRUint32 flags)
817 {
818 return nss_Init(configdir, certPrefix, keyPrefix, secmodName,
819 "", "", "", "", "", NULL, NULL,
820 ((flags & NSS_INIT_READONLY) == NSS_INIT_READONLY),
821 ((flags & NSS_INIT_NOCERTDB) == NSS_INIT_NOCERTDB),
822 ((flags & NSS_INIT_NOMODDB) == NSS_INIT_NOMODDB),
823 ((flags & NSS_INIT_FORCEOPEN) == NSS_INIT_FORCEOPEN),
824 ((flags & NSS_INIT_NOROOTINIT) == NSS_INIT_NOROOTINIT),
825 ((flags & NSS_INIT_OPTIMIZESPACE) == NSS_INIT_OPTIMIZESPACE),
826 ((flags & NSS_INIT_PK11THREADSAFE) == NSS_INIT_PK11THREADSAFE),
827 ((flags & NSS_INIT_PK11RELOAD) == NSS_INIT_PK11RELOAD),
828 ((flags & NSS_INIT_NOPK11FINALIZE) == NSS_INIT_NOPK11FINALIZE));
829 }
830
831 NSSInitContext *
832 NSS_InitContext(const char *configdir, const char *certPrefix,
833 const char *keyPrefix, const char *secmodName,
834 NSSInitParameters *initParams, PRUint32 flags)
835 {
836 SECStatus rv;
837 NSSInitContext *context;
838
839 rv = nss_Init(configdir, certPrefix, keyPrefix, secmodName,
840 "", "", "", "", "", &context, initParams,
841 ((flags & NSS_INIT_READONLY) == NSS_INIT_READONLY),
842 ((flags & NSS_INIT_NOCERTDB) == NSS_INIT_NOCERTDB),
843 ((flags & NSS_INIT_NOMODDB) == NSS_INIT_NOMODDB),
844 ((flags & NSS_INIT_FORCEOPEN) == NSS_INIT_FORCEOPEN), PR_TRUE,
845 ((flags & NSS_INIT_OPTIMIZESPACE) == NSS_INIT_OPTIMIZESPACE),
846 ((flags & NSS_INIT_PK11THREADSAFE) == NSS_INIT_PK11THREADSAFE),
847 ((flags & NSS_INIT_PK11RELOAD) == NSS_INIT_PK11RELOAD),
848 ((flags & NSS_INIT_NOPK11FINALIZE) == NSS_INIT_NOPK11FINALIZE));
849 return (rv == SECSuccess) ? context : NULL;
850 }
851
852 SECStatus
853 NSS_InitWithMerge(const char *configdir, const char *certPrefix,
854 const char *keyPrefix, const char *secmodName,
855 const char *updateDir, const char *updCertPrefix,
856 const char *updKeyPrefix, const char *updateID,
857 const char *updateName, PRUint32 flags)
858 {
859 return nss_Init(configdir, certPrefix, keyPrefix, secmodName,
860 updateDir, updCertPrefix, updKeyPrefix, updateID, updateName,
861 NULL, NULL,
862 ((flags & NSS_INIT_READONLY) == NSS_INIT_READONLY),
863 ((flags & NSS_INIT_NOCERTDB) == NSS_INIT_NOCERTDB),
864 ((flags & NSS_INIT_NOMODDB) == NSS_INIT_NOMODDB),
865 ((flags & NSS_INIT_FORCEOPEN) == NSS_INIT_FORCEOPEN),
866 ((flags & NSS_INIT_NOROOTINIT) == NSS_INIT_NOROOTINIT),
867 ((flags & NSS_INIT_OPTIMIZESPACE) == NSS_INIT_OPTIMIZESPACE),
868 ((flags & NSS_INIT_PK11THREADSAFE) == NSS_INIT_PK11THREADSAFE),
869 ((flags & NSS_INIT_PK11RELOAD) == NSS_INIT_PK11RELOAD),
870 ((flags & NSS_INIT_NOPK11FINALIZE) == NSS_INIT_NOPK11FINALIZE));
871 }
872
873 /*
874 * initialize NSS without a creating cert db's, key db's, or secmod db's.
875 */
876 SECStatus
877 NSS_NoDB_Init(const char * configdir)
878 {
879 return nss_Init("","","","", "", "", "", "", "", NULL, NULL,
880 PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,
881 PR_FALSE,PR_FALSE,PR_FALSE);
882 }
883
884
885 #define NSS_SHUTDOWN_STEP 10
886
887 struct NSSShutdownFuncPair {
888 NSS_ShutdownFunc func;
889 void *appData;
890 };
891
892 static struct NSSShutdownListStr {
893 PZLock *lock;
894 int allocatedFuncs;
895 int peakFuncs;
896 struct NSSShutdownFuncPair *funcs;
897 } nssShutdownList = { 0 };
898
899 /*
900 * find and existing shutdown function
901 */
902 static int
903 nss_GetShutdownEntry(NSS_ShutdownFunc sFunc, void *appData)
904 {
905 int count, i;
906 count = nssShutdownList.peakFuncs;
907
908 for (i=0; i < count; i++) {
909 if ((nssShutdownList.funcs[i].func == sFunc) &&
910 (nssShutdownList.funcs[i].appData == appData)){
911 return i;
912 }
913 }
914 return -1;
915 }
916
917 /*
918 * register a callback to be called when NSS shuts down
919 */
920 SECStatus
921 NSS_RegisterShutdown(NSS_ShutdownFunc sFunc, void *appData)
922 {
923 int i;
924
925 /* make sure our lock and condition variable are initialized one and only
926 * one time */
927 if (PR_CallOnce(&nssInitOnce, nss_doLockInit) != PR_SUCCESS) {
928 return SECFailure;
929 }
930
931 PZ_Lock(nssInitLock);
932 if (!NSS_IsInitialized()) {
933 PZ_Unlock(nssInitLock);
934 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
935 return SECFailure;
936 }
937 PZ_Unlock(nssInitLock);
938 if (sFunc == NULL) {
939 PORT_SetError(SEC_ERROR_INVALID_ARGS);
940 return SECFailure;
941 }
942
943 PORT_Assert(nssShutdownList.lock);
944 PZ_Lock(nssShutdownList.lock);
945
946 /* make sure we don't have a duplicate */
947 i = nss_GetShutdownEntry(sFunc, appData);
948 if (i >= 0) {
949 PZ_Unlock(nssShutdownList.lock);
950 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
951 return SECFailure;
952 }
953 /* find an empty slot */
954 i = nss_GetShutdownEntry(NULL, NULL);
955 if (i >= 0) {
956 nssShutdownList.funcs[i].func = sFunc;
957 nssShutdownList.funcs[i].appData = appData;
958 PZ_Unlock(nssShutdownList.lock);
959 return SECSuccess;
960 }
961 if (nssShutdownList.allocatedFuncs == nssShutdownList.peakFuncs) {
962 struct NSSShutdownFuncPair *funcs =
963 (struct NSSShutdownFuncPair *)PORT_Realloc
964 (nssShutdownList.funcs,
965 (nssShutdownList.allocatedFuncs + NSS_SHUTDOWN_STEP)
966 *sizeof(struct NSSShutdownFuncPair));
967 if (!funcs) {
968 PZ_Unlock(nssShutdownList.lock);
969 return SECFailure;
970 }
971 nssShutdownList.funcs = funcs;
972 nssShutdownList.allocatedFuncs += NSS_SHUTDOWN_STEP;
973 }
974 nssShutdownList.funcs[nssShutdownList.peakFuncs].func = sFunc;
975 nssShutdownList.funcs[nssShutdownList.peakFuncs].appData = appData;
976 nssShutdownList.peakFuncs++;
977 PZ_Unlock(nssShutdownList.lock);
978 return SECSuccess;
979 }
980
981 /*
982 * unregister a callback so it won't get called on shutdown.
983 */
984 SECStatus
985 NSS_UnregisterShutdown(NSS_ShutdownFunc sFunc, void *appData)
986 {
987 int i;
988
989 /* make sure our lock and condition variable are initialized one and only
990 * one time */
991 if (PR_CallOnce(&nssInitOnce, nss_doLockInit) != PR_SUCCESS) {
992 return SECFailure;
993 }
994 PZ_Lock(nssInitLock);
995 if (!NSS_IsInitialized()) {
996 PZ_Unlock(nssInitLock);
997 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
998 return SECFailure;
999 }
1000 PZ_Unlock(nssInitLock);
1001
1002 PORT_Assert(nssShutdownList.lock);
1003 PZ_Lock(nssShutdownList.lock);
1004 i = nss_GetShutdownEntry(sFunc, appData);
1005 if (i >= 0) {
1006 nssShutdownList.funcs[i].func = NULL;
1007 nssShutdownList.funcs[i].appData = NULL;
1008 }
1009 PZ_Unlock(nssShutdownList.lock);
1010
1011 if (i < 0) {
1012 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1013 return SECFailure;
1014 }
1015 return SECSuccess;
1016 }
1017
1018 /*
1019 * bring up and shutdown the shutdown list
1020 */
1021 static SECStatus
1022 nss_InitShutdownList(void)
1023 {
1024 if (nssShutdownList.lock != NULL) {
1025 return SECSuccess;
1026 }
1027 nssShutdownList.lock = PZ_NewLock(nssILockOther);
1028 if (nssShutdownList.lock == NULL) {
1029 return SECFailure;
1030 }
1031 nssShutdownList.funcs = PORT_ZNewArray(struct NSSShutdownFuncPair,
1032 NSS_SHUTDOWN_STEP);
1033 if (nssShutdownList.funcs == NULL) {
1034 PZ_DestroyLock(nssShutdownList.lock);
1035 nssShutdownList.lock = NULL;
1036 return SECFailure;
1037 }
1038 nssShutdownList.allocatedFuncs = NSS_SHUTDOWN_STEP;
1039 nssShutdownList.peakFuncs = 0;
1040
1041 return SECSuccess;
1042 }
1043
1044 static SECStatus
1045 nss_ShutdownShutdownList(void)
1046 {
1047 SECStatus rv = SECSuccess;
1048 int i;
1049
1050 /* call all the registerd functions first */
1051 for (i=0; i < nssShutdownList.peakFuncs; i++) {
1052 struct NSSShutdownFuncPair *funcPair = &nssShutdownList.funcs[i];
1053 if (funcPair->func) {
1054 if ((*funcPair->func)(funcPair->appData,NULL) != SECSuccess) {
1055 rv = SECFailure;
1056 }
1057 }
1058 }
1059
1060 nssShutdownList.peakFuncs = 0;
1061 nssShutdownList.allocatedFuncs = 0;
1062 PORT_Free(nssShutdownList.funcs);
1063 nssShutdownList.funcs = NULL;
1064 if (nssShutdownList.lock) {
1065 PZ_DestroyLock(nssShutdownList.lock);
1066 }
1067 nssShutdownList.lock = NULL;
1068 return rv;
1069 }
1070
1071
1072 extern const NSSError NSS_ERROR_BUSY;
1073
1074 SECStatus
1075 nss_Shutdown(void)
1076 {
1077 SECStatus shutdownRV = SECSuccess;
1078 SECStatus rv;
1079 PRStatus status;
1080 NSSInitContext *temp;
1081
1082 rv = nss_ShutdownShutdownList();
1083 if (rv != SECSuccess) {
1084 shutdownRV = SECFailure;
1085 }
1086 cert_DestroyLocks();
1087 ShutdownCRLCache();
1088 OCSP_ShutdownGlobal();
1089 #ifndef NSS_DISABLE_LIBPKIX
1090 PKIX_Shutdown(plContext);
1091 #endif
1092 SECOID_Shutdown();
1093 status = STAN_Shutdown();
1094 cert_DestroySubjectKeyIDHashTable();
1095 pk11_SetInternalKeySlot(NULL);
1096 rv = SECMOD_Shutdown();
1097 if (rv != SECSuccess) {
1098 shutdownRV = SECFailure;
1099 }
1100 pk11sdr_Shutdown();
1101 nssArena_Shutdown();
1102 if (status == PR_FAILURE) {
1103 if (NSS_GetError() == NSS_ERROR_BUSY) {
1104 PORT_SetError(SEC_ERROR_BUSY);
1105 }
1106 shutdownRV = SECFailure;
1107 }
1108 /*
1109 * A thread's error stack is automatically destroyed when the thread
1110 * terminates, except for the primordial thread, whose error stack is
1111 * destroyed by PR_Cleanup. Since NSS is usually shut down by the
1112 * primordial thread and many NSS-based apps don't call PR_Cleanup,
1113 * we destroy the calling thread's error stack here. This must be
1114 * done after any NSS_GetError call, otherwise NSS_GetError will
1115 * create the error stack again.
1116 */
1117 nss_DestroyErrorStack();
1118 nssIsInitted = PR_FALSE;
1119 temp = nssInitContextList;
1120 nssInitContextList = NULL;
1121 /* free the old list. This is necessary when we are called from
1122 * NSS_Shutdown(). */
1123 while (temp) {
1124 NSSInitContext *next = temp->next;
1125 temp->magic = 0;
1126 PORT_Free(temp);
1127 temp = next;
1128 }
1129 return shutdownRV;
1130 }
1131
1132 SECStatus
1133 NSS_Shutdown(void)
1134 {
1135 SECStatus rv;
1136 /* make sure our lock and condition variable are initialized one and only
1137 * one time */
1138 if (PR_CallOnce(&nssInitOnce, nss_doLockInit) != PR_SUCCESS) {
1139 return SECFailure;
1140 }
1141 PZ_Lock(nssInitLock);
1142
1143 if (!nssIsInitted) {
1144 PZ_Unlock(nssInitLock);
1145 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1146 return SECFailure;
1147 }
1148
1149 /* If one or more threads are in the middle of init, wait for them
1150 * to complete */
1151 while (nssIsInInit) {
1152 PZ_WaitCondVar(nssInitCondition,PR_INTERVAL_NO_TIMEOUT);
1153 }
1154 rv = nss_Shutdown();
1155 PZ_Unlock(nssInitLock);
1156 return rv;
1157 }
1158
1159 /*
1160 * remove the context from a list. return true if found, false if not
1161 */
1162 PRBool
1163 nss_RemoveList(NSSInitContext *context) {
1164 NSSInitContext *this = nssInitContextList;
1165 NSSInitContext **last = &nssInitContextList;
1166
1167 while (this) {
1168 if (this == context) {
1169 *last = this->next;
1170 this->magic = 0;
1171 PORT_Free(this);
1172 return PR_TRUE;
1173 }
1174 last = &this->next;
1175 this=this->next;
1176 }
1177 return PR_FALSE;
1178 }
1179
1180 /*
1181 * This form of shutdown is safe in the case where we may have multiple
1182 * entities using NSS in a single process. Each entity calls shutdown with
1183 * it's own context. The application (which doesn't get a context), calls
1184 * shutdown with NULL. Once all users have 'checked in' NSS will shutdown.
1185 * This is different than NSS_Shutdown, where calling it will shutdown NSS
1186 * irreguardless of who else may have NSS open.
1187 */
1188 SECStatus
1189 NSS_ShutdownContext(NSSInitContext *context)
1190 {
1191 SECStatus rv = SECSuccess;
1192
1193 /* make sure our lock and condition variable are initialized one and only
1194 * one time */
1195 if (PR_CallOnce(&nssInitOnce, nss_doLockInit) != PR_SUCCESS) {
1196 return SECFailure;
1197 }
1198 PZ_Lock(nssInitLock);
1199 /* If one or more threads are in the middle of init, wait for them
1200 * to complete */
1201 while (nssIsInInit) {
1202 PZ_WaitCondVar(nssInitCondition,PR_INTERVAL_NO_TIMEOUT);
1203 }
1204
1205 /* OK, we are the only thread now either initializing or shutting down */
1206
1207 if (!context) {
1208 if (!nssIsInitted) {
1209 PZ_Unlock(nssInitLock);
1210 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1211 return SECFailure;
1212 }
1213 nssIsInitted = 0;
1214 } else if (! nss_RemoveList(context)) {
1215 PZ_Unlock(nssInitLock);
1216 /* context was already freed or wasn't valid */
1217 PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
1218 return SECFailure;
1219 }
1220 if ((nssIsInitted == 0) && (nssInitContextList == NULL)) {
1221 rv = nss_Shutdown();
1222 }
1223
1224 /* NOTE: we don't try to free the nssInitLocks to prevent races against
1225 * the locks. There may be a thread, right now, waiting in NSS_Init for us
1226 * to free the lock below. If we delete the locks, bad things would happen
1227 * to that thread */
1228 PZ_Unlock(nssInitLock);
1229
1230 return rv;
1231 }
1232
1233 PRBool
1234 NSS_IsInitialized(void)
1235 {
1236 return (nssIsInitted) || (nssInitContextList != NULL);
1237 }
1238
1239
1240 extern const char __nss_base_version[];
1241
1242 PRBool
1243 NSS_VersionCheck(const char *importedVersion)
1244 {
1245 /*
1246 * This is the secret handshake algorithm.
1247 *
1248 * This release has a simple version compatibility
1249 * check algorithm. This release is not backward
1250 * compatible with previous major releases. It is
1251 * not compatible with future major, minor, or
1252 * patch releases or builds.
1253 */
1254 int vmajor = 0, vminor = 0, vpatch = 0, vbuild = 0;
1255 const char *ptr = importedVersion;
1256 #define NSS_VERSION_VARIABLE __nss_base_version
1257 #include "verref.h"
1258
1259 while (isdigit(*ptr)) {
1260 vmajor = 10 * vmajor + *ptr - '0';
1261 ptr++;
1262 }
1263 if (*ptr == '.') {
1264 ptr++;
1265 while (isdigit(*ptr)) {
1266 vminor = 10 * vminor + *ptr - '0';
1267 ptr++;
1268 }
1269 if (*ptr == '.') {
1270 ptr++;
1271 while (isdigit(*ptr)) {
1272 vpatch = 10 * vpatch + *ptr - '0';
1273 ptr++;
1274 }
1275 if (*ptr == '.') {
1276 ptr++;
1277 while (isdigit(*ptr)) {
1278 vbuild = 10 * vbuild + *ptr - '0';
1279 ptr++;
1280 }
1281 }
1282 }
1283 }
1284
1285 if (vmajor != NSS_VMAJOR) {
1286 return PR_FALSE;
1287 }
1288 if (vmajor == NSS_VMAJOR && vminor > NSS_VMINOR) {
1289 return PR_FALSE;
1290 }
1291 if (vmajor == NSS_VMAJOR && vminor == NSS_VMINOR && vpatch > NSS_VPATCH) {
1292 return PR_FALSE;
1293 }
1294 if (vmajor == NSS_VMAJOR && vminor == NSS_VMINOR &&
1295 vpatch == NSS_VPATCH && vbuild > NSS_VBUILD) {
1296 return PR_FALSE;
1297 }
1298 return PR_TRUE;
1299 }
1300
1301 const char *
1302 NSS_GetVersion(void)
1303 {
1304 return NSS_VERSION;
1305 }
OLDNEW
« no previous file with comments | « nss/lib/nss/nss.h ('k') | nss/lib/nss/nssoptions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698