Bug 921684 - SQL backend does not reload certificates, a=rrelyea,r=rsleevi
authorElio Maldonado <emaldona@redhat.com>
Tue, 03 Feb 2015 09:16:32 -0800
changeset 11360 ac277ab60e8fd2dec952bc139c15b631c089d558
parent 11359 775ef86566051a52f2ef0c272956c21d3e871d8d
child 11361 10c82beac9148ffb064d927e0e65df1ffe14b01c
push id562
push useremaldona@redhat.com
push dateTue, 03 Feb 2015 17:17:10 +0000
reviewersrrelyea, rsleevi
bugs921684
Bug 921684 - SQL backend does not reload certificates, a=rrelyea,r=rsleevi
lib/certdb/certi.h
lib/certdb/crl.c
--- a/lib/certdb/certi.h
+++ b/lib/certdb/certi.h
@@ -111,21 +111,26 @@ struct CachedCrlStr {
 */
 
 struct CRLDPCacheStr {
 #ifdef DPC_RWLOCK
     NSSRWLock* lock;
 #else
     PRLock* lock;
 #endif
-    CERTCertificate* issuer;    /* issuer cert
-                                   XXX there may be multiple issuer certs,
-                                       with different validity dates. Also
-                                       need to deal with SKID/AKID . See
-                                       bugzilla 217387, 233118 */
+    SECItem *issuerDERCert;    /* issuer DER cert. Don't hold a reference
+				  to the actual cert so the trust can be
+				  updated on the cert automatically.
+				  XXX there may be multiple issuer certs,
+				  with different validity dates. Also
+				  need to deal with SKID/AKID . See
+				  bugzilla 217387, 233118 */
+
+    CERTCertDBHandle *dbHandle;
+
     SECItem* subject;           /* DER of issuer subject */
     SECItem* distributionPoint; /* DER of distribution point. This may be
                                    NULL when distribution points aren't
                                    in use (ie. the CA has a single CRL).
                                    Currently not used. */
 
     /* array of full CRLs matching this distribution point */
     PRUint32 ncrls;              /* total number of CRLs in crls */
@@ -160,25 +165,16 @@ struct CRLDPCacheStr {
     XCRL once we support multiple issuing distribution points, this object
     will be a hash table. For now, it just holds the single CRL distribution
     point cache structure.
 */
 
 struct CRLIssuerCacheStr {
     SECItem* subject;           /* DER of issuer subject */
     CRLDPCache* dpp;
-#if 0
-    /* XCRL for future use.
-       We don't need to lock at the moment because we only have one DP,
-       which gets created at the same time as this object */
-    NSSRWLock* lock;
-    CRLDPCache** dps;
-    PLHashTable* distributionpoints;
-    CERTCertificate* issuer;
-#endif
 };
 
 /*  CRL revocation cache object
     This object tracks all the issuer caches
 */
 
 struct CRLCacheStr {
 #ifdef GLOBAL_RWLOCK
--- a/lib/certdb/crl.c
+++ b/lib/certdb/crl.c
@@ -1118,19 +1118,19 @@ static SECStatus DPCache_Destroy(CRLDPCa
         }
     }
     /* free the array of CRLs */
     if (cache->crls)
     {
 	PORT_Free(cache->crls);
     }
     /* destroy the cert */
-    if (cache->issuer)
+    if (cache->issuerDERCert)
     {
-        CERT_DestroyCertificate(cache->issuer);
+        SECITEM_FreeItem(cache->issuerDERCert, PR_TRUE);
     }
     /* free the subject */
     if (cache->subject)
     {
         SECITEM_FreeItem(cache->subject, PR_TRUE);
     }
     /* free the distribution points */
     if (cache->distributionPoint)
@@ -1566,24 +1566,30 @@ static SECStatus CachedCrl_Verify(CRLDPC
         crlobject->sigChecked = PR_TRUE; /* we can never verify a CRL
             with bogus DER. Mark it checked so we won't try again */
         PORT_SetError(SEC_ERROR_BAD_DER);
         return SECSuccess;
     }
     else
     {
         SECStatus signstatus = SECFailure;
-        if (cache->issuer)
+        if (cache->issuerDERCert)
         {
-            signstatus = CERT_VerifyCRL(crlobject->crl, cache->issuer, vfdate,
+	    CERTCertificate *issuer = CERT_NewTempCertificate(cache->dbHandle,
+		cache->issuerDERCert, NULL, PR_FALSE, PR_TRUE);
+
+	    if (issuer) {
+                signstatus = CERT_VerifyCRL(crlobject->crl, issuer, vfdate,
                                         wincx);
+		CERT_DestroyCertificate(issuer);
+	    }
         }
         if (SECSuccess != signstatus)
         {
-            if (!cache->issuer)
+            if (!cache->issuerDERCert)
             {
                 /* we tried to verify without an issuer cert . This is
                    because this CRL came through a call to SEC_FindCrlByName.
                    So, we don't cache this verification failure. We'll try
                    to verify the CRL again when a certificate from that issuer
                    becomes available */
             } else
             {
@@ -1920,36 +1926,37 @@ static SECStatus DPCache_GetUpToDate(CRL
         {
             cache->lastcheck = PR_Now();
             DPCache_UnlockWrite();
             mustunlock = PR_FALSE;
         }
     }
 
     /* add issuer certificate if it was previously unavailable */
-    if (issuer && (NULL == cache->issuer) &&
+    if (issuer && (NULL == cache->issuerDERCert) &&
         (SECSuccess == CERT_CheckCertUsage(issuer, KU_CRL_SIGN)))
     {
         /* if we didn't have a valid issuer cert yet, but we do now. add it */
         DPCache_LockWrite();
-        if (!cache->issuer)
+        if (!cache->issuerDERCert)
         {
             dirty = PR_TRUE;
-            cache->issuer = CERT_DupCertificate(issuer);    
+	    cache->dbHandle = issuer->dbhandle;
+    	    cache->issuerDERCert = SECITEM_DupItem(&issuer->derCert);
         }
         DPCache_UnlockWrite();
     }
 
     /* verify CRLs that couldn't be checked when inserted into the cache
        because the issuer cert or a verification date was unavailable.
        These are CRLs that were inserted into the cache through
        SEC_FindCrlByName, or through manual insertion, rather than through a
        certificate verification (CERT_CheckCRL) */
 
-    if (cache->issuer && vfdate )
+    if (cache->issuerDERCert && vfdate )
     {
 	mustunlock = PR_FALSE;
         /* re-process all unverified CRLs */
         for (i = 0; i < cache->ncrls ; i++)
         {
             CachedCrl* savcrl = cache->crls[i];
             if (!savcrl)
             {
@@ -2196,17 +2203,18 @@ static SECStatus DPCache_Create(CRLDPCac
 #endif
     if (!cache->lock)
     {
 	PORT_Free(cache);
         return SECFailure;
     }
     if (issuer)
     {
-        cache->issuer = CERT_DupCertificate(issuer);
+	cache->dbHandle = issuer->dbhandle;
+    	cache->issuerDERCert = SECITEM_DupItem(&issuer->derCert);
     }
     cache->distributionPoint = SECITEM_DupItem(dp);
     cache->subject = SECITEM_DupItem(subject);
     cache->lastfetch = 0;
     cache->lastcheck = 0;
     *returned = cache;
     return SECSuccess;
 }