From: Kaie Engert <kaie@kuix.de>
Date: Thu, 17 Mar 2011 14:40:13 -0700
Subject: Bug 642395 - change to handling of bad certificates. r=rrelyea, bsmith. a=sayrer

---
 security/manager/ssl/src/nsNSSCallbacks.cpp |   60 ++++++++++++++++++++++++++-
 1 files changed, 59 insertions(+), 1 deletions(-)

diff --git a/security/manager/ssl/src/nsNSSCallbacks.cpp b/security/manager/ssl/src/nsNSSCallbacks.cpp
index b2dc52e..64402df 100644
--- a/security/manager/ssl/src/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/src/nsNSSCallbacks.cpp
@@ -75,6 +75,7 @@
 #include "cert.h"
 #include "ocsp.h"
 #include "nssb64.h"
+#include "secerr.h"
 
 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
 NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
@@ -978,10 +979,68 @@ void PR_CALLBACK HandshakeCallback(PRFileDesc* fd, void* client_data) {
   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);
 
@@ -989,7 +1048,6 @@ SECStatus PR_CALLBACK AuthCertificateCallback(void* client_data, PRFileDesc* fd,
   // 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) {
