mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1715142 - introduce nsIPublicKeyPinningService and remove 'type' parameter from nsISiteSecurityService r=rmf,necko-reviewers
The public key pinning implementation is much less complex than the HSTS implementation, and only needs a small subset of the parameters of the latter. Furthermore, the information it relies on is static, and so is safe to access from content processes. This patch separates the two implementations, thus simplifying both of them and avoiding some unnecessary IPC calls in the process. Differential Revision: https://phabricator.services.mozilla.com/D117096
This commit is contained in:
parent
20319689f0
commit
ef0a88c6f2
@ -15,7 +15,6 @@ 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,6 +685,9 @@ 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
|
||||
@ -699,8 +702,8 @@ var NetworkHelper = {
|
||||
uri = Services.io.newURI("https://" + host);
|
||||
}
|
||||
|
||||
info.hsts = sss.isSecureURI(sss.HEADER_HSTS, uri, flags);
|
||||
info.hpkp = sss.isSecureURI(sss.STATIC_PINNING, uri, flags);
|
||||
info.hsts = sss.isSecureURI(uri, flags);
|
||||
info.hpkp = pkps.hostHasPins(uri);
|
||||
} 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(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
gSSService.resetState(uri, 0);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -139,6 +139,7 @@
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIPromptCollection.h"
|
||||
#include "nsIPromptFactory.h"
|
||||
#include "nsIPublicKeyPinningService.h"
|
||||
#include "nsIReflowObserver.h"
|
||||
#include "nsIScriptChannel.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
@ -3714,21 +3715,18 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
||||
nsCOMPtr<nsISiteSecurityService> sss =
|
||||
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
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);
|
||||
rv = sss->IsSecureURI(aURI, flags, attrsForHSTS, nullptr, nullptr,
|
||||
&isStsHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
mozilla::dom::ContentChild* cc =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
|
||||
attrsForHSTS, &isStsHost);
|
||||
cc->SendIsSecureURI(nsISiteSecurityService::STATIC_PINNING, aURI, flags,
|
||||
GetOriginAttributes(), &isPinnedHost);
|
||||
cc->SendIsSecureURI(aURI, flags, attrsForHSTS, &isStsHost);
|
||||
}
|
||||
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,6 +341,7 @@
|
||||
#include "nsIPermission.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsIPublicKeyPinningService.h"
|
||||
#include "nsIReferrerInfo.h"
|
||||
#include "nsIRefreshURI.h"
|
||||
#include "nsIRequest.h"
|
||||
@ -1890,23 +1891,22 @@ void Document::GetFailedCertSecurityInfo(FailedCertSecurityInfo& aInfo,
|
||||
if (XRE_IsContentProcess()) {
|
||||
ContentChild* cc = ContentChild::GetSingleton();
|
||||
MOZ_ASSERT(cc);
|
||||
cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags, attrs,
|
||||
&aInfo.mHasHSTS);
|
||||
cc->SendIsSecureURI(nsISiteSecurityService::STATIC_PINNING, aURI, flags,
|
||||
attrs, &aInfo.mHasHPKP);
|
||||
cc->SendIsSecureURI(aURI, flags, attrs, &aInfo.mHasHSTS);
|
||||
} else {
|
||||
nsCOMPtr<nsISiteSecurityService> sss =
|
||||
do_GetService(NS_SSSERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!sss)) {
|
||||
return;
|
||||
}
|
||||
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)));
|
||||
Unused << NS_WARN_IF(NS_FAILED(sss->IsSecureURI(aURI, flags, attrs, nullptr,
|
||||
nullptr, &aInfo.mHasHSTS)));
|
||||
}
|
||||
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(
|
||||
const uint32_t& aType, nsIURI* aURI, const uint32_t& aFlags,
|
||||
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(aType, aURI, aFlags, aOriginAttributes,
|
||||
nullptr, nullptr, aIsSecureURI);
|
||||
nsresult rv = sss->IsSecureURI(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(
|
||||
const uint32_t& aType, nsIURI* aURI, const uint32_t& aFlags,
|
||||
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(uint32_t aType, nsIURI aURI, uint32_t aFlags,
|
||||
sync IsSecureURI(nsIURI aURI, uint32_t aFlags,
|
||||
OriginAttributes aOriginAttributes)
|
||||
returns (bool isSecureURI);
|
||||
|
||||
|
@ -979,8 +979,7 @@ void nsMixedContentBlocker::AccumulateMixedContentHSTS(
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, 0,
|
||||
aOriginAttributes, nullptr, nullptr, &hsts);
|
||||
rv = sss->IsSecureURI(aURI, 0, aOriginAttributes, nullptr, nullptr, &hsts);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
@ -2964,9 +2964,9 @@ nsresult NS_ShouldSecureUpgrade(
|
||||
resultCallback{std::move(aResultCallback)}]() mutable {
|
||||
uint32_t hstsSource = 0;
|
||||
bool isStsHost = false;
|
||||
nsresult rv = service->IsSecureURI(
|
||||
nsISiteSecurityService::HEADER_HSTS, uri, flags,
|
||||
originAttributes, nullptr, &hstsSource, &isStsHost);
|
||||
nsresult rv =
|
||||
service->IsSecureURI(uri, flags, originAttributes, nullptr,
|
||||
&hstsSource, &isStsHost);
|
||||
|
||||
// Successfully get the result from |IsSecureURI| implies that
|
||||
// the storage is ready to read.
|
||||
@ -2985,9 +2985,8 @@ nsresult NS_ShouldSecureUpgrade(
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI, flags,
|
||||
aOriginAttributes, nullptr, &hstsSource, &isStsHost);
|
||||
nsresult rv = sss->IsSecureURI(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,8 +1785,7 @@ nsresult nsHttpChannel::ProcessHSTSHeader(nsITransportSecurityInfo* aSecInfo,
|
||||
|
||||
uint32_t failureResult;
|
||||
uint32_t headerSource = nsISiteSecurityService::SOURCE_ORGANIC_REQUEST;
|
||||
rv = sss->ProcessHeader(nsISiteSecurityService::HEADER_HSTS, mURI,
|
||||
securityHeader, aSecInfo, aFlags, headerSource,
|
||||
rv = sss->ProcessHeader(mURI, securityHeader, aSecInfo, aFlags, headerSource,
|
||||
originAttributes, nullptr, nullptr, &failureResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsAutoString consoleErrorCategory(u"Invalid HSTS Headers"_ns);
|
||||
|
@ -2436,9 +2436,8 @@ nsresult nsHttpHandler::SpeculativeConnectInternal(
|
||||
aURI, originAttributes);
|
||||
|
||||
nsCOMPtr<nsIURI> clone;
|
||||
if (NS_SUCCEEDED(sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI,
|
||||
flags, originAttributes, nullptr, nullptr,
|
||||
&isStsHost)) &&
|
||||
if (NS_SUCCEEDED(sss->IsSecureURI(aURI, flags, originAttributes, nullptr,
|
||||
nullptr, &isStsHost)) &&
|
||||
isStsHost) {
|
||||
if (NS_SUCCEEDED(NS_GetSecureUpgradedURI(aURI, getter_AddRefs(clone)))) {
|
||||
aURI = clone.get();
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsDependentString.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsSiteSecurityService.h"
|
||||
#include "mozpkix/pkixtypes.h"
|
||||
#include "mozpkix/pkixutil.h"
|
||||
#include "seccomon.h"
|
||||
@ -28,6 +29,8 @@ using namespace mozilla::psm;
|
||||
|
||||
LazyLogModule gPublicKeyPinningLog("PublicKeyPinningService");
|
||||
|
||||
NS_IMPL_ISUPPORTS(PublicKeyPinningService, nsIPublicKeyPinningService)
|
||||
|
||||
enum class PinningMode : uint32_t {
|
||||
Disabled = 0,
|
||||
AllowUserCAMITM = 1,
|
||||
@ -348,24 +351,32 @@ nsresult PublicKeyPinningService::ChainHasValidPins(
|
||||
pinningTelemetryInfo);
|
||||
}
|
||||
|
||||
nsresult PublicKeyPinningService::HostHasPins(const char* hostname,
|
||||
mozilla::pkix::Time time,
|
||||
/*out*/ bool& hostHasPins) {
|
||||
hostHasPins = false;
|
||||
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 canonicalizedHostname(CanonicalizeHostname(hostname));
|
||||
nsAutoCString hostname;
|
||||
nsresult rv = nsSiteSecurityService::GetHost(aURI, hostname);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (nsSiteSecurityService::HostIsIPAddress(hostname)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const TransportSecurityPreload* staticFingerprints = nullptr;
|
||||
nsresult rv = FindPinningInformation(canonicalizedHostname.get(), time,
|
||||
staticFingerprints);
|
||||
rv = FindPinningInformation(hostname.get(), Now(), staticFingerprints);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (staticFingerprints) {
|
||||
hostHasPins = !staticFingerprints->mTestMode ||
|
||||
pinningMode == PinningMode::EnforceTestMode;
|
||||
*hostHasPins = !staticFingerprints->mTestMode ||
|
||||
pinningMode == PinningMode::EnforceTestMode;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -6,9 +6,7 @@
|
||||
#define PublicKeyPinningService_h
|
||||
|
||||
#include "CertVerifier.h"
|
||||
#include "ScopedNSSTypes.h"
|
||||
#include "cert.h"
|
||||
#include "nsNSSCertificate.h"
|
||||
#include "nsIPublicKeyPinningService.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/Span.h"
|
||||
@ -17,8 +15,13 @@
|
||||
namespace mozilla {
|
||||
namespace psm {
|
||||
|
||||
class PublicKeyPinningService {
|
||||
class PublicKeyPinningService final : public nsIPublicKeyPinningService {
|
||||
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
|
||||
@ -34,20 +37,15 @@ class PublicKeyPinningService {
|
||||
/*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,
|
||||
/*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,6 +117,7 @@
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsICertOverrideService.h"
|
||||
#include "nsIPublicKeyPinningService.h"
|
||||
#include "nsISiteSecurityService.h"
|
||||
#include "nsISocketProvider.h"
|
||||
#include "nsThreadPool.h"
|
||||
@ -428,18 +429,24 @@ static nsresult OverrideAllowedForHost(
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, uri,
|
||||
aProviderFlags, aOriginAttributes, nullptr, nullptr,
|
||||
&strictTransportSecurityEnabled);
|
||||
rv = sss->IsSecureURI(uri, aProviderFlags, aOriginAttributes, nullptr,
|
||||
nullptr, &strictTransportSecurityEnabled);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
("[0x%" PRIx64 "] checking for HSTS failed", aPtrForLog));
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = sss->IsSecureURI(nsISiteSecurityService::STATIC_PINNING, uri,
|
||||
aProviderFlags, aOriginAttributes, nullptr, nullptr,
|
||||
&isStaticallyPinned);
|
||||
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);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
("[0x%" PRIx64 "] checking for static pin failed", aPtrForLog));
|
||||
|
@ -147,6 +147,12 @@ 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,6 +36,7 @@ XPIDL_SOURCES += [
|
||||
"nsIPKCS11ModuleDB.idl",
|
||||
"nsIPKCS11Slot.idl",
|
||||
"nsIProtectedAuthThread.idl",
|
||||
"nsIPublicKeyPinningService.idl",
|
||||
"nsISecretDecoderRing.idl",
|
||||
"nsISecurityUITelemetry.idl",
|
||||
"nsISiteSecurityService.idl",
|
||||
|
22
security/manager/ssl/nsIPublicKeyPinningService.idl
Normal file
22
security/manager/ssl/nsIPublicKeyPinningService.idl
Normal file
@ -0,0 +1,22 @@
|
||||
/* 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,10 +45,6 @@ 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;
|
||||
@ -84,7 +80,6 @@ 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.
|
||||
@ -107,8 +102,7 @@ interface nsISiteSecurityService : nsISupports
|
||||
* if there are unrecognized tokens in the header.
|
||||
*/
|
||||
[binaryname(ProcessHeader), noscript, must_use]
|
||||
void processHeaderNative(in uint32_t aType,
|
||||
in nsIURI aSourceURI,
|
||||
void processHeaderNative(in nsIURI aSourceURI,
|
||||
in ACString aHeader,
|
||||
in nsITransportSecurityInfo aSecInfo,
|
||||
in uint32_t aFlags,
|
||||
@ -120,8 +114,7 @@ interface nsISiteSecurityService : nsISupports
|
||||
|
||||
[binaryname(ProcessHeaderScriptable), implicit_jscontext, optional_argc,
|
||||
must_use]
|
||||
void processHeader(in uint32_t aType,
|
||||
in nsIURI aSourceURI,
|
||||
void processHeader(in nsIURI aSourceURI,
|
||||
in ACString aHeader,
|
||||
in nsITransportSecurityInfo aSecInfo,
|
||||
in uint32_t aFlags,
|
||||
@ -132,14 +125,12 @@ interface nsISiteSecurityService : nsISupports
|
||||
[optional] out uint32_t aFailureResult);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @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
|
||||
@ -150,21 +141,19 @@ interface nsISiteSecurityService : nsISupports
|
||||
* happens).
|
||||
*/
|
||||
[implicit_jscontext, optional_argc, must_use]
|
||||
void resetState(in uint32_t aType,
|
||||
in nsIURI aURI,
|
||||
void resetState(in nsIURI aURI,
|
||||
in uint32_t aFlags,
|
||||
[optional] in jsval aOriginAttributes);
|
||||
|
||||
/**
|
||||
* Checks whether or not the URI's hostname has a given security state set.
|
||||
* For example, for HSTS:
|
||||
* Checks whether or not the URI's hostname has HSTS set.
|
||||
* For example:
|
||||
* 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
|
||||
@ -179,21 +168,20 @@ interface nsISiteSecurityService : nsISupports
|
||||
* SOURCE_ORGANIC_REQUEST, or SOURCE_UNKNOWN.
|
||||
*/
|
||||
[binaryname(IsSecureURI), noscript, must_use]
|
||||
boolean isSecureURINative(in uint32_t aType, in nsIURI aURI,
|
||||
in uint32_t aFlags,
|
||||
boolean isSecureURINative(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 uint32_t aType, in nsIURI aURI, in uint32_t aFlags,
|
||||
boolean isSecureURI(in nsIURI aURI, in uint32_t aFlags,
|
||||
[optional] in jsval aOriginAttributes,
|
||||
[optional] out boolean aCached,
|
||||
[optional] out uint32_t aSource);
|
||||
|
||||
/**
|
||||
* Removes all non-preloaded security state by resetting to factory-original
|
||||
* Removes all non-preloaded HSTS state by resetting to factory-original
|
||||
* settings.
|
||||
*/
|
||||
[must_use]
|
||||
@ -204,11 +192,9 @@ 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(in uint32_t aType);
|
||||
nsISimpleEnumerator enumerate();
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -45,7 +45,7 @@ static LazyLogModule gSSSLog("nsSSService");
|
||||
|
||||
#define SSSLOG(args) MOZ_LOG(gSSSLog, mozilla::LogLevel::Debug, args)
|
||||
|
||||
const char kHSTSKeySuffix[] = ":HSTS";
|
||||
static const nsLiteralCString kHSTSKeySuffix = ":HSTS"_ns;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -286,7 +286,7 @@ nsresult nsSiteSecurityService::GetHost(nsIURI* aURI, nsACString& aResult) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void SetStorageKey(const nsACString& hostname, uint32_t aType,
|
||||
static void SetStorageKey(const nsACString& hostname,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
/*out*/ nsAutoCString& storageKey) {
|
||||
storageKey = hostname;
|
||||
@ -298,13 +298,7 @@ static void SetStorageKey(const nsACString& hostname, uint32_t aType,
|
||||
nsAutoCString originAttributesSuffix;
|
||||
originAttributesNoUserContext.CreateSuffix(originAttributesSuffix);
|
||||
storageKey.Append(originAttributesSuffix);
|
||||
switch (aType) {
|
||||
case nsISiteSecurityService::HEADER_HSTS:
|
||||
storageKey.AppendASCII(kHSTSKeySuffix);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("SSS:SetStorageKey got invalid type");
|
||||
}
|
||||
storageKey.Append(kHSTSKeySuffix);
|
||||
}
|
||||
|
||||
// Expire times are in millis. Since Headers max-age is in seconds, and
|
||||
@ -314,17 +308,16 @@ static int64_t ExpireTimeFromMaxAge(uint64_t maxAge) {
|
||||
}
|
||||
|
||||
nsresult nsSiteSecurityService::SetHSTSState(
|
||||
uint32_t aType, const char* aHost, int64_t maxage, bool includeSubdomains,
|
||||
uint32_t flags, SecurityPropertyState aHSTSState,
|
||||
SecurityPropertySource aSource, const OriginAttributes& aOriginAttributes) {
|
||||
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(aType, hostname, flags, isPreload,
|
||||
aOriginAttributes);
|
||||
return MarkHostAsNotHSTS(hostname, flags, isPreload, aOriginAttributes);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aHSTSState == SecurityPropertySet,
|
||||
@ -345,7 +338,7 @@ nsresult nsSiteSecurityService::SetHSTSState(
|
||||
? mozilla::DataStorage_Private
|
||||
: mozilla::DataStorage_Persistent;
|
||||
nsAutoCString storageKey;
|
||||
SetStorageKey(hostname, aType, aOriginAttributes, storageKey);
|
||||
SetStorageKey(hostname, aOriginAttributes, storageKey);
|
||||
SSSLOG(("SSS: storing HSTS site entry for %s", hostname.get()));
|
||||
nsCString value = mSiteStateStorage->Get(storageKey, storageType);
|
||||
RefPtr<SiteHSTSState> curSiteState =
|
||||
@ -367,12 +360,8 @@ nsresult nsSiteSecurityService::SetHSTSState(
|
||||
// entry that indicates this host is not HSTS to prevent the implementation
|
||||
// using the preloaded information.
|
||||
nsresult nsSiteSecurityService::MarkHostAsNotHSTS(
|
||||
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;
|
||||
}
|
||||
const nsAutoCString& aHost, uint32_t aFlags, bool aIsPreload,
|
||||
const OriginAttributes& aOriginAttributes) {
|
||||
if (aIsPreload && aOriginAttributes != OriginAttributes()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
@ -382,7 +371,7 @@ nsresult nsSiteSecurityService::MarkHostAsNotHSTS(
|
||||
? mozilla::DataStorage_Private
|
||||
: mozilla::DataStorage_Persistent;
|
||||
nsAutoCString storageKey;
|
||||
SetStorageKey(aHost, aType, aOriginAttributes, storageKey);
|
||||
SetStorageKey(aHost, aOriginAttributes, storageKey);
|
||||
|
||||
if (GetPreloadStatus(aHost)) {
|
||||
SSSLOG(("SSS: storing knockout entry for %s", aHost.get()));
|
||||
@ -402,7 +391,7 @@ nsresult nsSiteSecurityService::MarkHostAsNotHSTS(
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::ResetState(uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
nsSiteSecurityService::ResetState(nsIURI* aURI, uint32_t aFlags,
|
||||
JS::HandleValue aOriginAttributes,
|
||||
JSContext* aCx, uint8_t aArgc) {
|
||||
if (!XRE_IsParentProcess()) {
|
||||
@ -423,7 +412,7 @@ nsSiteSecurityService::ResetState(uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
}
|
||||
}
|
||||
|
||||
return ResetStateInternal(aType, aURI, aFlags, originAttributes);
|
||||
return ResetStateInternal(aURI, aFlags, originAttributes);
|
||||
}
|
||||
|
||||
// Helper function to reset stored state of the given type for the host
|
||||
@ -433,21 +422,17 @@ nsSiteSecurityService::ResetState(uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
// header with max-age=0 (meaning preloaded information will then not be used
|
||||
// for that host).
|
||||
nsresult nsSiteSecurityService::ResetStateInternal(
|
||||
uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes) {
|
||||
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, aType, aOriginAttributes, storageKey);
|
||||
SetStorageKey(hostname, aOriginAttributes, storageKey);
|
||||
bool isPrivate = aFlags & nsISocketProvider::NO_PERMANENT_STORAGE;
|
||||
mozilla::DataStorageType storageType = isPrivate
|
||||
? mozilla::DataStorage_Private
|
||||
@ -456,7 +441,7 @@ nsresult nsSiteSecurityService::ResetStateInternal(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool HostIsIPAddress(const nsCString& hostname) {
|
||||
bool nsSiteSecurityService::HostIsIPAddress(const nsCString& hostname) {
|
||||
PRNetAddr hostAddr;
|
||||
PRErrorCode prv = PR_StringToNetAddr(hostname.get(), &hostAddr);
|
||||
return (prv == PR_SUCCESS);
|
||||
@ -464,7 +449,7 @@ static bool HostIsIPAddress(const nsCString& hostname) {
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::ProcessHeaderScriptable(
|
||||
uint32_t aType, nsIURI* aSourceURI, const nsACString& aHeader,
|
||||
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,
|
||||
@ -476,14 +461,14 @@ nsSiteSecurityService::ProcessHeaderScriptable(
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
return ProcessHeader(aType, aSourceURI, aHeader, aSecInfo, aFlags, aSource,
|
||||
return ProcessHeader(aSourceURI, aHeader, aSecInfo, aFlags, aSource,
|
||||
originAttributes, aMaxAge, aIncludeSubdomains,
|
||||
aFailureResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::ProcessHeader(
|
||||
uint32_t aType, nsIURI* aSourceURI, const nsACString& aHeader,
|
||||
nsIURI* aSourceURI, const nsACString& aHeader,
|
||||
nsITransportSecurityInfo* aSecInfo, uint32_t aFlags, uint32_t aHeaderSource,
|
||||
const OriginAttributes& aOriginAttributes, uint64_t* aMaxAge,
|
||||
bool* aIncludeSubdomains, uint32_t* aFailureResult) {
|
||||
@ -497,8 +482,6 @@ 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) {
|
||||
@ -511,23 +494,19 @@ nsSiteSecurityService::ProcessHeader(
|
||||
}
|
||||
|
||||
NS_ENSURE_ARG(aSecInfo);
|
||||
return ProcessHeaderInternal(aType, aSourceURI, PromiseFlatCString(aHeader),
|
||||
return ProcessHeaderInternal(aSourceURI, PromiseFlatCString(aHeader),
|
||||
aSecInfo, aFlags, source, aOriginAttributes,
|
||||
aMaxAge, aIncludeSubdomains, aFailureResult);
|
||||
}
|
||||
|
||||
nsresult nsSiteSecurityService::ProcessHeaderInternal(
|
||||
uint32_t aType, nsIURI* aSourceURI, const nsCString& aHeader,
|
||||
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;
|
||||
}
|
||||
@ -569,19 +548,12 @@ nsresult nsSiteSecurityService::ProcessHeaderInternal(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
return ProcessSTSHeader(aSourceURI, aHeader, aFlags, aSource,
|
||||
aOriginAttributes, aMaxAge, aIncludeSubdomains,
|
||||
aFailureResult);
|
||||
}
|
||||
|
||||
static uint32_t ParseSSSHeaders(uint32_t aType, const nsCString& aHeader,
|
||||
static uint32_t ParseSSSHeaders(const nsCString& aHeader,
|
||||
bool& foundIncludeSubdomains, bool& foundMaxAge,
|
||||
bool& foundUnrecognizedDirective,
|
||||
uint64_t& maxAge) {
|
||||
@ -675,16 +647,13 @@ 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(aType, aHeader, foundIncludeSubdomains, foundMaxAge,
|
||||
foundUnrecognizedDirective, maxAge);
|
||||
uint32_t sssrv = ParseSSSHeaders(aHeader, foundIncludeSubdomains, foundMaxAge,
|
||||
foundUnrecognizedDirective, maxAge);
|
||||
if (sssrv != nsISiteSecurityService::Success) {
|
||||
if (aFailureResult) {
|
||||
*aFailureResult = sssrv;
|
||||
@ -707,8 +676,8 @@ nsresult nsSiteSecurityService::ProcessSTSHeader(
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// record the successfully parsed header data.
|
||||
rv = SetHSTSState(aType, hostname.get(), maxAge, foundIncludeSubdomains,
|
||||
aFlags, SecurityPropertySet, aSource, aOriginAttributes);
|
||||
rv = SetHSTSState(hostname.get(), maxAge, foundIncludeSubdomains, aFlags,
|
||||
SecurityPropertySet, aSource, aOriginAttributes);
|
||||
if (NS_FAILED(rv)) {
|
||||
SSSLOG(("SSS: failed to set STS state"));
|
||||
if (aFailureResult) {
|
||||
@ -730,8 +699,7 @@ nsresult nsSiteSecurityService::ProcessSTSHeader(
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::IsSecureURIScriptable(uint32_t aType, nsIURI* aURI,
|
||||
uint32_t aFlags,
|
||||
nsSiteSecurityService::IsSecureURIScriptable(nsIURI* aURI, uint32_t aFlags,
|
||||
JS::HandleValue aOriginAttributes,
|
||||
bool* aCached, uint32_t* aSource,
|
||||
JSContext* aCx, uint8_t aArgc,
|
||||
@ -743,31 +711,17 @@ nsSiteSecurityService::IsSecureURIScriptable(uint32_t aType, nsIURI* aURI,
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
return IsSecureURI(aType, aURI, aFlags, originAttributes, aCached, aSource,
|
||||
aResult);
|
||||
return IsSecureURI(aURI, aFlags, originAttributes, aCached, aSource, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::IsSecureURI(uint32_t aType, nsIURI* aURI,
|
||||
uint32_t aFlags,
|
||||
nsSiteSecurityService::IsSecureURI(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);
|
||||
@ -780,8 +734,8 @@ nsSiteSecurityService::IsSecureURI(uint32_t aType, nsIURI* aURI,
|
||||
SecurityPropertySource* source =
|
||||
BitwiseCast<SecurityPropertySource*>(aSource);
|
||||
|
||||
return IsSecureHost(aType, hostname, aFlags, aOriginAttributes, aCached,
|
||||
source, aResult);
|
||||
return IsSecureHost(hostname, aFlags, aOriginAttributes, aCached, source,
|
||||
aResult);
|
||||
}
|
||||
|
||||
// Checks if the given host is in the preload list.
|
||||
@ -837,17 +791,13 @@ bool nsSiteSecurityService::HostHasHSTSEntry(
|
||||
: mozilla::DataStorage_Persistent;
|
||||
nsAutoCString storageKey;
|
||||
SSSLOG(("Seeking HSTS entry for %s", aHost.get()));
|
||||
SetStorageKey(aHost, nsISiteSecurityService::HEADER_HSTS, aOriginAttributes,
|
||||
storageKey);
|
||||
nsAutoCString preloadKey;
|
||||
SetStorageKey(aHost, nsISiteSecurityService::HEADER_HSTS, OriginAttributes(),
|
||||
preloadKey);
|
||||
SetStorageKey(aHost, aOriginAttributes, storageKey);
|
||||
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(nsISiteSecurityService::HEADER_HSTS);
|
||||
bool expired = siteState->IsExpired();
|
||||
if (!expired) {
|
||||
SSSLOG(("Entry for %s is not expired", aHost.get()));
|
||||
if (siteState->mHSTSState == SecurityPropertySet) {
|
||||
@ -897,23 +847,11 @@ bool nsSiteSecurityService::HostHasHSTSEntry(
|
||||
}
|
||||
|
||||
nsresult nsSiteSecurityService::IsSecureHost(
|
||||
uint32_t aType, const nsACString& aHost, uint32_t aFlags,
|
||||
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;
|
||||
|
||||
@ -923,11 +861,6 @@ nsresult nsSiteSecurityService::IsSecureHost(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aType == nsISiteSecurityService::STATIC_PINNING) {
|
||||
return PublicKeyPinningService::HostHasPins(flatHost.get(),
|
||||
mozilla::pkix::Now(), *aResult);
|
||||
}
|
||||
|
||||
nsAutoCString host(
|
||||
PublicKeyPinningService::CanonicalizeHostname(flatHost.get()));
|
||||
|
||||
@ -979,46 +912,28 @@ nsSiteSecurityService::ClearAll() {
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::Enumerate(uint32_t aType,
|
||||
nsISimpleEnumerator** aEnumerator) {
|
||||
nsSiteSecurityService::Enumerate(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(), keySuffix)) {
|
||||
if (!StringEndsWith(item.key(), kHSTSKeySuffix)) {
|
||||
// The key does not end with correct suffix, so is not the type we want.
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCString origin(
|
||||
StringHead(item.key(), item.key().Length() - keySuffix.Length()));
|
||||
StringHead(item.key(), item.key().Length() - kHSTSKeySuffix.Length()));
|
||||
nsAutoCString hostname;
|
||||
OriginAttributes originAttributes;
|
||||
if (!originAttributes.PopulateFromOrigin(origin, hostname)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISiteSecurityState> state(
|
||||
new SiteHSTSState(hostname, originAttributes, item.value()));
|
||||
states.AppendObject(state);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ class SiteHSTSState : public nsISiteHSTSState {
|
||||
bool mHSTSIncludeSubdomains;
|
||||
SecurityPropertySource mHSTSSource;
|
||||
|
||||
bool IsExpired(uint32_t aType) {
|
||||
bool IsExpired() {
|
||||
// If mHSTSExpireTime is 0, this entry never expires (this is the case for
|
||||
// knockout entries).
|
||||
if (mHSTSExpireTime == 0) {
|
||||
@ -115,30 +115,34 @@ 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 GetHost(nsIURI* aURI, nsACString& aResult);
|
||||
nsresult SetHSTSState(uint32_t aType, const char* aHost, int64_t maxage,
|
||||
nsresult SetHSTSState(const char* aHost, int64_t maxage,
|
||||
bool includeSubdomains, uint32_t flags,
|
||||
SecurityPropertyState aHSTSState,
|
||||
SecurityPropertySource aSource,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
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 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 ProcessSTSHeader(nsIURI* aSourceURI, const nsCString& aHeader,
|
||||
uint32_t flags, SecurityPropertySource aSource,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
uint64_t* aMaxAge, bool* aIncludeSubdomains,
|
||||
uint32_t* aFailureResult);
|
||||
nsresult MarkHostAsNotHSTS(uint32_t aType, const nsAutoCString& aHost,
|
||||
uint32_t aFlags, bool aIsPreload,
|
||||
nsresult MarkHostAsNotHSTS(const nsAutoCString& aHost, uint32_t aFlags,
|
||||
bool aIsPreload,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
nsresult ResetStateInternal(uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
nsresult ResetStateInternal(nsIURI* aURI, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
bool HostHasHSTSEntry(const nsAutoCString& aHost,
|
||||
bool aRequireIncludeSubdomains, uint32_t aFlags,
|
||||
@ -148,8 +152,7 @@ class nsSiteSecurityService : public nsISiteSecurityService,
|
||||
bool GetPreloadStatus(
|
||||
const nsACString& aHost,
|
||||
/*optional out*/ bool* aIncludeSubdomains = nullptr) const;
|
||||
nsresult IsSecureHost(uint32_t aType, const nsACString& aHost,
|
||||
uint32_t aFlags,
|
||||
nsresult IsSecureHost(const nsACString& aHost, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
bool* aCached, SecurityPropertySource* aSource,
|
||||
bool* aResult);
|
||||
|
@ -38,7 +38,6 @@ 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,
|
||||
@ -46,11 +45,7 @@ function test() {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
privacyFlags(aIsPrivateMode)
|
||||
),
|
||||
gSSService.isSecureURI(uri, privacyFlags(aIsPrivateMode)),
|
||||
"checking sts host"
|
||||
);
|
||||
|
||||
@ -79,7 +74,7 @@ function test() {
|
||||
aWin.close();
|
||||
});
|
||||
uri = Services.io.newURI("http://localhost");
|
||||
gSSService.resetState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
gSSService.resetState(uri, 0);
|
||||
});
|
||||
|
||||
// test first when on private mode
|
||||
|
@ -7,57 +7,46 @@ function run_test() {
|
||||
);
|
||||
|
||||
ok(
|
||||
!SSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://expired.example.com"),
|
||||
0
|
||||
)
|
||||
!SSService.isSecureURI(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,7 +45,6 @@ function add_tests() {
|
||||
// longer.
|
||||
add_task(async function() {
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
GOOD_MAX_AGE,
|
||||
secInfo,
|
||||
@ -53,15 +52,12 @@ function add_tests() {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
"a.pinning.example.com should be HSTS"
|
||||
);
|
||||
Assert.ok(sss.isSecureURI(uri, 0), "a.pinning.example.com should be HSTS");
|
||||
|
||||
await ForgetAboutSite.removeDataFromDomain("a.pinning.example.com");
|
||||
|
||||
Assert.ok(
|
||||
!sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
!sss.isSecureURI(uri, 0),
|
||||
"a.pinning.example.com should not be HSTS now"
|
||||
);
|
||||
});
|
||||
@ -72,7 +68,6 @@ 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,
|
||||
@ -81,34 +76,30 @@ function add_tests() {
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
sss.isSecureURI(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(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI, 0),
|
||||
"example.org should be HSTS"
|
||||
);
|
||||
Assert.ok(sss.isSecureURI(unrelatedURI, 0), "example.org should be HSTS");
|
||||
|
||||
await ForgetAboutSite.removeDataFromDomain("example.com");
|
||||
|
||||
Assert.ok(
|
||||
!sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
!sss.isSecureURI(uri, 0),
|
||||
"a.pinning.example.com should not be HSTS now (subdomain case)"
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
sss.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, unrelatedURI, 0),
|
||||
sss.isSecureURI(unrelatedURI, 0),
|
||||
"example.org should still be HSTS"
|
||||
);
|
||||
});
|
||||
@ -130,7 +121,6 @@ function add_tests() {
|
||||
|
||||
for (let originAttributes of originAttributesList) {
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
GOOD_MAX_AGE,
|
||||
secInfo,
|
||||
@ -140,18 +130,12 @@ function add_tests() {
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
sss.isSecureURI(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,
|
||||
@ -160,12 +144,7 @@ function add_tests() {
|
||||
originAttributes
|
||||
);
|
||||
Assert.ok(
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
unrelatedURI,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
sss.isSecureURI(unrelatedURI, 0, originAttributes),
|
||||
"example.org should be HSTS (originAttributes case)"
|
||||
);
|
||||
}
|
||||
@ -174,23 +153,13 @@ function add_tests() {
|
||||
|
||||
for (let originAttributes of originAttributesList) {
|
||||
Assert.ok(
|
||||
!sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
!sss.isSecureURI(uri, 0, originAttributes),
|
||||
"a.pinning.example.com should not be HSTS now " +
|
||||
"(originAttributes case)"
|
||||
);
|
||||
|
||||
Assert.ok(
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
unrelatedURI,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
sss.isSecureURI(unrelatedURI, 0, originAttributes),
|
||||
"example.org should still be HSTS (originAttributes case)"
|
||||
);
|
||||
}
|
||||
|
@ -51,7 +51,6 @@ function run_test() {
|
||||
"@mozilla.org/security/transportsecurityinfo;1"
|
||||
].createInstance(Ci.nsITransportSecurityInfo);
|
||||
SSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=10000",
|
||||
secInfo,
|
||||
@ -59,7 +58,7 @@ function run_test() {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(
|
||||
SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
SSService.isSecureURI(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(type) {
|
||||
return Array.from(sss.enumerate(type));
|
||||
function getEntries() {
|
||||
return Array.from(sss.enumerate());
|
||||
}
|
||||
|
||||
function checkSiteSecurityStateAttrs(entries) {
|
||||
@ -71,7 +71,6 @@ function add_tests() {
|
||||
header += "; includeSubdomains";
|
||||
}
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
header,
|
||||
secInfo,
|
||||
@ -83,12 +82,12 @@ function add_tests() {
|
||||
}
|
||||
|
||||
add_task(() => {
|
||||
let hstsEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HSTS);
|
||||
let hstsEntries = getEntries();
|
||||
|
||||
checkSiteSecurityStateAttrs(hstsEntries);
|
||||
|
||||
sss.clearAll();
|
||||
hstsEntries = getEntries(Ci.nsISiteSecurityService.HEADER_HSTS);
|
||||
hstsEntries = getEntries();
|
||||
|
||||
equal(hstsEntries.length, 0, "Should clear all HSTS entries");
|
||||
});
|
||||
|
@ -53,7 +53,6 @@ function do_state_read(aSubject, aTopic, aData) {
|
||||
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://frequentlyused.example.com"),
|
||||
0
|
||||
)
|
||||
@ -64,7 +63,6 @@ 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,7 +24,6 @@ function doTest(secInfo, originAttributes1, originAttributes2, shouldShare) {
|
||||
let header = GOOD_MAX_AGE;
|
||||
// Set HSTS for originAttributes1.
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
header,
|
||||
secInfo,
|
||||
@ -33,21 +32,11 @@ function doTest(secInfo, originAttributes1, originAttributes2, shouldShare) {
|
||||
originAttributes1
|
||||
);
|
||||
ok(
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes1
|
||||
),
|
||||
sss.isSecureURI(uri, 0, originAttributes1),
|
||||
"URI should be secure given original origin attributes"
|
||||
);
|
||||
equal(
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes2
|
||||
),
|
||||
sss.isSecureURI(uri, 0, originAttributes2),
|
||||
shouldShare,
|
||||
"URI should be secure given different origin attributes if and " +
|
||||
"only if shouldShare is true"
|
||||
@ -55,37 +44,17 @@ function doTest(secInfo, originAttributes1, originAttributes2, shouldShare) {
|
||||
|
||||
if (!shouldShare) {
|
||||
// Remove originAttributes2 from the storage.
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes2
|
||||
);
|
||||
sss.resetState(uri, 0, originAttributes2);
|
||||
ok(
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes1
|
||||
),
|
||||
sss.isSecureURI(uri, 0, originAttributes1),
|
||||
"URI should still be secure given original origin attributes"
|
||||
);
|
||||
}
|
||||
|
||||
// Remove originAttributes1 from the storage.
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes1
|
||||
);
|
||||
sss.resetState(uri, 0, originAttributes1);
|
||||
ok(
|
||||
!sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes1
|
||||
),
|
||||
!sss.isSecureURI(uri, 0, originAttributes1),
|
||||
"URI should not be secure after removeState"
|
||||
);
|
||||
|
||||
@ -98,7 +67,6 @@ function testInvalidOriginAttributes(secInfo, originAttributes) {
|
||||
let callbacks = [
|
||||
() =>
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
header,
|
||||
secInfo,
|
||||
@ -106,20 +74,8 @@ function testInvalidOriginAttributes(secInfo, originAttributes) {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST,
|
||||
originAttributes
|
||||
),
|
||||
() =>
|
||||
sss.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
() =>
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes
|
||||
),
|
||||
() => sss.isSecureURI(uri, 0, originAttributes),
|
||||
() => sss.resetState(uri, 0, originAttributes),
|
||||
];
|
||||
|
||||
for (let callback of callbacks) {
|
||||
|
@ -17,56 +17,48 @@ 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
|
||||
)
|
||||
@ -76,56 +68,48 @@ 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,14 +12,12 @@ 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
|
||||
)
|
||||
@ -28,7 +26,6 @@ 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,11 +21,7 @@ function checkStateRead(aSubject, aTopic, aData) {
|
||||
];
|
||||
for (let host of HSTS_HOSTS) {
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI(host),
|
||||
0
|
||||
),
|
||||
gSSService.isSecureURI(Services.io.newURI(host), 0),
|
||||
`${host} should be HSTS enabled`
|
||||
);
|
||||
}
|
||||
@ -45,11 +41,7 @@ function checkStateRead(aSubject, aTopic, aData) {
|
||||
];
|
||||
for (let host of NOT_HSTS_HOSTS) {
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI(host),
|
||||
0
|
||||
),
|
||||
!gSSService.isSecureURI(Services.io.newURI(host), 0),
|
||||
`${host} should not be HSTS enabled`
|
||||
);
|
||||
}
|
||||
|
@ -18,49 +18,42 @@ 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,74 +14,70 @@ var gSSService = Cc["@mozilla.org/ssservice;1"].getService(
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
|
||||
function test_removeState(secInfo, type, flags) {
|
||||
info(`running test_removeState(type=${type}, flags=${flags})`);
|
||||
function test_removeState(secInfo, flags) {
|
||||
info(`running test_removeState(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(type, notPreloadedURI, flags));
|
||||
ok(!gSSService.isSecureURI(notPreloadedURI, flags));
|
||||
gSSService.processHeader(
|
||||
type,
|
||||
notPreloadedURI,
|
||||
"max-age=1000;",
|
||||
secInfo,
|
||||
flags,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
gSSService.resetState(type, notPreloadedURI, flags);
|
||||
ok(!gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
ok(gSSService.isSecureURI(notPreloadedURI, flags));
|
||||
gSSService.resetState(notPreloadedURI, flags);
|
||||
ok(!gSSService.isSecureURI(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(type, notPreloadedURI, flags));
|
||||
gSSService.resetState(type, notPreloadedURI, flags);
|
||||
ok(!gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
ok(!gSSService.isSecureURI(notPreloadedURI, flags));
|
||||
gSSService.resetState(notPreloadedURI, flags);
|
||||
ok(!gSSService.isSecureURI(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(type, preloadedURI, flags));
|
||||
ok(gSSService.isSecureURI(preloadedURI, flags));
|
||||
gSSService.processHeader(
|
||||
type,
|
||||
preloadedURI,
|
||||
"max-age=1000;",
|
||||
secInfo,
|
||||
flags,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
gSSService.resetState(type, preloadedURI, flags);
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
ok(gSSService.isSecureURI(preloadedURI, flags));
|
||||
gSSService.resetState(preloadedURI, flags);
|
||||
ok(gSSService.isSecureURI(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(type, preloadedURI, flags));
|
||||
gSSService.resetState(type, preloadedURI, flags);
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
ok(!gSSService.isSecureURI(preloadedURI, flags));
|
||||
gSSService.resetState(preloadedURI, flags);
|
||||
ok(gSSService.isSecureURI(preloadedURI, flags));
|
||||
}
|
||||
|
||||
function add_tests() {
|
||||
@ -96,12 +92,8 @@ function add_tests() {
|
||||
);
|
||||
|
||||
add_task(() => {
|
||||
test_removeState(secInfo, Ci.nsISiteSecurityService.HEADER_HSTS, 0);
|
||||
test_removeState(
|
||||
secInfo,
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Ci.nsISocketProvider.NO_PERMANENT_STORAGE
|
||||
);
|
||||
test_removeState(secInfo, 0);
|
||||
test_removeState(secInfo, Ci.nsISocketProvider.NO_PERMANENT_STORAGE);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,6 @@ 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,7 +108,6 @@ function run_test() {
|
||||
"@mozilla.org/security/transportsecurityinfo;1"
|
||||
].createInstance(Ci.nsITransportSecurityInfo);
|
||||
SSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uris[uriIndex],
|
||||
maxAge + includeSubdomains,
|
||||
secInfo,
|
||||
|
@ -11,30 +11,29 @@ 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(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri1, 0));
|
||||
ok(!SSService.isSecureURI(uri, 0));
|
||||
ok(!SSService.isSecureURI(uri1, 0));
|
||||
// These cases are only relevant as long as bug 1118522 hasn't been fixed.
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri2, 0));
|
||||
ok(!SSService.isSecureURI(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(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri1, 0));
|
||||
ok(SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri2, 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));
|
||||
SSService.resetState(uri, 0);
|
||||
ok(!SSService.isSecureURI(uri, 0));
|
||||
ok(!SSService.isSecureURI(uri1, 0));
|
||||
ok(!SSService.isSecureURI(uri2, 0));
|
||||
|
||||
// Somehow creating this malformed URI succeeds - we need to handle it
|
||||
// gracefully.
|
||||
@ -42,7 +41,7 @@ function run_test() {
|
||||
equal(uri.host, "..");
|
||||
throws(
|
||||
() => {
|
||||
SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
SSService.isSecureURI(uri, 0);
|
||||
},
|
||||
/NS_ERROR_UNEXPECTED/,
|
||||
"Malformed URI should be rejected"
|
||||
|
@ -16,12 +16,11 @@ function check_ip(s, v, ip) {
|
||||
str += "/";
|
||||
|
||||
let uri = Services.io.newURI(str);
|
||||
ok(!s.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(!s.isSecureURI(uri, 0));
|
||||
|
||||
let parsedMaxAge = {};
|
||||
let parsedIncludeSubdomains = {};
|
||||
s.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000;includeSubdomains",
|
||||
secInfo,
|
||||
@ -32,7 +31,7 @@ function check_ip(s, v, ip) {
|
||||
parsedIncludeSubdomains
|
||||
);
|
||||
ok(
|
||||
!s.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0),
|
||||
!s.isSecureURI(uri, 0),
|
||||
"URI should not be secure if it contains an IP address"
|
||||
);
|
||||
|
||||
|
@ -19,7 +19,6 @@ function testSuccess(header, expectedMaxAge, expectedIncludeSubdomains) {
|
||||
let includeSubdomains = {};
|
||||
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
dummyUri,
|
||||
header,
|
||||
secInfo,
|
||||
@ -46,7 +45,6 @@ function testFailure(header) {
|
||||
throws(
|
||||
() => {
|
||||
sss.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
dummyUri,
|
||||
header,
|
||||
secInfo,
|
||||
|
@ -40,20 +40,13 @@ 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(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://com"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(!gSSService.isSecureURI(Services.io.newURI("https://com"), 0));
|
||||
|
||||
// check that the pref to toggle using the preload list works
|
||||
Services.prefs.setBoolPref(
|
||||
@ -62,7 +55,6 @@ function test_part1() {
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
@ -73,7 +65,6 @@ function test_part1() {
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://includesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
@ -82,7 +73,6 @@ 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
|
||||
)
|
||||
@ -91,7 +81,6 @@ 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
|
||||
)
|
||||
@ -100,7 +89,6 @@ 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"
|
||||
),
|
||||
@ -111,7 +99,6 @@ 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
|
||||
)
|
||||
@ -124,40 +111,26 @@ 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(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(!gSSService.isSecureURI(uri, 0));
|
||||
ok(!gSSService.isSecureURI(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(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(gSSService.isSecureURI(uri, 0));
|
||||
// but this time include subdomains was not set, so test for that
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(!gSSService.isSecureURI(subDomainUri, 0));
|
||||
gSSService.clearAll();
|
||||
|
||||
// check that processing a header with max-age: 0 from a subdomain of a site
|
||||
@ -166,7 +139,6 @@ function test_part1() {
|
||||
"https://subdomain.noincludesubdomains.preloaded.test"
|
||||
);
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=0",
|
||||
secInfo,
|
||||
@ -175,18 +147,16 @@ function test_part1() {
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Services.io.newURI("https://noincludesubdomains.preloaded.test"),
|
||||
0
|
||||
)
|
||||
);
|
||||
ok(!gSSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(!gSSService.isSecureURI(uri, 0));
|
||||
|
||||
uri = Services.io.newURI(
|
||||
"https://subdomain.includesubdomains.preloaded.test"
|
||||
);
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=0",
|
||||
secInfo,
|
||||
@ -204,28 +174,24 @@ 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"
|
||||
),
|
||||
@ -234,7 +200,6 @@ function test_part1() {
|
||||
);
|
||||
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000",
|
||||
secInfo,
|
||||
@ -248,21 +213,18 @@ 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"
|
||||
),
|
||||
@ -277,9 +239,8 @@ 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(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(gSSService.isSecureURI(uri, 0));
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1",
|
||||
secInfo,
|
||||
@ -287,7 +248,7 @@ function test_part1() {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
do_timeout(1250, function() {
|
||||
ok(!gSSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(!gSSService.isSecureURI(uri, 0));
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
@ -301,92 +262,41 @@ function test_private_browsing1() {
|
||||
"https://a.b.c.subdomain.includesubdomains.preloaded.test"
|
||||
);
|
||||
// sanity - includesubdomains.preloaded.test is preloaded, includeSubdomains set
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(
|
||||
gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
ok(gSSService.isSecureURI(subDomainUri, IS_PRIVATE));
|
||||
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=0",
|
||||
secInfo,
|
||||
IS_PRIVATE,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(!gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
ok(!gSSService.isSecureURI(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(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
// but no includeSubdomains this time
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(!gSSService.isSecureURI(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(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
subDomainUri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(!gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
ok(!gSSService.isSecureURI(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.
|
||||
@ -395,15 +305,8 @@ 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(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1",
|
||||
secInfo,
|
||||
@ -411,13 +314,7 @@ function test_private_browsing1() {
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
do_timeout(1250, function() {
|
||||
ok(
|
||||
!gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
IS_PRIVATE
|
||||
)
|
||||
);
|
||||
ok(!gSSService.isSecureURI(uri, IS_PRIVATE));
|
||||
// Simulate leaving private browsing mode
|
||||
Services.obs.notifyObservers(null, "last-pb-context-exited");
|
||||
});
|
||||
@ -427,7 +324,6 @@ 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
|
||||
)
|
||||
@ -435,7 +331,6 @@ 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
|
||||
)
|
||||
@ -445,7 +340,6 @@ 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(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(SSService.isSecureURI(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(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(!SSService.isSecureURI(uri, 0));
|
||||
|
||||
// just make sure we can get everything back to normal
|
||||
Services.prefs.clearUserPref("test.currentTimeOffsetSeconds");
|
||||
ok(SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(SSService.isSecureURI(uri, 0));
|
||||
}
|
||||
|
@ -120,7 +120,6 @@ 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(Ci.nsISiteSecurityService.HEADER_HSTS, uri, flags);
|
||||
sss.resetState(uri, flags);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -42,12 +42,7 @@ function cleanupHSTS(aPartitionEnabled, aUseSite) {
|
||||
}
|
||||
}
|
||||
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
NetUtil.newURI("http://example.com/"),
|
||||
0,
|
||||
originAttributes
|
||||
);
|
||||
sss.resetState(NetUtil.newURI("http://example.com/"), 0, originAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1055,17 +1055,12 @@ const SecuritySettingsCleaner = {
|
||||
);
|
||||
// Also remove HSTS information for subdomains by enumerating
|
||||
// the information in the site security service.
|
||||
for (let entry of sss.enumerate(Ci.nsISiteSecurityService.HEADER_HSTS)) {
|
||||
for (let entry of sss.enumerate()) {
|
||||
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(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
entry.originAttributes
|
||||
);
|
||||
sss.resetState(uri, 0, entry.originAttributes);
|
||||
}
|
||||
}
|
||||
let cars = Cc[
|
||||
@ -1086,19 +1081,14 @@ const SecuritySettingsCleaner = {
|
||||
|
||||
// Remove HSTS information by enumerating entries of the site security
|
||||
// service.
|
||||
Array.from(sss.enumerate(Ci.nsISiteSecurityService.HEADER_HSTS))
|
||||
Array.from(sss.enumerate())
|
||||
.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(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
originAttributes
|
||||
);
|
||||
sss.resetState(uri, 0, originAttributes);
|
||||
});
|
||||
|
||||
let cars = Cc[
|
||||
|
@ -19,7 +19,6 @@ function addSecurityInfo({ host, topLevelBaseDomain, originAttributes = {} }) {
|
||||
].createInstance(Ci.nsITransportSecurityInfo);
|
||||
|
||||
gSSService.processHeader(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
"max-age=1000;",
|
||||
secInfo,
|
||||
@ -63,7 +62,6 @@ function testSecurityInfo({
|
||||
}) {
|
||||
let uri = Services.io.newURI(`https://${host}`);
|
||||
let isSecure = gSSService.isSecureURI(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
uri,
|
||||
0,
|
||||
getOAWithPartitionKey(topLevelBaseDomain, originAttributes)
|
||||
|
@ -23,6 +23,12 @@ 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
|
||||
@ -193,8 +199,8 @@ const SecurityInfo = {
|
||||
flags = Ci.nsISocketProvider.NO_PERMANENT_STORAGE;
|
||||
}
|
||||
|
||||
info.hsts = sss.isSecureURI(sss.HEADER_HSTS, uri, flags);
|
||||
info.hpkp = sss.isSecureURI(sss.STATIC_PINNING, uri, flags);
|
||||
info.hsts = sss.isSecureURI(uri, flags);
|
||||
info.hpkp = pkps.hostHasPins(uri);
|
||||
} else {
|
||||
info.hsts = false;
|
||||
info.hpkp = false;
|
||||
|
Loading…
Reference in New Issue
Block a user