michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef _NSNSSIOLAYER_H michael@0: #define _NSNSSIOLAYER_H michael@0: michael@0: #include "TransportSecurityInfo.h" michael@0: #include "nsISSLSocketControl.h" michael@0: #include "nsIClientAuthDialogs.h" michael@0: #include "nsIProxyInfo.h" michael@0: #include "nsNSSCertificate.h" michael@0: #include "nsDataHashtable.h" michael@0: #include "nsTHashtable.h" michael@0: #include "mozilla/TimeStamp.h" michael@0: #include "sslt.h" michael@0: michael@0: namespace mozilla { michael@0: namespace psm { michael@0: class SharedSSLState; michael@0: } michael@0: } michael@0: michael@0: class nsIObserver; michael@0: michael@0: class nsNSSSocketInfo : public mozilla::psm::TransportSecurityInfo, michael@0: public nsISSLSocketControl, michael@0: public nsIClientAuthUserDecision michael@0: { michael@0: public: michael@0: nsNSSSocketInfo(mozilla::psm::SharedSSLState& aState, uint32_t providerFlags); michael@0: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: NS_DECL_NSISSLSOCKETCONTROL michael@0: NS_DECL_NSICLIENTAUTHUSERDECISION michael@0: michael@0: void SetForSTARTTLS(bool aForSTARTTLS); michael@0: bool GetForSTARTTLS(); michael@0: michael@0: nsresult GetFileDescPtr(PRFileDesc** aFilePtr); michael@0: nsresult SetFileDescPtr(PRFileDesc* aFilePtr); michael@0: michael@0: bool IsHandshakePending() const { return mHandshakePending; } michael@0: void SetHandshakeNotPending() { mHandshakePending = false; } michael@0: michael@0: void GetPreviousCert(nsIX509Cert** _result); michael@0: michael@0: void SetTLSVersionRange(SSLVersionRange range) { mTLSVersionRange = range; } michael@0: SSLVersionRange GetTLSVersionRange() const { return mTLSVersionRange; }; michael@0: michael@0: PRStatus CloseSocketAndDestroy( michael@0: const nsNSSShutDownPreventionLock& proofOfLock); michael@0: michael@0: void SetNegotiatedNPN(const char* value, uint32_t length); michael@0: michael@0: void SetHandshakeCompleted(); michael@0: void NoteTimeUntilReady(); michael@0: michael@0: michael@0: void SetFalseStartCallbackCalled() { mFalseStartCallbackCalled = true; } michael@0: void SetFalseStarted() { mFalseStarted = true; } michael@0: michael@0: // Note that this is only valid *during* a handshake; at the end of the handshake, michael@0: // it gets reset back to false. michael@0: void SetFullHandshake() { mIsFullHandshake = true; } michael@0: bool IsFullHandshake() const { return mIsFullHandshake; } michael@0: michael@0: bool GetJoined() { return mJoined; } michael@0: void SetSentClientCert() { mSentClientCert = true; } michael@0: michael@0: uint32_t GetProviderFlags() const { return mProviderFlags; } michael@0: michael@0: mozilla::psm::SharedSSLState& SharedState(); michael@0: michael@0: // XXX: These are only used on for diagnostic purposes michael@0: enum CertVerificationState { michael@0: before_cert_verification, michael@0: waiting_for_cert_verification, michael@0: after_cert_verification michael@0: }; michael@0: void SetCertVerificationWaiting(); michael@0: // Use errorCode == 0 to indicate success; in that case, errorMessageType is michael@0: // ignored. michael@0: void SetCertVerificationResult(PRErrorCode errorCode, michael@0: ::mozilla::psm::SSLErrorMessageType errorMessageType); michael@0: michael@0: // for logging only michael@0: PRBool IsWaitingForCertVerification() const michael@0: { michael@0: return mCertVerificationState == waiting_for_cert_verification; michael@0: } michael@0: void AddPlaintextBytesRead(uint64_t val) { mPlaintextBytesRead += val; } michael@0: michael@0: bool IsPreliminaryHandshakeDone() const { return mPreliminaryHandshakeDone; } michael@0: void SetPreliminaryHandshakeDone() { mPreliminaryHandshakeDone = true; } michael@0: michael@0: void SetKEAUsed(uint16_t kea) { mKEAUsed = kea; } michael@0: inline int16_t GetKEAExpected() // infallible in nsISSLSocketControl michael@0: { michael@0: int16_t result; michael@0: mozilla::DebugOnly rv = GetKEAExpected(&result); michael@0: MOZ_ASSERT(NS_SUCCEEDED(rv)); michael@0: return result; michael@0: } michael@0: michael@0: void SetSSLVersionUsed(int16_t version) michael@0: { michael@0: mSSLVersionUsed = version; michael@0: } michael@0: michael@0: private: michael@0: PRFileDesc* mFd; michael@0: michael@0: CertVerificationState mCertVerificationState; michael@0: michael@0: mozilla::psm::SharedSSLState& mSharedState; michael@0: bool mForSTARTTLS; michael@0: SSLVersionRange mTLSVersionRange; michael@0: bool mHandshakePending; michael@0: bool mRememberClientAuthCertificate; michael@0: bool mPreliminaryHandshakeDone; // after false start items are complete michael@0: michael@0: nsresult ActivateSSL(); michael@0: michael@0: nsCString mNegotiatedNPN; michael@0: bool mNPNCompleted; michael@0: bool mFalseStartCallbackCalled; michael@0: bool mFalseStarted; michael@0: bool mIsFullHandshake; michael@0: bool mHandshakeCompleted; michael@0: bool mJoined; michael@0: bool mSentClientCert; michael@0: bool mNotedTimeUntilReady; michael@0: michael@0: // mKEA* are used in false start detetermination michael@0: // Values are from nsISSLSocketControl michael@0: int16_t mKEAUsed; michael@0: int16_t mKEAExpected; michael@0: int16_t mSSLVersionUsed; michael@0: michael@0: uint32_t mProviderFlags; michael@0: mozilla::TimeStamp mSocketCreationTimestamp; michael@0: uint64_t mPlaintextBytesRead; michael@0: }; michael@0: michael@0: class nsSSLIOLayerHelpers michael@0: { michael@0: public: michael@0: nsSSLIOLayerHelpers(); michael@0: ~nsSSLIOLayerHelpers(); michael@0: michael@0: nsresult Init(); michael@0: void Cleanup(); michael@0: michael@0: static bool nsSSLIOLayerInitialized; michael@0: static PRDescIdentity nsSSLIOLayerIdentity; michael@0: static PRDescIdentity nsSSLPlaintextLayerIdentity; michael@0: static PRIOMethods nsSSLIOLayerMethods; michael@0: static PRIOMethods nsSSLPlaintextLayerMethods; michael@0: michael@0: nsTHashtable* mRenegoUnrestrictedSites; michael@0: bool mTreatUnsafeNegotiationAsBroken; michael@0: int32_t mWarnLevelMissingRFC5746; michael@0: michael@0: void setTreatUnsafeNegotiationAsBroken(bool broken); michael@0: bool treatUnsafeNegotiationAsBroken(); michael@0: void setWarnLevelMissingRFC5746(int32_t level); michael@0: int32_t getWarnLevelMissingRFC5746(); michael@0: michael@0: private: michael@0: struct IntoleranceEntry michael@0: { michael@0: uint16_t tolerant; michael@0: uint16_t intolerant; michael@0: michael@0: void AssertInvariant() const michael@0: { michael@0: MOZ_ASSERT(intolerant == 0 || tolerant < intolerant); michael@0: } michael@0: }; michael@0: nsDataHashtable mTLSIntoleranceInfo; michael@0: public: michael@0: void rememberTolerantAtVersion(const nsACString& hostname, int16_t port, michael@0: uint16_t tolerant); michael@0: bool rememberIntolerantAtVersion(const nsACString& hostname, int16_t port, michael@0: uint16_t intolerant, uint16_t minVersion); michael@0: void adjustForTLSIntolerance(const nsACString& hostname, int16_t port, michael@0: /*in/out*/ SSLVersionRange& range); michael@0: michael@0: void setRenegoUnrestrictedSites(const nsCString& str); michael@0: bool isRenegoUnrestrictedSite(const nsCString& str); michael@0: void clearStoredData(); michael@0: michael@0: bool mFalseStartRequireNPN; michael@0: bool mFalseStartRequireForwardSecrecy; michael@0: private: michael@0: mozilla::Mutex mutex; michael@0: nsCOMPtr mPrefObserver; michael@0: }; michael@0: michael@0: nsresult nsSSLIOLayerNewSocket(int32_t family, michael@0: const char* host, michael@0: int32_t port, michael@0: nsIProxyInfo *proxy, michael@0: PRFileDesc** fd, michael@0: nsISupports** securityInfo, michael@0: bool forSTARTTLS, michael@0: uint32_t flags); michael@0: michael@0: nsresult nsSSLIOLayerAddToSocket(int32_t family, michael@0: const char* host, michael@0: int32_t port, michael@0: nsIProxyInfo *proxy, michael@0: PRFileDesc* fd, michael@0: nsISupports** securityInfo, michael@0: bool forSTARTTLS, michael@0: uint32_t flags); michael@0: michael@0: nsresult nsSSLIOLayerFreeTLSIntolerantSites(); michael@0: nsresult displayUnknownCertErrorAlert(nsNSSSocketInfo* infoObject, int error); michael@0: michael@0: #endif /* _NSNSSIOLAYER_H */