mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 722979 - Add privacy status argument to relevant nsIStrictTransportSecurityService methods. r=bsmith sr=biesi
This commit is contained in:
parent
ee01241abe
commit
e0bfa38e3b
@ -498,12 +498,15 @@
|
||||
var connector =
|
||||
Services.io.QueryInterface(Components.interfaces.nsISpeculativeConnect);
|
||||
var searchURI = engine.getSubmission("dummy").uri;
|
||||
connector.speculativeConnect(searchURI, null);
|
||||
let callbacks = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsILoadContext);
|
||||
connector.speculativeConnect(searchURI, callbacks);
|
||||
|
||||
if (engine.supportsResponseType(SUGGEST_TYPE)) {
|
||||
var suggestURI = engine.getSubmission("dummy", SUGGEST_TYPE).uri;
|
||||
if (suggestURI.prePath != searchURI.prePath)
|
||||
connector.speculativeConnect(suggestURI, null);
|
||||
connector.speculativeConnect(suggestURI, callbacks);
|
||||
}
|
||||
]]></handler>
|
||||
</handlers>
|
||||
|
@ -1233,7 +1233,13 @@ function test41()
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||
var thehost = ios.newURI("http://example.com", null, null);
|
||||
var stss = Cc["@mozilla.org/stsservice;1"].getService(Ci.nsIStrictTransportSecurityService);
|
||||
stss.removeStsState(thehost);
|
||||
var loadContext = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsILoadContext);
|
||||
var flags = 0;
|
||||
if (loadContext.usePrivateBrowsing)
|
||||
flags |= Ci.nsISocketProvider.NO_PERMANENT_STORAGE;
|
||||
stss.removeStsState(thehost, flags);
|
||||
doTest(42);
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +114,7 @@
|
||||
#include "nsIObserver.h"
|
||||
#include "nsINestedURI.h"
|
||||
#include "nsITransportSecurityInfo.h"
|
||||
#include "nsISSLSocketControl.h"
|
||||
#include "nsINSSErrorsService.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheChannel.h"
|
||||
@ -4174,9 +4175,14 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI,
|
||||
nsCOMPtr<nsIStrictTransportSecurityService> stss =
|
||||
do_GetService(NS_STSSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t flags = 0;
|
||||
nsCOMPtr<nsISSLSocketControl> socketControl = do_QueryInterface(tsi);
|
||||
if (socketControl) {
|
||||
socketControl->GetProviderFlags(&flags);
|
||||
}
|
||||
|
||||
bool isStsHost = false;
|
||||
rv = stss->IsStsURI(aURI, &isStsHost);
|
||||
rv = stss->IsStsURI(aURI, flags, &isStsHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t bucketId;
|
||||
|
@ -150,6 +150,16 @@ interface nsISocketTransport : nsITransport
|
||||
*/
|
||||
const unsigned long DISABLE_IPV6 = (1 << 2);
|
||||
|
||||
/**
|
||||
* If set, indicates that the connection was initiated from a source
|
||||
* defined as being private in the sense of Private Browsing. Generally,
|
||||
* there should be no state shared between connections that are private
|
||||
* and those that are not; it is OK for multiple private connections
|
||||
* to share state with each other, and it is OK for multiple non-private
|
||||
* connections to share state with each other.
|
||||
*/
|
||||
const unsigned long NO_PERMANENT_STORAGE = (1 << 3);
|
||||
|
||||
/**
|
||||
* Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or
|
||||
* IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported
|
||||
|
@ -8,7 +8,7 @@ interface nsIURI;
|
||||
interface nsIObserver;
|
||||
interface nsIHttpChannel;
|
||||
|
||||
[scriptable, uuid(aee925d1-2bc9-469e-9582-b27b1d6b5192)]
|
||||
[scriptable, uuid(c6138514-f212-4747-98c2-7abfce3be293)]
|
||||
interface nsIStrictTransportSecurityService : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -20,6 +20,8 @@ interface nsIStrictTransportSecurityService : nsISupports
|
||||
*
|
||||
* @param aSourceURI the URI of the resource with the HTTP header.
|
||||
* @param aHeader the HTTP response header specifying STS data.
|
||||
* @param aFlags options for this request as defined in nsISocketProvider:
|
||||
* NO_PERMANENT_STORAGE
|
||||
* @param aMaxAge the parsed max-age directive of the header.
|
||||
* @param aIncludeSubdomains the parsed includeSubdomains directive.
|
||||
* @return NS_OK if it succeeds
|
||||
@ -29,6 +31,7 @@ interface nsIStrictTransportSecurityService : nsISupports
|
||||
*/
|
||||
void processStsHeader(in nsIURI aSourceURI,
|
||||
in string aHeader,
|
||||
in uint32_t aFlags,
|
||||
[optional] out unsigned long long aMaxAge,
|
||||
[optional] out boolean aIncludeSubdomains);
|
||||
|
||||
@ -36,8 +39,12 @@ interface nsIStrictTransportSecurityService : nsISupports
|
||||
* Removes the STS state of a host, including the includeSubdomains state
|
||||
* that would affect subdomains. This essentially removes STS state for
|
||||
* the domain tree rooted at this host.
|
||||
* @param aURI the URI of the target host
|
||||
* @param aFlags options for this request as defined in nsISocketProvider:
|
||||
* NO_PERMANENT_STORAGE
|
||||
*/
|
||||
void removeStsState(in nsIURI aURI);
|
||||
void removeStsState(in nsIURI aURI,
|
||||
in uint32_t aFlags);
|
||||
|
||||
/**
|
||||
* Checks if the given security info is for an STS host with a broken
|
||||
@ -51,8 +58,10 @@ interface nsIStrictTransportSecurityService : nsISupports
|
||||
* its super-domains has an STS "includeSubdomains" permission set.
|
||||
*
|
||||
* @param aHost the hostname (punycode) to query for STS state.
|
||||
* @param aFlags options for this request as defined in nsISocketProvider:
|
||||
* NO_PERMANENT_STORAGE
|
||||
*/
|
||||
boolean isStsHost(in string aHost);
|
||||
boolean isStsHost(in string aHost, in uint32_t aFlags);
|
||||
|
||||
/**
|
||||
* Checks whether or not the URI's hostname has STS state set.
|
||||
@ -63,8 +72,10 @@ interface nsIStrictTransportSecurityService : nsISupports
|
||||
* such as path and port.
|
||||
*
|
||||
* @param aURI the URI to query for STS state.
|
||||
* @param aFlags options for this request as defined in nsISocketProvider:
|
||||
* NO_PERMANENT_STORAGE
|
||||
*/
|
||||
boolean isStsURI(in nsIURI aURI);
|
||||
boolean isStsURI(in nsIURI aURI, in uint32_t aFlags);
|
||||
|
||||
};
|
||||
|
||||
|
@ -977,6 +977,9 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
|
||||
if (mConnectionFlags & nsISocketTransport::ANONYMOUS_CONNECT)
|
||||
proxyFlags |= nsISocketProvider::ANONYMOUS_CONNECT;
|
||||
|
||||
if (mConnectionFlags & nsISocketTransport::NO_PERMANENT_STORAGE)
|
||||
proxyFlags |= nsISocketProvider::NO_PERMANENT_STORAGE;
|
||||
|
||||
nsCOMPtr<nsISupports> secinfo;
|
||||
if (i == 0) {
|
||||
// if this is the first type, we'll want the
|
||||
|
@ -370,7 +370,8 @@ nsHttpChannel::Connect()
|
||||
NS_ENSURE_TRUE(stss, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
bool isStsHost = false;
|
||||
rv = stss->IsStsURI(mURI, &isStsHost);
|
||||
uint32_t flags = mPrivateBrowsing ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
|
||||
rv = stss->IsStsURI(mURI, flags, &isStsHost);
|
||||
|
||||
// if STS fails, there's no reason to cancel the load, but it's
|
||||
// worrisome.
|
||||
@ -1112,7 +1113,9 @@ nsHttpChannel::ProcessSTSHeader()
|
||||
// If this wasn't an STS host, errors are allowed, but no more STS processing
|
||||
// will happen during the session.
|
||||
bool wasAlreadySTSHost;
|
||||
rv = stss->IsStsURI(mURI, &wasAlreadySTSHost);
|
||||
uint32_t flags =
|
||||
NS_UsePrivateBrowsing(this) ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
|
||||
rv = stss->IsStsURI(mURI, flags, &wasAlreadySTSHost);
|
||||
// Failure here means STS is broken. Don't prevent the load, but this
|
||||
// shouldn't fail.
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
@ -1140,7 +1143,7 @@ nsHttpChannel::ProcessSTSHeader()
|
||||
// All other failures are fatal.
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = stss->ProcessStsHeader(mURI, stsHeader.get(), NULL, NULL);
|
||||
rv = stss->ProcessStsHeader(mURI, stsHeader.get(), flags, NULL, NULL);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("STS: Failed to parse STS header, continuing load.\n"));
|
||||
return NS_OK;
|
||||
|
@ -2457,6 +2457,9 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport,
|
||||
if (mCaps & NS_HTTP_LOAD_ANONYMOUS)
|
||||
tmpFlags |= nsISocketTransport::ANONYMOUS_CONNECT;
|
||||
|
||||
if (mEnt->mConnInfo->GetPrivate())
|
||||
tmpFlags |= nsISocketTransport::NO_PERMANENT_STORAGE;
|
||||
|
||||
// For backup connections, we disable IPv6. That's because some users have
|
||||
// broken IPv6 connectivity (leading to very long timeouts), and disabling
|
||||
// IPv6 on the backup connection gives them a much better user experience
|
||||
|
@ -1620,8 +1620,12 @@ nsHttpHandler::SpeculativeConnect(nsIURI *aURI,
|
||||
if (!stss)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(aCallbacks);
|
||||
uint32_t flags = 0;
|
||||
if (loadContext && loadContext->UsePrivateBrowsing())
|
||||
flags |= nsISocketProvider::NO_PERMANENT_STORAGE;
|
||||
nsCOMPtr<nsIURI> clone;
|
||||
if (NS_SUCCEEDED(stss->IsStsURI(aURI, &isStsHost)) && isStsHost) {
|
||||
if (NS_SUCCEEDED(stss->IsStsURI(aURI, flags, &isStsHost)) && isStsHost) {
|
||||
if (NS_SUCCEEDED(aURI->Clone(getter_AddRefs(clone)))) {
|
||||
clone->SetScheme(NS_LITERAL_CSTRING("https"));
|
||||
aURI = clone.get();
|
||||
|
@ -14,7 +14,7 @@ class nsCString;
|
||||
%}
|
||||
[ref] native nsCStringTArrayRef(nsTArray<nsCString>);
|
||||
|
||||
[scriptable, uuid(753f0f13-681d-4de3-a6c6-11aa7e0b3afd)]
|
||||
[scriptable, uuid(bb2bb490-3ba4-4254-b8f5-8b43c7b714ea)]
|
||||
interface nsISSLSocketControl : nsISupports {
|
||||
attribute nsIInterfaceRequestor notificationCallbacks;
|
||||
|
||||
@ -49,6 +49,10 @@ interface nsISSLSocketControl : nsISupports {
|
||||
in ACString npnProtocol, /* e.g. "spdy/2" */
|
||||
in ACString hostname,
|
||||
in long port);
|
||||
|
||||
|
||||
/*
|
||||
* The original flags from the socket provider.
|
||||
*/
|
||||
readonly attribute uint32_t providerFlags;
|
||||
};
|
||||
|
||||
|
@ -81,7 +81,16 @@ interface nsISocketProvider : nsISupports
|
||||
* if this flag is set.
|
||||
*/
|
||||
const long ANONYMOUS_CONNECT = 1 << 1;
|
||||
|
||||
|
||||
/**
|
||||
* If set, indicates that the connection was initiated from a source
|
||||
* defined as being private in the sense of Private Browsing. Generally,
|
||||
* there should be no state shared between connections that are private
|
||||
* and those that are not; it is OK for multiple private connections
|
||||
* to share state with each other, and it is OK for multiple non-private
|
||||
* connections to share state with each other.
|
||||
*/
|
||||
const unsigned long NO_PERMANENT_STORAGE = 1 << 2;
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -47,7 +47,7 @@ nsSOCKSSocketProvider::NewSocket(int32_t family,
|
||||
const char *proxyHost,
|
||||
int32_t proxyPort,
|
||||
uint32_t flags,
|
||||
PRFileDesc **result,
|
||||
PRFileDesc **result,
|
||||
nsISupports **socksInfo)
|
||||
{
|
||||
PRFileDesc *sock;
|
||||
@ -80,7 +80,7 @@ nsSOCKSSocketProvider::AddToSocket(int32_t family,
|
||||
const char *proxyHost,
|
||||
int32_t proxyPort,
|
||||
uint32_t flags,
|
||||
PRFileDesc *sock,
|
||||
PRFileDesc *sock,
|
||||
nsISupports **socksInfo)
|
||||
{
|
||||
nsresult rv = nsSOCKSIOLayerAddToSocket(family,
|
||||
|
@ -49,7 +49,7 @@ TestSuccess(const char* hdr, bool extraTokens,
|
||||
|
||||
uint64_t maxAge = 0;
|
||||
bool includeSubdomains = false;
|
||||
rv = stss->ProcessStsHeader(dummyUri, hdr, &maxAge, &includeSubdomains);
|
||||
rv = stss->ProcessStsHeader(dummyUri, hdr, 0, &maxAge, &includeSubdomains);
|
||||
EXPECT_SUCCESS(rv, "Failed to process valid header: %s", hdr);
|
||||
|
||||
REQUIRE_EQUAL(maxAge, expectedMaxAge, "Did not correctly parse maxAge");
|
||||
@ -74,7 +74,7 @@ bool TestFailure(const char* hdr,
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(dummyUri), "https://foo.com/bar.html");
|
||||
EXPECT_SUCCESS(rv, "Failed to create URI");
|
||||
|
||||
rv = stss->ProcessStsHeader(dummyUri, hdr, NULL, NULL);
|
||||
rv = stss->ProcessStsHeader(dummyUri, hdr, 0, NULL, NULL);
|
||||
EXPECT_FAILURE(rv, "Parsed invalid header: %s", hdr);
|
||||
passed(hdr);
|
||||
return true;
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "prprf.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIPrivateBrowsingService.h"
|
||||
#include "nsISSLStatus.h"
|
||||
#include "nsISSLStatusProvider.h"
|
||||
#include "nsStrictTransportSecurityService.h"
|
||||
@ -16,6 +15,7 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISocketProvider.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
// A note about the preload list:
|
||||
@ -75,7 +75,7 @@ nsSTSHostEntry::nsSTSHostEntry(const nsSTSHostEntry& toCopy)
|
||||
|
||||
|
||||
nsStrictTransportSecurityService::nsStrictTransportSecurityService()
|
||||
: mInPrivateMode(false), mUsePreloadList(true)
|
||||
: mUsePreloadList(true)
|
||||
{
|
||||
}
|
||||
|
||||
@ -95,20 +95,13 @@ nsStrictTransportSecurityService::Init()
|
||||
mPermMgr = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// figure out if we're starting in private browsing mode
|
||||
nsCOMPtr<nsIPrivateBrowsingService> pbs =
|
||||
do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
|
||||
if (pbs)
|
||||
pbs->GetPrivateBrowsingEnabled(&mInPrivateMode);
|
||||
|
||||
mUsePreloadList = mozilla::Preferences::GetBool("network.stricttransportsecurity.preloadlist", true);
|
||||
mozilla::Preferences::AddStrongObserver(this, "network.stricttransportsecurity.preloadlist");
|
||||
mObserverService = mozilla::services::GetObserverService();
|
||||
if (mObserverService)
|
||||
mObserverService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, false);
|
||||
mObserverService->AddObserver(this, "last-pb-context-exited", false);
|
||||
|
||||
if (mInPrivateMode)
|
||||
mPrivateModeHostTable.Init();
|
||||
mPrivateModeHostTable.Init();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -153,25 +146,30 @@ nsStrictTransportSecurityService::GetPrincipalForURI(nsIURI* aURI,
|
||||
nsresult
|
||||
nsStrictTransportSecurityService::SetStsState(nsIURI* aSourceURI,
|
||||
int64_t maxage,
|
||||
bool includeSubdomains)
|
||||
bool includeSubdomains,
|
||||
uint32_t flags)
|
||||
{
|
||||
// If max-age is zero, that's an indication to immediately remove the
|
||||
// permissions, so here's a shortcut.
|
||||
if (!maxage)
|
||||
return RemoveStsState(aSourceURI);
|
||||
if (!maxage) {
|
||||
return RemoveStsState(aSourceURI, flags);
|
||||
}
|
||||
|
||||
// Expire time is millis from now. Since STS max-age is in seconds, and
|
||||
// PR_Now() is in micros, must equalize the units at milliseconds.
|
||||
int64_t expiretime = (PR_Now() / PR_USEC_PER_MSEC) +
|
||||
(maxage * PR_MSEC_PER_SEC);
|
||||
|
||||
bool isPrivate = flags & nsISocketProvider::NO_PERMANENT_STORAGE;
|
||||
|
||||
// record entry for this host with max-age in the permissions manager
|
||||
STSLOG(("STS: maxage permission SET, adding permission\n"));
|
||||
nsresult rv = AddPermission(aSourceURI,
|
||||
STS_PERMISSION,
|
||||
(uint32_t) STS_SET,
|
||||
(uint32_t) nsIPermissionManager::EXPIRE_TIME,
|
||||
expiretime);
|
||||
expiretime,
|
||||
isPrivate);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (includeSubdomains) {
|
||||
@ -181,7 +179,8 @@ nsStrictTransportSecurityService::SetStsState(nsIURI* aSourceURI,
|
||||
STS_SUBDOMAIN_PERMISSION,
|
||||
(uint32_t) STS_SET,
|
||||
(uint32_t) nsIPermissionManager::EXPIRE_TIME,
|
||||
expiretime);
|
||||
expiretime,
|
||||
isPrivate);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else { // !includeSubdomains
|
||||
nsAutoCString hostname;
|
||||
@ -189,14 +188,14 @@ nsStrictTransportSecurityService::SetStsState(nsIURI* aSourceURI,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
STSLOG(("STS: subdomains permission UNSET, removing any existing ones\n"));
|
||||
rv = RemovePermission(hostname, STS_SUBDOMAIN_PERMISSION);
|
||||
rv = RemovePermission(hostname, STS_SUBDOMAIN_PERMISSION, isPrivate);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStrictTransportSecurityService::RemoveStsState(nsIURI* aURI)
|
||||
nsStrictTransportSecurityService::RemoveStsState(nsIURI* aURI, uint32_t aFlags)
|
||||
{
|
||||
// Should be called on the main thread (or via proxy) since the permission
|
||||
// manager is used and it's not threadsafe.
|
||||
@ -206,11 +205,13 @@ nsStrictTransportSecurityService::RemoveStsState(nsIURI* aURI)
|
||||
nsresult rv = GetHost(aURI, hostname);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = RemovePermission(hostname, STS_PERMISSION);
|
||||
bool isPrivate = aFlags & nsISocketProvider::NO_PERMANENT_STORAGE;
|
||||
|
||||
rv = RemovePermission(hostname, STS_PERMISSION, isPrivate);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
STSLOG(("STS: deleted maxage permission\n"));
|
||||
|
||||
rv = RemovePermission(hostname, STS_SUBDOMAIN_PERMISSION);
|
||||
rv = RemovePermission(hostname, STS_SUBDOMAIN_PERMISSION, isPrivate);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
STSLOG(("STS: deleted subdomains permission\n"));
|
||||
|
||||
@ -220,6 +221,7 @@ nsStrictTransportSecurityService::RemoveStsState(nsIURI* aURI)
|
||||
NS_IMETHODIMP
|
||||
nsStrictTransportSecurityService::ProcessStsHeader(nsIURI* aSourceURI,
|
||||
const char* aHeader,
|
||||
uint32_t aFlags,
|
||||
uint64_t *aMaxAge,
|
||||
bool *aIncludeSubdomains)
|
||||
{
|
||||
@ -237,8 +239,8 @@ nsStrictTransportSecurityService::ProcessStsHeader(nsIURI* aSourceURI,
|
||||
|
||||
char * header = NS_strdup(aHeader);
|
||||
if (!header) return NS_ERROR_OUT_OF_MEMORY;
|
||||
nsresult rv = ProcessStsHeaderMutating(aSourceURI, header, aMaxAge,
|
||||
aIncludeSubdomains);
|
||||
nsresult rv = ProcessStsHeaderMutating(aSourceURI, header, aFlags,
|
||||
aMaxAge, aIncludeSubdomains);
|
||||
NS_Free(header);
|
||||
return rv;
|
||||
}
|
||||
@ -246,6 +248,7 @@ nsStrictTransportSecurityService::ProcessStsHeader(nsIURI* aSourceURI,
|
||||
nsresult
|
||||
nsStrictTransportSecurityService::ProcessStsHeaderMutating(nsIURI* aSourceURI,
|
||||
char* aHeader,
|
||||
uint32_t aFlags,
|
||||
uint64_t *aMaxAge,
|
||||
bool *aIncludeSubdomains)
|
||||
{
|
||||
@ -338,7 +341,7 @@ nsStrictTransportSecurityService::ProcessStsHeaderMutating(nsIURI* aSourceURI,
|
||||
("Parse ERROR: couldn't locate max-age token\n"));
|
||||
|
||||
// record the successfully parsed header data.
|
||||
SetStsState(aSourceURI, maxAge, includeSubdomains);
|
||||
SetStsState(aSourceURI, maxAge, includeSubdomains, aFlags);
|
||||
|
||||
if (aMaxAge != nullptr) {
|
||||
*aMaxAge = (uint64_t)maxAge;
|
||||
@ -354,7 +357,7 @@ nsStrictTransportSecurityService::ProcessStsHeaderMutating(nsIURI* aSourceURI,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStrictTransportSecurityService::IsStsHost(const char* aHost, bool* aResult)
|
||||
nsStrictTransportSecurityService::IsStsHost(const char* aHost, uint32_t aFlags, bool* aResult)
|
||||
{
|
||||
// Should be called on the main thread (or via proxy) since the permission
|
||||
// manager is used and it's not threadsafe.
|
||||
@ -365,7 +368,7 @@ nsStrictTransportSecurityService::IsStsHost(const char* aHost, bool* aResult)
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri),
|
||||
NS_LITERAL_CSTRING("https://") + hostString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return IsStsURI(uri, aResult);
|
||||
return IsStsURI(uri, aFlags, aResult);
|
||||
}
|
||||
|
||||
int STSPreloadCompare(const void *key, const void *entry)
|
||||
@ -401,7 +404,7 @@ nsStrictTransportSecurityService::GetPreloadListEntry(const char *aHost)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStrictTransportSecurityService::IsStsURI(nsIURI* aURI, bool* aResult)
|
||||
nsStrictTransportSecurityService::IsStsURI(nsIURI* aURI, uint32_t aFlags, bool* aResult)
|
||||
{
|
||||
// Should be called on the main thread (or via proxy) since the permission
|
||||
// manager is used and it's not threadsafe.
|
||||
@ -417,7 +420,8 @@ nsStrictTransportSecurityService::IsStsURI(nsIURI* aURI, bool* aResult)
|
||||
const nsSTSPreload *preload = nullptr;
|
||||
nsSTSHostEntry *pbEntry = nullptr;
|
||||
|
||||
if (mInPrivateMode) {
|
||||
bool isPrivate = aFlags & nsISocketProvider::NO_PERMANENT_STORAGE;
|
||||
if (isPrivate) {
|
||||
pbEntry = mPrivateModeHostTable.GetEntry(host.get());
|
||||
}
|
||||
|
||||
@ -479,7 +483,7 @@ nsStrictTransportSecurityService::IsStsURI(nsIURI* aURI, bool* aResult)
|
||||
break;
|
||||
}
|
||||
|
||||
if (mInPrivateMode) {
|
||||
if (isPrivate) {
|
||||
pbEntry = mPrivateModeHostTable.GetEntry(subdomain);
|
||||
}
|
||||
|
||||
@ -580,20 +584,8 @@ nsStrictTransportSecurityService::Observe(nsISupports *subject,
|
||||
const char *topic,
|
||||
const PRUnichar *data)
|
||||
{
|
||||
if (strcmp(topic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
|
||||
if(NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(data)) {
|
||||
// Indication to start recording stuff locally and not writing changes
|
||||
// out to the permission manager.
|
||||
|
||||
if (!mPrivateModeHostTable.IsInitialized()) {
|
||||
mPrivateModeHostTable.Init();
|
||||
}
|
||||
mInPrivateMode = true;
|
||||
}
|
||||
else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(data)) {
|
||||
mPrivateModeHostTable.Clear();
|
||||
mInPrivateMode = false;
|
||||
}
|
||||
if (strcmp(topic, "last-pb-context-exited") == 0) {
|
||||
mPrivateModeHostTable.Clear();
|
||||
}
|
||||
else if (strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
|
||||
mUsePreloadList = mozilla::Preferences::GetBool("network.stricttransportsecurity.preloadlist", true);
|
||||
@ -611,11 +603,12 @@ nsStrictTransportSecurityService::AddPermission(nsIURI *aURI,
|
||||
const char *aType,
|
||||
uint32_t aPermission,
|
||||
uint32_t aExpireType,
|
||||
int64_t aExpireTime)
|
||||
int64_t aExpireTime,
|
||||
bool aIsPrivate)
|
||||
{
|
||||
// Private mode doesn't address user-set (EXPIRE_NEVER) permissions: let
|
||||
// those be stored persistently.
|
||||
if (!mInPrivateMode || aExpireType == nsIPermissionManager::EXPIRE_NEVER) {
|
||||
if (!aIsPrivate || aExpireType == nsIPermissionManager::EXPIRE_NEVER) {
|
||||
// Not in private mode, or manually-set permission
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsresult rv = GetPrincipalForURI(aURI, getter_AddRefs(principal));
|
||||
@ -667,7 +660,8 @@ nsStrictTransportSecurityService::AddPermission(nsIURI *aURI,
|
||||
|
||||
nsresult
|
||||
nsStrictTransportSecurityService::RemovePermission(const nsCString &aHost,
|
||||
const char *aType)
|
||||
const char *aType,
|
||||
bool aIsPrivate)
|
||||
{
|
||||
// Build up a principal for use with the permission manager.
|
||||
// normalize all URIs with https://
|
||||
@ -680,7 +674,7 @@ nsStrictTransportSecurityService::RemovePermission(const nsCString &aHost,
|
||||
rv = GetPrincipalForURI(uri, getter_AddRefs(principal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mInPrivateMode) {
|
||||
if (!aIsPrivate) {
|
||||
// Not in private mode: remove permissions persistently.
|
||||
// This means setting the permission to STS_KNOCKOUT in case
|
||||
// this host is on the preload list (so we can override it).
|
||||
|
@ -135,8 +135,8 @@ public:
|
||||
private:
|
||||
nsresult GetHost(nsIURI *aURI, nsACString &aResult);
|
||||
nsresult GetPrincipalForURI(nsIURI *aURI, nsIPrincipal **aPrincipal);
|
||||
nsresult SetStsState(nsIURI* aSourceURI, int64_t maxage, bool includeSubdomains);
|
||||
nsresult ProcessStsHeaderMutating(nsIURI* aSourceURI, char* aHeader,
|
||||
nsresult SetStsState(nsIURI* aSourceURI, int64_t maxage, bool includeSubdomains, uint32_t flags);
|
||||
nsresult ProcessStsHeaderMutating(nsIURI* aSourceURI, char* aHeader, uint32_t flags,
|
||||
uint64_t *aMaxAge, bool *aIncludeSubdomains);
|
||||
const nsSTSPreload *GetPreloadListEntry(const char *aHost);
|
||||
|
||||
@ -145,15 +145,16 @@ private:
|
||||
const char *aType,
|
||||
uint32_t aPermission,
|
||||
uint32_t aExpireType,
|
||||
int64_t aExpireTime);
|
||||
int64_t aExpireTime,
|
||||
bool aIsPrivate);
|
||||
nsresult RemovePermission(const nsCString &aHost,
|
||||
const char *aType);
|
||||
const char *aType,
|
||||
bool aIsPrivate);
|
||||
|
||||
// cached services
|
||||
nsCOMPtr<nsIPermissionManager> mPermMgr;
|
||||
nsCOMPtr<nsIObserverService> mObserverService;
|
||||
|
||||
bool mInPrivateMode;
|
||||
nsTHashtable<nsSTSHostEntry> mPrivateModeHostTable;
|
||||
bool mUsePreloadList;
|
||||
};
|
||||
|
@ -293,7 +293,14 @@ CertErrorRunnable::CheckCertOverrides()
|
||||
nsCOMPtr<nsIStrictTransportSecurityService> stss
|
||||
= do_GetService(NS_STSSERVICE_CONTRACTID, &nsrv);
|
||||
if (NS_SUCCEEDED(nsrv)) {
|
||||
nsCOMPtr<nsISSLSocketControl> sslSocketControl = do_QueryInterface(
|
||||
NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, mInfoObject));
|
||||
uint32_t flags = 0;
|
||||
if (sslSocketControl) {
|
||||
sslSocketControl->GetProviderFlags(&flags);
|
||||
}
|
||||
nsrv = stss->IsStsHost(mInfoObject->GetHostName(),
|
||||
flags,
|
||||
&strictTransportSecurityEnabled);
|
||||
}
|
||||
if (NS_FAILED(nsrv)) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsIAssociatedContentSecurity.h"
|
||||
#include "nsNSSShutDown.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsISocketTransport.h"
|
||||
|
||||
namespace mozilla { namespace psm {
|
||||
|
||||
|
@ -61,7 +61,7 @@ typedef enum {ASK, AUTO} SSM_UserCertChoice;
|
||||
extern PRLogModuleInfo* gPIPNSSLog;
|
||||
#endif
|
||||
|
||||
nsNSSSocketInfo::nsNSSSocketInfo()
|
||||
nsNSSSocketInfo::nsNSSSocketInfo(uint32_t providerFlags)
|
||||
: mFd(nullptr),
|
||||
mCertVerificationState(before_cert_verification),
|
||||
mForSTARTTLS(false),
|
||||
@ -77,7 +77,8 @@ nsNSSSocketInfo::nsNSSSocketInfo()
|
||||
mNPNCompleted(false),
|
||||
mHandshakeCompleted(false),
|
||||
mJoined(false),
|
||||
mSentClientCert(false)
|
||||
mSentClientCert(false),
|
||||
mProviderFlags(providerFlags)
|
||||
{
|
||||
}
|
||||
|
||||
@ -85,6 +86,13 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsNSSSocketInfo, TransportSecurityInfo,
|
||||
nsISSLSocketControl,
|
||||
nsIClientAuthUserDecision)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetProviderFlags(uint32_t* aProviderFlags)
|
||||
{
|
||||
*aProviderFlags = mProviderFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNSSSocketInfo::GetHandshakePending(bool *aHandshakePending)
|
||||
{
|
||||
@ -1312,14 +1320,14 @@ nsSSLIOLayerNewSocket(int32_t family,
|
||||
PRFileDesc **fd,
|
||||
nsISupports** info,
|
||||
bool forSTARTTLS,
|
||||
bool anonymousLoad)
|
||||
uint32_t flags)
|
||||
{
|
||||
|
||||
PRFileDesc* sock = PR_OpenTCPSocket(family);
|
||||
if (!sock) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, proxyHost, proxyPort,
|
||||
sock, info, forSTARTTLS, anonymousLoad);
|
||||
sock, info, forSTARTTLS, flags);
|
||||
if (NS_FAILED(rv)) {
|
||||
PR_Close(sock);
|
||||
return rv;
|
||||
@ -2309,8 +2317,7 @@ done:
|
||||
static PRFileDesc*
|
||||
nsSSLIOLayerImportFD(PRFileDesc *fd,
|
||||
nsNSSSocketInfo *infoObject,
|
||||
const char *host,
|
||||
bool anonymousLoad)
|
||||
const char *host)
|
||||
{
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
PRFileDesc* sslSock = SSL_ImportFD(nullptr, fd);
|
||||
@ -2322,7 +2329,9 @@ nsSSLIOLayerImportFD(PRFileDesc *fd,
|
||||
SSL_HandshakeCallback(sslSock, HandshakeCallback, infoObject);
|
||||
|
||||
// Disable this hook if we connect anonymously. See bug 466080.
|
||||
if (anonymousLoad) {
|
||||
uint32_t flags = 0;
|
||||
infoObject->GetProviderFlags(&flags);
|
||||
if (flags & nsISocketTransport::ANONYMOUS_CONNECT) {
|
||||
SSL_GetClientAuthDataHook(sslSock, nullptr, infoObject);
|
||||
} else {
|
||||
SSL_GetClientAuthDataHook(sslSock,
|
||||
@ -2428,14 +2437,14 @@ nsSSLIOLayerAddToSocket(int32_t family,
|
||||
PRFileDesc* fd,
|
||||
nsISupports** info,
|
||||
bool forSTARTTLS,
|
||||
bool anonymousLoad)
|
||||
uint32_t providerFlags)
|
||||
{
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
PRFileDesc* layer = nullptr;
|
||||
nsresult rv;
|
||||
PRStatus stat;
|
||||
|
||||
nsNSSSocketInfo* infoObject = new nsNSSSocketInfo();
|
||||
nsNSSSocketInfo* infoObject = new nsNSSSocketInfo(providerFlags);
|
||||
if (!infoObject) return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ADDREF(infoObject);
|
||||
@ -2443,7 +2452,8 @@ nsSSLIOLayerAddToSocket(int32_t family,
|
||||
infoObject->SetHostName(host);
|
||||
infoObject->SetPort(port);
|
||||
|
||||
PRFileDesc *sslSock = nsSSLIOLayerImportFD(fd, infoObject, host, anonymousLoad);
|
||||
bool anonymousLoad = providerFlags & nsISocketProvider::ANONYMOUS_CONNECT;
|
||||
PRFileDesc *sslSock = nsSSLIOLayerImportFD(fd, infoObject, host);
|
||||
if (!sslSock) {
|
||||
NS_ASSERTION(false, "NSS: Error importing socket");
|
||||
goto loser;
|
||||
|
@ -13,13 +13,14 @@
|
||||
#include "nsNSSCertificate.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsISocketTransport.h"
|
||||
|
||||
class nsNSSSocketInfo : public mozilla::psm::TransportSecurityInfo,
|
||||
public nsISSLSocketControl,
|
||||
public nsIClientAuthUserDecision
|
||||
{
|
||||
public:
|
||||
nsNSSSocketInfo();
|
||||
nsNSSSocketInfo(uint32_t providerFlags);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSISSLSOCKETCONTROL
|
||||
@ -72,7 +73,7 @@ public:
|
||||
{
|
||||
return mCertVerificationState == waiting_for_cert_verification;
|
||||
}
|
||||
|
||||
|
||||
bool IsSSL3Enabled() const { return mSSL3Enabled; }
|
||||
void SetSSL3Enabled(bool enabled) { mSSL3Enabled = enabled; }
|
||||
bool IsTLSEnabled() const { return mTLSEnabled; }
|
||||
@ -100,6 +101,8 @@ private:
|
||||
bool mHandshakeCompleted;
|
||||
bool mJoined;
|
||||
bool mSentClientCert;
|
||||
|
||||
uint32_t mProviderFlags;
|
||||
};
|
||||
|
||||
class nsSSLIOLayerHelpers
|
||||
@ -146,7 +149,7 @@ nsresult nsSSLIOLayerNewSocket(int32_t family,
|
||||
PRFileDesc **fd,
|
||||
nsISupports **securityInfo,
|
||||
bool forSTARTTLS,
|
||||
bool anonymousLoad);
|
||||
uint32_t flags);
|
||||
|
||||
nsresult nsSSLIOLayerAddToSocket(int32_t family,
|
||||
const char *host,
|
||||
@ -156,7 +159,7 @@ nsresult nsSSLIOLayerAddToSocket(int32_t family,
|
||||
PRFileDesc *fd,
|
||||
nsISupports **securityInfo,
|
||||
bool forSTARTTLS,
|
||||
bool anonymousLoad);
|
||||
uint32_t flags);
|
||||
|
||||
nsresult nsSSLIOLayerFreeTLSIntolerantSites();
|
||||
nsresult displayUnknownCertErrorAlert(nsNSSSocketInfo *infoObject, int error);
|
||||
|
@ -36,7 +36,7 @@ nsSSLSocketProvider::NewSocket(int32_t family,
|
||||
_result,
|
||||
securityInfo,
|
||||
false,
|
||||
flags & ANONYMOUS_CONNECT);
|
||||
flags);
|
||||
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ nsSSLSocketProvider::AddToSocket(int32_t family,
|
||||
aSocket,
|
||||
securityInfo,
|
||||
false,
|
||||
flags & ANONYMOUS_CONNECT);
|
||||
flags);
|
||||
|
||||
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ nsTLSSocketProvider::NewSocket(int32_t family,
|
||||
_result,
|
||||
securityInfo,
|
||||
true,
|
||||
flags & ANONYMOUS_CONNECT);
|
||||
flags);
|
||||
|
||||
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
|
||||
}
|
||||
@ -60,7 +60,7 @@ nsTLSSocketProvider::AddToSocket(int32_t family,
|
||||
aSocket,
|
||||
securityInfo,
|
||||
true,
|
||||
flags & ANONYMOUS_CONNECT);
|
||||
flags);
|
||||
|
||||
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@
|
||||
var thehost = ios.newURI("http://example.com", null, null);
|
||||
|
||||
var stss = Cc["@mozilla.org/stsservice;1"].getService(Ci.nsIStrictTransportSecurityService);
|
||||
stss.removeStsState(thehost);
|
||||
stss.removeStsState(thehost, 0);
|
||||
}
|
||||
|
||||
function loadVerifyFrames(round) {
|
||||
|
@ -171,7 +171,12 @@
|
||||
var thehost = ios.newURI("http://example.com", null, null);
|
||||
var stss = Cc["@mozilla.org/stsservice;1"]
|
||||
.getService(Ci.nsIStrictTransportSecurityService);
|
||||
stss.removeStsState(thehost);
|
||||
var loadContext = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsILoadContext);
|
||||
var flags = loadContext.usePrivateBrowsing ?
|
||||
Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0
|
||||
stss.removeStsState(thehost, flags);
|
||||
dump_STSState();
|
||||
SimpleTest.executeSoon(nextTest);
|
||||
}
|
||||
@ -180,7 +185,12 @@ function dump_STSState() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
var stss = Components.classes["@mozilla.org/stsservice;1"]
|
||||
.getService(Components.interfaces.nsIStrictTransportSecurityService);
|
||||
SimpleTest.info("State of example.com: " + stss.isStsHost("example.com"));
|
||||
var loadContext = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsILoadContext);
|
||||
var flags = loadContext.usePrivateBrowsing ?
|
||||
Components.interfaces.nsISocketProvider.NO_PERMANENT_STORAGE : 0
|
||||
SimpleTest.info("State of example.com: " + stss.isStsHost("example.com", flags));
|
||||
}
|
||||
|
||||
// these are executed in the order presented.
|
||||
|
@ -3,73 +3,62 @@ var Ci = Components.interfaces;
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var _PBSvc = null;
|
||||
function get_PBSvc() {
|
||||
if (_PBSvc)
|
||||
return _PBSvc;
|
||||
|
||||
try {
|
||||
_PBSvc = Cc["@mozilla.org/privatebrowsing;1"]
|
||||
.getService(Ci.nsIPrivateBrowsingService);
|
||||
return _PBSvc;
|
||||
} catch (e) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
var gSTSService = Cc["@mozilla.org/stsservice;1"]
|
||||
.getService(Ci.nsIStrictTransportSecurityService);
|
||||
|
||||
function Observer() {}
|
||||
Observer.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
do_execute_soon(gNextTest);
|
||||
}
|
||||
};
|
||||
|
||||
var gObserver = new Observer();
|
||||
var gNextTest = null;
|
||||
|
||||
function cleanup() {
|
||||
Services.obs.removeObserver(gObserver, "private-browsing-transition-complete");
|
||||
get_PBSvc().privateBrowsingEnabled = false;
|
||||
leavePB();
|
||||
// (we have to remove any state added to the sts service so as to not muck
|
||||
// with other tests).
|
||||
var uri = Services.io.newURI("http://localhost", null, null);
|
||||
gSTSService.removeStsState(uri);
|
||||
gSTSService.removeStsState(uri, privacyFlags());
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let pb = get_PBSvc();
|
||||
if (pb) {
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanup);
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanup);
|
||||
|
||||
gNextTest = test_part1;
|
||||
Services.obs.addObserver(gObserver, "private-browsing-transition-complete", false);
|
||||
Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
|
||||
pb.privateBrowsingEnabled = true;
|
||||
}
|
||||
gNextTest = test_part1;
|
||||
enterPB();
|
||||
}
|
||||
|
||||
var gInPrivate = false;
|
||||
function enterPB() {
|
||||
gInPrivate = true;
|
||||
do_execute_soon(gNextTest);
|
||||
}
|
||||
|
||||
function leavePB() {
|
||||
gInPrivate = false;
|
||||
Services.obs.notifyObservers(null, "last-pb-context-exited", null);
|
||||
do_execute_soon(gNextTest);
|
||||
}
|
||||
|
||||
function privacyFlags() {
|
||||
return gInPrivate ? Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
|
||||
}
|
||||
|
||||
function test_part1() {
|
||||
var uri = Services.io.newURI("https://localhost/img.png", null, null);
|
||||
gSTSService.processStsHeader(uri, "max-age=1000");
|
||||
do_check_true(gSTSService.isStsHost("localhost"));
|
||||
gSTSService.processStsHeader(uri, "max-age=1000", privacyFlags());
|
||||
do_check_true(gSTSService.isStsHost("localhost", privacyFlags()));
|
||||
gNextTest = test_part2;
|
||||
get_PBSvc().privateBrowsingEnabled = false;
|
||||
leavePB();
|
||||
}
|
||||
|
||||
function test_part2() {
|
||||
var uri = Services.io.newURI("https://localhost/img.png", null, null);
|
||||
gSTSService.processStsHeader(uri, "max-age=1000");
|
||||
do_check_true(gSTSService.isStsHost("localhost"));
|
||||
gSTSService.processStsHeader(uri, "max-age=1000", privacyFlags());
|
||||
do_check_true(gSTSService.isStsHost("localhost", privacyFlags()));
|
||||
gNextTest = test_part3;
|
||||
get_PBSvc().privateBrowsingEnabled = true;
|
||||
enterPB();
|
||||
}
|
||||
|
||||
function test_part3() {
|
||||
var uri = Services.io.newURI("https://localhost/img.png", null, null);
|
||||
gSTSService.processStsHeader(uri, "max-age=1000");
|
||||
do_check_true(gSTSService.isStsHost("localhost"));
|
||||
gSTSService.processStsHeader(uri, "max-age=1000", privacyFlags());
|
||||
do_check_true(gSTSService.isStsHost("localhost", privacyFlags()));
|
||||
do_test_finished();
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ function cleanup() {
|
||||
|
||||
for (var host of hosts) {
|
||||
var uri = Services.io.newURI(host, null, null);
|
||||
gSTSService.removeStsState(uri);
|
||||
gSTSService.removeStsState(uri, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,65 +66,65 @@ function run_test() {
|
||||
|
||||
function test_part1() {
|
||||
// check that a host not in the list is not identified as an sts host
|
||||
do_check_false(gSTSService.isStsHost("nonexistent.mozilla.com"));
|
||||
do_check_false(gSTSService.isStsHost("nonexistent.mozilla.com", 0));
|
||||
|
||||
// check that an ancestor domain is not identified as an sts host
|
||||
do_check_false(gSTSService.isStsHost("com"));
|
||||
do_check_false(gSTSService.isStsHost("com", 0));
|
||||
|
||||
// Note: the following were taken from the STS preload list
|
||||
// as of Sept. 2012. If the list changes, this test will need to be modified.
|
||||
// check that the pref to toggle using the preload list works
|
||||
Services.prefs.setBoolPref("network.stricttransportsecurity.preloadlist", false);
|
||||
do_check_false(gSTSService.isStsHost("factor.cc"));
|
||||
do_check_false(gSTSService.isStsHost("factor.cc", 0));
|
||||
Services.prefs.setBoolPref("network.stricttransportsecurity.preloadlist", true);
|
||||
do_check_true(gSTSService.isStsHost("factor.cc"));
|
||||
do_check_true(gSTSService.isStsHost("factor.cc", 0));
|
||||
|
||||
// check that an entry at the beginning of the list is an sts host
|
||||
do_check_true(gSTSService.isStsHost("arivo.com.br"));
|
||||
do_check_true(gSTSService.isStsHost("arivo.com.br", 0));
|
||||
|
||||
// check that a subdomain is an sts host (includeSubdomains is set)
|
||||
do_check_true(gSTSService.isStsHost("subdomain.arivo.com.br"));
|
||||
do_check_true(gSTSService.isStsHost("subdomain.arivo.com.br", 0));
|
||||
|
||||
// check that another subdomain is an sts host (includeSubdomains is set)
|
||||
do_check_true(gSTSService.isStsHost("a.b.c.subdomain.arivo.com.br"));
|
||||
do_check_true(gSTSService.isStsHost("a.b.c.subdomain.arivo.com.br", 0));
|
||||
|
||||
// check that an entry in the middle of the list is an sts host
|
||||
do_check_true(gSTSService.isStsHost("neg9.org"));
|
||||
do_check_true(gSTSService.isStsHost("neg9.org", 0));
|
||||
|
||||
// check that a subdomain is not an sts host (includeSubdomains is not set)
|
||||
do_check_false(gSTSService.isStsHost("subdomain.neg9.org"));
|
||||
do_check_false(gSTSService.isStsHost("subdomain.neg9.org", 0));
|
||||
|
||||
// check that an entry at the end of the list is an sts host
|
||||
do_check_true(gSTSService.isStsHost("www.noisebridge.net"));
|
||||
do_check_true(gSTSService.isStsHost("www.noisebridge.net", 0));
|
||||
|
||||
// check that a subdomain is not an sts host (includeSubdomains is not set)
|
||||
do_check_false(gSTSService.isStsHost("a.subdomain.www.noisebridge.net"));
|
||||
do_check_false(gSTSService.isStsHost("a.subdomain.www.noisebridge.net", 0));
|
||||
|
||||
// check that a host with a dot on the end won't break anything
|
||||
do_check_false(gSTSService.isStsHost("notsts.nonexistent.mozilla.com."));
|
||||
do_check_false(gSTSService.isStsHost("notsts.nonexistent.mozilla.com.", 0));
|
||||
|
||||
// check that processing a header with max-age: 0 will remove a preloaded
|
||||
// site from the list
|
||||
var uri = Services.io.newURI("http://keyerror.com", null, null);
|
||||
gSTSService.processStsHeader(uri, "max-age=0");
|
||||
do_check_false(gSTSService.isStsHost("keyerror.com"));
|
||||
do_check_false(gSTSService.isStsHost("subdomain.keyerror.com"));
|
||||
gSTSService.processStsHeader(uri, "max-age=0", 0);
|
||||
do_check_false(gSTSService.isStsHost("keyerror.com", 0));
|
||||
do_check_false(gSTSService.isStsHost("subdomain.keyerror.com", 0));
|
||||
// check that processing another header (with max-age non-zero) will
|
||||
// re-enable a site's sts status
|
||||
gSTSService.processStsHeader(uri, "max-age=1000");
|
||||
do_check_true(gSTSService.isStsHost("keyerror.com"));
|
||||
gSTSService.processStsHeader(uri, "max-age=1000", 0);
|
||||
do_check_true(gSTSService.isStsHost("keyerror.com", 0));
|
||||
// but this time include subdomains was not set, so test for that
|
||||
do_check_false(gSTSService.isStsHost("subdomain.keyerror.com"));
|
||||
do_check_false(gSTSService.isStsHost("subdomain.keyerror.com", 0));
|
||||
|
||||
// check that processing a header with max-age: 0 from a subdomain of a site
|
||||
// will not remove that (ancestor) site from the list
|
||||
var uri = Services.io.newURI("http://subdomain.intercom.io", null, null);
|
||||
gSTSService.processStsHeader(uri, "max-age=0");
|
||||
do_check_true(gSTSService.isStsHost("intercom.io"));
|
||||
do_check_false(gSTSService.isStsHost("subdomain.intercom.io"));
|
||||
gSTSService.processStsHeader(uri, "max-age=0", 0);
|
||||
do_check_true(gSTSService.isStsHost("intercom.io", 0));
|
||||
do_check_false(gSTSService.isStsHost("subdomain.intercom.io", 0));
|
||||
|
||||
var uri = Services.io.newURI("http://subdomain.pixi.me", null, null);
|
||||
gSTSService.processStsHeader(uri, "max-age=0");
|
||||
gSTSService.processStsHeader(uri, "max-age=0", 0);
|
||||
// we received a header with "max-age=0", so we have "no information"
|
||||
// regarding the sts state of subdomain.pixi.me specifically, but
|
||||
// it is actually still an STS host, because of the preloaded pixi.me
|
||||
@ -134,19 +134,19 @@ function test_part1() {
|
||||
// |-- subdomain.pixi.me IS sts host
|
||||
// | `-- another.subdomain.pixi.me IS sts host
|
||||
// `-- sibling.pixi.me IS sts host
|
||||
do_check_true(gSTSService.isStsHost("subdomain.pixi.me"));
|
||||
do_check_true(gSTSService.isStsHost("sibling.pixi.me"));
|
||||
do_check_true(gSTSService.isStsHost("another.subdomain.pixi.me"));
|
||||
do_check_true(gSTSService.isStsHost("subdomain.pixi.me", 0));
|
||||
do_check_true(gSTSService.isStsHost("sibling.pixi.me", 0));
|
||||
do_check_true(gSTSService.isStsHost("another.subdomain.pixi.me", 0));
|
||||
|
||||
gSTSService.processStsHeader(uri, "max-age=1000");
|
||||
gSTSService.processStsHeader(uri, "max-age=1000", 0);
|
||||
// Here's what we have now:
|
||||
// |-- pixi.me (in preload list, includes subdomains) IS sts host
|
||||
// |-- subdomain.pixi.me (include subdomains is false) IS sts host
|
||||
// | `-- another.subdomain.pixi.me IS NOT sts host
|
||||
// `-- sibling.pixi.me IS sts host
|
||||
do_check_true(gSTSService.isStsHost("subdomain.pixi.me"));
|
||||
do_check_true(gSTSService.isStsHost("sibling.pixi.me"));
|
||||
do_check_false(gSTSService.isStsHost("another.subdomain.pixi.me"));
|
||||
do_check_true(gSTSService.isStsHost("subdomain.pixi.me", 0));
|
||||
do_check_true(gSTSService.isStsHost("sibling.pixi.me", 0));
|
||||
do_check_false(gSTSService.isStsHost("another.subdomain.pixi.me", 0));
|
||||
|
||||
// Test private browsing correctly interacts with removing preloaded sites.
|
||||
// If we don't have the private browsing service, don't run those tests
|
||||
@ -159,26 +159,28 @@ function test_part1() {
|
||||
}
|
||||
}
|
||||
|
||||
const IS_PRIVATE = Ci.nsISocketProvider.NO_PERMANENT_STORAGE;
|
||||
|
||||
function test_private_browsing1() {
|
||||
// sanity - crypto.cat is preloaded, includeSubdomains set
|
||||
do_check_true(gSTSService.isStsHost("crypto.cat"));
|
||||
do_check_true(gSTSService.isStsHost("a.b.c.subdomain.crypto.cat"));
|
||||
do_check_true(gSTSService.isStsHost("crypto.cat", IS_PRIVATE));
|
||||
do_check_true(gSTSService.isStsHost("a.b.c.subdomain.crypto.cat", IS_PRIVATE));
|
||||
|
||||
var uri = Services.io.newURI("http://crypto.cat", null, null);
|
||||
gSTSService.processStsHeader(uri, "max-age=0");
|
||||
do_check_false(gSTSService.isStsHost("crypto.cat"));
|
||||
do_check_false(gSTSService.isStsHost("a.b.subdomain.crypto.cat"));
|
||||
gSTSService.processStsHeader(uri, "max-age=0", IS_PRIVATE);
|
||||
do_check_false(gSTSService.isStsHost("crypto.cat", IS_PRIVATE));
|
||||
do_check_false(gSTSService.isStsHost("a.b.subdomain.crypto.cat", IS_PRIVATE));
|
||||
|
||||
// check adding it back in
|
||||
gSTSService.processStsHeader(uri, "max-age=1000");
|
||||
do_check_true(gSTSService.isStsHost("crypto.cat"));
|
||||
gSTSService.processStsHeader(uri, "max-age=1000", IS_PRIVATE);
|
||||
do_check_true(gSTSService.isStsHost("crypto.cat", IS_PRIVATE));
|
||||
// but no includeSubdomains this time
|
||||
do_check_false(gSTSService.isStsHost("b.subdomain.crypto.cat"));
|
||||
do_check_false(gSTSService.isStsHost("b.subdomain.crypto.cat", IS_PRIVATE));
|
||||
|
||||
// do the hokey-pokey...
|
||||
gSTSService.processStsHeader(uri, "max-age=0");
|
||||
do_check_false(gSTSService.isStsHost("crypto.cat"));
|
||||
do_check_false(gSTSService.isStsHost("subdomain.crypto.cat"));
|
||||
gSTSService.processStsHeader(uri, "max-age=0", IS_PRIVATE);
|
||||
do_check_false(gSTSService.isStsHost("crypto.cat", IS_PRIVATE));
|
||||
do_check_false(gSTSService.isStsHost("subdomain.crypto.cat", IS_PRIVATE));
|
||||
|
||||
// TODO unfortunately we don't have a good way to know when an entry
|
||||
// has expired in the permission manager, so we can't yet extend this test
|
||||
@ -189,12 +191,12 @@ function test_private_browsing1() {
|
||||
// a site on the preload list, and that header later expires. We need to
|
||||
// then treat that host as no longer an sts host.)
|
||||
// (sanity check first - this should be in the preload list)
|
||||
do_check_true(gSTSService.isStsHost("logentries.com"));
|
||||
do_check_true(gSTSService.isStsHost("logentries.com", IS_PRIVATE));
|
||||
var uri = Services.io.newURI("http://logentries.com", null, null);
|
||||
// according to the rfc, max-age can't be negative, but this is a great
|
||||
// way to test an expired entry
|
||||
gSTSService.processStsHeader(uri, "max-age=-1000");
|
||||
do_check_false(gSTSService.isStsHost("logentries.com"));
|
||||
gSTSService.processStsHeader(uri, "max-age=-1000", IS_PRIVATE);
|
||||
do_check_false(gSTSService.isStsHost("logentries.com", IS_PRIVATE));
|
||||
|
||||
// if this test gets this far, it means there's a private browsing service
|
||||
getPBSvc().privateBrowsingEnabled = false;
|
||||
@ -202,13 +204,13 @@ function test_private_browsing1() {
|
||||
|
||||
function test_private_browsing2() {
|
||||
// if this test gets this far, it means there's a private browsing service
|
||||
do_check_true(gSTSService.isStsHost("crypto.cat"));
|
||||
do_check_true(gSTSService.isStsHost("crypto.cat", 0));
|
||||
// the crypto.cat entry has includeSubdomains set
|
||||
do_check_true(gSTSService.isStsHost("subdomain.crypto.cat"));
|
||||
do_check_true(gSTSService.isStsHost("subdomain.crypto.cat", 0));
|
||||
|
||||
// Now that we're out of private browsing mode, we need to make sure
|
||||
// we've "forgotten" that we "forgot" this site's sts status.
|
||||
do_check_true(gSTSService.isStsHost("logentries.com"));
|
||||
do_check_true(gSTSService.isStsHost("logentries.com", 0));
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -9,16 +9,16 @@ function run_test() {
|
||||
.getService(Ci.nsIStrictTransportSecurityService);
|
||||
|
||||
// check that a host on the preload list is identified as an sts host
|
||||
do_check_true(STSService.isStsHost("alpha.irccloud.com"));
|
||||
do_check_true(STSService.isStsHost("alpha.irccloud.com", 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
|
||||
do_check_false(STSService.isStsHost("alpha.irccloud.com"));
|
||||
do_check_false(STSService.isStsHost("alpha.irccloud.com", 0));
|
||||
|
||||
// just make sure we can get everything back to normal
|
||||
Services.prefs.clearUserPref("test.currentTimeOffsetSeconds");
|
||||
do_check_true(STSService.isStsHost("alpha.irccloud.com"));
|
||||
do_check_true(STSService.isStsHost("alpha.irccloud.com", 0));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user