summaryrefslogtreecommitdiff
path: root/security/nss/lib/softoken/keydb.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/softoken/keydb.c')
-rw-r--r--security/nss/lib/softoken/keydb.c178
1 files changed, 104 insertions, 74 deletions
diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c
index f7ad1fe38..87819ff96 100644
--- a/security/nss/lib/softoken/keydb.c
+++ b/security/nss/lib/softoken/keydb.c
@@ -831,16 +831,116 @@ done:
return(SECSuccess);
}
+static SECStatus
+openNewDB(const char *appName, const char *prefix, const char *dbname,
+ NSSLOWKEYDBHandle *handle, NSSLOWKEYDBNameFunc namecb, void *cbarg)
+{
+ SECStatus rv = SECFailure;
+ char *updname = NULL;
+ DB *updatedb = NULL;
+ PRBool updated = PR_FALSE;
+ int ret;
+
+ if (appName) {
+ handle->db = rdbopen( appName, prefix, "key", NO_CREATE);
+ } else {
+ handle->db = dbopen( dbname, NO_CREATE, 0600, DB_HASH, 0 );
+ }
+ /* if create fails then we lose */
+ if ( handle->db == NULL ) {
+ return SECFailure;
+ }
+
+ rv = db_BeginTransaction(handle->db);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ /* force a transactional read, which will verify that one and only one
+ * process attempts the update. */
+ if (nsslowkey_version(updatedb) == NSSLOWKEY_DB_FILE_VERSION) {
+ /* someone else has already updated the database for us */
+ db_FinishTransaction(handle->db, PR_FALSE);
+ return SECSuccess;
+ }
+
+ /*
+ * if we are creating a multiaccess database, see if there is a
+ * local database we can update from.
+ */
+ if (appName) {
+ updatedb = dbopen( dbname, NO_RDONLY, 0600, DB_HASH, 0 );
+ if (updatedb) {
+ handle->version = nsslowkey_version(updatedb);
+ if (handle->version != NSSLOWKEY_DB_FILE_VERSION) {
+ (updatedb->close)(updatedb);
+ } else {
+ db_Copy(handle->db, updatedb);
+ (updatedb->close)(updatedb);
+ db_FinishTransaction(updatedb,PR_FALSE);
+ return SECSuccess;
+ }
+ }
+ }
+
+ /* update the version number */
+ rv = makeGlobalVersion(handle);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /*
+ * try to update from v2 db
+ */
+ updname = (*namecb)(cbarg, 2);
+ if ( updname != NULL ) {
+ handle->updatedb = dbopen( updname, NO_RDONLY, 0600, DB_HASH, 0 );
+ PORT_Free( updname );
+
+ if ( handle->updatedb ) {
+ /*
+ * Try to update the db using a null password. If the db
+ * doesn't have a password, then this will work. If it does
+ * have a password, then this will fail and we will do the
+ * update later
+ */
+ rv = nsslowkey_UpdateKeyDBPass1(handle);
+ if ( rv == SECSuccess ) {
+ updated = PR_TRUE;
+ }
+ }
+
+ }
+
+ /* we are using the old salt if we updated from an old db */
+ if ( ! updated ) {
+ rv = makeGlobalSalt(handle);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+ }
+
+ /* sync the database */
+ ret = (* handle->db->sync)(handle->db, 0);
+ if ( ret ) {
+ rv = SECFailure;
+ goto loser;
+ }
+ rv = SECSuccess;
+
+loser:
+ db_FinishTransaction(handle->db, rv != SECSuccess);
+ return rv;
+}
+
NSSLOWKEYDBHandle *
nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
NSSLOWKEYDBNameFunc namecb, void *cbarg)
{
NSSLOWKEYDBHandle *handle;
- int ret;
SECStatus rv;
int openflags;
char *dbname = NULL;
- PRBool updated = PR_FALSE;
handle = (NSSLOWKEYDBHandle *)PORT_ZAlloc (sizeof(NSSLOWKEYDBHandle));
if (handle == NULL) {
@@ -874,92 +974,22 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
/* bogus version number record, reset the database */
(* handle->db->close)( handle->db );
handle->db = NULL;
-
- goto newdb;
}
-
}
-newdb:
-
/* if first open fails, try to create a new DB */
if ( handle->db == NULL ) {
if ( readOnly ) {
goto loser;
}
- if (appName) {
- handle->db = rdbopen( appName, prefix, "key", NO_CREATE);
- handle->updatedb = dbopen( dbname, NO_RDONLY, 0600, DB_HASH, 0 );
- if (handle->updatedb) {
- handle->version = nsslowkey_version(handle->updatedb);
- if (handle->version != NSSLOWKEY_DB_FILE_VERSION) {
- (*handle->updatedb->close)(handle->updatedb);
- handle->updatedb = NULL;
- } else {
- db_Copy(handle->db, handle->updatedb);
- (*handle->updatedb->close)(handle->updatedb);
- handle->updatedb = NULL;
- goto done;
- }
- }
- } else {
- handle->db = dbopen( dbname, NO_CREATE, 0600, DB_HASH, 0 );
- }
-
- PORT_Free( dbname );
- dbname = NULL;
-
- /* if create fails then we lose */
- if ( handle->db == NULL ) {
- goto loser;
- }
-
- rv = makeGlobalVersion(handle);
- if ( rv != SECSuccess ) {
+ rv = openNewDB(appName, prefix, dbname, handle, namecb, cbarg);
+ if (rv != SECSuccess) {
goto loser;
}
- /*
- * try to update from v2 db
- */
- dbname = (*namecb)(cbarg, 2);
- if ( dbname != NULL ) {
- handle->updatedb = dbopen( dbname, NO_RDONLY, 0600, DB_HASH, 0 );
- PORT_Free( dbname );
- dbname = NULL;
-
- if ( handle->updatedb ) {
- /*
- * Try to update the db using a null password. If the db
- * doesn't have a password, then this will work. If it does
- * have a password, then this will fail and we will do the
- * update later
- */
- rv = nsslowkey_UpdateKeyDBPass1(handle);
- if ( rv == SECSuccess ) {
- updated = PR_TRUE;
- }
- }
-
- }
-
- /* we are using the old salt if we updated from an old db */
- if ( ! updated ) {
- rv = makeGlobalSalt(handle);
- if ( rv != SECSuccess ) {
- goto loser;
- }
- }
- /* sync the database */
- ret = (* handle->db->sync)(handle->db, 0);
- if ( ret ) {
- goto loser;
- }
}
-done:
-
handle->global_salt = GetKeyDBGlobalSalt(handle);
if ( dbname )
PORT_Free( dbname );