~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/softoken/pk11db.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-25 13:04:18 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825130418-ck1i2ms384tzb9m0
Tags: 1.8.1.16+nobinonly-0ubuntu1
* New upstream release (taken from upstream CVS), LP: #254618.
* Fix MFSA 2008-35, MFSA 2008-34, MFSA 2008-33, MFSA 2008-32, MFSA 2008-31,
  MFSA 2008-30, MFSA 2008-29, MFSA 2008-28, MFSA 2008-27, MFSA 2008-25,
  MFSA 2008-24, MFSA 2008-23, MFSA 2008-22, MFSA 2008-21, MFSA 2008-26 also
  known as CVE-2008-2933, CVE-2008-2785, CVE-2008-2811, CVE-2008-2810,
  CVE-2008-2809, CVE-2008-2808, CVE-2008-2807, CVE-2008-2806, CVE-2008-2805,
  CVE-2008-2803, CVE-2008-2802, CVE-2008-2801, CVE-2008-2800, CVE-2008-2798.
* Drop 89_bz419350_attachment_306066 patch, merged upstream.
* Bump Standards-Version to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
4
 * The contents of this file are subject to the Mozilla Public License Version
 
5
 * 1.1 (the "License"); you may not use this file except in compliance with
 
6
 * the License. You may obtain a copy of the License at
 
7
 * http://www.mozilla.org/MPL/
 
8
 *
 
9
 * Software distributed under the License is distributed on an "AS IS" basis,
 
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
11
 * for the specific language governing rights and limitations under the
 
12
 * License.
 
13
 *
 
14
 * The Original Code is the Netscape security libraries.
 
15
 *
 
16
 * The Initial Developer of the Original Code is
 
17
 * Netscape Communications Corporation.
 
18
 * Portions created by the Initial Developer are Copyright (C) 1994-2000
 
19
 * the Initial Developer. All Rights Reserved.
 
20
 *
 
21
 * Contributor(s):
 
22
 *
 
23
 * Alternatively, the contents of this file may be used under the terms of
 
24
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
25
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
26
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
27
 * of those above. If you wish to allow use of your version of this file only
 
28
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
29
 * use your version of this file under the terms of the MPL, indicate your
 
30
 * decision by deleting the provisions above and replace them with the notice
 
31
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
32
 * the provisions above, a recipient may use your version of this file under
 
33
 * the terms of any one of the MPL, the GPL or the LGPL.
 
34
 *
 
35
 * ***** END LICENSE BLOCK ***** */
 
36
/* 
 
37
 *  The following code handles the storage of PKCS 11 modules used by the
 
38
 * NSS. This file is written to abstract away how the modules are
 
39
 * stored so we can deside that later.
 
40
 */
 
41
 
 
42
#include "pk11pars.h"
 
43
#include "pkcs11i.h"
 
44
#include "mcom_db.h"
 
45
#include "cdbhdl.h"
 
46
#include "secerr.h"
 
47
 
 
48
#define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
 
49
 
 
50
static void
 
51
secmod_parseTokenFlags(char *tmp, sftk_token_parameters *parsed) { 
 
52
    parsed->readOnly = secmod_argHasFlag("flags","readOnly",tmp);
 
53
    parsed->noCertDB = secmod_argHasFlag("flags","noCertDB",tmp);
 
54
    parsed->noKeyDB = secmod_argHasFlag("flags","noKeyDB",tmp);
 
55
    parsed->forceOpen = secmod_argHasFlag("flags","forceOpen",tmp);
 
56
    parsed->pwRequired = secmod_argHasFlag("flags","passwordRequired",tmp);
 
57
    parsed->optimizeSpace = secmod_argHasFlag("flags","optimizeSpace",tmp);
 
58
    return;
 
59
}
 
60
 
 
61
static void
 
62
secmod_parseFlags(char *tmp, sftk_parameters *parsed) { 
 
63
    parsed->noModDB = secmod_argHasFlag("flags","noModDB",tmp);
 
64
    parsed->readOnly = secmod_argHasFlag("flags","readOnly",tmp);
 
65
    /* keep legacy interface working */
 
66
    parsed->noCertDB = secmod_argHasFlag("flags","noCertDB",tmp);
 
67
    parsed->forceOpen = secmod_argHasFlag("flags","forceOpen",tmp);
 
68
    parsed->pwRequired = secmod_argHasFlag("flags","passwordRequired",tmp);
 
69
    parsed->optimizeSpace = secmod_argHasFlag("flags","optimizeSpace",tmp);
 
70
    return;
 
71
}
 
72
 
 
73
CK_RV
 
74
secmod_parseTokenParameters(char *param, sftk_token_parameters *parsed) 
 
75
{
 
76
    int next;
 
77
    char *tmp;
 
78
    char *index;
 
79
    index = secmod_argStrip(param);
 
80
 
 
81
    while (*index) {
 
82
        SECMOD_HANDLE_STRING_ARG(index,parsed->configdir,"configDir=",;)
 
83
        SECMOD_HANDLE_STRING_ARG(index,parsed->certPrefix,"certPrefix=",;)
 
84
        SECMOD_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyPrefix=",;)
 
85
        SECMOD_HANDLE_STRING_ARG(index,parsed->tokdes,"tokenDescription=",;)
 
86
        SECMOD_HANDLE_STRING_ARG(index,parsed->slotdes,"slotDescription=",;)
 
87
        SECMOD_HANDLE_STRING_ARG(index,tmp,"minPWLen=", 
 
88
                        if(tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); })
 
89
        SECMOD_HANDLE_STRING_ARG(index,tmp,"flags=", 
 
90
           if(tmp) { secmod_parseTokenFlags(param,parsed); PORT_Free(tmp); })
 
91
        SECMOD_HANDLE_FINAL_ARG(index)
 
92
   }
 
93
   return CKR_OK;
 
94
}
 
95
 
 
96
static void
 
97
secmod_parseTokens(char *tokenParams, sftk_parameters *parsed)
 
98
{
 
99
    char *tokenIndex;
 
100
    sftk_token_parameters *tokens = NULL;
 
101
    int i=0,count = 0,next;
 
102
 
 
103
    if ((tokenParams == NULL) || (*tokenParams == 0))  return;
 
104
 
 
105
    /* first count the number of slots */
 
106
    for (tokenIndex = secmod_argStrip(tokenParams); *tokenIndex;
 
107
         tokenIndex = secmod_argStrip(secmod_argSkipParameter(tokenIndex))) {
 
108
        count++;
 
109
    }
 
110
 
 
111
    /* get the data structures */
 
112
    tokens = (sftk_token_parameters *) 
 
113
                        PORT_ZAlloc(count*sizeof(sftk_token_parameters));
 
114
    if (tokens == NULL) return;
 
115
 
 
116
    for (tokenIndex = secmod_argStrip(tokenParams), i = 0;
 
117
                                        *tokenIndex && i < count ; i++ ) {
 
118
        char *name;
 
119
        name = secmod_argGetName(tokenIndex,&next);
 
120
        tokenIndex += next;
 
121
 
 
122
        tokens[i].slotID = secmod_argDecodeNumber(name);
 
123
        tokens[i].readOnly = PR_FALSE;
 
124
        tokens[i].noCertDB = PR_FALSE;
 
125
        tokens[i].noKeyDB = PR_FALSE;
 
126
        if (!secmod_argIsBlank(*tokenIndex)) {
 
127
            char *args = secmod_argFetchValue(tokenIndex,&next);
 
128
            tokenIndex += next;
 
129
            if (args) {
 
130
                secmod_parseTokenParameters(args,&tokens[i]);
 
131
                PORT_Free(args);
 
132
            }
 
133
        }
 
134
        if (name) PORT_Free(name);
 
135
        tokenIndex = secmod_argStrip(tokenIndex);
 
136
    }
 
137
    parsed->token_count = i;
 
138
    parsed->tokens = tokens;
 
139
    return; 
 
140
}
 
141
 
 
142
CK_RV
 
143
secmod_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS) 
 
144
{
 
145
    int next;
 
146
    char *tmp;
 
147
    char *index;
 
148
    char *certPrefix = NULL, *keyPrefix = NULL;
 
149
    char *tokdes = NULL, *ptokdes = NULL;
 
150
    char *slotdes = NULL, *pslotdes = NULL;
 
151
    char *fslotdes = NULL, *fpslotdes = NULL;
 
152
    char *minPW = NULL;
 
153
    index = secmod_argStrip(param);
 
154
 
 
155
    PORT_Memset(parsed, 0, sizeof(sftk_parameters));
 
156
 
 
157
    while (*index) {
 
158
        SECMOD_HANDLE_STRING_ARG(index,parsed->configdir,"configDir=",;)
 
159
        SECMOD_HANDLE_STRING_ARG(index,parsed->secmodName,"secmod=",;)
 
160
        SECMOD_HANDLE_STRING_ARG(index,parsed->man,"manufacturerID=",;)
 
161
        SECMOD_HANDLE_STRING_ARG(index,parsed->libdes,"libraryDescription=",;)
 
162
        /* constructed values, used so legacy interfaces still work */
 
163
        SECMOD_HANDLE_STRING_ARG(index,certPrefix,"certPrefix=",;)
 
164
        SECMOD_HANDLE_STRING_ARG(index,keyPrefix,"keyPrefix=",;)
 
165
        SECMOD_HANDLE_STRING_ARG(index,tokdes,"cryptoTokenDescription=",;)
 
166
        SECMOD_HANDLE_STRING_ARG(index,ptokdes,"dbTokenDescription=",;)
 
167
        SECMOD_HANDLE_STRING_ARG(index,slotdes,"cryptoSlotDescription=",;)
 
168
        SECMOD_HANDLE_STRING_ARG(index,pslotdes,"dbSlotDescription=",;)
 
169
        SECMOD_HANDLE_STRING_ARG(index,fslotdes,"FIPSSlotDescription=",;)
 
170
        SECMOD_HANDLE_STRING_ARG(index,fpslotdes,"FIPSTokenDescription=",;)
 
171
        SECMOD_HANDLE_STRING_ARG(index,minPW,"minPWLen=",;)
 
172
 
 
173
        SECMOD_HANDLE_STRING_ARG(index,tmp,"flags=", 
 
174
                if(tmp) { secmod_parseFlags(param,parsed); PORT_Free(tmp); })
 
175
        SECMOD_HANDLE_STRING_ARG(index,tmp,"tokens=", 
 
176
                if(tmp) { secmod_parseTokens(tmp,parsed); PORT_Free(tmp); })
 
177
        SECMOD_HANDLE_FINAL_ARG(index)
 
178
    }
 
179
    if (parsed->tokens == NULL) {
 
180
        int  count = isFIPS ? 1 : 2;
 
181
        int  index = count-1;
 
182
        sftk_token_parameters *tokens = NULL;
 
183
 
 
184
        tokens = (sftk_token_parameters *) 
 
185
                        PORT_ZAlloc(count*sizeof(sftk_token_parameters));
 
186
        if (tokens == NULL) {
 
187
            goto loser;
 
188
        }
 
189
        parsed->tokens = tokens;
 
190
        parsed->token_count = count;
 
191
        tokens[index].slotID = isFIPS ? FIPS_SLOT_ID : PRIVATE_KEY_SLOT_ID;
 
192
        tokens[index].certPrefix = certPrefix;
 
193
        tokens[index].keyPrefix = keyPrefix;
 
194
        tokens[index].minPW = minPW ? atoi(minPW) : 0;
 
195
        tokens[index].readOnly = parsed->readOnly;
 
196
        tokens[index].noCertDB = parsed->noCertDB;
 
197
        tokens[index].noKeyDB = parsed->noCertDB;
 
198
        tokens[index].forceOpen = parsed->forceOpen;
 
199
        tokens[index].pwRequired = parsed->pwRequired;
 
200
        tokens[index].optimizeSpace = parsed->optimizeSpace;
 
201
        tokens[0].optimizeSpace = parsed->optimizeSpace;
 
202
        certPrefix = NULL;
 
203
        keyPrefix = NULL;
 
204
        if (isFIPS) {
 
205
            tokens[index].tokdes = fslotdes;
 
206
            tokens[index].slotdes = fpslotdes;
 
207
            fslotdes = NULL;
 
208
            fpslotdes = NULL;
 
209
        } else {
 
210
            tokens[index].tokdes = ptokdes;
 
211
            tokens[index].slotdes = pslotdes;
 
212
            tokens[0].slotID = NETSCAPE_SLOT_ID;
 
213
            tokens[0].tokdes = tokdes;
 
214
            tokens[0].slotdes = slotdes;
 
215
            tokens[0].noCertDB = PR_TRUE;
 
216
            tokens[0].noKeyDB = PR_TRUE;
 
217
            ptokdes = NULL;
 
218
            pslotdes = NULL;
 
219
            tokdes = NULL;
 
220
            slotdes = NULL;
 
221
        }
 
222
    }
 
223
 
 
224
loser:
 
225
    FREE_CLEAR(certPrefix);
 
226
    FREE_CLEAR(keyPrefix);
 
227
    FREE_CLEAR(tokdes);
 
228
    FREE_CLEAR(ptokdes);
 
229
    FREE_CLEAR(slotdes);
 
230
    FREE_CLEAR(pslotdes);
 
231
    FREE_CLEAR(fslotdes);
 
232
    FREE_CLEAR(fpslotdes);
 
233
    FREE_CLEAR(minPW);
 
234
    return CKR_OK;
 
235
}
 
236
 
 
237
void
 
238
secmod_freeParams(sftk_parameters *params)
 
239
{
 
240
    int i;
 
241
 
 
242
    for (i=0; i < params->token_count; i++) {
 
243
        FREE_CLEAR(params->tokens[i].configdir);
 
244
        FREE_CLEAR(params->tokens[i].certPrefix);
 
245
        FREE_CLEAR(params->tokens[i].keyPrefix);
 
246
        FREE_CLEAR(params->tokens[i].tokdes);
 
247
        FREE_CLEAR(params->tokens[i].slotdes);
 
248
    }
 
249
 
 
250
    FREE_CLEAR(params->configdir);
 
251
    FREE_CLEAR(params->secmodName);
 
252
    FREE_CLEAR(params->man);
 
253
    FREE_CLEAR(params->libdes); 
 
254
    FREE_CLEAR(params->tokens);
 
255
}
 
256
 
 
257
 
 
258
char *
 
259
secmod_getSecmodName(char *param, char **appName, char **filename,PRBool *rw)
 
260
{
 
261
    int next;
 
262
    char *configdir = NULL;
 
263
    char *secmodName = NULL;
 
264
    char *value = NULL;
 
265
    char *save_params = param;
 
266
    const char *lconfigdir;
 
267
    param = secmod_argStrip(param);
 
268
        
 
269
 
 
270
    while (*param) {
 
271
        SECMOD_HANDLE_STRING_ARG(param,configdir,"configDir=",;)
 
272
        SECMOD_HANDLE_STRING_ARG(param,secmodName,"secmod=",;)
 
273
        SECMOD_HANDLE_FINAL_ARG(param)
 
274
   }
 
275
 
 
276
   *rw = PR_TRUE;
 
277
   if (secmod_argHasFlag("flags","readOnly",save_params) ||
 
278
        secmod_argHasFlag("flags","noModDB",save_params)) *rw = PR_FALSE;
 
279
 
 
280
   if (!secmodName || *secmodName == '\0') {
 
281
        if (secmodName) PORT_Free(secmodName);
 
282
        secmodName = PORT_Strdup(SECMOD_DB);
 
283
   }
 
284
   *filename = secmodName;
 
285
 
 
286
   lconfigdir = sftk_EvaluateConfigDir(configdir, appName);
 
287
 
 
288
   if (lconfigdir) {
 
289
        value = PR_smprintf("%s" PATH_SEPARATOR "%s",lconfigdir,secmodName);
 
290
   } else {
 
291
        value = PR_smprintf("%s",secmodName);
 
292
   }
 
293
   if (configdir) PORT_Free(configdir);
 
294
   return value;
 
295
}
 
296
 
 
297
/* Construct a database key for a given module */
 
298
static SECStatus secmod_MakeKey(DBT *key, char * module) {
 
299
    int len = 0;
 
300
    char *commonName;
 
301
 
 
302
    commonName = secmod_argGetParamValue("name",module);
 
303
    if (commonName == NULL) {
 
304
        commonName = secmod_argGetParamValue("library",module);
 
305
    }
 
306
    if (commonName == NULL) return SECFailure;
 
307
    len = PORT_Strlen(commonName);
 
308
    key->data = commonName;
 
309
    key->size = len;
 
310
    return SECSuccess;
 
311
}
 
312
 
 
313
/* free out constructed database key */
 
314
static void 
 
315
secmod_FreeKey(DBT *key) 
 
316
{
 
317
    if (key->data) {
 
318
        PORT_Free(key->data);
 
319
    }
 
320
    key->data = NULL;
 
321
    key->size = 0;
 
322
}
 
323
 
 
324
typedef struct secmodDataStr secmodData;
 
325
typedef struct secmodSlotDataStr secmodSlotData;
 
326
struct secmodDataStr {
 
327
    unsigned char major;
 
328
    unsigned char minor;
 
329
    unsigned char nameStart[2];
 
330
    unsigned char slotOffset[2];
 
331
    unsigned char internal;
 
332
    unsigned char fips;
 
333
    unsigned char ssl[8];
 
334
    unsigned char trustOrder[4];
 
335
    unsigned char cipherOrder[4];
 
336
    unsigned char reserved1;
 
337
    unsigned char isModuleDB;
 
338
    unsigned char isModuleDBOnly;
 
339
    unsigned char isCritical;
 
340
    unsigned char reserved[4];
 
341
    unsigned char names[6];     /* enough space for the length fields */
 
342
};
 
343
 
 
344
struct secmodSlotDataStr {
 
345
    unsigned char slotID[4];
 
346
    unsigned char defaultFlags[4];
 
347
    unsigned char timeout[4];
 
348
    unsigned char askpw;
 
349
    unsigned char hasRootCerts;
 
350
    unsigned char reserved[18]; /* this makes it a round 32 bytes */
 
351
};
 
352
 
 
353
#define SECMOD_DB_VERSION_MAJOR 0
 
354
#define SECMOD_DB_VERSION_MINOR 6
 
355
#define SECMOD_DB_EXT1_VERSION_MAJOR 0
 
356
#define SECMOD_DB_EXT1_VERSION_MINOR 6
 
357
#define SECMOD_DB_NOUI_VERSION_MAJOR 0
 
358
#define SECMOD_DB_NOUI_VERSION_MINOR 4
 
359
 
 
360
#define SECMOD_PUTSHORT(dest,src) \
 
361
        (dest)[1] = (unsigned char) ((src)&0xff); \
 
362
        (dest)[0] = (unsigned char) (((src) >> 8) & 0xff);
 
363
#define SECMOD_PUTLONG(dest,src) \
 
364
        (dest)[3] = (unsigned char) ((src)&0xff); \
 
365
        (dest)[2] = (unsigned char) (((src) >> 8) & 0xff); \
 
366
        (dest)[1] = (unsigned char) (((src) >> 16) & 0xff); \
 
367
        (dest)[0] = (unsigned char) (((src) >> 24) & 0xff);
 
368
#define SECMOD_GETSHORT(src) \
 
369
        ((unsigned short) (((src)[0] << 8) | (src)[1]))
 
370
#define SECMOD_GETLONG(src) \
 
371
        ((unsigned long) (( (unsigned long) (src)[0] << 24) | \
 
372
                        ( (unsigned long) (src)[1] << 16)  | \
 
373
                        ( (unsigned long) (src)[2] << 8) | \
 
374
                        (unsigned long) (src)[3]))
 
375
 
 
376
/*
 
377
 * build a data base entry from a module 
 
378
 */
 
379
static SECStatus 
 
380
secmod_EncodeData(DBT *data, char * module) 
 
381
{
 
382
    secmodData *encoded = NULL;
 
383
    secmodSlotData *slot;
 
384
    unsigned char *dataPtr;
 
385
    unsigned short len, len2 = 0, len3 = 0;
 
386
    int count = 0;
 
387
    unsigned short offset;
 
388
    int dataLen, i;
 
389
    unsigned long order;
 
390
    unsigned long  ssl[2];
 
391
    char *commonName = NULL , *dllName = NULL, *param = NULL, *nss = NULL;
 
392
    char *slotParams, *ciphers;
 
393
    PK11PreSlotInfo *slotInfo = NULL;
 
394
    SECStatus rv = SECFailure;
 
395
 
 
396
    rv = secmod_argParseModuleSpec(module,&dllName,&commonName,&param,&nss);
 
397
    if (rv != SECSuccess) return rv;
 
398
    rv = SECFailure;
 
399
 
 
400
    if (commonName == NULL) {
 
401
        /* set error */
 
402
        goto loser;
 
403
    }
 
404
 
 
405
    len = PORT_Strlen(commonName);
 
406
    if (dllName) {
 
407
        len2 = PORT_Strlen(dllName);
 
408
    }
 
409
    if (param) {
 
410
        len3 = PORT_Strlen(param);
 
411
    }
 
412
 
 
413
    slotParams = secmod_argGetParamValue("slotParams",nss); 
 
414
    slotInfo = secmod_argParseSlotInfo(NULL,slotParams,&count);
 
415
    if (slotParams) PORT_Free(slotParams);
 
416
 
 
417
    if (count && slotInfo == NULL) {
 
418
        /* set error */
 
419
        goto loser;
 
420
    }
 
421
 
 
422
    dataLen = sizeof(secmodData) + len + len2 + len3 + sizeof(unsigned short) +
 
423
                                 count*sizeof(secmodSlotData);
 
424
 
 
425
    data->data = (unsigned char *) PORT_ZAlloc(dataLen);
 
426
    encoded = (secmodData *)data->data;
 
427
    dataPtr = (unsigned char *) data->data;
 
428
    data->size = dataLen;
 
429
 
 
430
    if (encoded == NULL) {
 
431
        /* set error */
 
432
        goto loser;
 
433
    }
 
434
 
 
435
    encoded->major = SECMOD_DB_VERSION_MAJOR;
 
436
    encoded->minor = SECMOD_DB_VERSION_MINOR;
 
437
    encoded->internal = (unsigned char) 
 
438
                        (secmod_argHasFlag("flags","internal",nss) ? 1 : 0);
 
439
    encoded->fips = (unsigned char) 
 
440
                        (secmod_argHasFlag("flags","FIPS",nss) ? 1 : 0);
 
441
    encoded->isModuleDB = (unsigned char) 
 
442
                        (secmod_argHasFlag("flags","isModuleDB",nss) ? 1 : 0);
 
443
    encoded->isModuleDBOnly = (unsigned char) 
 
444
                    (secmod_argHasFlag("flags","isModuleDBOnly",nss) ? 1 : 0);
 
445
    encoded->isCritical = (unsigned char) 
 
446
                        (secmod_argHasFlag("flags","critical",nss) ? 1 : 0);
 
447
 
 
448
    order = secmod_argReadLong("trustOrder", nss, SECMOD_DEFAULT_TRUST_ORDER, 
 
449
                               NULL);
 
450
    SECMOD_PUTLONG(encoded->trustOrder,order);
 
451
    order = secmod_argReadLong("cipherOrder", nss, SECMOD_DEFAULT_CIPHER_ORDER, 
 
452
                               NULL);
 
453
    SECMOD_PUTLONG(encoded->cipherOrder,order);
 
454
 
 
455
   
 
456
    ciphers = secmod_argGetParamValue("ciphers",nss); 
 
457
    secmod_argSetNewCipherFlags(&ssl[0], ciphers);
 
458
    SECMOD_PUTLONG(encoded->ssl,ssl[0]);
 
459
    SECMOD_PUTLONG(&encoded->ssl[4],ssl[1]);
 
460
    if (ciphers) PORT_Free(ciphers);
 
461
 
 
462
    offset = (unsigned short) &(((secmodData *)0)->names[0]);
 
463
    SECMOD_PUTSHORT(encoded->nameStart,offset);
 
464
    offset = offset + len + len2 + len3 + 3*sizeof(unsigned short);
 
465
    SECMOD_PUTSHORT(encoded->slotOffset,offset);
 
466
 
 
467
 
 
468
    SECMOD_PUTSHORT(&dataPtr[offset],((unsigned short)count));
 
469
    slot = (secmodSlotData *)(dataPtr+offset+sizeof(unsigned short));
 
470
 
 
471
    offset = 0;
 
472
    SECMOD_PUTSHORT(encoded->names,len);
 
473
    offset += sizeof(unsigned short);
 
474
    PORT_Memcpy(&encoded->names[offset],commonName,len);
 
475
    offset += len;
 
476
 
 
477
 
 
478
    SECMOD_PUTSHORT(&encoded->names[offset],len2);
 
479
    offset += sizeof(unsigned short);
 
480
    if (len2) PORT_Memcpy(&encoded->names[offset],dllName,len2);
 
481
    offset += len2;
 
482
 
 
483
    SECMOD_PUTSHORT(&encoded->names[offset],len3);
 
484
    offset += sizeof(unsigned short);
 
485
    if (len3) PORT_Memcpy(&encoded->names[offset],param,len3);
 
486
    offset += len3;
 
487
 
 
488
    if (count) {
 
489
        for (i=0; i < count; i++) {
 
490
            SECMOD_PUTLONG(slot[i].slotID, slotInfo[i].slotID);
 
491
            SECMOD_PUTLONG(slot[i].defaultFlags,
 
492
                                        slotInfo[i].defaultFlags);
 
493
            SECMOD_PUTLONG(slot[i].timeout,slotInfo[i].timeout);
 
494
            slot[i].askpw = slotInfo[i].askpw;
 
495
            slot[i].hasRootCerts = slotInfo[i].hasRootCerts;
 
496
            PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved));
 
497
        }
 
498
    }
 
499
    rv = SECSuccess;
 
500
 
 
501
loser:
 
502
    if (commonName) PORT_Free(commonName);
 
503
    if (dllName) PORT_Free(dllName);
 
504
    if (param) PORT_Free(param);
 
505
    if (slotInfo) PORT_Free(slotInfo);
 
506
    if (nss) PORT_Free(nss);
 
507
    return rv;
 
508
 
 
509
}
 
510
 
 
511
static void 
 
512
secmod_FreeData(DBT *data)
 
513
{
 
514
    if (data->data) {
 
515
        PORT_Free(data->data);
 
516
    }
 
517
}
 
518
 
 
519
static void
 
520
secmod_FreeSlotStrings(char **slotStrings, int count)
 
521
{
 
522
    int i;
 
523
 
 
524
    for (i=0; i < count; i++) {
 
525
        if (slotStrings[i]) {
 
526
            PR_smprintf_free(slotStrings[i]);
 
527
            slotStrings[i] = NULL;
 
528
        }
 
529
    }
 
530
}
 
531
 
 
532
/*
 
533
 * build a module from the data base entry.
 
534
 */
 
535
static char *
 
536
secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal)
 
537
{
 
538
    secmodData *encoded;
 
539
    secmodSlotData *slots;
 
540
    PLArenaPool *arena;
 
541
    char *commonName            = NULL;
 
542
    char *dllName               = NULL;
 
543
    char *parameters            = NULL;
 
544
    char *nss;
 
545
    char *moduleSpec;
 
546
    char **slotStrings          = NULL;
 
547
    unsigned char *names;
 
548
    unsigned long slotCount;
 
549
    unsigned long ssl0          =0;
 
550
    unsigned long ssl1          =0;
 
551
    unsigned long slotID;
 
552
    unsigned long defaultFlags;
 
553
    unsigned long timeout;
 
554
    unsigned long trustOrder    =SECMOD_DEFAULT_TRUST_ORDER;
 
555
    unsigned long cipherOrder   =SECMOD_DEFAULT_CIPHER_ORDER;
 
556
    unsigned short len;
 
557
    unsigned short namesOffset  = 0;    /* start of the names block */
 
558
    unsigned long namesRunningOffset;   /* offset to name we are 
 
559
                                         * currently processing */
 
560
    unsigned short slotOffset;
 
561
    PRBool isOldVersion         = PR_FALSE;
 
562
    PRBool internal;
 
563
    PRBool isFIPS;
 
564
    PRBool isModuleDB           =PR_FALSE;
 
565
    PRBool isModuleDBOnly       =PR_FALSE;
 
566
    PRBool extended             =PR_FALSE;
 
567
    int i;
 
568
 
 
569
 
 
570
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
 
571
    if (arena == NULL) 
 
572
        return NULL;
 
573
 
 
574
#define CHECK_SIZE(x) \
 
575
    if ((unsigned int) data->size < (unsigned int)(x)) goto db_loser
 
576
 
 
577
    /* -------------------------------------------------------------
 
578
    ** Process the buffer header, which is the secmodData struct. 
 
579
    ** It may be an old or new version.  Check the length for each. 
 
580
    */
 
581
 
 
582
    CHECK_SIZE( offsetof(secmodData, trustOrder[0]) );
 
583
 
 
584
    encoded = (secmodData *)data->data;
 
585
 
 
586
    internal = (encoded->internal != 0) ? PR_TRUE: PR_FALSE;
 
587
    isFIPS   = (encoded->fips     != 0) ? PR_TRUE: PR_FALSE;
 
588
 
 
589
    if (retInternal)
 
590
        *retInternal = internal;
 
591
    if (internal) {
 
592
        parameters = PORT_ArenaStrdup(arena,defParams);
 
593
        if (parameters == NULL) 
 
594
            goto loser;
 
595
    }
 
596
    if (internal && (encoded->major == SECMOD_DB_NOUI_VERSION_MAJOR) &&
 
597
        (encoded->minor <= SECMOD_DB_NOUI_VERSION_MINOR)) {
 
598
        isOldVersion = PR_TRUE;
 
599
    }
 
600
    if ((encoded->major == SECMOD_DB_EXT1_VERSION_MAJOR) &&
 
601
        (encoded->minor >= SECMOD_DB_EXT1_VERSION_MINOR)) {
 
602
        CHECK_SIZE( sizeof(secmodData));
 
603
        trustOrder     = SECMOD_GETLONG(encoded->trustOrder);
 
604
        cipherOrder    = SECMOD_GETLONG(encoded->cipherOrder);
 
605
        isModuleDB     = (encoded->isModuleDB != 0) ? PR_TRUE: PR_FALSE;
 
606
        isModuleDBOnly = (encoded->isModuleDBOnly != 0) ? PR_TRUE: PR_FALSE;
 
607
        extended       = PR_TRUE;
 
608
    } 
 
609
    if (internal && !extended) {
 
610
        trustOrder = 0;
 
611
        cipherOrder = 100;
 
612
    }
 
613
    /* decode SSL cipher enable flags */
 
614
    ssl0 = SECMOD_GETLONG(encoded->ssl);
 
615
    ssl1 = SECMOD_GETLONG(encoded->ssl + 4);
 
616
 
 
617
    slotOffset  = SECMOD_GETSHORT(encoded->slotOffset);
 
618
    namesOffset = SECMOD_GETSHORT(encoded->nameStart);
 
619
 
 
620
 
 
621
    /*--------------------------------------------------------------
 
622
    ** Now process the variable length set of names.                
 
623
    ** The names have this structure:
 
624
    ** struct {
 
625
    **     BYTE  commonNameLen[ 2 ];
 
626
    **     BYTE  commonName   [ commonNameLen ];
 
627
    **     BTTE  libNameLen   [ 2 ];
 
628
    **     BYTE  libName      [ libNameLen ];
 
629
    ** If it is "extended" it also has these members:
 
630
    **     BYTE  initStringLen[ 2 ];
 
631
    **     BYTE  initString   [ initStringLen ];
 
632
    ** }
 
633
    */
 
634
 
 
635
    namesRunningOffset = namesOffset;
 
636
    /* copy the module's common name */
 
637
    CHECK_SIZE( namesRunningOffset + 2);
 
638
    names = (unsigned char *)data->data;
 
639
    len   = SECMOD_GETSHORT(names+namesRunningOffset);
 
640
 
 
641
    CHECK_SIZE( namesRunningOffset + 2 + len);
 
642
    commonName = (char*)PORT_ArenaAlloc(arena,len+1);
 
643
    if (commonName == NULL) 
 
644
        goto loser;
 
645
    PORT_Memcpy(commonName, names + namesRunningOffset + 2, len);
 
646
    commonName[len] = 0;
 
647
    namesRunningOffset += len + 2;
 
648
 
 
649
    /* copy the module's shared library file name. */
 
650
    CHECK_SIZE( namesRunningOffset + 2);
 
651
    len = SECMOD_GETSHORT(names + namesRunningOffset);
 
652
    if (len) {
 
653
        CHECK_SIZE( namesRunningOffset + 2 + len);
 
654
        dllName = (char*)PORT_ArenaAlloc(arena,len + 1);
 
655
        if (dllName == NULL) 
 
656
            goto loser;
 
657
        PORT_Memcpy(dllName, names + namesRunningOffset + 2, len);
 
658
        dllName[len] = 0;
 
659
    }
 
660
    namesRunningOffset += len + 2;
 
661
 
 
662
    /* copy the module's initialization string, if present. */
 
663
    if (!internal && extended) {
 
664
        CHECK_SIZE( namesRunningOffset + 2);
 
665
        len = SECMOD_GETSHORT(names+namesRunningOffset);
 
666
        if (len) {
 
667
            CHECK_SIZE( namesRunningOffset + 2 + len );
 
668
            parameters = (char*)PORT_ArenaAlloc(arena,len + 1);
 
669
            if (parameters == NULL) 
 
670
                goto loser;
 
671
            PORT_Memcpy(parameters,names + namesRunningOffset + 2, len);
 
672
            parameters[len] = 0;
 
673
        }
 
674
        namesRunningOffset += len + 2;
 
675
    }
 
676
 
 
677
    /* 
 
678
     * Consistency check: Make sure the slot and names blocks don't
 
679
     * overlap. These blocks can occur in any order, so this check is made 
 
680
     * in 2 parts. First we check the case where the slot block starts 
 
681
     * after the name block. Later, when we have the slot block length,
 
682
     * we check the case where slot block starts before the name block.
 
683
     * NOTE: in most cases any overlap will likely be detected by invalid 
 
684
     * data read from the blocks, but it's better to find out sooner 
 
685
     * than later.
 
686
     */
 
687
    if (slotOffset >= namesOffset) { /* slot block starts after name block */
 
688
        if (slotOffset < namesRunningOffset) {
 
689
            goto db_loser;
 
690
        }
 
691
    }
 
692
 
 
693
    /* ------------------------------------------------------------------
 
694
    ** Part 3, process the slot table.
 
695
    ** This part has this structure:
 
696
    ** struct {
 
697
    **     BYTE slotCount [ 2 ];
 
698
    **     secmodSlotData [ slotCount ];
 
699
    ** {
 
700
    */
 
701
 
 
702
    CHECK_SIZE( slotOffset + 2 );
 
703
    slotCount = SECMOD_GETSHORT((unsigned char *)data->data + slotOffset);
 
704
 
 
705
    /* 
 
706
     * Consistency check: Part 2. We now have the slot block length, we can 
 
707
     * check the case where the slotblock procedes the name block.
 
708
     */
 
709
    if (slotOffset < namesOffset) { /* slot block starts before name block */
 
710
        if (namesOffset < slotOffset + 2 + slotCount*sizeof(secmodSlotData)) {
 
711
            goto db_loser;
 
712
        }
 
713
    }
 
714
 
 
715
    CHECK_SIZE( (slotOffset + 2 + slotCount * sizeof(secmodSlotData)));
 
716
    slots = (secmodSlotData *) ((unsigned char *)data->data + slotOffset + 2);
 
717
 
 
718
    /*  slotCount; */
 
719
    slotStrings = (char **)PORT_ArenaZAlloc(arena, slotCount * sizeof(char *));
 
720
    if (slotStrings == NULL)
 
721
        goto loser;
 
722
    for (i=0; i < (int) slotCount; i++, slots++) {
 
723
        PRBool hasRootCerts     =PR_FALSE;
 
724
        PRBool hasRootTrust     =PR_FALSE;
 
725
        slotID       = SECMOD_GETLONG(slots->slotID);
 
726
        defaultFlags = SECMOD_GETLONG(slots->defaultFlags);
 
727
        timeout      = SECMOD_GETLONG(slots->timeout);
 
728
        hasRootCerts = slots->hasRootCerts;
 
729
        if (isOldVersion && internal && (slotID != 2)) {
 
730
                unsigned long internalFlags=
 
731
                        secmod_argSlotFlags("slotFlags",SECMOD_SLOT_FLAGS);
 
732
                defaultFlags |= internalFlags;
 
733
        }
 
734
        if (hasRootCerts && !extended) {
 
735
            trustOrder = 100;
 
736
        }
 
737
 
 
738
        slotStrings[i] = secmod_mkSlotString(slotID, defaultFlags, timeout, 
 
739
                                           (unsigned char)slots->askpw, 
 
740
                                           hasRootCerts, hasRootTrust);
 
741
        if (slotStrings[i] == NULL) {
 
742
            secmod_FreeSlotStrings(slotStrings,i);
 
743
            goto loser;
 
744
        }
 
745
    }
 
746
 
 
747
    nss = secmod_mkNSS(slotStrings, slotCount, internal, isFIPS, isModuleDB, 
 
748
                     isModuleDBOnly, internal, trustOrder, cipherOrder, 
 
749
                     ssl0, ssl1);
 
750
    secmod_FreeSlotStrings(slotStrings,slotCount);
 
751
    /* it's permissible (and normal) for nss to be NULL. it simply means
 
752
     * there are no NSS specific parameters in the database */
 
753
    moduleSpec = secmod_mkNewModuleSpec(dllName,commonName,parameters,nss);
 
754
    PR_smprintf_free(nss);
 
755
    PORT_FreeArena(arena,PR_TRUE);
 
756
    return moduleSpec;
 
757
 
 
758
db_loser:
 
759
    PORT_SetError(SEC_ERROR_BAD_DATABASE);
 
760
loser:
 
761
    PORT_FreeArena(arena,PR_TRUE);
 
762
    return NULL;
 
763
}
 
764
 
 
765
 
 
766
 
 
767
static DB *
 
768
secmod_OpenDB(const char *appName, const char *filename, const char *dbName, 
 
769
                                PRBool readOnly, PRBool update)
 
770
{
 
771
    DB *pkcs11db = NULL;
 
772
 
 
773
 
 
774
    if (appName) {
 
775
        char *secname = PORT_Strdup(filename);
 
776
        int len = strlen(secname);
 
777
        int status = RDB_FAIL;
 
778
 
 
779
        if (len >= 3 && PORT_Strcmp(&secname[len-3],".db") == 0) {
 
780
           secname[len-3] = 0;
 
781
        }
 
782
        pkcs11db=
 
783
           rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_RDWR, NULL);
 
784
        if (update && !pkcs11db) {
 
785
            DB *updatedb;
 
786
 
 
787
            pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
 
788
            if (!pkcs11db) {
 
789
                if (status == RDB_RETRY) {
 
790
                    pkcs11db= rdbopen(appName, "", secname, 
 
791
                                        readOnly ? NO_RDONLY:NO_RDWR, NULL);
 
792
                }
 
793
                PORT_Free(secname);
 
794
                return pkcs11db;
 
795
            }
 
796
            updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
 
797
            if (updatedb) {
 
798
                db_Copy(pkcs11db,updatedb);
 
799
                (*updatedb->close)(updatedb);
 
800
            } else {
 
801
                (*pkcs11db->close)(pkcs11db);
 
802
                PORT_Free(secname);
 
803
                return NULL;
 
804
           }
 
805
        }
 
806
        PORT_Free(secname);
 
807
        return pkcs11db;
 
808
    }
 
809
  
 
810
    /* I'm sure we should do more checks here sometime... */
 
811
    pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0);
 
812
 
 
813
    /* didn't exist? create it */
 
814
    if (pkcs11db == NULL) {
 
815
         if (readOnly) 
 
816
             return NULL;
 
817
 
 
818
         pkcs11db = dbopen( dbName, NO_CREATE, 0600, DB_HASH, 0 );
 
819
         if (pkcs11db) 
 
820
             (* pkcs11db->sync)(pkcs11db, 0);
 
821
    }
 
822
    return pkcs11db;
 
823
}
 
824
 
 
825
static void 
 
826
secmod_CloseDB(DB *pkcs11db) 
 
827
{
 
828
     (*pkcs11db->close)(pkcs11db);
 
829
}
 
830
 
 
831
static char *
 
832
secmod_addEscape(const char *string, char quote)
 
833
{
 
834
    char *newString = 0;
 
835
    int escapes = 0, size = 0;
 
836
    const char *src;
 
837
    char *dest;
 
838
 
 
839
    for (src=string; *src ; src++) {
 
840
        if ((*src == quote) || (*src == '\\')) escapes++;
 
841
        size++;
 
842
    }
 
843
 
 
844
    newString = PORT_ZAlloc(escapes+size+1); 
 
845
    if (newString == NULL) {
 
846
        return NULL;
 
847
    }
 
848
 
 
849
    for (src=string, dest=newString; *src; src++,dest++) {
 
850
        if ((*src == '\\') || (*src == quote)) {
 
851
            *dest++ = '\\';
 
852
        }
 
853
        *dest = *src;
 
854
    }
 
855
 
 
856
    return newString;
 
857
}
 
858
 
 
859
#define SECMOD_STEP 10
 
860
#define SFTK_DEFAULT_INTERNAL_INIT "library= name=\"NSS Internal PKCS #11 Module\" parameters=\"%s\" NSS=\"Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={%s askpw=any timeout=30})\""
 
861
/*
 
862
 * Read all the existing modules in
 
863
 */
 
864
char **
 
865
secmod_ReadPermDB(const char *appName, const char *filename,
 
866
                                const char *dbname, char *params, PRBool rw)
 
867
{
 
868
    DBT key,data;
 
869
    int ret;
 
870
    DB *pkcs11db = NULL;
 
871
    char **moduleList = NULL, **newModuleList = NULL;
 
872
    int moduleCount = 1;
 
873
    int useCount = SECMOD_STEP;
 
874
 
 
875
    moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **));
 
876
    if (moduleList == NULL) return NULL;
 
877
 
 
878
    pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_TRUE,rw);
 
879
    if (pkcs11db == NULL) goto done;
 
880
 
 
881
    /* read and parse the file or data base */
 
882
    ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
 
883
    if (ret)  goto done;
 
884
 
 
885
 
 
886
    do {
 
887
        char *moduleString;
 
888
        PRBool internal = PR_FALSE;
 
889
        if ((moduleCount+1) >= useCount) {
 
890
            useCount += SECMOD_STEP;
 
891
            newModuleList =
 
892
                (char **)PORT_Realloc(moduleList,useCount*sizeof(char *));
 
893
            if (newModuleList == NULL) goto done;
 
894
            moduleList = newModuleList;
 
895
            PORT_Memset(&moduleList[moduleCount+1],0,
 
896
                                                sizeof(char *)*SECMOD_STEP);
 
897
        }
 
898
        moduleString = secmod_DecodeData(params,&data,&internal);
 
899
        if (internal) {
 
900
            moduleList[0] = moduleString;
 
901
        } else {
 
902
            moduleList[moduleCount] = moduleString;
 
903
            moduleCount++;
 
904
        }
 
905
    } while ( (*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
 
906
 
 
907
done:
 
908
    if (!moduleList[0]) {
 
909
        char * newparams = secmod_addEscape(params,'"');
 
910
        if (newparams) {
 
911
            moduleList[0] = PR_smprintf(SFTK_DEFAULT_INTERNAL_INIT,newparams,
 
912
                                                SECMOD_SLOT_FLAGS);
 
913
            PORT_Free(newparams);
 
914
        }
 
915
    }
 
916
    /* deal with trust cert db here */
 
917
 
 
918
    if (pkcs11db) {
 
919
        secmod_CloseDB(pkcs11db);
 
920
    } else if (moduleList[0] && rw) {
 
921
        secmod_AddPermDB(appName,filename,dbname,moduleList[0], rw) ;
 
922
    }
 
923
    if (!moduleList[0]) {
 
924
        PORT_Free(moduleList);
 
925
        moduleList = NULL;
 
926
    }
 
927
    return moduleList;
 
928
}
 
929
 
 
930
SECStatus
 
931
secmod_ReleasePermDBData(const char *appName, const char *filename, 
 
932
                        const char *dbname, char **moduleSpecList, PRBool rw)
 
933
{
 
934
    if (moduleSpecList) {
 
935
        char **index;
 
936
        for(index = moduleSpecList; *index; index++) {
 
937
            PR_smprintf_free(*index);
 
938
        }
 
939
        PORT_Free(moduleSpecList);
 
940
    }
 
941
    return SECSuccess;
 
942
}
 
943
 
 
944
/*
 
945
 * Delete a module from the Data Base
 
946
 */
 
947
SECStatus
 
948
secmod_DeletePermDB(const char *appName, const char *filename, 
 
949
                        const char *dbname, char *args, PRBool rw)
 
950
{
 
951
    DBT key;
 
952
    SECStatus rv = SECFailure;
 
953
    DB *pkcs11db = NULL;
 
954
    int ret;
 
955
 
 
956
    if (!rw) return SECFailure;
 
957
 
 
958
    /* make sure we have a db handle */
 
959
    pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
 
960
    if (pkcs11db == NULL) {
 
961
        return SECFailure;
 
962
    }
 
963
 
 
964
    rv = secmod_MakeKey(&key,args);
 
965
    if (rv != SECSuccess) goto done;
 
966
    rv = SECFailure;
 
967
    ret = (*pkcs11db->del)(pkcs11db, &key, 0);
 
968
    secmod_FreeKey(&key);
 
969
    if (ret != 0) goto done;
 
970
 
 
971
 
 
972
    ret = (*pkcs11db->sync)(pkcs11db, 0);
 
973
    if (ret == 0) rv = SECSuccess;
 
974
 
 
975
done:
 
976
    secmod_CloseDB(pkcs11db);
 
977
    return rv;
 
978
}
 
979
 
 
980
/*
 
981
 * Add a module to the Data base 
 
982
 */
 
983
SECStatus
 
984
secmod_AddPermDB(const char *appName, const char *filename, 
 
985
                        const char *dbname, char *module, PRBool rw)
 
986
{
 
987
    DBT key,data;
 
988
    SECStatus rv = SECFailure;
 
989
    DB *pkcs11db = NULL;
 
990
    int ret;
 
991
 
 
992
 
 
993
    if (!rw) return SECFailure;
 
994
 
 
995
    /* make sure we have a db handle */
 
996
    pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
 
997
    if (pkcs11db == NULL) {
 
998
        return SECFailure;
 
999
    }
 
1000
 
 
1001
    rv = secmod_MakeKey(&key,module);
 
1002
    if (rv != SECSuccess) goto done;
 
1003
    rv = secmod_EncodeData(&data,module);
 
1004
    if (rv != SECSuccess) {
 
1005
        secmod_FreeKey(&key);
 
1006
        goto done;
 
1007
    }
 
1008
    rv = SECFailure;
 
1009
    ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
 
1010
    secmod_FreeKey(&key);
 
1011
    secmod_FreeData(&data);
 
1012
    if (ret != 0) goto done;
 
1013
 
 
1014
    ret = (*pkcs11db->sync)(pkcs11db, 0);
 
1015
    if (ret == 0) rv = SECSuccess;
 
1016
 
 
1017
done:
 
1018
    secmod_CloseDB(pkcs11db);
 
1019
    return rv;
 
1020
}