зеркало из https://github.com/mozilla/gecko-dev.git
Bug 814141. Cross-site redirects of a CORS request should null out the request origin. r=sicking
This commit is contained in:
Родитель
eb28b72392
Коммит
8915de2bfc
|
@ -350,6 +350,7 @@ nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
|
||||||
bool aWithCredentials)
|
bool aWithCredentials)
|
||||||
: mOuterListener(aOuter),
|
: mOuterListener(aOuter),
|
||||||
mRequestingPrincipal(aRequestingPrincipal),
|
mRequestingPrincipal(aRequestingPrincipal),
|
||||||
|
mOriginHeaderPrincipal(aRequestingPrincipal),
|
||||||
mWithCredentials(aWithCredentials && !gDisableCORSPrivateData),
|
mWithCredentials(aWithCredentials && !gDisableCORSPrivateData),
|
||||||
mRequestApproved(false),
|
mRequestApproved(false),
|
||||||
mHasBeenCrossSite(false),
|
mHasBeenCrossSite(false),
|
||||||
|
@ -364,6 +365,7 @@ nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
|
||||||
const nsTArray<nsCString>& aPreflightHeaders)
|
const nsTArray<nsCString>& aPreflightHeaders)
|
||||||
: mOuterListener(aOuter),
|
: mOuterListener(aOuter),
|
||||||
mRequestingPrincipal(aRequestingPrincipal),
|
mRequestingPrincipal(aRequestingPrincipal),
|
||||||
|
mOriginHeaderPrincipal(aRequestingPrincipal),
|
||||||
mWithCredentials(aWithCredentials && !gDisableCORSPrivateData),
|
mWithCredentials(aWithCredentials && !gDisableCORSPrivateData),
|
||||||
mRequestApproved(false),
|
mRequestApproved(false),
|
||||||
mHasBeenCrossSite(false),
|
mHasBeenCrossSite(false),
|
||||||
|
@ -387,6 +389,7 @@ nsCORSListenerProxy::Init(nsIChannel* aChannel, bool aAllowDataURI)
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
mOuterListener = nullptr;
|
mOuterListener = nullptr;
|
||||||
mRequestingPrincipal = nullptr;
|
mRequestingPrincipal = nullptr;
|
||||||
|
mOriginHeaderPrincipal = nullptr;
|
||||||
mOuterNotificationCallbacks = nullptr;
|
mOuterNotificationCallbacks = nullptr;
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -404,6 +407,8 @@ nsCORSListenerProxy::OnStartRequest(nsIRequest* aRequest,
|
||||||
nsCOMPtr<nsIURI> uri;
|
nsCOMPtr<nsIURI> uri;
|
||||||
NS_GetFinalChannelURI(channel, getter_AddRefs(uri));
|
NS_GetFinalChannelURI(channel, getter_AddRefs(uri));
|
||||||
if (uri) {
|
if (uri) {
|
||||||
|
// OK to use mRequestingPrincipal since preflights never get
|
||||||
|
// redirected.
|
||||||
sPreflightCache->RemoveEntries(uri, mRequestingPrincipal);
|
sPreflightCache->RemoveEntries(uri, mRequestingPrincipal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,7 +493,7 @@ nsCORSListenerProxy::CheckRequestApproved(nsIRequest* aRequest)
|
||||||
|
|
||||||
if (mWithCredentials || !allowedOriginHeader.EqualsLiteral("*")) {
|
if (mWithCredentials || !allowedOriginHeader.EqualsLiteral("*")) {
|
||||||
nsAutoCString origin;
|
nsAutoCString origin;
|
||||||
rv = nsContentUtils::GetASCIIOrigin(mRequestingPrincipal, origin);
|
rv = nsContentUtils::GetASCIIOrigin(mOriginHeaderPrincipal, origin);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (!allowedOriginHeader.Equals(origin)) {
|
if (!allowedOriginHeader.Equals(origin)) {
|
||||||
|
@ -623,12 +628,47 @@ nsCORSListenerProxy::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
||||||
nsCOMPtr<nsIURI> oldURI;
|
nsCOMPtr<nsIURI> oldURI;
|
||||||
NS_GetFinalChannelURI(aOldChannel, getter_AddRefs(oldURI));
|
NS_GetFinalChannelURI(aOldChannel, getter_AddRefs(oldURI));
|
||||||
if (oldURI) {
|
if (oldURI) {
|
||||||
|
// OK to use mRequestingPrincipal since preflights never get
|
||||||
|
// redirected.
|
||||||
sPreflightCache->RemoveEntries(oldURI, mRequestingPrincipal);
|
sPreflightCache->RemoveEntries(oldURI, mRequestingPrincipal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
|
aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
|
||||||
return NS_ERROR_DOM_BAD_URI;
|
return NS_ERROR_DOM_BAD_URI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mHasBeenCrossSite) {
|
||||||
|
// Once we've been cross-site, cross-origin redirects reset our source
|
||||||
|
// origin.
|
||||||
|
nsCOMPtr<nsIPrincipal> oldChannelPrincipal;
|
||||||
|
nsContentUtils::GetSecurityManager()->
|
||||||
|
GetChannelPrincipal(aOldChannel, getter_AddRefs(oldChannelPrincipal));
|
||||||
|
nsCOMPtr<nsIPrincipal> newChannelPrincipal;
|
||||||
|
nsContentUtils::GetSecurityManager()->
|
||||||
|
GetChannelPrincipal(aNewChannel, getter_AddRefs(newChannelPrincipal));
|
||||||
|
if (!oldChannelPrincipal || !newChannelPrincipal) {
|
||||||
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
bool equal;
|
||||||
|
rv = oldChannelPrincipal->Equals(newChannelPrincipal, &equal);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
if (!equal) {
|
||||||
|
// Spec says to set our source origin to a unique origin.
|
||||||
|
mOriginHeaderPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1");
|
||||||
|
if (!mOriginHeaderPrincipal) {
|
||||||
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
aOldChannel->Cancel(rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare to receive callback
|
// Prepare to receive callback
|
||||||
|
@ -729,7 +769,7 @@ nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel, bool aAllowDataURI)
|
||||||
|
|
||||||
// Add the Origin header
|
// Add the Origin header
|
||||||
nsAutoCString origin;
|
nsAutoCString origin;
|
||||||
rv = nsContentUtils::GetASCIIOrigin(mRequestingPrincipal, origin);
|
rv = nsContentUtils::GetASCIIOrigin(mOriginHeaderPrincipal, origin);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aChannel);
|
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aChannel);
|
||||||
|
|
|
@ -66,7 +66,11 @@ private:
|
||||||
nsresult CheckRequestApproved(nsIRequest* aRequest);
|
nsresult CheckRequestApproved(nsIRequest* aRequest);
|
||||||
|
|
||||||
nsCOMPtr<nsIStreamListener> mOuterListener;
|
nsCOMPtr<nsIStreamListener> mOuterListener;
|
||||||
|
// The principal that originally kicked off the request
|
||||||
nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
|
nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
|
||||||
|
// The principal to use for our Origin header ("source origin" in spec terms).
|
||||||
|
// This can get changed during redirects, unlike mRequestingPrincipal.
|
||||||
|
nsCOMPtr<nsIPrincipal> mOriginHeaderPrincipal;
|
||||||
nsCOMPtr<nsIInterfaceRequestor> mOuterNotificationCallbacks;
|
nsCOMPtr<nsIInterfaceRequestor> mOuterNotificationCallbacks;
|
||||||
bool mWithCredentials;
|
bool mWithCredentials;
|
||||||
bool mRequestApproved;
|
bool mRequestApproved;
|
||||||
|
|
|
@ -859,7 +859,7 @@ function runTest() {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ pass: 1,
|
{ pass: 0,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
hops: [{ server: "http://example.com",
|
hops: [{ server: "http://example.com",
|
||||||
allowOrigin: origin
|
allowOrigin: origin
|
||||||
|
@ -869,6 +869,16 @@ function runTest() {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{ pass: 1,
|
||||||
|
method: "GET",
|
||||||
|
hops: [{ server: "http://example.com",
|
||||||
|
allowOrigin: origin
|
||||||
|
},
|
||||||
|
{ server: "http://example.org",
|
||||||
|
allowOrigin: "*"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{ pass: 0,
|
{ pass: 0,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
hops: [{ server: "http://example.com",
|
hops: [{ server: "http://example.com",
|
||||||
|
@ -902,7 +912,7 @@ function runTest() {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ pass: 1,
|
{ pass: 0,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
hops: [{ server: "http://example.com",
|
hops: [{ server: "http://example.com",
|
||||||
allowOrigin: origin
|
allowOrigin: origin
|
||||||
|
@ -918,6 +928,38 @@ function runTest() {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{ pass: 0,
|
||||||
|
method: "GET",
|
||||||
|
hops: [{ server: "http://example.com",
|
||||||
|
allowOrigin: origin
|
||||||
|
},
|
||||||
|
{ server: "http://test2.example.org:8000",
|
||||||
|
allowOrigin: origin
|
||||||
|
},
|
||||||
|
{ server: "http://sub2.xn--lt-uia.example.org",
|
||||||
|
allowOrigin: "*"
|
||||||
|
},
|
||||||
|
{ server: "http://sub1.test1.example.org",
|
||||||
|
allowOrigin: "*"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ pass: 1,
|
||||||
|
method: "GET",
|
||||||
|
hops: [{ server: "http://example.com",
|
||||||
|
allowOrigin: origin
|
||||||
|
},
|
||||||
|
{ server: "http://test2.example.org:8000",
|
||||||
|
allowOrigin: "*"
|
||||||
|
},
|
||||||
|
{ server: "http://sub2.xn--lt-uia.example.org",
|
||||||
|
allowOrigin: "*"
|
||||||
|
},
|
||||||
|
{ server: "http://sub1.test1.example.org",
|
||||||
|
allowOrigin: "*"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{ pass: 0,
|
{ pass: 0,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
hops: [{ server: "http://example.com",
|
hops: [{ server: "http://example.com",
|
||||||
|
@ -934,7 +976,7 @@ function runTest() {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ pass: 1,
|
{ pass: 0,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
hops: [{ server: "http://example.com",
|
hops: [{ server: "http://example.com",
|
||||||
allowOrigin: origin
|
allowOrigin: origin
|
||||||
|
|
Загрузка…
Ссылка в новой задаче