From 5addbcd61b21670b94705b9c7c0b248531df0fa0 Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Fri, 29 Nov 2024 11:45:38 +0000 Subject: [PATCH] LibWeb/CSP: Implement the manifest-src directive --- Libraries/LibWeb/CMakeLists.txt | 1 + .../Directives/DirectiveFactory.cpp | 4 ++ .../Directives/ManifestSourceDirective.cpp | 61 +++++++++++++++++++ .../Directives/ManifestSourceDirective.h | 28 +++++++++ Libraries/LibWeb/Forward.h | 1 + 5 files changed, 95 insertions(+) create mode 100644 Libraries/LibWeb/ContentSecurityPolicy/Directives/ManifestSourceDirective.cpp create mode 100644 Libraries/LibWeb/ContentSecurityPolicy/Directives/ManifestSourceDirective.h diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 87f4ebb79fb..59dd047e3cd 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -44,6 +44,7 @@ set(SOURCES ContentSecurityPolicy/Directives/FrameSourceDirective.cpp ContentSecurityPolicy/Directives/ImageSourceDirective.cpp ContentSecurityPolicy/Directives/KeywordSources.cpp + ContentSecurityPolicy/Directives/ManifestSourceDirective.cpp ContentSecurityPolicy/Directives/Names.cpp ContentSecurityPolicy/Directives/SerializedDirective.cpp ContentSecurityPolicy/Directives/SourceExpression.cpp diff --git a/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp b/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp index 95541e18f19..3ff78e8e4d7 100644 --- a/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp +++ b/Libraries/LibWeb/ContentSecurityPolicy/Directives/DirectiveFactory.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace Web::ContentSecurityPolicy::Directives { @@ -29,6 +30,9 @@ GC::Ref create_directive(GC::Heap& heap, String name, Vector if (name == Names::ImgSrc) return heap.allocate(move(name), move(value)); + if (name == Names::ManifestSrc) + return heap.allocate(move(name), move(value)); + return heap.allocate(move(name), move(value)); } diff --git a/Libraries/LibWeb/ContentSecurityPolicy/Directives/ManifestSourceDirective.cpp b/Libraries/LibWeb/ContentSecurityPolicy/Directives/ManifestSourceDirective.cpp new file mode 100644 index 00000000000..6c11eb3cf36 --- /dev/null +++ b/Libraries/LibWeb/ContentSecurityPolicy/Directives/ManifestSourceDirective.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Web::ContentSecurityPolicy::Directives { + +GC_DEFINE_ALLOCATOR(ManifestSourceDirective); + +ManifestSourceDirective::ManifestSourceDirective(String name, Vector value) + : Directive(move(name), move(value)) +{ +} + +// https://w3c.github.io/webappsec-csp/#manifest-src-pre-request +Directive::Result ManifestSourceDirective::pre_request_check(GC::Heap&, GC::Ref request, GC::Ref policy) const +{ + // 1. Let name be the result of executing § 6.8.1 Get the effective directive for request on request. + auto name = get_the_effective_directive_for_request(request); + + // 2. If the result of executing § 6.8.4 Should fetch directive execute on name, manifest-src and policy is "No", + // return "Allowed". + if (should_fetch_directive_execute(name, Names::ManifestSrc, policy) == ShouldExecute::No) + return Result::Allowed; + + // 3. If the result of executing § 6.7.2.5 Does request match source list? on request, this directive’s value, + // and policy, is "Does Not Match", return "Blocked". + if (does_request_match_source_list(request, value(), policy) == MatchResult::DoesNotMatch) + return Result::Blocked; + + // 4. Return "Allowed". + return Result::Allowed; +} + +// https://w3c.github.io/webappsec-csp/#manifest-src-post-request +Directive::Result ManifestSourceDirective::post_request_check(GC::Heap&, GC::Ref request, GC::Ref response, GC::Ref policy) const +{ + // 1. Let name be the result of executing § 6.8.1 Get the effective directive for request on request. + auto name = get_the_effective_directive_for_request(request); + + // 2. If the result of executing § 6.8.4 Should fetch directive execute on name, manifest-src and policy is "No", + // return "Allowed". + if (should_fetch_directive_execute(name, Names::ManifestSrc, policy) == ShouldExecute::No) + return Result::Allowed; + + // 3. If the result of executing § 6.7.2.6 Does response to request match source list? on response, request, this + // directive’s value, and policy, is "Does Not Match", return "Blocked". + if (does_response_match_source_list(response, request, value(), policy) == MatchResult::DoesNotMatch) + return Result::Blocked; + + // 4. Return "Allowed". + return Result::Allowed; +} + +} diff --git a/Libraries/LibWeb/ContentSecurityPolicy/Directives/ManifestSourceDirective.h b/Libraries/LibWeb/ContentSecurityPolicy/Directives/ManifestSourceDirective.h new file mode 100644 index 00000000000..50c00023f51 --- /dev/null +++ b/Libraries/LibWeb/ContentSecurityPolicy/Directives/ManifestSourceDirective.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::ContentSecurityPolicy::Directives { + +// https://w3c.github.io/webappsec-csp/#directive-manifest-src +class ManifestSourceDirective final : public Directive { + GC_CELL(ManifestSourceDirective, Directive) + GC_DECLARE_ALLOCATOR(ManifestSourceDirective); + +public: + virtual ~ManifestSourceDirective() = default; + + virtual Result pre_request_check(GC::Heap&, GC::Ref, GC::Ref) const override; + virtual Result post_request_check(GC::Heap&, GC::Ref, GC::Ref, GC::Ref) const override; + +private: + ManifestSourceDirective(String name, Vector value); +}; + +} diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index eb0414f4efb..be2516dec29 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -135,6 +135,7 @@ class Directive; class FontSourceDirective; class FrameSourceDirective; class ImageSourceDirective; +class ManifestSourceDirective; struct SerializedDirective; }