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