summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--security/nss/lib/softoken/cdbhdl.h8
-rw-r--r--security/nss/lib/softoken/dbinit.c35
-rw-r--r--security/nss/lib/softoken/keydb.c70
-rw-r--r--security/nss/lib/softoken/manifest.mn2
-rw-r--r--security/nss/lib/softoken/pcertdb.c59
-rw-r--r--security/nss/lib/softoken/pk11db.c17
6 files changed, 141 insertions, 50 deletions
diff --git a/security/nss/lib/softoken/cdbhdl.h b/security/nss/lib/softoken/cdbhdl.h
index 17fb6e638..8e309b208 100644
--- a/security/nss/lib/softoken/cdbhdl.h
+++ b/security/nss/lib/softoken/cdbhdl.h
@@ -63,15 +63,19 @@ struct NSSLOWCERTCertDBHandleStr {
typedef DB * (*rdbfunc)(const char *appName, const char *prefix,
const char *type, int flags);
+typedef int (*rdbstatusfunc)(void);
+
+#define RDB_FAIL 1
+#define RDB_RETRY 2
DB * rdbopen(const char *appName, const char *prefix,
- const char *type, int flags);
+ const char *type, int flags, int *status);
DB *dbsopen (const char *dbname , int flags, int mode, DBTYPE type,
const void * appData);
SECStatus db_Copy(DB *dest,DB *src);
int db_BeginTransaction(DB *db);
int db_FinishTransaction(DB *db, PRBool abort);
-
+int db_InitComplete(DB *db);
#endif
diff --git a/security/nss/lib/softoken/dbinit.c b/security/nss/lib/softoken/dbinit.c
index 40e295eaa..d230c9261 100644
--- a/security/nss/lib/softoken/dbinit.c
+++ b/security/nss/lib/softoken/dbinit.c
@@ -272,19 +272,23 @@ pk11_DBShutdown(NSSLOWCERTCertDBHandle *certHandle,
}
static int rdbmapflags(int flags);
-static rdbfunc pk11_rdbfunc;
+static rdbfunc pk11_rdbfunc = NULL;
+static rdbstatusfunc pk11_rdbstatusfunc = NULL;
/* NOTE: SHLIB_SUFFIX is defined on the command line */
-#define RDBLIB "rdb."SHLIB_SUFFIX
+#define RDBLIB SHLIB_PREFIX"rdb."SHLIB_SUFFIX
DB * rdbopen(const char *appName, const char *prefix,
- const char *type, int flags)
+ const char *type, int flags, int *status)
{
PRLibrary *lib;
DB *db;
if (pk11_rdbfunc) {
db = (*pk11_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
+ if (!db && status && pk11_rdbstatusfunc) {
+ *status = (*pk11_rdbstatusfunc)();
+ }
return db;
}
@@ -297,10 +301,14 @@ DB * rdbopen(const char *appName, const char *prefix,
return NULL;
}
- /* get the entry point */
+ /* get the entry points */
+ pk11_rdbstatusfunc = (rdbstatusfunc) PR_FindSymbol(lib,"rdbstatus");
pk11_rdbfunc = (rdbfunc) PR_FindSymbol(lib,"rdbopen");
if (pk11_rdbfunc) {
db = (*pk11_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
+ if (!db && status && pk11_rdbstatusfunc) {
+ *status = (*pk11_rdbstatusfunc)();
+ }
return db;
}
@@ -316,6 +324,8 @@ struct RDBStr {
DB db;
int (*xactstart)(DB *db);
int (*xactdone)(DB *db, PRBool abort);
+ int version;
+ int (*dbinitcomplete)(DB *db);
};
#define DB_RDB ((DBTYPE) 0xff)
@@ -367,6 +377,23 @@ db_FinishTransaction(DB *db, PRBool abort)
return rdb->xactdone(db, abort);
}
+int
+db_InitComplete(DB *db)
+{
+ struct RDBStr *rdb = (struct RDBStr *)db;
+ if (db->type != DB_RDB) {
+ return 0;
+ }
+ /* we should have addes a version number to the RDBS structure. Since we
+ * didn't, we detect that we have and 'extended' structure if the rdbstatus
+ * func exists */
+ if (!pk11_rdbstatusfunc) {
+ return 0;
+ }
+
+ return rdb->dbinitcomplete(db);
+}
+
SECStatus
diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c
index 64ae1db76..877ead2b5 100644
--- a/security/nss/lib/softoken/keydb.c
+++ b/security/nss/lib/softoken/keydb.c
@@ -830,23 +830,25 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
NSSLOWKEYDBHandle *handle, NSSLOWKEYDBNameFunc namecb, void *cbarg)
{
SECStatus rv = SECFailure;
+ int status = RDB_FAIL;
char *updname = NULL;
DB *updatedb = NULL;
PRBool updated = PR_FALSE;
int ret;
if (appName) {
- handle->db = rdbopen( appName, prefix, "key", NO_CREATE);
+ handle->db = rdbopen( appName, prefix, "key", NO_CREATE, &status);
} else {
handle->db = dbopen( dbname, NO_CREATE, 0600, DB_HASH, 0 );
}
/* if create fails then we lose */
if ( handle->db == NULL ) {
- return SECFailure;
+ return (status == RDB_RETRY) ? SECWouldBlock: SECFailure;
}
rv = db_BeginTransaction(handle->db);
if (rv != SECSuccess) {
+ db_InitComplete(handle->db);
return rv;
}
@@ -855,6 +857,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
if (nsslowkey_version(handle->db) == NSSLOWKEY_DB_FILE_VERSION) {
/* someone else has already updated the database for us */
db_FinishTransaction(handle->db, PR_FALSE);
+ db_InitComplete(handle->db);
return SECSuccess;
}
@@ -872,6 +875,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
db_Copy(handle->db, updatedb);
(updatedb->close)(updatedb);
db_FinishTransaction(handle->db,PR_FALSE);
+ db_InitComplete(handle->db);
return SECSuccess;
}
}
@@ -924,9 +928,34 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
loser:
db_FinishTransaction(handle->db, rv != SECSuccess);
+ db_InitComplete(handle->db);
return rv;
}
+
+static DB *
+openOldDB(const char *appName, const char *prefix, const char *dbname,
+ PRBool openflags, int *version) {
+ DB *db = NULL;
+
+ if (appName) {
+ db = rdbopen( appName, prefix, "key", openflags, NULL);
+ } else {
+ db = dbopen( dbname, openflags, 0600, DB_HASH, 0 );
+ }
+
+ /* check for correct version number */
+ if (db != NULL) {
+ *version = nsslowkey_version(db);
+ if (*version != NSSLOWKEY_DB_FILE_VERSION ) {
+ /* bogus version number record, reset the database */
+ (* db->close)( db );
+ db = NULL;
+ }
+ }
+ return db;
+}
+
NSSLOWKEYDBHandle *
nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
NSSLOWKEYDBNameFunc namecb, void *cbarg)
@@ -953,25 +982,14 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
handle->dbname = (appName == NULL) ? PORT_Strdup(dbname) :
(prefix ? PORT_Strdup(prefix) : NULL);
handle->readOnly = readOnly;
-
- if (appName) {
- handle->db = rdbopen( appName, prefix, "key", openflags);
- } else {
- handle->db = dbopen( dbname, openflags, 0600, DB_HASH, 0 );
- }
- /* check for correct version number */
- if (handle->db != NULL) {
- handle->version = nsslowkey_version(handle->db);
- if (handle->version == 255) {
- goto loser;
- }
- if (handle->version != NSSLOWKEY_DB_FILE_VERSION ) {
- /* bogus version number record, reset the database */
- (* handle->db->close)( handle->db );
- handle->db = NULL;
- }
+
+ handle->db = openOldDB(appName, prefix, dbname, openflags,
+ &handle->version);
+ if (handle->version == 255) {
+ goto loser;
}
+
/* if first open fails, try to create a new DB */
if ( handle->db == NULL ) {
@@ -980,7 +998,16 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
}
rv = openNewDB(appName, prefix, dbname, handle, namecb, cbarg);
- if (rv != SECSuccess) {
+ /* two processes started to initialize the database at the same time.
+ * The multiprocess code blocked the second one, then had it retry to
+ * see if it can just open the database normally */
+ if (rv == SECWouldBlock) {
+ handle->db = openOldDB(appName,prefix,dbname,
+ openflags, &handle->version);
+ if (handle->db == NULL) {
+ goto loser;
+ }
+ } else if (rv != SECSuccess) {
goto loser;
}
@@ -2453,7 +2480,8 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle)
(* handle->db->close)(handle->db);
if (handle->appname) {
- handle->db=rdbopen(handle->appname, handle->dbname, "key", NO_CREATE);
+ handle->db=
+ rdbopen(handle->appname, handle->dbname, "key", NO_CREATE, NULL);
} else {
handle->db = dbopen( handle->dbname, NO_CREATE, 0600, DB_HASH, 0 );
}
diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn
index 2d43a9db4..b362e31d0 100644
--- a/security/nss/lib/softoken/manifest.mn
+++ b/security/nss/lib/softoken/manifest.mn
@@ -40,7 +40,7 @@ LIBRARY_NAME = softokn
LIBRARY_VERSION = 3
MAPFILE = $(OBJDIR)/softokn.def
-DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\"
+DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\"
EXPORTS = \
diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c
index 496c50520..a4f947b75 100644
--- a/security/nss/lib/softoken/pcertdb.c
+++ b/security/nss/lib/softoken/pcertdb.c
@@ -3748,20 +3748,22 @@ openNewCertDB(const char *appName, const char *prefix, const char *certdbname,
certDBEntryVersion *versionEntry = NULL;
DB *updatedb = NULL;
char *tmpname;
+ int status = RDB_FAIL;
if (appName) {
- handle->permCertDB=rdbopen( appName, prefix, "cert", NO_CREATE);
+ handle->permCertDB=rdbopen( appName, prefix, "cert", NO_CREATE, &status);
} else {
handle->permCertDB=dbopen(certdbname, NO_CREATE, 0600, DB_HASH, 0);
}
/* if create fails then we lose */
if ( handle->permCertDB == 0 ) {
- return SECFailure;
+ return status == RDB_RETRY ? SECWouldBlock : SECFailure;
}
rv = db_BeginTransaction(handle->permCertDB);
if (rv != SECSuccess) {
+ db_InitComplete(handle->permCertDB);
return SECFailure;
}
@@ -3773,6 +3775,7 @@ openNewCertDB(const char *appName, const char *prefix, const char *certdbname,
db_Copy(handle->permCertDB,updatedb);
(*updatedb->close)(updatedb);
db_FinishTransaction(handle->permCertDB,PR_FALSE);
+ db_InitComplete(handle->permCertDB);
return(SECSuccess);
}
}
@@ -3829,9 +3832,26 @@ openNewCertDB(const char *appName, const char *prefix, const char *certdbname,
loser:
db_FinishTransaction(handle->permCertDB,rv != SECSuccess);
+ db_InitComplete(handle->permCertDB);
return rv;
}
+static int
+nsslowcert_GetVersionNumber(NSSLOWCERTCertDBHandle *handle)
+{
+ certDBEntryVersion *versionEntry = NULL;
+ int version = 0;
+
+ versionEntry = ReadDBVersionEntry(handle);
+ if ( versionEntry == NULL ) {
+ return 0;
+ }
+ version = versionEntry->common.version;
+ DestroyDBEntry((certDBEntry *)versionEntry);
+ return version;
+}
+
+
/*
* Open the certificate database and index databases. Create them if
* they are not there or bad.
@@ -3845,6 +3865,7 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
int openflags;
char *certdbname;
certDBEntryVersion *versionEntry = NULL;
+ int version;
certdbname = (* namecb)(cbarg, CERT_DB_FILE_VERSION);
if ( certdbname == NULL ) {
@@ -3857,27 +3878,16 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
* first open the permanent file based database.
*/
if (appName) {
- handle->permCertDB = rdbopen( appName, prefix, "cert", openflags);
+ handle->permCertDB = rdbopen( appName, prefix, "cert", openflags, NULL);
} else {
handle->permCertDB = dbopen( certdbname, openflags, 0600, DB_HASH, 0 );
}
/* check for correct version number */
if ( handle->permCertDB ) {
- versionEntry = ReadDBVersionEntry(handle);
-
- if ( versionEntry == NULL ) {
- /* no version number */
- certdb_Close(handle->permCertDB);
- handle->permCertDB = 0;
- } else if ( versionEntry->common.version != CERT_DB_FILE_VERSION ) {
- /* wrong version number, can't update in place */
- DestroyDBEntry((certDBEntry *)versionEntry);
- PORT_Free(certdbname);
- return(SECFailure);
- } else {
- DestroyDBEntry((certDBEntry *)versionEntry);
- versionEntry = NULL;
+ version = nsslowcert_GetVersionNumber(handle);
+ if (version != CERT_DB_FILE_VERSION ) {
+ goto loser;
}
}
@@ -3890,7 +3900,20 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
}
rv = openNewCertDB(appName,prefix,certdbname,handle,namecb,cbarg);
- if (rv != SECSuccess) {
+ if (rv == SECWouldBlock) {
+ /* only the rdb version can fail with wouldblock */
+ handle->permCertDB =
+ rdbopen( appName, prefix, "cert", openflags, NULL);
+
+ /* check for correct version number */
+ if ( !handle->permCertDB ) {
+ goto loser;
+ }
+ version = nsslowcert_GetVersionNumber(handle);
+ if (version != CERT_DB_FILE_VERSION ) {
+ goto loser;
+ }
+ } else if (rv != SECSuccess) {
goto loser;
}
diff --git a/security/nss/lib/softoken/pk11db.c b/security/nss/lib/softoken/pk11db.c
index 69b34dfa4..6f6583c80 100644
--- a/security/nss/lib/softoken/pk11db.c
+++ b/security/nss/lib/softoken/pk11db.c
@@ -273,7 +273,10 @@ secmod_getSecmodName(char *param, char **appName, char **filename,PRBool *rw)
if (pk11_argHasFlag("flags","readOnly",save_params) ||
pk11_argHasFlag("flags","noModDB",save_params)) *rw = PR_FALSE;
- if (!secmodName || *secmodName == '\0') secmodName = PORT_Strdup(SECMOD_DB);
+ if (!secmodName || *secmodName == '\0') {
+ if (secmodName) PORT_Free(secmodName);
+ secmodName = PORT_Strdup(SECMOD_DB);
+ }
*filename = secmodName;
lconfigdir = pk11_EvaluateConfigDir(configdir, appName);
@@ -649,18 +652,24 @@ secmod_OpenDB(const char *appName, const char *filename, const char *dbName,
if (appName) {
char *secname = PORT_Strdup(filename);
int len = strlen(secname);
+ int status = RDB_FAIL;
if (len >= 3 && PORT_Strcmp(&secname[len-3],".db") == 0) {
secname[len-3] = 0;
}
- pkcs11db=rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_CREATE);
+ pkcs11db=
+ rdbopen(appName, "", secname, readOnly ? NO_RDONLY:NO_RDWR, NULL);
if (update && !pkcs11db) {
DB *updatedb;
- pkcs11db = rdbopen(appName, "", secname, NO_CREATE);
+ pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status);
if (!pkcs11db) {
+ if (status == RDB_RETRY) {
+ pkcs11db= rdbopen(appName, "", secname,
+ readOnly ? NO_RDONLY:NO_RDWR, NULL);
+ }
PORT_Free(secname);
- return NULL;
+ return pkcs11db;
}
updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0);
if (updatedb) {