2012-04-30 08:00:22 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
2012-05-31 13:33:35 +04:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
#include "TransportSecurityInfo.h"
|
2014-01-23 05:13:19 +04:00
|
|
|
|
2016-11-22 02:58:37 +03:00
|
|
|
#include "DateTimeFormat.h"
|
2016-05-19 07:20:56 +03:00
|
|
|
#include "PSMRunnable.h"
|
|
|
|
#include "mozilla/Casting.h"
|
|
|
|
#include "nsComponentManagerUtils.h"
|
|
|
|
#include "nsIArray.h"
|
2012-04-30 08:00:22 +04:00
|
|
|
#include "nsICertOverrideService.h"
|
|
|
|
#include "nsIObjectInputStream.h"
|
|
|
|
#include "nsIObjectOutputStream.h"
|
2016-05-19 07:20:56 +03:00
|
|
|
#include "nsIWebProgressListener.h"
|
|
|
|
#include "nsIX509CertValidity.h"
|
2012-04-30 08:00:22 +04:00
|
|
|
#include "nsNSSCertHelper.h"
|
2016-05-19 07:20:56 +03:00
|
|
|
#include "nsNSSCertificate.h"
|
|
|
|
#include "nsNSSComponent.h"
|
2014-06-02 20:04:39 +04:00
|
|
|
#include "nsReadableUtils.h"
|
2013-06-23 02:57:15 +04:00
|
|
|
#include "nsServiceManagerUtils.h"
|
2015-01-16 15:48:38 +03:00
|
|
|
#include "nsXULAppAPI.h"
|
2016-05-19 07:20:56 +03:00
|
|
|
#include "pkix/pkixtypes.h"
|
2012-04-30 08:00:22 +04:00
|
|
|
#include "secerr.h"
|
|
|
|
|
2017-07-06 15:00:35 +03:00
|
|
|
//#define DEBUG_SSL_VERBOSE //Enable this define to get minimal
|
2012-04-30 08:00:22 +04:00
|
|
|
//reports when doing SSL read/write
|
2016-05-19 07:20:56 +03:00
|
|
|
|
2012-04-30 08:00:22 +04:00
|
|
|
//#define DUMP_BUFFER //Enable this define along with
|
|
|
|
//DEBUG_SSL_VERBOSE to dump SSL
|
|
|
|
//read/write buffer to a log.
|
|
|
|
//Uses PR_LOG except on Mac where
|
|
|
|
//we always write out to our own
|
|
|
|
//file.
|
|
|
|
|
|
|
|
namespace mozilla { namespace psm {
|
|
|
|
|
|
|
|
TransportSecurityInfo::TransportSecurityInfo()
|
2017-06-03 08:36:41 +03:00
|
|
|
: mMutex("TransportSecurityInfo::mMutex")
|
|
|
|
, mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE)
|
|
|
|
, mSubRequestsBrokenSecurity(0)
|
|
|
|
, mSubRequestsNoSecurity(0)
|
|
|
|
, mErrorCode(0)
|
|
|
|
, mErrorMessageType(SSLErrorMessageType::Plain)
|
|
|
|
, mPort(0)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TransportSecurityInfo::~TransportSecurityInfo()
|
|
|
|
{
|
|
|
|
nsNSSShutDownPreventionLock locker;
|
|
|
|
if (isAlreadyShutDown())
|
|
|
|
return;
|
|
|
|
|
2016-08-20 18:00:19 +03:00
|
|
|
shutdown(ShutdownCalledFrom::Object);
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TransportSecurityInfo::virtualDestroyNSSReference()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-04-27 11:06:00 +04:00
|
|
|
NS_IMPL_ISUPPORTS(TransportSecurityInfo,
|
|
|
|
nsITransportSecurityInfo,
|
|
|
|
nsIInterfaceRequestor,
|
|
|
|
nsISSLStatusProvider,
|
|
|
|
nsIAssociatedContentSecurity,
|
|
|
|
nsISerializable,
|
|
|
|
nsIClassInfo)
|
2012-04-30 08:00:22 +04:00
|
|
|
|
2017-03-28 17:57:15 +03:00
|
|
|
void
|
2012-04-30 08:00:22 +04:00
|
|
|
TransportSecurityInfo::SetHostName(const char* host)
|
|
|
|
{
|
2017-03-28 17:57:15 +03:00
|
|
|
mHostName.Assign(host);
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
2017-06-03 08:36:16 +03:00
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
TransportSecurityInfo::SetPort(int32_t aPort)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
mPort = aPort;
|
|
|
|
}
|
|
|
|
|
2017-06-03 08:36:16 +03:00
|
|
|
void
|
2016-11-14 13:26:15 +03:00
|
|
|
TransportSecurityInfo::SetOriginAttributes(
|
2017-01-12 19:38:48 +03:00
|
|
|
const OriginAttributes& aOriginAttributes)
|
2016-10-18 11:45:23 +03:00
|
|
|
{
|
2016-11-14 13:26:15 +03:00
|
|
|
mOriginAttributes = aOriginAttributes;
|
2016-10-18 11:45:23 +03:00
|
|
|
}
|
|
|
|
|
2017-09-23 04:43:18 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::GetErrorCode(int32_t* state)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
2017-09-23 04:43:18 +03:00
|
|
|
*state = mErrorCode;
|
|
|
|
return NS_OK;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
TransportSecurityInfo::SetCanceled(PRErrorCode errorCode,
|
|
|
|
SSLErrorMessageType errorMessageType)
|
|
|
|
{
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
|
|
|
mErrorCode = errorCode;
|
|
|
|
mErrorMessageType = errorMessageType;
|
|
|
|
mErrorMessageCached.Truncate();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
TransportSecurityInfo::GetSecurityState(uint32_t* state)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
*state = mSecurityState;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-06-03 08:36:16 +03:00
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
TransportSecurityInfo::SetSecurityState(uint32_t aState)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
mSecurityState = aState;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::GetCountSubRequestsBrokenSecurity(
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t *aSubRequestsBrokenSecurity)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
*aSubRequestsBrokenSecurity = mSubRequestsBrokenSecurity;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::SetCountSubRequestsBrokenSecurity(
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aSubRequestsBrokenSecurity)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
mSubRequestsBrokenSecurity = aSubRequestsBrokenSecurity;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::GetCountSubRequestsNoSecurity(
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t *aSubRequestsNoSecurity)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
*aSubRequestsNoSecurity = mSubRequestsNoSecurity;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::SetCountSubRequestsNoSecurity(
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aSubRequestsNoSecurity)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
mSubRequestsNoSecurity = aSubRequestsNoSecurity;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::Flush()
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2014-01-04 19:02:17 +04:00
|
|
|
TransportSecurityInfo::GetErrorMessage(char16_t** aText)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aText);
|
2012-07-30 18:20:58 +04:00
|
|
|
*aText = nullptr;
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
NS_ERROR("nsNSSSocketInfo::GetErrorMessage called off the main thread");
|
|
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
|
|
}
|
|
|
|
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
2012-08-28 17:32:34 +04:00
|
|
|
if (mErrorMessageCached.IsEmpty()) {
|
2017-07-06 15:00:35 +03:00
|
|
|
nsresult rv = formatErrorMessage(lock,
|
2012-08-28 17:32:34 +04:00
|
|
|
mErrorCode, mErrorMessageType,
|
|
|
|
true, true, mErrorMessageCached);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
*aText = ToNewUnicode(mErrorMessageCached);
|
2012-10-18 00:48:36 +04:00
|
|
|
return *aText ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
2012-08-28 17:32:34 +04:00
|
|
|
void
|
|
|
|
TransportSecurityInfo::GetErrorLogMessage(PRErrorCode errorCode,
|
|
|
|
SSLErrorMessageType errorMessageType,
|
|
|
|
nsString &result)
|
|
|
|
{
|
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
NS_ERROR("nsNSSSocketInfo::GetErrorLogMessage called off the main thread");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
(void) formatErrorMessage(lock, errorCode, errorMessageType,
|
|
|
|
false, false, result);
|
|
|
|
}
|
|
|
|
|
2012-04-30 08:00:22 +04:00
|
|
|
static nsresult
|
2017-03-28 17:57:15 +03:00
|
|
|
formatPlainErrorMessage(const nsCString& host, int32_t port,
|
|
|
|
PRErrorCode err,
|
2012-08-28 17:32:34 +04:00
|
|
|
bool suppressPort443,
|
2017-03-28 17:57:15 +03:00
|
|
|
/*out*/ nsString& returnedMessage);
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
static nsresult
|
2017-03-28 17:57:15 +03:00
|
|
|
formatOverridableCertErrorMessage(nsISSLStatus& sslStatus,
|
|
|
|
PRErrorCode errorCodeToReport,
|
|
|
|
const nsCString& host, int32_t port,
|
2012-08-28 17:32:34 +04:00
|
|
|
bool suppressPort443,
|
|
|
|
bool wantsHtml,
|
2017-03-28 17:57:15 +03:00
|
|
|
/*out*/ nsString& returnedMessage);
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
// XXX: uses nsNSSComponent string bundles off the main thread when called by
|
2012-08-28 17:32:34 +04:00
|
|
|
// nsNSSSocketInfo::Write().
|
2012-04-30 08:00:22 +04:00
|
|
|
nsresult
|
2017-03-28 17:57:15 +03:00
|
|
|
TransportSecurityInfo::formatErrorMessage(const MutexAutoLock& /*proofOfLock*/,
|
2012-08-28 17:32:34 +04:00
|
|
|
PRErrorCode errorCode,
|
|
|
|
SSLErrorMessageType errorMessageType,
|
2017-03-28 17:57:15 +03:00
|
|
|
bool wantsHtml, bool suppressPort443,
|
|
|
|
/*out*/ nsString& result)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
2015-01-16 15:48:38 +03:00
|
|
|
result.Truncate();
|
2012-08-28 17:32:34 +04:00
|
|
|
if (errorCode == 0) {
|
2012-04-30 08:00:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-07-04 04:29:00 +03:00
|
|
|
if (!XRE_IsParentProcess()) {
|
2015-01-16 15:48:38 +03:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2012-04-30 08:00:22 +04:00
|
|
|
nsresult rv;
|
2017-06-03 08:36:41 +03:00
|
|
|
MOZ_ASSERT(errorMessageType != SSLErrorMessageType::OverridableCert ||
|
2017-01-02 09:11:39 +03:00
|
|
|
(mSSLStatus && mSSLStatus->HasServerCert() &&
|
|
|
|
mSSLStatus->mHaveCertErrorBits),
|
|
|
|
"formatErrorMessage() called for cert error without cert");
|
2017-06-03 08:36:41 +03:00
|
|
|
if (errorMessageType == SSLErrorMessageType::OverridableCert &&
|
2014-12-24 16:04:24 +03:00
|
|
|
mSSLStatus && mSSLStatus->HasServerCert()) {
|
2012-08-28 17:32:34 +04:00
|
|
|
rv = formatOverridableCertErrorMessage(*mSSLStatus, errorCode,
|
2012-04-30 08:00:22 +04:00
|
|
|
mHostName, mPort,
|
2012-08-28 17:32:34 +04:00
|
|
|
suppressPort443,
|
|
|
|
wantsHtml,
|
|
|
|
result);
|
2012-04-30 08:00:22 +04:00
|
|
|
} else {
|
2017-07-06 15:00:35 +03:00
|
|
|
rv = formatPlainErrorMessage(mHostName, mPort,
|
2012-08-28 17:32:34 +04:00
|
|
|
errorCode,
|
|
|
|
suppressPort443,
|
|
|
|
result);
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
2012-08-28 17:32:34 +04:00
|
|
|
result.Truncate();
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::GetInterface(const nsIID & uuid, void * *result)
|
|
|
|
{
|
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
NS_ERROR("nsNSSSocketInfo::GetInterface called off the main thread");
|
|
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
if (!mCallbacks) {
|
|
|
|
nsCOMPtr<nsIInterfaceRequestor> ir = new PipUIContext();
|
|
|
|
rv = ir->GetInterface(uuid, result);
|
|
|
|
} else {
|
|
|
|
rv = mCallbacks->GetInterface(uuid, result);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2014-01-10 23:13:03 +04:00
|
|
|
// This is a new magic value. However, it re-uses the first 4 bytes
|
|
|
|
// of the previous value. This is so when older versions attempt to
|
|
|
|
// read a newer serialized TransportSecurityInfo, they will actually
|
|
|
|
// fail and return NS_ERROR_FAILURE instead of silently failing.
|
2015-01-16 15:48:38 +03:00
|
|
|
#define TRANSPORTSECURITYINFOMAGIC { 0xa9863a23, 0x1faa, 0x4169, \
|
|
|
|
{ 0xb0, 0xd2, 0x81, 0x29, 0xec, 0x7c, 0xb1, 0xde } }
|
2012-04-30 08:00:22 +04:00
|
|
|
static NS_DEFINE_CID(kTransportSecurityInfoMagic, TRANSPORTSECURITYINFOMAGIC);
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::Write(nsIObjectOutputStream* stream)
|
|
|
|
{
|
2014-01-10 23:13:03 +04:00
|
|
|
nsresult rv = stream->WriteID(kTransportSecurityInfoMagic);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
2014-01-10 23:13:03 +04:00
|
|
|
rv = stream->Write32(mSecurityState);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2014-01-10 23:13:03 +04:00
|
|
|
rv = stream->Write32(mSubRequestsBrokenSecurity);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
rv = stream->Write32(mSubRequestsNoSecurity);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2015-01-16 15:48:38 +03:00
|
|
|
rv = stream->Write32(static_cast<uint32_t>(mErrorCode));
|
2014-01-10 23:13:03 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2015-01-16 15:48:38 +03:00
|
|
|
if (mErrorMessageCached.IsEmpty()) {
|
|
|
|
// XXX: uses nsNSSComponent string bundles off the main thread
|
|
|
|
rv = formatErrorMessage(lock, mErrorCode, mErrorMessageType,
|
|
|
|
true, true, mErrorMessageCached);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
2014-01-10 23:13:03 +04:00
|
|
|
rv = stream->WriteWStringZ(mErrorMessageCached.get());
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-10-16 23:11:19 +04:00
|
|
|
|
|
|
|
// For successful connections and for connections with overridable errors,
|
|
|
|
// mSSLStatus will be non-null. However, for connections with non-overridable
|
|
|
|
// errors, it will be null.
|
2014-01-10 23:13:03 +04:00
|
|
|
nsCOMPtr<nsISerializable> serializable(mSSLStatus);
|
2014-10-16 23:11:19 +04:00
|
|
|
rv = NS_WriteOptionalCompoundObject(stream,
|
|
|
|
serializable,
|
|
|
|
NS_GET_IID(nsISSLStatus),
|
|
|
|
true);
|
2014-01-10 23:13:03 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-08-15 22:27:22 +04:00
|
|
|
|
|
|
|
rv = NS_WriteOptionalCompoundObject(stream,
|
|
|
|
mFailedCertChain,
|
|
|
|
NS_GET_IID(nsIX509CertList),
|
|
|
|
true);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2012-04-30 08:00:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::Read(nsIObjectInputStream* stream)
|
|
|
|
{
|
2014-01-10 23:13:03 +04:00
|
|
|
nsID id;
|
|
|
|
nsresult rv = stream->ReadID(&id);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2014-01-10 23:13:03 +04:00
|
|
|
if (!id.Equals(kTransportSecurityInfoMagic)) {
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
2014-01-10 23:13:03 +04:00
|
|
|
MutexAutoLock lock(mMutex);
|
2012-04-30 08:00:22 +04:00
|
|
|
|
2014-01-10 23:13:03 +04:00
|
|
|
rv = stream->Read32(&mSecurityState);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2014-01-10 23:13:03 +04:00
|
|
|
uint32_t subRequestsBrokenSecurity;
|
|
|
|
rv = stream->Read32(&subRequestsBrokenSecurity);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2014-01-10 23:13:03 +04:00
|
|
|
if (subRequestsBrokenSecurity >
|
|
|
|
static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2014-01-10 23:13:03 +04:00
|
|
|
mSubRequestsBrokenSecurity = subRequestsBrokenSecurity;
|
|
|
|
uint32_t subRequestsNoSecurity;
|
|
|
|
rv = stream->Read32(&subRequestsNoSecurity);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2014-01-10 23:13:03 +04:00
|
|
|
if (subRequestsNoSecurity >
|
|
|
|
static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2014-01-10 23:13:03 +04:00
|
|
|
mSubRequestsNoSecurity = subRequestsNoSecurity;
|
2015-01-16 15:48:38 +03:00
|
|
|
uint32_t errorCode;
|
|
|
|
rv = stream->Read32(&errorCode);
|
2014-01-10 23:13:03 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2015-01-16 15:48:38 +03:00
|
|
|
// PRErrorCode will be a negative value
|
|
|
|
mErrorCode = static_cast<PRErrorCode>(errorCode);
|
2014-10-16 23:11:19 +04:00
|
|
|
|
2015-01-16 15:48:38 +03:00
|
|
|
rv = stream->ReadString(mErrorMessageCached);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-10-16 23:11:19 +04:00
|
|
|
|
|
|
|
// For successful connections and for connections with overridable errors,
|
|
|
|
// mSSLStatus will be non-null. For connections with non-overridable errors,
|
|
|
|
// it will be null.
|
2014-01-10 23:13:03 +04:00
|
|
|
nsCOMPtr<nsISupports> supports;
|
2014-10-16 23:11:19 +04:00
|
|
|
rv = NS_ReadOptionalObject(stream, true, getter_AddRefs(supports));
|
2014-01-10 23:13:03 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2016-05-19 07:20:56 +03:00
|
|
|
mSSLStatus = BitwiseCast<nsSSLStatus*, nsISupports*>(supports.get());
|
2014-08-15 22:27:22 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> failedCertChainSupports;
|
|
|
|
rv = NS_ReadOptionalObject(stream, true, getter_AddRefs(failedCertChainSupports));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
mFailedCertChain = do_QueryInterface(failedCertChainSupports);
|
|
|
|
|
2012-04-30 08:00:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
TransportSecurityInfo::GetInterfaces(uint32_t *count, nsIID * **array)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
*count = 0;
|
2012-07-30 18:20:58 +04:00
|
|
|
*array = nullptr;
|
2012-04-30 08:00:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-03-29 17:52:54 +03:00
|
|
|
TransportSecurityInfo::GetScriptableHelper(nsIXPCScriptable **_retval)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
*_retval = nullptr;
|
2012-04-30 08:00:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::GetContractID(char * *aContractID)
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
*aContractID = nullptr;
|
2012-04-30 08:00:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::GetClassDescription(char * *aClassDescription)
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
*aClassDescription = nullptr;
|
2012-04-30 08:00:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::GetClassID(nsCID * *aClassID)
|
|
|
|
{
|
2015-03-27 03:01:12 +03:00
|
|
|
*aClassID = (nsCID*) moz_xmalloc(sizeof(nsCID));
|
2012-04-30 08:00:22 +04:00
|
|
|
if (!*aClassID)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
return GetClassIDNoAlloc(*aClassID);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
TransportSecurityInfo::GetFlags(uint32_t *aFlags)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
*aFlags = 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static NS_DEFINE_CID(kNSSSocketInfoCID, TRANSPORTSECURITYINFO_CID);
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
|
|
|
|
{
|
|
|
|
*aClassIDNoAlloc = kNSSSocketInfoCID;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
TransportSecurityInfo::GetSSLStatus(nsISSLStatus** _result)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(_result);
|
|
|
|
|
|
|
|
*_result = mSSLStatus;
|
|
|
|
NS_IF_ADDREF(*_result);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-06-03 08:36:16 +03:00
|
|
|
void
|
2012-04-30 08:00:22 +04:00
|
|
|
TransportSecurityInfo::SetSSLStatus(nsSSLStatus *aSSLStatus)
|
|
|
|
{
|
|
|
|
mSSLStatus = aSSLStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Formats an error message for non-certificate-related SSL errors
|
|
|
|
* and non-overridable certificate errors (both are of type
|
|
|
|
* PlainErrormMessage). Use formatOverridableCertErrorMessage
|
|
|
|
* for overridable cert errors.
|
|
|
|
*/
|
|
|
|
static nsresult
|
2017-03-28 17:57:15 +03:00
|
|
|
formatPlainErrorMessage(const nsCString& host, int32_t port,
|
|
|
|
PRErrorCode err,
|
2012-08-28 17:32:34 +04:00
|
|
|
bool suppressPort443,
|
2017-03-28 17:57:15 +03:00
|
|
|
/*out*/ nsString& returnedMessage)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
2013-11-26 22:18:21 +04:00
|
|
|
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
|
|
|
|
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t *params[1];
|
2012-04-30 08:00:22 +04:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsINSSComponent> component = do_GetService(kNSSComponentCID, &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (host.Length())
|
|
|
|
{
|
|
|
|
// For now, hide port when it's 443 and we're reporting the error.
|
|
|
|
// In the future a better mechanism should be used
|
|
|
|
// to make a decision about showing the port number, possibly by requiring
|
|
|
|
// the context object to implement a specific interface.
|
|
|
|
// The motivation is that Mozilla browser would like to hide the port number
|
|
|
|
// in error pages in the common case.
|
|
|
|
|
2017-03-28 17:57:15 +03:00
|
|
|
NS_ConvertASCIItoUTF16 hostWithPort(host);
|
2012-08-28 17:32:34 +04:00
|
|
|
if (!suppressPort443 || port != 443) {
|
2014-05-22 07:48:51 +04:00
|
|
|
hostWithPort.Append(':');
|
2012-04-30 08:00:22 +04:00
|
|
|
hostWithPort.AppendInt(port);
|
|
|
|
}
|
|
|
|
params[0] = hostWithPort.get();
|
|
|
|
|
|
|
|
nsString formattedString;
|
2017-03-28 17:57:15 +03:00
|
|
|
rv = component->PIPBundleFormatStringFromName("SSLConnectionErrorPrefix",
|
|
|
|
params, 1, formattedString);
|
2012-04-30 08:00:22 +04:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
returnedMessage.Append(formattedString);
|
2014-05-22 07:48:50 +04:00
|
|
|
returnedMessage.AppendLiteral("\n\n");
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsString explanation;
|
|
|
|
rv = nsNSSErrors::getErrorMessageFromCode(err, component, explanation);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
returnedMessage.Append(explanation);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
AppendErrorTextUntrusted(PRErrorCode errTrust,
|
|
|
|
const nsString &host,
|
|
|
|
nsIX509Cert* ix509,
|
|
|
|
nsINSSComponent *component,
|
|
|
|
nsString &returnedMessage)
|
|
|
|
{
|
2015-03-17 16:33:00 +03:00
|
|
|
const char* errorID = nullptr;
|
|
|
|
const char* errorID2 = nullptr;
|
|
|
|
const char* errorID3 = nullptr;
|
2014-07-04 09:09:24 +04:00
|
|
|
bool isSelfSigned;
|
|
|
|
if (NS_SUCCEEDED(ix509->GetIsSelfSigned(&isSelfSigned)) && isSelfSigned) {
|
|
|
|
errorID = "certErrorTrust_SelfSigned";
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!errorID) {
|
|
|
|
switch (errTrust) {
|
|
|
|
case SEC_ERROR_UNKNOWN_ISSUER:
|
2015-02-09 05:50:00 +03:00
|
|
|
errorID = "certErrorTrust_UnknownIssuer";
|
2015-03-17 16:33:00 +03:00
|
|
|
errorID2 = "certErrorTrust_UnknownIssuer2";
|
|
|
|
errorID3 = "certErrorTrust_UnknownIssuer3";
|
2012-04-30 08:00:22 +04:00
|
|
|
break;
|
|
|
|
case SEC_ERROR_CA_CERT_INVALID:
|
|
|
|
errorID = "certErrorTrust_CaInvalid";
|
|
|
|
break;
|
|
|
|
case SEC_ERROR_UNTRUSTED_ISSUER:
|
|
|
|
errorID = "certErrorTrust_Issuer";
|
|
|
|
break;
|
2012-07-11 06:42:50 +04:00
|
|
|
case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
|
|
|
|
errorID = "certErrorTrust_SignatureAlgorithmDisabled";
|
|
|
|
break;
|
2012-04-30 08:00:22 +04:00
|
|
|
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
|
|
|
|
errorID = "certErrorTrust_ExpiredIssuer";
|
|
|
|
break;
|
|
|
|
case SEC_ERROR_UNTRUSTED_CERT:
|
|
|
|
default:
|
|
|
|
errorID = "certErrorTrust_Untrusted";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-17 16:33:00 +03:00
|
|
|
const char* errorIDs[] = { errorID, errorID2, errorID3 };
|
|
|
|
for (size_t i = 0; i < ArrayLength(errorIDs); i++) {
|
|
|
|
if (!errorIDs[i]) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsString formattedString;
|
|
|
|
nsresult rv = component->GetPIPNSSBundleString(errorIDs[i], formattedString);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
returnedMessage.Append(formattedString);
|
|
|
|
returnedMessage.Append('\n');
|
|
|
|
}
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-05 02:25:24 +03:00
|
|
|
// Returns the number of dNSName or iPAddress entries encountered in the
|
|
|
|
// subject alternative name extension of the certificate.
|
|
|
|
// Returns zero if the extension is not present, could not be decoded, or if it
|
|
|
|
// does not contain any dNSName or iPAddress entries.
|
|
|
|
static uint32_t
|
|
|
|
GetSubjectAltNames(CERTCertificate* nssCert, nsString& allNames)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
allNames.Truncate();
|
|
|
|
|
2016-04-05 02:25:24 +03:00
|
|
|
ScopedAutoSECItem altNameExtension;
|
2012-07-27 18:03:25 +04:00
|
|
|
SECStatus rv = CERT_FindCertExtension(nssCert, SEC_OID_X509_SUBJECT_ALT_NAME,
|
|
|
|
&altNameExtension);
|
2014-06-20 01:36:31 +04:00
|
|
|
if (rv != SECSuccess) {
|
2016-04-05 02:25:24 +03:00
|
|
|
return 0;
|
2014-06-20 01:36:31 +04:00
|
|
|
}
|
2016-04-05 03:35:24 +03:00
|
|
|
UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
|
2014-06-20 01:36:31 +04:00
|
|
|
if (!arena) {
|
2016-04-05 02:25:24 +03:00
|
|
|
return 0;
|
2014-06-20 01:36:31 +04:00
|
|
|
}
|
2016-04-05 02:25:24 +03:00
|
|
|
CERTGeneralName* sanNameList(CERT_DecodeAltNameExtension(arena.get(),
|
|
|
|
&altNameExtension));
|
2014-06-20 01:36:31 +04:00
|
|
|
if (!sanNameList) {
|
2016-04-05 02:25:24 +03:00
|
|
|
return 0;
|
2014-06-20 01:36:31 +04:00
|
|
|
}
|
2012-04-30 08:00:22 +04:00
|
|
|
|
2016-04-05 02:25:24 +03:00
|
|
|
uint32_t nameCount = 0;
|
|
|
|
CERTGeneralName* current = sanNameList;
|
2012-04-30 08:00:22 +04:00
|
|
|
do {
|
|
|
|
nsAutoString name;
|
|
|
|
switch (current->type) {
|
|
|
|
case certDNSName:
|
2014-06-02 20:04:39 +04:00
|
|
|
{
|
2016-05-19 07:20:56 +03:00
|
|
|
nsDependentCSubstring nameFromCert(BitwiseCast<char*, unsigned char*>(
|
|
|
|
current->name.other.data),
|
|
|
|
current->name.other.len);
|
2014-06-02 20:04:39 +04:00
|
|
|
// dNSName fields are defined as type IA5String and thus should
|
|
|
|
// be limited to ASCII characters.
|
|
|
|
if (IsASCII(nameFromCert)) {
|
|
|
|
name.Assign(NS_ConvertASCIItoUTF16(nameFromCert));
|
|
|
|
if (!allNames.IsEmpty()) {
|
|
|
|
allNames.AppendLiteral(", ");
|
|
|
|
}
|
|
|
|
++nameCount;
|
|
|
|
allNames.Append(name);
|
|
|
|
}
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case certIPAddress:
|
|
|
|
{
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
PRNetAddr addr;
|
|
|
|
if (current->name.other.len == 4) {
|
|
|
|
addr.inet.family = PR_AF_INET;
|
|
|
|
memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
|
|
|
|
PR_NetAddrToString(&addr, buf, sizeof(buf));
|
|
|
|
name.AssignASCII(buf);
|
|
|
|
} else if (current->name.other.len == 16) {
|
|
|
|
addr.ipv6.family = PR_AF_INET6;
|
|
|
|
memcpy(&addr.ipv6.ip, current->name.other.data, current->name.other.len);
|
|
|
|
PR_NetAddrToString(&addr, buf, sizeof(buf));
|
|
|
|
name.AssignASCII(buf);
|
|
|
|
} else {
|
|
|
|
/* invalid IP address */
|
|
|
|
}
|
|
|
|
if (!name.IsEmpty()) {
|
|
|
|
if (!allNames.IsEmpty()) {
|
2014-05-22 07:48:50 +04:00
|
|
|
allNames.AppendLiteral(", ");
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
++nameCount;
|
|
|
|
allNames.Append(name);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default: // all other types of names are ignored
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
current = CERT_GetNextGeneralName(current);
|
|
|
|
} while (current != sanNameList); // double linked
|
|
|
|
|
2016-04-05 02:25:24 +03:00
|
|
|
return nameCount;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:25:24 +03:00
|
|
|
static nsresult
|
|
|
|
AppendErrorTextMismatch(const nsString& host, nsIX509Cert* ix509,
|
|
|
|
nsINSSComponent* component, bool wantsHtml,
|
|
|
|
nsString& returnedMessage)
|
|
|
|
{
|
|
|
|
// Prepare a default "not valid for <hostname>" string in case anything
|
|
|
|
// goes wrong (or in case the certificate is not valid for any hostnames).
|
|
|
|
nsAutoString notValidForHostnameString;
|
|
|
|
const char16_t* params[1];
|
|
|
|
params[0] = host.get();
|
|
|
|
nsresult rv = component->PIPBundleFormatStringFromName(
|
|
|
|
"certErrorMismatch", params, 1, notValidForHostnameString);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
notValidForHostnameString.Append('\n');
|
2012-04-30 08:00:22 +04:00
|
|
|
|
2016-04-20 11:14:22 +03:00
|
|
|
UniqueCERTCertificate nssCert(ix509->GetCert());
|
2012-04-30 08:00:22 +04:00
|
|
|
if (!nssCert) {
|
2016-04-05 02:25:24 +03:00
|
|
|
returnedMessage.Append(notValidForHostnameString);
|
|
|
|
return NS_OK;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:25:24 +03:00
|
|
|
nsAutoString allNames;
|
|
|
|
uint32_t nameCount = GetSubjectAltNames(nssCert.get(), allNames);
|
|
|
|
if (nameCount == 0) {
|
|
|
|
returnedMessage.Append(notValidForHostnameString);
|
|
|
|
} else if (nameCount > 1) {
|
2012-04-30 08:00:22 +04:00
|
|
|
nsString message;
|
2016-04-05 02:25:24 +03:00
|
|
|
rv = component->GetPIPNSSBundleString("certErrorMismatchMultiple", message);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2016-04-05 02:25:24 +03:00
|
|
|
returnedMessage.Append(message);
|
|
|
|
returnedMessage.AppendLiteral("\n ");
|
|
|
|
returnedMessage.Append(allNames);
|
|
|
|
returnedMessage.AppendLiteral(" \n");
|
|
|
|
} else if (nameCount == 1) {
|
2012-04-30 08:00:22 +04:00
|
|
|
params[0] = allNames.get();
|
|
|
|
|
2016-04-05 02:25:24 +03:00
|
|
|
const char* stringID = wantsHtml ? "certErrorMismatchSingle2"
|
|
|
|
: "certErrorMismatchSinglePlain";
|
|
|
|
nsAutoString formattedString;
|
|
|
|
rv = component->PIPBundleFormatStringFromName(stringID, params, 1,
|
2012-04-30 08:00:22 +04:00
|
|
|
formattedString);
|
2016-04-05 02:25:24 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2016-04-05 02:25:24 +03:00
|
|
|
returnedMessage.Append(formattedString);
|
|
|
|
returnedMessage.Append('\n');
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
2016-04-05 02:25:24 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
GetDateBoundary(nsIX509Cert* ix509,
|
|
|
|
nsString &formattedDate,
|
|
|
|
nsString &nowDate,
|
|
|
|
bool &trueExpired_falseNotYetValid)
|
|
|
|
{
|
|
|
|
trueExpired_falseNotYetValid = true;
|
|
|
|
formattedDate.Truncate();
|
|
|
|
|
|
|
|
PRTime notAfter, notBefore, timeToUse;
|
|
|
|
nsCOMPtr<nsIX509CertValidity> validity;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
rv = ix509->GetValidity(getter_AddRefs(validity));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
|
|
|
|
|
|
|
rv = validity->GetNotAfter(¬After);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
|
|
|
|
|
|
|
rv = validity->GetNotBefore(¬Before);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
|
|
|
|
|
|
|
PRTime now = PR_Now();
|
2012-10-03 18:13:19 +04:00
|
|
|
if (now > notAfter) {
|
2012-04-30 08:00:22 +04:00
|
|
|
timeToUse = notAfter;
|
|
|
|
} else {
|
|
|
|
timeToUse = notBefore;
|
|
|
|
trueExpired_falseNotYetValid = false;
|
|
|
|
}
|
|
|
|
|
2016-11-22 02:58:37 +03:00
|
|
|
DateTimeFormat::FormatPRTime(kDateFormatLong, kTimeFormatNoSeconds,
|
2015-09-14 00:33:00 +03:00
|
|
|
timeToUse, formattedDate);
|
2016-11-22 02:58:37 +03:00
|
|
|
DateTimeFormat::FormatPRTime(kDateFormatLong, kTimeFormatNoSeconds,
|
2015-09-14 00:33:00 +03:00
|
|
|
now, nowDate);
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
AppendErrorTextTime(nsIX509Cert* ix509,
|
|
|
|
nsINSSComponent *component,
|
|
|
|
nsString &returnedMessage)
|
|
|
|
{
|
|
|
|
nsAutoString formattedDate, nowDate;
|
|
|
|
bool trueExpired_falseNotYetValid;
|
|
|
|
GetDateBoundary(ix509, formattedDate, nowDate, trueExpired_falseNotYetValid);
|
|
|
|
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t *params[2];
|
2017-07-06 15:00:35 +03:00
|
|
|
params[0] = formattedDate.get(); // might be empty, if helper function had a problem
|
2012-04-30 08:00:22 +04:00
|
|
|
params[1] = nowDate.get();
|
|
|
|
|
2017-07-06 15:00:35 +03:00
|
|
|
const char *key = trueExpired_falseNotYetValid ?
|
2012-04-30 08:00:22 +04:00
|
|
|
"certErrorExpiredNow" : "certErrorNotYetValidNow";
|
|
|
|
nsresult rv;
|
|
|
|
nsString formattedString;
|
|
|
|
rv = component->PIPBundleFormatStringFromName(
|
|
|
|
key,
|
2017-07-06 15:00:35 +03:00
|
|
|
params,
|
2012-04-30 08:00:22 +04:00
|
|
|
ArrayLength(params),
|
|
|
|
formattedString);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
returnedMessage.Append(formattedString);
|
2014-05-22 07:48:50 +04:00
|
|
|
returnedMessage.Append('\n');
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
AppendErrorTextCode(PRErrorCode errorCodeToReport,
|
|
|
|
nsINSSComponent *component,
|
|
|
|
nsString &returnedMessage)
|
|
|
|
{
|
|
|
|
const char *codeName = nsNSSErrors::getDefaultErrorStringName(errorCodeToReport);
|
|
|
|
if (codeName)
|
|
|
|
{
|
|
|
|
nsCString error_id(codeName);
|
|
|
|
NS_ConvertASCIItoUTF16 idU(error_id);
|
|
|
|
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t *params[1];
|
2012-04-30 08:00:22 +04:00
|
|
|
params[0] = idU.get();
|
|
|
|
|
|
|
|
nsString formattedString;
|
|
|
|
nsresult rv;
|
2015-11-25 18:30:27 +03:00
|
|
|
rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix2",
|
2017-07-06 15:00:35 +03:00
|
|
|
params, 1,
|
2012-04-30 08:00:22 +04:00
|
|
|
formattedString);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2014-05-22 07:48:50 +04:00
|
|
|
returnedMessage.Append('\n');
|
2012-04-30 08:00:22 +04:00
|
|
|
returnedMessage.Append(formattedString);
|
2014-05-22 07:48:50 +04:00
|
|
|
returnedMessage.Append('\n');
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
else {
|
2014-05-22 07:48:50 +04:00
|
|
|
returnedMessage.AppendLiteral(" (");
|
2012-04-30 08:00:22 +04:00
|
|
|
returnedMessage.Append(idU);
|
2014-05-22 07:48:50 +04:00
|
|
|
returnedMessage.Append(')');
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Formats an error message for overridable certificate errors (of type
|
|
|
|
* OverridableCertErrorMessage). Use formatPlainErrorMessage to format
|
|
|
|
* non-overridable cert errors and non-cert-related errors.
|
|
|
|
*/
|
|
|
|
static nsresult
|
2017-03-28 17:57:15 +03:00
|
|
|
formatOverridableCertErrorMessage(nsISSLStatus& sslStatus,
|
|
|
|
PRErrorCode errorCodeToReport,
|
|
|
|
const nsCString& host, int32_t port,
|
2012-08-28 17:32:34 +04:00
|
|
|
bool suppressPort443,
|
|
|
|
bool wantsHtml,
|
2017-03-28 17:57:15 +03:00
|
|
|
/*out*/ nsString& returnedMessage)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
2013-11-26 22:18:21 +04:00
|
|
|
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
|
|
|
|
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t *params[1];
|
2012-04-30 08:00:22 +04:00
|
|
|
nsresult rv;
|
2017-03-28 17:57:15 +03:00
|
|
|
NS_ConvertASCIItoUTF16 hostWithPort(host);
|
|
|
|
NS_ConvertASCIItoUTF16 hostWithoutPort(host);
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
// For now, hide port when it's 443 and we're reporting the error.
|
|
|
|
// In the future a better mechanism should be used
|
|
|
|
// to make a decision about showing the port number, possibly by requiring
|
|
|
|
// the context object to implement a specific interface.
|
|
|
|
// The motivation is that Mozilla browser would like to hide the port number
|
|
|
|
// in error pages in the common case.
|
2012-08-28 17:32:34 +04:00
|
|
|
if (suppressPort443 && port == 443) {
|
2012-04-30 08:00:22 +04:00
|
|
|
params[0] = hostWithoutPort.get();
|
|
|
|
} else {
|
|
|
|
hostWithPort.Append(':');
|
|
|
|
hostWithPort.AppendInt(port);
|
|
|
|
params[0] = hostWithPort.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsINSSComponent> component = do_GetService(kNSSComponentCID, &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
returnedMessage.Truncate();
|
|
|
|
rv = component->PIPBundleFormatStringFromName("certErrorIntro", params, 1,
|
|
|
|
returnedMessage);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2014-05-22 07:48:50 +04:00
|
|
|
returnedMessage.AppendLiteral("\n\n");
|
2012-04-30 08:00:22 +04:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsIX509Cert> ix509;
|
2015-10-18 07:40:10 +03:00
|
|
|
rv = sslStatus.GetServerCert(getter_AddRefs(ix509));
|
2012-04-30 08:00:22 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
bool isUntrusted;
|
|
|
|
rv = sslStatus.GetIsUntrusted(&isUntrusted);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (isUntrusted) {
|
2017-07-06 15:00:35 +03:00
|
|
|
AppendErrorTextUntrusted(errorCodeToReport, hostWithoutPort, ix509,
|
2012-04-30 08:00:22 +04:00
|
|
|
component, returnedMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isDomainMismatch;
|
|
|
|
rv = sslStatus.GetIsDomainMismatch(&isDomainMismatch);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (isDomainMismatch) {
|
2016-04-05 02:25:24 +03:00
|
|
|
rv = AppendErrorTextMismatch(hostWithoutPort, ix509, component, wantsHtml,
|
|
|
|
returnedMessage);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-04-30 08:00:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isNotValidAtThisTime;
|
|
|
|
rv = sslStatus.GetIsNotValidAtThisTime(&isNotValidAtThisTime);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (isNotValidAtThisTime) {
|
|
|
|
AppendErrorTextTime(ix509, component, returnedMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
AppendErrorTextCode(errorCodeToReport, component, returnedMessage);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// RememberCertErrorsTable
|
|
|
|
|
|
|
|
/*static*/ RememberCertErrorsTable*
|
2012-07-30 18:20:58 +04:00
|
|
|
RememberCertErrorsTable::sInstance = nullptr;
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
RememberCertErrorsTable::RememberCertErrorsTable()
|
2014-08-06 17:31:21 +04:00
|
|
|
: mErrorHosts()
|
2013-09-02 12:41:57 +04:00
|
|
|
, mMutex("RememberCertErrorsTable::mMutex")
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsresult
|
2017-03-28 17:57:15 +03:00
|
|
|
GetHostPortKey(TransportSecurityInfo* infoObject, /*out*/ nsCString& result)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
2017-03-28 17:57:15 +03:00
|
|
|
MOZ_ASSERT(infoObject);
|
|
|
|
NS_ENSURE_ARG(infoObject);
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
result.Truncate();
|
|
|
|
|
2017-03-28 17:57:15 +03:00
|
|
|
result.Assign(infoObject->GetHostName());
|
2012-04-30 08:00:22 +04:00
|
|
|
result.Append(':');
|
2017-06-03 08:36:04 +03:00
|
|
|
result.AppendInt(infoObject->GetPort());
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RememberCertErrorsTable::RememberCertHasError(TransportSecurityInfo* infoObject,
|
|
|
|
nsSSLStatus* status,
|
|
|
|
SECStatus certVerificationResult)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString hostPortKey;
|
2012-04-30 08:00:22 +04:00
|
|
|
rv = GetHostPortKey(infoObject, hostPortKey);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (certVerificationResult != SECSuccess) {
|
2017-01-02 09:11:39 +03:00
|
|
|
MOZ_ASSERT(status, "Must have nsSSLStatus object when remembering flags");
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
if (!status)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CertStateBits bits;
|
|
|
|
bits.mIsDomainMismatch = status->mIsDomainMismatch;
|
|
|
|
bits.mIsNotValidAtThisTime = status->mIsNotValidAtThisTime;
|
|
|
|
bits.mIsUntrusted = status->mIsUntrusted;
|
|
|
|
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
mErrorHosts.Put(hostPortKey, bits);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
mErrorHosts.Remove(hostPortKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RememberCertErrorsTable::LookupCertErrorBits(TransportSecurityInfo* infoObject,
|
|
|
|
nsSSLStatus* status)
|
|
|
|
{
|
|
|
|
// Get remembered error bits from our cache, because of SSL session caching
|
|
|
|
// the NSS library potentially hasn't notified us for this socket.
|
|
|
|
if (status->mHaveCertErrorBits)
|
|
|
|
// Rather do not modify bits if already set earlier
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString hostPortKey;
|
2012-04-30 08:00:22 +04:00
|
|
|
rv = GetHostPortKey(infoObject, hostPortKey);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
|
|
|
|
|
|
|
CertStateBits bits;
|
|
|
|
{
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
if (!mErrorHosts.Get(hostPortKey, &bits))
|
|
|
|
// No record was found, this host had no cert errors
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This host had cert errors, update the bits correctly
|
|
|
|
status->mHaveCertErrorBits = true;
|
|
|
|
status->mIsDomainMismatch = bits.mIsDomainMismatch;
|
|
|
|
status->mIsNotValidAtThisTime = bits.mIsNotValidAtThisTime;
|
|
|
|
status->mIsUntrusted = bits.mIsUntrusted;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-02-27 22:33:36 +03:00
|
|
|
TransportSecurityInfo::SetStatusErrorBits(nsNSSCertificate* cert,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t collected_errors)
|
2012-04-30 08:00:22 +04:00
|
|
|
{
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
2015-02-27 22:33:36 +03:00
|
|
|
if (!mSSLStatus) {
|
2012-04-30 08:00:22 +04:00
|
|
|
mSSLStatus = new nsSSLStatus();
|
2015-02-27 22:33:36 +03:00
|
|
|
}
|
2012-04-30 08:00:22 +04:00
|
|
|
|
bug 1313491 - include more context when determining EV status r=Cykesiopka,jcj,mgoodwin
When doing TLS session resumption, the AuthCertificate hook is bypassed, which
means that the front-end doesn't know whether or not to show the EV indicator.
To deal with this, the platform attempts an EV verification. Before this patch,
this verification lacked much of the original context (e.g. stapled OCSP
responses, SCTs, the hostname, and in particular the first-party origin key).
Furthermore, it was unclear from a code architecture standpoint that a full
verification was even occurring. This patch brings the necessary context to the
verification and makes it much more clear that it is happening. It also takes
the opportunity to remove some unnecessary EV-related fields and information in
code and data structures that don't require it.
MozReview-Commit-ID: LTmZU4Z1YXL
--HG--
extra : rebase_source : 7db702f2037fae83c87fbb6aca75b4420544dff9
2016-11-01 03:02:57 +03:00
|
|
|
mSSLStatus->SetServerCert(cert, EVStatus::NotEV);
|
2012-04-30 08:00:22 +04:00
|
|
|
|
|
|
|
mSSLStatus->mHaveCertErrorBits = true;
|
2017-07-06 15:00:35 +03:00
|
|
|
mSSLStatus->mIsDomainMismatch =
|
2012-04-30 08:00:22 +04:00
|
|
|
collected_errors & nsICertOverrideService::ERROR_MISMATCH;
|
2017-07-06 15:00:35 +03:00
|
|
|
mSSLStatus->mIsNotValidAtThisTime =
|
2012-04-30 08:00:22 +04:00
|
|
|
collected_errors & nsICertOverrideService::ERROR_TIME;
|
2017-07-06 15:00:35 +03:00
|
|
|
mSSLStatus->mIsUntrusted =
|
2012-04-30 08:00:22 +04:00
|
|
|
collected_errors & nsICertOverrideService::ERROR_UNTRUSTED;
|
|
|
|
|
|
|
|
RememberCertErrorsTable::GetInstance().RememberCertHasError(this,
|
|
|
|
mSSLStatus,
|
|
|
|
SECFailure);
|
|
|
|
}
|
|
|
|
|
2014-08-15 22:27:22 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
TransportSecurityInfo::GetFailedCertChain(nsIX509CertList** _result)
|
|
|
|
{
|
2017-01-02 09:11:39 +03:00
|
|
|
MOZ_ASSERT(_result);
|
2014-08-15 22:27:22 +04:00
|
|
|
|
|
|
|
*_result = mFailedCertChain;
|
|
|
|
NS_IF_ADDREF(*_result);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2016-05-06 00:56:36 +03:00
|
|
|
TransportSecurityInfo::SetFailedCertChain(UniqueCERTCertList certList)
|
2014-08-15 22:27:22 +04:00
|
|
|
{
|
|
|
|
nsNSSShutDownPreventionLock lock;
|
|
|
|
if (isAlreadyShutDown()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsNSSCertList takes ownership of certList
|
2016-05-06 00:56:36 +03:00
|
|
|
mFailedCertChain = new nsNSSCertList(Move(certList), lock);
|
2014-08-15 22:27:22 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-04-30 08:00:22 +04:00
|
|
|
} } // namespace mozilla::psm
|