diff options
Diffstat (limited to 'toolkit/mozapps/webextensions/test/xpcshell/test_hotfix_cert.js')
-rw-r--r-- | toolkit/mozapps/webextensions/test/xpcshell/test_hotfix_cert.js | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/toolkit/mozapps/webextensions/test/xpcshell/test_hotfix_cert.js b/toolkit/mozapps/webextensions/test/xpcshell/test_hotfix_cert.js new file mode 100644 index 000000000..42ee59740 --- /dev/null +++ b/toolkit/mozapps/webextensions/test/xpcshell/test_hotfix_cert.js @@ -0,0 +1,167 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that hotfix installation works +const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; +const PREF_EM_HOTFIX_LASTVERSION = "extensions.hotfix.lastVersion"; +const PREF_EM_HOTFIX_URL = "extensions.hotfix.url"; +const PREF_EM_CERT_CHECKATTRIBUTES = "extensions.hotfix.cert.checkAttributes"; +const PREF_EM_HOTFIX_CERTS = "extensions.hotfix.certs."; + +// Derived from "openssl x509 -in firefox-hotfix.crt -fingerprint -sha1" +const GOOD_FINGERPRINT = "39:E7:2B:7A:5B:CF:37:78:F9:5D:4A:E0:53:2D:2F:3D:68:53:C5:60"; +const BAD_FINGERPRINT = "40:E7:2B:7A:5B:CF:37:78:F9:5D:4A:E0:53:2D:2F:3D:68:53:C5:60"; + +Components.utils.import("resource://testing-common/httpd.js"); +var testserver = new HttpServer(); +testserver.start(-1); +gPort = testserver.identity.primaryPort; +testserver.registerDirectory("/data/", do_get_file("data")); + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +// Ignore any certificate requirements the app has set +Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true); +Services.prefs.setCharPref(PREF_EM_HOTFIX_URL, "http://localhost:" + gPort + "/hotfix.rdf"); +// Clear out all hotfix cert prefs to make sure only the test prefs apply. +var defaults = Services.prefs.getDefaultBranch(""); +defaults.deleteBranch(PREF_EM_HOTFIX_CERTS); + +/* + * Register an addon install listener and return a promise that: + * resolves with the AddonInstall object if the install succeeds + * rejects with the AddonInstall if the install fails + */ +function promiseInstallListener() { + return new Promise((resolve, reject) => { + let listener = { + onDownloadFailed: ai => { + AddonManager.removeInstallListener(listener); + reject(ai); + }, + onInstallEnded: ai => { + AddonManager.removeInstallListener(listener); + resolve(ai); + }, + onDownloadCancelled: ai => { + AddonManager.removeInstallListener(listener); + reject(ai); + } + }; + AddonManager.addInstallListener(listener); + }); +} + +function promiseSuccessfulInstall() { + return promiseInstallListener().then( + aInstall => { + do_check_true(true); + do_check_eq(aInstall.addon.id, Services.prefs.getCharPref(PREF_EM_HOTFIX_ID)); + aInstall.addon.uninstall(); + Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION); + }, + aInstall => { + do_throw("Install should not have failed"); + }); +} + +function promiseFailedInstall() { + return promiseInstallListener().then( + aInstall => { + do_throw("Install should not have succeeded"); + aInstall.addon.uninstall(); + Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION); + }, + aInstall => { + do_check_true(true); + }); +} + +var tryInstallHotfix = Task.async(function*(id, file, installListener) { + Services.prefs.setCharPref(PREF_EM_HOTFIX_ID, id); + + testserver.registerPathHandler("/hotfix.rdf", function(request, response) { + response.write(createUpdateRDF({ + [id]: [{ + version: "1.0", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "0", + maxVersion: "*", + updateLink: "http://localhost:" + gPort + "/data/signing_checks/" + file, + }] + }] + })); + }); + + yield Promise.all([ + installListener, + AddonManagerPrivate.backgroundUpdateCheck() + ]); + + testserver.registerPathHandler("/hotfix.rdf", null); + Services.prefs.clearUserPref(PREF_EM_HOTFIX_ID); +}); + +// Test valid AMO hotfix signed add-ons doesn't work if the fingerprint pref is wrong +add_task(function* amo_signed_hotfix() { + Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", BAD_FINGERPRINT); + + yield tryInstallHotfix("firefox-hotfix@mozilla.org", + "hotfix_good.xpi", + promiseFailedInstall()); +}); + +// Test valid AMO hotfix signed add-ons works +add_task(function* amo_signed_hotfix() { + Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", GOOD_FINGERPRINT); + + yield tryInstallHotfix("firefox-hotfix@mozilla.org", + "hotfix_good.xpi", + promiseSuccessfulInstall()); +}); + +// A hotfix altered after signing should fail +add_task(function* amo_broken_hotfix() { + yield tryInstallHotfix("firefox-hotfix@mozilla.org", + "hotfix_broken.xpi", + promiseFailedInstall()); +}); + +// Test an add-on with the wrong ID but signed by the right cert fails +add_task(function* amo_wrongID_rightcert() { + yield tryInstallHotfix("test@tests.mozilla.org", + "hotfix_badid.xpi", + promiseFailedInstall()); +}); + +// It shouldn't matter that it requested the ID matching the cert to begin with +// if the embedded cert's ID doesn't match the add-on's ID +add_task(function* amo_wrongID_rightcert2() { + yield tryInstallHotfix("firefox-hotfix@mozilla.org", + "hotfix_badid.xpi", + promiseFailedInstall()); +}); + +// Test something signed by a regular AMO cert doesn't work +add_task(function* amo_signed_addon() { + yield tryInstallHotfix("test@tests.mozilla.org", + "signed_bootstrap_1.xpi", + promiseFailedInstall()); +}); + +// Test totally unsigned add-on fails +add_task(function* unsigned() { + yield tryInstallHotfix("test@tests.mozilla.org", + "unsigned_bootstrap_2.xpi", + promiseFailedInstall()); +}); + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); + + startupManager(); + + run_next_test(); +} |