summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoranonym <anonym@riseup.net>2019-02-27 09:30:10 +0100
committeranonym <anonym@riseup.net>2019-04-05 16:10:28 +0200
commitd09c62238cf786b9bb4d24dc8c30e3448926afa1 (patch)
treea7733fa5b8b9be943cc1e344b2acbe5259b755e1
parentafe31d9f1f93cd7d9b13cecae5f5290c7cd5ab57 (diff)
Add various security improvements to account auto-configuration.secure_account_creation-66.0_b1_squashed
* Also fetch ISP configuration using SSL, and prefer them over plaintext. * Support ISPs who only serve .well-known over SSL. This slightly increases defenses against passive attackers (who could snoop your username [0]), but for active attackers the "downgrade" attack that forces plaintext is trivial: just block all SSL traffic and then manipulate the HTTP traffic. In other words, a Man-in-the-middle can easily get full control over the client configuration. It would be reasonable to only do SSL by default, but it is not an option in certain enterprise deployments, so instead we allow security-focused distributions (and extensions like TorBirdy) to control the behavior via a new boolean pref: mailnews.auto_config.ssl_only_config_servers When set to true ISP fetches are done using SSL only, but it defaults to false which allows insecure fetches as well. [0] See the mailnews.auto_config.fetchFromISP.sendEmailAddress pref. * Make use of non-SSL Exchange AutoDiscover methods optional. If an attacker does a MitM they can presumably modify the Exchange server's HTTP response to redirect to an attacker controller Exchange server instead. So let's provide protection against this via the mailnews.auto_config.ssl_only_config_servers pref. * Add pref for whether we accept OAuth2 during autoconfiguration. For many providers JavaScript is required for OAuth2 to work; with it disabled autoconfiguration then result in a terrible UX (e.g. the web login fails, has to manually alter the authentication method). Let's provide a pref that discards OAuth2 configurations so e.g. extensions that disables JavaScript (like TorBirdy) can provide a workaround. * Add SOCKS proxy support for account guessing. Any configured SOCKS proxy will be used while probing servers, but HTTP(s) proxies etc will be ignored since they are not applicable. This solves Mozilla bug #669238: https://bugzilla.mozilla.org/show_bug.cgi?id=669238 * Add pref for setting the autoconfiguration guess timeout. The static 10 seconds is not enough for Tor users (delay spikes of 10 seconds is not uncommon), so let's make it possible for the TorBirdy extension to override this timeout. * Add pref for whether to accept plaintext protocols during autoconfiguration. Let's make it possible for security-focused distributions (and extensions like TorBirdy) to prevent insecure configurations to ever be displayed to users; for other users there is a warning explaining the consequences of accepting a non-SSL configuration. * Bugfix: invalidate config when restarting autoconfiguration. Otherwise residual data from previous attempts can leak into following attempts, e.g.: 1. Try "a@a.a" 2. All methods fail, so we end up in "manual edit" mode 3. Note that Server hostname == "a.a", which is expected 4. Then start over by changing the email to "b@b.b" 5. All methods fail, so we end up in "manual edit" mode 6. Note that Server hostname == "a.a", but should be "b.b"
-rw-r--r--comm/mail/components/accountcreation/content/emailWizard.js62
-rw-r--r--comm/mail/components/accountcreation/content/exchangeAutoDiscover.js12
-rw-r--r--comm/mail/components/accountcreation/content/fetchConfig.js32
-rw-r--r--comm/mail/components/accountcreation/content/guessConfig.js93
-rw-r--r--comm/mail/components/accountcreation/content/readFromXML.js36
-rw-r--r--comm/mailnews/mailnews.js27
6 files changed, 174 insertions, 88 deletions
diff --git a/comm/mail/components/accountcreation/content/emailWizard.js b/comm/mail/components/accountcreation/content/emailWizard.js
index 16e1991..8d357a2 100644
--- a/comm/mail/components/accountcreation/content/emailWizard.js
+++ b/comm/mail/components/accountcreation/content/emailWizard.js
@@ -411,6 +411,7 @@ EmailConfigWizard.prototype = {
* Start from beginning with possibly new email address.
*/
onStartOver() {
+ this._currentConfig = null;
if (this._abortable) {
this.onStop();
}
@@ -658,8 +659,9 @@ EmailConfigWizard.prototype = {
var self = this;
self._abortable = guessConfig(domain,
function(type, hostname, port, ssl, done, config) { // progress
- gEmailWizardLogger.info("progress callback host " + hostname +
- " port " + port + " type " + type);
+ var msg = hostname + ":" + port + " ssl=" + ssl + " " +
+ type + ": progress callback";
+ gEmailWizardLogger.info(msg);
},
function(config) { // success
self._abortable = null;
@@ -1194,19 +1196,21 @@ EmailConfigWizard.prototype = {
}
this.fillPortDropdown(config.incoming.type);
- // If the hostname supports OAuth2 and imap is enabled, enable OAuth2.
- let iDetails = OAuth2Providers.getHostnameDetails(config.incoming.hostname);
- if (iDetails) {
- gEmailWizardLogger.info("OAuth2 details for incoming server " +
- config.incoming.hostname + " is " + iDetails);
- }
- e("in-authMethod-oauth2").hidden = !(iDetails && e("incoming_protocol").value == 1);
- if (!e("in-authMethod-oauth2").hidden) {
- config.oauthSettings = {};
- [config.oauthSettings.issuer, config.oauthSettings.scope] = iDetails;
- // oauthsettings are not stored nor changeable in the user interface, so just
- // store them in the base configuration.
- this._currentConfig.oauthSettings = config.oauthSettings;
+ if (Services.prefs.getBoolPref("mailnews.auto_config.allow_oauth2")) {
+ // If the hostname supports OAuth2 and imap is enabled, enable OAuth2.
+ let iDetails = OAuth2Providers.getHostnameDetails(config.incoming.hostname);
+ if (iDetails) {
+ gEmailWizardLogger.info("OAuth2 details for incoming server " +
+ config.incoming.hostname + " is " + iDetails);
+ }
+ e("in-authMethod-oauth2").hidden = !(iDetails && e("incoming_protocol").value == 1);
+ if (!e("in-authMethod-oauth2").hidden) {
+ config.oauthSettings = {};
+ [config.oauthSettings.issuer, config.oauthSettings.scope] = iDetails;
+ // oauthsettings are not stored nor changeable in the user interface, so just
+ // store them in the base configuration.
+ this._currentConfig.oauthSettings = config.oauthSettings;
+ }
}
// outgoing server
@@ -1225,19 +1229,21 @@ EmailConfigWizard.prototype = {
this.adjustOutgoingPortToSSLAndProtocol(config);
}
- // If the hostname supports OAuth2 and imap is enabled, enable OAuth2.
- let oDetails = OAuth2Providers.getHostnameDetails(config.outgoing.hostname);
- if (oDetails) {
- gEmailWizardLogger.info("OAuth2 details for outgoing server " +
- config.outgoing.hostname + " is " + oDetails);
- }
- e("out-authMethod-oauth2").hidden = !oDetails;
- if (!e("out-authMethod-oauth2").hidden) {
- config.oauthSettings = {};
- [config.oauthSettings.issuer, config.oauthSettings.scope] = oDetails;
- // oauthsettings are not stored nor changeable in the user interface, so just
- // store them in the base configuration.
- this._currentConfig.oauthSettings = config.oauthSettings;
+ if (Services.prefs.getBoolPref("mailnews.auto_config.allow_oauth2")) {
+ // If the hostname supports OAuth2 and imap is enabled, enable OAuth2.
+ let oDetails = OAuth2Providers.getHostnameDetails(config.outgoing.hostname);
+ if (oDetails) {
+ gEmailWizardLogger.info("OAuth2 details for outgoing server " +
+ config.outgoing.hostname + " is " + oDetails);
+ }
+ e("out-authMethod-oauth2").hidden = !oDetails;
+ if (!e("out-authMethod-oauth2").hidden) {
+ config.oauthSettings = {};
+ [config.oauthSettings.issuer, config.oauthSettings.scope] = oDetails;
+ // oauthsettings are not stored nor changeable in the user interface, so just
+ // store them in the base configuration.
+ this._currentConfig.oauthSettings = config.oauthSettings;
+ }
}
// populate fields even if existingServerKey, in case user changes back
diff --git a/comm/mail/components/accountcreation/content/exchangeAutoDiscover.js b/comm/mail/components/accountcreation/content/exchangeAutoDiscover.js
index 7ca516e..6da4376 100644
--- a/comm/mail/components/accountcreation/content/exchangeAutoDiscover.js
+++ b/comm/mail/components/accountcreation/content/exchangeAutoDiscover.js
@@ -98,11 +98,13 @@ function fetchConfigFromExchange(domain, emailAddress, username, password,
fetch.start();
call.setAbortable(fetch);
- call = priority.addCall();
- fetch3 = new FetchHTTP(url3, callArgs,
- call.successCallback(), call.errorCallback());
- fetch3.start();
- call.setAbortable(fetch3);
+ if (!Services.prefs.getBoolPref("mailnews.auto_config.ssl_only_config_servers")) {
+ call = priority.addCall();
+ fetch3 = new FetchHTTP(url3, callArgs,
+ call.successCallback(), call.errorCallback());
+ fetch3.start();
+ call.setAbortable(fetch3);
+ }
// url3 is an HTTP URL that will redirect to the real one, usually a HTTPS
// URL of the hoster. XMLHttpRequest unfortunately loses the call
diff --git a/comm/mail/components/accountcreation/content/fetchConfig.js b/comm/mail/components/accountcreation/content/fetchConfig.js
index a794c8b..3085bbf 100644
--- a/comm/mail/components/accountcreation/content/fetchConfig.js
+++ b/comm/mail/components/accountcreation/content/fetchConfig.js
@@ -63,11 +63,16 @@ function fetchConfigFromISP(domain, emailAddress, successCallback,
return new Abortable();
}
- let url1 = "http://autoconfig." + sanitize.hostname(domain) +
- "/mail/config-v1.1.xml";
+ let conf1 = "autoconfig." + sanitize.hostname(domain) +
+ "/mail/config-v1.1.xml";
// .well-known/ <http://tools.ietf.org/html/draft-nottingham-site-meta-04>
- let url2 = "http://" + sanitize.hostname(domain) +
- "/.well-known/autoconfig/mail/config-v1.1.xml";
+ let conf2 = sanitize.hostname(domain) +
+ "/.well-known/autoconfig/mail/config-v1.1.xml";
+ // This list is sorted by decreasing priority
+ var urls = ["https://" + conf1, "https://" + conf2];
+ if (!Services.prefs.getBoolPref("mailnews.auto_config.ssl_only_config_servers")) {
+ urls.push("http://" + conf1, "http://" + conf2);
+ }
let callArgs = {
urlArgs: {
emailaddress: emailAddress,
@@ -83,18 +88,13 @@ function fetchConfigFromISP(domain, emailAddress, successCallback,
let priority = new PriorityOrderAbortable(
xml => successCallback(readFromXML(xml)),
errorCallback);
-
- call = priority.addCall();
- fetch = new FetchHTTP(url1, callArgs,
- call.successCallback(), call.errorCallback());
- call.setAbortable(fetch);
- fetch.start();
-
- call = priority.addCall();
- fetch = new FetchHTTP(url2, callArgs,
- call.successCallback(), call.errorCallback());
- call.setAbortable(fetch);
- fetch.start();
+ for (let url of urls) {
+ call = priority.addCall();
+ fetch = new FetchHTTP(url, callArgs,
+ call.successCallback(), call.errorCallback());
+ call.setAbortable(fetch);
+ fetch.start();
+ }
return priority;
}
diff --git a/comm/mail/components/accountcreation/content/guessConfig.js b/comm/mail/components/accountcreation/content/guessConfig.js
index b76deaa..e194e58 100644
--- a/comm/mail/components/accountcreation/content/guessConfig.js
+++ b/comm/mail/components/accountcreation/content/guessConfig.js
@@ -8,8 +8,6 @@
var { Log4Moz } = ChromeUtils.import("resource:///modules/gloda/log4moz.js", null);
ChromeUtils.import("resource://gre/modules/Services.jsm");
-var TIMEOUT = 10; // in seconds
-
// This is a bit ugly - we set outgoingDone to false
// when emailWizard.js cancels the outgoing probe because the user picked
// an outoing server. It does this by poking the probeAbortable object,
@@ -387,6 +385,7 @@ HostDetector.prototype = {
{ "imap": IMAP, "pop3": POP, "smtp": SMTP }, UNKNOWN);
if (!port)
port = UNKNOWN;
+ var ssl_only = Services.prefs.getBoolPref("mailnews.auto_config.ssl_only_mail_servers");
var ssl = ConvertSocketTypeToSSL(socketType);
this._cancel = false;
this._log.info("doing auto detect for protocol " + protocol +
@@ -408,8 +407,13 @@ HostDetector.prototype = {
let hostEntries = this._portsToTry(hostname, protocol, ssl, port);
for (let j = 0; j < hostEntries.length; j++) {
let hostTry = hostEntries[j]; // from getHostEntry()
+ if (ssl_only && hostTry.ssl == NONE)
+ continue;
hostTry.hostname = hostname;
hostTry.status = kNotTried;
+ hostTry.desc = hostTry.hostname + ":" + hostTry.port +
+ " ssl=" + hostTry.ssl + " " +
+ protocolToString(hostTry.protocol);
this._hostsToTry.push(hostTry);
}
}
@@ -426,34 +430,57 @@ HostDetector.prototype = {
if (this._cancel)
return;
var me = this;
+ var timeout = Services.prefs.getIntPref("mailnews.auto_config.guess.timeout");
for (let i = 0; i < this._hostsToTry.length; i++) {
let thisTry = this._hostsToTry[i]; // {HostTry}
if (thisTry.status != kNotTried)
continue;
- this._log.info("poking at " + thisTry.hostname + " port " +
- thisTry.port + " ssl " + thisTry.ssl + " protocol " +
- protocolToString(thisTry.protocol));
+ this._log.info(thisTry.desc + ": initializing probe...");
if (i == 0) // showing 50 servers at once is pointless
this.mProgressCallback(thisTry);
- thisTry.abortable = SocketUtil(
- thisTry.hostname, thisTry.port, thisTry.ssl,
- thisTry.commands, TIMEOUT,
- new SSLErrorHandler(thisTry, this._log),
- function(wiredata) { // result callback
- if (me._cancel)
- return; // don't use response anymore
- me.mProgressCallback(thisTry);
- me._processResult(thisTry, wiredata);
- me._checkFinished();
- },
- function(e) { // error callback
- if (me._cancel)
- return; // who set cancel to true already called mErrorCallback()
- me._log.warn(e);
- thisTry.status = kFailed;
- me._checkFinished();
- });
+ // This implements the nsIProtocolProxyCallback interface:
+ function ProxyResolveCallback() { }
+ ProxyResolveCallback.prototype = {
+ onProxyAvailable : function(req, uri, proxyInfo, status) {
+ // Anything but a SOCKS proxy will be unusable for the probes.
+ if (proxyInfo != null && proxyInfo.type != "socks" &&
+ proxyInfo.type != "socks4") {
+ proxyInfo = null;
+ }
+ thisTry.abortable = SocketUtil(
+ thisTry.hostname, thisTry.port, thisTry.ssl,
+ thisTry.commands, timeout, proxyInfo,
+ new SSLErrorHandler(thisTry, this._log),
+ function(wiredata) { // result callback
+ if (me._cancel)
+ return; // don't use response anymore
+ me.mProgressCallback(thisTry);
+ me._processResult(thisTry, wiredata);
+ me._checkFinished();
+ },
+ function(e) { // error callback
+ if (me._cancel)
+ return; // who set cancel to true already called mErrorCallback()
+ me._log.warn(thisTry.desc + ": " + e);
+ thisTry.status = kFailed;
+ me._checkFinished();
+ });
+ }
+ };
+
+ var proxyService = Cc["@mozilla.org/network/protocol-proxy-service;1"]
+ .getService(Ci.nsIProtocolProxyService);
+ // Use some arbitrary scheme just because it is required...
+ var uri = Services.io.newURI("http://" + thisTry.hostname, null, null);
+ // ... we'll ignore it any way. We prefer SOCKS since that's the
+ // only thing we can use for email protocols.
+ var proxyFlags = Ci.nsIProtocolProxyService.RESOLVE_IGNORE_URI_SCHEME |
+ Ci.nsIProtocolProxyService.RESOLVE_PREFER_SOCKS_PROXY;
+ if (Services.prefs.getBoolPref("network.proxy.socks_remote_dns")) {
+ proxyFlags |= Ci.nsIProtocolProxyService.RESOLVE_ALWAYS_TUNNEL;
+ }
+ proxyService.asyncResolve(uri, proxyFlags, new ProxyResolveCallback());
thisTry.status = kOngoing;
}
},
@@ -473,7 +500,7 @@ HostDetector.prototype = {
if (thisTry._gotCertError == Ci.nsICertOverrideService.ERROR_UNTRUSTED ||
thisTry._gotCertError == Ci.nsICertOverrideService.ERROR_TIME) {
- this._log.info("TRYING AGAIN, hopefully with exception recorded");
+ this._log.info(thisTry.desc + ": TRYING AGAIN, hopefully with exception recorded");
thisTry._gotCertError = 0;
thisTry.selfSignedCert = true; // _next_ run gets this exception
thisTry.status = kNotTried; // try again (with exception)
@@ -483,21 +510,19 @@ HostDetector.prototype = {
}
if (wiredata == null || wiredata === undefined) {
- this._log.info("no data");
+ this._log.info(thisTry.desc + ": no data");
thisTry.status = kFailed;
return;
}
- this._log.info("wiredata: " + wiredata.join(""));
+ this._log.info(thisTry.desc + ": wiredata: " + wiredata.join(""));
thisTry.authMethods =
this._advertisesAuthMethods(thisTry.protocol, wiredata);
if (thisTry.ssl == TLS && !this._hasTLS(thisTry, wiredata)) {
- this._log.info("STARTTLS wanted, but not offered");
+ this._log.info(thisTry.desc + ": STARTTLS wanted, but not offered");
thisTry.status = kFailed;
return;
}
- this._log.info("success with " + thisTry.hostname + ":" +
- thisTry.port + " " + protocolToString(thisTry.protocol) +
- " ssl " + thisTry.ssl +
+ this._log.info(thisTry.desc + ": success" +
(thisTry.selfSignedCert ? " (selfSignedCert)" : ""));
thisTry.status = kSuccess;
@@ -506,7 +531,8 @@ HostDetector.prototype = {
// earlier we get into an infinite loop, probably because the cert
// remembering is temporary and the next try gets a new connection which
// isn't covered by that temporariness.
- this._log.info("clearing validity override for " + thisTry.hostname);
+ this._log.info(thisTry.desc + ": clearing validity override for " +
+ thisTry.hostname);
Cc["@mozilla.org/security/certoverride;1"]
.getService(Ci.nsICertOverrideService)
.clearValidityOverride(thisTry.hostname, thisTry.port);
@@ -937,13 +963,14 @@ SSLErrorHandler.prototype = {
* @param commands {Array of String}: protocol commands
* to send to the server.
* @param timeout {Integer} seconds to wait for a server response, then cancel.
+ * @param proxy {nsIProxyInfo} The proxy to use (or null to not use any).
* @param sslErrorHandler {SSLErrorHandler}
* @param resultCallback {function(wiredata)} This function will
* be called with the result string array from the server
* or null if no communication occurred.
* @param errorCallback {function(e)}
*/
-function SocketUtil(hostname, port, ssl, commands, timeout,
+function SocketUtil(hostname, port, ssl, commands, timeout, proxy,
sslErrorHandler, resultCallback, errorCallback) {
assert(commands && commands.length, "need commands");
@@ -984,7 +1011,7 @@ function SocketUtil(hostname, port, ssl, commands, timeout,
}
var transport = transportService.createTransport([socketTypeName],
ssl == NONE ? 0 : 1,
- hostname, port, null);
+ hostname, port, proxy);
transport.setTimeout(Ci.nsISocketTransport.TIMEOUT_CONNECT, timeout);
transport.setTimeout(Ci.nsISocketTransport.TIMEOUT_READ_WRITE, timeout);
diff --git a/comm/mail/components/accountcreation/content/readFromXML.js b/comm/mail/components/accountcreation/content/readFromXML.js
index 7e486483..7fffddb 100644
--- a/comm/mail/components/accountcreation/content/readFromXML.js
+++ b/comm/mail/components/accountcreation/content/readFromXML.js
@@ -6,6 +6,7 @@
/* import-globals-from emailWizard.js */
var { logException } = ChromeUtils.import("resource:///modules/errUtils.js", null);
+ChromeUtils.import("resource://gre/modules/Services.jsm");
/* eslint-disable complexity */
/**
@@ -26,6 +27,10 @@ function readFromXML(clientConfigXML) {
function array_or_undef(value) {
return value === undefined ? [] : value;
}
+ var allow_oauth2 =
+ Services.prefs.getBoolPref("mailnews.auto_config.allow_oauth2");
+ var ssl_only =
+ Services.prefs.getBoolPref("mailnews.auto_config.ssl_only_mail_servers");
var exception;
if (typeof(clientConfigXML) != "object" ||
!("clientConfig" in clientConfigXML) ||
@@ -74,13 +79,21 @@ function readFromXML(clientConfigXML) {
try {
iO.socketType = sanitize.translate(iXsocketType,
{ plain: 1, SSL: 2, STARTTLS: 3 });
- break; // take first that we support
+
+ if (iO.socketType != 1) {
+ // pick first non-plaintext protocol, if available
+ break;
+ }
} catch (e) { exception = e; }
}
if (!iO.socketType)
throw exception ? exception : "need proper <socketType> in XML";
exception = null;
+ if (ssl_only && iO.socketType == 1) {
+ continue;
+ }
+
for (let iXauth of array_or_undef(iX.$authentication)) {
try {
iO.auth = sanitize.translate(iXauth,
@@ -93,6 +106,12 @@ function readFromXML(clientConfigXML) {
"GSSAPI": Ci.nsMsgAuthMethod.GSSAPI,
"NTLM": Ci.nsMsgAuthMethod.NTLM,
"OAuth2": Ci.nsMsgAuthMethod.OAuth2 });
+
+ if (!allow_oauth2 && iO.auth == Ci.nsMsgAuthMethod.OAuth2) {
+ iO.auth = null;
+ continue;
+ }
+
break; // take first that we support
} catch (e) { exception = e; }
}
@@ -144,13 +163,21 @@ function readFromXML(clientConfigXML) {
try {
oO.socketType = sanitize.translate(oXsocketType,
{ plain: 1, SSL: 2, STARTTLS: 3 });
- break; // take first that we support
+
+ if (oO.socketType != 1) {
+ // pick first non-plaintext protocol, if available
+ break;
+ }
} catch (e) { exception = e; }
}
if (!oO.socketType)
throw exception ? exception : "need proper <socketType> in XML";
exception = null;
+ if (ssl_only && oO.socketType == 1) {
+ continue;
+ }
+
for (let oXauth of array_or_undef(oX.$authentication)) {
try {
oO.auth = sanitize.translate(oXauth,
@@ -171,6 +198,11 @@ function readFromXML(clientConfigXML) {
"OAuth2": Ci.nsMsgAuthMethod.OAuth2,
});
+ if (!allow_oauth2 && oO.auth == Ci.nsMsgAuthMethod.OAuth2) {
+ oO.auth = null;
+ continue;
+ }
+
break; // take first that we support
} catch (e) { exception = e; }
}
diff --git a/comm/mailnews/mailnews.js b/comm/mailnews/mailnews.js
index 7f7d571..4a06010 100644
--- a/comm/mailnews/mailnews.js
+++ b/comm/mailnews/mailnews.js
@@ -901,17 +901,36 @@ pref("mailnews.auto_config_url", "https://live.thunderbird.net/autoconfig/v1.1/"
pref("mailnews.mx_service_url", "https://live.thunderbird.net/dns/mx/");
// The list of addons which can handle certain account types
pref("mailnews.auto_config.addons_url", "https://live.thunderbird.net/autoconfig/addons.json");
-// Allow to contact ISP (email address domain)
-// This happens via insecure means (HTTP), so the config cannot be trusted,
-// and also contains the email address
+// Whether to contact the ISP (email address domain).
+// This may happen via insecure means (HTTP) susceptible to eavesdropping and MitM.
pref("mailnews.auto_config.fetchFromISP.enabled", true);
-// Allow the fetch from ISP via HTTP, but not the email address
+// Whether we tell the ISP our username. Note that the username will
+// leak in plaintext if a non-SSL fetch is performed.
pref("mailnews.auto_config.fetchFromISP.sendEmailAddress", true);
// Allow the Microsoft Exchange AutoDiscover protocol.
// This also sends the email address and password to the server,
// which the protocol unfortunately requires in practice.
pref("mailnews.auto_config.fetchFromExchange.enabled", true);
+// Whether we will only allow SSL channels when fetching ISP configs
+// or using the Microsoft Exchange AutoDiscover protocol.
+// When false an active attacker can block non-SSL fetches and then
+// MitM the HTTP fetch, granting the attacker full control over the
+// client configuration.
+pref("mailnews.auto_config.ssl_only_config_servers", false);
+// Whether we will attempt to guess the account configuration based on
+// protocol default ports and common domain practices
+// (e.g. {mail,pop,imap,smtp}.<email-domain>).
pref("mailnews.auto_config.guess.enabled", true);
+// The timeout (in seconds) for each guess
+pref("mailnews.auto_config.guess.timeout", 10);
+// Whether we allow fetched configurations using OAuth2.
+pref("mailnews.auto_config.allow_oauth2", true);
+// Whether we allow fetched account configurations that employs
+// non-SSL/TLS protocols. With this option set, insecure
+// configurations are never presented to the user; with this option
+// unset, users picking an insecure configuration will get a warning
+// and have to opt-in.
+pref("mailnews.auto_config.ssl_only_mail_servers", false);
// Work around bug 1454325 by disabling mimetype mungling in XmlHttpRequest
pref("dom.xhr.standard_content_type_normalization", false);