Bug 1781104 - replace error type booleans with error category in nsITransportSecurityInfo r=necko-reviewers,mixedpuppy,jschanck,mccr8

Differential Revision: https://phabricator.services.mozilla.com/D154561
This commit is contained in:
Dana Keeler 2022-08-26 18:48:38 +00:00
Родитель b4c45d4248
Коммит 56e7ae8648
18 изменённых файлов: 260 добавлений и 289 удалений

Просмотреть файл

@ -989,7 +989,7 @@ async function setTechnicalDetailsOnCertError(
let args = {
hostname: hostString,
};
if (failedCertInfo.isUntrusted) {
if (failedCertInfo.overridableErrorCategory == "trust-error") {
switch (failedCertInfo.errorCodeString) {
case "MOZILLA_PKIX_ERROR_MITM_DETECTED":
setL10NLabel("cert-error-mitm-intro");
@ -1033,7 +1033,7 @@ async function setTechnicalDetailsOnCertError(
setL10NLabel("cert-error-intro", args);
setL10NLabel("cert-error-untrusted-default", {}, {}, false);
}
} else if (failedCertInfo.isDomainMismatch) {
} else if (failedCertInfo.overridableErrorCategory == "domain-mismatch") {
let serverCertBase64 = failedCertInfo.certChainStrings[0];
let parsed = await parse(pemToDER(serverCertBase64));
let subjectAltNamesExtension = parsed.ext.san;
@ -1116,7 +1116,9 @@ async function setTechnicalDetailsOnCertError(
} else {
setL10NLabel("cert-error-domain-mismatch", { hostname: hostString });
}
} else if (failedCertInfo.isNotValidAtThisTime) {
} else if (
failedCertInfo.overridableErrorCategory == "expired-or-not-yet-valid"
) {
let notBefore = failedCertInfo.validNotBefore;
let notAfter = failedCertInfo.validNotAfter;
args = {

Просмотреть файл

@ -1735,22 +1735,28 @@ void Document::GetFailedCertSecurityInfo(FailedCertSecurityInfo& aInfo,
}
aInfo.mErrorCodeString.Assign(errorCodeString);
rv = tsi->GetIsUntrusted(&aInfo.mIsUntrusted);
nsITransportSecurityInfo::OverridableErrorCategory errorCategory;
rv = tsi->GetOverridableErrorCategory(&errorCategory);
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return;
}
rv = tsi->GetIsDomainMismatch(&aInfo.mIsDomainMismatch);
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return;
}
rv = tsi->GetIsNotValidAtThisTime(&aInfo.mIsNotValidAtThisTime);
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return;
switch (errorCategory) {
case nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TRUST:
aInfo.mOverridableErrorCategory =
dom::OverridableErrorCategory::Trust_error;
break;
case nsITransportSecurityInfo::OverridableErrorCategory::ERROR_DOMAIN:
aInfo.mOverridableErrorCategory =
dom::OverridableErrorCategory::Domain_mismatch;
break;
case nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TIME:
aInfo.mOverridableErrorCategory =
dom::OverridableErrorCategory::Expired_or_not_yet_valid;
break;
default:
aInfo.mOverridableErrorCategory = dom::OverridableErrorCategory::Unset;
break;
}
nsCOMPtr<nsIX509Cert> cert;

Просмотреть файл

@ -9,11 +9,16 @@
* to about:certerror to display information.
*/
enum OverridableErrorCategory {
"unset",
"trust-error",
"domain-mismatch",
"expired-or-not-yet-valid",
};
dictionary FailedCertSecurityInfo {
DOMString errorCodeString = "";
boolean isUntrusted = false;
boolean isDomainMismatch = false;
boolean isNotValidAtThisTime = false;
OverridableErrorCategory overridableErrorCategory = "unset";
DOMTimeStamp validNotBefore = 0;
DOMTimeStamp validNotAfter = 0;
DOMString issuerCommonName = "";

Просмотреть файл

@ -110,23 +110,10 @@ FuzzySecurityInfo::GetCertificateTransparencyStatus(
}
NS_IMETHODIMP
FuzzySecurityInfo::GetIsDomainMismatch(bool* aIsDomainMismatch) {
NS_ENSURE_ARG_POINTER(aIsDomainMismatch);
*aIsDomainMismatch = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetIsNotValidAtThisTime(bool* aIsNotValidAtThisTime) {
NS_ENSURE_ARG_POINTER(aIsNotValidAtThisTime);
*aIsNotValidAtThisTime = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetIsUntrusted(bool* aIsUntrusted) {
NS_ENSURE_ARG_POINTER(aIsUntrusted);
*aIsUntrusted = false;
FuzzySecurityInfo::GetOverridableErrorCategory(
OverridableErrorCategory* aOverridableErrorCode) {
NS_ENSURE_ARG_POINTER(aOverridableErrorCode);
*aOverridableErrorCode = OverridableErrorCategory::ERROR_UNSET;
return NS_OK;
}

Просмотреть файл

@ -73,9 +73,10 @@ void QuicSocketControl::HandshakeCompleted() {
MutexAutoLock lock(mMutex);
// If we're here, the TLS handshake has succeeded. Thus if any of these
// booleans are true, the user has added an override for a certificate error.
if (mIsDomainMismatch || mIsUntrusted || mIsNotValidAtThisTime) {
// If we're here, the TLS handshake has succeeded. If the overridable error
// category is nonzero, the user has added an override for a certificate
// error.
if (mOverridableErrorCategory != OverridableErrorCategory::ERROR_UNSET) {
state |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
}

Просмотреть файл

@ -20,6 +20,13 @@ class MessageReader;
[builtinclass, scriptable, uuid(216112d3-28bc-4671-b057-f98cc09ba1ea)]
interface nsITransportSecurityInfo : nsISupports {
cenum OverridableErrorCategory : 32 {
ERROR_UNSET,
ERROR_TRUST,
ERROR_DOMAIN,
ERROR_TIME,
};
readonly attribute unsigned long securityState;
readonly attribute long errorCode; // PRErrorCode
// errorCode as string (e.g. "SEC_ERROR_UNKNOWN_ISSUER")
@ -71,12 +78,7 @@ interface nsITransportSecurityInfo : nsISupports {
[must_use]
readonly attribute boolean isDelegatedCredential;
[must_use]
readonly attribute boolean isDomainMismatch;
[must_use]
readonly attribute boolean isNotValidAtThisTime;
[must_use]
readonly attribute boolean isUntrusted;
readonly attribute nsITransportSecurityInfo_OverridableErrorCategory overridableErrorCategory;
/**
* True only if (and after) serverCert was successfully validated as

Просмотреть файл

@ -198,10 +198,6 @@ function handleTextChange() {
function updateCertStatus() {
var shortDesc, longDesc;
var shortDesc2, longDesc2;
var shortDesc3, longDesc3;
var use2 = false;
var use3 = false;
let l10nUpdatedElements = [];
if (gCert) {
if (gBroken) {
@ -211,37 +207,24 @@ function updateCertStatus() {
var exl = "add-exception-expired-long";
var uts = "add-exception-unverified-or-bad-signature-short";
var utl = "add-exception-unverified-or-bad-signature-long";
var use1 = false;
if (gSecInfo.isDomainMismatch) {
use1 = true;
if (
gSecInfo.overridableErrorCategory ==
Ci.nsITransportSecurityInfo.ERROR_TRUST
) {
shortDesc = uts;
longDesc = utl;
} else if (
gSecInfo.overridableErrorCategory ==
Ci.nsITransportSecurityInfo.ERROR_DOMAIN
) {
shortDesc = mms;
longDesc = mml;
}
if (gSecInfo.isNotValidAtThisTime) {
if (!use1) {
use1 = true;
shortDesc = exs;
longDesc = exl;
} else {
use2 = true;
shortDesc2 = exs;
longDesc2 = exl;
}
}
if (gSecInfo.isUntrusted) {
if (!use1) {
use1 = true;
shortDesc = uts;
longDesc = utl;
} else if (!use2) {
use2 = true;
shortDesc2 = uts;
longDesc2 = utl;
} else {
use3 = true;
shortDesc3 = uts;
longDesc3 = utl;
}
} else if (
gSecInfo.overridableErrorCategory ==
Ci.nsITransportSecurityInfo.ERROR_TIME
) {
shortDesc = exs;
longDesc = exl;
}
// In these cases, we do want to enable the "Add Exception" button
gDialog.getButton("extra1").disabled = false;
@ -299,28 +282,6 @@ function updateCertStatus() {
l10nUpdatedElements.push(statusDescription);
l10nUpdatedElements.push(statusLongDescription);
if (use2) {
let status2Description = document.getElementById("status2Description");
let status2LongDescription = document.getElementById(
"status2LongDescription"
);
document.l10n.setAttributes(status2Description, shortDesc2);
document.l10n.setAttributes(status2LongDescription, longDesc2);
l10nUpdatedElements.push(status2Description);
l10nUpdatedElements.push(status2LongDescription);
}
if (use3) {
let status3Description = document.getElementById("status3Description");
let status3LongDescription = document.getElementById(
"status3LongDescription"
);
document.l10n.setAttributes(status3Description, shortDesc3);
document.l10n.setAttributes(status3LongDescription, longDesc3);
l10nUpdatedElements.push(status3Description);
l10nUpdatedElements.push(status3LongDescription);
}
gNeedReset = true;
return l10nUpdatedElements;
}

Просмотреть файл

@ -264,18 +264,11 @@ static uint32_t MapCertErrorToProbeValue(PRErrorCode errorCode) {
return probeValue;
}
enum class OverridableErrorCategory : uint32_t {
Unset = 0,
Trust = 1,
Domain = 2,
Time = 3,
};
// If the given PRErrorCode is an overridable certificate error, return which
// category (trust, time, domain mismatch) it falls in. If it is not
// overridable, return Nothing.
Maybe<OverridableErrorCategory> CategorizeCertificateError(
PRErrorCode certificateError) {
Maybe<nsITransportSecurityInfo::OverridableErrorCategory>
CategorizeCertificateError(PRErrorCode certificateError) {
switch (certificateError) {
case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
@ -289,15 +282,18 @@ Maybe<OverridableErrorCategory> CategorizeCertificateError(
case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE:
case mozilla::pkix::MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT:
case mozilla::pkix::MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA:
return Some(OverridableErrorCategory::Trust);
return Some(
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TRUST);
case SSL_ERROR_BAD_CERT_DOMAIN:
return Some(
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_DOMAIN);
case SEC_ERROR_INVALID_TIME:
case SEC_ERROR_EXPIRED_CERTIFICATE:
case mozilla::pkix::MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE:
return Some(OverridableErrorCategory::Time);
case SSL_ERROR_BAD_CERT_DOMAIN:
return Some(OverridableErrorCategory::Domain);
return Some(
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TIME);
default:
break;
@ -632,12 +628,15 @@ PRErrorCode AuthCertificateParseResults(
const OriginAttributes& aOriginAttributes,
const nsCOMPtr<nsIX509Cert>& aCert, mozilla::pkix::Time aTime,
PRErrorCode aCertVerificationError,
/* out */ OverridableErrorCategory& aOverridableErrorCategory) {
/* out */
nsITransportSecurityInfo::OverridableErrorCategory&
aOverridableErrorCategory) {
uint32_t probeValue = MapCertErrorToProbeValue(aCertVerificationError);
Telemetry::Accumulate(Telemetry::SSL_CERT_VERIFICATION_ERRORS, probeValue);
Maybe<OverridableErrorCategory> maybeOverridableErrorCategory =
CategorizeCertificateError(aCertVerificationError);
Maybe<nsITransportSecurityInfo::OverridableErrorCategory>
maybeOverridableErrorCategory =
CategorizeCertificateError(aCertVerificationError);
// If this isn't an overridable error, return it now. This will stop the
// connection and report the given error.
if (!maybeOverridableErrorCategory.isSome()) {
@ -780,7 +779,8 @@ SSLServerCertVerificationJob::Run() {
std::move(builtChainBytesArray), std::move(mPeerCertChain),
TransportSecurityInfo::ConvertCertificateTransparencyInfoToStatus(
certificateTransparencyInfo),
evStatus, true, 0, OverridableErrorCategory::Unset,
evStatus, true, 0,
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET,
isCertChainRootBuiltInRoot, mProviderFlags);
return NS_OK;
}
@ -790,8 +790,8 @@ SSLServerCertVerificationJob::Run() {
jobStartTime, TimeStamp::Now());
PRErrorCode error = MapResultToPRErrorCode(rv);
OverridableErrorCategory overridableErrorCategory =
OverridableErrorCategory::Unset;
nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory =
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET;
nsCOMPtr<nsIX509Cert> cert(new nsNSSCertificate(std::move(certBytes)));
PRErrorCode finalError = AuthCertificateParseResults(
mAddrForLogging, mHostName, mPort, mOriginAttributes, cert, mTime, error,
@ -1022,7 +1022,8 @@ SSLServerCertVerificationResult::SSLServerCertVerificationResult(
mEVStatus(EVStatus::NotEV),
mSucceeded(false),
mFinalError(0),
mOverridableErrorCategory(OverridableErrorCategory::Unset),
mOverridableErrorCategory(
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET),
mProviderFlags(0) {}
void SSLServerCertVerificationResult::Dispatch(
@ -1030,7 +1031,8 @@ void SSLServerCertVerificationResult::Dispatch(
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus,
bool aSucceeded, PRErrorCode aFinalError,
OverridableErrorCategory aOverridableErrorCategory,
nsITransportSecurityInfo::OverridableErrorCategory
aOverridableErrorCategory,
bool aIsBuiltCertChainRootBuiltInRoot, uint32_t aProviderFlags) {
mBuiltChain = std::move(aBuiltChain);
mPeerCertChain = std::move(aPeerCertChain);
@ -1106,7 +1108,8 @@ SSLServerCertVerificationResult::Run() {
// Certificate validation failed; store the peer certificate chain on
// infoObject so it can be used for error reporting.
mInfoObject->SetFailedCertChain(std::move(mPeerCertChain));
if (mOverridableErrorCategory != OverridableErrorCategory::Unset) {
if (mOverridableErrorCategory !=
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
mInfoObject->SetStatusErrorBits(cert, mOverridableErrorCategory);
}
}

Просмотреть файл

@ -10,6 +10,7 @@
#include "ScopedNSSTypes.h"
#include "mozilla/Maybe.h"
#include "mozpkix/pkix.h"
#include "nsITransportSecurityInfo.h"
#include "nsIX509Cert.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
@ -38,8 +39,6 @@ SECStatus AuthCertificateHookWithInfo(
Maybe<nsTArray<nsTArray<uint8_t>>>& stapledOCSPResponses,
Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension, uint32_t providerFlags);
enum class OverridableErrorCategory : uint32_t;
// Base class for dispatching the certificate verification result.
class BaseSSLServerCertVerificationResult {
public:
@ -50,7 +49,8 @@ class BaseSSLServerCertVerificationResult {
uint16_t aCertificateTransparencyStatus,
EVStatus aEVStatus, bool aSucceeded,
PRErrorCode aFinalError,
OverridableErrorCategory aOverridableErrorCategory,
nsITransportSecurityInfo::OverridableErrorCategory
aOverridableErrorCategory,
bool aIsBuiltCertChainRootBuiltInRoot,
uint32_t aProviderFlags) = 0;
};
@ -74,7 +74,8 @@ class SSLServerCertVerificationResult final
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus,
bool aSucceeded, PRErrorCode aFinalError,
OverridableErrorCategory aOverridableErrorCategory,
nsITransportSecurityInfo::OverridableErrorCategory
aOverridableErrorCategory,
bool aIsBuiltCertChainRootBuiltInRoot,
uint32_t aProviderFlags) override;
@ -88,7 +89,7 @@ class SSLServerCertVerificationResult final
EVStatus mEVStatus;
bool mSucceeded;
PRErrorCode mFinalError;
OverridableErrorCategory mOverridableErrorCategory;
nsITransportSecurityInfo::OverridableErrorCategory mOverridableErrorCategory;
bool mIsBuiltCertChainRootBuiltInRoot;
uint32_t mProviderFlags;
};

Просмотреть файл

@ -39,9 +39,7 @@ namespace mozilla {
namespace psm {
TransportSecurityInfo::TransportSecurityInfo()
: mIsDomainMismatch(false),
mIsNotValidAtThisTime(false),
mIsUntrusted(false),
: mOverridableErrorCategory(OverridableErrorCategory::ERROR_UNSET),
mIsEV(false),
mHasIsEVStatus(false),
mHaveCipherSuiteAndProtocol(false),
@ -207,7 +205,7 @@ TransportSecurityInfo::Write(nsIObjectOutputStream* aStream) {
// Re-purpose mErrorMessageCached to represent serialization version
// If string doesn't match exact version it will be treated as older
// serialization.
rv = aStream->WriteWStringZ(NS_ConvertUTF8toUTF16("7").get());
rv = aStream->WriteWStringZ(NS_ConvertUTF8toUTF16("8").get());
if (NS_FAILED(rv)) {
return rv;
}
@ -223,11 +221,7 @@ TransportSecurityInfo::Write(nsIObjectOutputStream* aStream) {
rv = aStream->Write16(mProtocolVersion);
NS_ENSURE_SUCCESS(rv, rv);
rv = aStream->WriteBoolean(mIsDomainMismatch);
NS_ENSURE_SUCCESS(rv, rv);
rv = aStream->WriteBoolean(mIsNotValidAtThisTime);
NS_ENSURE_SUCCESS(rv, rv);
rv = aStream->WriteBoolean(mIsUntrusted);
rv = aStream->Write32(mOverridableErrorCategory);
NS_ENSURE_SUCCESS(rv, rv);
rv = aStream->WriteBoolean(mIsEV);
NS_ENSURE_SUCCESS(rv, rv);
@ -306,6 +300,39 @@ TransportSecurityInfo::Write(nsIObjectOutputStream* aStream) {
MOZ_DIAGNOSTIC_ASSERT(condition, message); \
}
nsresult TransportSecurityInfo::ReadOldOverridableErrorBits(
nsIObjectInputStream* aStream, MutexAutoLock& aProofOfLock) {
mMutex.AssertCurrentThreadOwns();
bool isDomainMismatch;
nsresult rv = aStream->ReadBoolean(&isDomainMismatch);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv), "Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
bool isNotValidAtThisTime;
rv = aStream->ReadBoolean(&isNotValidAtThisTime);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv), "Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
bool isUntrusted;
rv = aStream->ReadBoolean(&isUntrusted);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv), "Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
if (isUntrusted) {
mOverridableErrorCategory =
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TRUST;
} else if (isDomainMismatch) {
mOverridableErrorCategory =
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_DOMAIN;
} else if (isNotValidAtThisTime) {
mOverridableErrorCategory =
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TIME;
} else {
mOverridableErrorCategory =
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET;
}
return NS_OK;
}
// This is for backward compatibility to be able to read nsISSLStatus
// serialized object.
nsresult TransportSecurityInfo::ReadSSLStatus(nsIObjectInputStream* aStream,
@ -371,14 +398,7 @@ nsresult TransportSecurityInfo::ReadSSLStatus(nsIObjectInputStream* aStream,
const uint8_t streamFormatVersion =
(protocolVersionAndStreamFormatVersion >> 8) & 0xFF;
rv = ReadBoolAndSetAtomicFieldHelper(aStream, mIsDomainMismatch);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv), "Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
rv = ReadBoolAndSetAtomicFieldHelper(aStream, mIsNotValidAtThisTime);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv), "Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
rv = ReadBoolAndSetAtomicFieldHelper(aStream, mIsUntrusted);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv), "Deserialization should not fail");
rv = ReadOldOverridableErrorBits(aStream, aProofOfLock);
NS_ENSURE_SUCCESS(rv, rv);
rv = ReadBoolAndSetAtomicFieldHelper(aStream, mIsEV);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv), "Deserialization should not fail");
@ -500,6 +520,24 @@ nsresult TransportSecurityInfo::ReadCertificatesFromStream(
return NS_OK;
}
static nsITransportSecurityInfo::OverridableErrorCategory
IntToOverridableErrorCategory(uint32_t intVal) {
switch (intVal) {
case static_cast<uint32_t>(
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TRUST):
return nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TRUST;
case static_cast<uint32_t>(
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_DOMAIN):
return nsITransportSecurityInfo::OverridableErrorCategory::ERROR_DOMAIN;
case static_cast<uint32_t>(
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TIME):
return nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TIME;
default:
break;
}
return nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET;
}
// NB: Any updates (except disk-only fields) must be kept in sync with
// |DeserializeFromIPC|.
NS_IMETHODIMP
@ -607,18 +645,18 @@ TransportSecurityInfo::Read(nsIObjectInputStream* aStream) {
"Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
rv = ReadBoolAndSetAtomicFieldHelper(aStream, mIsDomainMismatch);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
"Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
rv = ReadBoolAndSetAtomicFieldHelper(aStream, mIsNotValidAtThisTime);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
"Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
rv = ReadBoolAndSetAtomicFieldHelper(aStream, mIsUntrusted);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
"Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
if (serVersionParsedToInt < 8) {
rv = ReadOldOverridableErrorBits(aStream, lock);
NS_ENSURE_SUCCESS(rv, rv);
} else {
uint32_t overridableErrorCategory;
rv = aStream->Read32(&overridableErrorCategory);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
"Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
mOverridableErrorCategory =
IntToOverridableErrorCategory(overridableErrorCategory);
}
rv = ReadBoolAndSetAtomicFieldHelper(aStream, mIsEV);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
"Deserialization should not fail");
@ -767,9 +805,7 @@ void TransportSecurityInfo::SerializeToIPC(IPC::MessageWriter* aWriter) {
WriteParam(aWriter, mServerCert);
WriteParam(aWriter, mCipherSuite);
WriteParam(aWriter, mProtocolVersion);
WriteParam(aWriter, static_cast<bool>(mIsDomainMismatch));
WriteParam(aWriter, static_cast<bool>(mIsNotValidAtThisTime));
WriteParam(aWriter, static_cast<bool>(mIsUntrusted));
WriteParam(aWriter, static_cast<uint32_t>(mOverridableErrorCategory));
WriteParam(aWriter, static_cast<bool>(mIsEV));
WriteParam(aWriter, static_cast<bool>(mHasIsEVStatus));
WriteParam(aWriter, static_cast<bool>(mHaveCipherSuiteAndProtocol));
@ -792,14 +828,13 @@ bool TransportSecurityInfo::DeserializeFromIPC(IPC::MessageReader* aReader) {
MutexAutoLock guard(mMutex);
int32_t errorCode = 0;
uint32_t overridableErrorCategory;
if (!ReadParamAtomicHelper(aReader, mSecurityState) ||
!ReadParam(aReader, &errorCode) || !ReadParam(aReader, &mServerCert) ||
!ReadParam(aReader, &mCipherSuite) ||
!ReadParam(aReader, &mProtocolVersion) ||
!ReadParamAtomicHelper(aReader, mIsDomainMismatch) ||
!ReadParamAtomicHelper(aReader, mIsNotValidAtThisTime) ||
!ReadParamAtomicHelper(aReader, mIsUntrusted) ||
!ReadParam(aReader, &overridableErrorCategory) ||
!ReadParamAtomicHelper(aReader, mIsEV) ||
!ReadParamAtomicHelper(aReader, mHasIsEVStatus) ||
!ReadParamAtomicHelper(aReader, mHaveCipherSuiteAndProtocol) ||
@ -821,6 +856,8 @@ bool TransportSecurityInfo::DeserializeFromIPC(IPC::MessageReader* aReader) {
if (mErrorCode != 0) {
mCanceled = true;
}
mOverridableErrorCategory =
IntToOverridableErrorCategory(overridableErrorCategory);
return true;
}
@ -908,13 +945,9 @@ void RememberCertErrorsTable::RememberCertHasError(
return;
}
CertStateBits bits;
bits.mIsDomainMismatch = infoObject->mIsDomainMismatch;
bits.mIsNotValidAtThisTime = infoObject->mIsNotValidAtThisTime;
bits.mIsUntrusted = infoObject->mIsUntrusted;
MutexAutoLock lock(mMutex);
mErrorHosts.InsertOrUpdate(hostPortKey, bits);
mErrorHosts.InsertOrUpdate(hostPortKey,
infoObject->mOverridableErrorCategory);
} else {
MutexAutoLock lock(mMutex);
mErrorHosts.Remove(hostPortKey);
@ -938,10 +971,10 @@ void RememberCertErrorsTable::LookupCertErrorBits(
return;
}
CertStateBits bits;
nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory;
{
MutexAutoLock lock(mMutex);
if (!mErrorHosts.Get(hostPortKey, &bits)) {
if (!mErrorHosts.Get(hostPortKey, &overridableErrorCategory)) {
// No record was found, this host had no cert errors
return;
}
@ -949,9 +982,7 @@ void RememberCertErrorsTable::LookupCertErrorBits(
// This host had cert errors, update the bits correctly
infoObject->mHaveCertErrorBits = true;
infoObject->mIsDomainMismatch = bits.mIsDomainMismatch;
infoObject->mIsNotValidAtThisTime = bits.mIsNotValidAtThisTime;
infoObject->mIsUntrusted = bits.mIsUntrusted;
infoObject->mOverridableErrorCategory = overridableErrorCategory;
}
void TransportSecurityInfo::SetStatusErrorBits(
@ -960,19 +991,7 @@ void TransportSecurityInfo::SetStatusErrorBits(
SetServerCert(cert, EVStatus::NotEV);
mHaveCertErrorBits = true;
switch (overridableErrorCategory) {
case OverridableErrorCategory::Trust:
mIsUntrusted = true;
break;
case OverridableErrorCategory::Time:
mIsNotValidAtThisTime = true;
break;
case OverridableErrorCategory::Domain:
mIsDomainMismatch = true;
break;
default:
break;
}
mOverridableErrorCategory = overridableErrorCategory;
RememberCertErrorsTable::GetInstance().RememberCertHasError(this, SECFailure);
}
@ -1189,23 +1208,14 @@ uint16_t TransportSecurityInfo::ConvertCertificateTransparencyInfoToStatus(
}
NS_IMETHODIMP
TransportSecurityInfo::GetIsDomainMismatch(bool* aIsDomainMismatch) {
NS_ENSURE_ARG_POINTER(aIsDomainMismatch);
*aIsDomainMismatch = mHaveCertErrorBits && mIsDomainMismatch;
return NS_OK;
}
NS_IMETHODIMP
TransportSecurityInfo::GetIsNotValidAtThisTime(bool* aIsNotValidAtThisTime) {
NS_ENSURE_ARG_POINTER(aIsNotValidAtThisTime);
*aIsNotValidAtThisTime = mHaveCertErrorBits && mIsNotValidAtThisTime;
return NS_OK;
}
NS_IMETHODIMP
TransportSecurityInfo::GetIsUntrusted(bool* aIsUntrusted) {
NS_ENSURE_ARG_POINTER(aIsUntrusted);
*aIsUntrusted = mHaveCertErrorBits && mIsUntrusted;
TransportSecurityInfo::GetOverridableErrorCategory(
OverridableErrorCategory* aOverridableErrorCategory) {
NS_ENSURE_ARG_POINTER(aOverridableErrorCategory);
if (mHaveCertErrorBits) {
*aOverridableErrorCategory = mOverridableErrorCategory;
} else {
*aOverridableErrorCategory = OverridableErrorCategory::ERROR_UNSET;
}
return NS_OK;
}

Просмотреть файл

@ -27,8 +27,6 @@
namespace mozilla {
namespace psm {
enum class OverridableErrorCategory : uint32_t;
class TransportSecurityInfo : public nsITransportSecurityInfo,
public nsIInterfaceRequestor,
public nsISerializable,
@ -109,12 +107,10 @@ class TransportSecurityInfo : public nsITransportSecurityInfo,
void SetResumed(bool aResumed);
Atomic<bool> mIsDomainMismatch;
Atomic<bool> mIsNotValidAtThisTime;
Atomic<bool> mIsUntrusted;
Atomic<OverridableErrorCategory> mOverridableErrorCategory;
Atomic<bool> mIsEV;
Atomic<bool> mHasIsEVStatus;
Atomic<bool> mHaveCipherSuiteAndProtocol;
/* mHaveCertErrrorBits is relied on to determine whether or not a SPDY
@ -195,6 +191,8 @@ class TransportSecurityInfo : public nsITransportSecurityInfo,
/* Peer cert chain for failed connections (for error reporting) */
nsTArray<RefPtr<nsIX509Cert>> mFailedCertChain MOZ_GUARDED_BY(mMutex);
nsresult ReadOldOverridableErrorBits(nsIObjectInputStream* aStream,
MutexAutoLock& aProofOfLock);
nsresult ReadSSLStatus(nsIObjectInputStream* aStream,
MutexAutoLock& aProofOfLock);
@ -213,13 +211,9 @@ class RememberCertErrorsTable {
private:
RememberCertErrorsTable();
struct CertStateBits {
bool mIsDomainMismatch;
bool mIsNotValidAtThisTime;
bool mIsUntrusted;
};
nsTHashMap<nsCStringHashKey, CertStateBits> mErrorHosts
MOZ_GUARDED_BY(mMutex);
nsTHashMap<nsCStringHashKey,
nsITransportSecurityInfo::OverridableErrorCategory>
mErrorHosts MOZ_GUARDED_BY(mMutex);
public:
void RememberCertHasError(TransportSecurityInfo* infoObject,

Просмотреть файл

@ -38,11 +38,11 @@ ipc::IPCResult VerifySSLServerCertChild::RecvOnVerifiedSSLServerCertSuccess(
certBytesArray.AppendElement(std::move(cert.data()));
}
mResultTask->Dispatch(std::move(certBytesArray), std::move(mPeerCertChain),
aCertTransparencyStatus,
static_cast<EVStatus>(aEVStatus), true, 0,
OverridableErrorCategory::Unset,
aIsBuiltCertChainRootBuiltInRoot, mProviderFlags);
mResultTask->Dispatch(
std::move(certBytesArray), std::move(mPeerCertChain),
aCertTransparencyStatus, static_cast<EVStatus>(aEVStatus), true, 0,
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET,
aIsBuiltCertChainRootBuiltInRoot, mProviderFlags);
return IPC_OK();
}
@ -52,8 +52,9 @@ ipc::IPCResult VerifySSLServerCertChild::RecvOnVerifiedSSLServerCertFailure(
nsTArray<nsTArray<uint8_t>>(), std::move(mPeerCertChain),
nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE,
EVStatus::NotEV, false, aFinalError,
static_cast<OverridableErrorCategory>(aOverridableErrorCategory), false,
mProviderFlags);
static_cast<nsITransportSecurityInfo::OverridableErrorCategory>(
aOverridableErrorCategory),
false, mProviderFlags);
return IPC_OK();
}

Просмотреть файл

@ -66,7 +66,8 @@ class IPCServerCertVerificationResult final
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus,
bool aSucceeded, PRErrorCode aFinalError,
OverridableErrorCategory aOverridableErrorCategory,
nsITransportSecurityInfo::OverridableErrorCategory
aOverridableErrorCategory,
bool aIsBuiltCertChainRootBuiltInRoot,
uint32_t aProviderFlags) override;
@ -82,7 +83,8 @@ void IPCServerCertVerificationResult::Dispatch(
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus,
bool aSucceeded, PRErrorCode aFinalError,
OverridableErrorCategory aOverridableErrorCategory,
nsITransportSecurityInfo::OverridableErrorCategory
aOverridableErrorCategory,
bool aIsBuiltCertChainRootBuiltInRoot, uint32_t aProviderFlags) {
nsTArray<ByteArray> builtCertChain;
if (aSucceeded) {

Просмотреть файл

@ -1272,16 +1272,13 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
}
}
bool domainMismatch;
bool untrusted;
bool notValidAtThisTime;
// These all return NS_OK, so don't even bother checking the return values.
Unused << infoObject->GetIsDomainMismatch(&domainMismatch);
Unused << infoObject->GetIsUntrusted(&untrusted);
Unused << infoObject->GetIsNotValidAtThisTime(&notValidAtThisTime);
nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory;
// This returns NS_OK, so don't even bother checking the return value.
Unused << infoObject->GetOverridableErrorCategory(&overridableErrorCategory);
// If we're here, the TLS handshake has succeeded. Thus if any of these
// booleans are true, the user has added an override for a certificate error.
if (domainMismatch || untrusted || notValidAtThisTime) {
if (overridableErrorCategory !=
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
state |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
}

Просмотреть файл

@ -454,21 +454,12 @@ nsresult nsSiteSecurityService::ProcessHeaderInternal(
}
if (aSecInfo) {
bool tlsIsBroken = false;
bool trustcheck;
nsresult rv;
rv = aSecInfo->GetIsDomainMismatch(&trustcheck);
nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory;
nsresult rv =
aSecInfo->GetOverridableErrorCategory(&overridableErrorCategory);
NS_ENSURE_SUCCESS(rv, rv);
tlsIsBroken = tlsIsBroken || trustcheck;
rv = aSecInfo->GetIsNotValidAtThisTime(&trustcheck);
NS_ENSURE_SUCCESS(rv, rv);
tlsIsBroken = tlsIsBroken || trustcheck;
rv = aSecInfo->GetIsUntrusted(&trustcheck);
NS_ENSURE_SUCCESS(rv, rv);
tlsIsBroken = tlsIsBroken || trustcheck;
if (tlsIsBroken) {
if (overridableErrorCategory !=
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
SSSLOG(("SSS: discarding header from untrustworthy connection"));
if (aFailureResult) {
*aFailureResult =

Просмотреть файл

@ -51,17 +51,10 @@ function add_resume_non_ev_with_override_test() {
0,
"ev-test.example.com should not have succeededCertChain set"
);
ok(
!transportSecurityInfo.isDomainMismatch,
"expired.example.com should not have isDomainMismatch set"
);
ok(
transportSecurityInfo.isNotValidAtThisTime,
"expired.example.com should have isNotValidAtThisTime set"
);
ok(
!transportSecurityInfo.isUntrusted,
"expired.example.com should not have isUntrusted set"
equal(
transportSecurityInfo.overridableErrorCategory,
Ci.nsITransportSecurityInfo.ERROR_TIME,
"expired.example.com should have time overridable error category"
);
ok(
!transportSecurityInfo.isExtendedValidation,
@ -101,17 +94,10 @@ function add_one_ev_test() {
transportSecurityInfo.succeededCertChain,
"ev-test.example.com should have succeededCertChain set"
);
ok(
!transportSecurityInfo.isDomainMismatch,
"ev-test.example.com should not have isDomainMismatch set"
);
ok(
!transportSecurityInfo.isNotValidAtThisTime,
"ev-test.example.com should not have isNotValidAtThisTime set"
);
ok(
!transportSecurityInfo.isUntrusted,
"ev-test.example.com should not have isUntrusted set"
equal(
transportSecurityInfo.overridableErrorCategory,
Ci.nsITransportSecurityInfo.ERROR_UNSET,
"ev-test.example.com should not have an overridable error category"
);
ok(
!gEVExpected || transportSecurityInfo.isExtendedValidation,
@ -181,17 +167,10 @@ function add_one_non_ev_test() {
transportSecurityInfo.succeededCertChain,
`${GOOD_DOMAIN} should have succeededCertChain set`
);
ok(
!transportSecurityInfo.isDomainMismatch,
`${GOOD_DOMAIN} should not have isDomainMismatch set`
);
ok(
!transportSecurityInfo.isNotValidAtThisTime,
`${GOOD_DOMAIN} should not have isNotValidAtThisTime set`
);
ok(
!transportSecurityInfo.isUntrusted,
`${GOOD_DOMAIN} should not have isUntrusted set`
equal(
transportSecurityInfo.overridableErrorCategory,
0,
`${GOOD_DOMAIN} should not have an overridable error category set`
);
ok(
!transportSecurityInfo.isExtendedValidation,

Просмотреть файл

@ -290,21 +290,34 @@
"type": "array",
"items": { "$ref": "CertificateInfo" }
},
"overridableErrorCategory": {
"description": "The type of certificate error that was overridden for this connection, if any.",
"type": "string",
"enum": [
"trust_error",
"domain_mismatch",
"expired_or_not_yet_valid"
],
"optional": true
},
"isDomainMismatch": {
"description": "The domain name does not match the certificate domain.",
"type": "boolean",
"optional": true
},
"isExtendedValidation": {
"type": "boolean",
"optional": true
"optional": true,
"deprecated": "Please use $(ref:SecurityInfo.overridableErrorCategory)."
},
"isNotValidAtThisTime": {
"description": "The certificate is either expired or is not yet valid. See <code>CertificateInfo.validity</code> for start and end dates.",
"type": "boolean",
"optional": true
"optional": true,
"deprecated": "Please use $(ref:SecurityInfo.overridableErrorCategory)."
},
"isUntrusted": {
"type": "boolean",
"optional": true,
"deprecated": "Please use $(ref:SecurityInfo.overridableErrorCategory)."
},
"isExtendedValidation": {
"type": "boolean",
"optional": true
},

Просмотреть файл

@ -162,10 +162,26 @@ const SecurityInfo = {
info.signatureSchemeName = securityInfo.signatureSchemeName;
}
info.isDomainMismatch = securityInfo.isDomainMismatch;
if (
securityInfo.overridableErrorCategory ==
Ci.nsITransportSecurityInfo.ERROR_TRUST
) {
info.overridableErrorCategory = "trust_error";
info.isUntrusted = true;
} else if (
securityInfo.overridableErrorCategory ==
Ci.nsITransportSecurityInfo.ERROR_DOMAIN
) {
info.overridableErrorCategory = "domain_mismatch";
info.isDomainMismatch = true;
} else if (
securityInfo.overridableErrorCategory ==
Ci.nsITransportSecurityInfo.ERROR_TIME
) {
info.overridableErrorCategory = "expired_or_not_yet_valid";
info.isNotValidAtThisTime = true;
}
info.isExtendedValidation = securityInfo.isExtendedValidation;
info.isNotValidAtThisTime = securityInfo.isNotValidAtThisTime;
info.isUntrusted = securityInfo.isUntrusted;
info.certificateTransparencyStatus = this.getTransparencyStatus(
securityInfo.certificateTransparencyStatus