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