tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AlternateServices.h (9449B)


      1 /* -*- Mode: C++; tab-width: 2; 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 /*
      8 Alt-Svc allows separation of transport routing from the origin host without
      9 using a proxy. See https://httpwg.github.io/http-extensions/alt-svc.html and
     10 https://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-06
     11 
     12 Nice To Have Future Enhancements::
     13 * flush on network change event when we have an indicator
     14 * use established https channel for http instead separate of conninfo hash
     15 * pin via http-tls header
     16 * clear based on origin when a random fail happens not just 421
     17 * upon establishment of channel, cancel and retry trans that have not yet
     18     written anything
     19 * persistent storage (including private browsing filter)
     20 * memory reporter for cache, but this is rather tiny
     21 */
     22 
     23 #ifndef mozilla_net_AlternateServices_h
     24 #define mozilla_net_AlternateServices_h
     25 
     26 #include "nsHttp.h"
     27 #include "nsRefPtrHashtable.h"
     28 #include "nsString.h"
     29 #include "nsIDataStorage.h"
     30 #include "nsIInterfaceRequestor.h"
     31 #include "nsIStreamListener.h"
     32 #include "nsISpeculativeConnect.h"
     33 #include "mozilla/BasePrincipal.h"
     34 #include "SpeculativeTransaction.h"
     35 
     36 class nsILoadInfo;
     37 
     38 namespace mozilla {
     39 namespace net {
     40 
     41 class nsProxyInfo;
     42 class nsHttpConnectionInfo;
     43 class nsHttpTransaction;
     44 class nsHttpChannel;
     45 class WellKnownChecker;
     46 
     47 class AltSvcMapping {
     48  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AltSvcMapping)
     49 
     50 private:  // ctor from ProcessHeader
     51  AltSvcMapping(nsIDataStorage* storage, int32_t storageEpoch,
     52                const nsACString& originScheme, const nsACString& originHost,
     53                int32_t originPort, const nsACString& username,
     54                bool privateBrowsing, uint32_t expiresAt,
     55                const nsACString& alternateHost, int32_t alternatePort,
     56                const nsACString& npnToken,
     57                const OriginAttributes& originAttributes, bool aIsHttp3,
     58                SupportedAlpnRank aRank);
     59 
     60 public:
     61  AltSvcMapping(nsIDataStorage* storage, int32_t storageEpoch,
     62                const nsCString& str);
     63 
     64  static void ProcessHeader(
     65      const nsCString& buf, const nsCString& originScheme,
     66      const nsCString& originHost, int32_t originPort,
     67      const nsACString& username, bool privateBrowsing,
     68      nsIInterfaceRequestor* callbacks, nsProxyInfo* proxyInfo, uint32_t caps,
     69      const OriginAttributes& originAttributes,
     70      nsHttpConnectionInfo* aTransConnInfo,
     71      bool aDontValidate = false);  // aDontValidate is only used for testing!
     72 
     73  // AcceptableProxy() decides whether a particular proxy configuration (pi) is
     74  // suitable for use with Alt-Svc. No proxy (including a null pi) is suitable.
     75  static bool AcceptableProxy(nsProxyInfo* proxyInfo);
     76 
     77  const nsCString& AlternateHost() const { return mAlternateHost; }
     78  const nsCString& OriginHost() const { return mOriginHost; }
     79  uint32_t OriginPort() const { return mOriginPort; }
     80  const nsCString& HashKey() const { return mHashKey; }
     81  uint32_t AlternatePort() const { return mAlternatePort; }
     82  bool Validated() { return mValidated; }
     83  int32_t GetExpiresAt() { return mExpiresAt; }
     84  bool RouteEquals(AltSvcMapping* map);
     85  bool HTTPS() { return mHttps; }
     86 
     87  void GetConnectionInfo(nsHttpConnectionInfo** outCI, nsProxyInfo* pi,
     88                         const OriginAttributes& originAttributes);
     89 
     90  int32_t TTL();
     91  int32_t StorageEpoch() { return mStorageEpoch; }
     92  bool Private() { return mPrivate; }
     93 
     94  void SetValidated(bool val);
     95  void SetMixedScheme(bool val);
     96  void SetExpiresAt(int32_t val);
     97  void SetExpired();
     98  void Sync();
     99  void SetSyncOnlyOnSuccess(bool aSOOS) { mSyncOnlyOnSuccess = aSOOS; }
    100 
    101  static void MakeHashKey(nsCString& outKey, const nsACString& originScheme,
    102                          const nsACString& originHost, int32_t originPort,
    103                          bool privateBrowsing,
    104                          const OriginAttributes& originAttributes,
    105                          bool aHttp3);
    106 
    107  bool IsHttp3() { return mIsHttp3; }
    108  const nsCString& NPNToken() const { return mNPNToken; }
    109  SupportedAlpnRank AlpnRank() const { return mAlpnRank; }
    110 
    111 private:
    112  virtual ~AltSvcMapping() = default;
    113  void SyncString(const nsCString& str);
    114  nsCOMPtr<nsIDataStorage> mStorage;
    115  int32_t mStorageEpoch;
    116  void Serialize(nsCString& out);
    117 
    118  nsCString mHashKey;
    119 
    120  // If you change any of these members, update Serialize()
    121  nsCString mAlternateHost;
    122  int32_t mAlternatePort{-1};
    123 
    124  nsCString mOriginHost;
    125  int32_t mOriginPort{-1};
    126 
    127  nsCString mUsername;
    128  bool mPrivate{false};
    129 
    130  // alt-svc mappping
    131  uint32_t mExpiresAt{0};
    132 
    133  bool mValidated{false};
    134  // origin is https://
    135  MOZ_INIT_OUTSIDE_CTOR bool mHttps{false};
    136  // .wk allows http and https on same con
    137  MOZ_INIT_OUTSIDE_CTOR bool mMixedScheme{false};
    138 
    139  nsCString mNPNToken;
    140 
    141  OriginAttributes mOriginAttributes;
    142 
    143  bool mSyncOnlyOnSuccess{false};
    144  bool mIsHttp3{false};
    145  SupportedAlpnRank mAlpnRank{SupportedAlpnRank::NOT_SUPPORTED};
    146 };
    147 
    148 class AltSvcOverride : public nsIInterfaceRequestor,
    149                       public nsISpeculativeConnectionOverrider {
    150 public:
    151  NS_DECL_THREADSAFE_ISUPPORTS
    152  NS_DECL_NSISPECULATIVECONNECTIONOVERRIDER
    153  NS_DECL_NSIINTERFACEREQUESTOR
    154 
    155  explicit AltSvcOverride(nsIInterfaceRequestor* aRequestor)
    156      : mCallbacks(aRequestor) {}
    157 
    158 private:
    159  virtual ~AltSvcOverride() = default;
    160  nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
    161 };
    162 
    163 class TransactionObserver final : public nsIStreamListener {
    164 public:
    165  NS_DECL_THREADSAFE_ISUPPORTS
    166  NS_DECL_NSISTREAMLISTENER
    167  NS_DECL_NSIREQUESTOBSERVER
    168 
    169  TransactionObserver(nsHttpChannel* channel, WellKnownChecker* checker);
    170  void Complete(bool versionOK, bool authOK, nsresult reason);
    171 
    172 private:
    173  friend class WellKnownChecker;
    174  virtual ~TransactionObserver() = default;
    175 
    176  nsCOMPtr<nsISupports> mChannelRef;
    177  nsHttpChannel* mChannel;
    178  WellKnownChecker* mChecker;
    179  nsCString mWKResponse;
    180 
    181  bool mRanOnce;
    182  bool mStatusOK;  // HTTP Status 200
    183  // These two values could be accessed on sts thread.
    184  Atomic<bool> mAuthOK;     // confirmed no TLS failure
    185  Atomic<bool> mVersionOK;  // connection h2
    186 };
    187 
    188 class AltSvcCache {
    189 public:
    190  AltSvcCache() = default;
    191  virtual ~AltSvcCache() = default;
    192  void UpdateAltServiceMapping(
    193      AltSvcMapping* map, nsProxyInfo* pi, nsIInterfaceRequestor*,
    194      uint32_t caps,
    195      const OriginAttributes& originAttributes);  // main thread
    196  void UpdateAltServiceMappingWithoutValidation(
    197      AltSvcMapping* map, nsProxyInfo* pi, nsIInterfaceRequestor*,
    198      uint32_t caps,
    199      const OriginAttributes& originAttributes);  // main thread
    200  already_AddRefed<AltSvcMapping> GetAltServiceMapping(
    201      const nsACString& scheme, const nsACString& host, int32_t port,
    202      bool privateBrowsing, const OriginAttributes& originAttributes,
    203      bool aHttp2Allowed, bool aHttp3Allowed);
    204  void ClearAltServiceMappings();
    205  void ClearHostMapping(const nsACString& host, int32_t port,
    206                        const OriginAttributes& originAttributes);
    207  void ClearHostMapping(nsHttpConnectionInfo* ci);
    208  nsIDataStorage* GetStoragePtr() { return mStorage.get(); }
    209  int32_t StorageEpoch() { return mStorageEpoch; }
    210  nsresult GetAltSvcCacheKeys(nsTArray<nsCString>& value);
    211 
    212 private:
    213  void EnsureStorageInited();
    214  already_AddRefed<AltSvcMapping> LookupMapping(const nsCString& key,
    215                                                bool privateBrowsing);
    216  nsCOMPtr<nsIDataStorage> mStorage;
    217  int32_t mStorageEpoch{0};
    218 };
    219 
    220 // This class is used to write the validated result to AltSvcMapping when the
    221 // AltSvcTransaction is closed and destroyed.
    222 class AltSvcMappingValidator final {
    223 public:
    224  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AltSvcMappingValidator)
    225 
    226  explicit AltSvcMappingValidator(AltSvcMapping* aMap);
    227 
    228  void OnTransactionDestroy(bool aValidateResult);
    229 
    230  void OnTransactionClose(bool aValidateResult);
    231 
    232 protected:
    233  virtual ~AltSvcMappingValidator() = default;
    234 
    235  RefPtr<AltSvcMapping> mMapping;
    236 };
    237 
    238 // This is the asynchronous null transaction used to validate
    239 // an alt-svc advertisement only for https://
    240 // When http over socket process is enabled, this class should live only in
    241 // socket process.
    242 template <class Validator>
    243 class AltSvcTransaction final : public SpeculativeTransaction {
    244 public:
    245  AltSvcTransaction(nsHttpConnectionInfo* ci, nsIInterfaceRequestor* callbacks,
    246                    uint32_t caps, Validator* aValidator, bool aIsHttp3);
    247 
    248  ~AltSvcTransaction() override;
    249 
    250  // AltSvcTransaction is used to validate the alt-svc record, so we don't want
    251  // to fetch HTTPS RR for this.
    252  virtual nsresult FetchHTTPSRR() override { return NS_ERROR_NOT_IMPLEMENTED; }
    253 
    254 private:
    255  // check on alternate route.
    256  // also evaluate 'reasonable assurances' for opportunistic security
    257  bool MaybeValidate(nsresult reason);
    258 
    259 public:
    260  void Close(nsresult reason) override;
    261  nsresult ReadSegments(nsAHttpSegmentReader* reader, uint32_t count,
    262                        uint32_t* countRead) override;
    263 
    264 private:
    265  RefPtr<Validator> mValidator;
    266  uint32_t mIsHttp3 : 1;
    267  uint32_t mRunning : 1;
    268  uint32_t mTriedToValidate : 1;
    269  uint32_t mTriedToWrite : 1;
    270  uint32_t mValidatedResult : 1;
    271 };
    272 
    273 }  // namespace net
    274 }  // namespace mozilla
    275 
    276 #endif  // include guard