tor-browser

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

NSSSocketControl.h (13484B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 *
      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 NSSSocketControl_h
      8 #define NSSSocketControl_h
      9 
     10 #include "CommonSocketControl.h"
     11 #include "TLSClientAuthCertSelection.h"
     12 #include "mozilla/Casting.h"
     13 #include "mozilla/Maybe.h"
     14 #include "nsNSSIOLayer.h"
     15 #include "nsThreadUtils.h"
     16 
     17 extern mozilla::LazyLogModule gPIPNSSLog;
     18 
     19 class SelectClientAuthCertificate;
     20 
     21 class NSSSocketControl final : public CommonSocketControl {
     22 public:
     23  NSSSocketControl(const nsCString& aHostName, int32_t aPort,
     24                   already_AddRefed<nsSSLIOLayerHelpers> aSSLIOLayerHelpers,
     25                   uint32_t providerFlags, uint32_t providerTlsFlags);
     26 
     27  NS_INLINE_DECL_REFCOUNTING_INHERITED(NSSSocketControl, CommonSocketControl);
     28 
     29  void SetForSTARTTLS(bool aForSTARTTLS);
     30  bool GetForSTARTTLS();
     31 
     32  nsresult GetFileDescPtr(PRFileDesc** aFilePtr);
     33  nsresult SetFileDescPtr(PRFileDesc* aFilePtr);
     34 
     35  bool IsHandshakePending() const {
     36    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
     37    return mHandshakePending;
     38  }
     39  void SetHandshakeNotPending() {
     40    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
     41    mHandshakePending = false;
     42  }
     43 
     44  void SetTLSVersionRange(SSLVersionRange range) {
     45    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
     46    mTLSVersionRange = range;
     47  }
     48  SSLVersionRange GetTLSVersionRange() const {
     49    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
     50    return mTLSVersionRange;
     51  };
     52 
     53  void RememberTLSTolerant() {
     54    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
     55    mSSLIOLayerHelpers->rememberTolerantAtVersion(
     56        GetHostName(), mozilla::AssertedCast<uint16_t>(GetPort()),
     57        mTLSVersionRange.max);
     58  }
     59 
     60  void RemoveInsecureTLSFallback() {
     61    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
     62    mSSLIOLayerHelpers->removeInsecureFallbackSite(
     63        GetHostName(), mozilla::AssertedCast<uint16_t>(GetPort()));
     64  }
     65 
     66  PRErrorCode GetTLSIntoleranceReason() {
     67    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
     68    return mSSLIOLayerHelpers->getIntoleranceReason(
     69        GetHostName(), mozilla::AssertedCast<uint16_t>(GetPort()));
     70  }
     71 
     72  void ForgetTLSIntolerance() {
     73    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
     74    mSSLIOLayerHelpers->forgetIntolerance(
     75        GetHostName(), mozilla::AssertedCast<uint16_t>(GetPort()));
     76  }
     77 
     78  bool RememberTLSIntolerant(PRErrorCode err) {
     79    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
     80    return mSSLIOLayerHelpers->rememberIntolerantAtVersion(
     81        GetHostName(), mozilla::AssertedCast<uint16_t>(GetPort()),
     82        mTLSVersionRange.min, mTLSVersionRange.max, err);
     83  }
     84 
     85  void AdjustForTLSIntolerance(SSLVersionRange& range) {
     86    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
     87    mSSLIOLayerHelpers->adjustForTLSIntolerance(
     88        GetHostName(), mozilla::AssertedCast<uint16_t>(GetPort()), range);
     89  }
     90 
     91  // From nsITLSSocketControl.
     92  NS_IMETHOD ProxyStartSSL(void) override;
     93  NS_IMETHOD StartTLS(void) override;
     94  NS_IMETHOD AsyncStartTLS(JSContext* aCx,
     95                           mozilla::dom::Promise** aPromise) override;
     96  NS_IMETHOD SetNPNList(nsTArray<nsCString>& aNPNList) override;
     97  NS_IMETHOD GetAlpnEarlySelection(nsACString& _retval) override;
     98  NS_IMETHOD GetEarlyDataAccepted(bool* aEarlyDataAccepted) override;
     99  NS_IMETHOD DriveHandshake(void) override;
    100  NS_IMETHOD GetKEAUsed(int16_t* aKEAUsed) override;
    101  NS_IMETHOD GetKEAKeyBits(uint32_t* aKEAKeyBits) override;
    102  NS_IMETHOD GetSSLVersionOffered(int16_t* aSSLVersionOffered) override;
    103  NS_IMETHOD GetMACAlgorithmUsed(int16_t* aMACAlgorithmUsed) override;
    104  bool GetDenyClientCert() override;
    105  void SetDenyClientCert(bool aDenyClientCert) override;
    106  NS_IMETHOD GetEsniTxt(nsACString& aEsniTxt) override;
    107  NS_IMETHOD SetEsniTxt(const nsACString& aEsniTxt) override;
    108  NS_IMETHOD GetEchConfig(nsACString& aEchConfig) override;
    109  NS_IMETHOD SetEchConfig(const nsACString& aEchConfig) override;
    110  NS_IMETHOD GetPeerId(nsACString& aResult) override;
    111  NS_IMETHOD GetRetryEchConfig(nsACString& aEchConfig) override;
    112  NS_IMETHOD DisableEarlyData(void) override;
    113  NS_IMETHOD SetHandshakeCallbackListener(
    114      nsITlsHandshakeCallbackListener* callback) override;
    115  NS_IMETHOD Claim() override;
    116  NS_IMETHOD SetBrowserId(uint64_t browserId) override;
    117  NS_IMETHOD GetBrowserId(uint64_t* browserId) override;
    118 
    119  PRStatus CloseSocketAndDestroy();
    120 
    121  void SetNegotiatedNPN(const char* value, uint32_t length);
    122  void SetEarlyDataAccepted(bool aAccepted);
    123 
    124  void SetHandshakeCompleted();
    125  bool IsHandshakeCompleted() const {
    126    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    127    return mHandshakeCompleted;
    128  }
    129  void NoteTimeUntilReady();
    130 
    131  void SetFalseStartCallbackCalled() {
    132    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    133    mFalseStartCallbackCalled = true;
    134  }
    135  void SetFalseStarted() {
    136    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    137    mFalseStarted = true;
    138  }
    139 
    140  // Note that this is only valid *during* a handshake; at the end of the
    141  // handshake, it gets reset back to false.
    142  void SetFullHandshake() {
    143    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    144    mIsFullHandshake = true;
    145  }
    146  bool IsFullHandshake() const {
    147    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    148    return mIsFullHandshake;
    149  }
    150 
    151  void UpdateEchExtensionStatus(EchExtensionStatus aEchExtensionStatus) {
    152    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    153    mEchExtensionStatus = std::max(aEchExtensionStatus, mEchExtensionStatus);
    154  }
    155  EchExtensionStatus GetEchExtensionStatus() const {
    156    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    157    return mEchExtensionStatus;
    158  }
    159 
    160  void WillSendMlkemShare() {
    161    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    162    mSentMlkemShare = true;
    163  }
    164 
    165  bool SentMlkemShare() {
    166    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    167    return mSentMlkemShare;
    168  }
    169 
    170  void SetHasTls13HandshakeSecrets() {
    171    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    172    mHasTls13HandshakeSecrets = true;
    173  }
    174 
    175  bool HasTls13HandshakeSecrets() {
    176    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    177    return mHasTls13HandshakeSecrets;
    178  }
    179 
    180  bool GetJoined() {
    181    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    182    return mJoined;
    183  }
    184 
    185  uint32_t GetProviderTlsFlags() const {
    186    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    187    return mProviderTlsFlags;
    188  }
    189 
    190  enum CertVerificationState {
    191    BeforeCertVerification,
    192    WaitingForCertVerification,
    193    AfterCertVerification
    194  };
    195 
    196  void SetCertVerificationWaiting();
    197 
    198  // Use errorCode == 0 to indicate success;
    199  void SetCertVerificationResult(PRErrorCode errorCode) override;
    200 
    201  void ClientAuthCertificateSelected(
    202      nsTArray<uint8_t>& certBytes,
    203      nsTArray<nsTArray<uint8_t>>& certChainBytes);
    204 
    205  bool IsWaitingForCertVerification() const {
    206    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    207    return mCertVerificationState == WaitingForCertVerification;
    208  }
    209 
    210  void AddPlaintextBytesRead(uint64_t val) {
    211    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    212    mPlaintextBytesRead += val;
    213  }
    214 
    215  bool IsPreliminaryHandshakeDone() const {
    216    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    217    return mPreliminaryHandshakeDone;
    218  }
    219  void SetPreliminaryHandshakeDone() {
    220    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    221    mPreliminaryHandshakeDone = true;
    222  }
    223 
    224  void SetKEAUsed(int16_t kea) {
    225    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    226    mKEAUsed = kea;
    227  }
    228 
    229  void SetKEAKeyBits(uint32_t keaBits) {
    230    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    231    mKEAKeyBits = keaBits;
    232  }
    233 
    234  void SetMACAlgorithmUsed(int16_t mac) {
    235    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    236    mMACAlgorithmUsed = mac;
    237  }
    238 
    239  void SetShortWritePending(int32_t amount, unsigned char data) {
    240    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    241    mIsShortWritePending = true;
    242    mShortWriteOriginalAmount = amount;
    243    mShortWritePendingByte = data;
    244  }
    245 
    246  bool IsShortWritePending() {
    247    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    248    return mIsShortWritePending;
    249  }
    250 
    251  unsigned char const* GetShortWritePendingByteRef() {
    252    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    253    return &mShortWritePendingByte;
    254  }
    255 
    256  int32_t ResetShortWritePending() {
    257    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    258    mIsShortWritePending = false;
    259    return mShortWriteOriginalAmount;
    260  }
    261 
    262 #ifdef DEBUG
    263  // These helpers assert that the caller does try to send the same data
    264  // as it was previously when we hit the short-write.  This is a measure
    265  // to make sure we communicate correctly to the consumer.
    266  void RememberShortWrittenBuffer(const unsigned char* data) {
    267    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    268    mShortWriteBufferCheck =
    269        mozilla::MakeUnique<char[]>(mShortWriteOriginalAmount);
    270    memcpy(mShortWriteBufferCheck.get(), data, mShortWriteOriginalAmount);
    271  }
    272  void CheckShortWrittenBuffer(const unsigned char* data, int32_t amount) {
    273    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    274    if (!mShortWriteBufferCheck) return;
    275    MOZ_ASSERT(amount >= mShortWriteOriginalAmount,
    276               "unexpected amount length after short write");
    277    MOZ_ASSERT(
    278        !memcmp(mShortWriteBufferCheck.get(), data, mShortWriteOriginalAmount),
    279        "unexpected buffer content after short write");
    280    mShortWriteBufferCheck = nullptr;
    281  }
    282 #endif
    283 
    284  nsresult SetResumptionTokenFromExternalCache(PRFileDesc* fd);
    285 
    286  void SetPreliminaryHandshakeInfo(const SSLChannelInfo& channelInfo,
    287                                   const SSLCipherSuiteInfo& cipherInfo);
    288 
    289  // Cancels an unclaimed (i.e. speculative) connection.
    290  bool CancelIfNotClaimed() {
    291    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    292    if (!mClaimed) {
    293      SetCanceled(PR_CONNECT_RESET_ERROR);
    294    }
    295    return !mClaimed;
    296  }
    297 
    298  void SetClientAuthCertificateRequest(
    299      mozilla::UniqueCERTCertificate&& serverCertificate,
    300      nsTArray<nsTArray<uint8_t>>&& caNames) {
    301    COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
    302    mClientAuthCertificateRequest.emplace(ClientAuthCertificateRequest{
    303        std::move(serverCertificate), std::move(caNames)});
    304  }
    305 
    306  void MaybeSelectClientAuthCertificate();
    307 
    308 private:
    309  ~NSSSocketControl() = default;
    310 
    311  PRFileDesc* mFd;
    312 
    313  CertVerificationState mCertVerificationState;
    314 
    315  RefPtr<nsSSLIOLayerHelpers> mSSLIOLayerHelpers;
    316  bool mForSTARTTLS;
    317  SSLVersionRange mTLSVersionRange;
    318  bool mHandshakePending;
    319  bool mPreliminaryHandshakeDone;  // after false start items are complete
    320 
    321  nsresult ActivateSSL();
    322 
    323  nsCString mEsniTxt;
    324  nsCString mEchConfig;
    325  bool mEarlyDataAccepted;
    326  bool mDenyClientCert;
    327  bool mFalseStartCallbackCalled;
    328  bool mFalseStarted;
    329  bool mIsFullHandshake;
    330  bool mNotedTimeUntilReady;
    331  EchExtensionStatus mEchExtensionStatus;  // Currently only used for telemetry.
    332  bool mSentMlkemShare;
    333  bool mHasTls13HandshakeSecrets;
    334 
    335  // True when SSL layer has indicated an "SSL short write", i.e. need
    336  // to call on send one or more times to push all pending data to write.
    337  bool mIsShortWritePending;
    338 
    339  // These are only valid if mIsShortWritePending is true.
    340  //
    341  // Value of the last byte pending from the SSL short write that needs
    342  // to be passed to subsequent calls to send to perform the flush.
    343  unsigned char mShortWritePendingByte;
    344 
    345  // Original amount of data the upper layer has requested to write to
    346  // return after the successful flush.
    347  int32_t mShortWriteOriginalAmount;
    348 
    349 #ifdef DEBUG
    350  mozilla::UniquePtr<char[]> mShortWriteBufferCheck;
    351 #endif
    352 
    353  // mKEA* are used in false start and http/2 detetermination
    354  // Values are from nsITLSSocketControl
    355  int16_t mKEAUsed;
    356  uint32_t mKEAKeyBits;
    357  int16_t mMACAlgorithmUsed;
    358 
    359  uint32_t mProviderTlsFlags;
    360  mozilla::TimeStamp mSocketCreationTimestamp;
    361  uint64_t mPlaintextBytesRead;
    362 
    363  // Whether or not this connection has been claimed. If it has not been
    364  // claimed, this is a speculative connection.
    365  bool mClaimed;
    366  // When a server requests a client authentication certificate, the server's
    367  // certificate may not have been verified yet. In order to prevent any
    368  // certificate dialogs from appearing before verification succeeds (and to
    369  // prevent them altogether if it fails), stash the information relevant to
    370  // selecting a certificate until it has succeeded.
    371  struct ClientAuthCertificateRequest {
    372    mozilla::UniqueCERTCertificate mServerCertificate;
    373    nsTArray<nsTArray<uint8_t>> mCANames;
    374  };
    375  mozilla::Maybe<ClientAuthCertificateRequest> mClientAuthCertificateRequest;
    376 
    377  // Regarding the client certificate message in the TLS handshake, RFC 5246
    378  // (TLS 1.2) says:
    379  //   If the certificate_authorities list in the certificate request
    380  //   message was non-empty, one of the certificates in the certificate
    381  //   chain SHOULD be issued by one of the listed CAs.
    382  // (RFC 8446 (TLS 1.3) has a similar provision)
    383  // These certificates may be known to gecko but not NSS (e.g. enterprise
    384  // intermediates). In order to make these certificates discoverable to NSS
    385  // so it can include them in the message, we cache them here as temporary
    386  // certificates.
    387  mozilla::UniqueCERTCertList mClientCertChain;
    388 
    389  nsCOMPtr<nsITlsHandshakeCallbackListener> mTlsHandshakeCallback;
    390 
    391  uint64_t mBrowserId;
    392 };
    393 
    394 #endif  // NSSSocketControl_h