summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2003-12-19 23:24:48 +0000
committerrelyea%netscape.com <devnull@localhost>2003-12-19 23:24:48 +0000
commite1d62e340ab8e1c7755663b8ac0922fec70d4787 (patch)
tree3e6301c80ab2e9bc1c6c8e6ba2cda500cfce293a
parent908fc8c51732d07dcecff968b2ba6242f608aa58 (diff)
downloadnss-hg-e1d62e340ab8e1c7755663b8ac0922fec70d4787.tar.gz
Make database access to the key db thread safe.
-rw-r--r--security/nss/lib/softoken/keydb.c212
1 files changed, 169 insertions, 43 deletions
diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c
index 92ea37d25..852307a8e 100644
--- a/security/nss/lib/softoken/keydb.c
+++ b/security/nss/lib/softoken/keydb.c
@@ -163,6 +163,36 @@ free_dbt(DBT *dbt)
return;
}
+static int keydb_Get(DB *db, DBT *key, DBT *data, unsigned int flags);
+static int keydb_Put(DB *db, DBT *key, DBT *data, unsigned int flags);
+static int keydb_Sync(DB *db, unsigned int flags);
+static int keydb_Del(DB *db, DBT *key, unsigned int flags);
+static int keydb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags);
+static void keydb_Close(DB *db);
+
+static PZLock *kdbLock = NULL;
+
+static void
+keydb_InitLocks(NSSLOWKEYDBHandle *handle)
+{
+ if (kdbLock == NULL) {
+ nss_InitLock(&kdbLock, nssILockKeyDB);
+ }
+
+ return;
+}
+
+static void
+keydb_DestroyLocks(NSSLOWKEYDBHandle *handle)
+{
+ if (kdbLock != NULL) {
+ PZ_DestroyLock(kdbLock);
+ kdbLock = NULL;
+ }
+
+ return;
+}
+
/*
* format of key database entries for version 3 of database:
* byte offset field
@@ -320,7 +350,7 @@ get_dbkey(NSSLOWKEYDBHandle *handle, DBT *index)
int ret;
/* get it from the database */
- ret = (* handle->db->get)(handle->db, index, &entry, 0);
+ ret = keydb_Get(handle->db, index, &entry, 0);
if ( ret ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
return NULL;
@@ -346,10 +376,9 @@ put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool u
/* put it in the database */
if ( update ) {
- status = (* handle->db->put)(handle->db, index, keydata, 0);
+ status = keydb_Put(handle->db, index, keydata, 0);
} else {
- status = (* handle->db->put)(handle->db, index, keydata,
- R_NOOVERWRITE);
+ status = keydb_Put(handle->db, index, keydata, R_NOOVERWRITE);
}
if ( status ) {
@@ -357,7 +386,7 @@ put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool u
}
/* sync the database */
- status = (* handle->db->sync)(handle->db, 0);
+ status = keydb_Sync(handle->db, 0);
if ( status ) {
goto loser;
}
@@ -387,7 +416,7 @@ nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
return(SECFailure);
}
- ret = (* handle->db->seq)(handle->db, &key, &data, R_FIRST);
+ ret = keydb_Seq(handle->db, &key, &data, R_FIRST);
if ( ret ) {
return(SECFailure);
}
@@ -414,7 +443,7 @@ nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
return(status);
}
}
- } while ( (* handle->db->seq)(handle->db, &key, &data, R_NEXT) == 0 );
+ } while ( keydb_Seq(handle->db, &key, &data, R_NEXT) == 0 );
return(SECSuccess);
}
@@ -494,7 +523,7 @@ GetKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle)
saltKey.data = SALT_STRING;
saltKey.size = sizeof(SALT_STRING) - 1;
- ret = (* handle->db->get)(handle->db, &saltKey, &saltData, 0);
+ ret = keydb_Get(handle->db, &saltKey, &saltData, 0);
if ( ret ) {
return(NULL);
}
@@ -516,7 +545,7 @@ StoreKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle)
saltData.size = handle->global_salt->len;
/* put global salt into the database now */
- status = (* handle->db->put)( handle->db, &saltKey, &saltData, 0);
+ status = keydb_Put(handle->db, &saltKey, &saltData, 0);
if ( status ) {
return(SECFailure);
}
@@ -539,7 +568,7 @@ makeGlobalVersion(NSSLOWKEYDBHandle *handle)
versionKey.size = sizeof(VERSION_STRING)-1;
/* put version string into the database now */
- status = (* handle->db->put)(handle->db, &versionKey, &versionData, 0);
+ status = keydb_Put(handle->db, &versionKey, &versionData, 0);
if ( status ) {
return(SECFailure);
}
@@ -565,7 +594,7 @@ makeGlobalSalt(NSSLOWKEYDBHandle *handle)
RNG_GenerateGlobalRandomBytes(saltbuf, sizeof(saltbuf));
/* put global salt into the database now */
- status = (* handle->db->put)( handle->db, &saltKey, &saltData, 0);
+ status = keydb_Put(handle->db, &saltKey, &saltData, 0);
if ( status ) {
return(SECFailure);
}
@@ -605,7 +634,7 @@ nsslowkey_version(DB *db)
versionKey.size = sizeof(VERSION_STRING)-1;
/* lookup version string in database */
- ret = (* db->get)( db, &versionKey, &versionData, 0 );
+ ret = keydb_Get( db, &versionKey, &versionData, 0 );
/* error accessing the database */
if ( ret < 0 ) {
@@ -626,7 +655,7 @@ seckey_HasAServerKey(DB *db)
int ret;
PRBool found = PR_FALSE;
- ret = (* db->seq)(db, &key, &data, R_FIRST);
+ ret = keydb_Seq(db, &key, &data, R_FIRST);
if ( ret ) {
return PR_FALSE;
}
@@ -663,7 +692,7 @@ seckey_HasAServerKey(DB *db)
}
}
- } while ( (* db->seq)(db, &key, &data, R_NEXT) == 0 );
+ } while ( keydb_Seq(db, &key, &data, R_NEXT) == 0 );
return found;
}
@@ -702,7 +731,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
saltKey.data = SALT_STRING;
saltKey.size = sizeof(SALT_STRING) - 1;
- ret = (* handle->updatedb->get)(handle->updatedb, &saltKey, &saltData, 0);
+ ret = keydb_Get(handle->updatedb, &saltKey, &saltData, 0);
if ( ret ) {
/* no salt in old db, so it is corrupted */
goto done;
@@ -720,7 +749,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
checkKey.data = KEYDB_PW_CHECK_STRING;
checkKey.size = KEYDB_PW_CHECK_LEN;
- ret = (* handle->updatedb->get)(handle->updatedb, &checkKey,
+ ret = keydb_Get(handle->updatedb, &checkKey,
&checkData, 0 );
if (ret) {
/*
@@ -741,11 +770,11 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
fcheckData.data = "1";
fcheckData.size = 1;
/* put global salt into the new database now */
- ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0);
+ ret = keydb_Put( handle->db, &saltKey, &saltData, 0);
if ( ret ) {
goto done;
}
- ret = (* handle->db->put)( handle->db, &fcheckKey, &fcheckData, 0);
+ ret = keydb_Put( handle->db, &fcheckKey, &fcheckData, 0);
if ( ret ) {
goto done;
}
@@ -754,7 +783,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
}
} else {
/* put global salt into the new database now */
- ret = (* handle->db->put)( handle->db, &saltKey, &saltData, 0);
+ ret = keydb_Put( handle->db, &saltKey, &saltData, 0);
if ( ret ) {
goto done;
}
@@ -784,7 +813,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
/* now traverse the database */
- ret = (* handle->updatedb->seq)(handle->updatedb, &key, &data, R_FIRST);
+ ret = keydb_Seq(handle->updatedb, &key, &data, R_FIRST);
if ( ret ) {
goto done;
}
@@ -830,16 +859,16 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
sec_destroy_dbkey(dbkey);
}
- } while ( (* handle->updatedb->seq)(handle->updatedb, &key, &data,
+ } while ( keydb_Seq(handle->updatedb, &key, &data,
R_NEXT) == 0 );
dbkey = NULL;
done:
/* sync the database */
- ret = (* handle->db->sync)(handle->db, 0);
+ ret = keydb_Sync(handle->db, 0);
- (* handle->updatedb->close)(handle->updatedb);
+ keydb_Close(handle->updatedb);
handle->updatedb = NULL;
if ( rc4key ) {
@@ -902,10 +931,10 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
if (updatedb) {
handle->version = nsslowkey_version(updatedb);
if (handle->version != NSSLOWKEY_DB_FILE_VERSION) {
- (updatedb->close)(updatedb);
+ keydb_Close(updatedb);
} else {
db_Copy(handle->db, updatedb);
- (updatedb->close)(updatedb);
+ keydb_Close(updatedb);
db_FinishTransaction(handle->db,PR_FALSE);
db_InitComplete(handle->db);
return SECSuccess;
@@ -951,7 +980,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
}
/* sync the database */
- ret = (* handle->db->sync)(handle->db, 0);
+ ret = keydb_Sync(handle->db, 0);
if ( ret ) {
rv = SECFailure;
goto loser;
@@ -981,7 +1010,7 @@ openOldDB(const char *appName, const char *prefix, const char *dbname,
*version = nsslowkey_version(db);
if (*version != NSSLOWKEY_DB_FILE_VERSION ) {
/* bogus version number record, reset the database */
- (* db->close)( db );
+ keydb_Close( db );
db = NULL;
}
}
@@ -1015,6 +1044,8 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
(prefix ? PORT_Strdup(prefix) : NULL);
handle->readOnly = readOnly;
+ keydb_InitLocks(handle);
+
handle->db = openOldDB(appName, prefix, dbname, openflags,
&handle->version);
@@ -1042,7 +1073,6 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
} else if (rv != SECSuccess) {
goto loser;
}
-
}
handle->global_salt = GetKeyDBGlobalSalt(handle);
@@ -1057,10 +1087,10 @@ loser:
PORT_SetError(SEC_ERROR_BAD_DATABASE);
if ( handle->db ) {
- (* handle->db->close)(handle->db);
+ keydb_Close(handle->db);
}
if ( handle->updatedb ) {
- (* handle->updatedb->close)(handle->updatedb);
+ keydb_Close(handle->updatedb);
}
PORT_Free(handle);
return NULL;
@@ -1074,13 +1104,14 @@ nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle)
{
if (handle != NULL) {
if (handle->db != NULL) {
- (* handle->db->close)(handle->db);
+ keydb_Close(handle->db);
}
if (handle->dbname) PORT_Free(handle->dbname);
if (handle->appname) PORT_Free(handle->appname);
if (handle->global_salt) {
SECITEM_FreeItem(handle->global_salt,PR_TRUE);
}
+ keydb_DestroyLocks(handle);
PORT_Free(handle);
}
@@ -1114,14 +1145,14 @@ nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle, SECItem *pubkey)
namekey.size = pubkey->len;
/* delete it from the database */
- ret = (* handle->db->del)(handle->db, &namekey, 0);
+ ret = keydb_Del(handle->db, &namekey, 0);
if ( ret ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
return(SECFailure);
}
/* sync the database */
- ret = (* handle->db->sync)(handle->db, 0);
+ ret = keydb_Sync(handle->db, 0);
if ( ret ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
return(SECFailure);
@@ -1166,7 +1197,7 @@ nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id)
namekey.data = (char *)id->data;
namekey.size = id->len;
- status = (* handle->db->get)(handle->db, &namekey, &dummy, 0);
+ status = keydb_Get(handle->db, &namekey, &dummy, 0);
if ( status ) {
return PR_FALSE;
}
@@ -1224,7 +1255,7 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer
namekey.size = sizeof(buf);
}
- status = (* handle->db->get)(handle->db, &namekey, &dummy, 0);
+ status = keydb_Get(handle->db, &namekey, &dummy, 0);
/* some databases have the key stored as a signed value */
if (status) {
unsigned char *buf = (unsigned char *)PORT_Alloc(namekey.size+1);
@@ -1233,7 +1264,7 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer
buf[0] = 0;
namekey.data = buf;
namekey.size ++;
- status = (* handle->db->get)(handle->db, &namekey, &dummy, 0);
+ status = keydb_Get(handle->db, &namekey, &dummy, 0);
PORT_Free(buf);
}
}
@@ -1261,12 +1292,12 @@ nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle)
checkkey.data = KEYDB_PW_CHECK_STRING;
checkkey.size = KEYDB_PW_CHECK_LEN;
- ret = (* handle->db->get)(handle->db, &checkkey, &checkdata, 0 );
+ ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 );
if ( ret ) {
/* see if this was an updated DB first */
checkkey.data = KEYDB_FAKE_PW_CHECK_STRING;
checkkey.size = KEYDB_FAKE_PW_CHECK_LEN;
- ret = (* handle->db->get)(handle->db, &checkkey, &checkdata, 0 );
+ ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 );
if ( ret ) {
return(SECFailure);
}
@@ -2381,8 +2412,7 @@ nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem)
if ( dbkey == NULL ) {
checkkey.data = KEYDB_FAKE_PW_CHECK_STRING;
checkkey.size = KEYDB_FAKE_PW_CHECK_LEN;
- ret = (* handle->db->get)(handle->db, &checkkey,
- &checkdata, 0 );
+ ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 );
if (ret) {
goto loser;
}
@@ -2527,7 +2557,7 @@ ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
}
/* delete the old record */
- ret = (* handle->db->del)(handle->db, &node->key, 0);
+ ret = keydb_Del(handle->db, &node->key, 0);
if ( ret ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
rv = SECFailure;
@@ -2644,7 +2674,7 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle)
return SECFailure;
}
- (* handle->db->close)(handle->db);
+ keydb_Close(handle->db);
if (handle->appname) {
handle->db=
rdbopen(handle->appname, handle->dbname, "key", NO_CREATE, NULL);
@@ -2676,8 +2706,104 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle)
done:
/* sync the database */
- ret = (* handle->db->sync)(handle->db, 0);
+ ret = keydb_Sync(handle->db, 0);
db_InitComplete(handle->db);
return (errors == 0 ? SECSuccess : SECFailure);
}
+
+static int
+keydb_Get(DB *db, DBT *key, DBT *data, unsigned int flags)
+{
+ PRStatus prstat;
+ int ret;
+
+ PORT_Assert(kdbLock != NULL);
+ PZ_Lock(kdbLock);
+
+ ret = (* db->get)(db, key, data, flags);
+
+ prstat = PZ_Unlock(kdbLock);
+
+ return(ret);
+}
+
+static int
+keydb_Put(DB *db, DBT *key, DBT *data, unsigned int flags)
+{
+ PRStatus prstat;
+ int ret = 0;
+
+ PORT_Assert(kdbLock != NULL);
+ PZ_Lock(kdbLock);
+
+ ret = (* db->put)(db, key, data, flags);
+
+ prstat = PZ_Unlock(kdbLock);
+
+ return(ret);
+}
+
+static int
+keydb_Sync(DB *db, unsigned int flags)
+{
+ PRStatus prstat;
+ int ret;
+
+ PORT_Assert(kdbLock != NULL);
+ PZ_Lock(kdbLock);
+
+ ret = (* db->sync)(db, flags);
+
+ prstat = PZ_Unlock(kdbLock);
+
+ return(ret);
+}
+
+static int
+keydb_Del(DB *db, DBT *key, unsigned int flags)
+{
+ PRStatus prstat;
+ int ret;
+
+ PORT_Assert(kdbLock != NULL);
+ PZ_Lock(kdbLock);
+
+ ret = (* db->del)(db, key, flags);
+
+ prstat = PZ_Unlock(kdbLock);
+
+ return(ret);
+}
+
+static int
+keydb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags)
+{
+ PRStatus prstat;
+ int ret;
+
+ PORT_Assert(kdbLock != NULL);
+ PZ_Lock(kdbLock);
+
+ ret = (* db->seq)(db, key, data, flags);
+
+ prstat = PZ_Unlock(kdbLock);
+
+ return(ret);
+}
+
+static void
+keydb_Close(DB *db)
+{
+ PRStatus prstat;
+
+ PORT_Assert(kdbLock != NULL);
+ PZ_Lock(kdbLock);
+
+ (* db->close)(db);
+
+ prstat = PZ_Unlock(kdbLock);
+
+ return;
+}
+