Bug 991177: Disallow overrides for SEC_ERROR_CA_CERT_INVALID (r=keeler)
authorMonica Chew <mmc@mozilla.com>
Tue, 15 Apr 2014 15:35:41 -0700
changeset 178741 eacdbceea76d73bb6226d70f0852f7e4db7fc2fc
parent 178740 8dfc1efbb580da0ad72f1d26c056438736e47576
child 178742 a9ec9de606a8d87b48e12929e83793d1dcbc02f7
push id26595
push usercbook@mozilla.com
push dateWed, 16 Apr 2014 12:48:58 +0000
treeherdermozilla-central@f7c4e7719778 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs991177
milestone31.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 991177: Disallow overrides for SEC_ERROR_CA_CERT_INVALID (r=keeler)
dom/browser-element/BrowserElementChildPreload.js
security/manager/ssl/src/NSSErrorsService.cpp
security/manager/ssl/src/SSLServerCertVerification.cpp
security/manager/ssl/tests/unit/test_cert_overrides.js
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -79,17 +79,16 @@ let SEC_ERROR_CERT_SIGNATURE_ALGORITHM_D
 let SSL_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SSL_ERROR_BASE;
 let SSL_ERROR_BAD_CERT_DOMAIN = (SSL_ERROR_BASE + 12);
 
 function getErrorClass(errorCode) {
   let NSPRCode = -1 * NS_ERROR_GET_CODE(errorCode);
 
   switch (NSPRCode) {
     case SEC_ERROR_UNKNOWN_ISSUER:
-    case SEC_ERROR_CA_CERT_INVALID:
     case SEC_ERROR_UNTRUSTED_ISSUER:
     case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
     case SEC_ERROR_UNTRUSTED_CERT:
     case SSL_ERROR_BAD_CERT_DOMAIN:
     case SEC_ERROR_EXPIRED_CERTIFICATE:
     case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
       return Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT;
     default:
--- a/security/manager/ssl/src/NSSErrorsService.cpp
+++ b/security/manager/ssl/src/NSSErrorsService.cpp
@@ -90,26 +90,27 @@ NSSErrorsService::GetErrorClass(nsresult
   
   int32_t aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
 
   if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
     return NS_ERROR_FAILURE;
 
   switch (aNSPRCode)
   {
+    // Overridable errors.
     case SEC_ERROR_UNKNOWN_ISSUER:
-    case SEC_ERROR_CA_CERT_INVALID:
     case SEC_ERROR_UNTRUSTED_ISSUER:
     case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
     case SEC_ERROR_UNTRUSTED_CERT:
     case SSL_ERROR_BAD_CERT_DOMAIN:
     case SEC_ERROR_EXPIRED_CERTIFICATE:
     case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
       *aErrorClass = ERROR_CLASS_BAD_CERT;
       break;
+    // Non-overridable errors.
     default:
       *aErrorClass = ERROR_CLASS_SSL_PROTOCOL;
       break;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/security/manager/ssl/src/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/src/SSLServerCertVerification.cpp
@@ -294,17 +294,16 @@ private:
 
 // A probe value of 1 means "no error".
 uint32_t
 MapCertErrorToProbeValue(PRErrorCode errorCode)
 {
   switch (errorCode)
   {
     case SEC_ERROR_UNKNOWN_ISSUER:                     return  2;
-    case SEC_ERROR_CA_CERT_INVALID:                    return  3;
     case SEC_ERROR_UNTRUSTED_ISSUER:                   return  4;
     case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:         return  5;
     case SEC_ERROR_UNTRUSTED_CERT:                     return  6;
     case SEC_ERROR_INADEQUATE_KEY_USAGE:               return  7;
     case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:  return  8;
     case SSL_ERROR_BAD_CERT_DOMAIN:                    return  9;
     case SEC_ERROR_EXPIRED_CERTIFICATE:                return 10;
   }
@@ -558,17 +557,16 @@ CertErrorRunnable::RunOnTargetThread()
 // if the given error code is an overridable error.
 // If it is not, then 0 is returned.
 uint32_t
 PRErrorCodeToOverrideType(PRErrorCode errorCode)
 {
   switch (errorCode)
   {
     case SEC_ERROR_UNKNOWN_ISSUER:
-    case SEC_ERROR_CA_CERT_INVALID:
     case SEC_ERROR_UNTRUSTED_ISSUER:
     case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
     case SEC_ERROR_UNTRUSTED_CERT:
     case SEC_ERROR_INADEQUATE_KEY_USAGE:
     case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
       // We group all these errors as "cert not trusted"
       return nsICertOverrideService::ERROR_UNTRUSTED;
     case SSL_ERROR_BAD_CERT_DOMAIN:
--- a/security/manager/ssl/tests/unit/test_cert_overrides.js
+++ b/security/manager/ssl/tests/unit/test_cert_overrides.js
@@ -29,32 +29,43 @@ function add_cert_override(aHost, aExpec
 }
 
 function add_cert_override_test(aHost, aExpectedBits, aExpectedError) {
   add_connection_test(aHost, aExpectedError, null,
                       add_cert_override.bind(this, aHost, aExpectedBits));
   add_connection_test(aHost, Cr.NS_OK);
 }
 
+function add_non_overridable_test(aHost, aExpectedError) {
+  add_connection_test(
+    aHost, getXPCOMStatusFromNSS(aExpectedError), null,
+    function (securityInfo) {
+      // bug 754369 - no SSLStatus probably means this is a non-overridable
+      // error, which is what we're testing (although it would be best to test
+      // this directly).
+      securityInfo.QueryInterface(Ci.nsISSLStatusProvider);
+      do_check_eq(securityInfo.SSLStatus, null);
+    });
+}
+
 function check_telemetry() {
   let histogram = Cc["@mozilla.org/base/telemetry;1"]
                     .getService(Ci.nsITelemetry)
                     .getHistogramById("SSL_CERT_ERROR_OVERRIDES")
                     .snapshot();
   do_check_eq(histogram.counts[ 0], 0);
   do_check_eq(histogram.counts[ 2], 8 + 1); // SEC_ERROR_UNKNOWN_ISSUER
-  do_check_eq(histogram.counts[ 3], 0 + 2); // SEC_ERROR_CA_CERT_INVALID
+  do_check_eq(histogram.counts[ 3], 0);     // SEC_ERROR_CA_CERT_INVALID
   do_check_eq(histogram.counts[ 4], 0 + 5); // SEC_ERROR_UNTRUSTED_ISSUER
   do_check_eq(histogram.counts[ 5], 0 + 1); // SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE
   do_check_eq(histogram.counts[ 6], 0 + 1); // SEC_ERROR_UNTRUSTED_CERT
   do_check_eq(histogram.counts[ 7], 0 + 1); // SEC_ERROR_INADEQUATE_KEY_USAGE
   do_check_eq(histogram.counts[ 8], 2 + 2); // SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
   do_check_eq(histogram.counts[ 9], 4 + 4); // SSL_ERROR_BAD_CERT_DOMAIN
   do_check_eq(histogram.counts[10], 5 + 5); // SEC_ERROR_EXPIRED_CERTIFICATE
-
   run_next_test();
 }
 
 function run_test() {
   add_tls_server_setup("BadCertServer");
 
   let fakeOCSPResponder = new HttpServer();
   fakeOCSPResponder.registerPrefixHandler("/", function (request, response) {
@@ -88,21 +99,24 @@ function add_tests_in_mode(useMozillaPKI
     run_next_test();
   });
 }
 
 function add_simple_tests(useMozillaPKIX) {
   add_cert_override_test("expired.example.com",
                          Ci.nsICertOverrideService.ERROR_TIME,
                          getXPCOMStatusFromNSS(SEC_ERROR_EXPIRED_CERTIFICATE));
-  add_cert_override_test("selfsigned.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         getXPCOMStatusFromNSS(
-                            useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
-                                           : SEC_ERROR_CA_CERT_INVALID));
+  if (useMozillaPKIX) {
+    add_cert_override_test("selfsigned.example.com",
+                           Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                           getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
+  } else {
+    add_non_overridable_test("selfsigned.example.com",
+                             SEC_ERROR_CA_CERT_INVALID);
+  }
   add_cert_override_test("unknownissuer.example.com",
                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
                          getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
   add_cert_override_test("expiredissuer.example.com",
                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
                          getXPCOMStatusFromNSS(
                             useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
                                            : SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE));
@@ -118,35 +132,30 @@ function add_simple_tests(useMozillaPKIX
   // properties similar to the one this "host" will present (see
   // tlsserver/generate_certs.sh).
   // One of the errors classic verification collects is that this
   // certificate has an inadequate key usage to sign a certificate
   // (i.e. itself). As a result, to be able to override this,
   // SEC_ERROR_INADEQUATE_KEY_USAGE must be overridable (although,
   // confusingly, this isn't the main error reported).
   // mozilla::pkix just says this certificate's issuer is unknown.
-  add_cert_override_test("selfsigned-inadequateEKU.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         getXPCOMStatusFromNSS(
-                            useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
-                                           : SEC_ERROR_CA_CERT_INVALID));
+  if (useMozillaPKIX) {
+    add_cert_override_test("selfsigned-inadequateEKU.example.com",
+                           Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                           getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
+  } else {
+    add_non_overridable_test("selfsigned-inadequateEKU.example.com",
+                             SEC_ERROR_CA_CERT_INVALID);
+  }
 
   // SEC_ERROR_INADEQUATE_KEY_USAGE is overridable in general for
   // classic verification, but not for mozilla::pkix verification.
   if (useMozillaPKIX) {
-    add_connection_test("inadequatekeyusage.example.com",
-                        getXPCOMStatusFromNSS(SEC_ERROR_INADEQUATE_KEY_USAGE),
-                        null,
-                        function (securityInfo) {
-                          // bug 754369 - no SSLStatus probably means this is
-                          // a non-overridable error, which is what we're testing
-                          // (although it would be best to test this directly).
-                          securityInfo.QueryInterface(Ci.nsISSLStatusProvider);
-                          do_check_eq(securityInfo.SSLStatus, null);
-                        });
+    add_non_overridable_test("inadequatekeyusage.example.com",
+                             SEC_ERROR_INADEQUATE_KEY_USAGE);
   } else {
     add_cert_override_test("inadequatekeyusage.example.com",
                            Ci.nsICertOverrideService.ERROR_UNTRUSTED,
                            getXPCOMStatusFromNSS(SEC_ERROR_INADEQUATE_KEY_USAGE));
   }
 
   // Bug 990603: Apache documentation has recommended generating a self-signed
   // test certificate with basic constraints: CA:true. For compatibility, this