From b48c49ffe45b9759c5bc7a7f12811aaaeaeec763 Mon Sep 17 00:00:00 2001 From: "nelsonb%netscape.com" Date: Fri, 8 Dec 2000 03:35:29 +0000 Subject: [PATCH] Change NewTempCertificate(), making the search for the cert and the subsequent insertion of the cert into the DB into one atomic operation by holding the certdb's lock around the pair of operations. Bug 62286. --- security/nss/lib/certdb/pcertdb.c | 53 ++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/security/nss/lib/certdb/pcertdb.c b/security/nss/lib/certdb/pcertdb.c index 3080855a4249..183b146ec32f 100644 --- a/security/nss/lib/certdb/pcertdb.c +++ b/security/nss/lib/certdb/pcertdb.c @@ -34,7 +34,7 @@ /* * Permanent Certificate database handling code * - * $Id: pcertdb.c,v 1.4 2000/10/02 23:23:50 wtc%netscape.com Exp $ + * $Id: pcertdb.c,v 1.5 2000/12/08 03:35:29 nelsonb%netscape.com Exp $ */ #include "prtime.h" @@ -57,6 +57,10 @@ #include "cdbhdl.h" +/* forward declaration */ +CERTCertificate * +CERT_FindCertByDERCertNoLocking(CERTCertDBHandle *handle, SECItem *derCert); + /* * the following functions are wrappers for the db library that implement * a global lock to make the database thread safe. @@ -4966,20 +4970,20 @@ NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, char *nickname, PRArenaPool *arena = NULL; SECItem keyitem; SECStatus rv; - + + if ( lockdb ) { + CERT_LockDB(handle); + } + if ( isperm == PR_FALSE ) { - cert = CERT_FindCertByDERCert(handle, derCert); + cert = CERT_FindCertByDERCertNoLocking(handle, derCert); if ( cert ) { - return(cert); + goto winner; } nickname = NULL; } - if ( lockdb ) { - CERT_LockDB(handle); - } - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( arena == NULL ) { goto loser; @@ -5047,6 +5051,8 @@ NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, char *nickname, PORT_FreeArena(arena, PR_FALSE); +winner: + if ( lockdb ) { CERT_UnlockDB(handle); } @@ -5475,6 +5481,37 @@ loser: return(cert); } +/* + * look for the given DER certificate in the database + */ +CERTCertificate * +CERT_FindCertByDERCertNoLocking(CERTCertDBHandle *handle, SECItem *derCert) +{ + PRArenaPool *arena; + SECItem certKey; + SECStatus rv; + CERTCertificate *cert = NULL; + + /* create a scratch arena */ + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + return(NULL); + } + + /* extract the database key from the cert */ + rv = CERT_KeyFromDERCert(arena, derCert, &certKey); + if ( rv != SECSuccess ) { + goto loser; + } + + /* find the certificate */ + cert = CERT_FindCertByKeyNoLocking(handle, &certKey); + +loser: + PORT_FreeArena(arena, PR_FALSE); + return(cert); +} + /* * The following is bunch of types and code to allow looking up a certificate * by a hash of its subject public key. Because the words "hash" and "key"