Pier Angelo Vendrame pushed to branch mullvad-browser-128.5.0esr-14.5-1 at The Tor Project / Applications / Mullvad Browser
Commits:
-
c1966f06
by Kershaw Chang at 2024-12-17T12:40:47+01:00
15 changed files:
- dom/chrome-webidl/NetDashboard.webidl
- netwerk/base/Dashboard.cpp
- netwerk/base/DashboardTypes.h
- netwerk/dns/nsHostResolver.cpp
- netwerk/protocol/http/nsHttp.cpp
- netwerk/protocol/http/nsHttp.h
- netwerk/protocol/http/nsHttpChannel.cpp
- netwerk/protocol/http/nsHttpChannel.h
- netwerk/protocol/http/nsHttpConnectionInfo.h
- netwerk/protocol/http/nsHttpConnectionMgr.cpp
- netwerk/protocol/http/nsHttpHandler.cpp
- netwerk/protocol/http/nsHttpHandler.h
- + netwerk/test/unit/test_proxyDNS_leak.js
- netwerk/test/unit/xpcshell.toml
- toolkit/content/aboutNetworking.js
Changes:
... | ... | @@ -68,6 +68,7 @@ dictionary DnsCacheEntry { |
68 | 68 | boolean trr = false;
|
69 | 69 | DOMString originAttributesSuffix = "";
|
70 | 70 | DOMString flags = "";
|
71 | + unsigned short type = 0;
|
|
71 | 72 | };
|
72 | 73 | |
73 | 74 | [GenerateConversionToJS]
|
... | ... | @@ -906,10 +906,13 @@ nsresult Dashboard::GetDNSCacheEntries(DnsData* dnsData) { |
906 | 906 | CopyASCIItoUTF16(dnsData->mData[i].hostaddr[j], *addr);
|
907 | 907 | }
|
908 | 908 | |
909 | - if (dnsData->mData[i].family == PR_AF_INET6) {
|
|
910 | - entry.mFamily.AssignLiteral(u"ipv6");
|
|
911 | - } else {
|
|
912 | - entry.mFamily.AssignLiteral(u"ipv4");
|
|
909 | + entry.mType = dnsData->mData[i].resolveType;
|
|
910 | + if (entry.mType == nsIDNSService::RESOLVE_TYPE_DEFAULT) {
|
|
911 | + if (dnsData->mData[i].family == PR_AF_INET6) {
|
|
912 | + entry.mFamily.AssignLiteral(u"ipv6");
|
|
913 | + } else {
|
|
914 | + entry.mFamily.AssignLiteral(u"ipv4");
|
|
915 | + }
|
|
913 | 916 | }
|
914 | 917 | |
915 | 918 | entry.mOriginAttributesSuffix =
|
... | ... | @@ -35,12 +35,12 @@ struct DnsAndConnectSockets { |
35 | 35 | struct DNSCacheEntries {
|
36 | 36 | nsCString hostname;
|
37 | 37 | nsTArray<nsCString> hostaddr;
|
38 | - uint16_t family;
|
|
39 | - int64_t expiration;
|
|
40 | - nsCString netInterface;
|
|
41 | - bool TRR;
|
|
38 | + uint16_t family{0};
|
|
39 | + int64_t expiration{0};
|
|
40 | + bool TRR{false};
|
|
42 | 41 | nsCString originAttributesSuffix;
|
43 | 42 | nsCString flags;
|
43 | + uint16_t resolveType{0};
|
|
44 | 44 | };
|
45 | 45 | |
46 | 46 | struct HttpConnInfo {
|
... | ... | @@ -99,8 +99,10 @@ struct ParamTraits<mozilla::net::DNSCacheEntries> { |
99 | 99 | WriteParam(aWriter, aParam.hostaddr);
|
100 | 100 | WriteParam(aWriter, aParam.family);
|
101 | 101 | WriteParam(aWriter, aParam.expiration);
|
102 | - WriteParam(aWriter, aParam.netInterface);
|
|
103 | 102 | WriteParam(aWriter, aParam.TRR);
|
103 | + WriteParam(aWriter, aParam.originAttributesSuffix);
|
|
104 | + WriteParam(aWriter, aParam.flags);
|
|
105 | + WriteParam(aWriter, aParam.resolveType);
|
|
104 | 106 | }
|
105 | 107 | |
106 | 108 | static bool Read(MessageReader* aReader, paramType* aResult) {
|
... | ... | @@ -108,8 +110,10 @@ struct ParamTraits<mozilla::net::DNSCacheEntries> { |
108 | 110 | ReadParam(aReader, &aResult->hostaddr) &&
|
109 | 111 | ReadParam(aReader, &aResult->family) &&
|
110 | 112 | ReadParam(aReader, &aResult->expiration) &&
|
111 | - ReadParam(aReader, &aResult->netInterface) &&
|
|
112 | - ReadParam(aReader, &aResult->TRR);
|
|
113 | + ReadParam(aReader, &aResult->TRR) &&
|
|
114 | + ReadParam(aReader, &aResult->originAttributesSuffix) &&
|
|
115 | + ReadParam(aReader, &aResult->flags) &&
|
|
116 | + ReadParam(aReader, &aResult->resolveType);
|
|
113 | 117 | }
|
114 | 118 | };
|
115 | 119 |
... | ... | @@ -1999,20 +1999,13 @@ void nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries>* args) { |
1999 | 1999 | continue;
|
2000 | 2000 | }
|
2001 | 2001 | |
2002 | - // For now we only show A/AAAA records.
|
|
2003 | - if (!rec->IsAddrRecord()) {
|
|
2004 | - continue;
|
|
2005 | - }
|
|
2006 | - |
|
2007 | - RefPtr<AddrHostRecord> addrRec = do_QueryObject(rec);
|
|
2008 | - MOZ_ASSERT(addrRec);
|
|
2009 | - if (!addrRec || !addrRec->addr_info) {
|
|
2010 | - continue;
|
|
2011 | - }
|
|
2012 | - |
|
2013 | 2002 | DNSCacheEntries info;
|
2003 | + info.resolveType = rec->type;
|
|
2014 | 2004 | info.hostname = rec->host;
|
2015 | 2005 | info.family = rec->af;
|
2006 | + if (rec->mValidEnd.IsNull()) {
|
|
2007 | + continue;
|
|
2008 | + }
|
|
2016 | 2009 | info.expiration =
|
2017 | 2010 | (int64_t)(rec->mValidEnd - TimeStamp::NowLoRes()).ToSeconds();
|
2018 | 2011 | if (info.expiration <= 0) {
|
... | ... | @@ -2020,7 +2013,12 @@ void nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries>* args) { |
2020 | 2013 | continue;
|
2021 | 2014 | }
|
2022 | 2015 | |
2023 | - {
|
|
2016 | + info.originAttributesSuffix = recordEntry.GetKey().originSuffix;
|
|
2017 | + info.flags = nsPrintfCString("%u|0x%x|%u|%d|%s", rec->type, rec->flags,
|
|
2018 | + rec->af, rec->pb, rec->mTrrServer.get());
|
|
2019 | + |
|
2020 | + RefPtr<AddrHostRecord> addrRec = do_QueryObject(rec);
|
|
2021 | + if (addrRec && addrRec->addr_info) {
|
|
2024 | 2022 | MutexAutoLock lock(addrRec->addr_info_lock);
|
2025 | 2023 | for (const auto& addr : addrRec->addr_info->Addresses()) {
|
2026 | 2024 | char buf[kIPv6CStrBufSize];
|
... | ... | @@ -2031,10 +2029,6 @@ void nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries>* args) { |
2031 | 2029 | info.TRR = addrRec->addr_info->IsTRR();
|
2032 | 2030 | }
|
2033 | 2031 | |
2034 | - info.originAttributesSuffix = recordEntry.GetKey().originSuffix;
|
|
2035 | - info.flags = nsPrintfCString("%u|0x%x|%u|%d|%s", rec->type, rec->flags,
|
|
2036 | - rec->af, rec->pb, rec->mTrrServer.get());
|
|
2037 | - |
|
2038 | 2032 | args->AppendElement(std::move(info));
|
2039 | 2033 | }
|
2040 | 2034 | }
|
... | ... | @@ -35,6 +35,8 @@ |
35 | 35 | namespace mozilla {
|
36 | 36 | namespace net {
|
37 | 37 | |
38 | +extern const char kProxyType_SOCKS[];
|
|
39 | + |
|
38 | 40 | const uint32_t kHttp3VersionCount = 5;
|
39 | 41 | const nsCString kHttp3Versions[] = {"h3-29"_ns, "h3-30"_ns, "h3-31"_ns,
|
40 | 42 | "h3-32"_ns, "h3"_ns};
|
... | ... | @@ -1165,5 +1167,19 @@ void DisallowHTTPSRR(uint32_t& aCaps) { |
1165 | 1167 | aCaps = (aCaps | NS_HTTP_DISALLOW_HTTPS_RR) & ~NS_HTTP_FORCE_WAIT_HTTP_RR;
|
1166 | 1168 | }
|
1167 | 1169 | |
1170 | +ProxyDNSStrategy GetProxyDNSStrategyHelper(const char* aType, uint32_t aFlag) {
|
|
1171 | + if (!aType) {
|
|
1172 | + return ProxyDNSStrategy::ORIGIN;
|
|
1173 | + }
|
|
1174 | + |
|
1175 | + if (!(aFlag & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST)) {
|
|
1176 | + if (aType == kProxyType_SOCKS) {
|
|
1177 | + return ProxyDNSStrategy::ORIGIN;
|
|
1178 | + }
|
|
1179 | + }
|
|
1180 | + |
|
1181 | + return ProxyDNSStrategy::PROXY;
|
|
1182 | +}
|
|
1183 | + |
|
1168 | 1184 | } // namespace net
|
1169 | 1185 | } // namespace mozilla |
... | ... | @@ -527,6 +527,16 @@ bool PossibleZeroRTTRetryError(nsresult aReason); |
527 | 527 | |
528 | 528 | void DisallowHTTPSRR(uint32_t& aCaps);
|
529 | 529 | |
530 | +enum class ProxyDNSStrategy : uint8_t {
|
|
531 | + // To resolve the origin of the end server we are connecting
|
|
532 | + // to.
|
|
533 | + ORIGIN = 1 << 0,
|
|
534 | + // To resolve the host name of the proxy.
|
|
535 | + PROXY = 1 << 1
|
|
536 | +};
|
|
537 | + |
|
538 | +ProxyDNSStrategy GetProxyDNSStrategyHelper(const char* aType, uint32_t aFlag);
|
|
539 | + |
|
530 | 540 | } // namespace net
|
531 | 541 | } // namespace mozilla
|
532 | 542 |
... | ... | @@ -762,6 +762,10 @@ nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade, |
762 | 762 | }
|
763 | 763 | |
764 | 764 | auto shouldSkipUpgradeWithHTTPSRR = [&]() -> bool {
|
765 | + if (mCaps & NS_HTTP_DISALLOW_HTTPS_RR) {
|
|
766 | + return true;
|
|
767 | + }
|
|
768 | + |
|
765 | 769 | // Skip using HTTPS RR to upgrade when this is not a top-level load and the
|
766 | 770 | // loading principal is http.
|
767 | 771 | if ((mLoadInfo->GetExternalContentPolicyType() !=
|
... | ... | @@ -784,6 +788,11 @@ nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade, |
784 | 788 | return true;
|
785 | 789 | }
|
786 | 790 | |
791 | + auto dnsStrategy = GetProxyDNSStrategy();
|
|
792 | + if (dnsStrategy != ProxyDNSStrategy::ORIGIN) {
|
|
793 | + return true;
|
|
794 | + }
|
|
795 | + |
|
787 | 796 | nsAutoCString uriHost;
|
788 | 797 | mURI->GetAsciiHost(uriHost);
|
789 | 798 | |
... | ... | @@ -808,11 +817,6 @@ nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade, |
808 | 817 | return ContinueOnBeforeConnect(hasHTTPSRR, aStatus, hasHTTPSRR);
|
809 | 818 | }
|
810 | 819 | |
811 | - auto dnsStrategy = GetProxyDNSStrategy();
|
|
812 | - if (!(dnsStrategy & DNS_PREFETCH_ORIGIN)) {
|
|
813 | - return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
|
|
814 | - }
|
|
815 | - |
|
816 | 820 | LOG(("nsHttpChannel::MaybeUseHTTPSRRForUpgrade [%p] wait for HTTPS RR",
|
817 | 821 | this));
|
818 | 822 | |
... | ... | @@ -1218,13 +1222,13 @@ void nsHttpChannel::SpeculativeConnect() { |
1218 | 1222 | NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
|
1219 | 1223 | getter_AddRefs(callbacks));
|
1220 | 1224 | if (!callbacks) return;
|
1221 | - |
|
1222 | - Unused << gHttpHandler->SpeculativeConnect(
|
|
1225 | + bool httpsRRAllowed = !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR);
|
|
1226 | + Unused << gHttpHandler->MaybeSpeculativeConnectWithHTTPSRR(
|
|
1223 | 1227 | mConnectionInfo, callbacks,
|
1224 | 1228 | mCaps & (NS_HTTP_DISALLOW_SPDY | NS_HTTP_TRR_MODE_MASK |
|
1225 | 1229 | NS_HTTP_DISABLE_IPV4 | NS_HTTP_DISABLE_IPV6 |
|
1226 | 1230 | NS_HTTP_DISALLOW_HTTP3 | NS_HTTP_REFRESH_DNS),
|
1227 | - gHttpHandler->EchConfigEnabled());
|
|
1231 | + gHttpHandler->EchConfigEnabled() && httpsRRAllowed);
|
|
1228 | 1232 | }
|
1229 | 1233 | |
1230 | 1234 | void nsHttpChannel::DoNotifyListenerCleanup() {
|
... | ... | @@ -6538,27 +6542,16 @@ nsHttpChannel::GetOrCreateChannelClassifier() { |
6538 | 6542 | return classifier.forget();
|
6539 | 6543 | }
|
6540 | 6544 | |
6541 | -uint16_t nsHttpChannel::GetProxyDNSStrategy() {
|
|
6542 | - // This function currently only supports returning DNS_PREFETCH_ORIGIN.
|
|
6543 | - // Support for the rest of the DNS_* flags will be added later.
|
|
6544 | - |
|
6545 | - if (!mProxyInfo) {
|
|
6546 | - return DNS_PREFETCH_ORIGIN;
|
|
6545 | +ProxyDNSStrategy nsHttpChannel::GetProxyDNSStrategy() {
|
|
6546 | + // When network_dns_force_use_https_rr is true, return DNS_PREFETCH_ORIGIN.
|
|
6547 | + // This ensures that we always perform HTTPS RR query.
|
|
6548 | + nsCOMPtr<nsProxyInfo> proxyInfo(static_cast<nsProxyInfo*>(mProxyInfo.get()));
|
|
6549 | + if (!proxyInfo || StaticPrefs::network_dns_force_use_https_rr()) {
|
|
6550 | + return ProxyDNSStrategy::ORIGIN;
|
|
6547 | 6551 | }
|
6548 | 6552 | |
6549 | - uint32_t flags = 0;
|
|
6550 | - nsAutoCString type;
|
|
6551 | - mProxyInfo->GetFlags(&flags);
|
|
6552 | - mProxyInfo->GetType(type);
|
|
6553 | - |
|
6554 | 6553 | // If the proxy is not to perform name resolution itself.
|
6555 | - if (!(flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST)) {
|
|
6556 | - if (type.EqualsLiteral("socks")) {
|
|
6557 | - return DNS_PREFETCH_ORIGIN;
|
|
6558 | - }
|
|
6559 | - }
|
|
6560 | - |
|
6561 | - return 0;
|
|
6554 | + return GetProxyDNSStrategyHelper(proxyInfo->Type(), proxyInfo->Flags());
|
|
6562 | 6555 | }
|
6563 | 6556 | |
6564 | 6557 | // BeginConnect() SHOULD NOT call AsyncAbort(). AsyncAbort will be called by
|
... | ... | @@ -6744,11 +6737,13 @@ nsresult nsHttpChannel::BeginConnect() { |
6744 | 6737 | }
|
6745 | 6738 | |
6746 | 6739 | bool trrEnabled = false;
|
6740 | + auto dnsStrategy = GetProxyDNSStrategy();
|
|
6747 | 6741 | bool httpsRRAllowed =
|
6748 | 6742 | !LoadBeConservative() && !(mCaps & NS_HTTP_BE_CONSERVATIVE) &&
|
6749 | 6743 | !(mLoadInfo->TriggeringPrincipal()->IsSystemPrincipal() &&
|
6750 | 6744 | mLoadInfo->GetExternalContentPolicyType() !=
|
6751 | 6745 | ExtContentPolicy::TYPE_DOCUMENT) &&
|
6746 | + dnsStrategy == ProxyDNSStrategy::ORIGIN &&
|
|
6752 | 6747 | !mConnectionInfo->UsingConnect() && canUseHTTPSRRonNetwork(trrEnabled) &&
|
6753 | 6748 | StaticPrefs::network_dns_use_https_rr_as_altsvc();
|
6754 | 6749 | if (!httpsRRAllowed) {
|
... | ... | @@ -6859,16 +6854,7 @@ nsresult nsHttpChannel::BeginConnect() { |
6859 | 6854 | ReEvaluateReferrerAfterTrackingStatusIsKnown();
|
6860 | 6855 | }
|
6861 | 6856 | |
6862 | - rv = MaybeStartDNSPrefetch();
|
|
6863 | - if (NS_FAILED(rv)) {
|
|
6864 | - auto dnsStrategy = GetProxyDNSStrategy();
|
|
6865 | - if (dnsStrategy & DNS_BLOCK_ON_ORIGIN_RESOLVE) {
|
|
6866 | - // TODO: Should this be fatal?
|
|
6867 | - return rv;
|
|
6868 | - }
|
|
6869 | - // Otherwise this shouldn't be fatal.
|
|
6870 | - return NS_OK;
|
|
6871 | - }
|
|
6857 | + MaybeStartDNSPrefetch();
|
|
6872 | 6858 | |
6873 | 6859 | rv = CallOrWaitForResume(
|
6874 | 6860 | [](nsHttpChannel* self) { return self->PrepareToConnect(); });
|
... | ... | @@ -6888,7 +6874,7 @@ nsresult nsHttpChannel::BeginConnect() { |
6888 | 6874 | return NS_OK;
|
6889 | 6875 | }
|
6890 | 6876 | |
6891 | -nsresult nsHttpChannel::MaybeStartDNSPrefetch() {
|
|
6877 | +void nsHttpChannel::MaybeStartDNSPrefetch() {
|
|
6892 | 6878 | // Start a DNS lookup very early in case the real open is queued the DNS can
|
6893 | 6879 | // happen in parallel. Do not do so in the presence of an HTTP proxy as
|
6894 | 6880 | // all lookups other than for the proxy itself are done by the proxy.
|
... | ... | @@ -6904,7 +6890,7 @@ nsresult nsHttpChannel::MaybeStartDNSPrefetch() { |
6904 | 6890 | // timing we used.
|
6905 | 6891 | if ((mLoadFlags & (LOAD_NO_NETWORK_IO | LOAD_ONLY_FROM_CACHE)) ||
|
6906 | 6892 | LoadAuthRedirectedChannel()) {
|
6907 | - return NS_OK;
|
|
6893 | + return;
|
|
6908 | 6894 | }
|
6909 | 6895 | |
6910 | 6896 | auto dnsStrategy = GetProxyDNSStrategy();
|
... | ... | @@ -6912,10 +6898,10 @@ nsresult nsHttpChannel::MaybeStartDNSPrefetch() { |
6912 | 6898 | LOG(
|
6913 | 6899 | ("nsHttpChannel::MaybeStartDNSPrefetch [this=%p, strategy=%u] "
|
6914 | 6900 | "prefetching%s\n",
|
6915 | - this, dnsStrategy,
|
|
6901 | + this, static_cast<uint32_t>(dnsStrategy),
|
|
6916 | 6902 | mCaps & NS_HTTP_REFRESH_DNS ? ", refresh requested" : ""));
|
6917 | 6903 | |
6918 | - if (dnsStrategy & DNS_PREFETCH_ORIGIN) {
|
|
6904 | + if (dnsStrategy == ProxyDNSStrategy::ORIGIN) {
|
|
6919 | 6905 | OriginAttributes originAttributes;
|
6920 | 6906 | StoragePrincipalHelper::GetOriginAttributesForNetworkState(
|
6921 | 6907 | this, originAttributes);
|
... | ... | @@ -6927,20 +6913,8 @@ nsresult nsHttpChannel::MaybeStartDNSPrefetch() { |
6927 | 6913 | if (mCaps & NS_HTTP_REFRESH_DNS) {
|
6928 | 6914 | dnsFlags |= nsIDNSService::RESOLVE_BYPASS_CACHE;
|
6929 | 6915 | }
|
6930 | - nsresult rv = mDNSPrefetch->PrefetchHigh(dnsFlags);
|
|
6931 | 6916 | |
6932 | - if (dnsStrategy & DNS_BLOCK_ON_ORIGIN_RESOLVE) {
|
|
6933 | - LOG((" blocking on prefetching origin"));
|
|
6934 | - |
|
6935 | - if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
6936 | - LOG((" lookup failed with 0x%08" PRIx32 ", aborting request",
|
|
6937 | - static_cast<uint32_t>(rv)));
|
|
6938 | - return rv;
|
|
6939 | - }
|
|
6940 | - |
|
6941 | - // Resolved in OnLookupComplete.
|
|
6942 | - mDNSBlockingThenable = mDNSBlockingPromise.Ensure(__func__);
|
|
6943 | - }
|
|
6917 | + Unused << mDNSPrefetch->PrefetchHigh(dnsFlags);
|
|
6944 | 6918 | |
6945 | 6919 | bool unused;
|
6946 | 6920 | if (StaticPrefs::network_dns_use_https_rr_as_altsvc() && !mHTTPSSVCRecord &&
|
... | ... | @@ -6960,8 +6934,6 @@ nsresult nsHttpChannel::MaybeStartDNSPrefetch() { |
6960 | 6934 | });
|
6961 | 6935 | }
|
6962 | 6936 | }
|
6963 | - |
|
6964 | - return NS_OK;
|
|
6965 | 6937 | }
|
6966 | 6938 | |
6967 | 6939 | NS_IMETHODIMP
|
... | ... | @@ -303,23 +303,11 @@ class nsHttpChannel final : public HttpBaseChannel, |
303 | 303 | // Connections will only be established in this function.
|
304 | 304 | // (including DNS prefetch and speculative connection.)
|
305 | 305 | void MaybeResolveProxyAndBeginConnect();
|
306 | - nsresult MaybeStartDNSPrefetch();
|
|
307 | - |
|
308 | - // Tells the channel to resolve the origin of the end server we are connecting
|
|
309 | - // to.
|
|
310 | - static uint16_t const DNS_PREFETCH_ORIGIN = 1 << 0;
|
|
311 | - // Tells the channel to resolve the host name of the proxy.
|
|
312 | - static uint16_t const DNS_PREFETCH_PROXY = 1 << 1;
|
|
313 | - // Will be set if the current channel uses an HTTP/HTTPS proxy.
|
|
314 | - static uint16_t const DNS_PROXY_IS_HTTP = 1 << 2;
|
|
315 | - // Tells the channel to wait for the result of the origin server resolution
|
|
316 | - // before any connection attempts are made.
|
|
317 | - static uint16_t const DNS_BLOCK_ON_ORIGIN_RESOLVE = 1 << 3;
|
|
306 | + void MaybeStartDNSPrefetch();
|
|
318 | 307 | |
319 | 308 | // Based on the proxy configuration determine the strategy for resolving the
|
320 | 309 | // end server host name.
|
321 | - // Returns a combination of the above flags.
|
|
322 | - uint16_t GetProxyDNSStrategy();
|
|
310 | + ProxyDNSStrategy GetProxyDNSStrategy();
|
|
323 | 311 | |
324 | 312 | // We might synchronously or asynchronously call BeginConnect,
|
325 | 313 | // which includes DNS prefetch and speculative connection, according to
|
... | ... | @@ -127,6 +127,13 @@ class nsHttpConnectionInfo final : public ARefBase { |
127 | 127 | const char* ProxyPassword() const {
|
128 | 128 | return mProxyInfo ? mProxyInfo->Password().get() : nullptr;
|
129 | 129 | }
|
130 | + uint32_t ProxyFlag() const {
|
|
131 | + uint32_t flags = 0;
|
|
132 | + if (mProxyInfo) {
|
|
133 | + mProxyInfo->GetFlags(&flags);
|
|
134 | + }
|
|
135 | + return flags;
|
|
136 | + }
|
|
130 | 137 | |
131 | 138 | const nsCString& ProxyAuthorizationHeader() const {
|
132 | 139 | return mProxyInfo ? mProxyInfo->ProxyAuthorizationHeader() : EmptyCString();
|
... | ... | @@ -3573,9 +3573,15 @@ void nsHttpConnectionMgr::DoSpeculativeConnectionInternal( |
3573 | 3573 | return;
|
3574 | 3574 | }
|
3575 | 3575 | |
3576 | - if (aFetchHTTPSRR && NS_SUCCEEDED(aTrans->FetchHTTPSRR())) {
|
|
3577 | - // nsHttpConnectionMgr::DoSpeculativeConnection will be called again when
|
|
3578 | - // HTTPS RR is available.
|
|
3576 | + ProxyDNSStrategy strategy = GetProxyDNSStrategyHelper(
|
|
3577 | + aEnt->mConnInfo->ProxyType(), aEnt->mConnInfo->ProxyFlag());
|
|
3578 | + // Speculative connections can be triggered by non-Necko consumers,
|
|
3579 | + // so add an extra check to ensure HTTPS RR isn't fetched when a proxy is
|
|
3580 | + // used.
|
|
3581 | + if (aFetchHTTPSRR && strategy == ProxyDNSStrategy::ORIGIN &&
|
|
3582 | + NS_SUCCEEDED(aTrans->FetchHTTPSRR())) {
|
|
3583 | + // nsHttpConnectionMgr::DoSpeculativeConnection will be called again
|
|
3584 | + // when HTTPS RR is available.
|
|
3579 | 3585 | return;
|
3580 | 3586 | }
|
3581 | 3587 |
... | ... | @@ -2388,7 +2388,9 @@ nsresult nsHttpHandler::SpeculativeConnectInternal( |
2388 | 2388 | }
|
2389 | 2389 | }
|
2390 | 2390 | |
2391 | - return SpeculativeConnect(ci, aCallbacks);
|
|
2391 | + // When ech is enabled, always do speculative connect with HTTPS RR.
|
|
2392 | + return MaybeSpeculativeConnectWithHTTPSRR(ci, aCallbacks, 0,
|
|
2393 | + EchConfigEnabled());
|
|
2392 | 2394 | }
|
2393 | 2395 | |
2394 | 2396 | NS_IMETHODIMP
|
... | ... | @@ -296,14 +296,13 @@ class nsHttpHandler final : public nsIHttpProtocolHandler, |
296 | 296 | return mConnMgr->GetSocketThreadTarget(target);
|
297 | 297 | }
|
298 | 298 | |
299 | - [[nodiscard]] nsresult SpeculativeConnect(nsHttpConnectionInfo* ci,
|
|
300 | - nsIInterfaceRequestor* callbacks,
|
|
301 | - uint32_t caps = 0,
|
|
302 | - bool aFetchHTTPSRR = false) {
|
|
299 | + [[nodiscard]] nsresult MaybeSpeculativeConnectWithHTTPSRR(
|
|
300 | + nsHttpConnectionInfo* ci, nsIInterfaceRequestor* callbacks, uint32_t caps,
|
|
301 | + bool aFetchHTTPSRR) {
|
|
303 | 302 | TickleWifi(callbacks);
|
304 | 303 | RefPtr<nsHttpConnectionInfo> clone = ci->Clone();
|
305 | 304 | return mConnMgr->SpeculativeConnect(clone, callbacks, caps, nullptr,
|
306 | - aFetchHTTPSRR | EchConfigEnabled());
|
|
305 | + aFetchHTTPSRR);
|
|
307 | 306 | }
|
308 | 307 | |
309 | 308 | [[nodiscard]] nsresult SpeculativeConnect(nsHttpConnectionInfo* ci,
|
1 | +/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2 | + * License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3 | + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
4 | + |
|
5 | +// Test when socks proxy is registered, we don't try to resolve HTTPS record.
|
|
6 | +// Steps:
|
|
7 | +// 1. Use addHTTPSRecordOverride to add an override for service.com.
|
|
8 | +// 2. Add a proxy filter to use socks proxy.
|
|
9 | +// 3. Create a request to load service.com.
|
|
10 | +// 4. See if the HTTPS record is in DNS cache entries.
|
|
11 | + |
|
12 | +"use strict";
|
|
13 | + |
|
14 | +const gDashboard = Cc["@mozilla.org/network/dashboard;1"].getService(
|
|
15 | + Ci.nsIDashboard
|
|
16 | +);
|
|
17 | +const pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
|
|
18 | + |
|
19 | +add_task(async function setup() {
|
|
20 | + Services.prefs.setBoolPref("network.dns.native_https_query", true);
|
|
21 | + Services.prefs.setBoolPref("network.dns.native_https_query_win10", true);
|
|
22 | + const override = Cc["@mozilla.org/network/native-dns-override;1"].getService(
|
|
23 | + Ci.nsINativeDNSResolverOverride
|
|
24 | + );
|
|
25 | + |
|
26 | + let rawBuffer = [
|
|
27 | + 0, 0, 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 7, 115, 101, 114, 118, 105, 99, 101,
|
|
28 | + 3, 99, 111, 109, 0, 0, 65, 0, 1, 0, 0, 0, 55, 0, 13, 0, 1, 0, 0, 1, 0, 6, 2,
|
|
29 | + 104, 50, 2, 104, 51,
|
|
30 | + ];
|
|
31 | + override.addHTTPSRecordOverride("service.com", rawBuffer, rawBuffer.length);
|
|
32 | + override.addIPOverride("service.com", "127.0.0.1");
|
|
33 | + registerCleanupFunction(() => {
|
|
34 | + Services.prefs.clearUserPref("network.dns.native_https_query");
|
|
35 | + Services.prefs.clearUserPref("network.dns.native_https_query_win10");
|
|
36 | + Services.prefs.clearUserPref("network.dns.localDomains");
|
|
37 | + override.clearOverrides();
|
|
38 | + });
|
|
39 | +});
|
|
40 | + |
|
41 | +function makeChan(uri) {
|
|
42 | + let chan = NetUtil.newChannel({
|
|
43 | + uri,
|
|
44 | + loadUsingSystemPrincipal: true,
|
|
45 | + contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
|
|
46 | + }).QueryInterface(Ci.nsIHttpChannel);
|
|
47 | + chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
|
|
48 | + return chan;
|
|
49 | +}
|
|
50 | + |
|
51 | +function channelOpenPromise(chan, flags) {
|
|
52 | + return new Promise(resolve => {
|
|
53 | + function finish(req, buffer) {
|
|
54 | + resolve([req, buffer]);
|
|
55 | + }
|
|
56 | + chan.asyncOpen(new ChannelListener(finish, null, flags));
|
|
57 | + });
|
|
58 | +}
|
|
59 | + |
|
60 | +async function isRecordFound(hostname) {
|
|
61 | + return new Promise(resolve => {
|
|
62 | + gDashboard.requestDNSInfo(function (data) {
|
|
63 | + let found = false;
|
|
64 | + for (let i = 0; i < data.entries.length; i++) {
|
|
65 | + if (
|
|
66 | + data.entries[i].hostname == hostname &&
|
|
67 | + data.entries[i].type == Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC
|
|
68 | + ) {
|
|
69 | + found = true;
|
|
70 | + break;
|
|
71 | + }
|
|
72 | + }
|
|
73 | + resolve(found);
|
|
74 | + });
|
|
75 | + });
|
|
76 | +}
|
|
77 | + |
|
78 | +async function do_test_with_proxy_filter(filter) {
|
|
79 | + pps.registerFilter(filter, 10);
|
|
80 | + |
|
81 | + let chan = makeChan(`https://service.com/`);
|
|
82 | + await channelOpenPromise(chan, CL_EXPECT_LATE_FAILURE | CL_ALLOW_UNKNOWN_CL);
|
|
83 | + |
|
84 | + let found = await isRecordFound("service.com");
|
|
85 | + pps.unregisterFilter(filter);
|
|
86 | + |
|
87 | + return found;
|
|
88 | +}
|
|
89 | + |
|
90 | +add_task(async function test_proxyDNS_do_leak() {
|
|
91 | + let filter = new NodeProxyFilter("socks", "localhost", 443, 0);
|
|
92 | + |
|
93 | + let res = await do_test_with_proxy_filter(filter);
|
|
94 | + |
|
95 | + Assert.ok(res, "Should find a DNS entry");
|
|
96 | +});
|
|
97 | + |
|
98 | +add_task(async function test_proxyDNS_dont_leak() {
|
|
99 | + Services.dns.clearCache(false);
|
|
100 | + |
|
101 | + let filter = new NodeProxyFilter(
|
|
102 | + "socks",
|
|
103 | + "localhost",
|
|
104 | + 443,
|
|
105 | + Ci.nsIProxyInfo.TRANSPARENT_PROXY_RESOLVES_HOST
|
|
106 | + );
|
|
107 | + |
|
108 | + let res = await do_test_with_proxy_filter(filter);
|
|
109 | + |
|
110 | + Assert.ok(!res, "Should not find a DNS entry");
|
|
111 | +}); |
... | ... | @@ -983,6 +983,12 @@ run-sequentially = "node server exceptions dont replay well" |
983 | 983 | |
984 | 984 | ["test_proxy_pac.js"]
|
985 | 985 | |
986 | +["test_proxyDNS_leak.js"]
|
|
987 | +skip-if = [
|
|
988 | + "os == 'android'",
|
|
989 | + "socketprocess_networking",
|
|
990 | +]
|
|
991 | + |
|
986 | 992 | ["test_proxyconnect.js"]
|
987 | 993 | skip-if = [
|
988 | 994 | "tsan",
|
... | ... | @@ -116,6 +116,11 @@ function displayDns(data) { |
116 | 116 | new_cont.setAttribute("id", "dns_content");
|
117 | 117 | |
118 | 118 | for (let i = 0; i < data.entries.length; i++) {
|
119 | + // TODO: Will be supported in bug 1889387.
|
|
120 | + if (data.entries[i].type != Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT) {
|
|
121 | + continue;
|
|
122 | + }
|
|
123 | + |
|
119 | 124 | let row = document.createElement("tr");
|
120 | 125 | row.appendChild(col(data.entries[i].hostname));
|
121 | 126 | row.appendChild(col(data.entries[i].family));
|