bug 1341734 - remove the disableSHA1rollout addon r?jcj,felipe
MozReview-Commit-ID: 5PUT6csFK5H
deleted file mode 100644
--- a/browser/extensions/disableSHA1rollout/README.md
+++ /dev/null
@@ -1,99 +0,0 @@
-This system add-on is a follow-up to the MITM prevalence experiment. The purpose
-is to facilitate rolling out the disabling of SHA-1 in signatures on
-certificates issued by publicly-trusted roots. When installed, this add-on will
-perform a number of checks to determine if it should change the preference that
-controls the SHA-1 policy. First, this should only apply to users on the beta
-update channel. It should also only apply to users who have not otherwise
-changed the policy to always allow or always forbid SHA-1. Additionally, it
-must double-check that the user is not affected by a TLS intercepting proxy
-using a publicly-trusted root. If these checks pass, the add-on will divide the
-population into a test group and a control group (starting on a 10%/90% split).
-The test group will have the policy changed. After doing this, a telemetry
-payload is reported with the following values:
-
-* cohortName -- the name of the group this user is in:
- 1. "notSafeToDisableSHA1" if the user is behind a MITM proxy using a
- publicly-trusted root
- 2. "optedOut" if the user already set the SHA-1 policy to always allow or
- always forbid
- 3. "optedIn" if the user already set the SHA-1 policy to only allow for
- non-built-in roots
- 4. "test" if the user is in the test cohort (and SHA-1 will be disabled)
- 5. "control" if the user is not in the test cohort
-* errorCode -- 0 for successful connections, some PR error code otherwise
-* error -- a short description of one of four error conditions encountered, if
- applicable, and an empty string otherwise:
- 1. "timeout" if the connection to telemetry.mozilla.org timed out
- 2. "user override" if the user has stored a permanent certificate exception
- override for telemetry.mozilla.org (due to technical limitations, we can't
- gather much information in this situation)
- 3. "certificate reverification" if re-building the certificate chain after
- connecting failed for some reason (unfortunately this step is necessary
- due to technical limitations)
- 4. "connection error" if the connection to telemetry.mozilla.org failed for
- another reason
-* chain -- a list of dictionaries each corresponding to a certificate in the
- verified certificate chain, if it was successfully constructed. The first
- entry is the end-entity certificate. The last entry is the root certificate.
- This will be empty if the connection failed or if reverification failed. Each
- element in the list contains the following values:
- * sha256Fingerprint -- a hex string representing the SHA-256 hash of the
- certificate
- * isBuiltInRoot -- true if the certificate is a trust anchor in the web PKI,
- false otherwise
- * signatureAlgorithm -- a description of the algorithm used to sign the
- certificate. Will be one of "md2WithRSAEncryption", "md5WithRSAEncryption",
- "sha1WithRSAEncryption", "sha256WithRSAEncryption",
- "sha384WithRSAEncryption", "sha512WithRSAEncryption", "ecdsaWithSHA1",
- "ecdsaWithSHA224", "ecdsaWithSHA256", "ecdsaWithSHA384", "ecdsaWithSHA512",
- or "unknown".
-* disabledSHA1 -- true if SHA-1 was disabled, false otherwise
-* didNotDisableSHA1Because -- a short string describing why SHA-1 could not be
- disabled, if applicable. Reasons are limited to:
- 1. "MITM" if the user is behind a TLS intercepting proxy using a
- publicly-trusted root
- 2. "connection error" if there was an error connecting to
- telemetry.mozilla.org
- 3. "code error" if some inconsistent state was detected, and it was
- determined that the experiment should not attempt to change the
- preference
- 4. "preference:userReset" if the user reset the SHA-1 policy after it had
- been changed by this add-on
- 5. "preference:allow" if the user had already configured Firefox to always
- accept SHA-1 signatures
- 6. "preference:forbid" if the user had already configured Firefox to always
- forbid SHA-1 signatures
-
-For a connection not intercepted by a TLS proxy and where the user is in the
-test cohort, the expected result will be:
-
- { "cohortName": "test",
- "errorCode": 0,
- "error": "",
- "chain": [
- { "sha256Fingerprint": "197feaf3faa0f0ad637a89c97cb91336bfc114b6b3018203cbd9c3d10c7fa86c",
- "isBuiltInRoot": false,
- "signatureAlgorithm": "sha256WithRSAEncryption"
- },
- { "sha256Fingerprint": "154c433c491929c5ef686e838e323664a00e6a0d822ccc958fb4dab03e49a08f",
- "isBuiltInRoot": false,
- "signatureAlgorithm": "sha256WithRSAEncryption"
- },
- { "sha256Fingerprint": "4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161",
- "isBuiltInRoot": true,
- "signatureAlgorithm": "sha1WithRSAEncryption"
- }
- ],
- "disabledSHA1": true,
- "didNotDisableSHA1Because": ""
- }
-
-When this result is encountered, the user's preferences are updated to disable
-SHA-1 in signatures on certificates issued by publicly-trusted roots.
-Similarly, if the user is behind a TLS intercepting proxy but the root
-certificate is not part of the public web PKI, we can also disable SHA-1 in
-signatures on certificates issued by publicly-trusted roots.
-
-If the user has already indicated in their preferences that they will always
-accept SHA-1 in signatures or that they will never accept SHA-1 in signatures,
-then the preference is not changed.
deleted file mode 100644
--- a/browser/extensions/disableSHA1rollout/bootstrap.js
+++ /dev/null
@@ -1,306 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-Cu.import("resource://gre/modules/Preferences.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/UpdateUtils.jsm");
-Cu.import("resource://gre/modules/TelemetryController.jsm");
-
- // Percentage of the population to attempt to disable SHA-1 for, by channel.
-const TEST_THRESHOLD = {
- beta: 0.1, // 10%
-};
-
-const PREF_COHORT_SAMPLE = "disableSHA1.rollout.cohortSample";
-const PREF_COHORT_NAME = "disableSHA1.rollout.cohort";
-const PREF_SHA1_POLICY = "security.pki.sha1_enforcement_level";
-const PREF_SHA1_POLICY_SET_BY_ADDON = "disableSHA1.rollout.policySetByAddOn";
-const PREF_SHA1_POLICY_RESET_BY_USER = "disableSHA1.rollout.userResetPref";
-
-const SHA1_MODE_ALLOW = 0;
-const SHA1_MODE_FORBID = 1;
-const SHA1_MODE_IMPORTED_ROOTS_ONLY = 3;
-const SHA1_MODE_CURRENT_DEFAULT = 4;
-
-function startup() {
- Preferences.observe(PREF_SHA1_POLICY, policyPreferenceChanged);
-}
-
-function install() {
- let updateChannel = UpdateUtils.getUpdateChannel(false);
- if (updateChannel in TEST_THRESHOLD) {
- makeRequest().then(defineCohort).catch((e) => console.error(e));
- }
-}
-
-function policyPreferenceChanged() {
- let currentPrefValue = Preferences.get(PREF_SHA1_POLICY,
- SHA1_MODE_CURRENT_DEFAULT);
- Preferences.reset(PREF_SHA1_POLICY_RESET_BY_USER);
- if (currentPrefValue == SHA1_MODE_CURRENT_DEFAULT) {
- Preferences.set(PREF_SHA1_POLICY_RESET_BY_USER, true);
- }
-}
-
-function defineCohort(result) {
- let userOptedOut = optedOut();
- let userOptedIn = optedIn();
- let shouldNotDisableSHA1Because = reasonToNotDisableSHA1(result);
- let safeToDisableSHA1 = shouldNotDisableSHA1Because.length == 0;
- let updateChannel = UpdateUtils.getUpdateChannel(false);
- let testGroup = getUserSample() < TEST_THRESHOLD[updateChannel];
-
- let cohortName;
- if (!safeToDisableSHA1) {
- cohortName = "notSafeToDisableSHA1";
- } else if (userOptedOut) {
- cohortName = "optedOut";
- } else if (userOptedIn) {
- cohortName = "optedIn";
- } else if (testGroup) {
- cohortName = "test";
- Preferences.ignore(PREF_SHA1_POLICY, policyPreferenceChanged);
- Preferences.set(PREF_SHA1_POLICY, SHA1_MODE_IMPORTED_ROOTS_ONLY);
- Preferences.observe(PREF_SHA1_POLICY, policyPreferenceChanged);
- Preferences.set(PREF_SHA1_POLICY_SET_BY_ADDON, true);
- } else {
- cohortName = "control";
- }
- Preferences.set(PREF_COHORT_NAME, cohortName);
- reportTelemetry(result, cohortName, shouldNotDisableSHA1Because,
- cohortName == "test");
-}
-
-function shutdown(data, reason) {
- Preferences.ignore(PREF_SHA1_POLICY, policyPreferenceChanged);
-}
-
-function uninstall() {
-}
-
-function getUserSample() {
- let prefValue = Preferences.get(PREF_COHORT_SAMPLE, undefined);
- let value = 0.0;
-
- if (typeof(prefValue) == "string") {
- value = parseFloat(prefValue, 10);
- return value;
- }
-
- value = Math.random();
-
- Preferences.set(PREF_COHORT_SAMPLE, value.toString().substr(0, 8));
- return value;
-}
-
-function reportTelemetry(result, cohortName, didNotDisableSHA1Because,
- disabledSHA1) {
- result.cohortName = cohortName;
- result.disabledSHA1 = disabledSHA1;
- if (cohortName == "optedOut") {
- let userResetPref = Preferences.get(PREF_SHA1_POLICY_RESET_BY_USER, false);
- let currentPrefValue = Preferences.get(PREF_SHA1_POLICY,
- SHA1_MODE_CURRENT_DEFAULT);
- if (userResetPref) {
- didNotDisableSHA1Because = "preference:userReset";
- } else if (currentPrefValue == SHA1_MODE_ALLOW) {
- didNotDisableSHA1Because = "preference:allow";
- } else {
- didNotDisableSHA1Because = "preference:forbid";
- }
- }
- result.didNotDisableSHA1Because = didNotDisableSHA1Because;
- return TelemetryController.submitExternalPing("disableSHA1rollout", result,
- {});
-}
-
-function optedIn() {
- let policySetByAddOn = Preferences.get(PREF_SHA1_POLICY_SET_BY_ADDON, false);
- let currentPrefValue = Preferences.get(PREF_SHA1_POLICY,
- SHA1_MODE_CURRENT_DEFAULT);
- return currentPrefValue == SHA1_MODE_IMPORTED_ROOTS_ONLY && !policySetByAddOn;
-}
-
-function optedOut() {
- // Users can also opt-out by setting the policy to always allow or always
- // forbid SHA-1, or by resetting the preference after this add-on has changed
- // it (in that case, this will be reported the next time this add-on is
- // updated).
- let currentPrefValue = Preferences.get(PREF_SHA1_POLICY,
- SHA1_MODE_CURRENT_DEFAULT);
- let userResetPref = Preferences.get(PREF_SHA1_POLICY_RESET_BY_USER, false);
- return currentPrefValue == SHA1_MODE_ALLOW ||
- currentPrefValue == SHA1_MODE_FORBID ||
- userResetPref;
-}
-
-function delocalizeAlgorithm(localizedString) {
- let bundle = Services.strings.createBundle(
- "chrome://pipnss/locale/pipnss.properties");
- let algorithmStringIdsToOIDDescriptionMap = {
- "CertDumpMD2WithRSA": "md2WithRSAEncryption",
- "CertDumpMD5WithRSA": "md5WithRSAEncryption",
- "CertDumpSHA1WithRSA": "sha1WithRSAEncryption",
- "CertDumpSHA256WithRSA": "sha256WithRSAEncryption",
- "CertDumpSHA384WithRSA": "sha384WithRSAEncryption",
- "CertDumpSHA512WithRSA": "sha512WithRSAEncryption",
- "CertDumpAnsiX962ECDsaSignatureWithSha1": "ecdsaWithSHA1",
- "CertDumpAnsiX962ECDsaSignatureWithSha224": "ecdsaWithSHA224",
- "CertDumpAnsiX962ECDsaSignatureWithSha256": "ecdsaWithSHA256",
- "CertDumpAnsiX962ECDsaSignatureWithSha384": "ecdsaWithSHA384",
- "CertDumpAnsiX962ECDsaSignatureWithSha512": "ecdsaWithSHA512",
- };
-
- let description;
- Object.keys(algorithmStringIdsToOIDDescriptionMap).forEach((l10nID) => {
- let candidateLocalizedString = bundle.GetStringFromName(l10nID);
- if (localizedString == candidateLocalizedString) {
- description = algorithmStringIdsToOIDDescriptionMap[l10nID];
- }
- });
- if (!description) {
- return "unknown";
- }
- return description;
-}
-
-function getSignatureAlgorithm(cert) {
- // Certificate ::= SEQUENCE {
- // tbsCertificate TBSCertificate,
- // signatureAlgorithm AlgorithmIdentifier,
- // signatureValue BIT STRING }
- let certificate = cert.ASN1Structure.QueryInterface(Ci.nsIASN1Sequence);
- let signatureAlgorithm = certificate.ASN1Objects
- .queryElementAt(1, Ci.nsIASN1Sequence);
- // AlgorithmIdentifier ::= SEQUENCE {
- // algorithm OBJECT IDENTIFIER,
- // parameters ANY DEFINED BY algorithm OPTIONAL }
-
- // If parameters is NULL (or empty), signatureAlgorithm won't be a container
- // under this implementation. Just get its displayValue.
- if (!signatureAlgorithm.isValidContainer) {
- return signatureAlgorithm.displayValue;
- }
- let oid = signatureAlgorithm.ASN1Objects.queryElementAt(0, Ci.nsIASN1Object);
- return oid.displayValue;
-}
-
-function processCertChain(chain) {
- let output = [];
- let enumerator = chain.getEnumerator();
- while (enumerator.hasMoreElements()) {
- let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
- output.push({
- sha256Fingerprint: cert.sha256Fingerprint.replace(/:/g, "").toLowerCase(),
- isBuiltInRoot: cert.isBuiltInRoot,
- signatureAlgorithm: delocalizeAlgorithm(getSignatureAlgorithm(cert)),
- });
- }
- return output;
-}
-
-class CertificateVerificationResult {
- constructor(resolve) {
- this.resolve = resolve;
- }
-
- verifyCertFinished(aPRErrorCode, aVerifiedChain, aEVStatus) {
- let result = { errorCode: aPRErrorCode, error: "", chain: [] };
- if (aPRErrorCode == 0) {
- result.chain = processCertChain(aVerifiedChain);
- } else {
- result.error = "certificate reverification";
- }
- this.resolve(result);
- }
-}
-
-function makeRequest() {
- return new Promise((resolve) => {
- let hostname = "telemetry.mozilla.org";
- let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
- .createInstance(Ci.nsIXMLHttpRequest);
- req.open("GET", "https://" + hostname);
- req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
- req.timeout = 30000;
- req.addEventListener("error", (evt) => {
- // If we can't connect to telemetry.mozilla.org, then how did we even
- // download the experiment? In any case, we may still be able to get some
- // information.
- let result = { error: "connection error" };
- if (evt.target.channel && evt.target.channel.securityInfo) {
- let securityInfo = evt.target.channel.securityInfo
- .QueryInterface(Ci.nsITransportSecurityInfo);
- if (securityInfo) {
- result.errorCode = securityInfo.errorCode;
- }
- if (securityInfo && securityInfo.failedCertChain) {
- result.chain = processCertChain(securityInfo.failedCertChain);
- }
- }
- resolve(result);
- });
- req.addEventListener("timeout", (evt) => {
- resolve({ error: "timeout" });
- });
- req.addEventListener("load", (evt) => {
- let securityInfo = evt.target.channel.securityInfo
- .QueryInterface(Ci.nsITransportSecurityInfo);
- if (securityInfo.securityState &
- Ci.nsIWebProgressListener.STATE_CERT_USER_OVERRIDDEN) {
- resolve({ error: "user override" });
- return;
- }
- let sslStatus = securityInfo.QueryInterface(Ci.nsISSLStatusProvider)
- .SSLStatus;
- let certdb = Cc["@mozilla.org/security/x509certdb;1"]
- .getService(Ci.nsIX509CertDB);
- let result = new CertificateVerificationResult(resolve);
- // Unfortunately, we don't have direct access to the verified certificate
- // chain as built by the AuthCertificate hook, so we have to re-build it
- // here. In theory we are likely to get the same result.
- certdb.asyncVerifyCertAtTime(sslStatus.serverCert,
- 2, // certificateUsageSSLServer
- 0, // flags
- hostname,
- Date.now() / 1000,
- result);
- });
- req.send();
- });
-}
-
-// As best we know, it is safe to disable SHA1 if the connection was successful
-// and either the connection was MITM'd by a root not in the public PKI or the
-// chain is part of the public PKI and is the one served by the real
-// telemetry.mozilla.org.
-// This will return a short string description of why it might not be safe to
-// disable SHA1 or an empty string if it is safe to disable SHA1.
-function reasonToNotDisableSHA1(result) {
- if (!("errorCode" in result) || result.errorCode != 0) {
- return "connection error";
- }
- if (!("chain" in result)) {
- return "code error";
- }
- if (!result.chain[result.chain.length - 1].isBuiltInRoot) {
- return "";
- }
- if (result.chain.length != 3) {
- return "MITM";
- }
- const kEndEntityFingerprint = "197feaf3faa0f0ad637a89c97cb91336bfc114b6b3018203cbd9c3d10c7fa86c";
- const kIntermediateFingerprint = "154c433c491929c5ef686e838e323664a00e6a0d822ccc958fb4dab03e49a08f";
- const kRootFingerprint = "4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161";
- if (result.chain[0].sha256Fingerprint != kEndEntityFingerprint ||
- result.chain[1].sha256Fingerprint != kIntermediateFingerprint ||
- result.chain[2].sha256Fingerprint != kRootFingerprint) {
- return "MITM";
- }
- return "";
-}
deleted file mode 100644
--- a/browser/extensions/disableSHA1rollout/install.rdf.in
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-#filter substitution
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
- <Description about="urn:mozilla:install-manifest">
- <em:id>disableSHA1rollout@mozilla.org</em:id>
- <em:version>1.0</em:version>
- <em:type>2</em:type>
- <em:bootstrap>true</em:bootstrap>
- <em:multiprocessCompatible>true</em:multiprocessCompatible>
-
- <!-- Target Application this theme can install into,
- with minimum and maximum supported versions. -->
- <em:targetApplication>
- <Description>
- <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
- <em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
- <em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
- </Description>
- </em:targetApplication>
-
- <!-- Front End MetaData -->
- <em:name>SHA-1 deprecation staged rollout</em:name>
- <em:description>Staged rollout deprecating SHA-1 in certificate signatures.</em:description>
- </Description>
-</RDF>
deleted file mode 100644
--- a/browser/extensions/disableSHA1rollout/moz.build
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
-DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION']
-
-FINAL_TARGET_FILES.features['disableSHA1rollout@mozilla.org'] += [
- 'bootstrap.js'
-]
-
-FINAL_TARGET_PP_FILES.features['disableSHA1rollout@mozilla.org'] += [
- 'install.rdf.in'
-]
--- a/browser/extensions/moz.build
+++ b/browser/extensions/moz.build
@@ -1,17 +1,16 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += [
'aushelper',
- 'disableSHA1rollout',
'e10srollout',
'pdfjs',
'pocket',
'webcompat',
'shield-recipe-client',
]
# Only include the following system add-ons if building Aurora or Nightly
--- a/testing/talos/talos/xtalos/xperf_whitelist.json
+++ b/testing/talos/talos/xtalos/xperf_whitelist.json
@@ -2,17 +2,16 @@
"C:\\$Mft": {"ignore": true},
"C:\\$Extend\\$UsnJrnl:$J": {"ignore": true},
"C:\\Windows\\Prefetch\\{prefetch}.pf": {"ignore": true},
"C:\\$Secure": {"ignore": true},
"C:\\$logfile": {"ignore": true},
"{firefox}\\omni.ja": {"mincount": 0, "maxcount": 46, "minbytes": 0, "maxbytes": 3014656},
"{firefox}\\browser\\omni.ja": {"mincount": 0, "maxcount": 28, "minbytes": 0, "maxbytes": 1835008},
"{firefox}\\browser\\features\\aushelper@mozilla.org.xpi": {"mincount": 0, "maxcount": 100, "minbytes": 0, "maxbytes": 10000000},
- "{firefox}\\browser\\features\\disableSHA1rollout@mozilla.org.xpi": {"mincount": 0, "maxcount": 100, "minbytes": 0, "maxbytes": 10000000},
"{firefox}\\browser\\features\\e10srollout@mozilla.org.xpi": {"mincount": 0, "maxcount": 100, "minbytes": 0, "maxbytes": 10000000},
"{firefox}\\browser\\features\\flyweb@mozilla.org.xpi": {"mincount": 0, "maxcount": 100, "minbytes": 0, "maxbytes": 10000000},
"{firefox}\\browser\\features\\formautofill@mozilla.org.xpi": {"mincount": 0, "maxcount": 100, "minbytes": 0, "maxbytes": 10000000},
"{firefox}\\browser\\features\\loop@mozilla.org.xpi": {"mincount": 0, "maxcount": 100, "minbytes": 0, "maxbytes": 10000000},
"{firefox}\\browser\\features\\firefox@getpocket.com.xpi": {"mincount": 0, "maxcount": 100, "minbytes": 0, "maxbytes": 10000000},
"{firefox}\\browser\\features\\presentation@mozilla.org.xpi": {"mincount": 0, "maxcount": 100, "minbytes": 0, "maxbytes": 10000000},
"{firefox}\\browser\\features\\webcompat@mozilla.org.xpi": {"mincount": 0, "maxcount": 100, "minbytes": 0, "maxbytes": 10000000},
"{firefox}\\browser\\features\\webcompat-reporter@mozilla.org.xpi": {"mincount": 0, "maxcount": 100, "minbytes": 0, "maxbytes": 10000000},