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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/manager/ssl/tests/unit/test_pinning.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,182 @@
     1.4 +// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
     1.5 +// This Source Code Form is subject to the terms of the Mozilla Public
     1.6 +// License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 +// file, You can obtain one at http://mozilla.org/MPL/2.0/.
     1.8 +//
     1.9 +// For all cases, the acceptable pinset includes only certificates pinned to
    1.10 +// Test End Entity Cert (signed by issuer testCA). Other certificates
    1.11 +// are issued by otherCA, which is never in the pinset but is a user-specified
    1.12 +// trust anchor. This test covers multiple cases:
    1.13 +//
    1.14 +// Pinned domain include-subdomains.pinning.example.com includes subdomains
    1.15 +// - PASS: include-subdomains.pinning.example.com serves a correct cert
    1.16 +// - PASS: good.include-subdomains.pinning.example.com serves a correct cert
    1.17 +// - FAIL (strict): bad.include-subdomains.pinning.example.com serves a cert
    1.18 +// not in the pinset
    1.19 +// - PASS (mitm): bad.include-subdomains.pinning.example.com serves a cert not
    1.20 +// in the pinset, but issued by a user-specified trust domain
    1.21 +//
    1.22 +// Pinned domain exclude-subdomains.pinning.example.com excludes subdomains
    1.23 +// - PASS: exclude-subdomains.pinning.example.com serves a correct cert
    1.24 +// - FAIL: exclude-subdomains.pinning.example.com services an incorrect cert
    1.25 +// (TODO: test using verifyCertnow)
    1.26 +// - PASS: sub.exclude-subdomains.pinning.example.com serves an incorrect cert
    1.27 +
    1.28 +"use strict";
    1.29 +
    1.30 +do_get_profile(); // must be called before getting nsIX509CertDB
    1.31 +const certdb = Cc["@mozilla.org/security/x509certdb;1"]
    1.32 +                  .getService(Ci.nsIX509CertDB);
    1.33 +
    1.34 +function test_strict() {
    1.35 +  // In strict mode, we always evaluate pinning data, regardless of whether the
    1.36 +  // issuer is a built-in trust anchor. We only enforce pins that are not in
    1.37 +  // test mode.
    1.38 +  add_test(function() {
    1.39 +    Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2);
    1.40 +    run_next_test();
    1.41 +  });
    1.42 +
    1.43 +  // If a host should be pinned but other errors (particularly overridable
    1.44 +  // errors) like 'unknown issuer' are encountered, the pinning error takes
    1.45 +  // precedence. This prevents overrides for such hosts.
    1.46 +  add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
    1.47 +    getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
    1.48 +
    1.49 +  // Issued by otherCA, which is not in the pinset for pinning.example.com.
    1.50 +  add_connection_test("bad.include-subdomains.pinning.example.com",
    1.51 +    getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
    1.52 +
    1.53 +  // These domains serve certs that match the pinset.
    1.54 +  add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
    1.55 +  add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
    1.56 +  add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
    1.57 +
    1.58 +  // This domain serves a cert that doesn't match the pinset, but subdomains
    1.59 +  // are excluded.
    1.60 +  add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
    1.61 +
    1.62 +  // This domain's pinset is exactly the same as
    1.63 +  // include-subdomains.pinning.example.com, serves the same cert as
    1.64 +  // bad.include-subdomains.pinning.example.com, but it should pass because
    1.65 +  // it's in test_mode.
    1.66 +  add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
    1.67 +}
    1.68 +
    1.69 +function test_mitm() {
    1.70 +  // In MITM mode, we allow pinning to pass if the chain resolves to any
    1.71 +  // user-specified trust anchor, even if it is not in the pinset.
    1.72 +  add_test(function() {
    1.73 +    Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 1);
    1.74 +    run_next_test();
    1.75 +  });
    1.76 +
    1.77 +  add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
    1.78 +  add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
    1.79 +
    1.80 +  add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
    1.81 +    getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
    1.82 +
    1.83 +  // In this case, even though otherCA is not in the pinset, it is a
    1.84 +  // user-specified trust anchor and the pinning check succeeds.
    1.85 +  add_connection_test("bad.include-subdomains.pinning.example.com", Cr.NS_OK);
    1.86 +
    1.87 +  add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
    1.88 +  add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
    1.89 +  add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
    1.90 +};
    1.91 +
    1.92 +function test_disabled() {
    1.93 +  // Disable pinning.
    1.94 +  add_test(function() {
    1.95 +    Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 0);
    1.96 +    run_next_test();
    1.97 +  });
    1.98 +
    1.99 +  add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
   1.100 +  add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
   1.101 +  add_connection_test("bad.include-subdomains.pinning.example.com", Cr.NS_OK);
   1.102 +  add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
   1.103 +  add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
   1.104 +  add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
   1.105 +
   1.106 +  add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
   1.107 +    getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
   1.108 +}
   1.109 +
   1.110 +function test_enforce_test_mode() {
   1.111 +  // In enforce test mode, we always enforce all pins, even test pins.
   1.112 +  add_test(function() {
   1.113 +    Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 3);
   1.114 +    run_next_test();
   1.115 +  });
   1.116 +
   1.117 +  add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
   1.118 +    getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
   1.119 +
   1.120 +  // Issued by otherCA, which is not in the pinset for pinning.example.com.
   1.121 +  add_connection_test("bad.include-subdomains.pinning.example.com",
   1.122 +    getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
   1.123 +
   1.124 +  // These domains serve certs that match the pinset.
   1.125 +  add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
   1.126 +  add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
   1.127 +  add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
   1.128 +
   1.129 +  // This domain serves a cert that doesn't match the pinset, but subdomains
   1.130 +  // are excluded.
   1.131 +  add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
   1.132 +
   1.133 +  // This domain's pinset is exactly the same as
   1.134 +  // include-subdomains.pinning.example.com, serves the same cert as
   1.135 +  // bad.include-subdomains.pinning.example.com, is in test-mode, but we are
   1.136 +  // enforcing test mode pins.
   1.137 +  add_connection_test("test-mode.pinning.example.com",
   1.138 +    getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
   1.139 +}
   1.140 +
   1.141 +function check_pinning_telemetry() {
   1.142 +  let service = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
   1.143 +  let prod_histogram = service.getHistogramById("CERT_PINNING_RESULTS")
   1.144 +                         .snapshot();
   1.145 +  let test_histogram = service.getHistogramById("CERT_PINNING_TEST_RESULTS")
   1.146 +                         .snapshot();
   1.147 +  // Because all of our test domains are pinned to user-specified trust
   1.148 +  // anchors, effectively only strict mode and enforce test-mode get evaluated
   1.149 +  do_check_eq(prod_histogram.counts[0], 4); // Failure count
   1.150 +  do_check_eq(prod_histogram.counts[1], 4); // Success count
   1.151 +  do_check_eq(test_histogram.counts[0], 2); // Failure count
   1.152 +  do_check_eq(test_histogram.counts[1], 0); // Success count
   1.153 +
   1.154 +  let moz_prod_histogram = service.getHistogramById("CERT_PINNING_MOZ_RESULTS")
   1.155 +                             .snapshot();
   1.156 +  let moz_test_histogram =
   1.157 +    service.getHistogramById("CERT_PINNING_MOZ_TEST_RESULTS").snapshot();
   1.158 +  do_check_eq(moz_prod_histogram.counts[0], 0); // Failure count
   1.159 +  do_check_eq(moz_prod_histogram.counts[1], 0); // Success count
   1.160 +  do_check_eq(moz_test_histogram.counts[0], 0); // Failure count
   1.161 +  do_check_eq(moz_test_histogram.counts[1], 0); // Success count
   1.162 +
   1.163 +  let per_host_histogram =
   1.164 +    service.getHistogramById("CERT_PINNING_MOZ_RESULTS_BY_HOST").snapshot();
   1.165 +  do_check_eq(per_host_histogram.counts[0], 0); // Failure count
   1.166 +  do_check_eq(per_host_histogram.counts[1], 2); // Success count
   1.167 +  run_next_test();
   1.168 +}
   1.169 +
   1.170 +function run_test() {
   1.171 +  add_tls_server_setup("BadCertServer");
   1.172 +
   1.173 +  // Add a user-specified trust anchor.
   1.174 +  addCertFromFile(certdb, "tlsserver/other-test-ca.der", "CTu,u,u");
   1.175 +
   1.176 +  test_strict();
   1.177 +  test_mitm();
   1.178 +  test_disabled();
   1.179 +  test_enforce_test_mode();
   1.180 +
   1.181 +  add_test(function () {
   1.182 +    check_pinning_telemetry();
   1.183 +  });
   1.184 +  run_next_test();
   1.185 +}

mercurial