mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 13:25:37 +00:00
Bug 1172028: Sideloaded add-ons without full signing shouldn't ever be loaded. r=dveditz
--HG-- extra : commitid : 58eDMD7nkod extra : rebase_source : f10644cd193e5fe0f69ca31b157eff400b320f67
This commit is contained in:
parent
22d917d06c
commit
936ce348c8
@ -221,6 +221,9 @@ class RefTest(object):
|
||||
# And for about:newtab content fetch and pings.
|
||||
prefs['browser.newtabpage.directory.source'] = 'data:application/json,{"reftest":1}'
|
||||
prefs['browser.newtabpage.directory.ping'] = ''
|
||||
# Only allow add-ons from the profile and app and allow foreign injection
|
||||
prefs["extensions.enabledScopes"] = 5;
|
||||
prefs["extensions.autoDisableScopes"] = 0;
|
||||
# Allow unsigned add-ons
|
||||
prefs['xpinstall.signatures.required'] = False
|
||||
|
||||
|
@ -69,6 +69,7 @@ user_pref("experiments.manifest.uri", "http://%(server)s/experiments-dummy/manif
|
||||
// Only load extensions from the application and user profile
|
||||
// AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
|
||||
user_pref("extensions.enabledScopes", 5);
|
||||
user_pref("extensions.autoDisableScopes", 0);
|
||||
// Disable metadata caching for installed add-ons by default
|
||||
user_pref("extensions.getAddons.cache.enabled", false);
|
||||
// Disable intalling any distribution add-ons
|
||||
|
@ -657,8 +657,12 @@ function isUsableAddon(aAddon) {
|
||||
if (aAddon.type == "theme" && aAddon.internalName == XPIProvider.defaultSkin)
|
||||
return true;
|
||||
|
||||
if (mustSign(aAddon.type) && aAddon.signedState <= AddonManager.SIGNEDSTATE_MISSING)
|
||||
return false;
|
||||
if (mustSign(aAddon.type)) {
|
||||
if (aAddon.signedState <= AddonManager.SIGNEDSTATE_MISSING)
|
||||
return false;
|
||||
if (aAddon.foreignInstall && aAddon.signedState < AddonManager.SIGNEDSTATE_SIGNED)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aAddon.blocklistState == Blocklist.STATE_BLOCKED)
|
||||
return false;
|
||||
@ -2751,9 +2755,12 @@ this.XPIProvider = {
|
||||
|
||||
let jsonfile = stagingDir.clone();
|
||||
jsonfile.append(id + ".json");
|
||||
// Assume this was a foreign install if there is no cached metadata file
|
||||
let foreignInstall = !jsonfile.exists();
|
||||
let addon;
|
||||
|
||||
try {
|
||||
aManifests[aLocation.name][id] = syncLoadManifestFromFile(stageDirEntry);
|
||||
addon = syncLoadManifestFromFile(stageDirEntry);
|
||||
}
|
||||
catch (e) {
|
||||
logger.error("Unable to read add-on manifest from " + stageDirEntry.path, e);
|
||||
@ -2763,9 +2770,9 @@ this.XPIProvider = {
|
||||
continue;
|
||||
}
|
||||
|
||||
let addon = aManifests[aLocation.name][id];
|
||||
|
||||
if ((addon.signedState <= AddonManager.SIGNEDSTATE_MISSING) && mustSign(addon.type)) {
|
||||
if (mustSign(addon.type) &&
|
||||
(addon.signedState <= AddonManager.SIGNEDSTATE_MISSING ||
|
||||
(foreignInstall && addon.signedState < AddonManager.SIGNEDSTATE_SIGNED))) {
|
||||
logger.warn("Refusing to install staged add-on " + id + " with signed state " + addon.signedState);
|
||||
seenFiles.push(stageDirEntry.leafName);
|
||||
seenFiles.push(jsonfile.leafName);
|
||||
@ -2774,7 +2781,7 @@ this.XPIProvider = {
|
||||
|
||||
// Check for a cached metadata for this add-on, it may contain updated
|
||||
// compatibility information
|
||||
if (jsonfile.exists()) {
|
||||
if (!foreignInstall) {
|
||||
logger.debug("Found updated metadata for " + id + " in " + aLocation.name);
|
||||
let fis = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Ci.nsIFileInputStream);
|
||||
@ -2785,6 +2792,10 @@ this.XPIProvider = {
|
||||
fis.init(jsonfile, -1, 0, 0);
|
||||
let metadata = json.decodeFromStream(fis, jsonfile.fileSize);
|
||||
addon.importMetadata(metadata);
|
||||
|
||||
// Pass this through to addMetadata so it knows this add-on was
|
||||
// likely installed through the UI
|
||||
aManifests[aLocation.name][id] = addon;
|
||||
}
|
||||
catch (e) {
|
||||
// If some data can't be recovered from the cached metadata then it
|
||||
@ -3380,6 +3391,9 @@ this.XPIProvider = {
|
||||
newAddon.updateDate = aAddonState.mtime;
|
||||
newAddon.foreignInstall = isDetectedInstall;
|
||||
|
||||
// appDisabled depends on whether the add-on is a foreignInstall so update
|
||||
newAddon.appDisabled = !isUsableAddon(newAddon);
|
||||
|
||||
if (aMigrateData) {
|
||||
// If there is migration data then apply it.
|
||||
logger.debug("Migrating data from old database");
|
||||
|
@ -9,6 +9,7 @@ const ADDONS = {
|
||||
unsigned: "unsigned_bootstrap_2.xpi",
|
||||
badid: "signed_bootstrap_badid_2.xpi",
|
||||
signed: "signed_bootstrap_2.xpi",
|
||||
preliminary: "preliminary_bootstrap_2.xpi",
|
||||
},
|
||||
nonbootstrap: {
|
||||
unsigned: "unsigned_nonbootstrap_2.xpi",
|
||||
@ -334,3 +335,45 @@ add_task(function*() {
|
||||
yield promiseShutdownManager();
|
||||
resetPrefs();
|
||||
});
|
||||
|
||||
// Only fully-signed sideloaded add-ons should work
|
||||
add_task(function*() {
|
||||
let file = manuallyInstall(do_get_file(DATA + ADDONS.bootstrap.preliminary), profileDir, ID);
|
||||
|
||||
startupManager();
|
||||
|
||||
// Currently we leave the sideloaded add-on there but just don't run it
|
||||
let addon = yield promiseAddonByID(ID);
|
||||
do_check_neq(addon, null);
|
||||
do_check_true(addon.appDisabled);
|
||||
do_check_false(addon.isActive);
|
||||
do_check_eq(addon.signedState, AddonManager.SIGNEDSTATE_PRELIMINARY);
|
||||
do_check_eq(getActiveVersion(), -1);
|
||||
|
||||
addon.uninstall();
|
||||
yield promiseShutdownManager();
|
||||
resetPrefs();
|
||||
|
||||
do_check_false(file.exists());
|
||||
clearCache(file);
|
||||
});
|
||||
|
||||
add_task(function*() {
|
||||
let stage = profileDir.clone();
|
||||
stage.append("staged");
|
||||
|
||||
let file = manuallyInstall(do_get_file(DATA + ADDONS.bootstrap.preliminary), stage, ID);
|
||||
|
||||
startupManager();
|
||||
|
||||
// Should have refused to install preliminarily signed version
|
||||
let addon = yield promiseAddonByID(ID);
|
||||
do_check_eq(addon, null);
|
||||
do_check_eq(getActiveVersion(), -1);
|
||||
|
||||
do_check_false(file.exists());
|
||||
clearCache(file);
|
||||
|
||||
yield promiseShutdownManager();
|
||||
resetPrefs();
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user