PageRenderTime 61ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/security/manager/ssl/src/nsNSSIOLayer.cpp

https://bitbucket.org/mkato/mozilla-1.9.0-win64
C++ | 3242 lines | 2434 code | 468 blank | 340 comment | 443 complexity | 85f34f69be218a96b3bcbf7f71e14f1d MD5 | raw file
Possible License(s): LGPL-3.0, MIT, BSD-3-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.1
  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. * Brian Ryner <bryner@brianryner.com>
  25. * Javier Delgadillo <javi@netscape.com>
  26. * Kai Engert <kengert@redhat.com>
  27. *
  28. * Alternatively, the contents of this file may be used under the terms of
  29. * either the GNU General Public License Version 2 or later (the "GPL"), or
  30. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  31. * in which case the provisions of the GPL or the LGPL are applicable instead
  32. * of those above. If you wish to allow use of your version of this file only
  33. * under the terms of either the GPL or the LGPL, and not to allow others to
  34. * use your version of this file under the terms of the MPL, indicate your
  35. * decision by deleting the provisions above and replace them with the notice
  36. * and other provisions required by the GPL or the LGPL. If you do not delete
  37. * the provisions above, a recipient may use your version of this file under
  38. * the terms of any one of the MPL, the GPL or the LGPL.
  39. *
  40. * ***** END LICENSE BLOCK ***** */
  41. #include "nsNSSComponent.h"
  42. #include "nsNSSIOLayer.h"
  43. #include "nsNSSCallbacks.h"
  44. #include "prlog.h"
  45. #include "prnetdb.h"
  46. #include "nsIPrompt.h"
  47. #include "nsIPrefService.h"
  48. #include "nsIPrefBranch.h"
  49. #include "nsIServiceManager.h"
  50. #include "nsIWebProgressListener.h"
  51. #include "nsIChannel.h"
  52. #include "nsNSSCertificate.h"
  53. #include "nsIX509CertValidity.h"
  54. #include "nsIProxyObjectManager.h"
  55. #include "nsProxiedService.h"
  56. #include "nsIDateTimeFormat.h"
  57. #include "nsDateTimeFormatCID.h"
  58. #include "nsIClientAuthDialogs.h"
  59. #include "nsICertOverrideService.h"
  60. #include "nsIBadCertListener2.h"
  61. #include "nsISSLErrorListener.h"
  62. #include "nsIObjectInputStream.h"
  63. #include "nsIObjectOutputStream.h"
  64. #include "nsRecentBadCerts.h"
  65. #include "nsXPIDLString.h"
  66. #include "nsReadableUtils.h"
  67. #include "nsHashSets.h"
  68. #include "nsCRT.h"
  69. #include "nsAutoPtr.h"
  70. #include "nsPrintfCString.h"
  71. #include "nsAutoLock.h"
  72. #include "nsSSLThread.h"
  73. #include "nsNSSShutDown.h"
  74. #include "nsSSLStatus.h"
  75. #include "nsNSSCertHelper.h"
  76. #include "nsNSSCleaner.h"
  77. #include "nsThreadUtils.h"
  78. #include "nsIDocShell.h"
  79. #include "nsIDocShellTreeItem.h"
  80. #include "nsISecureBrowserUI.h"
  81. #include "nsProxyRelease.h"
  82. #include "nsIClassInfoImpl.h"
  83. #include "nsIProgrammingLanguage.h"
  84. #include "ssl.h"
  85. #include "secerr.h"
  86. #include "sslerr.h"
  87. #include "secder.h"
  88. #include "secasn1.h"
  89. #include "certdb.h"
  90. #include "cert.h"
  91. #include "keyhi.h"
  92. #include "secport.h"
  93. //#define DEBUG_SSL_VERBOSE //Enable this define to get minimal
  94. //reports when doing SSL read/write
  95. //#define DUMP_BUFFER //Enable this define along with
  96. //DEBUG_SSL_VERBOSE to dump SSL
  97. //read/write buffer to a log.
  98. //Uses PR_LOG except on Mac where
  99. //we always write out to our own
  100. //file.
  101. NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
  102. NSSCleanupAutoPtrClass(char, PR_FREEIF)
  103. NSSCleanupAutoPtrClass_WithParam(PRArenaPool, PORT_FreeArena, FalseParam, PR_FALSE)
  104. /* SSM_UserCertChoice: enum for cert choice info */
  105. typedef enum {ASK, AUTO} SSM_UserCertChoice;
  106. static SECStatus PR_CALLBACK
  107. nsNSS_SSLGetClientAuthData(void *arg, PRFileDesc *socket,
  108. CERTDistNames *caNames,
  109. CERTCertificate **pRetCert,
  110. SECKEYPrivateKey **pRetKey);
  111. static SECStatus PR_CALLBACK
  112. nsNSS_SSLGetClientAuthData(void *arg, PRFileDesc *socket,
  113. CERTDistNames *caNames,
  114. CERTCertificate **pRetCert,
  115. SECKEYPrivateKey **pRetKey);
  116. #ifdef PR_LOGGING
  117. extern PRLogModuleInfo* gPIPNSSLog;
  118. #endif
  119. #if defined(DEBUG_SSL_VERBOSE) && defined (XP_MAC)
  120. #ifdef PR_LOG
  121. #undef PR_LOG
  122. #endif
  123. static PRFileDesc *gMyLogFile = nsnull;
  124. #define MAC_LOG_FILE "MAC PIPNSS Log File"
  125. void MyLogFunction(const char *fmt, ...)
  126. {
  127. va_list ap;
  128. va_start(ap,fmt);
  129. if (gMyLogFile == nsnull)
  130. gMyLogFile = PR_Open(MAC_LOG_FILE, PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
  131. 0600);
  132. if (!gMyLogFile)
  133. return;
  134. PR_vfprintf(gMyLogFile, fmt, ap);
  135. va_end(ap);
  136. }
  137. #define PR_LOG(module,level,args) MyLogFunction args
  138. #endif
  139. nsSSLSocketThreadData::nsSSLSocketThreadData()
  140. : mSSLState(ssl_idle)
  141. , mPRErrorCode(PR_SUCCESS)
  142. , mSSLDataBuffer(nsnull)
  143. , mSSLDataBufferAllocatedSize(0)
  144. , mSSLRequestedTransferAmount(0)
  145. , mSSLRemainingReadResultData(nsnull)
  146. , mSSLResultRemainingBytes(0)
  147. , mReplacedSSLFileDesc(nsnull)
  148. , mOneBytePendingFromEarlierWrite(PR_FALSE)
  149. , mThePendingByte(0)
  150. , mOriginalRequestedTransferAmount(0)
  151. {
  152. }
  153. nsSSLSocketThreadData::~nsSSLSocketThreadData()
  154. {
  155. NS_ASSERTION(mSSLState != ssl_pending_write
  156. &&
  157. mSSLState != ssl_pending_read,
  158. "oops??? ssl socket is not idle at the time it is being destroyed");
  159. if (mSSLDataBuffer) {
  160. nsMemory::Free(mSSLDataBuffer);
  161. }
  162. }
  163. PRBool nsSSLSocketThreadData::ensure_buffer_size(PRInt32 amount)
  164. {
  165. if (amount > mSSLDataBufferAllocatedSize) {
  166. if (mSSLDataBuffer) {
  167. mSSLDataBuffer = (char*)nsMemory::Realloc(mSSLDataBuffer, amount);
  168. }
  169. else {
  170. mSSLDataBuffer = (char*)nsMemory::Alloc(amount);
  171. }
  172. if (!mSSLDataBuffer)
  173. return PR_FALSE;
  174. mSSLDataBufferAllocatedSize = amount;
  175. }
  176. return PR_TRUE;
  177. }
  178. nsNSSSocketInfo::nsNSSSocketInfo()
  179. : mFd(nsnull),
  180. mBlockingState(blocking_state_unknown),
  181. mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE),
  182. mSubRequestsHighSecurity(0),
  183. mSubRequestsLowSecurity(0),
  184. mSubRequestsBrokenSecurity(0),
  185. mSubRequestsNoSecurity(0),
  186. mDocShellDependentStuffKnown(PR_FALSE),
  187. mExternalErrorReporting(PR_FALSE),
  188. mForSTARTTLS(PR_FALSE),
  189. mHandshakePending(PR_TRUE),
  190. mCanceled(PR_FALSE),
  191. mHasCleartextPhase(PR_FALSE),
  192. mHandshakeInProgress(PR_FALSE),
  193. mAllowTLSIntoleranceTimeout(PR_TRUE),
  194. mHandshakeStartTime(0),
  195. mPort(0)
  196. {
  197. mThreadData = new nsSSLSocketThreadData;
  198. }
  199. nsNSSSocketInfo::~nsNSSSocketInfo()
  200. {
  201. delete mThreadData;
  202. nsNSSShutDownPreventionLock locker;
  203. if (isAlreadyShutDown())
  204. return;
  205. shutdown(calledFromObject);
  206. }
  207. void nsNSSSocketInfo::virtualDestroyNSSReference()
  208. {
  209. }
  210. NS_IMPL_THREADSAFE_ISUPPORTS8(nsNSSSocketInfo,
  211. nsITransportSecurityInfo,
  212. nsISSLSocketControl,
  213. nsIInterfaceRequestor,
  214. nsISSLStatusProvider,
  215. nsIIdentityInfo,
  216. nsIAssociatedContentSecurity,
  217. nsISerializable,
  218. nsIClassInfo)
  219. nsresult
  220. nsNSSSocketInfo::GetHandshakePending(PRBool *aHandshakePending)
  221. {
  222. *aHandshakePending = mHandshakePending;
  223. return NS_OK;
  224. }
  225. nsresult
  226. nsNSSSocketInfo::SetHandshakePending(PRBool aHandshakePending)
  227. {
  228. mHandshakePending = aHandshakePending;
  229. return NS_OK;
  230. }
  231. nsresult
  232. nsNSSSocketInfo::SetHostName(const char* host)
  233. {
  234. mHostName.Adopt(host ? nsCRT::strdup(host) : 0);
  235. return NS_OK;
  236. }
  237. nsresult
  238. nsNSSSocketInfo::GetHostName(char **host)
  239. {
  240. *host = (mHostName) ? nsCRT::strdup(mHostName) : nsnull;
  241. return NS_OK;
  242. }
  243. nsresult
  244. nsNSSSocketInfo::SetPort(PRInt32 aPort)
  245. {
  246. mPort = aPort;
  247. return NS_OK;
  248. }
  249. nsresult
  250. nsNSSSocketInfo::GetPort(PRInt32 *aPort)
  251. {
  252. *aPort = mPort;
  253. return NS_OK;
  254. }
  255. void nsNSSSocketInfo::SetCanceled(PRBool aCanceled)
  256. {
  257. mCanceled = aCanceled;
  258. }
  259. PRBool nsNSSSocketInfo::GetCanceled()
  260. {
  261. return mCanceled;
  262. }
  263. void nsNSSSocketInfo::SetHasCleartextPhase(PRBool aHasCleartextPhase)
  264. {
  265. mHasCleartextPhase = aHasCleartextPhase;
  266. }
  267. PRBool nsNSSSocketInfo::GetHasCleartextPhase()
  268. {
  269. return mHasCleartextPhase;
  270. }
  271. NS_IMETHODIMP
  272. nsNSSSocketInfo::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks)
  273. {
  274. *aCallbacks = mCallbacks;
  275. NS_IF_ADDREF(*aCallbacks);
  276. return NS_OK;
  277. }
  278. NS_IMETHODIMP
  279. nsNSSSocketInfo::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
  280. {
  281. if (!aCallbacks) {
  282. mCallbacks = nsnull;
  283. return NS_OK;
  284. }
  285. mCallbacks = aCallbacks;
  286. mDocShellDependentStuffKnown = PR_FALSE;
  287. return NS_OK;
  288. }
  289. nsresult
  290. nsNSSSocketInfo::EnsureDocShellDependentStuffKnown()
  291. {
  292. if (mDocShellDependentStuffKnown)
  293. return NS_OK;
  294. if (!mCallbacks || nsSSLThread::exitRequested())
  295. return NS_ERROR_FAILURE;
  296. mDocShellDependentStuffKnown = PR_TRUE;
  297. nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks;
  298. NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
  299. NS_GET_IID(nsIInterfaceRequestor),
  300. static_cast<nsIInterfaceRequestor*>(mCallbacks),
  301. NS_PROXY_SYNC,
  302. getter_AddRefs(proxiedCallbacks));
  303. // Are we running within a context that wants external SSL error reporting?
  304. // We'll look at the presence of a security UI object inside docshell.
  305. // If the docshell wants the lock icon, you'll get the ssl error pages, too.
  306. // This is helpful to distinguish from all other contexts, like mail windows,
  307. // or any other SSL connections running in the background.
  308. // We must query it now and remember, because fatal SSL errors will come
  309. // with a socket close, and the socket transport might detach the callbacks
  310. // instance prior to our error reporting.
  311. nsCOMPtr<nsIDocShell> docshell;
  312. nsCOMPtr<nsIDocShellTreeItem> item(do_GetInterface(proxiedCallbacks));
  313. if (item)
  314. {
  315. nsCOMPtr<nsIDocShellTreeItem> proxiedItem;
  316. nsCOMPtr<nsIDocShellTreeItem> rootItem;
  317. NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
  318. NS_GET_IID(nsIDocShellTreeItem),
  319. item.get(),
  320. NS_PROXY_SYNC,
  321. getter_AddRefs(proxiedItem));
  322. proxiedItem->GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
  323. docshell = do_QueryInterface(rootItem);
  324. NS_ASSERTION(docshell, "rootItem do_QI is null");
  325. }
  326. if (docshell)
  327. {
  328. nsCOMPtr<nsIDocShell> proxiedDocShell;
  329. NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
  330. NS_GET_IID(nsIDocShell),
  331. docshell.get(),
  332. NS_PROXY_SYNC,
  333. getter_AddRefs(proxiedDocShell));
  334. nsISecureBrowserUI* secureUI = nsnull;
  335. if (proxiedDocShell)
  336. proxiedDocShell->GetSecurityUI(&secureUI);
  337. if (secureUI)
  338. {
  339. nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
  340. NS_ProxyRelease(mainThread, secureUI, PR_FALSE);
  341. mExternalErrorReporting = PR_TRUE;
  342. // If this socket is associated to a docshell, let's try to remember
  343. // the currently used cert. If this socket gets a notification from NSS
  344. // having the same raw socket, we can keep the PSM wrapper object
  345. // and all the data it has cached (like verification results).
  346. nsCOMPtr<nsISSLStatusProvider> statprov = do_QueryInterface(secureUI);
  347. if (statprov) {
  348. nsCOMPtr<nsISupports> isup_stat;
  349. statprov->GetSSLStatus(getter_AddRefs(isup_stat));
  350. if (isup_stat) {
  351. nsCOMPtr<nsISSLStatus> sslstat = do_QueryInterface(isup_stat);
  352. if (sslstat) {
  353. sslstat->GetServerCert(getter_AddRefs(mPreviousCert));
  354. }
  355. }
  356. }
  357. }
  358. }
  359. return NS_OK;
  360. }
  361. nsresult
  362. nsNSSSocketInfo::GetExternalErrorReporting(PRBool* state)
  363. {
  364. nsresult rv = EnsureDocShellDependentStuffKnown();
  365. NS_ENSURE_SUCCESS(rv, rv);
  366. *state = mExternalErrorReporting;
  367. return NS_OK;
  368. }
  369. nsresult
  370. nsNSSSocketInfo::SetExternalErrorReporting(PRBool aState)
  371. {
  372. mExternalErrorReporting = aState;
  373. return NS_OK;
  374. }
  375. NS_IMETHODIMP
  376. nsNSSSocketInfo::GetSecurityState(PRUint32* state)
  377. {
  378. *state = mSecurityState;
  379. return NS_OK;
  380. }
  381. nsresult
  382. nsNSSSocketInfo::SetSecurityState(PRUint32 aState)
  383. {
  384. mSecurityState = aState;
  385. return NS_OK;
  386. }
  387. /* attribute unsigned long countSubRequestsHighSecurity; */
  388. NS_IMETHODIMP nsNSSSocketInfo::GetCountSubRequestsHighSecurity(PRInt32 *aSubRequestsHighSecurity)
  389. {
  390. *aSubRequestsHighSecurity = mSubRequestsHighSecurity;
  391. return NS_OK;
  392. }
  393. NS_IMETHODIMP nsNSSSocketInfo::SetCountSubRequestsHighSecurity(PRInt32 aSubRequestsHighSecurity)
  394. {
  395. mSubRequestsHighSecurity = aSubRequestsHighSecurity;
  396. return NS_ERROR_NOT_IMPLEMENTED;
  397. }
  398. /* attribute unsigned long countSubRequestsLowSecurity; */
  399. NS_IMETHODIMP nsNSSSocketInfo::GetCountSubRequestsLowSecurity(PRInt32 *aSubRequestsLowSecurity)
  400. {
  401. *aSubRequestsLowSecurity = mSubRequestsLowSecurity;
  402. return NS_OK;
  403. }
  404. NS_IMETHODIMP nsNSSSocketInfo::SetCountSubRequestsLowSecurity(PRInt32 aSubRequestsLowSecurity)
  405. {
  406. mSubRequestsLowSecurity = aSubRequestsLowSecurity;
  407. return NS_OK;
  408. }
  409. /* attribute unsigned long countSubRequestsBrokenSecurity; */
  410. NS_IMETHODIMP nsNSSSocketInfo::GetCountSubRequestsBrokenSecurity(PRInt32 *aSubRequestsBrokenSecurity)
  411. {
  412. *aSubRequestsBrokenSecurity = mSubRequestsBrokenSecurity;
  413. return NS_OK;
  414. }
  415. NS_IMETHODIMP nsNSSSocketInfo::SetCountSubRequestsBrokenSecurity(PRInt32 aSubRequestsBrokenSecurity)
  416. {
  417. mSubRequestsBrokenSecurity = aSubRequestsBrokenSecurity;
  418. return NS_OK;
  419. }
  420. /* attribute unsigned long countSubRequestsNoSecurity; */
  421. NS_IMETHODIMP nsNSSSocketInfo::GetCountSubRequestsNoSecurity(PRInt32 *aSubRequestsNoSecurity)
  422. {
  423. *aSubRequestsNoSecurity = mSubRequestsNoSecurity;
  424. return NS_OK;
  425. }
  426. NS_IMETHODIMP nsNSSSocketInfo::SetCountSubRequestsNoSecurity(PRInt32 aSubRequestsNoSecurity)
  427. {
  428. mSubRequestsNoSecurity = aSubRequestsNoSecurity;
  429. return NS_OK;
  430. }
  431. NS_IMETHODIMP
  432. nsNSSSocketInfo::GetShortSecurityDescription(PRUnichar** aText) {
  433. if (mShortDesc.IsEmpty())
  434. *aText = nsnull;
  435. else {
  436. *aText = ToNewUnicode(mShortDesc);
  437. NS_ENSURE_TRUE(*aText, NS_ERROR_OUT_OF_MEMORY);
  438. }
  439. return NS_OK;
  440. }
  441. nsresult
  442. nsNSSSocketInfo::SetShortSecurityDescription(const PRUnichar* aText) {
  443. mShortDesc.Assign(aText);
  444. return NS_OK;
  445. }
  446. NS_IMETHODIMP
  447. nsNSSSocketInfo::GetErrorMessage(PRUnichar** aText) {
  448. if (mErrorMessage.IsEmpty())
  449. *aText = nsnull;
  450. else {
  451. *aText = ToNewUnicode(mErrorMessage);
  452. NS_ENSURE_TRUE(*aText, NS_ERROR_OUT_OF_MEMORY);
  453. }
  454. return NS_OK;
  455. }
  456. nsresult
  457. nsNSSSocketInfo::SetErrorMessage(const PRUnichar* aText) {
  458. mErrorMessage.Assign(aText);
  459. return NS_OK;
  460. }
  461. /* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
  462. NS_IMETHODIMP nsNSSSocketInfo::GetInterface(const nsIID & uuid, void * *result)
  463. {
  464. nsresult rv;
  465. if (!mCallbacks) {
  466. nsCOMPtr<nsIInterfaceRequestor> ir = new PipUIContext();
  467. if (!ir)
  468. return NS_ERROR_OUT_OF_MEMORY;
  469. rv = ir->GetInterface(uuid, result);
  470. } else {
  471. if (nsSSLThread::exitRequested())
  472. return NS_ERROR_FAILURE;
  473. nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks;
  474. NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
  475. NS_GET_IID(nsIInterfaceRequestor),
  476. mCallbacks,
  477. NS_PROXY_SYNC,
  478. getter_AddRefs(proxiedCallbacks));
  479. rv = proxiedCallbacks->GetInterface(uuid, result);
  480. }
  481. return rv;
  482. }
  483. nsresult
  484. nsNSSSocketInfo::GetForSTARTTLS(PRBool* aForSTARTTLS)
  485. {
  486. *aForSTARTTLS = mForSTARTTLS;
  487. return NS_OK;
  488. }
  489. nsresult
  490. nsNSSSocketInfo::SetForSTARTTLS(PRBool aForSTARTTLS)
  491. {
  492. mForSTARTTLS = aForSTARTTLS;
  493. return NS_OK;
  494. }
  495. NS_IMETHODIMP
  496. nsNSSSocketInfo::ProxyStartSSL()
  497. {
  498. return ActivateSSL();
  499. }
  500. NS_IMETHODIMP
  501. nsNSSSocketInfo::StartTLS()
  502. {
  503. return ActivateSSL();
  504. }
  505. NS_IMETHODIMP
  506. nsNSSSocketInfo::Write(nsIObjectOutputStream* stream) {
  507. stream->WriteCompoundObject(NS_ISUPPORTS_CAST(nsIX509Cert*, mCert),
  508. NS_GET_IID(nsISupports), PR_TRUE);
  509. stream->Write32(mSecurityState);
  510. stream->WriteWStringZ(mShortDesc.get());
  511. stream->WriteWStringZ(mErrorMessage.get());
  512. stream->WriteCompoundObject(NS_ISUPPORTS_CAST(nsISSLStatus*, mSSLStatus),
  513. NS_GET_IID(nsISupports), PR_TRUE);
  514. return NS_OK;
  515. }
  516. NS_IMETHODIMP
  517. nsNSSSocketInfo::Read(nsIObjectInputStream* stream) {
  518. nsCOMPtr<nsISupports> obj;
  519. stream->ReadObject(PR_TRUE, getter_AddRefs(obj));
  520. mCert = reinterpret_cast<nsNSSCertificate*>(obj.get());
  521. stream->Read32(&mSecurityState);
  522. stream->ReadString(mShortDesc);
  523. stream->ReadString(mErrorMessage);
  524. stream->ReadObject(PR_TRUE, getter_AddRefs(obj));
  525. mSSLStatus = reinterpret_cast<nsSSLStatus*>(obj.get());
  526. return NS_OK;
  527. }
  528. NS_IMETHODIMP
  529. nsNSSSocketInfo::GetInterfaces(PRUint32 *count, nsIID * **array)
  530. {
  531. *count = 0;
  532. *array = nsnull;
  533. return NS_OK;
  534. }
  535. NS_IMETHODIMP
  536. nsNSSSocketInfo::GetHelperForLanguage(PRUint32 language, nsISupports **_retval)
  537. {
  538. *_retval = nsnull;
  539. return NS_OK;
  540. }
  541. NS_IMETHODIMP
  542. nsNSSSocketInfo::GetContractID(char * *aContractID)
  543. {
  544. *aContractID = nsnull;
  545. return NS_OK;
  546. }
  547. NS_IMETHODIMP
  548. nsNSSSocketInfo::GetClassDescription(char * *aClassDescription)
  549. {
  550. *aClassDescription = nsnull;
  551. return NS_OK;
  552. }
  553. NS_IMETHODIMP
  554. nsNSSSocketInfo::GetClassID(nsCID * *aClassID)
  555. {
  556. *aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
  557. if (!*aClassID)
  558. return NS_ERROR_OUT_OF_MEMORY;
  559. return GetClassIDNoAlloc(*aClassID);
  560. }
  561. NS_IMETHODIMP
  562. nsNSSSocketInfo::GetImplementationLanguage(PRUint32 *aImplementationLanguage)
  563. {
  564. *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  565. return NS_OK;
  566. }
  567. NS_IMETHODIMP
  568. nsNSSSocketInfo::GetFlags(PRUint32 *aFlags)
  569. {
  570. *aFlags = 0;
  571. return NS_OK;
  572. }
  573. static NS_DEFINE_CID(kNSSSocketInfoCID, NS_NSSSOCKETINFO_CID);
  574. NS_IMETHODIMP
  575. nsNSSSocketInfo::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  576. {
  577. *aClassIDNoAlloc = kNSSSocketInfoCID;
  578. return NS_OK;
  579. }
  580. nsresult nsNSSSocketInfo::ActivateSSL()
  581. {
  582. nsNSSShutDownPreventionLock locker;
  583. if (isAlreadyShutDown())
  584. return NS_ERROR_NOT_AVAILABLE;
  585. nsresult rv = nsSSLThread::requestActivateSSL(this);
  586. if (NS_FAILED(rv))
  587. return rv;
  588. mHandshakePending = PR_TRUE;
  589. return NS_OK;
  590. }
  591. nsresult nsNSSSocketInfo::GetFileDescPtr(PRFileDesc** aFilePtr)
  592. {
  593. *aFilePtr = mFd;
  594. return NS_OK;
  595. }
  596. nsresult nsNSSSocketInfo::SetFileDescPtr(PRFileDesc* aFilePtr)
  597. {
  598. mFd = aFilePtr;
  599. return NS_OK;
  600. }
  601. nsresult nsNSSSocketInfo::GetPreviousCert(nsIX509Cert** _result)
  602. {
  603. NS_ENSURE_ARG_POINTER(_result);
  604. nsresult rv = EnsureDocShellDependentStuffKnown();
  605. NS_ENSURE_SUCCESS(rv, rv);
  606. *_result = mPreviousCert;
  607. NS_IF_ADDREF(*_result);
  608. return NS_OK;
  609. }
  610. nsresult nsNSSSocketInfo::GetCert(nsIX509Cert** _result)
  611. {
  612. NS_ENSURE_ARG_POINTER(_result);
  613. *_result = mCert;
  614. NS_IF_ADDREF(*_result);
  615. return NS_OK;
  616. }
  617. nsresult nsNSSSocketInfo::SetCert(nsIX509Cert *aCert)
  618. {
  619. mCert = aCert;
  620. return NS_OK;
  621. }
  622. nsresult nsNSSSocketInfo::GetSSLStatus(nsISupports** _result)
  623. {
  624. NS_ENSURE_ARG_POINTER(_result);
  625. *_result = NS_ISUPPORTS_CAST(nsISSLStatus*, mSSLStatus);
  626. NS_IF_ADDREF(*_result);
  627. return NS_OK;
  628. }
  629. nsresult nsNSSSocketInfo::SetSSLStatus(nsSSLStatus *aSSLStatus)
  630. {
  631. mSSLStatus = aSSLStatus;
  632. return NS_OK;
  633. }
  634. void nsNSSSocketInfo::SetHandshakeInProgress(PRBool aIsIn)
  635. {
  636. mHandshakeInProgress = aIsIn;
  637. if (mHandshakeInProgress && !mHandshakeStartTime)
  638. {
  639. mHandshakeStartTime = PR_IntervalNow();
  640. }
  641. }
  642. void nsNSSSocketInfo::SetAllowTLSIntoleranceTimeout(PRBool aAllow)
  643. {
  644. mAllowTLSIntoleranceTimeout = aAllow;
  645. }
  646. #define HANDSHAKE_TIMEOUT_SECONDS 25
  647. PRBool nsNSSSocketInfo::HandshakeTimeout()
  648. {
  649. if (!mHandshakeInProgress || !mAllowTLSIntoleranceTimeout)
  650. return PR_FALSE;
  651. return ((PRIntervalTime)(PR_IntervalNow() - mHandshakeStartTime)
  652. > PR_SecondsToInterval(HANDSHAKE_TIMEOUT_SECONDS));
  653. }
  654. void nsSSLIOLayerHelpers::Cleanup()
  655. {
  656. if (mTLSIntolerantSites) {
  657. delete mTLSIntolerantSites;
  658. mTLSIntolerantSites = nsnull;
  659. }
  660. if (mSharedPollableEvent)
  661. PR_DestroyPollableEvent(mSharedPollableEvent);
  662. if (mutex) {
  663. PR_DestroyLock(mutex);
  664. mutex = nsnull;
  665. }
  666. }
  667. static nsresult
  668. getErrorMessage(PRInt32 err,
  669. const nsString &host,
  670. PRInt32 port,
  671. PRBool externalErrorReporting,
  672. nsINSSComponent *component,
  673. nsString &returnedMessage)
  674. {
  675. NS_ENSURE_ARG_POINTER(component);
  676. const PRUnichar *params[1];
  677. nsresult rv;
  678. if (host.Length())
  679. {
  680. nsString hostWithPort;
  681. // For now, hide port when it's 443 and we're reporting the error using
  682. // external reporting. In the future a better mechanism should be used
  683. // to make a decision about showing the port number, possibly by requiring
  684. // the context object to implement a specific interface.
  685. // The motivation is that Mozilla browser would like to hide the port number
  686. // in error pages in the common case.
  687. if (externalErrorReporting && port == 443) {
  688. params[0] = host.get();
  689. }
  690. else {
  691. hostWithPort = host;
  692. hostWithPort.AppendLiteral(":");
  693. hostWithPort.AppendInt(port);
  694. params[0] = hostWithPort.get();
  695. }
  696. nsString formattedString;
  697. rv = component->PIPBundleFormatStringFromName("SSLConnectionErrorPrefix",
  698. params, 1,
  699. formattedString);
  700. if (NS_SUCCEEDED(rv))
  701. {
  702. returnedMessage.Append(formattedString);
  703. returnedMessage.Append(NS_LITERAL_STRING("\n\n"));
  704. }
  705. }
  706. nsString explanation;
  707. rv = nsNSSErrors::getErrorMessageFromCode(err, component, explanation);
  708. if (NS_SUCCEEDED(rv))
  709. returnedMessage.Append(explanation);
  710. return NS_OK;
  711. }
  712. static void
  713. AppendErrorTextUntrusted(PRErrorCode errTrust,
  714. const nsString &host,
  715. nsIX509Cert* ix509,
  716. nsINSSComponent *component,
  717. nsString &returnedMessage)
  718. {
  719. const char *errorID = nsnull;
  720. nsCOMPtr<nsIX509Cert3> cert3 = do_QueryInterface(ix509);
  721. if (cert3) {
  722. PRBool isSelfSigned;
  723. if (NS_SUCCEEDED(cert3->GetIsSelfSigned(&isSelfSigned))
  724. && isSelfSigned) {
  725. errorID = "certErrorTrust_SelfSigned";
  726. }
  727. }
  728. if (!errorID) {
  729. switch (errTrust) {
  730. case SEC_ERROR_UNKNOWN_ISSUER:
  731. errorID = "certErrorTrust_UnknownIssuer";
  732. break;
  733. case SEC_ERROR_INADEQUATE_KEY_USAGE:
  734. // Should get an individual string in the future
  735. // For now, use the same as CaInvalid
  736. case SEC_ERROR_CA_CERT_INVALID:
  737. errorID = "certErrorTrust_CaInvalid";
  738. break;
  739. case SEC_ERROR_UNTRUSTED_ISSUER:
  740. errorID = "certErrorTrust_Issuer";
  741. break;
  742. case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
  743. errorID = "certErrorTrust_ExpiredIssuer";
  744. break;
  745. case SEC_ERROR_UNTRUSTED_CERT:
  746. default:
  747. errorID = "certErrorTrust_Untrusted";
  748. break;
  749. }
  750. }
  751. nsString formattedString;
  752. nsresult rv = component->GetPIPNSSBundleString(errorID,
  753. formattedString);
  754. if (NS_SUCCEEDED(rv))
  755. {
  756. returnedMessage.Append(formattedString);
  757. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  758. }
  759. }
  760. // returns TRUE if SAN was used to produce names
  761. // return FALSE if nothing was produced
  762. // names => a single name or a list of names
  763. // multipleNames => whether multiple names were delivered
  764. static PRBool
  765. GetSubjectAltNames(CERTCertificate *nssCert,
  766. nsINSSComponent *component,
  767. nsString &allNames,
  768. PRUint32 &nameCount)
  769. {
  770. allNames.Truncate();
  771. nameCount = 0;
  772. PRArenaPool *san_arena = nsnull;
  773. SECItem altNameExtension = {siBuffer, NULL, 0 };
  774. CERTGeneralName *sanNameList = nsnull;
  775. nsresult rv;
  776. rv = CERT_FindCertExtension(nssCert, SEC_OID_X509_SUBJECT_ALT_NAME,
  777. &altNameExtension);
  778. if (rv != SECSuccess)
  779. return PR_FALSE;
  780. san_arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  781. if (!san_arena)
  782. return PR_FALSE;
  783. sanNameList = CERT_DecodeAltNameExtension(san_arena, &altNameExtension);
  784. if (!sanNameList)
  785. return PR_FALSE;
  786. SECITEM_FreeItem(&altNameExtension, PR_FALSE);
  787. CERTGeneralName *current = sanNameList;
  788. do {
  789. nsAutoString name;
  790. switch (current->type) {
  791. case certDNSName:
  792. name.AssignASCII((char*)current->name.other.data, current->name.other.len);
  793. if (!allNames.IsEmpty()) {
  794. allNames.Append(NS_LITERAL_STRING(" , "));
  795. }
  796. ++nameCount;
  797. allNames.Append(name);
  798. break;
  799. case certIPAddress:
  800. {
  801. char buf[INET6_ADDRSTRLEN];
  802. PRNetAddr addr;
  803. if (current->name.other.len == 4) {
  804. addr.inet.family = PR_AF_INET;
  805. memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
  806. PR_NetAddrToString(&addr, buf, sizeof(buf));
  807. name.AssignASCII(buf);
  808. } else if (current->name.other.len == 16) {
  809. addr.ipv6.family = PR_AF_INET6;
  810. memcpy(&addr.ipv6.ip, current->name.other.data, current->name.other.len);
  811. PR_NetAddrToString(&addr, buf, sizeof(buf));
  812. name.AssignASCII(buf);
  813. } else {
  814. /* invalid IP address */
  815. }
  816. if (!name.IsEmpty()) {
  817. if (!allNames.IsEmpty()) {
  818. allNames.Append(NS_LITERAL_STRING(" , "));
  819. }
  820. ++nameCount;
  821. allNames.Append(name);
  822. }
  823. break;
  824. }
  825. default: // all other types of names are ignored
  826. break;
  827. }
  828. current = CERT_GetNextGeneralName(current);
  829. } while (current != sanNameList); // double linked
  830. PORT_FreeArena(san_arena, PR_FALSE);
  831. return PR_TRUE;
  832. }
  833. static void
  834. AppendErrorTextMismatch(const nsString &host,
  835. nsIX509Cert* ix509,
  836. nsINSSComponent *component,
  837. nsString &returnedMessage)
  838. {
  839. const PRUnichar *params[1];
  840. nsresult rv;
  841. CERTCertificate *nssCert = NULL;
  842. CERTCertificateCleaner nssCertCleaner(nssCert);
  843. nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(ix509, &rv);
  844. if (cert2)
  845. nssCert = cert2->GetCert();
  846. if (!nssCert) {
  847. // We are unable to extract the valid names, say "not valid for name".
  848. params[0] = host.get();
  849. nsString formattedString;
  850. rv = component->PIPBundleFormatStringFromName("certErrorMismatch",
  851. params, 1,
  852. formattedString);
  853. if (NS_SUCCEEDED(rv)) {
  854. returnedMessage.Append(formattedString);
  855. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  856. }
  857. return;
  858. }
  859. nsString allNames;
  860. PRUint32 nameCount = 0;
  861. PRBool useSAN = PR_FALSE;
  862. if (nssCert)
  863. useSAN = GetSubjectAltNames(nssCert, component, allNames, nameCount);
  864. if (!useSAN) {
  865. char *certName = nsnull;
  866. // currently CERT_FindNSStringExtension is not being exported by NSS.
  867. // If it gets exported, enable the following line.
  868. // certName = CERT_FindNSStringExtension(nssCert, SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
  869. // However, it has been discussed to treat the extension as obsolete and ignore it.
  870. if (!certName)
  871. certName = CERT_GetCommonName(&nssCert->subject);
  872. if (certName) {
  873. ++nameCount;
  874. allNames.AssignASCII(certName);
  875. PORT_Free(certName);
  876. }
  877. }
  878. if (nameCount > 1) {
  879. nsString message;
  880. rv = component->GetPIPNSSBundleString("certErrorMismatchMultiple",
  881. message);
  882. if (NS_SUCCEEDED(rv)) {
  883. returnedMessage.Append(message);
  884. returnedMessage.Append(NS_LITERAL_STRING("\n "));
  885. returnedMessage.Append(allNames);
  886. returnedMessage.Append(NS_LITERAL_STRING(" \n"));
  887. }
  888. }
  889. else if (nameCount == 1) {
  890. const PRUnichar *params[1];
  891. params[0] = allNames.get();
  892. nsString formattedString;
  893. rv = component->PIPBundleFormatStringFromName("certErrorMismatchSingle2",
  894. params, 1,
  895. formattedString);
  896. if (NS_SUCCEEDED(rv)) {
  897. returnedMessage.Append(formattedString);
  898. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  899. }
  900. }
  901. else { // nameCount == 0
  902. nsString message;
  903. nsresult rv = component->GetPIPNSSBundleString("certErrorMismatchNoNames",
  904. message);
  905. if (NS_SUCCEEDED(rv)) {
  906. returnedMessage.Append(message);
  907. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  908. }
  909. }
  910. }
  911. static void
  912. GetDateBoundary(nsIX509Cert* ix509,
  913. nsString &formattedDate,
  914. PRBool &trueExpired_falseNotYetValid)
  915. {
  916. trueExpired_falseNotYetValid = PR_TRUE;
  917. formattedDate.Truncate();
  918. PRTime notAfter, notBefore, timeToUse;
  919. nsCOMPtr<nsIX509CertValidity> validity;
  920. nsresult rv;
  921. rv = ix509->GetValidity(getter_AddRefs(validity));
  922. if (NS_FAILED(rv))
  923. return;
  924. rv = validity->GetNotAfter(&notAfter);
  925. if (NS_FAILED(rv))
  926. return;
  927. rv = validity->GetNotBefore(&notBefore);
  928. if (NS_FAILED(rv))
  929. return;
  930. if (LL_CMP(PR_Now(), >, notAfter)) {
  931. timeToUse = notAfter;
  932. } else {
  933. timeToUse = notBefore;
  934. trueExpired_falseNotYetValid = PR_FALSE;
  935. }
  936. nsIDateTimeFormat* aDateTimeFormat;
  937. rv = CallCreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &aDateTimeFormat);
  938. if (NS_FAILED(rv))
  939. return;
  940. aDateTimeFormat->FormatPRTime(nsnull, kDateFormatShort,
  941. kTimeFormatNoSeconds, timeToUse,
  942. formattedDate);
  943. NS_IF_RELEASE(aDateTimeFormat);
  944. }
  945. static void
  946. AppendErrorTextTime(nsIX509Cert* ix509,
  947. nsINSSComponent *component,
  948. nsString &returnedMessage)
  949. {
  950. nsAutoString formattedDate;
  951. PRBool trueExpired_falseNotYetValid;
  952. GetDateBoundary(ix509, formattedDate, trueExpired_falseNotYetValid);
  953. const PRUnichar *params[1];
  954. params[0] = formattedDate.get(); // might be empty, if helper function had a problem
  955. const char *key = trueExpired_falseNotYetValid ?
  956. "certErrorExpired" : "certErrorNotYetValid";
  957. nsresult rv;
  958. nsString formattedString;
  959. rv = component->PIPBundleFormatStringFromName(key, params,
  960. 1, formattedString);
  961. if (NS_SUCCEEDED(rv))
  962. {
  963. returnedMessage.Append(formattedString);
  964. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  965. }
  966. }
  967. static void
  968. AppendErrorTextCode(PRErrorCode errorCodeToReport,
  969. nsINSSComponent *component,
  970. nsString &returnedMessage)
  971. {
  972. const char *codeName = nsNSSErrors::getDefaultErrorStringName(errorCodeToReport);
  973. if (codeName)
  974. {
  975. nsCString error_id(codeName);
  976. ToLowerCase(error_id);
  977. NS_ConvertASCIItoUTF16 idU(error_id);
  978. const PRUnichar *params[1];
  979. params[0] = idU.get();
  980. nsString formattedString;
  981. nsresult rv;
  982. rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix",
  983. params, 1,
  984. formattedString);
  985. if (NS_SUCCEEDED(rv)) {
  986. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  987. returnedMessage.Append(formattedString);
  988. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  989. }
  990. else {
  991. returnedMessage.Append(NS_LITERAL_STRING(" ("));
  992. returnedMessage.Append(idU);
  993. returnedMessage.Append(NS_LITERAL_STRING(")"));
  994. }
  995. }
  996. }
  997. static nsresult
  998. getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors,
  999. PRErrorCode errorCodeToReport,
  1000. PRErrorCode errTrust,
  1001. PRErrorCode errMismatch,
  1002. PRErrorCode errExpired,
  1003. const nsString &host,
  1004. const nsString &hostWithPort,
  1005. PRInt32 port,
  1006. nsIX509Cert* ix509,
  1007. PRBool externalErrorReporting,
  1008. nsINSSComponent *component,
  1009. nsString &returnedMessage)
  1010. {
  1011. NS_ENSURE_ARG_POINTER(component);
  1012. const PRUnichar *params[1];
  1013. nsresult rv;
  1014. // For now, hide port when it's 443 and we're reporting the error using
  1015. // external reporting. In the future a better mechanism should be used
  1016. // to make a decision about showing the port number, possibly by requiring
  1017. // the context object to implement a specific interface.
  1018. // The motivation is that Mozilla browser would like to hide the port number
  1019. // in error pages in the common case.
  1020. if (externalErrorReporting && port == 443)
  1021. params[0] = host.get();
  1022. else
  1023. params[0] = hostWithPort.get();
  1024. nsString formattedString;
  1025. rv = component->PIPBundleFormatStringFromName("certErrorIntro",
  1026. params, 1,
  1027. formattedString);
  1028. if (NS_SUCCEEDED(rv))
  1029. {
  1030. returnedMessage.Append(formattedString);
  1031. returnedMessage.Append(NS_LITERAL_STRING("\n\n"));
  1032. }
  1033. if (multipleCollectedErrors & nsICertOverrideService::ERROR_UNTRUSTED)
  1034. {
  1035. AppendErrorTextUntrusted(errTrust, host, ix509,
  1036. component, returnedMessage);
  1037. }
  1038. if (multipleCollectedErrors & nsICertOverrideService::ERROR_MISMATCH)
  1039. {
  1040. AppendErrorTextMismatch(host, ix509, component, returnedMessage);
  1041. }
  1042. if (multipleCollectedErrors & nsICertOverrideService::ERROR_TIME)
  1043. {
  1044. AppendErrorTextTime(ix509, component, returnedMessage);
  1045. }
  1046. AppendErrorTextCode(errorCodeToReport, component, returnedMessage);
  1047. return NS_OK;
  1048. }
  1049. static nsresult
  1050. displayAlert(nsAFlatString &formattedString, nsNSSSocketInfo *infoObject)
  1051. {
  1052. // The interface requestor object may not be safe, so proxy the call to get
  1053. // the nsIPrompt.
  1054. if (nsSSLThread::exitRequested())
  1055. return NS_ERROR_FAILURE;
  1056. nsCOMPtr<nsIInterfaceRequestor> proxiedCallbacks;
  1057. NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
  1058. NS_GET_IID(nsIInterfaceRequestor),
  1059. static_cast<nsIInterfaceRequestor*>(infoObject),
  1060. NS_PROXY_SYNC,
  1061. getter_AddRefs(proxiedCallbacks));
  1062. nsCOMPtr<nsIPrompt> prompt (do_GetInterface(proxiedCallbacks));
  1063. if (!prompt)
  1064. return NS_ERROR_NO_INTERFACE;
  1065. // Finally, get a proxy for the nsIPrompt
  1066. nsCOMPtr<nsIPrompt> proxyPrompt;
  1067. NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
  1068. NS_GET_IID(nsIPrompt),
  1069. prompt,
  1070. NS_PROXY_SYNC,
  1071. getter_AddRefs(proxyPrompt));
  1072. proxyPrompt->Alert(nsnull, formattedString.get());
  1073. return NS_OK;
  1074. }
  1075. static nsresult
  1076. nsHandleSSLError(nsNSSSocketInfo *socketInfo, PRInt32 err)
  1077. {
  1078. if (socketInfo->GetCanceled()) {
  1079. // If the socket has been flagged as canceled,
  1080. // the code who did was responsible for showing
  1081. // an error message (if desired).
  1082. return NS_OK;
  1083. }
  1084. if (nsSSLThread::exitRequested()) {
  1085. return NS_ERROR_FAILURE;
  1086. }
  1087. nsresult rv;
  1088. NS_DEFINE_CID(nssComponentCID, NS_NSSCOMPONENT_CID);
  1089. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(nssComponentCID, &rv));
  1090. if (NS_FAILED(rv))
  1091. return rv;
  1092. nsXPIDLCString hostName;
  1093. socketInfo->GetHostName(getter_Copies(hostName));
  1094. NS_ConvertASCIItoUTF16 hostNameU(hostName);
  1095. PRInt32 port;
  1096. socketInfo->GetPort(&port);
  1097. // Try to get a nsISSLErrorListener implementation from the socket consumer.
  1098. nsCOMPtr<nsIInterfaceRequestor> cb;
  1099. socketInfo->GetNotificationCallbacks(getter_AddRefs(cb));
  1100. if (cb) {
  1101. nsCOMPtr<nsIInterfaceRequestor> callbacks;
  1102. NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
  1103. NS_GET_IID(nsIInterfaceRequestor),
  1104. cb,
  1105. NS_PROXY_SYNC,
  1106. getter_AddRefs(callbacks));
  1107. nsCOMPtr<nsISSLErrorListener> sel = do_GetInterface(callbacks);
  1108. if (sel) {
  1109. nsISSLErrorListener *proxy_sel = nsnull;
  1110. NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
  1111. NS_GET_IID(nsISSLErrorListener),
  1112. sel,
  1113. NS_PROXY_SYNC,
  1114. (void**)&proxy_sel);
  1115. if (proxy_sel) {
  1116. nsIInterfaceRequestor *csi = static_cast<nsIInterfaceRequestor*>(socketInfo);
  1117. PRBool suppressMessage = PR_FALSE;
  1118. nsCString hostWithPortString = hostName;
  1119. hostWithPortString.AppendLiteral(":");
  1120. hostWithPortString.AppendInt(port);
  1121. rv = proxy_sel->NotifySSLError(csi, err, hostWithPortString,
  1122. &suppressMessage);
  1123. if (NS_SUCCEEDED(rv) && suppressMessage)
  1124. return NS_OK;
  1125. }
  1126. }
  1127. }
  1128. PRBool external = PR_FALSE;
  1129. socketInfo->GetExternalErrorReporting(&external);
  1130. nsString formattedString;
  1131. rv = getErrorMessage(err, hostNameU, port, external, nssComponent, formattedString);
  1132. if (external)
  1133. {
  1134. socketInfo->SetErrorMessage(formattedString.get());
  1135. }
  1136. else
  1137. {
  1138. nsPSMUITracker tracker;
  1139. if (tracker.isUIForbidden()) {
  1140. rv = NS_ERROR_NOT_AVAILABLE;
  1141. }
  1142. else {
  1143. rv = displayAlert(formattedString, socketInfo);
  1144. }
  1145. }
  1146. return rv;
  1147. }
  1148. static nsresult
  1149. nsHandleInvalidCertError(nsNSSSocketInfo *socketInfo,
  1150. PRUint32 multipleCollectedErrors,
  1151. const nsACString &host,
  1152. const nsACString &hostWithPort,
  1153. PRInt32 port,
  1154. PRErrorCode errorCodeToReport,
  1155. PRErrorCode errTrust,
  1156. PRErrorCode errMismatch,
  1157. PRErrorCode errExpired,
  1158. nsIX509Cert* ix509)
  1159. {
  1160. nsresult rv;
  1161. NS_DEFINE_CID(nssComponentCID, NS_NSSCOMPONENT_CID);
  1162. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(nssComponentCID, &rv));
  1163. if (NS_FAILED(rv))
  1164. return rv;
  1165. NS_ConvertASCIItoUTF16 hostU(host);
  1166. NS_ConvertASCIItoUTF16 hostWithPortU(hostWithPort);
  1167. // What mechanism is used to inform the user?
  1168. // The highest priority has the "external error reporting" feature,
  1169. // if set, we'll provide the strings to be used by the nsINSSErrorsService
  1170. PRBool external = PR_FALSE;
  1171. socketInfo->GetExternalErrorReporting(&external);
  1172. nsString formattedString;
  1173. rv = getInvalidCertErrorMessage(multipleCollectedErrors, errorCodeToReport,
  1174. errTrust, errMismatch, errExpired,
  1175. hostU, hostWithPortU, port,
  1176. ix509, external, nssComponent, formattedString);
  1177. if (external)
  1178. {
  1179. socketInfo->SetErrorMessage(formattedString.get());
  1180. }
  1181. else
  1182. {
  1183. nsPSMUITracker tracker;
  1184. if (tracker.isUIForbidden()) {
  1185. rv = NS_ERROR_NOT_AVAILABLE;
  1186. }
  1187. else {
  1188. rv = displayAlert(formattedString, socketInfo);
  1189. }
  1190. }
  1191. return rv;
  1192. }
  1193. static PRStatus PR_CALLBACK
  1194. nsSSLIOLayerConnect(PRFileDesc* fd, const PRNetAddr* addr,
  1195. PRIntervalTime timeout)
  1196. {
  1197. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] connecting SSL socket\n", (void*)fd));
  1198. nsNSSShutDownPreventionLock locker;
  1199. if (!fd || !fd->lower)
  1200. return PR_FAILURE;
  1201. PRStatus status = PR_SUCCESS;
  1202. #if defined(XP_BEOS)
  1203. // Due to BeOS net_server's lack of support for nonblocking sockets,
  1204. // we must execute this entire connect as a blocking operation - bug 70217
  1205. PRSocketOptionData sockopt;
  1206. sockopt.option = PR_SockOpt_Nonblocking;
  1207. PR_GetSocketOption(fd, &sockopt);
  1208. PRBool oldBlockVal = sockopt.value.non_blocking;
  1209. sockopt.option = PR_SockOpt_Nonblocking;
  1210. sockopt.value.non_blocking = PR_FALSE;
  1211. PR_SetSocketOption(fd, &sockopt);
  1212. #endif
  1213. status = fd->lower->methods->connect(fd->lower, addr,
  1214. #if defined(XP_BEOS) // bug 70217
  1215. PR_INTERVAL_NO_TIMEOUT);
  1216. #else
  1217. timeout);
  1218. #endif
  1219. if (status != PR_SUCCESS) {
  1220. PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("[%p] Lower layer connect error: %d\n",
  1221. (void*)fd, PR_GetError()));
  1222. #if defined(XP_BEOS) // bug 70217
  1223. goto loser;
  1224. #else
  1225. return status;
  1226. #endif
  1227. }
  1228. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] Connect\n", (void*)fd));
  1229. #if defined(XP_BEOS) // bug 70217
  1230. loser:
  1231. // We put the Nonblocking bit back to the value it was when
  1232. // we entered this function.
  1233. NS_ASSERTION(sockopt.option == PR_SockOpt_Nonblocking,
  1234. "sockopt.option was re-set to an unexpected value");
  1235. sockopt.value.non_blocking = oldBlockVal;
  1236. PR_SetSocketOption(fd, &sockopt);
  1237. #endif
  1238. return status;
  1239. }
  1240. // Call this function to report a site that is possibly TLS intolerant.
  1241. // This function will return true, if the given socket is currently using TLS.
  1242. PRBool
  1243. nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(PRFileDesc* ssl_layer_fd, nsNSSSocketInfo *socketInfo)
  1244. {
  1245. PRBool currentlyUsesTLS = PR_FALSE;
  1246. SSL_OptionGet(ssl_layer_fd, SSL_ENABLE_TLS, &currentlyUsesTLS);
  1247. if (currentlyUsesTLS) {
  1248. // Add this site to the list of TLS intolerant sites.
  1249. PRInt32 port;
  1250. nsXPIDLCString host;
  1251. socketInfo->GetPort(&port);
  1252. socketInfo->GetHostName(getter_Copies(host));
  1253. nsCAutoString key;
  1254. key = host + NS_LITERAL_CSTRING(":") + nsPrintfCString("%d", port);
  1255. addIntolerantSite(key);
  1256. }
  1257. return currentlyUsesTLS;
  1258. }
  1259. static PRStatus PR_CALLBACK
  1260. nsSSLIOLayerClose(PRFileDesc *fd)
  1261. {
  1262. nsNSSShutDownPreventionLock locker;
  1263. if (!fd)
  1264. return PR_FAILURE;
  1265. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] Shutting down socket\n", (void*)fd));
  1266. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1267. NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");
  1268. return nsSSLThread::requestClose(socketInfo);
  1269. }
  1270. PRStatus nsNSSSocketInfo::CloseSocketAndDestroy()
  1271. {
  1272. nsNSSShutDownPreventionLock locker;
  1273. nsNSSShutDownList::trackSSLSocketClose();
  1274. PRFileDesc* popped = PR_PopIOLayer(mFd, PR_TOP_IO_LAYER);
  1275. if (GetHandshakeInProgress()) {
  1276. nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(mFd->lower, this);
  1277. }
  1278. PRStatus status = mFd->methods->close(mFd);
  1279. if (status != PR_SUCCESS) return status;
  1280. popped->identity = PR_INVALID_IO_LAYER;
  1281. NS_RELEASE_THIS();
  1282. popped->dtor(popped);
  1283. return PR_SUCCESS;
  1284. }
  1285. #if defined(DEBUG_SSL_VERBOSE) && defined(DUMP_BUFFER)
  1286. /* Dumps a (potentially binary) buffer using SSM_DEBUG.
  1287. (We could have used the version in ssltrace.c, but that's
  1288. specifically tailored to SSLTRACE. Sigh. */
  1289. #define DUMPBUF_LINESIZE 24
  1290. static void
  1291. nsDumpBuffer(unsigned char *buf, PRIntn len)
  1292. {
  1293. char hexbuf[DUMPBUF_LINESIZE*3+1];
  1294. char chrbuf[DUMPBUF_LINESIZE+1];
  1295. static const char *hex = "0123456789abcdef";
  1296. PRIntn i = 0, l = 0;
  1297. char ch, *c, *h;
  1298. if (len == 0)
  1299. return;
  1300. hexbuf[DUMPBUF_LINESIZE*3] = '\0';
  1301. chrbuf[DUMPBUF_LINESIZE] = '\0';
  1302. (void) memset(hexbuf, 0x20, DUMPBUF_LINESIZE*3);
  1303. (void) memset(chrbuf, 0x20, DUMPBUF_LINESIZE);
  1304. h = hexbuf;
  1305. c = chrbuf;
  1306. while (i < len)
  1307. {
  1308. ch = buf[i];
  1309. if (l == DUMPBUF_LINESIZE)
  1310. {
  1311. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("%s%s\n", hexbuf, chrbuf));
  1312. (void) memset(hexbuf, 0x20, DUMPBUF_LINESIZE*3);
  1313. (void) memset(chrbuf, 0x20, DUMPBUF_LINESIZE);
  1314. h = hexbuf;
  1315. c = chrbuf;
  1316. l = 0;
  1317. }
  1318. /* Convert a character to hex. */
  1319. *h++ = hex[(ch >> 4) & 0xf];
  1320. *h++ = hex[ch & 0xf];
  1321. h++;
  1322. /* Put the character (if it's printable) into the character buffer. */
  1323. if ((ch >= 0x20) && (ch <= 0x7e))
  1324. *c++ = ch;
  1325. else
  1326. *c++ = '.';
  1327. i++; l++;
  1328. }
  1329. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("%s%s\n", hexbuf, chrbuf));
  1330. }
  1331. #define DEBUG_DUMP_BUFFER(buf,len) nsDumpBuffer(buf,len)
  1332. #else
  1333. #define DEBUG_DUMP_BUFFER(buf,len)
  1334. #endif
  1335. static PRBool
  1336. isNonSSLErrorThatWeAllowToRetry(PRInt32 err, PRBool withInitialCleartext)
  1337. {
  1338. switch (err)
  1339. {
  1340. case PR_CONNECT_RESET_ERROR:
  1341. if (!withInitialCleartext)
  1342. return PR_TRUE;
  1343. break;
  1344. case PR_END_OF_FILE_ERROR:
  1345. return PR_TRUE;
  1346. }
  1347. return PR_FALSE;
  1348. }
  1349. static PRBool
  1350. isTLSIntoleranceError(PRInt32 err, PRBool withInitialCleartext)
  1351. {
  1352. // This function is supposed to decide, which error codes should
  1353. // be used to conclude server is TLS intolerant.
  1354. // Note this only happens during the initial SSL handshake.
  1355. //
  1356. // When not using a proxy we'll see a connection reset error.
  1357. // When using a proxy, we'll see an end of file error.
  1358. // In addition check for some error codes where it is reasonable
  1359. // to retry without TLS.
  1360. if (isNonSSLErrorThatWeAllowToRetry(err, withInitialCleartext))
  1361. return PR_TRUE;
  1362. switch (err)
  1363. {
  1364. case SSL_ERROR_BAD_MAC_ALERT:
  1365. case SSL_ERROR_BAD_MAC_READ:
  1366. case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
  1367. case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
  1368. case SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE:
  1369. case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
  1370. case SSL_ERROR_NO_CYPHER_OVERLAP:
  1371. case SSL_ERROR_BAD_SERVER:
  1372. case SSL_ERROR_BAD_BLOCK_PADDING:
  1373. case SSL_ERROR_UNSUPPORTED_VERSION:
  1374. case SSL_ERROR_PROTOCOL_VERSION_ALERT:
  1375. case SSL_ERROR_RX_MALFORMED_FINISHED:
  1376. case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE:
  1377. case SSL_ERROR_DECODE_ERROR_ALERT:
  1378. case SSL_ERROR_RX_UNKNOWN_ALERT:
  1379. return PR_TRUE;
  1380. }
  1381. return PR_FALSE;
  1382. }
  1383. PRInt32
  1384. nsSSLThread::checkHandshake(PRInt32 bytesTransfered,
  1385. PRBool wasReading,
  1386. PRFileDesc* ssl_layer_fd,
  1387. nsNSSSocketInfo *socketInfo)
  1388. {
  1389. // This is where we work around all of those SSL servers that don't
  1390. // conform to the SSL spec and shutdown a connection when we request
  1391. // SSL v3.1 (aka TLS). The spec says the client says what version
  1392. // of the protocol we're willing to perform, in our case SSL v3.1
  1393. // In its response, the server says which version it wants to perform.
  1394. // Many servers out there only know how to do v3.0. Next, we're supposed
  1395. // to send back the version of the protocol we requested (ie v3.1). At
  1396. // this point many servers's implementations are broken and they shut
  1397. // down the connection when they don't see the version they sent back.
  1398. // This is supposed to prevent a man in the middle from forcing one
  1399. // side to dumb down to a lower level of the protocol. Unfortunately,
  1400. // there are enough broken servers out there that such a gross work-around
  1401. // is necessary. :(
  1402. // Additional comment added in August 2006:
  1403. // When we begun to use TLS hello extensions, we encountered a new class of
  1404. // broken server, which simply stall for a very long time.
  1405. // We would like to shorten the timeout, but limit this shorter timeout
  1406. // to the handshake phase.
  1407. // When we arrive here for the first time (for a given socket),
  1408. // we know the connection is established, and the application code
  1409. // tried the first read or write. This triggers the beginning of the
  1410. // SSL handshake phase at the SSL FD level.
  1411. // We'll make a note of the current time,
  1412. // and use this to measure the elapsed time since handshake begin.
  1413. // Do NOT assume TLS intolerance on a closed connection after bad cert ui was shown.
  1414. // Simply retry.
  1415. // This depends on the fact that Cert UI will not be shown again,
  1416. // should the user override the bad cert.
  1417. PRBool handleHandshakeResultNow;
  1418. socketInfo->GetHandshakePending(&handleHandshakeResultNow);
  1419. PRBool wantRetry = PR_FALSE;
  1420. if (0 > bytesTransfered) {
  1421. PRInt32 err = PR_GetError();
  1422. if (handleHandshakeResultNow) {
  1423. if (PR_WOULD_BLOCK_ERROR == err) {
  1424. socketInfo->SetHandshakeInProgress(PR_TRUE);
  1425. return bytesTransfered;
  1426. }
  1427. if (!wantRetry // no decision yet
  1428. && isTLSIntoleranceError(err, socketInfo->GetHasCleartextPhase()))
  1429. {
  1430. wantRetry = nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(ssl_layer_fd, socketInfo);
  1431. }
  1432. }
  1433. // This is the common place where we trigger an error message on a SSL socket.
  1434. // This might be reached at any time of the connection.
  1435. if (!wantRetry && (IS_SSL_ERROR(err) || IS_SEC_ERROR(err))) {
  1436. nsHandleSSLError(socketInfo, err);
  1437. }
  1438. }
  1439. else if (wasReading && 0 == bytesTransfered) // zero bytes on reading, socket closed
  1440. {
  1441. if (handleHandshakeResultNow)
  1442. {
  1443. if (!wantRetry // no decision yet
  1444. && !socketInfo->GetHasCleartextPhase()) // mirror PR_CONNECT_RESET_ERROR treament
  1445. {
  1446. wantRetry =
  1447. nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(ssl_layer_fd, socketInfo);
  1448. }
  1449. }
  1450. }
  1451. if (wantRetry) {
  1452. // We want to cause the network layer to retry the connection.
  1453. PR_SetError(PR_CONNECT_RESET_ERROR, 0);
  1454. if (wasReading)
  1455. bytesTransfered = -1;
  1456. }
  1457. // TLS intolerant servers only cause the first transfer to fail, so let's
  1458. // set the HandshakePending attribute to false so that we don't try the logic
  1459. // above again in a subsequent transfer.
  1460. if (handleHandshakeResultNow) {
  1461. socketInfo->SetHandshakePending(PR_FALSE);
  1462. socketInfo->SetHandshakeInProgress(PR_FALSE);
  1463. }
  1464. return bytesTransfered;
  1465. }
  1466. static PRInt16 PR_CALLBACK
  1467. nsSSLIOLayerPoll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
  1468. {
  1469. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] polling SSL socket\n", (void*)fd));
  1470. nsNSSShutDownPreventionLock locker;
  1471. if (!out_flags)
  1472. {
  1473. NS_WARNING("nsSSLIOLayerPoll called with null out_flags");
  1474. return 0;
  1475. }
  1476. *out_flags = 0;
  1477. if (!fd)
  1478. {
  1479. NS_WARNING("nsSSLIOLayerPoll called with null fd");
  1480. return 0;
  1481. }
  1482. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1483. NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");
  1484. return nsSSLThread::requestPoll(socketInfo, in_flags, out_flags);
  1485. }
  1486. PRBool nsSSLIOLayerHelpers::nsSSLIOLayerInitialized = PR_FALSE;
  1487. PRDescIdentity nsSSLIOLayerHelpers::nsSSLIOLayerIdentity;
  1488. PRIOMethods nsSSLIOLayerHelpers::nsSSLIOLayerMethods;
  1489. PRLock *nsSSLIOLayerHelpers::mutex = nsnull;
  1490. nsCStringHashSet *nsSSLIOLayerHelpers::mTLSIntolerantSites = nsnull;
  1491. PRFileDesc *nsSSLIOLayerHelpers::mSharedPollableEvent = nsnull;
  1492. nsNSSSocketInfo *nsSSLIOLayerHelpers::mSocketOwningPollableEvent = nsnull;
  1493. PRBool nsSSLIOLayerHelpers::mPollableEventCurrentlySet = PR_FALSE;
  1494. static PRIntn _PSM_InvalidInt(void)
  1495. {
  1496. PR_ASSERT(!"I/O method is invalid");
  1497. PR_SetError(PR_INVALID_METHOD_ERROR, 0);
  1498. return -1;
  1499. }
  1500. static PRInt64 _PSM_InvalidInt64(void)
  1501. {
  1502. PR_ASSERT(!"I/O method is invalid");
  1503. PR_SetError(PR_INVALID_METHOD_ERROR, 0);
  1504. return -1;
  1505. }
  1506. static PRStatus _PSM_InvalidStatus(void)
  1507. {
  1508. PR_ASSERT(!"I/O method is invalid");
  1509. PR_SetError(PR_INVALID_METHOD_ERROR, 0);
  1510. return PR_FAILURE;
  1511. }
  1512. static PRFileDesc *_PSM_InvalidDesc(void)
  1513. {
  1514. PR_ASSERT(!"I/O method is invalid");
  1515. PR_SetError(PR_INVALID_METHOD_ERROR, 0);
  1516. return NULL;
  1517. }
  1518. static PRStatus PR_CALLBACK PSMGetsockname(PRFileDesc *fd, PRNetAddr *addr)
  1519. {
  1520. nsNSSShutDownPreventionLock locker;
  1521. if (!fd || !fd->lower) {
  1522. return PR_FAILURE;
  1523. }
  1524. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1525. NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");
  1526. return nsSSLThread::requestGetsockname(socketInfo, addr);
  1527. }
  1528. static PRStatus PR_CALLBACK PSMGetpeername(PRFileDesc *fd, PRNetAddr *addr)
  1529. {
  1530. nsNSSShutDownPreventionLock locker;
  1531. if (!fd || !fd->lower) {
  1532. return PR_FAILURE;
  1533. }
  1534. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1535. NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");
  1536. return nsSSLThread::requestGetpeername(socketInfo, addr);
  1537. }
  1538. static PRStatus PR_CALLBACK PSMGetsocketoption(PRFileDesc *fd,
  1539. PRSocketOptionData *data)
  1540. {
  1541. nsNSSShutDownPreventionLock locker;
  1542. if (!fd || !fd->lower) {
  1543. return PR_FAILURE;
  1544. }
  1545. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1546. NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");
  1547. return nsSSLThread::requestGetsocketoption(socketInfo, data);
  1548. }
  1549. static PRStatus PR_CALLBACK PSMSetsocketoption(PRFileDesc *fd,
  1550. const PRSocketOptionData *data)
  1551. {
  1552. nsNSSShutDownPreventionLock locker;
  1553. if (!fd || !fd->lower) {
  1554. return PR_FAILURE;
  1555. }
  1556. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1557. NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");
  1558. return nsSSLThread::requestSetsocketoption(socketInfo, data);
  1559. }
  1560. static PRInt32 PR_CALLBACK PSMRecv(PRFileDesc *fd, void *buf, PRInt32 amount,
  1561. PRIntn flags, PRIntervalTime timeout)
  1562. {
  1563. nsNSSShutDownPreventionLock locker;
  1564. if (!fd || !fd->lower) {
  1565. PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
  1566. return -1;
  1567. }
  1568. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1569. NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");
  1570. if (flags == PR_MSG_PEEK) {
  1571. return nsSSLThread::requestRecvMsgPeek(socketInfo, buf, amount, flags, timeout);
  1572. }
  1573. if (flags != 0) {
  1574. PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  1575. return -1;
  1576. }
  1577. return nsSSLThread::requestRead(socketInfo, buf, amount, timeout);
  1578. }
  1579. static PRInt32 PR_CALLBACK PSMSend(PRFileDesc *fd, const void *buf, PRInt32 amount,
  1580. PRIntn flags, PRIntervalTime timeout)
  1581. {
  1582. nsNSSShutDownPreventionLock locker;
  1583. if (!fd || !fd->lower) {
  1584. PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
  1585. return -1;
  1586. }
  1587. if (flags != 0) {
  1588. PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  1589. return -1;
  1590. }
  1591. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1592. NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");
  1593. return nsSSLThread::requestWrite(socketInfo, buf, amount, timeout);
  1594. }
  1595. static PRInt32 PR_CALLBACK
  1596. nsSSLIOLayerRead(PRFileDesc* fd, void* buf, PRInt32 amount)
  1597. {
  1598. return PSMRecv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
  1599. }
  1600. static PRInt32 PR_CALLBACK
  1601. nsSSLIOLayerWrite(PRFileDesc* fd, const void* buf, PRInt32 amount)
  1602. {
  1603. return PSMSend(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
  1604. }
  1605. static PRStatus PR_CALLBACK PSMConnectcontinue(PRFileDesc *fd, PRInt16 out_flags)
  1606. {
  1607. nsNSSShutDownPreventionLock locker;
  1608. if (!fd || !fd->lower) {
  1609. return PR_FAILURE;
  1610. }
  1611. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1612. NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");
  1613. return nsSSLThread::requestConnectcontinue(socketInfo, out_flags);
  1614. }
  1615. nsresult nsSSLIOLayerHelpers::Init()
  1616. {
  1617. if (!nsSSLIOLayerInitialized) {
  1618. nsSSLIOLayerInitialized = PR_TRUE;
  1619. nsSSLIOLayerIdentity = PR_GetUniqueIdentity("NSS layer");
  1620. nsSSLIOLayerMethods = *PR_GetDefaultIOMethods();
  1621. nsSSLIOLayerMethods.available = (PRAvailableFN)_PSM_InvalidInt;
  1622. nsSSLIOLayerMethods.available64 = (PRAvailable64FN)_PSM_InvalidInt64;
  1623. nsSSLIOLayerMethods.fsync = (PRFsyncFN)_PSM_InvalidStatus;
  1624. nsSSLIOLayerMethods.seek = (PRSeekFN)_PSM_InvalidInt;
  1625. nsSSLIOLayerMethods.seek64 = (PRSeek64FN)_PSM_InvalidInt64;
  1626. nsSSLIOLayerMethods.fileInfo = (PRFileInfoFN)_PSM_InvalidStatus;
  1627. nsSSLIOLayerMethods.fileInfo64 = (PRFileInfo64FN)_PSM_InvalidStatus;
  1628. nsSSLIOLayerMethods.writev = (PRWritevFN)_PSM_InvalidInt;
  1629. nsSSLIOLayerMethods.accept = (PRAcceptFN)_PSM_InvalidDesc;
  1630. nsSSLIOLayerMethods.bind = (PRBindFN)_PSM_InvalidStatus;
  1631. nsSSLIOLayerMethods.listen = (PRListenFN)_PSM_InvalidStatus;
  1632. nsSSLIOLayerMethods.shutdown = (PRShutdownFN)_PSM_InvalidStatus;
  1633. nsSSLIOLayerMethods.recvfrom = (PRRecvfromFN)_PSM_InvalidInt;
  1634. nsSSLIOLayerMethods.sendto = (PRSendtoFN)_PSM_InvalidInt;
  1635. nsSSLIOLayerMethods.acceptread = (PRAcceptreadFN)_PSM_InvalidInt;
  1636. nsSSLIOLayerMethods.transmitfile = (PRTransmitfileFN)_PSM_InvalidInt;
  1637. nsSSLIOLayerMethods.sendfile = (PRSendfileFN)_PSM_InvalidInt;
  1638. nsSSLIOLayerMethods.getsockname = PSMGetsockname;
  1639. nsSSLIOLayerMethods.getpeername = PSMGetpeername;
  1640. nsSSLIOLayerMethods.getsocketoption = PSMGetsocketoption;
  1641. nsSSLIOLayerMethods.setsocketoption = PSMSetsocketoption;
  1642. nsSSLIOLayerMethods.recv = PSMRecv;
  1643. nsSSLIOLayerMethods.send = PSMSend;
  1644. nsSSLIOLayerMethods.connectcontinue = PSMConnectcontinue;
  1645. nsSSLIOLayerMethods.connect = nsSSLIOLayerConnect;
  1646. nsSSLIOLayerMethods.close = nsSSLIOLayerClose;
  1647. nsSSLIOLayerMethods.write = nsSSLIOLayerWrite;
  1648. nsSSLIOLayerMethods.read = nsSSLIOLayerRead;
  1649. nsSSLIOLayerMethods.poll = nsSSLIOLayerPoll;
  1650. }
  1651. mutex = PR_NewLock();
  1652. if (!mutex)
  1653. return NS_ERROR_OUT_OF_MEMORY;
  1654. mSharedPollableEvent = PR_NewPollableEvent();
  1655. // if we can not get a pollable event, we'll have to do busy waiting
  1656. mTLSIntolerantSites = new nsCStringHashSet();
  1657. if (!mTLSIntolerantSites)
  1658. return NS_ERROR_OUT_OF_MEMORY;
  1659. mTLSIntolerantSites->Init(1);
  1660. return NS_OK;
  1661. }
  1662. void nsSSLIOLayerHelpers::addIntolerantSite(const nsCString &str)
  1663. {
  1664. nsAutoLock lock(mutex);
  1665. nsSSLIOLayerHelpers::mTLSIntolerantSites->Put(str);
  1666. }
  1667. PRBool nsSSLIOLayerHelpers::isKnownAsIntolerantSite(const nsCString &str)
  1668. {
  1669. nsAutoLock lock(mutex);
  1670. return mTLSIntolerantSites->Contains(str);
  1671. }
  1672. nsresult
  1673. nsSSLIOLayerNewSocket(PRInt32 family,
  1674. const char *host,
  1675. PRInt32 port,
  1676. const char *proxyHost,
  1677. PRInt32 proxyPort,
  1678. PRFileDesc **fd,
  1679. nsISupports** info,
  1680. PRBool forSTARTTLS)
  1681. {
  1682. PRFileDesc* sock = PR_OpenTCPSocket(family);
  1683. if (!sock) return NS_ERROR_OUT_OF_MEMORY;
  1684. nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, proxyHost, proxyPort,
  1685. sock, info, forSTARTTLS);
  1686. if (NS_FAILED(rv)) {
  1687. PR_Close(sock);
  1688. return rv;
  1689. }
  1690. *fd = sock;
  1691. return NS_OK;
  1692. }
  1693. /*
  1694. * Function: SECStatus nsConvertCANamesToStrings()
  1695. * Purpose: creates CA names strings from (CERTDistNames* caNames)
  1696. *
  1697. * Arguments and return values
  1698. * - arena: arena to allocate strings on
  1699. * - caNameStrings: filled with CA names strings on return
  1700. * - caNames: CERTDistNames to extract strings from
  1701. * - return: SECSuccess if successful; error code otherwise
  1702. *
  1703. * Note: copied in its entirety from Nova code
  1704. */
  1705. SECStatus nsConvertCANamesToStrings(PRArenaPool* arena, char** caNameStrings,
  1706. CERTDistNames* caNames)
  1707. {
  1708. SECItem* dername;
  1709. SECStatus rv;
  1710. int headerlen;
  1711. PRUint32 contentlen;
  1712. SECItem newitem;
  1713. int n;
  1714. char* namestring;
  1715. for (n = 0; n < caNames->nnames; n++) {
  1716. newitem.data = NULL;
  1717. dername = &caNames->names[n];
  1718. rv = DER_Lengths(dername, &headerlen, &contentlen);
  1719. if (rv != SECSuccess) {
  1720. goto loser;
  1721. }
  1722. if (headerlen + contentlen != dername->len) {
  1723. /* This must be from an enterprise 2.x server, which sent
  1724. * incorrectly formatted der without the outer wrapper of
  1725. * type and length. Fix it up by adding the top level
  1726. * header.
  1727. */
  1728. if (dername->len <= 127) {
  1729. newitem.data = (unsigned char *) PR_Malloc(dername->len + 2);
  1730. if (newitem.data == NULL) {
  1731. goto loser;
  1732. }
  1733. newitem.data[0] = (unsigned char)0x30;
  1734. newitem.data[1] = (unsigned char)dername->len;
  1735. (void)memcpy(&newitem.data[2], dername->data, dername->len);
  1736. }
  1737. else if (dername->len <= 255) {
  1738. newitem.data = (unsigned char *) PR_Malloc(dername->len + 3);
  1739. if (newitem.data == NULL) {
  1740. goto loser;
  1741. }
  1742. newitem.data[0] = (unsigned char)0x30;
  1743. newitem.data[1] = (unsigned char)0x81;
  1744. newitem.data[2] = (unsigned char)dername->len;
  1745. (void)memcpy(&newitem.data[3], dername->data, dername->len);
  1746. }
  1747. else {
  1748. /* greater than 256, better be less than 64k */
  1749. newitem.data = (unsigned char *) PR_Malloc(dername->len + 4);
  1750. if (newitem.data == NULL) {
  1751. goto loser;
  1752. }
  1753. newitem.data[0] = (unsigned char)0x30;
  1754. newitem.data[1] = (unsigned char)0x82;
  1755. newitem.data[2] = (unsigned char)((dername->len >> 8) & 0xff);
  1756. newitem.data[3] = (unsigned char)(dername->len & 0xff);
  1757. memcpy(&newitem.data[4], dername->data, dername->len);
  1758. }
  1759. dername = &newitem;
  1760. }
  1761. namestring = CERT_DerNameToAscii(dername);
  1762. if (namestring == NULL) {
  1763. /* XXX - keep going until we fail to convert the name */
  1764. caNameStrings[n] = "";
  1765. }
  1766. else {
  1767. caNameStrings[n] = PORT_ArenaStrdup(arena, namestring);
  1768. PR_Free(namestring);
  1769. if (caNameStrings[n] == NULL) {
  1770. goto loser;
  1771. }
  1772. }
  1773. if (newitem.data != NULL) {
  1774. PR_Free(newitem.data);
  1775. }
  1776. }
  1777. return SECSuccess;
  1778. loser:
  1779. if (newitem.data != NULL) {
  1780. PR_Free(newitem.data);
  1781. }
  1782. return SECFailure;
  1783. }
  1784. /*
  1785. * structs and ASN1 templates for the limited scope-of-use extension
  1786. *
  1787. * CertificateScopeEntry ::= SEQUENCE {
  1788. * name GeneralName, -- pattern, as for NameConstraints
  1789. * portNumber INTEGER OPTIONAL }
  1790. *
  1791. * CertificateScopeOfUse ::= SEQUENCE OF CertificateScopeEntry
  1792. */
  1793. /*
  1794. * CERTCertificateScopeEntry: struct for scope entry that can be consumed by
  1795. * the code
  1796. * certCertificateScopeOfUse: struct that represents the decoded extension data
  1797. */
  1798. typedef struct {
  1799. SECItem derConstraint;
  1800. SECItem derPort;
  1801. CERTGeneralName* constraint; /* decoded constraint */
  1802. PRIntn port; /* decoded port number */
  1803. } CERTCertificateScopeEntry;
  1804. typedef struct {
  1805. CERTCertificateScopeEntry** entries;
  1806. } certCertificateScopeOfUse;
  1807. /* corresponding ASN1 templates */
  1808. static const SEC_ASN1Template cert_CertificateScopeEntryTemplate[] = {
  1809. { SEC_ASN1_SEQUENCE,
  1810. 0, NULL, sizeof(CERTCertificateScopeEntry) },
  1811. { SEC_ASN1_ANY,
  1812. offsetof(CERTCertificateScopeEntry, derConstraint) },
  1813. { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
  1814. offsetof(CERTCertificateScopeEntry, derPort) },
  1815. { 0 }
  1816. };
  1817. static const SEC_ASN1Template cert_CertificateScopeOfUseTemplate[] = {
  1818. { SEC_ASN1_SEQUENCE_OF, 0, cert_CertificateScopeEntryTemplate }
  1819. };
  1820. #if 0
  1821. /*
  1822. * decodes the extension data and create CERTCertificateScopeEntry that can
  1823. * be consumed by the code
  1824. */
  1825. static
  1826. SECStatus cert_DecodeScopeOfUseEntries(PRArenaPool* arena, SECItem* extData,
  1827. CERTCertificateScopeEntry*** entries,
  1828. int* numEntries)
  1829. {
  1830. certCertificateScopeOfUse* scope = NULL;
  1831. SECStatus rv = SECSuccess;
  1832. int i;
  1833. *entries = NULL; /* in case of failure */
  1834. *numEntries = 0; /* ditto */
  1835. scope = (certCertificateScopeOfUse*)
  1836. PORT_ArenaZAlloc(arena, sizeof(certCertificateScopeOfUse));
  1837. if (scope == NULL) {
  1838. goto loser;
  1839. }
  1840. rv = SEC_ASN1DecodeItem(arena, (void*)scope,
  1841. cert_CertificateScopeOfUseTemplate, extData);
  1842. if (rv != SECSuccess) {
  1843. goto loser;
  1844. }
  1845. *entries = scope->entries;
  1846. PR_ASSERT(*entries != NULL);
  1847. /* first, let's count 'em. */
  1848. for (i = 0; (*entries)[i] != NULL; i++) ;
  1849. *numEntries = i;
  1850. /* convert certCertificateScopeEntry sequence into what we can readily
  1851. * use
  1852. */
  1853. for (i = 0; i < *numEntries; i++) {
  1854. (*entries)[i]->constraint =
  1855. CERT_DecodeGeneralName(arena, &((*entries)[i]->derConstraint),
  1856. NULL);
  1857. if ((*entries)[i]->derPort.data != NULL) {
  1858. (*entries)[i]->port =
  1859. (int)DER_GetInteger(&((*entries)[i]->derPort));
  1860. }
  1861. else {
  1862. (*entries)[i]->port = 0;
  1863. }
  1864. }
  1865. goto done;
  1866. loser:
  1867. if (rv == SECSuccess) {
  1868. rv = SECFailure;
  1869. }
  1870. done:
  1871. return rv;
  1872. }
  1873. static SECStatus cert_DecodeCertIPAddress(SECItem* genname,
  1874. PRUint32* constraint, PRUint32* mask)
  1875. {
  1876. /* in case of failure */
  1877. *constraint = 0;
  1878. *mask = 0;
  1879. PR_ASSERT(genname->data != NULL);
  1880. if (genname->data == NULL) {
  1881. return SECFailure;
  1882. }
  1883. if (genname->len != 8) {
  1884. /* the length must be 4 byte IP address with 4 byte subnet mask */
  1885. return SECFailure;
  1886. }
  1887. /* get them in the right order */
  1888. *constraint = PR_ntohl((PRUint32)(*genname->data));
  1889. *mask = PR_ntohl((PRUint32)(*(genname->data + 4)));
  1890. return SECSuccess;
  1891. }
  1892. static char* _str_to_lower(char* string)
  1893. {
  1894. #ifdef XP_WIN
  1895. return _strlwr(string);
  1896. #else
  1897. int i;
  1898. for (i = 0; string[i] != '\0'; i++) {
  1899. string[i] = tolower(string[i]);
  1900. }
  1901. return string;
  1902. #endif
  1903. }
  1904. /*
  1905. * Sees if the client certificate has a restriction in presenting the cert
  1906. * to the host: returns PR_TRUE if there is no restriction or if the hostname
  1907. * (and the port) satisfies the restriction, or PR_FALSE if the hostname (and
  1908. * the port) does not satisfy the restriction
  1909. */
  1910. static PRBool CERT_MatchesScopeOfUse(CERTCertificate* cert, char* hostname,
  1911. char* hostIP, PRIntn port)
  1912. {
  1913. PRBool rv = PR_TRUE; /* whether the cert can be presented */
  1914. SECStatus srv;
  1915. SECItem extData;
  1916. PRArenaPool* arena = NULL;
  1917. CERTCertificateScopeEntry** entries = NULL;
  1918. /* arrays of decoded scope entries */
  1919. int numEntries = 0;
  1920. int i;
  1921. char* hostLower = NULL;
  1922. PRUint32 hostIPAddr = 0;
  1923. PR_ASSERT((cert != NULL) && (hostname != NULL) && (hostIP != NULL));
  1924. /* find cert extension */
  1925. srv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_SCOPE_OF_USE,
  1926. &extData);
  1927. if (srv != SECSuccess) {
  1928. /* most of the time, this means the extension was not found: also,
  1929. * since this is not a critical extension (as of now) we may simply
  1930. * return PR_TRUE
  1931. */
  1932. goto done;
  1933. }
  1934. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1935. if (arena == NULL) {
  1936. goto done;
  1937. }
  1938. /* decode the scope of use entries into pairs of GeneralNames and
  1939. * an optional port numbers
  1940. */
  1941. srv = cert_DecodeScopeOfUseEntries(arena, &extData, &entries, &numEntries);
  1942. if (srv != SECSuccess) {
  1943. /* XXX What should we do when we failed to decode the extension? This
  1944. * may mean either the extension was malformed or some (unlikely)
  1945. * fatal error on our part: my argument is that if the extension
  1946. * was malformed the extension "disqualifies" as a valid
  1947. * constraint and we may present the cert
  1948. */
  1949. goto done;
  1950. }
  1951. /* loop over these structures */
  1952. for (i = 0; i < numEntries; i++) {
  1953. /* determine whether the GeneralName is a DNS pattern, an IP address
  1954. * constraint, or else
  1955. */
  1956. CERTGeneralName* genname = entries[i]->constraint;
  1957. /* if constraint is NULL, don't bother looking */
  1958. if (genname == NULL) {
  1959. /* this is not a failure: just continue */
  1960. continue;
  1961. }
  1962. switch (genname->type) {
  1963. case certDNSName: {
  1964. /* we have a DNS name constraint; we should use only the host name
  1965. * information
  1966. */
  1967. char* pattern = NULL;
  1968. char* substring = NULL;
  1969. /* null-terminate the string */
  1970. genname->name.other.data[genname->name.other.len] = '\0';
  1971. pattern = _str_to_lower((char*)genname->name.other.data);
  1972. if (hostLower == NULL) {
  1973. /* so that it's done only if necessary and only once */
  1974. hostLower = _str_to_lower(PL_strdup(hostname));
  1975. }
  1976. /* the hostname satisfies the constraint */
  1977. if (((substring = strstr(hostLower, pattern)) != NULL) &&
  1978. /* the hostname contains the pattern */
  1979. (strlen(substring) == strlen(pattern)) &&
  1980. /* the hostname ends with the pattern */
  1981. ((substring == hostLower) || (*(substring-1) == '.'))) {
  1982. /* the hostname either is identical to the pattern or
  1983. * belongs to a subdomain
  1984. */
  1985. rv = PR_TRUE;
  1986. }
  1987. else {
  1988. rv = PR_FALSE;
  1989. }
  1990. /* clean up strings if necessary */
  1991. break;
  1992. }
  1993. case certIPAddress: {
  1994. PRUint32 constraint;
  1995. PRUint32 mask;
  1996. PRNetAddr addr;
  1997. if (hostIPAddr == 0) {
  1998. /* so that it's done only if necessary and only once */
  1999. PR_StringToNetAddr(hostIP, &addr);
  2000. hostIPAddr = addr.inet.ip;
  2001. }
  2002. if (cert_DecodeCertIPAddress(&(genname->name.other), &constraint,
  2003. &mask) != SECSuccess) {
  2004. continue;
  2005. }
  2006. if ((hostIPAddr & mask) == (constraint & mask)) {
  2007. rv = PR_TRUE;
  2008. }
  2009. else {
  2010. rv = PR_FALSE;
  2011. }
  2012. break;
  2013. }
  2014. default:
  2015. /* ill-formed entry: abort */
  2016. continue; /* go to the next entry */
  2017. }
  2018. if (!rv) {
  2019. /* we do not need to check the port: go to the next entry */
  2020. continue;
  2021. }
  2022. /* finally, check the optional port number */
  2023. if ((entries[i]->port != 0) && (port != entries[i]->port)) {
  2024. /* port number does not match */
  2025. rv = PR_FALSE;
  2026. continue;
  2027. }
  2028. /* we have a match */
  2029. PR_ASSERT(rv);
  2030. break;
  2031. }
  2032. done:
  2033. /* clean up entries */
  2034. if (arena != NULL) {
  2035. PORT_FreeArena(arena, PR_FALSE);
  2036. }
  2037. if (hostLower != NULL) {
  2038. PR_Free(hostLower);
  2039. }
  2040. return rv;
  2041. }
  2042. #endif
  2043. /*
  2044. * Function: SSMStatus SSM_SetUserCertChoice()
  2045. * Purpose: sets certChoice by reading the preference
  2046. *
  2047. * Arguments and return values
  2048. * - conn: SSMSSLDataConnection
  2049. * - returns: SSM_SUCCESS if successful; SSM_FAILURE otherwise
  2050. *
  2051. * Note: If done properly, this function will read the identifier strings
  2052. * for ASK and AUTO modes, read the selected strings from the
  2053. * preference, compare the strings, and determine in which mode it is
  2054. * in.
  2055. * We currently use ASK mode for UI apps and AUTO mode for UI-less
  2056. * apps without really asking for preferences.
  2057. */
  2058. nsresult nsGetUserCertChoice(SSM_UserCertChoice* certChoice)
  2059. {
  2060. char *mode=NULL;
  2061. nsresult ret;
  2062. NS_ENSURE_ARG_POINTER(certChoice);
  2063. nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
  2064. ret = pref->GetCharPref("security.default_personal_cert", &mode);
  2065. if (NS_FAILED(ret)) {
  2066. goto loser;
  2067. }
  2068. if (PL_strcmp(mode, "Select Automatically") == 0) {
  2069. *certChoice = AUTO;
  2070. }
  2071. else if (PL_strcmp(mode, "Ask Every Time") == 0) {
  2072. *certChoice = ASK;
  2073. }
  2074. else {
  2075. // Most likely we see a nickname from a migrated cert.
  2076. // We do not currently support that, ask the user which cert to use.
  2077. *certChoice = ASK;
  2078. }
  2079. loser:
  2080. if (mode) {
  2081. nsMemory::Free(mode);
  2082. }
  2083. return ret;
  2084. }
  2085. static PRBool hasExplicitKeyUsageNonRepudiation(CERTCertificate *cert)
  2086. {
  2087. /* There is no extension, v1 or v2 certificate */
  2088. if (!cert->extensions)
  2089. return PR_FALSE;
  2090. SECStatus srv;
  2091. SECItem keyUsageItem;
  2092. keyUsageItem.data = NULL;
  2093. srv = CERT_FindKeyUsageExtension(cert, &keyUsageItem);
  2094. if (srv == SECFailure)
  2095. return PR_FALSE;
  2096. unsigned char keyUsage = keyUsageItem.data[0];
  2097. PORT_Free (keyUsageItem.data);
  2098. return (keyUsage & KU_NON_REPUDIATION);
  2099. }
  2100. /*
  2101. * Function: SECStatus SSM_SSLGetClientAuthData()
  2102. * Purpose: this callback function is used to pull client certificate
  2103. * information upon server request
  2104. *
  2105. * Arguments and return values
  2106. * - arg: SSL data connection
  2107. * - socket: SSL socket we're dealing with
  2108. * - caNames: list of CA names
  2109. * - pRetCert: returns a pointer to a pointer to a valid certificate if
  2110. * successful; otherwise NULL
  2111. * - pRetKey: returns a pointer to a pointer to the corresponding key if
  2112. * successful; otherwise NULL
  2113. * - returns: SECSuccess if successful; error code otherwise
  2114. */
  2115. SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket,
  2116. CERTDistNames* caNames,
  2117. CERTCertificate** pRetCert,
  2118. SECKEYPrivateKey** pRetKey)
  2119. {
  2120. nsNSSShutDownPreventionLock locker;
  2121. void* wincx = NULL;
  2122. SECStatus ret = SECFailure;
  2123. nsresult rv;
  2124. nsNSSSocketInfo* info = NULL;
  2125. PRArenaPool* arena = NULL;
  2126. char** caNameStrings;
  2127. CERTCertificate* cert = NULL;
  2128. CERTCertificate* serverCert = NULL;
  2129. SECKEYPrivateKey* privKey = NULL;
  2130. CERTCertList* certList = NULL;
  2131. CERTCertListNode* node;
  2132. CERTCertNicknames* nicknames = NULL;
  2133. char* extracted = NULL;
  2134. PRIntn keyError = 0; /* used for private key retrieval error */
  2135. SSM_UserCertChoice certChoice;
  2136. PRInt32 NumberOfCerts = 0;
  2137. /* do some argument checking */
  2138. if (socket == NULL || caNames == NULL || pRetCert == NULL ||
  2139. pRetKey == NULL) {
  2140. PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  2141. return SECFailure;
  2142. }
  2143. /* get PKCS11 pin argument */
  2144. wincx = SSL_RevealPinArg(socket);
  2145. if (wincx == NULL) {
  2146. return SECFailure;
  2147. }
  2148. /* get the socket info */
  2149. info = (nsNSSSocketInfo*)socket->higher->secret;
  2150. /* create caNameStrings */
  2151. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2152. if (arena == NULL) {
  2153. goto loser;
  2154. }
  2155. caNameStrings = (char**)PORT_ArenaAlloc(arena,
  2156. sizeof(char*)*(caNames->nnames));
  2157. if (caNameStrings == NULL) {
  2158. goto loser;
  2159. }
  2160. ret = nsConvertCANamesToStrings(arena, caNameStrings, caNames);
  2161. if (ret != SECSuccess) {
  2162. goto loser;
  2163. }
  2164. /* get the preference */
  2165. if (NS_FAILED(nsGetUserCertChoice(&certChoice))) {
  2166. goto loser;
  2167. }
  2168. /* find valid user cert and key pair */
  2169. if (certChoice == AUTO) {
  2170. /* automatically find the right cert */
  2171. /* find all user certs that are valid and for SSL */
  2172. certList = CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
  2173. certUsageSSLClient, PR_FALSE,
  2174. PR_TRUE, wincx);
  2175. if (certList == NULL) {
  2176. goto noCert;
  2177. }
  2178. /* filter the list to those issued by CAs supported by the server */
  2179. ret = CERT_FilterCertListByCANames(certList, caNames->nnames,
  2180. caNameStrings, certUsageSSLClient);
  2181. if (ret != SECSuccess) {
  2182. goto noCert;
  2183. }
  2184. /* make sure the list is not empty */
  2185. node = CERT_LIST_HEAD(certList);
  2186. if (CERT_LIST_END(node, certList)) {
  2187. goto noCert;
  2188. }
  2189. CERTCertificate* low_prio_nonrep_cert = NULL;
  2190. CERTCertificateCleaner low_prio_cleaner(low_prio_nonrep_cert);
  2191. /* loop through the list until we find a cert with a key */
  2192. while (!CERT_LIST_END(node, certList)) {
  2193. /* if the certificate has restriction and we do not satisfy it
  2194. * we do not use it
  2195. */
  2196. #if 0 /* XXX This must be re-enabled */
  2197. if (!CERT_MatchesScopeOfUse(node->cert, info->GetHostName,
  2198. info->GetHostIP, info->GetHostPort)) {
  2199. node = CERT_LIST_NEXT(node);
  2200. continue;
  2201. }
  2202. #endif
  2203. privKey = PK11_FindKeyByAnyCert(node->cert, wincx);
  2204. if (privKey != NULL) {
  2205. if (hasExplicitKeyUsageNonRepudiation(node->cert)) {
  2206. SECKEY_DestroyPrivateKey(privKey);
  2207. privKey = NULL;
  2208. // Not a prefered cert
  2209. if (!low_prio_nonrep_cert) // did not yet find a low prio cert
  2210. low_prio_nonrep_cert = CERT_DupCertificate(node->cert);
  2211. }
  2212. else {
  2213. // this is a good cert to present
  2214. cert = CERT_DupCertificate(node->cert);
  2215. break;
  2216. }
  2217. }
  2218. keyError = PR_GetError();
  2219. if (keyError == SEC_ERROR_BAD_PASSWORD) {
  2220. /* problem with password: bail */
  2221. goto loser;
  2222. }
  2223. node = CERT_LIST_NEXT(node);
  2224. }
  2225. if (!cert && low_prio_nonrep_cert) {
  2226. cert = low_prio_nonrep_cert;
  2227. low_prio_nonrep_cert = NULL; // take it away from the cleaner
  2228. privKey = PK11_FindKeyByAnyCert(cert, wincx);
  2229. }
  2230. if (cert == NULL) {
  2231. goto noCert;
  2232. }
  2233. }
  2234. else {
  2235. /* user selects a cert to present */
  2236. nsIClientAuthDialogs *dialogs = NULL;
  2237. PRInt32 selectedIndex = -1;
  2238. PRUnichar **certNicknameList = NULL;
  2239. PRUnichar **certDetailsList = NULL;
  2240. PRBool canceled;
  2241. /* find all user certs that are for SSL */
  2242. /* note that we are allowing expired certs in this list */
  2243. certList = CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
  2244. certUsageSSLClient, PR_FALSE,
  2245. PR_FALSE, wincx);
  2246. if (certList == NULL) {
  2247. goto noCert;
  2248. }
  2249. if (caNames->nnames != 0) {
  2250. /* filter the list to those issued by CAs supported by the
  2251. * server
  2252. */
  2253. ret = CERT_FilterCertListByCANames(certList, caNames->nnames,
  2254. caNameStrings,
  2255. certUsageSSLClient);
  2256. if (ret != SECSuccess) {
  2257. goto loser;
  2258. }
  2259. }
  2260. if (CERT_LIST_END(CERT_LIST_HEAD(certList), certList)) {
  2261. /* list is empty - no matching certs */
  2262. goto noCert;
  2263. }
  2264. /* filter it further for hostname restriction */
  2265. node = CERT_LIST_HEAD(certList);
  2266. while (!CERT_LIST_END(node, certList)) {
  2267. ++NumberOfCerts;
  2268. #if 0 /* XXX Fix this */
  2269. if (!CERT_MatchesScopeOfUse(node->cert, conn->hostName,
  2270. conn->hostIP, conn->port)) {
  2271. CERTCertListNode* removed = node;
  2272. node = CERT_LIST_NEXT(removed);
  2273. CERT_RemoveCertListNode(removed);
  2274. }
  2275. else {
  2276. node = CERT_LIST_NEXT(node);
  2277. }
  2278. #endif
  2279. node = CERT_LIST_NEXT(node);
  2280. }
  2281. if (CERT_LIST_END(CERT_LIST_HEAD(certList), certList)) {
  2282. goto noCert;
  2283. }
  2284. nicknames = getNSSCertNicknamesFromCertList(certList);
  2285. if (nicknames == NULL) {
  2286. goto loser;
  2287. }
  2288. NS_ASSERTION(nicknames->numnicknames == NumberOfCerts, "nicknames->numnicknames != NumberOfCerts");
  2289. /* Get the SSL Certificate */
  2290. serverCert = SSL_PeerCertificate(socket);
  2291. if (serverCert == NULL) {
  2292. /* couldn't get the server cert: what do I do? */
  2293. goto loser;
  2294. }
  2295. /* Get CN and O of the subject and O of the issuer */
  2296. char *ccn = CERT_GetCommonName(&serverCert->subject);
  2297. charCleaner ccnCleaner(ccn);
  2298. NS_ConvertUTF8toUTF16 cn(ccn);
  2299. PRInt32 port;
  2300. info->GetPort(&port);
  2301. char *hostname = SSL_RevealURL(socket);
  2302. charCleaner hostnameCleaner(hostname);
  2303. nsString cn_host_port;
  2304. if (ccn && strcmp(ccn, hostname) == 0) {
  2305. cn_host_port.Append(cn);
  2306. cn_host_port.AppendLiteral(":");
  2307. cn_host_port.AppendInt(port);
  2308. }
  2309. else {
  2310. cn_host_port.Append(cn);
  2311. cn_host_port.AppendLiteral(" (");
  2312. cn_host_port.AppendLiteral(":");
  2313. cn_host_port.AppendInt(port);
  2314. cn_host_port.AppendLiteral(")");
  2315. }
  2316. char *corg = CERT_GetOrgName(&serverCert->subject);
  2317. NS_ConvertUTF8toUTF16 org(corg);
  2318. if (corg) PORT_Free(corg);
  2319. char *cissuer = CERT_GetOrgName(&serverCert->issuer);
  2320. NS_ConvertUTF8toUTF16 issuer(cissuer);
  2321. if (cissuer) PORT_Free(cissuer);
  2322. CERT_DestroyCertificate(serverCert);
  2323. certNicknameList = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * nicknames->numnicknames);
  2324. if (!certNicknameList)
  2325. goto loser;
  2326. certDetailsList = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * nicknames->numnicknames);
  2327. if (!certDetailsList) {
  2328. nsMemory::Free(certNicknameList);
  2329. goto loser;
  2330. }
  2331. PRInt32 CertsToUse;
  2332. for (CertsToUse = 0, node = CERT_LIST_HEAD(certList);
  2333. !CERT_LIST_END(node, certList) && CertsToUse < nicknames->numnicknames;
  2334. node = CERT_LIST_NEXT(node)
  2335. )
  2336. {
  2337. nsRefPtr<nsNSSCertificate> tempCert = new nsNSSCertificate(node->cert);
  2338. if (!tempCert)
  2339. continue;
  2340. NS_ConvertUTF8toUTF16 i_nickname(nicknames->nicknames[CertsToUse]);
  2341. nsAutoString nickWithSerial, details;
  2342. if (NS_FAILED(tempCert->FormatUIStrings(i_nickname, nickWithSerial, details)))
  2343. continue;
  2344. certNicknameList[CertsToUse] = ToNewUnicode(nickWithSerial);
  2345. if (!certNicknameList[CertsToUse])
  2346. continue;
  2347. certDetailsList[CertsToUse] = ToNewUnicode(details);
  2348. if (!certDetailsList[CertsToUse]) {
  2349. nsMemory::Free(certNicknameList[CertsToUse]);
  2350. continue;
  2351. }
  2352. ++CertsToUse;
  2353. }
  2354. /* Throw up the client auth dialog and get back the index of the selected cert */
  2355. rv = getNSSDialogs((void**)&dialogs,
  2356. NS_GET_IID(nsIClientAuthDialogs),
  2357. NS_CLIENTAUTHDIALOGS_CONTRACTID);
  2358. if (NS_FAILED(rv)) {
  2359. NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certNicknameList);
  2360. NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certDetailsList);
  2361. goto loser;
  2362. }
  2363. {
  2364. nsPSMUITracker tracker;
  2365. if (tracker.isUIForbidden()) {
  2366. rv = NS_ERROR_NOT_AVAILABLE;
  2367. }
  2368. else {
  2369. rv = dialogs->ChooseCertificate(info, cn_host_port.get(), org.get(), issuer.get(),
  2370. (const PRUnichar**)certNicknameList, (const PRUnichar**)certDetailsList,
  2371. CertsToUse, &selectedIndex, &canceled);
  2372. }
  2373. }
  2374. NS_RELEASE(dialogs);
  2375. NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certNicknameList);
  2376. NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certDetailsList);
  2377. if (NS_FAILED(rv)) goto loser;
  2378. if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
  2379. int i;
  2380. for (i = 0, node = CERT_LIST_HEAD(certList);
  2381. !CERT_LIST_END(node, certList);
  2382. ++i, node = CERT_LIST_NEXT(node)) {
  2383. if (i == selectedIndex) {
  2384. cert = CERT_DupCertificate(node->cert);
  2385. break;
  2386. }
  2387. }
  2388. if (cert == NULL) {
  2389. goto loser;
  2390. }
  2391. /* go get the private key */
  2392. privKey = PK11_FindKeyByAnyCert(cert, wincx);
  2393. if (privKey == NULL) {
  2394. keyError = PR_GetError();
  2395. if (keyError == SEC_ERROR_BAD_PASSWORD) {
  2396. /* problem with password: bail */
  2397. goto loser;
  2398. }
  2399. else {
  2400. goto noCert;
  2401. }
  2402. }
  2403. }
  2404. goto done;
  2405. noCert:
  2406. loser:
  2407. if (ret == SECSuccess) {
  2408. ret = SECFailure;
  2409. }
  2410. if (cert != NULL) {
  2411. CERT_DestroyCertificate(cert);
  2412. cert = NULL;
  2413. }
  2414. done:
  2415. if (extracted != NULL) {
  2416. PR_Free(extracted);
  2417. }
  2418. if (nicknames != NULL) {
  2419. CERT_FreeNicknames(nicknames);
  2420. }
  2421. if (certList != NULL) {
  2422. CERT_DestroyCertList(certList);
  2423. }
  2424. if (arena != NULL) {
  2425. PORT_FreeArena(arena, PR_FALSE);
  2426. }
  2427. *pRetCert = cert;
  2428. *pRetKey = privKey;
  2429. return ret;
  2430. }
  2431. static SECStatus
  2432. cancel_and_failure(nsNSSSocketInfo* infoObject)
  2433. {
  2434. infoObject->SetCanceled(PR_TRUE);
  2435. return SECFailure;
  2436. }
  2437. static SECStatus
  2438. nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket)
  2439. {
  2440. nsNSSShutDownPreventionLock locker;
  2441. nsNSSSocketInfo* infoObject = (nsNSSSocketInfo *)arg;
  2442. if (!infoObject)
  2443. return SECFailure;
  2444. if (nsSSLThread::exitRequested())
  2445. return cancel_and_failure(infoObject);
  2446. CERTCertificate *peerCert = nsnull;
  2447. CERTCertificateCleaner peerCertCleaner(peerCert);
  2448. peerCert = SSL_PeerCertificate(sslSocket);
  2449. if (!peerCert)
  2450. return cancel_and_failure(infoObject);
  2451. nsRefPtr<nsNSSCertificate> nssCert;
  2452. nssCert = new nsNSSCertificate(peerCert);
  2453. if (!nssCert)
  2454. return cancel_and_failure(infoObject);
  2455. nsCOMPtr<nsIX509Cert> ix509 = static_cast<nsIX509Cert*>(nssCert.get());
  2456. SECStatus srv;
  2457. nsresult nsrv;
  2458. PRUint32 collected_errors = 0;
  2459. PRUint32 remaining_display_errors = 0;
  2460. PRErrorCode errorCodeTrust = SECSuccess;
  2461. PRErrorCode errorCodeMismatch = SECSuccess;
  2462. PRErrorCode errorCodeExpired = SECSuccess;
  2463. char *hostname = SSL_RevealURL(sslSocket);
  2464. charCleaner hostnameCleaner(hostname);
  2465. nsDependentCString hostString(hostname);
  2466. PRInt32 port;
  2467. infoObject->GetPort(&port);
  2468. nsCString hostWithPortString = hostString;
  2469. hostWithPortString.AppendLiteral(":");
  2470. hostWithPortString.AppendInt(port);
  2471. NS_ConvertUTF8toUTF16 hostWithPortStringUTF16(hostWithPortString);
  2472. // Check the name field against the desired hostname.
  2473. if (hostname && hostname[0] &&
  2474. CERT_VerifyCertName(peerCert, hostname) != SECSuccess) {
  2475. collected_errors |= nsICertOverrideService::ERROR_MISMATCH;
  2476. errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN;
  2477. }
  2478. {
  2479. PRArenaPool *log_arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2480. if (!log_arena)
  2481. return cancel_and_failure(infoObject);
  2482. PRArenaPoolCleanerFalseParam log_arena_cleaner(log_arena);
  2483. CERTVerifyLog *verify_log = PORT_ArenaZNew(log_arena, CERTVerifyLog);
  2484. if (!verify_log)
  2485. return cancel_and_failure(infoObject);
  2486. CERTVerifyLogContentsCleaner verify_log_cleaner(verify_log);
  2487. verify_log->arena = log_arena;
  2488. srv = CERT_VerifyCertificate(CERT_GetDefaultCertDB(), peerCert,
  2489. PR_TRUE, certificateUsageSSLServer,
  2490. PR_Now(), (void*)infoObject,
  2491. verify_log, NULL);
  2492. // We ignore the result code of the cert verification.
  2493. // Either it is a failure, which is expected, and we'll process the
  2494. // verify log below.
  2495. // Or it is a success, then a domain mismatch is the only
  2496. // possible failure.
  2497. CERTVerifyLogNode *i_node;
  2498. for (i_node = verify_log->head; i_node; i_node = i_node->next)
  2499. {
  2500. switch (i_node->error)
  2501. {
  2502. case SEC_ERROR_UNKNOWN_ISSUER:
  2503. case SEC_ERROR_CA_CERT_INVALID:
  2504. case SEC_ERROR_UNTRUSTED_ISSUER:
  2505. case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
  2506. case SEC_ERROR_UNTRUSTED_CERT:
  2507. case SEC_ERROR_INADEQUATE_KEY_USAGE:
  2508. // We group all these errors as "cert not trusted"
  2509. collected_errors |= nsICertOverrideService::ERROR_UNTRUSTED;
  2510. if (errorCodeTrust == SECSuccess) {
  2511. errorCodeTrust = i_node->error;
  2512. }
  2513. break;
  2514. case SSL_ERROR_BAD_CERT_DOMAIN:
  2515. collected_errors |= nsICertOverrideService::ERROR_MISMATCH;
  2516. if (errorCodeMismatch == SECSuccess) {
  2517. errorCodeMismatch = i_node->error;
  2518. }
  2519. break;
  2520. case SEC_ERROR_EXPIRED_CERTIFICATE:
  2521. collected_errors |= nsICertOverrideService::ERROR_TIME;
  2522. if (errorCodeExpired == SECSuccess) {
  2523. errorCodeExpired = i_node->error;
  2524. }
  2525. break;
  2526. default:
  2527. // we are not willing to continue on any other error
  2528. nsHandleSSLError(infoObject, i_node->error);
  2529. // this error is our stop condition, so let's make sure
  2530. // this error code will be reported to the external world.
  2531. PR_SetError(i_node->error, 0);
  2532. return cancel_and_failure(infoObject);
  2533. }
  2534. }
  2535. }
  2536. if (!collected_errors)
  2537. {
  2538. NS_NOTREACHED("why did NSS call our bad cert handler if all looks good? Let's cancel the connection");
  2539. return SECFailure;
  2540. }
  2541. nsRefPtr<nsSSLStatus> status = infoObject->SSLStatus();
  2542. if (!status) {
  2543. status = new nsSSLStatus();
  2544. infoObject->SetSSLStatus(status);
  2545. }
  2546. if (status) {
  2547. if (!status->mServerCert) {
  2548. status->mServerCert = nssCert;
  2549. }
  2550. status->mHaveCertErrorBits = PR_TRUE;
  2551. status->mIsDomainMismatch = collected_errors & nsICertOverrideService::ERROR_MISMATCH;
  2552. status->mIsNotValidAtThisTime = collected_errors & nsICertOverrideService::ERROR_TIME;
  2553. status->mIsUntrusted = collected_errors & nsICertOverrideService::ERROR_UNTRUSTED;
  2554. }
  2555. remaining_display_errors = collected_errors;
  2556. nsCOMPtr<nsICertOverrideService> overrideService =
  2557. do_GetService(NS_CERTOVERRIDE_CONTRACTID);
  2558. // it is fine to continue without the nsICertOverrideService
  2559. PRUint32 overrideBits = 0;
  2560. if (overrideService)
  2561. {
  2562. PRBool haveOverride;
  2563. PRBool isTemporaryOverride; // we don't care
  2564. nsrv = overrideService->HasMatchingOverride(hostString, port,
  2565. ix509,
  2566. &overrideBits,
  2567. &isTemporaryOverride,
  2568. &haveOverride);
  2569. if (NS_SUCCEEDED(nsrv) && haveOverride)
  2570. {
  2571. // remove the errors that are already overriden
  2572. remaining_display_errors -= overrideBits;
  2573. }
  2574. }
  2575. if (!remaining_display_errors) {
  2576. // all errors are covered by override rules, so let's accept the cert
  2577. return SECSuccess;
  2578. }
  2579. // Ok, this is a full stop.
  2580. // First, deliver the technical details of the broken SSL status,
  2581. // giving the caller a chance to suppress the error messages.
  2582. PRBool suppressMessage = PR_FALSE;
  2583. nsresult rv;
  2584. // Try to get a nsIBadCertListener2 implementation from the socket consumer.
  2585. nsCOMPtr<nsIInterfaceRequestor> cb;
  2586. infoObject->GetNotificationCallbacks(getter_AddRefs(cb));
  2587. if (cb) {
  2588. nsCOMPtr<nsIInterfaceRequestor> callbacks;
  2589. NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
  2590. NS_GET_IID(nsIInterfaceRequestor),
  2591. cb,
  2592. NS_PROXY_SYNC,
  2593. getter_AddRefs(callbacks));
  2594. nsCOMPtr<nsIBadCertListener2> bcl = do_GetInterface(callbacks);
  2595. if (bcl) {
  2596. nsIBadCertListener2 *proxy_bcl = nsnull;
  2597. NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
  2598. NS_GET_IID(nsIBadCertListener2),
  2599. bcl,
  2600. NS_PROXY_SYNC,
  2601. (void**)&proxy_bcl);
  2602. if (proxy_bcl) {
  2603. nsIInterfaceRequestor *csi = static_cast<nsIInterfaceRequestor*>(infoObject);
  2604. rv = proxy_bcl->NotifyCertProblem(csi, status, hostWithPortString,
  2605. &suppressMessage);
  2606. }
  2607. }
  2608. }
  2609. nsCOMPtr<nsIRecentBadCertsService> recentBadCertsService =
  2610. do_GetService(NS_RECENTBADCERTS_CONTRACTID);
  2611. if (recentBadCertsService) {
  2612. recentBadCertsService->AddBadCert(hostWithPortStringUTF16, status);
  2613. }
  2614. // pick the error code to report by priority
  2615. PRErrorCode errorCodeToReport = SECSuccess;
  2616. if (remaining_display_errors & nsICertOverrideService::ERROR_UNTRUSTED)
  2617. errorCodeToReport = errorCodeTrust;
  2618. else if (remaining_display_errors & nsICertOverrideService::ERROR_MISMATCH)
  2619. errorCodeToReport = errorCodeMismatch;
  2620. else if (remaining_display_errors & nsICertOverrideService::ERROR_TIME)
  2621. errorCodeToReport = errorCodeExpired;
  2622. if (!suppressMessage) {
  2623. nsHandleInvalidCertError(infoObject,
  2624. remaining_display_errors,
  2625. hostString,
  2626. hostWithPortString,
  2627. port,
  2628. errorCodeToReport,
  2629. errorCodeTrust,
  2630. errorCodeMismatch,
  2631. errorCodeExpired,
  2632. ix509);
  2633. }
  2634. PR_SetError(errorCodeToReport, 0);
  2635. return cancel_and_failure(infoObject);
  2636. }
  2637. static PRFileDesc*
  2638. nsSSLIOLayerImportFD(PRFileDesc *fd,
  2639. nsNSSSocketInfo *infoObject,
  2640. const char *host)
  2641. {
  2642. nsNSSShutDownPreventionLock locker;
  2643. PRFileDesc* sslSock = SSL_ImportFD(nsnull, fd);
  2644. if (!sslSock) {
  2645. NS_ASSERTION(PR_FALSE, "NSS: Error importing socket");
  2646. return nsnull;
  2647. }
  2648. SSL_SetPKCS11PinArg(sslSock, (nsIInterfaceRequestor*)infoObject);
  2649. SSL_HandshakeCallback(sslSock, HandshakeCallback, infoObject);
  2650. SSL_GetClientAuthDataHook(sslSock,
  2651. (SSLGetClientAuthData)nsNSS_SSLGetClientAuthData,
  2652. infoObject);
  2653. SSL_AuthCertificateHook(sslSock, AuthCertificateCallback, 0);
  2654. PRInt32 ret = SSL_SetURL(sslSock, host);
  2655. if (ret == -1) {
  2656. NS_ASSERTION(PR_FALSE, "NSS: Error setting server name");
  2657. goto loser;
  2658. }
  2659. return sslSock;
  2660. loser:
  2661. if (sslSock) {
  2662. PR_Close(sslSock);
  2663. }
  2664. return nsnull;
  2665. }
  2666. static nsresult
  2667. nsSSLIOLayerSetOptions(PRFileDesc *fd, PRBool forSTARTTLS,
  2668. const char *proxyHost, const char *host, PRInt32 port,
  2669. nsNSSSocketInfo *infoObject)
  2670. {
  2671. nsNSSShutDownPreventionLock locker;
  2672. if (forSTARTTLS || proxyHost) {
  2673. if (SECSuccess != SSL_OptionSet(fd, SSL_SECURITY, PR_FALSE)) {
  2674. return NS_ERROR_FAILURE;
  2675. }
  2676. infoObject->SetHasCleartextPhase(PR_TRUE);
  2677. }
  2678. if (forSTARTTLS) {
  2679. if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_SSL2, PR_FALSE)) {
  2680. return NS_ERROR_FAILURE;
  2681. }
  2682. if (SECSuccess != SSL_OptionSet(fd, SSL_V2_COMPATIBLE_HELLO, PR_FALSE)) {
  2683. return NS_ERROR_FAILURE;
  2684. }
  2685. }
  2686. // Let's see if we're trying to connect to a site we know is
  2687. // TLS intolerant.
  2688. nsCAutoString key;
  2689. key = nsDependentCString(host) + NS_LITERAL_CSTRING(":") + nsPrintfCString("%d", port);
  2690. if (nsSSLIOLayerHelpers::isKnownAsIntolerantSite(key)) {
  2691. if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_TLS, PR_FALSE))
  2692. return NS_ERROR_FAILURE;
  2693. infoObject->SetAllowTLSIntoleranceTimeout(PR_FALSE);
  2694. // We assume that protocols that use the STARTTLS mechanism should support
  2695. // modern hellos. For other protocols, if we suspect a site
  2696. // does not support TLS, let's also use V2 hellos.
  2697. // One advantage of this approach, if a site only supports the older
  2698. // hellos, it is more likely that we will get a reasonable error code
  2699. // on our single retry attempt.
  2700. if (!forSTARTTLS &&
  2701. SECSuccess != SSL_OptionSet(fd, SSL_V2_COMPATIBLE_HELLO, PR_TRUE))
  2702. return NS_ERROR_FAILURE;
  2703. }
  2704. if (SECSuccess != SSL_OptionSet(fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE)) {
  2705. return NS_ERROR_FAILURE;
  2706. }
  2707. if (SECSuccess != SSL_BadCertHook(fd, (SSLBadCertHandler) nsNSSBadCertHandler,
  2708. infoObject)) {
  2709. return NS_ERROR_FAILURE;
  2710. }
  2711. // Set the Peer ID so that SSL proxy connections work properly.
  2712. char *peerId = PR_smprintf("%s:%d", host, port);
  2713. if (SECSuccess != SSL_SetSockPeerID(fd, peerId)) {
  2714. PR_smprintf_free(peerId);
  2715. return NS_ERROR_FAILURE;
  2716. }
  2717. PR_smprintf_free(peerId);
  2718. return NS_OK;
  2719. }
  2720. nsresult
  2721. nsSSLIOLayerAddToSocket(PRInt32 family,
  2722. const char* host,
  2723. PRInt32 port,
  2724. const char* proxyHost,
  2725. PRInt32 proxyPort,
  2726. PRFileDesc* fd,
  2727. nsISupports** info,
  2728. PRBool forSTARTTLS)
  2729. {
  2730. nsNSSShutDownPreventionLock locker;
  2731. PRFileDesc* layer = nsnull;
  2732. nsresult rv;
  2733. nsNSSSocketInfo* infoObject = new nsNSSSocketInfo();
  2734. if (!infoObject) return NS_ERROR_FAILURE;
  2735. NS_ADDREF(infoObject);
  2736. infoObject->SetForSTARTTLS(forSTARTTLS);
  2737. infoObject->SetHostName(host);
  2738. infoObject->SetPort(port);
  2739. PRFileDesc *sslSock = nsSSLIOLayerImportFD(fd, infoObject, host);
  2740. if (!sslSock) {
  2741. NS_ASSERTION(PR_FALSE, "NSS: Error importing socket");
  2742. goto loser;
  2743. }
  2744. infoObject->SetFileDescPtr(sslSock);
  2745. rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, proxyHost, host, port,
  2746. infoObject);
  2747. if (NS_FAILED(rv))
  2748. goto loser;
  2749. /* Now, layer ourselves on top of the SSL socket... */
  2750. layer = PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLIOLayerIdentity,
  2751. &nsSSLIOLayerHelpers::nsSSLIOLayerMethods);
  2752. if (!layer)
  2753. goto loser;
  2754. layer->secret = (PRFilePrivate*) infoObject;
  2755. rv = PR_PushIOLayer(sslSock, PR_GetLayersIdentity(sslSock), layer);
  2756. if (NS_FAILED(rv)) {
  2757. goto loser;
  2758. }
  2759. nsNSSShutDownList::trackSSLSocketCreate();
  2760. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] Socket set up\n", (void*)sslSock));
  2761. infoObject->QueryInterface(NS_GET_IID(nsISupports), (void**) (info));
  2762. // We are going use a clear connection first //
  2763. if (forSTARTTLS || proxyHost) {
  2764. infoObject->SetHandshakePending(PR_FALSE);
  2765. }
  2766. return NS_OK;
  2767. loser:
  2768. NS_IF_RELEASE(infoObject);
  2769. if (layer) {
  2770. layer->dtor(layer);
  2771. }
  2772. return NS_ERROR_FAILURE;
  2773. }