diff --git a/browser/base/content/aboutNetError.js b/browser/base/content/aboutNetError.js index cebc8d49aafb..8847c20f4120 100644 --- a/browser/base/content/aboutNetError.js +++ b/browser/base/content/aboutNetError.js @@ -74,6 +74,18 @@ function showPrefChangeContainer() { addAutofocus("#prefResetButton", "beforeend"); } +function showTls10Container() { + const panel = document.getElementById("enableTls10Container"); + panel.style.display = "block"; + document.getElementById("netErrorButtonContainer").style.display = "none"; + const button = document.getElementById("enableTls10Button"); + button.addEventListener("click", function enableTls10(e) { + RPMSetBoolPref("security.tls.version.enable-deprecated", true); + retryThis(button); + }); + addAutofocus("#enableTls10Button", "beforeend"); +} + function setupAdvancedButton() { // Get the hostname and add it to the panel var panel = document.getElementById("badCertAdvancedPanel"); @@ -264,26 +276,36 @@ function initPage() { if (err == "nssFailure2") { setupErrorUI(); - RPMAddMessageListener("HasChangedCertPrefs", msg => { - let hasChangedCertPrefs = msg.data.hasChangedCertPrefs; + const errorCode = document.getNetErrorInfo().errorCodeString; + const isTlsVersionError = (errorCode == "SSL_ERROR_UNSUPPORTED_VERSION"); + const tls10OverrideEnabled = RPMGetBoolPref( + "security.tls.version.enable-deprecated" + ); - let errorCode = document.getNetErrorInfo().errorCodeString; - let hasPrefStyleError = [ + if (isTlsVersionError && !tls10OverrideEnabled) { + // This is probably a TLS 1.0 server; offer to re-enable. + showTls10Container(); + } else { + const hasPrefStyleError = [ "interrupted", // This happens with subresources that are above the max tls - "SSL_ERROR_PROTOCOL_VERSION_ALERT", - "SSL_ERROR_UNSUPPORTED_VERSION", - "SSL_ERROR_NO_CYPHER_OVERLAP", "SSL_ERROR_NO_CIPHERS_SUPPORTED", + "SSL_ERROR_NO_CYPHER_OVERLAP", + "SSL_ERROR_PROTOCOL_VERSION_ALERT", + "SSL_ERROR_UNSUPPORTED_VERSION" ].some(substring => { return substring == errorCode; }); - // If it looks like an error that is user config based - if (hasPrefStyleError && hasChangedCertPrefs) { - showPrefChangeContainer(); + if (hasPrefStyleError) { + RPMAddMessageListener("HasChangedCertPrefs", msg => { + if (msg.data.hasChangedCertPrefs) { + // Configuration overrides might have caused this; offer to reset. + showPrefChangeContainer(); + } + }); + RPMSendAsyncMessage("GetChangedCertPrefs"); } - }); - RPMSendAsyncMessage("GetChangedCertPrefs"); + } } if (err == "sslv3Used") { diff --git a/browser/base/content/aboutNetError.xhtml b/browser/base/content/aboutNetError.xhtml index 4b73f65204a6..bfb46365a8d7 100644 --- a/browser/base/content/aboutNetError.xhtml +++ b/browser/base/content/aboutNetError.xhtml @@ -181,6 +181,14 @@ + +
+

&enableTls10.longDesc;

+

&enableTls10.note;

+ +
+
diff --git a/browser/base/content/test/about/browser_aboutNetError.js b/browser/base/content/test/about/browser_aboutNetError.js index d64c0c204341..387c616112d2 100644 --- a/browser/base/content/test/about/browser_aboutNetError.js +++ b/browser/base/content/test/about/browser_aboutNetError.js @@ -3,23 +3,25 @@ "use strict"; -const LOW_TLS_VERSION = "https://tls1.example.com/"; +const SSL3_PAGE = "https://ssl3.example.com/"; +const TLS10_PAGE = "https://tls1.example.com/"; +const TLS12_PAGE = "https://tls12.example.com/"; -add_task(async function checkReturnToPreviousPage() { +add_task(async function resetToDefaultConfig() { info( - "Loading a TLS page that isn't supported, ensure we have a fix button and clicking it then loads the page" + "Change TLS config to cause page load to fail, check that reset button is shown and that it works" ); // Set ourselves up for TLS error - Services.prefs.setIntPref("security.tls.version.max", 3); - Services.prefs.setIntPref("security.tls.version.min", 3); + Services.prefs.setIntPref("security.tls.version.min", 1); // TLS 1.0 + Services.prefs.setIntPref("security.tls.version.max", 1); let browser; let pageLoaded; await BrowserTestUtils.openNewForegroundTab( gBrowser, () => { - gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, LOW_TLS_VERSION); + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TLS12_PAGE); browser = gBrowser.selectedBrowser; pageLoaded = BrowserTestUtils.waitForErrorPage(browser); }, @@ -29,59 +31,54 @@ add_task(async function checkReturnToPreviousPage() { info("Loading and waiting for the net error"); await pageLoaded; - // NB: This code assumes that the error page and the test page load in the - // same process. If this test starts to fail, it could be because they load - // in different processes. - await ContentTask.spawn(browser, LOW_TLS_VERSION, async function( - LOW_TLS_VERSION_ - ) { - ok( - content.document.getElementById("prefResetButton").getBoundingClientRect() - .left >= 0, - "Should have a visible button" - ); + // Setup an observer for the target page. + const finalLoadComplete = BrowserTestUtils.browserLoaded( + browser, + false, + TLS12_PAGE + ); + await ContentTask.spawn(browser, null, async function() { + const doc = content.document; ok( - content.document.documentURI.startsWith("about:neterror"), + doc.documentURI.startsWith("about:neterror"), "Should be showing error page" ); - let doc = content.document; - let prefResetButton = doc.getElementById("prefResetButton"); + const prefResetButton = doc.getElementById("prefResetButton"); + ok( + ContentTaskUtils.is_visible(prefResetButton), + "prefResetButton should be visible" + ); is( prefResetButton.getAttribute("autofocus"), "true", "prefResetButton has autofocus" ); prefResetButton.click(); - - await ContentTaskUtils.waitForEvent(this, "pageshow", true); - - is( - content.document.documentURI, - LOW_TLS_VERSION_, - "Should not be showing page" - ); }); + info("Waiting for the TLS 1.2 page to load after the click"); + await finalLoadComplete; + + Services.prefs.clearUserPref("security.tls.version.min"); + Services.prefs.clearUserPref("security.tls.version.max"); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); add_task(async function checkLearnMoreLink() { - info( - "Loading a TLS page that isn't supported and checking the learn more link" - ); + info("Load an unsupported TLS page and check for a learn more link"); // Set ourselves up for TLS error - Services.prefs.setIntPref("security.tls.version.max", 3); Services.prefs.setIntPref("security.tls.version.min", 3); + Services.prefs.setIntPref("security.tls.version.max", 4); let browser; let pageLoaded; await BrowserTestUtils.openNewForegroundTab( gBrowser, () => { - gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, LOW_TLS_VERSION); + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TLS10_PAGE); browser = gBrowser.selectedBrowser; pageLoaded = BrowserTestUtils.waitForErrorPage(browser); }, @@ -91,16 +88,16 @@ add_task(async function checkLearnMoreLink() { info("Loading and waiting for the net error"); await pageLoaded; - let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL"); + const baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL"); await ContentTask.spawn(browser, baseURL, function(_baseURL) { + const doc = content.document; ok( - content.document.documentURI.startsWith("about:neterror"), + doc.documentURI.startsWith("about:neterror"), "Should be showing error page" ); - let doc = content.document; - let learnMoreLink = doc.getElementById("learnMoreLink"); + const learnMoreLink = doc.getElementById("learnMoreLink"); ok( ContentTaskUtils.is_visible(learnMoreLink), "Learn More link is visible" @@ -108,7 +105,120 @@ add_task(async function checkLearnMoreLink() { is(learnMoreLink.getAttribute("href"), _baseURL + "connection-not-secure"); }); - Services.prefs.clearUserPref("security.tls.version.max"); Services.prefs.clearUserPref("security.tls.version.min"); + Services.prefs.clearUserPref("security.tls.version.max"); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +add_task(async function checkEnable10() { + info( + "Load a page with a deprecated TLS version, an option to enable TLS 1.0 is offered and it works" + ); + + Services.prefs.setIntPref("security.tls.version.min", 3); + // Disable TLS 1.3 so that we trigger a SSL_ERROR_UNSUPPORTED_VERSION. + // As NSS generates an alert rather than negotiating a lower version + // if we use the supported_versions extension from TLS 1.3. + Services.prefs.setIntPref("security.tls.version.max", 3); + + let browser; + let pageLoaded; + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TLS10_PAGE); + browser = gBrowser.selectedBrowser; + pageLoaded = BrowserTestUtils.waitForErrorPage(browser); + }, + false + ); + + info("Loading and waiting for the net error"); + await pageLoaded; + + // Setup an observer for the target page. + const finalLoadComplete = BrowserTestUtils.browserLoaded( + browser, + false, + TLS10_PAGE + ); + + await ContentTask.spawn(browser, null, async function() { + const doc = content.document; + ok( + doc.documentURI.startsWith("about:neterror"), + "Should be showing error page" + ); + + const enableTls10Button = doc.getElementById("enableTls10Button"); + ok( + ContentTaskUtils.is_visible(enableTls10Button), + "Option to re-enable TLS 1.0 is visible" + ); + enableTls10Button.click(); + + // It should not also offer to reset preferences instead. + const prefResetButton = doc.getElementById("prefResetButton"); + ok( + !ContentTaskUtils.is_visible(prefResetButton), + "prefResetButton should NOT be visible" + ); + }); + + info("Waiting for the TLS 1.0 page to load after the click"); + await finalLoadComplete; + + Services.prefs.clearUserPref("security.tls.version.min"); + Services.prefs.clearUserPref("security.tls.version.max"); + Services.prefs.clearUserPref("security.tls.version.enable-deprecated"); + BrowserTestUtils.removeTab(gBrowser.selectedTab); +}); + +add_task(async function dontOffer10WhenAlreadyEnabled() { + info("An option to enable TLS 1.0 is not offered if already enabled"); + + Services.prefs.setIntPref("security.tls.version.min", 3); + Services.prefs.setIntPref("security.tls.version.max", 3); + Services.prefs.setBoolPref("security.tls.version.enable-deprecated", true); + + let browser; + let pageLoaded; + await BrowserTestUtils.openNewForegroundTab( + gBrowser, + () => { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, SSL3_PAGE); + browser = gBrowser.selectedBrowser; + pageLoaded = BrowserTestUtils.waitForErrorPage(browser); + }, + false + ); + + info("Loading and waiting for the net error"); + await pageLoaded; + + await ContentTask.spawn(browser, null, async function() { + const doc = content.document; + ok( + doc.documentURI.startsWith("about:neterror"), + "Should be showing error page" + ); + + const enableTls10Button = doc.getElementById("enableTls10Button"); + ok( + !ContentTaskUtils.is_visible(enableTls10Button), + "Option to re-enable TLS 1.0 is not visible" + ); + + // It should offer to reset preferences instead. + const prefResetButton = doc.getElementById("prefResetButton"); + ok( + ContentTaskUtils.is_visible(prefResetButton), + "prefResetButton should be visible" + ); + }); + + Services.prefs.clearUserPref("security.tls.version.min"); + Services.prefs.clearUserPref("security.tls.version.max"); + Services.prefs.clearUserPref("security.tls.version.enable-deprecated"); BrowserTestUtils.removeTab(gBrowser.selectedTab); }); diff --git a/browser/locales/en-US/chrome/overrides/netError.dtd b/browser/locales/en-US/chrome/overrides/netError.dtd index e0b0ce9b5bc4..83962a608717 100644 --- a/browser/locales/en-US/chrome/overrides/netError.dtd +++ b/browser/locales/en-US/chrome/overrides/netError.dtd @@ -230,5 +230,9 @@ was trying to connect. --> + + + + The page you are trying to view cannot be shown because an error in the network protocol was detected.

"> diff --git a/browser/themes/shared/aboutNetError.css b/browser/themes/shared/aboutNetError.css index 8f176f2bd7e3..e3c0221e9bc6 100644 --- a/browser/themes/shared/aboutNetError.css +++ b/browser/themes/shared/aboutNetError.css @@ -47,6 +47,10 @@ button:disabled { margin-top: 2em; } +#enableTls10Container { + display: none; +} + #prefChangeContainer { display: none; } diff --git a/toolkit/components/remotepagemanager/MessagePort.jsm b/toolkit/components/remotepagemanager/MessagePort.jsm index ba04f12457d8..fc2b932a8afb 100644 --- a/toolkit/components/remotepagemanager/MessagePort.jsm +++ b/toolkit/components/remotepagemanager/MessagePort.jsm @@ -56,9 +56,10 @@ let RPMAccessManager = { "about:neterror": { getFormatURLPref: ["app.support.baseURL"], getBoolPref: [ - "security.ssl.errorReporting.enabled", - "security.ssl.errorReporting.automatic", "security.certerror.hideAddException", + "security.ssl.errorReporting.automatic", + "security.ssl.errorReporting.enabled", + "security.tls.version.enable-deprecated", ], }, "about:privatebrowsing": { diff --git a/toolkit/modules/AsyncPrefs.jsm b/toolkit/modules/AsyncPrefs.jsm index b7b0118c5631..1a756afbb3dc 100644 --- a/toolkit/modules/AsyncPrefs.jsm +++ b/toolkit/modules/AsyncPrefs.jsm @@ -26,6 +26,8 @@ const kAllowedPrefs = new Set([ "reader.color_scheme", "reader.content_width", "reader.line_height", + + "security.tls.version.enable-deprecated", ]); const kPrefTypeMap = new Map([