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 TransportSecurityInfo_h
8 #define TransportSecurityInfo_h
9 
10 #include "CertVerifier.h"  // For CertificateTransparencyInfo, EVStatus
11 #include "ScopedNSSTypes.h"
12 #include "certt.h"
13 #include "mozilla/Assertions.h"
14 #include "mozilla/BasePrincipal.h"
15 #include "mozilla/Mutex.h"
16 #include "mozilla/RefPtr.h"
17 #include "mozilla/ipc/TransportSecurityInfoUtils.h"
18 #include "mozpkix/pkixtypes.h"
19 #include "nsTHashMap.h"
20 #include "nsIClassInfo.h"
21 #include "nsIObjectInputStream.h"
22 #include "nsIInterfaceRequestor.h"
23 #include "nsITransportSecurityInfo.h"
24 #include "nsNSSCertificate.h"
25 #include "nsString.h"
26 
27 namespace mozilla {
28 namespace psm {
29 
30 class TransportSecurityInfo : public nsITransportSecurityInfo,
31                               public nsIInterfaceRequestor,
32                               public nsISerializable,
33                               public nsIClassInfo {
34  protected:
35   virtual ~TransportSecurityInfo() = default;
36 
37  public:
38   TransportSecurityInfo();
39 
40   NS_DECL_THREADSAFE_ISUPPORTS
41   NS_DECL_NSITRANSPORTSECURITYINFO
42   NS_DECL_NSIINTERFACEREQUESTOR
43   NS_DECL_NSISERIALIZABLE
44   NS_DECL_NSICLASSINFO
45 
46   void SetPreliminaryHandshakeInfo(const SSLChannelInfo& channelInfo,
47                                    const SSLCipherSuiteInfo& cipherInfo);
48 
49   void SetSecurityState(uint32_t aState);
50 
GetErrorCode()51   inline int32_t GetErrorCode() {
52     int32_t result;
53     mozilla::DebugOnly<nsresult> rv = GetErrorCode(&result);
54     MOZ_ASSERT(NS_SUCCEEDED(rv));
55     return result;
56   }
57 
GetHostName()58   const nsACString& GetHostName() const {
59     MutexAutoLock lock(mMutex);
60     return mHostName;
61   }
62 
63   void SetHostName(const char* host);
64 
GetPort()65   int32_t GetPort() const { return mPort; }
66   void SetPort(int32_t aPort);
67 
GetOriginAttributes()68   const OriginAttributes& GetOriginAttributes() const {
69     MutexAutoLock lock(mMutex);
70     return mOriginAttributes;
71   }
GetOriginAttributes(MutexAutoLock & aProofOfLock)72   const OriginAttributes& GetOriginAttributes(
73       MutexAutoLock& aProofOfLock) const {
74     return mOriginAttributes;
75   }
76   void SetOriginAttributes(const OriginAttributes& aOriginAttributes);
77 
78   void SetCanceled(PRErrorCode errorCode);
79   bool IsCanceled();
80 
81   void SetStatusErrorBits(const nsCOMPtr<nsIX509Cert>& cert,
82                           uint32_t collected_errors);
83 
84   nsresult SetFailedCertChain(nsTArray<nsTArray<uint8_t>>&& certList);
85 
86   void SetServerCert(const nsCOMPtr<nsIX509Cert>& aServerCert,
87                      EVStatus aEVStatus);
88 
89   nsresult SetSucceededCertChain(nsTArray<nsTArray<uint8_t>>&& certList);
90 
HasServerCert()91   bool HasServerCert() {
92     MutexAutoLock lock(mMutex);
93     return mServerCert != nullptr;
94   }
95 
96   static uint16_t ConvertCertificateTransparencyInfoToStatus(
97       const mozilla::psm::CertificateTransparencyInfo& info);
98 
99   // Use errorCode == 0 to indicate success;
SetCertVerificationResult(PRErrorCode errorCode)100   virtual void SetCertVerificationResult(PRErrorCode errorCode){};
101 
SetCertificateTransparencyStatus(uint16_t aCertificateTransparencyStatus)102   void SetCertificateTransparencyStatus(
103       uint16_t aCertificateTransparencyStatus) {
104     MutexAutoLock lock(mMutex);
105     mCertificateTransparencyStatus = aCertificateTransparencyStatus;
106   }
107 
108   void SetResumed(bool aResumed);
109 
110   Atomic<bool> mIsDomainMismatch;
111   Atomic<bool> mIsNotValidAtThisTime;
112   Atomic<bool> mIsUntrusted;
113   Atomic<bool> mIsEV;
114 
115   Atomic<bool> mHasIsEVStatus;
116   Atomic<bool> mHaveCipherSuiteAndProtocol;
117 
118   /* mHaveCertErrrorBits is relied on to determine whether or not a SPDY
119      connection is eligible for joining in nsNSSSocketInfo::JoinConnection() */
120   Atomic<bool> mHaveCertErrorBits;
121 
122  private:
123   // True if SetCanceled has been called (or if this was deserialized with a
124   // non-zero mErrorCode, which can only be the case if SetCanceled was called
125   // on the original TransportSecurityInfo).
126   Atomic<bool> mCanceled;
127 
128  protected:
129   mutable ::mozilla::Mutex mMutex;
130 
131   uint16_t mCipherSuite;
132   uint16_t mProtocolVersion;
133   uint16_t mCertificateTransparencyStatus;
134   nsCString mKeaGroup;
135   nsCString mSignatureSchemeName;
136 
137   bool mIsAcceptedEch;
138   bool mIsDelegatedCredential;
139 
140   nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
141   nsTArray<RefPtr<nsIX509Cert>> mSucceededCertChain;
142   bool mNPNCompleted;
143   nsCString mNegotiatedNPN;
144   bool mResumed;
145   bool mIsBuiltCertChainRootBuiltInRoot;
146   nsCString mPeerId;
147 
148  private:
ReadBoolAndSetAtomicFieldHelper(nsIObjectInputStream * stream,Atomic<bool> & atomic)149   static nsresult ReadBoolAndSetAtomicFieldHelper(nsIObjectInputStream* stream,
150                                                   Atomic<bool>& atomic) {
151     bool tmpBool;
152     nsresult rv = stream->ReadBoolean(&tmpBool);
153     if (NS_FAILED(rv)) {
154       return rv;
155     }
156     atomic = tmpBool;
157     return rv;
158   }
159 
ReadUint32AndSetAtomicFieldHelper(nsIObjectInputStream * stream,Atomic<uint32_t> & atomic)160   static nsresult ReadUint32AndSetAtomicFieldHelper(
161       nsIObjectInputStream* stream, Atomic<uint32_t>& atomic) {
162     uint32_t tmpInt;
163     nsresult rv = stream->Read32(&tmpInt);
164     if (NS_FAILED(rv)) {
165       return rv;
166     }
167     atomic = tmpInt;
168     return rv;
169   }
170 
171   template <typename P>
ReadParamAtomicHelper(IPC::MessageReader * aReader,Atomic<P> & atomic)172   static bool ReadParamAtomicHelper(IPC::MessageReader* aReader,
173                                     Atomic<P>& atomic) {
174     P tmpStore;
175     bool result = ReadParam(aReader, &tmpStore);
176     if (result == false) {
177       return result;
178     }
179     atomic = tmpStore;
180     return result;
181   }
182 
183   Atomic<uint32_t> mSecurityState;
184 
185   Atomic<PRErrorCode> mErrorCode;
186 
187   Atomic<int32_t> mPort;
188   nsCString mHostName;
189   OriginAttributes mOriginAttributes;
190 
191   nsCOMPtr<nsIX509Cert> mServerCert;
192 
193   /* Peer cert chain for failed connections (for error reporting) */
194   nsTArray<RefPtr<nsIX509Cert>> mFailedCertChain;
195 
196   nsresult ReadSSLStatus(nsIObjectInputStream* aStream,
197                          MutexAutoLock& aProofOfLock);
198 
199   // This function is used to read the binary that are serialized
200   // by using nsIX509CertList
201   nsresult ReadCertList(nsIObjectInputStream* aStream,
202                         nsTArray<RefPtr<nsIX509Cert>>& aCertList,
203                         MutexAutoLock& aProofOfLock);
204   nsresult ReadCertificatesFromStream(nsIObjectInputStream* aStream,
205                                       uint32_t aSize,
206                                       nsTArray<RefPtr<nsIX509Cert>>& aCertList,
207                                       MutexAutoLock& aProofOfLock);
208 };
209 
210 class RememberCertErrorsTable {
211  private:
212   RememberCertErrorsTable();
213 
214   struct CertStateBits {
215     bool mIsDomainMismatch;
216     bool mIsNotValidAtThisTime;
217     bool mIsUntrusted;
218   };
219   nsTHashMap<nsCStringHashKey, CertStateBits> mErrorHosts;
220 
221  public:
222   void RememberCertHasError(TransportSecurityInfo* infoObject,
223                             SECStatus certVerificationResult);
224   void LookupCertErrorBits(TransportSecurityInfo* infoObject);
225 
Init()226   static void Init() { sInstance = new RememberCertErrorsTable(); }
227 
GetInstance()228   static RememberCertErrorsTable& GetInstance() {
229     MOZ_ASSERT(sInstance);
230     return *sInstance;
231   }
232 
Cleanup()233   static void Cleanup() {
234     delete sInstance;
235     sInstance = nullptr;
236   }
237 
238  private:
239   Mutex mMutex;
240 
241   static RememberCertErrorsTable* sInstance;
242 };
243 
244 }  // namespace psm
245 }  // namespace mozilla
246 
247 // 16786594-0296-4471-8096-8f84497ca428
248 #define TRANSPORTSECURITYINFO_CID                    \
249   {                                                  \
250     0x16786594, 0x0296, 0x4471, {                    \
251       0x80, 0x96, 0x8f, 0x84, 0x49, 0x7c, 0xa4, 0x28 \
252     }                                                \
253   }
254 
255 #endif  // TransportSecurityInfo_h
256