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

http://github.com/zpao/v8monkey · C++ · 3481 lines · 2587 code · 585 blank · 309 comment · 455 complexity · 66116bc7232cc97e1ff3ed29287b7653 MD5 · raw file

Large files are truncated click here to view the full file

  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_Ad