Bug 1518208 - Respect network.trr.excluded-domains in TRR-only mode r=dragana

Normally you wouldn't want localhost or *.local domain to be resolved by a
remote resolver.
This patch makes sure that even if we are in TRR-only mode, we still
successfully resolve the domains specified by network.trr.excluded-domains
using native DNS.

Also fixes bug in TRRService::ReadPrefs where we didn't clear mExcludedDomains
before reading the pref.

Differential Revision: https://phabricator.services.mozilla.com/D24380

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Valentin Gosu 2019-03-28 13:15:05 +00:00
parent 99cb87981e
commit 785fc97f60
5 changed files with 89 additions and 3 deletions

View File

@ -5616,7 +5616,7 @@ pref("network.trr.disable-ECS", true);
// After this many failed TRR requests in a row, consider TRR borked
pref("network.trr.max-fails", 5);
// Comma separated list of domains that we should not use TRR for
pref("network.trr.excluded-domains", "");
pref("network.trr.excluded-domains", "localhost,local");
pref("captivedetect.canonicalURL", "http://detectportal.firefox.com/success.txt");
pref("captivedetect.canonicalContent", "success\n");

View File

@ -268,10 +268,12 @@ nsresult TRRService::ReadPrefs(const char *name) {
nsAutoCString excludedDomains;
Preferences::GetCString(TRR_PREF("excluded-domains"), excludedDomains);
mExcludedDomains.Clear();
nsCCharSeparatedTokenizer tokenizer(
excludedDomains, ',', nsCCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
while (tokenizer.hasMoreTokens()) {
nsAutoCString token(tokenizer.nextToken());
LOG(("TRRService::ReadPrefs excluded-domains host:[%s]\n", token.get()));
mExcludedDomains.PutEntry(token);
}
}
@ -508,6 +510,28 @@ bool TRRService::IsTRRBlacklisted(const nsACString &aHost,
return false;
}
bool TRRService::IsExcludedFromTRR(const nsACString &aHost) {
if (mExcludedDomains.GetEntry(aHost)) {
LOG(("Host [%s] Is Excluded From TRR via pref\n", aHost.BeginReading()));
return true;
}
int32_t dot = aHost.FindChar('.');
if (dot != kNotFound) {
// there was a dot, check the parent first
dot++;
nsDependentCSubstring domain = Substring(aHost, dot, aHost.Length() - dot);
nsAutoCString check(domain);
// recursively check the domain part of this name
if (IsExcludedFromTRR(check)) {
return true;
}
}
return false;
}
class ProxyBlacklist : public Runnable {
public:
ProxyBlacklist(TRRService *service, const nsACString &aHost,

View File

@ -52,6 +52,7 @@ class TRRService : public nsIObserver,
bool IsTRRBlacklisted(const nsACString &aHost,
const nsACString &aOriginSuffix, bool aPrivateBrowsing,
bool aParentsToo);
bool IsExcludedFromTRR(const nsACString &aHost);
bool MaybeBootstrap(const nsACString &possible, nsACString &result);
enum TrrOkay { OKAY_NORMAL = 0, OKAY_TIMEOUT = 1, OKAY_BAD = 2 };

View File

@ -1433,12 +1433,22 @@ nsresult nsHostResolver::NameLookup(nsHostRecord *rec) {
mode = MODE_NATIVEONLY;
}
if (!TRR_DISABLED(mode)) {
// For domains that are excluded from TRR we fallback to NativeLookup.
// This happens even in MODE_TRRONLY.
// By default localhost and local are excluded (so we cover *.local hosts)
// See the network.trr.excluded-domains pref.
bool skipTRR = true;
if (gTRRService) {
skipTRR = gTRRService->IsExcludedFromTRR(rec->host);
}
if (!TRR_DISABLED(mode) && !skipTRR) {
rv = TrrLookup(rec);
}
if ((mode == MODE_PARALLEL) || TRR_DISABLED(mode) || (mode == MODE_SHADOW) ||
((mode == MODE_TRRFIRST) && NS_FAILED(rv))) {
((mode == MODE_TRRFIRST) && NS_FAILED(rv)) ||
(mode == MODE_TRRONLY && skipTRR)) {
if (!rec->IsAddrRecord()) {
return rv;
}

View File

@ -485,6 +485,53 @@ function test24c()
listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
}
// TRR-only check that localhost doesn't work if not in the excluded-domains list
function test25()
{
dns.clearCache(true);
prefs.setIntPref("network.trr.mode", 3); // TRR-only
prefs.setCharPref("network.trr.excluded-domains", "");
prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip");
test_answer = "127.0.0.1";
listen = dns.asyncResolve("localhost", 0, listenerFails, mainThread, defaultOriginAttributes);
}
// TRR-only check that localhost goes directly to native lookup when in the excluded-domains
function test25b()
{
dns.clearCache(true);
prefs.setIntPref("network.trr.mode", 3); // TRR-only
prefs.setCharPref("network.trr.excluded-domains", "localhost");
prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip");
test_answer = "127.0.0.1";
listen = dns.asyncResolve("localhost", 0, listenerFine, mainThread, defaultOriginAttributes);
}
// TRR-only check that test.local is resolved via native DNS
function test25c()
{
dns.clearCache(true);
prefs.setIntPref("network.trr.mode", 3); // TRR-only
prefs.setCharPref("network.trr.excluded-domains", "localhost,local");
prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip");
test_answer = "127.0.0.1";
listen = dns.asyncResolve("test.local", 0, listenerFine, mainThread, defaultOriginAttributes);
}
function test25d()
{
dns.clearCache(true);
prefs.setIntPref("network.trr.mode", 3); // TRR-only
prefs.setCharPref("network.trr.excluded-domains", "localhost,local,other");
prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip");
test_answer = "127.0.0.1";
listen = dns.asyncResolve("domain.other", 0, listenerFine, mainThread, defaultOriginAttributes);
}
var tests = [ test1,
test1b,
test2,
@ -515,6 +562,10 @@ var tests = [ test1,
test24,
test24b,
test24c,
test25,
test25b,
test25c,
test25d,
testsDone
];