summaryrefslogtreecommitdiffstats
path: root/toolkit/mozapps/extensions/internal
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
commitd8bbc7858622b6d9c278469aab701ca0b609cddf (patch)
treeeff41dc61d9f714852212739e6b3738b82a2af87 /toolkit/mozapps/extensions/internal
parentReleasing progress-linux version 125.0.3-1~progress7.99u1. (diff)
downloadfirefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz
firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/mozapps/extensions/internal')
-rw-r--r--toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs6
-rw-r--r--toolkit/mozapps/extensions/internal/AddonTestUtils.sys.mjs31
-rw-r--r--toolkit/mozapps/extensions/internal/GMPProvider.sys.mjs6
-rw-r--r--toolkit/mozapps/extensions/internal/ProductAddonChecker.sys.mjs37
-rw-r--r--toolkit/mozapps/extensions/internal/SitePermsAddonProvider.sys.mjs4
-rw-r--r--toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs61
-rw-r--r--toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs107
-rw-r--r--toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs6
-rw-r--r--toolkit/mozapps/extensions/internal/crypto-utils.sys.mjs10
9 files changed, 204 insertions, 64 deletions
diff --git a/toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs b/toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs
index e53e4af7a4..8d4d178924 100644
--- a/toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs
@@ -466,13 +466,13 @@ export var AddonRepository = {
request.open("GET", url, true);
request.responseType = "json";
- request.addEventListener("error", aEvent => {
+ request.addEventListener("error", () => {
reject(new Error(`GET ${url} failed`));
});
- request.addEventListener("timeout", aEvent => {
+ request.addEventListener("timeout", () => {
reject(new Error(`GET ${url} timed out`));
});
- request.addEventListener("load", aEvent => {
+ request.addEventListener("load", () => {
let response = request.response;
if (!response || (request.status != 200 && request.status != 0)) {
reject(new Error(`GET ${url} failed (status ${request.status})`));
diff --git a/toolkit/mozapps/extensions/internal/AddonTestUtils.sys.mjs b/toolkit/mozapps/extensions/internal/AddonTestUtils.sys.mjs
index f53d32092d..7e4adacd11 100644
--- a/toolkit/mozapps/extensions/internal/AddonTestUtils.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.sys.mjs
@@ -3,7 +3,7 @@
*/
/* eslint "mozilla/no-aArgs": 1 */
-/* eslint "no-unused-vars": [2, {"args": "none", "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS)$"}] */
+/* eslint "no-unused-vars": [2, {"argsIgnorePattern": "^_", "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS)$"}] */
/* eslint "semi": [2, "always"] */
/* eslint "valid-jsdoc": [2, {requireReturn: false}] */
@@ -424,6 +424,35 @@ export var AddonTestUtils = {
});
},
+ getXPIExports() {
+ return ChromeUtils.importESModule(
+ "resource://gre/modules/addons/XPIExports.sys.mjs"
+ ).XPIExports;
+ },
+
+ getWeakSignatureInstallPrefName() {
+ return this.getXPIExports().XPIInstall.getWeakSignatureInstallPrefName();
+ },
+
+ setWeakSignatureInstallAllowed(allowed) {
+ const prefName = this.getWeakSignatureInstallPrefName();
+ let cleanupCalled = false;
+ const cleanup = () => {
+ if (cleanupCalled) {
+ return;
+ }
+ this.testScope.info(
+ `=== clear ${prefName} pref value set by this test file ===`
+ );
+ Services.prefs.clearUserPref(prefName);
+ cleanupCalled = true;
+ };
+ this.testScope.registerCleanupFunction(cleanup);
+ this.testScope.info(`=== set ${prefName} pref value to ${allowed} ===`);
+ Services.prefs.setBoolPref(prefName, allowed);
+ return cleanup;
+ },
+
/**
* Iterates over the entries in a given directory.
*
diff --git a/toolkit/mozapps/extensions/internal/GMPProvider.sys.mjs b/toolkit/mozapps/extensions/internal/GMPProvider.sys.mjs
index aaac109fc0..22ca2365d1 100644
--- a/toolkit/mozapps/extensions/internal/GMPProvider.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/GMPProvider.sys.mjs
@@ -340,7 +340,7 @@ GMPWrapper.prototype = {
return { source: "gmp-plugin" };
},
- isCompatibleWith(aAppVersion, aPlatformVersion) {
+ isCompatibleWith() {
return true;
},
@@ -377,7 +377,7 @@ GMPWrapper.prototype = {
* Widevine is not yet installed, or if the user toggles prefs to enable EME.
* For the function used in those cases see `checkForUpdates`.
*/
- findUpdates(aListener, aReason, aAppVersion, aPlatformVersion) {
+ findUpdates(aListener, aReason) {
this._log.trace(
"findUpdates() - " + this._plugin.id + " - reason=" + aReason
);
@@ -895,7 +895,7 @@ var GMPProvider = {
}
},
- observe(subject, topic, data) {
+ observe(subject, topic) {
if (topic == FIRST_CONTENT_PROCESS_TOPIC) {
lazy.AddonManagerPrivate.registerProvider(GMPProvider, ["plugin"]);
Services.obs.notifyObservers(null, "gmp-provider-registered");
diff --git a/toolkit/mozapps/extensions/internal/ProductAddonChecker.sys.mjs b/toolkit/mozapps/extensions/internal/ProductAddonChecker.sys.mjs
index 1615a551c8..64b337af3f 100644
--- a/toolkit/mozapps/extensions/internal/ProductAddonChecker.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/ProductAddonChecker.sys.mjs
@@ -118,12 +118,18 @@ async function conservativeFetch(input) {
* @param contentSignatureHeader
* The contents of the 'content-signature' header received along with
* `data`.
+ * @param trustedRoot
+ * The identifier of the trusted root to use for certificate validation.
* @return A promise that will resolve to nothing if the signature verification
* succeeds, or rejects on failure, with an Error that sets its
* addonCheckerErr property disambiguate failure cases and a message
* explaining the error.
*/
-async function verifyGmpContentSignature(data, contentSignatureHeader) {
+async function verifyGmpContentSignature(
+ data,
+ contentSignatureHeader,
+ trustedRoot
+) {
if (!contentSignatureHeader) {
logger.warn(
"Unexpected missing content signature header during content signature validation"
@@ -186,13 +192,6 @@ async function verifyGmpContentSignature(data, contentSignatureHeader) {
"@mozilla.org/security/contentsignatureverifier;1"
].createInstance(Ci.nsIContentSignatureVerifier);
- // See bug 1771992. In the future, this may need to handle staging and dev
- // environments in addition to just production and testing.
- let root = Ci.nsIContentSignatureVerifier.ContentSignatureProdRoot;
- if (Services.env.exists("XPCSHELL_TEST_PROFILE_DIR")) {
- root = Ci.nsIX509CertDB.AppXPCShellRoot;
- }
-
let valid;
try {
valid = await verifier.asyncVerifyContentSignature(
@@ -200,7 +199,7 @@ async function verifyGmpContentSignature(data, contentSignatureHeader) {
signature,
certChain,
"aus.content-signature.mozilla.org",
- root
+ trustedRoot
);
} catch (err) {
logger.warn(`Unexpected error while validating content signature: ${err}`);
@@ -329,6 +328,9 @@ function downloadXMLWithRequest(
* @param verifyContentSignature
* When true, will verify the content signature information from the
* response header. Failure to verify will result in an error.
+ * @param trustedContentSignatureRoot
+ * The trusted root to use for certificate validation.
+ * Must be set if verifyContentSignature is true.
* @return a promise that resolves to the DOM document downloaded or rejects
* with a JS exception in case of error.
*/
@@ -336,7 +338,8 @@ async function downloadXML(
url,
allowNonBuiltIn = false,
allowedCerts = null,
- verifyContentSignature = false
+ verifyContentSignature = false,
+ trustedContentSignatureRoot = null
) {
let request = await downloadXMLWithRequest(
url,
@@ -346,7 +349,8 @@ async function downloadXML(
if (verifyContentSignature) {
await verifyGmpContentSignature(
request.response,
- request.getResponseHeader("content-signature")
+ request.getResponseHeader("content-signature"),
+ trustedContentSignatureRoot
);
}
return request.responseXML;
@@ -422,7 +426,7 @@ function downloadFile(url, options = { httpsOnlyNoUpgrade: false }) {
return new Promise((resolve, reject) => {
let sr = new lazy.ServiceRequest();
- sr.onload = function (response) {
+ sr.onload = function () {
logger.info("downloadFile File download. status=" + sr.status);
if (sr.status != 200 && sr.status != 206) {
reject(Components.Exception("File download failed", sr.status));
@@ -535,6 +539,9 @@ export const ProductAddonChecker = {
* @param verifyContentSignature
* When true, will verify the content signature information from the
* response header. Failure to verify will result in an error.
+ * @param trustedContentSignatureRoot
+ * The trusted root to use for certificate validation.
+ * Must be set if verifyContentSignature is true.
* @return a promise that resolves to an object containing the list of add-ons
* and whether the local fallback was used, or rejects with a JS
* exception in case of error. In the case of an error, a best effort
@@ -545,13 +552,15 @@ export const ProductAddonChecker = {
url,
allowNonBuiltIn = false,
allowedCerts = null,
- verifyContentSignature = false
+ verifyContentSignature = false,
+ trustedContentSignatureRoot = null
) {
return downloadXML(
url,
allowNonBuiltIn,
allowedCerts,
- verifyContentSignature
+ verifyContentSignature,
+ trustedContentSignatureRoot
).then(parseXML);
},
diff --git a/toolkit/mozapps/extensions/internal/SitePermsAddonProvider.sys.mjs b/toolkit/mozapps/extensions/internal/SitePermsAddonProvider.sys.mjs
index 7ca952dc8a..8af3c2affe 100644
--- a/toolkit/mozapps/extensions/internal/SitePermsAddonProvider.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/SitePermsAddonProvider.sys.mjs
@@ -190,7 +190,7 @@ class SitePermsAddonWrapper {
return 0;
}
- async updateBlocklistState(options = {}) {}
+ async updateBlocklistState() {}
get blocklistState() {
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
@@ -277,7 +277,7 @@ class SitePermsAddonWrapper {
return { source: "siteperm-addon-provider", method: "synthetic-install" };
}
- isCompatibleWith(aAppVersion, aPlatformVersion) {
+ isCompatibleWith() {
return true;
}
}
diff --git a/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs b/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs
index af0b02444a..d7541167fa 100644
--- a/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs
@@ -31,6 +31,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
DeferredTask: "resource://gre/modules/DeferredTask.sys.mjs",
ExtensionData: "resource://gre/modules/Extension.sys.mjs",
ExtensionUtils: "resource://gre/modules/ExtensionUtils.sys.mjs",
+ ObjectUtils: "resource://gre/modules/ObjectUtils.sys.mjs",
PermissionsUtils: "resource://gre/modules/PermissionsUtils.sys.mjs",
QuarantinedDomains: "resource://gre/modules/ExtensionPermissions.sys.mjs",
});
@@ -192,6 +193,7 @@ const PROP_JSON_FIELDS = [
"targetApplications",
"targetPlatforms",
"signedState",
+ "signedTypes",
"signedDate",
"seen",
"dependencies",
@@ -1556,6 +1558,7 @@ function defineAddonWrapperProperty(name, getter) {
"validInstallOrigins",
"dependencies",
"signedState",
+ "signedTypes",
"sitePermissions",
"siteOrigin",
"isCorrectlySigned",
@@ -2175,7 +2178,7 @@ export const XPIDatabase = {
*/
async verifySignatures() {
try {
- let addons = await this.getAddonList(a => true);
+ let addons = await this.getAddonList(() => true);
let changes = {
enabled: [],
@@ -2188,17 +2191,31 @@ export const XPIDatabase = {
continue;
}
- let signedState = await XPIExports.verifyBundleSignedState(
- addon._sourceBundle,
- addon
- );
+ let { signedState, signedTypes } =
+ await XPIExports.verifyBundleSignedState(addon._sourceBundle, addon);
+
+ const changedProperties = [];
if (signedState != addon.signedState) {
addon.signedState = signedState;
+ changedProperties.push("signedState");
+ }
+
+ if (
+ !lazy.ObjectUtils.deepEqual(
+ signedTypes?.toSorted(),
+ addon.signedTypes?.toSorted()
+ )
+ ) {
+ addon.signedTypes = signedTypes;
+ changedProperties.push("signedTypes");
+ }
+
+ if (changedProperties.length) {
lazy.AddonManagerPrivate.callAddonListeners(
"onPropertyChanged",
addon.wrapper,
- ["signedState"]
+ changedProperties
);
}
@@ -2426,7 +2443,7 @@ export const XPIDatabase = {
if (!this.addonDB) {
return [];
}
- return _filterDB(this.addonDB, aAddon => true);
+ return _filterDB(this.addonDB, () => true);
},
/**
@@ -3084,24 +3101,11 @@ export const XPIDatabaseReconcile = {
* The new state of the add-on
* @param {AddonInternal?} [aNewAddon]
* The manifest for the new add-on if it has already been loaded
- * @param {string?} [aOldAppVersion]
- * The version of the application last run with this profile or null
- * if it is a new profile or the version is unknown
- * @param {string?} [aOldPlatformVersion]
- * The version of the platform last run with this profile or null
- * if it is a new profile or the version is unknown
* @returns {boolean}
* A boolean indicating if flushing caches is required to complete
* changing this add-on
*/
- addMetadata(
- aLocation,
- aId,
- aAddonState,
- aNewAddon,
- aOldAppVersion,
- aOldPlatformVersion
- ) {
+ addMetadata(aLocation, aId, aAddonState, aNewAddon) {
logger.debug(`New add-on ${aId} installed in ${aLocation.name}`);
// We treat this is a new install if,
@@ -3348,6 +3352,10 @@ export const XPIDatabaseReconcile = {
let signedDateMissing =
aOldAddon.signedDate === undefined &&
(aOldAddon.signedState || checkSigning);
+ // signedTypes must be set if signedState is set.
+ let signedTypesMissing =
+ aOldAddon.signedTypes === undefined &&
+ (aOldAddon.signedState || checkSigning);
// If maxVersion was inadvertently updated for a locale, force a reload
// from the manifest. See Bug 1646016 for details.
@@ -3360,7 +3368,12 @@ export const XPIDatabaseReconcile = {
}
let manifest = null;
- if (checkSigning || aReloadMetadata || signedDateMissing) {
+ if (
+ checkSigning ||
+ aReloadMetadata ||
+ signedDateMissing ||
+ signedTypesMissing
+ ) {
try {
manifest = XPIExports.XPIInstall.syncLoadManifest(
aAddonState,
@@ -3384,6 +3397,10 @@ export const XPIDatabaseReconcile = {
aOldAddon.signedDate = manifest.signedDate;
}
+ if (signedTypesMissing) {
+ aOldAddon.signedTypes = manifest.signedTypes;
+ }
+
// May be updating from a version of the app that didn't support all the
// properties of the currently-installed add-ons.
if (aReloadMetadata) {
diff --git a/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs b/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs
index 0402c2f2ca..4a26785da8 100644
--- a/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.sys.mjs
@@ -21,6 +21,7 @@ import { XPIExports } from "resource://gre/modules/addons/XPIExports.sys.mjs";
import {
computeSha256HashAsString,
getHashStringForCrypto,
+ hasStrongSignature,
} from "resource://gre/modules/addons/crypto-utils.sys.mjs";
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
import {
@@ -94,6 +95,9 @@ const PREF_XPI_ENABLED = "xpinstall.enabled";
const PREF_XPI_DIRECT_WHITELISTED = "xpinstall.whitelist.directRequest";
const PREF_XPI_FILE_WHITELISTED = "xpinstall.whitelist.fileRequest";
const PREF_XPI_WHITELIST_REQUIRED = "xpinstall.whitelist.required";
+const PREF_XPI_WEAK_SIGNATURES_ALLOWED =
+ "xpinstall.signatures.weakSignaturesTemporarilyAllowed";
+const PREF_XPI_WEAK_SIGNATURES_ALLOWED_DEFAULT = true;
const PREF_SELECTED_THEME = "extensions.activeThemeID";
@@ -230,7 +234,15 @@ class Package {
let root = Ci.nsIX509CertDB.AddonsPublicRoot;
if (
- !AppConstants.MOZ_REQUIRE_SIGNING &&
+ (!AppConstants.MOZ_REQUIRE_SIGNING ||
+ // Allow mochitests to switch to dev-root on all channels.
+ Cu.isInAutomation ||
+ // Allow xpcshell tests to switch to dev-root on all channels,
+ // included tests where "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer"
+ // pref is set to false and Cu.isInAutomation is going to be false (e.g. test_signed_langpack.js).
+ // TODO(Bug 1598804): we should be able to remove the following checks once Cu.isAutomation is fixed.
+ (Services.env.exists("XPCSHELL_TEST_PROFILE_DIR") &&
+ Services.appinfo.name === "XPCShell")) &&
Services.prefs.getBoolPref(PREF_XPI_SIGNATURES_DEV_ROOT, false)
) {
root = Ci.nsIX509CertDB.AddonsStageRoot;
@@ -287,7 +299,7 @@ DirPackage = class DirPackage extends Package {
return IOUtils.read(PathUtils.join(this.filePath, ...path));
}
- async verifySignedStateForRoot(addonId, root) {
+ async verifySignedStateForRoot() {
return { signedState: AddonManager.SIGNEDSTATE_UNKNOWN, cert: null };
}
};
@@ -341,8 +353,11 @@ XPIPackage = class XPIPackage extends Package {
aZipReader.close();
}
resolve({
- signedState: getSignedStatus(aRv, cert, addonId),
cert,
+ signedState: getSignedStatus(aRv, cert, addonId),
+ signedTypes: aSignatureInfos?.map(
+ signatureInfo => signatureInfo.signatureAlgorithm
+ ),
});
},
};
@@ -511,17 +526,18 @@ async function loadManifestFromWebManifest(aPackage, aLocation) {
addon.siteOrigin = manifest.install_origins[0];
}
- if (manifest.options_ui) {
+ const { optionsPageProperties } = extension;
+ if (optionsPageProperties) {
// Store just the relative path here, the AddonWrapper getURL
// wrapper maps this to a full URL.
- addon.optionsURL = manifest.options_ui.page;
- if (manifest.options_ui.open_in_tab) {
+ addon.optionsURL = optionsPageProperties.page;
+ if (optionsPageProperties.open_in_tab) {
addon.optionsType = AddonManager.OPTIONS_TYPE_TAB;
} else {
addon.optionsType = AddonManager.OPTIONS_TYPE_INLINE_BROWSER;
}
- addon.optionsBrowserStyle = manifest.options_ui.browser_style;
+ addon.optionsBrowserStyle = optionsPageProperties.browser_style;
}
// WebExtensions don't use iconURLs
@@ -693,9 +709,13 @@ var loadManifest = async function (aPackage, aLocation, aOldAddon) {
addon.rootURI = aPackage.rootURI.spec;
addon.location = aLocation;
- let { signedState, cert } = verifiedSignedState;
+ let { cert, signedState, signedTypes } = verifiedSignedState;
addon.signedState = signedState;
addon.signedDate = cert?.validity?.notBefore / 1000 || null;
+ // An array of the algorithms used by the signatures found in the signed XPI files,
+ // as an array of integers (see nsIAppSignatureInfo_SignatureAlgorithm enum defined
+ // in nsIX509CertDB.idl).
+ addon.signedTypes = signedTypes;
if (!addon.id) {
if (cert) {
@@ -909,18 +929,21 @@ function shouldVerifySignedState(aAddonType, aLocation) {
* The nsIFile for the bundle to check, either a directory or zip file.
* @param {AddonInternal} aAddon
* The add-on object to verify.
- * @returns {Promise<number>}
- * A Promise that resolves to an AddonManager.SIGNEDSTATE_* constant.
+ * @returns {Promise<{ signedState: number, signedTypes: Array<number>}>?}
+ * A Promise that resolves to object including a signedState property set to
+ * an AddonManager.SIGNEDSTATE_* constant and a signedTypes property set to
+ * either an array of Ci.nsIAppSignatureInfo SignatureAlgorithm enum values
+ * or undefined if the file wasn't signed.
*/
export var verifyBundleSignedState = async function (aBundle, aAddon) {
let pkg = Package.get(aBundle);
try {
- let { signedState } = await pkg.verifySignedState(
+ let { signedState, signedTypes } = await pkg.verifySignedState(
aAddon.id,
aAddon.type,
aAddon.location
);
- return signedState;
+ return { signedState, signedTypes };
} finally {
pkg.close();
}
@@ -1633,6 +1656,49 @@ class AddonInstall {
"signature verification failed",
]);
}
+
+ // Restrict install for signed extension only signed with weak signature algorithms, unless the
+ // restriction is explicitly disabled through prefs or enterprise policies.
+ if (
+ !XPIInstall.isWeakSignatureInstallAllowed() &&
+ this.addon.signedDate &&
+ !hasStrongSignature(this.addon)
+ ) {
+ const addonAllowedByPolicies = Services.policies.getExtensionSettings(
+ this.addon.id
+ )?.temporarily_allow_weak_signatures;
+
+ const globallyAllowedByPolicies =
+ Services.policies.getExtensionSettings(
+ "*"
+ )?.temporarily_allow_weak_signatures;
+
+ const allowedByPolicies =
+ (globallyAllowedByPolicies &&
+ (addonAllowedByPolicies || addonAllowedByPolicies == null)) ||
+ addonAllowedByPolicies;
+
+ if (
+ !allowedByPolicies &&
+ (!this.existingAddon || hasStrongSignature(this.existingAddon))
+ ) {
+ // Reject if it is a new install or installing over an existing addon including
+ // strong cryptographic signatures.
+ return Promise.reject([
+ AddonManager.ERROR_CORRUPT_FILE,
+ "install rejected due to the package not including a strong cryptographic signature",
+ ]);
+ }
+
+ // Still allow installs using weak signatures to install if either:
+ // - it is explicitly allowed through Enterprise Policies Settings
+ // - or there is an existing addon with a weak signature.
+ logger.warn(
+ allowedByPolicies
+ ? `Allow weak signature install for ${this.addon.id} XPI due to Enterprise Policies`
+ : `Allow weak signature install over existing "${this.existingAddon.id}" XPI`
+ );
+ }
}
} finally {
pkg.close();
@@ -2321,7 +2387,7 @@ var DownloadAddonInstall = class extends AddonInstall {
}
}
- observe(aSubject, aTopic, aData) {
+ observe() {
// Network is going offline
this.cancel();
}
@@ -2592,7 +2658,7 @@ var DownloadAddonInstall = class extends AddonInstall {
new UpdateChecker(
this.addon,
{
- onUpdateFinished: aAddon => this.downloadCompleted(),
+ onUpdateFinished: () => this.downloadCompleted(),
},
AddonManager.UPDATE_WHEN_ADDON_INSTALLED
);
@@ -3880,7 +3946,7 @@ class SystemAddonInstaller extends DirectoryInstaller {
}
// old system add-on upgrade dirs get automatically removed
- uninstallAddon(aAddon) {}
+ uninstallAddon() {}
}
var AppUpdate = {
@@ -4344,6 +4410,17 @@ export var XPIInstall = {
return Services.prefs.getBoolPref(PREF_XPI_FILE_WHITELISTED, true);
},
+ isWeakSignatureInstallAllowed() {
+ return Services.prefs.getBoolPref(
+ PREF_XPI_WEAK_SIGNATURES_ALLOWED,
+ PREF_XPI_WEAK_SIGNATURES_ALLOWED_DEFAULT
+ );
+ },
+
+ getWeakSignatureInstallPrefName() {
+ return PREF_XPI_WEAK_SIGNATURES_ALLOWED;
+ },
+
/**
* Called to test whether installing XPI add-ons from a URI is allowed.
*
diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs b/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs
index 12d4fa1172..3c090b5f0f 100644
--- a/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.sys.mjs
@@ -120,7 +120,7 @@ const XPI_PERMISSION = "install";
const XPI_SIGNATURE_CHECK_PERIOD = 24 * 60 * 60;
-const DB_SCHEMA = 35;
+const DB_SCHEMA = 36;
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
@@ -1598,7 +1598,7 @@ var XPIStates = {
*
* @returns {XPIState?}
*/
- findAddon(aId, aFilter = location => true) {
+ findAddon(aId, aFilter = () => true) {
// Fortunately the Map iterator returns in order of insertion, which is
// also our highest -> lowest priority order.
for (let location of this.locations()) {
@@ -2706,7 +2706,7 @@ export var XPIProvider = {
"profile-before-change",
"test-load-xpi-database",
];
- let observer = (subject, topic, data) => {
+ let observer = (subject, topic) => {
if (
topic == "xul-window-visible" &&
!Services.wm.getMostRecentWindow("devtools:toolbox")
diff --git a/toolkit/mozapps/extensions/internal/crypto-utils.sys.mjs b/toolkit/mozapps/extensions/internal/crypto-utils.sys.mjs
index b1304bcdfc..9ef096df0f 100644
--- a/toolkit/mozapps/extensions/internal/crypto-utils.sys.mjs
+++ b/toolkit/mozapps/extensions/internal/crypto-utils.sys.mjs
@@ -8,6 +8,14 @@ const CryptoHash = Components.Constructor(
"initWithString"
);
+const XPI_WEAK_SIGNATURES = [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1];
+
+export function hasStrongSignature(addon) {
+ return !!addon.signedTypes?.filter(
+ algorithm => !XPI_WEAK_SIGNATURES.includes(algorithm)
+ ).length;
+}
+
export function computeHashAsString(hashType, input) {
const data = new Uint8Array(new TextEncoder().encode(input));
const crypto = CryptoHash(hashType);
@@ -42,7 +50,7 @@ export function computeSha1HashAsString(input) {
/**
* Returns the string representation (hex) of a given CryptoHashInstance.
*
- * @param {CryptoHash} aCrypto
+ * @param {nsICryptoHash} aCrypto
* @returns {string}
* The hex representation of a SHA256 hash.
*/