~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * NSS utility functions
 
3
 *
 
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/
 
8
 * 
 
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.
 
13
 * 
 
14
 * The Original Code is the Netscape security libraries.
 
15
 * 
 
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
 
19
 * Rights Reserved.
 
20
 * 
 
21
 * Contributor(s):
 
22
 * 
 
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
 
33
 * GPL.
 
34
 *
 
35
 # $Id: nssinit.c,v 1.64.22.1 2004/10/15 21:13:54 wchang0222%aol.com Exp $
 
36
 */
 
37
 
 
38
#include <ctype.h>
 
39
#include "seccomon.h"
 
40
#include "prinit.h"
 
41
#include "prprf.h"
 
42
#include "prmem.h"
 
43
#include "cert.h"
 
44
#include "key.h"
 
45
#include "ssl.h"
 
46
#include "sslproto.h"
 
47
#include "secmod.h"
 
48
#include "secoid.h"
 
49
#include "nss.h"
 
50
#include "pk11func.h"
 
51
#include "secerr.h"
 
52
#include "nssbase.h"
 
53
 
 
54
#include "pki3hack.h"
 
55
#include "certi.h"
 
56
#include "secmodi.h"
 
57
 
 
58
/*
 
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.
 
64
 */
 
65
#ifdef WIN32_NSS3_DLL_COMPAT
 
66
#include <io.h>
 
67
 
 
68
/* exported as 'mktemp' */
 
69
char *
 
70
nss_mktemp(char *path)
 
71
{
 
72
    return _mktemp(path);
 
73
}
 
74
#endif
 
75
 
 
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"
 
80
 
 
81
static char *
 
82
nss_makeFlags(PRBool readOnly, PRBool noCertDB, 
 
83
                                PRBool noModDB, PRBool forceOpen, 
 
84
                                PRBool passwordRequired, PRBool optimizeSpace) 
 
85
{
 
86
    char *flags = (char *)PORT_Alloc(NSS_MAX_FLAG_SIZE);
 
87
    PRBool first = PR_TRUE;
 
88
 
 
89
    PORT_Memset(flags,0,NSS_MAX_FLAG_SIZE);
 
90
    if (readOnly) {
 
91
        PORT_Strcat(flags,"readOnly");
 
92
        first = PR_FALSE;
 
93
    }
 
94
    if (noCertDB) {
 
95
        if (!first) PORT_Strcat(flags,",");
 
96
        PORT_Strcat(flags,"noCertDB");
 
97
        first = PR_FALSE;
 
98
    }
 
99
    if (noModDB) {
 
100
        if (!first) PORT_Strcat(flags,",");
 
101
        PORT_Strcat(flags,"noModDB");
 
102
        first = PR_FALSE;
 
103
    }
 
104
    if (forceOpen) {
 
105
        if (!first) PORT_Strcat(flags,",");
 
106
        PORT_Strcat(flags,"forceOpen");
 
107
        first = PR_FALSE;
 
108
    }
 
109
    if (passwordRequired) {
 
110
        if (!first) PORT_Strcat(flags,",");
 
111
        PORT_Strcat(flags,"passwordRequired");
 
112
        first = PR_FALSE;
 
113
    }
 
114
    if (optimizeSpace) {
 
115
        if (!first) PORT_Strcat(flags,",");
 
116
        PORT_Strcat(flags,"optimizeSpace");
 
117
        first = PR_FALSE;
 
118
    }
 
119
    return flags;
 
120
}
 
121
 
 
122
/*
 
123
 * statics to remember the PKCS11_ConfigurePKCS11()
 
124
 * info.
 
125
 */
 
126
static char * pk11_config_strings = NULL;
 
127
static char * pk11_config_name = NULL;
 
128
static PRBool pk11_password_required = PR_FALSE;
 
129
 
 
130
/*
 
131
 * this is a legacy configuration function which used to be part of
 
132
 * the PKCS #11 internal token.
 
133
 */
 
134
void
 
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)
 
138
{
 
139
   char *strings = NULL;
 
140
   char *newStrings;
 
141
 
 
142
   /* make sure the internationalization was done correctly... */
 
143
   strings = PR_smprintf("");
 
144
   if (strings == NULL) return;
 
145
 
 
146
    if (man) {
 
147
        newStrings = PR_smprintf("%s manufacturerID='%s'",strings,man);
 
148
        PR_smprintf_free(strings);
 
149
        strings = newStrings;
 
150
    }
 
151
   if (strings == NULL) return;
 
152
 
 
153
    if (libdes) {
 
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);
 
159
        }
 
160
        pk11_config_name = PORT_Strdup(libdes);
 
161
    }
 
162
   if (strings == NULL) return;
 
163
 
 
164
    if (tokdes) {
 
165
        newStrings = PR_smprintf("%s cryptoTokenDescription='%s'",strings,
 
166
                                                                tokdes);
 
167
        PR_smprintf_free(strings);
 
168
        strings = newStrings;
 
169
    }
 
170
   if (strings == NULL) return;
 
171
 
 
172
    if (ptokdes) {
 
173
        newStrings = PR_smprintf("%s dbTokenDescription='%s'",strings,ptokdes);
 
174
        PR_smprintf_free(strings);
 
175
        strings = newStrings;
 
176
    }
 
177
   if (strings == NULL) return;
 
178
 
 
179
    if (slotdes) {
 
180
        newStrings = PR_smprintf("%s cryptoSlotDescription='%s'",strings,
 
181
                                                                slotdes);
 
182
        PR_smprintf_free(strings);
 
183
        strings = newStrings;
 
184
    }
 
185
   if (strings == NULL) return;
 
186
 
 
187
    if (pslotdes) {
 
188
        newStrings = PR_smprintf("%s dbSlotDescription='%s'",strings,pslotdes);
 
189
        PR_smprintf_free(strings);
 
190
        strings = newStrings;
 
191
    }
 
192
   if (strings == NULL) return;
 
193
 
 
194
    if (fslotdes) {
 
195
        newStrings = PR_smprintf("%s FIPSSlotDescription='%s'",
 
196
                                                        strings,fslotdes);
 
197
        PR_smprintf_free(strings);
 
198
        strings = newStrings;
 
199
    }
 
200
   if (strings == NULL) return;
 
201
 
 
202
    if (fpslotdes) {
 
203
        newStrings = PR_smprintf("%s FIPSTokenDescription='%s'",
 
204
                                                        strings,fpslotdes);
 
205
        PR_smprintf_free(strings);
 
206
        strings = newStrings;
 
207
    }
 
208
   if (strings == NULL) return;
 
209
 
 
210
    newStrings = PR_smprintf("%s minPS=%d", strings, minPwd);
 
211
    PR_smprintf_free(strings);
 
212
    strings = newStrings;
 
213
   if (strings == NULL) return;
 
214
 
 
215
    if (pk11_config_strings != NULL) {
 
216
        PR_smprintf_free(pk11_config_strings);
 
217
    }
 
218
    pk11_config_strings = strings;
 
219
    pk11_password_required = pwRequired;
 
220
 
 
221
    return;
 
222
}
 
223
 
 
224
static char *
 
225
nss_addEscape(const char *string, char quote)
 
226
{
 
227
    char *newString = 0;
 
228
    int escapes = 0, size = 0;
 
229
    const char *src;
 
230
    char *dest;
 
231
 
 
232
    for (src=string; *src ; src++) {
 
233
        if ((*src == quote) || (*src == '\\')) escapes++;
 
234
        size++;
 
235
    }
 
236
 
 
237
    newString = PORT_ZAlloc(escapes+size+1); 
 
238
    if (newString == NULL) {
 
239
        return NULL;
 
240
    }
 
241
 
 
242
    for (src=string, dest=newString; *src; src++,dest++) {
 
243
        if ((*src == '\\') || (*src == quote)) {
 
244
            *dest++ = '\\';
 
245
        }
 
246
        *dest = *src;
 
247
    }
 
248
 
 
249
    return newString;
 
250
}
 
251
 
 
252
static char *
 
253
nss_doubleEscape(const char *string)
 
254
{
 
255
    char *round1 = NULL;
 
256
    char *retValue = NULL;
 
257
    if (string == NULL) {
 
258
        goto done;
 
259
    }
 
260
    round1 = nss_addEscape(string,'\'');
 
261
    if (round1) {
 
262
        retValue = nss_addEscape(round1,'"');
 
263
        PORT_Free(round1);
 
264
    }
 
265
 
 
266
done:
 
267
    if (retValue == NULL) {
 
268
        retValue = PORT_Strdup("");
 
269
    }
 
270
    return retValue;
 
271
}
 
272
 
 
273
 
 
274
#ifndef XP_MAC
 
275
/*
 
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.
 
280
 */
 
281
 
 
282
static const char *dllname =
 
283
#if defined(XP_WIN32) || defined(XP_OS2)
 
284
        "nssckbi.dll";
 
285
#elif defined(HPUX)
 
286
        "libnssckbi.sl";
 
287
#elif defined(DARWIN)
 
288
        "libnssckbi.dylib";
 
289
#elif defined(XP_UNIX) || defined(XP_BEOS)
 
290
        "libnssckbi.so";
 
291
#elif defined(XP_MAC)
 
292
        "NSS Builtin Root Certs";
 
293
#else
 
294
        #error "Uh! Oh! I don't know about this platform."
 
295
#endif
 
296
 
 
297
/* Should we have platform ifdefs here??? */
 
298
#define FILE_SEP '/'
 
299
 
 
300
static void nss_FindExternalRootPaths(const char *dbpath, const char* secmodprefix,
 
301
                              char** retoldpath, char** retnewpath)
 
302
{
 
303
    char *path, *oldpath = NULL, *lastsep;
 
304
    int len, path_len, secmod_len, dll_len;
 
305
 
 
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 */
 
310
 
 
311
    path = PORT_Alloc(len);
 
312
    if (path == NULL) return;
 
313
 
 
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;
 
318
    }
 
319
    PORT_Strcpy(&path[path_len],dllname);
 
320
    if (secmodprefix) {
 
321
        lastsep = PORT_Strrchr(secmodprefix, FILE_SEP);
 
322
        if (lastsep) {
 
323
            int secmoddir_len = lastsep-secmodprefix+1; /* FILE_SEP */
 
324
            oldpath = PORT_Alloc(len);
 
325
            if (oldpath == NULL) {
 
326
                PORT_Free(path);
 
327
                return;
 
328
            }
 
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);
 
332
        }
 
333
    }
 
334
    *retoldpath = oldpath;
 
335
    *retnewpath = path;
 
336
    return;
 
337
}
 
338
 
 
339
static void nss_FreeExternalRootPaths(char* oldpath, char* path)
 
340
{
 
341
    if (path) {
 
342
        PORT_Free(path);
 
343
    }
 
344
    if (oldpath) {
 
345
        PORT_Free(oldpath);
 
346
    }
 
347
}
 
348
 
 
349
static void
 
350
nss_FindExternalRoot(const char *dbpath, const char* secmodprefix)
 
351
{
 
352
        char *path = NULL;
 
353
        char *oldpath = NULL;
 
354
        PRBool hasrootcerts = PR_FALSE;
 
355
 
 
356
        /*
 
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.
 
360
         */
 
361
        nss_FindExternalRootPaths(dbpath, secmodprefix, &oldpath, &path);
 
362
        if (oldpath) {
 
363
            (void) SECMOD_AddNewModule("Root Certs",oldpath, 0, 0);
 
364
            hasrootcerts = SECMOD_HasRootCerts();
 
365
        }
 
366
        if (path && !hasrootcerts) {
 
367
            (void) SECMOD_AddNewModule("Root Certs",path, 0, 0);
 
368
        }
 
369
        nss_FreeExternalRootPaths(oldpath, path);
 
370
        return;
 
371
}
 
372
#endif
 
373
 
 
374
/*
 
375
 * OK there are now lots of options here, lets go through them all:
 
376
 *
 
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: "
 
379
 *                      "https-server1-"
 
380
 * keyPrefix - prefix added to the beginning of the key database example: "
 
381
 *                      "https-server1-"
 
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 
 
385
 *                      Volatile certdb.
 
386
 * nomoddb - Don't open the security module DB, just initialize the 
 
387
 *                      PKCS #11 module.
 
388
 * forceOpen - Continue to force initializations even if the databases cannot
 
389
 *                      be opened.
 
390
 */
 
391
 
 
392
static PRBool nss_IsInitted = PR_FALSE;
 
393
 
 
394
extern SECStatus secoid_Init(void);
 
395
 
 
396
static SECStatus
 
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)
 
401
{
 
402
    char *moduleSpec = NULL;
 
403
    char *flags = NULL;
 
404
    SECStatus rv = SECFailure;
 
405
    char *lconfigdir = NULL;
 
406
    char *lcertPrefix = NULL;
 
407
    char *lkeyPrefix = NULL;
 
408
    char *lsecmodName = NULL;
 
409
 
 
410
    if (nss_IsInitted) {
 
411
        return SECSuccess;
 
412
    }
 
413
 
 
414
    if (SECSuccess != InitCRLCache()) {
 
415
        return SECFailure;
 
416
    }
 
417
 
 
418
    flags = nss_makeFlags(readOnly,noCertDB,noModDB,forceOpen,
 
419
                                        pk11_password_required, optimizeSpace);
 
420
    if (flags == NULL) return rv;
 
421
 
 
422
    /*
 
423
     * configdir is double nested, and Windows uses the same character
 
424
     * for file seps as we use for escapes! (sigh).
 
425
     */
 
426
    lconfigdir = nss_doubleEscape(configdir);
 
427
    if (lconfigdir == NULL) {
 
428
        goto loser;
 
429
    }
 
430
    lcertPrefix = nss_doubleEscape(certPrefix);
 
431
    if (lcertPrefix == NULL) {
 
432
        goto loser;
 
433
    }
 
434
    lkeyPrefix = nss_doubleEscape(keyPrefix);
 
435
    if (lkeyPrefix == NULL) {
 
436
        goto loser;
 
437
    }
 
438
    lsecmodName = nss_doubleEscape(secmodName);
 
439
    if (lsecmodName == NULL) {
 
440
        goto loser;
 
441
    }
 
442
 
 
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 : "");
 
447
 
 
448
loser:
 
449
    PORT_Free(flags);
 
450
    if (lconfigdir) PORT_Free(lconfigdir);
 
451
    if (lcertPrefix) PORT_Free(lcertPrefix);
 
452
    if (lkeyPrefix) PORT_Free(lkeyPrefix);
 
453
    if (lsecmodName) PORT_Free(lsecmodName);
 
454
 
 
455
    if (moduleSpec) {
 
456
        SECMODModule *module = SECMOD_LoadModule(moduleSpec,NULL,PR_TRUE);
 
457
        PR_smprintf_free(moduleSpec);
 
458
        if (module) {
 
459
            if (module->loaded) rv=SECSuccess;
 
460
            SECMOD_DestroyModule(module);
 
461
        }
 
462
    }
 
463
 
 
464
    if (rv == SECSuccess) {
 
465
        if (secoid_Init() != SECSuccess) {
 
466
            return SECFailure;
 
467
        }
 
468
        if (STAN_LoadDefaultNSS3TrustDomain() != PR_SUCCESS) {
 
469
            return SECFailure;
 
470
        }
 
471
        CERT_SetDefaultCertDB((CERTCertDBHandle *)
 
472
                                STAN_GetDefaultTrustDomain());
 
473
#ifndef XP_MAC
 
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);
 
478
            }
 
479
        }
 
480
#endif
 
481
        pk11sdr_Init();
 
482
        cert_CreateSubjectKeyIDHashTable();
 
483
        nss_IsInitted = PR_TRUE;
 
484
    }
 
485
    return rv;
 
486
}
 
487
 
 
488
 
 
489
SECStatus
 
490
NSS_Init(const char *configdir)
 
491
{
 
492
    return nss_Init(configdir, "", "", SECMOD_DB, PR_TRUE, 
 
493
                PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_TRUE);
 
494
}
 
495
 
 
496
SECStatus
 
497
NSS_InitReadWrite(const char *configdir)
 
498
{
 
499
    return nss_Init(configdir, "", "", SECMOD_DB, PR_FALSE, 
 
500
                PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_TRUE);
 
501
}
 
502
 
 
503
/*
 
504
 * OK there are now lots of options here, lets go through them all:
 
505
 *
 
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: "
 
508
 *                      "https-server1-"
 
509
 * keyPrefix - prefix added to the beginning of the key database example: "
 
510
 *                      "https-server1-"
 
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.
 
520
 */
 
521
SECStatus
 
522
NSS_Initialize(const char *configdir, const char *certPrefix, 
 
523
        const char *keyPrefix, const char *secmodName, PRUint32 flags)
 
524
{
 
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));
 
532
}
 
533
 
 
534
/*
 
535
 * initialize NSS without a creating cert db's, key db's, or secmod db's.
 
536
 */
 
537
SECStatus
 
538
NSS_NoDB_Init(const char * configdir)
 
539
{
 
540
      return nss_Init("","","","",
 
541
                        PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE);
 
542
}
 
543
 
 
544
extern const NSSError NSS_ERROR_BUSY;
 
545
 
 
546
SECStatus
 
547
NSS_Shutdown(void)
 
548
{
 
549
    SECStatus rv;
 
550
    PRStatus status;
 
551
 
 
552
    ShutdownCRLCache();
 
553
    SECOID_Shutdown();
 
554
    status = STAN_Shutdown();
 
555
    cert_DestroySubjectKeyIDHashTable();
 
556
    rv = SECMOD_Shutdown();
 
557
    pk11sdr_Shutdown();
 
558
    if (status == PR_FAILURE) {
 
559
        if (NSS_GetError() == NSS_ERROR_BUSY) {
 
560
            PORT_SetError(SEC_ERROR_BUSY);
 
561
        }
 
562
        rv = SECFailure;
 
563
    }
 
564
    nss_IsInitted = PR_FALSE;
 
565
    return rv;
 
566
}
 
567
 
 
568
 
 
569
 
 
570
extern const char __nss_base_rcsid[];
 
571
PRBool
 
572
NSS_IsInitialized(void)
 
573
{
 
574
    return nss_IsInitted;
 
575
}
 
576
extern const char __nss_base_sccsid[];
 
577
 
 
578
PRBool
 
579
NSS_VersionCheck(const char *importedVersion)
 
580
{
 
581
    /*
 
582
     * This is the secret handshake algorithm.
 
583
     *
 
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
 
588
     * patch releases.
 
589
     */
 
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 */
 
593
 
 
594
    c = __nss_base_rcsid[0] + __nss_base_sccsid[0]; 
 
595
 
 
596
    while (isdigit(*ptr)) {
 
597
        vmajor = 10 * vmajor + *ptr - '0';
 
598
        ptr++;
 
599
    }
 
600
    if (*ptr == '.') {
 
601
        ptr++;
 
602
        while (isdigit(*ptr)) {
 
603
            vminor = 10 * vminor + *ptr - '0';
 
604
            ptr++;
 
605
        }
 
606
        if (*ptr == '.') {
 
607
            ptr++;
 
608
            while (isdigit(*ptr)) {
 
609
                vpatch = 10 * vpatch + *ptr - '0';
 
610
                ptr++;
 
611
            }
 
612
        }
 
613
    }
 
614
 
 
615
    if (vmajor != NSS_VMAJOR) {
 
616
        return PR_FALSE;
 
617
    }
 
618
    if (vmajor == NSS_VMAJOR && vminor > NSS_VMINOR) {
 
619
        return PR_FALSE;
 
620
    }
 
621
    if (vmajor == NSS_VMAJOR && vminor == NSS_VMINOR && vpatch > NSS_VPATCH) {
 
622
        return PR_FALSE;
 
623
    }
 
624
    /* Check dependent libraries */
 
625
    if (PR_VersionCheck(PR_VERSION) == PR_FALSE) {
 
626
        return PR_FALSE;
 
627
    }
 
628
    return PR_TRUE;
 
629
}
 
630
 
 
631