PageRenderTime 57ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/security/manager/ssl/src/nsNSSComponent.cpp

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