mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1216687: Add nsILoadInfo flags for cookie policies. r=ckerschb
This commit is contained in:
parent
f7193fdf30
commit
0bb4231605
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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)) {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ?
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user