155 lines
4.7 KiB
Diff
155 lines
4.7 KiB
Diff
From d52e9042bcec41a40b97b309b65aa32dc27379b2 Mon Sep 17 00:00:00 2001
|
|
From: Kershaw Chang <kershaw@mozilla.com>
|
|
Date: Fri, 12 Jul 2024 16:46:48 +0800
|
|
Subject: [PATCH] Show auth spoofing warning prompt for cached response r=necko-reviewers,dragana
|
|
|
|
Reference:https://hg.mozilla.org/integration/autoland/rev/3d26a1f3b809522af0152918341a4b5ff924e4bb
|
|
|
|
---
|
|
netwerk/protocol/http/nsHttpChannel.cpp | 11 +++
|
|
netwerk/test/unit/test_SuperfluousAuth.js | 100 ++++++++++++++++++++++
|
|
netwerk/test/unit/xpcshell.ini | 1 +
|
|
3 files changed, 112 insertions(+)
|
|
create mode 100644 netwerk/test/unit/test_SuperfluousAuth.js
|
|
|
|
diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp
|
|
index 2cb1f8d9fd..181c3ac785 100644
|
|
--- a/netwerk/protocol/http/nsHttpChannel.cpp
|
|
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
|
|
@@ -7365,6 +7365,17 @@ nsresult nsHttpChannel::ContinueOnStartRequest4(nsresult result) {
|
|
|
|
if (mFallingBack) return NS_OK;
|
|
|
|
+ if (NS_SUCCEEDED(mStatus) && mResponseHead && mAuthProvider) {
|
|
+ uint32_t httpStatus = mResponseHead->Status();
|
|
+ if (httpStatus != 401 && httpStatus != 407) {
|
|
+ nsresult rv = mAuthProvider->CheckForSuperfluousAuth();
|
|
+ if (NS_FAILED(rv)) {
|
|
+ LOG((" CheckForSuperfluousAuth failed (%08x)",
|
|
+ static_cast<uint32_t>(rv)));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
return CallOnStartRequest();
|
|
}
|
|
|
|
diff --git a/netwerk/test/unit/test_SuperfluousAuth.js b/netwerk/test/unit/test_SuperfluousAuth.js
|
|
new file mode 100644
|
|
index 0000000000..24b69186c8
|
|
--- /dev/null
|
|
+++ b/netwerk/test/unit/test_SuperfluousAuth.js
|
|
@@ -0,0 +1,100 @@
|
|
+/*
|
|
+
|
|
+Create two http requests with the same URL in which has a user name. We allow
|
|
+first http request to be loaded and saved in the cache, so the second request
|
|
+will be served from the cache. However, we disallow loading by returning 1
|
|
+in the prompt service. In the end, the second request will be failed.
|
|
+
|
|
+*/
|
|
+
|
|
+"use strict";
|
|
+
|
|
+const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
|
|
+
|
|
+const { MockRegistrar } = ChromeUtils.import(
|
|
+ "resource://testing-common/MockRegistrar.jsm"
|
|
+);
|
|
+
|
|
+var httpProtocolHandler = Cc[
|
|
+ "@mozilla.org/network/protocol;1?name=http"
|
|
+].getService(Ci.nsIHttpProtocolHandler);
|
|
+
|
|
+XPCOMUtils.defineLazyGetter(this, "URL", function() {
|
|
+ return "http://foo@localhost:" + httpServer.identity.primaryPort;
|
|
+});
|
|
+
|
|
+var httpServer = null;
|
|
+
|
|
+const gMockPromptService = {
|
|
+ firstTimeCalled: false,
|
|
+ confirmExBC() {
|
|
+ if (!this.firstTimeCalled) {
|
|
+ this.firstTimeCalled = true;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+ },
|
|
+
|
|
+ QueryInterface: ChromeUtils.generateQI(["nsIPromptService"]),
|
|
+};
|
|
+
|
|
+var gMockPromptServiceCID = MockRegistrar.register(
|
|
+ "@mozilla.org/embedcomp/prompt-service;1",
|
|
+ gMockPromptService
|
|
+);
|
|
+
|
|
+registerCleanupFunction(() => {
|
|
+ MockRegistrar.unregister(gMockPromptServiceCID);
|
|
+});
|
|
+
|
|
+function makeChan(uri) {
|
|
+ let chan = NetUtil.newChannel({
|
|
+ uri,
|
|
+ loadUsingSystemPrincipal: true,
|
|
+ }).QueryInterface(Ci.nsIHttpChannel);
|
|
+ chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
|
|
+ return chan;
|
|
+}
|
|
+
|
|
+const responseBody = "body";
|
|
+
|
|
+function contentHandler(metadata, response) {
|
|
+ response.setHeader("Content-Type", "text/plain");
|
|
+ response.setHeader("ETag", "Just testing");
|
|
+ response.setHeader("Cache-Control", "max-age=99999");
|
|
+ response.setHeader("Content-Length", "" + responseBody.length);
|
|
+ response.bodyOutputStream.write(responseBody, responseBody.length);
|
|
+}
|
|
+
|
|
+function run_test() {
|
|
+ do_get_profile();
|
|
+
|
|
+ Services.prefs.setBoolPref("network.http.rcwn.enabled", false);
|
|
+
|
|
+ httpServer = new HttpServer();
|
|
+ httpServer.registerPathHandler("/content", contentHandler);
|
|
+ httpServer.start(-1);
|
|
+
|
|
+ httpProtocolHandler.EnsureHSTSDataReady().then(function() {
|
|
+ var chan1 = makeChan(URL + "/content");
|
|
+ chan1.asyncOpen(new ChannelListener(firstTimeThrough, null));
|
|
+ var chan2 = makeChan(URL + "/content");
|
|
+ chan2.asyncOpen(
|
|
+ new ChannelListener(secondTimeThrough, null, CL_EXPECT_FAILURE)
|
|
+ );
|
|
+ });
|
|
+
|
|
+ do_test_pending();
|
|
+}
|
|
+
|
|
+function firstTimeThrough(request, buffer) {
|
|
+ Assert.equal(buffer, responseBody);
|
|
+ Assert.ok(gMockPromptService.firstTimeCalled, "Prompt service invoked");
|
|
+}
|
|
+
|
|
+function secondTimeThrough(request, buffer) {
|
|
+ Assert.equal(request.status, Cr.NS_ERROR_ABORT);
|
|
+ httpServer.stop(do_test_finished);
|
|
+}
|
|
+
|
|
diff --git a/netwerk/test/unit/xpcshell.ini b/netwerk/test/unit/xpcshell.ini
|
|
index 1cd274b004..3e6762f0dc 100644
|
|
--- a/netwerk/test/unit/xpcshell.ini
|
|
+++ b/netwerk/test/unit/xpcshell.ini
|
|
@@ -434,3 +434,4 @@ skip-if = true || asan || tsan || os == 'win' || os =='android'
|
|
[test_trr_case_sensitivity.js]
|
|
skip-if = os == "android"
|
|
[test_trr_proxy.js]
|
|
+[test_SuperfluousAuth.js]
|
|
--
|
|
2.27.0
|
|
|