diff options
Diffstat (limited to 'security/nss/lib/softoken/keydb.c')
-rw-r--r-- | security/nss/lib/softoken/keydb.c | 178 |
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 ); |