Title: [228231] trunk
Revision
228231
Author
dba...@webkit.org
Date
2018-02-07 10:56:02 -0800 (Wed, 07 Feb 2018)

Log Message

Log error when authentication challenge is blocked due to an insecure request
https://bugs.webkit.org/show_bug.cgi?id=182358

Reviewed by Andy Estes.

Source/WebCore:

Emit an error message to Web Inspector console that explains why an authentication
challenge was blocked so that a developer can fix up their site.

Tests: http/tests/security/mixedContent/insecure-basic-auth-image.https.html
       http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https.html
       http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https.html

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::receivedFirstData): Log to the console an error message
if the document we are loading was forbidden from prompting for credentials.
Also removed duplicate assertion to ensure document is non-null and update
call to LinkLoader::loadLinksFromHeader() to use local variable to access
the document we are loading instead of asking the frame for it, again.
(WebCore::FrameLoader::reportAuthenticationChallengeBlocked): Added.
* loader/FrameLoader.h:

* loader/ResourceLoader.cpp:
(WebCore::ResourceLoader::init):
(WebCore::ResourceLoader::willSendRequestInternal):
Track the decision to forbid asking for credentials due to Fetch spec. requirements (m_canAskClientForCredentials)
independently from the decision to forbid them due to making an insecure request (m_wasInsecureRequestSeen)
so that we know the reason why we blocked asking for credentials when we receive an authentication challenge.

(WebCore::ResourceLoader::didBlockAuthenticationChallenge): Added.
(WebCore::ResourceLoader::isAllowedToAskUserForCredentials const): Modified code now that we track
whether we have seen an insecure request so far independently from decision to forbid prompting for
credentials due to a Fetch spec. requirement.

(WebCore::ResourceLoader::didReceiveAuthenticationChallenge):
Store a bit whether we have seen an insecure request when loading the resource so far. Disallow
asking for credentials if we have seen an insecure request so far. Once we receive a response

* loader/ResourceLoader.h:
(WebCore::ResourceLoader::wasAuthenticationChallengeBlocked const): Added.
(WebCore::ResourceLoader::wasInsecureRequestSeen const): Added.

Source/WebKit:

Have network process notify the web process when it blocks an authentication challenge.

* NetworkProcess/NetworkLoad.cpp:
(WebKit::NetworkLoad::completeAuthenticationChallenge):
* NetworkProcess/NetworkLoadClient.h:
(WebKit::NetworkLoadClient::didBlockAuthenticationChallenge):
* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::didBlockAuthenticationChallenge):
* NetworkProcess/NetworkResourceLoader.h:
* WebProcess/Network/WebResourceLoader.cpp:
(WebKit::WebResourceLoader::didBlockAuthenticationChallenge):
* WebProcess/Network/WebResourceLoader.h:
* WebProcess/Network/WebResourceLoader.messages.in:

LayoutTests:

Add more tests and update expected results of existing tests now that we emit console messages.

Also fixed a typo in LayoutTests/http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html
so that it tests what it actually claims to test and made the test programmatically load the image
to avoid output flakiness caused by the preload scanner preloading it. The preload scanner performs
mixed content checks and this can cause duplicate mixed content warnings in the test output.

* http/tests/security/mixedContent/insecure-basic-auth-image.https-expected.txt: Added.
* http/tests/security/mixedContent/insecure-basic-auth-image.https.html: Copied from LayoutTests/http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html.
* http/tests/security/mixedContent/insecure-download-redirects-to-basic-auth-secure-download.https-expected.txt:
* http/tests/security/mixedContent/insecure-image-redirects-to-basic-auth-secure-image-expected.txt:
* http/tests/security/mixedContent/resources/subresource/protected-page.php: Added.
* http/tests/security/mixedContent/resources/subresource2/protected-image.php: Added.
* http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https-expected.txt: Added.
* http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https.html: Added.
* http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https-expected.txt: Added.
* http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https.html: Added.
* http/tests/security/mixedContent/secure-redirect-to-insecure-redirect-to-basic-auth-secure-image.https-expected.txt:
* http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https-expected.txt:
* http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (228230 => 228231)


--- trunk/LayoutTests/ChangeLog	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/LayoutTests/ChangeLog	2018-02-07 18:56:02 UTC (rev 228231)
@@ -1,3 +1,31 @@
+2018-02-07  Daniel Bates  <daba...@apple.com>
+
+        Log error when authentication challenge is blocked due to an insecure request
+        https://bugs.webkit.org/show_bug.cgi?id=182358
+
+        Reviewed by Andy Estes.
+
+        Add more tests and update expected results of existing tests now that we emit console messages.
+
+        Also fixed a typo in LayoutTests/http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html
+        so that it tests what it actually claims to test and made the test programmatically load the image
+        to avoid output flakiness caused by the preload scanner preloading it. The preload scanner performs
+        mixed content checks and this can cause duplicate mixed content warnings in the test output.
+
+        * http/tests/security/mixedContent/insecure-basic-auth-image.https-expected.txt: Added.
+        * http/tests/security/mixedContent/insecure-basic-auth-image.https.html: Copied from LayoutTests/http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html.
+        * http/tests/security/mixedContent/insecure-download-redirects-to-basic-auth-secure-download.https-expected.txt:
+        * http/tests/security/mixedContent/insecure-image-redirects-to-basic-auth-secure-image-expected.txt:
+        * http/tests/security/mixedContent/resources/subresource/protected-page.php: Added.
+        * http/tests/security/mixedContent/resources/subresource2/protected-image.php: Added.
+        * http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https-expected.txt: Added.
+        * http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https.html: Added.
+        * http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https-expected.txt: Added.
+        * http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https.html: Added.
+        * http/tests/security/mixedContent/secure-redirect-to-insecure-redirect-to-basic-auth-secure-image.https-expected.txt:
+        * http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https-expected.txt:
+        * http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html:
+
 2018-02-07  Chris Dumez  <cdu...@apple.com>
 
         IndexedDB in service workers is using a memory backed store

Added: trunk/LayoutTests/http/tests/security/mixedContent/insecure-basic-auth-image.https-expected.txt (0 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/insecure-basic-auth-image.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/mixedContent/insecure-basic-auth-image.https-expected.txt	2018-02-07 18:56:02 UTC (rev 228231)
@@ -0,0 +1,13 @@
+CONSOLE MESSAGE: line 33: The page at https://127.0.0.1:8443/security/mixedContent/insecure-basic-auth-image.https.html was allowed to display insecure content from http://localhost:8000/security/mixedContent/resources/subresource2/protected-image.php.
+
+CONSOLE MESSAGE: Blocked http://localhost:8000/security/mixedContent/resources/subresource2/protected-image.php from asking for credentials because it is insecure content.
+Tests that we do not ask for credentials when loading an insecure image that requires basic authentication.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS did not load image.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/security/mixedContent/insecure-basic-auth-image.https.html (0 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/insecure-basic-auth-image.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/mixedContent/insecure-basic-auth-image.https.html	2018-02-07 18:56:02 UTC (rev 228231)
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+if (window.testRunner) {
+    testRunner.setHandlesAuthenticationChallenges(true);
+    testRunner.setAuthenticationUsername("testUser");
+    testRunner.setAuthenticationPassword("testPassword");
+}
+
+window.jsTestIsAsync = true;
+
+function pass()
+{
+    testPassed("did not load image.");
+    finishJSTest();
+}
+
+function fail()
+{
+    testFailed("did load image.");
+    finishJSTest();
+}
+
+function runTest()
+{
+    // Load the image programmatically instead of declaratively to avoid output flakiness caused by
+    // the preload scanner performing mixed content checks as part of preloading the image.
+    let image = new Image;
+    image._onload_ = fail;
+    image._onerror_ = pass;
+    image.src = ""
+    document.body.appendChild(image);
+}
+
+window._onload_ = runTest;
+</script>
+</head>
+<body>
+<script>
+description("Tests that we do not ask for credentials when loading an insecure image that requires basic authentication.");
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/http/tests/security/mixedContent/insecure-download-redirects-to-basic-auth-secure-download.https-expected.txt (228230 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/insecure-download-redirects-to-basic-auth-secure-download.https-expected.txt	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/LayoutTests/http/tests/security/mixedContent/insecure-download-redirects-to-basic-auth-secure-download.https-expected.txt	2018-02-07 18:56:02 UTC (rev 228231)
@@ -1,2 +1,4 @@
+CONSOLE MESSAGE: Blocked https://localhost:8443/security/mixedContent/resources/subresource/protected-pdf.php from asking for credentials because it was loaded via an insecure redirect from http://127.0.0.1:8080/resources/redirect.php?url=""
+CONSOLE MESSAGE: Blocked https://localhost:8443/security/mixedContent/resources/subresource/protected-pdf.php from asking for credentials because it was navigated to from a secure page or went through an insecure redirect.
 ALERT: Unauthorized
 

Modified: trunk/LayoutTests/http/tests/security/mixedContent/insecure-image-redirects-to-basic-auth-secure-image-expected.txt (228230 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/insecure-image-redirects-to-basic-auth-secure-image-expected.txt	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/LayoutTests/http/tests/security/mixedContent/insecure-image-redirects-to-basic-auth-secure-image-expected.txt	2018-02-07 18:56:02 UTC (rev 228231)
@@ -1,5 +1,6 @@
 CONSOLE MESSAGE: line 17: The page at https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-image-redirects-to-basic-auth-secure-image.html was allowed to display insecure content from http://127.0.0.1:8080/resources/redirect.php?url=""
 
+CONSOLE MESSAGE: Blocked https://localhost:8443/security/mixedContent/resources/subresource/protected-image.php from asking for credentials because it was loaded via an insecure redirect from http://127.0.0.1:8080/resources/redirect.php?url=""
 This test opens a new window to a secure page that loads an insecure image that redirects to a secure image guarded by basic authentication. The secure image should be blocked because it requires credentials and was loaded via an insecure redirect.
 
 PASS did not load image.

Added: trunk/LayoutTests/http/tests/security/mixedContent/resources/subresource/protected-page.php (0 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/resources/subresource/protected-page.php	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/mixedContent/resources/subresource/protected-page.php	2018-02-07 18:56:02 UTC (rev 228231)
@@ -0,0 +1,23 @@
+<?php
+header("Cache-Control: no-store");
+header("Connection: close");
+if (!isset($_SERVER["PHP_AUTH_USER"])) {
+    header("WWW-authenticate: Basic realm=\"" . $_SERVER["REQUEST_URI"] . "\"");
+    header("HTTP/1.0 401 Unauthorized");
+}
+header("Content-Type: text/html");
+?>
+<!DOCTYPE html>
+<html>
+<body>
+<p><?php if (isset($_SERVER["PHP_AUTH_USER"])) { ?>
+Authenticated with username <?php echo htmlspecialchars($_SERVER["PHP_AUTH_USER"]); ?>.
+<?php } else { ?>
+Unauthorized.
+<?php } ?></p>
+<script>
+if (window.testRunner)
+    testRunner.notifyDone();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/security/mixedContent/resources/subresource2/protected-image.php (0 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/resources/subresource2/protected-image.php	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/mixedContent/resources/subresource2/protected-image.php	2018-02-07 18:56:02 UTC (rev 228231)
@@ -0,0 +1,12 @@
+<?php
+header("Cache-Control: no-store");
+header("Connection: close");
+if (!isset($_SERVER["PHP_AUTH_USER"])) {
+    header("WWW-authenticate: Basic realm=\"" . $_SERVER["REQUEST_URI"] . "\"");
+    header("HTTP/1.0 401 Unauthorized");
+    exit;
+}
+// Authenticated
+header("Content-Type: image/png");
+echo file_get_contents("../../../contentSecurityPolicy/block-all-mixed-content/resources/red-square.png");
+?>

Added: trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https-expected.txt (0 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https-expected.txt	2018-02-07 18:56:02 UTC (rev 228231)
@@ -0,0 +1,3 @@
+CONSOLE MESSAGE: Blocked http://127.0.0.1:8000/security/mixedContent/resources/subresource/protected-page.php from asking for credentials because it is insecure content.
+CONSOLE MESSAGE: Blocked http://127.0.0.1:8000/security/mixedContent/resources/subresource/protected-page.php from asking for credentials because it was navigated to from a secure page or went through an insecure redirect.
+Unauthorized.

Added: trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https.html (0 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https.html	2018-02-07 18:56:02 UTC (rev 228231)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.setHandlesAuthenticationChallenges(true);
+    testRunner.setAuthenticationUsername("testUser");
+    testRunner.setAuthenticationPassword("testPassword");
+    testRunner.waitUntilDone();
+}
+window.location.href = ""
+</script>
+</head>
+</html>

Added: trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https-expected.txt (0 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https-expected.txt	2018-02-07 18:56:02 UTC (rev 228231)
@@ -0,0 +1,3 @@
+CONSOLE MESSAGE: Blocked https://127.0.0.1:8443/security/mixedContent/resources/subresource/protected-page.php from asking for credentials because it was loaded via an insecure redirect from http://127.0.0.1:8000/resources/redirect.php?url=""
+CONSOLE MESSAGE: Blocked https://127.0.0.1:8443/security/mixedContent/resources/subresource/protected-page.php from asking for credentials because it was navigated to from a secure page or went through an insecure redirect.
+Unauthorized.

Added: trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https.html (0 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https.html	2018-02-07 18:56:02 UTC (rev 228231)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.setHandlesAuthenticationChallenges(true);
+    testRunner.setAuthenticationUsername("testUser");
+    testRunner.setAuthenticationPassword("testPassword");
+    testRunner.waitUntilDone();
+}
+window.location.href = ""
+</script>
+</head>
+</html>

Modified: trunk/LayoutTests/http/tests/security/mixedContent/secure-redirect-to-insecure-redirect-to-basic-auth-secure-image.https-expected.txt (228230 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/secure-redirect-to-insecure-redirect-to-basic-auth-secure-image.https-expected.txt	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/LayoutTests/http/tests/security/mixedContent/secure-redirect-to-insecure-redirect-to-basic-auth-secure-image.https-expected.txt	2018-02-07 18:56:02 UTC (rev 228231)
@@ -1,5 +1,6 @@
 CONSOLE MESSAGE: The page at https://127.0.0.1:8443/security/mixedContent/secure-redirect-to-insecure-redirect-to-basic-auth-secure-image.https.html was allowed to display insecure content from http://127.0.0.1:8080/resources/redirect.php?url=""
 
+CONSOLE MESSAGE: Blocked https://localhost:8443/security/mixedContent/resources/subresource/protected-image.php from asking for credentials because it was loaded via an insecure redirect from https://127.0.0.1:8443/resources/redirect.php?url=""
 This test loads a secure image that redirects to an insecure image that redirects to a secure image guarded by basic authentication. The secure image should be blocked because it requires credentials and was loaded via an insecure redirect.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".

Modified: trunk/LayoutTests/http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https-expected.txt (228230 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https-expected.txt	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/LayoutTests/http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https-expected.txt	2018-02-07 18:56:02 UTC (rev 228231)
@@ -1,5 +1,6 @@
-CONSOLE MESSAGE: The page at https://127.0.0.1:8443/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html was allowed to display insecure content from http://127.0.0.1:8443/resources/redirect.php?url=""
+CONSOLE MESSAGE: The page at https://127.0.0.1:8443/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html was allowed to display insecure content from http://localhost:8080/security/mixedContent/resources/subresource/protected-image.php.
 
+CONSOLE MESSAGE: Blocked http://localhost:8080/security/mixedContent/resources/subresource/protected-image.php from asking for credentials because it is insecure content that was loaded via a redirect from https://127.0.0.1:8443/resources/redirect.php?url=""
 This test loads a secure image that redirects to an secure image that redirects to an insecure image guarded by basic authentication. The insecure image should be blocked because it requires credentials.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".

Modified: trunk/LayoutTests/http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html (228230 => 228231)


--- trunk/LayoutTests/http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/LayoutTests/http/tests/security/mixedContent/secure-redirect-to-secure-redirect-to-basic-auth-insecure-image.https.html	2018-02-07 18:56:02 UTC (rev 228231)
@@ -22,10 +22,22 @@
     testFailed("did load image.");
     finishJSTest();
 }
+
+function runTest()
+{
+    // Load the image programmatically instead of declaratively to avoid output flakiness caused by
+    // the preload scanner performing mixed content checks as part of preloading the image.
+    let image = new Image;
+    image._onload_ = fail;
+    image._onerror_ = pass;
+    image.src = ""
+    document.body.appendChild(image);
+}
+
+window._onload_ = runTest;
 </script>
 <script>
 description("This test loads a secure image that redirects to an secure image that redirects to an insecure image guarded by basic authentication. The insecure image should be blocked because it requires credentials.");
 </script>
-<img src="" _onerror_="pass()" _onload_="fail()">
 </body>
 </html>

Modified: trunk/Source/WebCore/ChangeLog (228230 => 228231)


--- trunk/Source/WebCore/ChangeLog	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebCore/ChangeLog	2018-02-07 18:56:02 UTC (rev 228231)
@@ -1,3 +1,46 @@
+2018-02-07  Daniel Bates  <daba...@apple.com>
+
+        Log error when authentication challenge is blocked due to an insecure request
+        https://bugs.webkit.org/show_bug.cgi?id=182358
+
+        Reviewed by Andy Estes.
+
+        Emit an error message to Web Inspector console that explains why an authentication
+        challenge was blocked so that a developer can fix up their site.
+
+        Tests: http/tests/security/mixedContent/insecure-basic-auth-image.https.html
+               http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-insecure-page.https.html
+               http/tests/security/mixedContent/secure-page-navigates-to-basic-auth-secure-page-via-insecure-redirect.https.html
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::receivedFirstData): Log to the console an error message
+        if the document we are loading was forbidden from prompting for credentials.
+        Also removed duplicate assertion to ensure document is non-null and update
+        call to LinkLoader::loadLinksFromHeader() to use local variable to access
+        the document we are loading instead of asking the frame for it, again.
+        (WebCore::FrameLoader::reportAuthenticationChallengeBlocked): Added.
+        * loader/FrameLoader.h:
+
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::init):
+        (WebCore::ResourceLoader::willSendRequestInternal):
+        Track the decision to forbid asking for credentials due to Fetch spec. requirements (m_canAskClientForCredentials)
+        independently from the decision to forbid them due to making an insecure request (m_wasInsecureRequestSeen)
+        so that we know the reason why we blocked asking for credentials when we receive an authentication challenge.
+
+        (WebCore::ResourceLoader::didBlockAuthenticationChallenge): Added.
+        (WebCore::ResourceLoader::isAllowedToAskUserForCredentials const): Modified code now that we track
+        whether we have seen an insecure request so far independently from decision to forbid prompting for
+        credentials due to a Fetch spec. requirement.
+
+        (WebCore::ResourceLoader::didReceiveAuthenticationChallenge):
+        Store a bit whether we have seen an insecure request when loading the resource so far. Disallow
+        asking for credentials if we have seen an insecure request so far. Once we receive a response
+
+        * loader/ResourceLoader.h:
+        (WebCore::ResourceLoader::wasAuthenticationChallengeBlocked const): Added.
+        (WebCore::ResourceLoader::wasInsecureRequestSeen const): Added.
+
 2018-02-06  Matt Lewis  <jlew...@apple.com>
 
         Removed the assertions from VideoFullscreenInterfaceAVKit.mm temporarily to stop the resulting crashes during debugging.

Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (228230 => 228231)


--- trunk/Source/WebCore/loader/FrameLoader.cpp	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp	2018-02-07 18:56:02 UTC (rev 228231)
@@ -115,6 +115,7 @@
 #include "SerializedScriptValue.h"
 #include "Settings.h"
 #include "SubframeLoader.h"
+#include "SubresourceLoader.h"
 #include "TextResourceDecoder.h"
 #include "UserContentController.h"
 #include "UserGestureIndicator.h"
@@ -678,6 +679,10 @@
     ASSERT(m_frame.document());
     auto& document = *m_frame.document();
 
+    auto* mainResourceLoader = documentLoader.mainResourceLoader();
+    if (mainResourceLoader && mainResourceLoader->wasAuthenticationChallengeBlocked() && mainResourceLoader->wasInsecureRequestSeen())
+        reportAuthenticationChallengeBlocked(&m_frame, document.url(), ASCIILiteral { "it was navigated to from a secure page or went through an insecure redirect" });
+
     LinkLoader::loadLinksFromHeader(documentLoader.response().httpHeaderField(HTTPHeaderName::Link), document.url(), document, LinkLoader::MediaAttributeCheck::MediaAttributeEmpty);
 
     double delay;
@@ -1552,6 +1557,14 @@
     frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Not allowed to use restricted network port: " + url);
 }
 
+void FrameLoader::reportAuthenticationChallengeBlocked(Frame* frame, const URL& url, const String& reason)
+{
+    if (!frame)
+        return;
+
+    frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, makeString("Blocked ", url.stringCenterEllipsizedToLength(), " from asking for credentials because ", reason, '.'));
+}
+
 const ResourceRequest& FrameLoader::initialRequest() const
 {
     return activeDocumentLoader()->originalRequest();

Modified: trunk/Source/WebCore/loader/FrameLoader.h (228230 => 228231)


--- trunk/Source/WebCore/loader/FrameLoader.h	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebCore/loader/FrameLoader.h	2018-02-07 18:56:02 UTC (rev 228231)
@@ -131,6 +131,7 @@
 
     static void reportLocalLoadFailed(Frame*, const String& url);
     static void reportBlockedPortFailed(Frame*, const String& url);
+    static void reportAuthenticationChallengeBlocked(Frame*, const URL&, const String& reason);
 
     // FIXME: These are all functions which stop loads. We have too many.
     WEBCORE_EXPORT void stopAllLoaders(ClearProvisionalItemPolicy = ShouldClearProvisionalItem);

Modified: trunk/Source/WebCore/loader/ResourceLoader.cpp (228230 => 228231)


--- trunk/Source/WebCore/loader/ResourceLoader.cpp	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebCore/loader/ResourceLoader.cpp	2018-02-07 18:56:02 UTC (rev 228231)
@@ -133,7 +133,8 @@
 #endif
     
     m_defersLoading = m_options.defersLoadingPolicy == DefersLoadingPolicy::AllowDefersLoading && m_frame->page()->defersLoading();
-    m_canAskClientForCredentials = m_options.clientCredentialPolicy == ClientCredentialPolicy::MayAskClientForCredentials && !isMixedContent(clientRequest.url());
+    m_canAskClientForCredentials = m_options.clientCredentialPolicy == ClientCredentialPolicy::MayAskClientForCredentials;
+    m_wasInsecureRequestSeen = isMixedContent(clientRequest.url());
 
     if (m_options.securityCheck == DoSecurityCheck && !m_frame->document()->securityOrigin().canDisplay(clientRequest.url())) {
         FrameLoader::reportLocalLoadFailed(m_frame.get(), clientRequest.url().string());
@@ -404,7 +405,7 @@
     bool isRedirect = !redirectResponse.isNull();
 
     if (isMixedContent(m_request.url()) || (isRedirect && isMixedContent(request.url())))
-        m_canAskClientForCredentials = false;
+        m_wasInsecureRequestSeen = true;
 
     if (isRedirect)
         platformStrategies()->loaderStrategy()->crossOriginRedirectReceived(this, request.url());
@@ -462,6 +463,31 @@
     frame->page()->diagnosticLoggingClient().logDiagnosticMessage(DiagnosticLoggingKeys::resourceResponseSourceKey(), sourceKey, ShouldSample::Yes);
 }
 
+void ResourceLoader::didBlockAuthenticationChallenge()
+{
+    m_wasAuthenticationChallengeBlocked = true;
+
+    if (!m_canAskClientForCredentials)
+        return;
+
+    if (!m_wasInsecureRequestSeen)
+        return;
+
+    // Comparing the initial request URL and final request URL does not tell us whether a redirect happened or not since
+    // a server can serve a redirect to the same URL that was requested. However, this is good enough for our purpose.
+    bool wasRedirected = m_request.url() != originalRequest().url();
+
+    bool isMixedContent = this->isMixedContent(m_request.url());
+    String reason;
+    if (isMixedContent && wasRedirected)
+        reason = makeString("it is insecure content that was loaded via a redirect from ", originalRequest().url().stringCenterEllipsizedToLength());
+    else if (isMixedContent)
+        reason = ASCIILiteral { "it is insecure content" };
+    else
+        reason = makeString("it was loaded via an insecure redirect from ", originalRequest().url().stringCenterEllipsizedToLength());
+    FrameLoader::reportAuthenticationChallengeBlocked(m_frame.get(), m_request.url(), reason);
+}
+
 void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
 {
     ASSERT(!m_reachedTerminalState);
@@ -713,6 +739,8 @@
 {
     if (!m_canAskClientForCredentials)
         return false;
+    if (m_wasInsecureRequestSeen)
+        return false;
     return m_options.credentials == FetchOptions::Credentials::Include || (m_options.credentials == FetchOptions::Credentials::SameOrigin && m_frame->document()->securityOrigin().canRequest(originalRequest().url()));
 }
 
@@ -730,6 +758,7 @@
             frameLoader()->notifier().didReceiveAuthenticationChallenge(this, challenge);
             return;
         }
+        didBlockAuthenticationChallenge();
     }
     challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
     ASSERT(!m_handle || !m_handle->hasAuthenticationChallenge());

Modified: trunk/Source/WebCore/loader/ResourceLoader.h (228230 => 228231)


--- trunk/Source/WebCore/loader/ResourceLoader.h	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebCore/loader/ResourceLoader.h	2018-02-07 18:56:02 UTC (rev 228231)
@@ -89,6 +89,9 @@
 
     unsigned long identifier() const { return m_identifier; }
 
+    bool wasAuthenticationChallengeBlocked() const { return m_wasAuthenticationChallengeBlocked; }
+    bool wasInsecureRequestSeen() const { return m_wasInsecureRequestSeen; }
+
     virtual void releaseResources();
     const ResourceResponse& response() const { return m_response; }
 
@@ -106,6 +109,8 @@
     virtual void didFail(const ResourceError&);
     virtual void didRetrieveDerivedDataFromCache(const String& type, SharedBuffer&);
 
+    WEBCORE_EXPORT void didBlockAuthenticationChallenge();
+
     virtual bool shouldUseCredentialStorage();
 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
     virtual bool canAuthenticateAgainstProtectionSpace(const ProtectionSpace&);
@@ -149,6 +154,8 @@
 protected:
     ResourceLoader(Frame&, ResourceLoaderOptions);
 
+    bool isMixedContent(const URL&) const;
+
     void didFinishLoadingOnePart(const NetworkLoadMetrics&);
     void cleanupForError(const ResourceError&);
 
@@ -203,8 +210,6 @@
     bool shouldCacheResponse(ResourceHandle*, CFCachedURLResponseRef) override;
 #endif
 
-    bool isMixedContent(const URL&) const;
-
     ResourceRequest m_request;
     ResourceRequest m_originalRequest; // Before redirects.
     RefPtr<SharedBuffer> m_resourceData;
@@ -224,6 +229,8 @@
 
     bool m_defersLoading;
     bool m_canAskClientForCredentials;
+    bool m_wasInsecureRequestSeen { false };
+    bool m_wasAuthenticationChallengeBlocked { false };
     ResourceRequest m_deferredRequest;
     ResourceLoaderOptions m_options;
 

Modified: trunk/Source/WebKit/ChangeLog (228230 => 228231)


--- trunk/Source/WebKit/ChangeLog	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebKit/ChangeLog	2018-02-07 18:56:02 UTC (rev 228231)
@@ -1,3 +1,24 @@
+2018-02-07  Daniel Bates  <daba...@apple.com>
+
+        Log error when authentication challenge is blocked due to an insecure request
+        https://bugs.webkit.org/show_bug.cgi?id=182358
+
+        Reviewed by Andy Estes.
+
+        Have network process notify the web process when it blocks an authentication challenge.
+
+        * NetworkProcess/NetworkLoad.cpp:
+        (WebKit::NetworkLoad::completeAuthenticationChallenge):
+        * NetworkProcess/NetworkLoadClient.h:
+        (WebKit::NetworkLoadClient::didBlockAuthenticationChallenge):
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::didBlockAuthenticationChallenge):
+        * NetworkProcess/NetworkResourceLoader.h:
+        * WebProcess/Network/WebResourceLoader.cpp:
+        (WebKit::WebResourceLoader::didBlockAuthenticationChallenge):
+        * WebProcess/Network/WebResourceLoader.h:
+        * WebProcess/Network/WebResourceLoader.messages.in:
+
 2018-02-07  Chris Dumez  <cdu...@apple.com>
 
         IndexedDB in service workers is using a memory backed store

Modified: trunk/Source/WebKit/NetworkProcess/NetworkLoad.cpp (228230 => 228231)


--- trunk/Source/WebKit/NetworkProcess/NetworkLoad.cpp	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebKit/NetworkProcess/NetworkLoad.cpp	2018-02-07 18:56:02 UTC (rev 228231)
@@ -280,6 +280,7 @@
 {
     bool isServerTrustEvaluation = m_challenge->protectionSpace().authenticationScheme() == ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested;
     if (!isAllowedToAskUserForCredentials() && !isServerTrustEvaluation) {
+        m_client.get().didBlockAuthenticationChallenge();
         completionHandler(AuthenticationChallengeDisposition::UseCredential, { });
         return;
     }

Modified: trunk/Source/WebKit/NetworkProcess/NetworkLoadClient.h (228230 => 228231)


--- trunk/Source/WebKit/NetworkProcess/NetworkLoadClient.h	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebKit/NetworkProcess/NetworkLoadClient.h	2018-02-07 18:56:02 UTC (rev 228231)
@@ -56,6 +56,7 @@
     virtual void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) = 0;
     virtual void didFinishLoading(const WebCore::NetworkLoadMetrics&) = 0;
     virtual void didFailLoading(const WebCore::ResourceError&) = 0;
+    virtual void didBlockAuthenticationChallenge() { };
     virtual bool shouldCaptureExtraNetworkLoadMetrics() const { return false; }
 };
 

Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (228230 => 228231)


--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp	2018-02-07 18:56:02 UTC (rev 228231)
@@ -430,6 +430,11 @@
     cleanup();
 }
 
+void NetworkResourceLoader::didBlockAuthenticationChallenge()
+{
+    send(Messages::WebResourceLoader::DidBlockAuthenticationChallenge());
+}
+
 void NetworkResourceLoader::willSendRedirectedRequest(ResourceRequest&& request, WebCore::ResourceRequest&& redirectRequest, ResourceResponse&& redirectResponse)
 {
     ++m_redirectCount;

Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h (228230 => 228231)


--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h	2018-02-07 18:56:02 UTC (rev 228231)
@@ -97,6 +97,7 @@
     void didReceiveBuffer(Ref<WebCore::SharedBuffer>&&, int reportedEncodedDataLength) override;
     void didFinishLoading(const WebCore::NetworkLoadMetrics&) override;
     void didFailLoading(const WebCore::ResourceError&) override;
+    void didBlockAuthenticationChallenge() override;
     bool shouldCaptureExtraNetworkLoadMetrics() const override;
 
     void convertToDownload(DownloadID, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&);

Modified: trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp (228230 => 228231)


--- trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp	2018-02-07 18:56:02 UTC (rev 228231)
@@ -160,6 +160,14 @@
     m_coreLoader->didFail(error);
 }
 
+void WebResourceLoader::didBlockAuthenticationChallenge()
+{
+    LOG(Network, "(WebProcess) WebResourceLoader::didBlockAuthenticationChallenge for '%s'", m_coreLoader->url().string().latin1().data());
+    RELEASE_LOG_IF_ALLOWED("didBlockAuthenticationChallenge: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_trackingParameters.pageID, m_trackingParameters.frameID, m_trackingParameters.resourceID);
+
+    m_coreLoader->didBlockAuthenticationChallenge();
+}
+
 #if ENABLE(SHAREABLE_RESOURCE)
 void WebResourceLoader::didReceiveResource(const ShareableResource::Handle& handle)
 {

Modified: trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.h (228230 => 228231)


--- trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.h	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.h	2018-02-07 18:56:02 UTC (rev 228231)
@@ -81,6 +81,7 @@
     void didRetrieveDerivedData(const String& type, const IPC::DataReference&);
     void didFinishResourceLoad(const WebCore::NetworkLoadMetrics&);
     void didFailResourceLoad(const WebCore::ResourceError&);
+    void didBlockAuthenticationChallenge();
 #if ENABLE(SHAREABLE_RESOURCE)
     void didReceiveResource(const ShareableResource::Handle&);
 #endif

Modified: trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in (228230 => 228231)


--- trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in	2018-02-07 18:51:21 UTC (rev 228230)
+++ trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in	2018-02-07 18:56:02 UTC (rev 228231)
@@ -28,6 +28,7 @@
     DidFinishResourceLoad(WebCore::NetworkLoadMetrics networkLoadMetrics)
     DidRetrieveDerivedData(String type, IPC::DataReference data)
     DidFailResourceLoad(WebCore::ResourceError error)
+    DidBlockAuthenticationChallenge()
 
 #if ENABLE(SHAREABLE_RESOURCE)
     // DidReceiveResource is for when we have the entire resource data available at once, such as when the resource is cached in memory
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to