summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRobert Relyea <rrelyea@redhat.com>2016-10-26 17:44:33 -0700
committerRobert Relyea <rrelyea@redhat.com>2016-10-26 17:44:33 -0700
commita46d2916d1c48d176710bee9338204f59e3cc583 (patch)
treec5c01bfcde550cd1e47c5661343416e3806345b4 /lib
parent598614093c6e33f882c1a8ad820c68b482c1262b (diff)
downloadnss-hg-a46d2916d1c48d176710bee9338204f59e3cc583.tar.gz
Bug 1312141 - SECMOD_OpenUserDB will allow multiple opens of the same database.
r=mt
Diffstat (limited to 'lib')
-rw-r--r--lib/pk11wrap/pk11pars.c126
-rw-r--r--lib/pk11wrap/pk11util.c31
-rw-r--r--lib/pk11wrap/secmodi.h4
3 files changed, 152 insertions, 9 deletions
diff --git a/lib/pk11wrap/pk11pars.c b/lib/pk11wrap/pk11pars.c
index 8dd07e7e5..4c36a312a 100644
--- a/lib/pk11wrap/pk11pars.c
+++ b/lib/pk11wrap/pk11pars.c
@@ -17,6 +17,7 @@
#include "secerr.h"
#include "nss.h"
#include "utilpars.h"
+#include "pk11pub.h"
/* create a new module */
static SECMODModule *
@@ -1114,11 +1115,41 @@ secmod_matchPrefix(char *prefix1, char *prefix2)
return PR_FALSE;
}
+/* do two config paramters match? Not all callers are compariing
+ * SECMODConfigLists directly, so this function breaks them out to their
+ * components. */
+static PRBool
+secmod_matchConfig(char *configDir1, char *configDir2,
+ char *certPrefix1, char *certPrefix2,
+ char *keyPrefix1, char *keyPrefix2,
+ PRBool isReadOnly1, PRBool isReadOnly2)
+{
+ if (strcmp(configDir1,configDir2) != 0) {
+ return PR_FALSE;
+ }
+ if (!secmod_matchPrefix(certPrefix1, certPrefix2)) {
+ return PR_FALSE;
+ }
+ if (!secmod_matchPrefix(keyPrefix1, keyPrefix2)) {
+ return PR_FALSE;
+ }
+ /* these last test -- if we just need the DB open read only,
+ * than any open will suffice, but if we requested it read/write
+ * and it's only open read only, we need to open it again */
+ if (isReadOnly1) {
+ return PR_TRUE;
+ }
+ if (isReadOnly2) { /* isReadonly1 == PR_FALSE */
+ return PR_FALSE;
+ }
+ return PR_FALSE;
+}
+
/*
* return true if we are requesting a database that is already openned.
*/
PRBool
-secmod_MatchConfigList(char *spec, SECMODConfigList *conflist, int count)
+secmod_MatchConfigList(const char *spec, SECMODConfigList *conflist, int count)
{
char *config;
char *certPrefix;
@@ -1142,13 +1173,10 @@ secmod_MatchConfigList(char *spec, SECMODConfigList *conflist, int count)
isReadOnly = 1;
}
for (i=0; i < count; i++) {
- if ((strcmp(config,conflist[i].config) == 0) &&
- secmod_matchPrefix(certPrefix, conflist[i].certPrefix) &&
- secmod_matchPrefix(keyPrefix, conflist[i].keyPrefix) &&
- /* this last test -- if we just need the DB open read only,
- * than any open will suffice, but if we requested it read/write
- * and it's only open read only, we need to open it again */
- (isReadOnly || !conflist[i].isReadOnly)) {
+ if ( secmod_matchConfig(config,conflist[i].config,certPrefix,
+ conflist[i].certPrefix, keyPrefix,
+ conflist[i].keyPrefix, isReadOnly,
+ conflist[i].isReadOnly) ) {
ret = PR_TRUE;
goto done;
}
@@ -1162,6 +1190,88 @@ done:
return ret;
}
+/*
+ * Find the slot id from the module spec. If the slot is the database slot, we
+ * can get the slot id from the default database slot.
+ */
+CK_SLOT_ID
+secmod_GetSlotIDFromModuleSpec(const char *moduleSpec, SECMODModule *module)
+{
+ char *tmp_spec = NULL;;
+ char **children, **thisChild;
+ CK_SLOT_ID *ids, *thisID, slotID = -1;
+ char *inConfig = NULL, *thisConfig = NULL;
+ char *inCertPrefix, *thisCertPrefix;
+ char *inKeyPrefix, *thisKeyPrefix;
+ PRBool inReadOnly,thisReadOnly;
+
+ inConfig = secmod_getConfigDir(moduleSpec,&inCertPrefix, &inKeyPrefix,
+ &inReadOnly);
+ if (!inConfig) {
+ goto done;
+ }
+
+ if (secmod_configIsDBM(inConfig)) {
+ inReadOnly = 1;
+ }
+
+ tmp_spec = secmod_ParseModuleSpecForTokens(PR_TRUE, module->isFIPS,
+ module->libraryParams, &children, &ids);
+ if (tmp_spec == NULL) {
+ goto done;
+ }
+
+ /* first check to see if the parent is the database */
+ thisConfig = secmod_getConfigDir(tmp_spec,&thisCertPrefix, &thisKeyPrefix,
+ &thisReadOnly);
+ if (secmod_matchConfig(inConfig,thisConfig,inCertPrefix,thisCertPrefix,
+ inKeyPrefix, thisKeyPrefix, inReadOnly, thisReadOnly)) {
+ /* yup it's the default key slot, get the id for it */
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+ if (slot) {
+ slotID = slot->slotID;
+ PK11_FreeSlot(slot);
+ }
+ goto done;
+ }
+
+ /* find id of the token */
+ for (thisChild=children, thisID=ids; thisChild && *thisChild; thisChild++,
+ thisID++) {
+ thisConfig = secmod_getConfigDir(*thisChild, &thisCertPrefix,
+ &thisKeyPrefix, &thisReadOnly);
+ if (thisConfig == NULL) {
+ continue;
+ }
+ if (secmod_matchConfig(inConfig,thisConfig,inCertPrefix,thisCertPrefix,
+ inKeyPrefix, thisKeyPrefix, inReadOnly, thisReadOnly)) {
+ slotID = *thisID;
+ break;
+ }
+ PORT_Free(thisConfig);
+ PORT_Free(thisCertPrefix);
+ PORT_Free(thisKeyPrefix);
+ thisConfig = NULL;
+ }
+
+done:
+ if (inConfig) {
+ PORT_Free(inConfig);
+ PORT_Free(inCertPrefix);
+ PORT_Free(inKeyPrefix);
+ }
+ if (thisConfig) {
+ PORT_Free(thisConfig);
+ PORT_Free(thisCertPrefix);
+ PORT_Free(thisKeyPrefix);
+ }
+ if (tmp_spec) {
+ secmod_FreeChildren(children, ids);
+ PORT_Free(tmp_spec);
+ }
+ return slotID;
+}
+
void
secmod_FreeConfigList(SECMODConfigList *conflist, int count)
{
diff --git a/lib/pk11wrap/pk11util.c b/lib/pk11wrap/pk11util.c
index 712f267f1..b174363f1 100644
--- a/lib/pk11wrap/pk11util.c
+++ b/lib/pk11wrap/pk11util.c
@@ -1411,6 +1411,20 @@ SECMOD_OpenNewSlot(SECMODModule *mod, const char *moduleSpec)
}
/*
+ * given a module spec, find the slot in the module for it.
+ */
+PK11SlotInfo *
+secmod_FindSlotFromModuleSpec(const char *moduleSpec, SECMODModule *module)
+{
+ CK_SLOT_ID slot_id = secmod_GetSlotIDFromModuleSpec(moduleSpec,module);
+ if (slot_id == -1) {
+ return NULL;
+ }
+
+ return SECMOD_FindSlotByID(module, slot_id);
+}
+
+/*
* Open a new database using the softoken. The caller is responsible for making
* sure the module spec is correct and usable. The caller should ask for one
* new database per call if the caller wants to get meaningful information
@@ -1463,6 +1477,8 @@ PK11SlotInfo *
SECMOD_OpenUserDB(const char *moduleSpec)
{
SECMODModule *mod;
+ SECMODConfigList *conflist = NULL;
+ int count = 0;
if (moduleSpec == NULL) {
return NULL;
@@ -1476,6 +1492,21 @@ SECMOD_OpenUserDB(const char *moduleSpec)
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return NULL;
}
+
+ /* make sure we don't open the same database twice. We only understand
+ * the moduleSpec for internal databases well enough to do this, so only
+ * do this in OpenUserDB */
+ conflist = secmod_GetConfigList(mod->isFIPS, mod->libraryParams, &count);
+ if (conflist) {
+ PK11SlotInfo *slot = NULL;
+ if (secmod_MatchConfigList(moduleSpec, conflist, count)) {
+ slot = secmod_FindSlotFromModuleSpec(moduleSpec, mod);
+ }
+ secmod_FreeConfigList(conflist,count);
+ if (slot) {
+ return slot;
+ }
+ }
return SECMOD_OpenNewSlot(mod, moduleSpec);
}
diff --git a/lib/pk11wrap/secmodi.h b/lib/pk11wrap/secmodi.h
index 5bc49b438..4f85a491c 100644
--- a/lib/pk11wrap/secmodi.h
+++ b/lib/pk11wrap/secmodi.h
@@ -65,8 +65,10 @@ typedef struct SECMODConfigListStr SECMODConfigList;
/* collect all the databases in a given spec */
SECMODConfigList *secmod_GetConfigList(PRBool isFIPS, char *spec, int *count);
/* see is a spec matches a database on the list */
-PRBool secmod_MatchConfigList(char *spec,
+PRBool secmod_MatchConfigList(const char *spec,
SECMODConfigList *conflist, int count);
+/* returns the slot id from a module and modulespec */
+CK_SLOT_ID secmod_GetSlotIDFromModuleSpec(const char *moduleSpec, SECMODModule *module);
/* free our list of databases */
void secmod_FreeConfigList(SECMODConfigList *conflist, int count);