TransportSecurityInfo.cpp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2. *
  3. * This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. #include "TransportSecurityInfo.h"
  7. #include "PSMRunnable.h"
  8. #include "mozilla/Casting.h"
  9. #include "mozilla/net/DNS.h"
  10. #include "nsComponentManagerUtils.h"
  11. #include "nsIArray.h"
  12. #include "nsICertOverrideService.h"
  13. #include "nsIDateTimeFormat.h"
  14. #include "nsIObjectInputStream.h"
  15. #include "nsIObjectOutputStream.h"
  16. #include "nsIWebProgressListener.h"
  17. #include "nsIX509CertValidity.h"
  18. #include "nsNSSCertHelper.h"
  19. #include "nsNSSCertificate.h"
  20. #include "nsNSSComponent.h"
  21. #include "nsReadableUtils.h"
  22. #include "nsServiceManagerUtils.h"
  23. #include "nsXULAppAPI.h"
  24. #include "pkix/pkixtypes.h"
  25. #include "secerr.h"
  26. //#define DEBUG_SSL_VERBOSE //Enable this define to get minimal
  27. //reports when doing SSL read/write
  28. //#define DUMP_BUFFER //Enable this define along with
  29. //DEBUG_SSL_VERBOSE to dump SSL
  30. //read/write buffer to a log.
  31. //Uses PR_LOG except on Mac where
  32. //we always write out to our own
  33. //file.
  34. namespace mozilla { namespace psm {
  35. TransportSecurityInfo::TransportSecurityInfo()
  36. : mMutex("TransportSecurityInfo::mMutex"),
  37. mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE),
  38. mSubRequestsBrokenSecurity(0),
  39. mSubRequestsNoSecurity(0),
  40. mErrorCode(0),
  41. mErrorMessageType(PlainErrorMessage),
  42. mPort(0)
  43. {
  44. }
  45. TransportSecurityInfo::~TransportSecurityInfo()
  46. {
  47. nsNSSShutDownPreventionLock locker;
  48. if (isAlreadyShutDown())
  49. return;
  50. shutdown(ShutdownCalledFrom::Object);
  51. }
  52. void
  53. TransportSecurityInfo::virtualDestroyNSSReference()
  54. {
  55. }
  56. NS_IMPL_ISUPPORTS(TransportSecurityInfo,
  57. nsITransportSecurityInfo,
  58. nsIInterfaceRequestor,
  59. nsISSLStatusProvider,
  60. nsIAssociatedContentSecurity,
  61. nsISerializable,
  62. nsIClassInfo)
  63. nsresult
  64. TransportSecurityInfo::SetHostName(const char* host)
  65. {
  66. MutexAutoLock lock(mMutex);
  67. mHostName.Adopt(host ? NS_strdup(host) : 0);
  68. return NS_OK;
  69. }
  70. nsresult
  71. TransportSecurityInfo::GetHostName(char **host)
  72. {
  73. *host = (mHostName) ? NS_strdup(mHostName) : nullptr;
  74. return NS_OK;
  75. }
  76. nsresult
  77. TransportSecurityInfo::SetPort(int32_t aPort)
  78. {
  79. mPort = aPort;
  80. return NS_OK;
  81. }
  82. nsresult
  83. TransportSecurityInfo::GetPort(int32_t *aPort)
  84. {
  85. *aPort = mPort;
  86. return NS_OK;
  87. }
  88. nsresult
  89. TransportSecurityInfo::SetOriginAttributes(
  90. const NeckoOriginAttributes& aOriginAttributes)
  91. {
  92. MutexAutoLock lock(mMutex);
  93. mOriginAttributes = aOriginAttributes;
  94. return NS_OK;
  95. }
  96. PRErrorCode
  97. TransportSecurityInfo::GetErrorCode() const
  98. {
  99. MutexAutoLock lock(mMutex);
  100. return mErrorCode;
  101. }
  102. void
  103. TransportSecurityInfo::SetCanceled(PRErrorCode errorCode,
  104. SSLErrorMessageType errorMessageType)
  105. {
  106. MutexAutoLock lock(mMutex);
  107. mErrorCode = errorCode;
  108. mErrorMessageType = errorMessageType;
  109. mErrorMessageCached.Truncate();
  110. }
  111. NS_IMETHODIMP
  112. TransportSecurityInfo::GetSecurityState(uint32_t* state)
  113. {
  114. *state = mSecurityState;
  115. return NS_OK;
  116. }
  117. nsresult
  118. TransportSecurityInfo::SetSecurityState(uint32_t aState)
  119. {
  120. MutexAutoLock lock(mMutex);
  121. mSecurityState = aState;
  122. return NS_OK;
  123. }
  124. NS_IMETHODIMP
  125. TransportSecurityInfo::GetCountSubRequestsBrokenSecurity(
  126. int32_t *aSubRequestsBrokenSecurity)
  127. {
  128. *aSubRequestsBrokenSecurity = mSubRequestsBrokenSecurity;
  129. return NS_OK;
  130. }
  131. NS_IMETHODIMP
  132. TransportSecurityInfo::SetCountSubRequestsBrokenSecurity(
  133. int32_t aSubRequestsBrokenSecurity)
  134. {
  135. MutexAutoLock lock(mMutex);
  136. mSubRequestsBrokenSecurity = aSubRequestsBrokenSecurity;
  137. return NS_OK;
  138. }
  139. NS_IMETHODIMP
  140. TransportSecurityInfo::GetCountSubRequestsNoSecurity(
  141. int32_t *aSubRequestsNoSecurity)
  142. {
  143. *aSubRequestsNoSecurity = mSubRequestsNoSecurity;
  144. return NS_OK;
  145. }
  146. NS_IMETHODIMP
  147. TransportSecurityInfo::SetCountSubRequestsNoSecurity(
  148. int32_t aSubRequestsNoSecurity)
  149. {
  150. MutexAutoLock lock(mMutex);
  151. mSubRequestsNoSecurity = aSubRequestsNoSecurity;
  152. return NS_OK;
  153. }
  154. NS_IMETHODIMP
  155. TransportSecurityInfo::Flush()
  156. {
  157. return NS_OK;
  158. }
  159. NS_IMETHODIMP
  160. TransportSecurityInfo::GetErrorMessage(char16_t** aText)
  161. {
  162. NS_ENSURE_ARG_POINTER(aText);
  163. *aText = nullptr;
  164. if (!NS_IsMainThread()) {
  165. NS_ERROR("nsNSSSocketInfo::GetErrorMessage called off the main thread");
  166. return NS_ERROR_NOT_SAME_THREAD;
  167. }
  168. MutexAutoLock lock(mMutex);
  169. if (mErrorMessageCached.IsEmpty()) {
  170. nsresult rv = formatErrorMessage(lock,
  171. mErrorCode, mErrorMessageType,
  172. true, true, mErrorMessageCached);
  173. NS_ENSURE_SUCCESS(rv, rv);
  174. }
  175. *aText = ToNewUnicode(mErrorMessageCached);
  176. return *aText ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  177. }
  178. void
  179. TransportSecurityInfo::GetErrorLogMessage(PRErrorCode errorCode,
  180. SSLErrorMessageType errorMessageType,
  181. nsString &result)
  182. {
  183. if (!NS_IsMainThread()) {
  184. NS_ERROR("nsNSSSocketInfo::GetErrorLogMessage called off the main thread");
  185. return;
  186. }
  187. MutexAutoLock lock(mMutex);
  188. (void) formatErrorMessage(lock, errorCode, errorMessageType,
  189. false, false, result);
  190. }
  191. static nsresult
  192. formatPlainErrorMessage(nsXPIDLCString const & host, int32_t port,
  193. PRErrorCode err,
  194. bool suppressPort443,
  195. nsString &returnedMessage);
  196. static nsresult
  197. formatOverridableCertErrorMessage(nsISSLStatus & sslStatus,
  198. PRErrorCode errorCodeToReport,
  199. const nsXPIDLCString & host, int32_t port,
  200. bool suppressPort443,
  201. bool wantsHtml,
  202. nsString & returnedMessage);
  203. // XXX: uses nsNSSComponent string bundles off the main thread when called by
  204. // nsNSSSocketInfo::Write().
  205. nsresult
  206. TransportSecurityInfo::formatErrorMessage(MutexAutoLock const & proofOfLock,
  207. PRErrorCode errorCode,
  208. SSLErrorMessageType errorMessageType,
  209. bool wantsHtml, bool suppressPort443,
  210. nsString &result)
  211. {
  212. result.Truncate();
  213. if (errorCode == 0) {
  214. return NS_OK;
  215. }
  216. if (!XRE_IsParentProcess()) {
  217. return NS_ERROR_UNEXPECTED;
  218. }
  219. nsresult rv;
  220. NS_ConvertASCIItoUTF16 hostNameU(mHostName);
  221. NS_ASSERTION(errorMessageType != OverridableCertErrorMessage ||
  222. (mSSLStatus && mSSLStatus->HasServerCert() &&
  223. mSSLStatus->mHaveCertErrorBits),
  224. "GetErrorLogMessage called for cert error without cert");
  225. if (errorMessageType == OverridableCertErrorMessage &&
  226. mSSLStatus && mSSLStatus->HasServerCert()) {
  227. rv = formatOverridableCertErrorMessage(*mSSLStatus, errorCode,
  228. mHostName, mPort,
  229. suppressPort443,
  230. wantsHtml,
  231. result);
  232. } else {
  233. rv = formatPlainErrorMessage(mHostName, mPort,
  234. errorCode,
  235. suppressPort443,
  236. result);
  237. }
  238. if (NS_FAILED(rv)) {
  239. result.Truncate();
  240. }
  241. return rv;
  242. }
  243. NS_IMETHODIMP
  244. TransportSecurityInfo::GetErrorCode(int32_t* state)
  245. {
  246. *state = GetErrorCode();
  247. return NS_OK;
  248. }
  249. NS_IMETHODIMP
  250. TransportSecurityInfo::GetInterface(const nsIID & uuid, void * *result)
  251. {
  252. if (!NS_IsMainThread()) {
  253. NS_ERROR("nsNSSSocketInfo::GetInterface called off the main thread");
  254. return NS_ERROR_NOT_SAME_THREAD;
  255. }
  256. nsresult rv;
  257. if (!mCallbacks) {
  258. nsCOMPtr<nsIInterfaceRequestor> ir = new PipUIContext();
  259. rv = ir->GetInterface(uuid, result);
  260. } else {
  261. rv = mCallbacks->GetInterface(uuid, result);
  262. }
  263. return rv;
  264. }
  265. // This is a new magic value. However, it re-uses the first 4 bytes
  266. // of the previous value. This is so when older versions attempt to
  267. // read a newer serialized TransportSecurityInfo, they will actually
  268. // fail and return NS_ERROR_FAILURE instead of silently failing.
  269. #define TRANSPORTSECURITYINFOMAGIC { 0xa9863a23, 0xa940, 0x4002, \
  270. { 0x94, 0x3c, 0x43, 0xc4, 0x67, 0x38, 0x8f, 0x3d } }
  271. static NS_DEFINE_CID(kTransportSecurityInfoMagic, TRANSPORTSECURITYINFOMAGIC);
  272. NS_IMETHODIMP
  273. TransportSecurityInfo::Write(nsIObjectOutputStream* stream)
  274. {
  275. nsresult rv = stream->WriteID(kTransportSecurityInfoMagic);
  276. if (NS_FAILED(rv)) {
  277. return rv;
  278. }
  279. MutexAutoLock lock(mMutex);
  280. rv = stream->Write32(mSecurityState);
  281. if (NS_FAILED(rv)) {
  282. return rv;
  283. }
  284. rv = stream->Write32(mSubRequestsBrokenSecurity);
  285. if (NS_FAILED(rv)) {
  286. return rv;
  287. }
  288. rv = stream->Write32(mSubRequestsNoSecurity);
  289. if (NS_FAILED(rv)) {
  290. return rv;
  291. }
  292. rv = stream->Write32(static_cast<uint32_t>(mErrorCode));
  293. if (NS_FAILED(rv)) {
  294. return rv;
  295. }
  296. if (mErrorMessageCached.IsEmpty()) {
  297. // XXX: uses nsNSSComponent string bundles off the main thread
  298. rv = formatErrorMessage(lock, mErrorCode, mErrorMessageType,
  299. true, true, mErrorMessageCached);
  300. if (NS_FAILED(rv)) {
  301. return rv;
  302. }
  303. }
  304. rv = stream->WriteWStringZ(mErrorMessageCached.get());
  305. if (NS_FAILED(rv)) {
  306. return rv;
  307. }
  308. // For successful connections and for connections with overridable errors,
  309. // mSSLStatus will be non-null. However, for connections with non-overridable
  310. // errors, it will be null.
  311. nsCOMPtr<nsISerializable> serializable(mSSLStatus);
  312. rv = NS_WriteOptionalCompoundObject(stream,
  313. serializable,
  314. NS_GET_IID(nsISSLStatus),
  315. true);
  316. if (NS_FAILED(rv)) {
  317. return rv;
  318. }
  319. rv = NS_WriteOptionalCompoundObject(stream,
  320. mFailedCertChain,
  321. NS_GET_IID(nsIX509CertList),
  322. true);
  323. if (NS_FAILED(rv)) {
  324. return rv;
  325. }
  326. return NS_OK;
  327. }
  328. NS_IMETHODIMP
  329. TransportSecurityInfo::Read(nsIObjectInputStream* stream)
  330. {
  331. nsID id;
  332. nsresult rv = stream->ReadID(&id);
  333. if (NS_FAILED(rv)) {
  334. return rv;
  335. }
  336. if (!id.Equals(kTransportSecurityInfoMagic)) {
  337. return NS_ERROR_UNEXPECTED;
  338. }
  339. MutexAutoLock lock(mMutex);
  340. rv = stream->Read32(&mSecurityState);
  341. if (NS_FAILED(rv)) {
  342. return rv;
  343. }
  344. uint32_t subRequestsBrokenSecurity;
  345. rv = stream->Read32(&subRequestsBrokenSecurity);
  346. if (NS_FAILED(rv)) {
  347. return rv;
  348. }
  349. if (subRequestsBrokenSecurity >
  350. static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
  351. return NS_ERROR_UNEXPECTED;
  352. }
  353. mSubRequestsBrokenSecurity = subRequestsBrokenSecurity;
  354. uint32_t subRequestsNoSecurity;
  355. rv = stream->Read32(&subRequestsNoSecurity);
  356. if (NS_FAILED(rv)) {
  357. return rv;
  358. }
  359. if (subRequestsNoSecurity >
  360. static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
  361. return NS_ERROR_UNEXPECTED;
  362. }
  363. mSubRequestsNoSecurity = subRequestsNoSecurity;
  364. uint32_t errorCode;
  365. rv = stream->Read32(&errorCode);
  366. if (NS_FAILED(rv)) {
  367. return rv;
  368. }
  369. // PRErrorCode will be a negative value
  370. mErrorCode = static_cast<PRErrorCode>(errorCode);
  371. rv = stream->ReadString(mErrorMessageCached);
  372. if (NS_FAILED(rv)) {
  373. return rv;
  374. }
  375. // For successful connections and for connections with overridable errors,
  376. // mSSLStatus will be non-null. For connections with non-overridable errors,
  377. // it will be null.
  378. nsCOMPtr<nsISupports> supports;
  379. rv = NS_ReadOptionalObject(stream, true, getter_AddRefs(supports));
  380. if (NS_FAILED(rv)) {
  381. return rv;
  382. }
  383. nsCOMPtr<nsISSLStatus> castGuard(do_QueryInterface(supports));
  384. if (castGuard) {
  385. mSSLStatus = BitwiseCast<nsSSLStatus*, nsISSLStatus*>(castGuard.get());
  386. } else {
  387. mSSLStatus = nullptr;
  388. }
  389. nsCOMPtr<nsISupports> failedCertChainSupports;
  390. rv = NS_ReadOptionalObject(stream, true, getter_AddRefs(failedCertChainSupports));
  391. if (NS_FAILED(rv)) {
  392. return rv;
  393. }
  394. mFailedCertChain = do_QueryInterface(failedCertChainSupports);
  395. return NS_OK;
  396. }
  397. NS_IMETHODIMP
  398. TransportSecurityInfo::GetInterfaces(uint32_t *count, nsIID * **array)
  399. {
  400. *count = 0;
  401. *array = nullptr;
  402. return NS_OK;
  403. }
  404. NS_IMETHODIMP
  405. TransportSecurityInfo::GetScriptableHelper(nsIXPCScriptable **_retval)
  406. {
  407. *_retval = nullptr;
  408. return NS_OK;
  409. }
  410. NS_IMETHODIMP
  411. TransportSecurityInfo::GetContractID(char * *aContractID)
  412. {
  413. *aContractID = nullptr;
  414. return NS_OK;
  415. }
  416. NS_IMETHODIMP
  417. TransportSecurityInfo::GetClassDescription(char * *aClassDescription)
  418. {
  419. *aClassDescription = nullptr;
  420. return NS_OK;
  421. }
  422. NS_IMETHODIMP
  423. TransportSecurityInfo::GetClassID(nsCID * *aClassID)
  424. {
  425. *aClassID = (nsCID*) moz_xmalloc(sizeof(nsCID));
  426. if (!*aClassID)
  427. return NS_ERROR_OUT_OF_MEMORY;
  428. return GetClassIDNoAlloc(*aClassID);
  429. }
  430. NS_IMETHODIMP
  431. TransportSecurityInfo::GetFlags(uint32_t *aFlags)
  432. {
  433. *aFlags = 0;
  434. return NS_OK;
  435. }
  436. static NS_DEFINE_CID(kNSSSocketInfoCID, TRANSPORTSECURITYINFO_CID);
  437. NS_IMETHODIMP
  438. TransportSecurityInfo::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  439. {
  440. *aClassIDNoAlloc = kNSSSocketInfoCID;
  441. return NS_OK;
  442. }
  443. nsresult
  444. TransportSecurityInfo::GetSSLStatus(nsISSLStatus** _result)
  445. {
  446. NS_ENSURE_ARG_POINTER(_result);
  447. *_result = mSSLStatus;
  448. NS_IF_ADDREF(*_result);
  449. return NS_OK;
  450. }
  451. nsresult
  452. TransportSecurityInfo::SetSSLStatus(nsSSLStatus *aSSLStatus)
  453. {
  454. MutexAutoLock lock(mMutex);
  455. mSSLStatus = aSSLStatus;
  456. return NS_OK;
  457. }
  458. /* Formats an error message for non-certificate-related SSL errors
  459. * and non-overridable certificate errors (both are of type
  460. * PlainErrormMessage). Use formatOverridableCertErrorMessage
  461. * for overridable cert errors.
  462. */
  463. static nsresult
  464. formatPlainErrorMessage(const nsXPIDLCString &host, int32_t port,
  465. PRErrorCode err,
  466. bool suppressPort443,
  467. nsString &returnedMessage)
  468. {
  469. static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  470. const char16_t *params[1];
  471. nsresult rv;
  472. nsCOMPtr<nsINSSComponent> component = do_GetService(kNSSComponentCID, &rv);
  473. NS_ENSURE_SUCCESS(rv, rv);
  474. if (host.Length())
  475. {
  476. nsString hostWithPort;
  477. // For now, hide port when it's 443 and we're reporting the error.
  478. // In the future a better mechanism should be used
  479. // to make a decision about showing the port number, possibly by requiring
  480. // the context object to implement a specific interface.
  481. // The motivation is that Mozilla browser would like to hide the port number
  482. // in error pages in the common case.
  483. hostWithPort.AssignASCII(host);
  484. if (!suppressPort443 || port != 443) {
  485. hostWithPort.Append(':');
  486. hostWithPort.AppendInt(port);
  487. }
  488. params[0] = hostWithPort.get();
  489. nsString formattedString;
  490. rv = component->PIPBundleFormatStringFromName("SSLConnectionErrorPrefix",
  491. params, 1,
  492. formattedString);
  493. if (NS_SUCCEEDED(rv))
  494. {
  495. returnedMessage.Append(formattedString);
  496. returnedMessage.AppendLiteral("\n\n");
  497. }
  498. }
  499. nsString explanation;
  500. rv = nsNSSErrors::getErrorMessageFromCode(err, component, explanation);
  501. if (NS_SUCCEEDED(rv))
  502. returnedMessage.Append(explanation);
  503. return NS_OK;
  504. }
  505. static void
  506. AppendErrorTextUntrusted(PRErrorCode errTrust,
  507. const nsString &host,
  508. nsIX509Cert* ix509,
  509. nsINSSComponent *component,
  510. nsString &returnedMessage)
  511. {
  512. const char* errorID = nullptr;
  513. const char* errorID2 = nullptr;
  514. const char* errorID3 = nullptr;
  515. bool isSelfSigned;
  516. if (NS_SUCCEEDED(ix509->GetIsSelfSigned(&isSelfSigned)) && isSelfSigned) {
  517. errorID = "certErrorTrust_SelfSigned";
  518. }
  519. if (!errorID) {
  520. switch (errTrust) {
  521. case SEC_ERROR_UNKNOWN_ISSUER:
  522. errorID = "certErrorTrust_UnknownIssuer";
  523. errorID2 = "certErrorTrust_UnknownIssuer2";
  524. errorID3 = "certErrorTrust_UnknownIssuer3";
  525. break;
  526. case SEC_ERROR_CA_CERT_INVALID:
  527. errorID = "certErrorTrust_CaInvalid";
  528. break;
  529. case SEC_ERROR_UNTRUSTED_ISSUER:
  530. errorID = "certErrorTrust_Issuer";
  531. break;
  532. case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
  533. errorID = "certErrorTrust_SignatureAlgorithmDisabled";
  534. break;
  535. case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
  536. errorID = "certErrorTrust_ExpiredIssuer";
  537. break;
  538. case SEC_ERROR_UNTRUSTED_CERT:
  539. default:
  540. errorID = "certErrorTrust_Untrusted";
  541. break;
  542. }
  543. }
  544. const char* errorIDs[] = { errorID, errorID2, errorID3 };
  545. for (size_t i = 0; i < ArrayLength(errorIDs); i++) {
  546. if (!errorIDs[i]) {
  547. break;
  548. }
  549. nsString formattedString;
  550. nsresult rv = component->GetPIPNSSBundleString(errorIDs[i], formattedString);
  551. if (NS_SUCCEEDED(rv)) {
  552. returnedMessage.Append(formattedString);
  553. returnedMessage.Append('\n');
  554. }
  555. }
  556. }
  557. // Returns the number of dNSName or iPAddress entries encountered in the
  558. // subject alternative name extension of the certificate.
  559. // Returns zero if the extension is not present, could not be decoded, or if it
  560. // does not contain any dNSName or iPAddress entries.
  561. static uint32_t
  562. GetSubjectAltNames(CERTCertificate* nssCert, nsString& allNames)
  563. {
  564. allNames.Truncate();
  565. ScopedAutoSECItem altNameExtension;
  566. SECStatus rv = CERT_FindCertExtension(nssCert, SEC_OID_X509_SUBJECT_ALT_NAME,
  567. &altNameExtension);
  568. if (rv != SECSuccess) {
  569. return 0;
  570. }
  571. UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  572. if (!arena) {
  573. return 0;
  574. }
  575. CERTGeneralName* sanNameList(CERT_DecodeAltNameExtension(arena.get(),
  576. &altNameExtension));
  577. if (!sanNameList) {
  578. return 0;
  579. }
  580. uint32_t nameCount = 0;
  581. CERTGeneralName* current = sanNameList;
  582. do {
  583. nsAutoString name;
  584. switch (current->type) {
  585. case certDNSName:
  586. {
  587. nsDependentCSubstring nameFromCert(BitwiseCast<char*, unsigned char*>(
  588. current->name.other.data),
  589. current->name.other.len);
  590. // dNSName fields are defined as type IA5String and thus should
  591. // be limited to ASCII characters.
  592. if (IsASCII(nameFromCert)) {
  593. name.Assign(NS_ConvertASCIItoUTF16(nameFromCert));
  594. if (!allNames.IsEmpty()) {
  595. allNames.AppendLiteral(", ");
  596. }
  597. ++nameCount;
  598. allNames.Append(name);
  599. }
  600. }
  601. break;
  602. case certIPAddress:
  603. {
  604. // According to DNS.h, this includes space for the null-terminator
  605. char buf[net::kNetAddrMaxCStrBufSize] = {0};
  606. PRNetAddr addr;
  607. memset(&addr, 0, sizeof(addr));
  608. if (current->name.other.len == 4) {
  609. addr.inet.family = PR_AF_INET;
  610. memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
  611. PR_NetAddrToString(&addr, buf, sizeof(buf));
  612. name.AssignASCII(buf);
  613. } else if (current->name.other.len == 16) {
  614. addr.ipv6.family = PR_AF_INET6;
  615. memcpy(&addr.ipv6.ip, current->name.other.data, current->name.other.len);
  616. PR_NetAddrToString(&addr, buf, sizeof(buf));
  617. name.AssignASCII(buf);
  618. } else {
  619. /* invalid IP address */
  620. }
  621. if (!name.IsEmpty()) {
  622. if (!allNames.IsEmpty()) {
  623. allNames.AppendLiteral(", ");
  624. }
  625. ++nameCount;
  626. allNames.Append(name);
  627. }
  628. break;
  629. }
  630. default: // all other types of names are ignored
  631. break;
  632. }
  633. current = CERT_GetNextGeneralName(current);
  634. } while (current != sanNameList); // double linked
  635. return nameCount;
  636. }
  637. static nsresult
  638. AppendErrorTextMismatch(const nsString& host, nsIX509Cert* ix509,
  639. nsINSSComponent* component, bool wantsHtml,
  640. nsString& returnedMessage)
  641. {
  642. // Prepare a default "not valid for <hostname>" string in case anything
  643. // goes wrong (or in case the certificate is not valid for any hostnames).
  644. nsAutoString notValidForHostnameString;
  645. const char16_t* params[1];
  646. params[0] = host.get();
  647. nsresult rv = component->PIPBundleFormatStringFromName(
  648. "certErrorMismatch", params, 1, notValidForHostnameString);
  649. if (NS_FAILED(rv)) {
  650. return rv;
  651. }
  652. notValidForHostnameString.Append('\n');
  653. UniqueCERTCertificate nssCert(ix509->GetCert());
  654. if (!nssCert) {
  655. returnedMessage.Append(notValidForHostnameString);
  656. return NS_OK;
  657. }
  658. nsAutoString allNames;
  659. uint32_t nameCount = GetSubjectAltNames(nssCert.get(), allNames);
  660. if (nameCount == 0) {
  661. returnedMessage.Append(notValidForHostnameString);
  662. } else if (nameCount > 1) {
  663. nsString message;
  664. rv = component->GetPIPNSSBundleString("certErrorMismatchMultiple", message);
  665. if (NS_FAILED(rv)) {
  666. return rv;
  667. }
  668. returnedMessage.Append(message);
  669. returnedMessage.AppendLiteral("\n ");
  670. returnedMessage.Append(allNames);
  671. returnedMessage.AppendLiteral(" \n");
  672. } else if (nameCount == 1) {
  673. params[0] = allNames.get();
  674. const char* stringID = wantsHtml ? "certErrorMismatchSingle2"
  675. : "certErrorMismatchSinglePlain";
  676. nsAutoString formattedString;
  677. rv = component->PIPBundleFormatStringFromName(stringID, params, 1,
  678. formattedString);
  679. if (NS_FAILED(rv)) {
  680. return rv;
  681. }
  682. returnedMessage.Append(formattedString);
  683. returnedMessage.Append('\n');
  684. }
  685. return NS_OK;
  686. }
  687. static void
  688. GetDateBoundary(nsIX509Cert* ix509,
  689. nsString &formattedDate,
  690. nsString &nowDate,
  691. bool &trueExpired_falseNotYetValid)
  692. {
  693. trueExpired_falseNotYetValid = true;
  694. formattedDate.Truncate();
  695. PRTime notAfter, notBefore, timeToUse;
  696. nsCOMPtr<nsIX509CertValidity> validity;
  697. nsresult rv;
  698. rv = ix509->GetValidity(getter_AddRefs(validity));
  699. if (NS_FAILED(rv))
  700. return;
  701. rv = validity->GetNotAfter(&notAfter);
  702. if (NS_FAILED(rv))
  703. return;
  704. rv = validity->GetNotBefore(&notBefore);
  705. if (NS_FAILED(rv))
  706. return;
  707. PRTime now = PR_Now();
  708. if (now > notAfter) {
  709. timeToUse = notAfter;
  710. } else {
  711. timeToUse = notBefore;
  712. trueExpired_falseNotYetValid = false;
  713. }
  714. nsCOMPtr<nsIDateTimeFormat> dateTimeFormat = nsIDateTimeFormat::Create();
  715. if (!dateTimeFormat) {
  716. return;
  717. }
  718. dateTimeFormat->FormatPRTime(nullptr, kDateFormatLong, kTimeFormatNoSeconds,
  719. timeToUse, formattedDate);
  720. dateTimeFormat->FormatPRTime(nullptr, kDateFormatLong, kTimeFormatNoSeconds,
  721. now, nowDate);
  722. }
  723. static void
  724. AppendErrorTextTime(nsIX509Cert* ix509,
  725. nsINSSComponent *component,
  726. nsString &returnedMessage)
  727. {
  728. nsAutoString formattedDate, nowDate;
  729. bool trueExpired_falseNotYetValid;
  730. GetDateBoundary(ix509, formattedDate, nowDate, trueExpired_falseNotYetValid);
  731. const char16_t *params[2];
  732. params[0] = formattedDate.get(); // might be empty, if helper function had a problem
  733. params[1] = nowDate.get();
  734. const char *key = trueExpired_falseNotYetValid ?
  735. "certErrorExpiredNow" : "certErrorNotYetValidNow";
  736. nsresult rv;
  737. nsString formattedString;
  738. rv = component->PIPBundleFormatStringFromName(
  739. key,
  740. params,
  741. ArrayLength(params),
  742. formattedString);
  743. if (NS_SUCCEEDED(rv))
  744. {
  745. returnedMessage.Append(formattedString);
  746. returnedMessage.Append('\n');
  747. }
  748. }
  749. static void
  750. AppendErrorTextCode(PRErrorCode errorCodeToReport,
  751. nsINSSComponent *component,
  752. nsString &returnedMessage)
  753. {
  754. const char *codeName = nsNSSErrors::getDefaultErrorStringName(errorCodeToReport);
  755. if (codeName)
  756. {
  757. nsCString error_id(codeName);
  758. NS_ConvertASCIItoUTF16 idU(error_id);
  759. const char16_t *params[1];
  760. params[0] = idU.get();
  761. nsString formattedString;
  762. nsresult rv;
  763. rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix",
  764. params, 1,
  765. formattedString);
  766. if (NS_SUCCEEDED(rv)) {
  767. returnedMessage.Append('\n');
  768. returnedMessage.Append(formattedString);
  769. returnedMessage.Append('\n');
  770. }
  771. else {
  772. returnedMessage.AppendLiteral(" (");
  773. returnedMessage.Append(idU);
  774. returnedMessage.Append(')');
  775. }
  776. }
  777. }
  778. /* Formats an error message for overridable certificate errors (of type
  779. * OverridableCertErrorMessage). Use formatPlainErrorMessage to format
  780. * non-overridable cert errors and non-cert-related errors.
  781. */
  782. static nsresult
  783. formatOverridableCertErrorMessage(nsISSLStatus & sslStatus,
  784. PRErrorCode errorCodeToReport,
  785. const nsXPIDLCString & host, int32_t port,
  786. bool suppressPort443,
  787. bool wantsHtml,
  788. nsString & returnedMessage)
  789. {
  790. static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  791. const char16_t *params[1];
  792. nsresult rv;
  793. nsAutoString hostWithPort;
  794. nsAutoString hostWithoutPort;
  795. // For now, hide port when it's 443 and we're reporting the error.
  796. // In the future a better mechanism should be used
  797. // to make a decision about showing the port number, possibly by requiring
  798. // the context object to implement a specific interface.
  799. // The motivation is that Mozilla browser would like to hide the port number
  800. // in error pages in the common case.
  801. hostWithoutPort.AppendASCII(host);
  802. if (suppressPort443 && port == 443) {
  803. params[0] = hostWithoutPort.get();
  804. } else {
  805. hostWithPort.AppendASCII(host);
  806. hostWithPort.Append(':');
  807. hostWithPort.AppendInt(port);
  808. params[0] = hostWithPort.get();
  809. }
  810. nsCOMPtr<nsINSSComponent> component = do_GetService(kNSSComponentCID, &rv);
  811. NS_ENSURE_SUCCESS(rv, rv);
  812. returnedMessage.Truncate();
  813. rv = component->PIPBundleFormatStringFromName("certErrorIntro", params, 1,
  814. returnedMessage);
  815. NS_ENSURE_SUCCESS(rv, rv);
  816. returnedMessage.AppendLiteral("\n\n");
  817. RefPtr<nsIX509Cert> ix509;
  818. rv = sslStatus.GetServerCert(getter_AddRefs(ix509));
  819. NS_ENSURE_SUCCESS(rv, rv);
  820. bool isUntrusted;
  821. rv = sslStatus.GetIsUntrusted(&isUntrusted);
  822. NS_ENSURE_SUCCESS(rv, rv);
  823. if (isUntrusted) {
  824. AppendErrorTextUntrusted(errorCodeToReport, hostWithoutPort, ix509,
  825. component, returnedMessage);
  826. }
  827. bool isDomainMismatch;
  828. rv = sslStatus.GetIsDomainMismatch(&isDomainMismatch);
  829. NS_ENSURE_SUCCESS(rv, rv);
  830. if (isDomainMismatch) {
  831. rv = AppendErrorTextMismatch(hostWithoutPort, ix509, component, wantsHtml,
  832. returnedMessage);
  833. NS_ENSURE_SUCCESS(rv, rv);
  834. }
  835. bool isNotValidAtThisTime;
  836. rv = sslStatus.GetIsNotValidAtThisTime(&isNotValidAtThisTime);
  837. NS_ENSURE_SUCCESS(rv, rv);
  838. if (isNotValidAtThisTime) {
  839. AppendErrorTextTime(ix509, component, returnedMessage);
  840. }
  841. AppendErrorTextCode(errorCodeToReport, component, returnedMessage);
  842. return NS_OK;
  843. }
  844. // RememberCertErrorsTable
  845. /*static*/ RememberCertErrorsTable*
  846. RememberCertErrorsTable::sInstance = nullptr;
  847. RememberCertErrorsTable::RememberCertErrorsTable()
  848. : mErrorHosts()
  849. , mMutex("RememberCertErrorsTable::mMutex")
  850. {
  851. }
  852. static nsresult
  853. GetHostPortKey(TransportSecurityInfo* infoObject, nsAutoCString &result)
  854. {
  855. nsresult rv;
  856. result.Truncate();
  857. nsXPIDLCString hostName;
  858. rv = infoObject->GetHostName(getter_Copies(hostName));
  859. NS_ENSURE_SUCCESS(rv, rv);
  860. int32_t port;
  861. rv = infoObject->GetPort(&port);
  862. NS_ENSURE_SUCCESS(rv, rv);
  863. result.Assign(hostName);
  864. result.Append(':');
  865. result.AppendInt(port);
  866. return NS_OK;
  867. }
  868. void
  869. RememberCertErrorsTable::RememberCertHasError(TransportSecurityInfo* infoObject,
  870. nsSSLStatus* status,
  871. SECStatus certVerificationResult)
  872. {
  873. nsresult rv;
  874. nsAutoCString hostPortKey;
  875. rv = GetHostPortKey(infoObject, hostPortKey);
  876. if (NS_FAILED(rv))
  877. return;
  878. if (certVerificationResult != SECSuccess) {
  879. NS_ASSERTION(status,
  880. "Must have nsSSLStatus object when remembering flags");
  881. if (!status)
  882. return;
  883. CertStateBits bits;
  884. bits.mIsDomainMismatch = status->mIsDomainMismatch;
  885. bits.mIsNotValidAtThisTime = status->mIsNotValidAtThisTime;
  886. bits.mIsUntrusted = status->mIsUntrusted;
  887. MutexAutoLock lock(mMutex);
  888. mErrorHosts.Put(hostPortKey, bits);
  889. }
  890. else {
  891. MutexAutoLock lock(mMutex);
  892. mErrorHosts.Remove(hostPortKey);
  893. }
  894. }
  895. void
  896. RememberCertErrorsTable::LookupCertErrorBits(TransportSecurityInfo* infoObject,
  897. nsSSLStatus* status)
  898. {
  899. // Get remembered error bits from our cache, because of SSL session caching
  900. // the NSS library potentially hasn't notified us for this socket.
  901. if (status->mHaveCertErrorBits)
  902. // Rather do not modify bits if already set earlier
  903. return;
  904. nsresult rv;
  905. nsAutoCString hostPortKey;
  906. rv = GetHostPortKey(infoObject, hostPortKey);
  907. if (NS_FAILED(rv))
  908. return;
  909. CertStateBits bits;
  910. {
  911. MutexAutoLock lock(mMutex);
  912. if (!mErrorHosts.Get(hostPortKey, &bits))
  913. // No record was found, this host had no cert errors
  914. return;
  915. }
  916. // This host had cert errors, update the bits correctly
  917. status->mHaveCertErrorBits = true;
  918. status->mIsDomainMismatch = bits.mIsDomainMismatch;
  919. status->mIsNotValidAtThisTime = bits.mIsNotValidAtThisTime;
  920. status->mIsUntrusted = bits.mIsUntrusted;
  921. }
  922. void
  923. TransportSecurityInfo::SetStatusErrorBits(nsNSSCertificate* cert,
  924. uint32_t collected_errors)
  925. {
  926. MutexAutoLock lock(mMutex);
  927. if (!mSSLStatus) {
  928. mSSLStatus = new nsSSLStatus();
  929. }
  930. mSSLStatus->SetServerCert(cert, EVStatus::NotEV);
  931. mSSLStatus->mHaveCertErrorBits = true;
  932. mSSLStatus->mIsDomainMismatch =
  933. collected_errors & nsICertOverrideService::ERROR_MISMATCH;
  934. mSSLStatus->mIsNotValidAtThisTime =
  935. collected_errors & nsICertOverrideService::ERROR_TIME;
  936. mSSLStatus->mIsUntrusted =
  937. collected_errors & nsICertOverrideService::ERROR_UNTRUSTED;
  938. RememberCertErrorsTable::GetInstance().RememberCertHasError(this,
  939. mSSLStatus,
  940. SECFailure);
  941. }
  942. NS_IMETHODIMP
  943. TransportSecurityInfo::GetFailedCertChain(nsIX509CertList** _result)
  944. {
  945. NS_ASSERTION(_result, "non-NULL destination required");
  946. *_result = mFailedCertChain;
  947. NS_IF_ADDREF(*_result);
  948. return NS_OK;
  949. }
  950. nsresult
  951. TransportSecurityInfo::SetFailedCertChain(UniqueCERTCertList certList)
  952. {
  953. nsNSSShutDownPreventionLock lock;
  954. if (isAlreadyShutDown()) {
  955. return NS_ERROR_NOT_AVAILABLE;
  956. }
  957. // nsNSSCertList takes ownership of certList
  958. mFailedCertChain = new nsNSSCertList(Move(certList), lock);
  959. return NS_OK;
  960. }
  961. } } // namespace mozilla::psm