Skip to content

Commit

Permalink
Bug 1312141 - SECMOD_OpenUserDB will allow multiple opens of the same…
Browse files Browse the repository at this point in the history
… database.

r=mt
  • Loading branch information
rjrelyea committed Oct 27, 2016
1 parent 8c15b9e commit be382f2
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 9 deletions.
126 changes: 118 additions & 8 deletions lib/pk11wrap/pk11pars.c
Expand Up @@ -17,6 +17,7 @@
#include "secerr.h"
#include "nss.h"
#include "utilpars.h"
#include "pk11pub.h"

/* create a new module */
static SECMODModule *
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -1162,6 +1190,88 @@ secmod_MatchConfigList(char *spec, SECMODConfigList *conflist, int count)
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)
{
Expand Down
31 changes: 31 additions & 0 deletions lib/pk11wrap/pk11util.c
Expand Up @@ -1410,6 +1410,20 @@ SECMOD_OpenNewSlot(SECMODModule *mod, const char *moduleSpec)
return slot;
}

/*
* 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
Expand Down Expand Up @@ -1463,6 +1477,8 @@ PK11SlotInfo *
SECMOD_OpenUserDB(const char *moduleSpec)
{
SECMODModule *mod;
SECMODConfigList *conflist = NULL;
int count = 0;

if (moduleSpec == NULL) {
return NULL;
Expand All @@ -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);
}

Expand Down
4 changes: 3 additions & 1 deletion lib/pk11wrap/secmodi.h
Expand Up @@ -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);

Expand Down

0 comments on commit be382f2

Please sign in to comment.