/security/nss/lib/pk11wrap/pk11pars.c

http://github.com/zpao/v8monkey · C · 1245 lines · 884 code · 133 blank · 228 comment · 219 complexity · 38452803650482f5d04fc273c48abbf0 MD5 · raw file

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