Bug 1264117 - Limit length of hostnames to 253 characters r=nhnt11,necko-reviewers,dragana

Differential Revision: https://phabricator.services.mozilla.com/D105609
This commit is contained in:
Valentin Gosu 2021-02-19 17:02:34 +00:00
parent a570dfc9d1
commit c33fe1fe47
5 changed files with 115 additions and 0 deletions

View File

@ -8555,6 +8555,14 @@
value: false
mirror: always
# When this pref is true we enforce a 253 character limit on domains we try to
# resolve. See bug 1264117. If it doesn't cause any web-compat issues we can
# remove it in a few releases
- name: network.dns.limit_253_chars
type: RelaxedAtomicBool
value: true
mirror: always
# The proxy type. See nsIProtocolProxyService.idl
# PROXYCONFIG_DIRECT = 0
# PROXYCONFIG_MANUAL = 1

View File

@ -864,6 +864,12 @@ void net_ParseRequestContentType(const nsACString& aHeaderStr,
}
bool net_IsValidHostName(const nsACString& host) {
// A DNS name is limited to 255 bytes on the wire.
// In practice this means the host name is limited to 253 ascii characters.
if (StaticPrefs::network_dns_limit_253_chars() && host.Length() > 253) {
return false;
}
const char* end = host.EndReading();
// Use explicit whitelists to select which characters we are
// willing to send to lower-level DNS logic. This is more

View File

@ -0,0 +1,17 @@
// Tests that domains longer than 253 characters fail to load when pref is true
add_task(async function test_long_domain_fails() {
Services.prefs.setBoolPref("network.dns.limit_253_chars", true);
let domain = "http://" + "a".repeat(254);
let req = await new Promise(resolve => {
let chan = NetUtil.newChannel({
uri: domain,
loadUsingSystemPrincipal: true,
});
chan.asyncOpen(new ChannelListener(resolve, null, CL_EXPECT_FAILURE));
});
Assert.equal(req.status, Cr.NS_ERROR_UNKNOWN_HOST, "Request should fail");
Services.prefs.clearUserPref("network.dns.limit_253_chars");
});

View File

@ -9,6 +9,10 @@ const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
);
const mainThread = threadManager.currentThread;
const overrideService = Cc[
"@mozilla.org/network/native-dns-override;1"
].getService(Ci.nsINativeDNSResolverOverride);
class Listener {
constructor() {
this.promise = new Promise(resolve => {
@ -66,3 +70,82 @@ add_task(async function test_idn_cname() {
inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
Assert.equal(inRecord.canonicalName, ACE_IDN, "IDN is returned as punycode");
});
add_task(
{
skip_if: () =>
Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT,
},
async function test_long_domain() {
let listener = new Listener();
let domain = "a".repeat(253);
overrideService.addIPOverride(domain, "1.2.3.4");
dns.asyncResolve(
domain,
Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [, , inStatus] = await listener;
Assert.equal(inStatus, Cr.NS_OK);
listener = new Listener();
domain = "a".repeat(254);
overrideService.addIPOverride(domain, "1.2.3.4");
Services.prefs.setBoolPref("network.dns.limit_253_chars", true);
if (mozinfo.socketprocess_networking) {
// When using the socket process, the call fails asynchronously.
dns.asyncResolve(
domain,
Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [, , inStatus] = await listener;
Assert.equal(inStatus, Cr.NS_ERROR_UNKNOWN_HOST);
} else {
Assert.throws(
() => {
dns.asyncResolve(
domain,
Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
},
/NS_ERROR_UNKNOWN_HOST/,
"Should throw for large domains"
);
}
listener = new Listener();
domain = "a".repeat(254);
Services.prefs.setBoolPref("network.dns.limit_253_chars", false);
dns.asyncResolve(
domain,
Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
[, , inStatus] = await listener;
Assert.equal(inStatus, Cr.NS_OK);
Services.prefs.clearUserPref("network.dns.limit_253_chars");
overrideService.clearOverrides();
}
);

View File

@ -181,6 +181,7 @@ skip-if = bits != 32
[test_cache_jar.js]
[test_cache-entry-id.js]
[test_channel_close.js]
[test_channel_long_domain.js]
[test_compareURIs.js]
[test_compressappend.js]
[test_content_encoding_gzip.js]