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 nsNSSIOLayer_h 8 #define nsNSSIOLayer_h 9 10 #include "TransportSecurityInfo.h" 11 #include "mozilla/TimeStamp.h" 12 #include "nsCOMPtr.h" 13 #include "nsDataHashtable.h" 14 #include "nsIClientAuthDialogs.h" 15 #include "nsIProxyInfo.h" 16 #include "nsISSLSocketControl.h" 17 #include "nsNSSCertificate.h" 18 #include "nsTHashtable.h" 19 #include "sslt.h" 20 21 namespace mozilla { 22 class NeckoOriginAttributes; 23 namespace psm { 24 class SharedSSLState; 25 } // namespace psm 26 } // namespace mozilla 27 28 using mozilla::NeckoOriginAttributes; 29 30 class nsIObserver; 31 32 class nsNSSSocketInfo final : public mozilla::psm::TransportSecurityInfo, 33 public nsISSLSocketControl, 34 public nsIClientAuthUserDecision 35 { 36 public: 37 nsNSSSocketInfo(mozilla::psm::SharedSSLState& aState, uint32_t providerFlags); 38 39 NS_DECL_ISUPPORTS_INHERITED 40 NS_DECL_NSISSLSOCKETCONTROL 41 NS_DECL_NSICLIENTAUTHUSERDECISION 42 43 void SetForSTARTTLS(bool aForSTARTTLS); 44 bool GetForSTARTTLS(); 45 46 nsresult GetFileDescPtr(PRFileDesc** aFilePtr); 47 nsresult SetFileDescPtr(PRFileDesc* aFilePtr); 48 IsHandshakePending()49 bool IsHandshakePending() const { return mHandshakePending; } SetHandshakeNotPending()50 void SetHandshakeNotPending() { mHandshakePending = false; } 51 SetTLSVersionRange(SSLVersionRange range)52 void SetTLSVersionRange(SSLVersionRange range) { mTLSVersionRange = range; } GetTLSVersionRange()53 SSLVersionRange GetTLSVersionRange() const { return mTLSVersionRange; }; 54 55 PRStatus CloseSocketAndDestroy( 56 const nsNSSShutDownPreventionLock& proofOfLock); 57 58 void SetNegotiatedNPN(const char* value, uint32_t length); 59 void SetEarlyDataAccepted(bool aAccepted); 60 61 void SetHandshakeCompleted(); 62 void NoteTimeUntilReady(); 63 64 SetFalseStartCallbackCalled()65 void SetFalseStartCallbackCalled() { mFalseStartCallbackCalled = true; } SetFalseStarted()66 void SetFalseStarted() { mFalseStarted = true; } 67 68 // Note that this is only valid *during* a handshake; at the end of the handshake, 69 // it gets reset back to false. SetFullHandshake()70 void SetFullHandshake() { mIsFullHandshake = true; } IsFullHandshake()71 bool IsFullHandshake() const { return mIsFullHandshake; } 72 GetJoined()73 bool GetJoined() { return mJoined; } SetSentClientCert()74 void SetSentClientCert() { mSentClientCert = true; } 75 GetProviderFlags()76 uint32_t GetProviderFlags() const { return mProviderFlags; } 77 78 mozilla::psm::SharedSSLState& SharedState(); 79 80 // XXX: These are only used on for diagnostic purposes 81 enum CertVerificationState { 82 before_cert_verification, 83 waiting_for_cert_verification, 84 after_cert_verification 85 }; 86 void SetCertVerificationWaiting(); 87 // Use errorCode == 0 to indicate success; in that case, errorMessageType is 88 // ignored. 89 void SetCertVerificationResult(PRErrorCode errorCode, 90 ::mozilla::psm::SSLErrorMessageType errorMessageType); 91 92 // for logging only IsWaitingForCertVerification()93 PRBool IsWaitingForCertVerification() const 94 { 95 return mCertVerificationState == waiting_for_cert_verification; 96 } AddPlaintextBytesRead(uint64_t val)97 void AddPlaintextBytesRead(uint64_t val) { mPlaintextBytesRead += val; } 98 IsPreliminaryHandshakeDone()99 bool IsPreliminaryHandshakeDone() const { return mPreliminaryHandshakeDone; } SetPreliminaryHandshakeDone()100 void SetPreliminaryHandshakeDone() { mPreliminaryHandshakeDone = true; } 101 SetKEAUsed(uint16_t kea)102 void SetKEAUsed(uint16_t kea) { mKEAUsed = kea; } 103 SetKEAKeyBits(uint32_t keaBits)104 void SetKEAKeyBits(uint32_t keaBits) { mKEAKeyBits = keaBits; } 105 SetBypassAuthentication(bool val)106 void SetBypassAuthentication(bool val) 107 { 108 if (!mHandshakeCompleted) { 109 mBypassAuthentication = val; 110 } 111 } 112 SetSSLVersionUsed(int16_t version)113 void SetSSLVersionUsed(int16_t version) 114 { 115 mSSLVersionUsed = version; 116 } 117 SetMACAlgorithmUsed(int16_t mac)118 void SetMACAlgorithmUsed(int16_t mac) { mMACAlgorithmUsed = mac; } 119 120 protected: 121 virtual ~nsNSSSocketInfo(); 122 123 private: 124 PRFileDesc* mFd; 125 126 CertVerificationState mCertVerificationState; 127 128 mozilla::psm::SharedSSLState& mSharedState; 129 bool mForSTARTTLS; 130 SSLVersionRange mTLSVersionRange; 131 bool mHandshakePending; 132 bool mRememberClientAuthCertificate; 133 bool mPreliminaryHandshakeDone; // after false start items are complete 134 135 nsresult ActivateSSL(); 136 137 nsCString mNegotiatedNPN; 138 bool mNPNCompleted; 139 bool mEarlyDataAccepted; 140 bool mFalseStartCallbackCalled; 141 bool mFalseStarted; 142 bool mIsFullHandshake; 143 bool mHandshakeCompleted; 144 bool mJoined; 145 bool mSentClientCert; 146 bool mNotedTimeUntilReady; 147 bool mFailedVerification; 148 149 // mKEA* are used in false start and http/2 detetermination 150 // Values are from nsISSLSocketControl 151 int16_t mKEAUsed; 152 uint32_t mKEAKeyBits; 153 int16_t mSSLVersionUsed; 154 int16_t mMACAlgorithmUsed; 155 bool mBypassAuthentication; 156 157 uint32_t mProviderFlags; 158 mozilla::TimeStamp mSocketCreationTimestamp; 159 uint64_t mPlaintextBytesRead; 160 161 nsCOMPtr<nsIX509Cert> mClientCert; 162 }; 163 164 enum StrongCipherStatus { 165 StrongCipherStatusUnknown, 166 StrongCiphersWorked, 167 StrongCiphersFailed 168 }; 169 170 class nsSSLIOLayerHelpers 171 { 172 public: 173 nsSSLIOLayerHelpers(); 174 ~nsSSLIOLayerHelpers(); 175 176 nsresult Init(); 177 void Cleanup(); 178 179 static bool nsSSLIOLayerInitialized; 180 static PRDescIdentity nsSSLIOLayerIdentity; 181 static PRDescIdentity nsSSLPlaintextLayerIdentity; 182 static PRIOMethods nsSSLIOLayerMethods; 183 static PRIOMethods nsSSLPlaintextLayerMethods; 184 185 bool mTreatUnsafeNegotiationAsBroken; 186 187 void setTreatUnsafeNegotiationAsBroken(bool broken); 188 bool treatUnsafeNegotiationAsBroken(); 189 190 private: 191 struct IntoleranceEntry 192 { 193 uint16_t tolerant; 194 uint16_t intolerant; 195 PRErrorCode intoleranceReason; 196 StrongCipherStatus strongCipherStatus; 197 AssertInvariantIntoleranceEntry198 void AssertInvariant() const 199 { 200 MOZ_ASSERT(intolerant == 0 || tolerant < intolerant); 201 } 202 }; 203 nsDataHashtable<nsCStringHashKey, IntoleranceEntry> mTLSIntoleranceInfo; 204 // Sites that require insecure fallback to TLS 1.0, set by the pref 205 // security.tls.insecure_fallback_hosts, which is a comma-delimited 206 // list of domain names. 207 nsTHashtable<nsCStringHashKey> mInsecureFallbackSites; 208 public: 209 void rememberTolerantAtVersion(const nsACString& hostname, int16_t port, 210 uint16_t tolerant); 211 bool fallbackLimitReached(const nsACString& hostname, uint16_t intolerant); 212 bool rememberIntolerantAtVersion(const nsACString& hostname, int16_t port, 213 uint16_t intolerant, uint16_t minVersion, 214 PRErrorCode intoleranceReason); 215 bool rememberStrongCiphersFailed(const nsACString& hostName, int16_t port, 216 PRErrorCode intoleranceReason); 217 void forgetIntolerance(const nsACString& hostname, int16_t port); 218 void adjustForTLSIntolerance(const nsACString& hostname, int16_t port, 219 /*in/out*/ SSLVersionRange& range, 220 /*out*/ StrongCipherStatus& strongCipherStatus); 221 PRErrorCode getIntoleranceReason(const nsACString& hostname, int16_t port); 222 223 void clearStoredData(); 224 void loadVersionFallbackLimit(); 225 void setInsecureFallbackSites(const nsCString& str); 226 void initInsecureFallbackSites(); 227 bool isPublic() const; 228 void addInsecureFallbackSite(const nsCString& hostname, bool temporary); 229 void removeInsecureFallbackSite(const nsACString& hostname, uint16_t port); 230 bool isInsecureFallbackSite(const nsACString& hostname); 231 232 bool mFalseStartRequireNPN; 233 bool mUnrestrictedRC4Fallback; 234 uint16_t mVersionFallbackLimit; 235 private: 236 mozilla::Mutex mutex; 237 nsCOMPtr<nsIObserver> mPrefObserver; 238 }; 239 240 nsresult nsSSLIOLayerNewSocket(int32_t family, 241 const char* host, 242 int32_t port, 243 nsIProxyInfo *proxy, 244 const NeckoOriginAttributes& originAttributes, 245 PRFileDesc** fd, 246 nsISupports** securityInfo, 247 bool forSTARTTLS, 248 uint32_t flags); 249 250 nsresult nsSSLIOLayerAddToSocket(int32_t family, 251 const char* host, 252 int32_t port, 253 nsIProxyInfo *proxy, 254 const NeckoOriginAttributes& originAttributes, 255 PRFileDesc* fd, 256 nsISupports** securityInfo, 257 bool forSTARTTLS, 258 uint32_t flags); 259 260 nsresult nsSSLIOLayerFreeTLSIntolerantSites(); 261 nsresult displayUnknownCertErrorAlert(nsNSSSocketInfo* infoObject, int error); 262 263 #endif // nsNSSIOLayer_h 264