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 4 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   mHashKey.AssignLiteral(".........[tlsflags0x00000000]");
148 
149   mHashKey.Append(keyHost);
150   mHashKey.Append(':');
151   mHashKey.AppendInt(keyPort);
152   if (!mUsername.IsEmpty()) {
153     mHashKey.Append('[');
154     mHashKey.Append(mUsername);
155     mHashKey.Append(']');
156   }
157 
158   if (mUsingHttpsProxy) {
159     mHashKey.SetCharAt('T', 0);
160   } else if (mUsingHttpProxy) {
161     mHashKey.SetCharAt('P', 0);
162   }
163   if (mEndToEndSSL) {
164     mHashKey.SetCharAt('S', 1);
165   }
166 
167   // NOTE: for transparent proxies (e.g., SOCKS) we need to encode the proxy
168   // info in the hash key (this ensures that we will continue to speak the
169   // right protocol even if our proxy preferences change).
170   //
171   // NOTE: for SSL tunnels add the proxy information to the cache key.
172   // We cannot use the proxy as the host parameter (as we do for non SSL)
173   // because this is a single host tunnel, but we need to include the proxy
174   // information so that a change in proxy config will mean this connection
175   // is not reused
176 
177   // NOTE: Adding the username and the password provides a means to isolate
178   // keep-alive to the URL bar domain as well: If the username is the URL bar
179   // domain, keep-alive connections are not reused by resources bound to
180   // different URL bar domains as the respective hash keys are not matching.
181 
182   if ((!mUsingHttpProxy && ProxyHost()) || (mUsingHttpProxy && mUsingConnect)) {
183     mHashKey.AppendLiteral(" (");
184     mHashKey.Append(ProxyType());
185     mHashKey.Append(':');
186     mHashKey.Append(ProxyHost());
187     mHashKey.Append(':');
188     mHashKey.AppendInt(ProxyPort());
189     mHashKey.Append(')');
190     mHashKey.Append('[');
191     mHashKey.Append(ProxyUsername());
192     mHashKey.Append(':');
193     const char* password = ProxyPassword();
194     if (strlen(password) > 0) {
195       nsAutoCString digestedPassword;
196       nsresult rv = SHA256(password, digestedPassword);
197       if (rv == NS_OK) {
198         mHashKey.Append(digestedPassword);
199       }
200     }
201     mHashKey.Append(']');
202   }
203 
204   if (!mRoutedHost.IsEmpty()) {
205     mHashKey.AppendLiteral(" <ROUTE-via ");
206     mHashKey.Append(mRoutedHost);
207     mHashKey.Append(':');
208     mHashKey.AppendInt(mRoutedPort);
209     mHashKey.Append('>');
210   }
211 
212   if (!mNPNToken.IsEmpty()) {
213     mHashKey.AppendLiteral(" {NPN-TOKEN ");
214     mHashKey.Append(mNPNToken);
215     mHashKey.AppendLiteral("}");
216   }
217 
218   if (GetTRRMode() != nsIRequest::TRR_DEFAULT_MODE) {
219     // When connecting with another TRR mode, we enforce a separate connection
220     // hashkey so that we also can trigger a fresh DNS resolver that then
221     // doesn't use TRR as the previous connection might have.
222     mHashKey.AppendLiteral("[TRR:");
223     mHashKey.AppendInt(GetTRRMode());
224     mHashKey.AppendLiteral("]");
225   }
226 
227   if (GetIPv4Disabled()) {
228     mHashKey.AppendLiteral("[!v4]");
229   }
230 
231   if (GetIPv6Disabled()) {
232     mHashKey.AppendLiteral("[!v6]");
233   }
234 
235   if (mProxyInfo) {
236     const nsCString& connectionIsolationKey =
237         mProxyInfo->ConnectionIsolationKey();
238     if (!connectionIsolationKey.IsEmpty()) {
239       mHashKey.AppendLiteral("{CIK ");
240       mHashKey.Append(connectionIsolationKey);
241       mHashKey.AppendLiteral("}");
242     }
243     if (mProxyInfo->Flags() & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
244       mHashKey.AppendLiteral("{TPRH}");
245     }
246   }
247 
248   nsAutoCString originAttributes;
249   mOriginAttributes.CreateSuffix(originAttributes);
250   mHashKey.Append(originAttributes);
251 }
252 
RebuildHashKey()253 void nsHttpConnectionInfo::RebuildHashKey() {
254   // Create copies of all properties stored in our hash key.
255   bool isAnonymous = GetAnonymous();
256   bool isPrivate = GetPrivate();
257   bool isInsecureScheme = GetInsecureScheme();
258   bool isNoSpdy = GetNoSpdy();
259   bool isBeConservative = GetBeConservative();
260   bool isAnonymousAllowClientCert = GetAnonymousAllowClientCert();
261   bool isFallback = GetFallbackConnection();
262 
263   BuildHashKey();
264 
265   // Restore all of those properties.
266   SetAnonymous(isAnonymous);
267   SetPrivate(isPrivate);
268   SetInsecureScheme(isInsecureScheme);
269   SetNoSpdy(isNoSpdy);
270   SetBeConservative(isBeConservative);
271   SetAnonymousAllowClientCert(isAnonymousAllowClientCert);
272   SetFallbackConnection(isFallback);
273 }
274 
SetOriginServer(const nsACString & host,int32_t port)275 void nsHttpConnectionInfo::SetOriginServer(const nsACString& host,
276                                            int32_t port) {
277   mOrigin = host;
278   mOriginPort = port == -1 ? DefaultPort() : port;
279   // Use BuildHashKey() since this can only be called when constructing an
280   // nsHttpConnectionInfo object.
281   MOZ_DIAGNOSTIC_ASSERT(mHashKey.IsEmpty());
282   BuildHashKey();
283 }
284 
285 // Note that this function needs to be synced with
286 // nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs to make sure
287 // nsHttpConnectionInfo can be serialized/deserialized.
Clone() const288 already_AddRefed<nsHttpConnectionInfo> nsHttpConnectionInfo::Clone() const {
289   RefPtr<nsHttpConnectionInfo> clone;
290   if (mRoutedHost.IsEmpty()) {
291     clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername,
292                                      mProxyInfo, mOriginAttributes,
293                                      mEndToEndSSL, mIsHttp3);
294   } else {
295     MOZ_ASSERT(mEndToEndSSL);
296     clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername,
297                                      mProxyInfo, mOriginAttributes, mRoutedHost,
298                                      mRoutedPort, mIsHttp3);
299   }
300 
301   // Make sure the anonymous, insecure-scheme, and private flags are transferred
302   clone->SetAnonymous(GetAnonymous());
303   clone->SetPrivate(GetPrivate());
304   clone->SetInsecureScheme(GetInsecureScheme());
305   clone->SetNoSpdy(GetNoSpdy());
306   clone->SetBeConservative(GetBeConservative());
307   clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
308   clone->SetFallbackConnection(GetFallbackConnection());
309   clone->SetTlsFlags(GetTlsFlags());
310   clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
311   clone->SetTRRMode(GetTRRMode());
312   clone->SetIPv4Disabled(GetIPv4Disabled());
313   clone->SetIPv6Disabled(GetIPv6Disabled());
314   clone->SetHasIPHintAddress(HasIPHintAddress());
315   clone->SetEchConfig(GetEchConfig());
316   MOZ_ASSERT(clone->Equals(this));
317 
318   return clone.forget();
319 }
320 
321 already_AddRefed<nsHttpConnectionInfo>
CloneAndAdoptHTTPSSVCRecord(nsISVCBRecord * aRecord) const322 nsHttpConnectionInfo::CloneAndAdoptHTTPSSVCRecord(
323     nsISVCBRecord* aRecord) const {
324   MOZ_ASSERT(aRecord);
325 
326   // Get the domain name of this HTTPS RR. This name will be assigned to
327   // mRoutedHost in the new connection info.
328   nsAutoCString name;
329   aRecord->GetName(name);
330 
331   // Try to get the port and Alpn. If this record has SvcParamKeyPort defined,
332   // the new port will be used as mRoutedPort.
333   Maybe<uint16_t> port = aRecord->GetPort();
334   Maybe<Tuple<nsCString, bool>> alpn = aRecord->GetAlpn();
335 
336   // Let the new conn info learn h3 will be used.
337   bool isHttp3 = alpn ? Get<1>(*alpn) : false;
338 
339   LOG(("HTTPSSVC: use new routed host (%s) and new npnToken (%s)", name.get(),
340        alpn ? Get<0>(*alpn).get() : "None"));
341 
342   RefPtr<nsHttpConnectionInfo> clone;
343   if (name.IsEmpty()) {
344     clone = new nsHttpConnectionInfo(
345         mOrigin, mOriginPort, alpn ? Get<0>(*alpn) : EmptyCString(), mUsername,
346         mProxyInfo, mOriginAttributes, mEndToEndSSL, isHttp3);
347   } else {
348     MOZ_ASSERT(mEndToEndSSL);
349     clone = new nsHttpConnectionInfo(mOrigin, mOriginPort,
350                                      alpn ? Get<0>(*alpn) : EmptyCString(),
351                                      mUsername, mProxyInfo, mOriginAttributes,
352                                      name, port ? *port : mOriginPort, isHttp3);
353   }
354 
355   // Make sure the anonymous, insecure-scheme, and private flags are transferred
356   clone->SetAnonymous(GetAnonymous());
357   clone->SetPrivate(GetPrivate());
358   clone->SetInsecureScheme(GetInsecureScheme());
359   clone->SetNoSpdy(GetNoSpdy());
360   clone->SetBeConservative(GetBeConservative());
361   clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
362   clone->SetFallbackConnection(GetFallbackConnection());
363   clone->SetTlsFlags(GetTlsFlags());
364   clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
365   clone->SetTRRMode(GetTRRMode());
366   clone->SetIPv4Disabled(GetIPv4Disabled());
367   clone->SetIPv6Disabled(GetIPv6Disabled());
368 
369   bool hasIPHint = false;
370   Unused << aRecord->GetHasIPHintAddress(&hasIPHint);
371   if (hasIPHint) {
372     clone->SetHasIPHintAddress(hasIPHint);
373   }
374 
375   nsAutoCString echConfig;
376   Unused << aRecord->GetEchConfig(echConfig);
377   clone->SetEchConfig(echConfig);
378 
379   return clone.forget();
380 }
381 
382 /* static */
SerializeHttpConnectionInfo(nsHttpConnectionInfo * aInfo,HttpConnectionInfoCloneArgs & aArgs)383 void nsHttpConnectionInfo::SerializeHttpConnectionInfo(
384     nsHttpConnectionInfo* aInfo, HttpConnectionInfoCloneArgs& aArgs) {
385   aArgs.host() = aInfo->GetOrigin();
386   aArgs.port() = aInfo->OriginPort();
387   aArgs.npnToken() = aInfo->GetNPNToken();
388   aArgs.username() = aInfo->GetUsername();
389   aArgs.originAttributes() = aInfo->GetOriginAttributes();
390   aArgs.endToEndSSL() = aInfo->EndToEndSSL();
391   aArgs.routedHost() = aInfo->GetRoutedHost();
392   aArgs.routedPort() = aInfo->RoutedPort();
393   aArgs.anonymous() = aInfo->GetAnonymous();
394   aArgs.aPrivate() = aInfo->GetPrivate();
395   aArgs.insecureScheme() = aInfo->GetInsecureScheme();
396   aArgs.noSpdy() = aInfo->GetNoSpdy();
397   aArgs.beConservative() = aInfo->GetBeConservative();
398   aArgs.anonymousAllowClientCert() = aInfo->GetAnonymousAllowClientCert();
399   aArgs.tlsFlags() = aInfo->GetTlsFlags();
400   aArgs.isTrrServiceChannel() = aInfo->GetTRRMode();
401   aArgs.trrMode() = aInfo->GetTRRMode();
402   aArgs.isIPv4Disabled() = aInfo->GetIPv4Disabled();
403   aArgs.isIPv6Disabled() = aInfo->GetIPv6Disabled();
404   aArgs.isHttp3() = aInfo->IsHttp3();
405   aArgs.hasIPHintAddress() = aInfo->HasIPHintAddress();
406   aArgs.echConfig() = aInfo->GetEchConfig();
407 
408   if (!aInfo->ProxyInfo()) {
409     return;
410   }
411 
412   nsTArray<ProxyInfoCloneArgs> proxyInfoArray;
413   nsProxyInfo::SerializeProxyInfo(aInfo->ProxyInfo(), proxyInfoArray);
414   aArgs.proxyInfo() = std::move(proxyInfoArray);
415 }
416 
417 // This function needs to be synced with nsHttpConnectionInfo::Clone.
418 /* static */
419 already_AddRefed<nsHttpConnectionInfo>
DeserializeHttpConnectionInfoCloneArgs(const HttpConnectionInfoCloneArgs & aInfoArgs)420 nsHttpConnectionInfo::DeserializeHttpConnectionInfoCloneArgs(
421     const HttpConnectionInfoCloneArgs& aInfoArgs) {
422   nsProxyInfo* pi = nsProxyInfo::DeserializeProxyInfo(aInfoArgs.proxyInfo());
423   RefPtr<nsHttpConnectionInfo> cinfo;
424   if (aInfoArgs.routedHost().IsEmpty()) {
425     cinfo = new nsHttpConnectionInfo(
426         aInfoArgs.host(), aInfoArgs.port(), aInfoArgs.npnToken(),
427         aInfoArgs.username(), pi, aInfoArgs.originAttributes(),
428         aInfoArgs.endToEndSSL(), aInfoArgs.isHttp3());
429   } else {
430     MOZ_ASSERT(aInfoArgs.endToEndSSL());
431     cinfo = new nsHttpConnectionInfo(
432         aInfoArgs.host(), aInfoArgs.port(), aInfoArgs.npnToken(),
433         aInfoArgs.username(), pi, aInfoArgs.originAttributes(),
434         aInfoArgs.routedHost(), aInfoArgs.routedPort(), aInfoArgs.isHttp3());
435   }
436 
437   // Make sure the anonymous, insecure-scheme, and private flags are transferred
438   cinfo->SetAnonymous(aInfoArgs.anonymous());
439   cinfo->SetPrivate(aInfoArgs.aPrivate());
440   cinfo->SetInsecureScheme(aInfoArgs.insecureScheme());
441   cinfo->SetNoSpdy(aInfoArgs.noSpdy());
442   cinfo->SetBeConservative(aInfoArgs.beConservative());
443   cinfo->SetAnonymousAllowClientCert(aInfoArgs.anonymousAllowClientCert());
444   cinfo->SetFallbackConnection(aInfoArgs.fallbackConnection());
445   cinfo->SetTlsFlags(aInfoArgs.tlsFlags());
446   cinfo->SetIsTrrServiceChannel(aInfoArgs.isTrrServiceChannel());
447   cinfo->SetTRRMode(static_cast<nsIRequest::TRRMode>(aInfoArgs.trrMode()));
448   cinfo->SetIPv4Disabled(aInfoArgs.isIPv4Disabled());
449   cinfo->SetIPv6Disabled(aInfoArgs.isIPv6Disabled());
450   cinfo->SetHasIPHintAddress(aInfoArgs.hasIPHintAddress());
451   cinfo->SetEchConfig(aInfoArgs.echConfig());
452 
453   return cinfo.forget();
454 }
455 
CloneAsDirectRoute(nsHttpConnectionInfo ** outCI)456 void nsHttpConnectionInfo::CloneAsDirectRoute(nsHttpConnectionInfo** outCI) {
457   // Explicitly use an empty npnToken when |mIsHttp3| is true, since we want to
458   // create a non-http3 connection info.
459   RefPtr<nsHttpConnectionInfo> clone = new nsHttpConnectionInfo(
460       mOrigin, mOriginPort,
461       (mRoutedHost.IsEmpty() && !mIsHttp3) ? mNPNToken : ""_ns, mUsername,
462       mProxyInfo, mOriginAttributes, mEndToEndSSL);
463   // Make sure the anonymous, insecure-scheme, and private flags are transferred
464   clone->SetAnonymous(GetAnonymous());
465   clone->SetPrivate(GetPrivate());
466   clone->SetInsecureScheme(GetInsecureScheme());
467   clone->SetNoSpdy(GetNoSpdy());
468   clone->SetBeConservative(GetBeConservative());
469   clone->SetAnonymousAllowClientCert(GetAnonymousAllowClientCert());
470   clone->SetFallbackConnection(GetFallbackConnection());
471   clone->SetTlsFlags(GetTlsFlags());
472   clone->SetIsTrrServiceChannel(GetIsTrrServiceChannel());
473   clone->SetTRRMode(GetTRRMode());
474   clone->SetIPv4Disabled(GetIPv4Disabled());
475   clone->SetIPv6Disabled(GetIPv6Disabled());
476   clone->SetHasIPHintAddress(HasIPHintAddress());
477   clone->SetEchConfig(GetEchConfig());
478 
479   clone.forget(outCI);
480 }
481 
CreateWildCard(nsHttpConnectionInfo ** outParam)482 nsresult nsHttpConnectionInfo::CreateWildCard(nsHttpConnectionInfo** outParam) {
483   // T???mozilla.org:443 (https:proxy.ducksong.com:3128) [specifc form]
484   // TS??*:0 (https:proxy.ducksong.com:3128)   [wildcard form]
485 
486   if (!mUsingHttpsProxy) {
487     MOZ_ASSERT(false);
488     return NS_ERROR_NOT_IMPLEMENTED;
489   }
490 
491   RefPtr<nsHttpConnectionInfo> clone;
492   clone = new nsHttpConnectionInfo("*"_ns, 0, mNPNToken, mUsername, mProxyInfo,
493                                    mOriginAttributes, true, mIsHttp3);
494   // Make sure the anonymous and private flags are transferred!
495   clone->SetAnonymous(GetAnonymous());
496   clone->SetPrivate(GetPrivate());
497   clone.forget(outParam);
498   return NS_OK;
499 }
500 
SetTRRMode(nsIRequest::TRRMode aTRRMode)501 void nsHttpConnectionInfo::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
502   if (mTRRMode != aTRRMode) {
503     mTRRMode = aTRRMode;
504     RebuildHashKey();
505   }
506 }
507 
SetIPv4Disabled(bool aNoIPv4)508 void nsHttpConnectionInfo::SetIPv4Disabled(bool aNoIPv4) {
509   if (mIPv4Disabled != aNoIPv4) {
510     mIPv4Disabled = aNoIPv4;
511     RebuildHashKey();
512   }
513 }
514 
SetIPv6Disabled(bool aNoIPv6)515 void nsHttpConnectionInfo::SetIPv6Disabled(bool aNoIPv6) {
516   if (mIPv6Disabled != aNoIPv6) {
517     mIPv6Disabled = aNoIPv6;
518     RebuildHashKey();
519   }
520 }
521 
SetTlsFlags(uint32_t aTlsFlags)522 void nsHttpConnectionInfo::SetTlsFlags(uint32_t aTlsFlags) {
523   mTlsFlags = aTlsFlags;
524 
525   mHashKey.Replace(20, 8, nsPrintfCString("%08x", mTlsFlags));
526 }
527 
UsingProxy()528 bool nsHttpConnectionInfo::UsingProxy() {
529   if (!mProxyInfo) return false;
530   return !mProxyInfo->IsDirect();
531 }
532 
HostIsLocalIPLiteral() const533 bool nsHttpConnectionInfo::HostIsLocalIPLiteral() const {
534   NetAddr netAddr;
535   // If the host/proxy host is not an IP address literal, return false.
536   nsAutoCString host(ProxyHost() ? ProxyHost() : Origin());
537   if (NS_FAILED(netAddr.InitFromString(host))) {
538     return false;
539   }
540   return netAddr.IsIPAddrLocal();
541 }
542 
543 }  // namespace net
544 }  // namespace mozilla
545