Bug 1361099 - provide a way to map all dns to constant r?valentin
// When non empty all non-localhost DNS queries (including IP addresses)
// resolve to this value. The value can be a name or an IP address.
// domains mapped to localhost with localDomains stay localhost.
pref("network.dns.forceResolve", "");
Testing is the primary use case here - replay captive data on a 'fake
server' by directing all traffic to it at the DNS level. Chrome has
something similar.
MozReview-Commit-ID: 7AOgQZpZKec
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1913,16 +1913,21 @@ pref("network.dns.disablePrefetch", fals
// This preference controls whether .onion hostnames are
// rejected before being given to DNS. RFC 7686
pref("network.dns.blockDotOnion", true);
// These domains are treated as localhost equivalent
pref("network.dns.localDomains", "");
+// When non empty all non-localhost DNS queries (including IP addresses)
+// resolve to this value. The value can be a name or an IP address.
+// domains mapped to localhost with localDomains stay localhost.
+pref("network.dns.forceResolve", "");
+
// Contols whether or not "localhost" should resolve when offline
pref("network.dns.offline-localhost", true);
// The maximum allowed length for a URL - 1MB default
pref("network.standard-url.max-length", 1048576);
// The preference controls if the rust URL parser is run in parallel with the
// C++ implementation. Requires restart for changes to take effect.
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -45,16 +45,17 @@ using namespace mozilla::net;
static const char kPrefDnsCacheEntries[] = "network.dnsCacheEntries";
static const char kPrefDnsCacheExpiration[] = "network.dnsCacheExpiration";
static const char kPrefDnsCacheGrace[] = "network.dnsCacheExpirationGracePeriod";
static const char kPrefIPv4OnlyDomains[] = "network.dns.ipv4OnlyDomains";
static const char kPrefDisableIPv6[] = "network.dns.disableIPv6";
static const char kPrefDisablePrefetch[] = "network.dns.disablePrefetch";
static const char kPrefBlockDotOnion[] = "network.dns.blockDotOnion";
static const char kPrefDnsLocalDomains[] = "network.dns.localDomains";
+static const char kPrefDnsForceResolve[] = "network.dns.forceResolve";
static const char kPrefDnsOfflineLocalhost[] = "network.dns.offline-localhost";
static const char kPrefDnsNotifyResolution[] = "network.dns.notifyResolution";
//-----------------------------------------------------------------------------
class nsDNSRecord : public nsIDNSRecord
{
public:
@@ -477,16 +478,17 @@ private:
nsDNSService::nsDNSService()
: mLock("nsDNSServer.mLock")
, mDisableIPv6(false)
, mDisablePrefetch(false)
, mFirstTime(true)
, mNotifyResolution(false)
, mOfflineLocalhost(false)
+ , mForceResolveOn(false)
{
}
nsDNSService::~nsDNSService() = default;
NS_IMPL_ISUPPORTS(nsDNSService, nsIDNSService, nsPIDNSService, nsIObserver,
nsIMemoryReporter)
@@ -541,32 +543,34 @@ nsDNSService::Init()
bool offlineLocalhost = true;
bool disablePrefetch = false;
bool blockDotOnion = true;
int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT;
bool notifyResolution = false;
nsAdoptingCString ipv4OnlyDomains;
nsAdoptingCString localDomains;
+ nsAdoptingCString forceResolve;
// read prefs
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
int32_t val;
if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheEntries, &val)))
maxCacheEntries = (uint32_t) val;
if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheExpiration, &val)))
defaultCacheLifetime = val;
if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheGrace, &val)))
defaultGracePeriod = val;
// ASSUMPTION: pref branch does not modify out params on failure
prefs->GetBoolPref(kPrefDisableIPv6, &disableIPv6);
prefs->GetCharPref(kPrefIPv4OnlyDomains, getter_Copies(ipv4OnlyDomains));
prefs->GetCharPref(kPrefDnsLocalDomains, getter_Copies(localDomains));
+ prefs->GetCharPref(kPrefDnsForceResolve, getter_Copies(forceResolve));
prefs->GetBoolPref(kPrefDnsOfflineLocalhost, &offlineLocalhost);
prefs->GetBoolPref(kPrefDisablePrefetch, &disablePrefetch);
prefs->GetBoolPref(kPrefBlockDotOnion, &blockDotOnion);
// If a manual proxy is in use, disable prefetch implicitly
prefs->GetIntPref("network.proxy.type", &proxyType);
prefs->GetBoolPref(kPrefDnsNotifyResolution, ¬ifyResolution);
@@ -574,16 +578,17 @@ nsDNSService::Init()
mFirstTime = false;
// register as prefs observer
prefs->AddObserver(kPrefDnsCacheEntries, this, false);
prefs->AddObserver(kPrefDnsCacheExpiration, this, false);
prefs->AddObserver(kPrefDnsCacheGrace, this, false);
prefs->AddObserver(kPrefIPv4OnlyDomains, this, false);
prefs->AddObserver(kPrefDnsLocalDomains, this, false);
+ prefs->AddObserver(kPrefDnsForceResolve, this, false);
prefs->AddObserver(kPrefDisableIPv6, this, false);
prefs->AddObserver(kPrefDnsOfflineLocalhost, this, false);
prefs->AddObserver(kPrefDisablePrefetch, this, false);
prefs->AddObserver(kPrefBlockDotOnion, this, false);
prefs->AddObserver(kPrefDnsNotifyResolution, this, false);
// Monitor these to see if there is a change in proxy configuration
// If a manual proxy is in use, disable prefetch implicitly
@@ -611,16 +616,18 @@ nsDNSService::Init()
// now, set all of our member variables while holding the lock
MutexAutoLock lock(mLock);
mResolver = res;
mIDN = idn;
mIPv4OnlyDomains = ipv4OnlyDomains; // exchanges buffer ownership
mOfflineLocalhost = offlineLocalhost;
mDisableIPv6 = disableIPv6;
mBlockDotOnion = blockDotOnion;
+ mForceResolve = forceResolve;
+ mForceResolveOn = !mForceResolve.IsEmpty();
// Disable prefetching either by explicit preference or if a manual proxy is configured
mDisablePrefetch = disablePrefetch || (proxyType == nsIProtocolProxyService::PROXYCONFIG_MANUAL);
mLocalDomains.Clear();
if (localDomains) {
nsCCharSeparatedTokenizer tokenizer(localDomains, ',',
nsCCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
@@ -701,16 +708,25 @@ nsDNSService::PreprocessHostname(bool
return NS_ERROR_UNKNOWN_HOST;
}
if (aLocalDomain) {
aACE.AssignLiteral("localhost");
return NS_OK;
}
+ if (mForceResolveOn) {
+ MutexAutoLock lock(mLock);
+ if (!aInput.LowerCaseEqualsASCII("localhost") &&
+ !aInput.LowerCaseEqualsASCII("127.0.0.1")) {
+ aACE.Assign(mForceResolve);
+ return NS_OK;
+ }
+ }
+
if (!aIDN || IsASCII(aInput)) {
aACE = aInput;
return NS_OK;
}
if (!(IsUTF8(aInput) && NS_SUCCEEDED(aIDN->ConvertUTF8toACE(aInput, aACE)))) {
return NS_ERROR_FAILURE;
}
--- a/netwerk/dns/nsDNSService2.h
+++ b/netwerk/dns/nsDNSService2.h
@@ -55,18 +55,20 @@ private:
// mLock protects access to mResolver and mIPv4OnlyDomains
mozilla::Mutex mLock;
// mIPv4OnlyDomains is a comma-separated list of domains for which only
// IPv4 DNS lookups are performed. This allows the user to disable IPv6 on
// a per-domain basis and work around broken DNS servers. See bug 68796.
nsAdoptingCString mIPv4OnlyDomains;
+ nsAdoptingCString mForceResolve;
bool mDisableIPv6;
bool mDisablePrefetch;
bool mBlockDotOnion;
bool mFirstTime;
bool mNotifyResolution;
bool mOfflineLocalhost;
+ bool mForceResolveOn;
nsTHashtable<nsCStringHashKey> mLocalDomains;
};
#endif //nsDNSService2_h__
--- a/netwerk/test/unit/test_dns_localredirect.js
+++ b/netwerk/test/unit/test_dns_localredirect.js
@@ -1,18 +1,19 @@
var dns = Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService);
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+var nextTest;
+
var listener = {
onLookupComplete: function(inRequest, inRecord, inStatus) {
var answer = inRecord.getNextAddrAsString();
do_check_true(answer == "127.0.0.1" || answer == "::1");
- prefs.clearUserPref("network.dns.localDomains");
-
+ nextTest();
do_test_finished();
},
QueryInterface: function(aIID) {
if (aIID.equals(Ci.nsIDNSListener) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
@@ -21,14 +22,30 @@ var listener = {
const defaultOriginAttributes = {};
function run_test() {
prefs.setCharPref("network.dns.localDomains", "local.vingtetun.org");
var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
var mainThread = threadManager.currentThread;
+ nextTest = do_test_2;
dns.asyncResolve("local.vingtetun.org", 0, listener,
mainThread, defaultOriginAttributes);
do_test_pending();
}
+function do_test_2() {
+ var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
+ var mainThread = threadManager.currentThread;
+ nextTest = testsDone;
+ prefs.setCharPref("network.dns.forceResolve", "localhost");
+ dns.asyncResolve("www.example.com", 0, listener, mainThread, defaultOriginAttributes);
+
+ do_test_pending();
+}
+
+function testsDone() {
+ prefs.clearUserPref("network.dns.localDomains");
+ prefs.clearUserPref("network.dns.forceResolve");
+}
+