/* 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, results: Cr} = Components; Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); this.EXPORTED_SYMBOLS = ["cert"]; const registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); const sss = Cc["@mozilla.org/ssservice;1"] .getService(Ci.nsISiteSecurityService); const CONTRACT_ID = "@mozilla.org/security/certoverride;1"; const CERT_PINNING_ENFORCEMENT_PREF = "security.cert_pinning.enforcement_level"; const HSTS_PRELOAD_LIST_PREF = "network.stricttransportsecurity.preloadlist"; /** TLS certificate service override management for Marionette. */ this.cert = { Error: { Untrusted: 1, Mismatch: 2, Time: 4, }, currentOverride: null, }; /** * Installs a TLS certificate service override. * * The provided |service| must implement the |register| and |unregister| * functions that causes a new |nsICertOverrideService| interface * implementation to be registered with the |nsIComponentRegistrar|. * * After |service| is registered and made the |cert.currentOverride|, * |nsICertOverrideService| is reinitialised to cause all Gecko components * to pick up the new service. * * If an override is already installed, i.e. when |cert.currentOverride| * is not null, this functions acts as a NOOP. * * @param {cert.Override} service * Service generator that registers and unregisters the XPCOM service. * * @throws {Components.Exception} * If unable to register or initialise |service|. */ cert.installOverride = function (service) { if (this.currentOverride) { return; } service.register(); cert.currentOverride = service; }; /** * Uninstall a TLS certificate service override. * * After the service has been unregistered, |cert.currentOverride| * is reset to null. * * If there no current override installed, i.e. if |cert.currentOverride| * is null, this function acts as a NOOP. */ cert.uninstallOverride = function() { if (!cert.currentOverride) { return; } cert.currentOverride.unregister(); this.currentOverride = null; }; /** * Certificate override service that acts in an all-inclusive manner * on TLS certificates. * * When an invalid certificate is encountered, it is overriden * with the |matching| bit level, which is typically a combination of * |cert.Error.Untrusted|, |cert.Error.Mismatch|, and |cert.Error.Time|. * * @type cert.Override * * @throws {Components.Exception} * If there are any problems registering the service. */ cert.InsecureSweepingOverride = function() { const CID = Components.ID("{4b67cce0-a51c-11e6-9598-0800200c9a66}"); const DESC = "All-encompassing cert service that matches on a bitflag"; // This needs to be an old-style class with a function constructor // and prototype assignment because... XPCOM. Any attempt at // modernisation will be met with cryptic error messages which will // make your life miserable. let service = function() {}; service.prototype = { hasMatchingOverride: function ( aHostName, aPort, aCert, aOverrideBits, aIsTemporary) { aIsTemporary.value = false; aOverrideBits.value = cert.Error.Untrusted | cert.Error.Mismatch | cert.Error.Time; return true; }, QueryInterface: XPCOMUtils.generateQI([Ci.nsICertOverrideService]), }; let factory = XPCOMUtils.generateSingletonFactory(service); return { register: function() { // make it possible to register certificate overrides for domains // that use HSTS or HPKP Preferences.set(HSTS_PRELOAD_LIST_PREF, false); Preferences.set(CERT_PINNING_ENFORCEMENT_PREF, 0); registrar.registerFactory(CID, DESC, CONTRACT_ID, factory); }, unregister: function() { registrar.unregisterFactory(CID, factory); Preferences.reset(HSTS_PRELOAD_LIST_PREF); Preferences.reset(CERT_PINNING_ENFORCEMENT_PREF); // clear collected HSTS and HPKP state // through the site security service sss.clearAll(); }, }; };