From 8bab33d84e7804b7c6de0b3b9dcc3f490a907983 Mon Sep 17 00:00:00 2001 From: "wtc%netscape.com" Date: Thu, 9 Jan 2003 02:05:15 +0000 Subject: [PATCH] Bug 186586: If at NSS shutdown there are still certs in the cert caches, cause NSS shutdown and the next NSS initialization to fail but do not destroy the cert caches (and the crypto context and trust domain containing them) to avoid a crash if the NSS client destroys the certs later. New error codes needed to be added to indicate the failure of NSS shutdown and NSS initialization due to this cause. Modified Files: Tag: NSS_3_7_BRANCH base/errorval.c nss/nssinit.c pki/cryptocontext.c pki/pki3hack.c pki/pki3hack.h pki/pkistore.c pki/pkistore.h pki/tdcache.c pki/trustdomain.c util/secerr.h git-svn-id: svn://10.0.0.236/branches/NSS_3_7_BRANCH@136046 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/security/nss/lib/base/errorval.c | 4 +++- mozilla/security/nss/lib/nss/nssinit.c | 20 ++++++++++++---- mozilla/security/nss/lib/pki/cryptocontext.c | 10 +++++--- mozilla/security/nss/lib/pki/pki3hack.c | 25 ++++++++++++++++---- mozilla/security/nss/lib/pki/pki3hack.h | 4 ++-- mozilla/security/nss/lib/pki/pkistore.c | 11 +++++++-- mozilla/security/nss/lib/pki/pkistore.h | 4 ++-- mozilla/security/nss/lib/pki/tdcache.c | 10 +++++++- mozilla/security/nss/lib/pki/trustdomain.c | 10 +++++--- mozilla/security/nss/lib/util/secerr.h | 3 ++- 10 files changed, 78 insertions(+), 23 deletions(-) diff --git a/mozilla/security/nss/lib/base/errorval.c b/mozilla/security/nss/lib/base/errorval.c index ec465a9693b..c18868c6039 100644 --- a/mozilla/security/nss/lib/base/errorval.c +++ b/mozilla/security/nss/lib/base/errorval.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: errorval.c,v $ $Revision: 1.8 $ $Date: 2002-11-21 20:42:58 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: errorval.c,v $ $Revision: 1.8.2.1 $ $Date: 2003-01-09 02:05:02 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ /* @@ -88,4 +88,6 @@ const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE = 32; const NSSError NSS_ERROR_HASH_COLLISION = 33; const NSSError NSS_ERROR_DEVICE_ERROR = 34; const NSSError NSS_ERROR_INVALID_CERTIFICATE = 35; +const NSSError NSS_ERROR_BUSY = 36; +const NSSError NSS_ERROR_ALREADY_INITIALIZED = 37; diff --git a/mozilla/security/nss/lib/nss/nssinit.c b/mozilla/security/nss/lib/nss/nssinit.c index 5662927c7be..85a7937e24a 100644 --- a/mozilla/security/nss/lib/nss/nssinit.c +++ b/mozilla/security/nss/lib/nss/nssinit.c @@ -32,7 +32,7 @@ * may use your version of this file under either the MPL or the * GPL. * - # $Id: nssinit.c,v 1.57.10.2 2002-12-18 23:46:46 wtc%netscape.com Exp $ + # $Id: nssinit.c,v 1.57.10.3 2003-01-09 02:05:04 wtc%netscape.com Exp $ */ #include @@ -49,6 +49,8 @@ #include "nss.h" #include "secrng.h" #include "pk11func.h" +#include "secerr.h" +#include "nssbase.h" #include "pki3hack.h" #include "certi.h" @@ -464,8 +466,9 @@ loser: } if (rv == SECSuccess) { - /* can this function fail?? */ - STAN_LoadDefaultNSS3TrustDomain(); + if (STAN_LoadDefaultNSS3TrustDomain() != PR_SUCCESS) { + return SECFailure; + } CERT_SetDefaultCertDB((CERTCertDBHandle *) STAN_GetDefaultTrustDomain()); #ifndef XP_MAC @@ -540,18 +543,27 @@ NSS_NoDB_Init(const char * configdir) PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE); } +extern const NSSError NSS_ERROR_BUSY; + SECStatus NSS_Shutdown(void) { SECStatus rv; + PRStatus status; ShutdownCRLCache(); SECOID_Shutdown(); - STAN_Shutdown(); + status = STAN_Shutdown(); cert_DestroySubjectKeyIDHashTable(); SECMOD_CleanupCallOnce(); rv = SECMOD_Shutdown(); pk11sdr_Shutdown(); + if (status == PR_FAILURE) { + if (NSS_GetError() == NSS_ERROR_BUSY) { + PORT_SetError(SEC_ERROR_BUSY); + } + rv = SECFailure; + } nss_IsInitted = PR_FALSE; return rv; } diff --git a/mozilla/security/nss/lib/pki/cryptocontext.c b/mozilla/security/nss/lib/pki/cryptocontext.c index 356d974b688..62174e890c5 100644 --- a/mozilla/security/nss/lib/pki/cryptocontext.c +++ b/mozilla/security/nss/lib/pki/cryptocontext.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: cryptocontext.c,v $ $Revision: 1.11 $ $Date: 2002-09-23 21:32:31 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: cryptocontext.c,v $ $Revision: 1.11.10.1 $ $Date: 2003-01-09 02:05:06 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef DEV_H @@ -89,11 +89,15 @@ NSSCryptoContext_Destroy ( NSSCryptoContext *cc ) { + PRStatus status = PR_SUCCESS; if (cc->certStore) { - nssCertificateStore_Destroy(cc->certStore); + status = nssCertificateStore_Destroy(cc->certStore); + if (status == PR_FAILURE) { + return status; + } } nssArena_Destroy(cc->arena); - return PR_SUCCESS; + return status; } NSS_IMPLEMENT PRStatus diff --git a/mozilla/security/nss/lib/pki/pki3hack.c b/mozilla/security/nss/lib/pki/pki3hack.c index 4c2637a63da..c5a8575d39e 100644 --- a/mozilla/security/nss/lib/pki/pki3hack.c +++ b/mozilla/security/nss/lib/pki/pki3hack.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.71.2.1 $ $Date: 2002-12-17 05:35:02 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.71.2.2 $ $Date: 2003-01-09 02:05:07 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ /* @@ -87,6 +87,8 @@ STAN_GetDefaultCryptoContext() return g_default_crypto_context; } +extern const NSSError NSS_ERROR_ALREADY_INITIALIZED; + NSS_IMPLEMENT PRStatus STAN_LoadDefaultNSS3TrustDomain ( void @@ -98,6 +100,11 @@ STAN_LoadDefaultNSS3TrustDomain ( SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); int i; + if (g_default_trust_domain || g_default_crypto_context) { + /* Stan is already initialized or a previous shutdown failed. */ + nss_SetError(NSS_ERROR_ALREADY_INITIALIZED); + return PR_FAILURE; + } td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL); if (!td) { return PR_FAILURE; @@ -160,15 +167,25 @@ STAN_RemoveModuleFromDefaultTrustDomain ( return SECSuccess; } -NSS_IMPLEMENT void +NSS_IMPLEMENT PRStatus STAN_Shutdown() { + PRStatus status = PR_SUCCESS; if (g_default_trust_domain) { - NSSTrustDomain_Destroy(g_default_trust_domain); + if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) { + g_default_trust_domain = NULL; + } else { + status = PR_FAILURE; + } } if (g_default_crypto_context) { - NSSCryptoContext_Destroy(g_default_crypto_context); + if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) { + g_default_crypto_context = NULL; + } else { + status = PR_FAILURE; + } } + return status; } /* this function should not be a hack; it will be needed in 4.0 (rename) */ diff --git a/mozilla/security/nss/lib/pki/pki3hack.h b/mozilla/security/nss/lib/pki/pki3hack.h index ad9acfaccab..c37657315b4 100644 --- a/mozilla/security/nss/lib/pki/pki3hack.h +++ b/mozilla/security/nss/lib/pki/pki3hack.h @@ -35,7 +35,7 @@ #define PKINSS3HACK_H #ifdef DEBUG -static const char PKINSS3HACK_CVS_ID[] = "@(#) $RCSfile: pki3hack.h,v $ $Revision: 1.12 $ $Date: 2002-06-25 22:33:37 $ $Name: not supported by cvs2svn $"; +static const char PKINSS3HACK_CVS_ID[] = "@(#) $RCSfile: pki3hack.h,v $ $Revision: 1.12.12.1 $ $Date: 2003-01-09 02:05:08 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef NSSDEVT_H @@ -72,7 +72,7 @@ STAN_LoadDefaultNSS3TrustDomain void ); -NSS_EXTERN void +NSS_EXTERN PRStatus STAN_Shutdown(); NSS_EXTERN SECStatus diff --git a/mozilla/security/nss/lib/pki/pkistore.c b/mozilla/security/nss/lib/pki/pkistore.c index 8d46c631c80..ea623712701 100644 --- a/mozilla/security/nss/lib/pki/pkistore.c +++ b/mozilla/security/nss/lib/pki/pkistore.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: pkistore.c,v $ $Revision: 1.21 $ $Date: 2002-11-06 18:53:54 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: pkistore.c,v $ $Revision: 1.21.2.1 $ $Date: 2003-01-09 02:05:09 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef PKIM_H @@ -160,11 +160,17 @@ loser: return NULL; } -NSS_IMPLEMENT void +extern const NSSError NSS_ERROR_BUSY; + +NSS_IMPLEMENT PRStatus nssCertificateStore_Destroy ( nssCertificateStore *store ) { + if (nssHash_Count(store->issuer_and_serial) > 0) { + nss_SetError(NSS_ERROR_BUSY); + return PR_FAILURE; + } PZ_DestroyLock(store->lock); nssHash_Destroy(store->issuer_and_serial); nssHash_Destroy(store->subject); @@ -173,6 +179,7 @@ nssCertificateStore_Destroy ( } else { nss_ZFreeIf(store); } + return PR_SUCCESS; } static PRStatus diff --git a/mozilla/security/nss/lib/pki/pkistore.h b/mozilla/security/nss/lib/pki/pkistore.h index 2b10dc2a8ed..85ad712d0e7 100644 --- a/mozilla/security/nss/lib/pki/pkistore.h +++ b/mozilla/security/nss/lib/pki/pkistore.h @@ -35,7 +35,7 @@ #define PKISTORE_H #ifdef DEBUG -static const char PKISTORE_CVS_ID[] = "@(#) $RCSfile: pkistore.h,v $ $Revision: 1.4 $ $Date: 2002-11-06 18:53:54 $ $Name: not supported by cvs2svn $"; +static const char PKISTORE_CVS_ID[] = "@(#) $RCSfile: pkistore.h,v $ $Revision: 1.4.2.1 $ $Date: 2003-01-09 02:05:10 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef NSSPKIT_H @@ -72,7 +72,7 @@ nssCertificateStore_Create NSSArena *arenaOpt ); -NSS_EXTERN void +NSS_EXTERN PRStatus nssCertificateStore_Destroy ( nssCertificateStore *store diff --git a/mozilla/security/nss/lib/pki/tdcache.c b/mozilla/security/nss/lib/pki/tdcache.c index dc4bcb2db91..6e7608d6f80 100644 --- a/mozilla/security/nss/lib/pki/tdcache.c +++ b/mozilla/security/nss/lib/pki/tdcache.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: tdcache.c,v $ $Revision: 1.34 $ $Date: 2002-11-06 18:53:55 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: tdcache.c,v $ $Revision: 1.34.2.1 $ $Date: 2003-01-09 02:05:10 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef PKIM_H @@ -234,12 +234,20 @@ loser: * clean shutdown, it is necessary for there to be no certs in the cache. */ +extern const NSSError NSS_ERROR_INTERNAL_ERROR; +extern const NSSError NSS_ERROR_BUSY; + NSS_IMPLEMENT PRStatus nssTrustDomain_DestroyCache ( NSSTrustDomain *td ) { if (!td->cache) { + nss_SetError(NSS_ERROR_INTERNAL_ERROR); + return PR_FAILURE; + } + if (nssHash_Count(td->cache->issuerAndSN) > 0) { + nss_SetError(NSS_ERROR_BUSY); return PR_FAILURE; } PZ_DestroyLock(td->cache->lock); diff --git a/mozilla/security/nss/lib/pki/trustdomain.c b/mozilla/security/nss/lib/pki/trustdomain.c index 2e7e91ba5f4..f0a013b6c04 100644 --- a/mozilla/security/nss/lib/pki/trustdomain.c +++ b/mozilla/security/nss/lib/pki/trustdomain.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: trustdomain.c,v $ $Revision: 1.46 $ $Date: 2002-09-23 21:32:35 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: trustdomain.c,v $ $Revision: 1.46.10.1 $ $Date: 2003-01-09 02:05:11 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef DEV_H @@ -116,6 +116,7 @@ NSSTrustDomain_Destroy ( NSSTrustDomain *td ) { + PRStatus status = PR_SUCCESS; if (--td->refCount == 0) { /* Destroy each token in the list of tokens */ if (td->tokens) { @@ -123,11 +124,14 @@ NSSTrustDomain_Destroy ( nssList_Clear(td->tokenList, token_destructor); nssList_Destroy(td->tokenList); } - nssTrustDomain_DestroyCache(td); + status = nssTrustDomain_DestroyCache(td); + if (status == PR_FAILURE) { + return status; + } /* Destroy the trust domain */ nssArena_Destroy(td->arena); } - return PR_SUCCESS; + return status; } /* XXX uses tokens until slot list is in place */ diff --git a/mozilla/security/nss/lib/util/secerr.h b/mozilla/security/nss/lib/util/secerr.h index 525ed513b06..7e139cae1dc 100644 --- a/mozilla/security/nss/lib/util/secerr.h +++ b/mozilla/security/nss/lib/util/secerr.h @@ -183,7 +183,8 @@ SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE = (SEC_ERROR_BASE + 134), SEC_ERROR_MODULE_STUCK = (SEC_ERROR_BASE + 135), SEC_ERROR_BAD_TEMPLATE = (SEC_ERROR_BASE + 136), SEC_ERROR_CRL_NOT_FOUND = (SEC_ERROR_BASE + 137), -SEC_ERROR_REUSED_ISSUER_AND_SERIAL = (SEC_ERROR_BASE + 138) +SEC_ERROR_REUSED_ISSUER_AND_SERIAL = (SEC_ERROR_BASE + 138), +SEC_ERROR_BUSY = (SEC_ERROR_BASE + 139) } SECErrorCodes; #endif /* NO_SECURITY_ERROR_ENUM */