Bug 642395 - change to handling of bad certificates. r=rrelyea, bsmith. a=sayrer. OK for CLOSED TREE.
authorKai Engert <kaie@kuix.de>
Thu, 17 Mar 2011 14:47:39 -0700
changeset 63335 3d4c3670c0bd147dc61ff4d75d8ef8147a46c104
parent 63334 eb31089fb7d935a21ccef26ef6ed4d24906c79b7
child 63336 821cf4ad060ea3120b33940a0aaff3ccb7edcba2
child 63341 afbc0b4fd6180acdf0d977a5cff4f22a14d57d45
push id8
push userrsayre@mozilla.com
push dateThu, 17 Mar 2011 21:49:12 +0000
reviewersrrelyea, bsmith, sayrer
bugs642395
milestone2.0pre
Bug 642395 - change to handling of bad certificates. r=rrelyea, bsmith. a=sayrer. OK for CLOSED TREE.
security/manager/ssl/src/nsNSSCallbacks.cpp
--- a/security/manager/ssl/src/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/src/nsNSSCallbacks.cpp
@@ -70,16 +70,17 @@
 #include "nsIPrompt.h"
 #include "nsProxyRelease.h"
 #include "nsIConsoleService.h"
 
 #include "ssl.h"
 #include "cert.h"
 #include "ocsp.h"
 #include "nssb64.h"
+#include "secerr.h"
 
 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
 NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gPIPNSSLog;
 #endif
 
@@ -980,28 +981,85 @@ void PR_CALLBACK HandshakeCallback(PRFil
     status->mCipherName.Assign(cipherName);
   }
 
   PORT_Free(cipherName);
   PR_FREEIF(certOrgName);
   PR_Free(signer);
 }
 
+struct nsSerialBinaryBlacklistEntry
+{
+  unsigned int len;
+  const char *binary_serial;
+};
+
+// bug 642395
+static struct nsSerialBinaryBlacklistEntry myUTNBlacklistEntries[] = {
+  { 17, "\x00\x92\x39\xd5\x34\x8f\x40\xd1\x69\x5a\x74\x54\x70\xe1\xf2\x3f\x43" },
+  { 17, "\x00\xd8\xf3\x5f\x4e\xb7\x87\x2b\x2d\xab\x06\x92\xe3\x15\x38\x2f\xb0" },
+  { 16, "\x72\x03\x21\x05\xc5\x0c\x08\x57\x3d\x8e\xa5\x30\x4e\xfe\xe8\xb0" },
+  { 17, "\x00\xb0\xb7\x13\x3e\xd0\x96\xf9\xb5\x6f\xae\x91\xc8\x74\xbd\x3a\xc0" },
+  { 17, "\x00\xe9\x02\x8b\x95\x78\xe4\x15\xdc\x1a\x71\x0a\x2b\x88\x15\x44\x47" },
+  { 17, "\x00\xd7\x55\x8f\xda\xf5\xf1\x10\x5b\xb2\x13\x28\x2b\x70\x77\x29\xa3" },
+  { 16, "\x04\x7e\xcb\xe9\xfc\xa5\x5f\x7b\xd0\x9e\xae\x36\xe1\x0c\xae\x1e" },
+  { 17, "\x00\xf5\xc8\x6a\xf3\x61\x62\xf1\x3a\x64\xf5\x4f\x6d\xc9\x58\x7c\x06" },
+  { 0, 0 } // end marker
+};
+
 SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd,
                                               PRBool checksig, PRBool isServer) {
   nsNSSShutDownPreventionLock locker;
 
+  CERTCertificate *serverCert = SSL_PeerCertificate(fd);
+  if (serverCert && 
+      serverCert->serialNumber.data &&
+      !strcmp(serverCert->issuerName, 
+        "CN=UTN-USERFirst-Hardware,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US")) {
+
+    unsigned char *server_cert_comparison_start = (unsigned char*)serverCert->serialNumber.data;
+    unsigned int server_cert_comparison_len = serverCert->serialNumber.len;
+
+    while (server_cert_comparison_len) {
+      if (*server_cert_comparison_start != 0)
+        break;
+
+      ++server_cert_comparison_start;
+      --server_cert_comparison_len;
+    }
+
+    nsSerialBinaryBlacklistEntry *walk = myUTNBlacklistEntries;
+    for ( ; walk && walk->len; ++walk) {
+
+      unsigned char *locked_cert_comparison_start = (unsigned char*)walk->binary_serial;
+      unsigned int locked_cert_comparison_len = walk->len;
+      
+      while (locked_cert_comparison_len) {
+        if (*locked_cert_comparison_start != 0)
+          break;
+        
+        ++locked_cert_comparison_start;
+        --locked_cert_comparison_len;
+      }
+
+      if (server_cert_comparison_len == locked_cert_comparison_len &&
+          !memcmp(server_cert_comparison_start, locked_cert_comparison_start, locked_cert_comparison_len)) {
+        PR_SetError(SEC_ERROR_REVOKED_CERTIFICATE, 0);
+        return SECFailure;
+      }
+    }
+  }
+  
   // first the default action
   SECStatus rv = SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
 
   // We want to remember the CA certs in the temp db, so that the application can find the
   // complete chain at any time it might need it.
   // But we keep only those CA certs in the temp db, that we didn't already know.
   
-  CERTCertificate *serverCert = SSL_PeerCertificate(fd);
   CERTCertificateCleaner serverCertCleaner(serverCert);
 
   if (serverCert) {
     nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
     nsRefPtr<nsSSLStatus> status = infoObject->SSLStatus();
     nsRefPtr<nsNSSCertificate> nsc;
 
     if (!status || !status->mServerCert) {