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(&notValidAtThisTime);
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