Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/manager/ssl/TransportSecurityInfo.cpp
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
#include "TransportSecurityInfo.h"
8
9
#include "DateTimeFormat.h"
10
#include "PSMRunnable.h"
11
#include "mozilla/Casting.h"
12
#include "nsComponentManagerUtils.h"
13
#include "nsIArray.h"
14
#include "nsICertOverrideService.h"
15
#include "nsIObjectInputStream.h"
16
#include "nsIObjectOutputStream.h"
17
#include "nsIWebProgressListener.h"
18
#include "nsIX509CertValidity.h"
19
#include "nsNSSCertHelper.h"
20
#include "nsNSSCertificate.h"
21
#include "nsNSSComponent.h"
22
#include "nsNSSHelper.h"
23
#include "nsReadableUtils.h"
24
#include "nsServiceManagerUtils.h"
25
#include "nsXULAppAPI.h"
26
#include "pkix/pkixtypes.h"
27
#include "secerr.h"
28
29
//#define DEBUG_SSL_VERBOSE //Enable this define to get minimal
30
                            //reports when doing SSL read/write
31
32
//#define DUMP_BUFFER  //Enable this define along with
33
                       //DEBUG_SSL_VERBOSE to dump SSL
34
                       //read/write buffer to a log.
35
                       //Uses PR_LOG except on Mac where
36
                       //we always write out to our own
37
                       //file.
38
39
namespace mozilla { namespace psm {
40
41
TransportSecurityInfo::TransportSecurityInfo()
42
  : mCipherSuite(0)
43
  , mProtocolVersion(0)
44
  , mCertificateTransparencyStatus(nsITransportSecurityInfo::
45
      CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE)
46
  , mKeaGroup()
47
  , mSignatureSchemeName()
48
  , mIsDomainMismatch(false)
49
  , mIsNotValidAtThisTime(false)
50
  , mIsUntrusted(false)
51
  , mIsEV(false)
52
  , mHasIsEVStatus(false)
53
  , mHaveCipherSuiteAndProtocol(false)
54
  , mHaveCertErrorBits(false)
55
  , mMutex("TransportSecurityInfo::mMutex")
56
  , mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE)
57
  , mErrorCode(0)
58
  , mPort(0)
59
0
{
60
0
}
61
62
NS_IMPL_ISUPPORTS(TransportSecurityInfo,
63
                  nsITransportSecurityInfo,
64
                  nsIInterfaceRequestor,
65
                  nsISerializable,
66
                  nsIClassInfo)
67
68
void
69
TransportSecurityInfo::SetHostName(const char* host)
70
0
{
71
0
  mHostName.Assign(host);
72
0
}
73
74
void
75
TransportSecurityInfo::SetPort(int32_t aPort)
76
0
{
77
0
  mPort = aPort;
78
0
}
79
80
void
81
TransportSecurityInfo::SetOriginAttributes(
82
  const OriginAttributes& aOriginAttributes)
83
0
{
84
0
  mOriginAttributes = aOriginAttributes;
85
0
}
86
87
NS_IMETHODIMP
88
TransportSecurityInfo::GetErrorCode(int32_t* state)
89
0
{
90
0
  MutexAutoLock lock(mMutex);
91
0
92
0
  *state = mErrorCode;
93
0
  return NS_OK;
94
0
}
95
96
void
97
TransportSecurityInfo::SetCanceled(PRErrorCode errorCode)
98
0
{
99
0
  MutexAutoLock lock(mMutex);
100
0
101
0
  mErrorCode = errorCode;
102
0
}
103
104
NS_IMETHODIMP
105
TransportSecurityInfo::GetSecurityState(uint32_t* state)
106
0
{
107
0
  *state = mSecurityState;
108
0
  return NS_OK;
109
0
}
110
111
void
112
TransportSecurityInfo::SetSecurityState(uint32_t aState)
113
0
{
114
0
  mSecurityState = aState;
115
0
}
116
117
NS_IMETHODIMP
118
TransportSecurityInfo::GetErrorCodeString(nsAString& aErrorString)
119
0
{
120
0
  MutexAutoLock lock(mMutex);
121
0
122
0
  const char* codeName = PR_ErrorToName(mErrorCode);
123
0
  aErrorString.Truncate();
124
0
  if (codeName) {
125
0
    aErrorString = NS_ConvertASCIItoUTF16(codeName);
126
0
  }
127
0
128
0
  return NS_OK;
129
0
}
130
131
NS_IMETHODIMP
132
TransportSecurityInfo::GetInterface(const nsIID & uuid, void * *result)
133
0
{
134
0
  if (!NS_IsMainThread()) {
135
0
    NS_ERROR("nsNSSSocketInfo::GetInterface called off the main thread");
136
0
    return NS_ERROR_NOT_SAME_THREAD;
137
0
  }
138
0
139
0
  nsresult rv;
140
0
  if (!mCallbacks) {
141
0
    nsCOMPtr<nsIInterfaceRequestor> ir = new PipUIContext();
142
0
    rv = ir->GetInterface(uuid, result);
143
0
  } else {
144
0
    rv = mCallbacks->GetInterface(uuid, result);
145
0
  }
146
0
  return rv;
147
0
}
148
149
// This is a new magic value. However, it re-uses the first 4 bytes
150
// of the previous value. This is so when older versions attempt to
151
// read a newer serialized TransportSecurityInfo, they will actually
152
// fail and return NS_ERROR_FAILURE instead of silently failing.
153
#define TRANSPORTSECURITYINFOMAGIC { 0xa9863a23, 0x1faa, 0x4169, \
154
  { 0xb0, 0xd2, 0x81, 0x29, 0xec, 0x7c, 0xb1, 0xde } }
155
static NS_DEFINE_CID(kTransportSecurityInfoMagic, TRANSPORTSECURITYINFOMAGIC);
156
157
NS_IMETHODIMP
158
TransportSecurityInfo::Write(nsIObjectOutputStream* aStream)
159
0
{
160
0
  nsresult rv = aStream->WriteID(kTransportSecurityInfoMagic);
161
0
  if (NS_FAILED(rv)) {
162
0
    return rv;
163
0
  }
164
0
165
0
  MutexAutoLock lock(mMutex);
166
0
167
0
  rv = aStream->Write32(mSecurityState);
168
0
  if (NS_FAILED(rv)) {
169
0
    return rv;
170
0
  }
171
0
  // mSubRequestsBrokenSecurity was removed in bug 748809
172
0
  rv = aStream->Write32(0);
173
0
  if (NS_FAILED(rv)) {
174
0
    return rv;
175
0
  }
176
0
  // mSubRequestsNoSecurity was removed in bug 748809
177
0
  rv = aStream->Write32(0);
178
0
  if (NS_FAILED(rv)) {
179
0
    return rv;
180
0
  }
181
0
  rv = aStream->Write32(static_cast<uint32_t>(mErrorCode));
182
0
  if (NS_FAILED(rv)) {
183
0
    return rv;
184
0
  }
185
0
186
0
  // Re-purpose mErrorMessageCached to represent serialization version
187
0
  // If string doesn't match exact version it will be treated as older
188
0
  // serialization.
189
0
  rv = aStream->WriteWStringZ(NS_ConvertUTF8toUTF16("1").get());
190
0
  if (NS_FAILED(rv)) {
191
0
    return rv;
192
0
  }
193
0
194
0
  // moved from nsISSLStatus
195
0
  rv = NS_WriteOptionalCompoundObject(aStream, mServerCert,
196
0
                                      NS_GET_IID(nsIX509Cert),
197
0
                                      true);
198
0
  NS_ENSURE_SUCCESS(rv, rv);
199
0
200
0
  rv = aStream->Write16(mCipherSuite);
201
0
  NS_ENSURE_SUCCESS(rv, rv);
202
0
203
0
  rv = aStream->Write16(mProtocolVersion);
204
0
  NS_ENSURE_SUCCESS(rv, rv);
205
0
206
0
  rv = aStream->WriteBoolean(mIsDomainMismatch);
207
0
  NS_ENSURE_SUCCESS(rv, rv);
208
0
  rv = aStream->WriteBoolean(mIsNotValidAtThisTime);
209
0
  NS_ENSURE_SUCCESS(rv, rv);
210
0
  rv = aStream->WriteBoolean(mIsUntrusted);
211
0
  NS_ENSURE_SUCCESS(rv, rv);
212
0
  rv = aStream->WriteBoolean(mIsEV);
213
0
  NS_ENSURE_SUCCESS(rv, rv);
214
0
215
0
  rv = aStream->WriteBoolean(mHasIsEVStatus);
216
0
  NS_ENSURE_SUCCESS(rv, rv);
217
0
  rv = aStream->WriteBoolean(mHaveCipherSuiteAndProtocol);
218
0
  NS_ENSURE_SUCCESS(rv, rv);
219
0
  rv = aStream->WriteBoolean(mHaveCertErrorBits);
220
0
  NS_ENSURE_SUCCESS(rv, rv);
221
0
222
0
  rv = aStream->Write16(mCertificateTransparencyStatus);
223
0
  NS_ENSURE_SUCCESS(rv, rv);
224
0
225
0
  rv = aStream->WriteStringZ(mKeaGroup.get());
226
0
  NS_ENSURE_SUCCESS(rv, rv);
227
0
228
0
  rv = aStream->WriteStringZ(mSignatureSchemeName.get());
229
0
  NS_ENSURE_SUCCESS(rv, rv);
230
0
231
0
  rv = NS_WriteOptionalCompoundObject(aStream,
232
0
                                      mSucceededCertChain,
233
0
                                      NS_GET_IID(nsIX509CertList),
234
0
                                       true);
235
0
   if (NS_FAILED(rv)) {
236
0
     return rv;
237
0
   }
238
0
  // END moved from nsISSLStatus
239
0
240
0
  rv = NS_WriteOptionalCompoundObject(aStream,
241
0
                                      mFailedCertChain,
242
0
                                      NS_GET_IID(nsIX509CertList),
243
0
                                      true);
244
0
  if (NS_FAILED(rv)) {
245
0
    return rv;
246
0
  }
247
0
248
0
  return NS_OK;
249
0
}
250
251
// This is for backward compatability to be able to read nsISSLStatus
252
// serialized object.
253
nsresult TransportSecurityInfo::ReadSSLStatus(nsIObjectInputStream* aStream)
254
0
{
255
0
  bool nsISSLStatusPresent;
256
0
  nsresult rv = aStream->ReadBoolean(&nsISSLStatusPresent);
257
0
  NS_ENSURE_SUCCESS(rv, rv);
258
0
  if (!nsISSLStatusPresent) {
259
0
    return NS_OK;
260
0
  }
261
0
  // nsISSLStatus present.  Prepare to read elements.
262
0
  // Throw away cid, validate iid
263
0
  nsCID cid;
264
0
  nsIID iid;
265
0
  rv = aStream->ReadID(&cid);
266
0
  NS_ENSURE_SUCCESS(rv, rv);
267
0
  rv = aStream->ReadID(&iid);
268
0
  NS_ENSURE_SUCCESS(rv, rv);
269
0
270
0
  static const nsIID nsSSLStatusIID = {
271
0
    0xfa9ba95b, 0xca3b, 0x498a,
272
0
    { 0xb8, 0x89, 0x7c, 0x79, 0xcf, 0x28, 0xfe, 0xe8 }
273
0
  };
274
0
  if (!iid.Equals(nsSSLStatusIID)) {
275
0
    return NS_ERROR_UNEXPECTED;
276
0
  }
277
0
278
0
  nsCOMPtr<nsISupports> cert;
279
0
  rv = aStream->ReadObject(true, getter_AddRefs(cert));
280
0
  NS_ENSURE_SUCCESS(rv, rv);
281
0
282
0
  if (cert) {
283
0
    mServerCert = do_QueryInterface(cert);
284
0
    if (!mServerCert) {
285
0
      return NS_NOINTERFACE;
286
0
    }
287
0
  }
288
0
289
0
  rv = aStream->Read16(&mCipherSuite);
290
0
  NS_ENSURE_SUCCESS(rv, rv);
291
0
292
0
  // The code below is a workaround to allow serializing new fields
293
0
  // while preserving binary compatibility with older streams. For more details
294
0
  // on the binary compatibility requirement, refer to bug 1248628.
295
0
  // Here, we take advantage of the fact that mProtocolVersion was originally
296
0
  // stored as a 16 bits integer, but the highest 8 bits were never used.
297
0
  // These bits are now used for stream versioning.
298
0
  uint16_t protocolVersionAndStreamFormatVersion;
299
0
  rv = aStream->Read16(&protocolVersionAndStreamFormatVersion);
300
0
  NS_ENSURE_SUCCESS(rv, rv);
301
0
  mProtocolVersion = protocolVersionAndStreamFormatVersion & 0xFF;
302
0
  const uint8_t streamFormatVersion =
303
0
  (protocolVersionAndStreamFormatVersion >> 8) & 0xFF;
304
0
305
0
  rv = aStream->ReadBoolean(&mIsDomainMismatch);
306
0
  NS_ENSURE_SUCCESS(rv, rv);
307
0
  rv = aStream->ReadBoolean(&mIsNotValidAtThisTime);
308
0
  NS_ENSURE_SUCCESS(rv, rv);
309
0
  rv = aStream->ReadBoolean(&mIsUntrusted);
310
0
  NS_ENSURE_SUCCESS(rv, rv);
311
0
  rv = aStream->ReadBoolean(&mIsEV);
312
0
  NS_ENSURE_SUCCESS(rv, rv);
313
0
314
0
  rv = aStream->ReadBoolean(&mHasIsEVStatus);
315
0
  NS_ENSURE_SUCCESS(rv, rv);
316
0
  rv = aStream->ReadBoolean(&mHaveCipherSuiteAndProtocol);
317
0
  NS_ENSURE_SUCCESS(rv, rv);
318
0
  rv = aStream->ReadBoolean(&mHaveCertErrorBits);
319
0
  NS_ENSURE_SUCCESS(rv, rv);
320
0
321
0
  // Added in version 1 (see bug 1305289).
322
0
  if (streamFormatVersion >= 1) {
323
0
    rv = aStream->Read16(&mCertificateTransparencyStatus);
324
0
    NS_ENSURE_SUCCESS(rv, rv);
325
0
  }
326
0
327
0
  // Added in version 2 (see bug 1304923).
328
0
  if (streamFormatVersion >= 2) {
329
0
    rv = aStream->ReadCString(mKeaGroup);
330
0
    NS_ENSURE_SUCCESS(rv, rv);
331
0
332
0
    rv = aStream->ReadCString(mSignatureSchemeName);
333
0
    NS_ENSURE_SUCCESS(rv, rv);
334
0
  }
335
0
336
0
  // Added in version 3 (see bug 1406856).
337
0
  if (streamFormatVersion >= 3) {
338
0
    nsCOMPtr<nsISupports> succeededCertChainSupports;
339
0
    rv = NS_ReadOptionalObject(aStream, true,
340
0
                               getter_AddRefs(succeededCertChainSupports));
341
0
    if (NS_FAILED(rv)) {
342
0
      return rv;
343
0
    }
344
0
    mSucceededCertChain = do_QueryInterface(succeededCertChainSupports);
345
0
346
0
    // Read only to consume bytes from the stream.
347
0
    nsCOMPtr<nsISupports> failedCertChainSupports;
348
0
    rv = NS_ReadOptionalObject(aStream, true,
349
0
                               getter_AddRefs(failedCertChainSupports));
350
0
    if (NS_FAILED(rv)) {
351
0
      return rv;
352
0
    }
353
0
  }
354
0
  return rv;
355
0
}
356
357
NS_IMETHODIMP
358
TransportSecurityInfo::Read(nsIObjectInputStream* aStream)
359
0
{
360
0
  nsID id;
361
0
  nsresult rv = aStream->ReadID(&id);
362
0
  if (NS_FAILED(rv)) {
363
0
    return rv;
364
0
  }
365
0
  if (!id.Equals(kTransportSecurityInfoMagic)) {
366
0
    return NS_ERROR_UNEXPECTED;
367
0
  }
368
0
369
0
  MutexAutoLock lock(mMutex);
370
0
371
0
  rv = aStream->Read32(&mSecurityState);
372
0
  if (NS_FAILED(rv)) {
373
0
    return rv;
374
0
  }
375
0
  // mSubRequestsBrokenSecurity was removed in bug 748809
376
0
  uint32_t unusedSubRequestsBrokenSecurity;
377
0
  rv = aStream->Read32(&unusedSubRequestsBrokenSecurity);
378
0
  if (NS_FAILED(rv)) {
379
0
    return rv;
380
0
  }
381
0
  // mSubRequestsNoSecurity was removed in bug 748809
382
0
  uint32_t unusedSubRequestsNoSecurity;
383
0
  rv = aStream->Read32(&unusedSubRequestsNoSecurity);
384
0
  if (NS_FAILED(rv)) {
385
0
    return rv;
386
0
  }
387
0
  uint32_t errorCode;
388
0
  rv = aStream->Read32(&errorCode);
389
0
  if (NS_FAILED(rv)) {
390
0
    return rv;
391
0
  }
392
0
  // PRErrorCode will be a negative value
393
0
  mErrorCode = static_cast<PRErrorCode>(errorCode);
394
0
395
0
  // Re-purpose mErrorMessageCached to represent serialization version
396
0
  // If string doesn't match exact version it will be treated as older
397
0
  // serialization.
398
0
  nsAutoString serVersion;
399
0
  rv = aStream->ReadString(serVersion);
400
0
  if (NS_FAILED(rv)) {
401
0
    return rv;
402
0
  }
403
0
404
0
  // moved from nsISSLStatus
405
0
  if (!serVersion.EqualsASCII("1")) {
406
0
    // nsISSLStatus may be present
407
0
    rv = ReadSSLStatus(aStream);
408
0
    NS_ENSURE_SUCCESS(rv, rv);
409
0
  } else {
410
0
    nsCOMPtr<nsISupports> cert;
411
0
    rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(cert));
412
0
    NS_ENSURE_SUCCESS(rv, rv);
413
0
414
0
    if (cert != nullptr) {
415
0
      mServerCert = do_QueryInterface(cert);
416
0
      if (!mServerCert) {
417
0
        return NS_NOINTERFACE;
418
0
      }
419
0
    }
420
0
421
0
    rv = aStream->Read16(&mCipherSuite);
422
0
    NS_ENSURE_SUCCESS(rv, rv);
423
0
424
0
    rv = aStream->Read16(&mProtocolVersion);
425
0
    NS_ENSURE_SUCCESS(rv, rv);
426
0
427
0
    rv = aStream->ReadBoolean(&mIsDomainMismatch);
428
0
    NS_ENSURE_SUCCESS(rv, rv);
429
0
    rv = aStream->ReadBoolean(&mIsNotValidAtThisTime);
430
0
    NS_ENSURE_SUCCESS(rv, rv);
431
0
    rv = aStream->ReadBoolean(&mIsUntrusted);
432
0
    NS_ENSURE_SUCCESS(rv, rv);
433
0
    rv = aStream->ReadBoolean(&mIsEV);
434
0
    NS_ENSURE_SUCCESS(rv, rv);
435
0
436
0
    rv = aStream->ReadBoolean(&mHasIsEVStatus);
437
0
    NS_ENSURE_SUCCESS(rv, rv);
438
0
    rv = aStream->ReadBoolean(&mHaveCipherSuiteAndProtocol);
439
0
    NS_ENSURE_SUCCESS(rv, rv);
440
0
    rv = aStream->ReadBoolean(&mHaveCertErrorBits);
441
0
    NS_ENSURE_SUCCESS(rv, rv);
442
0
443
0
    rv = aStream->Read16(&mCertificateTransparencyStatus);
444
0
    NS_ENSURE_SUCCESS(rv, rv);
445
0
446
0
    rv = aStream->ReadCString(mKeaGroup);
447
0
    NS_ENSURE_SUCCESS(rv, rv);
448
0
449
0
    rv = aStream->ReadCString(mSignatureSchemeName);
450
0
    NS_ENSURE_SUCCESS(rv, rv);
451
0
452
0
    nsCOMPtr<nsISupports> succeededCertChainSupports;
453
0
    rv = NS_ReadOptionalObject(aStream, true,
454
0
                               getter_AddRefs(succeededCertChainSupports));
455
0
    if (NS_FAILED(rv)) {
456
0
      return rv;
457
0
    }
458
0
    mSucceededCertChain = do_QueryInterface(succeededCertChainSupports);
459
0
  }
460
0
  // END moved from nsISSLStatus
461
0
462
0
  nsCOMPtr<nsISupports> failedCertChainSupports;
463
0
  rv = NS_ReadOptionalObject(aStream, true,
464
0
                             getter_AddRefs(failedCertChainSupports));
465
0
  if (NS_FAILED(rv)) {
466
0
    return rv;
467
0
  }
468
0
  mFailedCertChain = do_QueryInterface(failedCertChainSupports);
469
0
470
0
  return NS_OK;
471
0
}
472
473
NS_IMETHODIMP
474
TransportSecurityInfo::GetInterfaces(uint32_t *count, nsIID * **array)
475
0
{
476
0
  *count = 0;
477
0
  *array = nullptr;
478
0
  return NS_OK;
479
0
}
480
481
NS_IMETHODIMP
482
TransportSecurityInfo::GetScriptableHelper(nsIXPCScriptable **_retval)
483
0
{
484
0
  *_retval = nullptr;
485
0
  return NS_OK;
486
0
}
487
488
NS_IMETHODIMP
489
TransportSecurityInfo::GetContractID(nsACString& aContractID)
490
0
{
491
0
  aContractID.SetIsVoid(true);
492
0
  return NS_OK;
493
0
}
494
495
NS_IMETHODIMP
496
TransportSecurityInfo::GetClassDescription(nsACString& aClassDescription)
497
0
{
498
0
  aClassDescription.SetIsVoid(true);
499
0
  return NS_OK;
500
0
}
501
502
NS_IMETHODIMP
503
TransportSecurityInfo::GetClassID(nsCID * *aClassID)
504
0
{
505
0
  *aClassID = (nsCID*) moz_xmalloc(sizeof(nsCID));
506
0
  return GetClassIDNoAlloc(*aClassID);
507
0
}
508
509
NS_IMETHODIMP
510
TransportSecurityInfo::GetFlags(uint32_t *aFlags)
511
0
{
512
0
  *aFlags = 0;
513
0
  return NS_OK;
514
0
}
515
516
static NS_DEFINE_CID(kNSSSocketInfoCID, TRANSPORTSECURITYINFO_CID);
517
518
NS_IMETHODIMP
519
TransportSecurityInfo::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
520
0
{
521
0
  *aClassIDNoAlloc = kNSSSocketInfoCID;
522
0
  return NS_OK;
523
0
}
524
525
// RememberCertErrorsTable
526
527
/*static*/ RememberCertErrorsTable*
528
RememberCertErrorsTable::sInstance = nullptr;
529
530
RememberCertErrorsTable::RememberCertErrorsTable()
531
  : mErrorHosts()
532
  , mMutex("RememberCertErrorsTable::mMutex")
533
0
{
534
0
}
535
536
static nsresult
537
GetHostPortKey(TransportSecurityInfo* infoObject, /*out*/ nsCString& result)
538
0
{
539
0
  MOZ_ASSERT(infoObject);
540
0
  NS_ENSURE_ARG(infoObject);
541
0
542
0
  result.Truncate();
543
0
544
0
  result.Assign(infoObject->GetHostName());
545
0
  result.Append(':');
546
0
  result.AppendInt(infoObject->GetPort());
547
0
548
0
  return NS_OK;
549
0
}
550
551
void
552
RememberCertErrorsTable::RememberCertHasError(TransportSecurityInfo* infoObject,
553
                                              SECStatus certVerificationResult)
554
0
{
555
0
  nsresult rv;
556
0
557
0
  nsAutoCString hostPortKey;
558
0
  rv = GetHostPortKey(infoObject, hostPortKey);
559
0
  if (NS_FAILED(rv)) {
560
0
    return;
561
0
  }
562
0
563
0
  if (certVerificationResult != SECSuccess) {
564
0
    MOZ_ASSERT(infoObject->mHaveCertErrorBits, "Must have error bits when remembering flags");
565
0
    if (!infoObject->mHaveCertErrorBits) {
566
0
      return;
567
0
    }
568
0
569
0
    CertStateBits bits;
570
0
    bits.mIsDomainMismatch = infoObject->mIsDomainMismatch;
571
0
    bits.mIsNotValidAtThisTime = infoObject->mIsNotValidAtThisTime;
572
0
    bits.mIsUntrusted = infoObject->mIsUntrusted;
573
0
574
0
    MutexAutoLock lock(mMutex);
575
0
    mErrorHosts.Put(hostPortKey, bits);
576
0
  } else {
577
0
    MutexAutoLock lock(mMutex);
578
0
    mErrorHosts.Remove(hostPortKey);
579
0
  }
580
0
}
581
582
void
583
RememberCertErrorsTable::LookupCertErrorBits(TransportSecurityInfo* infoObject)
584
0
{
585
0
  // Get remembered error bits from our cache, because of SSL session caching
586
0
  // the NSS library potentially hasn't notified us for this socket.
587
0
  if (infoObject->mHaveCertErrorBits) {
588
0
    // Rather do not modify bits if already set earlier
589
0
    return;
590
0
  }
591
0
592
0
  nsresult rv;
593
0
594
0
  nsAutoCString hostPortKey;
595
0
  rv = GetHostPortKey(infoObject, hostPortKey);
596
0
  if (NS_FAILED(rv)) {
597
0
    return;
598
0
  }
599
0
600
0
  CertStateBits bits;
601
0
  {
602
0
    MutexAutoLock lock(mMutex);
603
0
    if (!mErrorHosts.Get(hostPortKey, &bits)) {
604
0
      // No record was found, this host had no cert errors
605
0
      return;
606
0
    }
607
0
  }
608
0
609
0
  // This host had cert errors, update the bits correctly
610
0
  infoObject->mHaveCertErrorBits = true;
611
0
  infoObject->mIsDomainMismatch = bits.mIsDomainMismatch;
612
0
  infoObject->mIsNotValidAtThisTime = bits.mIsNotValidAtThisTime;
613
0
  infoObject->mIsUntrusted = bits.mIsUntrusted;
614
0
}
615
616
void
617
TransportSecurityInfo::SetStatusErrorBits(nsNSSCertificate* cert,
618
                                          uint32_t collected_errors)
619
0
{
620
0
  MutexAutoLock lock(mMutex);
621
0
622
0
  SetServerCert(cert, EVStatus::NotEV);
623
0
624
0
  mHaveCertErrorBits = true;
625
0
  mIsDomainMismatch =
626
0
    collected_errors & nsICertOverrideService::ERROR_MISMATCH;
627
0
  mIsNotValidAtThisTime =
628
0
    collected_errors & nsICertOverrideService::ERROR_TIME;
629
0
  mIsUntrusted =
630
0
    collected_errors & nsICertOverrideService::ERROR_UNTRUSTED;
631
0
632
0
  RememberCertErrorsTable::GetInstance().RememberCertHasError(this,
633
0
                                                              SECFailure);
634
0
}
635
636
NS_IMETHODIMP
637
TransportSecurityInfo::GetFailedCertChain(nsIX509CertList** _result)
638
0
{
639
0
  MOZ_ASSERT(_result);
640
0
641
0
  *_result = mFailedCertChain;
642
0
  NS_IF_ADDREF(*_result);
643
0
644
0
  return NS_OK;
645
0
}
646
647
nsresult
648
TransportSecurityInfo::SetFailedCertChain(UniqueCERTCertList certList)
649
0
{
650
0
  // nsNSSCertList takes ownership of certList
651
0
  mFailedCertChain = new nsNSSCertList(std::move(certList));
652
0
653
0
  return NS_OK;
654
0
}
655
656
NS_IMETHODIMP
657
TransportSecurityInfo::GetServerCert(nsIX509Cert** aServerCert)
658
0
{
659
0
  NS_ENSURE_ARG_POINTER(aServerCert);
660
0
661
0
  nsCOMPtr<nsIX509Cert> cert = mServerCert;
662
0
  cert.forget(aServerCert);
663
0
  return NS_OK;
664
0
}
665
666
void
667
TransportSecurityInfo::SetServerCert(nsNSSCertificate* aServerCert,
668
                                     EVStatus aEVStatus)
669
0
{
670
0
  MOZ_ASSERT(aServerCert);
671
0
672
0
  mServerCert = aServerCert;
673
0
  mIsEV = (aEVStatus == EVStatus::EV);
674
0
  mHasIsEVStatus = true;
675
0
}
676
677
NS_IMETHODIMP
678
TransportSecurityInfo::GetSucceededCertChain(nsIX509CertList** _result)
679
0
{
680
0
  NS_ENSURE_ARG_POINTER(_result);
681
0
682
0
  nsCOMPtr<nsIX509CertList> tmpList = mSucceededCertChain;
683
0
  tmpList.forget(_result);
684
0
685
0
  return NS_OK;
686
0
}
687
688
nsresult
689
TransportSecurityInfo::SetSucceededCertChain(UniqueCERTCertList aCertList)
690
0
{
691
0
  // nsNSSCertList takes ownership of certList
692
0
  mSucceededCertChain = new nsNSSCertList(std::move(aCertList));
693
0
694
0
  return NS_OK;
695
0
}
696
697
NS_IMETHODIMP
698
TransportSecurityInfo::GetCipherName(nsACString& aCipherName)
699
0
{
700
0
  if (!mHaveCipherSuiteAndProtocol) {
701
0
    return NS_ERROR_NOT_AVAILABLE;
702
0
  }
703
0
704
0
  SSLCipherSuiteInfo cipherInfo;
705
0
  if (SSL_GetCipherSuiteInfo(mCipherSuite, &cipherInfo,
706
0
                             sizeof(cipherInfo)) != SECSuccess) {
707
0
    return NS_ERROR_FAILURE;
708
0
  }
709
0
710
0
  aCipherName.Assign(cipherInfo.cipherSuiteName);
711
0
  return NS_OK;
712
0
}
713
714
NS_IMETHODIMP
715
TransportSecurityInfo::GetKeyLength(uint32_t* aKeyLength)
716
0
{
717
0
  NS_ENSURE_ARG_POINTER(aKeyLength);
718
0
  if (!mHaveCipherSuiteAndProtocol) {
719
0
    return NS_ERROR_NOT_AVAILABLE;
720
0
  }
721
0
722
0
  SSLCipherSuiteInfo cipherInfo;
723
0
  if (SSL_GetCipherSuiteInfo(mCipherSuite, &cipherInfo,
724
0
                             sizeof(cipherInfo)) != SECSuccess) {
725
0
    return NS_ERROR_FAILURE;
726
0
  }
727
0
728
0
  *aKeyLength = cipherInfo.symKeyBits;
729
0
  return NS_OK;
730
0
}
731
732
NS_IMETHODIMP
733
TransportSecurityInfo::GetSecretKeyLength(uint32_t* aSecretKeyLength)
734
0
{
735
0
  NS_ENSURE_ARG_POINTER(aSecretKeyLength);
736
0
  if (!mHaveCipherSuiteAndProtocol) {
737
0
    return NS_ERROR_NOT_AVAILABLE;
738
0
  }
739
0
740
0
  SSLCipherSuiteInfo cipherInfo;
741
0
  if (SSL_GetCipherSuiteInfo(mCipherSuite, &cipherInfo,
742
0
                             sizeof(cipherInfo)) != SECSuccess) {
743
0
    return NS_ERROR_FAILURE;
744
0
  }
745
0
746
0
  *aSecretKeyLength = cipherInfo.effectiveKeyBits;
747
0
  return NS_OK;
748
0
}
749
750
NS_IMETHODIMP
751
TransportSecurityInfo::GetKeaGroupName(nsACString& aKeaGroup)
752
0
{
753
0
  if (!mHaveCipherSuiteAndProtocol) {
754
0
    return NS_ERROR_NOT_AVAILABLE;
755
0
  }
756
0
757
0
  aKeaGroup.Assign(mKeaGroup);
758
0
  return NS_OK;
759
0
}
760
761
NS_IMETHODIMP
762
TransportSecurityInfo::GetSignatureSchemeName(nsACString& aSignatureScheme)
763
0
{
764
0
  if (!mHaveCipherSuiteAndProtocol) {
765
0
    return NS_ERROR_NOT_AVAILABLE;
766
0
  }
767
0
768
0
  aSignatureScheme.Assign(mSignatureSchemeName);
769
0
  return NS_OK;
770
0
}
771
772
NS_IMETHODIMP
773
TransportSecurityInfo::GetProtocolVersion(uint16_t* aProtocolVersion)
774
0
{
775
0
  NS_ENSURE_ARG_POINTER(aProtocolVersion);
776
0
  if (!mHaveCipherSuiteAndProtocol) {
777
0
    return NS_ERROR_NOT_AVAILABLE;
778
0
  }
779
0
780
0
  *aProtocolVersion = mProtocolVersion;
781
0
  return NS_OK;
782
0
}
783
784
NS_IMETHODIMP
785
TransportSecurityInfo::GetCertificateTransparencyStatus(
786
  uint16_t* aCertificateTransparencyStatus)
787
0
{
788
0
  NS_ENSURE_ARG_POINTER(aCertificateTransparencyStatus);
789
0
790
0
  *aCertificateTransparencyStatus = mCertificateTransparencyStatus;
791
0
  return NS_OK;
792
0
}
793
794
void
795
TransportSecurityInfo::SetCertificateTransparencyInfo(
796
  const mozilla::psm::CertificateTransparencyInfo& info)
797
0
{
798
0
  using mozilla::ct::CTPolicyCompliance;
799
0
800
0
  mCertificateTransparencyStatus =
801
0
    nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE;
802
0
803
0
  if (!info.enabled) {
804
0
    // CT disabled.
805
0
    return;
806
0
  }
807
0
808
0
  switch (info.policyCompliance) {
809
0
    case CTPolicyCompliance::Compliant:
810
0
      mCertificateTransparencyStatus =
811
0
        nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_POLICY_COMPLIANT;
812
0
      break;
813
0
    case CTPolicyCompliance::NotEnoughScts:
814
0
      mCertificateTransparencyStatus =
815
0
        nsITransportSecurityInfo
816
0
          ::CERTIFICATE_TRANSPARENCY_POLICY_NOT_ENOUGH_SCTS;
817
0
      break;
818
0
    case CTPolicyCompliance::NotDiverseScts:
819
0
      mCertificateTransparencyStatus =
820
0
        nsITransportSecurityInfo
821
0
          ::CERTIFICATE_TRANSPARENCY_POLICY_NOT_DIVERSE_SCTS;
822
0
      break;
823
0
    case CTPolicyCompliance::Unknown:
824
0
    default:
825
0
      MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
826
0
  }
827
0
}
828
829
NS_IMETHODIMP
830
TransportSecurityInfo::GetIsDomainMismatch(bool* aIsDomainMismatch)
831
0
{
832
0
  NS_ENSURE_ARG_POINTER(aIsDomainMismatch);
833
0
834
0
  *aIsDomainMismatch = mHaveCertErrorBits && mIsDomainMismatch;
835
0
  return NS_OK;
836
0
}
837
838
NS_IMETHODIMP
839
TransportSecurityInfo::GetIsNotValidAtThisTime(bool* aIsNotValidAtThisTime)
840
0
{
841
0
  NS_ENSURE_ARG_POINTER(aIsNotValidAtThisTime);
842
0
843
0
  *aIsNotValidAtThisTime = mHaveCertErrorBits && mIsNotValidAtThisTime;
844
0
  return NS_OK;
845
0
}
846
847
NS_IMETHODIMP
848
TransportSecurityInfo::GetIsUntrusted(bool* aIsUntrusted)
849
0
{
850
0
  NS_ENSURE_ARG_POINTER(aIsUntrusted);
851
0
852
0
  *aIsUntrusted = mHaveCertErrorBits && mIsUntrusted;
853
0
  return NS_OK;
854
0
}
855
856
NS_IMETHODIMP
857
TransportSecurityInfo::GetIsExtendedValidation(bool* aIsEV)
858
0
{
859
0
  NS_ENSURE_ARG_POINTER(aIsEV);
860
0
  *aIsEV = false;
861
0
862
0
  // Never allow bad certs for EV, regardless of overrides.
863
0
  if (mHaveCertErrorBits) {
864
0
    return NS_OK;
865
0
  }
866
0
867
0
  if (mHasIsEVStatus) {
868
0
    *aIsEV = mIsEV;
869
0
    return NS_OK;
870
0
  }
871
0
872
0
  return NS_ERROR_NOT_AVAILABLE;
873
0
}
874
875
} } // namespace mozilla::psm