diff options
author | relyea%netscape.com <devnull@localhost> | 2003-12-19 23:24:48 +0000 |
---|---|---|
committer | relyea%netscape.com <devnull@localhost> | 2003-12-19 23:24:48 +0000 |
commit | e1d62e340ab8e1c7755663b8ac0922fec70d4787 (patch) | |
tree | 3e6301c80ab2e9bc1c6c8e6ba2cda500cfce293a | |
parent | 908fc8c51732d07dcecff968b2ba6242f608aa58 (diff) | |
download | nss-hg-e1d62e340ab8e1c7755663b8ac0922fec70d4787.tar.gz |
Make database access to the key db thread safe.
-rw-r--r-- | security/nss/lib/softoken/keydb.c | 212 |
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; +} + |