security/manager/ssl/tests/unit/test_cert_overrides.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 // -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2 // This Source Code Form is subject to the terms of the Mozilla Public
     3 // License, v. 2.0. If a copy of the MPL was not distributed with this
     4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 "use strict";
     7 // Tests the certificate overrides we allow.
     8 // add_cert_override_test will queue a test that does the following:
     9 // 1. Attempt to connect to the given host. This should fail with the
    10 //    given error and override bits.
    11 // 2. Add an override for that host/port/certificate/override bits.
    12 // 3. Connect again. This should succeed.
    14 do_get_profile();
    15 let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
    16                             .getService(Ci.nsICertOverrideService);
    18 function add_cert_override(aHost, aExpectedBits, aSecurityInfo) {
    19   let sslstatus = aSecurityInfo.QueryInterface(Ci.nsISSLStatusProvider)
    20                                .SSLStatus;
    21   let bits =
    22     (sslstatus.isUntrusted ? Ci.nsICertOverrideService.ERROR_UNTRUSTED : 0) |
    23     (sslstatus.isDomainMismatch ? Ci.nsICertOverrideService.ERROR_MISMATCH : 0) |
    24     (sslstatus.isNotValidAtThisTime ? Ci.nsICertOverrideService.ERROR_TIME : 0);
    25   do_check_eq(bits, aExpectedBits);
    26   let cert = sslstatus.serverCert;
    27   certOverrideService.rememberValidityOverride(aHost, 8443, cert, aExpectedBits,
    28                                                true);
    29 }
    31 function add_cert_override_test(aHost, aExpectedBits, aExpectedError) {
    32   add_connection_test(aHost, aExpectedError, null,
    33                       add_cert_override.bind(this, aHost, aExpectedBits));
    34   add_connection_test(aHost, Cr.NS_OK);
    35 }
    37 function add_non_overridable_test(aHost, aExpectedError) {
    38   add_connection_test(
    39     aHost, getXPCOMStatusFromNSS(aExpectedError), null,
    40     function (securityInfo) {
    41       // bug 754369 - no SSLStatus probably means this is a non-overridable
    42       // error, which is what we're testing (although it would be best to test
    43       // this directly).
    44       securityInfo.QueryInterface(Ci.nsISSLStatusProvider);
    45       do_check_eq(securityInfo.SSLStatus, null);
    46     });
    47 }
    49 function check_telemetry() {
    50   let histogram = Cc["@mozilla.org/base/telemetry;1"]
    51                     .getService(Ci.nsITelemetry)
    52                     .getHistogramById("SSL_CERT_ERROR_OVERRIDES")
    53                     .snapshot();
    54   do_check_eq(histogram.counts[ 0], 0);
    55   do_check_eq(histogram.counts[ 2], 8 + 1); // SEC_ERROR_UNKNOWN_ISSUER
    56   do_check_eq(histogram.counts[ 3], 2);     // SEC_ERROR_CA_CERT_INVALID
    57   do_check_eq(histogram.counts[ 4], 0 + 5); // SEC_ERROR_UNTRUSTED_ISSUER
    58   do_check_eq(histogram.counts[ 5], 0 + 1); // SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE
    59   do_check_eq(histogram.counts[ 6], 0 + 1); // SEC_ERROR_UNTRUSTED_CERT
    60   do_check_eq(histogram.counts[ 7], 0 + 1); // SEC_ERROR_INADEQUATE_KEY_USAGE
    61   do_check_eq(histogram.counts[ 8], 2 + 2); // SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
    62   do_check_eq(histogram.counts[ 9], 4 + 4); // SSL_ERROR_BAD_CERT_DOMAIN
    63   do_check_eq(histogram.counts[10], 5 + 5); // SEC_ERROR_EXPIRED_CERTIFICATE
    64   run_next_test();
    65 }
    67 function run_test() {
    68   add_tls_server_setup("BadCertServer");
    70   let fakeOCSPResponder = new HttpServer();
    71   fakeOCSPResponder.registerPrefixHandler("/", function (request, response) {
    72     response.setStatusLine(request.httpVersion, 500, "Internal Server Error");
    73   });
    74   fakeOCSPResponder.start(8080);
    76   add_tests_in_mode(true);
    77   add_tests_in_mode(false);
    79   add_test(function () {
    80     fakeOCSPResponder.stop(check_telemetry);
    81   });
    83   run_next_test();
    84 }
    86 function add_tests_in_mode(useMozillaPKIX) {
    87   add_test(function () {
    88     Services.prefs.setBoolPref("security.use_mozillapkix_verification",
    89                                useMozillaPKIX);
    90     run_next_test();
    91   });
    93   add_simple_tests(useMozillaPKIX);
    94   add_combo_tests(useMozillaPKIX);
    95   add_distrust_tests(useMozillaPKIX);
    97   add_test(function () {
    98     certOverrideService.clearValidityOverride("all:temporary-certificates", 0);
    99     run_next_test();
   100   });
   101 }
   103 function add_simple_tests(useMozillaPKIX) {
   104   add_cert_override_test("expired.example.com",
   105                          Ci.nsICertOverrideService.ERROR_TIME,
   106                          getXPCOMStatusFromNSS(SEC_ERROR_EXPIRED_CERTIFICATE));
   107   if (useMozillaPKIX) {
   108     add_cert_override_test("selfsigned.example.com",
   109                            Ci.nsICertOverrideService.ERROR_UNTRUSTED,
   110                            getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
   111   } else {
   112     add_cert_override_test("selfsigned.example.com",
   113                            Ci.nsICertOverrideService.ERROR_UNTRUSTED,
   114                            getXPCOMStatusFromNSS(SEC_ERROR_CA_CERT_INVALID));
   115   }
   116   add_cert_override_test("unknownissuer.example.com",
   117                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
   118                          getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
   119   add_cert_override_test("expiredissuer.example.com",
   120                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
   121                          getXPCOMStatusFromNSS(
   122                             useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
   123                                            : SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE));
   124   add_cert_override_test("md5signature.example.com",
   125                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
   126                          getXPCOMStatusFromNSS(
   127                             SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED));
   128   add_cert_override_test("mismatch.example.com",
   129                          Ci.nsICertOverrideService.ERROR_MISMATCH,
   130                          getXPCOMStatusFromNSS(SSL_ERROR_BAD_CERT_DOMAIN));
   132   // A Microsoft IIS utility generates self-signed certificates with
   133   // properties similar to the one this "host" will present (see
   134   // tlsserver/generate_certs.sh).
   135   // One of the errors classic verification collects is that this
   136   // certificate has an inadequate key usage to sign a certificate
   137   // (i.e. itself). As a result, to be able to override this,
   138   // SEC_ERROR_INADEQUATE_KEY_USAGE must be overridable (although,
   139   // confusingly, this isn't the main error reported).
   140   // mozilla::pkix just says this certificate's issuer is unknown.
   141   if (useMozillaPKIX) {
   142     add_cert_override_test("selfsigned-inadequateEKU.example.com",
   143                            Ci.nsICertOverrideService.ERROR_UNTRUSTED,
   144                            getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
   145   } else {
   146     add_cert_override_test("selfsigned-inadequateEKU.example.com",
   147                            Ci.nsICertOverrideService.ERROR_UNTRUSTED,
   148                            getXPCOMStatusFromNSS(SEC_ERROR_CA_CERT_INVALID));
   149   }
   151   // SEC_ERROR_INADEQUATE_KEY_USAGE is overridable in general for
   152   // classic verification, but not for mozilla::pkix verification.
   153   if (useMozillaPKIX) {
   154     add_non_overridable_test("inadequatekeyusage.example.com",
   155                              SEC_ERROR_INADEQUATE_KEY_USAGE);
   156   } else {
   157     add_cert_override_test("inadequatekeyusage.example.com",
   158                            Ci.nsICertOverrideService.ERROR_UNTRUSTED,
   159                            getXPCOMStatusFromNSS(SEC_ERROR_INADEQUATE_KEY_USAGE));
   160   }
   162   // Bug 990603: Apache documentation has recommended generating a self-signed
   163   // test certificate with basic constraints: CA:true. For compatibility, this
   164   // is a scenario in which an override is allowed.
   165   add_cert_override_test("self-signed-end-entity-with-cA-true.example.com",
   166                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
   167                          getXPCOMStatusFromNSS(
   168                             useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
   169                                            : SEC_ERROR_UNTRUSTED_ISSUER));
   170 }
   172 function add_combo_tests(useMozillaPKIX) {
   173   // Note that "untrusted" here really is "unknown issuer" in the
   174   // mozilla::pkix case.
   176   add_cert_override_test("mismatch-expired.example.com",
   177                          Ci.nsICertOverrideService.ERROR_MISMATCH |
   178                          Ci.nsICertOverrideService.ERROR_TIME,
   179                          getXPCOMStatusFromNSS(SSL_ERROR_BAD_CERT_DOMAIN));
   180   add_cert_override_test("mismatch-untrusted.example.com",
   181                          Ci.nsICertOverrideService.ERROR_MISMATCH |
   182                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
   183                          getXPCOMStatusFromNSS(
   184                             useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
   185                                            : SEC_ERROR_UNTRUSTED_ISSUER));
   186   add_cert_override_test("untrusted-expired.example.com",
   187                          Ci.nsICertOverrideService.ERROR_UNTRUSTED |
   188                          Ci.nsICertOverrideService.ERROR_TIME,
   189                          getXPCOMStatusFromNSS(
   190                             useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
   191                                            : SEC_ERROR_UNTRUSTED_ISSUER));
   192   add_cert_override_test("mismatch-untrusted-expired.example.com",
   193                          Ci.nsICertOverrideService.ERROR_MISMATCH |
   194                          Ci.nsICertOverrideService.ERROR_UNTRUSTED |
   195                          Ci.nsICertOverrideService.ERROR_TIME,
   196                          getXPCOMStatusFromNSS(
   197                             useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
   198                                            : SEC_ERROR_UNTRUSTED_ISSUER));
   200   add_cert_override_test("md5signature-expired.example.com",
   201                          Ci.nsICertOverrideService.ERROR_UNTRUSTED |
   202                          Ci.nsICertOverrideService.ERROR_TIME,
   203                          getXPCOMStatusFromNSS(
   204                             SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED));
   205 }
   207 function add_distrust_tests(useMozillaPKIX) {
   208   // Before we specifically distrust this certificate, it should be trusted.
   209   add_connection_test("untrusted.example.com", Cr.NS_OK);
   211   // XXX(Bug 975777): Active distrust is an overridable error when NSS-based
   212   // verification is used.
   213   add_distrust_override_test("tlsserver/default-ee.der",
   214                              "untrusted.example.com",
   215                              getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_CERT),
   216                              useMozillaPKIX
   217                                 ? getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_CERT)
   218                                 : Cr.NS_OK);
   220   // XXX(Bug 975777): Active distrust is an overridable error when NSS-based
   221   // verification is used.
   222   add_distrust_override_test("tlsserver/other-test-ca.der",
   223                              "untrustedissuer.example.com",
   224                              getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER),
   225                              useMozillaPKIX
   226                                 ? getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER)
   227                                 : Cr.NS_OK);
   228 }
   230 function add_distrust_override_test(certFileName, hostName,
   231                                     expectedResultBefore, expectedResultAfter) {
   232   let certToDistrust = constructCertFromFile(certFileName);
   234   add_test(function () {
   235     // Add an entry to the NSS certDB that says to distrust the cert
   236     setCertTrust(certToDistrust, "pu,,");
   237     clearSessionCache();
   238     run_next_test();
   239   });
   240   add_connection_test(hostName, expectedResultBefore, null,
   241                       function (securityInfo) {
   242                         securityInfo.QueryInterface(Ci.nsISSLStatusProvider);
   243                         // XXX(Bug 754369): SSLStatus isn't available for
   244                         // non-overridable errors.
   245                         if (securityInfo.SSLStatus) {
   246                           certOverrideService.rememberValidityOverride(
   247                               hostName, 8443, securityInfo.SSLStatus.serverCert,
   248                               Ci.nsICertOverrideService.ERROR_UNTRUSTED, true);
   249                         } else {
   250                           // A missing SSLStatus probably means (due to bug
   251                           // 754369) that the error was non-overridable, which
   252                           // is what we're trying to test, though we'd rather
   253                           // not test it this way.
   254                           do_check_neq(expectedResultAfter, Cr.NS_OK);
   255                         }
   256                         clearSessionCache();
   257                       });
   258   add_connection_test(hostName, expectedResultAfter, null,
   259                       function () {
   260                         setCertTrust(certToDistrust, "u,,");
   261                       });
   262 }

mercurial