Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/manager/ssl/SSLServerCertVerification.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
// For connections that are not processed on the socket transport thread, we do
8
// NOT use the async logic described below. Instead, we authenticate the
9
// certificate on the thread that the connection's I/O happens on,
10
// synchronously. This allows us to do certificate verification for blocking
11
// (not non-blocking) sockets and sockets that have their I/O processed on a
12
// thread other than the socket transport service thread. Also, we DO NOT
13
// support blocking sockets on the socket transport service thread at all.
14
//
15
// During certificate authentication, we call CERT_PKIXVerifyCert or
16
// CERT_VerifyCert. These functions may make zero or more HTTP requests
17
// for OCSP responses, CRLs, intermediate certificates, etc. Our fetching logic
18
// for these requests processes them on the socket transport service thread.
19
//
20
// If the connection for which we are verifying the certificate is happening
21
// on the socket transport thread (the usually case, at least for HTTP), then
22
// if our cert auth hook were to call the CERT_*Verify* functions directly,
23
// there would be a deadlock: The CERT_*Verify* function would cause an event
24
// to be asynchronously posted to the socket transport thread, and then it
25
// would block the socket transport thread waiting to be notified of the HTTP
26
// response. However, the HTTP request would never actually be processed
27
// because the socket transport thread would be blocked and so it wouldn't be
28
// able process HTTP requests. (i.e. Deadlock.)
29
//
30
// Consequently, when we are asked to verify a certificate on the socket
31
// transport service thread, we must always call the CERT_*Verify* cert
32
// functions on another thread. To accomplish this, our auth cert hook
33
// dispatches a SSLServerCertVerificationJob to a pool of background threads,
34
// and then immediately returns SECWouldBlock to libssl. These jobs are where
35
// the CERT_*Verify* functions are actually called.
36
//
37
// When our auth cert hook returns SECWouldBlock, libssl will carry on the
38
// handshake while we validate the certificate. This will free up the socket
39
// transport thread so that HTTP requests--in particular, the OCSP/CRL/cert
40
// requests needed for cert verification as mentioned above--can be processed.
41
//
42
// Once the CERT_*Verify* function returns, the cert verification job
43
// dispatches a SSLServerCertVerificationResult to the socket transport thread;
44
// the SSLServerCertVerificationResult will notify libssl that the certificate
45
// authentication is complete. Once libssl is notified that the authentication
46
// is complete, it will continue the SSL handshake (if it hasn't already
47
// finished) and it will begin allowing us to send/receive data on the
48
// connection.
49
//
50
// Timeline of events (for connections managed by the socket transport service):
51
//
52
//    * libssl calls SSLServerCertVerificationJob::Dispatch on the socket
53
//      transport thread.
54
//    * SSLServerCertVerificationJob::Dispatch queues a job
55
//      (instance of SSLServerCertVerificationJob) to its background thread
56
//      pool and returns.
57
//    * One of the background threads calls CERT_*Verify*, which may enqueue
58
//      some HTTP request(s) onto the socket transport thread, and then
59
//      blocks that background thread waiting for the responses and/or timeouts
60
//      or errors for those requests.
61
//    * Once those HTTP responses have all come back or failed, the
62
//      CERT_*Verify* function returns a result indicating that the validation
63
//      succeeded or failed.
64
//    * If the validation succeeded, then a SSLServerCertVerificationResult
65
//      event is posted to the socket transport thread, and the cert
66
//      verification thread becomes free to verify other certificates.
67
//    * Otherwise, a CertErrorRunnable is posted to the socket transport thread
68
//      and then to the main thread (blocking both, see CertErrorRunnable) to
69
//      do cert override processing and bad cert listener notification. Then
70
//      the cert verification thread becomes free to verify other certificates.
71
//    * After processing cert overrides, the CertErrorRunnable will dispatch a
72
//      SSLServerCertVerificationResult event to the socket transport thread to
73
//      notify it of the result of the override processing; then it returns,
74
//      freeing up the main thread.
75
//    * The SSLServerCertVerificationResult event will either wake up the
76
//      socket (using SSL_RestartHandshakeAfterServerCert) if validation
77
//      succeeded or there was an error override, or it will set an error flag
78
//      so that the next I/O operation on the socket will fail, causing the
79
//      socket transport thread to close the connection.
80
//
81
// Cert override processing must happen on the main thread because it accesses
82
// the nsICertOverrideService, and that service must be accessed on the main
83
// thread because some extensions (Selenium, in particular) replace it with a
84
// Javascript implementation, and chrome JS must always be run on the main
85
// thread.
86
//
87
// SSLServerCertVerificationResult must be dispatched to the socket transport
88
// thread because we must only call SSL_* functions on the socket transport
89
// thread since they may do I/O, because many parts of nsNSSSocketInfo (the
90
// subclass of TransportSecurityInfo used when validating certificates during
91
// an SSL handshake) and the PSM NSS I/O layer are not thread-safe, and because
92
// we need the event to interrupt the PR_Poll that may waiting for I/O on the
93
// socket for which we are validating the cert.
94
95
#include "SSLServerCertVerification.h"
96
97
#include <cstring>
98
99
#include "BRNameMatchingPolicy.h"
100
#include "CertVerifier.h"
101
#include "CryptoTask.h"
102
#include "ExtendedValidation.h"
103
#include "NSSCertDBTrustDomain.h"
104
#include "PSMRunnable.h"
105
#include "RootCertificateTelemetryUtils.h"
106
#include "ScopedNSSTypes.h"
107
#include "SharedCertVerifier.h"
108
#include "SharedSSLState.h"
109
#include "TransportSecurityInfo.h" // For RememberCertErrorsTable
110
#include "cert.h"
111
#include "mozilla/Assertions.h"
112
#include "mozilla/Casting.h"
113
#include "mozilla/RefPtr.h"
114
#include "mozilla/Telemetry.h"
115
#include "mozilla/UniquePtr.h"
116
#include "mozilla/Unused.h"
117
#include "mozilla/net/DNS.h"
118
#include "nsComponentManagerUtils.h"
119
#include "nsContentUtils.h"
120
#include "nsIBadCertListener2.h"
121
#include "nsICertOverrideService.h"
122
#include "nsISiteSecurityService.h"
123
#include "nsISocketProvider.h"
124
#include "nsThreadPool.h"
125
#include "nsNetUtil.h"
126
#include "nsNSSCertificate.h"
127
#include "nsNSSComponent.h"
128
#include "nsNSSIOLayer.h"
129
#include "nsServiceManagerUtils.h"
130
#include "nsString.h"
131
#include "nsURLHelper.h"
132
#include "nsXPCOMCIDInternal.h"
133
#include "pkix/pkix.h"
134
#include "pkix/pkixnss.h"
135
#include "secerr.h"
136
#include "secoidt.h"
137
#include "secport.h"
138
#include "ssl.h"
139
#include "sslerr.h"
140
141
extern mozilla::LazyLogModule gPIPNSSLog;
142
143
using namespace mozilla::pkix;
144
145
namespace mozilla { namespace psm {
146
147
namespace {
148
149
// do not use a nsCOMPtr to avoid static initializer/destructor
150
nsIThreadPool* gCertVerificationThreadPool = nullptr;
151
152
} // unnamed namespace
153
154
// Called when the socket transport thread starts, to initialize the SSL cert
155
// verification thread pool. By tying the thread pool startup/shutdown directly
156
// to the STS thread's lifetime, we ensure that they are *always* available for
157
// SSL connections and that there are no races during startup and especially
158
// shutdown. (Previously, we have had multiple problems with races in PSM
159
// background threads, and the race-prevention/shutdown logic used there is
160
// brittle. Since this service is critical to things like downloading updates,
161
// we take no chances.) Also, by doing things this way, we avoid the need for
162
// locks, since gCertVerificationThreadPool is only ever accessed on the socket
163
// transport thread.
164
void
165
InitializeSSLServerCertVerificationThreads()
166
3
{
167
3
  // TODO: tuning, make parameters preferences
168
3
  gCertVerificationThreadPool = new nsThreadPool();
169
3
  NS_ADDREF(gCertVerificationThreadPool);
170
3
171
3
  (void) gCertVerificationThreadPool->SetIdleThreadLimit(5);
172
3
  (void) gCertVerificationThreadPool->SetIdleThreadTimeout(30 * 1000);
173
3
  (void) gCertVerificationThreadPool->SetThreadLimit(5);
174
3
  (void) gCertVerificationThreadPool->SetName(NS_LITERAL_CSTRING("SSL Cert"));
175
3
}
176
177
// Called when the socket transport thread finishes, to destroy the thread
178
// pool. Since the socket transport service has stopped processing events, it
179
// will not attempt any more SSL I/O operations, so it is clearly safe to shut
180
// down the SSL cert verification infrastructure. Also, the STS will not
181
// dispatch many SSL verification result events at this point, so any pending
182
// cert verifications will (correctly) fail at the point they are dispatched.
183
//
184
// The other shutdown race condition that is possible is a race condition with
185
// shutdown of the nsNSSComponent service. We use the
186
// nsNSSShutdownPreventionLock where needed (not here) to prevent that.
187
void StopSSLServerCertVerificationThreads()
188
0
{
189
0
  if (gCertVerificationThreadPool) {
190
0
    gCertVerificationThreadPool->Shutdown();
191
0
    NS_RELEASE(gCertVerificationThreadPool);
192
0
  }
193
0
}
194
195
namespace {
196
197
// Dispatched to the STS thread to notify the infoObject of the verification
198
// result.
199
//
200
// This will cause the PR_Poll in the STS thread to return, so things work
201
// correctly even if the STS thread is blocked polling (only) on the file
202
// descriptor that is waiting for this result.
203
class SSLServerCertVerificationResult : public Runnable
204
{
205
public:
206
  NS_DECL_NSIRUNNABLE
207
208
  SSLServerCertVerificationResult(nsNSSSocketInfo* infoObject,
209
                                  PRErrorCode errorCode,
210
                                  Telemetry::HistogramID telemetryID = Telemetry::HistogramCount,
211
                                  uint32_t telemetryValue = -1);
212
213
  void Dispatch();
214
private:
215
  const RefPtr<nsNSSSocketInfo> mInfoObject;
216
public:
217
  const PRErrorCode mErrorCode;
218
  const Telemetry::HistogramID mTelemetryID;
219
  const uint32_t mTelemetryValue;
220
};
221
222
class CertErrorRunnable : public SyncRunnableBase
223
{
224
 public:
225
  CertErrorRunnable(const void* fdForLogging,
226
                    nsIX509Cert* cert,
227
                    nsNSSSocketInfo* infoObject,
228
                    PRErrorCode defaultErrorCodeToReport,
229
                    uint32_t collectedErrors,
230
                    PRErrorCode errorCodeTrust,
231
                    PRErrorCode errorCodeMismatch,
232
                    PRErrorCode errorCodeTime,
233
                    uint32_t providerFlags)
234
    : mFdForLogging(fdForLogging), mCert(cert), mInfoObject(infoObject),
235
      mDefaultErrorCodeToReport(defaultErrorCodeToReport),
236
      mCollectedErrors(collectedErrors),
237
      mErrorCodeTrust(errorCodeTrust),
238
      mErrorCodeMismatch(errorCodeMismatch),
239
      mErrorCodeTime(errorCodeTime),
240
      mProviderFlags(providerFlags)
241
0
  {
242
0
  }
243
244
  virtual void RunOnTargetThread() override;
245
  RefPtr<SSLServerCertVerificationResult> mResult; // out
246
private:
247
  SSLServerCertVerificationResult* CheckCertOverrides();
248
  nsresult OverrideAllowedForHost(/*out*/ bool& overrideAllowed);
249
250
  const void* const mFdForLogging; // may become an invalid pointer; do not dereference
251
  const nsCOMPtr<nsIX509Cert> mCert;
252
  const RefPtr<nsNSSSocketInfo> mInfoObject;
253
  const PRErrorCode mDefaultErrorCodeToReport;
254
  const uint32_t mCollectedErrors;
255
  const PRErrorCode mErrorCodeTrust;
256
  const PRErrorCode mErrorCodeMismatch;
257
  const PRErrorCode mErrorCodeTime;
258
  const uint32_t mProviderFlags;
259
};
260
261
// A probe value of 1 means "no error".
262
uint32_t
263
MapOverridableErrorToProbeValue(PRErrorCode errorCode)
264
0
{
265
0
  switch (errorCode)
266
0
  {
267
0
    case SEC_ERROR_UNKNOWN_ISSUER:                     return  2;
268
0
    case SEC_ERROR_CA_CERT_INVALID:                    return  3;
269
0
    case SEC_ERROR_UNTRUSTED_ISSUER:                   return  4;
270
0
    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:         return  5;
271
0
    case SEC_ERROR_UNTRUSTED_CERT:                     return  6;
272
0
    case SEC_ERROR_INADEQUATE_KEY_USAGE:               return  7;
273
0
    case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:  return  8;
274
0
    case SSL_ERROR_BAD_CERT_DOMAIN:                    return  9;
275
0
    case SEC_ERROR_EXPIRED_CERTIFICATE:                return 10;
276
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY: return 11;
277
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA: return 12;
278
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE: return 13;
279
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE: return 14;
280
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE:
281
0
      return 15;
282
0
    case SEC_ERROR_INVALID_TIME: return 16;
283
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME: return 17;
284
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED:
285
0
      return 18;
286
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT: return 19;
287
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED: return 20;
288
0
  }
289
0
  NS_WARNING("Unknown certificate error code. Does MapOverridableErrorToProbeValue "
290
0
             "handle everything in DetermineCertOverrideErrors?");
291
0
  return 0;
292
0
}
293
294
static uint32_t
295
MapCertErrorToProbeValue(PRErrorCode errorCode)
296
0
{
297
0
  uint32_t probeValue;
298
0
  switch (errorCode)
299
0
  {
300
0
    // see security/pkix/include/pkix/Result.h
301
0
#define MOZILLA_PKIX_MAP(name, value, nss_name) case nss_name: probeValue = value; break;
302
0
    MOZILLA_PKIX_MAP_LIST
303
0
#undef MOZILLA_PKIX_MAP
304
0
    default: return 0;
305
0
  }
306
0
307
0
  // Since FATAL_ERROR_FLAG is 0x800, fatal error values are much larger than
308
0
  // non-fatal error values. To conserve space, we remap these so they start at
309
0
  // (decimal) 90 instead of 0x800. Currently there are ~50 non-fatal errors
310
0
  // mozilla::pkix might return, so saving space for 90 should be sufficient
311
0
  // (similarly, there are 4 fatal errors, so saving space for 10 should also
312
0
  // be sufficient).
313
0
  static_assert(FATAL_ERROR_FLAG == 0x800,
314
0
                "mozilla::pkix::FATAL_ERROR_FLAG is not what we were expecting");
315
0
  if (probeValue & FATAL_ERROR_FLAG) {
316
0
    probeValue ^= FATAL_ERROR_FLAG;
317
0
    probeValue += 90;
318
0
  }
319
0
  return probeValue;
320
0
}
321
322
SECStatus
323
DetermineCertOverrideErrors(const UniqueCERTCertificate& cert,
324
                            const nsACString& hostName,
325
                            PRTime now, PRErrorCode defaultErrorCodeToReport,
326
                            /*out*/ uint32_t& collectedErrors,
327
                            /*out*/ PRErrorCode& errorCodeTrust,
328
                            /*out*/ PRErrorCode& errorCodeMismatch,
329
                            /*out*/ PRErrorCode& errorCodeTime)
330
0
{
331
0
  MOZ_ASSERT(cert);
332
0
  MOZ_ASSERT(collectedErrors == 0);
333
0
  MOZ_ASSERT(errorCodeTrust == 0);
334
0
  MOZ_ASSERT(errorCodeMismatch == 0);
335
0
  MOZ_ASSERT(errorCodeTime == 0);
336
0
337
0
  // Assumes the error prioritization described in mozilla::pkix's
338
0
  // BuildForward function. Also assumes that CheckCertHostname was only
339
0
  // called if CertVerifier::VerifyCert succeeded.
340
0
  switch (defaultErrorCodeToReport) {
341
0
    case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
342
0
    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
343
0
    case SEC_ERROR_UNKNOWN_ISSUER:
344
0
    case SEC_ERROR_CA_CERT_INVALID:
345
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_ADDITIONAL_POLICY_CONSTRAINT_FAILED:
346
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY:
347
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME:
348
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE:
349
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_MITM_DETECTED:
350
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE:
351
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT:
352
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA:
353
0
    {
354
0
      collectedErrors = nsICertOverrideService::ERROR_UNTRUSTED;
355
0
      errorCodeTrust = defaultErrorCodeToReport;
356
0
357
0
      SECCertTimeValidity validity = CERT_CheckCertValidTimes(cert.get(), now,
358
0
                                                              false);
359
0
      if (validity == secCertTimeUndetermined) {
360
0
        // This only happens if cert is null. CERT_CheckCertValidTimes will
361
0
        // have set the error code to SEC_ERROR_INVALID_ARGS. We should really
362
0
        // be using mozilla::pkix here anyway.
363
0
        MOZ_ASSERT(PR_GetError() == SEC_ERROR_INVALID_ARGS);
364
0
        return SECFailure;
365
0
      }
366
0
      if (validity == secCertTimeExpired) {
367
0
        collectedErrors |= nsICertOverrideService::ERROR_TIME;
368
0
        errorCodeTime = SEC_ERROR_EXPIRED_CERTIFICATE;
369
0
      } else if (validity == secCertTimeNotValidYet) {
370
0
        collectedErrors |= nsICertOverrideService::ERROR_TIME;
371
0
        errorCodeTime =
372
0
          mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE;
373
0
      }
374
0
      break;
375
0
    }
376
0
377
0
    case SEC_ERROR_INVALID_TIME:
378
0
    case SEC_ERROR_EXPIRED_CERTIFICATE:
379
0
    case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE:
380
0
      collectedErrors = nsICertOverrideService::ERROR_TIME;
381
0
      errorCodeTime = defaultErrorCodeToReport;
382
0
      break;
383
0
384
0
    case SSL_ERROR_BAD_CERT_DOMAIN:
385
0
      collectedErrors = nsICertOverrideService::ERROR_MISMATCH;
386
0
      errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
387
0
      break;
388
0
389
0
    case 0:
390
0
      NS_ERROR("No error code set during certificate validation failure.");
391
0
      PR_SetError(PR_INVALID_STATE_ERROR, 0);
392
0
      return SECFailure;
393
0
394
0
    default:
395
0
      PR_SetError(defaultErrorCodeToReport, 0);
396
0
      return SECFailure;
397
0
  }
398
0
399
0
  if (defaultErrorCodeToReport != SSL_ERROR_BAD_CERT_DOMAIN) {
400
0
    Input certInput;
401
0
    if (certInput.Init(cert->derCert.data, cert->derCert.len) != Success) {
402
0
      PR_SetError(SEC_ERROR_BAD_DER, 0);
403
0
      return SECFailure;
404
0
    }
405
0
    Input hostnameInput;
406
0
    Result result = hostnameInput.Init(
407
0
      BitwiseCast<const uint8_t*, const char*>(hostName.BeginReading()),
408
0
      hostName.Length());
409
0
    if (result != Success) {
410
0
      PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
411
0
      return SECFailure;
412
0
    }
413
0
    // Use a lax policy so as to not generate potentially spurious name
414
0
    // mismatch "hints".
415
0
    BRNameMatchingPolicy nameMatchingPolicy(
416
0
      BRNameMatchingPolicy::Mode::DoNotEnforce);
417
0
    // CheckCertHostname expects that its input represents a certificate that
418
0
    // has already been successfully validated by BuildCertChain. This is
419
0
    // obviously not the case, however, because we're in the error path of
420
0
    // certificate verification. Thus, this is problematic. In the future, it
421
0
    // would be nice to remove this optimistic additional error checking and
422
0
    // simply punt to the front-end, which can more easily (and safely) perform
423
0
    // extra checks to give the user hints as to why verification failed.
424
0
    result = CheckCertHostname(certInput, hostnameInput, nameMatchingPolicy);
425
0
    // Treat malformed name information as a domain mismatch.
426
0
    if (result == Result::ERROR_BAD_DER ||
427
0
        result == Result::ERROR_BAD_CERT_DOMAIN) {
428
0
      collectedErrors |= nsICertOverrideService::ERROR_MISMATCH;
429
0
      errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
430
0
    } else if (IsFatalError(result)) {
431
0
      // Because its input has not been validated by BuildCertChain,
432
0
      // CheckCertHostname can return an error that is less important than the
433
0
      // original certificate verification error. Only return an error result
434
0
      // from this function if we've encountered a fatal error.
435
0
      PR_SetError(MapResultToPRErrorCode(result), 0);
436
0
      return SECFailure;
437
0
    }
438
0
  }
439
0
440
0
  return SECSuccess;
441
0
}
442
443
// Helper function to determine if overrides are allowed for this host.
444
// Overrides are not allowed for known HSTS or HPKP hosts. However, an IP
445
// address is never considered an HSTS or HPKP host.
446
nsresult
447
CertErrorRunnable::OverrideAllowedForHost(/*out*/ bool& overrideAllowed)
448
0
{
449
0
  overrideAllowed = false;
450
0
451
0
  // If this is an IP address, overrides are allowed, because an IP address is
452
0
  // never an HSTS or HPKP host. nsISiteSecurityService takes this into account
453
0
  // already, but the real problem here is that calling NS_NewURI with an IPv6
454
0
  // address fails. We do this to avoid that. A more comprehensive fix would be
455
0
  // to have Necko provide an nsIURI to PSM and to use that here (and
456
0
  // everywhere). However, that would be a wide-spanning change.
457
0
  const nsACString& hostname = mInfoObject->GetHostName();
458
0
  if (net_IsValidIPv6Addr(hostname.BeginReading(), hostname.Length())) {
459
0
    overrideAllowed = true;
460
0
    return NS_OK;
461
0
  }
462
0
463
0
  // If this is an HTTP Strict Transport Security host or a pinned host and the
464
0
  // certificate is bad, don't allow overrides (RFC 6797 section 12.1,
465
0
  // HPKP draft spec section 2.6).
466
0
  bool strictTransportSecurityEnabled = false;
467
0
  bool hasPinningInformation = false;
468
0
  nsCOMPtr<nsISiteSecurityService> sss(do_GetService(NS_SSSERVICE_CONTRACTID));
469
0
  if (!sss) {
470
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
471
0
            ("[%p][%p] couldn't get nsISiteSecurityService to check HSTS/HPKP",
472
0
            mFdForLogging, this));
473
0
    return NS_ERROR_FAILURE;
474
0
  }
475
0
  nsCOMPtr<nsIURI> uri;
476
0
  nsresult rv = NS_NewURI(getter_AddRefs(uri),
477
0
                          NS_LITERAL_CSTRING("https://") + hostname);
478
0
  if (NS_FAILED(rv)) {
479
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
480
0
            ("[%p][%p] Creating new URI failed", mFdForLogging, this));
481
0
    return rv;
482
0
  }
483
0
  rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS,
484
0
                        uri,
485
0
                        mProviderFlags,
486
0
                        mInfoObject->GetOriginAttributes(),
487
0
                        nullptr,
488
0
                        nullptr,
489
0
                        &strictTransportSecurityEnabled);
490
0
  if (NS_FAILED(rv)) {
491
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
492
0
            ("[%p][%p] checking for HSTS failed", mFdForLogging, this));
493
0
    return rv;
494
0
  }
495
0
  rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HPKP,
496
0
                        uri,
497
0
                        mProviderFlags,
498
0
                        mInfoObject->GetOriginAttributes(),
499
0
                        nullptr,
500
0
                        nullptr,
501
0
                        &hasPinningInformation);
502
0
  if (NS_FAILED(rv)) {
503
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
504
0
            ("[%p][%p] checking for HPKP failed", mFdForLogging, this));
505
0
    return rv;
506
0
  }
507
0
508
0
  overrideAllowed = !strictTransportSecurityEnabled && !hasPinningInformation;
509
0
  return NS_OK;
510
0
}
511
512
SSLServerCertVerificationResult*
513
CertErrorRunnable::CheckCertOverrides()
514
0
{
515
0
  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("[%p][%p] top of CheckCertOverrides\n",
516
0
                                    mFdForLogging, this));
517
0
  // "Use" mFdForLogging in non-PR_LOGGING builds, too, to suppress
518
0
  // clang's -Wunused-private-field build warning for this variable:
519
0
  Unused << mFdForLogging;
520
0
521
0
  if (!NS_IsMainThread()) {
522
0
    NS_ERROR("CertErrorRunnable::CheckCertOverrides called off main thread");
523
0
    return new SSLServerCertVerificationResult(mInfoObject,
524
0
                                               mDefaultErrorCodeToReport);
525
0
  }
526
0
527
0
  int32_t port = mInfoObject->GetPort();
528
0
529
0
  nsAutoCString hostWithPortString(mInfoObject->GetHostName());
530
0
  hostWithPortString.Append(':');
531
0
  hostWithPortString.AppendInt(port);
532
0
533
0
  uint32_t remaining_display_errors = mCollectedErrors;
534
0
535
0
  bool overrideAllowed;
536
0
  if (NS_FAILED(OverrideAllowedForHost(overrideAllowed))) {
537
0
    return new SSLServerCertVerificationResult(mInfoObject,
538
0
                                               mDefaultErrorCodeToReport);
539
0
  }
540
0
541
0
  if (overrideAllowed) {
542
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
543
0
           ("[%p][%p] no HSTS or HPKP - overrides allowed\n",
544
0
            mFdForLogging, this));
545
0
    nsCOMPtr<nsICertOverrideService> overrideService =
546
0
      do_GetService(NS_CERTOVERRIDE_CONTRACTID);
547
0
    // it is fine to continue without the nsICertOverrideService
548
0
549
0
    uint32_t overrideBits = 0;
550
0
551
0
    if (overrideService) {
552
0
      bool haveOverride;
553
0
      bool isTemporaryOverride; // we don't care
554
0
      const nsACString& hostString(mInfoObject->GetHostName());
555
0
      nsresult rv = overrideService->HasMatchingOverride(hostString, port,
556
0
                                                         mCert,
557
0
                                                         &overrideBits,
558
0
                                                         &isTemporaryOverride,
559
0
                                                         &haveOverride);
560
0
      if (NS_SUCCEEDED(rv) && haveOverride) {
561
0
       // remove the errors that are already overriden
562
0
        remaining_display_errors &= ~overrideBits;
563
0
      }
564
0
    }
565
0
566
0
    if (!remaining_display_errors) {
567
0
      // This can double- or triple-count one certificate with multiple
568
0
      // different types of errors. Since this is telemetry and we just
569
0
      // want a ballpark answer, we don't care.
570
0
      if (mErrorCodeTrust != 0) {
571
0
        uint32_t probeValue = MapOverridableErrorToProbeValue(mErrorCodeTrust);
572
0
        Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, probeValue);
573
0
      }
574
0
      if (mErrorCodeMismatch != 0) {
575
0
        uint32_t probeValue = MapOverridableErrorToProbeValue(mErrorCodeMismatch);
576
0
        Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, probeValue);
577
0
      }
578
0
      if (mErrorCodeTime != 0) {
579
0
        uint32_t probeValue = MapOverridableErrorToProbeValue(mErrorCodeTime);
580
0
        Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, probeValue);
581
0
      }
582
0
583
0
      // all errors are covered by override rules, so let's accept the cert
584
0
      MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
585
0
             ("[%p][%p] All errors covered by override rules\n",
586
0
             mFdForLogging, this));
587
0
      return new SSLServerCertVerificationResult(mInfoObject, 0);
588
0
    }
589
0
  } else {
590
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
591
0
           ("[%p][%p] HSTS or HPKP - no overrides allowed\n",
592
0
            mFdForLogging, this));
593
0
  }
594
0
595
0
  MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
596
0
         ("[%p][%p] Certificate error was not overridden\n",
597
0
         mFdForLogging, this));
598
0
599
0
  // Ok, this is a full stop.
600
0
  // First, deliver the technical details of the broken SSL status.
601
0
602
0
  // Try to get a nsIBadCertListener2 implementation from the socket consumer.
603
0
  nsCOMPtr<nsISSLSocketControl> sslSocketControl = do_QueryInterface(
604
0
    NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, mInfoObject));
605
0
  if (sslSocketControl) {
606
0
    nsCOMPtr<nsIInterfaceRequestor> cb;
607
0
    sslSocketControl->GetNotificationCallbacks(getter_AddRefs(cb));
608
0
    if (cb) {
609
0
      nsCOMPtr<nsIBadCertListener2> bcl = do_GetInterface(cb);
610
0
      if (bcl) {
611
0
        nsIInterfaceRequestor* csi
612
0
          = static_cast<nsIInterfaceRequestor*>(mInfoObject);
613
0
        bool suppressMessage = false; // obsolete, ignored
614
0
        Unused << bcl->NotifyCertProblem(csi, mInfoObject,
615
0
                                         hostWithPortString, &suppressMessage);
616
0
      }
617
0
    }
618
0
  }
619
0
620
0
  // pick the error code to report by priority
621
0
  PRErrorCode errorCodeToReport = mErrorCodeTrust    ? mErrorCodeTrust
622
0
                                : mErrorCodeMismatch ? mErrorCodeMismatch
623
0
                                : mErrorCodeTime     ? mErrorCodeTime
624
0
                                : mDefaultErrorCodeToReport;
625
0
626
0
  SSLServerCertVerificationResult* result =
627
0
    new SSLServerCertVerificationResult(mInfoObject,
628
0
                                        errorCodeToReport,
629
0
                                        Telemetry::HistogramCount,
630
0
                                        -1);
631
0
632
0
  return result;
633
0
}
634
635
void
636
CertErrorRunnable::RunOnTargetThread()
637
0
{
638
0
  MOZ_ASSERT(NS_IsMainThread());
639
0
640
0
  mResult = CheckCertOverrides();
641
0
642
0
  MOZ_ASSERT(mResult);
643
0
}
644
645
// Returns null with the error code (PR_GetError()) set if it does not create
646
// the CertErrorRunnable.
647
CertErrorRunnable*
648
CreateCertErrorRunnable(CertVerifier& certVerifier,
649
                        PRErrorCode defaultErrorCodeToReport,
650
                        nsNSSSocketInfo* infoObject,
651
                        const UniqueCERTCertificate& cert,
652
                        const void* fdForLogging,
653
                        uint32_t providerFlags,
654
                        PRTime now)
655
0
{
656
0
  MOZ_ASSERT(infoObject);
657
0
  MOZ_ASSERT(cert);
658
0
659
0
  uint32_t probeValue = MapCertErrorToProbeValue(defaultErrorCodeToReport);
660
0
  Telemetry::Accumulate(Telemetry::SSL_CERT_VERIFICATION_ERRORS, probeValue);
661
0
662
0
  uint32_t collected_errors = 0;
663
0
  PRErrorCode errorCodeTrust = 0;
664
0
  PRErrorCode errorCodeMismatch = 0;
665
0
  PRErrorCode errorCodeTime = 0;
666
0
  if (DetermineCertOverrideErrors(cert, infoObject->GetHostName(), now,
667
0
                                  defaultErrorCodeToReport, collected_errors,
668
0
                                  errorCodeTrust, errorCodeMismatch,
669
0
                                  errorCodeTime) != SECSuccess) {
670
0
    // Attempt to enforce that if DetermineCertOverrideErrors failed,
671
0
    // PR_SetError was set with a non-overridable error. This is because if we
672
0
    // return from CreateCertErrorRunnable without calling
673
0
    // infoObject->SetStatusErrorBits, we won't have the required information
674
0
    // to actually add a certificate error override. This results in a broken
675
0
    // UI which is annoying but not a security disaster.
676
0
    MOZ_ASSERT(!ErrorIsOverridable(PR_GetError()));
677
0
    return nullptr;
678
0
  }
679
0
680
0
  RefPtr<nsNSSCertificate> nssCert(nsNSSCertificate::Create(cert.get()));
681
0
  if (!nssCert) {
682
0
    NS_ERROR("nsNSSCertificate::Create failed");
683
0
    PR_SetError(SEC_ERROR_NO_MEMORY, 0);
684
0
    return nullptr;
685
0
  }
686
0
687
0
  if (!collected_errors) {
688
0
    // This will happen when CERT_*Verify* only returned error(s) that are
689
0
    // not on our whitelist of overridable certificate errors.
690
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("[%p] !collected_errors: %d\n",
691
0
           fdForLogging, static_cast<int>(defaultErrorCodeToReport)));
692
0
    PR_SetError(defaultErrorCodeToReport, 0);
693
0
    return nullptr;
694
0
  }
695
0
696
0
  infoObject->SetStatusErrorBits(nssCert, collected_errors);
697
0
698
0
  return new CertErrorRunnable(fdForLogging,
699
0
                               static_cast<nsIX509Cert*>(nssCert.get()),
700
0
                               infoObject, defaultErrorCodeToReport,
701
0
                               collected_errors, errorCodeTrust,
702
0
                               errorCodeMismatch, errorCodeTime,
703
0
                               providerFlags);
704
0
}
705
706
// When doing async cert processing, we dispatch one of these runnables to the
707
// socket transport service thread, which blocks the socket transport
708
// service thread while it waits for the inner CertErrorRunnable to execute
709
// CheckCertOverrides on the main thread. CheckCertOverrides must block events
710
// on both of these threads because it calls TransportSecurityInfo::GetInterface(),
711
// which may call nsHttpConnection::GetInterface() through
712
// TransportSecurityInfo::mCallbacks. nsHttpConnection::GetInterface must always
713
// execute on the main thread, with the socket transport service thread
714
// blocked.
715
class CertErrorRunnableRunnable : public Runnable
716
{
717
public:
718
  explicit CertErrorRunnableRunnable(CertErrorRunnable* certErrorRunnable)
719
    : Runnable("psm::CertErrorRunnableRunnable")
720
    , mCertErrorRunnable(certErrorRunnable)
721
0
  {
722
0
  }
723
private:
724
  NS_IMETHOD Run() override
725
0
  {
726
0
    nsresult rv = mCertErrorRunnable->DispatchToMainThreadAndWait();
727
0
    // The result must run on the socket transport thread, which we are already
728
0
    // on, so we can just run it directly, instead of dispatching it.
729
0
    if (NS_SUCCEEDED(rv)) {
730
0
      rv = mCertErrorRunnable->mResult ? mCertErrorRunnable->mResult->Run()
731
0
                                       : NS_ERROR_UNEXPECTED;
732
0
    }
733
0
    return rv;
734
0
  }
735
  RefPtr<CertErrorRunnable> mCertErrorRunnable;
736
};
737
738
class SSLServerCertVerificationJob : public Runnable
739
{
740
public:
741
  // Must be called only on the socket transport thread
742
  static SECStatus Dispatch(const RefPtr<SharedCertVerifier>& certVerifier,
743
                            const void* fdForLogging,
744
                            nsNSSSocketInfo* infoObject,
745
                            const UniqueCERTCertificate& serverCert,
746
                            const UniqueCERTCertList& peerCertChain,
747
                            const SECItem* stapledOCSPResponse,
748
                            const SECItem* sctsFromTLSExtension,
749
                            uint32_t providerFlags,
750
                            Time time,
751
                            PRTime prtime);
752
private:
753
  NS_DECL_NSIRUNNABLE
754
755
  // Must be called only on the socket transport thread
756
  SSLServerCertVerificationJob(const RefPtr<SharedCertVerifier>& certVerifier,
757
                               const void* fdForLogging,
758
                               nsNSSSocketInfo* infoObject,
759
                               const UniqueCERTCertificate& cert,
760
                               UniqueCERTCertList peerCertChain,
761
                               const SECItem* stapledOCSPResponse,
762
                               const SECItem* sctsFromTLSExtension,
763
                               uint32_t providerFlags,
764
                               Time time,
765
                               PRTime prtime);
766
  const RefPtr<SharedCertVerifier> mCertVerifier;
767
  const void* const mFdForLogging;
768
  const RefPtr<nsNSSSocketInfo> mInfoObject;
769
  const UniqueCERTCertificate mCert;
770
  UniqueCERTCertList mPeerCertChain;
771
  const uint32_t mProviderFlags;
772
  const Time mTime;
773
  const PRTime mPRTime;
774
  const TimeStamp mJobStartTime;
775
  const UniqueSECItem mStapledOCSPResponse;
776
  const UniqueSECItem mSCTsFromTLSExtension;
777
};
778
779
SSLServerCertVerificationJob::SSLServerCertVerificationJob(
780
  const RefPtr<SharedCertVerifier>& certVerifier,
781
  const void* fdForLogging,
782
  nsNSSSocketInfo* infoObject,
783
  const UniqueCERTCertificate& cert,
784
  UniqueCERTCertList peerCertChain,
785
  const SECItem* stapledOCSPResponse,
786
  const SECItem* sctsFromTLSExtension,
787
  uint32_t providerFlags,
788
  Time time,
789
  PRTime prtime)
790
  : Runnable("psm::SSLServerCertVerificationJob")
791
  , mCertVerifier(certVerifier)
792
  , mFdForLogging(fdForLogging)
793
  , mInfoObject(infoObject)
794
  , mCert(CERT_DupCertificate(cert.get()))
795
  , mPeerCertChain(std::move(peerCertChain))
796
  , mProviderFlags(providerFlags)
797
  , mTime(time)
798
  , mPRTime(prtime)
799
  , mJobStartTime(TimeStamp::Now())
800
  , mStapledOCSPResponse(SECITEM_DupItem(stapledOCSPResponse))
801
  , mSCTsFromTLSExtension(SECITEM_DupItem(sctsFromTLSExtension))
802
0
{
803
0
}
804
805
// This function assumes that we will only use the SPDY connection coalescing
806
// feature on connections where we have negotiated SPDY using NPN. If we ever
807
// talk SPDY without having negotiated it with SPDY, this code will give wrong
808
// and perhaps unsafe results.
809
//
810
// Returns SECSuccess on the initial handshake of all connections, on
811
// renegotiations for any connections where we did not negotiate SPDY, or on any
812
// SPDY connection where the server's certificate did not change.
813
//
814
// Prohibit changing the server cert only if we negotiated SPDY,
815
// in order to support SPDY's cross-origin connection pooling.
816
static SECStatus
817
BlockServerCertChangeForSpdy(nsNSSSocketInfo* infoObject,
818
                             const UniqueCERTCertificate& serverCert)
819
0
{
820
0
  // Get the existing cert. If there isn't one, then there is
821
0
  // no cert change to worry about.
822
0
  nsCOMPtr<nsIX509Cert> cert;
823
0
824
0
  if (!infoObject->IsHandshakeCompleted()) {
825
0
    // first handshake on this connection, not a
826
0
    // renegotiation.
827
0
    return SECSuccess;
828
0
  }
829
0
830
0
  infoObject->GetServerCert(getter_AddRefs(cert));
831
0
  if (!cert) {
832
0
    MOZ_ASSERT_UNREACHABLE(
833
0
             "TransportSecurityInfo must have a cert implementing nsIX509Cert");
834
0
    PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
835
0
    return SECFailure;
836
0
  }
837
0
838
0
  // Filter out sockets that did not neogtiate SPDY via NPN
839
0
  nsAutoCString negotiatedNPN;
840
0
  nsresult rv = infoObject->GetNegotiatedNPN(negotiatedNPN);
841
0
  MOZ_ASSERT(NS_SUCCEEDED(rv), "GetNegotiatedNPN() failed during renegotiation");
842
0
843
0
  if (NS_SUCCEEDED(rv) && !StringBeginsWith(negotiatedNPN,
844
0
                                            NS_LITERAL_CSTRING("spdy/"))) {
845
0
    return SECSuccess;
846
0
  }
847
0
  // If GetNegotiatedNPN() failed we will assume spdy for safety's safe
848
0
  if (NS_FAILED(rv)) {
849
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
850
0
           ("BlockServerCertChangeForSpdy failed GetNegotiatedNPN() call."
851
0
            " Assuming spdy.\n"));
852
0
  }
853
0
854
0
  // Check to see if the cert has actually changed
855
0
  UniqueCERTCertificate c(cert->GetCert());
856
0
  MOZ_ASSERT(c, "Somehow couldn't get underlying cert from nsIX509Cert");
857
0
  bool sameCert = CERT_CompareCerts(c.get(), serverCert.get());
858
0
  if (sameCert) {
859
0
    return SECSuccess;
860
0
  }
861
0
862
0
  // Report an error - changed cert is confirmed
863
0
  MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
864
0
         ("SPDY Refused to allow new cert during renegotiation\n"));
865
0
  PR_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, 0);
866
0
  return SECFailure;
867
0
}
868
869
void
870
AccumulateSubjectCommonNameTelemetry(const char* commonName,
871
                                     bool commonNameInSubjectAltNames)
872
0
{
873
0
  if (!commonName) {
874
0
    // 1 means no common name present
875
0
    Telemetry::Accumulate(Telemetry::BR_9_2_2_SUBJECT_COMMON_NAME, 1);
876
0
  } else if (!commonNameInSubjectAltNames) {
877
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
878
0
           ("BR telemetry: common name '%s' not in subject alt. names "
879
0
            "(or the subject alt. names extension is not present)\n",
880
0
            commonName));
881
0
    // 2 means the common name is not present in subject alt names
882
0
    Telemetry::Accumulate(Telemetry::BR_9_2_2_SUBJECT_COMMON_NAME, 2);
883
0
  } else {
884
0
    // 0 means the common name is present in subject alt names
885
0
    Telemetry::Accumulate(Telemetry::BR_9_2_2_SUBJECT_COMMON_NAME, 0);
886
0
  }
887
0
}
888
889
// Returns true if and only if commonName ends with altName (minus its leading
890
// "*"). altName has already been checked to be of the form "*.<something>".
891
// commonName may be NULL.
892
static bool
893
TryMatchingWildcardSubjectAltName(const char* commonName,
894
                                  const nsACString& altName)
895
0
{
896
0
  return commonName &&
897
0
         StringEndsWith(nsDependentCString(commonName), Substring(altName, 1));
898
0
}
899
900
// Gathers telemetry on Baseline Requirements 9.2.1 (Subject Alternative
901
// Names Extension) and 9.2.2 (Subject Common Name Field).
902
// Specifically:
903
//  - whether or not the subject common name field is present
904
//  - whether or not the subject alternative names extension is present
905
//  - if there is a malformed entry in the subject alt. names extension
906
//  - if there is an entry in the subject alt. names extension corresponding
907
//    to the subject common name
908
// Telemetry is only gathered for certificates that chain to a trusted root
909
// in Mozilla's Root CA program.
910
// certList consists of a validated certificate chain. The end-entity
911
// certificate is first and the root (trust anchor) is last.
912
void
913
GatherBaselineRequirementsTelemetry(const UniqueCERTCertList& certList)
914
0
{
915
0
  CERTCertListNode* endEntityNode = CERT_LIST_HEAD(certList);
916
0
  CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
917
0
  MOZ_ASSERT(!(CERT_LIST_END(endEntityNode, certList) ||
918
0
               CERT_LIST_END(rootNode, certList)));
919
0
  if (CERT_LIST_END(endEntityNode, certList) ||
920
0
      CERT_LIST_END(rootNode, certList)) {
921
0
    return;
922
0
  }
923
0
  CERTCertificate* cert = endEntityNode->cert;
924
0
  MOZ_ASSERT(cert);
925
0
  if (!cert) {
926
0
    return;
927
0
  }
928
0
  UniquePORTString commonName(CERT_GetCommonName(&cert->subject));
929
0
  // This only applies to certificates issued by authorities in our root
930
0
  // program.
931
0
  CERTCertificate* rootCert = rootNode->cert;
932
0
  MOZ_ASSERT(rootCert);
933
0
  if (!rootCert) {
934
0
    return;
935
0
  }
936
0
  bool isBuiltIn = false;
937
0
  Result result = IsCertBuiltInRoot(rootCert, isBuiltIn);
938
0
  if (result != Success || !isBuiltIn) {
939
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
940
0
           ("BR telemetry: root certificate for '%s' is not a built-in root "
941
0
            "(or IsCertBuiltInRoot failed)\n", commonName.get()));
942
0
    return;
943
0
  }
944
0
  ScopedAutoSECItem altNameExtension;
945
0
  SECStatus rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME,
946
0
                                        &altNameExtension);
947
0
  if (rv != SECSuccess) {
948
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
949
0
           ("BR telemetry: no subject alt names extension for '%s'\n",
950
0
            commonName.get()));
951
0
    // 1 means there is no subject alt names extension
952
0
    Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 1);
953
0
    AccumulateSubjectCommonNameTelemetry(commonName.get(), false);
954
0
    return;
955
0
  }
956
0
957
0
  UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
958
0
  CERTGeneralName* subjectAltNames =
959
0
    CERT_DecodeAltNameExtension(arena.get(), &altNameExtension);
960
0
  if (!subjectAltNames) {
961
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
962
0
           ("BR telemetry: could not decode subject alt names for '%s'\n",
963
0
            commonName.get()));
964
0
    // 2 means the subject alt names extension could not be decoded
965
0
    Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 2);
966
0
    AccumulateSubjectCommonNameTelemetry(commonName.get(), false);
967
0
    return;
968
0
  }
969
0
970
0
  CERTGeneralName* currentName = subjectAltNames;
971
0
  bool commonNameInSubjectAltNames = false;
972
0
  bool nonDNSNameOrIPAddressPresent = false;
973
0
  bool malformedDNSNameOrIPAddressPresent = false;
974
0
  bool nonFQDNPresent = false;
975
0
  do {
976
0
    nsAutoCString altName;
977
0
    if (currentName->type == certDNSName) {
978
0
      altName.Assign(BitwiseCast<char*, unsigned char*>(
979
0
                       currentName->name.other.data),
980
0
                     currentName->name.other.len);
981
0
      nsDependentCString altNameWithoutWildcard(altName, 0);
982
0
      if (StringBeginsWith(altNameWithoutWildcard, NS_LITERAL_CSTRING("*."))) {
983
0
        altNameWithoutWildcard.Rebind(altName, 2);
984
0
        commonNameInSubjectAltNames |=
985
0
          TryMatchingWildcardSubjectAltName(commonName.get(), altName);
986
0
      }
987
0
      // net_IsValidHostName appears to return true for valid IP addresses,
988
0
      // which would be invalid for a DNS name.
989
0
      // Note that the net_IsValidHostName check will catch things like
990
0
      // "a.*.example.com".
991
0
      if (!net_IsValidHostName(altNameWithoutWildcard) ||
992
0
          net_IsValidIPv4Addr(altName.get(), altName.Length()) ||
993
0
          net_IsValidIPv6Addr(altName.get(), altName.Length())) {
994
0
        MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
995
0
               ("BR telemetry: DNSName '%s' not valid (for '%s')\n",
996
0
                altName.get(), commonName.get()));
997
0
        malformedDNSNameOrIPAddressPresent = true;
998
0
      }
999
0
      if (!altName.Contains('.')) {
1000
0
        nonFQDNPresent = true;
1001
0
      }
1002
0
    } else if (currentName->type == certIPAddress) {
1003
0
      // According to DNS.h, this includes space for the null-terminator
1004
0
      char buf[net::kNetAddrMaxCStrBufSize] = { 0 };
1005
0
      PRNetAddr addr;
1006
0
      if (currentName->name.other.len == 4) {
1007
0
        addr.inet.family = PR_AF_INET;
1008
0
        memcpy(&addr.inet.ip, currentName->name.other.data,
1009
0
               currentName->name.other.len);
1010
0
        if (PR_NetAddrToString(&addr, buf, sizeof(buf) - 1) != PR_SUCCESS) {
1011
0
        MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1012
0
               ("BR telemetry: IPAddress (v4) not valid (for '%s')\n",
1013
0
                commonName.get()));
1014
0
          malformedDNSNameOrIPAddressPresent = true;
1015
0
        } else {
1016
0
          altName.Assign(buf);
1017
0
        }
1018
0
      } else if (currentName->name.other.len == 16) {
1019
0
        addr.inet.family = PR_AF_INET6;
1020
0
        memcpy(&addr.ipv6.ip, currentName->name.other.data,
1021
0
               currentName->name.other.len);
1022
0
        if (PR_NetAddrToString(&addr, buf, sizeof(buf) - 1) != PR_SUCCESS) {
1023
0
        MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1024
0
               ("BR telemetry: IPAddress (v6) not valid (for '%s')\n",
1025
0
                commonName.get()));
1026
0
          malformedDNSNameOrIPAddressPresent = true;
1027
0
        } else {
1028
0
          altName.Assign(buf);
1029
0
        }
1030
0
      } else {
1031
0
        MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1032
0
               ("BR telemetry: IPAddress not valid (for '%s')\n",
1033
0
                commonName.get()));
1034
0
        malformedDNSNameOrIPAddressPresent = true;
1035
0
      }
1036
0
    } else {
1037
0
      MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1038
0
             ("BR telemetry: non-DNSName, non-IPAddress present for '%s'\n",
1039
0
              commonName.get()));
1040
0
      nonDNSNameOrIPAddressPresent = true;
1041
0
    }
1042
0
    if (commonName && altName.Equals(commonName.get())) {
1043
0
      commonNameInSubjectAltNames = true;
1044
0
    }
1045
0
    currentName = CERT_GetNextGeneralName(currentName);
1046
0
  } while (currentName && currentName != subjectAltNames);
1047
0
1048
0
  if (nonDNSNameOrIPAddressPresent) {
1049
0
    // 3 means there's an entry that isn't an ip address or dns name
1050
0
    Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 3);
1051
0
  }
1052
0
  if (malformedDNSNameOrIPAddressPresent) {
1053
0
    // 4 means there's a malformed ip address or dns name entry
1054
0
    Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 4);
1055
0
  }
1056
0
  if (nonFQDNPresent) {
1057
0
    // 5 means there's a DNS name entry with a non-fully-qualified domain name
1058
0
    Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 5);
1059
0
  }
1060
0
  if (!nonDNSNameOrIPAddressPresent && !malformedDNSNameOrIPAddressPresent &&
1061
0
      !nonFQDNPresent) {
1062
0
    // 0 means the extension is acceptable
1063
0
    Telemetry::Accumulate(Telemetry::BR_9_2_1_SUBJECT_ALT_NAMES, 0);
1064
0
  }
1065
0
1066
0
  AccumulateSubjectCommonNameTelemetry(commonName.get(),
1067
0
                                       commonNameInSubjectAltNames);
1068
0
}
1069
1070
// Gather telemetry on whether the end-entity cert for a server has the
1071
// required TLS Server Authentication EKU, or any others
1072
void
1073
GatherEKUTelemetry(const UniqueCERTCertList& certList)
1074
0
{
1075
0
  CERTCertListNode* endEntityNode = CERT_LIST_HEAD(certList);
1076
0
  CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
1077
0
  MOZ_ASSERT(!(CERT_LIST_END(endEntityNode, certList) ||
1078
0
               CERT_LIST_END(rootNode, certList)));
1079
0
  if (CERT_LIST_END(endEntityNode, certList) ||
1080
0
      CERT_LIST_END(rootNode, certList)) {
1081
0
    return;
1082
0
  }
1083
0
  CERTCertificate* endEntityCert = endEntityNode->cert;
1084
0
  MOZ_ASSERT(endEntityCert);
1085
0
  if (!endEntityCert) {
1086
0
    return;
1087
0
  }
1088
0
1089
0
  // Only log telemetry if the root CA is built-in
1090
0
  CERTCertificate* rootCert = rootNode->cert;
1091
0
  MOZ_ASSERT(rootCert);
1092
0
  if (!rootCert) {
1093
0
    return;
1094
0
  }
1095
0
  bool isBuiltIn = false;
1096
0
  Result rv = IsCertBuiltInRoot(rootCert, isBuiltIn);
1097
0
  if (rv != Success || !isBuiltIn) {
1098
0
    return;
1099
0
  }
1100
0
1101
0
  // Find the EKU extension, if present
1102
0
  bool foundEKU = false;
1103
0
  SECOidTag oidTag;
1104
0
  CERTCertExtension* ekuExtension = nullptr;
1105
0
  for (size_t i = 0; endEntityCert->extensions && endEntityCert->extensions[i];
1106
0
       i++) {
1107
0
    oidTag = SECOID_FindOIDTag(&endEntityCert->extensions[i]->id);
1108
0
    if (oidTag == SEC_OID_X509_EXT_KEY_USAGE) {
1109
0
      foundEKU = true;
1110
0
      ekuExtension = endEntityCert->extensions[i];
1111
0
    }
1112
0
  }
1113
0
1114
0
  if (!foundEKU) {
1115
0
    Telemetry::Accumulate(Telemetry::SSL_SERVER_AUTH_EKU, 0);
1116
0
    return;
1117
0
  }
1118
0
1119
0
  // Parse the EKU extension
1120
0
  UniqueCERTOidSequence ekuSequence(
1121
0
    CERT_DecodeOidSequence(&ekuExtension->value));
1122
0
  if (!ekuSequence) {
1123
0
    return;
1124
0
  }
1125
0
1126
0
  // Search through the available EKUs
1127
0
  bool foundServerAuth = false;
1128
0
  bool foundOther = false;
1129
0
  for (SECItem** oids = ekuSequence->oids; oids && *oids; oids++) {
1130
0
    oidTag = SECOID_FindOIDTag(*oids);
1131
0
    if (oidTag == SEC_OID_EXT_KEY_USAGE_SERVER_AUTH) {
1132
0
      foundServerAuth = true;
1133
0
    } else {
1134
0
      foundOther = true;
1135
0
    }
1136
0
  }
1137
0
1138
0
  // Cases 3 is included only for completeness.  It should never
1139
0
  // appear in these statistics, because CheckExtendedKeyUsage()
1140
0
  // should require the EKU extension, if present, to contain the
1141
0
  // value id_kp_serverAuth.
1142
0
  if (foundServerAuth && !foundOther) {
1143
0
    Telemetry::Accumulate(Telemetry::SSL_SERVER_AUTH_EKU, 1);
1144
0
  } else if (foundServerAuth && foundOther) {
1145
0
    Telemetry::Accumulate(Telemetry::SSL_SERVER_AUTH_EKU, 2);
1146
0
  } else if (!foundServerAuth) {
1147
0
    Telemetry::Accumulate(Telemetry::SSL_SERVER_AUTH_EKU, 3);
1148
0
  }
1149
0
}
1150
1151
// Gathers telemetry on which CA is the root of a given cert chain.
1152
// If the root is a built-in root, then the telemetry makes a count
1153
// by root.  Roots that are not built-in are counted in one bin.
1154
void
1155
GatherRootCATelemetry(const UniqueCERTCertList& certList)
1156
0
{
1157
0
  CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
1158
0
  MOZ_ASSERT(rootNode);
1159
0
  if (!rootNode) {
1160
0
    return;
1161
0
  }
1162
0
  MOZ_ASSERT(!CERT_LIST_END(rootNode, certList));
1163
0
  if (CERT_LIST_END(rootNode, certList)) {
1164
0
    return;
1165
0
  }
1166
0
  CERTCertificate* rootCert = rootNode->cert;
1167
0
  MOZ_ASSERT(rootCert);
1168
0
  if (!rootCert) {
1169
0
    return;
1170
0
  }
1171
0
  AccumulateTelemetryForRootCA(Telemetry::CERT_VALIDATION_SUCCESS_BY_CA,
1172
0
                               rootCert);
1173
0
}
1174
1175
// These time are appoximate, i.e., doesn't account for leap seconds, etc
1176
const uint64_t ONE_WEEK_IN_SECONDS = (7 * (24 * 60 *60));
1177
const uint64_t ONE_YEAR_IN_WEEKS   = 52;
1178
1179
// Gathers telemetry on the certificate lifetimes we observe in the wild
1180
void
1181
GatherEndEntityTelemetry(const UniqueCERTCertList& certList)
1182
0
{
1183
0
  CERTCertListNode* endEntityNode = CERT_LIST_HEAD(certList);
1184
0
  MOZ_ASSERT(endEntityNode && !CERT_LIST_END(endEntityNode, certList));
1185
0
  if (!endEntityNode || CERT_LIST_END(endEntityNode, certList)) {
1186
0
    return;
1187
0
  }
1188
0
1189
0
  CERTCertificate* endEntityCert = endEntityNode->cert;
1190
0
  MOZ_ASSERT(endEntityCert);
1191
0
  if (!endEntityCert) {
1192
0
    return;
1193
0
  }
1194
0
1195
0
  PRTime notBefore;
1196
0
  PRTime notAfter;
1197
0
1198
0
  if (CERT_GetCertTimes(endEntityCert, &notBefore, &notAfter) != SECSuccess) {
1199
0
    return;
1200
0
  }
1201
0
1202
0
  MOZ_ASSERT(notAfter > notBefore);
1203
0
  if (notAfter <= notBefore) {
1204
0
    return;
1205
0
  }
1206
0
1207
0
  uint64_t durationInWeeks = (notAfter - notBefore)
1208
0
    / PR_USEC_PER_SEC
1209
0
    / ONE_WEEK_IN_SECONDS;
1210
0
1211
0
  if (durationInWeeks > (2 * ONE_YEAR_IN_WEEKS)) {
1212
0
    durationInWeeks = (2 * ONE_YEAR_IN_WEEKS) + 1;
1213
0
  }
1214
0
1215
0
  Telemetry::Accumulate(Telemetry::SSL_OBSERVED_END_ENTITY_CERTIFICATE_LIFETIME,
1216
0
      durationInWeeks);
1217
0
}
1218
1219
// There are various things that we want to measure about certificate
1220
// chains that we accept.  This is a single entry point for all of them.
1221
void
1222
GatherSuccessfulValidationTelemetry(const UniqueCERTCertList& certList)
1223
0
{
1224
0
  GatherBaselineRequirementsTelemetry(certList);
1225
0
  GatherEKUTelemetry(certList);
1226
0
  GatherRootCATelemetry(certList);
1227
0
  GatherEndEntityTelemetry(certList);
1228
0
}
1229
1230
void
1231
GatherTelemetryForSingleSCT(const ct::VerifiedSCT& verifiedSct)
1232
0
{
1233
0
  // See SSL_SCTS_ORIGIN in Histograms.json.
1234
0
  uint32_t origin = 0;
1235
0
  switch (verifiedSct.origin) {
1236
0
    case ct::VerifiedSCT::Origin::Embedded:
1237
0
      origin = 1;
1238
0
      break;
1239
0
    case ct::VerifiedSCT::Origin::TLSExtension:
1240
0
      origin = 2;
1241
0
      break;
1242
0
    case ct::VerifiedSCT::Origin::OCSPResponse:
1243
0
      origin = 3;
1244
0
      break;
1245
0
    default:
1246
0
      MOZ_ASSERT_UNREACHABLE("Unexpected VerifiedSCT::Origin type");
1247
0
  }
1248
0
  Telemetry::Accumulate(Telemetry::SSL_SCTS_ORIGIN, origin);
1249
0
1250
0
  // See SSL_SCTS_VERIFICATION_STATUS in Histograms.json.
1251
0
  uint32_t verificationStatus = 0;
1252
0
  switch (verifiedSct.status) {
1253
0
    case ct::VerifiedSCT::Status::Valid:
1254
0
      verificationStatus = 1;
1255
0
      break;
1256
0
    case ct::VerifiedSCT::Status::UnknownLog:
1257
0
      verificationStatus = 2;
1258
0
      break;
1259
0
    case ct::VerifiedSCT::Status::InvalidSignature:
1260
0
      verificationStatus = 3;
1261
0
      break;
1262
0
    case ct::VerifiedSCT::Status::InvalidTimestamp:
1263
0
      verificationStatus = 4;
1264
0
      break;
1265
0
    case ct::VerifiedSCT::Status::ValidFromDisqualifiedLog:
1266
0
      verificationStatus = 5;
1267
0
      break;
1268
0
    default:
1269
0
      MOZ_ASSERT_UNREACHABLE("Unexpected VerifiedSCT::Status type");
1270
0
  }
1271
0
  Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS,
1272
0
                        verificationStatus);
1273
0
}
1274
1275
void
1276
GatherCertificateTransparencyTelemetry(const UniqueCERTCertList& certList,
1277
                                       bool isEV,
1278
                                       const CertificateTransparencyInfo& info)
1279
0
{
1280
0
  if (!info.enabled) {
1281
0
    // No telemetry is gathered when CT is disabled.
1282
0
    return;
1283
0
  }
1284
0
1285
0
  for (const ct::VerifiedSCT& sct : info.verifyResult.verifiedScts) {
1286
0
    GatherTelemetryForSingleSCT(sct);
1287
0
  }
1288
0
1289
0
  // Decoding errors are reported to the 0th bucket
1290
0
  // of the SSL_SCTS_VERIFICATION_STATUS enumerated probe.
1291
0
  for (size_t i = 0; i < info.verifyResult.decodingErrors; ++i) {
1292
0
    Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS, 0);
1293
0
  }
1294
0
1295
0
  // Handle the histogram of SCTs counts.
1296
0
  uint32_t sctsCount =
1297
0
    static_cast<uint32_t>(info.verifyResult.verifiedScts.length());
1298
0
  // Note that sctsCount can also be 0 in case we've received SCT binary data,
1299
0
  // but it failed to parse (e.g. due to unsupported CT protocol version).
1300
0
  Telemetry::Accumulate(Telemetry::SSL_SCTS_PER_CONNECTION, sctsCount);
1301
0
1302
0
  // Report CT Policy compliance of EV certificates.
1303
0
  if (isEV) {
1304
0
    uint32_t evCompliance = 0;
1305
0
    switch (info.policyCompliance) {
1306
0
      case ct::CTPolicyCompliance::Compliant:
1307
0
        evCompliance = 1;
1308
0
        break;
1309
0
      case ct::CTPolicyCompliance::NotEnoughScts:
1310
0
        evCompliance = 2;
1311
0
        break;
1312
0
      case ct::CTPolicyCompliance::NotDiverseScts:
1313
0
        evCompliance = 3;
1314
0
        break;
1315
0
      case ct::CTPolicyCompliance::Unknown:
1316
0
      default:
1317
0
        MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
1318
0
    }
1319
0
    Telemetry::Accumulate(Telemetry::SSL_CT_POLICY_COMPLIANCE_OF_EV_CERTS,
1320
0
                          evCompliance);
1321
0
  }
1322
0
1323
0
  // Get the root cert.
1324
0
  CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
1325
0
  MOZ_ASSERT(rootNode);
1326
0
  if (!rootNode) {
1327
0
    return;
1328
0
  }
1329
0
  MOZ_ASSERT(!CERT_LIST_END(rootNode, certList));
1330
0
  if (CERT_LIST_END(rootNode, certList)) {
1331
0
    return;
1332
0
  }
1333
0
  CERTCertificate* rootCert = rootNode->cert;
1334
0
  MOZ_ASSERT(rootCert);
1335
0
  if (!rootCert) {
1336
0
    return;
1337
0
  }
1338
0
1339
0
  // Report CT Policy compliance by CA.
1340
0
  switch (info.policyCompliance) {
1341
0
    case ct::CTPolicyCompliance::Compliant:
1342
0
      AccumulateTelemetryForRootCA(
1343
0
        Telemetry::SSL_CT_POLICY_COMPLIANT_CONNECTIONS_BY_CA, rootCert);
1344
0
      break;
1345
0
    case ct::CTPolicyCompliance::NotEnoughScts:
1346
0
    case ct::CTPolicyCompliance::NotDiverseScts:
1347
0
      AccumulateTelemetryForRootCA(
1348
0
        Telemetry::SSL_CT_POLICY_NON_COMPLIANT_CONNECTIONS_BY_CA, rootCert);
1349
0
      break;
1350
0
    case ct::CTPolicyCompliance::Unknown:
1351
0
    default:
1352
0
      MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
1353
0
  }
1354
0
}
1355
1356
// Note: Takes ownership of |peerCertChain| if SECSuccess is not returned.
1357
SECStatus
1358
AuthCertificate(CertVerifier& certVerifier,
1359
                nsNSSSocketInfo* infoObject,
1360
                const UniqueCERTCertificate& cert,
1361
                UniqueCERTCertList& peerCertChain,
1362
                const SECItem* stapledOCSPResponse,
1363
                const SECItem* sctsFromTLSExtension,
1364
                uint32_t providerFlags,
1365
                Time time)
1366
0
{
1367
0
  MOZ_ASSERT(infoObject);
1368
0
  MOZ_ASSERT(cert);
1369
0
1370
0
  // We want to avoid storing any intermediate cert information when browsing
1371
0
  // in private, transient contexts.
1372
0
  bool saveIntermediates =
1373
0
    !(providerFlags & nsISocketProvider::NO_PERMANENT_STORAGE);
1374
0
1375
0
  SECOidTag evOidPolicy;
1376
0
  UniqueCERTCertList builtCertChain;
1377
0
  CertVerifier::OCSPStaplingStatus ocspStaplingStatus =
1378
0
    CertVerifier::OCSP_STAPLING_NEVER_CHECKED;
1379
0
  KeySizeStatus keySizeStatus = KeySizeStatus::NeverChecked;
1380
0
  SHA1ModeResult sha1ModeResult = SHA1ModeResult::NeverChecked;
1381
0
  PinningTelemetryInfo pinningTelemetryInfo;
1382
0
  CertificateTransparencyInfo certificateTransparencyInfo;
1383
0
1384
0
  int flags = 0;
1385
0
  if (!infoObject->SharedState().IsOCSPStaplingEnabled() ||
1386
0
      !infoObject->SharedState().IsOCSPMustStapleEnabled()) {
1387
0
    flags |= CertVerifier::FLAG_TLS_IGNORE_STATUS_REQUEST;
1388
0
  }
1389
0
1390
0
  Result rv = certVerifier.VerifySSLServerCert(cert, stapledOCSPResponse,
1391
0
                                               sctsFromTLSExtension, time,
1392
0
                                               infoObject,
1393
0
                                               infoObject->GetHostName(),
1394
0
                                               builtCertChain,
1395
0
                                               saveIntermediates, flags,
1396
0
                                               infoObject->
1397
0
                                                      GetOriginAttributes(),
1398
0
                                               &evOidPolicy,
1399
0
                                               &ocspStaplingStatus,
1400
0
                                               &keySizeStatus, &sha1ModeResult,
1401
0
                                               &pinningTelemetryInfo,
1402
0
                                               &certificateTransparencyInfo);
1403
0
1404
0
  uint32_t evStatus = (rv != Success) ? 0                   // 0 = Failure
1405
0
                    : (evOidPolicy == SEC_OID_UNKNOWN) ? 1  // 1 = DV
1406
0
                    : 2;                                    // 2 = EV
1407
0
  Telemetry::Accumulate(Telemetry::CERT_EV_STATUS, evStatus);
1408
0
1409
0
  if (ocspStaplingStatus != CertVerifier::OCSP_STAPLING_NEVER_CHECKED) {
1410
0
    Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, ocspStaplingStatus);
1411
0
  }
1412
0
  if (keySizeStatus != KeySizeStatus::NeverChecked) {
1413
0
    Telemetry::Accumulate(Telemetry::CERT_CHAIN_KEY_SIZE_STATUS,
1414
0
                          static_cast<uint32_t>(keySizeStatus));
1415
0
  }
1416
0
  if (sha1ModeResult != SHA1ModeResult::NeverChecked) {
1417
0
    Telemetry::Accumulate(Telemetry::CERT_CHAIN_SHA1_POLICY_STATUS,
1418
0
                          static_cast<uint32_t>(sha1ModeResult));
1419
0
  }
1420
0
1421
0
  if (pinningTelemetryInfo.accumulateForRoot) {
1422
0
    Telemetry::Accumulate(Telemetry::CERT_PINNING_FAILURES_BY_CA,
1423
0
                          pinningTelemetryInfo.rootBucket);
1424
0
  }
1425
0
1426
0
  if (pinningTelemetryInfo.accumulateResult) {
1427
0
    MOZ_ASSERT(pinningTelemetryInfo.certPinningResultHistogram.isSome());
1428
0
    Telemetry::Accumulate(pinningTelemetryInfo.certPinningResultHistogram.value(),
1429
0
                          pinningTelemetryInfo.certPinningResultBucket);
1430
0
  }
1431
0
1432
0
  if (rv == Success) {
1433
0
    // Certificate verification succeeded. Delete any potential record of
1434
0
    // certificate error bits.
1435
0
    RememberCertErrorsTable::GetInstance().RememberCertHasError(infoObject,
1436
0
                                                                SECSuccess);
1437
0
    GatherSuccessfulValidationTelemetry(builtCertChain);
1438
0
    GatherCertificateTransparencyTelemetry(builtCertChain,
1439
0
                                  /*isEV*/ evOidPolicy != SEC_OID_UNKNOWN,
1440
0
                                           certificateTransparencyInfo);
1441
0
1442
0
    EVStatus evStatus;
1443
0
    if (evOidPolicy == SEC_OID_UNKNOWN) {
1444
0
      evStatus = EVStatus::NotEV;
1445
0
    } else {
1446
0
      evStatus = EVStatus::EV;
1447
0
    }
1448
0
1449
0
    RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(cert.get());
1450
0
    infoObject->SetServerCert(nsc, evStatus);
1451
0
1452
0
    infoObject->SetSucceededCertChain(std::move(builtCertChain));
1453
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1454
0
            ("AuthCertificate setting NEW cert %p", nsc.get()));
1455
0
1456
0
    infoObject->SetCertificateTransparencyInfo(certificateTransparencyInfo);
1457
0
  }
1458
0
1459
0
  if (rv != Success) {
1460
0
    // Certificate validation failed; store the peer certificate chain on
1461
0
    // infoObject so it can be used for error reporting.
1462
0
    infoObject->SetFailedCertChain(std::move(peerCertChain));
1463
0
    PR_SetError(MapResultToPRErrorCode(rv), 0);
1464
0
  }
1465
0
1466
0
  return rv == Success ? SECSuccess : SECFailure;
1467
0
}
1468
1469
/*static*/ SECStatus
1470
SSLServerCertVerificationJob::Dispatch(
1471
  const RefPtr<SharedCertVerifier>& certVerifier,
1472
  const void* fdForLogging,
1473
  nsNSSSocketInfo* infoObject,
1474
  const UniqueCERTCertificate& serverCert,
1475
  const UniqueCERTCertList& peerCertChain,
1476
  const SECItem* stapledOCSPResponse,
1477
  const SECItem* sctsFromTLSExtension,
1478
  uint32_t providerFlags,
1479
  Time time,
1480
  PRTime prtime)
1481
0
{
1482
0
  // Runs on the socket transport thread
1483
0
  if (!certVerifier || !infoObject || !serverCert) {
1484
0
    NS_ERROR("Invalid parameters for SSL server cert validation");
1485
0
    PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
1486
0
    return SECFailure;
1487
0
  }
1488
0
1489
0
  if (!gCertVerificationThreadPool) {
1490
0
    PR_SetError(PR_INVALID_STATE_ERROR, 0);
1491
0
    return SECFailure;
1492
0
  }
1493
0
1494
0
  // Copy the certificate list so the runnable can take ownership of it in the
1495
0
  // constructor.
1496
0
  UniqueCERTCertList peerCertChainCopy =
1497
0
    nsNSSCertList::DupCertList(peerCertChain);
1498
0
  if (!peerCertChainCopy) {
1499
0
    PR_SetError(SEC_ERROR_NO_MEMORY, 0);
1500
0
    return SECFailure;
1501
0
  }
1502
0
1503
0
  RefPtr<SSLServerCertVerificationJob> job(
1504
0
    new SSLServerCertVerificationJob(certVerifier, fdForLogging, infoObject,
1505
0
                                     serverCert, std::move(peerCertChainCopy),
1506
0
                                     stapledOCSPResponse, sctsFromTLSExtension,
1507
0
                                     providerFlags, time, prtime));
1508
0
1509
0
  nsresult nrv = gCertVerificationThreadPool->Dispatch(job, NS_DISPATCH_NORMAL);
1510
0
  if (NS_FAILED(nrv)) {
1511
0
    // We can't call SetCertVerificationResult here to change
1512
0
    // mCertVerificationState because SetCertVerificationResult will call
1513
0
    // libssl functions that acquire SSL locks that are already being held at
1514
0
    // this point. However, we can set an error with PR_SetError and return
1515
0
    // SECFailure, and the correct thing will happen (the error will be
1516
0
    // propagated and this connection will be terminated).
1517
0
    PRErrorCode error = nrv == NS_ERROR_OUT_OF_MEMORY
1518
0
                      ? PR_OUT_OF_MEMORY_ERROR
1519
0
                      : PR_INVALID_STATE_ERROR;
1520
0
    PR_SetError(error, 0);
1521
0
    return SECFailure;
1522
0
  }
1523
0
1524
0
  PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
1525
0
  return SECWouldBlock;
1526
0
}
1527
1528
NS_IMETHODIMP
1529
SSLServerCertVerificationJob::Run()
1530
0
{
1531
0
  // Runs on a cert verification thread
1532
0
1533
0
  MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1534
0
          ("[%p] SSLServerCertVerificationJob::Run\n", mInfoObject.get()));
1535
0
1536
0
  PRErrorCode error;
1537
0
1538
0
  Telemetry::HistogramID successTelemetry
1539
0
    = Telemetry::SSL_SUCCESFUL_CERT_VALIDATION_TIME_MOZILLAPKIX;
1540
0
  Telemetry::HistogramID failureTelemetry
1541
0
    = Telemetry::SSL_INITIAL_FAILED_CERT_VALIDATION_TIME_MOZILLAPKIX;
1542
0
1543
0
  // Reset the error code here so we can detect if AuthCertificate fails to
1544
0
  // set the error code if/when it fails.
1545
0
  PR_SetError(0, 0);
1546
0
  SECStatus rv = AuthCertificate(*mCertVerifier, mInfoObject, mCert,
1547
0
                                 mPeerCertChain, mStapledOCSPResponse.get(),
1548
0
                                 mSCTsFromTLSExtension.get(),
1549
0
                                 mProviderFlags, mTime);
1550
0
  MOZ_ASSERT((mPeerCertChain && rv == SECSuccess) ||
1551
0
             (!mPeerCertChain && rv != SECSuccess),
1552
0
             "AuthCertificate() should take ownership of chain on failure");
1553
0
  if (rv == SECSuccess) {
1554
0
    uint32_t interval = (uint32_t) ((TimeStamp::Now() - mJobStartTime).ToMilliseconds());
1555
0
    RefPtr<SSLServerCertVerificationResult> restart(
1556
0
      new SSLServerCertVerificationResult(mInfoObject, 0,
1557
0
                                          successTelemetry, interval));
1558
0
    restart->Dispatch();
1559
0
    Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, 1);
1560
0
    return NS_OK;
1561
0
  }
1562
0
1563
0
  // Note: the interval is not calculated once as PR_GetError MUST be called
1564
0
  // before any other  function call
1565
0
  error = PR_GetError();
1566
0
1567
0
  TimeStamp now = TimeStamp::Now();
1568
0
  Telemetry::AccumulateTimeDelta(failureTelemetry, mJobStartTime, now);
1569
0
1570
0
  if (error != 0) {
1571
0
    RefPtr<CertErrorRunnable> runnable(
1572
0
        CreateCertErrorRunnable(*mCertVerifier, error, mInfoObject, mCert,
1573
0
                                mFdForLogging, mProviderFlags, mPRTime));
1574
0
    if (!runnable) {
1575
0
      // CreateCertErrorRunnable set a new error code
1576
0
      error = PR_GetError();
1577
0
    } else {
1578
0
      // We must block the the socket transport service thread while the
1579
0
      // main thread executes the CertErrorRunnable. The CertErrorRunnable
1580
0
      // will dispatch the result asynchronously, so we don't have to block
1581
0
      // this thread waiting for it.
1582
0
1583
0
      MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1584
0
              ("[%p][%p] Before dispatching CertErrorRunnable\n",
1585
0
              mFdForLogging, runnable.get()));
1586
0
1587
0
      nsresult nrv;
1588
0
      nsCOMPtr<nsIEventTarget> stsTarget
1589
0
        = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &nrv);
1590
0
      if (NS_SUCCEEDED(nrv)) {
1591
0
        nrv = stsTarget->Dispatch(new CertErrorRunnableRunnable(runnable),
1592
0
                                  NS_DISPATCH_NORMAL);
1593
0
      }
1594
0
      if (NS_SUCCEEDED(nrv)) {
1595
0
        return NS_OK;
1596
0
      }
1597
0
1598
0
      NS_ERROR("Failed to dispatch CertErrorRunnable");
1599
0
      error = PR_INVALID_STATE_ERROR;
1600
0
    }
1601
0
  }
1602
0
1603
0
  if (error == 0) {
1604
0
    MOZ_ASSERT_UNREACHABLE("No error set during certificate validation failure");
1605
0
    error = PR_INVALID_STATE_ERROR;
1606
0
  }
1607
0
1608
0
  RefPtr<SSLServerCertVerificationResult> failure(
1609
0
    new SSLServerCertVerificationResult(mInfoObject, error));
1610
0
  failure->Dispatch();
1611
0
  return NS_OK;
1612
0
}
1613
1614
} // unnamed namespace
1615
1616
// Extracts whatever information we need out of fd (using SSL_*) and passes it
1617
// to SSLServerCertVerificationJob::Dispatch. SSLServerCertVerificationJob should
1618
// never do anything with fd except logging.
1619
SECStatus
1620
AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checkSig, PRBool isServer)
1621
0
{
1622
0
  RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
1623
0
  if (!certVerifier) {
1624
0
    PR_SetError(SEC_ERROR_NOT_INITIALIZED, 0);
1625
0
    return SECFailure;
1626
0
  }
1627
0
1628
0
  // Runs on the socket transport thread
1629
0
1630
0
  MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1631
0
         ("[%p] starting AuthCertificateHook\n", fd));
1632
0
1633
0
  // Modern libssl always passes PR_TRUE for checkSig, and we have no means of
1634
0
  // doing verification without checking signatures.
1635
0
  MOZ_ASSERT(checkSig, "AuthCertificateHook: checkSig unexpectedly false");
1636
0
1637
0
  // PSM never causes libssl to call this function with PR_TRUE for isServer,
1638
0
  // and many things in PSM assume that we are a client.
1639
0
  MOZ_ASSERT(!isServer, "AuthCertificateHook: isServer unexpectedly true");
1640
0
1641
0
  nsNSSSocketInfo* socketInfo = static_cast<nsNSSSocketInfo*>(arg);
1642
0
1643
0
  UniqueCERTCertificate serverCert(SSL_PeerCertificate(fd));
1644
0
1645
0
  if (!checkSig || isServer || !socketInfo || !serverCert) {
1646
0
      PR_SetError(PR_INVALID_STATE_ERROR, 0);
1647
0
      return SECFailure;
1648
0
  }
1649
0
1650
0
  // Get the peer certificate chain for error reporting
1651
0
  UniqueCERTCertList peerCertChain(SSL_PeerCertificateChain(fd));
1652
0
  if (!peerCertChain) {
1653
0
    PR_SetError(PR_INVALID_STATE_ERROR, 0);
1654
0
    return SECFailure;
1655
0
  }
1656
0
1657
0
  socketInfo->SetFullHandshake();
1658
0
1659
0
  Time now(Now());
1660
0
  PRTime prnow(PR_Now());
1661
0
1662
0
  if (BlockServerCertChangeForSpdy(socketInfo, serverCert) != SECSuccess)
1663
0
    return SECFailure;
1664
0
1665
0
  nsCOMPtr<nsISSLSocketControl> sslSocketControl = do_QueryInterface(
1666
0
    NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, socketInfo));
1667
0
  if (sslSocketControl && sslSocketControl->GetBypassAuthentication()) {
1668
0
    MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1669
0
            ("[%p] Bypass Auth in AuthCertificateHook\n", fd));
1670
0
    return SECSuccess;
1671
0
  }
1672
0
1673
0
  bool onSTSThread;
1674
0
  nsresult nrv;
1675
0
  nsCOMPtr<nsIEventTarget> sts
1676
0
    = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &nrv);
1677
0
  if (NS_SUCCEEDED(nrv)) {
1678
0
    nrv = sts->IsOnCurrentThread(&onSTSThread);
1679
0
  }
1680
0
1681
0
  if (NS_FAILED(nrv)) {
1682
0
    NS_ERROR("Could not get STS service or IsOnCurrentThread failed");
1683
0
    PR_SetError(PR_UNKNOWN_ERROR, 0);
1684
0
    return SECFailure;
1685
0
  }
1686
0
1687
0
  // SSL_PeerStapledOCSPResponses will never return a non-empty response if
1688
0
  // OCSP stapling wasn't enabled because libssl wouldn't have let the server
1689
0
  // return a stapled OCSP response.
1690
0
  // We don't own these pointers.
1691
0
  const SECItemArray* csa = SSL_PeerStapledOCSPResponses(fd);
1692
0
  SECItem* stapledOCSPResponse = nullptr;
1693
0
  // we currently only support single stapled responses
1694
0
  if (csa && csa->len == 1) {
1695
0
    stapledOCSPResponse = &csa->items[0];
1696
0
  }
1697
0
1698
0
  const SECItem* sctsFromTLSExtension = SSL_PeerSignedCertTimestamps(fd);
1699
0
  if (sctsFromTLSExtension && sctsFromTLSExtension->len == 0) {
1700
0
    // SSL_PeerSignedCertTimestamps returns null on error and empty item
1701
0
    // when no extension was returned by the server. We always use null when
1702
0
    // no extension was received (for whatever reason), ignoring errors.
1703
0
    sctsFromTLSExtension = nullptr;
1704
0
  }
1705
0
1706
0
  uint32_t providerFlags = 0;
1707
0
  socketInfo->GetProviderFlags(&providerFlags);
1708
0
1709
0
  if (onSTSThread) {
1710
0
1711
0
    // We *must* do certificate verification on a background thread because
1712
0
    // we need the socket transport thread to be free for our OCSP requests,
1713
0
    // and we *want* to do certificate verification on a background thread
1714
0
    // because of the performance benefits of doing so.
1715
0
    socketInfo->SetCertVerificationWaiting();
1716
0
    SECStatus rv = SSLServerCertVerificationJob::Dispatch(
1717
0
                     certVerifier, static_cast<const void*>(fd), socketInfo,
1718
0
                     serverCert, peerCertChain, stapledOCSPResponse,
1719
0
                     sctsFromTLSExtension, providerFlags, now, prnow);
1720
0
    return rv;
1721
0
  }
1722
0
1723
0
  // We can't do certificate verification on a background thread, because the
1724
0
  // thread doing the network I/O may not interrupt its network I/O on receipt
1725
0
  // of our SSLServerCertVerificationResult event, and/or it might not even be
1726
0
  // a non-blocking socket.
1727
0
1728
0
  SECStatus rv = AuthCertificate(*certVerifier, socketInfo, serverCert,
1729
0
                                 peerCertChain, stapledOCSPResponse,
1730
0
                                 sctsFromTLSExtension, providerFlags, now);
1731
0
  MOZ_ASSERT((peerCertChain && rv == SECSuccess) ||
1732
0
             (!peerCertChain && rv != SECSuccess),
1733
0
             "AuthCertificate() should take ownership of chain on failure");
1734
0
  if (rv == SECSuccess) {
1735
0
    Telemetry::Accumulate(Telemetry::SSL_CERT_ERROR_OVERRIDES, 1);
1736
0
    return SECSuccess;
1737
0
  }
1738
0
1739
0
  PRErrorCode error = PR_GetError();
1740
0
  if (error != 0) {
1741
0
    RefPtr<CertErrorRunnable> runnable(
1742
0
        CreateCertErrorRunnable(*certVerifier, error, socketInfo, serverCert,
1743
0
                                static_cast<const void*>(fd), providerFlags,
1744
0
                                prnow));
1745
0
    if (!runnable) {
1746
0
      // CreateCertErrorRunnable sets a new error code when it fails
1747
0
      error = PR_GetError();
1748
0
    } else {
1749
0
      // We have to return SECSuccess or SECFailure based on the result of the
1750
0
      // override processing, so we must block this thread waiting for it. The
1751
0
      // CertErrorRunnable will NOT dispatch the result at all, since we passed
1752
0
      // false for CreateCertErrorRunnable's async parameter
1753
0
      nrv = runnable->DispatchToMainThreadAndWait();
1754
0
      if (NS_FAILED(nrv)) {
1755
0
        NS_ERROR("Failed to dispatch CertErrorRunnable");
1756
0
        PR_SetError(PR_INVALID_STATE_ERROR, 0);
1757
0
        return SECFailure;
1758
0
      }
1759
0
1760
0
      if (!runnable->mResult) {
1761
0
        NS_ERROR("CertErrorRunnable did not set result");
1762
0
        PR_SetError(PR_INVALID_STATE_ERROR, 0);
1763
0
        return SECFailure;
1764
0
      }
1765
0
1766
0
      if (runnable->mResult->mErrorCode == 0) {
1767
0
        return SECSuccess; // cert error override occurred.
1768
0
      }
1769
0
1770
0
      socketInfo->SetCanceled(runnable->mResult->mErrorCode);
1771
0
      error = runnable->mResult->mErrorCode;
1772
0
    }
1773
0
  }
1774
0
1775
0
  if (error == 0) {
1776
0
    NS_ERROR("error code not set");
1777
0
    error = PR_UNKNOWN_ERROR;
1778
0
  }
1779
0
1780
0
  PR_SetError(error, 0);
1781
0
  return SECFailure;
1782
0
}
1783
1784
SSLServerCertVerificationResult::SSLServerCertVerificationResult(
1785
  nsNSSSocketInfo* infoObject,
1786
  PRErrorCode errorCode,
1787
  Telemetry::HistogramID telemetryID,
1788
  uint32_t telemetryValue)
1789
  : Runnable("psm::SSLServerCertVerificationResult")
1790
  , mInfoObject(infoObject)
1791
  , mErrorCode(errorCode)
1792
  , mTelemetryID(telemetryID)
1793
  , mTelemetryValue(telemetryValue)
1794
0
{
1795
0
// We accumulate telemetry for (only) successful validations on the main thread
1796
0
// to avoid adversely affecting performance by acquiring the mutex that we use
1797
0
// when accumulating the telemetry for unsuccessful validations. Unsuccessful
1798
0
// validations times are accumulated elsewhere.
1799
0
MOZ_ASSERT(telemetryID == Telemetry::HistogramCount || errorCode == 0);
1800
0
}
1801
1802
void
1803
SSLServerCertVerificationResult::Dispatch()
1804
0
{
1805
0
  nsresult rv;
1806
0
  nsCOMPtr<nsIEventTarget> stsTarget
1807
0
    = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
1808
0
  MOZ_ASSERT(stsTarget,
1809
0
             "Failed to get socket transport service event target");
1810
0
  rv = stsTarget->Dispatch(this, NS_DISPATCH_NORMAL);
1811
0
  MOZ_ASSERT(NS_SUCCEEDED(rv),
1812
0
             "Failed to dispatch SSLServerCertVerificationResult");
1813
0
}
1814
1815
NS_IMETHODIMP
1816
SSLServerCertVerificationResult::Run()
1817
0
{
1818
0
  // TODO: Assert that we're on the socket transport thread
1819
0
  if (mTelemetryID != Telemetry::HistogramCount) {
1820
0
     Telemetry::Accumulate(mTelemetryID, mTelemetryValue);
1821
0
  }
1822
0
  mInfoObject->SetCertVerificationResult(mErrorCode);
1823
0
  return NS_OK;
1824
0
}
1825
1826
} } // namespace mozilla::psm