security/manager/ssl/src/TransportSecurityInfo.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial