зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1189668 - Check CSP before completing channel interception. r=ehsan
This commit is contained in:
Родитель
73f8a27244
Коммит
15e1767e1c
|
@ -53,6 +53,8 @@ public:
|
|||
void
|
||||
GetScriptURL(nsString& aURL) const;
|
||||
|
||||
const ServiceWorkerInfo* Info() const { return mInfo; }
|
||||
|
||||
void
|
||||
DispatchStateChange(ServiceWorkerState aState)
|
||||
{
|
||||
|
|
|
@ -6,15 +6,18 @@
|
|||
|
||||
#include "ServiceWorkerEvents.h"
|
||||
#include "ServiceWorkerClient.h"
|
||||
#include "ServiceWorkerManager.h"
|
||||
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsINetworkInterceptController.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsQueryObject.h"
|
||||
|
||||
|
@ -104,13 +107,17 @@ namespace {
|
|||
class FinishResponse final : public nsRunnable
|
||||
{
|
||||
nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel;
|
||||
nsMainThreadPtrHandle<ServiceWorker> mServiceWorker;
|
||||
nsRefPtr<InternalResponse> mInternalResponse;
|
||||
ChannelInfo mWorkerChannelInfo;
|
||||
|
||||
public:
|
||||
FinishResponse(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
|
||||
nsMainThreadPtrHandle<ServiceWorker> aServiceWorker,
|
||||
InternalResponse* aInternalResponse,
|
||||
const ChannelInfo& aWorkerChannelInfo)
|
||||
: mChannel(aChannel)
|
||||
, mServiceWorker(aServiceWorker)
|
||||
, mInternalResponse(aInternalResponse)
|
||||
, mWorkerChannelInfo(aWorkerChannelInfo)
|
||||
{
|
||||
|
@ -121,6 +128,11 @@ public:
|
|||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
if (!CSPPermitsResponse()) {
|
||||
mChannel->Cancel(NS_ERROR_CONTENT_BLOCKED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ChannelInfo channelInfo;
|
||||
if (mInternalResponse->GetChannelInfo().IsInitialized()) {
|
||||
channelInfo = mInternalResponse->GetChannelInfo();
|
||||
|
@ -147,6 +159,34 @@ public:
|
|||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to finish synthesized response");
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool CSPPermitsResponse()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsAutoCString url;
|
||||
mInternalResponse->GetUnfilteredUrl(url);
|
||||
if (url.IsEmpty()) {
|
||||
// Synthetic response. The buck stops at the worker script.
|
||||
url = mServiceWorker->Info()->ScriptSpec();
|
||||
}
|
||||
rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsCOMPtr<nsIChannel> underlyingChannel;
|
||||
rv = mChannel->GetChannel(getter_AddRefs(underlyingChannel));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
NS_ENSURE_TRUE(underlyingChannel, false);
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = underlyingChannel->GetLoadInfo();
|
||||
|
||||
int16_t decision = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(loadInfo->InternalContentPolicyType(), uri, loadInfo->LoadingPrincipal(),
|
||||
loadInfo->LoadingNode(), EmptyCString(), nullptr, &decision);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
return decision == nsIContentPolicy::ACCEPT;
|
||||
}
|
||||
};
|
||||
|
||||
class RespondWithHandler final : public PromiseNativeHandler
|
||||
|
@ -183,13 +223,16 @@ private:
|
|||
struct RespondWithClosure
|
||||
{
|
||||
nsMainThreadPtrHandle<nsIInterceptedChannel> mInterceptedChannel;
|
||||
nsMainThreadPtrHandle<ServiceWorker> mServiceWorker;
|
||||
nsRefPtr<InternalResponse> mInternalResponse;
|
||||
ChannelInfo mWorkerChannelInfo;
|
||||
|
||||
RespondWithClosure(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
|
||||
nsMainThreadPtrHandle<ServiceWorker>& aServiceWorker,
|
||||
InternalResponse* aInternalResponse,
|
||||
const ChannelInfo& aWorkerChannelInfo)
|
||||
: mInterceptedChannel(aChannel)
|
||||
, mServiceWorker(aServiceWorker)
|
||||
, mInternalResponse(aInternalResponse)
|
||||
, mWorkerChannelInfo(aWorkerChannelInfo)
|
||||
{
|
||||
|
@ -202,6 +245,7 @@ void RespondWithCopyComplete(void* aClosure, nsresult aStatus)
|
|||
nsCOMPtr<nsIRunnable> event;
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
event = new FinishResponse(data->mInterceptedChannel,
|
||||
data->mServiceWorker,
|
||||
data->mInternalResponse,
|
||||
data->mWorkerChannelInfo);
|
||||
} else {
|
||||
|
@ -307,7 +351,7 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu
|
|||
}
|
||||
|
||||
nsAutoPtr<RespondWithClosure> closure(
|
||||
new RespondWithClosure(mInterceptedChannel, ir, worker->GetChannelInfo()));
|
||||
new RespondWithClosure(mInterceptedChannel, mServiceWorker, ir, worker->GetChannelInfo()));
|
||||
nsCOMPtr<nsIInputStream> body;
|
||||
ir->GetUnfilteredBody(getter_AddRefs(body));
|
||||
// Errors and redirects may not have a body.
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[fetch-csp.https.html]
|
||||
type: testharness
|
||||
[Verify CSP control of fetch() in a Service Worker]
|
||||
expected: FAIL
|
||||
|
|
@ -6,12 +6,6 @@ var host_info = get_host_info();
|
|||
var results = '';
|
||||
var port = undefined;
|
||||
|
||||
var meta = document.createElement('meta');
|
||||
meta.setAttribute('http-equiv', 'Content-Security-Policy');
|
||||
meta.setAttribute('content', 'img-src ' + host_info['HTTPS_ORIGIN'] +
|
||||
'; script-src \'unsafe-inline\'');
|
||||
document.head.appendChild(meta);
|
||||
|
||||
function test1() {
|
||||
var img = document.createElement('img');
|
||||
document.body.appendChild(img);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Content-Security-Policy: img-src https://{{host}}:{{ports[https][0]}}
|
Загрузка…
Ссылка в новой задаче