security/nss/lib/pk11wrap/pk11pars.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 /*
     5  * The following handles the loading, unloading and management of
     6  * various PCKS #11 modules
     7  */
     9 #include <ctype.h>
    10 #include "pkcs11.h"
    11 #include "seccomon.h"
    12 #include "secmod.h"
    13 #include "secmodi.h"
    14 #include "secmodti.h"
    15 #include "pki3hack.h"
    16 #include "secerr.h"
    18 #include "utilpars.h" 
    20 /* create a new module */
    21 static  SECMODModule *
    22 secmod_NewModule(void)
    23 {
    24     SECMODModule *newMod;
    25     PLArenaPool *arena;
    28     /* create an arena in which dllName and commonName can be
    29      * allocated.
    30      */
    31     arena = PORT_NewArena(512);
    32     if (arena == NULL) {
    33 	return NULL;
    34     }
    36     newMod = (SECMODModule *)PORT_ArenaAlloc(arena,sizeof (SECMODModule));
    37     if (newMod == NULL) {
    38 	PORT_FreeArena(arena,PR_FALSE);
    39 	return NULL;
    40     }
    42     /*
    43      * initialize of the fields of the module
    44      */
    45     newMod->arena = arena;
    46     newMod->internal = PR_FALSE;
    47     newMod->loaded = PR_FALSE;
    48     newMod->isFIPS = PR_FALSE;
    49     newMod->dllName = NULL;
    50     newMod->commonName = NULL;
    51     newMod->library = NULL;
    52     newMod->functionList = NULL;
    53     newMod->slotCount = 0;
    54     newMod->slots = NULL;
    55     newMod->slotInfo = NULL;
    56     newMod->slotInfoCount = 0;
    57     newMod->refCount = 1;
    58     newMod->ssl[0] = 0;
    59     newMod->ssl[1] = 0;
    60     newMod->libraryParams = NULL;
    61     newMod->moduleDBFunc = NULL;
    62     newMod->parent = NULL;
    63     newMod->isCritical = PR_FALSE;
    64     newMod->isModuleDB = PR_FALSE;
    65     newMod->moduleDBOnly = PR_FALSE;
    66     newMod->trustOrder = 0;
    67     newMod->cipherOrder = 0;
    68     newMod->evControlMask = 0;
    69     newMod->refLock = PZ_NewLock(nssILockRefLock);
    70     if (newMod->refLock == NULL) {
    71 	PORT_FreeArena(arena,PR_FALSE);
    72 	return NULL;
    73     }
    74     return newMod;
    76 }
    78 /* private flags for isModuleDB (field in SECMODModule). */
    79 /* The meaing of these flags is as follows:
    80  *
    81  * SECMOD_FLAG_MODULE_DB_IS_MODULE_DB - This is a module that accesses the 
    82  *   database of other modules to load. Module DBs are loadable modules that
    83  *   tells NSS which PKCS #11 modules to load and when. These module DBs are 
    84  *   chainable. That is, one module DB can load another one. NSS system init 
    85  *   design takes advantage of this feature. In system NSS, a fixed system 
    86  *   module DB loads the system defined libraries, then chains out to the 
    87  *   traditional module DBs to load any system or user configured modules 
    88  *   (like smart cards). This bit is the same as the already existing meaning 
    89  *   of  isModuleDB = PR_TRUE. None of the other module db flags should be set 
    90  *   if this flag isn't on.
    91  *
    92  * SECMOD_FLAG_MODULE_DB_SKIP_FIRST - This flag tells NSS to skip the first 
    93  *   PKCS #11 module presented by a module DB. This allows the OS to load a 
    94  *   softoken from the system module, then ask the existing module DB code to 
    95  *   load the other PKCS #11 modules in that module DB (skipping it's request 
    96  *   to load softoken). This gives the system init finer control over the 
    97  *   configuration of that softoken module.
    98  *
    99  * SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB - This flag allows system init to mark a 
   100  *   different module DB as the 'default' module DB (the one in which 
   101  *   'Add module' changes will go). Without this flag NSS takes the first 
   102  *   module as the default Module DB, but in system NSS, that first module 
   103  *   is the system module, which is likely read only (at least to the user).
   104  *   This  allows system NSS to delegate those changes to the user's module DB, 
   105  *   preserving the user's ability to load new PKCS #11 modules (which only 
   106  *   affect him), from existing applications like Firefox.
   107  */
   108 #define SECMOD_FLAG_MODULE_DB_IS_MODULE_DB  0x01 /* must be set if any of the 
   109 						  *other flags are set */
   110 #define SECMOD_FLAG_MODULE_DB_SKIP_FIRST    0x02
   111 #define SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB 0x04
   114 /* private flags for internal (field in SECMODModule). */
   115 /* The meaing of these flags is as follows:
   116  *
   117  * SECMOD_FLAG_INTERNAL_IS_INTERNAL - This is a marks the the module is
   118  *   the internal module (that is, softoken). This bit is the same as the 
   119  *   already existing meaning of internal = PR_TRUE. None of the other 
   120  *   internal flags should be set if this flag isn't on.
   121  *
   122  * SECMOD_FLAG_MODULE_INTERNAL_KEY_SLOT - This flag allows system init to mark 
   123  *   a  different slot returned byt PK11_GetInternalKeySlot(). The 'primary'
   124  *   slot defined by this module will be the new internal key slot.
   125  */
   126 #define SECMOD_FLAG_INTERNAL_IS_INTERNAL       0x01 /* must be set if any of 
   127 						     *the other flags are set */
   128 #define SECMOD_FLAG_INTERNAL_KEY_SLOT          0x02
   130 /*
   131  * for 3.4 we continue to use the old SECMODModule structure
   132  */
   133 SECMODModule *
   134 SECMOD_CreateModule(const char *library, const char *moduleName, 
   135 				const char *parameters, const char *nss)
   136 {
   137     SECMODModule *mod = secmod_NewModule();
   138     char *slotParams,*ciphers;
   139     /* pk11pars.h still does not have const char * interfaces */
   140     char *nssc = (char *)nss;
   141     if (mod == NULL) return NULL;
   143     mod->commonName = PORT_ArenaStrdup(mod->arena,moduleName ? moduleName : "");
   144     if (library) {
   145 	mod->dllName = PORT_ArenaStrdup(mod->arena,library);
   146     }
   147     /* new field */
   148     if (parameters) {
   149 	mod->libraryParams = PORT_ArenaStrdup(mod->arena,parameters);
   150     }
   151     mod->internal   = NSSUTIL_ArgHasFlag("flags","internal",nssc);
   152     mod->isFIPS     = NSSUTIL_ArgHasFlag("flags","FIPS",nssc);
   153     mod->isCritical = NSSUTIL_ArgHasFlag("flags","critical",nssc);
   154     slotParams      = NSSUTIL_ArgGetParamValue("slotParams",nssc);
   155     mod->slotInfo   = NSSUTIL_ArgParseSlotInfo(mod->arena,slotParams,
   156 							&mod->slotInfoCount);
   157     if (slotParams) PORT_Free(slotParams);
   158     /* new field */
   159     mod->trustOrder  = NSSUTIL_ArgReadLong("trustOrder",nssc,
   160 					NSSUTIL_DEFAULT_TRUST_ORDER,NULL);
   161     /* new field */
   162     mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder",nssc,
   163 					NSSUTIL_DEFAULT_CIPHER_ORDER,NULL);
   164     /* new field */
   165     mod->isModuleDB   = NSSUTIL_ArgHasFlag("flags","moduleDB",nssc);
   166     mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags","moduleDBOnly",nssc);
   167     if (mod->moduleDBOnly) mod->isModuleDB = PR_TRUE;
   169     /* we need more bits, but we also want to preserve binary compatibility 
   170      * so we overload the isModuleDB PRBool with additional flags. 
   171      * These flags are only valid if mod->isModuleDB is already set.
   172      * NOTE: this depends on the fact that PRBool is at least a char on 
   173      * all platforms. These flags are only valid if moduleDB is set, so 
   174      * code checking if (mod->isModuleDB) will continue to work correctly. */
   175     if (mod->isModuleDB) {
   176 	char flags = SECMOD_FLAG_MODULE_DB_IS_MODULE_DB;
   177 	if (NSSUTIL_ArgHasFlag("flags","skipFirst",nssc)) {
   178 	    flags |= SECMOD_FLAG_MODULE_DB_SKIP_FIRST;
   179 	}
   180 	if (NSSUTIL_ArgHasFlag("flags","defaultModDB",nssc)) {
   181 	    flags |= SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB;
   182 	}
   183 	/* additional moduleDB flags could be added here in the future */
   184 	mod->isModuleDB = (PRBool) flags;
   185     }
   187     if (mod->internal) {
   188 	char flags = SECMOD_FLAG_INTERNAL_IS_INTERNAL;
   190 	if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nssc)) {
   191 	    flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT;
   192 	}
   193 	mod->internal = (PRBool) flags;
   194     }
   196     ciphers = NSSUTIL_ArgGetParamValue("ciphers",nssc);
   197     NSSUTIL_ArgParseCipherFlags(&mod->ssl[0],ciphers);
   198     if (ciphers) PORT_Free(ciphers);
   200     secmod_PrivateModuleCount++;
   202     return mod;
   203 }
   205 PRBool
   206 SECMOD_GetSkipFirstFlag(SECMODModule *mod)
   207 {
   208    char flags = (char) mod->isModuleDB;
   210    return (flags & SECMOD_FLAG_MODULE_DB_SKIP_FIRST) ? PR_TRUE : PR_FALSE;
   211 }
   213 PRBool
   214 SECMOD_GetDefaultModDBFlag(SECMODModule *mod)
   215 {
   216    char flags = (char) mod->isModuleDB;
   218    return (flags & SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE;
   219 }
   221 PRBool
   222 secmod_IsInternalKeySlot(SECMODModule *mod)
   223 {
   224    char flags = (char) mod->internal;
   226    return (flags & SECMOD_FLAG_INTERNAL_KEY_SLOT) ? PR_TRUE : PR_FALSE;
   227 }
   229 void
   230 secmod_SetInternalKeySlotFlag(SECMODModule *mod, PRBool val)
   231 {
   232    char flags = (char) mod->internal;
   234    if (val)  {
   235 	flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT;
   236    } else {
   237 	flags &= ~SECMOD_FLAG_INTERNAL_KEY_SLOT;
   238    }
   239    mod->internal = flags;
   240 }
   242 /*
   243  * copy desc and value into target. Target is known to be big enough to
   244  * hold desc +2 +value, which is good because the result of this will be
   245  * *desc"*value". We may, however, have to add some escapes for special
   246  * characters imbedded into value (rare). This string potentially comes from
   247  * a user, so we don't want the user overflowing the target buffer by using
   248  * excessive escapes. To prevent this we count the escapes we need to add and
   249  * try to expand the buffer with Realloc.
   250  */
   251 static char *
   252 secmod_doDescCopy(char *target, int *targetLen, const char *desc,
   253 			int descLen, char *value)
   254 {
   255     int diff, esc_len;
   257     esc_len = NSSUTIL_EscapeSize(value, '\"') - 1;
   258     diff = esc_len - strlen(value);
   259     if (diff > 0) {
   260 	/* we need to escape... expand newSpecPtr as well to make sure
   261 	 * we don't overflow it */
   262 	char *newPtr = PORT_Realloc(target, *targetLen * diff);
   263 	if (!newPtr) {
   264 	    return target; /* not enough space, just drop the whole copy */
   265 	}
   266 	*targetLen += diff;
   267 	target = newPtr;
   268 	value = NSSUTIL_Escape(value, '\"');
   269 	if (value == NULL) {
   270 	    return target; /* couldn't escape value, just drop the copy */
   271 	}
   272     }
   273     PORT_Memcpy(target, desc, descLen);
   274     target += descLen;
   275     *target++='\"';
   276     PORT_Memcpy(target, value, esc_len);
   277     target += esc_len;
   278     *target++='\"';
   279     if (diff > 0) {
   280 	PORT_Free(value);
   281     }
   282     return target;
   283 }
   285 #define SECMOD_SPEC_COPY(new, start, end)    \
   286   if (end > start) {                         \
   287 	int _cnt = end - start;	             \
   288 	PORT_Memcpy(new, start, _cnt);       \
   289 	new += _cnt;                         \
   290   }
   291 #define SECMOD_TOKEN_DESCRIPTION "tokenDescription="
   292 #define SECMOD_SLOT_DESCRIPTION   "slotDescription="
   295 /*
   296  * Find any tokens= values in the module spec. 
   297  * Always return a new spec which does not have any tokens= arguments.
   298  * If tokens= arguments are found, Split the the various tokens defined into
   299  * an array of child specs to return.
   300  *
   301  * Caller is responsible for freeing the child spec and the new token
   302  * spec.
   303  */
   304 char *
   305 secmod_ParseModuleSpecForTokens(PRBool convert, PRBool isFIPS, 
   306 				char *moduleSpec, char ***children, 
   307 				CK_SLOT_ID **ids)
   308 {
   309     int        newSpecLen   = PORT_Strlen(moduleSpec)+2;
   310     char       *newSpec     = PORT_Alloc(newSpecLen);
   311     char       *newSpecPtr  = newSpec;
   312     char       *modulePrev  = moduleSpec;
   313     char       *target      = NULL;
   314     char *tmp = NULL;
   315     char       **childArray = NULL;
   316     char       *tokenIndex;
   317     CK_SLOT_ID *idArray     = NULL;
   318     int        tokenCount = 0;
   319     int        i;
   321     if (newSpec == NULL) {
   322 	return NULL;
   323     }
   325     *children = NULL;
   326     if (ids) {
   327 	*ids = NULL;
   328     }
   329     moduleSpec = NSSUTIL_ArgStrip(moduleSpec);
   330     SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec);
   332     /* Notes on 'convert' and 'isFIPS' flags: The base parameters for opening 
   333      * a new softoken module takes the following parameters to name the 
   334      * various tokens:
   335      *  
   336      *  cryptoTokenDescription: name of the non-fips crypto token.
   337      *  cryptoSlotDescription: name of the non-fips crypto slot.
   338      *  dbTokenDescription: name of the non-fips db token.
   339      *  dbSlotDescription: name of the non-fips db slot.
   340      *  FIPSTokenDescription: name of the fips db/crypto token.
   341      *  FIPSSlotDescription: name of the fips db/crypto slot.
   342      *
   343      * if we are opening a new slot, we need to have the following
   344      * parameters:
   345      *  tokenDescription: name of the token.
   346      *  slotDescription: name of the slot.
   347      *
   348      *
   349      * The convert flag tells us to drop the unnecessary *TokenDescription 
   350      * and *SlotDescription arguments and convert the appropriate pair 
   351      * (either db or FIPS based on the isFIPS flag) to tokenDescription and 
   352      * slotDescription).
   353      */
   354     /*
   355      * walk down the list. if we find a tokens= argument, save it,
   356      * otherise copy the argument.
   357      */
   358     while (*moduleSpec) {
   359 	int next;
   360 	modulePrev = moduleSpec;
   361 	NSSUTIL_HANDLE_STRING_ARG(moduleSpec, target, "tokens=",
   362 			modulePrev = moduleSpec; /* skip copying */ )
   363 	NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "cryptoTokenDescription=",
   364 			if (convert) { modulePrev = moduleSpec; } );
   365 	NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "cryptoSlotDescription=",
   366 			if (convert) { modulePrev = moduleSpec; } );
   367 	NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "dbTokenDescription=",
   368 			if (convert) {
   369 			    modulePrev = moduleSpec; 
   370 			    if (!isFIPS) {
   371 				newSpecPtr = secmod_doDescCopy(newSpecPtr, 
   372 				    &newSpecLen, SECMOD_TOKEN_DESCRIPTION, 
   373 				    sizeof(SECMOD_TOKEN_DESCRIPTION)-1, tmp);
   374 			    }
   375 			});
   376 	NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "dbSlotDescription=",
   377 			if (convert) {
   378 			    modulePrev = moduleSpec; /* skip copying */ 
   379 			    if (!isFIPS) {
   380 				newSpecPtr = secmod_doDescCopy(newSpecPtr, 
   381 				    &newSpecLen, SECMOD_SLOT_DESCRIPTION, 
   382 				    sizeof(SECMOD_SLOT_DESCRIPTION)-1, tmp);
   383 			    }
   384 			} );
   385 	NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "FIPSTokenDescription=",
   386 			if (convert) {
   387 			    modulePrev = moduleSpec; /* skip copying */ 
   388 			    if (isFIPS) {
   389 				newSpecPtr = secmod_doDescCopy(newSpecPtr, 
   390 				    &newSpecLen, SECMOD_TOKEN_DESCRIPTION, 
   391 				    sizeof(SECMOD_TOKEN_DESCRIPTION)-1, tmp);
   392 			    }
   393 			} );
   394 	NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "FIPSSlotDescription=",
   395 			if (convert) {
   396 			    modulePrev = moduleSpec; /* skip copying */ 
   397 			    if (isFIPS) {
   398 				newSpecPtr = secmod_doDescCopy(newSpecPtr, 
   399 				    &newSpecLen, SECMOD_SLOT_DESCRIPTION, 
   400 				    sizeof(SECMOD_SLOT_DESCRIPTION)-1, tmp);
   401 			    }
   402 			} );
   403 	NSSUTIL_HANDLE_FINAL_ARG(moduleSpec)
   404 	SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec);
   405     }
   406     if (tmp) {
   407 	PORT_Free(tmp);
   408 	tmp = NULL;
   409     }
   410     *newSpecPtr = 0;
   412     /* no target found, return the newSpec */
   413     if (target == NULL) {
   414 	return newSpec;
   415     }
   417     /* now build the child array from target */
   418     /*first count them */
   419     for (tokenIndex = NSSUTIL_ArgStrip(target); *tokenIndex;
   420 	tokenIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(tokenIndex))) {
   421 	tokenCount++;
   422     }
   424     childArray = PORT_NewArray(char *, tokenCount+1);
   425     if (childArray == NULL) {
   426 	/* just return the spec as is then */
   427 	PORT_Free(target);
   428 	return newSpec;
   429     }
   430     if (ids) {
   431 	idArray = PORT_NewArray(CK_SLOT_ID, tokenCount+1);
   432 	if (idArray == NULL) {
   433 	    PORT_Free(childArray);
   434 	    PORT_Free(target);
   435 	    return newSpec;
   436 	}
   437     }
   439     /* now fill them in */
   440     for (tokenIndex = NSSUTIL_ArgStrip(target), i=0 ; 
   441 			*tokenIndex && (i < tokenCount); 
   442 			tokenIndex=NSSUTIL_ArgStrip(tokenIndex)) {
   443 	int next;
   444 	char *name = NSSUTIL_ArgGetLabel(tokenIndex, &next);
   445 	tokenIndex += next;
   447  	if (idArray) {
   448 	   idArray[i] = NSSUTIL_ArgDecodeNumber(name);
   449 	}
   451 	PORT_Free(name); /* drop the explicit number */
   453 	/* if anything is left, copy the args to the child array */
   454 	if (!NSSUTIL_ArgIsBlank(*tokenIndex)) {
   455 	    childArray[i++] = NSSUTIL_ArgFetchValue(tokenIndex, &next);
   456 	    tokenIndex += next;
   457 	}
   458     }
   460     PORT_Free(target);
   461     childArray[i] = 0;
   462     if (idArray) {
   463 	idArray[i] = 0;
   464     }
   466     /* return it */
   467     *children = childArray;
   468     if (ids) {
   469 	*ids = idArray;
   470     }
   471     return newSpec;
   472 }
   474 /* get the database and flags from the spec */
   475 static char *
   476 secmod_getConfigDir(char *spec, char **certPrefix, char **keyPrefix,
   477 			  PRBool *readOnly)
   478 {
   479     char * config = NULL;
   481     *certPrefix = NULL;
   482     *keyPrefix = NULL;
   483     *readOnly = NSSUTIL_ArgHasFlag("flags","readOnly",spec);
   485     spec = NSSUTIL_ArgStrip(spec);
   486     while (*spec) {
   487 	int next;
   488 	NSSUTIL_HANDLE_STRING_ARG(spec, config, "configdir=", ;)
   489 	NSSUTIL_HANDLE_STRING_ARG(spec, *certPrefix, "certPrefix=", ;)
   490 	NSSUTIL_HANDLE_STRING_ARG(spec, *keyPrefix, "keyPrefix=", ;)
   491 	NSSUTIL_HANDLE_FINAL_ARG(spec)
   492     }
   493     return config;
   494 }
   496 struct SECMODConfigListStr {
   497     char *config;
   498     char *certPrefix;
   499     char *keyPrefix;
   500     PRBool isReadOnly;
   501 };
   503 /*
   504  * return an array of already openned databases from a spec list.
   505  */
   506 SECMODConfigList *
   507 secmod_GetConfigList(PRBool isFIPS, char *spec, int *count)
   508 {
   509     char **children;
   510     CK_SLOT_ID *ids;
   511     char *strippedSpec;
   512     int childCount;
   513     SECMODConfigList *conflist = NULL;
   514     int i;
   516     strippedSpec = secmod_ParseModuleSpecForTokens(PR_TRUE, isFIPS, 
   517 						spec,&children,&ids);
   518     if (strippedSpec == NULL) {
   519 	return NULL;
   520     }
   522     for (childCount=0; children && children[childCount]; childCount++) ;
   523     *count = childCount+1; /* include strippedSpec */
   524     conflist = PORT_NewArray(SECMODConfigList,*count);
   525     if (conflist == NULL) {
   526 	*count = 0;
   527 	goto loser;
   528     }
   530     conflist[0].config = secmod_getConfigDir(strippedSpec, 
   531 					    &conflist[0].certPrefix, 
   532 					    &conflist[0].keyPrefix,
   533 					    &conflist[0].isReadOnly);
   534     for (i=0; i < childCount; i++) {
   535 	conflist[i+1].config = secmod_getConfigDir(children[i], 
   536 					    &conflist[i+1].certPrefix, 
   537 					    &conflist[i+1].keyPrefix,
   538 					    &conflist[i+1].isReadOnly);
   539     }
   541 loser:
   542     secmod_FreeChildren(children, ids);
   543     PORT_Free(strippedSpec);
   544     return conflist;
   545 }
   547 /*
   548  * determine if we are trying to open an old dbm database. For this test
   549  * RDB databases should return PR_FALSE.
   550  */
   551 static PRBool
   552 secmod_configIsDBM(char *configDir)
   553 {
   554     char *env;
   556     /* explicit dbm open */
   557     if (strncmp(configDir, "dbm:", 4) == 0) {
   558 	return PR_TRUE;
   559     }
   560     /* explicit open of a non-dbm database */
   561     if ((strncmp(configDir, "sql:",4) == 0) 
   562 	|| (strncmp(configDir, "rdb:", 4) == 0)
   563 	|| (strncmp(configDir, "extern:", 7) == 0)) {
   564 	return PR_FALSE;
   565     }
   566     env = PR_GetEnv("NSS_DEFAULT_DB_TYPE");
   567     /* implicit dbm open */
   568     if ((env == NULL) || (strcmp(env,"dbm") == 0)) {
   569 	return PR_TRUE;
   570     }
   571     /* implicit non-dbm open */
   572     return PR_FALSE;
   573 }
   575 /*
   576  * match two prefixes. prefix may be NULL. NULL patches '\0'
   577  */
   578 static PRBool
   579 secmod_matchPrefix(char *prefix1, char *prefix2)
   580 {
   581     if ((prefix1 == NULL) || (*prefix1 == 0)) {
   582 	if ((prefix2 == NULL) || (*prefix2 == 0)) {
   583 	    return PR_TRUE;
   584 	}
   585 	return PR_FALSE;
   586     }
   587     if (strcmp(prefix1, prefix2) == 0) {
   588 	return PR_TRUE;
   589     }
   590     return PR_FALSE;
   591 }
   593 /*
   594  * return true if we are requesting a database that is already openned.
   595  */
   596 PRBool
   597 secmod_MatchConfigList(char *spec, SECMODConfigList *conflist, int count)
   598 {
   599     char *config;
   600     char *certPrefix;
   601     char *keyPrefix;
   602     PRBool isReadOnly;
   603     PRBool ret=PR_FALSE;
   604     int i;
   606     config = secmod_getConfigDir(spec, &certPrefix, &keyPrefix, &isReadOnly);
   607     if (!config) {
   608 	ret=PR_TRUE;
   609 	goto done;
   610     }
   612     /* NOTE: we dbm isn't multiple open safe. If we open the same database 
   613      * twice from two different locations, then we can corrupt our database
   614      * (the cache will be inconsistent). Protect against this by claiming
   615      * for comparison only that we are always openning dbm databases read only.
   616      */
   617     if (secmod_configIsDBM(config)) {
   618 	isReadOnly = 1;
   619     }
   620     for (i=0; i < count; i++) {
   621 	if ((strcmp(config,conflist[i].config) == 0)  &&
   622 	    secmod_matchPrefix(certPrefix, conflist[i].certPrefix) &&
   623 	    secmod_matchPrefix(keyPrefix, conflist[i].keyPrefix) &&
   624 	    /* this last test -- if we just need the DB open read only,
   625 	     * than any open will suffice, but if we requested it read/write
   626 	     * and it's only open read only, we need to open it again */
   627 	    (isReadOnly || !conflist[i].isReadOnly)) {
   628 	    ret = PR_TRUE;
   629 	    goto done;
   630 	}
   631     }
   633     ret = PR_FALSE;
   634 done:
   635     PORT_Free(config);
   636     PORT_Free(certPrefix);
   637     PORT_Free(keyPrefix);
   638     return ret;
   639 }
   641 void
   642 secmod_FreeConfigList(SECMODConfigList *conflist, int count)
   643 {
   644     int i;
   645     for (i=0; i < count; i++) {
   646 	PORT_Free(conflist[i].config);
   647 	PORT_Free(conflist[i].certPrefix);
   648 	PORT_Free(conflist[i].keyPrefix);
   649     }
   650     PORT_Free(conflist);
   651 }
   653 void
   654 secmod_FreeChildren(char **children, CK_SLOT_ID *ids)
   655 {
   656     char **thisChild;
   658     if (!children) {
   659 	return;
   660     }
   662     for (thisChild = children; thisChild && *thisChild; thisChild++ ) {
   663 	PORT_Free(*thisChild);
   664     }
   665     PORT_Free(children);
   666     if (ids) {
   667 	PORT_Free(ids);
   668     }
   669     return;
   670 }
   672 /*
   673  * caclulate the length of each child record:
   674  * " 0x{id}=<{escaped_child}>"
   675  */
   676 static int
   677 secmod_getChildLength(char *child, CK_SLOT_ID id)
   678 {
   679     int length = NSSUTIL_DoubleEscapeSize(child, '>', ']');
   680     if (id == 0) {
   681 	length++;
   682     }
   683     while (id) {
   684 	length++;
   685 	id = id >> 4;
   686     }
   687     length += 6; /* {sp}0x[id]=<{child}> */
   688     return length;
   689 }
   691 /*
   692  * Build a child record:
   693  * " 0x{id}=<{escaped_child}>"
   694  */
   695 static SECStatus
   696 secmod_mkTokenChild(char **next, int *length, char *child, CK_SLOT_ID id)
   697 {
   698     int len;
   699     char *escSpec;
   701     len = PR_snprintf(*next, *length, " 0x%x=<",id);
   702     if (len < 0) {
   703 	return SECFailure;
   704     }
   705     *next += len;
   706     *length -= len;
   707     escSpec = NSSUTIL_DoubleEscape(child, '>', ']');
   708     if (escSpec == NULL) {
   709 	return SECFailure;
   710     }
   711     if (*child && (*escSpec == 0)) {
   712 	PORT_Free(escSpec);
   713 	return SECFailure;
   714     }
   715     len = strlen(escSpec);
   716     if (len+1 > *length) {
   717 	PORT_Free(escSpec);
   718 	return SECFailure;
   719     }
   720     PORT_Memcpy(*next,escSpec, len);
   721     *next += len;
   722     *length -= len;
   723     PORT_Free(escSpec);
   724     **next = '>';
   725     (*next)++;
   726     (*length)--;
   727     return SECSuccess;
   728 }
   730 #define TOKEN_STRING " tokens=["
   732 char *
   733 secmod_MkAppendTokensList(PLArenaPool *arena, char *oldParam, char *newToken,
   734 			CK_SLOT_ID newID, char **children, CK_SLOT_ID *ids)
   735 {
   736     char *rawParam = NULL;	/* oldParam with tokens stripped off */
   737     char *newParam = NULL;	/* space for the return parameter */
   738     char *nextParam = NULL;	/* current end of the new parameter */
   739     char **oldChildren = NULL;
   740     CK_SLOT_ID *oldIds = NULL;
   741     void *mark = NULL;         /* mark the arena pool in case we need 
   742 				* to release it */
   743     int length, i, tmpLen;
   744     SECStatus rv;
   746     /* first strip out and save the old tokenlist */
   747     rawParam = secmod_ParseModuleSpecForTokens(PR_FALSE,PR_FALSE, 
   748 					oldParam,&oldChildren,&oldIds);
   749     if (!rawParam) {
   750 	goto loser;
   751     }
   753     /* now calculate the total length of the new buffer */
   754     /* First the 'fixed stuff', length of rawparam (does not include a NULL),
   755      * length of the token string (does include the NULL), closing bracket */
   756     length = strlen(rawParam) + sizeof(TOKEN_STRING) + 1;
   757     /* now add then length of all the old children */
   758     for (i=0; oldChildren && oldChildren[i]; i++) {
   759 	length += secmod_getChildLength(oldChildren[i], oldIds[i]);
   760     }
   762     /* add the new token */
   763     length += secmod_getChildLength(newToken, newID);
   765     /* and it's new children */
   766     for (i=0; children && children[i]; i++) {
   767 	if (ids[i] == -1) {
   768 	    continue;
   769 	}
   770 	length += secmod_getChildLength(children[i], ids[i]);
   771     }
   773     /* now allocate and build the string */
   774     mark = PORT_ArenaMark(arena);
   775     if (!mark) {
   776 	goto loser;
   777     }
   778     newParam =  PORT_ArenaAlloc(arena,length);
   779     if (!newParam) {
   780 	goto loser;
   781     }
   783     PORT_Strcpy(newParam, oldParam);
   784     tmpLen = strlen(oldParam);
   785     nextParam = newParam + tmpLen;
   786     length -= tmpLen;
   787     PORT_Memcpy(nextParam, TOKEN_STRING, sizeof(TOKEN_STRING)-1);
   788     nextParam += sizeof(TOKEN_STRING)-1;
   789     length -= sizeof(TOKEN_STRING)-1;
   791     for (i=0; oldChildren && oldChildren[i]; i++) {
   792 	rv = secmod_mkTokenChild(&nextParam,&length,oldChildren[i],oldIds[i]);
   793 	if (rv != SECSuccess) {
   794 	    goto loser;
   795 	}
   796     }
   798     rv = secmod_mkTokenChild(&nextParam, &length, newToken, newID);
   799     if (rv != SECSuccess) {
   800 	goto loser;
   801     }
   803     for (i=0; children && children[i]; i++) {
   804 	if (ids[i] == -1) {
   805 	    continue;
   806 	}
   807 	rv = secmod_mkTokenChild(&nextParam, &length, children[i], ids[i]);
   808 	if (rv != SECSuccess) {
   809 	    goto loser;
   810 	}
   811     }
   813     if (length < 2) {
   814 	goto loser;
   815     }
   817     *nextParam++ = ']';
   818     *nextParam++ = 0;
   820     /* we are going to return newParam now, don't release the mark */
   821     PORT_ArenaUnmark(arena, mark);
   822     mark = NULL;
   824 loser:
   825     if (mark) {
   826 	PORT_ArenaRelease(arena, mark);
   827 	newParam = NULL; /* if the mark is still active, 
   828 			  * don't return the param */
   829     }
   830     if (rawParam) {
   831 	PORT_Free(rawParam);
   832     }
   833     if (oldChildren) {
   834 	secmod_FreeChildren(oldChildren, oldIds);
   835     }
   836     return newParam;
   837 }
   839 static char *
   840 secmod_mkModuleSpec(SECMODModule * module)
   841 {
   842     char *nss = NULL, *modSpec = NULL, **slotStrings = NULL;
   843     int slotCount, i, si;
   844     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
   846     /* allocate target slot info strings */
   847     slotCount = 0;
   849     SECMOD_GetReadLock(moduleLock);
   850     if (module->slotCount) {
   851 	for (i=0; i < module->slotCount; i++) {
   852 	    if (module->slots[i]->defaultFlags !=0) {
   853 		slotCount++;
   854 	    }
   855 	}
   856     } else {
   857 	slotCount = module->slotInfoCount;
   858     }
   860     slotStrings = (char **)PORT_ZAlloc(slotCount*sizeof(char *));
   861     if (slotStrings == NULL) {
   862         SECMOD_ReleaseReadLock(moduleLock);
   863 	goto loser;
   864     }
   867     /* build the slot info strings */
   868     if (module->slotCount) {
   869 	for (i=0, si= 0; i < module->slotCount; i++) {
   870 	    if (module->slots[i]->defaultFlags) {
   871 		PORT_Assert(si < slotCount);
   872 		if (si >= slotCount) break;
   873 		slotStrings[si] = NSSUTIL_MkSlotString(module->slots[i]->slotID,
   874 			module->slots[i]->defaultFlags,
   875 			module->slots[i]->timeout,
   876 			module->slots[i]->askpw,
   877 			module->slots[i]->hasRootCerts,
   878 			module->slots[i]->hasRootTrust);
   879 		si++;
   880 	    }
   881 	}
   882      } else {
   883 	for (i=0; i < slotCount; i++) {
   884 		slotStrings[i] = NSSUTIL_MkSlotString(
   885 			module->slotInfo[i].slotID,
   886 			module->slotInfo[i].defaultFlags,
   887 			module->slotInfo[i].timeout,
   888 			module->slotInfo[i].askpw,
   889 			module->slotInfo[i].hasRootCerts,
   890 			module->slotInfo[i].hasRootTrust);
   891 	}
   892     }
   894     SECMOD_ReleaseReadLock(moduleLock);
   895     nss = NSSUTIL_MkNSSString(slotStrings,slotCount,module->internal, 
   896 		       module->isFIPS, module->isModuleDB,
   897 		       module->moduleDBOnly, module->isCritical,
   898 		       module->trustOrder, module->cipherOrder,
   899 		       module->ssl[0],module->ssl[1]);
   900     modSpec= NSSUTIL_MkModuleSpec(module->dllName,module->commonName,
   901 						module->libraryParams,nss);
   902     PORT_Free(slotStrings);
   903     PR_smprintf_free(nss);
   904 loser:
   905     return (modSpec);
   906 }
   909 char **
   910 SECMOD_GetModuleSpecList(SECMODModule *module)
   911 {
   912     SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc;
   913     if (func) {
   914 	return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND,
   915 		module->libraryParams,NULL);
   916     }
   917     return NULL;
   918 }
   920 SECStatus
   921 SECMOD_AddPermDB(SECMODModule *module)
   922 {
   923     SECMODModuleDBFunc func;
   924     char *moduleSpec;
   925     char **retString;
   927     if (module->parent == NULL) return SECFailure;
   929     func  = (SECMODModuleDBFunc) module->parent->moduleDBFunc;
   930     if (func) {
   931 	moduleSpec = secmod_mkModuleSpec(module);
   932 	retString = (*func)(SECMOD_MODULE_DB_FUNCTION_ADD,
   933 		module->parent->libraryParams,moduleSpec);
   934 	PORT_Free(moduleSpec);
   935 	if (retString != NULL) return SECSuccess;
   936     }
   937     return SECFailure;
   938 }
   940 SECStatus
   941 SECMOD_DeletePermDB(SECMODModule *module)
   942 {
   943     SECMODModuleDBFunc func;
   944     char *moduleSpec;
   945     char **retString;
   947     if (module->parent == NULL) return SECFailure;
   949     func  = (SECMODModuleDBFunc) module->parent->moduleDBFunc;
   950     if (func) {
   951 	moduleSpec = secmod_mkModuleSpec(module);
   952 	retString = (*func)(SECMOD_MODULE_DB_FUNCTION_DEL,
   953 		module->parent->libraryParams,moduleSpec);
   954 	PORT_Free(moduleSpec);
   955 	if (retString != NULL) return SECSuccess;
   956     }
   957     return SECFailure;
   958 }
   960 SECStatus
   961 SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList)
   962 {
   963     SECMODModuleDBFunc func = (SECMODModuleDBFunc) module->moduleDBFunc;
   964     char **retString;
   965     if (func) {
   966 	retString = (*func)(SECMOD_MODULE_DB_FUNCTION_RELEASE,
   967 		module->libraryParams,moduleSpecList);
   968 	if (retString != NULL) return SECSuccess;
   969     }
   970     return SECFailure;
   971 }
   973 /*
   974  * load a PKCS#11 module but do not add it to the default NSS trust domain
   975  */
   976 SECMODModule *
   977 SECMOD_LoadModule(char *modulespec,SECMODModule *parent, PRBool recurse)
   978 {
   979     char *library = NULL, *moduleName = NULL, *parameters = NULL, *nss= NULL;
   980     SECStatus status;
   981     SECMODModule *module = NULL;
   982     SECMODModule *oldModule = NULL;
   983     SECStatus rv;
   985     /* initialize the underlying module structures */
   986     SECMOD_Init();
   988     status = NSSUTIL_ArgParseModuleSpec(modulespec, &library, &moduleName, 
   989 							&parameters, &nss);
   990     if (status != SECSuccess) {
   991 	goto loser;
   992     }
   994     module = SECMOD_CreateModule(library, moduleName, parameters, nss);
   995     if (library) PORT_Free(library);
   996     if (moduleName) PORT_Free(moduleName);
   997     if (parameters) PORT_Free(parameters);
   998     if (nss) PORT_Free(nss);
   999     if (!module) {
  1000 	goto loser;
  1002     if (parent) {
  1003     	module->parent = SECMOD_ReferenceModule(parent);
  1004 	if (module->internal && secmod_IsInternalKeySlot(parent)) {
  1005 	    module->internal = parent->internal;
  1009     /* load it */
  1010     rv = secmod_LoadPKCS11Module(module, &oldModule);
  1011     if (rv != SECSuccess) {
  1012 	goto loser;
  1015     /* if we just reload an old module, no need to add it to any lists.
  1016      * we simple release all our references */
  1017     if (oldModule) {
  1018 	/* This module already exists, don't link it anywhere. This
  1019 	 * will probably destroy this module */
  1020 	SECMOD_DestroyModule(module);
  1021 	return oldModule;
  1024     if (recurse && module->isModuleDB) {
  1025 	char ** moduleSpecList;
  1026 	PORT_SetError(0);
  1028 	moduleSpecList = SECMOD_GetModuleSpecList(module);
  1029 	if (moduleSpecList) {
  1030 	    char **index;
  1032 	    index = moduleSpecList;
  1033 	    if (*index && SECMOD_GetSkipFirstFlag(module)) {
  1034 		index++;
  1037 	    for (; *index; index++) {
  1038 		SECMODModule *child;
  1039 		if (0 == PORT_Strcmp(*index, modulespec)) {
  1040 		    /* avoid trivial infinite recursion */
  1041 		    PORT_SetError(SEC_ERROR_NO_MODULE);
  1042 		    rv = SECFailure;
  1043 		    break;
  1045 		child = SECMOD_LoadModule(*index,module,PR_TRUE);
  1046 		if (!child) break;
  1047 		if (child->isCritical && !child->loaded) {
  1048 		    int err = PORT_GetError();
  1049 		    if (!err)  
  1050 			err = SEC_ERROR_NO_MODULE;
  1051 		    SECMOD_DestroyModule(child);
  1052 		    PORT_SetError(err);
  1053 		    rv = SECFailure;
  1054 		    break;
  1056 		SECMOD_DestroyModule(child);
  1058 	    SECMOD_FreeModuleSpecList(module,moduleSpecList);
  1059 	} else {
  1060 	    if (!PORT_GetError())
  1061 		PORT_SetError(SEC_ERROR_NO_MODULE);
  1062 	    rv = SECFailure;
  1066     if (rv != SECSuccess) {
  1067 	goto loser;
  1071     /* inherit the reference */
  1072     if (!module->moduleDBOnly) {
  1073 	SECMOD_AddModuleToList(module);
  1074     } else {
  1075 	SECMOD_AddModuleToDBOnlyList(module);
  1078     /* handle any additional work here */
  1079     return module;
  1081 loser:
  1082     if (module) {
  1083 	if (module->loaded) {
  1084 	    SECMOD_UnloadModule(module);
  1086 	SECMOD_AddModuleToUnloadList(module);
  1088     return module;
  1091 /*
  1092  * load a PKCS#11 module and add it to the default NSS trust domain
  1093  */
  1094 SECMODModule *
  1095 SECMOD_LoadUserModule(char *modulespec,SECMODModule *parent, PRBool recurse)
  1097     SECStatus rv = SECSuccess;
  1098     SECMODModule * newmod = SECMOD_LoadModule(modulespec, parent, recurse);
  1099     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
  1101     if (newmod) {
  1102 	SECMOD_GetReadLock(moduleLock);
  1103         rv = STAN_AddModuleToDefaultTrustDomain(newmod);
  1104 	SECMOD_ReleaseReadLock(moduleLock);
  1105         if (SECSuccess != rv) {
  1106             SECMOD_DestroyModule(newmod);
  1107             return NULL;
  1110     return newmod;
  1113 /*
  1114  * remove the PKCS#11 module from the default NSS trust domain, call
  1115  * C_Finalize, and destroy the module structure
  1116  */
  1117 SECStatus SECMOD_UnloadUserModule(SECMODModule *mod)
  1119     SECStatus rv = SECSuccess;
  1120     int atype = 0;
  1121     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
  1122     if (!mod) {
  1123         return SECFailure;
  1126     SECMOD_GetReadLock(moduleLock);
  1127     rv = STAN_RemoveModuleFromDefaultTrustDomain(mod);
  1128     SECMOD_ReleaseReadLock(moduleLock);
  1129     if (SECSuccess != rv) {
  1130         return SECFailure;
  1132     return SECMOD_DeleteModuleEx(NULL, mod, &atype, PR_FALSE);

mercurial