1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 // HttpLog.h should generally be included first
8 #include "HttpLog.h"
9 
10 // Log on level :5, instead of default :4.
11 #undef LOG
12 #define LOG(args) LOG5(args)
13 #undef LOG_ENABLED
14 #define LOG_ENABLED() LOG5_ENABLED()
15 
16 #include "nsHttpConnectionInfo.h"
17 
18 #include "mozilla/net/DNS.h"
19 #include "mozilla/net/NeckoChannelParams.h"
20 #include "nsComponentManagerUtils.h"
21 #include "nsICryptoHash.h"
22 #include "nsIDNSByTypeRecord.h"
23 #include "nsIProtocolProxyService.h"
24 #include "nsHttpHandler.h"
25 #include "nsNetCID.h"
26 #include "nsProxyInfo.h"
27 #include "prnetdb.h"
28 
SHA256(const char * aPlainText,nsAutoCString & aResult)29 static nsresult SHA256(const char* aPlainText, nsAutoCString& aResult) {
30   nsresult rv;
31   nsCOMPtr<nsICryptoHash> hasher =
32       do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
33   if (NS_FAILED(rv)) {
34     LOG(("nsHttpDigestAuth: no crypto hash!\n"));
35     return rv;
36   }
37   rv = hasher->Init(nsICryptoHash::SHA256);
38   NS_ENSURE_SUCCESS(rv, rv);
39   rv = hasher->Update((unsigned char*)aPlainText, strlen(aPlainText));
40   NS_ENSURE_SUCCESS(rv, rv);
41   return hasher->Finish(false, aResult);
42 }
43 
44 namespace mozilla {
45 namespace net {
46 
nsHttpConnectionInfo(const nsACString & originHost,int32_t originPort,const nsACString & npnToken,const nsACString & username,nsProxyInfo * proxyInfo,const OriginAttributes & originAttributes,bool endToEndSSL,bool aIsHttp3)47 nsHttpConnectionInfo::nsHttpConnectionInfo(
48     const nsACString& originHost, int32_t originPort,
49     const nsACString& npnToken, const nsACString& username,
50     nsProxyInfo* proxyInfo, const OriginAttributes& originAttributes,
51     bool endToEndSSL, bool aIsHttp3)
52     : mRoutedPort(443), mLessThanTls13(false) {
53   Init(originHost, originPort, npnToken, username, proxyInfo, originAttributes,
54        endToEndSSL, aIsHttp3);
55 }
56 
nsHttpConnectionInfo(const nsACString & originHost,int32_t originPort,const nsACString & npnToken,const nsACString & username,nsProxyInfo * proxyInfo,const OriginAttributes & originAttributes,const nsACString & routedHost,int32_t routedPort,bool aIsHttp3)57 nsHttpConnectionInfo::nsHttpConnectionInfo(
58     const nsACString& originHost, int32_t originPort,
59     const nsACString& npnToken, const nsACString& username,
60     nsProxyInfo* proxyInfo, const OriginAttributes& originAttributes,
61     const nsACString& routedHost, int32_t routedPort, bool aIsHttp3)
62     : mLessThanTls13(false) {
63   mEndToEndSSL = true;  // so DefaultPort() works
64   mRoutedPort = routedPort == -1 ? DefaultPort() : routedPort;
65 
66   if (!originHost.Equals(routedHost) || (originPort != routedPort) ||
67       aIsHttp3) {
68     mRoutedHost = routedHost;
69   }
70   Init(originHost, originPort, npnToken, username, proxyInfo, originAttributes,
71        true, aIsHttp3);
72 }
73 
Init(const nsACString & host,int32_t port,const nsACString & npnToken,const nsACString & username,nsProxyInfo * proxyInfo,const OriginAttributes & originAttributes,bool e2eSSL,bool aIsHttp3)74 void nsHttpConnectionInfo::Init(const nsACString& host, int32_t port,
75                                 const nsACString& npnToken,
76                                 const nsACString& username,
77                                 nsProxyInfo* proxyInfo,
78                                 const OriginAttributes& originAttributes,
79                                 bool e2eSSL, bool aIsHttp3) {
80   LOG(("Init nsHttpConnectionInfo @%p\n", this));
81 
82   mUsername = username;
83   mProxyInfo = proxyInfo;
84   mEndToEndSSL = e2eSSL;
85   mUsingConnect = false;
86   mNPNToken = npnToken;
87   mIsHttp3 = aIsHttp3;
88   mOriginAttributes = originAttributes;
89   mTlsFlags = 0x0;
90   mIsTrrServiceChannel = false;
91   mTRRMode = nsIRequest::TRR_DEFAULT_MODE;
92   mIPv4Disabled = false;
93   mIPv6Disabled = false;
94   mHasIPHintAddress = false;
95 
96   mUsingHttpsProxy = (proxyInfo && proxyInfo->IsHTTPS());
97   mUsingHttpProxy = mUsingHttpsProxy || (proxyInfo && proxyInfo->IsHTTP());
98 
99   if (mUsingHttpProxy) {
100     mUsingConnect = mEndToEndSSL;  // SSL always uses CONNECT
101     uint32_t resolveFlags = 0;
102     if (NS_SUCCEEDED(mProxyInfo->GetResolveFlags(&resolveFlags)) &&
103         resolveFlags & nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL) {
104       mUsingConnect = true;
105     }
106   }
107 
108   SetOriginServer(host, port);
109 }
110 
BuildHashKey()111 void nsHttpConnectionInfo::BuildHashKey() {
112   //
113   // build hash key:
114   //
115   // the hash key uniquely identifies the connection type.  two connections
116   // are "equal" if they end up talking the same protocol to the same server
117   // and are both used for anonymous or non-anonymous connection only;
118   // anonymity of the connection is setup later from nsHttpChannel::AsyncOpen
119   // where we know we use anonymous connection (LOAD_ANONYMOUS load flag)
120   //
121 
122   const char* keyHost;
123   int32_t keyPort;
124 
125   if (mUsingHttpProxy && !mUsingConnect) {
126     keyHost = ProxyHost();
127     keyPort = ProxyPort();
128   } else {
129     keyHost = Origin();
130     keyPort = OriginPort();
131   }
132 
133   // The hashkey has 9 fields followed by host connection info
134   // byte 0 is P/T/. {P,T} for Plaintext/TLS Proxy over HTTP
135   // byte 1 is S/. S is for end to end ssl such as https:// uris
136   // byte 2 is A/. A is for an anonymous channel (no cookies, etc..)
137   // byte 3 is P/. P is for a private browising channel
138   // byte 4 is I/. I is for insecure scheme on TLS for http:// uris
139   // byte 5 is X/. X is for disallow_spdy flag
140   // byte 6 is C/. C is for be Conservative
141   // byte 7 is B/. B is for allowing client certs on an anonymous channel
142   // byte 8 is F/. F is for indicating a fallback connection
143   // Note: when adding/removing fields from this list which do not have
144   // corresponding data fields on the object itself, you may also need to
145   // modify RebuildHashKey.
146 
147   const auto keyTemplate =
148       std::string(UnderlyingIndex(HashKeyIndex::End), '.') +
149       std::string("[tlsflags0x00000000]");
150   mHashKey.Assign(keyTemplate.c_str());
151 
152   mHashKey.Append(keyHost);
153   mHashKey.Append(':');
154   mHashKey.AppendInt(keyPort);
155   if (!mUsername.IsEmpty()) {
156     mHashKey.Append('[');
157     mHashKey.Append(mUsername);
158     mHashKey.Append(']');
159   }
160 
161   if (mUsingHttpsProxy) {
162     SetHashCharAt('T', HashKeyIndex::Proxy);
163   } else if (mUsingHttpProxy) {
164     SetHashCharAt('P', HashKeyIndex::Proxy);
165   }
166   if (mEndToEndSSL) {
167     SetHashCharAt('S', HashKeyIndex::EndToEndSSL);
168   }
169 
170   // NOTE: for transparent proxies (e.g., SOCKS) we need to encode the proxy
171   // info in the hash key (this ensures that we will continue to speak the
172   // right protocol even if our proxy preferences change).
173   //
174   // NOTE: for SSL tunnels add the proxy information to the cache key.
175   // We cannot use the proxy as the host parameter (as we do for non SSL)
176   // because this is a single host tunnel, but we need to include the proxy
177   // information so that a change in proxy config will mean this connection
178   // is not reused
179 
180   // NOTE: Adding the username and the password provides a means to isolate
181   // keep-alive to the URL bar domain as well: If the username is the URL bar
182   // domain, keep-alive connections are not reused by resources bound to
183   // different URL bar domains as the respective hash keys are not matching.
184 
185   if ((!mUsingHttpProxy && ProxyHost()) || (mUsingHttpProxy && mUsingConnect)) {
186     mHashKey.AppendLiteral(" (");
187     mHashKey.Append(ProxyType());
188     mHashKey.Append(':');
189     mHashKey.Append(ProxyHost());
190     mHashKey.Append(':');
191     mHashKey.AppendInt(ProxyPort());
192     mHashKey.Append(')');
193     mHashKey.Append('[');
194     mHashKey.Append(ProxyUsername());
195     mHashKey.Append(':');
196     const char* password = ProxyPassword();
197     if (strlen(password) > 0) {
198       nsAutoCString digestedPassword;
199       nsresult rv = SHA256(password, digestedPassword);
200       if (rv == NS_OK) {
201         mHashKey.Append(digestedPassword);
202       }
203     }
204     mHashKey.Append(']');
205   }
206 
207   if (!mRoutedHost.IsEmpty()) {
208     mHashKey.AppendLiteral(" <ROUTE-via ");
209     mHashKey.Append(mRoutedHost);
210     mHashKey.Append(':');
211     mHashKey.AppendInt(mRoutedPort);
212     mHashKey.Append('>');
213   }
214 
215   if (!mNPNToken.IsEmpty()) {
216     mHashKey.AppendLiteral(" {NPN-TOKEN ");
217     mHashKey.Append(mNPNToken);
218     mHashKey.AppendLiteral("}");
219   }
220 
221   if (GetTRRMode() != nsIRequest::TRR_DEFAULT_MODE) {
222     // When connecting with another TRR mode, we enforce a separate connection
223     // hashkey so that we also can trigger a fresh DNS resolver that then
224     // doesn't use TRR as the previous connection might have.
225     mHashKey.AppendLiteral("[TRR:");
226     mHashKey.AppendInt(GetTRRMode());
227     mHashKey.AppendLiteral("]");
228   }
229 
230   if (GetIPv4Disabled()) {
231     mHashKey.AppendLiteral("[!v4]");
232   }
233 
234   if (GetIPv6Disabled()) {
235     mHashKey.AppendLiteral("[!v6]");
236   }
237 
238   if (mProxyInfo) {
239     const nsCString& connectionIsolationKey =
240         mProxyInfo->ConnectionIsolationKey();
241     if (!connectionIsolationKey.IsEmpty()) {
242       mHashKey.AppendLiteral("{CIK ");
243       mHashKey.Append(connectionIsolationKey);
244       mHashKey.AppendLiteral("}");
245     }
246     if (mProxyInfo->Flags() & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
247       mHashKey.AppendLiteral("{TPRH}");
248     }
249   }
250 
251   nsAutoCString originAttributes;
252   mOriginAttributes.CreateSuffix(originAttributes);
253   mHashKey.Append(originAttributes);
254 }
255 
RebuildHashKey()256 void nsHttpConnectionInfo::RebuildHashKey() {
257   // Create copies of all properties stored in our hash key.
258   bool isAnonymous = GetAnonymous();
259   bool isPrivate = GetPrivate();
260   bool isInsecureScheme = GetInsecureScheme();
261   bool isNoSpdy = GetNoSpdy();
262   bool isBeConservative = GetBeConservative();
263   bool isAnonymousAllowClientCert = GetAnonymousAllowClientCert();
264   bool isFallback = GetFallbackConnection();
265 
266   BuildHashKey();
267 
268   // Restore all of those properties.
269   SetAnonymous(isAnonymous);
270   SetPrivate(isPrivate);
271   SetInsecureScheme(isInsecureScheme);
272   SetNoSpdy(isNoSpdy);
273   SetBeConservative(isBeConservative);
274   SetAnonymousAllowClientCert(isAnonymousAllowClientCert);
275   SetFallbackConnection(isFallback);
276 }
277 
SetOriginServer(const nsACString & host,int32_t port)278 void nsHttpConnectionInfo::SetOriginServer(const nsACString& host,
279                                            int32_t port) {
280   mOrigin = host;
281   mOriginPort = port == -1 ? DefaultPort() : port;
282   // Use BuildHashKey() since this can only be called when constructing an
283   // nsHttpConnectionInfo object.
284   MOZ_DIAGNOSTIC_ASSERT(mHashKey.IsEmpty());
285   BuildHashKey();
286 }
287 
288 // Note that this function needs to be synced with
289 // nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs to make sure
290 // nsHttpConnectionInfo can be serialized/deserialized.
Clone() const291 already_AddRefed<nsHttpConnectionInfo> nsHttpConnectionInfo::Clone() const {
292   RefPtr<nsHttpConnectionInfo> clone;
293   if (mRoutedHost.IsEmpty()) {
294     clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername,
295                                      mProxyInfo, mOriginAttributes,
296                                      mEndToEndSSL, mIsHttp3);
297   } else {
298     MOZ_ASSERT(mEndToEndSSL);
299     clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername,
300                                      mProxyInfo, mOriginAttributes, mRoutedHost,
301                                      mRoutedPort, mIsHttp3);
302   }
303 
304   // Make sure the anonymous, insecure-scheme, and private flags are transferred
305   clone->SetAnonymous(GetAnonymous());
306   clone->SetPrivate(GetPrivate());
307   clone->SetInsecureScheme(GetInsecureScheme());
308   clone->SetNoSpdy(GetNoSpdy());
309   clone->SetBeConservative(GetBeConservative());
310   clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
311   clone->SetFallbackConnection(GetFallbackConnection());
312   clone->SetTlsFlags(GetTlsFlags());
313   clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
314   clone->SetTRRMode(GetTRRMode());
315   clone->SetIPv4Disabled(GetIPv4Disabled());
316   clone->SetIPv6Disabled(GetIPv6Disabled());
317   clone->SetHasIPHintAddress(HasIPHintAddress());
318   clone->SetEchConfig(GetEchConfig());
319   MOZ_ASSERT(clone->Equals(this));
320 
321   return clone.forget();
322 }
323 
324 already_AddRefed<nsHttpConnectionInfo>
CloneAndAdoptHTTPSSVCRecord(nsISVCBRecord * aRecord) const325 nsHttpConnectionInfo::CloneAndAdoptHTTPSSVCRecord(
326     nsISVCBRecord* aRecord) const {
327   MOZ_ASSERT(aRecord);
328 
329   // Get the domain name of this HTTPS RR. This name will be assigned to
330   // mRoutedHost in the new connection info.
331   nsAutoCString name;
332   aRecord->GetName(name);
333 
334   // Try to get the port and Alpn. If this record has SvcParamKeyPort defined,
335   // the new port will be used as mRoutedPort.
336   Maybe<uint16_t> port = aRecord->GetPort();
337   Maybe<Tuple<nsCString, SupportedAlpnRank>> alpn = aRecord->GetAlpn();
338 
339   // Let the new conn info learn h3 will be used.
340   bool isHttp3 = alpn ? mozilla::net::IsHttp3(Get<1>(*alpn)) : false;
341 
342   LOG(("HTTPSSVC: use new routed host (%s) and new npnToken (%s)", name.get(),
343        alpn ? Get<0>(*alpn).get() : "None"));
344 
345   RefPtr<nsHttpConnectionInfo> clone;
346   if (name.IsEmpty()) {
347     clone = new nsHttpConnectionInfo(
348         mOrigin, mOriginPort, alpn ? Get<0>(*alpn) : EmptyCString(), mUsername,
349         mProxyInfo, mOriginAttributes, mEndToEndSSL, isHttp3);
350   } else {
351     MOZ_ASSERT(mEndToEndSSL);
352     clone = new nsHttpConnectionInfo(mOrigin, mOriginPort,
353                                      alpn ? Get<0>(*alpn) : EmptyCString(),
354                                      mUsername, mProxyInfo, mOriginAttributes,
355                                      name, port ? *port : mOriginPort, isHttp3);
356   }
357 
358   // Make sure the anonymous, insecure-scheme, and private flags are transferred
359   clone->SetAnonymous(GetAnonymous());
360   clone->SetPrivate(GetPrivate());
361   clone->SetInsecureScheme(GetInsecureScheme());
362   clone->SetNoSpdy(GetNoSpdy());
363   clone->SetBeConservative(GetBeConservative());
364   clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
365   clone->SetFallbackConnection(GetFallbackConnection());
366   clone->SetTlsFlags(GetTlsFlags());
367   clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
368   clone->SetTRRMode(GetTRRMode());
369   clone->SetIPv4Disabled(GetIPv4Disabled());
370   clone->SetIPv6Disabled(GetIPv6Disabled());
371 
372   bool hasIPHint = false;
373   Unused << aRecord->GetHasIPHintAddress(&hasIPHint);
374   if (hasIPHint) {
375     clone->SetHasIPHintAddress(hasIPHint);
376   }
377 
378   nsAutoCString echConfig;
379   Unused << aRecord->GetEchConfig(echConfig);
380   clone->SetEchConfig(echConfig);
381 
382   return clone.forget();
383 }
384 
385 /* static */
SerializeHttpConnectionInfo(nsHttpConnectionInfo * aInfo,HttpConnectionInfoCloneArgs & aArgs)386 void nsHttpConnectionInfo::SerializeHttpConnectionInfo(
387     nsHttpConnectionInfo* aInfo, HttpConnectionInfoCloneArgs& aArgs) {
388   aArgs.host() = aInfo->GetOrigin();
389   aArgs.port() = aInfo->OriginPort();
390   aArgs.npnToken() = aInfo->GetNPNToken();
391   aArgs.username() = aInfo->GetUsername();
392   aArgs.originAttributes() = aInfo->GetOriginAttributes();
393   aArgs.endToEndSSL() = aInfo->EndToEndSSL();
394   aArgs.routedHost() = aInfo->GetRoutedHost();
395   aArgs.routedPort() = aInfo->RoutedPort();
396   aArgs.anonymous() = aInfo->GetAnonymous();
397   aArgs.aPrivate() = aInfo->GetPrivate();
398   aArgs.insecureScheme() = aInfo->GetInsecureScheme();
399   aArgs.noSpdy() = aInfo->GetNoSpdy();
400   aArgs.beConservative() = aInfo->GetBeConservative();
401   aArgs.anonymousAllowClientCert() = aInfo->GetAnonymousAllowClientCert();
402   aArgs.tlsFlags() = aInfo->GetTlsFlags();
403   aArgs.isTrrServiceChannel() = aInfo->GetTRRMode();
404   aArgs.trrMode() = aInfo->GetTRRMode();
405   aArgs.isIPv4Disabled() = aInfo->GetIPv4Disabled();
406   aArgs.isIPv6Disabled() = aInfo->GetIPv6Disabled();
407   aArgs.isHttp3() = aInfo->IsHttp3();
408   aArgs.hasIPHintAddress() = aInfo->HasIPHintAddress();
409   aArgs.echConfig() = aInfo->GetEchConfig();
410 
411   if (!aInfo->ProxyInfo()) {
412     return;
413   }
414 
415   nsTArray<ProxyInfoCloneArgs> proxyInfoArray;
416   nsProxyInfo::SerializeProxyInfo(aInfo->ProxyInfo(), proxyInfoArray);
417   aArgs.proxyInfo() = std::move(proxyInfoArray);
418 }
419 
420 // This function needs to be synced with nsHttpConnectionInfo::Clone.
421 /* static */
422 already_AddRefed<nsHttpConnectionInfo>
DeserializeHttpConnectionInfoCloneArgs(const HttpConnectionInfoCloneArgs & aInfoArgs)423 nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs(
424     const HttpConnectionInfoCloneArgs& aInfoArgs) {
425   nsProxyInfo* pi = nsProxyInfo::DeserializeProxyInfo(aInfoArgs.proxyInfo());
426   RefPtr<nsHttpConnectionInfo> cinfo;
427   if (aInfoArgs.routedHost().IsEmpty()) {
428     cinfo = new nsHttpConnectionInfo(
429         aInfoArgs.host(), aInfoArgs.port(), aInfoArgs.npnToken(),
430         aInfoArgs.username(), pi, aInfoArgs.originAttributes(),
431         aInfoArgs.endToEndSSL(), aInfoArgs.isHttp3());
432   } else {
433     MOZ_ASSERT(aInfoArgs.endToEndSSL());
434     cinfo = new nsHttpConnectionInfo(
435         aInfoArgs.host(), aInfoArgs.port(), aInfoArgs.npnToken(),
436         aInfoArgs.username(), pi, aInfoArgs.originAttributes(),
437         aInfoArgs.routedHost(), aInfoArgs.routedPort(), aInfoArgs.isHttp3());
438   }
439 
440   // Make sure the anonymous, insecure-scheme, and private flags are transferred
441   cinfo->SetAnonymous(aInfoArgs.anonymous());
442   cinfo->SetPrivate(aInfoArgs.aPrivate());
443   cinfo->SetInsecureScheme(aInfoArgs.insecureScheme());
444   cinfo->SetNoSpdy(aInfoArgs.noSpdy());
445   cinfo->SetBeConservative(aInfoArgs.beConservative());
446   cinfo->SetAnonymousAllowClientCert(aInfoArgs.anonymousAllowClientCert());
447   cinfo->SetFallbackConnection(aInfoArgs.fallbackConnection());
448   cinfo->SetTlsFlags(aInfoArgs.tlsFlags());
449   cinfo->SetIsTrrServiceChannel(aInfoArgs.isTrrServiceChannel());
450   cinfo->SetTRRMode(static_cast<nsIRequest::TRRMode>(aInfoArgs.trrMode()));
451   cinfo->SetIPv4Disabled(aInfoArgs.isIPv4Disabled());
452   cinfo->SetIPv6Disabled(aInfoArgs.isIPv6Disabled());
453   cinfo->SetHasIPHintAddress(aInfoArgs.hasIPHintAddress());
454   cinfo->SetEchConfig(aInfoArgs.echConfig());
455 
456   return cinfo.forget();
457 }
458 
CloneAsDirectRoute(nsHttpConnectionInfo ** outCI)459 void nsHttpConnectionInfo::CloneAsDirectRoute(nsHttpConnectionInfo** outCI) {
460   // Explicitly use an empty npnToken when |mIsHttp3| is true, since we want to
461   // create a non-http3 connection info.
462   RefPtr<nsHttpConnectionInfo> clone = new nsHttpConnectionInfo(
463       mOrigin, mOriginPort,
464       (mRoutedHost.IsEmpty() && !mIsHttp3) ? mNPNToken : ""_ns, mUsername,
465       mProxyInfo, mOriginAttributes, mEndToEndSSL);
466   // Make sure the anonymous, insecure-scheme, and private flags are transferred
467   clone->SetAnonymous(GetAnonymous());
468   clone->SetPrivate(GetPrivate());
469   clone->SetInsecureScheme(GetInsecureScheme());
470   clone->SetNoSpdy(GetNoSpdy());
471   clone->SetBeConservative(GetBeConservative());
472   clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
473   clone->SetFallbackConnection(GetFallbackConnection());
474   clone->SetTlsFlags(GetTlsFlags());
475   clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
476   clone->SetTRRMode(GetTRRMode());
477   clone->SetIPv4Disabled(GetIPv4Disabled());
478   clone->SetIPv6Disabled(GetIPv6Disabled());
479   clone->SetHasIPHintAddress(HasIPHintAddress());
480   clone->SetEchConfig(GetEchConfig());
481 
482   clone.forget(outCI);
483 }
484 
CreateWildCard(nsHttpConnectionInfo ** outParam)485 nsresult nsHttpConnectionInfo::CreateWildCard(nsHttpConnectionInfo** outParam) {
486   // T???mozilla.org:443 (https:proxy.ducksong.com:3128) [specifc form]
487   // TS??*:0 (https:proxy.ducksong.com:3128)   [wildcard form]
488 
489   if (!mUsingHttpsProxy) {
490     MOZ_ASSERT(false);
491     return NS_ERROR_NOT_IMPLEMENTED;
492   }
493 
494   RefPtr<nsHttpConnectionInfo> clone;
495   clone = new nsHttpConnectionInfo("*"_ns, 0, mNPNToken, mUsername, mProxyInfo,
496                                    mOriginAttributes, true, mIsHttp3);
497   // Make sure the anonymous and private flags are transferred!
498   clone->SetAnonymous(GetAnonymous());
499   clone->SetPrivate(GetPrivate());
500   clone.forget(outParam);
501   return NS_OK;
502 }
503 
SetTRRMode(nsIRequest::TRRMode aTRRMode)504 void nsHttpConnectionInfo::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
505   if (mTRRMode != aTRRMode) {
506     mTRRMode = aTRRMode;
507     RebuildHashKey();
508   }
509 }
510 
SetIPv4Disabled(bool aNoIPv4)511 void nsHttpConnectionInfo::SetIPv4Disabled(bool aNoIPv4) {
512   if (mIPv4Disabled != aNoIPv4) {
513     mIPv4Disabled = aNoIPv4;
514     RebuildHashKey();
515   }
516 }
517 
SetIPv6Disabled(bool aNoIPv6)518 void nsHttpConnectionInfo::SetIPv6Disabled(bool aNoIPv6) {
519   if (mIPv6Disabled != aNoIPv6) {
520     mIPv6Disabled = aNoIPv6;
521     RebuildHashKey();
522   }
523 }
524 
SetTlsFlags(uint32_t aTlsFlags)525 void nsHttpConnectionInfo::SetTlsFlags(uint32_t aTlsFlags) {
526   mTlsFlags = aTlsFlags;
527   const uint32_t tlsFlagsIndex =
528       UnderlyingIndex(HashKeyIndex::End) + strlen("[tlsflags0x");
529   mHashKey.Replace(tlsFlagsIndex, 8, nsPrintfCString("%08x", mTlsFlags));
530 }
531 
UsingProxy()532 bool nsHttpConnectionInfo::UsingProxy() {
533   if (!mProxyInfo) return false;
534   return !mProxyInfo->IsDirect();
535 }
536 
HostIsLocalIPLiteral() const537 bool nsHttpConnectionInfo::HostIsLocalIPLiteral() const {
538   NetAddr netAddr;
539   // If the host/proxy host is not an IP address literal, return false.
540   nsAutoCString host(ProxyHost() ? ProxyHost() : Origin());
541   if (NS_FAILED(netAddr.InitFromString(host))) {
542     return false;
543   }
544   return netAddr.IsIPAddrLocal();
545 }
546 
547 }  // namespace net
548 }  // namespace mozilla
549