1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "nsNSSCallbacks.h"
8
9 #include "PSMRunnable.h"
10 #include "ScopedNSSTypes.h"
11 #include "SharedCertVerifier.h"
12 #include "SharedSSLState.h"
13 #include "mozilla/ArrayUtils.h"
14 #include "mozilla/Assertions.h"
15 #include "mozilla/Casting.h"
16 #include "mozilla/RefPtr.h"
17 #include "mozilla/Telemetry.h"
18 #include "mozilla/TimeStamp.h"
19 #include "mozilla/Unused.h"
20 #include "nsContentUtils.h"
21 #include "nsICertOverrideService.h"
22 #include "nsIHttpChannelInternal.h"
23 #include "nsIPrompt.h"
24 #include "nsISupportsPriority.h"
25 #include "nsITokenDialogs.h"
26 #include "nsIUploadChannel.h"
27 #include "nsIWebProgressListener.h"
28 #include "nsNSSCertificate.h"
29 #include "nsNSSComponent.h"
30 #include "nsNSSIOLayer.h"
31 #include "nsNetUtil.h"
32 #include "nsProtectedAuthThread.h"
33 #include "nsProxyRelease.h"
34 #include "pkix/pkixtypes.h"
35 #include "ssl.h"
36 #include "sslproto.h"
37
38 using namespace mozilla;
39 using namespace mozilla::psm;
40
41 extern LazyLogModule gPIPNSSLog;
42
43 static void AccumulateCipherSuite(Telemetry::ID probe,
44 const SSLChannelInfo& channelInfo);
45
46 namespace {
47
48 // Bits in bit mask for SSL_REASONS_FOR_NOT_FALSE_STARTING telemetry probe
49 // These bits are numbered so that the least subtle issues have higher values.
50 // This should make it easier for us to interpret the results.
51 const uint32_t NPN_NOT_NEGOTIATED = 64;
52 const uint32_t POSSIBLE_VERSION_DOWNGRADE = 4;
53 const uint32_t POSSIBLE_CIPHER_SUITE_DOWNGRADE = 2;
54 const uint32_t KEA_NOT_SUPPORTED = 1;
55
56 } // namespace
57
58 class nsHTTPDownloadEvent : public Runnable {
59 public:
60 nsHTTPDownloadEvent();
61 ~nsHTTPDownloadEvent();
62
63 NS_IMETHOD Run();
64
65 nsNSSHttpRequestSession *mRequestSession;
66
67 RefPtr<nsHTTPListener> mListener;
68 bool mResponsibleForDoneSignal;
69 TimeStamp mStartTime;
70 };
71
nsHTTPDownloadEvent()72 nsHTTPDownloadEvent::nsHTTPDownloadEvent()
73 :mResponsibleForDoneSignal(true)
74 {
75 }
76
~nsHTTPDownloadEvent()77 nsHTTPDownloadEvent::~nsHTTPDownloadEvent()
78 {
79 if (mResponsibleForDoneSignal && mListener)
80 mListener->send_done_signal();
81
82 mRequestSession->Release();
83 }
84
85 NS_IMETHODIMP
Run()86 nsHTTPDownloadEvent::Run()
87 {
88 if (!mListener)
89 return NS_OK;
90
91 nsresult rv;
92
93 nsCOMPtr<nsIIOService> ios = do_GetIOService();
94 NS_ENSURE_STATE(ios);
95
96 nsCOMPtr<nsIChannel> chan;
97 ios->NewChannel2(mRequestSession->mURL,
98 nullptr,
99 nullptr,
100 nullptr, // aLoadingNode
101 nsContentUtils::GetSystemPrincipal(),
102 nullptr, // aTriggeringPrincipal
103 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
104 nsIContentPolicy::TYPE_OTHER,
105 getter_AddRefs(chan));
106 NS_ENSURE_STATE(chan);
107
108 // Security operations scheduled through normal HTTP channels are given
109 // high priority to accommodate real time OCSP transactions.
110 nsCOMPtr<nsISupportsPriority> priorityChannel = do_QueryInterface(chan);
111 if (priorityChannel)
112 priorityChannel->AdjustPriority(nsISupportsPriority::PRIORITY_HIGHEST);
113
114 chan->SetLoadFlags(nsIRequest::LOAD_ANONYMOUS |
115 nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
116
117 // For OCSP requests, only the first party domain aspect of origin attributes
118 // is used. This means that OCSP requests are shared across different
119 // containers.
120 if (mRequestSession->mOriginAttributes != NeckoOriginAttributes()) {
121 NeckoOriginAttributes attrs;
122 attrs.mFirstPartyDomain =
123 mRequestSession->mOriginAttributes.mFirstPartyDomain;
124
125 nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo();
126 if (loadInfo) {
127 rv = loadInfo->SetOriginAttributes(attrs);
128 NS_ENSURE_SUCCESS(rv, rv);
129 }
130 }
131
132 // Create a loadgroup for this new channel. This way if the channel
133 // is redirected, we'll have a way to cancel the resulting channel.
134 nsCOMPtr<nsILoadGroup> lg = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
135 chan->SetLoadGroup(lg);
136
137 if (mRequestSession->mHasPostData)
138 {
139 nsCOMPtr<nsIInputStream> uploadStream;
140 rv = NS_NewPostDataStream(getter_AddRefs(uploadStream),
141 false,
142 mRequestSession->mPostData);
143 NS_ENSURE_SUCCESS(rv, rv);
144
145 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(chan));
146 NS_ENSURE_STATE(uploadChannel);
147
148 rv = uploadChannel->SetUploadStream(uploadStream,
149 mRequestSession->mPostContentType,
150 -1);
151 NS_ENSURE_SUCCESS(rv, rv);
152 }
153
154 // Do not use SPDY for internal security operations. It could result
155 // in the silent upgrade to ssl, which in turn could require an SSL
156 // operation to fulfill something like an OCSP fetch, which is an
157 // endless loop.
158 nsCOMPtr<nsIHttpChannelInternal> internalChannel = do_QueryInterface(chan);
159 if (internalChannel) {
160 rv = internalChannel->SetAllowSpdy(false);
161 NS_ENSURE_SUCCESS(rv, rv);
162 }
163
164 nsCOMPtr<nsIHttpChannel> hchan = do_QueryInterface(chan);
165 NS_ENSURE_STATE(hchan);
166
167 rv = hchan->SetAllowSTS(false);
168 NS_ENSURE_SUCCESS(rv, rv);
169
170 rv = hchan->SetRequestMethod(mRequestSession->mRequestMethod);
171 NS_ENSURE_SUCCESS(rv, rv);
172
173 mResponsibleForDoneSignal = false;
174 mListener->mResponsibleForDoneSignal = true;
175
176 mListener->mLoadGroup = lg.get();
177 NS_ADDREF(mListener->mLoadGroup);
178 mListener->mLoadGroupOwnerThread = PR_GetCurrentThread();
179
180 rv = NS_NewStreamLoader(getter_AddRefs(mListener->mLoader),
181 mListener);
182
183 if (NS_SUCCEEDED(rv)) {
184 mStartTime = TimeStamp::Now();
185 rv = hchan->AsyncOpen2(mListener->mLoader);
186 }
187
188 if (NS_FAILED(rv)) {
189 mListener->mResponsibleForDoneSignal = false;
190 mResponsibleForDoneSignal = true;
191
192 NS_RELEASE(mListener->mLoadGroup);
193 mListener->mLoadGroup = nullptr;
194 mListener->mLoadGroupOwnerThread = nullptr;
195 }
196
197 return NS_OK;
198 }
199
200 struct nsCancelHTTPDownloadEvent : Runnable {
201 RefPtr<nsHTTPListener> mListener;
202
RunnsCancelHTTPDownloadEvent203 NS_IMETHOD Run() override {
204 mListener->FreeLoadGroup(true);
205 mListener = nullptr;
206 return NS_OK;
207 }
208 };
209
210 mozilla::pkix::Result
createSessionFcn(const char * host,uint16_t portnum,nsNSSHttpServerSession ** pSession)211 nsNSSHttpServerSession::createSessionFcn(const char* host,
212 uint16_t portnum,
213 /*out*/ nsNSSHttpServerSession** pSession)
214 {
215 if (!host || !pSession) {
216 return Result::FATAL_ERROR_INVALID_ARGS;
217 }
218
219 nsNSSHttpServerSession* hss = new nsNSSHttpServerSession;
220 if (!hss) {
221 return Result::FATAL_ERROR_NO_MEMORY;
222 }
223
224 hss->mHost = host;
225 hss->mPort = portnum;
226
227 *pSession = hss;
228 return Success;
229 }
230
231 mozilla::pkix::Result
createFcn(const nsNSSHttpServerSession * session,const char * http_protocol_variant,const char * path_and_query_string,const char * http_request_method,const NeckoOriginAttributes & origin_attributes,const PRIntervalTime timeout,nsNSSHttpRequestSession ** pRequest)232 nsNSSHttpRequestSession::createFcn(const nsNSSHttpServerSession* session,
233 const char* http_protocol_variant,
234 const char* path_and_query_string,
235 const char* http_request_method,
236 const NeckoOriginAttributes& origin_attributes,
237 const PRIntervalTime timeout,
238 /*out*/ nsNSSHttpRequestSession** pRequest)
239 {
240 if (!session || !http_protocol_variant || !path_and_query_string ||
241 !http_request_method || !pRequest) {
242 return Result::FATAL_ERROR_INVALID_ARGS;
243 }
244
245 nsNSSHttpRequestSession* rs = new nsNSSHttpRequestSession;
246 if (!rs) {
247 return Result::FATAL_ERROR_NO_MEMORY;
248 }
249
250 rs->mTimeoutInterval = timeout;
251
252 // Use a maximum timeout value of 10 seconds because of bug 404059.
253 // FIXME: Use a better approach once 406120 is ready.
254 uint32_t maxBug404059Timeout = PR_TicksPerSecond() * 10;
255 if (timeout > maxBug404059Timeout) {
256 rs->mTimeoutInterval = maxBug404059Timeout;
257 }
258
259 rs->mURL.Assign(http_protocol_variant);
260 rs->mURL.AppendLiteral("://");
261 rs->mURL.Append(session->mHost);
262 rs->mURL.Append(':');
263 rs->mURL.AppendInt(session->mPort);
264 rs->mURL.Append(path_and_query_string);
265
266 rs->mOriginAttributes = origin_attributes;
267
268 rs->mRequestMethod = http_request_method;
269
270 *pRequest = rs;
271 return Success;
272 }
273
274 mozilla::pkix::Result
setPostDataFcn(const char * http_data,const uint32_t http_data_len,const char * http_content_type)275 nsNSSHttpRequestSession::setPostDataFcn(const char* http_data,
276 const uint32_t http_data_len,
277 const char* http_content_type)
278 {
279 mHasPostData = true;
280 mPostData.Assign(http_data, http_data_len);
281 mPostContentType.Assign(http_content_type);
282
283 return Success;
284 }
285
286 mozilla::pkix::Result
trySendAndReceiveFcn(PRPollDesc ** pPollDesc,uint16_t * http_response_code,const char ** http_response_content_type,const char ** http_response_headers,const char ** http_response_data,uint32_t * http_response_data_len)287 nsNSSHttpRequestSession::trySendAndReceiveFcn(PRPollDesc** pPollDesc,
288 uint16_t* http_response_code,
289 const char** http_response_content_type,
290 const char** http_response_headers,
291 const char** http_response_data,
292 uint32_t* http_response_data_len)
293 {
294 MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
295 ("nsNSSHttpRequestSession::trySendAndReceiveFcn to %s\n", mURL.get()));
296
297 bool onSTSThread;
298 nsresult nrv;
299 nsCOMPtr<nsIEventTarget> sts
300 = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &nrv);
301 if (NS_FAILED(nrv)) {
302 NS_ERROR("Could not get STS service");
303 return Result::FATAL_ERROR_INVALID_STATE;
304 }
305
306 nrv = sts->IsOnCurrentThread(&onSTSThread);
307 if (NS_FAILED(nrv)) {
308 NS_ERROR("IsOnCurrentThread failed");
309 return Result::FATAL_ERROR_INVALID_STATE;
310 }
311
312 if (onSTSThread) {
313 NS_ERROR("nsNSSHttpRequestSession::trySendAndReceiveFcn called on socket "
314 "thread; this will not work.");
315 return Result::FATAL_ERROR_INVALID_STATE;
316 }
317
318 const int max_retries = 2;
319 int retry_count = 0;
320 bool retryable_error = false;
321 Result rv = Result::ERROR_UNKNOWN_ERROR;
322
323 do
324 {
325 if (retry_count > 0)
326 {
327 if (retryable_error)
328 {
329 MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
330 ("nsNSSHttpRequestSession::trySendAndReceiveFcn - sleeping and retrying: %d of %d\n",
331 retry_count, max_retries));
332 }
333
334 PR_Sleep( PR_MillisecondsToInterval(300) * retry_count );
335 }
336
337 ++retry_count;
338 retryable_error = false;
339
340 rv =
341 internal_send_receive_attempt(retryable_error, pPollDesc, http_response_code,
342 http_response_content_type, http_response_headers,
343 http_response_data, http_response_data_len);
344 }
345 while (retryable_error &&
346 retry_count < max_retries);
347
348 if (retry_count > 1)
349 {
350 if (retryable_error)
351 MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
352 ("nsNSSHttpRequestSession::trySendAndReceiveFcn - still failing, giving up...\n"));
353 else
354 MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
355 ("nsNSSHttpRequestSession::trySendAndReceiveFcn - success at attempt %d\n",
356 retry_count));
357 }
358
359 return rv;
360 }
361
362 void
AddRef()363 nsNSSHttpRequestSession::AddRef()
364 {
365 ++mRefCount;
366 }
367
368 void
Release()369 nsNSSHttpRequestSession::Release()
370 {
371 int32_t newRefCount = --mRefCount;
372 if (!newRefCount) {
373 delete this;
374 }
375 }
376
377 mozilla::pkix::Result
internal_send_receive_attempt(bool & retryable_error,PRPollDesc ** pPollDesc,uint16_t * http_response_code,const char ** http_response_content_type,const char ** http_response_headers,const char ** http_response_data,uint32_t * http_response_data_len)378 nsNSSHttpRequestSession::internal_send_receive_attempt(bool &retryable_error,
379 PRPollDesc **pPollDesc,
380 uint16_t *http_response_code,
381 const char **http_response_content_type,
382 const char **http_response_headers,
383 const char **http_response_data,
384 uint32_t *http_response_data_len)
385 {
386 if (pPollDesc) *pPollDesc = nullptr;
387 if (http_response_code) *http_response_code = 0;
388 if (http_response_content_type) *http_response_content_type = 0;
389 if (http_response_headers) *http_response_headers = 0;
390 if (http_response_data) *http_response_data = 0;
391
392 uint32_t acceptableResultSize = 0;
393
394 if (http_response_data_len)
395 {
396 acceptableResultSize = *http_response_data_len;
397 *http_response_data_len = 0;
398 }
399
400 if (!mListener) {
401 return Result::FATAL_ERROR_INVALID_STATE;
402 }
403
404 Mutex& waitLock = mListener->mLock;
405 CondVar& waitCondition = mListener->mCondition;
406 volatile bool &waitFlag = mListener->mWaitFlag;
407 waitFlag = true;
408
409 RefPtr<nsHTTPDownloadEvent> event(new nsHTTPDownloadEvent);
410 if (!event) {
411 return Result::FATAL_ERROR_NO_MEMORY;
412 }
413
414 event->mListener = mListener;
415 this->AddRef();
416 event->mRequestSession = this;
417
418 nsresult rv = NS_DispatchToMainThread(event);
419 if (NS_FAILED(rv)) {
420 event->mResponsibleForDoneSignal = false;
421 return Result::FATAL_ERROR_LIBRARY_FAILURE;
422 }
423
424 bool request_canceled = false;
425
426 {
427 MutexAutoLock locker(waitLock);
428
429 const PRIntervalTime start_time = PR_IntervalNow();
430 PRIntervalTime wait_interval;
431
432 bool running_on_main_thread = NS_IsMainThread();
433 if (running_on_main_thread)
434 {
435 // The result of running this on the main thread
436 // is a series of small timeouts mixed with spinning the
437 // event loop - this is always dangerous as there is so much main
438 // thread code that does not expect to be called re-entrantly. Your
439 // app really shouldn't do that.
440 NS_WARNING("Security network blocking I/O on Main Thread");
441
442 // let's process events quickly
443 wait_interval = PR_MicrosecondsToInterval(50);
444 }
445 else
446 {
447 // On a secondary thread, it's fine to wait some more for
448 // for the condition variable.
449 wait_interval = PR_MillisecondsToInterval(250);
450 }
451
452 while (waitFlag)
453 {
454 if (running_on_main_thread)
455 {
456 // Networking runs on the main thread, which we happen to block here.
457 // Processing events will allow the OCSP networking to run while we
458 // are waiting. Thanks a lot to Darin Fisher for rewriting the
459 // thread manager. Thanks a lot to Christian Biesinger who
460 // made me aware of this possibility. (kaie)
461
462 MutexAutoUnlock unlock(waitLock);
463 NS_ProcessNextEvent(nullptr);
464 }
465
466 waitCondition.Wait(wait_interval);
467
468 if (!waitFlag)
469 break;
470
471 if (!request_canceled)
472 {
473 bool timeout =
474 (PRIntervalTime)(PR_IntervalNow() - start_time) > mTimeoutInterval;
475
476 if (timeout)
477 {
478 request_canceled = true;
479
480 RefPtr<nsCancelHTTPDownloadEvent> cancelevent(
481 new nsCancelHTTPDownloadEvent);
482 cancelevent->mListener = mListener;
483 rv = NS_DispatchToMainThread(cancelevent);
484 if (NS_FAILED(rv)) {
485 NS_WARNING("cannot post cancel event");
486 }
487 break;
488 }
489 }
490 }
491 }
492
493 if (!event->mStartTime.IsNull()) {
494 if (request_canceled) {
495 Telemetry::Accumulate(Telemetry::CERT_VALIDATION_HTTP_REQUEST_RESULT, 0);
496 Telemetry::AccumulateTimeDelta(
497 Telemetry::CERT_VALIDATION_HTTP_REQUEST_CANCELED_TIME,
498 event->mStartTime, TimeStamp::Now());
499 }
500 else if (NS_SUCCEEDED(mListener->mResultCode) &&
501 mListener->mHttpResponseCode == 200) {
502 Telemetry::Accumulate(Telemetry::CERT_VALIDATION_HTTP_REQUEST_RESULT, 1);
503 Telemetry::AccumulateTimeDelta(
504 Telemetry::CERT_VALIDATION_HTTP_REQUEST_SUCCEEDED_TIME,
505 event->mStartTime, TimeStamp::Now());
506 }
507 else {
508 Telemetry::Accumulate(Telemetry::CERT_VALIDATION_HTTP_REQUEST_RESULT, 2);
509 Telemetry::AccumulateTimeDelta(
510 Telemetry::CERT_VALIDATION_HTTP_REQUEST_FAILED_TIME,
511 event->mStartTime, TimeStamp::Now());
512 }
513 }
514 else {
515 Telemetry::Accumulate(Telemetry::CERT_VALIDATION_HTTP_REQUEST_RESULT, 3);
516 }
517
518 if (request_canceled) {
519 return Result::ERROR_OCSP_SERVER_ERROR;
520 }
521
522 if (NS_FAILED(mListener->mResultCode)) {
523 if (mListener->mResultCode == NS_ERROR_CONNECTION_REFUSED ||
524 mListener->mResultCode == NS_ERROR_NET_RESET) {
525 retryable_error = true;
526 }
527 return Result::ERROR_OCSP_SERVER_ERROR;
528 }
529
530 if (http_response_code)
531 *http_response_code = mListener->mHttpResponseCode;
532
533 if (mListener->mHttpRequestSucceeded && http_response_data &&
534 http_response_data_len) {
535 *http_response_data_len = mListener->mResultLen;
536
537 // acceptableResultSize == 0 means: any size is acceptable
538 if (acceptableResultSize != 0 &&
539 acceptableResultSize < mListener->mResultLen) {
540 return Result::ERROR_OCSP_SERVER_ERROR;
541 }
542
543 // Return data by reference, result data will be valid until "this" gets
544 // destroyed.
545 *http_response_data = (const char*)mListener->mResultData;
546 }
547
548 if (mListener->mHttpRequestSucceeded && http_response_content_type) {
549 if (mListener->mHttpResponseContentType.Length()) {
550 *http_response_content_type = mListener->mHttpResponseContentType.get();
551 }
552 }
553
554 return Success;
555 }
556
nsNSSHttpRequestSession()557 nsNSSHttpRequestSession::nsNSSHttpRequestSession()
558 : mRefCount(1),
559 mHasPostData(false),
560 mTimeoutInterval(0),
561 mListener(new nsHTTPListener)
562 {
563 }
564
~nsNSSHttpRequestSession()565 nsNSSHttpRequestSession::~nsNSSHttpRequestSession()
566 {
567 }
568
nsHTTPListener()569 nsHTTPListener::nsHTTPListener()
570 : mResultData(nullptr),
571 mResultLen(0),
572 mLock("nsHTTPListener.mLock"),
573 mCondition(mLock, "nsHTTPListener.mCondition"),
574 mWaitFlag(true),
575 mResponsibleForDoneSignal(false),
576 mLoadGroup(nullptr),
577 mLoadGroupOwnerThread(nullptr)
578 {
579 }
580
~nsHTTPListener()581 nsHTTPListener::~nsHTTPListener()
582 {
583 if (mResponsibleForDoneSignal)
584 send_done_signal();
585
586 if (mResultData) {
587 free(const_cast<uint8_t *>(mResultData));
588 }
589
590 if (mLoader) {
591 NS_ReleaseOnMainThread(mLoader.forget());
592 }
593 }
594
NS_IMPL_ISUPPORTS(nsHTTPListener,nsIStreamLoaderObserver)595 NS_IMPL_ISUPPORTS(nsHTTPListener, nsIStreamLoaderObserver)
596
597 void
598 nsHTTPListener::FreeLoadGroup(bool aCancelLoad)
599 {
600 nsILoadGroup *lg = nullptr;
601
602 MutexAutoLock locker(mLock);
603
604 if (mLoadGroup) {
605 if (mLoadGroupOwnerThread != PR_GetCurrentThread()) {
606 NS_ASSERTION(false,
607 "attempt to access nsHTTPDownloadEvent::mLoadGroup on multiple threads, leaking it!");
608 }
609 else {
610 lg = mLoadGroup;
611 mLoadGroup = nullptr;
612 }
613 }
614
615 if (lg) {
616 if (aCancelLoad) {
617 lg->Cancel(NS_ERROR_ABORT);
618 }
619 NS_RELEASE(lg);
620 }
621 }
622
623 NS_IMETHODIMP
OnStreamComplete(nsIStreamLoader * aLoader,nsISupports * aContext,nsresult aStatus,uint32_t stringLen,const uint8_t * string)624 nsHTTPListener::OnStreamComplete(nsIStreamLoader* aLoader,
625 nsISupports* aContext,
626 nsresult aStatus,
627 uint32_t stringLen,
628 const uint8_t* string)
629 {
630 mResultCode = aStatus;
631
632 FreeLoadGroup(false);
633
634 nsCOMPtr<nsIRequest> req;
635 nsCOMPtr<nsIHttpChannel> hchan;
636
637 nsresult rv = aLoader->GetRequest(getter_AddRefs(req));
638
639 if (NS_FAILED(aStatus))
640 {
641 MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
642 ("nsHTTPListener::OnStreamComplete status failed %d", aStatus));
643 }
644
645 if (NS_SUCCEEDED(rv))
646 hchan = do_QueryInterface(req, &rv);
647
648 if (NS_SUCCEEDED(rv))
649 {
650 rv = hchan->GetRequestSucceeded(&mHttpRequestSucceeded);
651 if (NS_FAILED(rv))
652 mHttpRequestSucceeded = false;
653
654 mResultLen = stringLen;
655 mResultData = string; // take ownership of allocation
656 aStatus = NS_SUCCESS_ADOPTED_DATA;
657
658 unsigned int rcode;
659 rv = hchan->GetResponseStatus(&rcode);
660 if (NS_FAILED(rv))
661 mHttpResponseCode = 500;
662 else
663 mHttpResponseCode = rcode;
664
665 hchan->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"),
666 mHttpResponseContentType);
667 }
668
669 if (mResponsibleForDoneSignal)
670 send_done_signal();
671
672 return aStatus;
673 }
674
send_done_signal()675 void nsHTTPListener::send_done_signal()
676 {
677 mResponsibleForDoneSignal = false;
678
679 {
680 MutexAutoLock locker(mLock);
681 mWaitFlag = false;
682 mCondition.NotifyAll();
683 }
684 }
685
686 static char*
ShowProtectedAuthPrompt(PK11SlotInfo * slot,nsIInterfaceRequestor * ir)687 ShowProtectedAuthPrompt(PK11SlotInfo* slot, nsIInterfaceRequestor *ir)
688 {
689 if (!NS_IsMainThread()) {
690 NS_ERROR("ShowProtectedAuthPrompt called off the main thread");
691 return nullptr;
692 }
693
694 char* protAuthRetVal = nullptr;
695
696 // Get protected auth dialogs
697 nsCOMPtr<nsITokenDialogs> dialogs;
698 nsresult nsrv = getNSSDialogs(getter_AddRefs(dialogs),
699 NS_GET_IID(nsITokenDialogs),
700 NS_TOKENDIALOGS_CONTRACTID);
701 if (NS_SUCCEEDED(nsrv))
702 {
703 nsProtectedAuthThread* protectedAuthRunnable = new nsProtectedAuthThread();
704 if (protectedAuthRunnable)
705 {
706 NS_ADDREF(protectedAuthRunnable);
707
708 protectedAuthRunnable->SetParams(slot);
709
710 nsCOMPtr<nsIProtectedAuthThread> runnable = do_QueryInterface(protectedAuthRunnable);
711 if (runnable)
712 {
713 nsrv = dialogs->DisplayProtectedAuth(ir, runnable);
714
715 // We call join on the thread,
716 // so we can be sure that no simultaneous access will happen.
717 protectedAuthRunnable->Join();
718
719 if (NS_SUCCEEDED(nsrv))
720 {
721 SECStatus rv = protectedAuthRunnable->GetResult();
722 switch (rv)
723 {
724 case SECSuccess:
725 protAuthRetVal = ToNewCString(nsDependentCString(PK11_PW_AUTHENTICATED));
726 break;
727 case SECWouldBlock:
728 protAuthRetVal = ToNewCString(nsDependentCString(PK11_PW_RETRY));
729 break;
730 default:
731 protAuthRetVal = nullptr;
732 break;
733 }
734 }
735 }
736
737 NS_RELEASE(protectedAuthRunnable);
738 }
739 }
740
741 return protAuthRetVal;
742 }
743
744 class PK11PasswordPromptRunnable : public SyncRunnableBase
745 , public nsNSSShutDownObject
746 {
747 public:
PK11PasswordPromptRunnable(PK11SlotInfo * slot,nsIInterfaceRequestor * ir)748 PK11PasswordPromptRunnable(PK11SlotInfo* slot,
749 nsIInterfaceRequestor* ir)
750 : mResult(nullptr),
751 mSlot(slot),
752 mIR(ir)
753 {
754 }
755 virtual ~PK11PasswordPromptRunnable();
756
757 // This doesn't own the PK11SlotInfo or any other NSS objects, so there's
758 // nothing to release.
virtualDestroyNSSReference()759 virtual void virtualDestroyNSSReference() override {}
760 char * mResult; // out
761 virtual void RunOnTargetThread() override;
762 private:
763 PK11SlotInfo* const mSlot; // in
764 nsIInterfaceRequestor* const mIR; // in
765 };
766
~PK11PasswordPromptRunnable()767 PK11PasswordPromptRunnable::~PK11PasswordPromptRunnable()
768 {
769 nsNSSShutDownPreventionLock locker;
770 if (isAlreadyShutDown()) {
771 return;
772 }
773
774 shutdown(ShutdownCalledFrom::Object);
775 }
776
777 void
RunOnTargetThread()778 PK11PasswordPromptRunnable::RunOnTargetThread()
779 {
780 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
781
782 nsNSSShutDownPreventionLock locker;
783 if (isAlreadyShutDown()) {
784 return;
785 }
786
787 nsresult rv;
788 nsCOMPtr<nsIPrompt> prompt;
789 if (!mIR) {
790 rv = nsNSSComponent::GetNewPrompter(getter_AddRefs(prompt));
791 if (NS_FAILED(rv)) {
792 return;
793 }
794 } else {
795 prompt = do_GetInterface(mIR);
796 MOZ_ASSERT(prompt, "Interface requestor should implement nsIPrompt");
797 }
798
799 if (!prompt) {
800 return;
801 }
802
803 if (PK11_ProtectedAuthenticationPath(mSlot)) {
804 mResult = ShowProtectedAuthPrompt(mSlot, mIR);
805 return;
806 }
807
808 nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID));
809 if (!nssComponent) {
810 return;
811 }
812
813 NS_ConvertUTF8toUTF16 tokenName(PK11_GetTokenName(mSlot));
814 const char16_t* formatStrings[] = {
815 tokenName.get(),
816 };
817 nsAutoString promptString;
818 rv = nssComponent->PIPBundleFormatStringFromName("CertPassPrompt",
819 formatStrings,
820 ArrayLength(formatStrings),
821 promptString);
822 if (NS_FAILED(rv)) {
823 return;
824 }
825
826 nsXPIDLString password;
827 // |checkState| is unused because |checkMsg| (the argument just before it) is
828 // null, but XPConnect requires it to point to a valid bool nonetheless.
829 bool checkState = false;
830 bool userClickedOK = false;
831 rv = prompt->PromptPassword(nullptr, promptString.get(),
832 getter_Copies(password), nullptr, &checkState,
833 &userClickedOK);
834 if (NS_FAILED(rv) || !userClickedOK) {
835 return;
836 }
837
838 mResult = ToNewUTF8String(password);
839 }
840
841 char*
PK11PasswordPrompt(PK11SlotInfo * slot,PRBool,void * arg)842 PK11PasswordPrompt(PK11SlotInfo* slot, PRBool /*retry*/, void* arg)
843 {
844 RefPtr<PK11PasswordPromptRunnable> runnable(
845 new PK11PasswordPromptRunnable(slot,
846 static_cast<nsIInterfaceRequestor*>(arg)));
847 runnable->DispatchToMainThreadAndWait();
848 return runnable->mResult;
849 }
850
851 // call with shutdown prevention lock held
852 static void
PreliminaryHandshakeDone(PRFileDesc * fd)853 PreliminaryHandshakeDone(PRFileDesc* fd)
854 {
855 nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
856 if (!infoObject)
857 return;
858
859 SSLChannelInfo channelInfo;
860 if (SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)) == SECSuccess) {
861 infoObject->SetSSLVersionUsed(channelInfo.protocolVersion);
862 infoObject->SetEarlyDataAccepted(channelInfo.earlyDataAccepted);
863
864 SSLCipherSuiteInfo cipherInfo;
865 if (SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
866 sizeof cipherInfo) == SECSuccess) {
867 /* Set the SSL Status information */
868 RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
869 if (!status) {
870 status = new nsSSLStatus();
871 infoObject->SetSSLStatus(status);
872 }
873
874 status->mHaveCipherSuiteAndProtocol = true;
875 status->mCipherSuite = channelInfo.cipherSuite;
876 status->mProtocolVersion = channelInfo.protocolVersion & 0xFF;
877 infoObject->SetKEAUsed(channelInfo.keaType);
878 infoObject->SetKEAKeyBits(channelInfo.keaKeyBits);
879 infoObject->SetMACAlgorithmUsed(cipherInfo.macAlgorithm);
880 }
881 }
882
883 // Don't update NPN details on renegotiation.
884 if (infoObject->IsPreliminaryHandshakeDone()) {
885 return;
886 }
887
888 // Get the NPN value.
889 SSLNextProtoState state;
890 unsigned char npnbuf[256];
891 unsigned int npnlen;
892
893 if (SSL_GetNextProto(fd, &state, npnbuf, &npnlen,
894 AssertedCast<unsigned int>(ArrayLength(npnbuf)))
895 == SECSuccess) {
896 if (state == SSL_NEXT_PROTO_NEGOTIATED ||
897 state == SSL_NEXT_PROTO_SELECTED) {
898 infoObject->SetNegotiatedNPN(BitwiseCast<char*, unsigned char*>(npnbuf),
899 npnlen);
900 } else {
901 infoObject->SetNegotiatedNPN(nullptr, 0);
902 }
903 mozilla::Telemetry::Accumulate(Telemetry::SSL_NPN_TYPE, state);
904 } else {
905 infoObject->SetNegotiatedNPN(nullptr, 0);
906 }
907
908 infoObject->SetPreliminaryHandshakeDone();
909 }
910
911 SECStatus
CanFalseStartCallback(PRFileDesc * fd,void * client_data,PRBool * canFalseStart)912 CanFalseStartCallback(PRFileDesc* fd, void* client_data, PRBool *canFalseStart)
913 {
914 *canFalseStart = false;
915
916 nsNSSShutDownPreventionLock locker;
917
918 nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
919 if (!infoObject) {
920 PR_SetError(PR_INVALID_STATE_ERROR, 0);
921 return SECFailure;
922 }
923
924 infoObject->SetFalseStartCallbackCalled();
925
926 if (infoObject->isAlreadyShutDown()) {
927 MOZ_CRASH("SSL socket used after NSS shut down");
928 PR_SetError(PR_INVALID_STATE_ERROR, 0);
929 return SECFailure;
930 }
931
932 PreliminaryHandshakeDone(fd);
933
934 uint32_t reasonsForNotFalseStarting = 0;
935
936 SSLChannelInfo channelInfo;
937 if (SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)) != SECSuccess) {
938 return SECSuccess;
939 }
940
941 SSLCipherSuiteInfo cipherInfo;
942 if (SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
943 sizeof (cipherInfo)) != SECSuccess) {
944 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("CanFalseStartCallback [%p] failed - "
945 " KEA %d\n", fd,
946 static_cast<int32_t>(channelInfo.keaType)));
947 return SECSuccess;
948 }
949
950 nsSSLIOLayerHelpers& helpers = infoObject->SharedState().IOLayerHelpers();
951
952 // Prevent version downgrade attacks from TLS 1.2, and avoid False Start for
953 // TLS 1.3 and later. See Bug 861310 for all the details as to why.
954 if (channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2) {
955 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("CanFalseStartCallback [%p] failed - "
956 "SSL Version must be TLS 1.2, was %x\n", fd,
957 static_cast<int32_t>(channelInfo.protocolVersion)));
958 reasonsForNotFalseStarting |= POSSIBLE_VERSION_DOWNGRADE;
959 }
960
961 // See bug 952863 for why ECDHE is allowed, but DHE (and RSA) are not.
962 if (channelInfo.keaType != ssl_kea_ecdh) {
963 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("CanFalseStartCallback [%p] failed - "
964 "unsupported KEA %d\n", fd,
965 static_cast<int32_t>(channelInfo.keaType)));
966 reasonsForNotFalseStarting |= KEA_NOT_SUPPORTED;
967 }
968
969 // Prevent downgrade attacks on the symmetric cipher. We do not allow CBC
970 // mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt
971 // design. See bug 1109766 for more details.
972 if (cipherInfo.macAlgorithm != ssl_mac_aead) {
973 MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
974 ("CanFalseStartCallback [%p] failed - non-AEAD cipher used, %d, "
975 "is not supported with False Start.\n", fd,
976 static_cast<int32_t>(cipherInfo.symCipher)));
977 reasonsForNotFalseStarting |= POSSIBLE_CIPHER_SUITE_DOWNGRADE;
978 }
979
980 // XXX: An attacker can choose which protocols are advertised in the
981 // NPN extension. TODO(Bug 861311): We should restrict the ability
982 // of an attacker leverage this capability by restricting false start
983 // to the same protocol we previously saw for the server, after the
984 // first successful connection to the server.
985
986 // Enforce NPN to do false start if policy requires it. Do this as an
987 // indicator if server compatibility.
988 if (helpers.mFalseStartRequireNPN) {
989 nsAutoCString negotiatedNPN;
990 if (NS_FAILED(infoObject->GetNegotiatedNPN(negotiatedNPN)) ||
991 !negotiatedNPN.Length()) {
992 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("CanFalseStartCallback [%p] failed - "
993 "NPN cannot be verified\n", fd));
994 reasonsForNotFalseStarting |= NPN_NOT_NEGOTIATED;
995 }
996 }
997
998 Telemetry::Accumulate(Telemetry::SSL_REASONS_FOR_NOT_FALSE_STARTING,
999 reasonsForNotFalseStarting);
1000
1001 if (reasonsForNotFalseStarting == 0) {
1002 *canFalseStart = PR_TRUE;
1003 infoObject->SetFalseStarted();
1004 infoObject->NoteTimeUntilReady();
1005 MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("CanFalseStartCallback [%p] ok\n", fd));
1006 }
1007
1008 return SECSuccess;
1009 }
1010
1011 static void
AccumulateNonECCKeySize(Telemetry::ID probe,uint32_t bits)1012 AccumulateNonECCKeySize(Telemetry::ID probe, uint32_t bits)
1013 {
1014 unsigned int value = bits < 512 ? 1 : bits == 512 ? 2
1015 : bits < 768 ? 3 : bits == 768 ? 4
1016 : bits < 1024 ? 5 : bits == 1024 ? 6
1017 : bits < 1280 ? 7 : bits == 1280 ? 8
1018 : bits < 1536 ? 9 : bits == 1536 ? 10
1019 : bits < 2048 ? 11 : bits == 2048 ? 12
1020 : bits < 3072 ? 13 : bits == 3072 ? 14
1021 : bits < 4096 ? 15 : bits == 4096 ? 16
1022 : bits < 8192 ? 17 : bits == 8192 ? 18
1023 : bits < 16384 ? 19 : bits == 16384 ? 20
1024 : 0;
1025 Telemetry::Accumulate(probe, value);
1026 }
1027
1028 // XXX: This attempts to map a bit count to an ECC named curve identifier. In
1029 // the vast majority of situations, we only have the Suite B curves available.
1030 // In that case, this mapping works fine. If we were to have more curves
1031 // available, the mapping would be ambiguous since there could be multiple
1032 // named curves for a given size (e.g. secp256k1 vs. secp256r1). We punt on
1033 // that for now. See also NSS bug 323674.
1034 static void
AccumulateECCCurve(Telemetry::ID probe,uint32_t bits)1035 AccumulateECCCurve(Telemetry::ID probe, uint32_t bits)
1036 {
1037 unsigned int value = bits == 256 ? 23 // P-256
1038 : bits == 384 ? 24 // P-384
1039 : bits == 521 ? 25 // P-521
1040 : 0; // Unknown
1041 Telemetry::Accumulate(probe, value);
1042 }
1043
1044 static void
AccumulateCipherSuite(Telemetry::ID probe,const SSLChannelInfo & channelInfo)1045 AccumulateCipherSuite(Telemetry::ID probe, const SSLChannelInfo& channelInfo)
1046 {
1047 uint32_t value;
1048 switch (channelInfo.cipherSuite) {
1049 // ECDHE key exchange
1050 case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: value = 1; break;
1051 case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: value = 2; break;
1052 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: value = 3; break;
1053 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: value = 4; break;
1054 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: value = 5; break;
1055 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: value = 6; break;
1056 case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: value = 7; break;
1057 case TLS_ECDHE_RSA_WITH_RC4_128_SHA: value = 8; break;
1058 case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: value = 9; break;
1059 case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: value = 10; break;
1060 case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: value = 11; break;
1061 case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: value = 12; break;
1062 case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: value = 13; break;
1063 case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: value = 14; break;
1064 // DHE key exchange
1065 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: value = 21; break;
1066 case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: value = 22; break;
1067 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: value = 23; break;
1068 case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: value = 24; break;
1069 case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: value = 25; break;
1070 case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: value = 26; break;
1071 case TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: value = 27; break;
1072 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: value = 28; break;
1073 case TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: value = 29; break;
1074 case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: value = 30; break;
1075 // ECDH key exchange
1076 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: value = 41; break;
1077 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: value = 42; break;
1078 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: value = 43; break;
1079 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: value = 44; break;
1080 case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: value = 45; break;
1081 case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: value = 46; break;
1082 case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: value = 47; break;
1083 case TLS_ECDH_RSA_WITH_RC4_128_SHA: value = 48; break;
1084 // RSA key exchange
1085 case TLS_RSA_WITH_AES_128_CBC_SHA: value = 61; break;
1086 case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: value = 62; break;
1087 case TLS_RSA_WITH_AES_256_CBC_SHA: value = 63; break;
1088 case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: value = 64; break;
1089 case SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA: value = 65; break;
1090 case TLS_RSA_WITH_3DES_EDE_CBC_SHA: value = 66; break;
1091 case TLS_RSA_WITH_SEED_CBC_SHA: value = 67; break;
1092 case TLS_RSA_WITH_RC4_128_SHA: value = 68; break;
1093 case TLS_RSA_WITH_RC4_128_MD5: value = 69; break;
1094 // TLS 1.3 PSK resumption
1095 case TLS_AES_128_GCM_SHA256: value = 70; break;
1096 case TLS_CHACHA20_POLY1305_SHA256: value = 71; break;
1097 case TLS_AES_256_GCM_SHA384: value = 72; break;
1098 // unknown
1099 default:
1100 value = 0;
1101 break;
1102 }
1103 MOZ_ASSERT(value != 0);
1104 Telemetry::Accumulate(probe, value);
1105 }
1106
1107 // In the case of session resumption, the AuthCertificate hook has been bypassed
1108 // (because we've previously successfully connected to our peer). That being the
1109 // case, we unfortunately don't know if the peer's server certificate verified
1110 // as extended validation or not. To address this, we attempt to build a
1111 // verified EV certificate chain here using as much of the original context as
1112 // possible (e.g. stapled OCSP responses, SCTs, the hostname, the first party
1113 // domain, etc.). Note that because we are on the socket thread, this must not
1114 // cause any network requests, hence the use of FLAG_LOCAL_ONLY.
1115 static void
DetermineEVStatusAndSetNewCert(RefPtr<nsSSLStatus> sslStatus,PRFileDesc * fd,nsNSSSocketInfo * infoObject)1116 DetermineEVStatusAndSetNewCert(RefPtr<nsSSLStatus> sslStatus, PRFileDesc* fd,
1117 nsNSSSocketInfo* infoObject)
1118 {
1119 MOZ_ASSERT(sslStatus);
1120 MOZ_ASSERT(fd);
1121 MOZ_ASSERT(infoObject);
1122
1123 if (!sslStatus || !fd || !infoObject) {
1124 return;
1125 }
1126
1127 UniqueCERTCertificate cert(SSL_PeerCertificate(fd));
1128 MOZ_ASSERT(cert, "SSL_PeerCertificate failed in TLS handshake callback?");
1129 if (!cert) {
1130 return;
1131 }
1132
1133 RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
1134 MOZ_ASSERT(certVerifier,
1135 "Certificate verifier uninitialized in TLS handshake callback?");
1136 if (!certVerifier) {
1137 return;
1138 }
1139
1140 // We don't own these pointers.
1141 const SECItemArray* stapledOCSPResponses = SSL_PeerStapledOCSPResponses(fd);
1142 const SECItem* stapledOCSPResponse = nullptr;
1143 // we currently only support single stapled responses
1144 if (stapledOCSPResponses && stapledOCSPResponses->len == 1) {
1145 stapledOCSPResponse = &stapledOCSPResponses->items[0];
1146 }
1147 const SECItem* sctsFromTLSExtension = SSL_PeerSignedCertTimestamps(fd);
1148 if (sctsFromTLSExtension && sctsFromTLSExtension->len == 0) {
1149 // SSL_PeerSignedCertTimestamps returns null on error and empty item
1150 // when no extension was returned by the server. We always use null when
1151 // no extension was received (for whatever reason), ignoring errors.
1152 sctsFromTLSExtension = nullptr;
1153 }
1154
1155 int flags = mozilla::psm::CertVerifier::FLAG_LOCAL_ONLY |
1156 mozilla::psm::CertVerifier::FLAG_MUST_BE_EV;
1157 if (!infoObject->SharedState().IsOCSPStaplingEnabled() ||
1158 !infoObject->SharedState().IsOCSPMustStapleEnabled()) {
1159 flags |= CertVerifier::FLAG_TLS_IGNORE_STATUS_REQUEST;
1160 }
1161
1162 SECOidTag evOidPolicy;
1163 UniqueCERTCertList unusedBuiltChain;
1164 const bool saveIntermediates = false;
1165 mozilla::pkix::Result rv = certVerifier->VerifySSLServerCert(
1166 cert,
1167 stapledOCSPResponse,
1168 sctsFromTLSExtension,
1169 mozilla::pkix::Now(),
1170 infoObject,
1171 infoObject->GetHostNameRaw(),
1172 unusedBuiltChain,
1173 saveIntermediates,
1174 flags,
1175 infoObject->GetOriginAttributes(),
1176 &evOidPolicy);
1177
1178 RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(cert.get()));
1179 if (rv == Success && evOidPolicy != SEC_OID_UNKNOWN) {
1180 MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1181 ("HandshakeCallback using NEW cert %p (is EV)", nssc.get()));
1182 sslStatus->SetServerCert(nssc, EVStatus::EV);
1183 } else {
1184 MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1185 ("HandshakeCallback using NEW cert %p (is not EV)", nssc.get()));
1186 sslStatus->SetServerCert(nssc, EVStatus::NotEV);
1187 }
1188 }
1189
HandshakeCallback(PRFileDesc * fd,void * client_data)1190 void HandshakeCallback(PRFileDesc* fd, void* client_data) {
1191 nsNSSShutDownPreventionLock locker;
1192 SECStatus rv;
1193
1194 nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
1195
1196 // Do the bookkeeping that needs to be done after the
1197 // server's ServerHello...ServerHelloDone have been processed, but that doesn't
1198 // need the handshake to be completed.
1199 PreliminaryHandshakeDone(fd);
1200
1201 nsSSLIOLayerHelpers& ioLayerHelpers
1202 = infoObject->SharedState().IOLayerHelpers();
1203
1204 SSLVersionRange versions(infoObject->GetTLSVersionRange());
1205
1206 MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1207 ("[%p] HandshakeCallback: succeeded using TLS version range (0x%04x,0x%04x)\n",
1208 fd, static_cast<unsigned int>(versions.min),
1209 static_cast<unsigned int>(versions.max)));
1210
1211 // If the handshake completed, then we know the site is TLS tolerant
1212 ioLayerHelpers.rememberTolerantAtVersion(infoObject->GetHostName(),
1213 infoObject->GetPort(),
1214 versions.max);
1215
1216 bool usesFallbackCipher = false;
1217 SSLChannelInfo channelInfo;
1218 rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo));
1219 MOZ_ASSERT(rv == SECSuccess);
1220 if (rv == SECSuccess) {
1221 // Get the protocol version for telemetry
1222 // 1=tls1, 2=tls1.1, 3=tls1.2
1223 unsigned int versionEnum = channelInfo.protocolVersion & 0xFF;
1224 MOZ_ASSERT(versionEnum > 0);
1225 Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_VERSION, versionEnum);
1226 AccumulateCipherSuite(
1227 infoObject->IsFullHandshake() ? Telemetry::SSL_CIPHER_SUITE_FULL
1228 : Telemetry::SSL_CIPHER_SUITE_RESUMED,
1229 channelInfo);
1230
1231 SSLCipherSuiteInfo cipherInfo;
1232 rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
1233 sizeof cipherInfo);
1234 MOZ_ASSERT(rv == SECSuccess);
1235 if (rv == SECSuccess) {
1236 usesFallbackCipher = channelInfo.keaType == ssl_kea_dh;
1237
1238 // keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4
1239 Telemetry::Accumulate(
1240 infoObject->IsFullHandshake()
1241 ? Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_FULL
1242 : Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_RESUMED,
1243 channelInfo.keaType);
1244
1245 MOZ_ASSERT(infoObject->GetKEAUsed() == channelInfo.keaType);
1246
1247 if (infoObject->IsFullHandshake()) {
1248 switch (channelInfo.keaType) {
1249 case ssl_kea_rsa:
1250 AccumulateNonECCKeySize(Telemetry::SSL_KEA_RSA_KEY_SIZE_FULL,
1251 channelInfo.keaKeyBits);
1252 break;
1253 case ssl_kea_dh:
1254 AccumulateNonECCKeySize(Telemetry::SSL_KEA_DHE_KEY_SIZE_FULL,
1255 channelInfo.keaKeyBits);
1256 break;
1257 case ssl_kea_ecdh:
1258 AccumulateECCCurve(Telemetry::SSL_KEA_ECDHE_CURVE_FULL,
1259 channelInfo.keaKeyBits);
1260 break;
1261 default:
1262 MOZ_CRASH("impossible KEA");
1263 break;
1264 }
1265
1266 Telemetry::Accumulate(Telemetry::SSL_AUTH_ALGORITHM_FULL,
1267 channelInfo.authType);
1268
1269 // RSA key exchange doesn't use a signature for auth.
1270 if (channelInfo.keaType != ssl_kea_rsa) {
1271 switch (channelInfo.authType) {
1272 case ssl_auth_rsa:
1273 case ssl_auth_rsa_sign:
1274 AccumulateNonECCKeySize(Telemetry::SSL_AUTH_RSA_KEY_SIZE_FULL,
1275 channelInfo.authKeyBits);
1276 break;
1277 case ssl_auth_ecdsa:
1278 AccumulateECCCurve(Telemetry::SSL_AUTH_ECDSA_CURVE_FULL,
1279 channelInfo.authKeyBits);
1280 break;
1281 default:
1282 MOZ_CRASH("impossible auth algorithm");
1283 break;
1284 }
1285 }
1286 }
1287
1288 Telemetry::Accumulate(
1289 infoObject->IsFullHandshake()
1290 ? Telemetry::SSL_SYMMETRIC_CIPHER_FULL
1291 : Telemetry::SSL_SYMMETRIC_CIPHER_RESUMED,
1292 cipherInfo.symCipher);
1293 }
1294 }
1295
1296 PRBool siteSupportsSafeRenego;
1297 if (channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_3) {
1298 rv = SSL_HandshakeNegotiatedExtension(fd, ssl_renegotiation_info_xtn,
1299 &siteSupportsSafeRenego);
1300 MOZ_ASSERT(rv == SECSuccess);
1301 if (rv != SECSuccess) {
1302 siteSupportsSafeRenego = false;
1303 }
1304 } else {
1305 // TLS 1.3 dropped support for renegotiation.
1306 siteSupportsSafeRenego = true;
1307 }
1308 bool renegotiationUnsafe = !siteSupportsSafeRenego &&
1309 ioLayerHelpers.treatUnsafeNegotiationAsBroken();
1310
1311
1312 /* Set the SSL Status information */
1313 RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
1314 if (!status) {
1315 status = new nsSSLStatus();
1316 infoObject->SetSSLStatus(status);
1317 }
1318
1319 RememberCertErrorsTable::GetInstance().LookupCertErrorBits(infoObject,
1320 status);
1321
1322 uint32_t state;
1323 if (renegotiationUnsafe) {
1324 state = nsIWebProgressListener::STATE_IS_BROKEN;
1325 } else {
1326 state = nsIWebProgressListener::STATE_IS_SECURE |
1327 nsIWebProgressListener::STATE_SECURE_HIGH;
1328 if (!usesFallbackCipher) {
1329 SSLVersionRange defVersion;
1330 rv = SSL_VersionRangeGetDefault(ssl_variant_stream, &defVersion);
1331 if (rv == SECSuccess && versions.max >= defVersion.max) {
1332 // we know this site no longer requires a fallback cipher
1333 ioLayerHelpers.removeInsecureFallbackSite(infoObject->GetHostName(),
1334 infoObject->GetPort());
1335 }
1336 }
1337 }
1338
1339 if (status->HasServerCert()) {
1340 MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
1341 ("HandshakeCallback KEEPING existing cert\n"));
1342 } else {
1343 DetermineEVStatusAndSetNewCert(status, fd, infoObject);
1344 }
1345
1346 bool domainMismatch;
1347 bool untrusted;
1348 bool notValidAtThisTime;
1349 // These all return NS_OK, so don't even bother checking the return values.
1350 Unused << status->GetIsDomainMismatch(&domainMismatch);
1351 Unused << status->GetIsUntrusted(&untrusted);
1352 Unused << status->GetIsNotValidAtThisTime(¬ValidAtThisTime);
1353 // If we're here, the TLS handshake has succeeded. Thus if any of these
1354 // booleans are true, the user has added an override for a certificate error.
1355 if (domainMismatch || untrusted || notValidAtThisTime) {
1356 state |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
1357 }
1358
1359 infoObject->SetSecurityState(state);
1360
1361 // XXX Bug 883674: We shouldn't be formatting messages here in PSM; instead,
1362 // we should set a flag on the channel that higher (UI) level code can check
1363 // to log the warning. In particular, these warnings should go to the web
1364 // console instead of to the error console. Also, the warning is not
1365 // localized.
1366 if (!siteSupportsSafeRenego) {
1367 nsXPIDLCString hostName;
1368 infoObject->GetHostName(getter_Copies(hostName));
1369
1370 nsAutoString msg;
1371 msg.Append(NS_ConvertASCIItoUTF16(hostName));
1372 msg.AppendLiteral(" : server does not support RFC 5746, see CVE-2009-3555");
1373
1374 nsContentUtils::LogSimpleConsoleError(msg, "SSL");
1375 }
1376
1377 infoObject->NoteTimeUntilReady();
1378 infoObject->SetHandshakeCompleted();
1379 }
1380