mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 23:35:34 +00:00
Backed out 3 changesets (bug 1715142) for causing build bustages. CLOSED TREE
Backed out changeset 7e67994f6a65 (bug 1715142) Backed out changeset f58d5156f332 (bug 1715142) Backed out changeset f8a7bd4519c6 (bug 1715142)
This commit is contained in:
parent
5b30ebbe89
commit
e4394b27a2
@ -15,6 +15,7 @@ add_task(async function test_star_redirect() {
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
NetUtil.newURI("http://example.com/"),
|
||||
0,
|
||||
Services.prefs.getBoolPref("privacy.partition.network_state")
|
||||
|
@ -685,9 +685,6 @@ var NetworkHelper = {
|
||||
const sss = Cc["@mozilla.org/ssservice;1"].getService(
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
const pkps = Cc[
|
||||
"@mozilla.org/security/publickeypinningservice;1"
|
||||
].getService(Ci.nsIPublicKeyPinningService);
|
||||
|
||||
// SiteSecurityService uses different storage if the channel is
|
||||
// private. Thus we must give isSecureURI correct flags or we
|
||||
@ -702,8 +699,8 @@ var NetworkHelper = {
|
||||
uri = Services.io.newURI("https://" + host);
|
||||
}
|
||||
|
||||
info.hsts = sss.isSecureURI(uri, flags);
|
||||
info.hpkp = pkps.hostHasPins(uri);
|
||||
info.hsts = sss.isSecureURI(sss.HEADER_HSTS, uri, flags);
|
||||
info.hpkp = sss.isSecureURI(sss.STATIC_PINNING, uri, flags);
|
||||
} else {
|
||||
DevToolsUtils.reportException(
|
||||
"NetworkHelper.parseSecurityInfo",
|
||||
|
@ -47,7 +47,7 @@ async function startTest()
|
||||
// Reset HSTS state.
|
||||
const gSSService = Cc["@mozilla.org/ssservice;1"].getService(Ci.nsISiteSecurityService);
|
||||
const uri = Services.io.newURI(TEST_CASES[0].url);
|
||||
gSSService.resetState(uri, 0);
|
||||
gSSService.resetState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -139,7 +139,6 @@
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIPromptCollection.h"
|
||||
#include "nsIPromptFactory.h"
|
||||
#include "nsIPublicKeyPinningService.h"
|
||||
#include "nsIReflowObserver.h"
|
||||
#include "nsIScriptChannel.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
@ -3715,18 +3714,21 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
||||
nsCOMPtr<nsISiteSecurityService> sss =
|
||||
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = sss->IsSecureURI(aURI, flags, attrsForHSTS, nullptr, nullptr,
|
||||
&isStsHost);
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
|
||||
attrsForHSTS, nullptr, nullptr, &isStsHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::STATIC_PINNING, aURI,
|
||||
flags, GetOriginAttributes(), nullptr, nullptr,
|
||||
&isPinnedHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
mozilla::dom::ContentChild* cc =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
cc->SendIsSecureURI(aURI, flags, attrsForHSTS, &isStsHost);
|
||||
cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
|
||||
attrsForHSTS, &isStsHost);
|
||||
cc->SendIsSecureURI(nsISiteSecurityService::STATIC_PINNING, aURI, flags,
|
||||
GetOriginAttributes(), &isPinnedHost);
|
||||
}
|
||||
nsCOMPtr<nsIPublicKeyPinningService> pkps =
|
||||
do_GetService(NS_PKPSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = pkps->HostHasPins(aURI, &isPinnedHost);
|
||||
|
||||
if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert",
|
||||
false)) {
|
||||
|
@ -341,7 +341,6 @@
|
||||
#include "nsIPermission.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsIPublicKeyPinningService.h"
|
||||
#include "nsIReferrerInfo.h"
|
||||
#include "nsIRefreshURI.h"
|
||||
#include "nsIRequest.h"
|
||||
@ -1891,22 +1890,23 @@ void Document::GetFailedCertSecurityInfo(FailedCertSecurityInfo& aInfo,
|
||||
if (XRE_IsContentProcess()) {
|
||||
ContentChild* cc = ContentChild::GetSingleton();
|
||||
MOZ_ASSERT(cc);
|
||||
cc->SendIsSecureURI(aURI, flags, attrs, &aInfo.mHasHSTS);
|
||||
cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags, attrs,
|
||||
&aInfo.mHasHSTS);
|
||||
cc->SendIsSecureURI(nsISiteSecurityService::STATIC_PINNING, aURI, flags,
|
||||
attrs, &aInfo.mHasHPKP);
|
||||
} else {
|
||||
nsCOMPtr<nsISiteSecurityService> sss =
|
||||
do_GetService(NS_SSSERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!sss)) {
|
||||
return;
|
||||
}
|
||||
Unused << NS_WARN_IF(NS_FAILED(sss->IsSecureURI(aURI, flags, attrs, nullptr,
|
||||
nullptr, &aInfo.mHasHSTS)));
|
||||
Unused << NS_WARN_IF(NS_FAILED(
|
||||
sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
|
||||
attrs, nullptr, nullptr, &aInfo.mHasHSTS)));
|
||||
Unused << NS_WARN_IF(NS_FAILED(
|
||||
sss->IsSecureURI(nsISiteSecurityService::STATIC_PINNING, aURI, flags,
|
||||
attrs, nullptr, nullptr, &aInfo.mHasHPKP)));
|
||||
}
|
||||
nsCOMPtr<nsIPublicKeyPinningService> pkps =
|
||||
do_GetService(NS_PKPSERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!pkps)) {
|
||||
return;
|
||||
}
|
||||
Unused << NS_WARN_IF(NS_FAILED(pkps->HostHasPins(aURI, &aInfo.mHasHPKP)));
|
||||
}
|
||||
|
||||
bool Document::AllowDeprecatedTls() {
|
||||
|
@ -4399,7 +4399,7 @@ mozilla::ipc::IPCResult ContentParent::RecvSetURITitle(nsIURI* uri,
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvIsSecureURI(
|
||||
nsIURI* aURI, const uint32_t& aFlags,
|
||||
const uint32_t& aType, nsIURI* aURI, const uint32_t& aFlags,
|
||||
const OriginAttributes& aOriginAttributes, bool* aIsSecureURI) {
|
||||
nsCOMPtr<nsISiteSecurityService> sss(do_GetService(NS_SSSERVICE_CONTRACTID));
|
||||
if (!sss) {
|
||||
@ -4408,8 +4408,8 @@ mozilla::ipc::IPCResult ContentParent::RecvIsSecureURI(
|
||||
if (!aURI) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
nsresult rv = sss->IsSecureURI(aURI, aFlags, aOriginAttributes, nullptr,
|
||||
nullptr, aIsSecureURI);
|
||||
nsresult rv = sss->IsSecureURI(aType, aURI, aFlags, aOriginAttributes,
|
||||
nullptr, nullptr, aIsSecureURI);
|
||||
if (NS_FAILED(rv)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
@ -941,7 +941,7 @@ class ContentParent final
|
||||
const uint32_t& chromeFlags);
|
||||
|
||||
mozilla::ipc::IPCResult RecvIsSecureURI(
|
||||
nsIURI* aURI, const uint32_t& aFlags,
|
||||
const uint32_t& aType, nsIURI* aURI, const uint32_t& aFlags,
|
||||
const OriginAttributes& aOriginAttributes, bool* aIsSecureURI);
|
||||
|
||||
mozilla::ipc::IPCResult RecvAccumulateMixedContentHSTS(
|
||||
|
@ -998,7 +998,7 @@ parent:
|
||||
|
||||
async InitCrashReporter(NativeThreadId tid);
|
||||
|
||||
sync IsSecureURI(nsIURI aURI, uint32_t aFlags,
|
||||
sync IsSecureURI(uint32_t aType, nsIURI aURI, uint32_t aFlags,
|
||||
OriginAttributes aOriginAttributes)
|
||||
returns (bool isSecureURI);
|
||||
|
||||
|
@ -979,7 +979,8 @@ void nsMixedContentBlocker::AccumulateMixedContentHSTS(
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
rv = sss->IsSecureURI(aURI, 0, aOriginAttributes, nullptr, nullptr, &hsts);
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, 0,
|
||||
aOriginAttributes, nullptr, nullptr, &hsts);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
@ -10596,13 +10596,6 @@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# Disable preloaded static key pins by default.
|
||||
- name: security.cert_pinning.enforcement_level
|
||||
type: ReleaseAcquireAtomicUint32
|
||||
value: 0
|
||||
mirror: always
|
||||
do_not_use_directly: true
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Prefs starting with "slider."
|
||||
#---------------------------------------------------------------------------
|
||||
|
@ -156,6 +156,11 @@ pref("security.webauth.webauthn_enable_softtoken", false);
|
||||
pref("security.xfocsp.errorReporting.enabled", true);
|
||||
pref("security.xfocsp.errorReporting.automatic", false);
|
||||
|
||||
// Impose a maximum age on HPKP headers, to avoid sites getting permanently
|
||||
// blacking themselves out by setting a bad pin. (60 days by default)
|
||||
// https://tools.ietf.org/html/rfc7469#section-4.1
|
||||
pref("security.cert_pinning.max_max_age_seconds", 5184000);
|
||||
|
||||
// 0: Disable CRLite entirely
|
||||
// 1: Enable and check revocations via CRLite, but only collect telemetry
|
||||
// 2: Enable and enforce revocations via CRLite
|
||||
@ -2163,6 +2168,22 @@ pref("security.ssl.enable_ocsp_must_staple", true);
|
||||
pref("security.insecure_field_warning.contextual.enabled", false);
|
||||
pref("security.insecure_field_warning.ignore_local_ip_address", true);
|
||||
|
||||
// Disable pinning checks by default.
|
||||
pref("security.cert_pinning.enforcement_level", 0);
|
||||
// Do not process hpkp headers rooted by not built in roots by default.
|
||||
// This is to prevent accidental pinning from MITM devices and is used
|
||||
// for tests.
|
||||
pref("security.cert_pinning.process_headers_from_non_builtin_roots", false);
|
||||
|
||||
// Controls whether or not HPKP (the HTTP Public Key Pinning header) is enabled.
|
||||
// If true, the header is processed and collected HPKP information is consulted
|
||||
// when looking for pinning information.
|
||||
// If false, the header is not processed and collected HPKP information is not
|
||||
// consulted when looking for pinning information. Preloaded pins are not
|
||||
// affected by this preference.
|
||||
// Default: false
|
||||
pref("security.cert_pinning.hpkp.enabled", false);
|
||||
|
||||
// Remote settings preferences
|
||||
// Note: if you change this, make sure to also review security.onecrl.maximum_staleness_in_seconds
|
||||
pref("services.settings.poll_interval", 86400); // 24H
|
||||
|
@ -243,6 +243,7 @@ static const char* gCallbackSecurityPrefs[] = {
|
||||
"security.ssl.enable_ocsp_stapling",
|
||||
"security.ssl.enable_ocsp_must_staple",
|
||||
"security.pki.certificate_transparency.mode",
|
||||
"security.cert_pinning.enforcement_level",
|
||||
"security.pki.name_matching_mode",
|
||||
nullptr,
|
||||
};
|
||||
@ -389,6 +390,7 @@ void nsIOService::OnTLSPrefChange(const char* aPref, void* aSelf) {
|
||||
} else if (pref.EqualsLiteral("security.ssl.enable_ocsp_stapling") ||
|
||||
pref.EqualsLiteral("security.ssl.enable_ocsp_must_staple") ||
|
||||
pref.EqualsLiteral("security.pki.certificate_transparency.mode") ||
|
||||
pref.EqualsLiteral("security.cert_pinning.enforcement_level") ||
|
||||
pref.EqualsLiteral("security.pki.name_matching_mode")) {
|
||||
SetValidationOptionsCommon();
|
||||
}
|
||||
|
@ -2964,9 +2964,9 @@ nsresult NS_ShouldSecureUpgrade(
|
||||
resultCallback{std::move(aResultCallback)}]() mutable {
|
||||
uint32_t hstsSource = 0;
|
||||
bool isStsHost = false;
|
||||
nsresult rv =
|
||||
service->IsSecureURI(uri, flags, originAttributes, nullptr,
|
||||
&hstsSource, &isStsHost);
|
||||
nsresult rv = service->IsSecureURI(
|
||||
nsISiteSecurityService::HEADER_HSTS, uri, flags,
|
||||
originAttributes, nullptr, &hstsSource, &isStsHost);
|
||||
|
||||
// Successfully get the result from |IsSecureURI| implies that
|
||||
// the storage is ready to read.
|
||||
@ -2985,8 +2985,9 @@ nsresult NS_ShouldSecureUpgrade(
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult rv = sss->IsSecureURI(aURI, flags, aOriginAttributes, nullptr,
|
||||
&hstsSource, &isStsHost);
|
||||
nsresult rv =
|
||||
sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
|
||||
aOriginAttributes, nullptr, &hstsSource, &isStsHost);
|
||||
|
||||
// if the SSS check fails, it's likely because this load is on a
|
||||
// malformed URI or something else in the setup is wrong, so any error
|
||||
|
@ -1785,7 +1785,8 @@ nsresult nsHttpChannel::ProcessHSTSHeader(nsITransportSecurityInfo* aSecInfo,
|
||||
|
||||
uint32_t failureResult;
|
||||
uint32_t headerSource = nsISiteSecurityService::SOURCE_ORGANIC_REQUEST;
|
||||
rv = sss->ProcessHeader(mURI, securityHeader, aSecInfo, aFlags, headerSource,
|
||||
rv = sss->ProcessHeader(nsISiteSecurityService::HEADER_HSTS, mURI,
|
||||
securityHeader, aSecInfo, aFlags, headerSource,
|
||||
originAttributes, nullptr, nullptr, &failureResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsAutoString consoleErrorCategory(u"Invalid HSTS Headers"_ns);
|
||||
|
@ -2436,8 +2436,9 @@ nsresult nsHttpHandler::SpeculativeConnectInternal(
|
||||
aURI, originAttributes);
|
||||
|
||||
nsCOMPtr<nsIURI> clone;
|
||||
if (NS_SUCCEEDED(sss->IsSecureURI(aURI, flags, originAttributes, nullptr,
|
||||
nullptr, &isStsHost)) &&
|
||||
if (NS_SUCCEEDED(sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI,
|
||||
flags, originAttributes, nullptr, nullptr,
|
||||
&isStsHost)) &&
|
||||
isStsHost) {
|
||||
if (NS_SUCCEEDED(NS_GetSecureUpgradedURI(aURI, getter_AddRefs(clone)))) {
|
||||
aURI = clone.get();
|
||||
|
@ -88,7 +88,8 @@ void CertificateTransparencyInfo::Reset() {
|
||||
CertVerifier::CertVerifier(OcspDownloadConfig odc, OcspStrictConfig osc,
|
||||
mozilla::TimeDuration ocspTimeoutSoft,
|
||||
mozilla::TimeDuration ocspTimeoutHard,
|
||||
uint32_t certShortLifetimeInDays, SHA1Mode sha1Mode,
|
||||
uint32_t certShortLifetimeInDays,
|
||||
PinningMode pinningMode, SHA1Mode sha1Mode,
|
||||
BRNameMatchingPolicy::Mode nameMatchingMode,
|
||||
NetscapeStepUpPolicy netscapeStepUpPolicy,
|
||||
CertificateTransparencyMode ctMode,
|
||||
@ -100,6 +101,7 @@ CertVerifier::CertVerifier(OcspDownloadConfig odc, OcspStrictConfig osc,
|
||||
mOCSPTimeoutSoft(ocspTimeoutSoft),
|
||||
mOCSPTimeoutHard(ocspTimeoutHard),
|
||||
mCertShortLifetimeInDays(certShortLifetimeInDays),
|
||||
mPinningMode(pinningMode),
|
||||
mSHA1Mode(sha1Mode),
|
||||
mNameMatchingMode(nameMatchingMode),
|
||||
mNetscapeStepUpPolicy(netscapeStepUpPolicy),
|
||||
@ -562,9 +564,9 @@ Result CertVerifier::VerifyCert(
|
||||
// just use trustEmail as it is the closest alternative.
|
||||
NSSCertDBTrustDomain trustDomain(
|
||||
trustEmail, defaultOCSPFetching, mOCSPCache, pinArg, mOCSPTimeoutSoft,
|
||||
mOCSPTimeoutHard, mCertShortLifetimeInDays, MIN_RSA_BITS_WEAK,
|
||||
ValidityCheckingMode::CheckingOff, SHA1Mode::Allowed,
|
||||
NetscapeStepUpPolicy::NeverMatch, mCRLiteMode,
|
||||
mOCSPTimeoutHard, mCertShortLifetimeInDays, pinningDisabled,
|
||||
MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff,
|
||||
SHA1Mode::Allowed, NetscapeStepUpPolicy::NeverMatch, mCRLiteMode,
|
||||
mCRLiteCTMergeDelaySeconds, originAttributes, mThirdPartyRootInputs,
|
||||
mThirdPartyIntermediateInputs, extraCertificates, builtChain, nullptr,
|
||||
nullptr);
|
||||
@ -635,10 +637,10 @@ Result CertVerifier::VerifyCert(
|
||||
|
||||
NSSCertDBTrustDomain trustDomain(
|
||||
trustSSL, evOCSPFetching, mOCSPCache, pinArg, mOCSPTimeoutSoft,
|
||||
mOCSPTimeoutHard, mCertShortLifetimeInDays, MIN_RSA_BITS,
|
||||
ValidityCheckingMode::CheckForEV, sha1ModeConfigurations[i],
|
||||
mNetscapeStepUpPolicy, mCRLiteMode, mCRLiteCTMergeDelaySeconds,
|
||||
originAttributes, mThirdPartyRootInputs,
|
||||
mOCSPTimeoutHard, mCertShortLifetimeInDays, mPinningMode,
|
||||
MIN_RSA_BITS, ValidityCheckingMode::CheckForEV,
|
||||
sha1ModeConfigurations[i], mNetscapeStepUpPolicy, mCRLiteMode,
|
||||
mCRLiteCTMergeDelaySeconds, originAttributes, mThirdPartyRootInputs,
|
||||
mThirdPartyIntermediateInputs, extraCertificates, builtChain,
|
||||
pinningTelemetryInfo, hostname);
|
||||
rv = BuildCertChainForOneKeyUsage(
|
||||
@ -718,11 +720,12 @@ Result CertVerifier::VerifyCert(
|
||||
NSSCertDBTrustDomain trustDomain(
|
||||
trustSSL, defaultOCSPFetching, mOCSPCache, pinArg,
|
||||
mOCSPTimeoutSoft, mOCSPTimeoutHard, mCertShortLifetimeInDays,
|
||||
keySizeOptions[i], ValidityCheckingMode::CheckingOff,
|
||||
sha1ModeConfigurations[j], mNetscapeStepUpPolicy, mCRLiteMode,
|
||||
mCRLiteCTMergeDelaySeconds, originAttributes,
|
||||
mThirdPartyRootInputs, mThirdPartyIntermediateInputs,
|
||||
extraCertificates, builtChain, pinningTelemetryInfo, hostname);
|
||||
mPinningMode, keySizeOptions[i],
|
||||
ValidityCheckingMode::CheckingOff, sha1ModeConfigurations[j],
|
||||
mNetscapeStepUpPolicy, mCRLiteMode, mCRLiteCTMergeDelaySeconds,
|
||||
originAttributes, mThirdPartyRootInputs,
|
||||
mThirdPartyIntermediateInputs, extraCertificates, builtChain,
|
||||
pinningTelemetryInfo, hostname);
|
||||
rv = BuildCertChainForOneKeyUsage(
|
||||
trustDomain, certDER, time,
|
||||
KeyUsage::digitalSignature, //(EC)DHE
|
||||
@ -787,10 +790,10 @@ Result CertVerifier::VerifyCert(
|
||||
case certificateUsageSSLCA: {
|
||||
NSSCertDBTrustDomain trustDomain(
|
||||
trustSSL, defaultOCSPFetching, mOCSPCache, pinArg, mOCSPTimeoutSoft,
|
||||
mOCSPTimeoutHard, mCertShortLifetimeInDays, MIN_RSA_BITS_WEAK,
|
||||
ValidityCheckingMode::CheckingOff, SHA1Mode::Allowed,
|
||||
mNetscapeStepUpPolicy, mCRLiteMode, mCRLiteCTMergeDelaySeconds,
|
||||
originAttributes, mThirdPartyRootInputs,
|
||||
mOCSPTimeoutHard, mCertShortLifetimeInDays, pinningDisabled,
|
||||
MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff,
|
||||
SHA1Mode::Allowed, mNetscapeStepUpPolicy, mCRLiteMode,
|
||||
mCRLiteCTMergeDelaySeconds, originAttributes, mThirdPartyRootInputs,
|
||||
mThirdPartyIntermediateInputs, extraCertificates, builtChain, nullptr,
|
||||
nullptr);
|
||||
rv = BuildCertChain(trustDomain, certDER, time, EndEntityOrCA::MustBeCA,
|
||||
@ -802,9 +805,9 @@ Result CertVerifier::VerifyCert(
|
||||
case certificateUsageEmailSigner: {
|
||||
NSSCertDBTrustDomain trustDomain(
|
||||
trustEmail, defaultOCSPFetching, mOCSPCache, pinArg, mOCSPTimeoutSoft,
|
||||
mOCSPTimeoutHard, mCertShortLifetimeInDays, MIN_RSA_BITS_WEAK,
|
||||
ValidityCheckingMode::CheckingOff, SHA1Mode::Allowed,
|
||||
NetscapeStepUpPolicy::NeverMatch, mCRLiteMode,
|
||||
mOCSPTimeoutHard, mCertShortLifetimeInDays, pinningDisabled,
|
||||
MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff,
|
||||
SHA1Mode::Allowed, NetscapeStepUpPolicy::NeverMatch, mCRLiteMode,
|
||||
mCRLiteCTMergeDelaySeconds, originAttributes, mThirdPartyRootInputs,
|
||||
mThirdPartyIntermediateInputs, extraCertificates, builtChain, nullptr,
|
||||
nullptr);
|
||||
@ -827,9 +830,9 @@ Result CertVerifier::VerifyCert(
|
||||
// based on the result of the verification(s).
|
||||
NSSCertDBTrustDomain trustDomain(
|
||||
trustEmail, defaultOCSPFetching, mOCSPCache, pinArg, mOCSPTimeoutSoft,
|
||||
mOCSPTimeoutHard, mCertShortLifetimeInDays, MIN_RSA_BITS_WEAK,
|
||||
ValidityCheckingMode::CheckingOff, SHA1Mode::Allowed,
|
||||
NetscapeStepUpPolicy::NeverMatch, mCRLiteMode,
|
||||
mOCSPTimeoutHard, mCertShortLifetimeInDays, pinningDisabled,
|
||||
MIN_RSA_BITS_WEAK, ValidityCheckingMode::CheckingOff,
|
||||
SHA1Mode::Allowed, NetscapeStepUpPolicy::NeverMatch, mCRLiteMode,
|
||||
mCRLiteCTMergeDelaySeconds, originAttributes, mThirdPartyRootInputs,
|
||||
mThirdPartyIntermediateInputs, extraCertificates, builtChain, nullptr,
|
||||
nullptr);
|
||||
|
@ -195,6 +195,13 @@ class CertVerifier {
|
||||
/*optional out*/ CertificateTransparencyInfo* ctInfo = nullptr,
|
||||
/*optional out*/ bool* isBuiltCertChainRootBuiltInRoot = nullptr);
|
||||
|
||||
enum PinningMode {
|
||||
pinningDisabled = 0,
|
||||
pinningAllowUserCAMITM = 1,
|
||||
pinningStrict = 2,
|
||||
pinningEnforceTestMode = 3
|
||||
};
|
||||
|
||||
enum class SHA1Mode {
|
||||
Allowed = 0,
|
||||
Forbidden = 1,
|
||||
@ -217,8 +224,8 @@ class CertVerifier {
|
||||
CertVerifier(OcspDownloadConfig odc, OcspStrictConfig osc,
|
||||
mozilla::TimeDuration ocspTimeoutSoft,
|
||||
mozilla::TimeDuration ocspTimeoutHard,
|
||||
uint32_t certShortLifetimeInDays, SHA1Mode sha1Mode,
|
||||
BRNameMatchingPolicy::Mode nameMatchingMode,
|
||||
uint32_t certShortLifetimeInDays, PinningMode pinningMode,
|
||||
SHA1Mode sha1Mode, BRNameMatchingPolicy::Mode nameMatchingMode,
|
||||
NetscapeStepUpPolicy netscapeStepUpPolicy,
|
||||
CertificateTransparencyMode ctMode, CRLiteMode crliteMode,
|
||||
uint64_t crliteCTMergeDelaySeconds,
|
||||
@ -232,6 +239,7 @@ class CertVerifier {
|
||||
const mozilla::TimeDuration mOCSPTimeoutSoft;
|
||||
const mozilla::TimeDuration mOCSPTimeoutHard;
|
||||
const uint32_t mCertShortLifetimeInDays;
|
||||
const PinningMode mPinningMode;
|
||||
const SHA1Mode mSHA1Mode;
|
||||
const BRNameMatchingPolicy::Mode mNameMatchingMode;
|
||||
const NetscapeStepUpPolicy mNetscapeStepUpPolicy;
|
||||
@ -268,9 +276,9 @@ class CertVerifier {
|
||||
};
|
||||
|
||||
mozilla::pkix::Result IsCertBuiltInRoot(CERTCertificate* cert, bool& result);
|
||||
mozilla::pkix::Result CertListContainsExpectedKeys(const CERTCertList* certList,
|
||||
const char* hostname,
|
||||
mozilla::pkix::Time time);
|
||||
mozilla::pkix::Result CertListContainsExpectedKeys(
|
||||
const CERTCertList* certList, const char* hostname,
|
||||
mozilla::pkix::Time time, CertVerifier::PinningMode pinningMode);
|
||||
|
||||
} // namespace psm
|
||||
} // namespace mozilla
|
||||
|
@ -66,9 +66,10 @@ NSSCertDBTrustDomain::NSSCertDBTrustDomain(
|
||||
OCSPCache& ocspCache,
|
||||
/*optional but shouldn't be*/ void* pinArg, TimeDuration ocspTimeoutSoft,
|
||||
TimeDuration ocspTimeoutHard, uint32_t certShortLifetimeInDays,
|
||||
unsigned int minRSABits, ValidityCheckingMode validityCheckingMode,
|
||||
CertVerifier::SHA1Mode sha1Mode, NetscapeStepUpPolicy netscapeStepUpPolicy,
|
||||
CRLiteMode crliteMode, uint64_t crliteCTMergeDelaySeconds,
|
||||
CertVerifier::PinningMode pinningMode, unsigned int minRSABits,
|
||||
ValidityCheckingMode validityCheckingMode, CertVerifier::SHA1Mode sha1Mode,
|
||||
NetscapeStepUpPolicy netscapeStepUpPolicy, CRLiteMode crliteMode,
|
||||
uint64_t crliteCTMergeDelaySeconds,
|
||||
const OriginAttributes& originAttributes,
|
||||
const Vector<Input>& thirdPartyRootInputs,
|
||||
const Vector<Input>& thirdPartyIntermediateInputs,
|
||||
@ -83,6 +84,7 @@ NSSCertDBTrustDomain::NSSCertDBTrustDomain(
|
||||
mOCSPTimeoutSoft(ocspTimeoutSoft),
|
||||
mOCSPTimeoutHard(ocspTimeoutHard),
|
||||
mCertShortLifetimeInDays(certShortLifetimeInDays),
|
||||
mPinningMode(pinningMode),
|
||||
mMinRSABits(minRSABits),
|
||||
mValidityCheckingMode(validityCheckingMode),
|
||||
mSHA1Mode(sha1Mode),
|
||||
@ -1184,9 +1186,16 @@ Result NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time,
|
||||
if (NS_FAILED(nsrv)) {
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
bool skipPinningChecksBecauseOfMITMMode =
|
||||
(!isBuiltInRoot && mPinningMode == CertVerifier::pinningAllowUserCAMITM);
|
||||
// If mHostname isn't set, we're not verifying in the context of a TLS
|
||||
// handshake, so don't verify key pinning in those cases.
|
||||
if (mHostname) {
|
||||
// handshake, so don't verify HPKP in those cases.
|
||||
if (mHostname && (mPinningMode != CertVerifier::pinningDisabled) &&
|
||||
!skipPinningChecksBecauseOfMITMMode) {
|
||||
bool enforceTestMode =
|
||||
(mPinningMode == CertVerifier::pinningEnforceTestMode);
|
||||
bool chainHasValidPins;
|
||||
|
||||
nsTArray<Span<const uint8_t>> derCertSpanList;
|
||||
size_t numCerts = certArray.GetLength();
|
||||
for (size_t i = numCerts; i > 0; --i) {
|
||||
@ -1197,10 +1206,9 @@ Result NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time,
|
||||
derCertSpanList.EmplaceBack(der->UnsafeGetData(), der->GetLength());
|
||||
}
|
||||
|
||||
bool chainHasValidPins;
|
||||
nsrv = PublicKeyPinningService::ChainHasValidPins(
|
||||
derCertSpanList, mHostname, time, isBuiltInRoot, chainHasValidPins,
|
||||
mPinningTelemetryInfo);
|
||||
derCertSpanList, mHostname, time, enforceTestMode, mOriginAttributes,
|
||||
chainHasValidPins, mPinningTelemetryInfo);
|
||||
if (NS_FAILED(nsrv)) {
|
||||
return Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
|
@ -128,7 +128,8 @@ class NSSCertDBTrustDomain : public mozilla::pkix::TrustDomain {
|
||||
SECTrustType certDBTrustType, OCSPFetching ocspFetching,
|
||||
OCSPCache& ocspCache, void* pinArg, mozilla::TimeDuration ocspTimeoutSoft,
|
||||
mozilla::TimeDuration ocspTimeoutHard, uint32_t certShortLifetimeInDays,
|
||||
unsigned int minRSABits, ValidityCheckingMode validityCheckingMode,
|
||||
CertVerifier::PinningMode pinningMode, unsigned int minRSABits,
|
||||
ValidityCheckingMode validityCheckingMode,
|
||||
CertVerifier::SHA1Mode sha1Mode,
|
||||
NetscapeStepUpPolicy netscapeStepUpPolicy, CRLiteMode crliteMode,
|
||||
uint64_t crliteCTMergeDelaySeconds,
|
||||
@ -246,6 +247,7 @@ class NSSCertDBTrustDomain : public mozilla::pkix::TrustDomain {
|
||||
const mozilla::TimeDuration mOCSPTimeoutSoft;
|
||||
const mozilla::TimeDuration mOCSPTimeoutHard;
|
||||
const uint32_t mCertShortLifetimeInDays;
|
||||
CertVerifier::PinningMode mPinningMode;
|
||||
const unsigned int mMinRSABits;
|
||||
ValidityCheckingMode mValidityCheckingMode;
|
||||
CertVerifier::SHA1Mode mSHA1Mode;
|
||||
|
@ -202,26 +202,34 @@ CommonSocketControl::IsAcceptableForHost(const nsACString& hostname,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsTArray<nsTArray<uint8_t>> rawDerCertList;
|
||||
nsTArray<Span<const uint8_t>> derCertSpanList;
|
||||
for (const auto& cert : mSucceededCertChain) {
|
||||
rawDerCertList.EmplaceBack();
|
||||
nsresult nsrv = cert->GetRawDER(rawDerCertList.LastElement());
|
||||
if (NS_FAILED(nsrv)) {
|
||||
return nsrv;
|
||||
}
|
||||
derCertSpanList.EmplaceBack(rawDerCertList.LastElement());
|
||||
}
|
||||
bool chainHasValidPins;
|
||||
nsresult nsrv = mozilla::psm::PublicKeyPinningService::ChainHasValidPins(
|
||||
derCertSpanList, PromiseFlatCString(hostname).BeginReading(), Now(),
|
||||
mIsBuiltCertChainRootBuiltInRoot, chainHasValidPins, nullptr);
|
||||
if (NS_FAILED(nsrv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
mozilla::psm::CertVerifier::PinningMode pinningMode =
|
||||
mozilla::psm::PublicSSLState()->PinningMode();
|
||||
if (pinningMode != mozilla::psm::CertVerifier::pinningDisabled) {
|
||||
bool chainHasValidPins;
|
||||
bool enforceTestMode =
|
||||
(pinningMode == mozilla::psm::CertVerifier::pinningEnforceTestMode);
|
||||
|
||||
if (!chainHasValidPins) {
|
||||
return NS_OK;
|
||||
nsTArray<nsTArray<uint8_t>> rawDerCertList;
|
||||
nsTArray<Span<const uint8_t>> derCertSpanList;
|
||||
for (const auto& cert : mSucceededCertChain) {
|
||||
rawDerCertList.EmplaceBack();
|
||||
nsresult nsrv = cert->GetRawDER(rawDerCertList.LastElement());
|
||||
if (NS_FAILED(nsrv)) {
|
||||
return nsrv;
|
||||
}
|
||||
derCertSpanList.EmplaceBack(rawDerCertList.LastElement());
|
||||
}
|
||||
|
||||
nsresult nsrv = mozilla::psm::PublicKeyPinningService::ChainHasValidPins(
|
||||
derCertSpanList, PromiseFlatCString(hostname).BeginReading(), Now(),
|
||||
enforceTestMode, GetOriginAttributes(lock), chainHasValidPins, nullptr);
|
||||
if (NS_FAILED(nsrv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!chainHasValidPins) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// All tests pass
|
||||
|
@ -11,11 +11,9 @@
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Span.h"
|
||||
#include "mozilla/StaticPrefs_security.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsDependentString.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsSiteSecurityService.h"
|
||||
#include "mozpkix/pkixtypes.h"
|
||||
#include "mozpkix/pkixutil.h"
|
||||
#include "seccomon.h"
|
||||
@ -29,32 +27,6 @@ using namespace mozilla::psm;
|
||||
|
||||
LazyLogModule gPublicKeyPinningLog("PublicKeyPinningService");
|
||||
|
||||
NS_IMPL_ISUPPORTS(PublicKeyPinningService, nsIPublicKeyPinningService)
|
||||
|
||||
enum class PinningMode : uint32_t {
|
||||
Disabled = 0,
|
||||
AllowUserCAMITM = 1,
|
||||
Strict = 2,
|
||||
EnforceTestMode = 3
|
||||
};
|
||||
|
||||
PinningMode GetPinningMode() {
|
||||
PinningMode pinningMode = static_cast<PinningMode>(
|
||||
StaticPrefs::security_cert_pinning_enforcement_level_DoNotUseDirectly());
|
||||
switch (pinningMode) {
|
||||
case PinningMode::Disabled:
|
||||
return PinningMode::Disabled;
|
||||
case PinningMode::AllowUserCAMITM:
|
||||
return PinningMode::AllowUserCAMITM;
|
||||
case PinningMode::Strict:
|
||||
return PinningMode::Strict;
|
||||
case PinningMode::EnforceTestMode:
|
||||
return PinningMode::EnforceTestMode;
|
||||
default:
|
||||
return PinningMode::Disabled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Computes in the location specified by base64Out the SHA256 digest
|
||||
of the DER Encoded subject Public Key Info for the given cert
|
||||
@ -189,6 +161,7 @@ static void ValidatePinningPreloadList() {
|
||||
// information that is valid for the given host at the given time.
|
||||
static nsresult FindPinningInformation(
|
||||
const char* hostname, mozilla::pkix::Time time,
|
||||
const OriginAttributes& originAttributes,
|
||||
/*out*/ const TransportSecurityPreload*& staticFingerprints) {
|
||||
#ifdef DEBUG
|
||||
ValidatePinningPreloadList();
|
||||
@ -244,6 +217,7 @@ static nsresult FindPinningInformation(
|
||||
static nsresult CheckPinsForHostname(
|
||||
const nsTArray<Span<const uint8_t>>& certList, const char* hostname,
|
||||
bool enforceTestMode, mozilla::pkix::Time time,
|
||||
const OriginAttributes& originAttributes,
|
||||
/*out*/ bool& chainHasValidPins,
|
||||
/*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo) {
|
||||
chainHasValidPins = false;
|
||||
@ -255,10 +229,8 @@ static nsresult CheckPinsForHostname(
|
||||
}
|
||||
|
||||
const TransportSecurityPreload* staticFingerprints = nullptr;
|
||||
nsresult rv = FindPinningInformation(hostname, time, staticFingerprints);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsresult rv = FindPinningInformation(hostname, time, originAttributes,
|
||||
staticFingerprints);
|
||||
// If we have no pinning information, the certificate chain trivially
|
||||
// validates with respect to pinning.
|
||||
if (!staticFingerprints) {
|
||||
@ -327,16 +299,10 @@ static nsresult CheckPinsForHostname(
|
||||
|
||||
nsresult PublicKeyPinningService::ChainHasValidPins(
|
||||
const nsTArray<Span<const uint8_t>>& certList, const char* hostname,
|
||||
mozilla::pkix::Time time, bool isBuiltInRoot,
|
||||
mozilla::pkix::Time time, bool enforceTestMode,
|
||||
const OriginAttributes& originAttributes,
|
||||
/*out*/ bool& chainHasValidPins,
|
||||
/*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo) {
|
||||
PinningMode pinningMode(GetPinningMode());
|
||||
if (pinningMode == PinningMode::Disabled ||
|
||||
(!isBuiltInRoot && pinningMode == PinningMode::AllowUserCAMITM)) {
|
||||
chainHasValidPins = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
chainHasValidPins = false;
|
||||
if (certList.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
@ -345,38 +311,25 @@ nsresult PublicKeyPinningService::ChainHasValidPins(
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
nsAutoCString canonicalizedHostname(CanonicalizeHostname(hostname));
|
||||
bool enforceTestMode = pinningMode == PinningMode::EnforceTestMode;
|
||||
return CheckPinsForHostname(certList, canonicalizedHostname.get(),
|
||||
enforceTestMode, time, chainHasValidPins,
|
||||
pinningTelemetryInfo);
|
||||
enforceTestMode, time, originAttributes,
|
||||
chainHasValidPins, pinningTelemetryInfo);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PublicKeyPinningService::HostHasPins(nsIURI* aURI, bool* hostHasPins) {
|
||||
NS_ENSURE_ARG(aURI);
|
||||
NS_ENSURE_ARG(hostHasPins);
|
||||
*hostHasPins = false;
|
||||
PinningMode pinningMode(GetPinningMode());
|
||||
if (pinningMode == PinningMode::Disabled) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsAutoCString hostname;
|
||||
nsresult rv = nsSiteSecurityService::GetHost(aURI, hostname);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (nsSiteSecurityService::HostIsIPAddress(hostname)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PublicKeyPinningService::HostHasPins(
|
||||
const char* hostname, mozilla::pkix::Time time, bool enforceTestMode,
|
||||
const OriginAttributes& originAttributes,
|
||||
/*out*/ bool& hostHasPins) {
|
||||
hostHasPins = false;
|
||||
nsAutoCString canonicalizedHostname(CanonicalizeHostname(hostname));
|
||||
const TransportSecurityPreload* staticFingerprints = nullptr;
|
||||
rv = FindPinningInformation(hostname.get(), Now(), staticFingerprints);
|
||||
nsresult rv = FindPinningInformation(canonicalizedHostname.get(), time,
|
||||
originAttributes, staticFingerprints);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (staticFingerprints) {
|
||||
*hostHasPins = !staticFingerprints->mTestMode ||
|
||||
pinningMode == PinningMode::EnforceTestMode;
|
||||
hostHasPins = !staticFingerprints->mTestMode || enforceTestMode;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -6,22 +6,25 @@
|
||||
#define PublicKeyPinningService_h
|
||||
|
||||
#include "CertVerifier.h"
|
||||
#include "nsIPublicKeyPinningService.h"
|
||||
#include "ScopedNSSTypes.h"
|
||||
#include "cert.h"
|
||||
#include "nsNSSCertificate.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/Span.h"
|
||||
#include "mozpkix/Time.h"
|
||||
|
||||
namespace mozilla {
|
||||
class OriginAttributes;
|
||||
}
|
||||
|
||||
using mozilla::OriginAttributes;
|
||||
|
||||
namespace mozilla {
|
||||
namespace psm {
|
||||
|
||||
class PublicKeyPinningService final : public nsIPublicKeyPinningService {
|
||||
class PublicKeyPinningService {
|
||||
public:
|
||||
PublicKeyPinningService() = default;
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIPUBLICKEYPINNINGSERVICE
|
||||
|
||||
/**
|
||||
* Sets chainHasValidPins to true if the given (host, certList) passes pinning
|
||||
* checks, or to false otherwise. If the host is pinned, returns true via
|
||||
@ -33,19 +36,27 @@ class PublicKeyPinningService final : public nsIPublicKeyPinningService {
|
||||
*/
|
||||
static nsresult ChainHasValidPins(
|
||||
const nsTArray<Span<const uint8_t>>& certList, const char* hostname,
|
||||
mozilla::pkix::Time time, bool isBuiltInRoot,
|
||||
mozilla::pkix::Time time, bool enforceTestMode,
|
||||
const OriginAttributes& originAttributes,
|
||||
/*out*/ bool& chainHasValidPins,
|
||||
/*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo);
|
||||
|
||||
/**
|
||||
* Returns true via the output parameter hostHasPins if there is pinning
|
||||
* information for the given host that is valid at the given time, and false
|
||||
* otherwise.
|
||||
*/
|
||||
static nsresult HostHasPins(const char* hostname, mozilla::pkix::Time time,
|
||||
bool enforceTestMode,
|
||||
const OriginAttributes& originAttributes,
|
||||
/*out*/ bool& hostHasPins);
|
||||
|
||||
/**
|
||||
* Given a hostname of potentially mixed case with potentially multiple
|
||||
* trailing '.' (see bug 1118522), canonicalizes it to lowercase with no
|
||||
* trailing '.'.
|
||||
*/
|
||||
static nsAutoCString CanonicalizeHostname(const char* hostname);
|
||||
|
||||
private:
|
||||
~PublicKeyPinningService() = default;
|
||||
};
|
||||
|
||||
} // namespace psm
|
||||
|
@ -117,7 +117,6 @@
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsICertOverrideService.h"
|
||||
#include "nsIPublicKeyPinningService.h"
|
||||
#include "nsISiteSecurityService.h"
|
||||
#include "nsISocketProvider.h"
|
||||
#include "nsThreadPool.h"
|
||||
@ -429,24 +428,18 @@ static nsresult OverrideAllowedForHost(
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = sss->IsSecureURI(uri, aProviderFlags, aOriginAttributes, nullptr,
|
||||
nullptr, &strictTransportSecurityEnabled);
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, uri,
|
||||
aProviderFlags, aOriginAttributes, nullptr, nullptr,
|
||||
&strictTransportSecurityEnabled);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
("[0x%" PRIx64 "] checking for HSTS failed", aPtrForLog));
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPublicKeyPinningService> pkps =
|
||||
do_GetService(NS_PKPSERVICE_CONTRACTID, &rv);
|
||||
if (!pkps) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
("[0x%" PRIx64
|
||||
"] Couldn't get nsIPublicKeyPinningService to check pinning",
|
||||
aPtrForLog));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = pkps->HostHasPins(uri, &isStaticallyPinned);
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::STATIC_PINNING, uri,
|
||||
aProviderFlags, aOriginAttributes, nullptr, nullptr,
|
||||
&isStaticallyPinned);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
("[0x%" PRIx64 "] checking for static pin failed", aPtrForLog));
|
||||
|
@ -23,7 +23,8 @@ class SharedCertVerifier : public mozilla::psm::CertVerifier {
|
||||
SharedCertVerifier(OcspDownloadConfig odc, OcspStrictConfig osc,
|
||||
mozilla::TimeDuration ocspSoftTimeout,
|
||||
mozilla::TimeDuration ocspHardTimeout,
|
||||
uint32_t certShortLifetimeInDays, SHA1Mode sha1Mode,
|
||||
uint32_t certShortLifetimeInDays, PinningMode pinningMode,
|
||||
SHA1Mode sha1Mode,
|
||||
BRNameMatchingPolicy::Mode nameMatchingMode,
|
||||
NetscapeStepUpPolicy netscapeStepUpPolicy,
|
||||
CertificateTransparencyMode ctMode, CRLiteMode crliteMode,
|
||||
@ -31,8 +32,8 @@ class SharedCertVerifier : public mozilla::psm::CertVerifier {
|
||||
const Vector<EnterpriseCert>& thirdPartyCerts)
|
||||
: mozilla::psm::CertVerifier(
|
||||
odc, osc, ocspSoftTimeout, ocspHardTimeout, certShortLifetimeInDays,
|
||||
sha1Mode, nameMatchingMode, netscapeStepUpPolicy, ctMode,
|
||||
crliteMode, crliteCTMergeDelaySeconds, thirdPartyCerts) {}
|
||||
pinningMode, sha1Mode, nameMatchingMode, netscapeStepUpPolicy,
|
||||
ctMode, crliteMode, crliteCTMergeDelaySeconds, thirdPartyCerts) {}
|
||||
};
|
||||
|
||||
} // namespace psm
|
||||
|
@ -36,6 +36,9 @@ class SharedSSLState {
|
||||
void SetSignedCertTimestampsEnabled(bool signedCertTimestampsEnabled) {
|
||||
mSignedCertTimestampsEnabled = signedCertTimestampsEnabled;
|
||||
}
|
||||
void SetPinningMode(CertVerifier::PinningMode aPinningMode) {
|
||||
mPinningMode = aPinningMode;
|
||||
}
|
||||
void SetNameMatchingMode(BRNameMatchingPolicy::Mode aMode) {
|
||||
mNameMatchingMode = aMode;
|
||||
}
|
||||
@ -49,6 +52,7 @@ class SharedSSLState {
|
||||
bool IsSignedCertTimestampsEnabled() const {
|
||||
return mSignedCertTimestampsEnabled;
|
||||
}
|
||||
CertVerifier::PinningMode PinningMode() { return mPinningMode; }
|
||||
BRNameMatchingPolicy::Mode NameMatchingMode() { return mNameMatchingMode; }
|
||||
|
||||
private:
|
||||
@ -67,6 +71,7 @@ class SharedSSLState {
|
||||
bool mOCSPStaplingEnabled;
|
||||
bool mOCSPMustStapleEnabled;
|
||||
bool mSignedCertTimestampsEnabled;
|
||||
CertVerifier::PinningMode mPinningMode;
|
||||
BRNameMatchingPolicy::Mode mNameMatchingMode;
|
||||
};
|
||||
|
||||
|
@ -147,12 +147,6 @@ Classes = [
|
||||
'headers': ['/security/manager/ssl/cert_storage/src/cert_storage.h'],
|
||||
'legacy_constructor': 'cert_storage_constructor',
|
||||
},
|
||||
{
|
||||
'cid': '{f64432b9-e8c6-41b4-b2da-8eb004344bba}',
|
||||
'contract_ids': ['@mozilla.org/security/publickeypinningservice;1'],
|
||||
'type': 'psm::PublicKeyPinningService',
|
||||
'headers': ['/security/manager/ssl/PublicKeyPinningService.h'],
|
||||
},
|
||||
]
|
||||
|
||||
if defined('MOZ_XUL'):
|
||||
|
@ -36,7 +36,6 @@ XPIDL_SOURCES += [
|
||||
"nsIPKCS11ModuleDB.idl",
|
||||
"nsIPKCS11Slot.idl",
|
||||
"nsIProtectedAuthThread.idl",
|
||||
"nsIPublicKeyPinningService.idl",
|
||||
"nsISecretDecoderRing.idl",
|
||||
"nsISecurityUITelemetry.idl",
|
||||
"nsISiteSecurityService.idl",
|
||||
|
@ -827,18 +827,8 @@ nsCertOverrideService::
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mDisableAllSecurityCheck = aDisable;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINSSComponent> nss(do_GetService(PSM_COMPONENT_CONTRACTID));
|
||||
if (nss) {
|
||||
nss->ClearSSLExternalAndInternalSessionCache();
|
||||
} else {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
mDisableAllSecurityCheck = aDisable;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
|
||||
[scriptable, uuid(f64432b9-e8c6-41b4-b2da-8eb004344bba), builtinclass]
|
||||
interface nsIPublicKeyPinningService : nsISupports
|
||||
{
|
||||
/**
|
||||
* Returns true if the host of the given URI has pinning information, and
|
||||
* false otherwise.
|
||||
*/
|
||||
[must_use]
|
||||
bool hostHasPins(in nsIURI aURI);
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_PKPSERVICE_CONTRACTID "@mozilla.org/security/publickeypinningservice;1"
|
||||
%}
|
@ -45,6 +45,10 @@ interface nsISiteHSTSState : nsISiteSecurityState
|
||||
[scriptable, uuid(275127f8-dbd7-4681-afbf-6df0c6587a01)]
|
||||
interface nsISiteSecurityService : nsISupports
|
||||
{
|
||||
const uint32_t HEADER_HSTS = 0;
|
||||
const uint32_t STATIC_PINNING = 1; // was HEADER_HPKP
|
||||
// HEADER_OMS was 2 (but was never implemented)
|
||||
|
||||
const uint32_t Success = 0;
|
||||
const uint32_t ERROR_UNKNOWN = 1;
|
||||
const uint32_t ERROR_UNTRUSTWORTHY_CONNECTION = 2;
|
||||
@ -80,6 +84,7 @@ interface nsISiteSecurityService : nsISupports
|
||||
* and allows a host to specify that future HTTP requests should be
|
||||
* upgraded to HTTPS.
|
||||
*
|
||||
* @param aType the type of security header in question.
|
||||
* @param aSourceURI the URI of the resource with the HTTP header.
|
||||
* @param aHeader the HTTP response header specifying security data.
|
||||
* @param aSecInfo the TransportSecurityInfo of the current channel.
|
||||
@ -102,7 +107,8 @@ interface nsISiteSecurityService : nsISupports
|
||||
* if there are unrecognized tokens in the header.
|
||||
*/
|
||||
[binaryname(ProcessHeader), noscript, must_use]
|
||||
void processHeaderNative(in nsIURI aSourceURI,
|
||||
void processHeaderNative(in uint32_t aType,
|
||||
in nsIURI aSourceURI,
|
||||
in ACString aHeader,
|
||||
in nsITransportSecurityInfo aSecInfo,
|
||||
in uint32_t aFlags,
|
||||
@ -114,7 +120,8 @@ interface nsISiteSecurityService : nsISupports
|
||||
|
||||
[binaryname(ProcessHeaderScriptable), implicit_jscontext, optional_argc,
|
||||
must_use]
|
||||
void processHeader(in nsIURI aSourceURI,
|
||||
void processHeader(in uint32_t aType,
|
||||
in nsIURI aSourceURI,
|
||||
in ACString aHeader,
|
||||
in nsITransportSecurityInfo aSecInfo,
|
||||
in uint32_t aFlags,
|
||||
@ -125,12 +132,14 @@ interface nsISiteSecurityService : nsISupports
|
||||
[optional] out uint32_t aFailureResult);
|
||||
|
||||
/**
|
||||
* Resets HSTS state a host, including the includeSubdomains state that
|
||||
* would affect subdomains. This essentially removes the state for the
|
||||
* domain tree rooted at this host. If any preloaded information is present
|
||||
* for that host, that information will then be used instead of any other
|
||||
* previously existing state.
|
||||
* Given a header type, resets state relating to that header of a host,
|
||||
* including the includeSubdomains state that would affect subdomains.
|
||||
* This essentially removes the state for the domain tree rooted at this
|
||||
* host. If any preloaded information is present for that host, that
|
||||
* information will then be used instead of any other previously existing
|
||||
* state.
|
||||
*
|
||||
* @param aType the type of security state in question
|
||||
* @param aURI the URI of the target host
|
||||
* @param aFlags options for this request as defined in nsISocketProvider:
|
||||
* NO_PERMANENT_STORAGE
|
||||
@ -141,19 +150,21 @@ interface nsISiteSecurityService : nsISupports
|
||||
* happens).
|
||||
*/
|
||||
[implicit_jscontext, optional_argc, must_use]
|
||||
void resetState(in nsIURI aURI,
|
||||
void resetState(in uint32_t aType,
|
||||
in nsIURI aURI,
|
||||
in uint32_t aFlags,
|
||||
[optional] in jsval aOriginAttributes);
|
||||
|
||||
/**
|
||||
* Checks whether or not the URI's hostname has HSTS set.
|
||||
* For example:
|
||||
* Checks whether or not the URI's hostname has a given security state set.
|
||||
* For example, for HSTS:
|
||||
* The URI is an HSTS URI if either the host has the HSTS state set, or one
|
||||
* of its super-domains has the HSTS "includeSubdomains" flag set.
|
||||
* NOTE: this function makes decisions based only on the
|
||||
* host contained in the URI, and disregards other portions of the URI
|
||||
* such as path and port.
|
||||
*
|
||||
* @param aType the type of security state in question.
|
||||
* @param aURI the URI to query for STS state.
|
||||
* @param aFlags options for this request as defined in nsISocketProvider:
|
||||
* NO_PERMANENT_STORAGE
|
||||
@ -168,20 +179,21 @@ interface nsISiteSecurityService : nsISupports
|
||||
* SOURCE_ORGANIC_REQUEST, or SOURCE_UNKNOWN.
|
||||
*/
|
||||
[binaryname(IsSecureURI), noscript, must_use]
|
||||
boolean isSecureURINative(in nsIURI aURI, in uint32_t aFlags,
|
||||
boolean isSecureURINative(in uint32_t aType, in nsIURI aURI,
|
||||
in uint32_t aFlags,
|
||||
in const_OriginAttributesRef aOriginAttributes,
|
||||
[optional] out boolean aCached,
|
||||
[optional] out uint32_t aSource);
|
||||
|
||||
[binaryname(IsSecureURIScriptable), implicit_jscontext, optional_argc,
|
||||
must_use]
|
||||
boolean isSecureURI(in nsIURI aURI, in uint32_t aFlags,
|
||||
boolean isSecureURI(in uint32_t aType, in nsIURI aURI, in uint32_t aFlags,
|
||||
[optional] in jsval aOriginAttributes,
|
||||
[optional] out boolean aCached,
|
||||
[optional] out uint32_t aSource);
|
||||
|
||||
/**
|
||||
* Removes all non-preloaded HSTS state by resetting to factory-original
|
||||
* Removes all non-preloaded security state by resetting to factory-original
|
||||
* settings.
|
||||
*/
|
||||
[must_use]
|
||||
@ -192,9 +204,11 @@ interface nsISiteSecurityService : nsISupports
|
||||
* the enumeration is a nsISiteSecurityState that can be QueryInterfaced to
|
||||
* nsISiteHSTSState.
|
||||
* Doesn't include hard-coded preloaded entries.
|
||||
*
|
||||
* @param aType the type of security state in question.
|
||||
*/
|
||||
[must_use]
|
||||
nsISimpleEnumerator enumerate();
|
||||
nsISimpleEnumerator enumerate(in uint32_t aType);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -1292,6 +1292,16 @@ void SetValidationOptionsCommon() {
|
||||
PublicSSLState()->SetSignedCertTimestampsEnabled(sctsEnabled);
|
||||
PrivateSSLState()->SetSignedCertTimestampsEnabled(sctsEnabled);
|
||||
|
||||
CertVerifier::PinningMode pinningMode =
|
||||
static_cast<CertVerifier::PinningMode>(
|
||||
Preferences::GetInt("security.cert_pinning.enforcement_level",
|
||||
CertVerifier::pinningDisabled));
|
||||
if (pinningMode > CertVerifier::pinningEnforceTestMode) {
|
||||
pinningMode = CertVerifier::pinningDisabled;
|
||||
}
|
||||
PublicSSLState()->SetPinningMode(pinningMode);
|
||||
PrivateSSLState()->SetPinningMode(pinningMode);
|
||||
|
||||
BRNameMatchingPolicy::Mode nameMatchingMode =
|
||||
static_cast<BRNameMatchingPolicy::Mode>(Preferences::GetInt(
|
||||
"security.pki.name_matching_mode",
|
||||
@ -1498,7 +1508,8 @@ void nsNSSComponent::setValidationOptions(
|
||||
softTimeout, hardTimeout, proofOfLock);
|
||||
|
||||
mDefaultCertVerifier = new SharedCertVerifier(
|
||||
odc, osc, softTimeout, hardTimeout, certShortLifetimeInDays, sha1Mode,
|
||||
odc, osc, softTimeout, hardTimeout, certShortLifetimeInDays,
|
||||
PublicSSLState()->PinningMode(), sha1Mode,
|
||||
PublicSSLState()->NameMatchingMode(), netscapeStepUpPolicy, ctMode,
|
||||
crliteMode, crliteCTMergeDelaySeconds, mEnterpriseCerts);
|
||||
}
|
||||
@ -1516,8 +1527,8 @@ void nsNSSComponent::UpdateCertVerifierWithEnterpriseRoots() {
|
||||
oldCertVerifier->mOCSPStrict ? CertVerifier::ocspStrict
|
||||
: CertVerifier::ocspRelaxed,
|
||||
oldCertVerifier->mOCSPTimeoutSoft, oldCertVerifier->mOCSPTimeoutHard,
|
||||
oldCertVerifier->mCertShortLifetimeInDays, oldCertVerifier->mSHA1Mode,
|
||||
oldCertVerifier->mNameMatchingMode,
|
||||
oldCertVerifier->mCertShortLifetimeInDays, oldCertVerifier->mPinningMode,
|
||||
oldCertVerifier->mSHA1Mode, oldCertVerifier->mNameMatchingMode,
|
||||
oldCertVerifier->mNetscapeStepUpPolicy, oldCertVerifier->mCTMode,
|
||||
oldCertVerifier->mCRLiteMode, oldCertVerifier->mCRLiteCTMergeDelaySeconds,
|
||||
mEnterpriseCerts);
|
||||
@ -2273,6 +2284,8 @@ nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
prefName.EqualsLiteral("security.ssl.enable_ocsp_must_staple") ||
|
||||
prefName.EqualsLiteral(
|
||||
"security.pki.certificate_transparency.mode") ||
|
||||
prefName.EqualsLiteral(
|
||||
"security.cert_pinning.enforcement_level") ||
|
||||
prefName.EqualsLiteral("security.pki.sha1_enforcement_level") ||
|
||||
prefName.EqualsLiteral("security.pki.name_matching_mode") ||
|
||||
prefName.EqualsLiteral("security.pki.netscape_step_up_policy") ||
|
||||
|
@ -45,7 +45,7 @@ static LazyLogModule gSSSLog("nsSSService");
|
||||
|
||||
#define SSSLOG(args) MOZ_LOG(gSSSLog, mozilla::LogLevel::Debug, args)
|
||||
|
||||
static const nsLiteralCString kHSTSKeySuffix = ":HSTS"_ns;
|
||||
const char kHSTSKeySuffix[] = ":HSTS";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -286,7 +286,7 @@ nsresult nsSiteSecurityService::GetHost(nsIURI* aURI, nsACString& aResult) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void SetStorageKey(const nsACString& hostname,
|
||||
static void SetStorageKey(const nsACString& hostname, uint32_t aType,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
/*out*/ nsAutoCString& storageKey) {
|
||||
storageKey = hostname;
|
||||
@ -298,7 +298,13 @@ static void SetStorageKey(const nsACString& hostname,
|
||||
nsAutoCString originAttributesSuffix;
|
||||
originAttributesNoUserContext.CreateSuffix(originAttributesSuffix);
|
||||
storageKey.Append(originAttributesSuffix);
|
||||
storageKey.Append(kHSTSKeySuffix);
|
||||
switch (aType) {
|
||||
case nsISiteSecurityService::HEADER_HSTS:
|
||||
storageKey.AppendASCII(kHSTSKeySuffix);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("SSS:SetStorageKey got invalid type");
|
||||
}
|
||||
}
|
||||
|
||||
// Expire times are in millis. Since Headers max-age is in seconds, and
|
||||
@ -308,16 +314,17 @@ static int64_t ExpireTimeFromMaxAge(uint64_t maxAge) {
|
||||
}
|
||||
|
||||
nsresult nsSiteSecurityService::SetHSTSState(
|
||||
const char* aHost, int64_t maxage, bool includeSubdomains, uint32_t flags,
|
||||
SecurityPropertyState aHSTSState, SecurityPropertySource aSource,
|
||||
const OriginAttributes& aOriginAttributes) {
|
||||
uint32_t aType, const char* aHost, int64_t maxage, bool includeSubdomains,
|
||||
uint32_t flags, SecurityPropertyState aHSTSState,
|
||||
SecurityPropertySource aSource, const OriginAttributes& aOriginAttributes) {
|
||||
nsAutoCString hostname(aHost);
|
||||
bool isPreload = (aSource == SourcePreload);
|
||||
// If max-age is zero, the host is no longer considered HSTS. If the host was
|
||||
// preloaded, we store an entry indicating that this host is not HSTS, causing
|
||||
// the preloaded information to be ignored.
|
||||
if (maxage == 0) {
|
||||
return MarkHostAsNotHSTS(hostname, flags, isPreload, aOriginAttributes);
|
||||
return MarkHostAsNotHSTS(aType, hostname, flags, isPreload,
|
||||
aOriginAttributes);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aHSTSState == SecurityPropertySet,
|
||||
@ -338,7 +345,7 @@ nsresult nsSiteSecurityService::SetHSTSState(
|
||||
? mozilla::DataStorage_Private
|
||||
: mozilla::DataStorage_Persistent;
|
||||
nsAutoCString storageKey;
|
||||
SetStorageKey(hostname, aOriginAttributes, storageKey);
|
||||
SetStorageKey(hostname, aType, aOriginAttributes, storageKey);
|
||||
SSSLOG(("SSS: storing HSTS site entry for %s", hostname.get()));
|
||||
nsCString value = mSiteStateStorage->Get(storageKey, storageType);
|
||||
RefPtr<SiteHSTSState> curSiteState =
|
||||
@ -360,8 +367,12 @@ nsresult nsSiteSecurityService::SetHSTSState(
|
||||
// entry that indicates this host is not HSTS to prevent the implementation
|
||||
// using the preloaded information.
|
||||
nsresult nsSiteSecurityService::MarkHostAsNotHSTS(
|
||||
const nsAutoCString& aHost, uint32_t aFlags, bool aIsPreload,
|
||||
const OriginAttributes& aOriginAttributes) {
|
||||
uint32_t aType, const nsAutoCString& aHost, uint32_t aFlags,
|
||||
bool aIsPreload, const OriginAttributes& aOriginAttributes) {
|
||||
// This only applies to HSTS.
|
||||
if (aType != nsISiteSecurityService::HEADER_HSTS) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (aIsPreload && aOriginAttributes != OriginAttributes()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
@ -371,7 +382,7 @@ nsresult nsSiteSecurityService::MarkHostAsNotHSTS(
|
||||
? mozilla::DataStorage_Private
|
||||
: mozilla::DataStorage_Persistent;
|
||||
nsAutoCString storageKey;
|
||||
SetStorageKey(aHost, aOriginAttributes, storageKey);
|
||||
SetStorageKey(aHost, aType, aOriginAttributes, storageKey);
|
||||
|
||||
if (GetPreloadStatus(aHost)) {
|
||||
SSSLOG(("SSS: storing knockout entry for %s", aHost.get()));
|
||||
@ -391,7 +402,7 @@ nsresult nsSiteSecurityService::MarkHostAsNotHSTS(
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::ResetState(nsIURI* aURI, uint32_t aFlags,
|
||||
nsSiteSecurityService::ResetState(uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
JS::HandleValue aOriginAttributes,
|
||||
JSContext* aCx, uint8_t aArgc) {
|
||||
if (!XRE_IsParentProcess()) {
|
||||
@ -412,7 +423,7 @@ nsSiteSecurityService::ResetState(nsIURI* aURI, uint32_t aFlags,
|
||||
}
|
||||
}
|
||||
|
||||
return ResetStateInternal(aURI, aFlags, originAttributes);
|
||||
return ResetStateInternal(aType, aURI, aFlags, originAttributes);
|
||||
}
|
||||
|
||||
// Helper function to reset stored state of the given type for the host
|
||||
@ -422,17 +433,21 @@ nsSiteSecurityService::ResetState(nsIURI* aURI, uint32_t aFlags,
|
||||
// header with max-age=0 (meaning preloaded information will then not be used
|
||||
// for that host).
|
||||
nsresult nsSiteSecurityService::ResetStateInternal(
|
||||
nsIURI* aURI, uint32_t aFlags, const OriginAttributes& aOriginAttributes) {
|
||||
uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes) {
|
||||
if (!aURI) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (aType != nsISiteSecurityService::HEADER_HSTS) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
nsAutoCString hostname;
|
||||
nsresult rv = GetHost(aURI, hostname);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsAutoCString storageKey;
|
||||
SetStorageKey(hostname, aOriginAttributes, storageKey);
|
||||
SetStorageKey(hostname, aType, aOriginAttributes, storageKey);
|
||||
bool isPrivate = aFlags & nsISocketProvider::NO_PERMANENT_STORAGE;
|
||||
mozilla::DataStorageType storageType = isPrivate
|
||||
? mozilla::DataStorage_Private
|
||||
@ -441,7 +456,7 @@ nsresult nsSiteSecurityService::ResetStateInternal(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsSiteSecurityService::HostIsIPAddress(const nsCString& hostname) {
|
||||
static bool HostIsIPAddress(const nsCString& hostname) {
|
||||
PRNetAddr hostAddr;
|
||||
PRErrorCode prv = PR_StringToNetAddr(hostname.get(), &hostAddr);
|
||||
return (prv == PR_SUCCESS);
|
||||
@ -449,7 +464,7 @@ bool nsSiteSecurityService::HostIsIPAddress(const nsCString& hostname) {
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::ProcessHeaderScriptable(
|
||||
nsIURI* aSourceURI, const nsACString& aHeader,
|
||||
uint32_t aType, nsIURI* aSourceURI, const nsACString& aHeader,
|
||||
nsITransportSecurityInfo* aSecInfo, uint32_t aFlags, uint32_t aSource,
|
||||
JS::HandleValue aOriginAttributes, uint64_t* aMaxAge,
|
||||
bool* aIncludeSubdomains, uint32_t* aFailureResult, JSContext* aCx,
|
||||
@ -461,14 +476,14 @@ nsSiteSecurityService::ProcessHeaderScriptable(
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
return ProcessHeader(aSourceURI, aHeader, aSecInfo, aFlags, aSource,
|
||||
return ProcessHeader(aType, aSourceURI, aHeader, aSecInfo, aFlags, aSource,
|
||||
originAttributes, aMaxAge, aIncludeSubdomains,
|
||||
aFailureResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::ProcessHeader(
|
||||
nsIURI* aSourceURI, const nsACString& aHeader,
|
||||
uint32_t aType, nsIURI* aSourceURI, const nsACString& aHeader,
|
||||
nsITransportSecurityInfo* aSecInfo, uint32_t aFlags, uint32_t aHeaderSource,
|
||||
const OriginAttributes& aOriginAttributes, uint64_t* aMaxAge,
|
||||
bool* aIncludeSubdomains, uint32_t* aFailureResult) {
|
||||
@ -482,6 +497,8 @@ nsSiteSecurityService::ProcessHeader(
|
||||
if (aFailureResult) {
|
||||
*aFailureResult = nsISiteSecurityService::ERROR_UNKNOWN;
|
||||
}
|
||||
NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS,
|
||||
NS_ERROR_NOT_IMPLEMENTED);
|
||||
SecurityPropertySource source =
|
||||
static_cast<SecurityPropertySource>(aHeaderSource);
|
||||
switch (source) {
|
||||
@ -494,19 +511,23 @@ nsSiteSecurityService::ProcessHeader(
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG(aSecInfo);
|
||||
return ProcessHeaderInternal(aSourceURI, PromiseFlatCString(aHeader),
|
||||
return ProcessHeaderInternal(aType, aSourceURI, PromiseFlatCString(aHeader),
|
||||
aSecInfo, aFlags, source, aOriginAttributes,
|
||||
aMaxAge, aIncludeSubdomains, aFailureResult);
|
||||
}
|
||||
|
||||
nsresult nsSiteSecurityService::ProcessHeaderInternal(
|
||||
nsIURI* aSourceURI, const nsCString& aHeader,
|
||||
uint32_t aType, nsIURI* aSourceURI, const nsCString& aHeader,
|
||||
nsITransportSecurityInfo* aSecInfo, uint32_t aFlags,
|
||||
SecurityPropertySource aSource, const OriginAttributes& aOriginAttributes,
|
||||
uint64_t* aMaxAge, bool* aIncludeSubdomains, uint32_t* aFailureResult) {
|
||||
if (aFailureResult) {
|
||||
*aFailureResult = nsISiteSecurityService::ERROR_UNKNOWN;
|
||||
}
|
||||
// Only HSTS is supported at the moment.
|
||||
NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS,
|
||||
NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
if (aMaxAge != nullptr) {
|
||||
*aMaxAge = 0;
|
||||
}
|
||||
@ -548,12 +569,19 @@ nsresult nsSiteSecurityService::ProcessHeaderInternal(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return ProcessSTSHeader(aSourceURI, aHeader, aFlags, aSource,
|
||||
aOriginAttributes, aMaxAge, aIncludeSubdomains,
|
||||
aFailureResult);
|
||||
switch (aType) {
|
||||
case nsISiteSecurityService::HEADER_HSTS:
|
||||
rv = ProcessSTSHeader(aSourceURI, aHeader, aFlags, aSource,
|
||||
aOriginAttributes, aMaxAge, aIncludeSubdomains,
|
||||
aFailureResult);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("unexpected header type");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static uint32_t ParseSSSHeaders(const nsCString& aHeader,
|
||||
static uint32_t ParseSSSHeaders(uint32_t aType, const nsCString& aHeader,
|
||||
bool& foundIncludeSubdomains, bool& foundMaxAge,
|
||||
bool& foundUnrecognizedDirective,
|
||||
uint64_t& maxAge) {
|
||||
@ -647,13 +675,16 @@ nsresult nsSiteSecurityService::ProcessSTSHeader(
|
||||
}
|
||||
SSSLOG(("SSS: processing HSTS header '%s'", aHeader.get()));
|
||||
|
||||
const uint32_t aType = nsISiteSecurityService::HEADER_HSTS;
|
||||
bool foundMaxAge = false;
|
||||
bool foundIncludeSubdomains = false;
|
||||
bool foundUnrecognizedDirective = false;
|
||||
uint64_t maxAge = 0;
|
||||
nsTArray<nsCString> unusedSHA256keys; // Required for sane internal interface
|
||||
|
||||
uint32_t sssrv = ParseSSSHeaders(aHeader, foundIncludeSubdomains, foundMaxAge,
|
||||
foundUnrecognizedDirective, maxAge);
|
||||
uint32_t sssrv =
|
||||
ParseSSSHeaders(aType, aHeader, foundIncludeSubdomains, foundMaxAge,
|
||||
foundUnrecognizedDirective, maxAge);
|
||||
if (sssrv != nsISiteSecurityService::Success) {
|
||||
if (aFailureResult) {
|
||||
*aFailureResult = sssrv;
|
||||
@ -676,8 +707,8 @@ nsresult nsSiteSecurityService::ProcessSTSHeader(
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// record the successfully parsed header data.
|
||||
rv = SetHSTSState(hostname.get(), maxAge, foundIncludeSubdomains, aFlags,
|
||||
SecurityPropertySet, aSource, aOriginAttributes);
|
||||
rv = SetHSTSState(aType, hostname.get(), maxAge, foundIncludeSubdomains,
|
||||
aFlags, SecurityPropertySet, aSource, aOriginAttributes);
|
||||
if (NS_FAILED(rv)) {
|
||||
SSSLOG(("SSS: failed to set STS state"));
|
||||
if (aFailureResult) {
|
||||
@ -699,7 +730,8 @@ nsresult nsSiteSecurityService::ProcessSTSHeader(
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::IsSecureURIScriptable(nsIURI* aURI, uint32_t aFlags,
|
||||
nsSiteSecurityService::IsSecureURIScriptable(uint32_t aType, nsIURI* aURI,
|
||||
uint32_t aFlags,
|
||||
JS::HandleValue aOriginAttributes,
|
||||
bool* aCached, uint32_t* aSource,
|
||||
JSContext* aCx, uint8_t aArgc,
|
||||
@ -711,17 +743,31 @@ nsSiteSecurityService::IsSecureURIScriptable(nsIURI* aURI, uint32_t aFlags,
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
return IsSecureURI(aURI, aFlags, originAttributes, aCached, aSource, aResult);
|
||||
return IsSecureURI(aType, aURI, aFlags, originAttributes, aCached, aSource,
|
||||
aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::IsSecureURI(nsIURI* aURI, uint32_t aFlags,
|
||||
nsSiteSecurityService::IsSecureURI(uint32_t aType, nsIURI* aURI,
|
||||
uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
bool* aCached, uint32_t* aSource,
|
||||
bool* aResult) {
|
||||
// Child processes are not allowed direct access to this.
|
||||
if (!XRE_IsParentProcess() && aType != nsISiteSecurityService::HEADER_HSTS) {
|
||||
MOZ_CRASH(
|
||||
"Child process: no direct access to "
|
||||
"nsISiteSecurityService::IsSecureURI for non-HSTS entries");
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG(aURI);
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
// Only HSTS and static pinning are supported.
|
||||
NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS ||
|
||||
aType == nsISiteSecurityService::STATIC_PINNING,
|
||||
NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
nsAutoCString hostname;
|
||||
nsresult rv = GetHost(aURI, hostname);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -734,8 +780,8 @@ nsSiteSecurityService::IsSecureURI(nsIURI* aURI, uint32_t aFlags,
|
||||
SecurityPropertySource* source =
|
||||
BitwiseCast<SecurityPropertySource*>(aSource);
|
||||
|
||||
return IsSecureHost(hostname, aFlags, aOriginAttributes, aCached, source,
|
||||
aResult);
|
||||
return IsSecureHost(aType, hostname, aFlags, aOriginAttributes, aCached,
|
||||
source, aResult);
|
||||
}
|
||||
|
||||
// Checks if the given host is in the preload list.
|
||||
@ -791,13 +837,17 @@ bool nsSiteSecurityService::HostHasHSTSEntry(
|
||||
: mozilla::DataStorage_Persistent;
|
||||
nsAutoCString storageKey;
|
||||
SSSLOG(("Seeking HSTS entry for %s", aHost.get()));
|
||||
SetStorageKey(aHost, aOriginAttributes, storageKey);
|
||||
SetStorageKey(aHost, nsISiteSecurityService::HEADER_HSTS, aOriginAttributes,
|
||||
storageKey);
|
||||
nsAutoCString preloadKey;
|
||||
SetStorageKey(aHost, nsISiteSecurityService::HEADER_HSTS, OriginAttributes(),
|
||||
preloadKey);
|
||||
nsCString value = mSiteStateStorage->Get(storageKey, storageType);
|
||||
RefPtr<SiteHSTSState> siteState =
|
||||
new SiteHSTSState(aHost, aOriginAttributes, value);
|
||||
if (siteState->mHSTSState != SecurityPropertyUnset) {
|
||||
SSSLOG(("Found HSTS entry for %s", aHost.get()));
|
||||
bool expired = siteState->IsExpired();
|
||||
bool expired = siteState->IsExpired(nsISiteSecurityService::HEADER_HSTS);
|
||||
if (!expired) {
|
||||
SSSLOG(("Entry for %s is not expired", aHost.get()));
|
||||
if (siteState->mHSTSState == SecurityPropertySet) {
|
||||
@ -847,11 +897,23 @@ bool nsSiteSecurityService::HostHasHSTSEntry(
|
||||
}
|
||||
|
||||
nsresult nsSiteSecurityService::IsSecureHost(
|
||||
const nsACString& aHost, uint32_t aFlags,
|
||||
uint32_t aType, const nsACString& aHost, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes, bool* aCached,
|
||||
SecurityPropertySource* aSource, bool* aResult) {
|
||||
// Child processes are not allowed direct access to this.
|
||||
if (!XRE_IsParentProcess() && aType != nsISiteSecurityService::HEADER_HSTS) {
|
||||
MOZ_CRASH(
|
||||
"Child process: no direct access to "
|
||||
"nsISiteSecurityService::IsSecureHost for non-HSTS entries");
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
// Only HSTS and static pinning are supported.
|
||||
NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS ||
|
||||
aType == nsISiteSecurityService::STATIC_PINNING,
|
||||
NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
// set default in case if we can't find any STS information
|
||||
*aResult = false;
|
||||
|
||||
@ -861,6 +923,22 @@ nsresult nsSiteSecurityService::IsSecureHost(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aType == nsISiteSecurityService::STATIC_PINNING) {
|
||||
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
||||
if (!certVerifier) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (certVerifier->mPinningMode ==
|
||||
CertVerifier::PinningMode::pinningDisabled) {
|
||||
return NS_OK;
|
||||
}
|
||||
bool enforceTestMode = certVerifier->mPinningMode ==
|
||||
CertVerifier::PinningMode::pinningEnforceTestMode;
|
||||
return PublicKeyPinningService::HostHasPins(
|
||||
flatHost.get(), mozilla::pkix::Now(), enforceTestMode,
|
||||
aOriginAttributes, *aResult);
|
||||
}
|
||||
|
||||
nsAutoCString host(
|
||||
PublicKeyPinningService::CanonicalizeHostname(flatHost.get()));
|
||||
|
||||
@ -912,28 +990,46 @@ nsSiteSecurityService::ClearAll() {
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::Enumerate(nsISimpleEnumerator** aEnumerator) {
|
||||
nsSiteSecurityService::Enumerate(uint32_t aType,
|
||||
nsISimpleEnumerator** aEnumerator) {
|
||||
NS_ENSURE_ARG(aEnumerator);
|
||||
|
||||
nsAutoCString keySuffix;
|
||||
switch (aType) {
|
||||
case nsISiteSecurityService::HEADER_HSTS:
|
||||
keySuffix.AssignASCII(kHSTSKeySuffix);
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsTArray<mozilla::psm::DataStorageItem> items;
|
||||
mSiteStateStorage->GetAll(&items);
|
||||
|
||||
nsCOMArray<nsISiteSecurityState> states;
|
||||
for (const mozilla::psm::DataStorageItem& item : items) {
|
||||
if (!StringEndsWith(item.key(), kHSTSKeySuffix)) {
|
||||
if (!StringEndsWith(item.key(), keySuffix)) {
|
||||
// The key does not end with correct suffix, so is not the type we want.
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCString origin(
|
||||
StringHead(item.key(), item.key().Length() - kHSTSKeySuffix.Length()));
|
||||
StringHead(item.key(), item.key().Length() - keySuffix.Length()));
|
||||
nsAutoCString hostname;
|
||||
OriginAttributes originAttributes;
|
||||
if (!originAttributes.PopulateFromOrigin(origin, hostname)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISiteSecurityState> state(
|
||||
new SiteHSTSState(hostname, originAttributes, item.value()));
|
||||
nsCOMPtr<nsISiteSecurityState> state;
|
||||
switch (aType) {
|
||||
case nsISiteSecurityService::HEADER_HSTS:
|
||||
state = new SiteHSTSState(hostname, originAttributes, item.value());
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("SSS:Enumerate got invalid type");
|
||||
}
|
||||
|
||||
states.AppendObject(state);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ class SiteHSTSState : public nsISiteHSTSState {
|
||||
bool mHSTSIncludeSubdomains;
|
||||
SecurityPropertySource mHSTSSource;
|
||||
|
||||
bool IsExpired() {
|
||||
bool IsExpired(uint32_t aType) {
|
||||
// If mHSTSExpireTime is 0, this entry never expires (this is the case for
|
||||
// knockout entries).
|
||||
if (mHSTSExpireTime == 0) {
|
||||
@ -115,34 +115,30 @@ class nsSiteSecurityService : public nsISiteSecurityService,
|
||||
nsSiteSecurityService();
|
||||
nsresult Init();
|
||||
|
||||
static nsresult GetHost(nsIURI* aURI, nsACString& aResult);
|
||||
static bool HostIsIPAddress(const nsCString& hostname);
|
||||
|
||||
protected:
|
||||
virtual ~nsSiteSecurityService();
|
||||
|
||||
private:
|
||||
nsresult SetHSTSState(const char* aHost, int64_t maxage,
|
||||
nsresult GetHost(nsIURI* aURI, nsACString& aResult);
|
||||
nsresult SetHSTSState(uint32_t aType, const char* aHost, int64_t maxage,
|
||||
bool includeSubdomains, uint32_t flags,
|
||||
SecurityPropertyState aHSTSState,
|
||||
SecurityPropertySource aSource,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
nsresult ProcessHeaderInternal(nsIURI* aSourceURI, const nsCString& aHeader,
|
||||
nsITransportSecurityInfo* aSecInfo,
|
||||
uint32_t aFlags,
|
||||
SecurityPropertySource aSource,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
uint64_t* aMaxAge, bool* aIncludeSubdomains,
|
||||
uint32_t* aFailureResult);
|
||||
nsresult ProcessHeaderInternal(
|
||||
uint32_t aType, nsIURI* aSourceURI, const nsCString& aHeader,
|
||||
nsITransportSecurityInfo* aSecInfo, uint32_t aFlags,
|
||||
SecurityPropertySource aSource, const OriginAttributes& aOriginAttributes,
|
||||
uint64_t* aMaxAge, bool* aIncludeSubdomains, uint32_t* aFailureResult);
|
||||
nsresult ProcessSTSHeader(nsIURI* aSourceURI, const nsCString& aHeader,
|
||||
uint32_t flags, SecurityPropertySource aSource,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
uint64_t* aMaxAge, bool* aIncludeSubdomains,
|
||||
uint32_t* aFailureResult);
|
||||
nsresult MarkHostAsNotHSTS(const nsAutoCString& aHost, uint32_t aFlags,
|
||||
bool aIsPreload,
|
||||
nsresult MarkHostAsNotHSTS(uint32_t aType, const nsAutoCString& aHost,
|
||||
uint32_t aFlags, bool aIsPreload,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
nsresult ResetStateInternal(nsIURI* aURI, uint32_t aFlags,
|
||||
nsresult ResetStateInternal(uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
bool HostHasHSTSEntry(const nsAutoCString& aHost,
|
||||
bool aRequireIncludeSubdomains, uint32_t aFlags,
|
||||
@ -152,7 +148,8 @@ class nsSiteSecurityService : public nsISiteSecurityService,
|
||||
bool GetPreloadStatus(
|
||||
const nsACString& aHost,
|
||||
/*optional out*/ bool* aIncludeSubdomains = nullptr) const;
|
||||
nsresult IsSecureHost(const nsACString& aHost, uint32_t aFlags,
|
||||
nsresult IsSecureHost(uint32_t aType, const nsACString& aHost,
|
||||
uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
bool* aCached, SecurityPropertySource* aSource,
|
||||
bool* aResult);
|
||||
|
@ -38,6 +38,7 @@ function test() {
|
||||
].createInstance(Ci.nsITransportSecurityInfo);
|
||||
uri = aWindow.Services.io.newURI("https://localhost/img.png");
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000",
|
||||
secInfo,
|
||||
@ -45,7 +46,11 @@ function test() {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(uri, privacyFlags(aIsPrivateMode)),
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
privacyFlags(aIsPrivateMode)
|
||||
),
|
||||
"checking sts host"
|
||||
);
|
||||
|
||||
@ -74,7 +79,7 @@ function test() {
|
||||
aWin.close();
|
||||
});
|
||||
uri = Services.io.newURI("http://localhost");
|
||||
gSSService.resetState(uri, 0);
|
||||
gSSService.resetState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
});
|
||||
|
||||
// test first when on private mode
|
||||
|
@ -7,46 +7,57 @@ function run_test() {
|
||||
);
|
||||
|
||||
ok(
|
||||
!SSService.isSecureURI(Services.io.newURI("https://expired.example.com"), 0)
|
||||
!SSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://expired.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
SSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://notexpired.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
SSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!SSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sub.includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
SSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://incsubdomain.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
SSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sub.incsubdomain.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!SSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains2.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!SSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sub.includesubdomains2.preloaded.test"),
|
||||
0
|
||||
)
|
||||
|
@ -45,6 +45,7 @@ function add_tests() {
|
||||
// longer.
|
||||
add_task(async function() {
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
GOOD_MAX_AGE,
|
||||
secInfo,
|
||||
@ -52,12 +53,15 @@ function add_tests() {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
|
||||
Assert.ok(sss.isSecureURI(uri, 0), "a.pinning.example.com should be HSTS");
|
||||
Assert.ok(
|
||||
sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
"a.pinning.example.com should be HSTS"
|
||||
);
|
||||
|
||||
await ForgetAboutSite.removeDataFromDomain("a.pinning.example.com");
|
||||
|
||||
Assert.ok(
|
||||
!sss.isSecureURI(uri, 0),
|
||||
!sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
"a.pinning.example.com should not be HSTS now"
|
||||
);
|
||||
});
|
||||
@ -68,6 +72,7 @@ function add_tests() {
|
||||
// unrelated sites don't also get removed.
|
||||
add_task(async function() {
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
GOOD_MAX_AGE,
|
||||
secInfo,
|
||||
@ -76,30 +81,34 @@ function add_tests() {
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
sss.isSecureURI(uri, 0),
|
||||
sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
"a.pinning.example.com should be HSTS (subdomain case)"
|
||||
);
|
||||
|
||||
// Add an unrelated site to HSTS.
|
||||
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(unrelatedURI, 0), "example.org should be HSTS");
|
||||
Assert.ok(
|
||||
sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI, 0),
|
||||
"example.org should be HSTS"
|
||||
);
|
||||
|
||||
await ForgetAboutSite.removeDataFromDomain("example.com");
|
||||
|
||||
Assert.ok(
|
||||
!sss.isSecureURI(uri, 0),
|
||||
!sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
"a.pinning.example.com should not be HSTS now (subdomain case)"
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
sss.isSecureURI(unrelatedURI, 0),
|
||||
sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI, 0),
|
||||
"example.org should still be HSTS"
|
||||
);
|
||||
});
|
||||
@ -121,6 +130,7 @@ function add_tests() {
|
||||
|
||||
for (let originAttributes of originAttributesList) {
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
GOOD_MAX_AGE,
|
||||
secInfo,
|
||||
@ -130,12 +140,18 @@ function add_tests() {
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
sss.isSecureURI(uri, 0, originAttributes),
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
"a.pinning.example.com should be HSTS (originAttributes case)"
|
||||
);
|
||||
|
||||
// Add an unrelated site to HSTS.
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
unrelatedURI,
|
||||
GOOD_MAX_AGE,
|
||||
secInfo,
|
||||
@ -144,7 +160,12 @@ function add_tests() {
|
||||
originAttributes
|
||||
);
|
||||
Assert.ok(
|
||||
sss.isSecureURI(unrelatedURI, 0, originAttributes),
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
unrelatedURI,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
"example.org should be HSTS (originAttributes case)"
|
||||
);
|
||||
}
|
||||
@ -153,13 +174,23 @@ function add_tests() {
|
||||
|
||||
for (let originAttributes of originAttributesList) {
|
||||
Assert.ok(
|
||||
!sss.isSecureURI(uri, 0, originAttributes),
|
||||
!sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
"a.pinning.example.com should not be HSTS now " +
|
||||
"(originAttributes case)"
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
sss.isSecureURI(unrelatedURI, 0, originAttributes),
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
unrelatedURI,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
"example.org should still be HSTS (originAttributes case)"
|
||||
);
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ function run_test() {
|
||||
"@mozilla.org/security/transportsecurityinfo;1"
|
||||
].createInstance(Ci.nsITransportSecurityInfo);
|
||||
SSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=10000",
|
||||
secInfo,
|
||||
@ -58,7 +59,7 @@ function run_test() {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(
|
||||
SSService.isSecureURI(uri, 0),
|
||||
SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
"Domain for the OCSP AIA URI should be considered a HSTS host, otherwise" +
|
||||
" we wouldn't be testing what we think we're testing"
|
||||
);
|
||||
|
@ -21,8 +21,8 @@ const TESTCASES = [
|
||||
|
||||
let sss = Cc["@mozilla.org/ssservice;1"].getService(Ci.nsISiteSecurityService);
|
||||
|
||||
function getEntries() {
|
||||
return Array.from(sss.enumerate());
|
||||
function getEntries(type) {
|
||||
return Array.from(sss.enumerate(type));
|
||||
}
|
||||
|
||||
function checkSiteSecurityStateAttrs(entries) {
|
||||
@ -71,6 +71,7 @@ function add_tests() {
|
||||
header += "; includeSubdomains";
|
||||
}
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
header,
|
||||
secInfo,
|
||||
@ -82,12 +83,12 @@ function add_tests() {
|
||||
}
|
||||
|
||||
add_task(() => {
|
||||
let hstsEntries = getEntries();
|
||||
let hstsEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HSTS);
|
||||
|
||||
checkSiteSecurityStateAttrs(hstsEntries);
|
||||
|
||||
sss.clearAll();
|
||||
hstsEntries = getEntries();
|
||||
hstsEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HSTS);
|
||||
|
||||
equal(hstsEntries.length, 0, "Should clear all HSTS entries");
|
||||
});
|
||||
|
@ -53,6 +53,7 @@ function do_state_read(aSubject, aTopic, aData) {
|
||||
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://frequentlyused.example.com"),
|
||||
0
|
||||
)
|
||||
@ -63,6 +64,7 @@ function do_state_read(aSubject, aTopic, aData) {
|
||||
for (let i = 0; i < 2000; i++) {
|
||||
let uri = Services.io.newURI("http://bad" + i + ".example.com");
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000",
|
||||
secInfo,
|
||||
|
@ -24,6 +24,7 @@ function doTest(secInfo, originAttributes1, originAttributes2, shouldShare) {
|
||||
let header = GOOD_MAX_AGE;
|
||||
// Set HSTS for originAttributes1.
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
header,
|
||||
secInfo,
|
||||
@ -32,11 +33,21 @@ function doTest(secInfo, originAttributes1, originAttributes2, shouldShare) {
|
||||
originAttributes1
|
||||
);
|
||||
ok(
|
||||
sss.isSecureURI(uri, 0, originAttributes1),
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes1
|
||||
),
|
||||
"URI should be secure given original origin attributes"
|
||||
);
|
||||
equal(
|
||||
sss.isSecureURI(uri, 0, originAttributes2),
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes2
|
||||
),
|
||||
shouldShare,
|
||||
"URI should be secure given different origin attributes if and " +
|
||||
"only if shouldShare is true"
|
||||
@ -44,17 +55,37 @@ function doTest(secInfo, originAttributes1, originAttributes2, shouldShare) {
|
||||
|
||||
if (!shouldShare) {
|
||||
// Remove originAttributes2 from the storage.
|
||||
sss.resetState(uri, 0, originAttributes2);
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes2
|
||||
);
|
||||
ok(
|
||||
sss.isSecureURI(uri, 0, originAttributes1),
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes1
|
||||
),
|
||||
"URI should still be secure given original origin attributes"
|
||||
);
|
||||
}
|
||||
|
||||
// Remove originAttributes1 from the storage.
|
||||
sss.resetState(uri, 0, originAttributes1);
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes1
|
||||
);
|
||||
ok(
|
||||
!sss.isSecureURI(uri, 0, originAttributes1),
|
||||
!sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes1
|
||||
),
|
||||
"URI should not be secure after removeState"
|
||||
);
|
||||
|
||||
@ -67,6 +98,7 @@ function testInvalidOriginAttributes(secInfo, originAttributes) {
|
||||
let callbacks = [
|
||||
() =>
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
header,
|
||||
secInfo,
|
||||
@ -74,8 +106,20 @@ function testInvalidOriginAttributes(secInfo, originAttributes) {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST,
|
||||
originAttributes
|
||||
),
|
||||
() => sss.isSecureURI(uri, 0, originAttributes),
|
||||
() => sss.resetState(uri, 0, originAttributes),
|
||||
() =>
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
() =>
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
];
|
||||
|
||||
for (let callback of callbacks) {
|
||||
|
@ -17,48 +17,56 @@ function checkStateRead(aSubject, aTopic, aData) {
|
||||
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://expired.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://notexpired.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sub.includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://incsubdomain.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sub.incsubdomain.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains2.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sub.includesubdomains2.preloaded.test"),
|
||||
0
|
||||
)
|
||||
@ -68,48 +76,56 @@ function checkStateRead(aSubject, aTopic, aData) {
|
||||
gSSService.clearAll();
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://expired.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://notexpired.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sub.includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://incsubdomain.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sub.incsubdomain.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains2.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sub.includesubdomains2.preloaded.test"),
|
||||
0
|
||||
)
|
||||
|
@ -12,12 +12,14 @@ function checkStateRead(aSubject, aTopic, aData) {
|
||||
// nonexistent.example.com should never be an HSTS host
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://nonexistent.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
@ -26,6 +28,7 @@ function checkStateRead(aSubject, aTopic, aData) {
|
||||
// want to make sure that test hasn't interfered with this one.
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://notexpired.example.com"),
|
||||
0
|
||||
)
|
||||
|
@ -21,7 +21,11 @@ function checkStateRead(aSubject, aTopic, aData) {
|
||||
];
|
||||
for (let host of HSTS_HOSTS) {
|
||||
ok(
|
||||
gSSService.isSecureURI(Services.io.newURI(host), 0),
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI(host),
|
||||
0
|
||||
),
|
||||
`${host} should be HSTS enabled`
|
||||
);
|
||||
}
|
||||
@ -41,7 +45,11 @@ function checkStateRead(aSubject, aTopic, aData) {
|
||||
];
|
||||
for (let host of NOT_HSTS_HOSTS) {
|
||||
ok(
|
||||
!gSSService.isSecureURI(Services.io.newURI(host), 0),
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI(host),
|
||||
0
|
||||
),
|
||||
`${host} should not be HSTS enabled`
|
||||
);
|
||||
}
|
||||
|
@ -18,42 +18,49 @@ function checkStateRead(aSubject, aTopic, aData) {
|
||||
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://example0.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://example423.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://example1023.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://example1024.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://example1025.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://example9000.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://example99999.example.com"),
|
||||
0
|
||||
)
|
||||
|
@ -14,70 +14,74 @@ var gSSService = Cc["@mozilla.org/ssservice;1"].getService(
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
|
||||
function test_removeState(secInfo, flags) {
|
||||
info(`running test_removeState(flags=${flags})`);
|
||||
function test_removeState(secInfo, type, flags) {
|
||||
info(`running test_removeState(type=${type}, flags=${flags})`);
|
||||
// Simulate visiting a non-preloaded site by processing an HSTS header check
|
||||
// that the HSTS bit gets set, simulate "forget about this site" (call
|
||||
// removeState), and then check that the HSTS bit isn't set.
|
||||
let notPreloadedURI = Services.io.newURI("https://not-preloaded.example.com");
|
||||
ok(!gSSService.isSecureURI(notPreloadedURI, flags));
|
||||
ok(!gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
gSSService.processHeader(
|
||||
type,
|
||||
notPreloadedURI,
|
||||
"max-age=1000;",
|
||||
secInfo,
|
||||
flags,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(gSSService.isSecureURI(notPreloadedURI, flags));
|
||||
gSSService.resetState(notPreloadedURI, flags);
|
||||
ok(!gSSService.isSecureURI(notPreloadedURI, flags));
|
||||
ok(gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
gSSService.resetState(type, notPreloadedURI, flags);
|
||||
ok(!gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
|
||||
// Simulate visiting a non-preloaded site that unsets HSTS by processing
|
||||
// an HSTS header with "max-age=0", check that the HSTS bit isn't
|
||||
// set, simulate "forget about this site" (call removeState), and then check
|
||||
// that the HSTS bit isn't set.
|
||||
gSSService.processHeader(
|
||||
type,
|
||||
notPreloadedURI,
|
||||
"max-age=0;",
|
||||
secInfo,
|
||||
flags,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(!gSSService.isSecureURI(notPreloadedURI, flags));
|
||||
gSSService.resetState(notPreloadedURI, flags);
|
||||
ok(!gSSService.isSecureURI(notPreloadedURI, flags));
|
||||
ok(!gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
gSSService.resetState(type, notPreloadedURI, flags);
|
||||
ok(!gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
|
||||
// Simulate visiting a preloaded site by processing an HSTS header, check
|
||||
// that the HSTS bit is still set, simulate "forget about this site"
|
||||
// (call removeState), and then check that the HSTS bit is still set.
|
||||
let preloadedHost = "includesubdomains.preloaded.test";
|
||||
let preloadedURI = Services.io.newURI(`https://${preloadedHost}`);
|
||||
ok(gSSService.isSecureURI(preloadedURI, flags));
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
gSSService.processHeader(
|
||||
type,
|
||||
preloadedURI,
|
||||
"max-age=1000;",
|
||||
secInfo,
|
||||
flags,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(gSSService.isSecureURI(preloadedURI, flags));
|
||||
gSSService.resetState(preloadedURI, flags);
|
||||
ok(gSSService.isSecureURI(preloadedURI, flags));
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
gSSService.resetState(type, preloadedURI, flags);
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
|
||||
// Simulate visiting a preloaded site that unsets HSTS by processing an
|
||||
// HSTS header with "max-age=0", check that the HSTS bit is what we
|
||||
// expect (see below), simulate "forget about this site" (call removeState),
|
||||
// and then check that the HSTS bit is set.
|
||||
gSSService.processHeader(
|
||||
type,
|
||||
preloadedURI,
|
||||
"max-age=0;",
|
||||
secInfo,
|
||||
flags,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(!gSSService.isSecureURI(preloadedURI, flags));
|
||||
gSSService.resetState(preloadedURI, flags);
|
||||
ok(gSSService.isSecureURI(preloadedURI, flags));
|
||||
ok(!gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
gSSService.resetState(type, preloadedURI, flags);
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
}
|
||||
|
||||
function add_tests() {
|
||||
@ -92,8 +96,12 @@ function add_tests() {
|
||||
);
|
||||
|
||||
add_task(() => {
|
||||
test_removeState(secInfo, 0);
|
||||
test_removeState(secInfo, Ci.nsISocketProvider.NO_PERMANENT_STORAGE);
|
||||
test_removeState(secInfo, Ci.nsISiteSecurityService.HEADER_HSTS, 0);
|
||||
test_removeState(
|
||||
secInfo,
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Ci.nsISocketProvider.NO_PERMANENT_STORAGE
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ add_task(async function run_test() {
|
||||
].createInstance(Ci.nsITransportSecurityInfo);
|
||||
let header = "max-age=50000";
|
||||
SSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("http://example.com"),
|
||||
header,
|
||||
secInfo,
|
||||
|
@ -108,6 +108,7 @@ function run_test() {
|
||||
"@mozilla.org/security/transportsecurityinfo;1"
|
||||
].createInstance(Ci.nsITransportSecurityInfo);
|
||||
SSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uris[uriIndex],
|
||||
maxAge + includeSubdomains,
|
||||
secInfo,
|
||||
|
@ -11,29 +11,30 @@ function run_test() {
|
||||
let uri = Services.io.newURI("https://example.com");
|
||||
let uri1 = Services.io.newURI("https://example.com.");
|
||||
let uri2 = Services.io.newURI("https://example.com..");
|
||||
ok(!SSService.isSecureURI(uri, 0));
|
||||
ok(!SSService.isSecureURI(uri1, 0));
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri1, 0));
|
||||
// These cases are only relevant as long as bug 1118522 hasn't been fixed.
|
||||
ok(!SSService.isSecureURI(uri2, 0));
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri2, 0));
|
||||
|
||||
let secInfo = Cc[
|
||||
"@mozilla.org/security/transportsecurityinfo;1"
|
||||
].createInstance(Ci.nsITransportSecurityInfo);
|
||||
SSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000;includeSubdomains",
|
||||
secInfo,
|
||||
0,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(SSService.isSecureURI(uri, 0));
|
||||
ok(SSService.isSecureURI(uri1, 0));
|
||||
ok(SSService.isSecureURI(uri2, 0));
|
||||
ok(SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri1, 0));
|
||||
ok(SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri2, 0));
|
||||
|
||||
SSService.resetState(uri, 0);
|
||||
ok(!SSService.isSecureURI(uri, 0));
|
||||
ok(!SSService.isSecureURI(uri1, 0));
|
||||
ok(!SSService.isSecureURI(uri2, 0));
|
||||
SSService.resetState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri1, 0));
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri2, 0));
|
||||
|
||||
// Somehow creating this malformed URI succeeds - we need to handle it
|
||||
// gracefully.
|
||||
@ -41,7 +42,7 @@ function run_test() {
|
||||
equal(uri.host, "..");
|
||||
throws(
|
||||
() => {
|
||||
SSService.isSecureURI(uri, 0);
|
||||
SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
},
|
||||
/NS_ERROR_UNEXPECTED/,
|
||||
"Malformed URI should be rejected"
|
||||
|
@ -16,11 +16,12 @@ function check_ip(s, v, ip) {
|
||||
str += "/";
|
||||
|
||||
let uri = Services.io.newURI(str);
|
||||
ok(!s.isSecureURI(uri, 0));
|
||||
ok(!s.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
|
||||
let parsedMaxAge = {};
|
||||
let parsedIncludeSubdomains = {};
|
||||
s.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000;includeSubdomains",
|
||||
secInfo,
|
||||
@ -31,7 +32,7 @@ function check_ip(s, v, ip) {
|
||||
parsedIncludeSubdomains
|
||||
);
|
||||
ok(
|
||||
!s.isSecureURI(uri, 0),
|
||||
!s.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
"URI should not be secure if it contains an IP address"
|
||||
);
|
||||
|
||||
|
@ -19,6 +19,7 @@ function testSuccess(header, expectedMaxAge, expectedIncludeSubdomains) {
|
||||
let includeSubdomains = {};
|
||||
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
dummyUri,
|
||||
header,
|
||||
secInfo,
|
||||
@ -45,6 +46,7 @@ function testFailure(header) {
|
||||
throws(
|
||||
() => {
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
dummyUri,
|
||||
header,
|
||||
secInfo,
|
||||
|
@ -40,13 +40,20 @@ function test_part1() {
|
||||
// check that a host not in the list is not identified as an sts host
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://nonexistent.example.com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
// check that an ancestor domain is not identified as an sts host
|
||||
ok(!gSSService.isSecureURI(Services.io.newURI("https://com"), 0));
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
// check that the pref to toggle using the preload list works
|
||||
Services.prefs.setBoolPref(
|
||||
@ -55,6 +62,7 @@ function test_part1() {
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
@ -65,6 +73,7 @@ function test_part1() {
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
@ -73,6 +82,7 @@ function test_part1() {
|
||||
// check that a subdomain is an sts host (includeSubdomains is set)
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://subdomain.includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
@ -81,6 +91,7 @@ function test_part1() {
|
||||
// check that another subdomain is an sts host (includeSubdomains is set)
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://a.b.c.def.includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
@ -89,6 +100,7 @@ function test_part1() {
|
||||
// check that a subdomain is not an sts host (includeSubdomains is not set)
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI(
|
||||
"https://subdomain.noincludesubdomains.preloaded.test"
|
||||
),
|
||||
@ -99,6 +111,7 @@ function test_part1() {
|
||||
// check that a host with a dot on the end won't break anything
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://notsts.nonexistent.example.com."),
|
||||
0
|
||||
)
|
||||
@ -111,26 +124,40 @@ function test_part1() {
|
||||
"https://subdomain.includesubdomains.preloaded.test"
|
||||
);
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=0",
|
||||
secInfo,
|
||||
0,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(!gSSService.isSecureURI(uri, 0));
|
||||
ok(!gSSService.isSecureURI(subDomainUri, 0));
|
||||
ok(!gSSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
0
|
||||
)
|
||||
);
|
||||
// check that processing another header (with max-age non-zero) will
|
||||
// re-enable a site's sts status
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000",
|
||||
secInfo,
|
||||
0,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(gSSService.isSecureURI(uri, 0));
|
||||
ok(gSSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
// but this time include subdomains was not set, so test for that
|
||||
ok(!gSSService.isSecureURI(subDomainUri, 0));
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
0
|
||||
)
|
||||
);
|
||||
gSSService.clearAll();
|
||||
|
||||
// check that processing a header with max-age: 0 from a subdomain of a site
|
||||
@ -139,6 +166,7 @@ function test_part1() {
|
||||
"https://subdomain.noincludesubdomains.preloaded.test"
|
||||
);
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=0",
|
||||
secInfo,
|
||||
@ -147,16 +175,18 @@ function test_part1() {
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://noincludesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(!gSSService.isSecureURI(uri, 0));
|
||||
ok(!gSSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
|
||||
uri = Services.io.newURI(
|
||||
"https://subdomain.includesubdomains.preloaded.test"
|
||||
);
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=0",
|
||||
secInfo,
|
||||
@ -174,24 +204,28 @@ function test_part1() {
|
||||
// `-- sibling.includesubdomains.preloaded.test IS sts host
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://subdomain.includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sibling.includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI(
|
||||
"https://another.subdomain.includesubdomains.preloaded.test"
|
||||
),
|
||||
@ -200,6 +234,7 @@ function test_part1() {
|
||||
);
|
||||
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000",
|
||||
secInfo,
|
||||
@ -213,18 +248,21 @@ function test_part1() {
|
||||
// `-- sibling.includesubdomains.preloaded.test IS sts host
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://subdomain.includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://sibling.includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI(
|
||||
"https://another.subdomain.includesubdomains.preloaded.test"
|
||||
),
|
||||
@ -239,8 +277,9 @@ function test_part1() {
|
||||
// then treat that host as no longer an sts host.)
|
||||
// (sanity check first - this should be in the preload list)
|
||||
uri = Services.io.newURI("https://includesubdomains2.preloaded.test");
|
||||
ok(gSSService.isSecureURI(uri, 0));
|
||||
ok(gSSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1",
|
||||
secInfo,
|
||||
@ -248,7 +287,7 @@ function test_part1() {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
do_timeout(1250, function() {
|
||||
ok(!gSSService.isSecureURI(uri, 0));
|
||||
ok(!gSSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
@ -262,41 +301,92 @@ function test_private_browsing1() {
|
||||
"https://a.b.c.subdomain.includesubdomains.preloaded.test"
|
||||
);
|
||||
// sanity - includesubdomains.preloaded.test is preloaded, includeSubdomains set
|
||||
ok(gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
ok(gSSService.isSecureURI(subDomainUri, IS_PRIVATE));
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=0",
|
||||
secInfo,
|
||||
IS_PRIVATE,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(!gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
ok(!gSSService.isSecureURI(subDomainUri, IS_PRIVATE));
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
|
||||
// check adding it back in
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000",
|
||||
secInfo,
|
||||
IS_PRIVATE,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
// but no includeSubdomains this time
|
||||
ok(!gSSService.isSecureURI(subDomainUri, IS_PRIVATE));
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
|
||||
// do the hokey-pokey...
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=0",
|
||||
secInfo,
|
||||
IS_PRIVATE,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(!gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
ok(!gSSService.isSecureURI(subDomainUri, IS_PRIVATE));
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
|
||||
// Test that an expired private browsing entry results in correctly
|
||||
// identifying a host that is on the preload list as no longer sts.
|
||||
@ -305,8 +395,15 @@ function test_private_browsing1() {
|
||||
// then treat that host as no longer an sts host.)
|
||||
// (sanity check first - this should be in the preload list)
|
||||
uri = Services.io.newURI("https://includesubdomains2.preloaded.test");
|
||||
ok(gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1",
|
||||
secInfo,
|
||||
@ -314,7 +411,13 @@ function test_private_browsing1() {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
do_timeout(1250, function() {
|
||||
ok(!gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
// Simulate leaving private browsing mode
|
||||
Services.obs.notifyObservers(null, "last-pb-context-exited");
|
||||
});
|
||||
@ -324,6 +427,7 @@ function test_private_browsing2() {
|
||||
// if this test gets this far, it means there's a private browsing service
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
@ -331,6 +435,7 @@ function test_private_browsing2() {
|
||||
// the includesubdomains.preloaded.test entry has includeSubdomains set
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://subdomain.includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
@ -340,6 +445,7 @@ function test_private_browsing2() {
|
||||
// we've "forgotten" that we "forgot" this site's sts status.
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains2.preloaded.test"),
|
||||
0
|
||||
)
|
||||
|
@ -7,16 +7,16 @@ function run_test() {
|
||||
let uri = Services.io.newURI("https://includesubdomains.preloaded.test");
|
||||
|
||||
// check that a host on the preload list is identified as an sts host
|
||||
ok(SSService.isSecureURI(uri, 0));
|
||||
ok(SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
|
||||
// now simulate that it's 19 weeks later than it actually is
|
||||
let offsetSeconds = 19 * 7 * 24 * 60 * 60;
|
||||
Services.prefs.setIntPref("test.currentTimeOffsetSeconds", offsetSeconds);
|
||||
|
||||
// check that the preloaded host is no longer considered sts
|
||||
ok(!SSService.isSecureURI(uri, 0));
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
|
||||
// just make sure we can get everything back to normal
|
||||
Services.prefs.clearUserPref("test.currentTimeOffsetSeconds");
|
||||
ok(SSService.isSecureURI(uri, 0));
|
||||
ok(SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
}
|
||||
|
@ -120,6 +120,7 @@ function processStsHeader(host, header, status, securityInfo) {
|
||||
let uri = Services.io.newURI("https://" + host.name);
|
||||
let secInfo = securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
header,
|
||||
secInfo,
|
||||
|
@ -1039,7 +1039,7 @@ class SpecialPowersParent extends JSWindowActorParent {
|
||||
let sss = Cc["@mozilla.org/ssservice;1"].getService(
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
sss.resetState(uri, flags);
|
||||
sss.resetState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, flags);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,12 @@ function cleanupHSTS(aPartitionEnabled, aUseSite) {
|
||||
}
|
||||
}
|
||||
|
||||
sss.resetState(NetUtil.newURI("http://example.com/"), 0, originAttributes);
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
NetUtil.newURI("http://example.com/"),
|
||||
0,
|
||||
originAttributes
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1055,12 +1055,17 @@ const SecuritySettingsCleaner = {
|
||||
);
|
||||
// Also remove HSTS information for subdomains by enumerating
|
||||
// the information in the site security service.
|
||||
for (let entry of sss.enumerate()) {
|
||||
for (let entry of sss.enumerate(Ci.nsISiteSecurityService.HEADER_HSTS)) {
|
||||
let hostname = entry.hostname;
|
||||
if (Services.eTLD.hasRootDomain(hostname, aHost)) {
|
||||
// This uri is used as a key to reset the state.
|
||||
let uri = Services.io.newURI("https://" + hostname);
|
||||
sss.resetState(uri, 0, entry.originAttributes);
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
entry.originAttributes
|
||||
);
|
||||
}
|
||||
}
|
||||
let cars = Cc[
|
||||
@ -1081,14 +1086,19 @@ const SecuritySettingsCleaner = {
|
||||
|
||||
// Remove HSTS information by enumerating entries of the site security
|
||||
// service.
|
||||
Array.from(sss.enumerate())
|
||||
Array.from(sss.enumerate(Ci.nsISiteSecurityService.HEADER_HSTS))
|
||||
.filter(({ hostname, originAttributes }) =>
|
||||
hasBaseDomain({ host: hostname, originAttributes }, aDomain)
|
||||
)
|
||||
.forEach(({ hostname, originAttributes }) => {
|
||||
// This uri is used as a key to reset the state.
|
||||
let uri = Services.io.newURI("https://" + hostname);
|
||||
sss.resetState(uri, 0, originAttributes);
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes
|
||||
);
|
||||
});
|
||||
|
||||
let cars = Cc[
|
||||
|
@ -19,6 +19,7 @@ function addSecurityInfo({ host, topLevelBaseDomain, originAttributes = {} }) {
|
||||
].createInstance(Ci.nsITransportSecurityInfo);
|
||||
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000;",
|
||||
secInfo,
|
||||
@ -62,6 +63,7 @@ function testSecurityInfo({
|
||||
}) {
|
||||
let uri = Services.io.newURI(`https://${host}`);
|
||||
let isSecure = gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
getOAWithPartitionKey(topLevelBaseDomain, originAttributes)
|
||||
|
@ -23,12 +23,6 @@ XPCOMUtils.defineLazyServiceGetter(
|
||||
"@mozilla.org/ssservice;1",
|
||||
"nsISiteSecurityService"
|
||||
);
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
this,
|
||||
"pkps",
|
||||
"@mozilla.org/security/publickeypinningservice;1",
|
||||
"nsIPublicKeyPinningService"
|
||||
);
|
||||
|
||||
// NOTE: SecurityInfo is largely reworked from the devtools NetworkHelper with changes
|
||||
// to better support the WebRequest api. The objects returned are formatted specifically
|
||||
@ -199,8 +193,8 @@ const SecurityInfo = {
|
||||
flags = Ci.nsISocketProvider.NO_PERMANENT_STORAGE;
|
||||
}
|
||||
|
||||
info.hsts = sss.isSecureURI(uri, flags);
|
||||
info.hpkp = pkps.hostHasPins(uri);
|
||||
info.hsts = sss.isSecureURI(sss.HEADER_HSTS, uri, flags);
|
||||
info.hpkp = sss.isSecureURI(sss.STATIC_PINNING, uri, flags);
|
||||
} else {
|
||||
info.hsts = false;
|
||||
info.hpkp = false;
|
||||
|
Loading…
Reference in New Issue
Block a user