Bug 1216687: Add nsILoadInfo flags for cookie policies. r=ckerschb

This commit is contained in:
Jonas Sicking 2015-12-06 18:33:15 -05:00
parent f7193fdf30
commit 0bb4231605
14 changed files with 130 additions and 194 deletions

View File

@ -678,7 +678,7 @@ EventSource::InitChannelAndRequestEventSource()
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
if (mWithCredentials) {
securityFlags |= nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS;
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
nsCOMPtr<nsIChannel> channel;

View File

@ -1205,7 +1205,7 @@ Navigator::SendBeacon(const nsAString& aUrl,
uri,
doc,
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS |
nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS,
nsILoadInfo::SEC_COOKIES_INCLUDE,
nsIContentPolicy::TYPE_BEACON);
if (NS_FAILED(rv)) {

View File

@ -298,7 +298,7 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL
: nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
if (aRequest->mCORSMode == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS;
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;

View File

@ -1691,6 +1691,10 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
}
if (mIsAnon) {
secFlags |= nsILoadInfo::SEC_COOKIES_OMIT;
}
// If we have the document, use it. Unfortunately, for dedicated workers
// 'doc' ends up being the parent document, which is not the document
// that we want to use. So make sure to avoid using 'doc' in that situation.
@ -2794,18 +2798,17 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
ResetResponse();
bool withCredentials = !!(mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS);
if (!IsSystemXHR() && withCredentials) {
if (!IsSystemXHR() && !mIsAnon &&
(mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS)) {
// This is quite sad. We have to create the channel in .open(), since the
// chrome-only xhr.channel API depends on that. However .withCredentials
// can be modified after, so we don't know what to set the
// SEC_REQUIRE_CORS_WITH_CREDENTIALS flag to when the channel is
// SEC_COOKIES_INCLUDE flag to when the channel is
// created. So set it here using a hacky internal API.
// Not doing this for system XHR uses since those don't use CORS.
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
static_cast<LoadInfo*>(loadInfo.get())->SetWithCredentialsSecFlag();
static_cast<LoadInfo*>(loadInfo.get())->SetIncludeCookiesSecFlag();
}
// Blocking gets are common enough out of XHR that we should mark
@ -2827,10 +2830,7 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
internalHttpChannel->SetResponseTimeoutEnabled(false);
}
if (mIsAnon) {
AddLoadFlags(mChannel, nsIRequest::LOAD_ANONYMOUS);
}
else {
if (!mIsAnon) {
AddLoadFlags(mChannel, nsIChannel::LOAD_EXPLICIT_CREDENTIALS);
}
@ -3250,8 +3250,9 @@ nsXMLHttpRequest::SetWithCredentials(bool aWithCredentials, ErrorResult& aRv)
// Return error if we're already processing a request. Note that we can't use
// ReadyState() here, because it can't differentiate between "opened" and
// "sent", so we use mState directly.
if (!(mState & XML_HTTP_REQUEST_UNSENT) &&
!(mState & XML_HTTP_REQUEST_OPENED)) {
if ((!(mState & XML_HTTP_REQUEST_UNSENT) &&
!(mState & XML_HTTP_REQUEST_OPENED)) ||
mIsAnon) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}

View File

@ -466,7 +466,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
{
// credentials using the auth cache
var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
xhr.withCredentials = true;
// also, test mixed mode UI
xhr.open("GET", "https://example.com/tests/dom/base/test/file_restrictedEventSource.sjs?test=user1_xhr", true, "user 1", "password 1");
xhr.send();
@ -495,7 +494,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
function doTest5_d(test_id)
{
var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
xhr.withCredentials = true;
xhr.open("GET", "https://example.com/tests/dom/base/test/file_restrictedEventSource.sjs?test=user2_xhr", true, "user 2", "password 2");
xhr.send();
xhr.onloadend = function() {
@ -523,7 +521,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
{
// credentials using the auth cache
var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
xhr.withCredentials = true;
xhr.open("GET", "http://example.org/tests/dom/base/test/file_restrictedEventSource.sjs?test=user1_xhr", true, "user 1", "password 1");
xhr.send();
xhr.onloadend = function() {
@ -551,7 +548,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
function doTest5_f(test_id)
{
var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
xhr.withCredentials = true;
xhr.open("GET", "http://example.org/tests/dom/base/test/file_restrictedEventSource.sjs?test=user2_xhr", true, "user 2", "password 2");
xhr.send();
xhr.onloadend = function() {

View File

@ -43,7 +43,7 @@ namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS(FetchDriver,
nsIStreamListener, nsIChannelEventSink, nsIInterfaceRequestor,
nsIStreamListener, nsIInterfaceRequestor,
nsIThreadRetargetableStreamListener)
FetchDriver::FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal,
@ -98,16 +98,6 @@ FetchDriver::ContinueFetch()
return rv;
}
static void
AddLoadFlags(nsIRequest *aRequest, nsLoadFlags aNewFlags)
{
MOZ_ASSERT(aRequest);
nsLoadFlags flags;
aRequest->GetLoadFlags(&flags);
flags |= aNewFlags;
aRequest->SetLoadFlags(flags);
}
// This function implements the "HTTP Fetch" algorithm from the Fetch spec.
// Functionality is often split between here, the CORS listener proxy and the
// Necko HTTP implementation.
@ -168,17 +158,13 @@ FetchDriver::HttpFetch()
const nsLoadFlags bypassFlag = mRequest->SkipServiceWorker() ?
nsIChannel::LOAD_BYPASS_SERVICE_WORKER : 0;
nsSecurityFlags secFlags;
if (mRequest->Mode() == RequestMode::Cors &&
mRequest->GetCredentialsMode() == RequestCredentials::Include) {
secFlags = nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS |
nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS;
} else if (mRequest->Mode() == RequestMode::Cors) {
secFlags = nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
nsSecurityFlags secFlags = nsILoadInfo::SEC_ABOUT_BLANK_INHERITS;
if (mRequest->Mode() == RequestMode::Cors) {
secFlags |= nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
} else if (mRequest->Mode() == RequestMode::Same_origin) {
secFlags = nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS;
secFlags |= nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS;
} else if (mRequest->Mode() == RequestMode::No_cors) {
secFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
secFlags |= nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
} else {
MOZ_ASSERT_UNREACHABLE("Unexpected request mode!");
return NS_ERROR_UNEXPECTED;
@ -188,6 +174,20 @@ FetchDriver::HttpFetch()
secFlags |= nsILoadInfo::SEC_DONT_FOLLOW_REDIRECTS;
}
// This is handles the use credentials flag in "HTTP
// network or cache fetch" in the spec and decides whether to transmit
// cookies and other identifying information.
if (mRequest->GetCredentialsMode() == RequestCredentials::Include) {
secFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
} else if (mRequest->GetCredentialsMode() == RequestCredentials::Omit) {
secFlags |= nsILoadInfo::SEC_COOKIES_OMIT;
} else if (mRequest->GetCredentialsMode() == RequestCredentials::Same_origin) {
secFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
} else {
MOZ_ASSERT_UNREACHABLE("Unexpected credentials mode!");
return NS_ERROR_UNEXPECTED;
}
// From here on we create a channel and set its properties with the
// information from the InternalRequest. This is an implementation detail.
MOZ_ASSERT(mLoadGroup);
@ -200,8 +200,7 @@ FetchDriver::HttpFetch()
rv = NS_NewChannel(getter_AddRefs(chan),
uri,
mDocument,
secFlags |
nsILoadInfo::SEC_ABOUT_BLANK_INHERITS,
secFlags,
mRequest->ContentPolicyType(),
mLoadGroup,
nullptr, /* aCallbacks */
@ -211,8 +210,7 @@ FetchDriver::HttpFetch()
rv = NS_NewChannel(getter_AddRefs(chan),
uri,
mPrincipal,
secFlags |
nsILoadInfo::SEC_ABOUT_BLANK_INHERITS,
secFlags,
mRequest->ContentPolicyType(),
mLoadGroup,
nullptr, /* aCallbacks */
@ -223,28 +221,6 @@ FetchDriver::HttpFetch()
mLoadGroup = nullptr;
// Insert ourselves into the notification callbacks chain so we can handle
// cross-origin redirects.
#ifdef DEBUG
{
nsCOMPtr<nsIInterfaceRequestor> notificationCallbacks;
chan->GetNotificationCallbacks(getter_AddRefs(notificationCallbacks));
MOZ_ASSERT(!notificationCallbacks);
}
#endif
chan->SetNotificationCallbacks(this);
// This is effectivetly the opposite of the use credentials flag in "HTTP
// network or cache fetch" in the spec and decides whether to transmit
// cookies and other identifying information. LOAD_ANONYMOUS also prevents
// new cookies sent by the server from being stored. This value will
// propagate across redirects, which is what we want.
if (mRequest->GetCredentialsMode() == RequestCredentials::Omit ||
(mRequest->GetCredentialsMode() == RequestCredentials::Same_origin &&
NS_HasBeenCrossOrigin(chan))) {
AddLoadFlags(chan, nsIRequest::LOAD_ANONYMOUS);
}
// FIXME(nsm): Bug 1120715.
// Step 3.4 "If request's cache mode is default and request's header list
// contains a header named `If-Modified-Since`, `If-None-Match`,
@ -698,84 +674,6 @@ FetchDriver::OnStopRequest(nsIRequest* aRequest,
return NS_OK;
}
// This is called when the channel is redirected.
NS_IMETHODIMP
FetchDriver::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
nsIChannel* aNewChannel,
uint32_t aFlags,
nsIAsyncVerifyRedirectCallback *aCallback)
{
NS_PRECONDITION(aNewChannel, "Redirect without a channel?");
// We should only ever get here if we use a "follow" redirect policy,
// or if if we set an "error" policy as a result of a CORS policy.
MOZ_ASSERT(NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags) ||
NS_IsHSTSUpgradeRedirect(aOldChannel, aNewChannel, aFlags) ||
mRequest->GetRedirectMode() == RequestRedirect::Follow);
// HTTP Fetch step 5, "redirect status", step 1 is done by necko
// HTTP Fetch step 5, "redirect status", steps 2 through 6 are automatically
// handled by necko before calling AsyncOnChannelRedirect() with the new
// nsIChannel.
// HTTP Fetch step 5, "redirect status", steps 7 and 8 enforcing a redirect
// count are done by Necko. The pref used is "network.http.redirection-limit"
// which is set to 20 by default.
// HTTP Fetch Step 9, "redirect status". This is enforced by the
// nsCORSListenerProxy. It forbids redirecting to data:
// HTTP Fetch step 5, "redirect status", step 10 requires us to halt the
// redirect, but successfully return an opaqueredirect Response to the
// initiating Fetch.
// The following steps are from HTTP Fetch step 5, "redirect status", step 11
// which requires the RequestRedirect to be "follow". We asserted that we're
// in either "follow" or "error" mode here.
// HTTP Fetch step 5, "redirect status", steps 11.1 and 11.2 block redirecting
// to a URL with credentials in CORS mode. This is implemented in
// nsCORSListenerProxy.
// Implement Main Fetch step 8 again on redirect.
// Requests that require preflight are not permitted to redirect.
// Fetch spec section 4.2 "HTTP Fetch", step 4.9 just uses the manual
// redirect flag to decide whether to execute step 4.10 or not. We do not
// represent it in our implementation.
// This is handled by nsCORSListenerProxy.
// Otherwise, we rely on necko and the CORS proxy to do the right thing
// as the redirect is followed. In general this means http
// fetch. If we've ever been CORS, we need to stay CORS.
// Possibly set the LOAD_ANONYMOUS flag on the channel.
if (mRequest->GetCredentialsMode() == RequestCredentials::Same_origin &&
NS_HasBeenCrossOrigin(aNewChannel)) {
AddLoadFlags(aNewChannel, nsIRequest::LOAD_ANONYMOUS);
}
#ifdef DEBUG
{
// Make sure nothing in the redirect chain screws up our credentials
// settings. LOAD_ANONYMOUS must be set if we RequestCredentials is "omit"
// or "same-origin".
nsLoadFlags flags;
aNewChannel->GetLoadFlags(&flags);
bool shouldBeAnon =
mRequest->GetCredentialsMode() == RequestCredentials::Omit ||
(NS_HasBeenCrossOrigin(aNewChannel) &&
mRequest->GetCredentialsMode() == RequestCredentials::Same_origin);
MOZ_ASSERT(!!(flags & nsIRequest::LOAD_ANONYMOUS) == shouldBeAnon);
}
#endif
aCallback->OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
NS_IMETHODIMP
FetchDriver::CheckListenerChain()
{
@ -785,12 +683,6 @@ FetchDriver::CheckListenerChain()
NS_IMETHODIMP
FetchDriver::GetInterface(const nsIID& aIID, void **aResult)
{
if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
*aResult = static_cast<nsIChannelEventSink*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIStreamListener))) {
*aResult = static_cast<nsIStreamListener*>(this);
NS_ADDREF_THIS();

View File

@ -55,7 +55,6 @@ private:
};
class FetchDriver final : public nsIStreamListener,
public nsIChannelEventSink,
public nsIInterfaceRequestor,
public nsIThreadRetargetableStreamListener
{
@ -63,7 +62,6 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER

View File

@ -1289,7 +1289,7 @@ nsresult HTMLMediaElement::LoadResource()
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
if (GetCORSMode() == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS;
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
MOZ_ASSERT(IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video));

View File

@ -26,12 +26,6 @@ ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
return NS_ERROR_FAILURE;
}
// make sure that cors-with-credentials is only used in combination with CORS.
if (aLoadInfo->GetRequireCorsWithCredentials() &&
securityMode != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
MOZ_ASSERT(false, "can not use cors-with-credentials without cors");
return NS_ERROR_FAILURE;
}
// all good, found the right security flags
return NS_OK;
}
@ -115,7 +109,8 @@ DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
RefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(aInAndOutListener,
loadingPrincipal,
aLoadInfo->GetRequireCorsWithCredentials());
aLoadInfo->GetCookiePolicy() ==
nsILoadInfo::SEC_COOKIES_INCLUDE);
// XXX: @arg: DataURIHandling::Allow
// lets use DataURIHandling::Allow for now and then decide on callsite basis. see also:
// http://mxr.mozilla.org/mozilla-central/source/dom/security/nsCORSListenerProxy.h#33
@ -422,6 +417,15 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
return NS_OK;
}
static void
AddLoadFlags(nsIRequest *aRequest, nsLoadFlags aNewFlags)
{
nsLoadFlags flags;
aRequest->GetLoadFlags(&flags);
flags |= aNewFlags;
aRequest->SetLoadFlags(flags);
}
/*
* Check that this channel passes all security checks. Returns an error code
* if this requesst should not be permitted.
@ -432,6 +436,26 @@ nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
MOZ_ASSERT(loadInfo);
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
// Handle cookie policies
uint32_t cookiePolicy = loadInfo->GetCookiePolicy();
if (cookiePolicy == nsILoadInfo::SEC_COOKIES_SAME_ORIGIN) {
nsIPrincipal* loadingPrincipal = loadInfo->LoadingPrincipal();
// It doesn't matter what we pass for the third, data-inherits, argument.
// Any protocol which inherits won't pay attention to cookies anyway.
rv = loadingPrincipal->CheckMayLoad(uri, false, false);
if (NS_FAILED(rv)) {
AddLoadFlags(aChannel, nsIRequest::LOAD_ANONYMOUS);
}
}
else if (cookiePolicy == nsILoadInfo::SEC_COOKIES_OMIT) {
AddLoadFlags(aChannel, nsIRequest::LOAD_ANONYMOUS);
}
nsSecurityFlags securityMode = loadInfo->GetSecurityMode();
// CORS mode is handled by nsCORSListenerProxy
@ -442,11 +466,6 @@ nsContentSecurityManager::CheckChannel(nsIChannel* aChannel)
return NS_OK;
}
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
// if none of the REQUIRE_SAME_ORIGIN flags are set, then SOP does not apply
if ((securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS) ||
(securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED)) {

View File

@ -269,14 +269,6 @@ LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult)
return NS_OK;
}
void
LoadInfo::SetWithCredentialsSecFlag()
{
MOZ_ASSERT(!mEnforceSecurity,
"Request should not have been opened yet");
mSecurityFlags |= nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS;
}
NS_IMETHODIMP
LoadInfo::GetSecurityMode(uint32_t* aFlags)
{
@ -296,14 +288,36 @@ LoadInfo::GetIsInThirdPartyContext(bool* aIsInThirdPartyContext)
return NS_OK;
}
static const uint32_t sCookiePolicyMask =
nsILoadInfo::SEC_COOKIES_DEFAULT |
nsILoadInfo::SEC_COOKIES_INCLUDE |
nsILoadInfo::SEC_COOKIES_SAME_ORIGIN |
nsILoadInfo::SEC_COOKIES_OMIT;
NS_IMETHODIMP
LoadInfo::GetRequireCorsWithCredentials(bool* aResult)
LoadInfo::GetCookiePolicy(uint32_t *aResult)
{
*aResult =
(mSecurityFlags & nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS);
uint32_t policy = mSecurityFlags & sCookiePolicyMask;
if (policy == nsILoadInfo::SEC_COOKIES_DEFAULT) {
policy = (mSecurityFlags & SEC_REQUIRE_CORS_DATA_INHERITS) ?
nsILoadInfo::SEC_COOKIES_SAME_ORIGIN : nsILoadInfo::SEC_COOKIES_INCLUDE;
}
*aResult = policy;
return NS_OK;
}
void
LoadInfo::SetIncludeCookiesSecFlag()
{
MOZ_ASSERT(!mEnforceSecurity,
"Request should not have been opened yet");
MOZ_ASSERT((mSecurityFlags & sCookiePolicyMask) ==
nsILoadInfo::SEC_COOKIES_DEFAULT);
mSecurityFlags = (mSecurityFlags & ~sCookiePolicyMask) |
nsILoadInfo::SEC_COOKIES_INCLUDE;
}
NS_IMETHODIMP
LoadInfo::GetForceInheritPrincipal(bool* aInheritPrincipal)
{

View File

@ -101,7 +101,7 @@ private:
// This function is the *only* function which can change the securityflags
// of a loadinfo. It only exists because of the XHR code. Don't call it
// from anywhere else!
void SetWithCredentialsSecFlag();
void SetIncludeCookiesSecFlag();
friend class ::nsXMLHttpRequest;
// if you add a member, please also update the copy constructor

View File

@ -29,7 +29,7 @@ typedef unsigned long nsSecurityFlags;
/**
* An nsILoadOwner represents per-load information about who started the load.
*/
[scriptable, builtinclass, uuid(b7b9830e-013e-4ba0-b6c6-a0fc669f4980)]
[scriptable, builtinclass, uuid(41e311d0-5894-4aaa-80b5-5b7099dfc404)]
interface nsILoadInfo : nsISupports
{
/**
@ -89,11 +89,21 @@ interface nsILoadInfo : nsISupports
const unsigned long SEC_REQUIRE_CORS_DATA_INHERITS = (1<<4);
/**
* Use this flag in addition to SEC_REQUIRE_CORS_DATA_INHERITS
* to make cross-origin CORS loads happen with credentials
* (such as cookies and client side certs).
* Choose cookie policy. The default policy is equivalent to "INCLUDE" for
* SEC_REQUIRE_SAME_ORIGIN_* and SEC_ALLOW_CROSS_ORIGIN_* modes, and
* equivalent to "SAME_ORIGIN" for SEC_REQUIRE_CORS_DATA_INHERITS mode.
*
* This means that if you want to perform a CORS load with credentials, pass
* SEC_COOKIES_INCLUDE.
*
* Note that these flags are still subject to the user's cookie policies.
* For example, if the user is blocking 3rd party cookies, those cookies
* will be blocked no matter which of these flags are set.
*/
const unsigned long SEC_REQUIRE_CORS_WITH_CREDENTIALS = (1<<5);
const unsigned long SEC_COOKIES_DEFAULT = (0 << 5);
const unsigned long SEC_COOKIES_INCLUDE = (1 << 5);
const unsigned long SEC_COOKIES_SAME_ORIGIN = (2 << 5);
const unsigned long SEC_COOKIES_OMIT = (3 << 5);
/**
* Force inheriting of the Principal. The resulting resource will use the
@ -110,7 +120,7 @@ interface nsILoadInfo : nsISupports
*
* This flag can not be used together with SEC_SANDBOXED.
*/
const unsigned long SEC_FORCE_INHERIT_PRINCIPAL = (1<<6);
const unsigned long SEC_FORCE_INHERIT_PRINCIPAL = (1<<7);
/**
* Sandbox the load. The resulting resource will use a freshly created
@ -122,17 +132,17 @@ interface nsILoadInfo : nsISupports
*
* This flag can not be used together with SEC_FORCE_INHERIT_PRINCIPAL.
*/
const unsigned long SEC_SANDBOXED = (1<<7);
const unsigned long SEC_SANDBOXED = (1<<8);
/**
* Inherit the Principal for about:blank.
*/
const unsigned long SEC_ABOUT_BLANK_INHERITS = (1<<8);
const unsigned long SEC_ABOUT_BLANK_INHERITS = (1<<9);
/**
* Allow access to chrome: packages that are content accessible.
*/
const unsigned long SEC_ALLOW_CHROME = (1<<9);
const unsigned long SEC_ALLOW_CHROME = (1<<10);
/**
* Don't follow redirects. Instead the redirect response is returned
@ -145,7 +155,7 @@ interface nsILoadInfo : nsISupports
* the response body might not be available.
* This can happen if the redirect was cached.
*/
const unsigned long SEC_DONT_FOLLOW_REDIRECTS = (1<<10);
const unsigned long SEC_DONT_FOLLOW_REDIRECTS = (1<<11);
/**
* The loadingPrincipal is the principal that is responsible for the load.
@ -244,10 +254,12 @@ interface nsILoadInfo : nsISupports
[infallible] readonly attribute boolean isInThirdPartyContext;
/**
* Determines whether credentials are sent with CORS requests.
* Using this flag requires SEC_REQUIRE_CORS_DATA_INHERITS also to be set.
* See the SEC_COOKIES_* flags above. This attribute will never return
* SEC_COOKIES_DEFAULT, but will instead return what the policy resolves to.
* I.e. SEC_COOKIES_SAME_ORIGIN for CORS mode, and SEC_COOKIES_INCLUDE
* otherwise.
*/
[infallible] readonly attribute boolean requireCorsWithCredentials;
[infallible] readonly attribute unsigned long cookiePolicy;
/**
* If forceInheritPrincipal is true, the data coming from the channel should

View File

@ -821,6 +821,8 @@ nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel,
rv = aChannel->GetOriginalURI(getter_AddRefs(originalURI));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
// exempt data URIs from the same origin check.
if (aAllowDataURI == DataURIHandling::Allow && originalURI == uri) {
bool dataScheme = false;
@ -829,8 +831,6 @@ nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel,
if (dataScheme) {
return NS_OK;
}
nsCOMPtr<nsILoadInfo> loadInfo;
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
if (loadInfo && loadInfo->GetAboutBlankInherits() &&
NS_IsAboutBlank(uri)) {
return NS_OK;
@ -904,8 +904,11 @@ nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel,
rv = http->SetRequestHeader(NS_LITERAL_CSTRING("Origin"), origin, false);
NS_ENSURE_SUCCESS(rv, rv);
// Make cookie-less if needed
if (!mWithCredentials) {
// Make cookie-less if needed. We don't need to do anything here if the
// channel was opened with AsyncOpen2, since then AsyncOpen2 will take
// care of the cookie policy for us.
if (!mWithCredentials &&
(!loadInfo || !loadInfo->GetEnforceSecurity())) {
nsLoadFlags flags;
rv = http->GetLoadFlags(&flags);
NS_ENSURE_SUCCESS(rv, rv);
@ -1337,7 +1340,8 @@ nsCORSListenerProxy::StartCORSPreflight(nsIChannel* aRequestChannel,
"how did we end up here?");
nsCOMPtr<nsIPrincipal> principal = originalLoadInfo->LoadingPrincipal();
bool withCredentials = originalLoadInfo->GetRequireCorsWithCredentials();
bool withCredentials = originalLoadInfo->GetCookiePolicy() ==
nsILoadInfo::SEC_COOKIES_INCLUDE;
nsPreflightCache::CacheEntry* entry =
sPreflightCache ?

View File

@ -106,7 +106,7 @@ nsPrefetchNode::OpenChannel()
} else {
securityFlags = nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
if (corsMode == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS;
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
}
}
nsresult rv = NS_NewChannelInternal(getter_AddRefs(mChannel),