Pier Angelo Vendrame pushed to branch mullvad-browser-128.8.0esr-14.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
-
cd9cd4ed
by Kershaw Chang at 2025-02-27T16:08:04+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 |
| ... | ... | @@ -1986,20 +1986,13 @@ void nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries>* args) { |
| 1986 | 1986 | continue;
|
| 1987 | 1987 | }
|
| 1988 | 1988 | |
| 1989 | - // For now we only show A/AAAA records.
|
|
| 1990 | - if (!rec->IsAddrRecord()) {
|
|
| 1991 | - continue;
|
|
| 1992 | - }
|
|
| 1993 | - |
|
| 1994 | - RefPtr<AddrHostRecord> addrRec = do_QueryObject(rec);
|
|
| 1995 | - MOZ_ASSERT(addrRec);
|
|
| 1996 | - if (!addrRec || !addrRec->addr_info) {
|
|
| 1997 | - continue;
|
|
| 1998 | - }
|
|
| 1999 | - |
|
| 2000 | 1989 | DNSCacheEntries info;
|
| 1990 | + info.resolveType = rec->type;
|
|
| 2001 | 1991 | info.hostname = rec->host;
|
| 2002 | 1992 | info.family = rec->af;
|
| 1993 | + if (rec->mValidEnd.IsNull()) {
|
|
| 1994 | + continue;
|
|
| 1995 | + }
|
|
| 2003 | 1996 | info.expiration =
|
| 2004 | 1997 | (int64_t)(rec->mValidEnd - TimeStamp::NowLoRes()).ToSeconds();
|
| 2005 | 1998 | if (info.expiration <= 0) {
|
| ... | ... | @@ -2007,7 +2000,13 @@ void nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries>* args) { |
| 2007 | 2000 | continue;
|
| 2008 | 2001 | }
|
| 2009 | 2002 | |
| 2010 | - {
|
|
| 2003 | + info.originAttributesSuffix = recordEntry.GetKey().originSuffix;
|
|
| 2004 | + info.flags = nsPrintfCString("%u|0x%x|%u|%d|%s", rec->type,
|
|
| 2005 | + static_cast<uint32_t>(rec->flags), rec->af,
|
|
| 2006 | + rec->pb, rec->mTrrServer.get());
|
|
| 2007 | + |
|
| 2008 | + RefPtr<AddrHostRecord> addrRec = do_QueryObject(rec);
|
|
| 2009 | + if (addrRec && addrRec->addr_info) {
|
|
| 2011 | 2010 | MutexAutoLock lock(addrRec->addr_info_lock);
|
| 2012 | 2011 | for (const auto& addr : addrRec->addr_info->Addresses()) {
|
| 2013 | 2012 | char buf[kIPv6CStrBufSize];
|
| ... | ... | @@ -2018,11 +2017,6 @@ void nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries>* args) { |
| 2018 | 2017 | info.TRR = addrRec->addr_info->IsTRR();
|
| 2019 | 2018 | }
|
| 2020 | 2019 | |
| 2021 | - info.originAttributesSuffix = recordEntry.GetKey().originSuffix;
|
|
| 2022 | - info.flags = nsPrintfCString("%u|0x%x|%u|%d|%s", rec->type,
|
|
| 2023 | - static_cast<uint32_t>(rec->flags), rec->af,
|
|
| 2024 | - rec->pb, rec->mTrrServer.get());
|
|
| 2025 | - |
|
| 2026 | 2020 | args->AppendElement(std::move(info));
|
| 2027 | 2021 | }
|
| 2028 | 2022 | }
|
| ... | ... | @@ -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 |
| ... | ... | @@ -759,6 +759,10 @@ nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade, |
| 759 | 759 | }
|
| 760 | 760 | |
| 761 | 761 | auto shouldSkipUpgradeWithHTTPSRR = [&]() -> bool {
|
| 762 | + if (mCaps & NS_HTTP_DISALLOW_HTTPS_RR) {
|
|
| 763 | + return true;
|
|
| 764 | + }
|
|
| 765 | + |
|
| 762 | 766 | // Skip using HTTPS RR to upgrade when this is not a top-level load and the
|
| 763 | 767 | // loading principal is http.
|
| 764 | 768 | if ((mLoadInfo->GetExternalContentPolicyType() !=
|
| ... | ... | @@ -781,6 +785,11 @@ nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade, |
| 781 | 785 | return true;
|
| 782 | 786 | }
|
| 783 | 787 | |
| 788 | + auto dnsStrategy = GetProxyDNSStrategy();
|
|
| 789 | + if (dnsStrategy != ProxyDNSStrategy::ORIGIN) {
|
|
| 790 | + return true;
|
|
| 791 | + }
|
|
| 792 | + |
|
| 784 | 793 | nsAutoCString uriHost;
|
| 785 | 794 | mURI->GetAsciiHost(uriHost);
|
| 786 | 795 | |
| ... | ... | @@ -805,11 +814,6 @@ nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade, |
| 805 | 814 | return ContinueOnBeforeConnect(hasHTTPSRR, aStatus, hasHTTPSRR);
|
| 806 | 815 | }
|
| 807 | 816 | |
| 808 | - auto dnsStrategy = GetProxyDNSStrategy();
|
|
| 809 | - if (!(dnsStrategy & DNS_PREFETCH_ORIGIN)) {
|
|
| 810 | - return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
|
|
| 811 | - }
|
|
| 812 | - |
|
| 813 | 817 | LOG(("nsHttpChannel::MaybeUseHTTPSRRForUpgrade [%p] wait for HTTPS RR",
|
| 814 | 818 | this));
|
| 815 | 819 | |
| ... | ... | @@ -1215,13 +1219,13 @@ void nsHttpChannel::SpeculativeConnect() { |
| 1215 | 1219 | NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
|
| 1216 | 1220 | getter_AddRefs(callbacks));
|
| 1217 | 1221 | if (!callbacks) return;
|
| 1218 | - |
|
| 1219 | - Unused << gHttpHandler->SpeculativeConnect(
|
|
| 1222 | + bool httpsRRAllowed = !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR);
|
|
| 1223 | + Unused << gHttpHandler->MaybeSpeculativeConnectWithHTTPSRR(
|
|
| 1220 | 1224 | mConnectionInfo, callbacks,
|
| 1221 | 1225 | mCaps & (NS_HTTP_DISALLOW_SPDY | NS_HTTP_TRR_MODE_MASK |
|
| 1222 | 1226 | NS_HTTP_DISABLE_IPV4 | NS_HTTP_DISABLE_IPV6 |
|
| 1223 | 1227 | NS_HTTP_DISALLOW_HTTP3 | NS_HTTP_REFRESH_DNS),
|
| 1224 | - gHttpHandler->EchConfigEnabled());
|
|
| 1228 | + gHttpHandler->EchConfigEnabled() && httpsRRAllowed);
|
|
| 1225 | 1229 | }
|
| 1226 | 1230 | |
| 1227 | 1231 | void nsHttpChannel::DoNotifyListenerCleanup() {
|
| ... | ... | @@ -6537,27 +6541,16 @@ nsHttpChannel::GetOrCreateChannelClassifier() { |
| 6537 | 6541 | return classifier.forget();
|
| 6538 | 6542 | }
|
| 6539 | 6543 | |
| 6540 | -uint16_t nsHttpChannel::GetProxyDNSStrategy() {
|
|
| 6541 | - // This function currently only supports returning DNS_PREFETCH_ORIGIN.
|
|
| 6542 | - // Support for the rest of the DNS_* flags will be added later.
|
|
| 6543 | - |
|
| 6544 | - if (!mProxyInfo) {
|
|
| 6545 | - return DNS_PREFETCH_ORIGIN;
|
|
| 6544 | +ProxyDNSStrategy nsHttpChannel::GetProxyDNSStrategy() {
|
|
| 6545 | + // When network_dns_force_use_https_rr is true, return DNS_PREFETCH_ORIGIN.
|
|
| 6546 | + // This ensures that we always perform HTTPS RR query.
|
|
| 6547 | + nsCOMPtr<nsProxyInfo> proxyInfo(static_cast<nsProxyInfo*>(mProxyInfo.get()));
|
|
| 6548 | + if (!proxyInfo || StaticPrefs::network_dns_force_use_https_rr()) {
|
|
| 6549 | + return ProxyDNSStrategy::ORIGIN;
|
|
| 6546 | 6550 | }
|
| 6547 | 6551 | |
| 6548 | - uint32_t flags = 0;
|
|
| 6549 | - nsAutoCString type;
|
|
| 6550 | - mProxyInfo->GetFlags(&flags);
|
|
| 6551 | - mProxyInfo->GetType(type);
|
|
| 6552 | - |
|
| 6553 | 6552 | // If the proxy is not to perform name resolution itself.
|
| 6554 | - if (!(flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST)) {
|
|
| 6555 | - if (type.EqualsLiteral("socks")) {
|
|
| 6556 | - return DNS_PREFETCH_ORIGIN;
|
|
| 6557 | - }
|
|
| 6558 | - }
|
|
| 6559 | - |
|
| 6560 | - return 0;
|
|
| 6553 | + return GetProxyDNSStrategyHelper(proxyInfo->Type(), proxyInfo->Flags());
|
|
| 6561 | 6554 | }
|
| 6562 | 6555 | |
| 6563 | 6556 | // BeginConnect() SHOULD NOT call AsyncAbort(). AsyncAbort will be called by
|
| ... | ... | @@ -6743,11 +6736,13 @@ nsresult nsHttpChannel::BeginConnect() { |
| 6743 | 6736 | }
|
| 6744 | 6737 | |
| 6745 | 6738 | bool trrEnabled = false;
|
| 6739 | + auto dnsStrategy = GetProxyDNSStrategy();
|
|
| 6746 | 6740 | bool httpsRRAllowed =
|
| 6747 | 6741 | !LoadBeConservative() && !(mCaps & NS_HTTP_BE_CONSERVATIVE) &&
|
| 6748 | 6742 | !(mLoadInfo->TriggeringPrincipal()->IsSystemPrincipal() &&
|
| 6749 | 6743 | mLoadInfo->GetExternalContentPolicyType() !=
|
| 6750 | 6744 | ExtContentPolicy::TYPE_DOCUMENT) &&
|
| 6745 | + dnsStrategy == ProxyDNSStrategy::ORIGIN &&
|
|
| 6751 | 6746 | !mConnectionInfo->UsingConnect() && canUseHTTPSRRonNetwork(trrEnabled) &&
|
| 6752 | 6747 | StaticPrefs::network_dns_use_https_rr_as_altsvc();
|
| 6753 | 6748 | if (!httpsRRAllowed) {
|
| ... | ... | @@ -6858,16 +6853,7 @@ nsresult nsHttpChannel::BeginConnect() { |
| 6858 | 6853 | ReEvaluateReferrerAfterTrackingStatusIsKnown();
|
| 6859 | 6854 | }
|
| 6860 | 6855 | |
| 6861 | - rv = MaybeStartDNSPrefetch();
|
|
| 6862 | - if (NS_FAILED(rv)) {
|
|
| 6863 | - auto dnsStrategy = GetProxyDNSStrategy();
|
|
| 6864 | - if (dnsStrategy & DNS_BLOCK_ON_ORIGIN_RESOLVE) {
|
|
| 6865 | - // TODO: Should this be fatal?
|
|
| 6866 | - return rv;
|
|
| 6867 | - }
|
|
| 6868 | - // Otherwise this shouldn't be fatal.
|
|
| 6869 | - return NS_OK;
|
|
| 6870 | - }
|
|
| 6856 | + MaybeStartDNSPrefetch();
|
|
| 6871 | 6857 | |
| 6872 | 6858 | rv = CallOrWaitForResume(
|
| 6873 | 6859 | [](nsHttpChannel* self) { return self->PrepareToConnect(); });
|
| ... | ... | @@ -6887,7 +6873,7 @@ nsresult nsHttpChannel::BeginConnect() { |
| 6887 | 6873 | return NS_OK;
|
| 6888 | 6874 | }
|
| 6889 | 6875 | |
| 6890 | -nsresult nsHttpChannel::MaybeStartDNSPrefetch() {
|
|
| 6876 | +void nsHttpChannel::MaybeStartDNSPrefetch() {
|
|
| 6891 | 6877 | // Start a DNS lookup very early in case the real open is queued the DNS can
|
| 6892 | 6878 | // happen in parallel. Do not do so in the presence of an HTTP proxy as
|
| 6893 | 6879 | // all lookups other than for the proxy itself are done by the proxy.
|
| ... | ... | @@ -6903,7 +6889,7 @@ nsresult nsHttpChannel::MaybeStartDNSPrefetch() { |
| 6903 | 6889 | // timing we used.
|
| 6904 | 6890 | if ((mLoadFlags & (LOAD_NO_NETWORK_IO | LOAD_ONLY_FROM_CACHE)) ||
|
| 6905 | 6891 | LoadAuthRedirectedChannel()) {
|
| 6906 | - return NS_OK;
|
|
| 6892 | + return;
|
|
| 6907 | 6893 | }
|
| 6908 | 6894 | |
| 6909 | 6895 | auto dnsStrategy = GetProxyDNSStrategy();
|
| ... | ... | @@ -6911,10 +6897,10 @@ nsresult nsHttpChannel::MaybeStartDNSPrefetch() { |
| 6911 | 6897 | LOG(
|
| 6912 | 6898 | ("nsHttpChannel::MaybeStartDNSPrefetch [this=%p, strategy=%u] "
|
| 6913 | 6899 | "prefetching%s\n",
|
| 6914 | - this, dnsStrategy,
|
|
| 6900 | + this, static_cast<uint32_t>(dnsStrategy),
|
|
| 6915 | 6901 | mCaps & NS_HTTP_REFRESH_DNS ? ", refresh requested" : ""));
|
| 6916 | 6902 | |
| 6917 | - if (dnsStrategy & DNS_PREFETCH_ORIGIN) {
|
|
| 6903 | + if (dnsStrategy == ProxyDNSStrategy::ORIGIN) {
|
|
| 6918 | 6904 | OriginAttributes originAttributes;
|
| 6919 | 6905 | StoragePrincipalHelper::GetOriginAttributesForNetworkState(
|
| 6920 | 6906 | this, originAttributes);
|
| ... | ... | @@ -6926,20 +6912,8 @@ nsresult nsHttpChannel::MaybeStartDNSPrefetch() { |
| 6926 | 6912 | if (mCaps & NS_HTTP_REFRESH_DNS) {
|
| 6927 | 6913 | dnsFlags |= nsIDNSService::RESOLVE_BYPASS_CACHE;
|
| 6928 | 6914 | }
|
| 6929 | - nsresult rv = mDNSPrefetch->PrefetchHigh(dnsFlags);
|
|
| 6930 | 6915 | |
| 6931 | - if (dnsStrategy & DNS_BLOCK_ON_ORIGIN_RESOLVE) {
|
|
| 6932 | - LOG((" blocking on prefetching origin"));
|
|
| 6933 | - |
|
| 6934 | - if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
| 6935 | - LOG((" lookup failed with 0x%08" PRIx32 ", aborting request",
|
|
| 6936 | - static_cast<uint32_t>(rv)));
|
|
| 6937 | - return rv;
|
|
| 6938 | - }
|
|
| 6939 | - |
|
| 6940 | - // Resolved in OnLookupComplete.
|
|
| 6941 | - mDNSBlockingThenable = mDNSBlockingPromise.Ensure(__func__);
|
|
| 6942 | - }
|
|
| 6916 | + Unused << mDNSPrefetch->PrefetchHigh(dnsFlags);
|
|
| 6943 | 6917 | |
| 6944 | 6918 | bool unused;
|
| 6945 | 6919 | if (StaticPrefs::network_dns_use_https_rr_as_altsvc() && !mHTTPSSVCRecord &&
|
| ... | ... | @@ -6959,8 +6933,6 @@ nsresult nsHttpChannel::MaybeStartDNSPrefetch() { |
| 6959 | 6933 | });
|
| 6960 | 6934 | }
|
| 6961 | 6935 | }
|
| 6962 | - |
|
| 6963 | - return NS_OK;
|
|
| 6964 | 6936 | }
|
| 6965 | 6937 | |
| 6966 | 6938 | 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 |
| ... | ... | @@ -2392,7 +2392,9 @@ nsresult nsHttpHandler::SpeculativeConnectInternal( |
| 2392 | 2392 | }
|
| 2393 | 2393 | }
|
| 2394 | 2394 | |
| 2395 | - return SpeculativeConnect(ci, aCallbacks);
|
|
| 2395 | + // When ech is enabled, always do speculative connect with HTTPS RR.
|
|
| 2396 | + return MaybeSpeculativeConnectWithHTTPSRR(ci, aCallbacks, 0,
|
|
| 2397 | + EchConfigEnabled());
|
|
| 2396 | 2398 | }
|
| 2397 | 2399 | |
| 2398 | 2400 | 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));
|