Add transactions to the database update portion of the code.

This commit is contained in:
relyea%netscape.com 2002-06-13 23:25:37 +00:00
parent 9e6b49ed4f
commit d31340924d
2 changed files with 203 additions and 161 deletions

View File

@ -32,7 +32,7 @@
*
* Private Key Database code
*
* $Id: keydb.c,v 1.20 2002/06/01 00:37:00 rangansen%netscape.com Exp $
* $Id: keydb.c,v 1.21 2002/06/13 23:25:37 relyea%netscape.com Exp $
*/
#include "lowkeyi.h"
@ -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 ) {
rv = openNewDB(appName, prefix, dbname, handle, namecb, cbarg);
if (rv != SECSuccess) {
goto loser;
}
rv = makeGlobalVersion(handle);
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 );

View File

@ -34,7 +34,7 @@
/*
* Permanent Certificate database handling code
*
* $Id: pcertdb.c,v 1.20 2002/05/21 21:26:14 relyea%netscape.com Exp $
* $Id: pcertdb.c,v 1.21 2002/06/13 23:25:37 relyea%netscape.com Exp $
*/
#include "prtime.h"
@ -3565,6 +3565,100 @@ nsslowcert_CertNicknameConflict(char *nickname, SECItem *derSubject,
#define NO_CREATE (O_RDWR | O_CREAT | O_TRUNC)
#endif
static SECStatus
openNewCertDB(const char *appName, const char *prefix, const char *certdbname,
NSSLOWCERTCertDBHandle *handle, NSSLOWCERTDBNameFunc namecb, void *cbarg)
{
SECStatus rv;
certDBEntryVersion *versionEntry = NULL;
DB *updatedb = NULL;
char *tmpname;
PRBool updated = PR_FALSE;
PRBool forceUpdate = PR_FALSE;
if (appName) {
handle->permCertDB=rdbopen( appName, prefix, "cert", NO_CREATE);
} else {
handle->permCertDB=dbopen(certdbname, NO_CREATE, 0600, DB_HASH, 0);
}
/* if create fails then we lose */
if ( handle->permCertDB == 0 ) {
return SECFailure;
}
rv = db_BeginTransaction(handle->permCertDB);
if (rv != SECSuccess) {
return SECFailure;
}
/* Verify version number; */
if (appName) {
updatedb = dbopen(certdbname, NO_RDONLY, 0600, DB_HASH, 0);
if (updatedb) {
db_Copy(handle->permCertDB,updatedb);
(*updatedb->close)(updatedb);
db_FinishTransaction(handle->permCertDB,PR_FALSE);
return(SECSuccess);
}
}
versionEntry = NewDBVersionEntry(0);
if ( versionEntry == NULL ) {
rv = SECFailure;
goto loser;
}
rv = WriteDBVersionEntry(handle, versionEntry);
DestroyDBEntry((certDBEntry *)versionEntry);
if ( rv != SECSuccess ) {
goto loser;
}
/* try to upgrade old db here */
tmpname = (* namecb)(cbarg, 6); /* get v6 db name */
rv = SECSuccess;
if ( tmpname ) {
updatedb = dbopen( tmpname, NO_RDONLY, 0600, DB_HASH, 0 );
PORT_Free(tmpname);
if ( updatedb ) {
rv = UpdateV6DB(handle, updatedb);
} else { /* no v6 db, so try v5 db */
tmpname = (* namecb)(cbarg, 5); /* get v5 db name */
if ( tmpname ) {
updatedb = dbopen( tmpname, NO_RDONLY, 0600, DB_HASH, 0 );
PORT_Free(tmpname);
if ( updatedb ) {
rv = UpdateV5DB(handle, updatedb);
} else { /* no v5 db, so try v4 db */
/* try to upgrade v4 db */
tmpname = (* namecb)(cbarg, 4); /* get v4 db name */
if ( tmpname ) {
updatedb = dbopen( tmpname, NO_RDONLY, 0600,
DB_HASH, 0 );
PORT_Free(tmpname);
if ( updatedb ) {
/* NES has v5 db's with v4 db names! */
if (isV4DB(updatedb)) {
rv = UpdateV4DB(handle, updatedb);
} else {
rv = UpdateV5DB(handle, updatedb);
}
}
}
}
}
}
}
loser:
db_FinishTransaction(handle->permCertDB,rv != SECSuccess);
return rv;
}
/*
* Open the certificate database and index databases. Create them if
* they are not there or bad.
@ -3576,12 +3670,8 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
{
SECStatus rv;
int openflags;
certDBEntryVersion *versionEntry = NULL;
DB *updatedb = NULL;
char *tmpname;
char *certdbname;
PRBool updated = PR_FALSE;
PRBool forceUpdate = PR_FALSE;
certDBEntryVersion *versionEntry = NULL;
certdbname = (* namecb)(cbarg, CERT_DB_FILE_VERSION);
if ( certdbname == NULL ) {
@ -3625,90 +3715,12 @@ nsslowcert_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
if ( readOnly ) {
goto loser;
}
if (appName) {
handle->permCertDB=rdbopen( appName, prefix, "cert", NO_CREATE);
updatedb = dbopen(certdbname, NO_RDONLY, 0600, DB_HASH, 0);
if (updatedb) {
db_Copy(handle->permCertDB,updatedb);
(*updatedb->close)(updatedb);
PORT_Free(certdbname);
return(SECSuccess);
}
} else {
handle->permCertDB=dbopen(certdbname, NO_CREATE, 0600, DB_HASH, 0);
}
/* if create fails then we lose */
if ( handle->permCertDB == 0 ) {
rv = openNewCertDB(appName,prefix,certdbname,handle,namecb,cbarg);
if (rv != SECSuccess) {
goto loser;
}
versionEntry = NewDBVersionEntry(0);
if ( versionEntry == NULL ) {
goto loser;
}
rv = WriteDBVersionEntry(handle, versionEntry);
DestroyDBEntry((certDBEntry *)versionEntry);
if ( rv != SECSuccess ) {
goto loser;
}
/* try to upgrade old db here */
tmpname = (* namecb)(cbarg, 6); /* get v6 db name */
if ( tmpname ) {
updatedb = dbopen( tmpname, NO_RDONLY, 0600, DB_HASH, 0 );
PORT_Free(tmpname);
if ( updatedb ) {
rv = UpdateV6DB(handle, updatedb);
if ( rv != SECSuccess ) {
goto loser;
}
updated = PR_TRUE;
} else { /* no v6 db, so try v5 db */
tmpname = (* namecb)(cbarg, 5); /* get v5 db name */
if ( tmpname ) {
updatedb = dbopen( tmpname, NO_RDONLY, 0600, DB_HASH, 0 );
PORT_Free(tmpname);
if ( updatedb ) {
rv = UpdateV5DB(handle, updatedb);
if ( rv != SECSuccess ) {
goto loser;
}
updated = PR_TRUE;
} else { /* no v5 db, so try v4 db */
/* try to upgrade v4 db */
tmpname = (* namecb)(cbarg, 4); /* get v4 db name */
if ( tmpname ) {
updatedb = dbopen( tmpname, NO_RDONLY, 0600,
DB_HASH, 0 );
PORT_Free(tmpname);
if ( updatedb ) {
/* NES has v5 db's with v4 db names! */
if (isV4DB(updatedb)) {
rv = UpdateV4DB(handle, updatedb);
} else {
rv = UpdateV5DB(handle, updatedb);
}
if ( rv != SECSuccess ) {
goto loser;
}
forceUpdate = PR_TRUE;
updated = PR_TRUE;
}
}
}
}
}
}
/* Root certs are no longer automatically added to the DB. They
* come from and external PKCS #11 file.
*/
}
PORT_Free(certdbname);