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

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

http://github.com/zpao/v8monkey
C++ | 3656 lines | 2687 code | 541 blank | 428 comment | 506 complexity | 2d05e328bccca59597b112725aedb031 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, LGPL-2.1, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2. *
  3. * ***** BEGIN LICENSE BLOCK *****
  4. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5. *
  6. * The contents of this file are subject to the Mozilla Public License Version
  7. * 1.1 (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. * http://www.mozilla.org/MPL/
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. *
  16. * The Original Code is mozilla.org code.
  17. *
  18. * The Initial Developer of the Original Code is
  19. * Netscape Communications Corporation.
  20. * Portions created by the Initial Developer are Copyright (C) 1998
  21. * the Initial Developer. All Rights Reserved.
  22. *
  23. * Contributor(s):
  24. * 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 "nsIPrefService.h"
  47. #include "nsIPrefBranch.h"
  48. #include "nsIServiceManager.h"
  49. #include "nsIWebProgressListener.h"
  50. #include "nsIChannel.h"
  51. #include "nsNSSCertificate.h"
  52. #include "nsIX509CertValidity.h"
  53. #include "nsIDateTimeFormat.h"
  54. #include "nsDateTimeFormatCID.h"
  55. #include "nsIClientAuthDialogs.h"
  56. #include "nsClientAuthRemember.h"
  57. #include "nsICertOverrideService.h"
  58. #include "nsISSLErrorListener.h"
  59. #include "nsIObjectInputStream.h"
  60. #include "nsIObjectOutputStream.h"
  61. #include "nsXPIDLString.h"
  62. #include "nsReadableUtils.h"
  63. #include "nsHashSets.h"
  64. #include "nsCRT.h"
  65. #include "nsAutoPtr.h"
  66. #include "nsPrintfCString.h"
  67. #include "SSLServerCertVerification.h"
  68. #include "nsNSSShutDown.h"
  69. #include "nsSSLStatus.h"
  70. #include "nsNSSCertHelper.h"
  71. #include "nsNSSCleaner.h"
  72. #include "nsIDocShell.h"
  73. #include "nsIDocShellTreeItem.h"
  74. #include "nsISecureBrowserUI.h"
  75. #include "nsIClassInfoImpl.h"
  76. #include "nsIProgrammingLanguage.h"
  77. #include "nsIArray.h"
  78. #include "nsCharSeparatedTokenizer.h"
  79. #include "PSMRunnable.h"
  80. #include "ssl.h"
  81. #include "secerr.h"
  82. #include "sslerr.h"
  83. #include "secder.h"
  84. #include "secasn1.h"
  85. #include "certdb.h"
  86. #include "cert.h"
  87. #include "keyhi.h"
  88. #include "mozilla/Util.h"
  89. using namespace mozilla;
  90. using namespace mozilla::psm;
  91. //#define DEBUG_SSL_VERBOSE //Enable this define to get minimal
  92. //reports when doing SSL read/write
  93. //#define DUMP_BUFFER //Enable this define along with
  94. //DEBUG_SSL_VERBOSE to dump SSL
  95. //read/write buffer to a log.
  96. //Uses PR_LOG except on Mac where
  97. //we always write out to our own
  98. //file.
  99. NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
  100. NSSCleanupAutoPtrClass(void, PR_FREEIF)
  101. static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  102. /* SSM_UserCertChoice: enum for cert choice info */
  103. typedef enum {ASK, AUTO} SSM_UserCertChoice;
  104. #ifdef PR_LOGGING
  105. extern PRLogModuleInfo* gPIPNSSLog;
  106. #endif
  107. #if defined(DEBUG_SSL_VERBOSE) && defined (XP_MAC)
  108. #ifdef PR_LOG
  109. #undef PR_LOG
  110. #endif
  111. static PRFileDesc *gMyLogFile = nsnull;
  112. #define MAC_LOG_FILE "MAC PIPNSS Log File"
  113. void MyLogFunction(const char *fmt, ...)
  114. {
  115. va_list ap;
  116. va_start(ap,fmt);
  117. if (gMyLogFile == nsnull)
  118. gMyLogFile = PR_Open(MAC_LOG_FILE, PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
  119. 0600);
  120. if (!gMyLogFile)
  121. return;
  122. PR_vfprintf(gMyLogFile, fmt, ap);
  123. va_end(ap);
  124. }
  125. #define PR_LOG(module,level,args) MyLogFunction args
  126. #endif
  127. nsNSSSocketInfo::nsNSSSocketInfo()
  128. : mMutex("nsNSSSocketInfo::nsNSSSocketInfo"),
  129. mFd(nsnull),
  130. mCertVerificationState(before_cert_verification),
  131. mCertVerificationStarted(0),
  132. mCertVerificationEnded(0),
  133. mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE),
  134. mSubRequestsHighSecurity(0),
  135. mSubRequestsLowSecurity(0),
  136. mSubRequestsBrokenSecurity(0),
  137. mSubRequestsNoSecurity(0),
  138. mErrorCode(0),
  139. mErrorMessageType(PlainErrorMessage),
  140. mForSTARTTLS(false),
  141. mSSL3Enabled(false),
  142. mTLSEnabled(false),
  143. mHandshakePending(true),
  144. mHasCleartextPhase(false),
  145. mHandshakeInProgress(false),
  146. mAllowTLSIntoleranceTimeout(true),
  147. mRememberClientAuthCertificate(false),
  148. mHandshakeStartTime(0),
  149. mPort(0),
  150. mIsCertIssuerBlacklisted(false),
  151. mNPNCompleted(false),
  152. mHandshakeCompleted(false),
  153. mJoined(false),
  154. mSentClientCert(false)
  155. {
  156. }
  157. nsNSSSocketInfo::~nsNSSSocketInfo()
  158. {
  159. nsNSSShutDownPreventionLock locker;
  160. if (isAlreadyShutDown())
  161. return;
  162. shutdown(calledFromObject);
  163. }
  164. void nsNSSSocketInfo::virtualDestroyNSSReference()
  165. {
  166. }
  167. NS_IMPL_THREADSAFE_ISUPPORTS8(nsNSSSocketInfo,
  168. nsITransportSecurityInfo,
  169. nsISSLSocketControl,
  170. nsIInterfaceRequestor,
  171. nsISSLStatusProvider,
  172. nsIAssociatedContentSecurity,
  173. nsISerializable,
  174. nsIClassInfo,
  175. nsIClientAuthUserDecision)
  176. nsresult
  177. nsNSSSocketInfo::GetHandshakePending(bool *aHandshakePending)
  178. {
  179. *aHandshakePending = mHandshakePending;
  180. return NS_OK;
  181. }
  182. nsresult
  183. nsNSSSocketInfo::SetHandshakePending(bool aHandshakePending)
  184. {
  185. mHandshakePending = aHandshakePending;
  186. return NS_OK;
  187. }
  188. nsresult
  189. nsNSSSocketInfo::SetHostName(const char* host)
  190. {
  191. mHostName.Adopt(host ? NS_strdup(host) : 0);
  192. return NS_OK;
  193. }
  194. nsresult
  195. nsNSSSocketInfo::GetHostName(char **host)
  196. {
  197. *host = (mHostName) ? NS_strdup(mHostName) : nsnull;
  198. return NS_OK;
  199. }
  200. nsresult
  201. nsNSSSocketInfo::SetPort(PRInt32 aPort)
  202. {
  203. mPort = aPort;
  204. return NS_OK;
  205. }
  206. nsresult
  207. nsNSSSocketInfo::GetPort(PRInt32 *aPort)
  208. {
  209. *aPort = mPort;
  210. return NS_OK;
  211. }
  212. PRErrorCode
  213. nsNSSSocketInfo::GetErrorCode() const
  214. {
  215. MutexAutoLock lock(mMutex);
  216. return mErrorCode;
  217. }
  218. void
  219. nsNSSSocketInfo::SetCanceled(PRErrorCode errorCode,
  220. SSLErrorMessageType errorMessageType)
  221. {
  222. MutexAutoLock lock(mMutex);
  223. mErrorCode = errorCode;
  224. mErrorMessageType = errorMessageType;
  225. mErrorMessageCached.Truncate();
  226. }
  227. NS_IMETHODIMP nsNSSSocketInfo::GetRememberClientAuthCertificate(bool *aRememberClientAuthCertificate)
  228. {
  229. NS_ENSURE_ARG_POINTER(aRememberClientAuthCertificate);
  230. *aRememberClientAuthCertificate = mRememberClientAuthCertificate;
  231. return NS_OK;
  232. }
  233. NS_IMETHODIMP nsNSSSocketInfo::SetRememberClientAuthCertificate(bool aRememberClientAuthCertificate)
  234. {
  235. mRememberClientAuthCertificate = aRememberClientAuthCertificate;
  236. return NS_OK;
  237. }
  238. void nsNSSSocketInfo::SetHasCleartextPhase(bool aHasCleartextPhase)
  239. {
  240. mHasCleartextPhase = aHasCleartextPhase;
  241. }
  242. bool nsNSSSocketInfo::GetHasCleartextPhase()
  243. {
  244. return mHasCleartextPhase;
  245. }
  246. NS_IMETHODIMP
  247. nsNSSSocketInfo::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks)
  248. {
  249. *aCallbacks = mCallbacks;
  250. NS_IF_ADDREF(*aCallbacks);
  251. return NS_OK;
  252. }
  253. NS_IMETHODIMP
  254. nsNSSSocketInfo::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
  255. {
  256. if (!aCallbacks) {
  257. mCallbacks = nsnull;
  258. return NS_OK;
  259. }
  260. mCallbacks = aCallbacks;
  261. return NS_OK;
  262. }
  263. static void
  264. getSecureBrowserUI(nsIInterfaceRequestor * callbacks,
  265. nsISecureBrowserUI ** result)
  266. {
  267. NS_ASSERTION(result != nsnull, "result parameter to getSecureBrowserUI is null");
  268. *result = nsnull;
  269. NS_ASSERTION(NS_IsMainThread(),
  270. "getSecureBrowserUI called off the main thread");
  271. if (!callbacks)
  272. return;
  273. nsCOMPtr<nsISecureBrowserUI> secureUI = do_GetInterface(callbacks);
  274. if (secureUI) {
  275. secureUI.forget(result);
  276. return;
  277. }
  278. nsCOMPtr<nsIDocShellTreeItem> item = do_GetInterface(callbacks);
  279. if (item) {
  280. nsCOMPtr<nsIDocShellTreeItem> rootItem;
  281. (void) item->GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
  282. nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(rootItem);
  283. if (docShell) {
  284. (void) docShell->GetSecurityUI(result);
  285. }
  286. }
  287. }
  288. NS_IMETHODIMP
  289. nsNSSSocketInfo::GetSecurityState(PRUint32* state)
  290. {
  291. *state = mSecurityState;
  292. return NS_OK;
  293. }
  294. nsresult
  295. nsNSSSocketInfo::SetSecurityState(PRUint32 aState)
  296. {
  297. mSecurityState = aState;
  298. return NS_OK;
  299. }
  300. /* attribute unsigned long countSubRequestsHighSecurity; */
  301. NS_IMETHODIMP nsNSSSocketInfo::GetCountSubRequestsHighSecurity(PRInt32 *aSubRequestsHighSecurity)
  302. {
  303. *aSubRequestsHighSecurity = mSubRequestsHighSecurity;
  304. return NS_OK;
  305. }
  306. NS_IMETHODIMP nsNSSSocketInfo::SetCountSubRequestsHighSecurity(PRInt32 aSubRequestsHighSecurity)
  307. {
  308. mSubRequestsHighSecurity = aSubRequestsHighSecurity;
  309. return NS_ERROR_NOT_IMPLEMENTED;
  310. }
  311. /* attribute unsigned long countSubRequestsLowSecurity; */
  312. NS_IMETHODIMP nsNSSSocketInfo::GetCountSubRequestsLowSecurity(PRInt32 *aSubRequestsLowSecurity)
  313. {
  314. *aSubRequestsLowSecurity = mSubRequestsLowSecurity;
  315. return NS_OK;
  316. }
  317. NS_IMETHODIMP nsNSSSocketInfo::SetCountSubRequestsLowSecurity(PRInt32 aSubRequestsLowSecurity)
  318. {
  319. mSubRequestsLowSecurity = aSubRequestsLowSecurity;
  320. return NS_OK;
  321. }
  322. /* attribute unsigned long countSubRequestsBrokenSecurity; */
  323. NS_IMETHODIMP nsNSSSocketInfo::GetCountSubRequestsBrokenSecurity(PRInt32 *aSubRequestsBrokenSecurity)
  324. {
  325. *aSubRequestsBrokenSecurity = mSubRequestsBrokenSecurity;
  326. return NS_OK;
  327. }
  328. NS_IMETHODIMP nsNSSSocketInfo::SetCountSubRequestsBrokenSecurity(PRInt32 aSubRequestsBrokenSecurity)
  329. {
  330. mSubRequestsBrokenSecurity = aSubRequestsBrokenSecurity;
  331. return NS_OK;
  332. }
  333. /* attribute unsigned long countSubRequestsNoSecurity; */
  334. NS_IMETHODIMP nsNSSSocketInfo::GetCountSubRequestsNoSecurity(PRInt32 *aSubRequestsNoSecurity)
  335. {
  336. *aSubRequestsNoSecurity = mSubRequestsNoSecurity;
  337. return NS_OK;
  338. }
  339. NS_IMETHODIMP nsNSSSocketInfo::SetCountSubRequestsNoSecurity(PRInt32 aSubRequestsNoSecurity)
  340. {
  341. mSubRequestsNoSecurity = aSubRequestsNoSecurity;
  342. return NS_OK;
  343. }
  344. NS_IMETHODIMP nsNSSSocketInfo::Flush()
  345. {
  346. return NS_OK;
  347. }
  348. NS_IMETHODIMP
  349. nsNSSSocketInfo::GetShortSecurityDescription(PRUnichar** aText) {
  350. if (mShortDesc.IsEmpty())
  351. *aText = nsnull;
  352. else {
  353. *aText = ToNewUnicode(mShortDesc);
  354. NS_ENSURE_TRUE(*aText, NS_ERROR_OUT_OF_MEMORY);
  355. }
  356. return NS_OK;
  357. }
  358. nsresult
  359. nsNSSSocketInfo::SetShortSecurityDescription(const PRUnichar* aText) {
  360. mShortDesc.Assign(aText);
  361. return NS_OK;
  362. }
  363. NS_IMETHODIMP
  364. nsNSSSocketInfo::GetErrorMessage(PRUnichar** aText)
  365. {
  366. NS_ENSURE_ARG_POINTER(aText);
  367. *aText = nsnull;
  368. if (!NS_IsMainThread()) {
  369. NS_ERROR("nsNSSSocketInfo::GetErrorMessage called off the main thread");
  370. return NS_ERROR_NOT_SAME_THREAD;
  371. }
  372. MutexAutoLock lock(mMutex);
  373. nsresult rv = formatErrorMessage(lock);
  374. NS_ENSURE_SUCCESS(rv, rv);
  375. *aText = ToNewUnicode(mErrorMessageCached);
  376. return *aText != nsnull ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  377. }
  378. void
  379. nsNSSSocketInfo::SetNegotiatedNPN(const char *value, PRUint32 length)
  380. {
  381. if (!value)
  382. mNegotiatedNPN.Truncate();
  383. else
  384. mNegotiatedNPN.Assign(value, length);
  385. mNPNCompleted = true;
  386. }
  387. NS_IMETHODIMP
  388. nsNSSSocketInfo::GetNegotiatedNPN(nsACString &aNegotiatedNPN)
  389. {
  390. if (!mNPNCompleted)
  391. return NS_ERROR_NOT_CONNECTED;
  392. aNegotiatedNPN = mNegotiatedNPN;
  393. return NS_OK;
  394. }
  395. NS_IMETHODIMP
  396. nsNSSSocketInfo::JoinConnection(const nsACString & npnProtocol,
  397. const nsACString & hostname,
  398. PRInt32 port,
  399. bool *_retval NS_OUTPARAM)
  400. {
  401. *_retval = false;
  402. // Different ports may not be joined together
  403. if (port != mPort)
  404. return NS_OK;
  405. // Make sure NPN has been completed and matches requested npnProtocol
  406. if (!mNPNCompleted || !mNegotiatedNPN.Equals(npnProtocol))
  407. return NS_OK;
  408. // If this is the same hostname then the certicate status does not
  409. // need to be considered. They are joinable.
  410. if (mHostName && hostname.Equals(mHostName)) {
  411. *_retval = true;
  412. return NS_OK;
  413. }
  414. // Before checking the server certificate we need to make sure the
  415. // handshake has completed.
  416. if (!mHandshakeCompleted || !SSLStatus() || !SSLStatus()->mServerCert)
  417. return NS_OK;
  418. // If the cert has error bits (e.g. it is untrusted) then do not join.
  419. // The value of mHaveCertErrorBits is only reliable because we know that
  420. // the handshake completed.
  421. if (SSLStatus()->mHaveCertErrorBits)
  422. return NS_OK;
  423. // If the connection is using client certificates then do not join
  424. // because the user decides on whether to send client certs to hosts on a
  425. // per-domain basis.
  426. if (mSentClientCert)
  427. return NS_OK;
  428. // Ensure that the server certificate covers the hostname that would
  429. // like to join this connection
  430. CERTCertificate *nssCert = nsnull;
  431. CERTCertificateCleaner nsscertCleaner(nssCert);
  432. nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(SSLStatus()->mServerCert);
  433. if (cert2)
  434. nssCert = cert2->GetCert();
  435. if (!nssCert)
  436. return NS_OK;
  437. if (CERT_VerifyCertName(nssCert, PromiseFlatCString(hostname).get()) !=
  438. SECSuccess)
  439. return NS_OK;
  440. // All tests pass - this is joinable
  441. mJoined = true;
  442. *_retval = true;
  443. return NS_OK;
  444. }
  445. static nsresult
  446. formatPlainErrorMessage(nsXPIDLCString const & host, PRInt32 port,
  447. PRErrorCode err, nsString &returnedMessage);
  448. static nsresult
  449. formatOverridableCertErrorMessage(nsISSLStatus & sslStatus,
  450. PRErrorCode errorCodeToReport,
  451. const nsXPIDLCString & host, PRInt32 port,
  452. nsString & returnedMessage);
  453. // XXX: uses nsNSSComponent string bundles off the main thread when called by
  454. // nsNSSSocketInfo::Write(). When we remove the error message from the
  455. // serialization of nsNSSSocketInfo (bug 697781) we can inline
  456. // formatErrorMessage into GetErrorMessage().
  457. nsresult
  458. nsNSSSocketInfo::formatErrorMessage(MutexAutoLock const & proofOfLock)
  459. {
  460. if (mErrorCode == 0 || !mErrorMessageCached.IsEmpty()) {
  461. return NS_OK;
  462. }
  463. nsresult rv;
  464. NS_ConvertASCIItoUTF16 hostNameU(mHostName);
  465. NS_ASSERTION(mErrorMessageType != OverridableCertErrorMessage ||
  466. (mSSLStatus && mSSLStatus->mServerCert &&
  467. mSSLStatus->mHaveCertErrorBits),
  468. "GetErrorMessage called for cert error without cert");
  469. if (mErrorMessageType == OverridableCertErrorMessage &&
  470. mSSLStatus && mSSLStatus->mServerCert) {
  471. rv = formatOverridableCertErrorMessage(*mSSLStatus, mErrorCode,
  472. mHostName, mPort,
  473. mErrorMessageCached);
  474. } else {
  475. rv = formatPlainErrorMessage(mHostName, mPort, mErrorCode,
  476. mErrorMessageCached);
  477. }
  478. if (NS_FAILED(rv)) {
  479. mErrorMessageCached.Truncate();
  480. }
  481. return rv;
  482. }
  483. /* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
  484. NS_IMETHODIMP nsNSSSocketInfo::GetInterface(const nsIID & uuid, void * *result)
  485. {
  486. if (!NS_IsMainThread()) {
  487. NS_ERROR("nsNSSSocketInfo::GetInterface called off the main thread");
  488. return NS_ERROR_NOT_SAME_THREAD;
  489. }
  490. nsresult rv;
  491. if (!mCallbacks) {
  492. nsCOMPtr<nsIInterfaceRequestor> ir = new PipUIContext();
  493. if (!ir)
  494. return NS_ERROR_OUT_OF_MEMORY;
  495. rv = ir->GetInterface(uuid, result);
  496. } else {
  497. rv = mCallbacks->GetInterface(uuid, result);
  498. }
  499. return rv;
  500. }
  501. nsresult
  502. nsNSSSocketInfo::GetForSTARTTLS(bool* aForSTARTTLS)
  503. {
  504. *aForSTARTTLS = mForSTARTTLS;
  505. return NS_OK;
  506. }
  507. nsresult
  508. nsNSSSocketInfo::SetForSTARTTLS(bool aForSTARTTLS)
  509. {
  510. mForSTARTTLS = aForSTARTTLS;
  511. return NS_OK;
  512. }
  513. NS_IMETHODIMP
  514. nsNSSSocketInfo::ProxyStartSSL()
  515. {
  516. return ActivateSSL();
  517. }
  518. NS_IMETHODIMP
  519. nsNSSSocketInfo::StartTLS()
  520. {
  521. return ActivateSSL();
  522. }
  523. NS_IMETHODIMP
  524. nsNSSSocketInfo::SetNPNList(nsTArray<nsCString> &protocolArray)
  525. {
  526. nsNSSShutDownPreventionLock locker;
  527. if (isAlreadyShutDown())
  528. return NS_ERROR_NOT_AVAILABLE;
  529. if (!mFd)
  530. return NS_ERROR_FAILURE;
  531. // the npn list is a concatenated list of 8 bit byte strings.
  532. nsCString npnList;
  533. for (PRUint32 index = 0; index < protocolArray.Length(); ++index) {
  534. if (protocolArray[index].IsEmpty() ||
  535. protocolArray[index].Length() > 255)
  536. return NS_ERROR_ILLEGAL_VALUE;
  537. npnList.Append(protocolArray[index].Length());
  538. npnList.Append(protocolArray[index]);
  539. }
  540. if (SSL_SetNextProtoNego(
  541. mFd,
  542. reinterpret_cast<const unsigned char *>(npnList.get()),
  543. npnList.Length()) != SECSuccess)
  544. return NS_ERROR_FAILURE;
  545. return NS_OK;
  546. }
  547. static NS_DEFINE_CID(kNSSCertificateCID, NS_X509CERT_CID);
  548. #define NSSSOCKETINFOMAGIC { 0xa9863a23, 0x26b8, 0x4a9c, \
  549. { 0x83, 0xf1, 0xe9, 0xda, 0xdb, 0x36, 0xb8, 0x30 } }
  550. static NS_DEFINE_CID(kNSSSocketInfoMagic, NSSSOCKETINFOMAGIC);
  551. NS_IMETHODIMP
  552. nsNSSSocketInfo::Write(nsIObjectOutputStream* stream) {
  553. stream->WriteID(kNSSSocketInfoMagic);
  554. MutexAutoLock lock(mMutex);
  555. nsRefPtr<nsSSLStatus> status = mSSLStatus;
  556. nsCOMPtr<nsISerializable> certSerializable;
  557. // Write a redundant copy of the certificate for backward compatibility
  558. // with previous versions, which also unnecessarily wrote it.
  559. //
  560. // As we are reading the object our self, not using ReadObject, we have
  561. // to store it here 'manually' as well, mimicking our object stream
  562. // implementation.
  563. if (status) {
  564. nsCOMPtr<nsIX509Cert> cert = status->mServerCert;
  565. certSerializable = do_QueryInterface(cert);
  566. if (!certSerializable) {
  567. NS_ERROR("certificate is missing or isn't serializable");
  568. return NS_ERROR_UNEXPECTED;
  569. }
  570. } else {
  571. NS_WARNING("Serializing nsNSSSocketInfo without mSSLStatus");
  572. }
  573. // Store the flag if there is the certificate present
  574. stream->WriteBoolean(certSerializable);
  575. if (certSerializable) {
  576. stream->WriteID(kNSSCertificateCID);
  577. stream->WriteID(NS_GET_IID(nsISupports));
  578. certSerializable->Write(stream);
  579. }
  580. // Store the version number of the binary stream data format.
  581. // The 0xFFFF0000 mask is included to the version number
  582. // to distinguish version number from mSecurityState
  583. // field stored in times before versioning has been introduced.
  584. // This mask value has been chosen as mSecurityState could
  585. // never be assigned such value.
  586. PRUint32 version = 3;
  587. stream->Write32(version | 0xFFFF0000);
  588. stream->Write32(mSecurityState);
  589. stream->WriteWStringZ(mShortDesc.get());
  590. // XXX: uses nsNSSComponent string bundles off the main thread
  591. nsresult rv = formatErrorMessage(lock);
  592. NS_ENSURE_SUCCESS(rv, rv);
  593. stream->WriteWStringZ(mErrorMessageCached.get());
  594. stream->WriteCompoundObject(NS_ISUPPORTS_CAST(nsISSLStatus*, status),
  595. NS_GET_IID(nsISupports), true);
  596. stream->Write32((PRUint32)mSubRequestsHighSecurity);
  597. stream->Write32((PRUint32)mSubRequestsLowSecurity);
  598. stream->Write32((PRUint32)mSubRequestsBrokenSecurity);
  599. stream->Write32((PRUint32)mSubRequestsNoSecurity);
  600. return NS_OK;
  601. }
  602. static bool CheckUUIDEquals(PRUint32 m0,
  603. nsIObjectInputStream* stream,
  604. const nsCID& id)
  605. {
  606. nsID tempID;
  607. tempID.m0 = m0;
  608. stream->Read16(&tempID.m1);
  609. stream->Read16(&tempID.m2);
  610. for (int i = 0; i < 8; ++i)
  611. stream->Read8(&tempID.m3[i]);
  612. return tempID.Equals(id);
  613. }
  614. NS_IMETHODIMP
  615. nsNSSSocketInfo::Read(nsIObjectInputStream* stream) {
  616. nsresult rv;
  617. PRUint32 version;
  618. bool certificatePresent;
  619. // Check what we have here...
  620. PRUint32 UUID_0;
  621. stream->Read32(&UUID_0);
  622. if (UUID_0 == kNSSSocketInfoMagic.m0) {
  623. // It seems this stream begins with our magic ID, check it really is there
  624. if (!CheckUUIDEquals(UUID_0, stream, kNSSSocketInfoMagic))
  625. return NS_ERROR_FAILURE;
  626. // OK, this seems to be our stream, now continue to check there is
  627. // the certificate
  628. stream->ReadBoolean(&certificatePresent);
  629. stream->Read32(&UUID_0);
  630. }
  631. else {
  632. // There is no magic, assume there is a certificate present as in versions
  633. // prior to those with the magic didn't store that flag; we check the
  634. // certificate is present by cheking the CID then
  635. certificatePresent = true;
  636. }
  637. if (certificatePresent && UUID_0 == kNSSCertificateCID.m0) {
  638. // It seems there is the certificate CID present, check it now; we only
  639. // have this single certificate implementation at this time.
  640. if (!CheckUUIDEquals(UUID_0, stream, kNSSCertificateCID))
  641. return NS_ERROR_FAILURE;
  642. // OK, we have read the CID of the certificate, check the interface ID
  643. nsID tempID;
  644. stream->ReadID(&tempID);
  645. if (!tempID.Equals(NS_GET_IID(nsISupports)))
  646. return NS_ERROR_FAILURE;
  647. nsCOMPtr<nsISerializable> serializable =
  648. do_CreateInstance(kNSSCertificateCID, &rv);
  649. NS_ENSURE_SUCCESS(rv, rv);
  650. // This is the redundant copy of the certificate; just ignore it
  651. serializable->Read(stream);
  652. // We are done with reading the certificate, now read the version
  653. // as we did before.
  654. stream->Read32(&version);
  655. }
  656. else {
  657. // There seems not to be the certificate present in the stream.
  658. version = UUID_0;
  659. }
  660. MutexAutoLock lock(mMutex);
  661. // If the version field we have just read is not masked with 0xFFFF0000
  662. // then it is stored mSecurityState field and this is version 1 of
  663. // the binary data stream format.
  664. if ((version & 0xFFFF0000) == 0xFFFF0000) {
  665. version &= ~0xFFFF0000;
  666. stream->Read32(&mSecurityState);
  667. }
  668. else {
  669. mSecurityState = version;
  670. version = 1;
  671. }
  672. stream->ReadString(mShortDesc);
  673. stream->ReadString(mErrorMessageCached);
  674. mErrorCode = 0;
  675. nsCOMPtr<nsISupports> obj;
  676. stream->ReadObject(true, getter_AddRefs(obj));
  677. mSSLStatus = reinterpret_cast<nsSSLStatus*>(obj.get());
  678. if (!mSSLStatus) {
  679. NS_WARNING("deserializing nsNSSSocketInfo without mSSLStatus");
  680. }
  681. if (version >= 2) {
  682. stream->Read32((PRUint32*)&mSubRequestsHighSecurity);
  683. stream->Read32((PRUint32*)&mSubRequestsLowSecurity);
  684. stream->Read32((PRUint32*)&mSubRequestsBrokenSecurity);
  685. stream->Read32((PRUint32*)&mSubRequestsNoSecurity);
  686. }
  687. else {
  688. mSubRequestsHighSecurity = 0;
  689. mSubRequestsLowSecurity = 0;
  690. mSubRequestsBrokenSecurity = 0;
  691. mSubRequestsNoSecurity = 0;
  692. }
  693. return NS_OK;
  694. }
  695. NS_IMETHODIMP
  696. nsNSSSocketInfo::GetInterfaces(PRUint32 *count, nsIID * **array)
  697. {
  698. *count = 0;
  699. *array = nsnull;
  700. return NS_OK;
  701. }
  702. NS_IMETHODIMP
  703. nsNSSSocketInfo::GetHelperForLanguage(PRUint32 language, nsISupports **_retval)
  704. {
  705. *_retval = nsnull;
  706. return NS_OK;
  707. }
  708. NS_IMETHODIMP
  709. nsNSSSocketInfo::GetContractID(char * *aContractID)
  710. {
  711. *aContractID = nsnull;
  712. return NS_OK;
  713. }
  714. NS_IMETHODIMP
  715. nsNSSSocketInfo::GetClassDescription(char * *aClassDescription)
  716. {
  717. *aClassDescription = nsnull;
  718. return NS_OK;
  719. }
  720. NS_IMETHODIMP
  721. nsNSSSocketInfo::GetClassID(nsCID * *aClassID)
  722. {
  723. *aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
  724. if (!*aClassID)
  725. return NS_ERROR_OUT_OF_MEMORY;
  726. return GetClassIDNoAlloc(*aClassID);
  727. }
  728. NS_IMETHODIMP
  729. nsNSSSocketInfo::GetImplementationLanguage(PRUint32 *aImplementationLanguage)
  730. {
  731. *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
  732. return NS_OK;
  733. }
  734. NS_IMETHODIMP
  735. nsNSSSocketInfo::GetFlags(PRUint32 *aFlags)
  736. {
  737. *aFlags = 0;
  738. return NS_OK;
  739. }
  740. static NS_DEFINE_CID(kNSSSocketInfoCID, NS_NSSSOCKETINFO_CID);
  741. NS_IMETHODIMP
  742. nsNSSSocketInfo::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  743. {
  744. *aClassIDNoAlloc = kNSSSocketInfoCID;
  745. return NS_OK;
  746. }
  747. nsresult nsNSSSocketInfo::ActivateSSL()
  748. {
  749. nsNSSShutDownPreventionLock locker;
  750. if (isAlreadyShutDown())
  751. return NS_ERROR_NOT_AVAILABLE;
  752. if (SECSuccess != SSL_OptionSet(mFd, SSL_SECURITY, true))
  753. return NS_ERROR_FAILURE;
  754. if (SECSuccess != SSL_ResetHandshake(mFd, false))
  755. return NS_ERROR_FAILURE;
  756. mHandshakePending = true;
  757. return NS_OK;
  758. }
  759. nsresult nsNSSSocketInfo::GetFileDescPtr(PRFileDesc** aFilePtr)
  760. {
  761. *aFilePtr = mFd;
  762. return NS_OK;
  763. }
  764. nsresult nsNSSSocketInfo::SetFileDescPtr(PRFileDesc* aFilePtr)
  765. {
  766. mFd = aFilePtr;
  767. return NS_OK;
  768. }
  769. class PreviousCertRunnable : public SyncRunnableBase
  770. {
  771. public:
  772. PreviousCertRunnable(nsIInterfaceRequestor * callbacks)
  773. : mCallbacks(callbacks)
  774. {
  775. }
  776. virtual void RunOnTargetThread()
  777. {
  778. nsCOMPtr<nsISecureBrowserUI> secureUI;
  779. getSecureBrowserUI(mCallbacks, getter_AddRefs(secureUI));
  780. nsCOMPtr<nsISSLStatusProvider> statusProvider = do_QueryInterface(secureUI);
  781. if (statusProvider) {
  782. nsCOMPtr<nsISSLStatus> status;
  783. (void) statusProvider->GetSSLStatus(getter_AddRefs(status));
  784. if (status) {
  785. (void) status->GetServerCert(getter_AddRefs(mPreviousCert));
  786. }
  787. }
  788. }
  789. nsCOMPtr<nsIX509Cert> mPreviousCert; // out
  790. private:
  791. nsCOMPtr<nsIInterfaceRequestor> mCallbacks; // in
  792. };
  793. void nsNSSSocketInfo::GetPreviousCert(nsIX509Cert** _result)
  794. {
  795. NS_ASSERTION(_result, "_result parameter to GetPreviousCert is null");
  796. *_result = nsnull;
  797. nsRefPtr<PreviousCertRunnable> runnable = new PreviousCertRunnable(mCallbacks);
  798. nsresult rv = runnable->DispatchToMainThreadAndWait();
  799. NS_ASSERTION(NS_SUCCEEDED(rv), "runnable->DispatchToMainThreadAndWait() failed");
  800. runnable->mPreviousCert.forget(_result);
  801. }
  802. void
  803. nsNSSSocketInfo::SetCertVerificationWaiting()
  804. {
  805. // mCertVerificationState may be before_cert_verification for the first
  806. // handshake on the connection, or after_cert_verification for subsequent
  807. // renegotiation handshakes.
  808. NS_ASSERTION(mCertVerificationState != waiting_for_cert_verification,
  809. "Invalid state transition to waiting_for_cert_verification");
  810. mCertVerificationState = waiting_for_cert_verification;
  811. mCertVerificationStarted = PR_IntervalNow();
  812. }
  813. // Be careful that SetCertVerificationResult does NOT get called while we are
  814. // processing a SSL callback function, because SSL_AuthCertificateComplete will
  815. // attempt to acquire locks that are already held by libssl when it calls
  816. // callbacks.
  817. void
  818. nsNSSSocketInfo::SetCertVerificationResult(PRErrorCode errorCode,
  819. SSLErrorMessageType errorMessageType)
  820. {
  821. NS_ASSERTION(mCertVerificationState == waiting_for_cert_verification,
  822. "Invalid state transition to cert_verification_finished");
  823. mCertVerificationEnded = PR_IntervalNow();
  824. if (mFd) {
  825. SECStatus rv = SSL_AuthCertificateComplete(mFd, errorCode);
  826. // Only replace errorCode if there was originally no error
  827. if (rv != SECSuccess && errorCode == 0) {
  828. errorCode = PR_GetError();
  829. errorMessageType = PlainErrorMessage;
  830. if (errorCode == 0) {
  831. NS_ERROR("SSL_AuthCertificateComplete didn't set error code");
  832. errorCode = PR_INVALID_STATE_ERROR;
  833. }
  834. }
  835. }
  836. if (errorCode) {
  837. SetCanceled(errorCode, errorMessageType);
  838. }
  839. mCertVerificationState = after_cert_verification;
  840. }
  841. nsresult nsNSSSocketInfo::GetSSLStatus(nsISSLStatus** _result)
  842. {
  843. NS_ENSURE_ARG_POINTER(_result);
  844. *_result = mSSLStatus;
  845. NS_IF_ADDREF(*_result);
  846. return NS_OK;
  847. }
  848. nsresult nsNSSSocketInfo::SetSSLStatus(nsSSLStatus *aSSLStatus)
  849. {
  850. mSSLStatus = aSSLStatus;
  851. return NS_OK;
  852. }
  853. void nsNSSSocketInfo::SetHandshakeInProgress(bool aIsIn)
  854. {
  855. mHandshakeInProgress = aIsIn;
  856. if (mHandshakeInProgress && !mHandshakeStartTime)
  857. {
  858. mHandshakeStartTime = PR_IntervalNow();
  859. }
  860. }
  861. void nsNSSSocketInfo::SetAllowTLSIntoleranceTimeout(bool aAllow)
  862. {
  863. mAllowTLSIntoleranceTimeout = aAllow;
  864. }
  865. #define HANDSHAKE_TIMEOUT_SECONDS 25
  866. bool nsNSSSocketInfo::HandshakeTimeout()
  867. {
  868. if (mCertVerificationState == waiting_for_cert_verification) {
  869. // Do not do a TLS interlerance timeout during cert verification because:
  870. //
  871. // * If we would have timed out, but cert verification is still ongoing,
  872. // then the handshake probably already completed, and it is probably the
  873. // certificate validation (OCSP responder or similar) that is timing
  874. // out.
  875. // * If certificate validation AND the handshake is slow, then that is a
  876. // good indication that the network is bad, and so the problem probably
  877. // isn't the server being TLS intolerant.
  878. // * When we timeout, we return non-zero flags from PR_Poll, which will
  879. // cause the application to try to read from and/or write to the socket,
  880. // possibly in a loop. But, it is likely that the socket is blocked on
  881. // cert authentication, so those read and/or write calls would result in
  882. // PR_WOULD_BLOCK_ERROR, causing the application to spin.
  883. return false;
  884. }
  885. if (!mHandshakeInProgress || !mAllowTLSIntoleranceTimeout)
  886. return false;
  887. PRIntervalTime now = PR_IntervalNow();
  888. PRIntervalTime certVerificationTime =
  889. mCertVerificationEnded - mCertVerificationStarted;
  890. PRIntervalTime totalTime = now - mHandshakeStartTime;
  891. PRIntervalTime totalTimeExceptCertVerificationTime =
  892. totalTime - certVerificationTime;
  893. return totalTimeExceptCertVerificationTime >
  894. PR_SecondsToInterval(HANDSHAKE_TIMEOUT_SECONDS);
  895. }
  896. void nsSSLIOLayerHelpers::Cleanup()
  897. {
  898. if (mTLSIntolerantSites) {
  899. delete mTLSIntolerantSites;
  900. mTLSIntolerantSites = nsnull;
  901. }
  902. if (mTLSTolerantSites) {
  903. delete mTLSTolerantSites;
  904. mTLSTolerantSites = nsnull;
  905. }
  906. if (mRenegoUnrestrictedSites) {
  907. delete mRenegoUnrestrictedSites;
  908. mRenegoUnrestrictedSites = nsnull;
  909. }
  910. if (mutex) {
  911. delete mutex;
  912. mutex = nsnull;
  913. }
  914. if (mHostsWithCertErrors) {
  915. delete mHostsWithCertErrors;
  916. mHostsWithCertErrors = nsnull;
  917. }
  918. }
  919. /* Formats an error message for non-certificate-related SSL errors
  920. * and non-overridable certificate errors (both are of type
  921. * PlainErrormMessage). Use formatOverridableCertErrorMessage
  922. * for overridable cert errors.
  923. */
  924. static nsresult
  925. formatPlainErrorMessage(const nsXPIDLCString &host, PRInt32 port,
  926. PRErrorCode err, nsString &returnedMessage)
  927. {
  928. const PRUnichar *params[1];
  929. nsresult rv;
  930. nsCOMPtr<nsINSSComponent> component = do_GetService(kNSSComponentCID, &rv);
  931. NS_ENSURE_SUCCESS(rv, rv);
  932. if (host.Length())
  933. {
  934. nsString hostWithPort;
  935. // For now, hide port when it's 443 and we're reporting the error.
  936. // In the future a better mechanism should be used
  937. // to make a decision about showing the port number, possibly by requiring
  938. // the context object to implement a specific interface.
  939. // The motivation is that Mozilla browser would like to hide the port number
  940. // in error pages in the common case.
  941. hostWithPort.AssignASCII(host);
  942. if (port != 443) {
  943. hostWithPort.AppendLiteral(":");
  944. hostWithPort.AppendInt(port);
  945. }
  946. params[0] = hostWithPort.get();
  947. nsString formattedString;
  948. rv = component->PIPBundleFormatStringFromName("SSLConnectionErrorPrefix",
  949. params, 1,
  950. formattedString);
  951. if (NS_SUCCEEDED(rv))
  952. {
  953. returnedMessage.Append(formattedString);
  954. returnedMessage.Append(NS_LITERAL_STRING("\n\n"));
  955. }
  956. }
  957. nsString explanation;
  958. rv = nsNSSErrors::getErrorMessageFromCode(err, component, explanation);
  959. if (NS_SUCCEEDED(rv))
  960. returnedMessage.Append(explanation);
  961. return NS_OK;
  962. }
  963. static void
  964. AppendErrorTextUntrusted(PRErrorCode errTrust,
  965. const nsString &host,
  966. nsIX509Cert* ix509,
  967. nsINSSComponent *component,
  968. nsString &returnedMessage)
  969. {
  970. const char *errorID = nsnull;
  971. nsCOMPtr<nsIX509Cert3> cert3 = do_QueryInterface(ix509);
  972. if (cert3) {
  973. bool isSelfSigned;
  974. if (NS_SUCCEEDED(cert3->GetIsSelfSigned(&isSelfSigned))
  975. && isSelfSigned) {
  976. errorID = "certErrorTrust_SelfSigned";
  977. }
  978. }
  979. if (!errorID) {
  980. switch (errTrust) {
  981. case SEC_ERROR_UNKNOWN_ISSUER:
  982. {
  983. nsCOMPtr<nsIArray> chain;
  984. ix509->GetChain(getter_AddRefs(chain));
  985. PRUint32 length = 0;
  986. if (chain && NS_FAILED(chain->GetLength(&length)))
  987. length = 0;
  988. if (length == 1)
  989. errorID = "certErrorTrust_MissingChain";
  990. else
  991. errorID = "certErrorTrust_UnknownIssuer";
  992. break;
  993. }
  994. case SEC_ERROR_INADEQUATE_KEY_USAGE:
  995. // Should get an individual string in the future
  996. // For now, use the same as CaInvalid
  997. case SEC_ERROR_CA_CERT_INVALID:
  998. errorID = "certErrorTrust_CaInvalid";
  999. break;
  1000. case SEC_ERROR_UNTRUSTED_ISSUER:
  1001. errorID = "certErrorTrust_Issuer";
  1002. break;
  1003. case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
  1004. errorID = "certErrorTrust_ExpiredIssuer";
  1005. break;
  1006. case SEC_ERROR_UNTRUSTED_CERT:
  1007. default:
  1008. errorID = "certErrorTrust_Untrusted";
  1009. break;
  1010. }
  1011. }
  1012. nsString formattedString;
  1013. nsresult rv = component->GetPIPNSSBundleString(errorID,
  1014. formattedString);
  1015. if (NS_SUCCEEDED(rv))
  1016. {
  1017. returnedMessage.Append(formattedString);
  1018. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  1019. }
  1020. }
  1021. // returns TRUE if SAN was used to produce names
  1022. // return FALSE if nothing was produced
  1023. // names => a single name or a list of names
  1024. // multipleNames => whether multiple names were delivered
  1025. static bool
  1026. GetSubjectAltNames(CERTCertificate *nssCert,
  1027. nsINSSComponent *component,
  1028. nsString &allNames,
  1029. PRUint32 &nameCount)
  1030. {
  1031. allNames.Truncate();
  1032. nameCount = 0;
  1033. PRArenaPool *san_arena = nsnull;
  1034. SECItem altNameExtension = {siBuffer, NULL, 0 };
  1035. CERTGeneralName *sanNameList = nsnull;
  1036. nsresult rv;
  1037. rv = CERT_FindCertExtension(nssCert, SEC_OID_X509_SUBJECT_ALT_NAME,
  1038. &altNameExtension);
  1039. if (rv != SECSuccess)
  1040. return false;
  1041. san_arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1042. if (!san_arena)
  1043. return false;
  1044. sanNameList = CERT_DecodeAltNameExtension(san_arena, &altNameExtension);
  1045. if (!sanNameList)
  1046. return false;
  1047. SECITEM_FreeItem(&altNameExtension, false);
  1048. CERTGeneralName *current = sanNameList;
  1049. do {
  1050. nsAutoString name;
  1051. switch (current->type) {
  1052. case certDNSName:
  1053. name.AssignASCII((char*)current->name.other.data, current->name.other.len);
  1054. if (!allNames.IsEmpty()) {
  1055. allNames.Append(NS_LITERAL_STRING(" , "));
  1056. }
  1057. ++nameCount;
  1058. allNames.Append(name);
  1059. break;
  1060. case certIPAddress:
  1061. {
  1062. char buf[INET6_ADDRSTRLEN];
  1063. PRNetAddr addr;
  1064. if (current->name.other.len == 4) {
  1065. addr.inet.family = PR_AF_INET;
  1066. memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
  1067. PR_NetAddrToString(&addr, buf, sizeof(buf));
  1068. name.AssignASCII(buf);
  1069. } else if (current->name.other.len == 16) {
  1070. addr.ipv6.family = PR_AF_INET6;
  1071. memcpy(&addr.ipv6.ip, current->name.other.data, current->name.other.len);
  1072. PR_NetAddrToString(&addr, buf, sizeof(buf));
  1073. name.AssignASCII(buf);
  1074. } else {
  1075. /* invalid IP address */
  1076. }
  1077. if (!name.IsEmpty()) {
  1078. if (!allNames.IsEmpty()) {
  1079. allNames.Append(NS_LITERAL_STRING(" , "));
  1080. }
  1081. ++nameCount;
  1082. allNames.Append(name);
  1083. }
  1084. break;
  1085. }
  1086. default: // all other types of names are ignored
  1087. break;
  1088. }
  1089. current = CERT_GetNextGeneralName(current);
  1090. } while (current != sanNameList); // double linked
  1091. PORT_FreeArena(san_arena, false);
  1092. return true;
  1093. }
  1094. static void
  1095. AppendErrorTextMismatch(const nsString &host,
  1096. nsIX509Cert* ix509,
  1097. nsINSSComponent *component,
  1098. nsString &returnedMessage)
  1099. {
  1100. const PRUnichar *params[1];
  1101. nsresult rv;
  1102. CERTCertificate *nssCert = NULL;
  1103. CERTCertificateCleaner nssCertCleaner(nssCert);
  1104. nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(ix509, &rv);
  1105. if (cert2)
  1106. nssCert = cert2->GetCert();
  1107. if (!nssCert) {
  1108. // We are unable to extract the valid names, say "not valid for name".
  1109. params[0] = host.get();
  1110. nsString formattedString;
  1111. rv = component->PIPBundleFormatStringFromName("certErrorMismatch",
  1112. params, 1,
  1113. formattedString);
  1114. if (NS_SUCCEEDED(rv)) {
  1115. returnedMessage.Append(formattedString);
  1116. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  1117. }
  1118. return;
  1119. }
  1120. nsString allNames;
  1121. PRUint32 nameCount = 0;
  1122. bool useSAN = false;
  1123. if (nssCert)
  1124. useSAN = GetSubjectAltNames(nssCert, component, allNames, nameCount);
  1125. if (!useSAN) {
  1126. char *certName = nsnull;
  1127. // currently CERT_FindNSStringExtension is not being exported by NSS.
  1128. // If it gets exported, enable the following line.
  1129. // certName = CERT_FindNSStringExtension(nssCert, SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
  1130. // However, it has been discussed to treat the extension as obsolete and ignore it.
  1131. if (!certName)
  1132. certName = CERT_GetCommonName(&nssCert->subject);
  1133. if (certName) {
  1134. ++nameCount;
  1135. allNames.AssignASCII(certName);
  1136. PORT_Free(certName);
  1137. }
  1138. }
  1139. if (nameCount > 1) {
  1140. nsString message;
  1141. rv = component->GetPIPNSSBundleString("certErrorMismatchMultiple",
  1142. message);
  1143. if (NS_SUCCEEDED(rv)) {
  1144. returnedMessage.Append(message);
  1145. returnedMessage.Append(NS_LITERAL_STRING("\n "));
  1146. returnedMessage.Append(allNames);
  1147. returnedMessage.Append(NS_LITERAL_STRING(" \n"));
  1148. }
  1149. }
  1150. else if (nameCount == 1) {
  1151. const PRUnichar *params[1];
  1152. params[0] = allNames.get();
  1153. nsString formattedString;
  1154. rv = component->PIPBundleFormatStringFromName("certErrorMismatchSingle2",
  1155. params, 1,
  1156. formattedString);
  1157. if (NS_SUCCEEDED(rv)) {
  1158. returnedMessage.Append(formattedString);
  1159. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  1160. }
  1161. }
  1162. else { // nameCount == 0
  1163. nsString message;
  1164. nsresult rv = component->GetPIPNSSBundleString("certErrorMismatchNoNames",
  1165. message);
  1166. if (NS_SUCCEEDED(rv)) {
  1167. returnedMessage.Append(message);
  1168. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  1169. }
  1170. }
  1171. }
  1172. static void
  1173. GetDateBoundary(nsIX509Cert* ix509,
  1174. nsString &formattedDate,
  1175. nsString &nowDate,
  1176. bool &trueExpired_falseNotYetValid)
  1177. {
  1178. trueExpired_falseNotYetValid = true;
  1179. formattedDate.Truncate();
  1180. PRTime notAfter, notBefore, timeToUse;
  1181. nsCOMPtr<nsIX509CertValidity> validity;
  1182. nsresult rv;
  1183. rv = ix509->GetValidity(getter_AddRefs(validity));
  1184. if (NS_FAILED(rv))
  1185. return;
  1186. rv = validity->GetNotAfter(&notAfter);
  1187. if (NS_FAILED(rv))
  1188. return;
  1189. rv = validity->GetNotBefore(&notBefore);
  1190. if (NS_FAILED(rv))
  1191. return;
  1192. PRTime now = PR_Now();
  1193. if (LL_CMP(now, >, notAfter)) {
  1194. timeToUse = notAfter;
  1195. } else {
  1196. timeToUse = notBefore;
  1197. trueExpired_falseNotYetValid = false;
  1198. }
  1199. nsCOMPtr<nsIDateTimeFormat> dateTimeFormat(do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv));
  1200. if (NS_FAILED(rv))
  1201. return;
  1202. dateTimeFormat->FormatPRTime(nsnull, kDateFormatShort,
  1203. kTimeFormatNoSeconds, timeToUse,
  1204. formattedDate);
  1205. dateTimeFormat->FormatPRTime(nsnull, kDateFormatShort,
  1206. kTimeFormatNoSeconds, now,
  1207. nowDate);
  1208. }
  1209. static void
  1210. AppendErrorTextTime(nsIX509Cert* ix509,
  1211. nsINSSComponent *component,
  1212. nsString &returnedMessage)
  1213. {
  1214. nsAutoString formattedDate, nowDate;
  1215. bool trueExpired_falseNotYetValid;
  1216. GetDateBoundary(ix509, formattedDate, nowDate, trueExpired_falseNotYetValid);
  1217. const PRUnichar *params[2];
  1218. params[0] = formattedDate.get(); // might be empty, if helper function had a problem
  1219. params[1] = nowDate.get();
  1220. const char *key = trueExpired_falseNotYetValid ?
  1221. "certErrorExpiredNow" : "certErrorNotYetValidNow";
  1222. nsresult rv;
  1223. nsString formattedString;
  1224. rv = component->PIPBundleFormatStringFromName(
  1225. key,
  1226. params,
  1227. ArrayLength(params),
  1228. formattedString);
  1229. if (NS_SUCCEEDED(rv))
  1230. {
  1231. returnedMessage.Append(formattedString);
  1232. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  1233. }
  1234. }
  1235. static void
  1236. AppendErrorTextCode(PRErrorCode errorCodeToReport,
  1237. nsINSSComponent *component,
  1238. nsString &returnedMessage)
  1239. {
  1240. const char *codeName = nsNSSErrors::getDefaultErrorStringName(errorCodeToReport);
  1241. if (codeName)
  1242. {
  1243. nsCString error_id(codeName);
  1244. ToLowerCase(error_id);
  1245. NS_ConvertASCIItoUTF16 idU(error_id);
  1246. const PRUnichar *params[1];
  1247. params[0] = idU.get();
  1248. nsString formattedString;
  1249. nsresult rv;
  1250. rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix",
  1251. params, 1,
  1252. formattedString);
  1253. if (NS_SUCCEEDED(rv)) {
  1254. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  1255. returnedMessage.Append(formattedString);
  1256. returnedMessage.Append(NS_LITERAL_STRING("\n"));
  1257. }
  1258. else {
  1259. returnedMessage.Append(NS_LITERAL_STRING(" ("));
  1260. returnedMessage.Append(idU);
  1261. returnedMessage.Append(NS_LITERAL_STRING(")"));
  1262. }
  1263. }
  1264. }
  1265. /* Formats an error message for overridable certificate errors (of type
  1266. * OverridableCertErrorMessage). Use formatPlainErrorMessage to format
  1267. * non-overridable cert errors and non-cert-related errors.
  1268. */
  1269. static nsresult
  1270. formatOverridableCertErrorMessage(nsISSLStatus & sslStatus,
  1271. PRErrorCode errorCodeToReport,
  1272. const nsXPIDLCString & host, PRInt32 port,
  1273. nsString & returnedMessage)
  1274. {
  1275. const PRUnichar *params[1];
  1276. nsresult rv;
  1277. nsAutoString hostWithPort;
  1278. nsAutoString hostWithoutPort;
  1279. // For now, hide port when it's 443 and we're reporting the error.
  1280. // In the future a better mechanism should be used
  1281. // to make a decision about showing the port number, possibly by requiring
  1282. // the context object to implement a specific interface.
  1283. // The motivation is that Mozilla browser would like to hide the port number
  1284. // in error pages in the common case.
  1285. hostWithoutPort.AppendASCII(host);
  1286. if (port == 443) {
  1287. params[0] = hostWithoutPort.get();
  1288. } else {
  1289. hostWithPort.AppendASCII(host);
  1290. hostWithPort.Append(':');
  1291. hostWithPort.AppendInt(port);
  1292. params[0] = hostWithPort.get();
  1293. }
  1294. nsCOMPtr<nsINSSComponent> component = do_GetService(kNSSComponentCID, &rv);
  1295. NS_ENSURE_SUCCESS(rv, rv);
  1296. returnedMessage.Truncate();
  1297. rv = component->PIPBundleFormatStringFromName("certErrorIntro", params, 1,
  1298. returnedMessage);
  1299. NS_ENSURE_SUCCESS(rv, rv);
  1300. returnedMessage.Append(NS_LITERAL_STRING("\n\n"));
  1301. nsRefPtr<nsIX509Cert> ix509;
  1302. rv = sslStatus.GetServerCert(getter_AddRefs(ix509));
  1303. NS_ENSURE_SUCCESS(rv, rv);
  1304. bool isUntrusted;
  1305. rv = sslStatus.GetIsUntrusted(&isUntrusted);
  1306. NS_ENSURE_SUCCESS(rv, rv);
  1307. if (isUntrusted) {
  1308. AppendErrorTextUntrusted(errorCodeToReport, hostWithoutPort, ix509,
  1309. component, returnedMessage);
  1310. }
  1311. bool isDomainMismatch;
  1312. rv = sslStatus.GetIsDomainMismatch(&isDomainMismatch);
  1313. NS_ENSURE_SUCCESS(rv, rv);
  1314. if (isDomainMismatch) {
  1315. AppendErrorTextMismatch(hostWithoutPort, ix509, component, returnedMessage);
  1316. }
  1317. bool isNotValidAtThisTime;
  1318. rv = sslStatus.GetIsNotValidAtThisTime(&isNotValidAtThisTime);
  1319. NS_ENSURE_SUCCESS(rv, rv);
  1320. if (isNotValidAtThisTime) {
  1321. AppendErrorTextTime(ix509, component, returnedMessage);
  1322. }
  1323. AppendErrorTextCode(errorCodeToReport, component, returnedMessage);
  1324. return NS_OK;
  1325. }
  1326. static void
  1327. nsHandleSSLError(nsNSSSocketInfo *socketInfo, PRErrorCode err)
  1328. {
  1329. if (!NS_IsMainThread()) {
  1330. NS_ERROR("nsHandleSSLError called off the main thread");
  1331. return;
  1332. }
  1333. // SetCanceled is only called by the main thread or the socket transport
  1334. // thread. Whenever this function is called on the main thread, the SSL
  1335. // thread is blocked on it. So, no mutex is necessary for
  1336. // SetCanceled()/GetError*().
  1337. if (socketInfo->GetErrorCode()) {
  1338. // If the socket has been flagged as canceled,
  1339. // the code who did was responsible for setting the error code.
  1340. return;
  1341. }
  1342. nsresult rv;
  1343. NS_DEFINE_CID(nssComponentCID, NS_NSSCOMPONENT_CID);
  1344. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(nssComponentCID, &rv));
  1345. if (NS_FAILED(rv))
  1346. return;
  1347. nsXPIDLCString hostName;
  1348. socketInfo->GetHostName(getter_Copies(hostName));
  1349. PRInt32 port;
  1350. socketInfo->GetPort(&port);
  1351. // Try to get a nsISSLErrorListener implementation from the socket consumer.
  1352. nsCOMPtr<nsIInterfaceRequestor> cb;
  1353. socketInfo->GetNotificationCallbacks(getter_AddRefs(cb));
  1354. if (cb) {
  1355. nsCOMPtr<nsISSLErrorListener> sel = do_GetInterface(cb);
  1356. if (sel) {
  1357. nsIInterfaceRequestor *csi = static_cast<nsIInterfaceRequestor*>(socketInfo);
  1358. nsCString hostWithPortString = hostName;
  1359. hostWithPortString.AppendLiteral(":");
  1360. hostWithPortString.AppendInt(port);
  1361. bool suppressMessage = false; // obsolete, ignored
  1362. rv = sel->NotifySSLError(csi, err, hostWithPortString, &suppressMessage);
  1363. }
  1364. }
  1365. socketInfo->SetCanceled(err, PlainErrorMessage);
  1366. }
  1367. namespace {
  1368. enum Operation { reading, writing, not_reading_or_writing };
  1369. PRInt32 checkHandshake(PRInt32 bytesTransfered, bool wasReading,
  1370. PRFileDesc* ssl_layer_fd,
  1371. nsNSSSocketInfo *socketInfo);
  1372. nsNSSSocketInfo *
  1373. getSocketInfoIfRunning(PRFileDesc * fd, Operation op,
  1374. const nsNSSShutDownPreventionLock & /*proofOfLock*/)
  1375. {
  1376. if (!fd || !fd->lower || !fd->secret ||
  1377. fd->identity != nsSSLIOLayerHelpers::nsSSLIOLayerIdentity) {
  1378. NS_ERROR("bad file descriptor passed to getSocketInfoIfRunning");
  1379. PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
  1380. return nsnull;
  1381. }
  1382. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1383. if (socketInfo->isAlreadyShutDown() || socketInfo->isPK11LoggedOut()) {
  1384. PR_SetError(PR_SOCKET_SHUTDOWN_ERROR, 0);
  1385. return nsnull;
  1386. }
  1387. if (socketInfo->GetErrorCode()) {
  1388. PRErrorCode err = socketInfo->GetErrorCode();
  1389. PR_SetError(err, 0);
  1390. if (op == reading || op == writing) {
  1391. // We must do TLS intolerance checks for reads and writes, for timeouts
  1392. // in particular.
  1393. (void) checkHandshake(-1, op == reading, fd, socketInfo);
  1394. }
  1395. // If we get here, it is probably because cert verification failed and this
  1396. // is the first I/O attempt since that failure.
  1397. return nsnull;
  1398. }
  1399. return socketInfo;
  1400. }
  1401. } // unnnamed namespace
  1402. static PRStatus PR_CALLBACK
  1403. nsSSLIOLayerConnect(PRFileDesc* fd, const PRNetAddr* addr,
  1404. PRIntervalTime timeout)
  1405. {
  1406. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] connecting SSL socket\n", (void*)fd));
  1407. nsNSSShutDownPreventionLock locker;
  1408. if (!getSocketInfoIfRunning(fd, not_reading_or_writing, locker))
  1409. return PR_FAILURE;
  1410. PRStatus status = fd->lower->methods->connect(fd->lower, addr, timeout);
  1411. if (status != PR_SUCCESS) {
  1412. PR_LOG(gPIPNSSLog, PR_LOG_ERROR, ("[%p] Lower layer connect error: %d\n",
  1413. (void*)fd, PR_GetError()));
  1414. return status;
  1415. }
  1416. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] Connect\n", (void*)fd));
  1417. return status;
  1418. }
  1419. // nsPSMRememberCertErrorsTable
  1420. nsPSMRememberCertErrorsTable::nsPSMRememberCertErrorsTable()
  1421. {
  1422. mErrorHosts.Init(16);
  1423. }
  1424. nsresult
  1425. nsPSMRememberCertErrorsTable::GetHostPortKey(nsNSSSocketInfo* infoObject,
  1426. nsCAutoString &result)
  1427. {
  1428. nsresult rv;
  1429. result.Truncate();
  1430. nsXPIDLCString hostName;
  1431. rv = infoObject->GetHostName(getter_Copies(hostName));
  1432. NS_ENSURE_SUCCESS(rv, rv);
  1433. PRInt32 port;
  1434. rv = infoObject->GetPort(&port);
  1435. NS_ENSURE_SUCCESS(rv, rv);
  1436. result.Assign(hostName);
  1437. result.Append(':');
  1438. result.AppendInt(port);
  1439. return NS_OK;
  1440. }
  1441. void
  1442. nsPSMRememberCertErrorsTable::RememberCertHasError(nsNSSSocketInfo* infoObject,
  1443. nsSSLStatus* status,
  1444. SECStatus certVerificationResult)
  1445. {
  1446. nsresult rv;
  1447. nsCAutoString hostPortKey;
  1448. rv = GetHostPortKey(infoObject, hostPortKey);
  1449. if (NS_FAILED(rv))
  1450. return;
  1451. if (certVerificationResult != SECSuccess) {
  1452. NS_ASSERTION(status,
  1453. "Must have nsSSLStatus object when remembering flags");
  1454. if (!status)
  1455. return;
  1456. CertStateBits bits;
  1457. bits.mIsDomainMismatch = status->mIsDomainMismatch;
  1458. bits.mIsNotValidAtThisTime = status->mIsNotValidAtThisTime;
  1459. bits.mIsUntrusted = status->mIsUntrusted;
  1460. mErrorHosts.Put(hostPortKey, bits);
  1461. }
  1462. else {
  1463. mErrorHosts.Remove(hostPortKey);
  1464. }
  1465. }
  1466. void
  1467. nsPSMRememberCertErrorsTable::LookupCertErrorBits(nsNSSSocketInfo* infoObject,
  1468. nsSSLStatus* status)
  1469. {
  1470. // Get remembered error bits from our cache, because of SSL session caching
  1471. // the NSS library potentially hasn't notified us for this socket.
  1472. if (status->mHaveCertErrorBits)
  1473. // Rather do not modify bits if already set earlier
  1474. return;
  1475. nsresult rv;
  1476. nsCAutoString hostPortKey;
  1477. rv = GetHostPortKey(infoObject, hostPortKey);
  1478. if (NS_FAILED(rv))
  1479. return;
  1480. CertStateBits bits;
  1481. if (!mErrorHosts.Get(hostPortKey, &bits))
  1482. // No record was found, this host had no cert errors
  1483. return;
  1484. // This host had cert errors, update the bits correctly
  1485. status->mHaveCertErrorBits = true;
  1486. status->mIsDomainMismatch = bits.mIsDomainMismatch;
  1487. status->mIsNotValidAtThisTime = bits.mIsNotValidAtThisTime;
  1488. status->mIsUntrusted = bits.mIsUntrusted;
  1489. }
  1490. void
  1491. nsSSLIOLayerHelpers::getSiteKey(nsNSSSocketInfo *socketInfo, nsCSubstring &key)
  1492. {
  1493. PRInt32 port;
  1494. socketInfo->GetPort(&port);
  1495. nsXPIDLCString host;
  1496. socketInfo->GetHostName(getter_Copies(host));
  1497. key = host + NS_LITERAL_CSTRING(":") + nsPrintfCString("%d", port);
  1498. }
  1499. // Call this function to report a site that is possibly TLS intolerant.
  1500. // This function will return true, if the given socket is currently using TLS.
  1501. bool
  1502. nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(nsNSSSocketInfo *socketInfo)
  1503. {
  1504. nsCAutoString key;
  1505. getSiteKey(socketInfo, key);
  1506. if (!socketInfo->IsTLSEnabled()) {
  1507. // We did not offer TLS but failed with an intolerant error using
  1508. // a different protocol. To give TLS a try on next connection attempt again
  1509. // drop this site from the list of intolerant sites. TLS failure might be
  1510. // caused only by a traffic congestion while the server is TLS tolerant.
  1511. removeIntolerantSite(key);
  1512. return false;
  1513. }
  1514. if (socketInfo->IsSSL3Enabled()) {
  1515. // Add this site to the list of TLS intolerant sites.
  1516. addIntolerantSite(key);
  1517. }
  1518. return socketInfo->IsTLSEnabled();
  1519. }
  1520. void
  1521. nsSSLIOLayerHelpers::rememberTolerantSite(nsNSSSocketInfo *socketInfo)
  1522. {
  1523. if (!socketInfo->IsTLSEnabled())
  1524. return;
  1525. nsCAutoString key;
  1526. getSiteKey(socketInfo, key);
  1527. MutexAutoLock lock(*mutex);
  1528. nsSSLIOLayerHelpers::mTLSTolerantSites->Put(key);
  1529. }
  1530. static PRStatus PR_CALLBACK
  1531. nsSSLIOLayerClose(PRFileDesc *fd)
  1532. {
  1533. nsNSSShutDownPreventionLock locker;
  1534. if (!fd)
  1535. return PR_FAILURE;
  1536. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] Shutting down socket\n", (void*)fd));
  1537. nsNSSSocketInfo *socketInfo = (nsNSSSocketInfo*)fd->secret;
  1538. NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");
  1539. return socketInfo->CloseSocketAndDestroy(locker);
  1540. }
  1541. PRStatus nsNSSSocketInfo::CloseSocketAndDestroy(
  1542. const nsNSSShutDownPreventionLock & /*proofOfLock*/)
  1543. {
  1544. nsNSSShutDownList::trackSSLSocketClose();
  1545. PRFileDesc* popped = PR_PopIOLayer(mFd, PR_TOP_IO_LAYER);
  1546. PRStatus status = mFd->methods->close(mFd);
  1547. // the nsNSSSocketInfo instance can out-live the connection, so we need some
  1548. // indication that the connection has been closed. mFd == nsnull is that
  1549. // indication. This is needed, for example, when the connection is closed
  1550. // before we have finished validating the server's certificate.
  1551. mFd = nsnull;
  1552. if (status != PR_SUCCESS) return status;
  1553. popped->identity = PR_INVALID_IO_LAYER;
  1554. NS_RELEASE_THIS();
  1555. popped->dtor(popped);
  1556. return PR_SUCCESS;
  1557. }
  1558. #if defined(DEBUG_SSL_VERBOSE) && defined(DUMP_BUFFER)
  1559. /* Dumps a (potentially binary) buffer using SSM_DEBUG.
  1560. (We could have used the version in ssltrace.c, but that's
  1561. specifically tailored to SSLTRACE. Sigh. */
  1562. #define DUMPBUF_LINESIZE 24
  1563. static void
  1564. nsDumpBuffer(unsigned char *buf, PRIntn len)
  1565. {
  1566. char hexbuf[DUMPBUF_LINESIZE*3+1];
  1567. char chrbuf[DUMPBUF_LINESIZE+1];
  1568. static const char *hex = "0123456789abcdef";
  1569. PRIntn i = 0, l = 0;
  1570. char ch, *c, *h;
  1571. if (len == 0)
  1572. return;
  1573. hexbuf[DUMPBUF_LINESIZE*3] = '\0';
  1574. chrbuf[DUMPBUF_LINESIZE] = '\0';
  1575. (void) memset(hexbuf, 0x20, DUMPBUF_LINESIZE*3);
  1576. (void) memset(chrbuf, 0x20, DUMPBUF_LINESIZE);
  1577. h = hexbuf;
  1578. c = chrbuf;
  1579. while (i < len)
  1580. {
  1581. ch = buf[i];
  1582. if (l == DUMPBUF_LINESIZE)
  1583. {
  1584. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("%s%s\n", hexbuf, chrbuf));
  1585. (void) memset(hexbuf, 0x20, DUMPBUF_LINESIZE*3);
  1586. (void) memset(chrbuf, 0x20, DUMPBUF_LINESIZE);
  1587. h = hexbuf;
  1588. c = chrbuf;
  1589. l = 0;
  1590. }
  1591. /* Convert a character to hex. */
  1592. *h++ = hex[(ch >> 4) & 0xf];
  1593. *h++ = hex[ch & 0xf];
  1594. h++;
  1595. /* Put the character (if it's printable) into the character buffer. */
  1596. if ((ch >= 0x20) && (ch <= 0x7e))
  1597. *c++ = ch;
  1598. else
  1599. *c++ = '.';
  1600. i++; l++;
  1601. }
  1602. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("%s%s\n", hexbuf, chrbuf));
  1603. }
  1604. #define DEBUG_DUMP_BUFFER(buf,len) nsDumpBuffer(buf,len)
  1605. #else
  1606. #define DEBUG_DUMP_BUFFER(buf,len)
  1607. #endif
  1608. static bool
  1609. isNonSSLErrorThatWeAllowToRetry(PRInt32 err, bool withInitialCleartext)
  1610. {
  1611. switch (err)
  1612. {
  1613. case PR_CONNECT_RESET_ERROR:
  1614. if (!withInitialCleartext)
  1615. return true;
  1616. break;
  1617. case PR_END_OF_FILE_ERROR:
  1618. return true;
  1619. }
  1620. return false;
  1621. }
  1622. static bool
  1623. isTLSIntoleranceError(PRInt32 err, bool withInitialCleartext)
  1624. {
  1625. // This function is supposed to decide, which error codes should
  1626. // be used to conclude server is TLS intolerant.
  1627. // Note this only happens during the initial SSL handshake.
  1628. //
  1629. // When not using a proxy we'll see a connection reset error.
  1630. // When using a proxy, we'll see an end of file error.
  1631. // In addition check for some error codes where it is reasonable
  1632. // to retry without TLS.
  1633. if (isNonSSLErrorThatWeAllowToRetry(err, withInitialCleartext))
  1634. return true;
  1635. switch (err)
  1636. {
  1637. case SSL_ERROR_BAD_MAC_ALERT:
  1638. case SSL_ERROR_BAD_MAC_READ:
  1639. case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
  1640. case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
  1641. case SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE:
  1642. case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
  1643. case SSL_ERROR_NO_CYPHER_OVERLAP:
  1644. case SSL_ERROR_BAD_SERVER:
  1645. case SSL_ERROR_BAD_BLOCK_PADDING:
  1646. case SSL_ERROR_UNSUPPORTED_VERSION:
  1647. case SSL_ERROR_PROTOCOL_VERSION_ALERT:
  1648. case SSL_ERROR_RX_MALFORMED_FINISHED:
  1649. case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE:
  1650. case SSL_ERROR_DECODE_ERROR_ALERT:
  1651. case SSL_ERROR_RX_UNKNOWN_ALERT:
  1652. return true;
  1653. }
  1654. return false;
  1655. }
  1656. class SSLErrorRunnable : public SyncRunnableBase
  1657. {
  1658. public:
  1659. SSLErrorRunnable(nsNSSSocketInfo * infoObject, PRErrorCode errorCode)
  1660. : mInfoObject(infoObject), mErrorCode(errorCode)
  1661. {
  1662. }
  1663. virtual void RunOnTargetThread()
  1664. {
  1665. nsHandleSSLError(mInfoObject, mErrorCode);
  1666. }
  1667. nsRefPtr<nsNSSSocketInfo> mInfoObject;
  1668. const PRErrorCode mErrorCode;
  1669. };
  1670. namespace {
  1671. PRInt32 checkHandshake(PRInt32 bytesTransfered, bool wasReading,
  1672. PRFileDesc* ssl_layer_fd,
  1673. nsNSSSocketInfo *socketInfo)
  1674. {
  1675. // This is where we work around all of those SSL servers that don't
  1676. // conform to the SSL spec and shutdown a connection when we request
  1677. // SSL v3.1 (aka TLS). The spec says the client says what version
  1678. // of the protocol we're willing to perform, in our case SSL v3.1
  1679. // In its response, the server says which version it wants to perform.
  1680. // Many servers out there only know how to do v3.0. Next, we're supposed
  1681. // to send back the version of the protocol we requested (ie v3.1). At
  1682. // this point many servers's implementations are broken and they shut
  1683. // down the connection when they don't see the version they sent back.
  1684. // This is supposed to prevent a man in the middle from forcing one
  1685. // side to dumb down to a lower level of the protocol. Unfortunately,
  1686. // there are enough broken servers out there that such a gross work-around
  1687. // is necessary. :(
  1688. // Additional comment added in August 2006:
  1689. // When we begun to use TLS hello extensions, we encountered a new class of
  1690. // broken server, which simply stall for a very long time.
  1691. // We would like to shorten the timeout, but limit this shorter timeout
  1692. // to the handshake phase.
  1693. // When we arrive here for the first time (for a given socket),
  1694. // we know the connection is established, and the application code
  1695. // tried the first read or write. This triggers the beginning of the
  1696. // SSL handshake phase at the SSL FD level.
  1697. // We'll make a note of the current time,
  1698. // and use this to measure the elapsed time since handshake begin.
  1699. // Do NOT assume TLS intolerance on a closed connection after bad cert ui was shown.
  1700. // Simply retry.
  1701. // This depends on the fact that Cert UI will not be shown again,
  1702. // should the user override the bad cert.
  1703. bool handleHandshakeResultNow;
  1704. socketInfo->GetHandshakePending(&handleHandshakeResultNow);
  1705. bool wantRetry = false;
  1706. if (0 > bytesTransfered) {
  1707. PRInt32 err = PR_GetError();
  1708. if (handleHandshakeResultNow) {
  1709. if (PR_WOULD_BLOCK_ERROR == err) {
  1710. socketInfo->SetHandshakeInProgress(true);
  1711. return bytesTransfered;
  1712. }
  1713. if (!wantRetry // no decision yet
  1714. && isTLSIntoleranceError(err, socketInfo->GetHasCleartextPhase()))
  1715. {
  1716. wantRetry = nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(socketInfo);
  1717. }
  1718. }
  1719. // This is the common place where we trigger non-cert-errors on a SSL
  1720. // socket. This might be reached at any time of the connection.
  1721. //
  1722. // The socketInfo->GetErrorCode() check is here to ensure we don't try to
  1723. // do the synchronous dispatch to the main thread unnecessarily after we've
  1724. // already handled a certificate error. (SSLErrorRunnable calls
  1725. // nsHandleSSLError, which has logic to avoid replacing the error message,
  1726. // so without the !socketInfo->GetErrorCode(), it would just be an
  1727. // expensive no-op.)
  1728. if (!wantRetry && (IS_SSL_ERROR(err) || IS_SEC_ERROR(err)) &&
  1729. !socketInfo->GetErrorCode()) {
  1730. nsRefPtr<SyncRunnableBase> runnable = new SSLErrorRunnable(socketInfo,
  1731. err);
  1732. (void) runnable->DispatchToMainThreadAndWait();
  1733. }
  1734. }
  1735. else if (wasReading && 0 == bytesTransfered) // zero bytes on reading, socket closed
  1736. {
  1737. if (handleHandshakeResultNow)
  1738. {
  1739. if (!wantRetry // no decision yet
  1740. && !socketInfo->GetHasCleartextPhase()) // mirror PR_CONNECT_RESET_ERROR treament
  1741. {
  1742. wantRetry =
  1743. nsSSLIOLayerHelpers::rememberPossibleTLSProblemSite(socketInfo);
  1744. }
  1745. }
  1746. }
  1747. if (wantRetry) {
  1748. // We want to cause the network layer to retry the connection.
  1749. PR_SetError(PR_CONNECT_RESET_ERROR, 0);
  1750. if (wasReading)
  1751. bytesTransfered = -1;
  1752. }
  1753. // TLS intolerant servers only cause the first transfer to fail, so let's
  1754. // set the HandshakePending attribute to false so that we don't try the logic
  1755. // above again in a subsequent transfer.
  1756. if (handleHandshakeResultNow) {
  1757. socketInfo->SetHandshakePending(false);
  1758. socketInfo->SetHandshakeInProgress(false);
  1759. }
  1760. return bytesTransfered;
  1761. }
  1762. }
  1763. static PRInt16 PR_CALLBACK
  1764. nsSSLIOLayerPoll(PRFileDesc * fd, PRInt16 in_flags, PRInt16 *out_flags)
  1765. {
  1766. nsNSSShutDownPreventionLock locker;
  1767. if (!out_flags)
  1768. {
  1769. NS_WARNING("nsSSLIOLayerPoll called with null out_flags");
  1770. return 0;
  1771. }
  1772. *out_flags = 0;
  1773. nsNSSSocketInfo * socketInfo =
  1774. getSocketInfoIfRunning(fd, not_reading_or_writing, locker);
  1775. if (!socketInfo) {
  1776. // If we get here, it is probably because certificate validation failed
  1777. // and this is the first I/O operation after the failure.
  1778. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
  1779. ("[%p] polling SSL socket right after certificate verification failed "
  1780. "or NSS shutdown or SDR logout %d\n",
  1781. fd, (int) in_flags));
  1782. NS_ASSERTION(in_flags & PR_POLL_EXCEPT,
  1783. "caller did not poll for EXCEPT (canceled)");
  1784. // Since this poll method cannot return errors, we want the caller to call
  1785. // PR_Send/PR_Recv right away to get the error, so we tell that we are
  1786. // ready for whatever I/O they are asking for. (See getSocketInfoIfRunning).
  1787. *out_flags = in_flags | PR_POLL_EXCEPT; // see also bug 480619
  1788. return in_flags;
  1789. }
  1790. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
  1791. (socketInfo->IsWaitingForCertVerification()
  1792. ? "[%p] polling SSL socket during certificate verification using lower %d\n"
  1793. : "[%p] poll SSL socket using lower %d\n",
  1794. fd, (int) in_flags));
  1795. // See comments in HandshakeTimeout before moving and/or changing this block
  1796. if (socketInfo->HandshakeTimeout()) {
  1797. NS_WARNING("SSL handshake timed out");
  1798. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] handshake timed out\n", fd));
  1799. NS_ASSERTION(in_flags & PR_POLL_EXCEPT,
  1800. "caller did not poll for EXCEPT (handshake timeout)");
  1801. *out_flags = in_flags | PR_POLL_EXCEPT;
  1802. socketInfo->SetCanceled(PR_CONNECT_RESET_ERROR, PlainErrorMessage);
  1803. return in_flags;
  1804. }
  1805. // We want the handshake to continue during certificate validation, so we
  1806. // don't need to do anything special here. libssl automatically blocks when
  1807. // it reaches any point that would be unsafe to send/receive something before
  1808. // cert validation is complete.
  1809. PRInt16 result = fd->lower->methods->poll(fd->lower, in_flags, out_flags);
  1810. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] poll SSL socket returned %d\n",
  1811. (void*)fd, (int) result));
  1812. return result;
  1813. }
  1814. bool nsSSLIOLayerHelpers::nsSSLIOLayerInitialized = false;
  1815. PRDescIdentity nsSSLIOLayerHelpers::nsSSLIOLayerIdentity;
  1816. PRIOMethods nsSSLIOLayerHelpers::nsSSLIOLayerMethods;
  1817. Mutex *nsSSLIOLayerHelpers::mutex = nsnull;
  1818. nsCStringHashSet *nsSSLIOLayerHelpers::mTLSIntolerantSites = nsnull;
  1819. nsCStringHashSet *nsSSLIOLayerHelpers::mTLSTolerantSites = nsnull;
  1820. nsPSMRememberCertErrorsTable *nsSSLIOLayerHelpers::mHostsWithCertErrors = nsnull;
  1821. nsCStringHashSet *nsSSLIOLayerHelpers::mRenegoUnrestrictedSites = nsnull;
  1822. bool nsSSLIOLayerHelpers::mTreatUnsafeNegotiationAsBroken = false;
  1823. PRInt32 nsSSLIOLayerHelpers::mWarnLevelMissingRFC5746 = 1;
  1824. static PRIntn _PSM_InvalidInt(void)
  1825. {
  1826. PR_ASSERT(!"I/O method is invalid");
  1827. PR_SetError(PR_INVALID_METHOD_ERROR, 0);
  1828. return -1;
  1829. }
  1830. static PRInt64 _PSM_InvalidInt64(void)
  1831. {
  1832. PR_ASSERT(!"I/O method is invalid");
  1833. PR_SetError(PR_INVALID_METHOD_ERROR, 0);
  1834. return -1;
  1835. }
  1836. static PRStatus _PSM_InvalidStatus(void)
  1837. {
  1838. PR_ASSERT(!"I/O method is invalid");
  1839. PR_SetError(PR_INVALID_METHOD_ERROR, 0);
  1840. return PR_FAILURE;
  1841. }
  1842. static PRFileDesc *_PSM_InvalidDesc(void)
  1843. {
  1844. PR_ASSERT(!"I/O method is invalid");
  1845. PR_SetError(PR_INVALID_METHOD_ERROR, 0);
  1846. return NULL;
  1847. }
  1848. static PRStatus PR_CALLBACK PSMGetsockname(PRFileDesc *fd, PRNetAddr *addr)
  1849. {
  1850. nsNSSShutDownPreventionLock locker;
  1851. if (!getSocketInfoIfRunning(fd, not_reading_or_writing, locker))
  1852. return PR_FAILURE;
  1853. return fd->lower->methods->getsockname(fd->lower, addr);
  1854. }
  1855. static PRStatus PR_CALLBACK PSMGetpeername(PRFileDesc *fd, PRNetAddr *addr)
  1856. {
  1857. nsNSSShutDownPreventionLock locker;
  1858. if (!getSocketInfoIfRunning(fd, not_reading_or_writing, locker))
  1859. return PR_FAILURE;
  1860. return fd->lower->methods->getpeername(fd->lower, addr);
  1861. }
  1862. static PRStatus PR_CALLBACK PSMGetsocketoption(PRFileDesc *fd,
  1863. PRSocketOptionData *data)
  1864. {
  1865. nsNSSShutDownPreventionLock locker;
  1866. if (!getSocketInfoIfRunning(fd, not_reading_or_writing, locker))
  1867. return PR_FAILURE;
  1868. return fd->lower->methods->getsocketoption(fd, data);
  1869. }
  1870. static PRStatus PR_CALLBACK PSMSetsocketoption(PRFileDesc *fd,
  1871. const PRSocketOptionData *data)
  1872. {
  1873. nsNSSShutDownPreventionLock locker;
  1874. if (!getSocketInfoIfRunning(fd, not_reading_or_writing, locker))
  1875. return PR_FAILURE;
  1876. return fd->lower->methods->setsocketoption(fd, data);
  1877. }
  1878. static PRInt32 PR_CALLBACK PSMRecv(PRFileDesc *fd, void *buf, PRInt32 amount,
  1879. PRIntn flags, PRIntervalTime timeout)
  1880. {
  1881. nsNSSShutDownPreventionLock locker;
  1882. nsNSSSocketInfo *socketInfo = getSocketInfoIfRunning(fd, reading, locker);
  1883. if (!socketInfo)
  1884. return -1;
  1885. if (flags != PR_MSG_PEEK && flags != 0) {
  1886. PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  1887. return -1;
  1888. }
  1889. PRInt32 bytesRead = fd->lower->methods->recv(fd->lower, buf, amount, flags,
  1890. timeout);
  1891. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] read %d bytes\n", (void*)fd, bytesRead));
  1892. #ifdef DEBUG_SSL_VERBOSE
  1893. DEBUG_DUMP_BUFFER((unsigned char*)buf, bytesRead);
  1894. #endif
  1895. return checkHandshake(bytesRead, true, fd, socketInfo);
  1896. }
  1897. static PRInt32 PR_CALLBACK PSMSend(PRFileDesc *fd, const void *buf, PRInt32 amount,
  1898. PRIntn flags, PRIntervalTime timeout)
  1899. {
  1900. nsNSSShutDownPreventionLock locker;
  1901. nsNSSSocketInfo *socketInfo = getSocketInfoIfRunning(fd, writing, locker);
  1902. if (!socketInfo)
  1903. return -1;
  1904. if (flags != 0) {
  1905. PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  1906. return -1;
  1907. }
  1908. #ifdef DEBUG_SSL_VERBOSE
  1909. DEBUG_DUMP_BUFFER((unsigned char*)buf, amount);
  1910. #endif
  1911. PRInt32 bytesWritten = fd->lower->methods->send(fd->lower, buf, amount,
  1912. flags, timeout);
  1913. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] wrote %d bytes\n",
  1914. fd, bytesWritten));
  1915. return checkHandshake(bytesWritten, false, fd, socketInfo);
  1916. }
  1917. static PRInt32 PR_CALLBACK
  1918. nsSSLIOLayerRead(PRFileDesc* fd, void* buf, PRInt32 amount)
  1919. {
  1920. return PSMRecv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
  1921. }
  1922. static PRInt32 PR_CALLBACK
  1923. nsSSLIOLayerWrite(PRFileDesc* fd, const void* buf, PRInt32 amount)
  1924. {
  1925. return PSMSend(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
  1926. }
  1927. static PRStatus PR_CALLBACK PSMConnectcontinue(PRFileDesc *fd, PRInt16 out_flags)
  1928. {
  1929. nsNSSShutDownPreventionLock locker;
  1930. if (!getSocketInfoIfRunning(fd, not_reading_or_writing, locker)) {
  1931. return PR_FAILURE;
  1932. }
  1933. return fd->lower->methods->connectcontinue(fd, out_flags);
  1934. }
  1935. static PRIntn PSMAvailable(void)
  1936. {
  1937. // This is called through PR_Available(), but is not implemented in PSM
  1938. PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
  1939. return -1;
  1940. }
  1941. static PRInt64 PSMAvailable64(void)
  1942. {
  1943. // This is called through PR_Available(), but is not implemented in PSM
  1944. PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
  1945. return -1;
  1946. }
  1947. nsresult nsSSLIOLayerHelpers::Init()
  1948. {
  1949. if (!nsSSLIOLayerInitialized) {
  1950. nsSSLIOLayerInitialized = true;
  1951. nsSSLIOLayerIdentity = PR_GetUniqueIdentity("NSS layer");
  1952. nsSSLIOLayerMethods = *PR_GetDefaultIOMethods();
  1953. nsSSLIOLayerMethods.available = (PRAvailableFN)PSMAvailable;
  1954. nsSSLIOLayerMethods.available64 = (PRAvailable64FN)PSMAvailable64;
  1955. nsSSLIOLayerMethods.fsync = (PRFsyncFN)_PSM_InvalidStatus;
  1956. nsSSLIOLayerMethods.seek = (PRSeekFN)_PSM_InvalidInt;
  1957. nsSSLIOLayerMethods.seek64 = (PRSeek64FN)_PSM_InvalidInt64;
  1958. nsSSLIOLayerMethods.fileInfo = (PRFileInfoFN)_PSM_InvalidStatus;
  1959. nsSSLIOLayerMethods.fileInfo64 = (PRFileInfo64FN)_PSM_InvalidStatus;
  1960. nsSSLIOLayerMethods.writev = (PRWritevFN)_PSM_InvalidInt;
  1961. nsSSLIOLayerMethods.accept = (PRAcceptFN)_PSM_InvalidDesc;
  1962. nsSSLIOLayerMethods.bind = (PRBindFN)_PSM_InvalidStatus;
  1963. nsSSLIOLayerMethods.listen = (PRListenFN)_PSM_InvalidStatus;
  1964. nsSSLIOLayerMethods.shutdown = (PRShutdownFN)_PSM_InvalidStatus;
  1965. nsSSLIOLayerMethods.recvfrom = (PRRecvfromFN)_PSM_InvalidInt;
  1966. nsSSLIOLayerMethods.sendto = (PRSendtoFN)_PSM_InvalidInt;
  1967. nsSSLIOLayerMethods.acceptread = (PRAcceptreadFN)_PSM_InvalidInt;
  1968. nsSSLIOLayerMethods.transmitfile = (PRTransmitfileFN)_PSM_InvalidInt;
  1969. nsSSLIOLayerMethods.sendfile = (PRSendfileFN)_PSM_InvalidInt;
  1970. nsSSLIOLayerMethods.getsockname = PSMGetsockname;
  1971. nsSSLIOLayerMethods.getpeername = PSMGetpeername;
  1972. nsSSLIOLayerMethods.getsocketoption = PSMGetsocketoption;
  1973. nsSSLIOLayerMethods.setsocketoption = PSMSetsocketoption;
  1974. nsSSLIOLayerMethods.recv = PSMRecv;
  1975. nsSSLIOLayerMethods.send = PSMSend;
  1976. nsSSLIOLayerMethods.connectcontinue = PSMConnectcontinue;
  1977. nsSSLIOLayerMethods.connect = nsSSLIOLayerConnect;
  1978. nsSSLIOLayerMethods.close = nsSSLIOLayerClose;
  1979. nsSSLIOLayerMethods.write = nsSSLIOLayerWrite;
  1980. nsSSLIOLayerMethods.read = nsSSLIOLayerRead;
  1981. nsSSLIOLayerMethods.poll = nsSSLIOLayerPoll;
  1982. }
  1983. mutex = new Mutex("nsSSLIOLayerHelpers.mutex");
  1984. mTLSIntolerantSites = new nsCStringHashSet();
  1985. if (!mTLSIntolerantSites)
  1986. return NS_ERROR_OUT_OF_MEMORY;
  1987. mTLSIntolerantSites->Init(1);
  1988. mTLSTolerantSites = new nsCStringHashSet();
  1989. if (!mTLSTolerantSites)
  1990. return NS_ERROR_OUT_OF_MEMORY;
  1991. // Initialize the tolerant site hashtable to 16 items at the start seems
  1992. // reasonable as most servers are TLS tolerant. We just want to lower
  1993. // the rate of hashtable array reallocation.
  1994. mTLSTolerantSites->Init(16);
  1995. mRenegoUnrestrictedSites = new nsCStringHashSet();
  1996. if (!mRenegoUnrestrictedSites)
  1997. return NS_ERROR_OUT_OF_MEMORY;
  1998. mRenegoUnrestrictedSites->Init(1);
  1999. mTreatUnsafeNegotiationAsBroken = false;
  2000. mHostsWithCertErrors = new nsPSMRememberCertErrorsTable();
  2001. if (!mHostsWithCertErrors || !mHostsWithCertErrors->mErrorHosts.IsInitialized())
  2002. return NS_ERROR_OUT_OF_MEMORY;
  2003. return NS_OK;
  2004. }
  2005. void nsSSLIOLayerHelpers::addIntolerantSite(const nsCString &str)
  2006. {
  2007. MutexAutoLock lock(*mutex);
  2008. // Remember intolerant site only if it is not known as tolerant
  2009. if (!mTLSTolerantSites->Contains(str))
  2010. nsSSLIOLayerHelpers::mTLSIntolerantSites->Put(str);
  2011. }
  2012. void nsSSLIOLayerHelpers::removeIntolerantSite(const nsCString &str)
  2013. {
  2014. MutexAutoLock lock(*mutex);
  2015. nsSSLIOLayerHelpers::mTLSIntolerantSites->Remove(str);
  2016. }
  2017. bool nsSSLIOLayerHelpers::isKnownAsIntolerantSite(const nsCString &str)
  2018. {
  2019. MutexAutoLock lock(*mutex);
  2020. return mTLSIntolerantSites->Contains(str);
  2021. }
  2022. void nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(const nsCString &str)
  2023. {
  2024. MutexAutoLock lock(*mutex);
  2025. if (mRenegoUnrestrictedSites) {
  2026. delete mRenegoUnrestrictedSites;
  2027. mRenegoUnrestrictedSites = nsnull;
  2028. }
  2029. mRenegoUnrestrictedSites = new nsCStringHashSet();
  2030. if (!mRenegoUnrestrictedSites)
  2031. return;
  2032. mRenegoUnrestrictedSites->Init(1);
  2033. nsCCharSeparatedTokenizer toker(str, ',');
  2034. while (toker.hasMoreTokens()) {
  2035. const nsCSubstring &host = toker.nextToken();
  2036. if (!host.IsEmpty()) {
  2037. mRenegoUnrestrictedSites->Put(host);
  2038. }
  2039. }
  2040. }
  2041. bool nsSSLIOLayerHelpers::isRenegoUnrestrictedSite(const nsCString &str)
  2042. {
  2043. MutexAutoLock lock(*mutex);
  2044. return mRenegoUnrestrictedSites->Contains(str);
  2045. }
  2046. void nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(bool broken)
  2047. {
  2048. MutexAutoLock lock(*mutex);
  2049. mTreatUnsafeNegotiationAsBroken = broken;
  2050. }
  2051. bool nsSSLIOLayerHelpers::treatUnsafeNegotiationAsBroken()
  2052. {
  2053. MutexAutoLock lock(*mutex);
  2054. return mTreatUnsafeNegotiationAsBroken;
  2055. }
  2056. void nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(PRInt32 level)
  2057. {
  2058. MutexAutoLock lock(*mutex);
  2059. mWarnLevelMissingRFC5746 = level;
  2060. }
  2061. PRInt32 nsSSLIOLayerHelpers::getWarnLevelMissingRFC5746()
  2062. {
  2063. MutexAutoLock lock(*mutex);
  2064. return mWarnLevelMissingRFC5746;
  2065. }
  2066. nsresult
  2067. nsSSLIOLayerNewSocket(PRInt32 family,
  2068. const char *host,
  2069. PRInt32 port,
  2070. const char *proxyHost,
  2071. PRInt32 proxyPort,
  2072. PRFileDesc **fd,
  2073. nsISupports** info,
  2074. bool forSTARTTLS,
  2075. bool anonymousLoad)
  2076. {
  2077. PRFileDesc* sock = PR_OpenTCPSocket(family);
  2078. if (!sock) return NS_ERROR_OUT_OF_MEMORY;
  2079. nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, proxyHost, proxyPort,
  2080. sock, info, forSTARTTLS, anonymousLoad);
  2081. if (NS_FAILED(rv)) {
  2082. PR_Close(sock);
  2083. return rv;
  2084. }
  2085. *fd = sock;
  2086. return NS_OK;
  2087. }
  2088. /*
  2089. * Function: SECStatus nsConvertCANamesToStrings()
  2090. * Purpose: creates CA names strings from (CERTDistNames* caNames)
  2091. *
  2092. * Arguments and return values
  2093. * - arena: arena to allocate strings on
  2094. * - caNameStrings: filled with CA names strings on return
  2095. * - caNames: CERTDistNames to extract strings from
  2096. * - return: SECSuccess if successful; error code otherwise
  2097. *
  2098. * Note: copied in its entirety from Nova code
  2099. */
  2100. SECStatus nsConvertCANamesToStrings(PRArenaPool* arena, char** caNameStrings,
  2101. CERTDistNames* caNames)
  2102. {
  2103. SECItem* dername;
  2104. SECStatus rv;
  2105. int headerlen;
  2106. PRUint32 contentlen;
  2107. SECItem newitem;
  2108. int n;
  2109. char* namestring;
  2110. for (n = 0; n < caNames->nnames; n++) {
  2111. newitem.data = NULL;
  2112. dername = &caNames->names[n];
  2113. rv = DER_Lengths(dername, &headerlen, &contentlen);
  2114. if (rv != SECSuccess) {
  2115. goto loser;
  2116. }
  2117. if (headerlen + contentlen != dername->len) {
  2118. /* This must be from an enterprise 2.x server, which sent
  2119. * incorrectly formatted der without the outer wrapper of
  2120. * type and length. Fix it up by adding the top level
  2121. * header.
  2122. */
  2123. if (dername->len <= 127) {
  2124. newitem.data = (unsigned char *) PR_Malloc(dername->len + 2);
  2125. if (newitem.data == NULL) {
  2126. goto loser;
  2127. }
  2128. newitem.data[0] = (unsigned char)0x30;
  2129. newitem.data[1] = (unsigned char)dername->len;
  2130. (void)memcpy(&newitem.data[2], dername->data, dername->len);
  2131. }
  2132. else if (dername->len <= 255) {
  2133. newitem.data = (unsigned char *) PR_Malloc(dername->len + 3);
  2134. if (newitem.data == NULL) {
  2135. goto loser;
  2136. }
  2137. newitem.data[0] = (unsigned char)0x30;
  2138. newitem.data[1] = (unsigned char)0x81;
  2139. newitem.data[2] = (unsigned char)dername->len;
  2140. (void)memcpy(&newitem.data[3], dername->data, dername->len);
  2141. }
  2142. else {
  2143. /* greater than 256, better be less than 64k */
  2144. newitem.data = (unsigned char *) PR_Malloc(dername->len + 4);
  2145. if (newitem.data == NULL) {
  2146. goto loser;
  2147. }
  2148. newitem.data[0] = (unsigned char)0x30;
  2149. newitem.data[1] = (unsigned char)0x82;
  2150. newitem.data[2] = (unsigned char)((dername->len >> 8) & 0xff);
  2151. newitem.data[3] = (unsigned char)(dername->len & 0xff);
  2152. memcpy(&newitem.data[4], dername->data, dername->len);
  2153. }
  2154. dername = &newitem;
  2155. }
  2156. namestring = CERT_DerNameToAscii(dername);
  2157. if (namestring == NULL) {
  2158. /* XXX - keep going until we fail to convert the name */
  2159. caNameStrings[n] = const_cast<char*>("");
  2160. }
  2161. else {
  2162. caNameStrings[n] = PORT_ArenaStrdup(arena, namestring);
  2163. PR_Free(namestring);
  2164. if (caNameStrings[n] == NULL) {
  2165. goto loser;
  2166. }
  2167. }
  2168. if (newitem.data != NULL) {
  2169. PR_Free(newitem.data);
  2170. }
  2171. }
  2172. return SECSuccess;
  2173. loser:
  2174. if (newitem.data != NULL) {
  2175. PR_Free(newitem.data);
  2176. }
  2177. return SECFailure;
  2178. }
  2179. /*
  2180. * structs and ASN1 templates for the limited scope-of-use extension
  2181. *
  2182. * CertificateScopeEntry ::= SEQUENCE {
  2183. * name GeneralName, -- pattern, as for NameConstraints
  2184. * portNumber INTEGER OPTIONAL }
  2185. *
  2186. * CertificateScopeOfUse ::= SEQUENCE OF CertificateScopeEntry
  2187. */
  2188. /*
  2189. * CERTCertificateScopeEntry: struct for scope entry that can be consumed by
  2190. * the code
  2191. * certCertificateScopeOfUse: struct that represents the decoded extension data
  2192. */
  2193. typedef struct {
  2194. SECItem derConstraint;
  2195. SECItem derPort;
  2196. CERTGeneralName* constraint; /* decoded constraint */
  2197. PRIntn port; /* decoded port number */
  2198. } CERTCertificateScopeEntry;
  2199. typedef struct {
  2200. CERTCertificateScopeEntry** entries;
  2201. } certCertificateScopeOfUse;
  2202. /* corresponding ASN1 templates */
  2203. static const SEC_ASN1Template cert_CertificateScopeEntryTemplate[] = {
  2204. { SEC_ASN1_SEQUENCE,
  2205. 0, NULL, sizeof(CERTCertificateScopeEntry) },
  2206. { SEC_ASN1_ANY,
  2207. offsetof(CERTCertificateScopeEntry, derConstraint) },
  2208. { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
  2209. offsetof(CERTCertificateScopeEntry, derPort) },
  2210. { 0 }
  2211. };
  2212. static const SEC_ASN1Template cert_CertificateScopeOfUseTemplate[] = {
  2213. { SEC_ASN1_SEQUENCE_OF, 0, cert_CertificateScopeEntryTemplate }
  2214. };
  2215. #if 0
  2216. /*
  2217. * decodes the extension data and create CERTCertificateScopeEntry that can
  2218. * be consumed by the code
  2219. */
  2220. static
  2221. SECStatus cert_DecodeScopeOfUseEntries(PRArenaPool* arena, SECItem* extData,
  2222. CERTCertificateScopeEntry*** entries,
  2223. int* numEntries)
  2224. {
  2225. certCertificateScopeOfUse* scope = NULL;
  2226. SECStatus rv = SECSuccess;
  2227. int i;
  2228. *entries = NULL; /* in case of failure */
  2229. *numEntries = 0; /* ditto */
  2230. scope = (certCertificateScopeOfUse*)
  2231. PORT_ArenaZAlloc(arena, sizeof(certCertificateScopeOfUse));
  2232. if (scope == NULL) {
  2233. goto loser;
  2234. }
  2235. rv = SEC_ASN1DecodeItem(arena, (void*)scope,
  2236. cert_CertificateScopeOfUseTemplate, extData);
  2237. if (rv != SECSuccess) {
  2238. goto loser;
  2239. }
  2240. *entries = scope->entries;
  2241. PR_ASSERT(*entries != NULL);
  2242. /* first, let's count 'em. */
  2243. for (i = 0; (*entries)[i] != NULL; i++) ;
  2244. *numEntries = i;
  2245. /* convert certCertificateScopeEntry sequence into what we can readily
  2246. * use
  2247. */
  2248. for (i = 0; i < *numEntries; i++) {
  2249. (*entries)[i]->constraint =
  2250. CERT_DecodeGeneralName(arena, &((*entries)[i]->derConstraint),
  2251. NULL);
  2252. if ((*entries)[i]->derPort.data != NULL) {
  2253. (*entries)[i]->port =
  2254. (int)DER_GetInteger(&((*entries)[i]->derPort));
  2255. }
  2256. else {
  2257. (*entries)[i]->port = 0;
  2258. }
  2259. }
  2260. goto done;
  2261. loser:
  2262. if (rv == SECSuccess) {
  2263. rv = SECFailure;
  2264. }
  2265. done:
  2266. return rv;
  2267. }
  2268. static SECStatus cert_DecodeCertIPAddress(SECItem* genname,
  2269. PRUint32* constraint, PRUint32* mask)
  2270. {
  2271. /* in case of failure */
  2272. *constraint = 0;
  2273. *mask = 0;
  2274. PR_ASSERT(genname->data != NULL);
  2275. if (genname->data == NULL) {
  2276. return SECFailure;
  2277. }
  2278. if (genname->len != 8) {
  2279. /* the length must be 4 byte IP address with 4 byte subnet mask */
  2280. return SECFailure;
  2281. }
  2282. /* get them in the right order */
  2283. *constraint = PR_ntohl((PRUint32)(*genname->data));
  2284. *mask = PR_ntohl((PRUint32)(*(genname->data + 4)));
  2285. return SECSuccess;
  2286. }
  2287. static char* _str_to_lower(char* string)
  2288. {
  2289. #ifdef XP_WIN
  2290. return _strlwr(string);
  2291. #else
  2292. int i;
  2293. for (i = 0; string[i] != '\0'; i++) {
  2294. string[i] = tolower(string[i]);
  2295. }
  2296. return string;
  2297. #endif
  2298. }
  2299. /*
  2300. * Sees if the client certificate has a restriction in presenting the cert
  2301. * to the host: returns true if there is no restriction or if the hostname
  2302. * (and the port) satisfies the restriction, or false if the hostname (and
  2303. * the port) does not satisfy the restriction
  2304. */
  2305. static bool CERT_MatchesScopeOfUse(CERTCertificate* cert, char* hostname,
  2306. char* hostIP, PRIntn port)
  2307. {
  2308. bool rv = true; /* whether the cert can be presented */
  2309. SECStatus srv;
  2310. SECItem extData;
  2311. PRArenaPool* arena = NULL;
  2312. CERTCertificateScopeEntry** entries = NULL;
  2313. /* arrays of decoded scope entries */
  2314. int numEntries = 0;
  2315. int i;
  2316. char* hostLower = NULL;
  2317. PRUint32 hostIPAddr = 0;
  2318. PR_ASSERT((cert != NULL) && (hostname != NULL) && (hostIP != NULL));
  2319. /* find cert extension */
  2320. srv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_SCOPE_OF_USE,
  2321. &extData);
  2322. if (srv != SECSuccess) {
  2323. /* most of the time, this means the extension was not found: also,
  2324. * since this is not a critical extension (as of now) we may simply
  2325. * return true
  2326. */
  2327. goto done;
  2328. }
  2329. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2330. if (arena == NULL) {
  2331. goto done;
  2332. }
  2333. /* decode the scope of use entries into pairs of GeneralNames and
  2334. * an optional port numbers
  2335. */
  2336. srv = cert_DecodeScopeOfUseEntries(arena, &extData, &entries, &numEntries);
  2337. if (srv != SECSuccess) {
  2338. /* XXX What should we do when we failed to decode the extension? This
  2339. * may mean either the extension was malformed or some (unlikely)
  2340. * fatal error on our part: my argument is that if the extension
  2341. * was malformed the extension "disqualifies" as a valid
  2342. * constraint and we may present the cert
  2343. */
  2344. goto done;
  2345. }
  2346. /* loop over these structures */
  2347. for (i = 0; i < numEntries; i++) {
  2348. /* determine whether the GeneralName is a DNS pattern, an IP address
  2349. * constraint, or else
  2350. */
  2351. CERTGeneralName* genname = entries[i]->constraint;
  2352. /* if constraint is NULL, don't bother looking */
  2353. if (genname == NULL) {
  2354. /* this is not a failure: just continue */
  2355. continue;
  2356. }
  2357. switch (genname->type) {
  2358. case certDNSName: {
  2359. /* we have a DNS name constraint; we should use only the host name
  2360. * information
  2361. */
  2362. char* pattern = NULL;
  2363. char* substring = NULL;
  2364. /* null-terminate the string */
  2365. genname->name.other.data[genname->name.other.len] = '\0';
  2366. pattern = _str_to_lower((char*)genname->name.other.data);
  2367. if (hostLower == NULL) {
  2368. /* so that it's done only if necessary and only once */
  2369. hostLower = _str_to_lower(PL_strdup(hostname));
  2370. }
  2371. /* the hostname satisfies the constraint */
  2372. if (((substring = strstr(hostLower, pattern)) != NULL) &&
  2373. /* the hostname contains the pattern */
  2374. (strlen(substring) == strlen(pattern)) &&
  2375. /* the hostname ends with the pattern */
  2376. ((substring == hostLower) || (*(substring-1) == '.'))) {
  2377. /* the hostname either is identical to the pattern or
  2378. * belongs to a subdomain
  2379. */
  2380. rv = true;
  2381. }
  2382. else {
  2383. rv = false;
  2384. }
  2385. /* clean up strings if necessary */
  2386. break;
  2387. }
  2388. case certIPAddress: {
  2389. PRUint32 constraint;
  2390. PRUint32 mask;
  2391. PRNetAddr addr;
  2392. if (hostIPAddr == 0) {
  2393. /* so that it's done only if necessary and only once */
  2394. PR_StringToNetAddr(hostIP, &addr);
  2395. hostIPAddr = addr.inet.ip;
  2396. }
  2397. if (cert_DecodeCertIPAddress(&(genname->name.other), &constraint,
  2398. &mask) != SECSuccess) {
  2399. continue;
  2400. }
  2401. if ((hostIPAddr & mask) == (constraint & mask)) {
  2402. rv = true;
  2403. }
  2404. else {
  2405. rv = false;
  2406. }
  2407. break;
  2408. }
  2409. default:
  2410. /* ill-formed entry: abort */
  2411. continue; /* go to the next entry */
  2412. }
  2413. if (!rv) {
  2414. /* we do not need to check the port: go to the next entry */
  2415. continue;
  2416. }
  2417. /* finally, check the optional port number */
  2418. if ((entries[i]->port != 0) && (port != entries[i]->port)) {
  2419. /* port number does not match */
  2420. rv = false;
  2421. continue;
  2422. }
  2423. /* we have a match */
  2424. PR_ASSERT(rv);
  2425. break;
  2426. }
  2427. done:
  2428. /* clean up entries */
  2429. if (arena != NULL) {
  2430. PORT_FreeArena(arena, false);
  2431. }
  2432. if (hostLower != NULL) {
  2433. PR_Free(hostLower);
  2434. }
  2435. return rv;
  2436. }
  2437. #endif
  2438. /*
  2439. * Function: SSMStatus SSM_SetUserCertChoice()
  2440. * Purpose: sets certChoice by reading the preference
  2441. *
  2442. * Arguments and return values
  2443. * - conn: SSMSSLDataConnection
  2444. * - returns: SSM_SUCCESS if successful; SSM_FAILURE otherwise
  2445. *
  2446. * Note: If done properly, this function will read the identifier strings
  2447. * for ASK and AUTO modes, read the selected strings from the
  2448. * preference, compare the strings, and determine in which mode it is
  2449. * in.
  2450. * We currently use ASK mode for UI apps and AUTO mode for UI-less
  2451. * apps without really asking for preferences.
  2452. */
  2453. nsresult nsGetUserCertChoice(SSM_UserCertChoice* certChoice)
  2454. {
  2455. char *mode=NULL;
  2456. nsresult ret;
  2457. NS_ENSURE_ARG_POINTER(certChoice);
  2458. nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
  2459. ret = pref->GetCharPref("security.default_personal_cert", &mode);
  2460. if (NS_FAILED(ret)) {
  2461. goto loser;
  2462. }
  2463. if (PL_strcmp(mode, "Select Automatically") == 0) {
  2464. *certChoice = AUTO;
  2465. }
  2466. else if (PL_strcmp(mode, "Ask Every Time") == 0) {
  2467. *certChoice = ASK;
  2468. }
  2469. else {
  2470. // Most likely we see a nickname from a migrated cert.
  2471. // We do not currently support that, ask the user which cert to use.
  2472. *certChoice = ASK;
  2473. }
  2474. loser:
  2475. if (mode) {
  2476. nsMemory::Free(mode);
  2477. }
  2478. return ret;
  2479. }
  2480. static bool hasExplicitKeyUsageNonRepudiation(CERTCertificate *cert)
  2481. {
  2482. /* There is no extension, v1 or v2 certificate */
  2483. if (!cert->extensions)
  2484. return false;
  2485. SECStatus srv;
  2486. SECItem keyUsageItem;
  2487. keyUsageItem.data = NULL;
  2488. srv = CERT_FindKeyUsageExtension(cert, &keyUsageItem);
  2489. if (srv == SECFailure)
  2490. return false;
  2491. unsigned char keyUsage = keyUsageItem.data[0];
  2492. PORT_Free (keyUsageItem.data);
  2493. return !!(keyUsage & KU_NON_REPUDIATION);
  2494. }
  2495. class ClientAuthDataRunnable : public SyncRunnableBase
  2496. {
  2497. public:
  2498. ClientAuthDataRunnable(CERTDistNames* caNames,
  2499. CERTCertificate** pRetCert,
  2500. SECKEYPrivateKey** pRetKey,
  2501. nsNSSSocketInfo * info,
  2502. CERTCertificate * serverCert)
  2503. : mRV(SECFailure)
  2504. , mErrorCodeToReport(SEC_ERROR_NO_MEMORY)
  2505. , mPRetCert(pRetCert)
  2506. , mPRetKey(pRetKey)
  2507. , mCANames(caNames)
  2508. , mSocketInfo(info)
  2509. , mServerCert(serverCert)
  2510. {
  2511. }
  2512. SECStatus mRV; // out
  2513. PRErrorCode mErrorCodeToReport; // out
  2514. CERTCertificate** const mPRetCert; // in/out
  2515. SECKEYPrivateKey** const mPRetKey; // in/out
  2516. protected:
  2517. virtual void RunOnTargetThread();
  2518. private:
  2519. CERTDistNames* const mCANames; // in
  2520. nsNSSSocketInfo * const mSocketInfo; // in
  2521. CERTCertificate * const mServerCert; // in
  2522. };
  2523. /*
  2524. * Function: SECStatus SSM_SSLGetClientAuthData()
  2525. * Purpose: this callback function is used to pull client certificate
  2526. * information upon server request
  2527. *
  2528. * Arguments and return values
  2529. * - arg: SSL data connection
  2530. * - socket: SSL socket we're dealing with
  2531. * - caNames: list of CA names
  2532. * - pRetCert: returns a pointer to a pointer to a valid certificate if
  2533. * successful; otherwise NULL
  2534. * - pRetKey: returns a pointer to a pointer to the corresponding key if
  2535. * successful; otherwise NULL
  2536. * - returns: SECSuccess if successful; error code otherwise
  2537. */
  2538. SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket,
  2539. CERTDistNames* caNames,
  2540. CERTCertificate** pRetCert,
  2541. SECKEYPrivateKey** pRetKey)
  2542. {
  2543. nsNSSShutDownPreventionLock locker;
  2544. if (!socket || !caNames || !pRetCert || !pRetKey) {
  2545. PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  2546. return SECFailure;
  2547. }
  2548. nsRefPtr<nsNSSSocketInfo> info
  2549. = reinterpret_cast<nsNSSSocketInfo*>(socket->higher->secret);
  2550. CERTCertificate* serverCert = SSL_PeerCertificate(socket);
  2551. if (!serverCert) {
  2552. NS_NOTREACHED("Missing server certificate should have been detected during "
  2553. "server cert authentication.");
  2554. PR_SetError(SSL_ERROR_NO_CERTIFICATE, 0);
  2555. return SECFailure;
  2556. }
  2557. if (info->GetJoined()) {
  2558. // We refuse to send a client certificate when there are multiple hostnames
  2559. // joined on this connection, because we only show the user one hostname
  2560. // (mHostName) in the client certificate UI.
  2561. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
  2562. ("[%p] Not returning client cert due to previous join\n", socket));
  2563. *pRetCert = nsnull;
  2564. *pRetKey = nsnull;
  2565. return SECSuccess;
  2566. }
  2567. // XXX: This should be done asynchronously; see bug 696976
  2568. nsRefPtr<ClientAuthDataRunnable> runnable =
  2569. new ClientAuthDataRunnable(caNames, pRetCert, pRetKey, info, serverCert);
  2570. nsresult rv = runnable->DispatchToMainThreadAndWait();
  2571. if (NS_FAILED(rv)) {
  2572. PR_SetError(SEC_ERROR_NO_MEMORY, 0);
  2573. return SECFailure;
  2574. }
  2575. if (runnable->mRV != SECSuccess) {
  2576. PR_SetError(runnable->mErrorCodeToReport, 0);
  2577. } else if (*runnable->mPRetCert || *runnable->mPRetKey) {
  2578. // Make joinConnection prohibit joining after we've sent a client cert
  2579. info->SetSentClientCert();
  2580. }
  2581. return runnable->mRV;
  2582. }
  2583. void ClientAuthDataRunnable::RunOnTargetThread()
  2584. {
  2585. PRArenaPool* arena = NULL;
  2586. char** caNameStrings;
  2587. CERTCertificate* cert = NULL;
  2588. SECKEYPrivateKey* privKey = NULL;
  2589. CERTCertList* certList = NULL;
  2590. CERTCertListNode* node;
  2591. CERTCertNicknames* nicknames = NULL;
  2592. char* extracted = NULL;
  2593. PRIntn keyError = 0; /* used for private key retrieval error */
  2594. SSM_UserCertChoice certChoice;
  2595. PRInt32 NumberOfCerts = 0;
  2596. void * wincx = mSocketInfo;
  2597. /* create caNameStrings */
  2598. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2599. if (arena == NULL) {
  2600. goto loser;
  2601. }
  2602. caNameStrings = (char**)PORT_ArenaAlloc(arena,
  2603. sizeof(char*)*(mCANames->nnames));
  2604. if (caNameStrings == NULL) {
  2605. goto loser;
  2606. }
  2607. mRV = nsConvertCANamesToStrings(arena, caNameStrings, mCANames);
  2608. if (mRV != SECSuccess) {
  2609. goto loser;
  2610. }
  2611. /* get the preference */
  2612. if (NS_FAILED(nsGetUserCertChoice(&certChoice))) {
  2613. goto loser;
  2614. }
  2615. /* find valid user cert and key pair */
  2616. if (certChoice == AUTO) {
  2617. /* automatically find the right cert */
  2618. /* find all user certs that are valid and for SSL */
  2619. certList = CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
  2620. certUsageSSLClient, false,
  2621. true, wincx);
  2622. if (certList == NULL) {
  2623. goto noCert;
  2624. }
  2625. /* filter the list to those issued by CAs supported by the server */
  2626. mRV = CERT_FilterCertListByCANames(certList, mCANames->nnames,
  2627. caNameStrings, certUsageSSLClient);
  2628. if (mRV != SECSuccess) {
  2629. goto noCert;
  2630. }
  2631. /* make sure the list is not empty */
  2632. node = CERT_LIST_HEAD(certList);
  2633. if (CERT_LIST_END(node, certList)) {
  2634. goto noCert;
  2635. }
  2636. CERTCertificate* low_prio_nonrep_cert = NULL;
  2637. CERTCertificateCleaner low_prio_cleaner(low_prio_nonrep_cert);
  2638. /* loop through the list until we find a cert with a key */
  2639. while (!CERT_LIST_END(node, certList)) {
  2640. /* if the certificate has restriction and we do not satisfy it
  2641. * we do not use it
  2642. */
  2643. #if 0 /* XXX This must be re-enabled */
  2644. if (!CERT_MatchesScopeOfUse(node->cert, mSocketInfo->GetHostName,
  2645. info->GetHostIP, info->GetHostPort)) {
  2646. node = CERT_LIST_NEXT(node);
  2647. continue;
  2648. }
  2649. #endif
  2650. privKey = PK11_FindKeyByAnyCert(node->cert, wincx);
  2651. if (privKey != NULL) {
  2652. if (hasExplicitKeyUsageNonRepudiation(node->cert)) {
  2653. SECKEY_DestroyPrivateKey(privKey);
  2654. privKey = NULL;
  2655. // Not a prefered cert
  2656. if (!low_prio_nonrep_cert) // did not yet find a low prio cert
  2657. low_prio_nonrep_cert = CERT_DupCertificate(node->cert);
  2658. }
  2659. else {
  2660. // this is a good cert to present
  2661. cert = CERT_DupCertificate(node->cert);
  2662. break;
  2663. }
  2664. }
  2665. keyError = PR_GetError();
  2666. if (keyError == SEC_ERROR_BAD_PASSWORD) {
  2667. /* problem with password: bail */
  2668. goto loser;
  2669. }
  2670. node = CERT_LIST_NEXT(node);
  2671. }
  2672. if (!cert && low_prio_nonrep_cert) {
  2673. cert = low_prio_nonrep_cert;
  2674. low_prio_nonrep_cert = NULL; // take it away from the cleaner
  2675. privKey = PK11_FindKeyByAnyCert(cert, wincx);
  2676. }
  2677. if (cert == NULL) {
  2678. goto noCert;
  2679. }
  2680. }
  2681. else { // Not Auto => ask
  2682. /* Get the SSL Certificate */
  2683. nsXPIDLCString hostname;
  2684. mSocketInfo->GetHostName(getter_Copies(hostname));
  2685. nsresult rv;
  2686. NS_DEFINE_CID(nssComponentCID, NS_NSSCOMPONENT_CID);
  2687. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(nssComponentCID, &rv));
  2688. nsRefPtr<nsClientAuthRememberService> cars;
  2689. if (nssComponent) {
  2690. nssComponent->GetClientAuthRememberService(getter_AddRefs(cars));
  2691. }
  2692. bool hasRemembered = false;
  2693. nsCString rememberedDBKey;
  2694. if (cars) {
  2695. bool found;
  2696. nsresult rv = cars->HasRememberedDecision(hostname, mServerCert,
  2697. rememberedDBKey, &found);
  2698. if (NS_SUCCEEDED(rv) && found) {
  2699. hasRemembered = true;
  2700. }
  2701. }
  2702. bool canceled = false;
  2703. if (hasRemembered)
  2704. {
  2705. if (rememberedDBKey.IsEmpty())
  2706. {
  2707. canceled = true;
  2708. }
  2709. else
  2710. {
  2711. nsCOMPtr<nsIX509CertDB> certdb;
  2712. certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
  2713. if (certdb)
  2714. {
  2715. nsCOMPtr<nsIX509Cert> found_cert;
  2716. nsresult find_rv =
  2717. certdb->FindCertByDBKey(rememberedDBKey.get(), nsnull,
  2718. getter_AddRefs(found_cert));
  2719. if (NS_SUCCEEDED(find_rv) && found_cert) {
  2720. nsNSSCertificate *obj_cert = reinterpret_cast<nsNSSCertificate *>(found_cert.get());
  2721. if (obj_cert) {
  2722. cert = obj_cert->GetCert();
  2723. #ifdef DEBUG_kaie
  2724. nsAutoString nick, nickWithSerial, details;
  2725. if (NS_SUCCEEDED(obj_cert->FormatUIStrings(nick,
  2726. nickWithSerial,
  2727. details))) {
  2728. NS_LossyConvertUTF16toASCII asc(nickWithSerial);
  2729. fprintf(stderr, "====> remembered serial %s\n", asc.get());
  2730. }
  2731. #endif
  2732. }
  2733. }
  2734. if (!cert) {
  2735. hasRemembered = false;
  2736. }
  2737. }
  2738. }
  2739. }
  2740. if (!hasRemembered)
  2741. {
  2742. /* user selects a cert to present */
  2743. nsIClientAuthDialogs *dialogs = NULL;
  2744. PRInt32 selectedIndex = -1;
  2745. PRUnichar **certNicknameList = NULL;
  2746. PRUnichar **certDetailsList = NULL;
  2747. /* find all user certs that are for SSL */
  2748. /* note that we are allowing expired certs in this list */
  2749. certList = CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
  2750. certUsageSSLClient, false,
  2751. false, wincx);
  2752. if (certList == NULL) {
  2753. goto noCert;
  2754. }
  2755. if (mCANames->nnames != 0) {
  2756. /* filter the list to those issued by CAs supported by the
  2757. * server
  2758. */
  2759. mRV = CERT_FilterCertListByCANames(certList, mCANames->nnames,
  2760. caNameStrings,
  2761. certUsageSSLClient);
  2762. if (mRV != SECSuccess) {
  2763. goto loser;
  2764. }
  2765. }
  2766. if (CERT_LIST_END(CERT_LIST_HEAD(certList), certList)) {
  2767. /* list is empty - no matching certs */
  2768. goto noCert;
  2769. }
  2770. /* filter it further for hostname restriction */
  2771. node = CERT_LIST_HEAD(certList);
  2772. while (!CERT_LIST_END(node, certList)) {
  2773. ++NumberOfCerts;
  2774. #if 0 /* XXX Fix this */
  2775. if (!CERT_MatchesScopeOfUse(node->cert, conn->hostName,
  2776. conn->hostIP, conn->port)) {
  2777. CERTCertListNode* removed = node;
  2778. node = CERT_LIST_NEXT(removed);
  2779. CERT_RemoveCertListNode(removed);
  2780. }
  2781. else {
  2782. node = CERT_LIST_NEXT(node);
  2783. }
  2784. #endif
  2785. node = CERT_LIST_NEXT(node);
  2786. }
  2787. if (CERT_LIST_END(CERT_LIST_HEAD(certList), certList)) {
  2788. goto noCert;
  2789. }
  2790. nicknames = getNSSCertNicknamesFromCertList(certList);
  2791. if (nicknames == NULL) {
  2792. goto loser;
  2793. }
  2794. NS_ASSERTION(nicknames->numnicknames == NumberOfCerts, "nicknames->numnicknames != NumberOfCerts");
  2795. /* Get CN and O of the subject and O of the issuer */
  2796. char *ccn = CERT_GetCommonName(&mServerCert->subject);
  2797. void *v = ccn;
  2798. voidCleaner ccnCleaner(v);
  2799. NS_ConvertUTF8toUTF16 cn(ccn);
  2800. PRInt32 port;
  2801. mSocketInfo->GetPort(&port);
  2802. nsString cn_host_port;
  2803. if (ccn && strcmp(ccn, hostname) == 0) {
  2804. cn_host_port.Append(cn);
  2805. cn_host_port.AppendLiteral(":");
  2806. cn_host_port.AppendInt(port);
  2807. }
  2808. else {
  2809. cn_host_port.Append(cn);
  2810. cn_host_port.AppendLiteral(" (");
  2811. cn_host_port.AppendLiteral(":");
  2812. cn_host_port.AppendInt(port);
  2813. cn_host_port.AppendLiteral(")");
  2814. }
  2815. char *corg = CERT_GetOrgName(&mServerCert->subject);
  2816. NS_ConvertUTF8toUTF16 org(corg);
  2817. if (corg) PORT_Free(corg);
  2818. char *cissuer = CERT_GetOrgName(&mServerCert->issuer);
  2819. NS_ConvertUTF8toUTF16 issuer(cissuer);
  2820. if (cissuer) PORT_Free(cissuer);
  2821. certNicknameList = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * nicknames->numnicknames);
  2822. if (!certNicknameList)
  2823. goto loser;
  2824. certDetailsList = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * nicknames->numnicknames);
  2825. if (!certDetailsList) {
  2826. nsMemory::Free(certNicknameList);
  2827. goto loser;
  2828. }
  2829. PRInt32 CertsToUse;
  2830. for (CertsToUse = 0, node = CERT_LIST_HEAD(certList);
  2831. !CERT_LIST_END(node, certList) && CertsToUse < nicknames->numnicknames;
  2832. node = CERT_LIST_NEXT(node)
  2833. )
  2834. {
  2835. nsRefPtr<nsNSSCertificate> tempCert = nsNSSCertificate::Create(node->cert);
  2836. if (!tempCert)
  2837. continue;
  2838. NS_ConvertUTF8toUTF16 i_nickname(nicknames->nicknames[CertsToUse]);
  2839. nsAutoString nickWithSerial, details;
  2840. if (NS_FAILED(tempCert->FormatUIStrings(i_nickname, nickWithSerial, details)))
  2841. continue;
  2842. certNicknameList[CertsToUse] = ToNewUnicode(nickWithSerial);
  2843. if (!certNicknameList[CertsToUse])
  2844. continue;
  2845. certDetailsList[CertsToUse] = ToNewUnicode(details);
  2846. if (!certDetailsList[CertsToUse]) {
  2847. nsMemory::Free(certNicknameList[CertsToUse]);
  2848. continue;
  2849. }
  2850. ++CertsToUse;
  2851. }
  2852. /* Throw up the client auth dialog and get back the index of the selected cert */
  2853. rv = getNSSDialogs((void**)&dialogs,
  2854. NS_GET_IID(nsIClientAuthDialogs),
  2855. NS_CLIENTAUTHDIALOGS_CONTRACTID);
  2856. if (NS_FAILED(rv)) {
  2857. NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certNicknameList);
  2858. NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certDetailsList);
  2859. goto loser;
  2860. }
  2861. {
  2862. nsPSMUITracker tracker;
  2863. if (tracker.isUIForbidden()) {
  2864. rv = NS_ERROR_NOT_AVAILABLE;
  2865. }
  2866. else {
  2867. rv = dialogs->ChooseCertificate(mSocketInfo, cn_host_port.get(),
  2868. org.get(), issuer.get(),
  2869. (const PRUnichar**)certNicknameList,
  2870. (const PRUnichar**)certDetailsList,
  2871. CertsToUse, &selectedIndex, &canceled);
  2872. }
  2873. }
  2874. NS_RELEASE(dialogs);
  2875. NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certNicknameList);
  2876. NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(CertsToUse, certDetailsList);
  2877. if (NS_FAILED(rv)) goto loser;
  2878. // even if the user has canceled, we want to remember that, to avoid repeating prompts
  2879. bool wantRemember = false;
  2880. mSocketInfo->GetRememberClientAuthCertificate(&wantRemember);
  2881. int i;
  2882. if (!canceled)
  2883. for (i = 0, node = CERT_LIST_HEAD(certList);
  2884. !CERT_LIST_END(node, certList);
  2885. ++i, node = CERT_LIST_NEXT(node)) {
  2886. if (i == selectedIndex) {
  2887. cert = CERT_DupCertificate(node->cert);
  2888. break;
  2889. }
  2890. }
  2891. if (cars && wantRemember) {
  2892. cars->RememberDecision(hostname, mServerCert, canceled ? 0 : cert);
  2893. }
  2894. }
  2895. if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; }
  2896. if (cert == NULL) {
  2897. goto loser;
  2898. }
  2899. /* go get the private key */
  2900. privKey = PK11_FindKeyByAnyCert(cert, wincx);
  2901. if (privKey == NULL) {
  2902. keyError = PR_GetError();
  2903. if (keyError == SEC_ERROR_BAD_PASSWORD) {
  2904. /* problem with password: bail */
  2905. goto loser;
  2906. }
  2907. else {
  2908. goto noCert;
  2909. }
  2910. }
  2911. }
  2912. goto done;
  2913. noCert:
  2914. loser:
  2915. if (mRV == SECSuccess) {
  2916. mRV = SECFailure;
  2917. }
  2918. if (cert != NULL) {
  2919. CERT_DestroyCertificate(cert);
  2920. cert = NULL;
  2921. }
  2922. done:
  2923. int error = PR_GetError();
  2924. if (extracted != NULL) {
  2925. PR_Free(extracted);
  2926. }
  2927. if (nicknames != NULL) {
  2928. CERT_FreeNicknames(nicknames);
  2929. }
  2930. if (certList != NULL) {
  2931. CERT_DestroyCertList(certList);
  2932. }
  2933. if (arena != NULL) {
  2934. PORT_FreeArena(arena, false);
  2935. }
  2936. *mPRetCert = cert;
  2937. *mPRetKey = privKey;
  2938. if (mRV == SECFailure) {
  2939. mErrorCodeToReport = error;
  2940. }
  2941. }
  2942. void
  2943. nsNSSSocketInfo::SetStatusErrorBits(nsIX509Cert & cert,
  2944. PRUint32 collected_errors)
  2945. {
  2946. MutexAutoLock lock(mMutex);
  2947. if (!mSSLStatus)
  2948. mSSLStatus = new nsSSLStatus();
  2949. mSSLStatus->mServerCert = &cert;
  2950. mSSLStatus->mHaveCertErrorBits = true;
  2951. mSSLStatus->mIsDomainMismatch =
  2952. collected_errors & nsICertOverrideService::ERROR_MISMATCH;
  2953. mSSLStatus->mIsNotValidAtThisTime =
  2954. collected_errors & nsICertOverrideService::ERROR_TIME;
  2955. mSSLStatus->mIsUntrusted =
  2956. collected_errors & nsICertOverrideService::ERROR_UNTRUSTED;
  2957. nsSSLIOLayerHelpers::mHostsWithCertErrors->RememberCertHasError(
  2958. this, mSSLStatus, SECFailure);
  2959. }
  2960. static PRFileDesc*
  2961. nsSSLIOLayerImportFD(PRFileDesc *fd,
  2962. nsNSSSocketInfo *infoObject,
  2963. const char *host,
  2964. bool anonymousLoad)
  2965. {
  2966. nsNSSShutDownPreventionLock locker;
  2967. PRFileDesc* sslSock = SSL_ImportFD(nsnull, fd);
  2968. if (!sslSock) {
  2969. NS_ASSERTION(false, "NSS: Error importing socket");
  2970. return nsnull;
  2971. }
  2972. SSL_SetPKCS11PinArg(sslSock, (nsIInterfaceRequestor*)infoObject);
  2973. SSL_HandshakeCallback(sslSock, HandshakeCallback, infoObject);
  2974. // Disable this hook if we connect anonymously. See bug 466080.
  2975. if (anonymousLoad) {
  2976. SSL_GetClientAuthDataHook(sslSock, NULL, infoObject);
  2977. } else {
  2978. SSL_GetClientAuthDataHook(sslSock,
  2979. (SSLGetClientAuthData)nsNSS_SSLGetClientAuthData,
  2980. infoObject);
  2981. }
  2982. if (SECSuccess != SSL_AuthCertificateHook(sslSock, AuthCertificateHook,
  2983. infoObject)) {
  2984. NS_NOTREACHED("failed to configure AuthCertificateHook");
  2985. goto loser;
  2986. }
  2987. if (SECSuccess != SSL_SetURL(sslSock, host)) {
  2988. NS_NOTREACHED("SSL_SetURL failed");
  2989. goto loser;
  2990. }
  2991. return sslSock;
  2992. loser:
  2993. if (sslSock) {
  2994. PR_Close(sslSock);
  2995. }
  2996. return nsnull;
  2997. }
  2998. static nsresult
  2999. nsSSLIOLayerSetOptions(PRFileDesc *fd, bool forSTARTTLS,
  3000. const char *proxyHost, const char *host, PRInt32 port,
  3001. bool anonymousLoad, nsNSSSocketInfo *infoObject)
  3002. {
  3003. nsNSSShutDownPreventionLock locker;
  3004. if (forSTARTTLS || proxyHost) {
  3005. if (SECSuccess != SSL_OptionSet(fd, SSL_SECURITY, false)) {
  3006. return NS_ERROR_FAILURE;
  3007. }
  3008. infoObject->SetHasCleartextPhase(true);
  3009. }
  3010. // Let's see if we're trying to connect to a site we know is
  3011. // TLS intolerant.
  3012. nsCAutoString key;
  3013. key = nsDependentCString(host) + NS_LITERAL_CSTRING(":") + nsPrintfCString("%d", port);
  3014. if (nsSSLIOLayerHelpers::isKnownAsIntolerantSite(key)) {
  3015. if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_TLS, false))
  3016. return NS_ERROR_FAILURE;
  3017. infoObject->SetAllowTLSIntoleranceTimeout(false);
  3018. // We assume that protocols that use the STARTTLS mechanism should support
  3019. // modern hellos. For other protocols, if we suspect a site
  3020. // does not support TLS, let's also use V2 hellos.
  3021. // One advantage of this approach, if a site only supports the older
  3022. // hellos, it is more likely that we will get a reasonable error code
  3023. // on our single retry attempt.
  3024. }
  3025. PRBool enabled;
  3026. if (SECSuccess != SSL_OptionGet(fd, SSL_ENABLE_SSL3, &enabled)) {
  3027. return NS_ERROR_FAILURE;
  3028. }
  3029. infoObject->SetSSL3Enabled(enabled);
  3030. if (SECSuccess != SSL_OptionGet(fd, SSL_ENABLE_TLS, &enabled)) {
  3031. return NS_ERROR_FAILURE;
  3032. }
  3033. infoObject->SetTLSEnabled(enabled);
  3034. if (SECSuccess != SSL_OptionSet(fd, SSL_HANDSHAKE_AS_CLIENT, true)) {
  3035. return NS_ERROR_FAILURE;
  3036. }
  3037. if (nsSSLIOLayerHelpers::isRenegoUnrestrictedSite(nsDependentCString(host))) {
  3038. if (SECSuccess != SSL_OptionSet(fd, SSL_REQUIRE_SAFE_NEGOTIATION, false)) {
  3039. return NS_ERROR_FAILURE;
  3040. }
  3041. if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_UNRESTRICTED)) {
  3042. return NS_ERROR_FAILURE;
  3043. }
  3044. }
  3045. // Set the Peer ID so that SSL proxy connections work properly.
  3046. char *peerId;
  3047. if (anonymousLoad) { // See bug #466080. Separate the caches.
  3048. peerId = PR_smprintf("anon:%s:%d", host, port);
  3049. } else {
  3050. peerId = PR_smprintf("%s:%d", host, port);
  3051. }
  3052. if (SECSuccess != SSL_SetSockPeerID(fd, peerId)) {
  3053. PR_smprintf_free(peerId);
  3054. return NS_ERROR_FAILURE;
  3055. }
  3056. PR_smprintf_free(peerId);
  3057. return NS_OK;
  3058. }
  3059. nsresult
  3060. nsSSLIOLayerAddToSocket(PRInt32 family,
  3061. const char* host,
  3062. PRInt32 port,
  3063. const char* proxyHost,
  3064. PRInt32 proxyPort,
  3065. PRFileDesc* fd,
  3066. nsISupports** info,
  3067. bool forSTARTTLS,
  3068. bool anonymousLoad)
  3069. {
  3070. nsNSSShutDownPreventionLock locker;
  3071. PRFileDesc* layer = nsnull;
  3072. nsresult rv;
  3073. nsNSSSocketInfo* infoObject = new nsNSSSocketInfo();
  3074. if (!infoObject) return NS_ERROR_FAILURE;
  3075. NS_ADDREF(infoObject);
  3076. infoObject->SetForSTARTTLS(forSTARTTLS);
  3077. infoObject->SetHostName(host);
  3078. infoObject->SetPort(port);
  3079. PRFileDesc *sslSock = nsSSLIOLayerImportFD(fd, infoObject, host, anonymousLoad);
  3080. if (!sslSock) {
  3081. NS_ASSERTION(false, "NSS: Error importing socket");
  3082. goto loser;
  3083. }
  3084. infoObject->SetFileDescPtr(sslSock);
  3085. rv = nsSSLIOLayerSetOptions(sslSock,
  3086. forSTARTTLS, proxyHost, host, port, anonymousLoad,
  3087. infoObject);
  3088. if (NS_FAILED(rv))
  3089. goto loser;
  3090. /* Now, layer ourselves on top of the SSL socket... */
  3091. layer = PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLIOLayerIdentity,
  3092. &nsSSLIOLayerHelpers::nsSSLIOLayerMethods);
  3093. if (!layer)
  3094. goto loser;
  3095. layer->secret = (PRFilePrivate*) infoObject;
  3096. rv = PR_PushIOLayer(sslSock, PR_GetLayersIdentity(sslSock), layer);
  3097. if (NS_FAILED(rv)) {
  3098. goto loser;
  3099. }
  3100. nsNSSShutDownList::trackSSLSocketCreate();
  3101. PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] Socket set up\n", (void*)sslSock));
  3102. infoObject->QueryInterface(NS_GET_IID(nsISupports), (void**) (info));
  3103. // We are going use a clear connection first //
  3104. if (forSTARTTLS || proxyHost) {
  3105. infoObject->SetHandshakePending(false);
  3106. }
  3107. return NS_OK;
  3108. loser:
  3109. NS_IF_RELEASE(infoObject);
  3110. if (layer) {
  3111. layer->dtor(layer);
  3112. }
  3113. return NS_ERROR_FAILURE;
  3114. }