diff options
4 files changed, 42 insertions, 20 deletions
diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index 3feeef9b6..4e753d422 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -2661,6 +2661,11 @@ function getWebNavigation() } function BrowserReloadWithFlags(reloadFlags) { + + // Reset DOS mitigation for auth prompts when user initiates a reload. + let browser = gBrowser.selectedBrowser; + delete browser.authPromptCounter; + /* First, we'll try to use the session history object to reload so * that framesets are handled properly. If we're in a special * window (such as view-source) that has no session history, fall diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml index 988cae55c..c3b4872db 100644 --- a/application/palemoon/base/content/tabbrowser.xml +++ b/application/palemoon/base/content/tabbrowser.xml @@ -2458,7 +2458,10 @@ <parameter name="aTab"/> <body> <![CDATA[ - this.getBrowserForTab(aTab).reload(); + let browser = this.getBrowserForTab(aTab); + // Reset DOS mitigation for basic auth prompt + delete browser.authPromptCounter; + browser.reload(); ]]> </body> </method> diff --git a/application/palemoon/base/content/urlbarBindings.xml b/application/palemoon/base/content/urlbarBindings.xml index d188e6658..d2d9cc720 100644 --- a/application/palemoon/base/content/urlbarBindings.xml +++ b/application/palemoon/base/content/urlbarBindings.xml @@ -302,6 +302,10 @@ // but don't let that interfere with the loading of the url. Cu.reportError(ex); } + + // Reset DOS mitigations for the basic auth prompt. + let browser = gBrowser.selectedBrowser; + delete browser.authPromptCounter; function loadCurrent() { let flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; diff --git a/toolkit/components/passwordmgr/nsLoginManagerPrompter.js b/toolkit/components/passwordmgr/nsLoginManagerPrompter.js index 720e80446..35315110c 100644 --- a/toolkit/components/passwordmgr/nsLoginManagerPrompter.js +++ b/toolkit/components/passwordmgr/nsLoginManagerPrompter.js @@ -97,17 +97,25 @@ LoginManagerPromptFactory.prototype = { return; } - // Allow only a limited number of authentication dialogs when they are all - // canceled by the user. - var cancelationCounter = (prompter._browser && prompter._browser.canceledAuthenticationPromptCounter) || { count: 0, id: 0 }; - if (prompt.channel) { - var httpChannel = prompt.channel.QueryInterface(Ci.nsIHttpChannel); - if (httpChannel) { - var windowId = httpChannel.topLevelContentWindowId; - if (windowId != cancelationCounter.id) { - // window has been reloaded or navigated, reset the counter - cancelationCounter = { count: 0, id: windowId }; - } + // Set up a counter for ensuring that the basic auth prompt can not + // be abused for DOS-style attacks. With this counter, each eTLD+1 + // per browser will get a limited number of times a user can + // cancel the prompt until we stop showing it. + let browser = prompter._browser; + let baseDomain = null; + if (browser) { + try { + baseDomain = Services.eTLD.getBaseDomainFromHost(hostname); + } catch (e) { + baseDomain = hostname; + } + + if (!browser.authPromptCounter) { + browser.authPromptCounter = {}; + } + + if (!browser.authPromptCounter[baseDomain]) { + browser.authPromptCounter[baseDomain] = 0; } } @@ -137,13 +145,14 @@ LoginManagerPromptFactory.prototype = { prompt.inProgress = false; self._asyncPromptInProgress = false; - if (ok) { - cancelationCounter.count = 0; - } else { - cancelationCounter.count++; - } - if (prompter._browser) { - prompter._browser.canceledAuthenticationPromptCounter = cancelationCounter; + if (browser) { + // Reset the counter state if the user replied to a prompt and actually + // tried to login (vs. simply clicking any button to get out). + if (ok && (prompt.authInfo.username || prompt.authInfo.password)) { + browser.authPromptCounter[baseDomain] = 0; + } else { + browser.authPromptCounter[baseDomain] += 1; + } } } @@ -168,8 +177,9 @@ LoginManagerPromptFactory.prototype = { var cancelDialogLimit = Services.prefs.getIntPref("prompts.authentication_dialog_abuse_limit"); + let cancelationCounter = browser.authPromptCounter[baseDomain]; this.log("cancelationCounter =", cancelationCounter); - if (cancelDialogLimit && cancelationCounter.count >= cancelDialogLimit) { + if (cancelDialogLimit && cancelationCounter >= cancelDialogLimit) { this.log("Blocking auth dialog, due to exceeding dialog bloat limit"); delete this._asyncPrompts[hashKey]; |