Backed out 18 changesets (bug 1700076, bug 1699691) for causing windows xpcshell failures on test_trr_cancel.js. CLOSED TREE

Backed out changeset 5f3eb0797c06 (bug 1699691)
Backed out changeset 768e56ccd244 (bug 1699691)
Backed out changeset d89075d72c83 (bug 1700076)
Backed out changeset fcf92dd5158a (bug 1700076)
Backed out changeset 8094a7ffc6a4 (bug 1700076)
Backed out changeset 9bc2539a1f5d (bug 1700076)
Backed out changeset fcf27f3c7b69 (bug 1700076)
Backed out changeset 753f4df63689 (bug 1700076)
Backed out changeset 1315c00d2137 (bug 1700076)
Backed out changeset 776c44be95f5 (bug 1700076)
Backed out changeset 2b8d8d63cacd (bug 1700076)
Backed out changeset bc92b34e5d71 (bug 1700076)
Backed out changeset 016c856573da (bug 1700076)
Backed out changeset c085324cb20e (bug 1700076)
Backed out changeset 26dc88b74377 (bug 1700076)
Backed out changeset 8dc21acb87f9 (bug 1700076)
Backed out changeset f36e9cb05851 (bug 1700076)
Backed out changeset fb3f2329ca37 (bug 1700076)
This commit is contained in:
Cosmin Sabou 2021-04-06 21:49:20 +03:00
Родитель 9115c44d2f
Коммит a9dd657e32
35 изменённых файлов: 1579 добавлений и 849 удалений

Просмотреть файл

@ -40,14 +40,6 @@ interface nsICaptivePortalService : nsISupports
*/
readonly attribute long state;
%{C++
int32_t State() {
int32_t result = nsICaptivePortalService::UNKNOWN;
GetState(&result);
return result;
}
%}
/**
* Returns the time difference between NOW and the last time a request was
* completed in milliseconds.

Просмотреть файл

@ -53,7 +53,8 @@ already_AddRefed<ChildDNSService> ChildDNSService::GetSingleton() {
NS_IMPL_ISUPPORTS(ChildDNSService, nsIDNSService, nsPIDNSService, nsIObserver)
ChildDNSService::ChildDNSService() {
ChildDNSService::ChildDNSService()
: mPendingRequestsLock("DNSPendingRequestsLock") {
MOZ_ASSERT_IF(nsIOService::UseSocketProcess(),
XRE_IsContentProcess() || XRE_IsParentProcess());
MOZ_ASSERT_IF(!nsIOService::UseSocketProcess(),

Просмотреть файл

@ -60,7 +60,7 @@ class ChildDNSService final : public nsPIDNSService, public nsIObserver {
// We need to remember pending dns requests to be able to cancel them.
nsClassHashtable<nsCStringHashKey, nsTArray<RefPtr<DNSRequestSender>>>
mPendingRequests;
Mutex mPendingRequestsLock{"DNSPendingRequestsLock"};
Mutex mPendingRequestsLock;
RefPtr<TRRServiceParent> mTRRServiceParent;
};

Просмотреть файл

@ -209,10 +209,13 @@ bool NetAddr::IsIPAddrV4Mapped() const {
static bool isLocalIPv4(uint32_t networkEndianIP) {
uint32_t addr32 = ntohl(networkEndianIP);
return addr32 >> 24 == 0x0A || // 10/8 prefix (RFC 1918).
addr32 >> 20 == 0xAC1 || // 172.16/12 prefix (RFC 1918).
addr32 >> 16 == 0xC0A8 || // 192.168/16 prefix (RFC 1918).
addr32 >> 16 == 0xA9FE; // 169.254/16 prefix (Link Local).
if (addr32 >> 24 == 0x0A || // 10/8 prefix (RFC 1918).
addr32 >> 20 == 0xAC1 || // 172.16/12 prefix (RFC 1918).
addr32 >> 16 == 0xC0A8 || // 192.168/16 prefix (RFC 1918).
addr32 >> 16 == 0xA9FE) { // 169.254/16 prefix (Link Local).
return true;
}
return false;
}
bool NetAddr::IsIPAddrLocal() const {

Просмотреть файл

@ -178,7 +178,7 @@ enum ObliviousDoHMessageType : uint8_t {
};
struct ObliviousDoHMessage {
ObliviousDoHMessageType mType{ODOH_QUERY};
ObliviousDoHMessageType mType;
nsTArray<uint8_t> mKeyId;
nsTArray<uint8_t> mEncryptedMessage;
};

Просмотреть файл

@ -1393,8 +1393,9 @@ static SECStatus HKDFExtract(SECItem* aSalt, PK11SymKey* aIkm,
return SECSuccess;
}
static SECStatus HKDFExpand(PK11SymKey* aPrk, const SECItem* aInfo, int aLen,
bool aKey, UniquePK11SymKey& aOutKey) {
static SECStatus HKDFExpand(PK11SymKey* aPrk, const SECItem* aInfo,
unsigned int aLen, bool aKey,
UniquePK11SymKey& aOutKey) {
CK_HKDF_PARAMS params = {0};
SECItem paramsItem = {siBuffer, (unsigned char*)&params, sizeof(params)};
@ -1448,8 +1449,8 @@ bool ODoHDNSPacket::DecryptDNSResponse() {
const SECItem kODoHSecretInfoItem = {
siBuffer, (unsigned char*)kODoHSecret,
static_cast<unsigned int>(strlen(kODoHSecret))};
const int kAes128GcmKeyLen = 16;
const int kAes128GcmNonceLen = 12;
const unsigned int kAes128GcmKeyLen = 16;
const unsigned int kAes128GcmNonceLen = 12;
PK11SymKey* tmp = nullptr;
SECStatus rv =
PK11_HPKE_ExportSecret(mContext, &kODoHSecretInfoItem, 32, &tmp);

Просмотреть файл

@ -85,12 +85,12 @@ class DNSRequestSender final : public DNSRequestBase, public nsICancelable {
nsCOMPtr<nsIDNSListener> mListener;
nsCOMPtr<nsIEventTarget> mTarget;
nsCOMPtr<nsIDNSRecord> mResultRecord;
nsresult mResultStatus = NS_OK;
nsresult mResultStatus;
nsCString mHost;
nsCString mTrrServer;
uint16_t mType = 0;
uint16_t mType;
const OriginAttributes mOriginAttributes;
uint16_t mFlags = 0;
uint16_t mFlags;
};
// DNSRequestHandler handles the dns request and sends the result back via IPC.
@ -100,7 +100,7 @@ class DNSRequestHandler final : public DNSRequestBase, public nsIDNSListener {
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIDNSLISTENER
DNSRequestHandler() = default;
DNSRequestHandler();
void DoAsyncResolve(const nsACString& hostname, const nsACString& trrServer,
uint16_t type, const OriginAttributes& originAttributes,
@ -120,7 +120,7 @@ class DNSRequestHandler final : public DNSRequestBase, public nsIDNSListener {
private:
virtual ~DNSRequestHandler() = default;
uint32_t mFlags = 0;
uint32_t mFlags;
};
// Provides some common methods for DNSRequestChild and DNSRequestParent.

Просмотреть файл

@ -49,18 +49,18 @@ class ChildDNSRecord : public nsIDNSAddrRecord {
nsCString mCanonicalName;
nsTArray<NetAddr> mAddresses;
uint32_t mCurrent = 0; // addr iterator
uint16_t mFlags = 0;
double mTrrFetchDuration = 0;
double mTrrFetchDurationNetworkOnly = 0;
bool mIsTRR = false;
uint32_t mEffectiveTRRMode = 0;
uint32_t mCurrent; // addr iterator
uint16_t mFlags;
double mTrrFetchDuration;
double mTrrFetchDurationNetworkOnly;
bool mIsTRR;
uint32_t mEffectiveTRRMode;
};
NS_IMPL_ISUPPORTS(ChildDNSRecord, nsIDNSRecord, nsIDNSAddrRecord)
ChildDNSRecord::ChildDNSRecord(const DNSRecord& reply, uint16_t flags)
: mFlags(flags) {
: mCurrent(0), mFlags(flags) {
mCanonicalName = reply.canonicalName();
mTrrFetchDuration = reply.trrFetchDuration();
mTrrFetchDurationNetworkOnly = reply.trrFetchDurationNetworkOnly();
@ -208,7 +208,7 @@ NS_IMPL_ISUPPORTS(ChildDNSByTypeRecord, nsIDNSByTypeRecord, nsIDNSRecord,
ChildDNSByTypeRecord::ChildDNSByTypeRecord(const TypeRecordResultType& reply,
const nsACString& aHost)
: DNSHTTPSSVCRecordBase(aHost) {
: DNSHTTPSSVCRecordBase(aHost), mAllRecordsExcluded(false) {
mResults = reply;
}

Просмотреть файл

@ -20,6 +20,8 @@ using namespace mozilla::ipc;
namespace mozilla {
namespace net {
DNSRequestHandler::DNSRequestHandler() : mFlags(0) {}
//-----------------------------------------------------------------------------
// DNSRequestHandler::nsISupports
//-----------------------------------------------------------------------------

Просмотреть файл

@ -66,13 +66,13 @@ class NativeDNSResolverOverride : public nsINativeDNSResolverOverride {
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSINATIVEDNSRESOLVEROVERRIDE
public:
NativeDNSResolverOverride() = default;
NativeDNSResolverOverride() : mLock("NativeDNSResolverOverride") {}
static already_AddRefed<nsINativeDNSResolverOverride> GetSingleton();
private:
virtual ~NativeDNSResolverOverride() = default;
mozilla::RWLock mLock{"NativeDNSResolverOverride"};
mozilla::RWLock mLock;
nsTHashMap<nsCStringHashKey, nsTArray<PRNetAddr>> mOverrides;
nsTHashMap<nsCStringHashKey, nsCString> mCnames;

Просмотреть файл

@ -202,9 +202,6 @@ bool TRR::MaybeBlockRequest() {
nsresult TRR::SendHTTPRequest() {
// This is essentially the "run" method - created from nsHostResolver
if (mCancelled) {
return NS_ERROR_FAILURE;
}
if ((mType != TRRTYPE_A) && (mType != TRRTYPE_AAAA) &&
(mType != TRRTYPE_NS) && (mType != TRRTYPE_TXT) &&
@ -1011,11 +1008,6 @@ void TRR::Cancel(nsresult aStatus) {
}
}
if (mCancelled) {
return;
}
mCancelled = true;
if (mChannel) {
RecordReason(TRRSkippedReason::TRR_REQ_CANCELLED);
LOG(("TRR: %p canceling Channel %p %s %d status=%" PRIx32 "\n", this,

Просмотреть файл

@ -116,15 +116,14 @@ class TRR : public Runnable,
void StoreIPHintAsDNSRecord(const struct SVCB& aSVCBRecord);
nsCOMPtr<nsIChannel> mChannel;
enum TrrType mType { TRRTYPE_A };
enum TrrType mType;
UniquePtr<DNSPacket> mPacket;
bool mFailed = false;
bool mPB = false;
bool mPB;
DOHresp mDNS;
nsresult mChannelStatus = NS_OK;
RequestPurpose mPurpose = Resolve;
Atomic<bool, Relaxed> mCancelled{false};
// The request timeout in milliseconds. If 0 we will use the default timeout
// we get from the prefs.

Просмотреть файл

@ -224,12 +224,8 @@ bool TRRService::GetParentalControlEnabledInternal() {
}
void TRRService::SetDetectedTrrURI(const nsACString& aURI) {
LOG(("SetDetectedTrrURI(%s", nsPromiseFlatCString(aURI).get()));
// If the user has set a custom URI then we don't want to override that.
// If the URI is set via doh-rollout.uri, mURIPrefHasUserValue will be false
// (see TRRServiceBase::OnTRRURIChange)
if (mURIPrefHasUserValue) {
LOG(("Already has user value. Not setting URI"));
return;
}
@ -290,9 +286,8 @@ void TRRService::GetPrefBranch(nsIPrefBranch** result) {
bool TRRService::MaybeSetPrivateURI(const nsACString& aURI) {
bool clearCache = false;
nsAutoCString newURI(aURI);
LOG(("MaybeSetPrivateURI(%s)", newURI.get()));
ProcessURITemplate(newURI);
{
MutexAutoLock lock(mLock);
if (mPrivateURI.Equals(newURI)) {
@ -591,16 +586,9 @@ TRRService::Observe(nsISupports* aSubject, const char* aTopic,
MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
LOG(("TRR::Observe() topic=%s\n", aTopic));
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
TRR* prevConf = mConfirmation.mTask;
ReadPrefs(NS_ConvertUTF16toUTF8(aData).get());
mConfirmation.RecordEvent("pref-change");
// We should only trigger a new confirmation if reading the prefs didn't
// already trigger one.
if (prevConf == mConfirmation.mTask) {
HandleConfirmationEvent(ConfirmationEvent::PrefChange);
}
HandleConfirmationEvent(ConfirmationEvent::PrefChange);
} else if (!strcmp(aTopic, kOpenCaptivePortalLoginEvent)) {
// We are in a captive portal
LOG(("TRRservice in captive portal\n"));
@ -609,19 +597,13 @@ TRRService::Observe(nsISupports* aSubject, const char* aTopic,
} else if (!strcmp(aTopic, NS_CAPTIVE_PORTAL_CONNECTIVITY)) {
nsAutoCString data = NS_ConvertUTF16toUTF8(aData);
LOG(("TRRservice captive portal was %s\n", data.get()));
nsCOMPtr<nsICaptivePortalService> cps = do_QueryInterface(aSubject);
if (cps) {
mConfirmation.mCaptivePortalStatus = cps->State();
}
// If we were previously in a captive portal, this event means we will
// need to trigger confirmation again. Otherwise it's just a periodical
// captive-portal check that completed and we don't need to react to it.
if (!mCaptiveIsPassed) {
HandleConfirmationEvent(ConfirmationEvent::CaptivePortalConnectivity);
}
HandleConfirmationEvent(ConfirmationEvent::CaptivePortalConnectivity);
mCaptiveIsPassed = true;
nsCOMPtr<nsICaptivePortalService> cps = do_QueryInterface(aSubject);
if (cps) {
cps->GetState(&mConfirmation.mCaptivePortalStatus);
}
} else if (!strcmp(aTopic, kClearPrivateData) || !strcmp(aTopic, kPurge)) {
// flush the TRR blocklist
auto bl = mTRRBLStorage.Lock();

Просмотреть файл

@ -71,7 +71,8 @@ class nsDNSRecord : public nsIDNSAddrRecord {
NS_DECL_NSIDNSRECORD
NS_DECL_NSIDNSADDRRECORD
explicit nsDNSRecord(nsHostRecord* hostRecord) {
explicit nsDNSRecord(nsHostRecord* hostRecord)
: mIterGenCnt(-1), mDone(false) {
mHostRecord = do_QueryObject(hostRecord);
}
@ -94,10 +95,10 @@ class nsDNSRecord : public nsIDNSAddrRecord {
return &*mIter;
}
int mIterGenCnt = -1; // the generation count of
// mHostRecord->addr_info when we
// start iterating
bool mDone = false;
int mIterGenCnt; // the generation count of
// mHostRecord->addr_info when we
// start iterating
bool mDone;
};
NS_IMPL_ISUPPORTS(nsDNSRecord, nsIDNSRecord, nsIDNSAddrRecord)
@ -464,12 +465,12 @@ class nsDNSAsyncRequest final : public nsResolveHostCallback,
RefPtr<nsHostResolver> mResolver;
nsCString mHost; // hostname we're resolving
nsCString mTrrServer; // A trr server to be used.
uint16_t mType = 0;
uint16_t mType;
const OriginAttributes
mOriginAttributes; // The originAttributes for this resolving
nsCOMPtr<nsIDNSListener> mListener;
uint16_t mFlags = 0;
uint16_t mAF = 0;
uint16_t mFlags;
uint16_t mAF;
private:
virtual ~nsDNSAsyncRequest() = default;
@ -533,20 +534,21 @@ nsDNSAsyncRequest::Cancel(nsresult reason) {
class nsDNSSyncRequest : public nsResolveHostCallback {
NS_DECL_THREADSAFE_ISUPPORTS
public:
explicit nsDNSSyncRequest(PRMonitor* mon) : mMonitor(mon) {}
explicit nsDNSSyncRequest(PRMonitor* mon)
: mDone(false), mStatus(NS_OK), mMonitor(mon) {}
void OnResolveHostComplete(nsHostResolver*, nsHostRecord*, nsresult) override;
bool EqualsAsyncListener(nsIDNSListener* aListener) override;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const override;
bool mDone = false;
nsresult mStatus = NS_OK;
bool mDone;
nsresult mStatus;
RefPtr<nsHostRecord> mHostRecord;
private:
virtual ~nsDNSSyncRequest() = default;
PRMonitor* mMonitor = nullptr;
PRMonitor* mMonitor;
};
NS_IMPL_ISUPPORTS0(nsDNSSyncRequest)
@ -602,6 +604,23 @@ class NotifyDNSResolution : public Runnable {
//-----------------------------------------------------------------------------
nsDNSService::nsDNSService()
: mLock("nsDNSServer.mLock"),
mDisableIPv6(false),
mDisablePrefetch(false),
mBlockDotOnion(false),
mNotifyResolution(false),
mOfflineLocalhost(false),
mForceResolveOn(false),
mTrrService(nullptr),
mHasSocksProxy(false),
mResCacheEntries(0),
mResCacheExpiration(0),
mResCacheGrace(0),
mResolverPrefsUpdated(false) {}
nsDNSService::~nsDNSService() = default;
NS_IMPL_ISUPPORTS(nsDNSService, nsIDNSService, nsPIDNSService, nsIObserver,
nsIMemoryReporter)

Просмотреть файл

@ -32,7 +32,7 @@ class nsDNSService final : public nsPIDNSService,
NS_DECL_NSIOBSERVER
NS_DECL_NSIMEMORYREPORTER
nsDNSService() = default;
nsDNSService();
static already_AddRefed<nsIDNSService> GetXPCOMSingleton();
@ -49,7 +49,7 @@ class nsDNSService final : public nsPIDNSService,
nsIDNSRecord** result);
private:
~nsDNSService() = default;
~nsDNSService();
nsresult ReadPrefs(const char* name);
static already_AddRefed<nsDNSService> GetSingleton();
@ -85,27 +85,27 @@ class nsDNSService final : public nsPIDNSService,
// mLock protects access to mResolver, mLocalDomains, mIPv4OnlyDomains and
// mFailedSVCDomainNames
mozilla::Mutex mLock{"nsDNSServer.mLock"};
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.
nsCString mIPv4OnlyDomains;
nsCString mForceResolve;
bool mDisableIPv6 = false;
bool mDisablePrefetch = false;
bool mBlockDotOnion = false;
bool mNotifyResolution = false;
bool mOfflineLocalhost = false;
bool mForceResolveOn = false;
bool mDisableIPv6;
bool mDisablePrefetch;
bool mBlockDotOnion;
bool mNotifyResolution;
bool mOfflineLocalhost;
bool mForceResolveOn;
nsTHashSet<nsCString> mLocalDomains;
RefPtr<mozilla::net::TRRService> mTrrService;
mozilla::Atomic<bool, mozilla::Relaxed> mHasSocksProxy{false};
mozilla::Atomic<bool, mozilla::Relaxed> mHasSocksProxy;
uint32_t mResCacheEntries = 0;
uint32_t mResCacheExpiration = 0;
uint32_t mResCacheGrace = 0;
bool mResolverPrefsUpdated = false;
uint32_t mResCacheEntries;
uint32_t mResCacheExpiration;
uint32_t mResCacheGrace;
bool mResolverPrefsUpdated;
bool mODoHActivated = false;
nsClassHashtable<nsCStringHashKey, nsTArray<nsCString>> mFailedSVCDomainNames;
};

Просмотреть файл

@ -197,7 +197,12 @@ size_t nsHostKey::SizeOfExcludingThis(
NS_IMPL_ISUPPORTS0(nsHostRecord)
nsHostRecord::nsHostRecord(const nsHostKey& key)
: nsHostKey(key), mTRRQuery("nsHostRecord.mTRRQuery") {}
: nsHostKey(key),
mEffectiveTRRMode(nsIRequest::TRR_DEFAULT_MODE),
mTRRQuery("nsHostRecord.mTRRQuery"),
mResolving(0),
negative(false),
mDoomed(false) {}
void nsHostRecord::Invalidate() { mDoomed = true; }
@ -285,7 +290,15 @@ static size_t SizeOfResolveHostCallbackListExcludingHead(
NS_IMPL_ISUPPORTS_INHERITED(AddrHostRecord, nsHostRecord, AddrHostRecord)
AddrHostRecord::AddrHostRecord(const nsHostKey& key) : nsHostRecord(key) {}
AddrHostRecord::AddrHostRecord(const nsHostKey& key)
: nsHostRecord(key),
addr_info_lock("AddrHostRecord.addr_info_lock"),
addr_info_gencnt(0),
addr_info(nullptr),
addr(nullptr),
mResolverType(DNSResolverType::Native),
mTRRSuccess(0),
mNativeSuccess(0) {}
AddrHostRecord::~AddrHostRecord() {
mCallbacks.clear();
@ -498,7 +511,10 @@ NS_IMPL_ISUPPORTS_INHERITED(TypeHostRecord, nsHostRecord, TypeHostRecord,
nsIDNSTXTRecord, nsIDNSHTTPSSVCRecord)
TypeHostRecord::TypeHostRecord(const nsHostKey& key)
: nsHostRecord(key), DNSHTTPSSVCRecordBase(key.host) {}
: nsHostRecord(key),
DNSHTTPSSVCRecordBase(key.host),
mResultsLock("TypeHostRecord.mResultsLock"),
mAllRecordsExcluded(false) {}
TypeHostRecord::~TypeHostRecord() { mCallbacks.clear(); }
@ -676,7 +692,14 @@ nsHostResolver::nsHostResolver(uint32_t maxCacheEntries,
: mMaxCacheEntries(maxCacheEntries),
mDefaultCacheLifetime(defaultCacheEntryLifetime),
mDefaultGracePeriod(defaultGracePeriod),
mIdleTaskCV(mLock, "nsHostResolver.mIdleTaskCV") {
mLock("nsHostResolver.mLock"),
mIdleTaskCV(mLock, "nsHostResolver.mIdleTaskCV"),
mEvictionQSize(0),
mShutdown(true),
mNumIdleTasks(0),
mActiveTaskCount(0),
mActiveAnyThreadCount(0),
mPendingCount(0) {
mCreationTime = PR_Now();
mLongIdleTimeout = TimeDuration::FromSeconds(LongIdleTimeoutSeconds);
@ -803,13 +826,8 @@ void nsHostResolver::FlushCache(bool aTrrToo) {
if (record->isInList()) {
record->remove();
}
LOG(("Removing (%s) Addr record from mRecordDB", record->host.get()));
iter.Remove();
}
} else if (aTrrToo) {
// remove by type records
LOG(("Removing (%s) type record from mRecordDB", record->host.get()));
iter.Remove();
}
}
}
@ -2139,29 +2157,26 @@ void nsHostResolver::CancelAsyncRequest(
nsHostKey key(host, aTrrServer, aType, flags, af,
(aOriginAttributes.mPrivateBrowsingId > 0), originSuffix);
RefPtr<nsHostRecord> rec = mRecordDB.Get(key);
if (!rec) {
return;
}
if (rec) {
nsHostRecord* recPtr = nullptr;
for (RefPtr<nsResolveHostCallback> c : rec->mCallbacks) {
if (c->EqualsAsyncListener(aListener)) {
c->remove();
c->OnResolveHostComplete(this, rec.get(), status);
break;
}
}
// If there are no more callbacks, remove the hash table entry
if (rec->mCallbacks.isEmpty()) {
mRecordDB.Remove(*static_cast<nsHostKey*>(rec.get()));
// If record is on a Queue, remove it
if (rec->isInList()) {
// if the queue this record is in is the eviction queue
// then we should also update mEvictionQSize
if (mEvictionQ.contains(rec)) {
mEvictionQSize--;
for (const RefPtr<nsResolveHostCallback>& c : rec->mCallbacks) {
if (c->EqualsAsyncListener(aListener)) {
RefPtr<nsResolveHostCallback> callback = c;
c->remove();
recPtr = rec;
callback->OnResolveHostComplete(this, recPtr, status);
break;
}
}
// If there are no more callbacks, remove the hash table entry
if (recPtr && recPtr->mCallbacks.isEmpty()) {
mRecordDB.Remove(*static_cast<nsHostKey*>(recPtr));
// If record is on a Queue, remove it and then deref it
if (recPtr->isInList()) {
recPtr->remove();
}
rec->remove();
}
}
}

Просмотреть файл

@ -58,10 +58,10 @@ extern mozilla::Atomic<bool, mozilla::Relaxed> gNativeIsLocalhost;
struct nsHostKey {
const nsCString host;
const nsCString mTrrServer;
uint16_t type = 0;
uint16_t flags = 0;
uint16_t af = 0;
bool pb = false;
uint16_t type;
uint16_t flags;
uint16_t af;
bool pb;
const nsCString originSuffix;
explicit nsHostKey(const nsACString& host, const nsACString& aTrrServer,
uint16_t type, uint16_t flags, uint16_t af, bool pb,
@ -159,7 +159,7 @@ class nsHostRecord : public mozilla::LinkedListElement<RefPtr<nsHostRecord>>,
// default resolver and the TRRMode encoded in the flags.
// The mode into account if the TRR service is disabled,
// parental controls are on, domain matches exclusion list, etc.
nsIRequest::TRRMode mEffectiveTRRMode = nsIRequest::TRR_DEFAULT_MODE;
nsIRequest::TRRMode mEffectiveTRRMode;
TRRSkippedReason mTRRSkippedReason = TRRSkippedReason::TRR_UNSET;
TRRSkippedReason mTRRAFailReason = TRRSkippedReason::TRR_UNSET;
@ -167,16 +167,15 @@ class nsHostRecord : public mozilla::LinkedListElement<RefPtr<nsHostRecord>>,
mozilla::DataMutex<RefPtr<mozilla::net::TRRQuery>> mTRRQuery;
// counter of outstanding resolving calls
mozilla::Atomic<int32_t> mResolving{0};
mozilla::Atomic<int32_t>
mResolving; // counter of outstanding resolving calls
// True if this record is a cache of a failed lookup. Negative cache
// entries are valid just like any other (though never for more than 60
// seconds), but a use of that negative entry forces an asynchronous refresh.
bool negative = false;
// Explicitly expired
bool mDoomed = false;
uint8_t negative : 1; /* True if this record is a cache of a failed
lookup. Negative cache entries are valid just
like any other (though never for more than 60
seconds), but a use of that negative entry
forces an asynchronous refresh. */
uint8_t mDoomed : 1; // explicitly expired
};
// b020e996-f6ab-45e5-9bf5-1da71dd0053a
@ -189,7 +188,6 @@ class nsHostRecord : public mozilla::LinkedListElement<RefPtr<nsHostRecord>>,
class AddrHostRecord final : public nsHostRecord {
using Mutex = mozilla::Mutex;
using DNSResolverType = mozilla::net::DNSResolverType;
public:
NS_DECLARE_STATIC_IID_ACCESSOR(ADDRHOSTRECORD_IID)
@ -212,9 +210,8 @@ class AddrHostRecord final : public nsHostRecord {
* the other threads just read it. therefore the resolver worker
* thread doesn't need to lock when reading |addr_info|.
*/
Mutex addr_info_lock{"AddrHostRecord.addr_info_lock"};
// generation count of |addr_info|
int addr_info_gencnt = 0;
Mutex addr_info_lock;
int addr_info_gencnt; /* generation count of |addr_info| */
RefPtr<mozilla::net::AddrInfo> addr_info;
mozilla::UniquePtr<mozilla::net::NetAddr> addr;
@ -260,9 +257,9 @@ class AddrHostRecord final : public nsHostRecord {
mozilla::TimeDuration mNativeDuration;
// TRR or ODoH was used on this record
mozilla::Atomic<DNSResolverType> mResolverType{DNSResolverType::Native};
uint8_t mTRRSuccess = 0; // number of successful TRR responses
uint8_t mNativeSuccess = 0; // number of native lookup responses
mozilla::Atomic<mozilla::net::DNSResolverType> mResolverType;
uint8_t mTRRSuccess; // number of successful TRR responses
uint8_t mNativeSuccess; // number of native lookup responses
// clang-format off
MOZ_ATOMIC_BITFIELDS(mAtomicBitfields, 8, (
@ -324,7 +321,7 @@ class TypeHostRecord final : public nsHostRecord,
bool HasUsableResult();
mozilla::net::TypeRecordResultType mResults = AsVariant(mozilla::Nothing());
mozilla::Mutex mResultsLock{"TypeHostRecord.mResultsLock"};
mozilla::Mutex mResultsLock;
// When the lookups of this record started (for telemetry).
mozilla::TimeStamp mStart;
@ -587,18 +584,17 @@ class nsHostResolver : public nsISupports, public AHostResolver {
METHOD_NETWORK_SHARED = 7
};
uint32_t mMaxCacheEntries = 0;
uint32_t mDefaultCacheLifetime = 0; // granularity seconds
uint32_t mDefaultGracePeriod = 0; // granularity seconds
// mutable so SizeOfIncludingThis can be const
mutable Mutex mLock{"nsHostResolver.mLock"};
uint32_t mMaxCacheEntries;
uint32_t mDefaultCacheLifetime; // granularity seconds
uint32_t mDefaultGracePeriod; // granularity seconds
mutable Mutex mLock; // mutable so SizeOfIncludingThis can be const
CondVar mIdleTaskCV;
nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord> mRecordDB;
mozilla::LinkedList<RefPtr<nsHostRecord>> mHighQ;
mozilla::LinkedList<RefPtr<nsHostRecord>> mMediumQ;
mozilla::LinkedList<RefPtr<nsHostRecord>> mLowQ;
mozilla::LinkedList<RefPtr<nsHostRecord>> mEvictionQ;
uint32_t mEvictionQSize = 0;
uint32_t mEvictionQSize;
PRTime mCreationTime;
mozilla::TimeDuration mLongIdleTimeout;
mozilla::TimeDuration mShortIdleTimeout;
@ -606,11 +602,11 @@ class nsHostResolver : public nsISupports, public AHostResolver {
RefPtr<nsIThreadPool> mResolverThreads;
RefPtr<mozilla::net::NetworkConnectivityService> mNCS;
mozilla::Atomic<bool> mShutdown{true};
mozilla::Atomic<uint32_t> mNumIdleTasks{0};
mozilla::Atomic<uint32_t> mActiveTaskCount{0};
mozilla::Atomic<uint32_t> mActiveAnyThreadCount{0};
mozilla::Atomic<uint32_t> mPendingCount{0};
mozilla::Atomic<bool> mShutdown;
mozilla::Atomic<uint32_t> mNumIdleTasks;
mozilla::Atomic<uint32_t> mActiveTaskCount;
mozilla::Atomic<uint32_t> mActiveAnyThreadCount;
mozilla::Atomic<uint32_t> mPendingCount;
// Set the expiration time stamps appropriately.
void PrepareRecordExpirationAddrRecord(AddrHostRecord* rec) const;

Просмотреть файл

@ -133,7 +133,11 @@ void nsIDNService::prefsChanged(const char* pref) {
}
}
nsIDNService::nsIDNService() {
nsIDNService::nsIDNService()
: mLock("DNService pref value lock"),
mShowPunycode(false),
mRestrictionProfile(static_cast<restrictionProfile>(0)),
mIDNUseWhitelist(false) {
MOZ_ASSERT(NS_IsMainThread());
uint32_t IDNAOptions = UIDNA_CHECK_BIDI | UIDNA_CHECK_CONTEXTJ;
@ -383,11 +387,10 @@ NS_IMETHODIMP nsIDNService::Normalize(const nsACString& input,
namespace {
class MOZ_STACK_CLASS MutexSettableAutoUnlock final {
private:
Mutex* mMutex = nullptr;
Mutex* mMutex;
public:
MutexSettableAutoUnlock() = default;
MutexSettableAutoUnlock() : mMutex(nullptr) {}
void Acquire(mozilla::Mutex& aMutex) {
MOZ_ASSERT(!mMutex);

Просмотреть файл

@ -170,7 +170,7 @@ class nsIDNService final : public nsIIDNService,
// These members can only be updated on the main thread and
// read on any thread. Therefore, acquiring the mutex is required
// only for threads other than the main thread.
mozilla::Mutex mLock{"IDNService"};
mozilla::Mutex mLock;
// guarded by mLock
nsTArray<mozilla::net::BlocklistRange> mIDNBlocklist;
@ -182,7 +182,7 @@ class nsIDNService final : public nsIIDNService,
*
* guarded by mLock
*/
bool mShowPunycode = false;
bool mShowPunycode;
/**
* Restriction-level Detection profiles defined in UTR 39
@ -195,11 +195,11 @@ class nsIDNService final : public nsIIDNService,
eModeratelyRestrictiveProfile
};
// guarded by mLock;
restrictionProfile mRestrictionProfile{eASCIIOnlyProfile};
restrictionProfile mRestrictionProfile;
// guarded by mLock;
nsCOMPtr<nsIPrefBranch> mIDNWhitelistPrefBranch;
// guarded by mLock
bool mIDNUseWhitelist = false;
bool mIDNUseWhitelist;
};
#endif // nsIDNService_h__

Просмотреть файл

@ -108,7 +108,6 @@ class TRRDNSListener {
trrServer: args[4] ?? "",
expectEarlyFail: args[5] ?? "",
flags: args[6] ?? 0,
type: args[7] ?? Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
};
}
this.expectedAnswer = this.options.expectedAnswer ?? undefined;
@ -117,7 +116,6 @@ class TRRDNSListener {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
this.type = this.options.type ?? Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT;
let trrServer = this.options.trrServer || "";
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
@ -131,14 +129,14 @@ class TRRDNSListener {
);
}
this.resolverInfo =
let resolverInfo =
trrServer == "" ? null : gDNS.newTRRResolverInfo(trrServer);
try {
this.request = gDNS.asyncResolve(
this.name,
this.type,
Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
this.options.flags || 0,
this.resolverInfo,
resolverInfo,
this,
currentThread,
{} // defaultOriginAttributes
@ -164,12 +162,6 @@ class TRRDNSListener {
}
Assert.equal(inStatus, Cr.NS_OK, "Checking status");
if (this.type != Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT) {
this.resolve([inRequest, inRecord, inStatus]);
return;
}
inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
let answer = inRecord.getNextAddrAsString();
Assert.equal(
@ -222,18 +214,6 @@ class TRRDNSListener {
then() {
return this.promise.then.apply(this.promise, arguments);
}
cancel(aStatus = Cr.NS_ERROR_ABORT) {
gDNS.cancelAsyncResolve(
this.name,
this.type,
this.options.flags || 0,
this.resolverInfo,
this,
aStatus,
{}
);
}
}
/// Implements a basic HTTP2 server
@ -267,10 +247,6 @@ class TRRServerCode {
// value: array [answer1, answer2]
global.dns_query_answers = {};
// key: domain
// value: a map containing {key: type, value: number of requests}
global.dns_query_counts = {};
global.http2 = require("http2");
global.server = global.http2.createSecureServer(options, global.handler);
@ -281,13 +257,6 @@ class TRRServerCode {
return global.server.address().port;
}
static getRequestCount(domain, type) {
if (!global.dns_query_counts[domain]) {
return 0;
}
return global.dns_query_counts[domain][type] || 0;
}
}
/// This is the default handler for /dns-query
@ -322,20 +291,12 @@ function trrQueryHandler(req, resp, url) {
function processRequest(req, resp, payload) {
let dnsQuery = global.dnsPacket.decode(payload);
let domain = dnsQuery.questions[0].name;
let type = dnsQuery.questions[0].type;
let response = global.dns_query_answers[`${domain}/${type}`] || {};
if (!global.dns_query_counts[domain]) {
global.dns_query_counts[domain] = {};
}
global.dns_query_counts[domain][type] =
global.dns_query_counts[domain][type] + 1 || 1;
let response =
global.dns_query_answers[
`${dnsQuery.questions[0].name}/${dnsQuery.questions[0].type}`
] || {};
let flags = global.dnsPacket.RECURSION_DESIRED;
if (!response.answers && !response.flags) {
flags |= 2; // SERVFAIL
}
flags |= response.flags || 0;
let buf = global.dnsPacket.encode({
type: "response",
@ -438,10 +399,4 @@ class TRRServer {
)}`;
return this.execute(text);
}
async requestCount(domain, type) {
return this.execute(
`TRRServerCode.getRequestCount("${domain}", "${type}")`
);
}
}

Просмотреть файл

@ -6,11 +6,19 @@
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
let prefs;
let h2Port;
let listen;
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
Ci.nsIDNSService
);
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
Ci.nsIThreadManager
);
const mainThread = threadManager.currentThread;
const defaultOriginAttributes = {};
function setup() {
let env = Cc["@mozilla.org/process/environment;1"].getService(
@ -20,29 +28,98 @@ function setup() {
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
trr_test_setup();
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
prefs.setBoolPref("network.dns.native-is-localhost", true);
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
prefs.setIntPref("network.trr.mode", 2); // TRR first
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
}
setup();
registerCleanupFunction(() => {
trr_clear_prefs();
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.blacklist-duration");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
});
let test_answer = "bXkgdm9pY2UgaXMgbXkgcGFzc3dvcmQ=";
let test_answer_addr = "127.0.0.1";
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
add_task(async function testTXTResolve() {
// use the h2 server as DOH provider
Services.prefs.setCharPref(
prefs.setCharPref(
"network.trr.uri",
"https://foo.example.com:" + h2Port + "/doh"
);
let [, inRecord] = await new TRRDNSListener("_esni.example.com", {
type: dns.RESOLVE_TYPE_TXT,
});
let listenerEsni = new DNSListener();
let request = dns.asyncResolve(
"_esni.example.com",
dns.RESOLVE_TYPE_TXT,
0,
null, // resolverInfo
listenerEsni,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus] = await listenerEsni;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let answer = inRecord
.QueryInterface(Ci.nsIDNSTXTRecord)
.getRecordsAsOneString();
@ -51,15 +128,24 @@ add_task(async function testTXTResolve() {
// verify TXT record pushed on a A record request
add_task(async function testTXTRecordPushPart1() {
Services.prefs.setCharPref(
prefs.setCharPref(
"network.trr.uri",
"https://foo.example.com:" + h2Port + "/txt-dns-push"
);
let [, inRecord] = await new TRRDNSListener("_esni_push.example.com", {
type: dns.RESOLVE_TYPE_DEFAULT,
expectedAnswer: "127.0.0.1",
});
let listenerAddr = new DNSListener();
let request = dns.asyncResolve(
"_esni_push.example.com",
dns.RESOLVE_TYPE_DEFAULT,
0,
null, // resolverInfo
listenerAddr,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus] = await listenerAddr;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
let answer = inRecord.getNextAddrAsString();
Assert.equal(answer, test_answer_addr, "got correct answer");
@ -69,14 +155,24 @@ add_task(async function testTXTRecordPushPart1() {
add_task(async function testTXTRecordPushPart2() {
// At this point the second host name should've been pushed and we can resolve it using
// cache only. Set back the URI to a path that fails.
Services.prefs.setCharPref(
prefs.setCharPref(
"network.trr.uri",
"https://foo.example.com:" + h2Port + "/404"
);
let [, inRecord] = await new TRRDNSListener("_esni_push.example.com", {
type: dns.RESOLVE_TYPE_TXT,
});
let listenerEsni = new DNSListener();
let request = dns.asyncResolve(
"_esni_push.example.com",
dns.RESOLVE_TYPE_TXT,
0,
null, // resolverInfo
listenerEsni,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus] = await listenerEsni;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let answer = inRecord
.QueryInterface(Ci.nsIDNSTXTRecord)
.getRecordsAsOneString();

Просмотреть файл

@ -38,24 +38,63 @@ function setup() {
Assert.notEqual(h3Port, null);
Assert.notEqual(h3Port, "");
trr_test_setup();
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.security.esni.enabled", false);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
prefs.setBoolPref("network.dns.native-is-localhost", true);
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
prefs.setIntPref("network.trr.mode", 2); // TRR first
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
Services.prefs.setIntPref("network.trr.mode", 2); // TRR first
Services.prefs.setBoolPref("network.http.http3.enabled", true);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
}
setup();
registerCleanupFunction(async () => {
trr_clear_prefs();
Services.prefs.clearUserPref("network.dns.upgrade_with_https_rr");
Services.prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
Services.prefs.clearUserPref("network.dns.echconfig.enabled");
Services.prefs.clearUserPref("network.dns.echconfig.fallback_to_origin");
Services.prefs.clearUserPref("network.dns.httpssvc.reset_exclustion_list");
Services.prefs.clearUserPref("network.http.http3.enabled");
Services.prefs.clearUserPref(
"network.dns.httpssvc.http3_fast_fallback_timeout"
);
prefs.clearUserPref("network.security.esni.enabled");
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
prefs.clearUserPref("network.dns.upgrade_with_https_rr");
prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
prefs.clearUserPref("network.dns.echconfig.enabled");
prefs.clearUserPref("network.dns.echconfig.fallback_to_origin");
prefs.clearUserPref("network.dns.httpssvc.reset_exclustion_list");
prefs.clearUserPref("network.http.http3.enabled");
prefs.clearUserPref("network.dns.httpssvc.http3_fast_fallback_timeout");
Services.prefs.clearUserPref(
"network.http.http3.alt-svc-mapping-for-testing"
);
@ -66,6 +105,25 @@ registerCleanupFunction(async () => {
}
});
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
function makeChan(url) {
let chan = NetUtil.newChannel({
uri: url,

Просмотреть файл

@ -6,50 +6,115 @@
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
let prefs;
let h2Port;
let listen;
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
Ci.nsIDNSService
);
const certOverrideService = Cc[
"@mozilla.org/security/certoverride;1"
].getService(Ci.nsICertOverrideService);
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
Ci.nsIThreadManager
);
const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
const mainThread = threadManager.currentThread;
const defaultOriginAttributes = {};
function setup() {
trr_test_setup();
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
let h2Port = env.get("MOZHTTP2_PORT");
h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
prefs.setBoolPref("network.dns.native-is-localhost", true);
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
prefs.setIntPref("network.trr.mode", 2); // TRR first
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
Services.prefs.setBoolPref("network.dns.upgrade_with_https_rr", true);
Services.prefs.setBoolPref("network.dns.use_https_rr_as_altsvc", true);
Services.prefs.setCharPref(
"network.trr.uri",
"https://foo.example.com:" + h2Port + "/httpssvc_as_altsvc"
);
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
Services.prefs.setBoolPref("network.dns.upgrade_with_https_rr", true);
Services.prefs.setBoolPref("network.dns.use_https_rr_as_altsvc", true);
Services.prefs.setBoolPref(
"network.dns.use_https_rr_for_speculative_connection",
true
);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
}
setup();
registerCleanupFunction(async () => {
trr_clear_prefs();
Services.prefs.clearUserPref("network.dns.upgrade_with_https_rr");
Services.prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
Services.prefs.clearUserPref(
"network.dns.use_https_rr_for_speculative_connection"
);
registerCleanupFunction(() => {
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
prefs.clearUserPref("network.dns.upgrade_with_https_rr");
prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
prefs.clearUserPref("network.dns.use_https_rr_for_speculative_connection");
});
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
function makeChan(url) {
let chan = NetUtil.newChannel({
uri: url,
@ -103,11 +168,24 @@ EventSinkListener.prototype.QueryInterface = ChromeUtils.generateQI([
// Test if the request is upgraded to https with a HTTPSSVC record.
add_task(async function testUseHTTPSSVCAsHSTS() {
dns.clearCache(true);
let dnsListener = new DNSListener();
// Do DNS resolution before creating the channel, so the HTTPSSVC record will
// be resolved from the cache.
await new TRRDNSListener("test.httpssvc.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let request = dns.asyncResolve(
"test.httpssvc.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
dnsListener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await dnsListener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
// Since the HTTPS RR should be served from cache, the DNS record is available
// before nsHttpChannel::MaybeUseHTTPSRRForUpgrade() is called.
@ -187,11 +265,21 @@ add_task(async function testInvalidDNSResult1() {
Services.obs.removeObserver(observer, topic);
let channel = aSubject.QueryInterface(Ci.nsIChannel);
channel.suspend();
new TRRDNSListener("foo.notexisted.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
expectedSuccess: false,
}).then(() => channel.resume());
let dnsListener = {
QueryInterface: ChromeUtils.generateQI(["nsIDNSListener"]),
onLookupComplete(inRequest, inRecord, inStatus) {
channel.resume();
},
};
dns.asyncResolve(
"foo.notexisted.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
dnsListener,
mainThread,
defaultOriginAttributes
);
}
},
};

Просмотреть файл

@ -6,7 +6,9 @@
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
let prefs;
let h2Port;
let listen;
let trrServer;
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
@ -30,21 +32,78 @@ function setup() {
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
trr_test_setup();
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
prefs.setBoolPref("network.dns.native-is-localhost", true);
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
Services.prefs.setBoolPref("network.dns.upgrade_with_https_rr", true);
Services.prefs.setBoolPref("network.dns.use_https_rr_as_altsvc", true);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
}
setup();
registerCleanupFunction(async () => {
trr_clear_prefs();
Services.prefs.clearUserPref("network.dns.upgrade_with_https_rr");
Services.prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
Services.prefs.clearUserPref("network.dns.disablePrefetch");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
prefs.clearUserPref("network.dns.upgrade_with_https_rr");
prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.dns.disablePrefetch");
await trrServer.stop();
});
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
// Test if IP hint addresses can be accessed as regular A/AAAA records.
add_task(async function testStoreIPHint() {
trrServer = new TRRServer();
@ -80,9 +139,21 @@ add_task(async function testStoreIPHint() {
],
});
let [, inRecord] = await new TRRDNSListener("test.IPHint.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.IPHint.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
Assert.equal(answer[0].priority, 1);
@ -124,10 +195,20 @@ add_task(async function testStoreIPHint() {
);
async function verifyAnswer(flags, answer) {
let [, inRecord] = await new TRRDNSListener("test.IPHint.com", {
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.IPHint.com",
dns.RESOLVE_TYPE_DEFAULT,
flags,
expectedSuccess: false,
});
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
let addresses = [];
while (inRecord.hasMore()) {
@ -179,16 +260,26 @@ function channelOpenPromise(chan, flags) {
// Test if we can connect to the server with the IP hint address.
add_task(async function testConnectionWithIPHint() {
dns.clearCache(true);
Services.prefs.setIntPref("network.trr.mode", 3);
Services.prefs.setCharPref(
prefs.setIntPref("network.trr.mode", 3);
prefs.setCharPref(
"network.trr.uri",
"https://127.0.0.1:" + h2Port + "/httpssvc_use_iphint"
);
// Resolving test.iphint.com should be failed.
let [, , inStatus] = await new TRRDNSListener("test.iphint.com", {
expectedSuccess: false,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.iphint.com",
dns.RESOLVE_TYPE_DEFAULT,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(
inStatus,
Cr.NS_ERROR_UNKNOWN_HOST,
@ -265,10 +356,20 @@ add_task(async function testIPHintWithFreshDNS() {
],
});
let [, inRecord] = await new TRRDNSListener("test.iphint.org", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.iphint.org",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
Assert.equal(answer[0].priority, 1);
Assert.equal(answer[0].name, "svc.iphint.net");

Просмотреть файл

@ -6,15 +6,97 @@
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
trr_test_setup();
registerCleanupFunction(async () => {
trr_clear_prefs();
Services.prefs.clearUserPref("network.dns.echconfig.enabled");
});
let prefs;
let h2Port;
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
Ci.nsIDNSService
);
const certOverrideService = Cc[
"@mozilla.org/security/certoverride;1"
].getService(Ci.nsICertOverrideService);
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
Ci.nsIThreadManager
);
const mainThread = threadManager.currentThread;
const defaultOriginAttributes = {};
function setup() {
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
prefs.setBoolPref("network.dns.native-is-localhost", true);
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
prefs.setIntPref("network.trr.mode", 2); // TRR first
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
}
setup();
registerCleanupFunction(() => {
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
prefs.clearUserPref("network.dns.echconfig.enabled");
});
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
add_task(async function testPriorityAndECHConfig() {
let trrServer = new TRRServer();
@ -79,9 +161,21 @@ add_task(async function testPriorityAndECHConfig() {
],
});
let [, inRecord] = await new TRRDNSListener("test.priority.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.priority.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
Assert.equal(answer.length, 4);
@ -100,9 +194,21 @@ add_task(async function testPriorityAndECHConfig() {
Services.prefs.setBoolPref("network.dns.echconfig.enabled", true);
dns.clearCache(true);
[, inRecord] = await new TRRDNSListener("test.priority.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
listener = new DNSListener();
request = dns.asyncResolve(
"test.priority.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
[inRequest, inRecord, inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
Assert.equal(answer.length, 4);

Просмотреть файл

@ -6,6 +6,9 @@
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
let prefs;
let h2Port;
let listen;
let trrServer;
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
@ -14,15 +17,55 @@ const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
const certOverrideService = Cc[
"@mozilla.org/security/certoverride;1"
].getService(Ci.nsICertOverrideService);
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
Ci.nsIThreadManager
);
const mainThread = threadManager.currentThread;
const defaultOriginAttributes = {};
function setup() {
trr_test_setup();
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.security.esni.enabled", false);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
prefs.setBoolPref("network.dns.native-is-localhost", true);
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
prefs.setIntPref("network.trr.mode", 2); // TRR first
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
Services.prefs.setBoolPref("network.dns.upgrade_with_https_rr", true);
Services.prefs.setBoolPref("network.dns.use_https_rr_as_altsvc", true);
Services.prefs.setBoolPref("network.dns.echconfig.enabled", true);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
add_tls_server_setup(
"EncryptedClientHelloServer",
"../../../security/manager/ssl/tests/unit/test_encrypted_client_hello"
@ -31,16 +74,49 @@ function setup() {
setup();
registerCleanupFunction(async () => {
trr_clear_prefs();
Services.prefs.clearUserPref("network.dns.upgrade_with_https_rr");
Services.prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
Services.prefs.clearUserPref("network.dns.echconfig.enabled");
Services.prefs.clearUserPref("network.dns.echconfig.fallback_to_origin");
prefs.clearUserPref("network.security.esni.enabled");
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
prefs.clearUserPref("network.dns.upgrade_with_https_rr");
prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
prefs.clearUserPref("network.dns.echconfig.enabled");
prefs.clearUserPref("network.dns.echconfig.fallback_to_origin");
if (trrServer) {
await trrServer.stop();
}
});
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
function makeChan(url) {
let chan = NetUtil.newChannel({
uri: url,
@ -116,9 +192,21 @@ add_task(async function testConnectWithECH() {
],
});
await new TRRDNSListener("ech-private.example.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"ech-private.example.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let chan = makeChan(`https://ech-private.example.com`);
await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL);
@ -181,9 +269,21 @@ add_task(async function testEchRetry() {
],
});
await new TRRDNSListener("ech-private.example.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"ech-private.example.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
Services.prefs.setBoolPref("network.dns.echconfig.enabled", true);
let chan = makeChan(`https://ech-private.example.com`);

Просмотреть файл

@ -6,6 +6,9 @@
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
let prefs;
let h2Port;
let listen;
let trrServer;
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
@ -14,15 +17,55 @@ const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
const certOverrideService = Cc[
"@mozilla.org/security/certoverride;1"
].getService(Ci.nsICertOverrideService);
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
Ci.nsIThreadManager
);
const mainThread = threadManager.currentThread;
const defaultOriginAttributes = {};
function setup() {
trr_test_setup();
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.security.esni.enabled", false);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
prefs.setBoolPref("network.dns.native-is-localhost", true);
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
prefs.setIntPref("network.trr.mode", 2); // TRR first
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
Services.prefs.setBoolPref("network.dns.upgrade_with_https_rr", true);
Services.prefs.setBoolPref("network.dns.use_https_rr_as_altsvc", true);
Services.prefs.setBoolPref("network.dns.echconfig.enabled", true);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
// An arbitrary, non-ECH server.
add_tls_server_setup(
"DelegatedCredentialsServer",
@ -35,16 +78,49 @@ function setup() {
setup();
registerCleanupFunction(async () => {
trr_clear_prefs();
Services.prefs.clearUserPref("network.dns.upgrade_with_https_rr");
Services.prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
Services.prefs.clearUserPref("network.dns.echconfig.enabled");
Services.prefs.clearUserPref("network.dns.echconfig.fallback_to_origin");
prefs.clearUserPref("network.security.esni.enabled");
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
prefs.clearUserPref("network.dns.upgrade_with_https_rr");
prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
prefs.clearUserPref("network.dns.echconfig.enabled");
prefs.clearUserPref("network.dns.echconfig.fallback_to_origin");
if (trrServer) {
await trrServer.stop();
}
});
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
function makeChan(url) {
let chan = NetUtil.newChannel({
uri: url,
@ -122,9 +198,21 @@ add_task(async function testRetryWithoutECH() {
],
});
await new TRRDNSListener("delegated-disabled.example.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"delegated-disabled.example.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let chan = makeChan(`https://delegated-disabled.example.com:8443`);
await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL);

Просмотреть файл

@ -1,182 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
Ci.nsIDNSService
);
const { TestUtils } = ChromeUtils.import(
"resource://testing-common/TestUtils.jsm"
);
trr_test_setup();
registerCleanupFunction(async () => {
trr_clear_prefs();
});
let trrServer = null;
add_task(async function start_trr_server() {
trrServer = new TRRServer();
registerCleanupFunction(async () => {
await trrServer.stop();
});
await trrServer.start();
dump(`port = ${trrServer.port}\n`);
Services.prefs.setCharPref(
"network.trr.uri",
`https://foo.example.com:${trrServer.port}/dns-query`
);
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
});
add_task(async function sanity_check() {
await trrServer.registerDoHAnswers("example.com", "A", {
answers: [
{
name: "example.com",
ttl: 55,
type: "A",
flush: false,
data: "1.2.3.4",
},
],
});
// Simple check to see that TRR works.
await new TRRDNSListener("example.com", { expectedAnswer: "1.2.3.4" });
});
add_task(async function cancel_immediately() {
await trrServer.registerDoHAnswers("example.org", "A", {
answers: [
{
name: "example.org",
ttl: 55,
type: "A",
flush: false,
data: "2.3.4.5",
},
],
});
let r1 = new TRRDNSListener("example.org", { expectedSuccess: false });
let r2 = new TRRDNSListener("example.org", { expectedAnswer: "2.3.4.5" });
r1.cancel();
let [, , inStatus] = await r1;
equal(inStatus, Cr.NS_ERROR_ABORT);
await r2;
equal(await trrServer.requestCount("example.org", "A"), 1);
// Now cancel both of them before a request is sent and check that
// no request reaches the server.
dns.clearCache(true);
r1 = new TRRDNSListener("example.org", { expectedSuccess: false });
r2 = new TRRDNSListener("example.org", { expectedSuccess: false });
r1.cancel();
r2.cancel();
[, , inStatus] = await r1;
equal(inStatus, Cr.NS_ERROR_ABORT);
[, , inStatus] = await r2;
equal(inStatus, Cr.NS_ERROR_ABORT);
equal(await trrServer.requestCount("example.org", "A"), 2);
});
add_task(async function cancel_delayed() {
dns.clearCache(true);
await trrServer.registerDoHAnswers("example.com", "A", {
answers: [
{
name: "example.com",
ttl: 55,
type: "A",
flush: false,
data: "1.1.1.1",
},
],
delay: 500,
});
let r1 = new TRRDNSListener("example.com", { expectedSuccess: false });
let r2 = new TRRDNSListener("example.com", { expectedAnswer: "1.1.1.1" });
await new Promise(resolve => do_timeout(50, resolve));
r1.cancel();
let [, , inStatus] = await r1;
equal(inStatus, Cr.NS_ERROR_ABORT);
await r2;
});
add_task(async function cancel_after_completed() {
dns.clearCache(true);
await trrServer.registerDoHAnswers("example.com", "A", {
answers: [
{
name: "example.com",
ttl: 55,
type: "A",
flush: false,
data: "2.2.2.2",
},
],
});
let r1 = new TRRDNSListener("example.com", { expectedAnswer: "2.2.2.2" });
await r1;
let r2 = new TRRDNSListener("example.com", { expectedAnswer: "2.2.2.2" });
// Check that cancelling r1 after it's complete does not affect r2 in any way.
r1.cancel();
await r2;
});
add_task(async function clearCacheWhileResolving() {
dns.clearCache(true);
await trrServer.registerDoHAnswers("example.com", "A", {
answers: [
{
name: "example.com",
ttl: 55,
type: "A",
flush: false,
data: "3.3.3.3",
},
],
delay: 500,
});
// Check that calling clearCache does not leave the request hanging.
let r1 = new TRRDNSListener("example.com", { expectedAnswer: "3.3.3.3" });
let r2 = new TRRDNSListener("example.com", { expectedAnswer: "3.3.3.3" });
dns.clearCache(true);
await r1;
await r2;
// Also check the same for HTTPS records
await trrServer.registerDoHAnswers("httpsvc.com", "HTTPS", {
answers: [
{
name: "httpsvc.com",
ttl: 55,
type: "HTTPS",
flush: false,
data: {
priority: 1,
name: "test.p1.com",
values: [{ key: "alpn", value: ["h2", "h3"] }],
},
},
],
delay: 500,
});
let r3 = new TRRDNSListener("httpsvc.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let r4 = new TRRDNSListener("httpsvc.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
dns.clearCache(true);
await r3;
await r4;
equal(await trrServer.requestCount("httpsvc.com", "HTTPS"), 1);
dns.clearCache(true);
await new TRRDNSListener("httpsvc.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
equal(await trrServer.requestCount("httpsvc.com", "HTTPS"), 2);
});

Просмотреть файл

@ -41,61 +41,8 @@ add_task(async function start_trr_server() {
});
await trrServer.start();
dump(`port = ${trrServer.port}\n`);
await trrServer.registerDoHAnswers(`faily.com`, "NS", {
answers: [
{
name: "faily.com",
ttl: 55,
type: "NS",
flush: false,
data: "ns.faily.com",
},
],
});
for (let i = 0; i < 15; i++) {
await trrServer.registerDoHAnswers(`failing-domain${i}.faily.com`, "A", {
error: 600,
});
await trrServer.registerDoHAnswers(`failing-domain${i}.faily.com`, "AAAA", {
error: 600,
});
}
});
function trigger15Failures() {
// We need to clear the cache in case a previous call to this method
// put the results in the DNS cache.
dns.clearCache(true);
let dnsRequests = [];
for (let i = 0; i < 15; i++) {
dnsRequests.push(
new TRRDNSListener(`failing-domain${i}.faily.com`, {
expectedAnswer: "127.0.0.1",
})
);
}
return Promise.all(dnsRequests);
}
async function registerNS(delay) {
return trrServer.registerDoHAnswers("confirm.example.com", "NS", {
answers: [
{
name: "confirm.example.com",
ttl: 55,
type: "NS",
flush: false,
data: "test.com",
},
],
delay,
});
}
add_task(async function confirm_off() {
Services.prefs.setCharPref(
"network.trr.confirmationNS",
@ -128,7 +75,17 @@ add_task(async function confirm_ok() {
"network.trr.confirmationNS",
"confirm.example.com"
);
await registerNS(0);
await trrServer.registerDoHAnswers("confirm.example.com", "NS", {
answers: [
{
name: "confirm.example.com",
ttl: 55,
type: "NS",
flush: false,
data: "test.com",
},
],
});
await trrServer.registerDoHAnswers("example.com", "A", {
answers: [
{
@ -142,7 +99,7 @@ add_task(async function confirm_ok() {
});
Services.prefs.setCharPref(
"network.trr.uri",
`https://foo.example.com:${trrServer.port}/dns-query`
`https://foo.example.com:${trrServer.port}/dns-query` // No server on this port
);
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
equal(
@ -151,10 +108,20 @@ add_task(async function confirm_ok() {
"Should be CONFIRM_TRYING_OK"
);
await new TRRDNSListener("example.com", { expectedAnswer: "1.2.3.4" });
equal(await trrServer.requestCount("example.com", "A"), 1);
await waitForConfirmationState(CONFIRM_OK, 1000);
await registerNS(500);
await trrServer.registerDoHAnswers("confirm.example.com", "NS", {
answers: [
{
name: "confirm.example.com",
ttl: 55,
type: "NS",
flush: false,
data: "test.com",
},
],
delay: 500,
});
Services.prefs.setIntPref(
"network.trr.mode",
Ci.nsIDNSService.MODE_NATIVEONLY
@ -180,7 +147,18 @@ add_task(async function confirm_timeout() {
Ci.nsIDNSService.MODE_NATIVEONLY
);
equal(dns.currentTrrConfirmationState, CONFIRM_OFF);
await registerNS(7000);
await trrServer.registerDoHAnswers("confirm.example.com", "NS", {
answers: [
{
name: "confirm.example.com",
ttl: 55,
type: "NS",
flush: false,
data: "test.com",
},
],
delay: 7000,
});
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
equal(
dns.currentTrrConfirmationState,
@ -217,8 +195,18 @@ add_task(async function multiple_failures() {
Ci.nsIDNSService.MODE_NATIVEONLY
);
equal(dns.currentTrrConfirmationState, CONFIRM_OFF);
await registerNS(100);
await trrServer.registerDoHAnswers("confirm.example.com", "NS", {
answers: [
{
name: "confirm.example.com",
ttl: 55,
type: "NS",
flush: false,
data: "test.com",
},
],
delay: 100,
});
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
equal(
dns.currentTrrConfirmationState,
@ -226,165 +214,27 @@ add_task(async function multiple_failures() {
"Should be CONFIRM_TRYING_OK"
);
await waitForConfirmationState(CONFIRM_OK, 1000);
await registerNS(4000);
let failures = trigger15Failures();
await waitForConfirmationState(CONFIRM_TRYING_OK, 3000);
await failures;
// Check that failures during confirmation are ignored.
await trigger15Failures();
equal(
dns.currentTrrConfirmationState,
CONFIRM_TRYING_OK,
"Should be CONFIRM_TRYING_OK"
);
await waitForConfirmationState(CONFIRM_OK, 4500);
});
add_task(async function test_connectivity_change() {
await registerNS(100);
Services.prefs.setIntPref(
"network.trr.mode",
Ci.nsIDNSService.MODE_NATIVEONLY
);
let confirmationCount = await trrServer.requestCount(
"confirm.example.com",
"NS"
);
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
equal(
dns.currentTrrConfirmationState,
CONFIRM_TRYING_OK,
"Should be CONFIRM_TRYING_OK"
);
await waitForConfirmationState(CONFIRM_OK, 1000);
equal(
await trrServer.requestCount("confirm.example.com", "NS"),
confirmationCount + 1
);
Services.obs.notifyObservers(
null,
"network:captive-portal-connectivity",
"clear"
);
// This means a CP check completed successfully. But no CP was previously
// detected, so this is mostly a no-op.
equal(dns.currentTrrConfirmationState, CONFIRM_OK);
Services.obs.notifyObservers(
null,
"network:captive-portal-connectivity",
"captive"
);
// This basically a successful CP login event. Wasn't captive before.
// Still treating as a no-op.
equal(dns.currentTrrConfirmationState, CONFIRM_OK);
// This makes the TRR service set mCaptiveIsPassed=false
Services.obs.notifyObservers(
null,
"captive-portal-login",
"{type: 'captive-portal-login', id: 0, url: 'http://localhost/'}"
);
await registerNS(500);
let failures = trigger15Failures();
// The failure should cause us to go into CONFIRM_TRYING_OK and do an NS req
await waitForConfirmationState(CONFIRM_TRYING_OK, 3000);
await failures;
// The notification sets mCaptiveIsPassed=true then triggers an entirely new
// confirmation.
Services.obs.notifyObservers(
null,
"network:captive-portal-connectivity",
"clear"
);
// The notification should cause us to send a new confirmation request
equal(
dns.currentTrrConfirmationState,
CONFIRM_TRYING_OK,
"Should be CONFIRM_TRYING_OK"
);
await waitForConfirmationState(CONFIRM_OK, 1000);
// two extra confirmation events should have been received by the server
equal(
await trrServer.requestCount("confirm.example.com", "NS"),
confirmationCount + 3
);
});
add_task(async function test_network_change() {
let confirmationCount = await trrServer.requestCount(
"confirm.example.com",
"NS"
);
equal(dns.currentTrrConfirmationState, CONFIRM_OK);
Services.obs.notifyObservers(null, "network:link-status-changed", "up");
equal(dns.currentTrrConfirmationState, CONFIRM_OK);
equal(
await trrServer.requestCount("confirm.example.com", "NS"),
confirmationCount
);
let failures = trigger15Failures();
// The failure should cause us to go into CONFIRM_TRYING_OK and do an NS req
await waitForConfirmationState(CONFIRM_TRYING_OK, 3000);
await failures;
// The network up event should reset the confirmation to TRYING_OK and do
// another NS req
Services.obs.notifyObservers(null, "network:link-status-changed", "up");
equal(dns.currentTrrConfirmationState, CONFIRM_TRYING_OK);
await waitForConfirmationState(CONFIRM_OK, 1000);
// two extra confirmation events should have been received by the server
equal(
await trrServer.requestCount("confirm.example.com", "NS"),
confirmationCount + 2
);
});
add_task(async function test_uri_pref_change() {
let confirmationCount = await trrServer.requestCount(
"confirm.example.com",
"NS"
);
equal(dns.currentTrrConfirmationState, CONFIRM_OK);
Services.prefs.setCharPref(
"network.trr.uri",
`https://foo.example.com:${trrServer.port}/dns-query?changed`
);
equal(dns.currentTrrConfirmationState, CONFIRM_TRYING_OK);
await waitForConfirmationState(CONFIRM_OK, 1000);
equal(
await trrServer.requestCount("confirm.example.com", "NS"),
confirmationCount + 1
);
});
add_task(async function test_autodetected_uri() {
const defaultPrefBranch = Services.prefs.getDefaultBranch("");
let defaultURI = defaultPrefBranch.getCharPref("network.trr.uri");
defaultPrefBranch.setCharPref(
"network.trr.uri",
`https://foo.example.com:${trrServer.port}/dns-query?changed`
);
// For setDetectedTrrURI to work we must pretend we are using the default.
Services.prefs.clearUserPref("network.trr.uri");
await waitForConfirmationState(CONFIRM_OK, 1000);
let confirmationCount = await trrServer.requestCount(
"confirm.example.com",
"NS"
);
dns.setDetectedTrrURI(
`https://foo.example.com:${trrServer.port}/dns-query?changed2`
);
equal(dns.currentTrrConfirmationState, CONFIRM_TRYING_OK);
await waitForConfirmationState(CONFIRM_OK, 1000);
equal(
await trrServer.requestCount("confirm.example.com", "NS"),
confirmationCount + 1
);
// reset the default URI
defaultPrefBranch.setCharPref("network.trr.uri", defaultURI);
for (let i = 0; i < 15; i++) {
await trrServer.registerDoHAnswers(`domain${i}.example.com`, "A", {
error: 600,
});
await trrServer.registerDoHAnswers(`domain${i}.example.com`, "AAAA", {
error: 600,
});
}
let p = waitForConfirmationState(CONFIRM_TRYING_OK, 3000);
let dnsRequests = [];
for (let i = 0; i < 15; i++) {
dnsRequests.push(
new TRRDNSListener(`domain${i}.example.com`, {
expectedAnswer: "127.0.0.1",
})
);
}
await p;
await Promise.all(dnsRequests);
await waitForConfirmationState(CONFIRM_OK, 1000);
});

Просмотреть файл

@ -6,8 +6,10 @@
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
let prefs;
let h2Port;
let h3Port;
let listen;
let trrServer;
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
@ -16,10 +18,14 @@ const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
const certOverrideService = Cc[
"@mozilla.org/security/certoverride;1"
].getService(Ci.nsICertOverrideService);
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
Ci.nsIThreadManager
);
const mainThread = threadManager.currentThread;
const defaultOriginAttributes = {};
function setup() {
trr_test_setup();
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
@ -31,31 +37,90 @@ function setup() {
Assert.notEqual(h3Port, null);
Assert.notEqual(h3Port, "");
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.security.esni.enabled", false);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
prefs.setBoolPref("network.dns.native-is-localhost", true);
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
prefs.setIntPref("network.trr.mode", 2); // TRR first
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
Services.prefs.setBoolPref("network.dns.upgrade_with_https_rr", true);
Services.prefs.setBoolPref("network.dns.use_https_rr_as_altsvc", true);
Services.prefs.setBoolPref("network.dns.echconfig.enabled", true);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
}
setup();
registerCleanupFunction(async () => {
trr_clear_prefs();
Services.prefs.clearUserPref("network.dns.upgrade_with_https_rr");
Services.prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
Services.prefs.clearUserPref("network.dns.echconfig.enabled");
Services.prefs.clearUserPref("network.dns.echconfig.fallback_to_origin");
Services.prefs.clearUserPref("network.dns.httpssvc.reset_exclustion_list");
Services.prefs.clearUserPref("network.http.http3.enabled");
Services.prefs.clearUserPref(
"network.dns.httpssvc.http3_fast_fallback_timeout"
);
Services.prefs.clearUserPref("network.http.speculative-parallel-limit");
prefs.clearUserPref("network.security.esni.enabled");
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
prefs.clearUserPref("network.dns.upgrade_with_https_rr");
prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
prefs.clearUserPref("network.dns.echconfig.enabled");
prefs.clearUserPref("network.dns.echconfig.fallback_to_origin");
prefs.clearUserPref("network.dns.httpssvc.reset_exclustion_list");
prefs.clearUserPref("network.http.http3.enabled");
prefs.clearUserPref("network.dns.httpssvc.http3_fast_fallback_timeout");
prefs.clearUserPref("network.http.speculative-parallel-limit");
if (trrServer) {
await trrServer.stop();
}
});
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
function makeChan(url) {
let chan = NetUtil.newChannel({
uri: url,
@ -156,9 +221,21 @@ add_task(async function testFallbackToTheLastRecord() {
],
});
await new TRRDNSListener("test.fallback.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.fallback.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let chan = makeChan(`https://test.fallback.com:${h2Port}/server-timing`);
let [req] = await channelOpenPromise(chan);
@ -238,9 +315,21 @@ add_task(async function testFallbackToTheOrigin() {
],
});
await new TRRDNSListener("test.foo.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.foo.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let chan = makeChan(`https://test.foo.com:${h2Port}/server-timing`);
let [req] = await channelOpenPromise(chan);
@ -309,9 +398,21 @@ add_task(async function testAllRecordsFailed() {
],
});
await new TRRDNSListener("test.bar.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.bar.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
// This channel should be failed.
let chan = makeChan(`https://test.bar.com:${h2Port}/server-timing`);
@ -358,9 +459,21 @@ add_task(async function testFallbackToTheOrigin2() {
],
});
await new TRRDNSListener("test.example.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.example.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let chan = makeChan(`https://test.example.com:${h2Port}/server-timing`);
await channelOpenPromise(chan, CL_EXPECT_LATE_FAILURE | CL_ALLOW_UNKNOWN_CL);
@ -452,9 +565,21 @@ add_task(async function testFallbackToTheOrigin3() {
],
});
await new TRRDNSListener("vulnerable.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"vulnerable.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let chan = makeChan(`https://vulnerable.com:${h2Port}/server-timing`);
await channelOpenPromise(chan);
@ -509,9 +634,21 @@ add_task(async function testResetExclusionList() {
],
});
await new TRRDNSListener("test.reset.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.reset.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
// After this request, test.reset1.com and test.reset2.com should be both in
// the exclusion list.
@ -595,9 +732,21 @@ add_task(async function testH3Connection() {
],
});
await new TRRDNSListener("test.h3.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.h3.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let chan = makeChan(`https://test.h3.com`);
let [req] = await channelOpenPromise(chan);
@ -670,9 +819,21 @@ add_task(async function testFastfallbackToH2() {
],
});
await new TRRDNSListener("test.fastfallback.com", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.fastfallback.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let chan = makeChan(`https://test.fastfallback.com/server-timing`);
let [req] = await channelOpenPromise(chan);
@ -731,9 +892,21 @@ add_task(async function testFailedH3Connection() {
],
});
await new TRRDNSListener("test.h3.org", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.h3.org",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let chan = makeChan(`https://test.h3.org`);
await channelOpenPromise(chan, CL_EXPECT_LATE_FAILURE | CL_ALLOW_UNKNOWN_CL);
@ -802,9 +975,21 @@ add_task(async function testHttp3ExcludedList() {
],
});
await new TRRDNSListener("test.h3_excluded.org", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.h3_excluded.org",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
chan = makeChan(`https://test.h3_excluded.org`);
let [req] = await channelOpenPromise(chan);
@ -905,9 +1090,21 @@ add_task(async function testAllRecordsInHttp3ExcludedList() {
],
});
await new TRRDNSListener("www.h3_all_excluded.org", {
type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"www.h3_all_excluded.org",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0);
Services.obs.notifyObservers(null, "net:prune-all-connections");

Просмотреть файл

@ -6,7 +6,9 @@
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
let prefs;
let h2Port;
let listen;
function inChildProcess() {
return (
@ -18,9 +20,14 @@ function inChildProcess() {
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
Ci.nsIDNSService
);
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
Ci.nsIThreadManager
);
const mainThread = threadManager.currentThread;
const defaultOriginAttributes = {};
function setup() {
trr_test_setup();
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
@ -28,28 +35,99 @@ function setup() {
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRFIRST);
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
prefs.setBoolPref("network.dns.native-is-localhost", true);
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
prefs.setIntPref("network.trr.mode", 2); // TRR first
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
}
if (!inChildProcess()) {
setup();
registerCleanupFunction(() => {
trr_clear_prefs();
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.blacklist-duration");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
});
}
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
add_task(async function testHTTPSSVC() {
// use the h2 server as DOH provider
if (!inChildProcess()) {
Services.prefs.setCharPref(
prefs.setCharPref(
"network.trr.uri",
"https://foo.example.com:" + h2Port + "/httpssvc"
);
}
let [, inRecord] = await new TRRDNSListener("test.httpssvc.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
});
let listenerEsni = new DNSListener();
let request = dns.asyncResolve(
"test.httpssvc.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listenerEsni,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus] = await listenerEsni;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
Assert.equal(answer[0].priority, 1);
Assert.equal(answer[0].name, "h3pool");
@ -372,10 +450,19 @@ add_task(async function test_aliasform() {
],
});
let [, , inStatus2] = await new TRRDNSListener("multi.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
expectedSuccess: false,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"multi.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus2] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.ok(
!Components.isSuccessCode(inStatus2),
`${inStatus2} should be an error code`
@ -405,10 +492,19 @@ add_task(async function test_aliasform() {
],
});
[, , inStatus2] = await new TRRDNSListener("order.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
expectedSuccess: false,
});
listener = new DNSListener();
request = dns.asyncResolve(
"order.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
[inRequest, inRecord, inStatus2] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.ok(
!Components.isSuccessCode(inStatus2),
`${inStatus2} should be an error code`
@ -434,10 +530,19 @@ add_task(async function test_aliasform() {
],
});
[, , inStatus2] = await new TRRDNSListener("duplicate.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
expectedSuccess: false,
});
listener = new DNSListener();
request = dns.asyncResolve(
"duplicate.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
[inRequest, inRecord, inStatus2] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.ok(
!Components.isSuccessCode(inStatus2),
`${inStatus2} should be an error code`
@ -464,10 +569,19 @@ add_task(async function test_aliasform() {
],
});
[, , inStatus2] = await new TRRDNSListener("mandatory.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
expectedSuccess: false,
});
listener = new DNSListener();
request = dns.asyncResolve(
"mandatory.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
[inRequest, inRecord, inStatus2] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.ok(!Components.isSuccessCode(inStatus2), `${inStatus2} should fail`);
// mandatory svcparam
@ -505,10 +619,19 @@ add_task(async function test_aliasform() {
],
});
[, , inStatus2] = await new TRRDNSListener("mandatory2.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
});
listener = new DNSListener();
request = dns.asyncResolve(
"mandatory2.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
[inRequest, inRecord, inStatus2] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.ok(Components.isSuccessCode(inStatus2), `${inStatus2} should succeed`);
// alias-mode with . targetName
@ -528,11 +651,19 @@ add_task(async function test_aliasform() {
],
});
[, , inStatus2] = await new TRRDNSListener("no-alias.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
expectedSuccess: false,
});
listener = new DNSListener();
request = dns.asyncResolve(
"no-alias.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
[inRequest, inRecord, inStatus2] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.ok(!Components.isSuccessCode(inStatus2), `${inStatus2} should fail`);
// service-mode with . targetName
@ -552,10 +683,19 @@ add_task(async function test_aliasform() {
],
});
let inRecord;
[, inRecord, inStatus2] = await new TRRDNSListener("service.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
});
listener = new DNSListener();
request = dns.asyncResolve(
"service.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
[inRequest, inRecord, inStatus2] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.ok(Components.isSuccessCode(inStatus2), `${inStatus2} should work`);
let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
Assert.equal(answer[0].priority, 1);

Просмотреть файл

@ -6,7 +6,9 @@
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
let prefs;
let h2Port;
let listen;
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
Ci.nsIDNSService
@ -14,29 +16,94 @@ const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
const certOverrideService = Cc[
"@mozilla.org/security/certoverride;1"
].getService(Ci.nsICertOverrideService);
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
Ci.nsIThreadManager
);
const mainThread = threadManager.currentThread;
const defaultOriginAttributes = {};
function setup() {
trr_test_setup();
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
h2Port = env.get("MOZHTTP2_PORT");
Assert.notEqual(h2Port, null);
Assert.notEqual(h2Port, "");
Services.prefs.setIntPref("network.trr.mode", 2); // TRR first
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
prefs.setBoolPref("network.dns.native-is-localhost", true);
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
prefs.setIntPref("network.trr.mode", 2); // TRR first
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
Services.prefs.setBoolPref("network.dns.upgrade_with_https_rr", true);
Services.prefs.setBoolPref("network.dns.use_https_rr_as_altsvc", true);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
}
setup();
registerCleanupFunction(() => {
trr_clear_prefs();
Services.prefs.clearUserPref("network.dns.upgrade_with_https_rr");
Services.prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.blacklist-duration");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
prefs.clearUserPref("network.dns.upgrade_with_https_rr");
prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
});
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
function makeChan(url) {
let chan = NetUtil.newChannel({
uri: url,
@ -61,7 +128,7 @@ function channelOpenPromise(chan) {
// the transaction is added in connection manager.
add_task(async function testUseHTTPSSVCForHttpsUpgrade() {
// use the h2 server as DOH provider
Services.prefs.setCharPref(
prefs.setCharPref(
"network.trr.uri",
"https://foo.example.com:" + h2Port + "/httpssvc_as_altsvc"
);
@ -102,7 +169,7 @@ EventSinkListener.prototype.QueryInterface = ChromeUtils.generateQI([
// Test if the request is upgraded to https with a HTTPSSVC record.
add_task(async function testUseHTTPSSVCAsHSTS() {
// use the h2 server as DOH provider
Services.prefs.setCharPref(
prefs.setCharPref(
"network.trr.uri",
"https://foo.example.com:" + h2Port + "/httpssvc_as_altsvc"
);
@ -143,16 +210,28 @@ add_task(async function testUseHTTPSSVCAsHSTS() {
// the transaction is added in connection manager.
add_task(async function testUseHTTPSSVC() {
// use the h2 server as DOH provider
Services.prefs.setCharPref(
prefs.setCharPref(
"network.trr.uri",
"https://foo.example.com:" + h2Port + "/httpssvc_as_altsvc"
);
let listener = new DNSListener();
// Do DNS resolution before creating the channel, so the HTTPSSVC record will
// be resolved from the cache.
await new TRRDNSListener("test.httpssvc.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
});
let request = dns.asyncResolve(
"test.httpssvc.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, , inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
// We need to skip the security check, since our test cert is signed for
// foo.example.com, not test.httpssvc.com.
@ -212,9 +291,21 @@ add_task(async function testFallback() {
],
});
let [, inRecord] = await new TRRDNSListener("test.fallback.com", {
type: dns.RESOLVE_TYPE_HTTPSSVC,
});
let listener = new DNSListener();
let request = dns.asyncResolve(
"test.fallback.com",
dns.RESOLVE_TYPE_HTTPSSVC,
0,
null, // resolverInfo
listener,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus] = await listener;
Assert.equal(inRequest, request, "correct request was used");
Assert.equal(inStatus, Cr.NS_OK, "status OK");
let record = inRecord
.QueryInterface(Ci.nsIDNSHTTPSSVCRecord)

Просмотреть файл

@ -523,6 +523,3 @@ run-sequentially = node server exceptions dont replay well
[test_trr_confirmation.js]
skip-if = os =='android' || socketprocess_networking # confirmation state isn't passed cross-process
run-sequentially = node server exceptions dont replay well
[test_trr_cancel.js]
skip-if = os =='android'
run-sequentially = node server exceptions dont replay well

Просмотреть файл

@ -1,24 +1,53 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/* import-globals-from ../unit/head_trr.js */
const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
Ci.nsIDNSService
);
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
Ci.nsIThreadManager
);
const mainThread = threadManager.currentThread;
const defaultOriginAttributes = {};
let test_answer = "bXkgdm9pY2UgaXMgbXkgcGFzc3dvcmQ=";
let test_answer_addr = "127.0.0.1";
class DNSListener {
constructor() {
this.promise = new Promise(resolve => {
this.resolve = resolve;
});
}
onLookupComplete(inRequest, inRecord, inStatus) {
this.resolve([inRequest, inRecord, inStatus]);
}
// So we can await this as a promise.
then() {
return this.promise.then.apply(this.promise, arguments);
}
}
DNSListener.prototype.QueryInterface = ChromeUtils.generateQI([
"nsIDNSListener",
]);
add_task(async function testTXTResolve() {
// use the h2 server as DOH provider
let [, inRecord, inStatus] = await new TRRDNSListener("_esni.example.com", {
type: dns.RESOLVE_TYPE_TXT,
});
let listenerEsni = new DNSListener();
let request = dns.asyncResolve(
"_esni.example.com",
dns.RESOLVE_TYPE_TXT,
0,
null, // resolverInfo
listenerEsni,
mainThread,
defaultOriginAttributes
);
let [inRequest, inRecord, inStatus] = await listenerEsni;
Assert.equal(inStatus, Cr.NS_OK, "status OK");
Assert.equal(inRequest, request, "correct request was used");
let answer = inRecord
.QueryInterface(Ci.nsIDNSTXTRecord)
.getRecordsAsOneString();

Просмотреть файл

@ -1,8 +1,7 @@
"use strict";
let h2Port;
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
let prefs;
function setup() {
let env = Cc["@mozilla.org/process/environment;1"].getService(
@ -14,45 +13,57 @@ function setup() {
// Set to allow the cert presented by our H2 server
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
Services.prefs.setBoolPref("network.http.spdy.enabled", true);
Services.prefs.setBoolPref("network.http.spdy.enabled.http2", true);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
// the TRR server is on 127.0.0.1
Services.prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
// make all native resolve calls "secretly" resolve localhost instead
Services.prefs.setBoolPref("network.dns.native-is-localhost", true);
prefs.setBoolPref("network.dns.native-is-localhost", true);
// 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
Services.prefs.setBoolPref("network.trr.wait-for-portal", false);
prefs.setIntPref("network.trr.mode", 2); // TRR first
prefs.setBoolPref("network.trr.wait-for-portal", false);
// don't confirm that TRR is working, just go!
Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
prefs.setCharPref("network.trr.confirmationNS", "skip");
// So we can change the pref without clearing the cache to check a pushed
// record with a TRR path that fails.
Services.prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
prefs.setBoolPref("network.trr.clear-cache-on-pref-change", false);
// The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
// so add that cert to the trust list as a signing cert. // the foo.example.com domain name.
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
// XXX(valentin): It would be nice to just call trr_test_setup() here, but
// the relative path here makes it awkward. Would be nice to fix someday.
addCertFromFile(certdb, "../unit/http2-ca.pem", "CTu,u,u");
}
setup();
registerCleanupFunction(() => {
trr_clear_prefs();
prefs.clearUserPref("network.http.spdy.enabled");
prefs.clearUserPref("network.http.spdy.enabled.http2");
prefs.clearUserPref("network.dns.localDomains");
prefs.clearUserPref("network.dns.native-is-localhost");
prefs.clearUserPref("network.trr.mode");
prefs.clearUserPref("network.trr.uri");
prefs.clearUserPref("network.trr.credentials");
prefs.clearUserPref("network.trr.wait-for-portal");
prefs.clearUserPref("network.trr.allow-rfc1918");
prefs.clearUserPref("network.trr.useGET");
prefs.clearUserPref("network.trr.confirmationNS");
prefs.clearUserPref("network.trr.bootstrapAddress");
prefs.clearUserPref("network.trr.blacklist-duration");
prefs.clearUserPref("network.trr.request-timeout");
prefs.clearUserPref("network.trr.clear-cache-on-pref-change");
});
function run_test() {
Services.prefs.setCharPref(
prefs.setCharPref(
"network.trr.uri",
"https://foo.example.com:" + h2Port + "/doh"
);
Services.prefs.setIntPref("network.trr.mode", 2); // TRR first
run_test_in_child("child_dns_by_type_resolve.js");
}