diff --git a/devtools/shared/webconsole/test/unit/test_security-info-parser.js b/devtools/shared/webconsole/test/unit/test_security-info-parser.js index ce3c8b39d5c8..692b342efba6 100644 --- a/devtools/shared/webconsole/test/unit/test_security-info-parser.js +++ b/devtools/shared/webconsole/test/unit/test_security-info-parser.js @@ -32,10 +32,8 @@ const MockCertificate = { }, }; -// This *cannot* be used as an nsITransportSecurityInfo (since that interface is -// builtinclass) but the methods being tested aren't defined by XPCOM and aren't -// calling QueryInterface, so this usage is fine. const MockSecurityInfo = { + QueryInterface: ChromeUtils.generateQI([Ci.nsITransportSecurityInfo]), securityState: wpl.STATE_IS_SECURE, errorCode: 0, cipherName: "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", diff --git a/devtools/shared/webconsole/test/unit/test_security-info-state.js b/devtools/shared/webconsole/test/unit/test_security-info-state.js index 7c0888cd443f..8e9212eb768a 100644 --- a/devtools/shared/webconsole/test/unit/test_security-info-state.js +++ b/devtools/shared/webconsole/test/unit/test_security-info-state.js @@ -18,11 +18,8 @@ Object.defineProperty(this, "NetworkHelper", { }); const wpl = Ci.nsIWebProgressListener; - -// This *cannot* be used as an nsITransportSecurityInfo (since that interface is -// builtinclass) but the methods being tested aren't defined by XPCOM and aren't -// calling QueryInterface, so this usage is fine. const MockSecurityInfo = { + QueryInterface: ChromeUtils.generateQI([Ci.nsITransportSecurityInfo]), securityState: wpl.STATE_IS_BROKEN, errorCode: 0, // nsISSLStatus.TLS_VERSION_1_2 diff --git a/devtools/shared/webconsole/test/unit/test_security-info-static-hpkp.js b/devtools/shared/webconsole/test/unit/test_security-info-static-hpkp.js index 6d6d908246ca..d1e4415beb74 100644 --- a/devtools/shared/webconsole/test/unit/test_security-info-static-hpkp.js +++ b/devtools/shared/webconsole/test/unit/test_security-info-static-hpkp.js @@ -19,10 +19,8 @@ Object.defineProperty(this, "NetworkHelper", { const wpl = Ci.nsIWebProgressListener; -// This *cannot* be used as an nsITransportSecurityInfo (since that interface is -// builtinclass) but the methods being tested aren't defined by XPCOM and aren't -// calling QueryInterface, so this usage is fine. const MockSecurityInfo = { + QueryInterface: ChromeUtils.generateQI([Ci.nsITransportSecurityInfo]), securityState: wpl.STATE_IS_SECURE, errorCode: 0, cipherName: "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", diff --git a/netwerk/socket/nsITransportSecurityInfo.idl b/netwerk/socket/nsITransportSecurityInfo.idl index 989e5842d5e8..feae6daadcaa 100644 --- a/netwerk/socket/nsITransportSecurityInfo.idl +++ b/netwerk/socket/nsITransportSecurityInfo.idl @@ -9,7 +9,7 @@ interface nsIX509Cert; interface nsIX509CertList; -[builtinclass, scriptable, uuid(216112d3-28bc-4671-b057-f98cc09ba1ea)] +[scriptable, uuid(216112d3-28bc-4671-b057-f98cc09ba1ea)] interface nsITransportSecurityInfo : nsISupports { readonly attribute unsigned long securityState; readonly attribute long errorCode; // PRErrorCode @@ -72,3 +72,4 @@ interface nsITransportSecurityInfo : nsISupports { [must_use] readonly attribute boolean isExtendedValidation; }; + diff --git a/security/manager/ssl/components.conf b/security/manager/ssl/components.conf index 4a06129c4242..807663c81266 100644 --- a/security/manager/ssl/components.conf +++ b/security/manager/ssl/components.conf @@ -139,7 +139,7 @@ Classes = [ }, { 'cid': '{16786594-0296-4471-8096-8f84497ca428}', - 'contract_ids': ['@mozilla.org/security/transportsecurityinfo;1'], + 'contract_ids': [], 'type': 'mozilla::psm::TransportSecurityInfo', 'legacy_constructor': 'mozilla::psm::NSSConstructor', diff --git a/security/manager/ssl/tests/mochitest/browser/browser_bug627234_perwindowpb.js b/security/manager/ssl/tests/mochitest/browser/browser_bug627234_perwindowpb.js index a1be1d2a29dc..0ed800cc9a0a 100644 --- a/security/manager/ssl/tests/mochitest/browser/browser_bug627234_perwindowpb.js +++ b/security/manager/ssl/tests/mochitest/browser/browser_bug627234_perwindowpb.js @@ -3,6 +3,22 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; +var FakeTransportSecurityInfo = function() {}; + +FakeTransportSecurityInfo.prototype = { + serverCert: null, + cipherName: null, + keyLength: 2048, + isDomainMismatch: false, + isNotValidAtThisTime: false, + isUntrusted: false, + isExtendedValidation: false, + getInterface(aIID) { + return this.QueryInterface(aIID); + }, + QueryInterface: ChromeUtils.generateQI(["nsITransportSecurityInfo"]), +}; + function whenNewWindowLoaded(aOptions, aCallback) { let win = OpenBrowserWindow(aOptions); win.addEventListener( @@ -33,9 +49,7 @@ function test() { function doTest(aIsPrivateMode, aWindow, aCallback) { BrowserTestUtils.browserLoaded(aWindow.gBrowser.selectedBrowser).then( () => { - let secInfo = Cc[ - "@mozilla.org/security/transportsecurityinfo;1" - ].createInstance(Ci.nsITransportSecurityInfo); + let secInfo = new FakeTransportSecurityInfo(); uri = aWindow.Services.io.newURI("https://localhost/img.png"); gSSService.processHeader( Ci.nsISiteSecurityService.HEADER_HSTS, diff --git a/security/manager/ssl/tests/unit/head_psm.js b/security/manager/ssl/tests/unit/head_psm.js index 61bcc8ca3a17..c149d1ca7349 100644 --- a/security/manager/ssl/tests/unit/head_psm.js +++ b/security/manager/ssl/tests/unit/head_psm.js @@ -837,6 +837,25 @@ function stopOCSPResponder(responder) { }); } +// A prototype for a fake, error-free secInfo +var FakeTransportSecurityInfo = function(certificate) { + this.serverCert = certificate; +}; + +FakeTransportSecurityInfo.prototype = { + serverCert: null, + cipherName: null, + keyLength: 2048, + isDomainMismatch: false, + isNotValidAtThisTime: false, + isUntrusted: false, + isExtendedValidation: false, + getInterface(aIID) { + return this.QueryInterface(aIID); + }, + QueryInterface: ChromeUtils.generateQI(["nsITransportSecurityInfo"]), +}; + // Utility functions for adding tests relating to certificate error overrides // Helper function for add_cert_override_test. Probably doesn't need to be diff --git a/security/manager/ssl/tests/unit/test_forget_about_site_security_headers.js b/security/manager/ssl/tests/unit/test_forget_about_site_security_headers.js index 7b7377efd800..11313c0ba77d 100644 --- a/security/manager/ssl/tests/unit/test_forget_about_site_security_headers.js +++ b/security/manager/ssl/tests/unit/test_forget_about_site_security_headers.js @@ -9,12 +9,10 @@ // Ensures that HSTS (HTTP Strict Transport Security) and HPKP (HTTP Public key // pinning) are cleared when using "Forget About This Site". -const { ForgetAboutSite } = ChromeUtils.import( +var { ForgetAboutSite } = ChromeUtils.import( "resource://gre/modules/ForgetAboutSite.jsm" ); -do_get_profile(); // must be done before instantiating nsIX509CertDB - registerCleanupFunction(() => { Services.prefs.clearUserPref("security.cert_pinning.enforcement_level"); Services.prefs.clearUserPref( @@ -29,35 +27,162 @@ const VALID_PIN = `pin-sha256="${PINNING_ROOT_KEY_HASH}";`; const BACKUP_PIN = `pin-sha256="${NON_ISSUED_KEY_HASH}";`; const GOOD_MAX_AGE = `max-age=${GOOD_MAX_AGE_SECONDS};`; -const sss = Cc["@mozilla.org/ssservice;1"].getService( - Ci.nsISiteSecurityService +do_get_profile(); // must be done before instantiating nsIX509CertDB + +Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2); +Services.prefs.setBoolPref( + "security.cert_pinning.process_headers_from_non_builtin_roots", + true ); -const uri = Services.io.newURI("https://a.pinning.example.com"); -function add_tests() { - let secInfo = null; +var certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB +); +addCertFromFile(certdb, "test_pinning_dynamic/pinningroot.pem", "CTu,CTu,CTu"); - add_connection_test( - "a.pinning.example.com", - PRErrorCodeSuccess, - undefined, - aSecInfo => { - secInfo = aSecInfo; - } +var sss = Cc["@mozilla.org/ssservice;1"].getService(Ci.nsISiteSecurityService); +var uri = Services.io.newURI("https://a.pinning2.example.com"); + +// This test re-uses certificates from pinning tests because that's easier and +// simpler than recreating new certificates, hence the slightly longer than +// necessary domain name. +var secInfo = new FakeTransportSecurityInfo( + constructCertFromFile( + "test_pinning_dynamic/a.pinning2.example.com-pinningroot.pem" + ) +); + +// Test the normal case of processing HSTS and HPKP headers for +// a.pinning2.example.com, using "Forget About Site" on a.pinning2.example.com, +// and then checking that the platform doesn't consider a.pinning2.example.com +// to be HSTS or HPKP any longer. +add_task(async function() { + sss.processHeader( + Ci.nsISiteSecurityService.HEADER_HSTS, + uri, + GOOD_MAX_AGE, + secInfo, + 0, + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST + ); + sss.processHeader( + Ci.nsISiteSecurityService.HEADER_HPKP, + uri, + GOOD_MAX_AGE + VALID_PIN + BACKUP_PIN, + secInfo, + 0, + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST ); - // Test the normal case of processing HSTS and HPKP headers for - // a.pinning.example.com, using "Forget About Site" on a.pinning2.example.com, - // and then checking that the platform doesn't consider a.pinning.example.com - // to be HSTS or HPKP any longer. - add_task(async function() { + Assert.ok( + sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0), + "a.pinning2.example.com should be HSTS" + ); + Assert.ok( + sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0), + "a.pinning2.example.com should be HPKP" + ); + + await ForgetAboutSite.removeDataFromDomain("a.pinning2.example.com"); + + Assert.ok( + !sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0), + "a.pinning2.example.com should not be HSTS now" + ); + Assert.ok( + !sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0), + "a.pinning2.example.com should not be HPKP now" + ); +}); + +// Test the case of processing HSTS and HPKP headers for a.pinning2.example.com, +// using "Forget About Site" on example.com, and then checking that the platform +// doesn't consider the subdomain to be HSTS or HPKP any longer. Also test that +// unrelated sites don't also get removed. +add_task(async function() { + sss.processHeader( + Ci.nsISiteSecurityService.HEADER_HSTS, + uri, + GOOD_MAX_AGE, + secInfo, + 0, + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST + ); + sss.processHeader( + Ci.nsISiteSecurityService.HEADER_HPKP, + uri, + GOOD_MAX_AGE + VALID_PIN + BACKUP_PIN, + secInfo, + 0, + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST + ); + + Assert.ok( + sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0), + "a.pinning2.example.com should be HSTS (subdomain case)" + ); + Assert.ok( + sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0), + "a.pinning2.example.com should be HPKP (subdomain case)" + ); + + // Add an unrelated site to HSTS. Not HPKP because we have no valid keys for + // example.org. + let unrelatedURI = Services.io.newURI("https://example.org"); + sss.processHeader( + Ci.nsISiteSecurityService.HEADER_HSTS, + unrelatedURI, + GOOD_MAX_AGE, + secInfo, + 0, + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST + ); + Assert.ok( + sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI, 0), + "example.org should be HSTS" + ); + + await ForgetAboutSite.removeDataFromDomain("example.com"); + + Assert.ok( + !sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0), + "a.pinning2.example.com should not be HSTS now (subdomain case)" + ); + Assert.ok( + !sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0), + "a.pinning2.example.com should not be HPKP now (subdomain case)" + ); + + Assert.ok( + sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI, 0), + "example.org should still be HSTS" + ); +}); + +// Test the case of processing HSTS and HPKP headers for a.pinning2.example.com +// with various originAttributes, using "Forget About Site" on example.com, and +// then checking that the platform doesn't consider the subdomain to be HSTS or +// HPKP for any originAttributes any longer. Also test that unrelated sites +// don't also get removed. +add_task(async function() { + let originAttributesList = [ + {}, + { userContextId: 1 }, + { firstPartyDomain: "foo.com" }, + { userContextId: 1, firstPartyDomain: "foo.com" }, + ]; + + let unrelatedURI = Services.io.newURI("https://example.org"); + + for (let originAttributes of originAttributesList) { sss.processHeader( Ci.nsISiteSecurityService.HEADER_HSTS, uri, GOOD_MAX_AGE, secInfo, 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST, + originAttributes ); sss.processHeader( Ci.nsISiteSecurityService.HEADER_HPKP, @@ -65,216 +190,82 @@ function add_tests() { GOOD_MAX_AGE + VALID_PIN + BACKUP_PIN, secInfo, 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST, + originAttributes ); Assert.ok( - sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0), - "a.pinning.example.com should be HSTS" + sss.isSecureURI( + Ci.nsISiteSecurityService.HEADER_HSTS, + uri, + 0, + originAttributes + ), + "a.pinning2.example.com should be HSTS (originAttributes case)" ); Assert.ok( - sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0), - "a.pinning.example.com should be HPKP" + sss.isSecureURI( + Ci.nsISiteSecurityService.HEADER_HPKP, + uri, + 0, + originAttributes + ), + "a.pinning2.example.com should be HPKP (originAttributes case)" ); - await ForgetAboutSite.removeDataFromDomain("a.pinning.example.com"); - - Assert.ok( - !sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0), - "a.pinning.example.com should not be HSTS now" - ); - Assert.ok( - !sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0), - "a.pinning.example.com should not be HPKP now" - ); - }); - - // Test the case of processing HSTS and HPKP headers for a.pinning.example.com, - // using "Forget About Site" on example.com, and then checking that the platform - // doesn't consider the subdomain to be HSTS or HPKP any longer. Also test that - // unrelated sites don't also get removed. - add_task(async function() { - sss.processHeader( - Ci.nsISiteSecurityService.HEADER_HSTS, - uri, - GOOD_MAX_AGE, - secInfo, - 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST - ); - sss.processHeader( - Ci.nsISiteSecurityService.HEADER_HPKP, - uri, - GOOD_MAX_AGE + VALID_PIN + BACKUP_PIN, - secInfo, - 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST - ); - - Assert.ok( - sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0), - "a.pinning.example.com should be HSTS (subdomain case)" - ); - Assert.ok( - sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0), - "a.pinning.example.com should be HPKP (subdomain case)" - ); - - // Add an unrelated site to HSTS. Not HPKP because we have no valid keys for - // example.org. - let unrelatedURI = Services.io.newURI("https://example.org"); + // Add an unrelated site to HSTS. Not HPKP because we have no valid keys. sss.processHeader( Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI, GOOD_MAX_AGE, secInfo, 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST, + originAttributes ); Assert.ok( - sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI, 0), - "example.org should be HSTS" - ); - - await ForgetAboutSite.removeDataFromDomain("example.com"); - - Assert.ok( - !sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0), - "a.pinning.example.com should not be HSTS now (subdomain case)" - ); - Assert.ok( - !sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0), - "a.pinning.example.com should not be HPKP now (subdomain case)" - ); - - Assert.ok( - sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI, 0), - "example.org should still be HSTS" - ); - }); - - // Test the case of processing HSTS and HPKP headers for a.pinning.example.com - // with various originAttributes, using "Forget About Site" on example.com, and - // then checking that the platform doesn't consider the subdomain to be HSTS or - // HPKP for any originAttributes any longer. Also test that unrelated sites - // don't also get removed. - add_task(async function() { - let originAttributesList = [ - {}, - { userContextId: 1 }, - { firstPartyDomain: "foo.com" }, - { userContextId: 1, firstPartyDomain: "foo.com" }, - ]; - - let unrelatedURI = Services.io.newURI("https://example.org"); - - for (let originAttributes of originAttributesList) { - sss.processHeader( - Ci.nsISiteSecurityService.HEADER_HSTS, - uri, - GOOD_MAX_AGE, - secInfo, - 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST, - originAttributes - ); - sss.processHeader( - Ci.nsISiteSecurityService.HEADER_HPKP, - uri, - GOOD_MAX_AGE + VALID_PIN + BACKUP_PIN, - secInfo, - 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST, - originAttributes - ); - - Assert.ok( - sss.isSecureURI( - Ci.nsISiteSecurityService.HEADER_HSTS, - uri, - 0, - originAttributes - ), - "a.pinning.example.com should be HSTS (originAttributes case)" - ); - Assert.ok( - sss.isSecureURI( - Ci.nsISiteSecurityService.HEADER_HPKP, - uri, - 0, - originAttributes - ), - "a.pinning.example.com should be HPKP (originAttributes case)" - ); - - // Add an unrelated site to HSTS. Not HPKP because we have no valid keys. - sss.processHeader( + sss.isSecureURI( Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI, - GOOD_MAX_AGE, - secInfo, 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST, originAttributes - ); - Assert.ok( - sss.isSecureURI( - Ci.nsISiteSecurityService.HEADER_HSTS, - unrelatedURI, - 0, - originAttributes - ), - "example.org should be HSTS (originAttributes case)" - ); - } + ), + "example.org should be HSTS (originAttributes case)" + ); + } - await ForgetAboutSite.removeDataFromDomain("example.com"); + await ForgetAboutSite.removeDataFromDomain("example.com"); - for (let originAttributes of originAttributesList) { - Assert.ok( - !sss.isSecureURI( - Ci.nsISiteSecurityService.HEADER_HSTS, - uri, - 0, - originAttributes - ), - "a.pinning.example.com should not be HSTS now " + - "(originAttributes case)" - ); - Assert.ok( - !sss.isSecureURI( - Ci.nsISiteSecurityService.HEADER_HPKP, - uri, - 0, - originAttributes - ), - "a.pinning.example.com should not be HPKP now " + - "(originAttributes case)" - ); + for (let originAttributes of originAttributesList) { + Assert.ok( + !sss.isSecureURI( + Ci.nsISiteSecurityService.HEADER_HSTS, + uri, + 0, + originAttributes + ), + "a.pinning2.example.com should not be HSTS now " + + "(originAttributes case)" + ); + Assert.ok( + !sss.isSecureURI( + Ci.nsISiteSecurityService.HEADER_HPKP, + uri, + 0, + originAttributes + ), + "a.pinning2.example.com should not be HPKP now " + + "(originAttributes case)" + ); - Assert.ok( - sss.isSecureURI( - Ci.nsISiteSecurityService.HEADER_HSTS, - unrelatedURI, - 0, - originAttributes - ), - "example.org should still be HSTS (originAttributes case)" - ); - } - }); -} - -function run_test() { - Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2); - Services.prefs.setBoolPref( - "security.cert_pinning.process_headers_from_non_builtin_roots", - true - ); - - add_tls_server_setup("BadCertAndPinningServer", "bad_certs"); - - add_tests(); - - run_next_test(); -} + Assert.ok( + sss.isSecureURI( + Ci.nsISiteSecurityService.HEADER_HSTS, + unrelatedURI, + 0, + originAttributes + ), + "example.org should still be HSTS (originAttributes case)" + ); + } +}); diff --git a/security/manager/ssl/tests/unit/test_ocsp_must_staple.js b/security/manager/ssl/tests/unit/test_ocsp_must_staple.js index ed7fa511840a..56aec21674d4 100644 --- a/security/manager/ssl/tests/unit/test_ocsp_must_staple.js +++ b/security/manager/ssl/tests/unit/test_ocsp_must_staple.js @@ -14,23 +14,17 @@ function add_ocsp_test( aHost, aExpectedResult, aStaplingEnabled, - aExpectOCSPRequest = false, - aWithSecurityInfo = undefined + aExpectOCSPRequest = false ) { - add_connection_test( - aHost, - aExpectedResult, - function() { - gExpectOCSPRequest = aExpectOCSPRequest; - clearOCSPCache(); - clearSessionCache(); - Services.prefs.setBoolPref( - "security.ssl.enable_ocsp_stapling", - aStaplingEnabled - ); - }, - aWithSecurityInfo - ); + add_connection_test(aHost, aExpectedResult, function() { + gExpectOCSPRequest = aExpectOCSPRequest; + clearOCSPCache(); + clearSessionCache(); + Services.prefs.setBoolPref( + "security.ssl.enable_ocsp_stapling", + aStaplingEnabled + ); + }); } function add_tests() { @@ -39,45 +33,50 @@ function add_tests() { add_ocsp_test( "ocsp-stapling-must-staple-ee-with-must-staple-int.example.com", PRErrorCodeSuccess, - true, - false, - function(aSecInfo) { - Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 1); - Services.prefs.setBoolPref( - "security.cert_pinning.process_headers_from_non_builtin_roots", - true - ); - let uri = Services.io.newURI( - "https://ocsp-stapling-must-staple-ee-with-must-staple-int.example.com" - ); - let keyHash = "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8="; - let backupKeyHash = "KHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN="; - let header = `max-age=1000; pin-sha256="${keyHash}"; pin-sha256="${backupKeyHash}"`; - let ssservice = Cc["@mozilla.org/ssservice;1"].getService( - Ci.nsISiteSecurityService - ); - ssservice.processHeader( - Ci.nsISiteSecurityService.HEADER_HPKP, - uri, - header, - aSecInfo, - 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST - ); - ok( - ssservice.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0), - "ocsp-stapling-must-staple-ee-with-must-staple-int.example.com should have HPKP set" - ); - - // Clear accumulated state. - ssservice.resetState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0); - Services.prefs.clearUserPref( - "security.cert_pinning.process_headers_from_non_builtin_roots" - ); - Services.prefs.clearUserPref("security.cert_pinning.enforcement_level"); - } + true ); + add_test(() => { + Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 1); + Services.prefs.setBoolPref( + "security.cert_pinning.process_headers_from_non_builtin_roots", + true + ); + let uri = Services.io.newURI( + "https://ocsp-stapling-must-staple-ee-with-must-staple-int.example.com" + ); + let keyHash = "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8="; + let backupKeyHash = "KHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN="; + let header = `max-age=1000; pin-sha256="${keyHash}"; pin-sha256="${backupKeyHash}"`; + let ssservice = Cc["@mozilla.org/ssservice;1"].getService( + Ci.nsISiteSecurityService + ); + let secInfo = new FakeTransportSecurityInfo(); + secInfo.serverCert = constructCertFromFile( + "ocsp_certs/must-staple-ee-with-must-staple-int.pem" + ); + ssservice.processHeader( + Ci.nsISiteSecurityService.HEADER_HPKP, + uri, + header, + secInfo, + 0, + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST + ); + ok( + ssservice.isSecureURI(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0), + "ocsp-stapling-must-staple-ee-with-must-staple-int.example.com should have HPKP set" + ); + + // Clear accumulated state. + ssservice.resetState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0); + Services.prefs.clearUserPref( + "security.cert_pinning.process_headers_from_non_builtin_roots" + ); + Services.prefs.clearUserPref("security.cert_pinning.enforcement_level"); + run_next_test(); + }); + // Next, a case where it's present in the intermediate, not the ee add_ocsp_test( "ocsp-stapling-plain-ee-with-must-staple-int.example.com", diff --git a/security/manager/ssl/tests/unit/test_ocsp_no_hsts_upgrade.js b/security/manager/ssl/tests/unit/test_ocsp_no_hsts_upgrade.js index 1c9ba6dcce16..2c074695719d 100644 --- a/security/manager/ssl/tests/unit/test_ocsp_no_hsts_upgrade.js +++ b/security/manager/ssl/tests/unit/test_ocsp_no_hsts_upgrade.js @@ -47,9 +47,7 @@ function run_test() { Ci.nsISiteSecurityService ); let uri = Services.io.newURI("http://localhost"); - let secInfo = Cc[ - "@mozilla.org/security/transportsecurityinfo;1" - ].createInstance(Ci.nsITransportSecurityInfo); + let secInfo = new FakeTransportSecurityInfo(); SSService.processHeader( Ci.nsISiteSecurityService.HEADER_HSTS, uri, diff --git a/security/manager/ssl/tests/unit/test_pinning_header_parsing.js b/security/manager/ssl/tests/unit/test_pinning_header_parsing.js index 29105f3fd75d..d1859436e454 100644 --- a/security/manager/ssl/tests/unit/test_pinning_header_parsing.js +++ b/security/manager/ssl/tests/unit/test_pinning_header_parsing.js @@ -6,14 +6,29 @@ // The purpose of this test is to check that parsing of HPKP headers // is correct. -do_get_profile(); - -const gSSService = Cc["@mozilla.org/ssservice;1"].getService( +var profileDir = do_get_profile(); +const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB +); +var gSSService = Cc["@mozilla.org/ssservice;1"].getService( Ci.nsISiteSecurityService ); -function checkFailParseInvalidPin(secInfo, pinValue) { - let uri = Services.io.newURI("https://a.pinning.example.com"); +function certFromFile(cert_name) { + return constructCertFromFile("test_pinning_dynamic/" + cert_name + ".pem"); +} + +function loadCert(cert_name, trust_string) { + let cert_filename = "test_pinning_dynamic/" + cert_name + ".pem"; + addCertFromFile(certdb, cert_filename, trust_string); + return constructCertFromFile(cert_filename); +} + +function checkFailParseInvalidPin(pinValue) { + let secInfo = new FakeTransportSecurityInfo( + certFromFile("a.pinning2.example.com-pinningroot") + ); + let uri = Services.io.newURI("https://a.pinning2.example.com"); throws( () => { gSSService.processHeader( @@ -30,8 +45,11 @@ function checkFailParseInvalidPin(secInfo, pinValue) { ); } -function checkPassValidPin(secInfo, pinValue, settingPin, expectedMaxAge) { - let uri = Services.io.newURI("https://a.pinning.example.com"); +function checkPassValidPin(pinValue, settingPin, expectedMaxAge) { + let secInfo = new FakeTransportSecurityInfo( + certFromFile("a.pinning2.example.com-pinningroot") + ); + let uri = Services.io.newURI("https://a.pinning2.example.com"); let maxAge = {}; // setup preconditions for the test, if setting ensure there is no previous @@ -88,12 +106,12 @@ function checkPassValidPin(secInfo, pinValue, settingPin, expectedMaxAge) { } } -function checkPassSettingPin(secInfo, pinValue, expectedMaxAge) { - return checkPassValidPin(secInfo, pinValue, true, expectedMaxAge); +function checkPassSettingPin(pinValue, expectedMaxAge) { + return checkPassValidPin(pinValue, true, expectedMaxAge); } -function checkPassRemovingPin(secInfo, pinValue) { - return checkPassValidPin(secInfo, pinValue, false); +function checkPassRemovingPin(pinValue) { + return checkPassValidPin(pinValue, false); } const MAX_MAX_AGE_SECONDS = 100000; @@ -113,111 +131,77 @@ const INCLUDE_SUBDOMAINS = "includeSubdomains;"; const REPORT_URI = 'report-uri="https://www.example.com/report/";'; const UNRECOGNIZED_DIRECTIVE = "unreconized-dir=12343;"; -function add_tests() { - let secInfo = null; - add_connection_test( - "a.pinning.example.com", - PRErrorCodeSuccess, - undefined, - aSecInfo => { - secInfo = aSecInfo; - } - ); - - add_task(() => { - checkFailParseInvalidPin(secInfo, "max-age=INVALID"); - // check that incomplete headers are failure - checkFailParseInvalidPin(secInfo, GOOD_MAX_AGE); - checkFailParseInvalidPin(secInfo, VALID_PIN1); - checkFailParseInvalidPin(secInfo, REPORT_URI); - checkFailParseInvalidPin(secInfo, UNRECOGNIZED_DIRECTIVE); - checkFailParseInvalidPin(secInfo, VALID_PIN1 + BACKUP_PIN1); - checkFailParseInvalidPin(secInfo, GOOD_MAX_AGE + VALID_PIN1); - checkFailParseInvalidPin(secInfo, GOOD_MAX_AGE + VALID_PIN1 + BROKEN_PIN1); - // next ensure a backup pin is present - checkFailParseInvalidPin(secInfo, GOOD_MAX_AGE + VALID_PIN1 + VALID_PIN1); - // next section ensure duplicate directives result in failure - checkFailParseInvalidPin( - secInfo, - GOOD_MAX_AGE + GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1 - ); - checkFailParseInvalidPin( - secInfo, - GOOD_MAX_AGE + - VALID_PIN1 + - BACKUP_PIN1 + - INCLUDE_SUBDOMAINS + - INCLUDE_SUBDOMAINS - ); - checkFailParseInvalidPin( - secInfo, - GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1 + REPORT_URI + REPORT_URI - ); - checkFailParseInvalidPin(secInfo, "thisisinvalidtest"); - checkFailParseInvalidPin( - secInfo, - "invalid" + GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1 - ); - - checkPassRemovingPin(secInfo, "max-age=0"); // test removal without terminating ';' - checkPassRemovingPin(secInfo, MAX_AGE_ZERO); - checkPassRemovingPin(secInfo, MAX_AGE_ZERO + VALID_PIN1); - - checkPassSettingPin( - secInfo, - GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1, - GOOD_MAX_AGE_SECONDS - ); - checkPassSettingPin( - secInfo, - LONG_MAX_AGE + VALID_PIN1 + BACKUP_PIN1, - MAX_MAX_AGE_SECONDS - ); - - checkPassRemovingPin(secInfo, VALID_PIN1 + MAX_AGE_ZERO + VALID_PIN1); - checkPassSettingPin(secInfo, GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1); - checkPassSettingPin(secInfo, GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN2); - checkPassSettingPin( - secInfo, - GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN2 + INCLUDE_SUBDOMAINS - ); - checkPassSettingPin( - secInfo, - VALID_PIN1 + GOOD_MAX_AGE + BACKUP_PIN2 + INCLUDE_SUBDOMAINS - ); - checkPassSettingPin( - secInfo, - VALID_PIN1 + GOOD_MAX_AGE + BACKUP_PIN2 + REPORT_URI + INCLUDE_SUBDOMAINS - ); - checkPassSettingPin( - secInfo, - INCLUDE_SUBDOMAINS + VALID_PIN1 + GOOD_MAX_AGE + BACKUP_PIN2 - ); - checkPassSettingPin( - secInfo, - GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1 + UNRECOGNIZED_DIRECTIVE - ); - }); -} - -registerCleanupFunction(() => { - Services.prefs.clearUserPref("security.cert_pinning.enforcement_level"); - Services.prefs.clearUserPref("security.cert_pinning.max_max_age_seconds"); -}); - function run_test() { Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2); Services.prefs.setIntPref( "security.cert_pinning.max_max_age_seconds", MAX_MAX_AGE_SECONDS ); - Services.prefs.setBoolPref( "security.cert_pinning.process_headers_from_non_builtin_roots", true ); - add_tls_server_setup("BadCertAndPinningServer", "bad_certs"); - add_tests(); - run_next_test(); + loadCert("pinningroot", "CTu,CTu,CTu"); + loadCert("badca", "CTu,CTu,CTu"); + + checkFailParseInvalidPin("max-age=INVALID"); + // check that incomplete headers are failure + checkFailParseInvalidPin(GOOD_MAX_AGE); + checkFailParseInvalidPin(VALID_PIN1); + checkFailParseInvalidPin(REPORT_URI); + checkFailParseInvalidPin(UNRECOGNIZED_DIRECTIVE); + checkFailParseInvalidPin(VALID_PIN1 + BACKUP_PIN1); + checkFailParseInvalidPin(GOOD_MAX_AGE + VALID_PIN1); + checkFailParseInvalidPin(GOOD_MAX_AGE + VALID_PIN1 + BROKEN_PIN1); + // next ensure a backup pin is present + checkFailParseInvalidPin(GOOD_MAX_AGE + VALID_PIN1 + VALID_PIN1); + // next section ensure duplicate directives result in failure + checkFailParseInvalidPin( + GOOD_MAX_AGE + GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1 + ); + checkFailParseInvalidPin( + GOOD_MAX_AGE + + VALID_PIN1 + + BACKUP_PIN1 + + INCLUDE_SUBDOMAINS + + INCLUDE_SUBDOMAINS + ); + checkFailParseInvalidPin( + GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1 + REPORT_URI + REPORT_URI + ); + checkFailParseInvalidPin("thisisinvalidtest"); + checkFailParseInvalidPin("invalid" + GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1); + + checkPassRemovingPin("max-age=0"); // test removal without terminating ';' + checkPassRemovingPin(MAX_AGE_ZERO); + checkPassRemovingPin(MAX_AGE_ZERO + VALID_PIN1); + + checkPassSettingPin( + GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1, + GOOD_MAX_AGE_SECONDS + ); + checkPassSettingPin( + LONG_MAX_AGE + VALID_PIN1 + BACKUP_PIN1, + MAX_MAX_AGE_SECONDS + ); + + checkPassRemovingPin(VALID_PIN1 + MAX_AGE_ZERO + VALID_PIN1); + checkPassSettingPin(GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1); + checkPassSettingPin(GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN2); + checkPassSettingPin( + GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN2 + INCLUDE_SUBDOMAINS + ); + checkPassSettingPin( + VALID_PIN1 + GOOD_MAX_AGE + BACKUP_PIN2 + INCLUDE_SUBDOMAINS + ); + checkPassSettingPin( + VALID_PIN1 + GOOD_MAX_AGE + BACKUP_PIN2 + REPORT_URI + INCLUDE_SUBDOMAINS + ); + checkPassSettingPin( + INCLUDE_SUBDOMAINS + VALID_PIN1 + GOOD_MAX_AGE + BACKUP_PIN2 + ); + checkPassSettingPin( + GOOD_MAX_AGE + VALID_PIN1 + BACKUP_PIN1 + UNRECOGNIZED_DIRECTIVE + ); } diff --git a/security/manager/ssl/tests/unit/test_sss_enumerate.js b/security/manager/ssl/tests/unit/test_sss_enumerate.js index 99eef28105ce..b52d730c4755 100644 --- a/security/manager/ssl/tests/unit/test_sss_enumerate.js +++ b/security/manager/ssl/tests/unit/test_sss_enumerate.js @@ -3,8 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; -do_get_profile(); // must be done before instantiating nsIX509CertDB - // This had better not be larger than the maximum maxAge for HPKP. const NON_ISSUED_KEY_HASH = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; const PINNING_ROOT_KEY_HASH = "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8="; @@ -12,19 +10,78 @@ const KEY_HASHES = [NON_ISSUED_KEY_HASH, PINNING_ROOT_KEY_HASH]; const SECS_IN_A_WEEK = 7 * 24 * 60 * 60 * 1000; const TESTCASES = [ { - hostname: "a.pinning.example.com", + hostname: "a.pinning2.example.com", includeSubdomains: true, expireTime: Date.now() + 12 * SECS_IN_A_WEEK * 1000, }, { - hostname: "b.pinning.example.com", + hostname: "b.pinning2.example.com", includeSubdomains: false, expireTime: Date.now() + 13 * SECS_IN_A_WEEK * 1000, }, ].sort((a, b) => a.expireTime - b.expireTime); +registerCleanupFunction(() => { + Services.prefs.clearUserPref( + "security.cert_pinning.process_headers_from_non_builtin_roots" + ); + Services.prefs.clearUserPref("security.cert_pinning.max_max_age_seconds"); +}); + +do_get_profile(); + +Services.prefs.setBoolPref( + "security.cert_pinning.process_headers_from_non_builtin_roots", + true +); +Services.prefs.setIntPref( + "security.cert_pinning.max_max_age_seconds", + 20 * SECS_IN_A_WEEK +); + +let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB +); +addCertFromFile(certdb, "test_pinning_dynamic/pinningroot.pem", "CTu,CTu,CTu"); + let sss = Cc["@mozilla.org/ssservice;1"].getService(Ci.nsISiteSecurityService); +function insertEntries() { + for (let testcase of TESTCASES) { + let uri = Services.io.newURI("https://" + testcase.hostname); + let secInfo = new FakeTransportSecurityInfo( + constructCertFromFile( + `test_pinning_dynamic/${testcase.hostname}-pinningroot.pem` + ) + ); + // MaxAge is in seconds. + let maxAge = Math.round((testcase.expireTime - Date.now()) / 1000); + let header = `max-age=${maxAge}`; + if (testcase.includeSubdomains) { + header += "; includeSubdomains"; + } + sss.processHeader( + Ci.nsISiteSecurityService.HEADER_HSTS, + uri, + header, + secInfo, + 0, + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST + ); + for (let key of KEY_HASHES) { + header += `; pin-sha256="${key}"`; + } + sss.processHeader( + Ci.nsISiteSecurityService.HEADER_HPKP, + uri, + header, + secInfo, + 0, + Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST + ); + } +} + function getEntries(type) { return Array.from(sss.enumerate(type)); } @@ -72,84 +129,23 @@ function checkSha256Keys(hpkpEntries) { } } -registerCleanupFunction(() => { - Services.prefs.clearUserPref( - "security.cert_pinning.process_headers_from_non_builtin_roots" - ); - Services.prefs.clearUserPref("security.cert_pinning.max_max_age_seconds"); -}); - -function add_tests() { +function run_test() { sss.clearAll(); - for (const testcase of TESTCASES) { - add_connection_test( - testcase.hostname, - PRErrorCodeSuccess, - undefined, - function insertEntry(secInfo) { - const uri = Services.io.newURI(`https://${testcase.hostname}`); + insertEntries(); - // MaxAge is in seconds. - let maxAge = Math.round((testcase.expireTime - Date.now()) / 1000); - let header = `max-age=${maxAge}`; - if (testcase.includeSubdomains) { - header += "; includeSubdomains"; - } - sss.processHeader( - Ci.nsISiteSecurityService.HEADER_HSTS, - uri, - header, - secInfo, - 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST - ); - for (let key of KEY_HASHES) { - header += `; pin-sha256="${key}"`; - } - sss.processHeader( - Ci.nsISiteSecurityService.HEADER_HPKP, - uri, - header, - secInfo, - 0, - Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST - ); - } - ); - } + let hstsEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HSTS); + let hpkpEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HPKP); - add_task(() => { - let hstsEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HSTS); - let hpkpEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HPKP); + checkSiteSecurityStateAttrs(hstsEntries); + checkSiteSecurityStateAttrs(hpkpEntries); - checkSiteSecurityStateAttrs(hstsEntries); - checkSiteSecurityStateAttrs(hpkpEntries); + checkSha256Keys(hpkpEntries); - checkSha256Keys(hpkpEntries); + sss.clearAll(); + hstsEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HSTS); + hpkpEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HPKP); - sss.clearAll(); - hstsEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HSTS); - hpkpEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HPKP); - - equal(hstsEntries.length, 0, "Should clear all HSTS entries"); - equal(hpkpEntries.length, 0, "Should clear all HPKP entries"); - }); -} - -function run_test() { - Services.prefs.setBoolPref( - "security.cert_pinning.process_headers_from_non_builtin_roots", - true - ); - Services.prefs.setIntPref( - "security.cert_pinning.max_max_age_seconds", - 20 * SECS_IN_A_WEEK - ); - - add_tls_server_setup("BadCertAndPinningServer", "bad_certs"); - - add_tests(); - - run_next_test(); + equal(hstsEntries.length, 0, "Should clear all HSTS entries"); + equal(hpkpEntries.length, 0, "Should clear all HPKP entries"); } diff --git a/security/manager/ssl/tests/unit/test_sss_eviction.js b/security/manager/ssl/tests/unit/test_sss_eviction.js index bb6582f41bea..e3b3d2a66473 100644 --- a/security/manager/ssl/tests/unit/test_sss_eviction.js +++ b/security/manager/ssl/tests/unit/test_sss_eviction.js @@ -58,9 +58,7 @@ function do_state_read(aSubject, aTopic, aData) { 0 ) ); - let secInfo = Cc[ - "@mozilla.org/security/transportsecurityinfo;1" - ].createInstance(Ci.nsITransportSecurityInfo); + let secInfo = new FakeTransportSecurityInfo(); for (let i = 0; i < 2000; i++) { let uri = Services.io.newURI("http://bad" + i + ".example.com"); gSSService.processHeader( diff --git a/security/manager/ssl/tests/unit/test_sss_originAttributes.js b/security/manager/ssl/tests/unit/test_sss_originAttributes.js index 150b82122ed1..a1de2edb29e5 100644 --- a/security/manager/ssl/tests/unit/test_sss_originAttributes.js +++ b/security/manager/ssl/tests/unit/test_sss_originAttributes.js @@ -30,13 +30,27 @@ Services.prefs.setBoolPref( true ); +let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB +); +addCertFromFile(certdb, "test_pinning_dynamic/pinningroot.pem", "CTu,CTu,CTu"); + let sss = Cc["@mozilla.org/ssservice;1"].getService(Ci.nsISiteSecurityService); -let host = "a.pinning.example.com"; +let host = "a.pinning2.example.com"; let uri = Services.io.newURI("https://" + host); +// This test re-uses certificates from pinning tests because that's easier and +// simpler than recreating new certificates, hence the slightly longer than +// necessary domain name. +let secInfo = new FakeTransportSecurityInfo( + constructCertFromFile( + "test_pinning_dynamic/a.pinning2.example.com-pinningroot.pem" + ) +); + // Check if originAttributes1 and originAttributes2 are isolated with respect // to HSTS/HPKP storage. -function doTest(secInfo, originAttributes1, originAttributes2, shouldShare) { +function doTest(originAttributes1, originAttributes2, shouldShare) { sss.clearAll(); for (let type of [ Ci.nsISiteSecurityService.HEADER_HSTS, @@ -125,7 +139,7 @@ function doTest(secInfo, originAttributes1, originAttributes2, shouldShare) { ); } -function testInvalidOriginAttributes(secInfo, originAttributes) { +function testInvalidOriginAttributes(originAttributes) { for (let type of [ Ci.nsISiteSecurityService.HEADER_HSTS, Ci.nsISiteSecurityService.HEADER_HPKP, @@ -174,49 +188,27 @@ function testInvalidOriginAttributes(secInfo, originAttributes) { ); } -function add_tests() { - sss.clearAll(); - - let secInfo = null; - add_connection_test( - "a.pinning.example.com", - PRErrorCodeSuccess, - undefined, - aSecInfo => { - secInfo = aSecInfo; - } - ); - - add_task(function() { - let originAttributesList = []; - for (let userContextId of [0, 1, 2]) { - for (let firstPartyDomain of ["", "foo.com", "bar.com"]) { - originAttributesList.push({ userContextId, firstPartyDomain }); - } - } - for (let attrs1 of originAttributesList) { - for (let attrs2 of originAttributesList) { - // SSS storage is not isolated by userContext - doTest( - secInfo, - attrs1, - attrs2, - attrs1.firstPartyDomain == attrs2.firstPartyDomain - ); - } - } - - testInvalidOriginAttributes(secInfo, undefined); - testInvalidOriginAttributes(secInfo, null); - testInvalidOriginAttributes(secInfo, 1); - testInvalidOriginAttributes(secInfo, "foo"); - }); -} - function run_test() { - add_tls_server_setup("BadCertAndPinningServer", "bad_certs"); + sss.clearAll(); + let originAttributesList = []; + for (let userContextId of [0, 1, 2]) { + for (let firstPartyDomain of ["", "foo.com", "bar.com"]) { + originAttributesList.push({ userContextId, firstPartyDomain }); + } + } + for (let attrs1 of originAttributesList) { + for (let attrs2 of originAttributesList) { + // SSS storage is not isolated by userContext + doTest( + attrs1, + attrs2, + attrs1.firstPartyDomain == attrs2.firstPartyDomain + ); + } + } - add_tests(); - - run_next_test(); + testInvalidOriginAttributes(undefined); + testInvalidOriginAttributes(null); + testInvalidOriginAttributes(1); + testInvalidOriginAttributes("foo"); } diff --git a/security/manager/ssl/tests/unit/test_sss_resetState.js b/security/manager/ssl/tests/unit/test_sss_resetState.js index 509fe2f2e750..b3849689468c 100644 --- a/security/manager/ssl/tests/unit/test_sss_resetState.js +++ b/security/manager/ssl/tests/unit/test_sss_resetState.js @@ -10,17 +10,42 @@ do_get_profile(); +var gCertDB = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB +); +const ROOT_CERT = addCertFromFile(gCertDB, "bad_certs/test-ca.pem", "CTu,,"); + var gSSService = Cc["@mozilla.org/ssservice;1"].getService( Ci.nsISiteSecurityService ); -function test_removeState(secInfo, type, flags) { +function run_test() { + Services.prefs.setBoolPref( + "security.cert_pinning.process_headers_from_non_builtin_roots", + true + ); + test_removeState(Ci.nsISiteSecurityService.HEADER_HSTS, 0); + test_removeState( + Ci.nsISiteSecurityService.HEADER_HSTS, + Ci.nsISocketProvider.NO_PERMANENT_STORAGE + ); + test_removeState(Ci.nsISiteSecurityService.HEADER_HPKP, 0); + test_removeState( + Ci.nsISiteSecurityService.HEADER_HPKP, + Ci.nsISocketProvider.NO_PERMANENT_STORAGE + ); +} + +function test_removeState(type, flags) { info(`running test_removeState(type=${type}, flags=${flags})`); const NON_ISSUED_KEY_HASH = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; const PINNING_ROOT_KEY_HASH = "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8="; const PINNING_HEADERS = `pin-sha256="${NON_ISSUED_KEY_HASH}"; pin-sha256="${PINNING_ROOT_KEY_HASH}"`; let headerAddendum = type == Ci.nsISiteSecurityService.HEADER_HPKP ? PINNING_HEADERS : ""; + let secInfo = new FakeTransportSecurityInfo( + constructCertFromFile("bad_certs/default-ee.pem") + ); // Simulate visiting a non-preloaded site by processing an HSTS or HPKP header // (depending on which type we were given), check that the HSTS/HPKP bit gets // set, simulate "forget about this site" (call removeState), and then check @@ -99,49 +124,3 @@ function test_removeState(secInfo, type, flags) { gSSService.resetState(type, preloadedURI, flags); ok(gSSService.isSecureURI(type, preloadedURI, flags)); } - -function add_tests() { - let secInfo = null; - add_connection_test( - "not-preloaded.example.com", - PRErrorCodeSuccess, - undefined, - aSecInfo => { - secInfo = aSecInfo; - } - ); - - add_task(() => { - test_removeState(secInfo, Ci.nsISiteSecurityService.HEADER_HSTS, 0); - test_removeState( - secInfo, - Ci.nsISiteSecurityService.HEADER_HSTS, - Ci.nsISocketProvider.NO_PERMANENT_STORAGE - ); - - test_removeState(secInfo, Ci.nsISiteSecurityService.HEADER_HPKP, 0); - test_removeState( - secInfo, - Ci.nsISiteSecurityService.HEADER_HPKP, - Ci.nsISocketProvider.NO_PERMANENT_STORAGE - ); - }); -} - -registerCleanupFunction(() => { - Services.prefs.clearUserPref( - "sercurity.cert_pinning.process_headers_from_non_builtin_roots" - ); -}); - -function run_test() { - Services.prefs.setBoolPref( - "security.cert_pinning.process_headers_from_non_builtin_roots", - true - ); - - add_tls_server_setup("BadCertAndPinningServer", "bad_certs"); - - add_tests(); - run_next_test(); -} diff --git a/security/manager/ssl/tests/unit/test_sss_sanitizeOnShutdown.js b/security/manager/ssl/tests/unit/test_sss_sanitizeOnShutdown.js index 2b4486634c67..422fa64fefd9 100644 --- a/security/manager/ssl/tests/unit/test_sss_sanitizeOnShutdown.js +++ b/security/manager/ssl/tests/unit/test_sss_sanitizeOnShutdown.js @@ -26,9 +26,7 @@ add_task(async function run_test() { let SSService = Cc["@mozilla.org/ssservice;1"].getService( Ci.nsISiteSecurityService ); - let secInfo = Cc[ - "@mozilla.org/security/transportsecurityinfo;1" - ].createInstance(Ci.nsITransportSecurityInfo); + let secInfo = new FakeTransportSecurityInfo(); let header = "max-age=50000"; SSService.processHeader( Ci.nsISiteSecurityService.HEADER_HSTS, diff --git a/security/manager/ssl/tests/unit/test_sss_savestate.js b/security/manager/ssl/tests/unit/test_sss_savestate.js index 5f676431db53..57ed639daadb 100644 --- a/security/manager/ssl/tests/unit/test_sss_savestate.js +++ b/security/manager/ssl/tests/unit/test_sss_savestate.js @@ -121,9 +121,7 @@ function run_test() { let maxAge = "max-age=" + i * 1000; // alternate setting includeSubdomains let includeSubdomains = i % 2 == 0 ? "; includeSubdomains" : ""; - let secInfo = Cc[ - "@mozilla.org/security/transportsecurityinfo;1" - ].createInstance(Ci.nsITransportSecurityInfo); + let secInfo = new FakeTransportSecurityInfo(); SSService.processHeader( Ci.nsISiteSecurityService.HEADER_HSTS, uris[uriIndex], diff --git a/security/manager/ssl/tests/unit/test_sts_fqdn.js b/security/manager/ssl/tests/unit/test_sts_fqdn.js index d8ecbf153015..78b3cabc86bc 100644 --- a/security/manager/ssl/tests/unit/test_sts_fqdn.js +++ b/security/manager/ssl/tests/unit/test_sts_fqdn.js @@ -16,9 +16,7 @@ function run_test() { // These cases are only relevant as long as bug 1118522 hasn't been fixed. ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri2, 0)); - let secInfo = Cc[ - "@mozilla.org/security/transportsecurityinfo;1" - ].createInstance(Ci.nsITransportSecurityInfo); + let secInfo = new FakeTransportSecurityInfo(); SSService.processHeader( Ci.nsISiteSecurityService.HEADER_HSTS, uri, diff --git a/security/manager/ssl/tests/unit/test_sts_ipv4_ipv6.js b/security/manager/ssl/tests/unit/test_sts_ipv4_ipv6.js index 1950d7b1bddb..aa3f10abbefb 100644 --- a/security/manager/ssl/tests/unit/test_sts_ipv4_ipv6.js +++ b/security/manager/ssl/tests/unit/test_sts_ipv4_ipv6.js @@ -1,9 +1,7 @@ "use strict"; function check_ip(s, v, ip) { - let secInfo = Cc[ - "@mozilla.org/security/transportsecurityinfo;1" - ].createInstance(Ci.nsITransportSecurityInfo); + let secInfo = new FakeTransportSecurityInfo(); let str = "https://"; if (v == 6) { diff --git a/security/manager/ssl/tests/unit/test_sts_parser.js b/security/manager/ssl/tests/unit/test_sts_parser.js index 8475d2e558b6..cd9abbd9b5fb 100644 --- a/security/manager/ssl/tests/unit/test_sts_parser.js +++ b/security/manager/ssl/tests/unit/test_sts_parser.js @@ -9,9 +9,7 @@ // STS parser tests let sss = Cc["@mozilla.org/ssservice;1"].getService(Ci.nsISiteSecurityService); -let secInfo = Cc[ - "@mozilla.org/security/transportsecurityinfo;1" -].createInstance(Ci.nsITransportSecurityInfo); +let secInfo = new FakeTransportSecurityInfo(); function testSuccess(header, expectedMaxAge, expectedIncludeSubdomains) { let dummyUri = Services.io.newURI("https://foo.com/bar.html"); diff --git a/security/manager/ssl/tests/unit/test_sts_preload_dynamic.js b/security/manager/ssl/tests/unit/test_sts_preload_dynamic.js index f66f13ddd988..d90ab600d232 100644 --- a/security/manager/ssl/tests/unit/test_sts_preload_dynamic.js +++ b/security/manager/ssl/tests/unit/test_sts_preload_dynamic.js @@ -16,9 +16,7 @@ function run_test() { let SSService = Cc["@mozilla.org/ssservice;1"].getService( Ci.nsISiteSecurityService ); - let secInfo = Cc[ - "@mozilla.org/security/transportsecurityinfo;1" - ].createInstance(Ci.nsITransportSecurityInfo); + let secInfo = new FakeTransportSecurityInfo(); let unlikelyHost = "highlyunlikely.example.com"; let uri = Services.io.newURI("https://" + unlikelyHost); let subDomainUri = Services.io.newURI("https://subdomain." + unlikelyHost); diff --git a/security/manager/ssl/tests/unit/test_sts_preloadlist_perwindowpb.js b/security/manager/ssl/tests/unit/test_sts_preloadlist_perwindowpb.js index 3f5b621e2a22..b29fb7b6595f 100644 --- a/security/manager/ssl/tests/unit/test_sts_preloadlist_perwindowpb.js +++ b/security/manager/ssl/tests/unit/test_sts_preloadlist_perwindowpb.js @@ -14,9 +14,7 @@ Observer.prototype = { }; var gObserver = new Observer(); -var secInfo = Cc[ - "@mozilla.org/security/transportsecurityinfo;1" -].createInstance(Ci.nsITransportSecurityInfo); +var secInfo = new FakeTransportSecurityInfo(); function cleanup() { Services.obs.removeObserver(gObserver, "last-pb-context-exited"); diff --git a/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertAndPinningServer.cpp b/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertAndPinningServer.cpp index b8e90041bd3a..c686f5e7f446 100644 --- a/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertAndPinningServer.cpp +++ b/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertAndPinningServer.cpp @@ -83,9 +83,6 @@ const BadCertAndPinningHost sBadCertAndPinningHosts[] = { "ee-from-missing-intermediate"}, {"imminently-distrusted.example.com", "ee-imminently-distrusted"}, {"localhost", "unknownissuer"}, - {"a.pinning.example.com", "default-ee"}, - {"b.pinning.example.com", "default-ee"}, - {"not-preloaded.example.com", "default-ee"}, {nullptr, nullptr}}; int32_t DoSNISocketConfigBySubjectCN(PRFileDesc* aFd, diff --git a/security/manager/ssl/tests/unit/xpcshell.ini b/security/manager/ssl/tests/unit/xpcshell.ini index 1e21e3a4abe9..d28e1bd97050 100644 --- a/security/manager/ssl/tests/unit/xpcshell.ini +++ b/security/manager/ssl/tests/unit/xpcshell.ini @@ -112,7 +112,6 @@ tags = blocklist psm run-sequentially = hardcoded ports [test_forget_about_site_security_headers.js] skip-if = toolkit == 'android' -run-sequentially = hardcoded ports [test_hash_algorithms.js] [test_hash_algorithms_wrap.js] # bug 1124289 - run_test_in_child violates the sandbox on android @@ -175,7 +174,6 @@ skip-if = os == 'win' || os == 'mac' run-sequentially = hardcoded ports [test_pinning_dynamic.js] [test_pinning_header_parsing.js] -run-sequentially = hardcoded ports [test_sdr.js] [test_sdr_preexisting.js] [test_sdr_preexisting_with_password.js] @@ -191,10 +189,8 @@ run-sequentially = hardcoded ports [test_ssl_status.js] run-sequentially = hardcoded ports [test_sss_enumerate.js] -run-sequentially = hardcoded ports [test_sss_eviction.js] [test_sss_originAttributes.js] -run-sequentially = hardcoded ports [test_sss_readstate.js] [test_sss_readstate_child.js] support-files = sss_readstate_child_worker.js @@ -204,7 +200,6 @@ skip-if = toolkit == 'android' [test_sss_readstate_garbage.js] [test_sss_readstate_huge.js] [test_sss_resetState.js] -run-sequentially = hardcoded ports [test_sss_savestate.js] [test_sss_sanitizeOnShutdown.js] firefox-appdir = browser