Title: [287414] trunk
Revision
287414
Author
[email protected]
Date
2021-12-23 15:09:43 -0800 (Thu, 23 Dec 2021)

Log Message

Check allowed network hosts list when we schedule the load in the network process
https://bugs.webkit.org/show_bug.cgi?id=234543
<rdar://83501315>

Patch by Matt Woodrow <[email protected]> on 2021-12-23
Reviewed by Alex Christensen.

The check for WKWebViewConfiguration._allowedNetworkHost previously happened before the check to see if
the given ResourceRequest would directly from an archive.
This moves to the allowed network host list check to happen when we schedule the network request, and thus
allows subresources cached within an archive to load, even if their original URL would be blocked.
Source/WebCore:

New test LoadWebArchive.DisallowedNetworkHosts added.

* loader/ResourceLoadNotifier.cpp:
(WebCore::ResourceLoadNotifier::dispatchWillSendRequest):
* loader/ResourceLoadNotifier.h:
(WebCore::ResourceLoadNotifier::isInitialRequestIdentifier):

Source/WebKit:

We also need to check when redirecting to prevent an allowed domain from redirecting to a forbidden domain.
This also makes it so that WKWebViewConfiguration._loadsSubresources only prevents
subresource loads that would touch the network, so we can't use WKURLSchemeHandler to test it any more.
That's fine, since the two users of the SPI only load URLs from the network.

New test LoadWebArchive.DisallowedNetworkHosts added.

* WebProcess/Network/WebLoaderStrategy.cpp:
(WebKit::WebLoaderStrategy::scheduleLoadFromNetworkProcess):
* WebProcess/Network/WebResourceLoader.cpp:
(WebKit::WebResourceLoader::willSendRequest):

Tools:

New test LoadWebArchive.DisallowedNetworkHosts added.

* TestWebKitAPI/Tests/mac/LoadWebArchive.mm:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (287413 => 287414)


--- trunk/Source/WebCore/ChangeLog	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Source/WebCore/ChangeLog	2021-12-23 23:09:43 UTC (rev 287414)
@@ -1,3 +1,23 @@
+2021-12-23  Matt Woodrow  <[email protected]>
+
+        Check allowed network hosts list when we schedule the load in the network process
+        https://bugs.webkit.org/show_bug.cgi?id=234543
+        <rdar://83501315>
+
+        Reviewed by Alex Christensen.
+
+        The check for WKWebViewConfiguration._allowedNetworkHost previously happened before the check to see if
+        the given ResourceRequest would directly from an archive.
+        This moves to the allowed network host list check to happen when we schedule the network request, and thus
+        allows subresources cached within an archive to load, even if their original URL would be blocked.
+
+        New test LoadWebArchive.DisallowedNetworkHosts added.
+
+        * loader/ResourceLoadNotifier.cpp:
+        (WebCore::ResourceLoadNotifier::dispatchWillSendRequest):
+        * loader/ResourceLoadNotifier.h:
+        (WebCore::ResourceLoadNotifier::isInitialRequestIdentifier):
+
 2021-12-23  Brady Eidson  <[email protected]>
 
         Add WTF::UUID class which is natively a 128-bit integer

Modified: trunk/Source/WebCore/loader/ResourceLoadNotifier.cpp (287413 => 287414)


--- trunk/Source/WebCore/loader/ResourceLoadNotifier.cpp	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Source/WebCore/loader/ResourceLoadNotifier.cpp	2021-12-23 23:09:43 UTC (rev 287414)
@@ -137,12 +137,6 @@
     Ref<Frame> protectedFrame(m_frame);
     m_frame.loader().client().dispatchWillSendRequest(loader, identifier, request, redirectResponse);
 
-    if (auto* page = m_frame.page()) {
-        auto mainFrameMainResource = m_frame.isMainFrame() && m_initialRequestIdentifier == identifier ? MainFrameMainResource::Yes : MainFrameMainResource::No;
-        if (!page->allowsLoadFromURL(request.url(), mainFrameMainResource))
-            request = { };
-    }
-
     // If the URL changed, then we want to put that new URL in the "did tell client" set too.
     if (!request.isNull() && oldRequestURL != request.url().string() && m_frame.loader().documentLoader())
         m_frame.loader().documentLoader()->didTellClientAboutLoad(request.url().string());

Modified: trunk/Source/WebCore/loader/ResourceLoadNotifier.h (287413 => 287414)


--- trunk/Source/WebCore/loader/ResourceLoadNotifier.h	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Source/WebCore/loader/ResourceLoadNotifier.h	2021-12-23 23:09:43 UTC (rev 287414)
@@ -68,6 +68,11 @@
 
     void sendRemainingDelegateMessages(DocumentLoader*, ResourceLoaderIdentifier, const ResourceRequest&, const ResourceResponse&, const uint8_t* data, int dataLength, int encodedDataLength, const ResourceError&);
 
+    bool isInitialRequestIdentifier(ResourceLoaderIdentifier identifier)
+    {
+        return m_initialRequestIdentifier == identifier;
+    }
+
 private:
     Frame& m_frame;
     std::optional<ResourceLoaderIdentifier> m_initialRequestIdentifier;

Modified: trunk/Source/WebCore/loader/ResourceLoader.h (287413 => 287414)


--- trunk/Source/WebCore/loader/ResourceLoader.h	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Source/WebCore/loader/ResourceLoader.h	2021-12-23 23:09:43 UTC (rev 287414)
@@ -85,7 +85,7 @@
     WEBCORE_EXPORT void start();
     WEBCORE_EXPORT void cancel(const ResourceError&);
     WEBCORE_EXPORT ResourceError cancelledError();
-    ResourceError blockedError();
+    WEBCORE_EXPORT ResourceError blockedError();
     ResourceError blockedByContentBlockerError();
     ResourceError cannotShowURLError();
     

Modified: trunk/Source/WebKit/ChangeLog (287413 => 287414)


--- trunk/Source/WebKit/ChangeLog	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Source/WebKit/ChangeLog	2021-12-23 23:09:43 UTC (rev 287414)
@@ -1,3 +1,27 @@
+2021-12-23  Matt Woodrow  <[email protected]>
+
+        Check allowed network hosts list when we schedule the load in the network process
+        https://bugs.webkit.org/show_bug.cgi?id=234543
+        <rdar://83501315>
+
+        Reviewed by Alex Christensen.
+
+        The check for WKWebViewConfiguration._allowedNetworkHost previously happened before the check to see if
+        the given ResourceRequest would directly from an archive.
+        This moves to the allowed network host list check to happen when we schedule the network request, and thus
+        allows subresources cached within an archive to load, even if their original URL would be blocked.
+        We also need to check when redirecting to prevent an allowed domain from redirecting to a forbidden domain.
+        This also makes it so that WKWebViewConfiguration._loadsSubresources only prevents
+        subresource loads that would touch the network, so we can't use WKURLSchemeHandler to test it any more.
+        That's fine, since the two users of the SPI only load URLs from the network.
+
+        New test LoadWebArchive.DisallowedNetworkHosts added.
+
+        * WebProcess/Network/WebLoaderStrategy.cpp:
+        (WebKit::WebLoaderStrategy::scheduleLoadFromNetworkProcess):
+        * WebProcess/Network/WebResourceLoader.cpp:
+        (WebKit::WebResourceLoader::willSendRequest):
+
 2021-12-23  Brent Fulgham  <[email protected]>
 
         Allow a necessary syscall in the WebContent sandbox

Modified: trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp (287413 => 287414)


--- trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp	2021-12-23 23:09:43 UTC (rev 287414)
@@ -299,6 +299,21 @@
     auto identifier = resourceLoader.identifier();
     ASSERT(identifier);
 
+    auto* frame = resourceLoader.frame();
+
+    if (auto* page = frame ? frame->page() : nullptr) {
+        auto mainFrameMainResource = frame->isMainFrame()
+            && resourceLoader.frameLoader()
+            && resourceLoader.frameLoader()->notifier().isInitialRequestIdentifier(identifier)
+            ? MainFrameMainResource::Yes : MainFrameMainResource::No;
+        if (!page->allowsLoadFromURL(request.url(), mainFrameMainResource)) {
+            RunLoop::main().dispatch([resourceLoader = Ref { resourceLoader }] {
+                resourceLoader->didFail(resourceLoader->blockedError());
+            });
+            return;
+        }
+    }
+
     ContentSniffingPolicy contentSniffingPolicy = resourceLoader.shouldSniffContent() ? ContentSniffingPolicy::SniffContent : ContentSniffingPolicy::DoNotSniffContent;
     ContentEncodingSniffingPolicy contentEncodingSniffingPolicy = resourceLoader.shouldSniffContentEncoding() ? ContentEncodingSniffingPolicy::Sniff : ContentEncodingSniffingPolicy::DoNotSniff;
     StoredCredentialsPolicy storedCredentialsPolicy = resourceLoader.shouldUseCredentialStorage() ? StoredCredentialsPolicy::Use : StoredCredentialsPolicy::DoNotUse;
@@ -305,8 +320,6 @@
 
     LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, url '%s' will be scheduled with the NetworkProcess with priority %d, storedCredentialsPolicy %i", resourceLoader.url().string().latin1().data(), static_cast<int>(resourceLoader.request().priority()), (int)storedCredentialsPolicy);
 
-    auto* frame = resourceLoader.frame();
-
     NetworkResourceLoadParameters loadParameters;
     loadParameters.identifier = identifier;
     loadParameters.webPageProxyID = trackingParameters.webPageProxyID;

Modified: trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp (287413 => 287414)


--- trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp	2021-12-23 23:09:43 UTC (rev 287414)
@@ -106,6 +106,17 @@
         WEBRESOURCELOADER_RELEASE_LOG("willSendRequest: exiting early because maybeLoadFallbackForRedirect returned false");
         return;
     }
+    
+    if (auto* frame = m_coreLoader->frame()) {
+        if (auto* page = frame->page()) {
+            auto mainFrameMainResource = frame->isMainFrame()
+                && m_coreLoader->frameLoader()
+                && m_coreLoader->frameLoader()->notifier().isInitialRequestIdentifier(m_coreLoader->identifier())
+                ? MainFrameMainResource::Yes : MainFrameMainResource::No;
+            if (!page->allowsLoadFromURL(proposedRequest.url(), mainFrameMainResource))
+                proposedRequest = { };
+        }
+    }
 
     m_coreLoader->willSendRequest(WTFMove(proposedRequest), redirectResponse, [this, protectedThis = WTFMove(protectedThis)](ResourceRequest&& request) {
         if (!m_coreLoader || !m_coreLoader->identifier()) {

Modified: trunk/Tools/ChangeLog (287413 => 287414)


--- trunk/Tools/ChangeLog	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Tools/ChangeLog	2021-12-23 23:09:43 UTC (rev 287414)
@@ -1,3 +1,21 @@
+2021-12-23  Matt Woodrow  <[email protected]>
+
+        Check allowed network hosts list when we schedule the load in the network process
+        https://bugs.webkit.org/show_bug.cgi?id=234543
+        <rdar://83501315>
+
+        Reviewed by Alex Christensen.
+
+        The check for WKWebViewConfiguration._allowedNetworkHost previously happened before the check to see if
+        the given ResourceRequest would directly from an archive.
+        This moves to the allowed network host list check to happen when we schedule the network request, and thus
+        allows subresources cached within an archive to load, even if their original URL would be blocked.
+
+        New test LoadWebArchive.DisallowedNetworkHosts added.
+
+        * TestWebKitAPI/Tests/mac/LoadWebArchive.mm:
+        (TestWebKitAPI::TEST):
+
 2021-12-23  Brady Eidson  <[email protected]>
 
         Add WTF::UUID class which is natively a 128-bit integer

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm (287413 => 287414)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm	2021-12-23 23:09:43 UTC (rev 287414)
@@ -1255,36 +1255,43 @@
     EXPECT_EQ(server127001.totalRequests(), 2u);
 }
 
-TEST(URLSchemeHandler, LoadsSubresources)
+static void serverLoop(const TestWebKitAPI::Connection& connection, bool& loadedImage, bool& loadedIFrame)
 {
+    using namespace TestWebKitAPI;
+    connection.receiveHTTPRequest([&, connection] (Vector<char>&& request) {
+        auto path = HTTPServer::parsePath(request);
+        auto sendReply = [&, connection] (const HTTPResponse& response) {
+            connection.send(response.serialize(), [&, connection] {
+                serverLoop(connection, loadedImage, loadedIFrame);
+            });
+        };
+        if (path == "/main.html")
+            sendReply({ { { "Content-Type", "text/html" } }, "<img src=''></img><iframe src=''></iframe>" });
+        else if (path == "/imgsrc") {
+            loadedImage = true;
+            sendReply({ "image content" });
+        } else if (path == "/iframesrc") {
+            loadedIFrame = true;
+            sendReply({ "iframe content" });
+        } else
+            ASSERT_NOT_REACHED();
+    });
+}
+
+TEST(WKWebViewConfiguration, LoadsSubresources)
+{
     bool loadedImage = false;
     bool loadedIFrame = false;
 
-    auto handler = adoptNS([TestURLSchemeHandler new]);
-
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"test"];
 
-    [handler setStartURLSchemeTaskHandler:[&](WKWebView *, id<WKURLSchemeTask> task) {
-        NSString *response = nil;
-        if ([task.request.URL.path isEqualToString:@"/main.html"])
-            response = @"<img src=''></img><iframe src=''></iframe>";
-        else if ([task.request.URL.path isEqualToString:@"/imgsrc"]) {
-            response = @"image content";
-            loadedImage = true;
-        } else if ([task.request.URL.path isEqualToString:@"/iframesrc"]) {
-            response = @"iframe content";
-            loadedIFrame = true;
-        } else
-            ASSERT_NOT_REACHED();
-        [task didReceiveResponse:adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:response.length textEncodingName:nil]).get()];
-        [task didReceiveData:[response dataUsingEncoding:NSUTF8StringEncoding]];
-        [task didFinish];
-    }];
-    
+    TestWebKitAPI::HTTPServer server([&] (const TestWebKitAPI::Connection& connection) {
+        serverLoop(connection, loadedIFrame, loadedImage);
+    });
+
     {
         auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
-        [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test://host1/main.html"]]];
+        [webView loadRequest:server.request("/main.html")];
         TestWebKitAPI::Util::run(&loadedImage);
         TestWebKitAPI::Util::run(&loadedIFrame);
     }
@@ -1297,7 +1304,7 @@
         auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
         auto delegate = adoptNS([TestNavigationDelegate new]);
         webView.get().navigationDelegate = delegate.get();
-        [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test://host1/main.html"]]];
+        [webView loadRequest:server.request("/main.html")];
         [delegate waitForDidFinishNavigation];
         TestWebKitAPI::Util::spinRunLoop(100);
         EXPECT_FALSE(loadedIFrame);

Modified: trunk/Tools/TestWebKitAPI/Tests/mac/LoadWebArchive.mm (287413 => 287414)


--- trunk/Tools/TestWebKitAPI/Tests/mac/LoadWebArchive.mm	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Tools/TestWebKitAPI/Tests/mac/LoadWebArchive.mm	2021-12-23 23:09:43 UTC (rev 287414)
@@ -33,6 +33,7 @@
 #import <WebKit/WKDragDestinationAction.h>
 #import <WebKit/WKNavigationPrivate.h>
 #import <WebKit/WKWebView.h>
+#import <WebKit/WKWebViewConfigurationPrivate.h>
 #import <WebKit/WKWebViewPrivate.h>
 #import <wtf/RetainPtr.h>
 #import <wtf/text/WTFString.h>
@@ -204,7 +205,7 @@
     EXPECT_WK_STREQ(finalURL, "");
 }
 
-TEST(LoadWebArchive, HTTPSUpgrade)
+static NSData* constructArchive()
 {
     NSString *js = @"alert('loaded http subresource successfully')";
     auto response = adoptNS([[NSURLResponse alloc] initWithURL:[NSURL URLWithString:@"http://download/script.js"] MIMEType:@"application/_javascript_" expectedContentLength:js.length textEncodingName:@"utf-8"]);
@@ -226,11 +227,28 @@
             @"WebResourceURL": @"http://download/script.js",
         }]
     };
-    NSData *data = "" dataFromPropertyList:archive format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil];
+    return [NSPropertyListSerialization dataFromPropertyList:archive format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil];
+}
 
+TEST(LoadWebArchive, HTTPSUpgrade)
+{
+    NSData *data = ""
+
     auto webView = adoptNS([WKWebView new]);
     [webView loadData:data MIMEType:@"application/x-webarchive" characterEncodingName:@"utf-8" baseURL:[NSURL URLWithString:@"http://download/"]];
     EXPECT_WK_STREQ([webView _test_waitForAlert], "loaded http subresource successfully");
 }
 
+TEST(LoadWebArchive, DisallowedNetworkHosts)
+{
+    NSData *data = ""
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    configuration.get()._allowedNetworkHosts = [NSSet set];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView loadData:data MIMEType:@"application/x-webarchive" characterEncodingName:@"utf-8" baseURL:[NSURL URLWithString:@"http://download/"]];
+    EXPECT_WK_STREQ([webView _test_waitForAlert], "loaded http subresource successfully");
+}
+
 } // namespace TestWebKitAPI

Modified: trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h (287413 => 287414)


--- trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h	2021-12-23 23:09:43 UTC (rev 287414)
@@ -117,7 +117,7 @@
     HTTPResponse& operator=(HTTPResponse&&) = default;
 
     enum class IncludeContentLength : bool { No, Yes };
-    Vector<uint8_t> serialize(IncludeContentLength = IncludeContentLength::Yes);
+    Vector<uint8_t> serialize(IncludeContentLength = IncludeContentLength::Yes) const;
     static Vector<uint8_t> bodyFromString(const String&);
 
     unsigned statusCode { 200 };

Modified: trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm (287413 => 287414)


--- trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm	2021-12-23 22:00:33 UTC (rev 287413)
+++ trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm	2021-12-23 23:09:43 UTC (rev 287414)
@@ -483,7 +483,7 @@
     return vector;
 }
 
-Vector<uint8_t> HTTPResponse::serialize(IncludeContentLength includeContentLength)
+Vector<uint8_t> HTTPResponse::serialize(IncludeContentLength includeContentLength) const
 {
     StringBuilder responseBuilder;
     responseBuilder.append("HTTP/1.1 ", statusCode, ' ', statusText(statusCode), "\r\n");
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to