1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : *
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Hubbie Shaw
25 : * Doug Turner <dougt@netscape.com>
26 : * Mitch Stoltz <mstoltz@netscape.com>
27 : * Brian Ryner <bryner@brianryner.com>
28 : * Kai Engert <kaie@netscape.com>
29 : * Vipul Gupta <vipul.gupta@sun.com>
30 : * Douglas Stebila <douglas@stebila.ca>
31 : * Kai Engert <kengert@redhat.com>
32 : *
33 : * Alternatively, the contents of this file may be used under the terms of
34 : * either the GNU General Public License Version 2 or later (the "GPL"), or
35 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
36 : * in which case the provisions of the GPL or the LGPL are applicable instead
37 : * of those above. If you wish to allow use of your version of this file only
38 : * under the terms of either the GPL or the LGPL, and not to allow others to
39 : * use your version of this file under the terms of the MPL, indicate your
40 : * decision by deleting the provisions above and replace them with the notice
41 : * and other provisions required by the GPL or the LGPL. If you do not delete
42 : * the provisions above, a recipient may use your version of this file under
43 : * the terms of any one of the MPL, the GPL or the LGPL.
44 : *
45 : * ***** END LICENSE BLOCK ***** */
46 :
47 : #include "nsNSSComponent.h"
48 : #include "nsNSSCallbacks.h"
49 : #include "nsNSSIOLayer.h"
50 : #include "nsCertVerificationThread.h"
51 :
52 : #include "nsNetUtil.h"
53 : #include "nsAppDirectoryServiceDefs.h"
54 : #include "nsDirectoryService.h"
55 : #include "nsIStreamListener.h"
56 : #include "nsIStringBundle.h"
57 : #include "nsIDirectoryService.h"
58 : #include "nsIDOMNode.h"
59 : #include "nsCURILoader.h"
60 : #include "nsDirectoryServiceDefs.h"
61 : #include "nsIX509Cert.h"
62 : #include "nsIX509CertDB.h"
63 : #include "nsIProfileChangeStatus.h"
64 : #include "nsNSSCertificate.h"
65 : #include "nsNSSHelper.h"
66 : #include "nsSmartCardMonitor.h"
67 : #include "prlog.h"
68 : #include "nsIPrefService.h"
69 : #include "nsIPrefBranch.h"
70 : #include "nsIDateTimeFormat.h"
71 : #include "nsDateTimeFormatCID.h"
72 : #include "nsIDOMEvent.h"
73 : #include "nsIDOMDocument.h"
74 : #include "nsIDOMWindow.h"
75 : #include "nsIDOMWindowCollection.h"
76 : #include "nsIDOMSmartCardEvent.h"
77 : #include "nsIDOMCrypto.h"
78 : #include "nsThreadUtils.h"
79 : #include "nsAutoPtr.h"
80 : #include "nsCRT.h"
81 : #include "nsCRLInfo.h"
82 : #include "nsCertOverrideService.h"
83 :
84 : #include "nsIWindowWatcher.h"
85 : #include "nsIPrompt.h"
86 : #include "nsIPrincipal.h"
87 : #include "nsReadableUtils.h"
88 : #include "nsIDateTimeFormat.h"
89 : #include "prtypes.h"
90 : #include "nsIEntropyCollector.h"
91 : #include "nsIBufEntropyCollector.h"
92 : #include "nsIServiceManager.h"
93 : #include "nsILocalFile.h"
94 : #include "nsITokenPasswordDialogs.h"
95 : #include "nsICRLManager.h"
96 : #include "nsNSSShutDown.h"
97 : #include "nsSmartCardEvent.h"
98 : #include "nsIKeyModule.h"
99 :
100 : #include "nss.h"
101 : #include "pk11func.h"
102 : #include "ssl.h"
103 : #include "sslproto.h"
104 : #include "secmod.h"
105 : #include "sechash.h"
106 : #include "secmime.h"
107 : #include "ocsp.h"
108 : #include "cms.h"
109 : #include "nssckbi.h"
110 : #include "base64.h"
111 : #include "secerr.h"
112 : #include "sslerr.h"
113 : #include "cert.h"
114 :
115 : #include "nsXULAppAPI.h"
116 :
117 : #ifdef XP_WIN
118 : #include "nsILocalFileWin.h"
119 : #endif
120 :
121 : extern "C" {
122 : #include "pkcs12.h"
123 : #include "p12plcy.h"
124 : }
125 :
126 : using namespace mozilla;
127 :
128 : #ifdef PR_LOGGING
129 : PRLogModuleInfo* gPIPNSSLog = nsnull;
130 : #endif
131 :
132 : #define NS_CRYPTO_HASH_BUFFER_SIZE 4096
133 :
134 : static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
135 : int nsNSSComponent::mInstanceCount = 0;
136 : bool nsNSSComponent::globalConstFlagUsePKIXVerification = false;
137 :
138 : // XXX tmp callback for slot password
139 : extern char * PR_CALLBACK
140 : pk11PasswordPrompt(PK11SlotInfo *slot, PRBool retry, void *arg);
141 :
142 : #define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties"
143 : #define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties"
144 :
145 0 : static PLHashNumber PR_CALLBACK certHashtable_keyHash(const void *key)
146 : {
147 0 : if (!key)
148 0 : return 0;
149 :
150 0 : SECItem *certKey = (SECItem*)key;
151 :
152 : // lazy hash function, sum up all char values of SECItem
153 :
154 0 : PLHashNumber hash = 0;
155 0 : unsigned int i = 0;
156 0 : unsigned char *c = certKey->data;
157 :
158 0 : for (i = 0; i < certKey->len; ++i, ++c) {
159 0 : hash += *c;
160 : }
161 :
162 0 : return hash;
163 : }
164 :
165 0 : static PRIntn PR_CALLBACK certHashtable_keyCompare(const void *k1, const void *k2)
166 : {
167 : // return type is a bool, answering the question "are the keys equal?"
168 :
169 0 : if (!k1 || !k2)
170 0 : return false;
171 :
172 0 : SECItem *certKey1 = (SECItem*)k1;
173 0 : SECItem *certKey2 = (SECItem*)k2;
174 :
175 0 : if (certKey1->len != certKey2->len) {
176 0 : return false;
177 : }
178 :
179 0 : unsigned int i = 0;
180 0 : unsigned char *c1 = certKey1->data;
181 0 : unsigned char *c2 = certKey2->data;
182 :
183 0 : for (i = 0; i < certKey1->len; ++i, ++c1, ++c2) {
184 0 : if (*c1 != *c2) {
185 0 : return false;
186 : }
187 : }
188 :
189 0 : return true;
190 : }
191 :
192 0 : static PRIntn PR_CALLBACK certHashtable_valueCompare(const void *v1, const void *v2)
193 : {
194 : // two values are identical if their keys are identical
195 :
196 0 : if (!v1 || !v2)
197 0 : return false;
198 :
199 0 : CERTCertificate *cert1 = (CERTCertificate*)v1;
200 0 : CERTCertificate *cert2 = (CERTCertificate*)v2;
201 :
202 0 : return certHashtable_keyCompare(&cert1->certKey, &cert2->certKey);
203 : }
204 :
205 0 : static PRIntn PR_CALLBACK certHashtable_clearEntry(PLHashEntry *he, PRIntn /*index*/, void * /*userdata*/)
206 : {
207 0 : if (he && he->value) {
208 0 : CERT_DestroyCertificate((CERTCertificate*)he->value);
209 : }
210 :
211 0 : return HT_ENUMERATE_NEXT;
212 : }
213 :
214 0 : class CRLDownloadEvent : public nsRunnable {
215 : public:
216 0 : CRLDownloadEvent(const nsCSubstring &urlString, nsIStreamListener *listener)
217 : : mURLString(urlString)
218 0 : , mListener(listener)
219 0 : {}
220 :
221 : // Note that nsNSSComponent is a singleton object across all threads,
222 : // and automatic downloads are always scheduled sequentially - that is,
223 : // once one crl download is complete, the next one is scheduled
224 0 : NS_IMETHOD Run()
225 : {
226 0 : if (!mListener || mURLString.IsEmpty())
227 0 : return NS_OK;
228 :
229 0 : nsCOMPtr<nsIURI> uri;
230 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri), mURLString);
231 0 : if (NS_SUCCEEDED(rv)){
232 0 : NS_OpenURI(mListener, nsnull, uri);
233 : }
234 :
235 0 : return NS_OK;
236 : }
237 :
238 : private:
239 : nsCString mURLString;
240 : nsCOMPtr<nsIStreamListener> mListener;
241 : };
242 :
243 : //This class is used to run the callback code
244 : //passed to the event handlers for smart card notification
245 : class nsTokenEventRunnable : public nsIRunnable {
246 : public:
247 : nsTokenEventRunnable(const nsAString &aType, const nsAString &aTokenName);
248 : virtual ~nsTokenEventRunnable();
249 :
250 : NS_IMETHOD Run ();
251 : NS_DECL_ISUPPORTS
252 : private:
253 : nsString mType;
254 : nsString mTokenName;
255 : };
256 :
257 : // ISuuports implementation for nsTokenEventRunnable
258 0 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsTokenEventRunnable, nsIRunnable)
259 :
260 0 : nsTokenEventRunnable::nsTokenEventRunnable(const nsAString &aType,
261 0 : const nsAString &aTokenName): mType(aType), mTokenName(aTokenName) { }
262 :
263 0 : nsTokenEventRunnable::~nsTokenEventRunnable() { }
264 :
265 : //Implementation that runs the callback passed to
266 : //crypto.generateCRMFRequest as an event.
267 : NS_IMETHODIMP
268 0 : nsTokenEventRunnable::Run()
269 : {
270 : nsresult rv;
271 0 : nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
272 0 : if (NS_FAILED(rv))
273 0 : return rv;
274 :
275 0 : return nssComponent->DispatchEvent(mType, mTokenName);
276 : }
277 :
278 : bool nsPSMInitPanic::isPanic = false;
279 :
280 : // We must ensure that the nsNSSComponent has been loaded before
281 : // creating any other components.
282 9864 : bool EnsureNSSInitialized(EnsureNSSOperator op)
283 : {
284 9864 : if (nsPSMInitPanic::GetPanic())
285 0 : return false;
286 :
287 9864 : if (GeckoProcessType_Default != XRE_GetProcessType())
288 : {
289 0 : if (op == nssEnsureOnChromeOnly)
290 : {
291 : // If the component needs PSM/NSS initialized only on the chrome process,
292 : // pretend we successfully initiated it but in reality we bypass it.
293 : // It's up to the programmer to check for process type in such components
294 : // and take care not to call anything that needs NSS/PSM initiated.
295 0 : return true;
296 : }
297 :
298 0 : NS_ERROR("Trying to initialize PSM/NSS in a non-chrome process!");
299 0 : return false;
300 : }
301 :
302 : static bool loading = false;
303 : static PRInt32 haveLoaded = 0;
304 :
305 9864 : switch (op)
306 : {
307 : // In following 4 cases we are protected by monitor of XPCOM component
308 : // manager - we are inside of do_GetService call for nss component, so it is
309 : // safe to move with the flags here.
310 : case nssLoadingComponent:
311 328 : if (loading)
312 0 : return false; // We are reentered during nss component creation
313 328 : loading = true;
314 328 : return true;
315 :
316 : case nssInitSucceeded:
317 328 : NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitSucceeded)");
318 328 : loading = false;
319 328 : PR_AtomicSet(&haveLoaded, 1);
320 328 : return true;
321 :
322 : case nssInitFailed:
323 0 : NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitFailed)");
324 0 : loading = false;
325 : // no break
326 :
327 : case nssShutdown:
328 656 : PR_AtomicSet(&haveLoaded, 0);
329 656 : return false;
330 :
331 : // In this case we are called from a component to ensure nss initilization.
332 : // If the component has not yet been loaded and is not currently loading
333 : // call do_GetService for nss component to ensure it.
334 : case nssEnsure:
335 : case nssEnsureOnChromeOnly:
336 : // We are reentered during nss component creation or nss component is already up
337 8552 : if (PR_AtomicAdd(&haveLoaded, 0) || loading)
338 8273 : return true;
339 :
340 : {
341 : nsCOMPtr<nsINSSComponent> nssComponent
342 558 : = do_GetService(PSM_COMPONENT_CONTRACTID);
343 :
344 : // Nss component failed to initialize, inform the caller of that fact.
345 : // Flags are appropriately set by component constructor itself.
346 279 : if (!nssComponent)
347 0 : return false;
348 :
349 : bool isInitialized;
350 279 : nsresult rv = nssComponent->IsNSSInitialized(&isInitialized);
351 279 : return NS_SUCCEEDED(rv) && isInitialized;
352 : }
353 :
354 : default:
355 0 : NS_ASSERTION(false, "Bad operator to EnsureNSSInitialized");
356 0 : return false;
357 : }
358 : }
359 :
360 328 : nsNSSComponent::nsNSSComponent()
361 : :mutex("nsNSSComponent.mutex"),
362 : mNSSInitialized(false),
363 : mCrlTimerLock("nsNSSComponent.mCrlTimerLock"),
364 : mThreadList(nsnull),
365 328 : mCertVerificationThread(NULL)
366 : {
367 : #ifdef PR_LOGGING
368 328 : if (!gPIPNSSLog)
369 328 : gPIPNSSLog = PR_NewLogModule("pipnss");
370 : #endif
371 328 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ctor\n"));
372 328 : mUpdateTimerInitialized = false;
373 328 : crlDownloadTimerOn = false;
374 328 : crlsScheduledForDownload = nsnull;
375 328 : mTimer = nsnull;
376 328 : mObserversRegistered = false;
377 :
378 : // In order to keep startup time lower, we delay loading and
379 : // registering all identity data until first needed.
380 328 : memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType));
381 :
382 328 : NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!");
383 328 : ++mInstanceCount;
384 328 : hashTableCerts = nsnull;
385 328 : mShutdownObjectList = nsNSSShutDownList::construct();
386 328 : mIsNetworkDown = false;
387 328 : }
388 :
389 : void
390 328 : nsNSSComponent::deleteBackgroundThreads()
391 : {
392 328 : if (mCertVerificationThread)
393 : {
394 328 : mCertVerificationThread->requestExit();
395 328 : delete mCertVerificationThread;
396 328 : mCertVerificationThread = nsnull;
397 : }
398 328 : }
399 :
400 : void
401 328 : nsNSSComponent::createBackgroundThreads()
402 : {
403 328 : NS_ASSERTION(mCertVerificationThread == nsnull,
404 : "Cert verification thread already created.");
405 :
406 328 : mCertVerificationThread = new nsCertVerificationThread;
407 328 : nsresult rv = mCertVerificationThread->startThread();
408 328 : if (NS_FAILED(rv)) {
409 0 : delete mCertVerificationThread;
410 0 : mCertVerificationThread = nsnull;
411 : }
412 328 : }
413 :
414 984 : nsNSSComponent::~nsNSSComponent()
415 : {
416 328 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor\n"));
417 :
418 328 : deleteBackgroundThreads();
419 :
420 328 : if (mUpdateTimerInitialized) {
421 : {
422 34 : MutexAutoLock lock(mCrlTimerLock);
423 17 : if (crlDownloadTimerOn) {
424 0 : mTimer->Cancel();
425 : }
426 17 : crlDownloadTimerOn = false;
427 : }
428 17 : if(crlsScheduledForDownload != nsnull){
429 17 : crlsScheduledForDownload->Reset();
430 17 : delete crlsScheduledForDownload;
431 : }
432 :
433 17 : mUpdateTimerInitialized = false;
434 : }
435 :
436 : // All cleanup code requiring services needs to happen in xpcom_shutdown
437 :
438 328 : ShutdownNSS();
439 328 : nsSSLIOLayerHelpers::Cleanup();
440 328 : --mInstanceCount;
441 328 : delete mShutdownObjectList;
442 :
443 : // We are being freed, drop the haveLoaded flag to re-enable
444 : // potential nss initialization later.
445 328 : EnsureNSSInitialized(nssShutdown);
446 :
447 328 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::dtor finished\n"));
448 1312 : }
449 :
450 : NS_IMETHODIMP
451 0 : nsNSSComponent::PostEvent(const nsAString &eventType,
452 : const nsAString &tokenName)
453 : {
454 : nsCOMPtr<nsIRunnable> runnable =
455 0 : new nsTokenEventRunnable(eventType, tokenName);
456 0 : if (!runnable) {
457 0 : return NS_ERROR_OUT_OF_MEMORY;
458 : }
459 :
460 0 : return NS_DispatchToMainThread(runnable);
461 : }
462 :
463 :
464 : NS_IMETHODIMP
465 0 : nsNSSComponent::DispatchEvent(const nsAString &eventType,
466 : const nsAString &tokenName)
467 : {
468 : // 'Dispatch' the event to all the windows. 'DispatchEventToWindow()' will
469 : // first check to see if a given window has requested crypto events.
470 : nsresult rv;
471 : nsCOMPtr<nsIWindowWatcher> windowWatcher =
472 0 : do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
473 :
474 0 : if (NS_FAILED(rv)) {
475 0 : return rv;
476 : }
477 :
478 0 : nsCOMPtr<nsISimpleEnumerator> enumerator;
479 0 : rv = windowWatcher->GetWindowEnumerator(getter_AddRefs(enumerator));
480 0 : if (NS_FAILED(rv)) {
481 0 : return rv;
482 : }
483 :
484 : bool hasMoreWindows;
485 :
486 0 : while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreWindows))
487 : && hasMoreWindows) {
488 0 : nsCOMPtr<nsISupports> supports;
489 0 : enumerator->GetNext(getter_AddRefs(supports));
490 0 : nsCOMPtr<nsIDOMWindow> domWin(do_QueryInterface(supports));
491 0 : if (domWin) {
492 0 : nsresult rv2 = DispatchEventToWindow(domWin, eventType, tokenName);
493 0 : if (NS_FAILED(rv2)) {
494 : // return the last failure, don't let a single failure prevent
495 : // continued delivery of events.
496 0 : rv = rv2;
497 : }
498 : }
499 : }
500 0 : return rv;
501 : }
502 :
503 : nsresult
504 0 : nsNSSComponent::DispatchEventToWindow(nsIDOMWindow *domWin,
505 : const nsAString &eventType, const nsAString &tokenName)
506 : {
507 : // first walk the children and dispatch their events
508 : {
509 : nsresult rv;
510 0 : nsCOMPtr<nsIDOMWindowCollection> frames;
511 0 : rv = domWin->GetFrames(getter_AddRefs(frames));
512 0 : if (NS_FAILED(rv)) {
513 0 : return rv;
514 : }
515 :
516 : PRUint32 length;
517 0 : frames->GetLength(&length);
518 : PRUint32 i;
519 0 : for (i = 0; i < length; i++) {
520 0 : nsCOMPtr<nsIDOMWindow> childWin;
521 0 : frames->Item(i, getter_AddRefs(childWin));
522 0 : DispatchEventToWindow(childWin, eventType, tokenName);
523 : }
524 : }
525 :
526 : // check if we've enabled smart card events on this window
527 : // NOTE: it's not an error to say that we aren't going to dispatch
528 : // the event.
529 : {
530 0 : nsCOMPtr<nsIDOMWindow> domWindow = domWin;
531 0 : if (!domWindow) {
532 0 : return NS_OK; // nope, it's not an internal window
533 : }
534 :
535 0 : nsCOMPtr<nsIDOMCrypto> crypto;
536 0 : domWindow->GetCrypto(getter_AddRefs(crypto));
537 0 : if (!crypto) {
538 0 : return NS_OK; // nope, it doesn't have a crypto property
539 : }
540 :
541 : bool boolrv;
542 0 : crypto->GetEnableSmartCardEvents(&boolrv);
543 0 : if (!boolrv) {
544 0 : return NS_OK; // nope, it's not enabled.
545 : }
546 : }
547 :
548 : // dispatch the event ...
549 :
550 : nsresult rv;
551 : // find the document
552 0 : nsCOMPtr<nsIDOMDocument> doc;
553 0 : rv = domWin->GetDocument(getter_AddRefs(doc));
554 0 : if (doc == nsnull) {
555 0 : return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
556 : }
557 :
558 : // create the event
559 0 : nsCOMPtr<nsIDOMEvent> event;
560 0 : rv = doc->CreateEvent(NS_LITERAL_STRING("Events"),
561 0 : getter_AddRefs(event));
562 0 : if (NS_FAILED(rv)) {
563 0 : return rv;
564 : }
565 :
566 0 : event->InitEvent(eventType, false, true);
567 :
568 : // create the Smart Card Event;
569 : nsCOMPtr<nsIDOMSmartCardEvent> smartCardEvent =
570 0 : new nsSmartCardEvent(tokenName);
571 : // init the smart card event, fail here if we can't complete the
572 : // initialization.
573 0 : if (!smartCardEvent) {
574 0 : return NS_ERROR_OUT_OF_MEMORY;
575 : }
576 :
577 0 : rv = smartCardEvent->Init(event);
578 0 : if (NS_FAILED(rv)) {
579 0 : return rv;
580 : }
581 :
582 : // Send it
583 0 : nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(doc, &rv);
584 0 : if (NS_FAILED(rv)) {
585 0 : return rv;
586 : }
587 :
588 : bool boolrv;
589 0 : rv = target->DispatchEvent(smartCardEvent, &boolrv);
590 0 : return rv;
591 : }
592 :
593 :
594 : NS_IMETHODIMP
595 4 : nsNSSComponent::PIPBundleFormatStringFromName(const char *name,
596 : const PRUnichar **params,
597 : PRUint32 numParams,
598 : nsAString &outString)
599 : {
600 4 : nsresult rv = NS_ERROR_FAILURE;
601 :
602 4 : if (mPIPNSSBundle && name) {
603 8 : nsXPIDLString result;
604 8 : rv = mPIPNSSBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
605 : params, numParams,
606 8 : getter_Copies(result));
607 4 : if (NS_SUCCEEDED(rv)) {
608 4 : outString = result;
609 : }
610 : }
611 4 : return rv;
612 : }
613 :
614 : NS_IMETHODIMP
615 3280 : nsNSSComponent::GetPIPNSSBundleString(const char *name,
616 : nsAString &outString)
617 : {
618 3280 : nsresult rv = NS_ERROR_FAILURE;
619 :
620 3280 : outString.SetLength(0);
621 3280 : if (mPIPNSSBundle && name) {
622 6560 : nsXPIDLString result;
623 6560 : rv = mPIPNSSBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
624 6560 : getter_Copies(result));
625 3280 : if (NS_SUCCEEDED(rv)) {
626 3280 : outString = result;
627 3280 : rv = NS_OK;
628 : }
629 : }
630 :
631 3280 : return rv;
632 : }
633 :
634 : NS_IMETHODIMP
635 0 : nsNSSComponent::NSSBundleFormatStringFromName(const char *name,
636 : const PRUnichar **params,
637 : PRUint32 numParams,
638 : nsAString &outString)
639 : {
640 0 : nsresult rv = NS_ERROR_FAILURE;
641 :
642 0 : if (mNSSErrorsBundle && name) {
643 0 : nsXPIDLString result;
644 0 : rv = mNSSErrorsBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(name).get(),
645 : params, numParams,
646 0 : getter_Copies(result));
647 0 : if (NS_SUCCEEDED(rv)) {
648 0 : outString = result;
649 : }
650 : }
651 0 : return rv;
652 : }
653 :
654 : NS_IMETHODIMP
655 0 : nsNSSComponent::GetNSSBundleString(const char *name,
656 : nsAString &outString)
657 : {
658 0 : nsresult rv = NS_ERROR_FAILURE;
659 :
660 0 : outString.SetLength(0);
661 0 : if (mNSSErrorsBundle && name) {
662 0 : nsXPIDLString result;
663 0 : rv = mNSSErrorsBundle->GetStringFromName(NS_ConvertASCIItoUTF16(name).get(),
664 0 : getter_Copies(result));
665 0 : if (NS_SUCCEEDED(rv)) {
666 0 : outString = result;
667 0 : rv = NS_OK;
668 : }
669 : }
670 :
671 0 : return rv;
672 : }
673 :
674 : void
675 328 : nsNSSComponent::LaunchSmartCardThreads()
676 : {
677 656 : nsNSSShutDownPreventionLock locker;
678 : {
679 : SECMODModuleList *list;
680 328 : SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
681 328 : if (!lock) {
682 0 : PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
683 : ("Couldn't get the module list lock, can't launch smart card threads\n"));
684 : return;
685 : }
686 328 : SECMOD_GetReadLock(lock);
687 328 : list = SECMOD_GetDefaultModuleList();
688 :
689 1312 : while (list) {
690 656 : SECMODModule *module = list->module;
691 656 : LaunchSmartCardThread(module);
692 656 : list = list->next;
693 : }
694 328 : SECMOD_ReleaseReadLock(lock);
695 : }
696 : }
697 :
698 : NS_IMETHODIMP
699 656 : nsNSSComponent::LaunchSmartCardThread(SECMODModule *module)
700 : {
701 : SmartCardMonitoringThread *newThread;
702 656 : if (SECMOD_HasRemovableSlots(module)) {
703 0 : if (mThreadList == nsnull) {
704 0 : mThreadList = new SmartCardThreadList();
705 0 : if (!mThreadList) {
706 0 : return NS_ERROR_OUT_OF_MEMORY;
707 : }
708 : }
709 0 : newThread = new SmartCardMonitoringThread(module);
710 0 : if (!newThread) {
711 0 : return NS_ERROR_OUT_OF_MEMORY;
712 : }
713 : // newThread is adopted by the add.
714 0 : return mThreadList->Add(newThread);
715 : }
716 656 : return NS_OK;
717 : }
718 :
719 : NS_IMETHODIMP
720 0 : nsNSSComponent::ShutdownSmartCardThread(SECMODModule *module)
721 : {
722 0 : if (!mThreadList) {
723 0 : return NS_OK;
724 : }
725 0 : mThreadList->Remove(module);
726 0 : return NS_OK;
727 : }
728 :
729 : void
730 328 : nsNSSComponent::ShutdownSmartCardThreads()
731 : {
732 328 : delete mThreadList;
733 328 : mThreadList = nsnull;
734 328 : }
735 :
736 : static char *
737 328 : nss_addEscape(const char *string, char quote)
738 : {
739 328 : char *newString = 0;
740 328 : int escapes = 0, size = 0;
741 : const char *src;
742 : char *dest;
743 :
744 24272 : for (src=string; *src ; src++) {
745 23944 : if ((*src == quote) || (*src == '\\')) {
746 0 : escapes++;
747 : }
748 23944 : size++;
749 : }
750 :
751 328 : newString = (char*)PORT_ZAlloc(escapes+size+1);
752 328 : if (newString == NULL) {
753 0 : return NULL;
754 : }
755 :
756 24272 : for (src=string, dest=newString; *src; src++,dest++) {
757 23944 : if ((*src == quote) || (*src == '\\')) {
758 0 : *dest++ = '\\';
759 : }
760 23944 : *dest = *src;
761 : }
762 :
763 328 : return newString;
764 : }
765 :
766 : void
767 328 : nsNSSComponent::InstallLoadableRoots()
768 : {
769 656 : nsNSSShutDownPreventionLock locker;
770 328 : SECMODModule *RootsModule = nsnull;
771 :
772 : // In the past we used SECMOD_AddNewModule to load our module containing
773 : // root CA certificates. This caused problems, refer to bug 176501.
774 : // On startup, we fix our database and clean any stored module reference,
775 : // and will use SECMOD_LoadUserModule to temporarily load it
776 : // for the session. (This approach requires to clean up
777 : // using SECMOD_UnloadUserModule at the end of the session.)
778 :
779 : {
780 : // Find module containing root certs
781 :
782 : SECMODModuleList *list;
783 328 : SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
784 328 : if (!lock) {
785 0 : PR_LOG(gPIPNSSLog, PR_LOG_ERROR,
786 : ("Couldn't get the module list lock, can't install loadable roots\n"));
787 : return;
788 : }
789 328 : SECMOD_GetReadLock(lock);
790 328 : list = SECMOD_GetDefaultModuleList();
791 :
792 984 : while (!RootsModule && list) {
793 328 : SECMODModule *module = list->module;
794 :
795 984 : for (int i=0; i < module->slotCount; i++) {
796 656 : PK11SlotInfo *slot = module->slots[i];
797 656 : if (PK11_IsPresent(slot)) {
798 656 : if (PK11_HasRootCerts(slot)) {
799 0 : RootsModule = SECMOD_ReferenceModule(module);
800 0 : break;
801 : }
802 : }
803 : }
804 :
805 328 : list = list->next;
806 : }
807 328 : SECMOD_ReleaseReadLock(lock);
808 : }
809 :
810 328 : if (RootsModule) {
811 : PRInt32 modType;
812 0 : SECMOD_DeleteModule(RootsModule->commonName, &modType);
813 0 : SECMOD_DestroyModule(RootsModule);
814 0 : RootsModule = nsnull;
815 : }
816 :
817 : // Find the best Roots module for our purposes.
818 : // Prefer the application's installation directory,
819 : // but also ensure the library is at least the version we expect.
820 :
821 : nsresult rv;
822 656 : nsAutoString modName;
823 328 : rv = GetPIPNSSBundleString("RootCertModuleName", modName);
824 328 : if (NS_FAILED(rv)) return;
825 :
826 656 : nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
827 328 : if (!directoryService)
828 : return;
829 :
830 : static const char nss_lib[] = "nss3";
831 : const char *possible_ckbi_locations[] = {
832 : nss_lib, // This special value means: search for ckbi in the directory
833 : // where nss3 is.
834 : NS_XPCOM_CURRENT_PROCESS_DIR,
835 : NS_GRE_DIR,
836 : 0 // This special value means:
837 : // search for ckbi in the directories on the shared
838 : // library/DLL search path
839 328 : };
840 :
841 328 : for (size_t il = 0; il < sizeof(possible_ckbi_locations)/sizeof(const char*); ++il) {
842 656 : nsCOMPtr<nsILocalFile> mozFile;
843 328 : char *fullLibraryPath = nsnull;
844 :
845 328 : if (!possible_ckbi_locations[il])
846 : {
847 0 : fullLibraryPath = PR_GetLibraryName(nsnull, "nssckbi");
848 : }
849 : else
850 : {
851 328 : if (possible_ckbi_locations[il] == nss_lib) {
852 : // Get the location of the nss3 library.
853 : char *nss_path = PR_GetLibraryFilePathname(DLL_PREFIX "nss3" DLL_SUFFIX,
854 328 : (PRFuncPtr) NSS_Initialize);
855 328 : if (!nss_path) {
856 0 : continue;
857 : }
858 : // Get the directory containing the nss3 library.
859 656 : nsCOMPtr<nsILocalFile> nssLib(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
860 328 : if (NS_SUCCEEDED(rv)) {
861 328 : rv = nssLib->InitWithNativePath(nsDependentCString(nss_path));
862 : }
863 328 : PR_Free(nss_path);
864 328 : if (NS_SUCCEEDED(rv)) {
865 656 : nsCOMPtr<nsIFile> file;
866 328 : if (NS_SUCCEEDED(nssLib->GetParent(getter_AddRefs(file)))) {
867 328 : mozFile = do_QueryInterface(file);
868 : }
869 : }
870 : } else {
871 0 : directoryService->Get( possible_ckbi_locations[il],
872 : NS_GET_IID(nsILocalFile),
873 0 : getter_AddRefs(mozFile));
874 : }
875 :
876 328 : if (!mozFile) {
877 0 : continue;
878 : }
879 :
880 656 : nsCAutoString processDir;
881 328 : mozFile->GetNativePath(processDir);
882 328 : fullLibraryPath = PR_GetLibraryName(processDir.get(), "nssckbi");
883 : }
884 :
885 328 : if (!fullLibraryPath) {
886 0 : continue;
887 : }
888 :
889 328 : char *escaped_fullLibraryPath = nss_addEscape(fullLibraryPath, '\"');
890 328 : if (!escaped_fullLibraryPath) {
891 0 : PR_FreeLibraryName(fullLibraryPath); // allocated by NSPR
892 0 : continue;
893 : }
894 :
895 : /* If a module exists with the same name, delete it. */
896 656 : NS_ConvertUTF16toUTF8 modNameUTF8(modName);
897 : int modType;
898 328 : SECMOD_DeleteModule(const_cast<char*>(modNameUTF8.get()), &modType);
899 :
900 656 : nsCString pkcs11moduleSpec;
901 328 : pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("name=\""));
902 328 : pkcs11moduleSpec.Append(modNameUTF8.get());
903 328 : pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("\" library=\""));
904 328 : pkcs11moduleSpec.Append(escaped_fullLibraryPath);
905 328 : pkcs11moduleSpec.Append(NS_LITERAL_CSTRING("\""));
906 :
907 328 : PR_FreeLibraryName(fullLibraryPath); // allocated by NSPR
908 328 : PORT_Free(escaped_fullLibraryPath);
909 :
910 : RootsModule =
911 328 : SECMOD_LoadUserModule(const_cast<char*>(pkcs11moduleSpec.get()),
912 : nsnull, // no parent
913 328 : false); // do not recurse
914 :
915 328 : if (RootsModule) {
916 328 : bool found = (RootsModule->loaded);
917 :
918 328 : SECMOD_DestroyModule(RootsModule);
919 328 : RootsModule = nsnull;
920 :
921 328 : if (found) {
922 : break;
923 : }
924 : }
925 : }
926 : }
927 :
928 : void
929 328 : nsNSSComponent::UnloadLoadableRoots()
930 : {
931 : nsresult rv;
932 656 : nsAutoString modName;
933 328 : rv = GetPIPNSSBundleString("RootCertModuleName", modName);
934 328 : if (NS_FAILED(rv)) return;
935 :
936 656 : NS_ConvertUTF16toUTF8 modNameUTF8(modName);
937 328 : SECMODModule *RootsModule = SECMOD_FindModule(modNameUTF8.get());
938 :
939 328 : if (RootsModule) {
940 328 : SECMOD_UnloadUserModule(RootsModule);
941 328 : SECMOD_DestroyModule(RootsModule);
942 : }
943 : }
944 :
945 : nsresult
946 328 : nsNSSComponent::ConfigureInternalPKCS11Token()
947 : {
948 656 : nsNSSShutDownPreventionLock locker;
949 656 : nsAutoString manufacturerID;
950 656 : nsAutoString libraryDescription;
951 656 : nsAutoString tokenDescription;
952 656 : nsAutoString privateTokenDescription;
953 656 : nsAutoString slotDescription;
954 656 : nsAutoString privateSlotDescription;
955 656 : nsAutoString fips140TokenDescription;
956 656 : nsAutoString fips140SlotDescription;
957 :
958 : nsresult rv;
959 328 : rv = GetPIPNSSBundleString("ManufacturerID", manufacturerID);
960 328 : if (NS_FAILED(rv)) return rv;
961 :
962 328 : rv = GetPIPNSSBundleString("LibraryDescription", libraryDescription);
963 328 : if (NS_FAILED(rv)) return rv;
964 :
965 328 : rv = GetPIPNSSBundleString("TokenDescription", tokenDescription);
966 328 : if (NS_FAILED(rv)) return rv;
967 :
968 328 : rv = GetPIPNSSBundleString("PrivateTokenDescription", privateTokenDescription);
969 328 : if (NS_FAILED(rv)) return rv;
970 :
971 328 : rv = GetPIPNSSBundleString("SlotDescription", slotDescription);
972 328 : if (NS_FAILED(rv)) return rv;
973 :
974 328 : rv = GetPIPNSSBundleString("PrivateSlotDescription", privateSlotDescription);
975 328 : if (NS_FAILED(rv)) return rv;
976 :
977 328 : rv = GetPIPNSSBundleString("Fips140TokenDescription", fips140TokenDescription);
978 328 : if (NS_FAILED(rv)) return rv;
979 :
980 328 : rv = GetPIPNSSBundleString("Fips140SlotDescription", fips140SlotDescription);
981 328 : if (NS_FAILED(rv)) return rv;
982 :
983 328 : PK11_ConfigurePKCS11(NS_ConvertUTF16toUTF8(manufacturerID).get(),
984 328 : NS_ConvertUTF16toUTF8(libraryDescription).get(),
985 328 : NS_ConvertUTF16toUTF8(tokenDescription).get(),
986 328 : NS_ConvertUTF16toUTF8(privateTokenDescription).get(),
987 328 : NS_ConvertUTF16toUTF8(slotDescription).get(),
988 328 : NS_ConvertUTF16toUTF8(privateSlotDescription).get(),
989 328 : NS_ConvertUTF16toUTF8(fips140TokenDescription).get(),
990 328 : NS_ConvertUTF16toUTF8(fips140SlotDescription).get(),
991 328 : 0, 0);
992 328 : return NS_OK;
993 : }
994 :
995 : nsresult
996 328 : nsNSSComponent::InitializePIPNSSBundle()
997 : {
998 : // Called during init only, no mutex required.
999 :
1000 : nsresult rv;
1001 656 : nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
1002 328 : if (NS_FAILED(rv) || !bundleService)
1003 0 : return NS_ERROR_FAILURE;
1004 :
1005 328 : bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL,
1006 328 : getter_AddRefs(mPIPNSSBundle));
1007 328 : if (!mPIPNSSBundle)
1008 0 : rv = NS_ERROR_FAILURE;
1009 :
1010 328 : bundleService->CreateBundle(NSSERR_STRBUNDLE_URL,
1011 328 : getter_AddRefs(mNSSErrorsBundle));
1012 328 : if (!mNSSErrorsBundle)
1013 0 : rv = NS_ERROR_FAILURE;
1014 :
1015 328 : return rv;
1016 : }
1017 :
1018 : nsresult
1019 328 : nsNSSComponent::RegisterPSMContentListener()
1020 : {
1021 : // Called during init only, no mutex required.
1022 :
1023 328 : nsresult rv = NS_OK;
1024 328 : if (!mPSMContentListener) {
1025 656 : nsCOMPtr<nsIURILoader> dispatcher(do_GetService(NS_URI_LOADER_CONTRACTID));
1026 328 : if (dispatcher) {
1027 328 : mPSMContentListener = do_CreateInstance(NS_PSMCONTENTLISTEN_CONTRACTID);
1028 328 : rv = dispatcher->RegisterContentListener(mPSMContentListener);
1029 : }
1030 : }
1031 328 : return rv;
1032 : }
1033 :
1034 : /* Table of pref names and SSL cipher ID */
1035 : typedef struct {
1036 : const char* pref;
1037 : long id;
1038 : } CipherPref;
1039 :
1040 : static CipherPref CipherPrefs[] = {
1041 : /* SSL3/TLS cipher suites*/
1042 : {"security.ssl3.rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5}, // 128-bit RC4 encryption with RSA and an MD5 MAC
1043 : {"security.ssl3.rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with RSA and a SHA1 MAC
1044 : {"security.ssl3.rsa_fips_des_ede3_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with RSA and a SHA1 MAC (FIPS)
1045 : {"security.ssl3.rsa_des_ede3_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with RSA and a SHA1 MAC
1046 : {"security.ssl3.rsa_fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA and a SHA1 MAC (FIPS)
1047 : {"security.ssl3.rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA and a SHA1 MAC
1048 : {"security.ssl3.rsa_1024_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, // 56-bit RC4 encryption with RSA and a SHA1 MAC (export)
1049 : {"security.ssl3.rsa_1024_des_cbc_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA and a SHA1 MAC (export)
1050 : {"security.ssl3.rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5}, // 40-bit RC4 encryption with RSA and an MD5 MAC (export)
1051 : {"security.ssl3.rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5}, // 40-bit RC2 encryption with RSA and an MD5 MAC (export)
1052 : /* Extra SSL3/TLS cipher suites */
1053 : {"security.ssl3.dhe_rsa_camellia_256_sha", TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA}, // 256-bit Camellia encryption with RSA, DHE, and a SHA1 MAC
1054 : {"security.ssl3.dhe_dss_camellia_256_sha", TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA}, // 256-bit Camellia encryption with DSA, DHE, and a SHA1 MAC
1055 : {"security.ssl3.rsa_camellia_256_sha", TLS_RSA_WITH_CAMELLIA_256_CBC_SHA}, // 256-bit Camellia encryption with RSA and a SHA1 MAC
1056 : {"security.ssl3.dhe_rsa_aes_256_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with RSA, DHE, and a SHA1 MAC
1057 : {"security.ssl3.dhe_dss_aes_256_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with DSA, DHE, and a SHA1 MAC
1058 : {"security.ssl3.rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with RSA and a SHA1 MAC
1059 : /* TLS_DHE_DSS_WITH_RC4_128_SHA // 128-bit RC4 encryption with DSA, DHE, and a SHA1 MAC
1060 : If this cipher gets included at a later time, it should get added at this position */
1061 : {"security.ssl3.ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with ECDHE-ECDSA and a SHA1 MAC
1062 : {"security.ssl3.ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with ECDHE-ECDSA and a SHA1 MAC
1063 : {"security.ssl3.ecdhe_ecdsa_des_ede3_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with ECDHE-ECDSA and a SHA1 MAC
1064 : {"security.ssl3.ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with ECDHE-ECDSA and a SHA1 MAC
1065 : {"security.ssl3.ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA}, // No encryption with ECDHE-ECDSA and a SHA1 MAC
1066 : {"security.ssl3.ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with ECDHE-RSA and a SHA1 MAC
1067 : {"security.ssl3.ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with ECDHE-RSA and a SHA1 MAC
1068 : {"security.ssl3.ecdhe_rsa_des_ede3_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with ECDHE-RSA and a SHA1 MAC
1069 : {"security.ssl3.ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with ECDHE-RSA and a SHA1 MAC
1070 : {"security.ssl3.ecdhe_rsa_null_sha", TLS_ECDHE_RSA_WITH_NULL_SHA}, // No encryption with ECDHE-RSA and a SHA1 MAC
1071 : {"security.ssl3.ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with ECDH-ECDSA and a SHA1 MAC
1072 : {"security.ssl3.ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with ECDH-ECDSA and a SHA1 MAC
1073 : {"security.ssl3.ecdh_ecdsa_des_ede3_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with ECDH-ECDSA and a SHA1 MAC
1074 : {"security.ssl3.ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with ECDH-ECDSA and a SHA1 MAC
1075 : {"security.ssl3.ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA}, // No encryption with ECDH-ECDSA and a SHA1 MAC
1076 : {"security.ssl3.ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA}, // 256-bit AES encryption with ECDH-RSA and a SHA1 MAC
1077 : {"security.ssl3.ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with ECDH-RSA and a SHA1 MAC
1078 : {"security.ssl3.ecdh_rsa_des_ede3_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with ECDH-RSA and a SHA1 MAC
1079 : {"security.ssl3.ecdh_rsa_rc4_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA}, // 128-bit RC4 encryption with ECDH-RSA and a SHA1 MAC
1080 : {"security.ssl3.ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA}, // No encryption with ECDH-RSA and a SHA1 MAC
1081 : {"security.ssl3.dhe_rsa_camellia_128_sha", TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA}, // 128-bit Camellia encryption with RSA, DHE, and a SHA1 MAC
1082 : {"security.ssl3.dhe_dss_camellia_128_sha", TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA}, // 128-bit Camellia encryption with DSA, DHE, and a SHA1 MAC
1083 : {"security.ssl3.rsa_camellia_128_sha", TLS_RSA_WITH_CAMELLIA_128_CBC_SHA}, // 128-bit Camellia encryption with RSA and a SHA1 MAC
1084 : {"security.ssl3.dhe_rsa_aes_128_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with RSA, DHE, and a SHA1 MAC
1085 : {"security.ssl3.dhe_dss_aes_128_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with DSA, DHE, and a SHA1 MAC
1086 : {"security.ssl3.rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA}, // 128-bit AES encryption with RSA and a SHA1 MAC
1087 : {"security.ssl3.dhe_rsa_des_ede3_sha", SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with RSA, DHE, and a SHA1 MAC
1088 : {"security.ssl3.dhe_dss_des_ede3_sha", SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA}, // 168-bit Triple DES with DSA, DHE, and a SHA1 MAC
1089 : {"security.ssl3.dhe_rsa_des_sha", SSL_DHE_RSA_WITH_DES_CBC_SHA}, // 56-bit DES encryption with RSA, DHE, and a SHA1 MAC
1090 : {"security.ssl3.dhe_dss_des_sha", SSL_DHE_DSS_WITH_DES_CBC_SHA}, // 56-bit DES encryption with DSA, DHE, and a SHA1 MAC
1091 : {"security.ssl3.rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, // No encryption with RSA authentication and a SHA1 MAC
1092 : {"security.ssl3.rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, // No encryption with RSA authentication and an MD5 MAC
1093 : {"security.ssl3.rsa_seed_sha", TLS_RSA_WITH_SEED_CBC_SHA}, // SEED encryption with RSA and a SHA1 MAC
1094 : {NULL, 0} /* end marker */
1095 : };
1096 :
1097 : static void
1098 328 : setNonPkixOcspEnabled(PRInt32 ocspEnabled, nsIPrefBranch * pref)
1099 : {
1100 328 : switch (ocspEnabled) {
1101 : case 0:
1102 0 : CERT_DisableOCSPChecking(CERT_GetDefaultCertDB());
1103 0 : CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
1104 0 : break;
1105 : case 1:
1106 328 : CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
1107 328 : CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
1108 328 : break;
1109 : case 2:
1110 : {
1111 0 : char *signingCA = nsnull;
1112 0 : char *url = nsnull;
1113 :
1114 : // Get the signing CA and service url //
1115 0 : pref->GetCharPref("security.OCSP.signingCA", &signingCA);
1116 0 : pref->GetCharPref("security.OCSP.URL", &url);
1117 :
1118 : // Set OCSP up
1119 0 : CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
1120 0 : CERT_SetOCSPDefaultResponder(CERT_GetDefaultCertDB(), url, signingCA);
1121 0 : CERT_EnableOCSPDefaultResponder(CERT_GetDefaultCertDB());
1122 :
1123 0 : nsMemory::Free(signingCA);
1124 0 : nsMemory::Free(url);
1125 : }
1126 0 : break;
1127 : }
1128 328 : }
1129 :
1130 : #define CRL_DOWNLOAD_DEFAULT false
1131 : #define OCSP_ENABLED_DEFAULT 1
1132 : #define OCSP_REQUIRED_DEFAULT 0
1133 : #define FRESH_REVOCATION_REQUIRED_DEFAULT false
1134 : #define MISSING_CERT_DOWNLOAD_DEFAULT false
1135 : #define FIRST_REVO_METHOD_DEFAULT "ocsp"
1136 : #define USE_NSS_LIBPKIX_DEFAULT false
1137 :
1138 : // Caller must hold a lock on nsNSSComponent::mutex when calling this function
1139 328 : void nsNSSComponent::setValidationOptions(nsIPrefBranch * pref)
1140 : {
1141 656 : nsNSSShutDownPreventionLock locker;
1142 : nsresult rv;
1143 :
1144 : bool crlDownloading;
1145 328 : rv = pref->GetBoolPref("security.CRL_download.enabled", &crlDownloading);
1146 328 : if (NS_FAILED(rv))
1147 328 : crlDownloading = CRL_DOWNLOAD_DEFAULT;
1148 :
1149 : PRInt32 ocspEnabled;
1150 328 : rv = pref->GetIntPref("security.OCSP.enabled", &ocspEnabled);
1151 : // 0 = disabled, 1 = enabled,
1152 : // 2 = enabled with given default responder
1153 328 : if (NS_FAILED(rv))
1154 0 : ocspEnabled = OCSP_ENABLED_DEFAULT;
1155 :
1156 : bool ocspRequired;
1157 328 : rv = pref->GetBoolPref("security.OCSP.require", &ocspRequired);
1158 328 : if (NS_FAILED(rv))
1159 0 : ocspRequired = OCSP_REQUIRED_DEFAULT;
1160 :
1161 : bool anyFreshRequired;
1162 328 : rv = pref->GetBoolPref("security.fresh_revocation_info.require", &anyFreshRequired);
1163 328 : if (NS_FAILED(rv))
1164 328 : anyFreshRequired = FRESH_REVOCATION_REQUIRED_DEFAULT;
1165 :
1166 : bool aiaDownloadEnabled;
1167 328 : rv = pref->GetBoolPref("security.missing_cert_download.enabled", &aiaDownloadEnabled);
1168 328 : if (NS_FAILED(rv))
1169 328 : aiaDownloadEnabled = MISSING_CERT_DOWNLOAD_DEFAULT;
1170 :
1171 656 : nsCString firstNetworkRevo;
1172 328 : rv = pref->GetCharPref("security.first_network_revocation_method", getter_Copies(firstNetworkRevo));
1173 328 : if (NS_FAILED(rv))
1174 328 : firstNetworkRevo = FIRST_REVO_METHOD_DEFAULT;
1175 :
1176 328 : setNonPkixOcspEnabled(ocspEnabled, pref);
1177 :
1178 : CERT_SetOCSPFailureMode( ocspRequired ?
1179 : ocspMode_FailureIsVerificationFailure
1180 328 : : ocspMode_FailureIsNotAVerificationFailure);
1181 :
1182 656 : nsRefPtr<nsCERTValInParamWrapper> newCVIN = new nsCERTValInParamWrapper;
1183 328 : if (NS_SUCCEEDED(newCVIN->Construct(
1184 : aiaDownloadEnabled ?
1185 : nsCERTValInParamWrapper::missing_cert_download_on : nsCERTValInParamWrapper::missing_cert_download_off,
1186 : crlDownloading ?
1187 : nsCERTValInParamWrapper::crl_download_allowed : nsCERTValInParamWrapper::crl_local_only,
1188 : ocspEnabled ?
1189 : nsCERTValInParamWrapper::ocsp_on : nsCERTValInParamWrapper::ocsp_off,
1190 : ocspRequired ?
1191 : nsCERTValInParamWrapper::ocsp_strict : nsCERTValInParamWrapper::ocsp_relaxed,
1192 : anyFreshRequired ?
1193 : nsCERTValInParamWrapper::any_revo_strict : nsCERTValInParamWrapper::any_revo_relaxed,
1194 : firstNetworkRevo.get()))) {
1195 : // Swap to new defaults, and will cause the old defaults to be released,
1196 : // as soon as any concurrent use of the old default objects has finished.
1197 328 : mDefaultCERTValInParam = newCVIN;
1198 : }
1199 :
1200 : /*
1201 : * The new defaults might change the validity of already established SSL sessions,
1202 : * let's not reuse them.
1203 : */
1204 328 : SSL_ClearSessionCache();
1205 328 : }
1206 :
1207 : NS_IMETHODIMP
1208 0 : nsNSSComponent::SkipOcsp()
1209 : {
1210 0 : nsNSSShutDownPreventionLock locker;
1211 0 : CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
1212 :
1213 0 : SECStatus rv = CERT_DisableOCSPChecking(certdb);
1214 0 : return (rv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
1215 : }
1216 :
1217 : NS_IMETHODIMP
1218 0 : nsNSSComponent::SkipOcspOff()
1219 : {
1220 0 : nsNSSShutDownPreventionLock locker;
1221 : PRInt32 ocspEnabled;
1222 0 : if (NS_FAILED(mPrefBranch->GetIntPref("security.OCSP.enabled", &ocspEnabled)))
1223 0 : ocspEnabled = OCSP_ENABLED_DEFAULT;
1224 : // 0 = disabled, 1 = enabled,
1225 : // 2 = enabled with given default responder
1226 :
1227 0 : setNonPkixOcspEnabled(ocspEnabled, mPrefBranch);
1228 :
1229 0 : if (ocspEnabled)
1230 0 : SSL_ClearSessionCache();
1231 :
1232 0 : return NS_OK;
1233 : }
1234 :
1235 : nsresult
1236 0 : nsNSSComponent::PostCRLImportEvent(const nsCSubstring &urlString,
1237 : nsIStreamListener *listener)
1238 : {
1239 : //Create the event
1240 0 : nsCOMPtr<nsIRunnable> event = new CRLDownloadEvent(urlString, listener);
1241 0 : if (!event)
1242 0 : return NS_ERROR_OUT_OF_MEMORY;
1243 :
1244 : //Get a handle to the ui thread
1245 0 : return NS_DispatchToMainThread(event);
1246 : }
1247 :
1248 : nsresult
1249 0 : nsNSSComponent::DownloadCRLDirectly(nsAutoString url, nsAutoString key)
1250 : {
1251 : //This api is meant to support direct interactive update of crl from the crl manager
1252 : //or other such ui.
1253 : nsCOMPtr<nsIStreamListener> listener =
1254 0 : new PSMContentDownloader(PSMContentDownloader::PKCS7_CRL);
1255 :
1256 0 : NS_ConvertUTF16toUTF8 url8(url);
1257 0 : return PostCRLImportEvent(url8, listener);
1258 : }
1259 :
1260 0 : nsresult nsNSSComponent::DownloadCrlSilently()
1261 : {
1262 : //Add this attempt to the hashtable
1263 0 : nsStringKey hashKey(mCrlUpdateKey.get());
1264 0 : crlsScheduledForDownload->Put(&hashKey,(void *)nsnull);
1265 :
1266 : //Set up the download handler
1267 : nsRefPtr<PSMContentDownloader> psmDownloader =
1268 0 : new PSMContentDownloader(PSMContentDownloader::PKCS7_CRL);
1269 0 : psmDownloader->setSilentDownload(true);
1270 0 : psmDownloader->setCrlAutodownloadKey(mCrlUpdateKey);
1271 :
1272 : //Now get the url string
1273 0 : NS_ConvertUTF16toUTF8 url8(mDownloadURL);
1274 0 : return PostCRLImportEvent(url8, psmDownloader);
1275 : }
1276 :
1277 328 : nsresult nsNSSComponent::getParamsForNextCrlToDownload(nsAutoString *url, PRTime *time, nsAutoString *key)
1278 : {
1279 328 : const char *updateEnabledPref = CRL_AUTOUPDATE_ENABLED_PREF;
1280 328 : const char *updateTimePref = CRL_AUTOUPDATE_TIME_PREF;
1281 328 : const char *updateURLPref = CRL_AUTOUPDATE_URL_PREF;
1282 : char **allCrlsToBeUpdated;
1283 : PRUint32 noOfCrls;
1284 328 : PRTime nearestUpdateTime = 0;
1285 656 : nsAutoString crlKey;
1286 : char *tempUrl;
1287 : nsresult rv;
1288 :
1289 656 : nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID,&rv);
1290 328 : if(NS_FAILED(rv)){
1291 0 : return rv;
1292 : }
1293 :
1294 328 : rv = pref->GetChildList(updateEnabledPref, &noOfCrls, &allCrlsToBeUpdated);
1295 328 : if ( (NS_FAILED(rv)) || (noOfCrls==0) ){
1296 328 : return NS_ERROR_FAILURE;
1297 : }
1298 :
1299 0 : for(PRUint32 i=0;i<noOfCrls;i++) {
1300 : //First check if update pref is enabled for this crl
1301 0 : bool autoUpdateEnabled = false;
1302 0 : rv = pref->GetBoolPref(*(allCrlsToBeUpdated+i), &autoUpdateEnabled);
1303 0 : if (NS_FAILED(rv) || !autoUpdateEnabled) {
1304 0 : continue;
1305 : }
1306 :
1307 0 : nsAutoString tempCrlKey;
1308 :
1309 : //Now, generate the crl key. Same key would be used as hashkey as well
1310 0 : nsCAutoString enabledPrefCString(*(allCrlsToBeUpdated+i));
1311 0 : enabledPrefCString.ReplaceSubstring(updateEnabledPref,".");
1312 0 : tempCrlKey.AssignWithConversion(enabledPrefCString.get());
1313 :
1314 : //Check if this crl has already been scheduled. Its presence in the hashtable
1315 : //implies that it has been scheduled already this client session, and
1316 : //is either in the process of being downloaded, or its download failed
1317 : //for some reason. In the second case, we will not retry in the current client session
1318 0 : nsStringKey hashKey(tempCrlKey.get());
1319 0 : if(crlsScheduledForDownload->Exists(&hashKey)){
1320 0 : continue;
1321 : }
1322 :
1323 : char *tempTimeString;
1324 : PRTime tempTime;
1325 0 : nsCAutoString timingPrefCString(updateTimePref);
1326 0 : timingPrefCString.AppendWithConversion(tempCrlKey);
1327 0 : rv = pref->GetCharPref(timingPrefCString.get(), &tempTimeString);
1328 0 : if (NS_FAILED(rv)){
1329 0 : continue;
1330 : }
1331 0 : rv = PR_ParseTimeString(tempTimeString,true, &tempTime);
1332 0 : nsMemory::Free(tempTimeString);
1333 0 : if (NS_FAILED(rv)){
1334 0 : continue;
1335 : }
1336 :
1337 0 : if(nearestUpdateTime == 0 || tempTime < nearestUpdateTime){
1338 0 : nsCAutoString urlPrefCString(updateURLPref);
1339 0 : urlPrefCString.AppendWithConversion(tempCrlKey);
1340 0 : rv = pref->GetCharPref(urlPrefCString.get(), &tempUrl);
1341 0 : if (NS_FAILED(rv) || (!tempUrl)){
1342 0 : continue;
1343 : }
1344 0 : nearestUpdateTime = tempTime;
1345 0 : crlKey = tempCrlKey;
1346 : }
1347 : }
1348 :
1349 0 : if(noOfCrls > 0)
1350 0 : NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(noOfCrls, allCrlsToBeUpdated);
1351 :
1352 0 : if(nearestUpdateTime > 0){
1353 0 : *time = nearestUpdateTime;
1354 0 : url->AssignWithConversion((const char *)tempUrl);
1355 0 : nsMemory::Free(tempUrl);
1356 0 : *key = crlKey;
1357 0 : rv = NS_OK;
1358 : } else{
1359 0 : rv = NS_ERROR_FAILURE;
1360 : }
1361 :
1362 0 : return rv;
1363 : }
1364 :
1365 : NS_IMETHODIMP
1366 0 : nsNSSComponent::Notify(nsITimer *timer)
1367 : {
1368 : //Timer has fired. So set the flag accordingly
1369 : {
1370 0 : MutexAutoLock lock(mCrlTimerLock);
1371 0 : crlDownloadTimerOn = false;
1372 : }
1373 :
1374 : //First, handle this download
1375 0 : DownloadCrlSilently();
1376 :
1377 : //Dont Worry if successful or not
1378 : //Set the next timer
1379 0 : DefineNextTimer();
1380 0 : return NS_OK;
1381 : }
1382 :
1383 : nsresult
1384 0 : nsNSSComponent::RemoveCrlFromList(nsAutoString key)
1385 : {
1386 0 : nsStringKey hashKey(key.get());
1387 0 : if(crlsScheduledForDownload->Exists(&hashKey)){
1388 0 : crlsScheduledForDownload->Remove(&hashKey);
1389 : }
1390 0 : return NS_OK;
1391 : }
1392 :
1393 : nsresult
1394 328 : nsNSSComponent::DefineNextTimer()
1395 : {
1396 : PRTime nextFiring;
1397 328 : PRTime now = PR_Now();
1398 : PRUint64 diff;
1399 : PRUint32 interval;
1400 328 : PRUint32 primaryDelay = CRL_AUTOUPDATE_DEFAULT_DELAY;
1401 : nsresult rv;
1402 :
1403 328 : if(!mTimer){
1404 0 : mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
1405 0 : if(NS_FAILED(rv))
1406 0 : return rv;
1407 : }
1408 :
1409 : //If some timer is already running, cancel it. Thus, the request that came last,
1410 : //wins. This would ensure that in no way we end up setting two different timers
1411 : //This part should be synchronized because this function might be called from separate
1412 : //threads
1413 :
1414 656 : MutexAutoLock lock(mCrlTimerLock);
1415 :
1416 328 : if (crlDownloadTimerOn) {
1417 0 : mTimer->Cancel();
1418 : }
1419 :
1420 328 : rv = getParamsForNextCrlToDownload(&mDownloadURL, &nextFiring, &mCrlUpdateKey);
1421 : //If there are no more crls to be updated any time in future
1422 328 : if(NS_FAILED(rv)){
1423 : // Return - no error - just implies nothing to schedule
1424 328 : return NS_OK;
1425 : }
1426 :
1427 : //Define the firing interval, from NOW
1428 0 : if ( now < nextFiring) {
1429 0 : LL_SUB(diff,nextFiring,now);
1430 0 : LL_L2UI(interval, diff);
1431 : //Now, we are doing 32 operations - so, don't need LL_ functions...
1432 0 : interval = interval/PR_USEC_PER_MSEC;
1433 : }else {
1434 0 : interval = primaryDelay;
1435 : }
1436 :
1437 0 : mTimer->InitWithCallback(static_cast<nsITimerCallback*>(this),
1438 : interval,
1439 0 : nsITimer::TYPE_ONE_SHOT);
1440 0 : crlDownloadTimerOn = true;
1441 :
1442 0 : return NS_OK;
1443 : }
1444 :
1445 : //Note that the StopCRLUpdateTimer and InitializeCRLUpdateTimer functions should never be called
1446 : //simultaneously from diff threads - they are NOT threadsafe. But, since there is no chance of
1447 : //that happening, there is not much benefit it trying to make it so at this point
1448 : nsresult
1449 315 : nsNSSComponent::StopCRLUpdateTimer()
1450 : {
1451 :
1452 : //If it is at all running.
1453 315 : if (mUpdateTimerInitialized) {
1454 311 : if(crlsScheduledForDownload != nsnull){
1455 311 : crlsScheduledForDownload->Reset();
1456 311 : delete crlsScheduledForDownload;
1457 311 : crlsScheduledForDownload = nsnull;
1458 : }
1459 : {
1460 622 : MutexAutoLock lock(mCrlTimerLock);
1461 311 : if (crlDownloadTimerOn) {
1462 0 : mTimer->Cancel();
1463 : }
1464 311 : crlDownloadTimerOn = false;
1465 : }
1466 311 : mUpdateTimerInitialized = false;
1467 : }
1468 :
1469 315 : return NS_OK;
1470 : }
1471 :
1472 : nsresult
1473 328 : nsNSSComponent::InitializeCRLUpdateTimer()
1474 : {
1475 : nsresult rv;
1476 :
1477 : //First check if this is already initialized. Then we stop it.
1478 328 : if (!mUpdateTimerInitialized) {
1479 328 : mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
1480 328 : if(NS_FAILED(rv)){
1481 0 : return rv;
1482 : }
1483 328 : crlsScheduledForDownload = new nsHashtable(16, true);
1484 328 : DefineNextTimer();
1485 328 : mUpdateTimerInitialized = true;
1486 : }
1487 :
1488 328 : return NS_OK;
1489 : }
1490 :
1491 : #ifdef XP_MACOSX
1492 : void
1493 : nsNSSComponent::TryCFM2MachOMigration(nsIFile *cfmPath, nsIFile *machoPath)
1494 : {
1495 : // We will modify the parameters.
1496 : //
1497 : // If neither cert7.db, cert8.db, key3.db, are available,
1498 : // copy from filenames that were used in the old days
1499 : // test for key3.db first, since a new profile might only contain cert8.db,
1500 : // but not cert7.db - this optimizes number of tests
1501 :
1502 : NS_NAMED_LITERAL_CSTRING(cstr_key3db, "key3.db");
1503 : NS_NAMED_LITERAL_CSTRING(cstr_cert7db, "cert7.db");
1504 : NS_NAMED_LITERAL_CSTRING(cstr_cert8db, "cert8.db");
1505 : NS_NAMED_LITERAL_CSTRING(cstr_keydatabase3, "Key Database3");
1506 : NS_NAMED_LITERAL_CSTRING(cstr_certificate7, "Certificates7");
1507 : NS_NAMED_LITERAL_CSTRING(cstr_certificate8, "Certificates8");
1508 :
1509 : bool bExists;
1510 : nsresult rv;
1511 :
1512 : nsCOMPtr<nsIFile> macho_key3db;
1513 : rv = machoPath->Clone(getter_AddRefs(macho_key3db));
1514 : if (NS_FAILED(rv)) {
1515 : return;
1516 : }
1517 :
1518 : macho_key3db->AppendNative(cstr_key3db);
1519 : rv = macho_key3db->Exists(&bExists);
1520 : if (NS_FAILED(rv) || bExists) {
1521 : return;
1522 : }
1523 :
1524 : nsCOMPtr<nsIFile> macho_cert7db;
1525 : rv = machoPath->Clone(getter_AddRefs(macho_cert7db));
1526 : if (NS_FAILED(rv)) {
1527 : return;
1528 : }
1529 :
1530 : macho_cert7db->AppendNative(cstr_cert7db);
1531 : rv = macho_cert7db->Exists(&bExists);
1532 : if (NS_FAILED(rv) || bExists) {
1533 : return;
1534 : }
1535 :
1536 : nsCOMPtr<nsIFile> macho_cert8db;
1537 : rv = machoPath->Clone(getter_AddRefs(macho_cert8db));
1538 : if (NS_FAILED(rv)) {
1539 : return;
1540 : }
1541 :
1542 : macho_cert8db->AppendNative(cstr_cert8db);
1543 : rv = macho_cert7db->Exists(&bExists);
1544 : if (NS_FAILED(rv) || bExists) {
1545 : return;
1546 : }
1547 :
1548 : // None of the new files exist. Try to copy any available old files.
1549 :
1550 : nsCOMPtr<nsIFile> cfm_key3;
1551 : rv = cfmPath->Clone(getter_AddRefs(cfm_key3));
1552 : if (NS_FAILED(rv)) {
1553 : return;
1554 : }
1555 :
1556 : cfm_key3->AppendNative(cstr_keydatabase3);
1557 : rv = cfm_key3->Exists(&bExists);
1558 : if (NS_FAILED(rv)) {
1559 : return;
1560 : }
1561 :
1562 : if (bExists) {
1563 : cfm_key3->CopyToFollowingLinksNative(machoPath, cstr_key3db);
1564 : }
1565 :
1566 : nsCOMPtr<nsIFile> cfm_cert7;
1567 : rv = cfmPath->Clone(getter_AddRefs(cfm_cert7));
1568 : if (NS_FAILED(rv)) {
1569 : return;
1570 : }
1571 :
1572 : cfm_cert7->AppendNative(cstr_certificate7);
1573 : rv = cfm_cert7->Exists(&bExists);
1574 : if (NS_FAILED(rv)) {
1575 : return;
1576 : }
1577 :
1578 : if (bExists) {
1579 : cfm_cert7->CopyToFollowingLinksNative(machoPath, cstr_cert7db);
1580 : }
1581 :
1582 : nsCOMPtr<nsIFile> cfm_cert8;
1583 : rv = cfmPath->Clone(getter_AddRefs(cfm_cert8));
1584 : if (NS_FAILED(rv)) {
1585 : return;
1586 : }
1587 :
1588 : cfm_cert8->AppendNative(cstr_certificate8);
1589 : rv = cfm_cert8->Exists(&bExists);
1590 : if (NS_FAILED(rv)) {
1591 : return;
1592 : }
1593 :
1594 : if (bExists) {
1595 : cfm_cert8->CopyToFollowingLinksNative(machoPath, cstr_cert8db);
1596 : }
1597 : }
1598 : #endif
1599 :
1600 328 : static void configureMD5(bool enabled)
1601 : {
1602 328 : if (enabled) { // set flags
1603 : NSS_SetAlgorithmPolicy(SEC_OID_MD5,
1604 328 : NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
1605 : NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
1606 328 : NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
1607 : NSS_SetAlgorithmPolicy(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,
1608 328 : NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0);
1609 : }
1610 : else { // clear flags
1611 : NSS_SetAlgorithmPolicy(SEC_OID_MD5,
1612 0 : 0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
1613 : NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
1614 0 : 0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
1615 : NSS_SetAlgorithmPolicy(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,
1616 0 : 0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE);
1617 : }
1618 328 : }
1619 :
1620 : nsresult
1621 328 : nsNSSComponent::InitializeNSS(bool showWarningBox)
1622 : {
1623 : // Can be called both during init and profile change.
1624 : // Needs mutex protection.
1625 :
1626 328 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::InitializeNSS\n"));
1627 :
1628 : // If we ever run into this assertion, we must update the values
1629 : // in nsINSSErrorsService.idl
1630 : PR_STATIC_ASSERT(nsINSSErrorsService::NSS_SEC_ERROR_BASE == SEC_ERROR_BASE
1631 : && nsINSSErrorsService::NSS_SEC_ERROR_LIMIT == SEC_ERROR_LIMIT
1632 : && nsINSSErrorsService::NSS_SSL_ERROR_BASE == SSL_ERROR_BASE
1633 : && nsINSSErrorsService::NSS_SSL_ERROR_LIMIT == SSL_ERROR_LIMIT);
1634 :
1635 : // variables used for flow control within this function
1636 :
1637 : enum { problem_none, problem_no_rw, problem_no_security_at_all }
1638 328 : which_nss_problem = problem_none;
1639 :
1640 : {
1641 656 : MutexAutoLock lock(mutex);
1642 :
1643 : // Init phase 1, prepare own variables used for NSS
1644 :
1645 328 : if (mNSSInitialized) {
1646 0 : PR_ASSERT(!"Trying to initialize NSS twice"); // We should never try to
1647 : // initialize NSS more than
1648 : // once in a process.
1649 0 : return NS_ERROR_FAILURE;
1650 : }
1651 :
1652 : nsresult rv;
1653 656 : nsCAutoString profileStr;
1654 656 : nsCOMPtr<nsIFile> profilePath;
1655 :
1656 : rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
1657 328 : getter_AddRefs(profilePath));
1658 328 : if (NS_FAILED(rv)) {
1659 15 : PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to get profile directory\n"));
1660 15 : ConfigureInternalPKCS11Token();
1661 15 : SECStatus init_rv = NSS_NoDB_Init(NULL);
1662 15 : if (init_rv != SECSuccess) {
1663 0 : nsPSMInitPanic::SetPanic();
1664 0 : return NS_ERROR_NOT_AVAILABLE;
1665 : }
1666 : }
1667 : else
1668 : {
1669 :
1670 : // XP_MAC == CFM
1671 : // XP_MACOSX == MachO
1672 :
1673 : #if defined(XP_MAC) && defined(XP_MACOSX)
1674 : #error "This code assumes XP_MAC and XP_MACOSX will never be defined at the same time"
1675 : #endif
1676 :
1677 : #if defined(XP_MAC) || defined(XP_MACOSX)
1678 : // On Mac CFM we place all NSS DBs in the Security
1679 : // Folder in the profile directory.
1680 : nsCOMPtr<nsIFile> cfmSecurityPath;
1681 : cfmSecurityPath = profilePath; // alias for easier code reading
1682 : cfmSecurityPath->AppendNative(NS_LITERAL_CSTRING("Security"));
1683 : #endif
1684 :
1685 : #if defined(XP_MAC)
1686 : // on CFM, cfmSecurityPath and profilePath point to the same oject
1687 : profilePath->Create(nsIFile::DIRECTORY_TYPE, 0); //This is for Mac, don't worry about
1688 : //permissions.
1689 : #elif defined(XP_MACOSX)
1690 : // On MachO, we need to access both directories,
1691 : // and therefore need separate nsIFile instances.
1692 : // Keep cfmSecurityPath instance, obtain new instance for MachO profilePath.
1693 : rv = cfmSecurityPath->GetParent(getter_AddRefs(profilePath));
1694 : if (NS_FAILED(rv)) {
1695 : nsPSMInitPanic::SetPanic();
1696 : return rv;
1697 : }
1698 : #endif
1699 :
1700 313 : const char *dbdir_override = getenv("MOZPSM_NSSDBDIR_OVERRIDE");
1701 313 : if (dbdir_override && strlen(dbdir_override)) {
1702 0 : profileStr = dbdir_override;
1703 : }
1704 : else {
1705 : #if defined(XP_WIN)
1706 : // Native path will drop Unicode characters that cannot be mapped to system's
1707 : // codepage, using short (canonical) path as workaround.
1708 : nsCOMPtr<nsILocalFileWin> profilePathWin(do_QueryInterface(profilePath, &rv));
1709 : if (profilePathWin)
1710 : rv = profilePathWin->GetNativeCanonicalPath(profileStr);
1711 : #else
1712 313 : rv = profilePath->GetNativePath(profileStr);
1713 : #endif
1714 313 : if (NS_FAILED(rv)) {
1715 0 : nsPSMInitPanic::SetPanic();
1716 0 : return rv;
1717 : }
1718 : }
1719 :
1720 : hashTableCerts = PL_NewHashTable( 0, certHashtable_keyHash, certHashtable_keyCompare,
1721 313 : certHashtable_valueCompare, 0, 0 );
1722 :
1723 : #if defined(XP_MACOSX)
1724 : // function may modify the parameters
1725 : // ignore return code from conversion, we continue anyway
1726 : TryCFM2MachOMigration(cfmSecurityPath, profilePath);
1727 : #endif
1728 :
1729 313 : rv = mPrefBranch->GetBoolPref("security.use_libpkix_verification", &globalConstFlagUsePKIXVerification);
1730 313 : if (NS_FAILED(rv))
1731 313 : globalConstFlagUsePKIXVerification = USE_NSS_LIBPKIX_DEFAULT;
1732 :
1733 313 : bool supress_warning_preference = false;
1734 313 : rv = mPrefBranch->GetBoolPref("security.suppress_nss_rw_impossible_warning", &supress_warning_preference);
1735 :
1736 313 : if (NS_FAILED(rv)) {
1737 313 : supress_warning_preference = false;
1738 : }
1739 :
1740 : // init phase 2, init calls to NSS library
1741 :
1742 313 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS Initialization beginning\n"));
1743 :
1744 : // The call to ConfigureInternalPKCS11Token needs to be done before NSS is initialized,
1745 : // but affects only static data.
1746 : // If we could assume i18n will not change between profiles, one call per application
1747 : // run were sufficient. As I can't predict what happens in the future, let's repeat
1748 : // this call for every re-init of NSS.
1749 :
1750 313 : ConfigureInternalPKCS11Token();
1751 :
1752 : // The NSS_INIT_NOROOTINIT flag turns off the loading of the root certs
1753 : // module by NSS_Initialize because we will load it in InstallLoadableRoots
1754 : // later. It also allows us to work around a bug in the system NSS in
1755 : // Ubuntu 8.04, which loads any nonexistent "<configdir>/libnssckbi.so" as
1756 : // "/usr/lib/nss/libnssckbi.so".
1757 313 : PRUint32 init_flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE;
1758 : SECStatus init_rv = ::NSS_Initialize(profileStr.get(), "", "",
1759 313 : SECMOD_DB, init_flags);
1760 :
1761 313 : if (init_rv != SECSuccess) {
1762 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can not init NSS r/w in %s\n", profileStr.get()));
1763 :
1764 0 : if (supress_warning_preference) {
1765 0 : which_nss_problem = problem_none;
1766 : }
1767 : else {
1768 0 : which_nss_problem = problem_no_rw;
1769 : }
1770 :
1771 : // try to init r/o
1772 0 : init_flags |= NSS_INIT_READONLY;
1773 : init_rv = ::NSS_Initialize(profileStr.get(), "", "",
1774 0 : SECMOD_DB, init_flags);
1775 :
1776 0 : if (init_rv != SECSuccess) {
1777 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can not init in r/o either\n"));
1778 0 : which_nss_problem = problem_no_security_at_all;
1779 :
1780 0 : init_rv = NSS_NoDB_Init(profileStr.get());
1781 0 : if (init_rv != SECSuccess) {
1782 0 : nsPSMInitPanic::SetPanic();
1783 0 : return NS_ERROR_NOT_AVAILABLE;
1784 : }
1785 : }
1786 : } // have profile dir
1787 : } // lock
1788 :
1789 : // init phase 3, only if phase 2 was successful
1790 :
1791 328 : if (problem_no_security_at_all != which_nss_problem) {
1792 :
1793 328 : mNSSInitialized = true;
1794 :
1795 328 : ::NSS_SetDomesticPolicy();
1796 : // SSL_EnableCipher(SSL_RSA_WITH_NULL_MD5, SSL_ALLOWED);
1797 : // SSL_EnableCipher(SSL_RSA_WITH_NULL_SHA, SSL_ALLOWED);
1798 :
1799 328 : PK11_SetPasswordFunc(PK11PasswordPrompt);
1800 :
1801 : // Register an observer so we can inform NSS when these prefs change
1802 328 : mPrefBranch->AddObserver("security.", this, false);
1803 :
1804 328 : SSL_OptionSetDefault(SSL_ENABLE_SSL2, false);
1805 328 : SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, false);
1806 : bool enabled;
1807 328 : mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
1808 328 : SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
1809 328 : mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
1810 328 : SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
1811 328 : mPrefBranch->GetBoolPref("security.enable_md5_signatures", &enabled);
1812 328 : configureMD5(enabled);
1813 :
1814 : // Configure TLS session tickets
1815 328 : mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
1816 328 : SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
1817 :
1818 328 : mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
1819 328 : SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
1820 :
1821 328 : mPrefBranch->GetBoolPref(
1822 : "security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref",
1823 328 : &enabled);
1824 : SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
1825 328 : enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
1826 :
1827 : #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
1828 328 : mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
1829 328 : SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
1830 : #endif
1831 :
1832 : // Disable any ciphers that NSS might have enabled by default
1833 18696 : for (PRUint16 i = 0; i < SSL_NumImplementedCiphers; ++i)
1834 : {
1835 18368 : PRUint16 cipher_id = SSL_ImplementedCiphers[i];
1836 18368 : SSL_CipherPrefSetDefault(cipher_id, false);
1837 : }
1838 :
1839 : // Now only set SSL/TLS ciphers we knew about at compile time
1840 16400 : for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
1841 16072 : rv = mPrefBranch->GetBoolPref(cp->pref, &enabled);
1842 16072 : if (NS_FAILED(rv))
1843 0 : enabled = false;
1844 :
1845 16072 : SSL_CipherPrefSetDefault(cp->id, enabled);
1846 : }
1847 :
1848 : // Enable ciphers for PKCS#12
1849 328 : SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
1850 328 : SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
1851 328 : SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
1852 328 : SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
1853 328 : SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
1854 328 : SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
1855 328 : SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
1856 328 : PORT_SetUCS2_ASCIIConversionFunction(pip_ucs2_ascii_conversion_fn);
1857 :
1858 : // dynamic options from prefs
1859 328 : setValidationOptions(mPrefBranch);
1860 :
1861 : // static validation options for usagesarray - do not hit the network
1862 328 : mDefaultCERTValInParamLocalOnly = new nsCERTValInParamWrapper;
1863 : rv = mDefaultCERTValInParamLocalOnly->Construct(
1864 : nsCERTValInParamWrapper::missing_cert_download_off,
1865 : nsCERTValInParamWrapper::crl_local_only,
1866 : nsCERTValInParamWrapper::ocsp_off,
1867 : nsCERTValInParamWrapper::ocsp_relaxed,
1868 : nsCERTValInParamWrapper::any_revo_relaxed,
1869 328 : FIRST_REVO_METHOD_DEFAULT);
1870 328 : if (NS_FAILED(rv)) {
1871 0 : nsPSMInitPanic::SetPanic();
1872 0 : return rv;
1873 : }
1874 :
1875 328 : RegisterMyOCSPAIAInfoCallback();
1876 :
1877 328 : mHttpForNSS.initTable();
1878 328 : mHttpForNSS.registerHttpClient();
1879 :
1880 328 : InstallLoadableRoots();
1881 :
1882 328 : LaunchSmartCardThreads();
1883 :
1884 328 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS Initialization done\n"));
1885 : }
1886 : }
1887 :
1888 328 : if (problem_none != which_nss_problem) {
1889 0 : nsPSMInitPanic::SetPanic();
1890 :
1891 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS problem, trying to bring up GUI error message\n"));
1892 :
1893 : // We might want to use different messages, depending on what failed.
1894 : // For now, let's use the same message.
1895 0 : if (showWarningBox) {
1896 0 : ShowAlertFromStringBundle("NSSInitProblemX");
1897 : }
1898 : }
1899 :
1900 328 : return NS_OK;
1901 : }
1902 :
1903 : nsresult
1904 639 : nsNSSComponent::ShutdownNSS()
1905 : {
1906 : // Can be called both during init and profile change,
1907 : // needs mutex protection.
1908 :
1909 639 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent::ShutdownNSS\n"));
1910 :
1911 1278 : MutexAutoLock lock(mutex);
1912 639 : nsresult rv = NS_OK;
1913 :
1914 639 : if (hashTableCerts) {
1915 313 : PL_HashTableEnumerateEntries(hashTableCerts, certHashtable_clearEntry, 0);
1916 313 : PL_HashTableDestroy(hashTableCerts);
1917 313 : hashTableCerts = nsnull;
1918 : }
1919 :
1920 639 : if (mNSSInitialized) {
1921 328 : mNSSInitialized = false;
1922 :
1923 328 : PK11_SetPasswordFunc((PK11PasswordFunc)nsnull);
1924 328 : mHttpForNSS.unregisterHttpClient();
1925 328 : UnregisterMyOCSPAIAInfoCallback();
1926 :
1927 328 : if (mPrefBranch) {
1928 328 : mPrefBranch->RemoveObserver("security.", this);
1929 : }
1930 :
1931 328 : ShutdownSmartCardThreads();
1932 328 : SSL_ClearSessionCache();
1933 328 : if (mClientAuthRememberService) {
1934 328 : mClientAuthRememberService->ClearRememberedDecisions();
1935 : }
1936 328 : UnloadLoadableRoots();
1937 328 : CleanupIdentityInfo();
1938 328 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("evaporating psm resources\n"));
1939 328 : mShutdownObjectList->evaporateAllNSSResources();
1940 328 : EnsureNSSInitialized(nssShutdown);
1941 328 : if (SECSuccess != ::NSS_Shutdown()) {
1942 36 : PR_LOG(gPIPNSSLog, PR_LOG_ALWAYS, ("NSS SHUTDOWN FAILURE\n"));
1943 36 : rv = NS_ERROR_FAILURE;
1944 : }
1945 : else {
1946 292 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS shutdown =====>> OK <<=====\n"));
1947 : }
1948 : }
1949 :
1950 639 : return rv;
1951 : }
1952 :
1953 : NS_IMETHODIMP
1954 328 : nsNSSComponent::Init()
1955 : {
1956 : // No mutex protection.
1957 : // Assume Init happens before any concurrency on "this" can start.
1958 :
1959 328 : nsresult rv = NS_OK;
1960 :
1961 328 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Beginning NSS initialization\n"));
1962 :
1963 328 : if (!mShutdownObjectList)
1964 : {
1965 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, out of memory in constructor\n"));
1966 0 : return NS_ERROR_OUT_OF_MEMORY;
1967 : }
1968 :
1969 328 : rv = InitializePIPNSSBundle();
1970 328 : if (NS_FAILED(rv)) {
1971 0 : PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to create pipnss bundle.\n"));
1972 0 : return rv;
1973 : }
1974 :
1975 : // Access our string bundles now, this prevents assertions from I/O
1976 : // - nsStandardURL not thread-safe
1977 : // - wrong thread: 'NS_IsMainThread()' in nsIOService.cpp
1978 : // when loading error strings on the SSL threads.
1979 : {
1980 656 : NS_NAMED_LITERAL_STRING(dummy_name, "dummy");
1981 656 : nsXPIDLString result;
1982 328 : mPIPNSSBundle->GetStringFromName(dummy_name.get(),
1983 328 : getter_Copies(result));
1984 328 : mNSSErrorsBundle->GetStringFromName(dummy_name.get(),
1985 328 : getter_Copies(result));
1986 : }
1987 :
1988 328 : if (!mPrefBranch) {
1989 328 : mPrefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
1990 328 : NS_ASSERTION(mPrefBranch, "Unable to get pref service");
1991 : }
1992 :
1993 : // Do that before NSS init, to make sure we won't get unloaded.
1994 328 : RegisterObservers();
1995 :
1996 328 : rv = InitializeNSS(true); // ok to show a warning box on failure
1997 328 : if (NS_FAILED(rv)) {
1998 0 : PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS.\n"));
1999 :
2000 0 : DeregisterObservers();
2001 0 : mPIPNSSBundle = nsnull;
2002 0 : return rv;
2003 : }
2004 :
2005 328 : nsSSLIOLayerHelpers::Init();
2006 328 : char *unrestricted_hosts=nsnull;
2007 328 : mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
2008 328 : if (unrestricted_hosts) {
2009 328 : nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
2010 328 : nsMemory::Free(unrestricted_hosts);
2011 328 : unrestricted_hosts=nsnull;
2012 : }
2013 :
2014 328 : bool enabled = false;
2015 328 : mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
2016 328 : nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
2017 :
2018 328 : PRInt32 warnLevel = 1;
2019 328 : mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
2020 328 : nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
2021 :
2022 328 : mClientAuthRememberService = new nsClientAuthRememberService;
2023 328 : if (mClientAuthRememberService)
2024 328 : mClientAuthRememberService->Init();
2025 :
2026 328 : createBackgroundThreads();
2027 328 : if (!mCertVerificationThread)
2028 : {
2029 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NSS init, could not create threads\n"));
2030 :
2031 0 : DeregisterObservers();
2032 0 : mPIPNSSBundle = nsnull;
2033 0 : return NS_ERROR_OUT_OF_MEMORY;
2034 : }
2035 :
2036 328 : InitializeCRLUpdateTimer();
2037 328 : RegisterPSMContentListener();
2038 :
2039 : nsCOMPtr<nsIEntropyCollector> ec
2040 656 : = do_GetService(NS_ENTROPYCOLLECTOR_CONTRACTID);
2041 :
2042 656 : nsCOMPtr<nsIBufEntropyCollector> bec;
2043 :
2044 328 : if (ec) {
2045 328 : bec = do_QueryInterface(ec);
2046 : }
2047 :
2048 328 : NS_ASSERTION(bec, "No buffering entropy collector. "
2049 : "This means no entropy will be collected.");
2050 328 : if (bec) {
2051 328 : bec->ForwardTo(this);
2052 : }
2053 :
2054 328 : return rv;
2055 : }
2056 :
2057 : /* nsISupports Implementation for the class */
2058 22242 : NS_IMPL_THREADSAFE_ISUPPORTS6(nsNSSComponent,
2059 : nsISignatureVerifier,
2060 : nsIEntropyCollector,
2061 : nsINSSComponent,
2062 : nsIObserver,
2063 : nsISupportsWeakReference,
2064 : nsITimerCallback)
2065 :
2066 :
2067 : /* Callback functions for decoder. For now, use empty/default functions. */
2068 0 : static void ContentCallback(void *arg,
2069 : const char *buf,
2070 : unsigned long len)
2071 : {
2072 0 : }
2073 :
2074 0 : static PK11SymKey * GetDecryptKeyCallback(void *arg,
2075 : SECAlgorithmID *algid)
2076 : {
2077 0 : return nsnull;
2078 : }
2079 :
2080 0 : static PRBool DecryptionAllowedCallback(SECAlgorithmID *algid,
2081 : PK11SymKey *bulkkey)
2082 : {
2083 0 : return SECMIME_DecryptionAllowed(algid, bulkkey);
2084 : }
2085 :
2086 0 : static void * GetPasswordKeyCallback(void *arg, void *handle)
2087 : {
2088 0 : return NULL;
2089 : }
2090 :
2091 : NS_IMETHODIMP
2092 0 : nsNSSComponent::VerifySignature(const char* aRSABuf, PRUint32 aRSABufLen,
2093 : const char* aPlaintext, PRUint32 aPlaintextLen,
2094 : PRInt32* aErrorCode,
2095 : nsIPrincipal** aPrincipal)
2096 : {
2097 0 : if (!aPrincipal || !aErrorCode) {
2098 0 : return NS_ERROR_NULL_POINTER;
2099 : }
2100 :
2101 0 : *aErrorCode = 0;
2102 0 : *aPrincipal = nsnull;
2103 :
2104 0 : nsNSSShutDownPreventionLock locker;
2105 0 : SEC_PKCS7ContentInfo * p7_info = nsnull;
2106 : unsigned char hash[SHA1_LENGTH];
2107 :
2108 : SECItem item;
2109 0 : item.type = siEncodedCertBuffer;
2110 0 : item.data = (unsigned char*)aRSABuf;
2111 0 : item.len = aRSABufLen;
2112 : p7_info = SEC_PKCS7DecodeItem(&item,
2113 : ContentCallback, nsnull,
2114 : GetPasswordKeyCallback, nsnull,
2115 : GetDecryptKeyCallback, nsnull,
2116 0 : DecryptionAllowedCallback);
2117 :
2118 0 : if (!p7_info) {
2119 0 : return NS_ERROR_FAILURE;
2120 : }
2121 :
2122 : // Make sure we call SEC_PKCS7DestroyContentInfo after this point;
2123 : // otherwise we leak data in p7_info
2124 :
2125 : //-- If a plaintext was provided, hash it.
2126 : SECItem digest;
2127 0 : digest.data = nsnull;
2128 0 : digest.len = 0;
2129 :
2130 0 : if (aPlaintext) {
2131 : HASHContext* hash_ctxt;
2132 0 : PRUint32 hashLen = 0;
2133 :
2134 0 : hash_ctxt = HASH_Create(HASH_AlgSHA1);
2135 0 : HASH_Begin(hash_ctxt);
2136 0 : HASH_Update(hash_ctxt,(const unsigned char*)aPlaintext, aPlaintextLen);
2137 0 : HASH_End(hash_ctxt, hash, &hashLen, SHA1_LENGTH);
2138 0 : HASH_Destroy(hash_ctxt);
2139 :
2140 0 : digest.data = hash;
2141 0 : digest.len = SHA1_LENGTH;
2142 : }
2143 :
2144 : //-- Verify signature
2145 : bool rv = SEC_PKCS7VerifyDetachedSignature(p7_info, certUsageObjectSigner,
2146 0 : &digest, HASH_AlgSHA1, false);
2147 0 : if (!rv) {
2148 0 : *aErrorCode = PR_GetError();
2149 : }
2150 :
2151 : // Get the signing cert //
2152 0 : CERTCertificate *cert = p7_info->content.signedData->signerInfos[0]->cert;
2153 0 : nsresult rv2 = NS_OK;
2154 0 : if (cert) {
2155 : // Use |do { } while (0);| as a "more C++-ish" thing than goto;
2156 : // this way we don't have to worry about goto across variable
2157 : // declarations. We have no loops in this code, so it's OK.
2158 : do {
2159 0 : nsCOMPtr<nsIX509Cert> pCert = nsNSSCertificate::Create(cert);
2160 0 : if (!pCert) {
2161 0 : rv2 = NS_ERROR_OUT_OF_MEMORY;
2162 : break;
2163 : }
2164 :
2165 0 : if (!mScriptSecurityManager) {
2166 0 : MutexAutoLock lock(mutex);
2167 : // re-test the condition to prevent double initialization
2168 0 : if (!mScriptSecurityManager) {
2169 : mScriptSecurityManager =
2170 0 : do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv2);
2171 0 : if (NS_FAILED(rv2)) {
2172 : break;
2173 : }
2174 : }
2175 : }
2176 :
2177 : //-- Create a certificate principal with id and organization data
2178 0 : nsAutoString fingerprint;
2179 0 : rv2 = pCert->GetSha1Fingerprint(fingerprint);
2180 0 : if (NS_FAILED(rv2)) {
2181 : break;
2182 : }
2183 0 : nsAutoString orgName;
2184 0 : rv2 = pCert->GetOrganization(orgName);
2185 0 : if (NS_FAILED(rv2)) {
2186 : break;
2187 : }
2188 0 : nsAutoString subjectName;
2189 0 : rv2 = pCert->GetSubjectName(subjectName);
2190 0 : if (NS_FAILED(rv2)) {
2191 : break;
2192 : }
2193 :
2194 0 : nsCOMPtr<nsIPrincipal> certPrincipal;
2195 0 : rv2 = mScriptSecurityManager->
2196 0 : GetCertificatePrincipal(NS_ConvertUTF16toUTF8(fingerprint),
2197 0 : NS_ConvertUTF16toUTF8(subjectName),
2198 0 : NS_ConvertUTF16toUTF8(orgName),
2199 0 : pCert, nsnull, getter_AddRefs(certPrincipal));
2200 0 : if (NS_FAILED(rv2) || !certPrincipal) {
2201 : break;
2202 : }
2203 :
2204 0 : certPrincipal.swap(*aPrincipal);
2205 : } while (0);
2206 : }
2207 :
2208 0 : SEC_PKCS7DestroyContentInfo(p7_info);
2209 :
2210 0 : return rv2;
2211 : }
2212 :
2213 : NS_IMETHODIMP
2214 328 : nsNSSComponent::RandomUpdate(void *entropy, PRInt32 bufLen)
2215 : {
2216 656 : nsNSSShutDownPreventionLock locker;
2217 :
2218 : // Asynchronous event happening often,
2219 : // must not interfere with initialization or profile switch.
2220 :
2221 656 : MutexAutoLock lock(mutex);
2222 :
2223 328 : if (!mNSSInitialized)
2224 0 : return NS_ERROR_NOT_INITIALIZED;
2225 :
2226 328 : PK11_RandomUpdate(entropy, bufLen);
2227 328 : return NS_OK;
2228 : }
2229 :
2230 : #define PROFILE_CHANGE_NET_TEARDOWN_TOPIC "profile-change-net-teardown"
2231 : #define PROFILE_CHANGE_NET_RESTORE_TOPIC "profile-change-net-restore"
2232 : #define PROFILE_APPROVE_CHANGE_TOPIC "profile-approve-change"
2233 : #define PROFILE_CHANGE_TEARDOWN_TOPIC "profile-change-teardown"
2234 : #define PROFILE_CHANGE_TEARDOWN_VETO_TOPIC "profile-change-teardown-veto"
2235 : #define PROFILE_BEFORE_CHANGE_TOPIC "profile-before-change"
2236 : #define PROFILE_DO_CHANGE_TOPIC "profile-do-change"
2237 :
2238 : NS_IMETHODIMP
2239 1273 : nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic,
2240 : const PRUnichar *someData)
2241 : {
2242 1273 : if (nsCRT::strcmp(aTopic, PROFILE_APPROVE_CHANGE_TOPIC) == 0) {
2243 0 : DoProfileApproveChange(aSubject);
2244 : }
2245 1273 : else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_TOPIC) == 0) {
2246 315 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("in PSM code, receiving change-teardown\n"));
2247 315 : DoProfileChangeTeardown(aSubject);
2248 : }
2249 958 : else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC) == 0) {
2250 0 : mShutdownObjectList->allowUI();
2251 : }
2252 958 : else if (nsCRT::strcmp(aTopic, PROFILE_BEFORE_CHANGE_TOPIC) == 0) {
2253 315 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving profile change topic\n"));
2254 315 : DoProfileBeforeChange(aSubject);
2255 : }
2256 643 : else if (nsCRT::strcmp(aTopic, PROFILE_DO_CHANGE_TOPIC) == 0) {
2257 0 : if (someData && NS_LITERAL_STRING("startup").Equals(someData)) {
2258 : // The application is initializing against a known profile directory for
2259 : // the first time during process execution.
2260 : // However, earlier code execution might have already triggered NSS init.
2261 : // We must ensure that NSS gets shut down prior to any attempt to init
2262 : // it again. We use the same cleanup functionality used when switching
2263 : // profiles. The order of function calls must correspond to the order
2264 : // of notifications sent by Profile Manager (nsProfile).
2265 0 : DoProfileApproveChange(aSubject);
2266 0 : DoProfileChangeNetTeardown();
2267 0 : DoProfileChangeTeardown(aSubject);
2268 0 : DoProfileBeforeChange(aSubject);
2269 0 : DoProfileChangeNetRestore();
2270 : }
2271 :
2272 0 : bool needsInit = true;
2273 :
2274 : {
2275 0 : MutexAutoLock lock(mutex);
2276 :
2277 0 : if (mNSSInitialized) {
2278 : // We have already initialized NSS before the profile came up,
2279 : // no need to do it again
2280 0 : needsInit = false;
2281 : }
2282 : }
2283 :
2284 0 : if (needsInit) {
2285 0 : if (NS_FAILED(InitializeNSS(false))) { // do not show a warning box on failure
2286 0 : PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("Unable to Initialize NSS after profile switch.\n"));
2287 0 : nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
2288 0 : if (status) {
2289 0 : status->ChangeFailed();
2290 : }
2291 : }
2292 : }
2293 :
2294 0 : InitializeCRLUpdateTimer();
2295 : }
2296 643 : else if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
2297 :
2298 328 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: XPCom shutdown observed\n"));
2299 :
2300 : // Cleanup code that requires services, it's too late in destructor.
2301 :
2302 328 : if (mPSMContentListener) {
2303 656 : nsCOMPtr<nsIURILoader> dispatcher(do_GetService(NS_URI_LOADER_CONTRACTID));
2304 328 : if (dispatcher) {
2305 328 : dispatcher->UnRegisterContentListener(mPSMContentListener);
2306 : }
2307 328 : mPSMContentListener = nsnull;
2308 : }
2309 :
2310 : nsCOMPtr<nsIEntropyCollector> ec
2311 656 : = do_GetService(NS_ENTROPYCOLLECTOR_CONTRACTID);
2312 :
2313 328 : if (ec) {
2314 : nsCOMPtr<nsIBufEntropyCollector> bec
2315 656 : = do_QueryInterface(ec);
2316 328 : if (bec) {
2317 328 : bec->DontForward();
2318 : }
2319 : }
2320 : }
2321 315 : else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
2322 0 : nsNSSShutDownPreventionLock locker;
2323 0 : bool clearSessionCache = false;
2324 : bool enabled;
2325 0 : NS_ConvertUTF16toUTF8 prefName(someData);
2326 :
2327 0 : if (prefName.Equals("security.enable_ssl3")) {
2328 0 : mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
2329 0 : SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
2330 0 : clearSessionCache = true;
2331 0 : } else if (prefName.Equals("security.enable_tls")) {
2332 0 : mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
2333 0 : SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
2334 0 : clearSessionCache = true;
2335 0 : } else if (prefName.Equals("security.enable_md5_signatures")) {
2336 0 : mPrefBranch->GetBoolPref("security.enable_md5_signatures", &enabled);
2337 0 : configureMD5(enabled);
2338 0 : clearSessionCache = true;
2339 0 : } else if (prefName.Equals("security.enable_tls_session_tickets")) {
2340 0 : mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
2341 0 : SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
2342 0 : } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
2343 0 : mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
2344 0 : SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
2345 0 : } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
2346 0 : mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
2347 : SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
2348 0 : enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
2349 0 : } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
2350 0 : char *unrestricted_hosts=nsnull;
2351 0 : mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
2352 0 : if (unrestricted_hosts) {
2353 0 : nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
2354 0 : nsMemory::Free(unrestricted_hosts);
2355 : }
2356 0 : } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
2357 0 : mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
2358 0 : nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
2359 0 : } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
2360 0 : PRInt32 warnLevel = 1;
2361 0 : mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
2362 0 : nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
2363 : #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
2364 0 : } else if (prefName.Equals("security.ssl.enable_false_start")) {
2365 0 : mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
2366 0 : SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
2367 : #endif
2368 0 : } else if (prefName.Equals("security.OCSP.enabled")
2369 0 : || prefName.Equals("security.CRL_download.enabled")
2370 0 : || prefName.Equals("security.fresh_revocation_info.require")
2371 0 : || prefName.Equals("security.missing_cert_download.enabled")
2372 0 : || prefName.Equals("security.first_network_revocation_method")
2373 0 : || prefName.Equals("security.OCSP.require")) {
2374 0 : MutexAutoLock lock(mutex);
2375 0 : setValidationOptions(mPrefBranch);
2376 : } else {
2377 : /* Look through the cipher table and set according to pref setting */
2378 0 : for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
2379 0 : if (prefName.Equals(cp->pref)) {
2380 0 : mPrefBranch->GetBoolPref(cp->pref, &enabled);
2381 0 : SSL_CipherPrefSetDefault(cp->id, enabled);
2382 0 : clearSessionCache = true;
2383 0 : break;
2384 : }
2385 : }
2386 : }
2387 0 : if (clearSessionCache)
2388 0 : SSL_ClearSessionCache();
2389 : }
2390 315 : else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_TEARDOWN_TOPIC) == 0) {
2391 315 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network teardown topic\n"));
2392 315 : DoProfileChangeNetTeardown();
2393 : }
2394 0 : else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_RESTORE_TOPIC) == 0) {
2395 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network restore topic\n"));
2396 0 : DoProfileChangeNetRestore();
2397 : }
2398 :
2399 1273 : return NS_OK;
2400 : }
2401 :
2402 : /*static*/ nsresult
2403 0 : nsNSSComponent::GetNewPrompter(nsIPrompt ** result)
2404 : {
2405 0 : NS_ENSURE_ARG_POINTER(result);
2406 0 : *result = nsnull;
2407 :
2408 0 : if (!NS_IsMainThread()) {
2409 0 : NS_ERROR("nsSDRContext::GetNewPrompter called off the main thread");
2410 0 : return NS_ERROR_NOT_SAME_THREAD;
2411 : }
2412 :
2413 : nsresult rv;
2414 0 : nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
2415 0 : NS_ENSURE_SUCCESS(rv, rv);
2416 :
2417 0 : rv = wwatch->GetNewPrompter(0, result);
2418 0 : NS_ENSURE_SUCCESS(rv, rv);
2419 :
2420 0 : return rv;
2421 : }
2422 :
2423 : /*static*/ nsresult
2424 0 : nsNSSComponent::ShowAlertWithConstructedString(const nsString & message)
2425 : {
2426 0 : nsCOMPtr<nsIPrompt> prompter;
2427 0 : nsresult rv = GetNewPrompter(getter_AddRefs(prompter));
2428 0 : if (prompter) {
2429 0 : nsPSMUITracker tracker;
2430 0 : if (tracker.isUIForbidden()) {
2431 0 : NS_WARNING("Suppressing alert because PSM UI is forbidden");
2432 0 : rv = NS_ERROR_UNEXPECTED;
2433 : } else {
2434 0 : rv = prompter->Alert(nsnull, message.get());
2435 : }
2436 : }
2437 0 : return rv;
2438 : }
2439 :
2440 : NS_IMETHODIMP
2441 0 : nsNSSComponent::ShowAlertFromStringBundle(const char * messageID)
2442 : {
2443 0 : nsString message;
2444 : nsresult rv;
2445 :
2446 0 : rv = GetPIPNSSBundleString(messageID, message);
2447 0 : if (NS_FAILED(rv)) {
2448 0 : NS_ERROR("GetPIPNSSBundleString failed");
2449 0 : return rv;
2450 : }
2451 :
2452 0 : return ShowAlertWithConstructedString(message);
2453 : }
2454 :
2455 142 : nsresult nsNSSComponent::LogoutAuthenticatedPK11()
2456 : {
2457 : nsCOMPtr<nsICertOverrideService> icos =
2458 284 : do_GetService("@mozilla.org/security/certoverride;1");
2459 142 : if (icos) {
2460 142 : icos->ClearValidityOverride(
2461 142 : NS_LITERAL_CSTRING("all:temporary-certificates"),
2462 142 : 0);
2463 : }
2464 :
2465 142 : if (mClientAuthRememberService) {
2466 142 : mClientAuthRememberService->ClearRememberedDecisions();
2467 : }
2468 :
2469 142 : return mShutdownObjectList->doPK11Logout();
2470 : }
2471 :
2472 : nsresult
2473 328 : nsNSSComponent::RegisterObservers()
2474 : {
2475 : // Happens once during init only, no mutex protection.
2476 :
2477 656 : nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1"));
2478 328 : NS_ASSERTION(observerService, "could not get observer service");
2479 328 : if (observerService) {
2480 328 : mObserversRegistered = true;
2481 328 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: adding observers\n"));
2482 :
2483 : // We are a service.
2484 : // Once we are loaded, don't allow being removed from memory.
2485 : // This makes sense, as initializing NSS is expensive.
2486 :
2487 : // By using false for parameter ownsWeak in AddObserver,
2488 : // we make sure that we won't get unloaded until the application shuts down.
2489 :
2490 328 : observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
2491 :
2492 328 : observerService->AddObserver(this, PROFILE_APPROVE_CHANGE_TOPIC, false);
2493 328 : observerService->AddObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC, false);
2494 328 : observerService->AddObserver(this, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC, false);
2495 328 : observerService->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
2496 328 : observerService->AddObserver(this, PROFILE_DO_CHANGE_TOPIC, false);
2497 328 : observerService->AddObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC, false);
2498 328 : observerService->AddObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC, false);
2499 : }
2500 328 : return NS_OK;
2501 : }
2502 :
2503 : nsresult
2504 0 : nsNSSComponent::DeregisterObservers()
2505 : {
2506 0 : if (!mObserversRegistered)
2507 0 : return NS_OK;
2508 :
2509 0 : nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1"));
2510 0 : NS_ASSERTION(observerService, "could not get observer service");
2511 0 : if (observerService) {
2512 0 : mObserversRegistered = false;
2513 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsNSSComponent: removing observers\n"));
2514 :
2515 0 : observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
2516 :
2517 0 : observerService->RemoveObserver(this, PROFILE_APPROVE_CHANGE_TOPIC);
2518 0 : observerService->RemoveObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC);
2519 0 : observerService->RemoveObserver(this, PROFILE_CHANGE_TEARDOWN_VETO_TOPIC);
2520 0 : observerService->RemoveObserver(this, PROFILE_BEFORE_CHANGE_TOPIC);
2521 0 : observerService->RemoveObserver(this, PROFILE_DO_CHANGE_TOPIC);
2522 0 : observerService->RemoveObserver(this, PROFILE_CHANGE_NET_TEARDOWN_TOPIC);
2523 0 : observerService->RemoveObserver(this, PROFILE_CHANGE_NET_RESTORE_TOPIC);
2524 : }
2525 0 : return NS_OK;
2526 : }
2527 :
2528 : NS_IMETHODIMP
2529 0 : nsNSSComponent::RememberCert(CERTCertificate *cert)
2530 : {
2531 0 : nsNSSShutDownPreventionLock locker;
2532 :
2533 : // Must not interfere with init / shutdown / profile switch.
2534 :
2535 0 : MutexAutoLock lock(mutex);
2536 :
2537 0 : if (!hashTableCerts || !cert)
2538 0 : return NS_OK;
2539 :
2540 0 : void *found = PL_HashTableLookup(hashTableCerts, (void*)&cert->certKey);
2541 :
2542 0 : if (found) {
2543 : // we remember that cert already
2544 0 : return NS_OK;
2545 : }
2546 :
2547 0 : CERTCertificate *myDupCert = CERT_DupCertificate(cert);
2548 :
2549 0 : if (!myDupCert)
2550 0 : return NS_ERROR_OUT_OF_MEMORY;
2551 :
2552 0 : if (!PL_HashTableAdd(hashTableCerts, (void*)&myDupCert->certKey, myDupCert)) {
2553 0 : CERT_DestroyCertificate(myDupCert);
2554 : }
2555 :
2556 0 : return NS_OK;
2557 : }
2558 :
2559 : static const char PROFILE_SWITCH_CRYPTO_UI_ACTIVE[] =
2560 : "ProfileSwitchCryptoUIActive";
2561 : static const char PROFILE_SWITCH_SOCKETS_STILL_ACTIVE[] =
2562 : "ProfileSwitchSocketsStillActive";
2563 :
2564 : void
2565 0 : nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject)
2566 : {
2567 0 : if (mShutdownObjectList->isUIActive()) {
2568 0 : ShowAlertFromStringBundle(PROFILE_SWITCH_CRYPTO_UI_ACTIVE);
2569 0 : nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
2570 0 : if (status) {
2571 0 : status->VetoChange();
2572 : }
2573 : }
2574 0 : }
2575 :
2576 : void
2577 315 : nsNSSComponent::DoProfileChangeNetTeardown()
2578 : {
2579 315 : if (mCertVerificationThread)
2580 315 : mCertVerificationThread->requestExit();
2581 315 : mIsNetworkDown = true;
2582 315 : }
2583 :
2584 : void
2585 315 : nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
2586 : {
2587 315 : bool callVeto = false;
2588 :
2589 315 : if (!mShutdownObjectList->ifPossibleDisallowUI()) {
2590 0 : callVeto = true;
2591 0 : ShowAlertFromStringBundle(PROFILE_SWITCH_CRYPTO_UI_ACTIVE);
2592 : }
2593 315 : else if (mShutdownObjectList->areSSLSocketsActive()) {
2594 0 : callVeto = true;
2595 0 : ShowAlertFromStringBundle(PROFILE_SWITCH_SOCKETS_STILL_ACTIVE);
2596 : }
2597 :
2598 315 : if (callVeto) {
2599 0 : nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
2600 0 : if (status) {
2601 0 : status->VetoChange();
2602 : }
2603 : }
2604 315 : }
2605 :
2606 : void
2607 315 : nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
2608 : {
2609 315 : NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
2610 :
2611 315 : bool needsCleanup = true;
2612 :
2613 : {
2614 630 : MutexAutoLock lock(mutex);
2615 :
2616 315 : if (!mNSSInitialized) {
2617 : // Make sure we don't try to cleanup if we have already done so.
2618 : // This makes sure we behave safely, in case we are notified
2619 : // multiple times.
2620 4 : needsCleanup = false;
2621 : }
2622 : }
2623 :
2624 315 : StopCRLUpdateTimer();
2625 :
2626 315 : if (needsCleanup) {
2627 311 : if (NS_FAILED(ShutdownNSS())) {
2628 66 : nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
2629 33 : if (status) {
2630 0 : status->ChangeFailed();
2631 : }
2632 : }
2633 : }
2634 315 : mShutdownObjectList->allowUI();
2635 315 : }
2636 :
2637 : void
2638 0 : nsNSSComponent::DoProfileChangeNetRestore()
2639 : {
2640 : /* XXX this doesn't work well, since nothing expects null pointers */
2641 0 : deleteBackgroundThreads();
2642 0 : createBackgroundThreads();
2643 0 : mIsNetworkDown = false;
2644 0 : }
2645 :
2646 : NS_IMETHODIMP
2647 0 : nsNSSComponent::GetClientAuthRememberService(nsClientAuthRememberService **cars)
2648 : {
2649 0 : NS_ENSURE_ARG_POINTER(cars);
2650 0 : NS_IF_ADDREF(*cars = mClientAuthRememberService);
2651 0 : return NS_OK;
2652 : }
2653 :
2654 : NS_IMETHODIMP
2655 279 : nsNSSComponent::IsNSSInitialized(bool *initialized)
2656 : {
2657 558 : MutexAutoLock lock(mutex);
2658 279 : *initialized = mNSSInitialized;
2659 279 : return NS_OK;
2660 : }
2661 :
2662 : NS_IMETHODIMP
2663 0 : nsNSSComponent::GetDefaultCERTValInParam(nsRefPtr<nsCERTValInParamWrapper> &out)
2664 : {
2665 0 : MutexAutoLock lock(mutex);
2666 0 : if (!mNSSInitialized)
2667 0 : return NS_ERROR_NOT_INITIALIZED;
2668 0 : out = mDefaultCERTValInParam;
2669 0 : return NS_OK;
2670 : }
2671 :
2672 : NS_IMETHODIMP
2673 0 : nsNSSComponent::GetDefaultCERTValInParamLocalOnly(nsRefPtr<nsCERTValInParamWrapper> &out)
2674 : {
2675 0 : MutexAutoLock lock(mutex);
2676 0 : if (!mNSSInitialized)
2677 0 : return NS_ERROR_NOT_INITIALIZED;
2678 0 : out = mDefaultCERTValInParamLocalOnly;
2679 0 : return NS_OK;
2680 : }
2681 :
2682 : //---------------------------------------------
2683 : // Implementing nsICryptoHash
2684 : //---------------------------------------------
2685 :
2686 1466 : nsCryptoHash::nsCryptoHash()
2687 : : mHashContext(nsnull)
2688 1466 : , mInitialized(false)
2689 : {
2690 1466 : }
2691 :
2692 4398 : nsCryptoHash::~nsCryptoHash()
2693 : {
2694 2932 : nsNSSShutDownPreventionLock locker;
2695 :
2696 1466 : if (isAlreadyShutDown())
2697 : return;
2698 :
2699 951 : destructorSafeDestroyNSSReference();
2700 2417 : shutdown(calledFromObject);
2701 5864 : }
2702 :
2703 515 : void nsCryptoHash::virtualDestroyNSSReference()
2704 : {
2705 515 : destructorSafeDestroyNSSReference();
2706 515 : }
2707 :
2708 1466 : void nsCryptoHash::destructorSafeDestroyNSSReference()
2709 : {
2710 1466 : if (isAlreadyShutDown())
2711 0 : return;
2712 :
2713 1466 : if (mHashContext)
2714 1450 : HASH_Destroy(mHashContext);
2715 1466 : mHashContext = nsnull;
2716 : }
2717 :
2718 23427 : NS_IMPL_ISUPPORTS1(nsCryptoHash, nsICryptoHash)
2719 :
2720 : NS_IMETHODIMP
2721 2252 : nsCryptoHash::Init(PRUint32 algorithm)
2722 : {
2723 4504 : nsNSSShutDownPreventionLock locker;
2724 :
2725 2252 : HASH_HashType hashType = (HASH_HashType)algorithm;
2726 2252 : if (mHashContext)
2727 : {
2728 802 : if ((!mInitialized) && (HASH_GetType(mHashContext) == hashType))
2729 : {
2730 802 : mInitialized = true;
2731 802 : HASH_Begin(mHashContext);
2732 802 : return NS_OK;
2733 : }
2734 :
2735 : // Destroy current hash context if the type was different
2736 : // or Finish method wasn't called.
2737 0 : HASH_Destroy(mHashContext);
2738 0 : mInitialized = false;
2739 : }
2740 :
2741 1450 : mHashContext = HASH_Create(hashType);
2742 1450 : if (!mHashContext)
2743 0 : return NS_ERROR_INVALID_ARG;
2744 :
2745 1450 : HASH_Begin(mHashContext);
2746 1450 : mInitialized = true;
2747 1450 : return NS_OK;
2748 : }
2749 :
2750 : NS_IMETHODIMP
2751 290 : nsCryptoHash::InitWithString(const nsACString & aAlgorithm)
2752 : {
2753 290 : if (aAlgorithm.LowerCaseEqualsLiteral("md2"))
2754 5 : return Init(nsICryptoHash::MD2);
2755 :
2756 285 : if (aAlgorithm.LowerCaseEqualsLiteral("md5"))
2757 5 : return Init(nsICryptoHash::MD5);
2758 :
2759 280 : if (aAlgorithm.LowerCaseEqualsLiteral("sha1"))
2760 265 : return Init(nsICryptoHash::SHA1);
2761 :
2762 15 : if (aAlgorithm.LowerCaseEqualsLiteral("sha256"))
2763 5 : return Init(nsICryptoHash::SHA256);
2764 :
2765 10 : if (aAlgorithm.LowerCaseEqualsLiteral("sha384"))
2766 5 : return Init(nsICryptoHash::SHA384);
2767 :
2768 5 : if (aAlgorithm.LowerCaseEqualsLiteral("sha512"))
2769 5 : return Init(nsICryptoHash::SHA512);
2770 :
2771 0 : return NS_ERROR_INVALID_ARG;
2772 : }
2773 :
2774 : NS_IMETHODIMP
2775 2252 : nsCryptoHash::Update(const PRUint8 *data, PRUint32 len)
2776 : {
2777 4504 : nsNSSShutDownPreventionLock locker;
2778 :
2779 2252 : if (!mInitialized)
2780 0 : return NS_ERROR_NOT_INITIALIZED;
2781 :
2782 2252 : HASH_Update(mHashContext, data, len);
2783 2252 : return NS_OK;
2784 : }
2785 :
2786 : NS_IMETHODIMP
2787 1109 : nsCryptoHash::UpdateFromStream(nsIInputStream *data, PRUint32 len)
2788 : {
2789 1109 : if (!mInitialized)
2790 0 : return NS_ERROR_NOT_INITIALIZED;
2791 :
2792 1109 : if (!data)
2793 0 : return NS_ERROR_INVALID_ARG;
2794 :
2795 : PRUint32 n;
2796 1109 : nsresult rv = data->Available(&n);
2797 1109 : if (NS_FAILED(rv))
2798 0 : return rv;
2799 :
2800 : // if the user has passed PR_UINT32_MAX, then read
2801 : // everything in the stream
2802 :
2803 1109 : if (len == PR_UINT32_MAX)
2804 843 : len = n;
2805 :
2806 : // So, if the stream has NO data available for the hash,
2807 : // or if the data available is less then what the caller
2808 : // requested, we can not fulfill the hash update. In this
2809 : // case, just return NS_ERROR_NOT_AVAILABLE indicating
2810 : // that there is not enough data in the stream to satisify
2811 : // the request.
2812 :
2813 1109 : if (n == 0 || n < len)
2814 0 : return NS_ERROR_NOT_AVAILABLE;
2815 :
2816 : char buffer[NS_CRYPTO_HASH_BUFFER_SIZE];
2817 : PRUint32 read, readLimit;
2818 :
2819 3327 : while(NS_SUCCEEDED(rv) && len>0)
2820 : {
2821 1109 : readLimit = NS_MIN(PRUint32(NS_CRYPTO_HASH_BUFFER_SIZE), len);
2822 :
2823 1109 : rv = data->Read(buffer, readLimit, &read);
2824 :
2825 1109 : if (NS_SUCCEEDED(rv))
2826 1109 : rv = Update((const PRUint8*)buffer, read);
2827 :
2828 1109 : len -= read;
2829 : }
2830 :
2831 1109 : return rv;
2832 : }
2833 :
2834 : NS_IMETHODIMP
2835 2233 : nsCryptoHash::Finish(bool ascii, nsACString & _retval)
2836 : {
2837 4466 : nsNSSShutDownPreventionLock locker;
2838 :
2839 2233 : if (!mInitialized)
2840 0 : return NS_ERROR_NOT_INITIALIZED;
2841 :
2842 2233 : PRUint32 hashLen = 0;
2843 : unsigned char buffer[HASH_LENGTH_MAX];
2844 2233 : unsigned char* pbuffer = buffer;
2845 :
2846 2233 : HASH_End(mHashContext, pbuffer, &hashLen, HASH_LENGTH_MAX);
2847 :
2848 2233 : mInitialized = false;
2849 :
2850 2233 : if (ascii)
2851 : {
2852 24 : char *asciiData = BTOA_DataToAscii(buffer, hashLen);
2853 24 : NS_ENSURE_TRUE(asciiData, NS_ERROR_OUT_OF_MEMORY);
2854 :
2855 24 : _retval.Assign(asciiData);
2856 24 : PORT_Free(asciiData);
2857 : }
2858 : else
2859 : {
2860 2209 : _retval.Assign((const char*)buffer, hashLen);
2861 : }
2862 :
2863 2233 : return NS_OK;
2864 : }
2865 :
2866 : //---------------------------------------------
2867 : // Implementing nsICryptoHMAC
2868 : //---------------------------------------------
2869 :
2870 27280 : NS_IMPL_ISUPPORTS1(nsCryptoHMAC, nsICryptoHMAC)
2871 :
2872 1558 : nsCryptoHMAC::nsCryptoHMAC()
2873 : {
2874 1558 : mHMACContext = nsnull;
2875 1558 : }
2876 :
2877 4674 : nsCryptoHMAC::~nsCryptoHMAC()
2878 : {
2879 3116 : nsNSSShutDownPreventionLock locker;
2880 :
2881 1558 : if (isAlreadyShutDown())
2882 : return;
2883 :
2884 458 : destructorSafeDestroyNSSReference();
2885 2016 : shutdown(calledFromObject);
2886 6232 : }
2887 :
2888 1100 : void nsCryptoHMAC::virtualDestroyNSSReference()
2889 : {
2890 1100 : destructorSafeDestroyNSSReference();
2891 1100 : }
2892 :
2893 1558 : void nsCryptoHMAC::destructorSafeDestroyNSSReference()
2894 : {
2895 1558 : if (isAlreadyShutDown())
2896 0 : return;
2897 :
2898 1558 : if (mHMACContext)
2899 1558 : PK11_DestroyContext(mHMACContext, true);
2900 1558 : mHMACContext = nsnull;
2901 : }
2902 :
2903 : /* void init (in unsigned long aAlgorithm, in nsIKeyObject aKeyObject); */
2904 1558 : NS_IMETHODIMP nsCryptoHMAC::Init(PRUint32 aAlgorithm, nsIKeyObject *aKeyObject)
2905 : {
2906 3116 : nsNSSShutDownPreventionLock locker;
2907 :
2908 1558 : if (mHMACContext)
2909 : {
2910 0 : PK11_DestroyContext(mHMACContext, true);
2911 0 : mHMACContext = nsnull;
2912 : }
2913 :
2914 : CK_MECHANISM_TYPE HMACMechType;
2915 1558 : switch (aAlgorithm)
2916 : {
2917 : case nsCryptoHMAC::MD2:
2918 0 : HMACMechType = CKM_MD2_HMAC; break;
2919 : case nsCryptoHMAC::MD5:
2920 5 : HMACMechType = CKM_MD5_HMAC; break;
2921 : case nsCryptoHMAC::SHA1:
2922 27 : HMACMechType = CKM_SHA_1_HMAC; break;
2923 : case nsCryptoHMAC::SHA256:
2924 1519 : HMACMechType = CKM_SHA256_HMAC; break;
2925 : case nsCryptoHMAC::SHA384:
2926 1 : HMACMechType = CKM_SHA384_HMAC; break;
2927 : case nsCryptoHMAC::SHA512:
2928 6 : HMACMechType = CKM_SHA512_HMAC; break;
2929 : default:
2930 0 : return NS_ERROR_INVALID_ARG;
2931 : }
2932 :
2933 1558 : NS_ENSURE_ARG_POINTER(aKeyObject);
2934 :
2935 : nsresult rv;
2936 :
2937 : PRInt16 keyType;
2938 1558 : rv = aKeyObject->GetType(&keyType);
2939 1558 : NS_ENSURE_SUCCESS(rv, rv);
2940 :
2941 1558 : NS_ENSURE_TRUE(keyType == nsIKeyObject::SYM_KEY, NS_ERROR_INVALID_ARG);
2942 :
2943 : PK11SymKey* key;
2944 : // GetKeyObj doesn't addref the key
2945 1558 : rv = aKeyObject->GetKeyObj((void**)&key);
2946 1558 : NS_ENSURE_SUCCESS(rv, rv);
2947 :
2948 : SECItem rawData;
2949 1558 : rawData.data = 0;
2950 1558 : rawData.len = 0;
2951 : mHMACContext = PK11_CreateContextBySymKey(
2952 1558 : HMACMechType, CKA_SIGN, key, &rawData);
2953 1558 : NS_ENSURE_TRUE(mHMACContext, NS_ERROR_FAILURE);
2954 :
2955 1558 : SECStatus ss = PK11_DigestBegin(mHMACContext);
2956 1558 : NS_ENSURE_TRUE(ss == SECSuccess, NS_ERROR_FAILURE);
2957 :
2958 1558 : return NS_OK;
2959 : }
2960 :
2961 : /* void update ([array, size_is (aLen), const] in octet aData, in unsigned long aLen); */
2962 22078 : NS_IMETHODIMP nsCryptoHMAC::Update(const PRUint8 *aData, PRUint32 aLen)
2963 : {
2964 44156 : nsNSSShutDownPreventionLock locker;
2965 :
2966 22078 : if (!mHMACContext)
2967 0 : return NS_ERROR_NOT_INITIALIZED;
2968 :
2969 22078 : if (!aData)
2970 0 : return NS_ERROR_INVALID_ARG;
2971 :
2972 22078 : SECStatus ss = PK11_DigestOp(mHMACContext, aData, aLen);
2973 22078 : NS_ENSURE_TRUE(ss == SECSuccess, NS_ERROR_FAILURE);
2974 :
2975 22078 : return NS_OK;
2976 : }
2977 :
2978 : /* void updateFromStream (in nsIInputStream aStream, in unsigned long aLen); */
2979 0 : NS_IMETHODIMP nsCryptoHMAC::UpdateFromStream(nsIInputStream *aStream, PRUint32 aLen)
2980 : {
2981 0 : if (!mHMACContext)
2982 0 : return NS_ERROR_NOT_INITIALIZED;
2983 :
2984 0 : if (!aStream)
2985 0 : return NS_ERROR_INVALID_ARG;
2986 :
2987 : PRUint32 n;
2988 0 : nsresult rv = aStream->Available(&n);
2989 0 : if (NS_FAILED(rv))
2990 0 : return rv;
2991 :
2992 : // if the user has passed PR_UINT32_MAX, then read
2993 : // everything in the stream
2994 :
2995 0 : if (aLen == PR_UINT32_MAX)
2996 0 : aLen = n;
2997 :
2998 : // So, if the stream has NO data available for the hash,
2999 : // or if the data available is less then what the caller
3000 : // requested, we can not fulfill the HMAC update. In this
3001 : // case, just return NS_ERROR_NOT_AVAILABLE indicating
3002 : // that there is not enough data in the stream to satisify
3003 : // the request.
3004 :
3005 0 : if (n == 0 || n < aLen)
3006 0 : return NS_ERROR_NOT_AVAILABLE;
3007 :
3008 : char buffer[NS_CRYPTO_HASH_BUFFER_SIZE];
3009 : PRUint32 read, readLimit;
3010 :
3011 0 : while(NS_SUCCEEDED(rv) && aLen > 0)
3012 : {
3013 0 : readLimit = NS_MIN(PRUint32(NS_CRYPTO_HASH_BUFFER_SIZE), aLen);
3014 :
3015 0 : rv = aStream->Read(buffer, readLimit, &read);
3016 0 : if (read == 0)
3017 0 : return NS_BASE_STREAM_CLOSED;
3018 :
3019 0 : if (NS_SUCCEEDED(rv))
3020 0 : rv = Update((const PRUint8*)buffer, read);
3021 :
3022 0 : aLen -= read;
3023 : }
3024 :
3025 0 : return rv;
3026 : }
3027 :
3028 : /* ACString finish (in bool aASCII); */
3029 22078 : NS_IMETHODIMP nsCryptoHMAC::Finish(bool aASCII, nsACString & _retval)
3030 : {
3031 44156 : nsNSSShutDownPreventionLock locker;
3032 :
3033 22078 : if (!mHMACContext)
3034 0 : return NS_ERROR_NOT_INITIALIZED;
3035 :
3036 22078 : PRUint32 hashLen = 0;
3037 : unsigned char buffer[HASH_LENGTH_MAX];
3038 22078 : unsigned char* pbuffer = buffer;
3039 :
3040 22078 : PK11_DigestFinal(mHMACContext, pbuffer, &hashLen, HASH_LENGTH_MAX);
3041 22078 : if (aASCII)
3042 : {
3043 12 : char *asciiData = BTOA_DataToAscii(buffer, hashLen);
3044 12 : NS_ENSURE_TRUE(asciiData, NS_ERROR_OUT_OF_MEMORY);
3045 :
3046 12 : _retval.Assign(asciiData);
3047 12 : PORT_Free(asciiData);
3048 : }
3049 : else
3050 : {
3051 22066 : _retval.Assign((const char*)buffer, hashLen);
3052 : }
3053 :
3054 22078 : return NS_OK;
3055 : }
3056 :
3057 : /* void reset (); */
3058 22048 : NS_IMETHODIMP nsCryptoHMAC::Reset()
3059 : {
3060 44096 : nsNSSShutDownPreventionLock locker;
3061 :
3062 22048 : SECStatus ss = PK11_DigestBegin(mHMACContext);
3063 22048 : NS_ENSURE_TRUE(ss == SECSuccess, NS_ERROR_FAILURE);
3064 :
3065 22048 : return NS_OK;
3066 : }
3067 :
3068 17265 : NS_IMPL_THREADSAFE_ISUPPORTS1(PipUIContext, nsIInterfaceRequestor)
3069 :
3070 3453 : PipUIContext::PipUIContext()
3071 : {
3072 3453 : }
3073 :
3074 6906 : PipUIContext::~PipUIContext()
3075 : {
3076 13812 : }
3077 :
3078 : /* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
3079 0 : NS_IMETHODIMP PipUIContext::GetInterface(const nsIID & uuid, void * *result)
3080 : {
3081 0 : NS_ENSURE_ARG_POINTER(result);
3082 0 : *result = nsnull;
3083 :
3084 0 : if (!NS_IsMainThread()) {
3085 0 : NS_ERROR("PipUIContext::GetInterface called off the main thread");
3086 0 : return NS_ERROR_NOT_SAME_THREAD;
3087 : }
3088 :
3089 0 : if (!uuid.Equals(NS_GET_IID(nsIPrompt)))
3090 0 : return NS_ERROR_NO_INTERFACE;
3091 :
3092 0 : nsIPrompt * prompt = nsnull;
3093 0 : nsresult rv = nsNSSComponent::GetNewPrompter(&prompt);
3094 0 : *result = prompt;
3095 0 : return rv;
3096 : }
3097 :
3098 : nsresult
3099 0 : getNSSDialogs(void **_result, REFNSIID aIID, const char *contract)
3100 : {
3101 0 : if (!NS_IsMainThread()) {
3102 0 : NS_ERROR("getNSSDialogs called off the main thread");
3103 0 : return NS_ERROR_NOT_SAME_THREAD;
3104 : }
3105 :
3106 : nsresult rv;
3107 :
3108 0 : nsCOMPtr<nsISupports> svc = do_GetService(contract, &rv);
3109 0 : if (NS_FAILED(rv))
3110 0 : return rv;
3111 :
3112 0 : rv = svc->QueryInterface(aIID, _result);
3113 :
3114 0 : return rv;
3115 : }
3116 :
3117 : nsresult
3118 339 : setPassword(PK11SlotInfo *slot, nsIInterfaceRequestor *ctx)
3119 : {
3120 678 : nsNSSShutDownPreventionLock locker;
3121 339 : nsresult rv = NS_OK;
3122 :
3123 339 : if (PK11_NeedUserInit(slot)) {
3124 : nsITokenPasswordDialogs *dialogs;
3125 : bool canceled;
3126 0 : NS_ConvertUTF8toUTF16 tokenName(PK11_GetTokenName(slot));
3127 :
3128 : rv = getNSSDialogs((void**)&dialogs,
3129 : NS_GET_IID(nsITokenPasswordDialogs),
3130 0 : NS_TOKENPASSWORDSDIALOG_CONTRACTID);
3131 :
3132 0 : if (NS_FAILED(rv)) goto loser;
3133 :
3134 : {
3135 0 : nsPSMUITracker tracker;
3136 0 : if (tracker.isUIForbidden()) {
3137 0 : rv = NS_ERROR_NOT_AVAILABLE;
3138 : }
3139 : else {
3140 : rv = dialogs->SetPassword(ctx,
3141 : tokenName.get(),
3142 0 : &canceled);
3143 : }
3144 : }
3145 0 : NS_RELEASE(dialogs);
3146 0 : if (NS_FAILED(rv)) goto loser;
3147 :
3148 0 : if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
3149 : }
3150 : loser:
3151 339 : return rv;
3152 : }
3153 :
3154 :
3155 0 : PSMContentDownloader::PSMContentDownloader(PRUint32 type)
3156 : : mByteData(nsnull),
3157 : mType(type),
3158 0 : mDoSilentDownload(false)
3159 : {
3160 0 : }
3161 :
3162 0 : PSMContentDownloader::~PSMContentDownloader()
3163 : {
3164 0 : if (mByteData)
3165 0 : nsMemory::Free(mByteData);
3166 0 : }
3167 :
3168 0 : NS_IMPL_ISUPPORTS2(PSMContentDownloader, nsIStreamListener, nsIRequestObserver)
3169 :
3170 : const PRInt32 kDefaultCertAllocLength = 2048;
3171 :
3172 : NS_IMETHODIMP
3173 0 : PSMContentDownloader::OnStartRequest(nsIRequest* request, nsISupports* context)
3174 : {
3175 : nsresult rv;
3176 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnStartRequest\n"));
3177 0 : nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
3178 0 : if (!channel) return NS_ERROR_FAILURE;
3179 :
3180 : // Get the URI //
3181 0 : channel->GetURI(getter_AddRefs(mURI));
3182 :
3183 : PRInt32 contentLength;
3184 0 : rv = channel->GetContentLength(&contentLength);
3185 0 : if (NS_FAILED(rv) || contentLength <= 0)
3186 0 : contentLength = kDefaultCertAllocLength;
3187 :
3188 0 : mBufferOffset = 0;
3189 0 : mBufferSize = 0;
3190 0 : mByteData = (char*) nsMemory::Alloc(contentLength);
3191 0 : if (!mByteData)
3192 0 : return NS_ERROR_OUT_OF_MEMORY;
3193 :
3194 0 : mBufferSize = contentLength;
3195 0 : return NS_OK;
3196 : }
3197 :
3198 : NS_IMETHODIMP
3199 0 : PSMContentDownloader::OnDataAvailable(nsIRequest* request,
3200 : nsISupports* context,
3201 : nsIInputStream *aIStream,
3202 : PRUint32 aSourceOffset,
3203 : PRUint32 aLength)
3204 : {
3205 0 : if (!mByteData)
3206 0 : return NS_ERROR_OUT_OF_MEMORY;
3207 :
3208 : PRUint32 amt;
3209 : nsresult err;
3210 : //Do a check to see if we need to allocate more memory.
3211 0 : if ((mBufferOffset + (PRInt32)aLength) > mBufferSize) {
3212 0 : size_t newSize = (mBufferOffset + aLength) *2; // grow some more than needed
3213 : char *newBuffer;
3214 0 : newBuffer = (char*)nsMemory::Realloc(mByteData, newSize);
3215 0 : if (newBuffer == nsnull) {
3216 0 : return NS_ERROR_OUT_OF_MEMORY;
3217 : }
3218 0 : mByteData = newBuffer;
3219 0 : mBufferSize = newSize;
3220 : }
3221 :
3222 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnDataAvailable\n"));
3223 0 : do {
3224 : err = aIStream->Read(mByteData+mBufferOffset,
3225 0 : aLength, &amt);
3226 0 : if (NS_FAILED(err)) return err;
3227 0 : if (amt == 0) break;
3228 :
3229 0 : aLength -= amt;
3230 0 : mBufferOffset += amt;
3231 :
3232 : } while (aLength > 0);
3233 :
3234 0 : return NS_OK;
3235 : }
3236 :
3237 : NS_IMETHODIMP
3238 0 : PSMContentDownloader::OnStopRequest(nsIRequest* request,
3239 : nsISupports* context,
3240 : nsresult aStatus)
3241 : {
3242 0 : nsNSSShutDownPreventionLock locker;
3243 : //Check if the download succeeded - it might have failed due to
3244 : //network issues, etc.
3245 0 : if (NS_FAILED(aStatus)){
3246 0 : handleContentDownloadError(aStatus);
3247 0 : return aStatus;
3248 : }
3249 :
3250 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnStopRequest\n"));
3251 :
3252 0 : nsCOMPtr<nsIX509CertDB> certdb;
3253 0 : nsCOMPtr<nsICRLManager> crlManager;
3254 :
3255 : nsresult rv;
3256 0 : nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
3257 :
3258 0 : switch (mType) {
3259 : case PSMContentDownloader::X509_CA_CERT:
3260 : case PSMContentDownloader::X509_USER_CERT:
3261 : case PSMContentDownloader::X509_EMAIL_CERT:
3262 0 : certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
3263 0 : break;
3264 :
3265 : case PSMContentDownloader::PKCS7_CRL:
3266 0 : crlManager = do_GetService(NS_CRLMANAGER_CONTRACTID);
3267 :
3268 : default:
3269 0 : break;
3270 : }
3271 :
3272 0 : switch (mType) {
3273 : case PSMContentDownloader::X509_CA_CERT:
3274 0 : return certdb->ImportCertificates((PRUint8*)mByteData, mBufferOffset, mType, ctx);
3275 : case PSMContentDownloader::X509_USER_CERT:
3276 0 : return certdb->ImportUserCertificate((PRUint8*)mByteData, mBufferOffset, ctx);
3277 : case PSMContentDownloader::X509_EMAIL_CERT:
3278 0 : return certdb->ImportEmailCertificate((PRUint8*)mByteData, mBufferOffset, ctx);
3279 : case PSMContentDownloader::PKCS7_CRL:
3280 0 : return crlManager->ImportCrl((PRUint8*)mByteData, mBufferOffset, mURI, SEC_CRL_TYPE, mDoSilentDownload, mCrlAutoDownloadKey.get());
3281 : default:
3282 0 : rv = NS_ERROR_FAILURE;
3283 : break;
3284 : }
3285 :
3286 0 : return rv;
3287 : }
3288 :
3289 :
3290 : nsresult
3291 0 : PSMContentDownloader::handleContentDownloadError(nsresult errCode)
3292 : {
3293 0 : nsString tmpMessage;
3294 : nsresult rv;
3295 0 : nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
3296 0 : if(NS_FAILED(rv)){
3297 0 : return rv;
3298 : }
3299 :
3300 : //Handling errors for crl download only, for now.
3301 0 : switch (mType){
3302 : case PSMContentDownloader::PKCS7_CRL:
3303 :
3304 : //TO DO: Handle network errors in details
3305 : //XXXXXXXXXXXXXXXXXX
3306 0 : nssComponent->GetPIPNSSBundleString("CrlImportFailureNetworkProblem", tmpMessage);
3307 :
3308 0 : if (mDoSilentDownload) {
3309 : //This is the case for automatic download. Update failure history
3310 0 : nsCAutoString updateErrCntPrefStr(CRL_AUTOUPDATE_ERRCNT_PREF);
3311 0 : nsCAutoString updateErrDetailPrefStr(CRL_AUTOUPDATE_ERRDETAIL_PREF);
3312 : PRUnichar *nameInDb;
3313 0 : nsCString errMsg;
3314 : PRInt32 errCnt;
3315 :
3316 0 : nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID,&rv);
3317 0 : if(NS_FAILED(rv)){
3318 0 : return rv;
3319 : }
3320 :
3321 0 : nameInDb = (PRUnichar *)mCrlAutoDownloadKey.get();
3322 0 : updateErrCntPrefStr.AppendWithConversion(nameInDb);
3323 0 : updateErrDetailPrefStr.AppendWithConversion(nameInDb);
3324 0 : errMsg.AssignWithConversion(tmpMessage.get());
3325 :
3326 0 : rv = pref->GetIntPref(updateErrCntPrefStr.get(),&errCnt);
3327 0 : if( (NS_FAILED(rv)) || (errCnt == 0) ){
3328 0 : pref->SetIntPref(updateErrCntPrefStr.get(),1);
3329 : }else{
3330 0 : pref->SetIntPref(updateErrCntPrefStr.get(),errCnt+1);
3331 : }
3332 0 : pref->SetCharPref(updateErrDetailPrefStr.get(),errMsg.get());
3333 0 : nsCOMPtr<nsIPrefService> prefSvc(do_QueryInterface(pref));
3334 0 : prefSvc->SavePrefFile(nsnull);
3335 : }else{
3336 0 : nsString message;
3337 0 : nssComponent->GetPIPNSSBundleString("CrlImportFailure1x", message);
3338 0 : message.Append(NS_LITERAL_STRING("\n").get());
3339 0 : message.Append(tmpMessage);
3340 0 : nssComponent->GetPIPNSSBundleString("CrlImportFailure2", tmpMessage);
3341 0 : message.Append(NS_LITERAL_STRING("\n").get());
3342 0 : message.Append(tmpMessage);
3343 0 : nsNSSComponent::ShowAlertWithConstructedString(message);
3344 : }
3345 0 : break;
3346 : default:
3347 0 : break;
3348 : }
3349 :
3350 0 : return NS_OK;
3351 :
3352 : }
3353 :
3354 : void
3355 0 : PSMContentDownloader::setSilentDownload(bool flag)
3356 : {
3357 0 : mDoSilentDownload = flag;
3358 0 : }
3359 :
3360 : void
3361 0 : PSMContentDownloader::setCrlAutodownloadKey(nsAutoString key)
3362 : {
3363 0 : mCrlAutoDownloadKey = key;
3364 0 : }
3365 :
3366 :
3367 : /* other mime types that we should handle sometime:
3368 :
3369 : application/x-pkcs7-crl
3370 : application/x-pkcs7-mime
3371 : application/pkcs7-signature
3372 : application/pre-encrypted
3373 :
3374 : */
3375 :
3376 : PRUint32
3377 0 : getPSMContentType(const char * aContentType)
3378 : {
3379 : // Don't forget to update RegisterPSMContentListeners in nsNSSModule.cpp
3380 : // for every supported content type.
3381 :
3382 0 : if (!nsCRT::strcasecmp(aContentType, "application/x-x509-ca-cert"))
3383 0 : return PSMContentDownloader::X509_CA_CERT;
3384 0 : else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-server-cert"))
3385 0 : return PSMContentDownloader::X509_SERVER_CERT;
3386 0 : else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-user-cert"))
3387 0 : return PSMContentDownloader::X509_USER_CERT;
3388 0 : else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-email-cert"))
3389 0 : return PSMContentDownloader::X509_EMAIL_CERT;
3390 0 : else if (!nsCRT::strcasecmp(aContentType, "application/x-pkcs7-crl"))
3391 0 : return PSMContentDownloader::PKCS7_CRL;
3392 0 : else if (!nsCRT::strcasecmp(aContentType, "application/x-x509-crl"))
3393 0 : return PSMContentDownloader::PKCS7_CRL;
3394 0 : else if (!nsCRT::strcasecmp(aContentType, "application/pkix-crl"))
3395 0 : return PSMContentDownloader::PKCS7_CRL;
3396 0 : return PSMContentDownloader::UNKNOWN_TYPE;
3397 : }
3398 :
3399 :
3400 4592 : NS_IMPL_ISUPPORTS2(PSMContentListener,
3401 : nsIURIContentListener,
3402 : nsISupportsWeakReference)
3403 :
3404 328 : PSMContentListener::PSMContentListener()
3405 : {
3406 328 : mLoadCookie = nsnull;
3407 328 : mParentContentListener = nsnull;
3408 328 : }
3409 :
3410 656 : PSMContentListener::~PSMContentListener()
3411 : {
3412 1312 : }
3413 :
3414 : nsresult
3415 328 : PSMContentListener::init()
3416 : {
3417 328 : return NS_OK;
3418 : }
3419 :
3420 : NS_IMETHODIMP
3421 0 : PSMContentListener::OnStartURIOpen(nsIURI *aURI, bool *aAbortOpen)
3422 : {
3423 : //if we don't want to handle the URI, return true in
3424 : //*aAbortOpen
3425 0 : return NS_OK;
3426 : }
3427 :
3428 : NS_IMETHODIMP
3429 0 : PSMContentListener::IsPreferred(const char * aContentType,
3430 : char ** aDesiredContentType,
3431 : bool * aCanHandleContent)
3432 : {
3433 : return CanHandleContent(aContentType, true,
3434 0 : aDesiredContentType, aCanHandleContent);
3435 : }
3436 :
3437 : NS_IMETHODIMP
3438 0 : PSMContentListener::CanHandleContent(const char * aContentType,
3439 : bool aIsContentPreferred,
3440 : char ** aDesiredContentType,
3441 : bool * aCanHandleContent)
3442 : {
3443 : PRUint32 type;
3444 0 : type = getPSMContentType(aContentType);
3445 0 : if (type == PSMContentDownloader::UNKNOWN_TYPE) {
3446 0 : *aCanHandleContent = false;
3447 : } else {
3448 0 : *aCanHandleContent = true;
3449 : }
3450 0 : return NS_OK;
3451 : }
3452 :
3453 : NS_IMETHODIMP
3454 0 : PSMContentListener::DoContent(const char * aContentType,
3455 : bool aIsContentPreferred,
3456 : nsIRequest * aRequest,
3457 : nsIStreamListener ** aContentHandler,
3458 : bool * aAbortProcess)
3459 : {
3460 : PSMContentDownloader *downLoader;
3461 : PRUint32 type;
3462 0 : type = getPSMContentType(aContentType);
3463 0 : PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("PSMContentListener::DoContent\n"));
3464 0 : if (type != PSMContentDownloader::UNKNOWN_TYPE) {
3465 0 : downLoader = new PSMContentDownloader(type);
3466 0 : if (downLoader) {
3467 : downLoader->QueryInterface(NS_GET_IID(nsIStreamListener),
3468 0 : (void **)aContentHandler);
3469 0 : return NS_OK;
3470 : }
3471 : }
3472 0 : return NS_ERROR_FAILURE;
3473 : }
3474 :
3475 : NS_IMETHODIMP
3476 0 : PSMContentListener::GetLoadCookie(nsISupports * *aLoadCookie)
3477 : {
3478 0 : *aLoadCookie = mLoadCookie;
3479 0 : NS_IF_ADDREF(*aLoadCookie);
3480 0 : return NS_OK;
3481 : }
3482 :
3483 : NS_IMETHODIMP
3484 0 : PSMContentListener::SetLoadCookie(nsISupports * aLoadCookie)
3485 : {
3486 0 : mLoadCookie = aLoadCookie;
3487 0 : return NS_OK;
3488 : }
3489 :
3490 : NS_IMETHODIMP
3491 0 : PSMContentListener::GetParentContentListener(nsIURIContentListener ** aContentListener)
3492 : {
3493 0 : *aContentListener = mParentContentListener;
3494 0 : NS_IF_ADDREF(*aContentListener);
3495 0 : return NS_OK;
3496 : }
3497 :
3498 : NS_IMETHODIMP
3499 0 : PSMContentListener::SetParentContentListener(nsIURIContentListener * aContentListener)
3500 : {
3501 0 : mParentContentListener = aContentListener;
3502 0 : return NS_OK;
3503 : }
|