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 #ifndef nsHttpConnectionInfo_h__ 8 #define nsHttpConnectionInfo_h__ 9 10 #include "nsHttp.h" 11 #include "nsProxyInfo.h" 12 #include "nsCOMPtr.h" 13 #include "nsStringFwd.h" 14 #include "mozilla/Logging.h" 15 #include "mozilla/BasePrincipal.h" 16 #include "mozilla/AlreadyAddRefed.h" 17 #include "ARefBase.h" 18 #include "nsIRequest.h" 19 20 //----------------------------------------------------------------------------- 21 // nsHttpConnectionInfo - holds the properties of a connection 22 //----------------------------------------------------------------------------- 23 24 // http:// uris through a proxy will all share the same CI, because they can 25 // all use the same connection. (modulo pb and anonymous flags). They just use 26 // the proxy as the origin host name. 27 // however, https:// uris tunnel through the proxy so they will have different 28 // CIs - the CI reflects both the proxy and the origin. 29 // however, proxy conenctions made with http/2 (or spdy) can tunnel to the 30 // origin and multiplex non tunneled transactions at the same time, so they have 31 // a special wildcard CI that accepts all origins through that proxy. 32 33 class nsISVCBRecord; 34 35 namespace mozilla { 36 namespace net { 37 38 extern LazyLogModule gHttpLog; 39 class HttpConnectionInfoCloneArgs; 40 class nsHttpTransaction; 41 42 class nsHttpConnectionInfo final : public ARefBase { 43 public: 44 nsHttpConnectionInfo(const nsACString& originHost, int32_t originPort, 45 const nsACString& npnToken, const nsACString& username, 46 nsProxyInfo* proxyInfo, 47 const OriginAttributes& originAttributes, 48 bool endToEndSSL = false, bool aIsHttp3 = false); 49 50 // this version must use TLS and you may supply separate 51 // connection (aka routing) information than the authenticated 52 // origin information 53 nsHttpConnectionInfo(const nsACString& originHost, int32_t originPort, 54 const nsACString& npnToken, const nsACString& username, 55 nsProxyInfo* proxyInfo, 56 const OriginAttributes& originAttributes, 57 const nsACString& routedHost, int32_t routedPort, 58 bool aIsHttp3); 59 60 static void SerializeHttpConnectionInfo(nsHttpConnectionInfo* aInfo, 61 HttpConnectionInfoCloneArgs& aArgs); 62 static already_AddRefed<nsHttpConnectionInfo> 63 DeserializeHttpConnectionInfoCloneArgs( 64 const HttpConnectionInfoCloneArgs& aInfoArgs); 65 66 private: ~nsHttpConnectionInfo()67 virtual ~nsHttpConnectionInfo() { 68 MOZ_LOG(gHttpLog, LogLevel::Debug, 69 ("Destroying nsHttpConnectionInfo @%p\n", this)); 70 } 71 72 void BuildHashKey(); 73 void RebuildHashKey(); 74 75 // See comments in nsHttpConnectionInfo::BuildHashKey for the meaning of each 76 // field. 77 enum class HashKeyIndex : uint32_t { 78 Proxy = 0, 79 EndToEndSSL, 80 Anonymous, 81 Private, 82 InsecureScheme, 83 NoSpdy, 84 BeConservative, 85 AnonymousAllowClientCert, 86 FallbackConnection, 87 End, 88 }; UnderlyingIndex(HashKeyIndex aIndex)89 constexpr inline auto UnderlyingIndex(HashKeyIndex aIndex) const { 90 return std::underlying_type_t<HashKeyIndex>(aIndex); 91 } 92 93 public: HashKey()94 const nsCString& HashKey() const { return mHashKey; } 95 GetOrigin()96 const nsCString& GetOrigin() const { return mOrigin; } Origin()97 const char* Origin() const { return mOrigin.get(); } OriginPort()98 int32_t OriginPort() const { return mOriginPort; } 99 GetRoutedHost()100 const nsCString& GetRoutedHost() const { return mRoutedHost; } RoutedHost()101 const char* RoutedHost() const { return mRoutedHost.get(); } RoutedPort()102 int32_t RoutedPort() const { return mRoutedPort; } 103 104 // OK to treat these as an infalible allocation 105 already_AddRefed<nsHttpConnectionInfo> Clone() const; 106 // This main prupose of this function is to clone this connection info, but 107 // replace mRoutedHost with SvcDomainName in the given SVCB record. Note that 108 // if SvcParamKeyPort and SvcParamKeyAlpn are presented in the SVCB record, 109 // mRoutedPort and mNPNToken will be replaced as well. 110 already_AddRefed<nsHttpConnectionInfo> CloneAndAdoptHTTPSSVCRecord( 111 nsISVCBRecord* aRecord) const; 112 void CloneAsDirectRoute(nsHttpConnectionInfo** outCI); 113 [[nodiscard]] nsresult CreateWildCard(nsHttpConnectionInfo** outParam); 114 ProxyHost()115 const char* ProxyHost() const { 116 return mProxyInfo ? mProxyInfo->Host().get() : nullptr; 117 } ProxyPort()118 int32_t ProxyPort() const { return mProxyInfo ? mProxyInfo->Port() : -1; } ProxyType()119 const char* ProxyType() const { 120 return mProxyInfo ? mProxyInfo->Type() : nullptr; 121 } ProxyUsername()122 const char* ProxyUsername() const { 123 return mProxyInfo ? mProxyInfo->Username().get() : nullptr; 124 } ProxyPassword()125 const char* ProxyPassword() const { 126 return mProxyInfo ? mProxyInfo->Password().get() : nullptr; 127 } 128 ProxyAuthorizationHeader()129 const nsCString& ProxyAuthorizationHeader() const { 130 return mProxyInfo ? mProxyInfo->ProxyAuthorizationHeader() : EmptyCString(); 131 } ConnectionIsolationKey()132 const nsCString& ConnectionIsolationKey() const { 133 return mProxyInfo ? mProxyInfo->ConnectionIsolationKey() : EmptyCString(); 134 } 135 136 // Compare this connection info to another... 137 // Two connections are 'equal' if they end up talking the same 138 // protocol to the same server. This is needed to properly manage 139 // persistent connections to proxies 140 // Note that we don't care about transparent proxies - 141 // it doesn't matter if we're talking via socks or not, since 142 // a request will end up at the same host. Equals(const nsHttpConnectionInfo * info)143 bool Equals(const nsHttpConnectionInfo* info) { 144 return mHashKey.Equals(info->HashKey()); 145 } 146 Username()147 const char* Username() const { return mUsername.get(); } ProxyInfo()148 nsProxyInfo* ProxyInfo() const { return mProxyInfo; } DefaultPort()149 int32_t DefaultPort() const { 150 return mEndToEndSSL ? NS_HTTPS_DEFAULT_PORT : NS_HTTP_DEFAULT_PORT; 151 } SetAnonymous(bool anon)152 void SetAnonymous(bool anon) { 153 SetHashCharAt(anon ? 'A' : '.', HashKeyIndex::Anonymous); 154 } GetAnonymous()155 bool GetAnonymous() const { 156 return GetHashCharAt(HashKeyIndex::Anonymous) == 'A'; 157 } SetPrivate(bool priv)158 void SetPrivate(bool priv) { 159 SetHashCharAt(priv ? 'P' : '.', HashKeyIndex::Private); 160 } GetPrivate()161 bool GetPrivate() const { 162 return GetHashCharAt(HashKeyIndex::Private) == 'P'; 163 } SetInsecureScheme(bool insecureScheme)164 void SetInsecureScheme(bool insecureScheme) { 165 SetHashCharAt(insecureScheme ? 'I' : '.', HashKeyIndex::InsecureScheme); 166 } GetInsecureScheme()167 bool GetInsecureScheme() const { 168 return GetHashCharAt(HashKeyIndex::InsecureScheme) == 'I'; 169 } 170 SetNoSpdy(bool aNoSpdy)171 void SetNoSpdy(bool aNoSpdy) { 172 SetHashCharAt(aNoSpdy ? 'X' : '.', HashKeyIndex::NoSpdy); 173 if (aNoSpdy && mNPNToken == "h2"_ns) { 174 mNPNToken.Truncate(); 175 RebuildHashKey(); 176 } 177 } GetNoSpdy()178 bool GetNoSpdy() const { return GetHashCharAt(HashKeyIndex::NoSpdy) == 'X'; } 179 SetBeConservative(bool aBeConservative)180 void SetBeConservative(bool aBeConservative) { 181 SetHashCharAt(aBeConservative ? 'C' : '.', HashKeyIndex::BeConservative); 182 } GetBeConservative()183 bool GetBeConservative() const { 184 return GetHashCharAt(HashKeyIndex::BeConservative) == 'C'; 185 } 186 SetAnonymousAllowClientCert(bool anon)187 void SetAnonymousAllowClientCert(bool anon) { 188 SetHashCharAt(anon ? 'B' : '.', HashKeyIndex::AnonymousAllowClientCert); 189 } GetAnonymousAllowClientCert()190 bool GetAnonymousAllowClientCert() const { 191 return GetHashCharAt(HashKeyIndex::AnonymousAllowClientCert) == 'B'; 192 } 193 SetFallbackConnection(bool aFallback)194 void SetFallbackConnection(bool aFallback) { 195 SetHashCharAt(aFallback ? 'F' : '.', HashKeyIndex::FallbackConnection); 196 } GetFallbackConnection()197 bool GetFallbackConnection() const { 198 return GetHashCharAt(HashKeyIndex::FallbackConnection) == 'F'; 199 } 200 201 void SetTlsFlags(uint32_t aTlsFlags); GetTlsFlags()202 uint32_t GetTlsFlags() const { return mTlsFlags; } 203 204 // IsTrrServiceChannel means that this connection is used to send TRR requests 205 // over SetIsTrrServiceChannel(bool aIsTRRChannel)206 void SetIsTrrServiceChannel(bool aIsTRRChannel) { 207 mIsTrrServiceChannel = aIsTRRChannel; 208 } GetIsTrrServiceChannel()209 bool GetIsTrrServiceChannel() const { return mIsTrrServiceChannel; } 210 211 void SetTRRMode(nsIRequest::TRRMode aTRRMode); GetTRRMode()212 nsIRequest::TRRMode GetTRRMode() const { return mTRRMode; } 213 214 void SetIPv4Disabled(bool aNoIPv4); GetIPv4Disabled()215 bool GetIPv4Disabled() const { return mIPv4Disabled; } 216 217 void SetIPv6Disabled(bool aNoIPv6); GetIPv6Disabled()218 bool GetIPv6Disabled() const { return mIPv6Disabled; } 219 GetNPNToken()220 const nsCString& GetNPNToken() { return mNPNToken; } GetUsername()221 const nsCString& GetUsername() { return mUsername; } 222 GetOriginAttributes()223 const OriginAttributes& GetOriginAttributes() { return mOriginAttributes; } 224 225 // Returns true for any kind of proxy (http, socks, https, etc..) 226 bool UsingProxy(); 227 228 // Returns true when proxying over HTTP or HTTPS UsingHttpProxy()229 bool UsingHttpProxy() const { return mUsingHttpProxy || mUsingHttpsProxy; } 230 231 // Returns true when proxying over HTTPS UsingHttpsProxy()232 bool UsingHttpsProxy() const { return mUsingHttpsProxy; } 233 234 // Returns true when a resource is in SSL end to end (e.g. https:// uri) EndToEndSSL()235 bool EndToEndSSL() const { return mEndToEndSSL; } 236 237 // Returns true when at least first hop is SSL (e.g. proxy over https or https 238 // uri) FirstHopSSL()239 bool FirstHopSSL() const { return mEndToEndSSL || mUsingHttpsProxy; } 240 241 // Returns true when CONNECT is used to tunnel through the proxy (e.g. 242 // https:// or ws://) UsingConnect()243 bool UsingConnect() const { return mUsingConnect; } 244 245 // Returns true when origin/proxy is an RFC1918 literal. 246 bool HostIsLocalIPLiteral() const; 247 GetLessThanTls13()248 bool GetLessThanTls13() const { return mLessThanTls13; } SetLessThanTls13(bool aLessThanTls13)249 void SetLessThanTls13(bool aLessThanTls13) { 250 mLessThanTls13 = aLessThanTls13; 251 } 252 IsHttp3()253 bool IsHttp3() const { return mIsHttp3; } 254 SetHasIPHintAddress(bool aHasIPHint)255 void SetHasIPHintAddress(bool aHasIPHint) { mHasIPHintAddress = aHasIPHint; } HasIPHintAddress()256 bool HasIPHintAddress() const { return mHasIPHintAddress; } 257 SetEchConfig(const nsACString & aEchConfig)258 void SetEchConfig(const nsACString& aEchConfig) { mEchConfig = aEchConfig; } GetEchConfig()259 const nsCString& GetEchConfig() const { return mEchConfig; } 260 261 private: 262 void Init(const nsACString& host, int32_t port, const nsACString& npnToken, 263 const nsACString& username, nsProxyInfo* proxyInfo, 264 const OriginAttributes& originAttributes, bool e2eSSL, 265 bool aIsHttp3); 266 void SetOriginServer(const nsACString& host, int32_t port); GetHashCharAt(HashKeyIndex aIndex)267 nsCString::char_type GetHashCharAt(HashKeyIndex aIndex) const { 268 return mHashKey.CharAt(UnderlyingIndex(aIndex)); 269 } SetHashCharAt(nsCString::char_type aValue,HashKeyIndex aIndex)270 void SetHashCharAt(nsCString::char_type aValue, HashKeyIndex aIndex) { 271 mHashKey.SetCharAt(aValue, UnderlyingIndex(aIndex)); 272 } 273 274 nsCString mOrigin; 275 int32_t mOriginPort = 0; 276 nsCString mRoutedHost; 277 int32_t mRoutedPort; 278 279 nsCString mHashKey; 280 nsCString mUsername; 281 nsCOMPtr<nsProxyInfo> mProxyInfo; 282 bool mUsingHttpProxy = false; 283 bool mUsingHttpsProxy = false; 284 bool mEndToEndSSL = false; 285 // if will use CONNECT with http proxy 286 bool mUsingConnect = false; 287 nsCString mNPNToken; 288 OriginAttributes mOriginAttributes; 289 nsIRequest::TRRMode mTRRMode; 290 291 uint32_t mTlsFlags = 0; 292 uint16_t mIsTrrServiceChannel : 1; 293 uint16_t mIPv4Disabled : 1; 294 uint16_t mIPv6Disabled : 1; 295 296 bool mLessThanTls13; // This will be set to true if we negotiate less than 297 // tls1.3. If the tls version is till not know or it 298 // is 1.3 or greater the value will be false. 299 bool mIsHttp3 = false; 300 301 bool mHasIPHintAddress = false; 302 nsCString mEchConfig; 303 304 // for RefPtr 305 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHttpConnectionInfo, override) 306 }; 307 308 } // namespace net 309 } // namespace mozilla 310 311 #endif // nsHttpConnectionInfo_h__ 312