Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/manager/ssl/nsNSSIOLayer.h
Line
Count
Source (jump to first uncovered line)
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/Assertions.h"
12
#include "mozilla/TimeStamp.h"
13
#include "mozilla/UniquePtr.h"
14
#include "nsCOMPtr.h"
15
#include "nsDataHashtable.h"
16
#include "nsIClientAuthDialogs.h"
17
#include "nsIProxyInfo.h"
18
#include "nsISSLSocketControl.h"
19
#include "nsNSSCertificate.h"
20
#include "nsTHashtable.h"
21
#include "sslt.h"
22
23
namespace mozilla {
24
class OriginAttributes;
25
namespace psm {
26
class SharedSSLState;
27
} // namespace psm
28
} // namespace mozilla
29
30
using mozilla::OriginAttributes;
31
32
class nsIObserver;
33
34
class nsNSSSocketInfo final : public mozilla::psm::TransportSecurityInfo,
35
                              public nsISSLSocketControl,
36
                              public nsIClientAuthUserDecision
37
{
38
public:
39
  nsNSSSocketInfo(mozilla::psm::SharedSSLState& aState, uint32_t providerFlags,
40
                  uint32_t providerTlsFlags);
41
42
  NS_DECL_ISUPPORTS_INHERITED
43
  NS_DECL_NSISSLSOCKETCONTROL
44
  NS_DECL_NSICLIENTAUTHUSERDECISION
45
46
  void SetForSTARTTLS(bool aForSTARTTLS);
47
  bool GetForSTARTTLS();
48
49
  nsresult GetFileDescPtr(PRFileDesc** aFilePtr);
50
  nsresult SetFileDescPtr(PRFileDesc* aFilePtr);
51
52
0
  bool IsHandshakePending() const { return mHandshakePending; }
53
0
  void SetHandshakeNotPending() { mHandshakePending = false; }
54
55
0
  void SetTLSVersionRange(SSLVersionRange range) { mTLSVersionRange = range; }
56
0
  SSLVersionRange GetTLSVersionRange() const { return mTLSVersionRange; };
57
58
  PRStatus CloseSocketAndDestroy();
59
60
  void SetNegotiatedNPN(const char* value, uint32_t length);
61
  void SetEarlyDataAccepted(bool aAccepted);
62
63
  void SetHandshakeCompleted();
64
0
  bool IsHandshakeCompleted() const { return mHandshakeCompleted; }
65
  void NoteTimeUntilReady();
66
67
68
0
  void SetFalseStartCallbackCalled() { mFalseStartCallbackCalled = true; }
69
0
  void SetFalseStarted() { mFalseStarted = true; }
70
71
  // Note that this is only valid *during* a handshake; at the end of the handshake,
72
  // it gets reset back to false.
73
0
  void SetFullHandshake() { mIsFullHandshake = true; }
74
0
  bool IsFullHandshake() const { return mIsFullHandshake; }
75
76
0
  bool GetJoined() { return mJoined; }
77
0
  bool GetDenyClientCert() { return mDenyClientCert; }
78
0
  void SetSentClientCert() { mSentClientCert = true; }
79
80
0
  uint32_t GetProviderFlags() const { return mProviderFlags; }
81
0
  uint32_t GetProviderTlsFlags() const { return mProviderTlsFlags; }
82
83
  mozilla::psm::SharedSSLState& SharedState();
84
85
  // XXX: These are only used on for diagnostic purposes
86
  enum CertVerificationState {
87
    before_cert_verification,
88
    waiting_for_cert_verification,
89
    after_cert_verification
90
  };
91
  void SetCertVerificationWaiting();
92
  // Use errorCode == 0 to indicate success;
93
  void SetCertVerificationResult(PRErrorCode errorCode);
94
95
  // for logging only
96
  PRBool IsWaitingForCertVerification() const
97
0
  {
98
0
    return mCertVerificationState == waiting_for_cert_verification;
99
0
  }
100
0
  void AddPlaintextBytesRead(uint64_t val) { mPlaintextBytesRead += val; }
101
102
0
  bool IsPreliminaryHandshakeDone() const { return mPreliminaryHandshakeDone; }
103
0
  void SetPreliminaryHandshakeDone() { mPreliminaryHandshakeDone = true; }
104
105
0
  void SetKEAUsed(uint16_t kea) { mKEAUsed = kea; }
106
107
0
  void SetKEAKeyBits(uint32_t keaBits) { mKEAKeyBits = keaBits; }
108
109
  void SetBypassAuthentication(bool val)
110
0
  {
111
0
    if (!mHandshakeCompleted) {
112
0
      mBypassAuthentication = val;
113
0
    }
114
0
  }
115
116
  void SetSSLVersionUsed(int16_t version)
117
0
  {
118
0
    mSSLVersionUsed = version;
119
0
  }
120
121
0
  void SetMACAlgorithmUsed(int16_t mac) { mMACAlgorithmUsed = mac; }
122
123
  void SetShortWritePending(int32_t amount, unsigned char data)
124
0
  {
125
0
    mIsShortWritePending = true;
126
0
    mShortWriteOriginalAmount = amount;
127
0
    mShortWritePendingByte = data;
128
0
  }
129
130
  bool IsShortWritePending()
131
0
  {
132
0
    return mIsShortWritePending;
133
0
  }
134
135
  unsigned char const* GetShortWritePendingByteRef()
136
0
  {
137
0
    return &mShortWritePendingByte;
138
0
  }
139
140
  int32_t ResetShortWritePending()
141
0
  {
142
0
    mIsShortWritePending = false;
143
0
    return mShortWriteOriginalAmount;
144
0
  }
145
146
#ifdef DEBUG
147
  // These helpers assert that the caller does try to send the same data
148
  // as it was previously when we hit the short-write.  This is a measure
149
  // to make sure we communicate correctly to the consumer.
150
  void RememberShortWrittenBuffer(const unsigned char *data)
151
  {
152
    mShortWriteBufferCheck = mozilla::MakeUnique<char[]>(mShortWriteOriginalAmount);
153
    memcpy(mShortWriteBufferCheck.get(), data, mShortWriteOriginalAmount);
154
  }
155
  void CheckShortWrittenBuffer(const unsigned char *data, int32_t amount)
156
  {
157
    if (!mShortWriteBufferCheck) return;
158
    MOZ_ASSERT(amount >= mShortWriteOriginalAmount,
159
               "unexpected amount length after short write");
160
    MOZ_ASSERT(!memcmp(mShortWriteBufferCheck.get(), data, mShortWriteOriginalAmount),
161
               "unexpected buffer content after short write");
162
    mShortWriteBufferCheck = nullptr;
163
  }
164
#endif
165
166
  void SetSharedOwningReference(mozilla::psm::SharedSSLState* ref);
167
168
protected:
169
  virtual ~nsNSSSocketInfo();
170
171
private:
172
  PRFileDesc* mFd;
173
174
  CertVerificationState mCertVerificationState;
175
176
  mozilla::psm::SharedSSLState& mSharedState;
177
  bool mForSTARTTLS;
178
  SSLVersionRange mTLSVersionRange;
179
  bool mHandshakePending;
180
  bool mRememberClientAuthCertificate;
181
  bool mPreliminaryHandshakeDone; // after false start items are complete
182
183
  nsresult ActivateSSL();
184
185
  nsCString mNegotiatedNPN;
186
  nsCString mEsniTxt;
187
  bool      mNPNCompleted;
188
  bool      mEarlyDataAccepted;
189
  bool      mDenyClientCert;
190
  bool      mFalseStartCallbackCalled;
191
  bool      mFalseStarted;
192
  bool      mIsFullHandshake;
193
  bool      mHandshakeCompleted;
194
  bool      mJoined;
195
  bool      mSentClientCert;
196
  bool      mNotedTimeUntilReady;
197
  bool      mFailedVerification;
198
199
  // True when SSL layer has indicated an "SSL short write", i.e. need
200
  // to call on send one or more times to push all pending data to write.
201
  bool      mIsShortWritePending;
202
203
  // These are only valid if mIsShortWritePending is true.
204
  //
205
  // Value of the last byte pending from the SSL short write that needs
206
  // to be passed to subsequent calls to send to perform the flush.
207
  unsigned char mShortWritePendingByte;
208
209
  // Original amount of data the upper layer has requested to write to
210
  // return after the successful flush.
211
  int32_t   mShortWriteOriginalAmount;
212
213
#ifdef DEBUG
214
  mozilla::UniquePtr<char[]> mShortWriteBufferCheck;
215
#endif
216
217
  // mKEA* are used in false start and http/2 detetermination
218
  // Values are from nsISSLSocketControl
219
  int16_t mKEAUsed;
220
  uint32_t mKEAKeyBits;
221
  int16_t mSSLVersionUsed;
222
  int16_t mMACAlgorithmUsed;
223
  bool    mBypassAuthentication;
224
225
  uint32_t mProviderFlags;
226
  uint32_t mProviderTlsFlags;
227
  mozilla::TimeStamp mSocketCreationTimestamp;
228
  uint64_t mPlaintextBytesRead;
229
230
  nsCOMPtr<nsIX509Cert> mClientCert;
231
232
  // if non-null this is a reference to the mSharedState (which is
233
  // not an owning reference). If this is used, the info has a private
234
  // state that does not share things like intolerance lists with the
235
  // rest of the session. This is normally used when you have per
236
  // socket tls flags overriding session wide defaults.
237
  RefPtr<mozilla::psm::SharedSSLState> mOwningSharedRef;
238
};
239
240
class nsSSLIOLayerHelpers
241
{
242
public:
243
  explicit nsSSLIOLayerHelpers(uint32_t aTlsFlags = 0);
244
  ~nsSSLIOLayerHelpers();
245
246
  nsresult Init();
247
  void Cleanup();
248
249
  static bool nsSSLIOLayerInitialized;
250
  static PRDescIdentity nsSSLIOLayerIdentity;
251
  static PRDescIdentity nsSSLPlaintextLayerIdentity;
252
  static PRIOMethods nsSSLIOLayerMethods;
253
  static PRIOMethods nsSSLPlaintextLayerMethods;
254
255
  bool mTreatUnsafeNegotiationAsBroken;
256
257
  void setTreatUnsafeNegotiationAsBroken(bool broken);
258
  bool treatUnsafeNegotiationAsBroken();
259
260
private:
261
  struct IntoleranceEntry
262
  {
263
    uint16_t tolerant;
264
    uint16_t intolerant;
265
    PRErrorCode intoleranceReason;
266
267
    void AssertInvariant() const
268
0
    {
269
0
      MOZ_ASSERT(intolerant == 0 || tolerant < intolerant);
270
0
    }
271
  };
272
  nsDataHashtable<nsCStringHashKey, IntoleranceEntry> mTLSIntoleranceInfo;
273
  // Sites that require insecure fallback to TLS 1.0, set by the pref
274
  // security.tls.insecure_fallback_hosts, which is a comma-delimited
275
  // list of domain names.
276
  nsTHashtable<nsCStringHashKey> mInsecureFallbackSites;
277
public:
278
  void rememberTolerantAtVersion(const nsACString& hostname, int16_t port,
279
                                 uint16_t tolerant);
280
  bool fallbackLimitReached(const nsACString& hostname, uint16_t intolerant);
281
  bool rememberIntolerantAtVersion(const nsACString& hostname, int16_t port,
282
                                   uint16_t intolerant, uint16_t minVersion,
283
                                   PRErrorCode intoleranceReason);
284
  void forgetIntolerance(const nsACString& hostname, int16_t port);
285
  void adjustForTLSIntolerance(const nsACString& hostname, int16_t port,
286
                               /*in/out*/ SSLVersionRange& range);
287
  PRErrorCode getIntoleranceReason(const nsACString& hostname, int16_t port);
288
289
  void clearStoredData();
290
  void loadVersionFallbackLimit();
291
  void setInsecureFallbackSites(const nsCString& str);
292
  void initInsecureFallbackSites();
293
  bool isPublic() const;
294
  void removeInsecureFallbackSite(const nsACString& hostname, uint16_t port);
295
  bool isInsecureFallbackSite(const nsACString& hostname);
296
297
  uint16_t mVersionFallbackLimit;
298
private:
299
  mozilla::Mutex mutex;
300
  nsCOMPtr<nsIObserver> mPrefObserver;
301
  uint32_t mTlsFlags;
302
};
303
304
nsresult nsSSLIOLayerNewSocket(int32_t family,
305
                               const char* host,
306
                               int32_t port,
307
                               nsIProxyInfo *proxy,
308
                               const OriginAttributes& originAttributes,
309
                               PRFileDesc** fd,
310
                               nsISupports** securityInfo,
311
                               bool forSTARTTLS,
312
                               uint32_t flags,
313
                               uint32_t tlsFlags);
314
315
nsresult nsSSLIOLayerAddToSocket(int32_t family,
316
                                 const char* host,
317
                                 int32_t port,
318
                                 nsIProxyInfo *proxy,
319
                                 const OriginAttributes& originAttributes,
320
                                 PRFileDesc* fd,
321
                                 nsISupports** securityInfo,
322
                                 bool forSTARTTLS,
323
                                 uint32_t flags,
324
                                 uint32_t tlsFlags);
325
326
nsresult nsSSLIOLayerFreeTLSIntolerantSites();
327
328
#endif // nsNSSIOLayer_h