summaryrefslogtreecommitdiffstats
path: root/toolkit/modules
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 02:40:47 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 02:40:47 +0000
commit46db793222dee55d0b846c6ba99a39e2d969c52a (patch)
treed95f8ea0fb9c9c4eb9ae55c70faa2bc02a7bcea4 /toolkit/modules
parentAdding upstream version 115.9.1esr. (diff)
downloadfirefox-esr-upstream/115.10.0esr.tar.xz
firefox-esr-upstream/115.10.0esr.zip
Adding upstream version 115.10.0esr.upstream/115.10.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/modules')
-rw-r--r--toolkit/modules/GMPInstallManager.sys.mjs48
-rw-r--r--toolkit/modules/GMPUtils.sys.mjs1
-rw-r--r--toolkit/modules/tests/xpcshell/test_GMPInstallManager.js54
3 files changed, 100 insertions, 3 deletions
diff --git a/toolkit/modules/GMPInstallManager.sys.mjs b/toolkit/modules/GMPInstallManager.sys.mjs
index 9cb4802e58..421a843c71 100644
--- a/toolkit/modules/GMPInstallManager.sys.mjs
+++ b/toolkit/modules/GMPInstallManager.sys.mjs
@@ -43,6 +43,16 @@ const LOCAL_GMP_SOURCES = [
},
];
+function getLocalSources() {
+ if (GMPPrefs.getBool(GMPPrefs.KEY_ALLOW_LOCAL_SOURCES, true)) {
+ return LOCAL_GMP_SOURCES;
+ }
+
+ let log = getScopedLogger("GMPInstallManager.downloadLocalConfig");
+ log.info("ignoring local sources");
+ return [];
+}
+
function downloadJSON(uri) {
let log = getScopedLogger("GMPInstallManager.checkForAddons");
log.info("fetching config from: " + uri);
@@ -70,7 +80,7 @@ function downloadJSON(uri) {
function downloadLocalConfig() {
let log = getScopedLogger("GMPInstallManager.downloadLocalConfig");
return Promise.all(
- LOCAL_GMP_SOURCES.map(conf => {
+ getLocalSources().map(conf => {
return downloadJSON(conf.src).then(addons => {
let platforms = addons.vendors[conf.id].platforms;
let target = Services.appinfo.OS + "_" + lazy.UpdateUtils.ABI;
@@ -146,6 +156,36 @@ GMPInstallManager.prototype = {
},
/**
+ * Determines the root to use for verifying content signatures.
+ * @param url
+ * The Balrog URL, i.e. the return value of _getURL().
+ */
+ _getContentSignatureRootForURL(url) {
+ // The prod and stage URLs of Balrog are documented at:
+ // https://mozilla-balrog.readthedocs.io/en/latest/infrastructure.html
+ // Note: we are matching by prefix without the full domain nor slash, to
+ // enable us to move to a different host name in the future if desired.
+ if (url.startsWith("https://aus")) {
+ return Ci.nsIContentSignatureVerifier.ContentSignatureProdRoot;
+ }
+ if (url.startsWith("https://stage.")) {
+ return Ci.nsIContentSignatureVerifier.ContentSignatureStageRoot;
+ }
+ if (Services.env.exists("XPCSHELL_TEST_PROFILE_DIR")) {
+ return Ci.nsIX509CertDB.AppXPCShellRoot;
+ }
+ // When content signature verification for GMP was added (bug 1714621), a
+ // pref existed to configure an arbitrary root, which enabled local testing.
+ // This pref was removed later in bug 1769669, and replaced with hard-coded
+ // roots (prod and tests only). Support for testing against the stage server
+ // was restored in bug 1771992.
+ // Note: other verifiers ultimately fall back to ContentSignatureLocalRoot,
+ // to support local development. Here we use ContentSignatureProdRoot to
+ // minimize risk (and the unclear demand for "local" development).
+ return Ci.nsIContentSignatureVerifier.ContentSignatureProdRoot;
+ },
+
+ /**
* Records telemetry results on if fetching update.xml from Balrog succeeded
* when content signature was used to verify the response from Balrog.
* @param didGetAddonList
@@ -318,15 +358,17 @@ GMPInstallManager.prototype = {
}
let url = await this._getURL();
+ let trustedContentSignatureRoot = this._getContentSignatureRootForURL(url);
log.info(
- `Fetching product addon list url=${url}, allowNonBuiltIn=${allowNonBuiltIn}, certs=${certs}, checkContentSignature=${checkContentSignature}`
+ `Fetching product addon list url=${url}, allowNonBuiltIn=${allowNonBuiltIn}, certs=${certs}, checkContentSignature=${checkContentSignature}, trustedContentSignatureRoot=${trustedContentSignatureRoot}`
);
let addonPromise = ProductAddonChecker.getProductAddonList(
url,
allowNonBuiltIn,
certs,
- checkContentSignature
+ checkContentSignature,
+ trustedContentSignatureRoot
)
.then(res => {
if (checkContentSignature) {
diff --git a/toolkit/modules/GMPUtils.sys.mjs b/toolkit/modules/GMPUtils.sys.mjs
index 488a024d13..c21576e0a9 100644
--- a/toolkit/modules/GMPUtils.sys.mjs
+++ b/toolkit/modules/GMPUtils.sys.mjs
@@ -124,6 +124,7 @@ export var GMPPrefs = {
KEY_PLUGIN_ABI: "media.{0}.abi",
KEY_PLUGIN_FORCE_SUPPORTED: "media.{0}.forceSupported",
KEY_PLUGIN_ALLOW_X64_ON_ARM64: "media.{0}.allow-x64-plugin-on-arm64",
+ KEY_ALLOW_LOCAL_SOURCES: "media.gmp-manager.allowLocalSources",
KEY_URL: "media.gmp-manager.url",
KEY_URL_OVERRIDE: "media.gmp-manager.url.override",
KEY_CERT_CHECKATTRS: "media.gmp-manager.cert.checkAttributes",
diff --git a/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js b/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
index 87de57efaf..e755690e6c 100644
--- a/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
+++ b/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
@@ -802,6 +802,60 @@ add_task(async function test_checkForAddons_contentSignatureFailure() {
});
/**
+ * Tests that the signature verification URL is as expected.
+ */
+add_task(async function test_checkForAddons_get_verifier_url() {
+ const previousUrlOverride = setupContentSigTestPrefs();
+
+ let installManager = new GMPInstallManager();
+ // checkForAddons() calls _getContentSignatureRootForURL() with the return
+ // value of _getURL(), which is effectively KEY_URL_OVERRIDE or KEY_URL
+ // followed by some normalization.
+ const rootForUrl = async () => {
+ const url = await installManager._getURL();
+ return installManager._getContentSignatureRootForURL(url);
+ };
+
+ Assert.equal(
+ await rootForUrl(),
+ Ci.nsIX509CertDB.AppXPCShellRoot,
+ "XPCShell root used by default in xpcshell test"
+ );
+
+ const defaultPrefs = Services.prefs.getDefaultBranch("");
+ const defaultUrl = defaultPrefs.getStringPref(GMPPrefs.KEY_URL);
+ Preferences.set(GMPPrefs.KEY_URL_OVERRIDE, defaultUrl);
+ Assert.equal(
+ await rootForUrl(),
+ Ci.nsIContentSignatureVerifier.ContentSignatureProdRoot,
+ "Production cert should be used for the default Balrog URL: " + defaultUrl
+ );
+
+ // The current Balrog endpoint is at aus5.mozilla.org. Confirm that the prod
+ // cert is used even if we bump the version (e.g. aus6):
+ const potentialProdUrl = "https://aus1337.mozilla.org/potential/prod/URL";
+ Preferences.set(GMPPrefs.KEY_URL_OVERRIDE, potentialProdUrl);
+ Assert.equal(
+ await rootForUrl(),
+ Ci.nsIContentSignatureVerifier.ContentSignatureProdRoot,
+ "Production cert should be used for: " + potentialProdUrl
+ );
+
+ // Stage URL documented at https://mozilla-balrog.readthedocs.io/en/latest/infrastructure.html
+ const stageUrl = "https://stage.balrog.nonprod.cloudops.mozgcp.net/etc.";
+ Preferences.set(GMPPrefs.KEY_URL_OVERRIDE, stageUrl);
+ Assert.equal(
+ await rootForUrl(),
+ Ci.nsIContentSignatureVerifier.ContentSignatureStageRoot,
+ "Stage cert should be used with the stage URL: " + stageUrl
+ );
+
+ installManager.uninit();
+
+ revertContentSigTestPrefs(previousUrlOverride);
+});
+
+/**
* Tests that checkForAddons() works as expected when certificate pinning
* checking is enabled. We plan to move away from cert pinning in favor of
* content signature checks, but part of doing this is comparing the telemetry