1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14
* The Original Code is the Netscape security libraries.
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.
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.
35
* ***** END LICENSE BLOCK ***** */
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.
48
#define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
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);
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);
74
secmod_parseTokenParameters(char *param, sftk_token_parameters *parsed)
79
index = secmod_argStrip(param);
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)
97
secmod_parseTokens(char *tokenParams, sftk_parameters *parsed)
100
sftk_token_parameters *tokens = NULL;
101
int i=0,count = 0,next;
103
if ((tokenParams == NULL) || (*tokenParams == 0)) return;
105
/* first count the number of slots */
106
for (tokenIndex = secmod_argStrip(tokenParams); *tokenIndex;
107
tokenIndex = secmod_argStrip(secmod_argSkipParameter(tokenIndex))) {
111
/* get the data structures */
112
tokens = (sftk_token_parameters *)
113
PORT_ZAlloc(count*sizeof(sftk_token_parameters));
114
if (tokens == NULL) return;
116
for (tokenIndex = secmod_argStrip(tokenParams), i = 0;
117
*tokenIndex && i < count ; i++ ) {
119
name = secmod_argGetName(tokenIndex,&next);
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);
130
secmod_parseTokenParameters(args,&tokens[i]);
134
if (name) PORT_Free(name);
135
tokenIndex = secmod_argStrip(tokenIndex);
137
parsed->token_count = i;
138
parsed->tokens = tokens;
143
secmod_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS)
148
char *certPrefix = NULL, *keyPrefix = NULL;
149
char *tokdes = NULL, *ptokdes = NULL;
150
char *slotdes = NULL, *pslotdes = NULL;
151
char *fslotdes = NULL, *fpslotdes = NULL;
153
index = secmod_argStrip(param);
155
PORT_Memset(parsed, 0, sizeof(sftk_parameters));
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=",;)
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)
179
if (parsed->tokens == NULL) {
180
int count = isFIPS ? 1 : 2;
182
sftk_token_parameters *tokens = NULL;
184
tokens = (sftk_token_parameters *)
185
PORT_ZAlloc(count*sizeof(sftk_token_parameters));
186
if (tokens == NULL) {
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;
205
tokens[index].tokdes = fslotdes;
206
tokens[index].slotdes = fpslotdes;
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;
225
FREE_CLEAR(certPrefix);
226
FREE_CLEAR(keyPrefix);
230
FREE_CLEAR(pslotdes);
231
FREE_CLEAR(fslotdes);
232
FREE_CLEAR(fpslotdes);
238
secmod_freeParams(sftk_parameters *params)
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);
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);
259
secmod_getSecmodName(char *param, char **appName, char **filename,PRBool *rw)
262
char *configdir = NULL;
263
char *secmodName = NULL;
265
char *save_params = param;
266
const char *lconfigdir;
267
param = secmod_argStrip(param);
271
SECMOD_HANDLE_STRING_ARG(param,configdir,"configDir=",;)
272
SECMOD_HANDLE_STRING_ARG(param,secmodName,"secmod=",;)
273
SECMOD_HANDLE_FINAL_ARG(param)
277
if (secmod_argHasFlag("flags","readOnly",save_params) ||
278
secmod_argHasFlag("flags","noModDB",save_params)) *rw = PR_FALSE;
280
if (!secmodName || *secmodName == '\0') {
281
if (secmodName) PORT_Free(secmodName);
282
secmodName = PORT_Strdup(SECMOD_DB);
284
*filename = secmodName;
286
lconfigdir = sftk_EvaluateConfigDir(configdir, appName);
289
value = PR_smprintf("%s" PATH_SEPARATOR "%s",lconfigdir,secmodName);
291
value = PR_smprintf("%s",secmodName);
293
if (configdir) PORT_Free(configdir);
297
/* Construct a database key for a given module */
298
static SECStatus secmod_MakeKey(DBT *key, char * module) {
302
commonName = secmod_argGetParamValue("name",module);
303
if (commonName == NULL) {
304
commonName = secmod_argGetParamValue("library",module);
306
if (commonName == NULL) return SECFailure;
307
len = PORT_Strlen(commonName);
308
key->data = commonName;
313
/* free out constructed database key */
315
secmod_FreeKey(DBT *key)
318
PORT_Free(key->data);
324
typedef struct secmodDataStr secmodData;
325
typedef struct secmodSlotDataStr secmodSlotData;
326
struct secmodDataStr {
329
unsigned char nameStart[2];
330
unsigned char slotOffset[2];
331
unsigned char internal;
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 */
344
struct secmodSlotDataStr {
345
unsigned char slotID[4];
346
unsigned char defaultFlags[4];
347
unsigned char timeout[4];
349
unsigned char hasRootCerts;
350
unsigned char reserved[18]; /* this makes it a round 32 bytes */
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
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]))
377
* build a data base entry from a module
380
secmod_EncodeData(DBT *data, char * module)
382
secmodData *encoded = NULL;
383
secmodSlotData *slot;
384
unsigned char *dataPtr;
385
unsigned short len, len2 = 0, len3 = 0;
387
unsigned short offset;
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;
396
rv = secmod_argParseModuleSpec(module,&dllName,&commonName,¶m,&nss);
397
if (rv != SECSuccess) return rv;
400
if (commonName == NULL) {
405
len = PORT_Strlen(commonName);
407
len2 = PORT_Strlen(dllName);
410
len3 = PORT_Strlen(param);
413
slotParams = secmod_argGetParamValue("slotParams",nss);
414
slotInfo = secmod_argParseSlotInfo(NULL,slotParams,&count);
415
if (slotParams) PORT_Free(slotParams);
417
if (count && slotInfo == NULL) {
422
dataLen = sizeof(secmodData) + len + len2 + len3 + sizeof(unsigned short) +
423
count*sizeof(secmodSlotData);
425
data->data = (unsigned char *) PORT_ZAlloc(dataLen);
426
encoded = (secmodData *)data->data;
427
dataPtr = (unsigned char *) data->data;
428
data->size = dataLen;
430
if (encoded == NULL) {
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);
448
order = secmod_argReadLong("trustOrder", nss, SECMOD_DEFAULT_TRUST_ORDER,
450
SECMOD_PUTLONG(encoded->trustOrder,order);
451
order = secmod_argReadLong("cipherOrder", nss, SECMOD_DEFAULT_CIPHER_ORDER,
453
SECMOD_PUTLONG(encoded->cipherOrder,order);
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);
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);
468
SECMOD_PUTSHORT(&dataPtr[offset],((unsigned short)count));
469
slot = (secmodSlotData *)(dataPtr+offset+sizeof(unsigned short));
472
SECMOD_PUTSHORT(encoded->names,len);
473
offset += sizeof(unsigned short);
474
PORT_Memcpy(&encoded->names[offset],commonName,len);
478
SECMOD_PUTSHORT(&encoded->names[offset],len2);
479
offset += sizeof(unsigned short);
480
if (len2) PORT_Memcpy(&encoded->names[offset],dllName,len2);
483
SECMOD_PUTSHORT(&encoded->names[offset],len3);
484
offset += sizeof(unsigned short);
485
if (len3) PORT_Memcpy(&encoded->names[offset],param,len3);
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));
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);
512
secmod_FreeData(DBT *data)
515
PORT_Free(data->data);
520
secmod_FreeSlotStrings(char **slotStrings, int count)
524
for (i=0; i < count; i++) {
525
if (slotStrings[i]) {
526
PR_smprintf_free(slotStrings[i]);
527
slotStrings[i] = NULL;
533
* build a module from the data base entry.
536
secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal)
539
secmodSlotData *slots;
541
char *commonName = NULL;
542
char *dllName = NULL;
543
char *parameters = NULL;
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;
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;
564
PRBool isModuleDB =PR_FALSE;
565
PRBool isModuleDBOnly =PR_FALSE;
566
PRBool extended =PR_FALSE;
570
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
574
#define CHECK_SIZE(x) \
575
if ((unsigned int) data->size < (unsigned int)(x)) goto db_loser
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.
582
CHECK_SIZE( offsetof(secmodData, trustOrder[0]) );
584
encoded = (secmodData *)data->data;
586
internal = (encoded->internal != 0) ? PR_TRUE: PR_FALSE;
587
isFIPS = (encoded->fips != 0) ? PR_TRUE: PR_FALSE;
590
*retInternal = internal;
592
parameters = PORT_ArenaStrdup(arena,defParams);
593
if (parameters == NULL)
596
if (internal && (encoded->major == SECMOD_DB_NOUI_VERSION_MAJOR) &&
597
(encoded->minor <= SECMOD_DB_NOUI_VERSION_MINOR)) {
598
isOldVersion = PR_TRUE;
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;
609
if (internal && !extended) {
613
/* decode SSL cipher enable flags */
614
ssl0 = SECMOD_GETLONG(encoded->ssl);
615
ssl1 = SECMOD_GETLONG(encoded->ssl + 4);
617
slotOffset = SECMOD_GETSHORT(encoded->slotOffset);
618
namesOffset = SECMOD_GETSHORT(encoded->nameStart);
621
/*--------------------------------------------------------------
622
** Now process the variable length set of names.
623
** The names have this structure:
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 ];
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);
641
CHECK_SIZE( namesRunningOffset + 2 + len);
642
commonName = (char*)PORT_ArenaAlloc(arena,len+1);
643
if (commonName == NULL)
645
PORT_Memcpy(commonName, names + namesRunningOffset + 2, len);
647
namesRunningOffset += len + 2;
649
/* copy the module's shared library file name. */
650
CHECK_SIZE( namesRunningOffset + 2);
651
len = SECMOD_GETSHORT(names + namesRunningOffset);
653
CHECK_SIZE( namesRunningOffset + 2 + len);
654
dllName = (char*)PORT_ArenaAlloc(arena,len + 1);
657
PORT_Memcpy(dllName, names + namesRunningOffset + 2, len);
660
namesRunningOffset += len + 2;
662
/* copy the module's initialization string, if present. */
663
if (!internal && extended) {
664
CHECK_SIZE( namesRunningOffset + 2);
665
len = SECMOD_GETSHORT(names+namesRunningOffset);
667
CHECK_SIZE( namesRunningOffset + 2 + len );
668
parameters = (char*)PORT_ArenaAlloc(arena,len + 1);
669
if (parameters == NULL)
671
PORT_Memcpy(parameters,names + namesRunningOffset + 2, len);
674
namesRunningOffset += len + 2;
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
687
if (slotOffset >= namesOffset) { /* slot block starts after name block */
688
if (slotOffset < namesRunningOffset) {
693
/* ------------------------------------------------------------------
694
** Part 3, process the slot table.
695
** This part has this structure:
697
** BYTE slotCount [ 2 ];
698
** secmodSlotData [ slotCount ];
702
CHECK_SIZE( slotOffset + 2 );
703
slotCount = SECMOD_GETSHORT((unsigned char *)data->data + slotOffset);
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.
709
if (slotOffset < namesOffset) { /* slot block starts before name block */
710
if (namesOffset < slotOffset + 2 + slotCount*sizeof(secmodSlotData)) {
715
CHECK_SIZE( (slotOffset + 2 + slotCount * sizeof(secmodSlotData)));
716
slots = (secmodSlotData *) ((unsigned char *)data->data + slotOffset + 2);
719
slotStrings = (char **)PORT_ArenaZAlloc(arena, slotCount * sizeof(char *));
720
if (slotStrings == NULL)
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;
734
if (hasRootCerts && !extended) {
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);
747
nss = secmod_mkNSS(slotStrings, slotCount, internal, isFIPS, isModuleDB,
748
isModuleDBOnly, internal, trustOrder, cipherOrder,
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);
759
PORT_SetError(SEC_ERROR_BAD_DATABASE);
761
PORT_FreeArena(arena,PR_TRUE);
768
secmod_OpenDB(const char *appName, const char *filename, const char *dbName,
769
PRBool readOnly, PRBool update)
775
char *secname = PORT_Strdup(filename);
776
int len = strlen(secname);
777
int status = RDB_FAIL;
779
if (len >= 3 && PORT_Strcmp(&secname[len-3],".db") == 0) {
783
rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_RDWR, NULL);
784
if (update && !pkcs11db) {
787
pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
789
if (status == RDB_RETRY) {
790
pkcs11db= rdbopen(appName, "", secname,
791
readOnly ? NO_RDONLY:NO_RDWR, NULL);
796
updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
798
db_Copy(pkcs11db,updatedb);
799
(*updatedb->close)(updatedb);
801
(*pkcs11db->close)(pkcs11db);
810
/* I'm sure we should do more checks here sometime... */
811
pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0);
813
/* didn't exist? create it */
814
if (pkcs11db == NULL) {
818
pkcs11db = dbopen( dbName, NO_CREATE, 0600, DB_HASH, 0 );
820
(* pkcs11db->sync)(pkcs11db, 0);
826
secmod_CloseDB(DB *pkcs11db)
828
(*pkcs11db->close)(pkcs11db);
832
secmod_addEscape(const char *string, char quote)
835
int escapes = 0, size = 0;
839
for (src=string; *src ; src++) {
840
if ((*src == quote) || (*src == '\\')) escapes++;
844
newString = PORT_ZAlloc(escapes+size+1);
845
if (newString == NULL) {
849
for (src=string, dest=newString; *src; src++,dest++) {
850
if ((*src == '\\') || (*src == quote)) {
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})\""
862
* Read all the existing modules in
865
secmod_ReadPermDB(const char *appName, const char *filename,
866
const char *dbname, char *params, PRBool rw)
871
char **moduleList = NULL, **newModuleList = NULL;
873
int useCount = SECMOD_STEP;
875
moduleList = (char **) PORT_ZAlloc(useCount*sizeof(char **));
876
if (moduleList == NULL) return NULL;
878
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_TRUE,rw);
879
if (pkcs11db == NULL) goto done;
881
/* read and parse the file or data base */
882
ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
888
PRBool internal = PR_FALSE;
889
if ((moduleCount+1) >= useCount) {
890
useCount += SECMOD_STEP;
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);
898
moduleString = secmod_DecodeData(params,&data,&internal);
900
moduleList[0] = moduleString;
902
moduleList[moduleCount] = moduleString;
905
} while ( (*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
908
if (!moduleList[0]) {
909
char * newparams = secmod_addEscape(params,'"');
911
moduleList[0] = PR_smprintf(SFTK_DEFAULT_INTERNAL_INIT,newparams,
913
PORT_Free(newparams);
916
/* deal with trust cert db here */
919
secmod_CloseDB(pkcs11db);
920
} else if (moduleList[0] && rw) {
921
secmod_AddPermDB(appName,filename,dbname,moduleList[0], rw) ;
923
if (!moduleList[0]) {
924
PORT_Free(moduleList);
931
secmod_ReleasePermDBData(const char *appName, const char *filename,
932
const char *dbname, char **moduleSpecList, PRBool rw)
934
if (moduleSpecList) {
936
for(index = moduleSpecList; *index; index++) {
937
PR_smprintf_free(*index);
939
PORT_Free(moduleSpecList);
945
* Delete a module from the Data Base
948
secmod_DeletePermDB(const char *appName, const char *filename,
949
const char *dbname, char *args, PRBool rw)
952
SECStatus rv = SECFailure;
956
if (!rw) return SECFailure;
958
/* make sure we have a db handle */
959
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
960
if (pkcs11db == NULL) {
964
rv = secmod_MakeKey(&key,args);
965
if (rv != SECSuccess) goto done;
967
ret = (*pkcs11db->del)(pkcs11db, &key, 0);
968
secmod_FreeKey(&key);
969
if (ret != 0) goto done;
972
ret = (*pkcs11db->sync)(pkcs11db, 0);
973
if (ret == 0) rv = SECSuccess;
976
secmod_CloseDB(pkcs11db);
981
* Add a module to the Data base
984
secmod_AddPermDB(const char *appName, const char *filename,
985
const char *dbname, char *module, PRBool rw)
988
SECStatus rv = SECFailure;
993
if (!rw) return SECFailure;
995
/* make sure we have a db handle */
996
pkcs11db = secmod_OpenDB(appName,filename,dbname,PR_FALSE,PR_FALSE);
997
if (pkcs11db == NULL) {
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);
1009
ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
1010
secmod_FreeKey(&key);
1011
secmod_FreeData(&data);
1012
if (ret != 0) goto done;
1014
ret = (*pkcs11db->sync)(pkcs11db, 0);
1015
if (ret == 0) rv = SECSuccess;
1018
secmod_CloseDB(pkcs11db);