Bug 1139297 - Implement CSP upgrade-insecure-requests directive - cors changes (r=smaug)

--HG--
extra : rebase_source : f7faab7a9cceb962b4eaf4598f1a45fb0f73a756
This commit is contained in:
Christoph Kerschbaumer 2015-07-10 09:15:03 -07:00
Родитель 9ea890b6d7
Коммит d261954005
2 изменённых файлов: 82 добавлений и 0 удалений

Просмотреть файл

@ -820,6 +820,73 @@ nsCORSListenerProxy::OnRedirectVerifyCallback(nsresult result)
return NS_OK;
}
// Please note that the CSP directive 'upgrade-insecure-requests' relies
// on the promise that channels get updated from http: to https: before
// the channel fetches any data from the netwerk. Such channels should
// not be blocked by CORS and marked as cross origin requests. E.g.:
// toplevel page: https://www.example.com loads
// xhr: http://www.example.com/foo which gets updated to
// https://www.example.com/foo
// In such a case we should bail out of CORS and rely on the promise that
// nsHttpChannel::Connect() upgrades the request from http to https.
bool
CheckUpgradeInsecureRequestsPreventsCORS(nsIPrincipal* aRequestingPrincipal,
nsIChannel* aChannel)
{
nsCOMPtr<nsIURI> channelURI;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
NS_ENSURE_SUCCESS(rv, false);
bool isHttpScheme = false;
rv = channelURI->SchemeIs("http", &isHttpScheme);
NS_ENSURE_SUCCESS(rv, false);
// upgrade insecure requests is only applicable to http requests
if (!isHttpScheme) {
return false;
}
nsCOMPtr<nsIURI> principalURI;
rv = aRequestingPrincipal->GetURI(getter_AddRefs(principalURI));
NS_ENSURE_SUCCESS(rv, false);
// if the requestingPrincipal does not have a uri, there is nothing to do
if (!principalURI) {
return false;
}
nsCOMPtr<nsIURI>originalURI;
rv = aChannel->GetOriginalURI(getter_AddRefs(originalURI));
NS_ENSURE_SUCCESS(rv, false);
nsAutoCString principalHost, channelHost, origChannelHost;
// if we can not query a host from the uri, there is nothing to do
if (NS_FAILED(principalURI->GetAsciiHost(principalHost)) ||
NS_FAILED(channelURI->GetAsciiHost(channelHost)) ||
NS_FAILED(originalURI->GetAsciiHost(origChannelHost))) {
return false;
}
// if the hosts do not match, there is nothing to do
if (!principalHost.EqualsIgnoreCase(channelHost.get())) {
return false;
}
// also check that uri matches the one of the originalURI
if (!channelHost.EqualsIgnoreCase(origChannelHost.get())) {
return false;
}
nsCOMPtr<nsILoadInfo> loadInfo;
rv = aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
NS_ENSURE_SUCCESS(rv, false);
// lets see if the loadInfo indicates that the request will
// be upgraded before fetching any data from the netwerk.
return loadInfo->GetUpgradeInsecureRequests();
}
nsresult
nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel,
DataURIHandling aAllowDataURI)
@ -877,6 +944,17 @@ nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel,
return NS_OK;
}
// if the CSP directive 'upgrade-insecure-requests' is used then we should
// not incorrectly require CORS if the only difference of a subresource
// request and the main page is the scheme.
// e.g. toplevel page: https://www.example.com loads
// xhr: http://www.example.com/somefoo,
// then the xhr request will be upgraded to https before it fetches any data
// from the netwerk, hence we shouldn't require CORS in that specific case.
if (CheckUpgradeInsecureRequestsPreventsCORS(mRequestingPrincipal, aChannel)) {
return NS_OK;
}
// It's a cross site load
mHasBeenCrossSite = true;

Просмотреть файл

@ -83,6 +83,10 @@ private:
nsCOMPtr<nsINetworkInterceptController> mInterceptController;
bool mWithCredentials;
bool mRequestApproved;
// Please note that the member variable mHasBeenCrossSite may rely on the
// promise that the CSP directive 'upgrade-insecure-requests' upgrades
// an http: request to https: in nsHttpChannel::Connect() and hence
// a request might not be marked as cross site request based on that promise.
bool mHasBeenCrossSite;
bool mIsPreflight;
#ifdef DEBUG