Bug 1485652 - Reimplement IsAcceptableForHost r=keeler

Differential Revision: https://phabricator.services.mozilla.com/D67949
This commit is contained in:
Kershaw Chang 2020-04-24 14:45:56 +00:00
Родитель 88e6dd92b0
Коммит b0ac2c6c92
20 изменённых файлов: 234 добавлений и 85 удалений

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

@ -335,5 +335,16 @@ FuzzySecurityInfo::GetPeerId(nsACString& aResult) {
return NS_OK;
}
NS_IMETHODIMP FuzzySecurityInfo::SetIsBuiltCertChainRootBuiltInRoot(
bool aIsBuiltInRoot) {
return NS_OK;
}
NS_IMETHODIMP FuzzySecurityInfo::GetIsBuiltCertChainRootBuiltInRoot(
bool* aIsBuiltInRoot) {
*aIsBuiltInRoot = false;
return NS_OK;
}
} // namespace net
} // namespace mozilla

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

@ -154,6 +154,7 @@ nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
return rv;
}
Maybe<bool> isBuiltCertChainRootBuiltInRoot;
if (!succeededCertArray.IsEmpty()) {
succeededCertChainBytes.emplace();
for (const auto& cert : succeededCertArray) {
@ -164,6 +165,13 @@ nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
}
succeededCertChainBytes->AppendElement(std::move(rawCert));
}
bool builtInRoot = false;
rv = aSecInfo->GetIsBuiltCertChainRootBuiltInRoot(&builtInRoot);
if (NS_FAILED(rv)) {
return rv;
}
isBuiltCertChainRootBuiltInRoot.emplace(builtInRoot);
}
bool isEV;
@ -207,6 +215,9 @@ nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
rec->mSessionCacheInfo.mCertificateTransparencyStatus =
certificateTransparencyStatus;
rec->mSessionCacheInfo.mIsBuiltCertChainRootBuiltInRoot =
std::move(isBuiltCertChainRootBuiltInRoot);
gInstance->mCacheSize += rec->Size();
gInstance->LogStats();

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

@ -23,6 +23,7 @@ struct SessionCacheInfo {
nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE;
nsTArray<uint8_t> mServerCertBytes;
Maybe<nsTArray<nsTArray<uint8_t>>> mSucceededCertChainBytes;
Maybe<bool> mIsBuiltCertChainRootBuiltInRoot;
};
class SSLTokensCache : public nsIMemoryReporter {

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

@ -244,6 +244,8 @@ static const char* gCallbackSecurityPrefs[] = {
"security.ssl.enable_ocsp_stapling",
"security.ssl.enable_ocsp_must_staple",
"security.pki.certificate_transparency.mode",
"security.cert_pinning.enforcement_level",
"security.pki.name_matching_mode",
nullptr,
};
@ -325,7 +327,9 @@ void nsIOService::OnTLSPrefChange(const char* aPref, void* aSelf) {
LOG(("HandleTLSPrefChange done"));
} else if (pref.EqualsLiteral("security.ssl.enable_ocsp_stapling") ||
pref.EqualsLiteral("security.ssl.enable_ocsp_must_staple") ||
pref.EqualsLiteral("security.pki.certificate_transparency.mode")) {
pref.EqualsLiteral("security.pki.certificate_transparency.mode") ||
pref.EqualsLiteral("security.cert_pinning.enforcement_level") ||
pref.EqualsLiteral("security.pki.name_matching_mode")) {
SetValidationOptionsCommon();
}
nsNSSComponent::ClearSSLExternalAndInternalSessionCacheNative();

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

@ -104,4 +104,9 @@ interface nsITransportSecurityInfo : nsISupports {
* True iff the connection was resumed using the resumption token.
*/
readonly attribute boolean resumed;
/**
* True iff the succeededCertChain is built in root.
*/
attribute boolean isBuiltCertChainRootBuiltInRoot;
};

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

@ -903,13 +903,18 @@ Result CertVerifier::VerifySSLServerCert(
/*optional out*/ SHA1ModeResult* sha1ModeResult,
/*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo,
/*optional out*/ CertificateTransparencyInfo* ctInfo,
/*optional out*/ CRLiteTelemetryInfo* crliteInfo) {
/*optional out*/ CRLiteTelemetryInfo* crliteInfo,
/*optional out*/ bool* isBuiltCertChainRootBuiltInRoot) {
MOZ_ASSERT(peerCert);
// XXX: MOZ_ASSERT(pinarg);
MOZ_ASSERT(!hostname.IsEmpty());
SECOidTag evPolicyOidTag = SEC_OID_UNKNOWN;
if (isBuiltCertChainRootBuiltInRoot) {
*isBuiltCertChainRootBuiltInRoot = false;
}
if (evOidPolicy) {
*evOidPolicy = evPolicyOidTag;
}
@ -998,6 +1003,11 @@ Result CertVerifier::VerifySSLServerCert(
if (rv != Success) {
return rv;
}
if (isBuiltCertChainRootBuiltInRoot) {
*isBuiltCertChainRootBuiltInRoot = isBuiltInRoot;
}
BRNameMatchingPolicy nameMatchingPolicy(
isBuiltInRoot ? mNameMatchingMode
: BRNameMatchingPolicy::Mode::DoNotEnforce);

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

@ -227,7 +227,8 @@ class CertVerifier {
/*optional out*/ SHA1ModeResult* sha1ModeResult = nullptr,
/*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo = nullptr,
/*optional out*/ CertificateTransparencyInfo* ctInfo = nullptr,
/*optional out*/ CRLiteTelemetryInfo* crliteInfo = nullptr);
/*optional out*/ CRLiteTelemetryInfo* crliteInfo = nullptr,
/*optional out*/ bool* isBuiltCertChainRootBuiltInRoot = nullptr);
enum PinningMode {
pinningDisabled = 0,

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

@ -5,8 +5,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CommonSocketControl.h"
#include "BRNameMatchingPolicy.h"
#include "PublicKeyPinningService.h"
#include "SharedCertVerifier.h"
#include "nsNSSComponent.h"
#include "SharedSSLState.h"
#include "sslt.h"
#include "ssl.h"
@ -139,36 +143,58 @@ CommonSocketControl::IsAcceptableForHost(const nsACString& hostname,
return NS_OK;
}
// Attempt to verify the joinee's certificate using the joining hostname.
// This ensures that any hostname-specific verification logic (e.g. key
// pinning) is satisfied by the joinee's certificate chain.
// This verification only uses local information; since we're on the network
// thread, we would be blocking on ourselves if we attempted any network i/o.
// TODO(bug 1056935): The certificate chain built by this verification may be
// different than the certificate chain originally built during the joined
// connection's TLS handshake. Consequently, we may report a wrong and/or
// misleading certificate chain for HTTP transactions coalesced onto this
// connection. This may become problematic in the future. For example,
// if/when we begin relying on intermediate certificates being stored in the
// securityInfo of a cached HTTPS response, that cached certificate chain may
// actually be the wrong chain. We should consider having JoinConnection
// return the certificate chain built here, so that the calling Necko code
// can associate the correct certificate chain with the HTTP transactions it
// is trying to join onto this connection.
RefPtr<psm::SharedCertVerifier> certVerifier(psm::GetDefaultCertVerifier());
if (!certVerifier) {
// An empty mSucceededCertChain means the server certificate verification
// failed before, so don't join in this case.
if (mSucceededCertChain.IsEmpty()) {
return NS_OK;
}
psm::CertVerifier::Flags flags = psm::CertVerifier::FLAG_LOCAL_ONLY;
UniqueCERTCertList unusedBuiltChain;
mozilla::pkix::Result result =
certVerifier->VerifySSLServerCert(nssCert, mozilla::pkix::Now(),
nullptr, // pinarg
hostname, unusedBuiltChain, flags);
if (result != mozilla::pkix::Success) {
// See where CheckCertHostname() is called in
// CertVerifier::VerifySSLServerCert. We are doing the same hostname-specific
// checks here. If any hostname-specific checks are added to
// CertVerifier::VerifySSLServerCert we need to add them here too.
Input serverCertInput;
mozilla::pkix::Result rv =
serverCertInput.Init(nssCert->derCert.data, nssCert->derCert.len);
if (rv != Success) {
return NS_OK;
}
Input hostnameInput;
rv = hostnameInput.Init(
BitwiseCast<const uint8_t*, const char*>(hostname.BeginReading()),
hostname.Length());
if (rv != Success) {
return NS_OK;
}
mozilla::psm::BRNameMatchingPolicy nameMatchingPolicy(
mIsBuiltCertChainRootBuiltInRoot
? mozilla::psm::PublicSSLState()->NameMatchingMode()
: mozilla::psm::BRNameMatchingPolicy::Mode::DoNotEnforce);
rv = CheckCertHostname(serverCertInput, hostnameInput, nameMatchingPolicy);
if (rv != Success) {
return NS_OK;
}
mozilla::psm::CertVerifier::PinningMode pinningMode =
mozilla::psm::PublicSSLState()->PinningMode();
if (pinningMode != mozilla::psm::CertVerifier::pinningDisabled) {
bool chainHasValidPins;
bool enforceTestMode =
(pinningMode == mozilla::psm::CertVerifier::pinningEnforceTestMode);
nsresult nsrv = mozilla::psm::PublicKeyPinningService::ChainHasValidPins(
mSucceededCertChain, PromiseFlatCString(hostname).BeginReading(), Now(),
enforceTestMode, GetOriginAttributes(), chainHasValidPins, nullptr);
if (NS_FAILED(nsrv)) {
return NS_OK;
}
if (!chainHasValidPins) {
return NS_OK;
}
}
// All tests pass
*_retval = true;
return NS_OK;

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

@ -18,7 +18,8 @@ refcounted protocol PVerifySSLServerCert
child:
async OnVerifiedSSLServerCertSuccess(ByteArray[] aBuiltCertChain,
uint16_t aCertTransparencyStatus,
uint8_t aEVStatus);
uint8_t aEVStatus,
bool isBuiltCertChainRootBuiltInRoot);
async OnVerifiedSSLServerCertFailure(uint32_t aFinalError,
uint32_t aCollectedErrors);

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

@ -1043,7 +1043,7 @@ static void AuthCertificateSetResults(
nsTArray<nsTArray<uint8_t>>&& aBuiltCertChain,
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
uint16_t aCertificateTransparencyStatus, EVStatus aEvStatus,
bool aSucceeded) {
bool aSucceeded, bool aIsCertChainRootBuiltInRoot) {
MOZ_ASSERT(aInfoObject);
if (aSucceeded) {
@ -1057,6 +1057,8 @@ static void AuthCertificateSetResults(
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("AuthCertificate setting NEW cert %p", aCert));
aInfoObject->SetIsBuiltCertChainRootBuiltInRoot(
aIsCertChainRootBuiltInRoot);
aInfoObject->SetCertificateTransparencyStatus(
aCertificateTransparencyStatus);
} else {
@ -1078,7 +1080,8 @@ Result AuthCertificate(
Time time, uint32_t certVerifierFlags,
/*out*/ UniqueCERTCertList& builtCertChain,
/*out*/ SECOidTag& evOidPolicy,
/*out*/ CertificateTransparencyInfo& certificateTransparencyInfo) {
/*out*/ CertificateTransparencyInfo& certificateTransparencyInfo,
/*out*/ bool& aIsCertChainRootBuiltInRoot) {
MOZ_ASSERT(cert);
// We want to avoid storing any intermediate cert information when browsing
@ -1105,7 +1108,8 @@ Result AuthCertificate(
Some(peerCertsBytes), stapledOCSPResponse, sctsFromTLSExtension, dcInfo,
aOriginAttributes, saveIntermediates, &evOidPolicy, &ocspStaplingStatus,
&keySizeStatus, &sha1ModeResult, &pinningTelemetryInfo,
&certificateTransparencyInfo, &crliteTelemetryInfo);
&certificateTransparencyInfo, &crliteTelemetryInfo,
&aIsCertChainRootBuiltInRoot);
CollectCertTelemetry(rv, evOidPolicy, ocspStaplingStatus, keySizeStatus,
sha1ModeResult, pinningTelemetryInfo, builtCertChain,
@ -1296,11 +1300,12 @@ SSLServerCertVerificationJob::Run() {
UniqueCERTCertList builtCertChain;
SECOidTag evOidPolicy;
CertificateTransparencyInfo certificateTransparencyInfo;
bool isCertChainRootBuiltInRoot = false;
Result rv = AuthCertificate(
*certVerifier, mPinArg, mCert, mPeerCertChain, mHostName,
mOriginAttributes, mStapledOCSPResponse, mSCTsFromTLSExtension, mDCInfo,
mProviderFlags, mTime, mCertVerifierFlags, builtCertChain, evOidPolicy,
certificateTransparencyInfo);
certificateTransparencyInfo, isCertChainRootBuiltInRoot);
RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(mCert.get());
nsTArray<nsTArray<uint8_t>> certBytesArray;
@ -1318,7 +1323,7 @@ SSLServerCertVerificationJob::Run() {
nsc, std::move(certBytesArray), std::move(mPeerCertChain),
TransportSecurityInfo::ConvertCertificateTransparencyInfoToStatus(
certificateTransparencyInfo),
evStatus, true, 0, 0);
evStatus, true, 0, 0, isCertChainRootBuiltInRoot);
return NS_OK;
}
@ -1336,7 +1341,7 @@ SSLServerCertVerificationJob::Run() {
mResultTask->Dispatch(
nsc, std::move(certBytesArray), std::move(mPeerCertChain),
nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE,
EVStatus::NotEV, false, finalError, collectedErrors);
EVStatus::NotEV, false, finalError, collectedErrors, false);
return NS_OK;
}
@ -1561,7 +1566,8 @@ void SSLServerCertVerificationResult::Dispatch(
nsNSSCertificate* aCert, nsTArray<nsTArray<uint8_t>>&& aBuiltChain,
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus,
bool aSucceeded, PRErrorCode aFinalError, uint32_t aCollectedErrors) {
bool aSucceeded, PRErrorCode aFinalError, uint32_t aCollectedErrors,
bool aIsCertChainRootBuiltInRoot) {
mCert = aCert;
mBuiltChain = std::move(aBuiltChain);
mPeerCertChain = std::move(aPeerCertChain);
@ -1570,6 +1576,7 @@ void SSLServerCertVerificationResult::Dispatch(
mSucceeded = aSucceeded;
mFinalError = aFinalError;
mCollectedErrors = aCollectedErrors;
mIsBuiltCertChainRootBuiltInRoot = aIsCertChainRootBuiltInRoot;
nsresult rv;
nsCOMPtr<nsIEventTarget> stsTarget =
@ -1594,9 +1601,10 @@ SSLServerCertVerificationResult::Run() {
MOZ_ASSERT(onSTSThread);
#endif
AuthCertificateSetResults(
mInfoObject, mCert, std::move(mBuiltChain), std::move(mPeerCertChain),
mCertificateTransparencyStatus, mEVStatus, mSucceeded);
AuthCertificateSetResults(mInfoObject, mCert, std::move(mBuiltChain),
std::move(mPeerCertChain),
mCertificateTransparencyStatus, mEVStatus,
mSucceeded, mIsBuiltCertChainRootBuiltInRoot);
if (!mSucceeded && mCollectedErrors != 0) {
mInfoObject->SetStatusErrorBits(mCert, mCollectedErrors);

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

@ -49,7 +49,8 @@ class BaseSSLServerCertVerificationResult {
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
uint16_t aCertificateTransparencyStatus,
EVStatus aEVStatus, bool aSucceeded,
PRErrorCode aFinalError, uint32_t aCollectedErrors) = 0;
PRErrorCode aFinalError, uint32_t aCollectedErrors,
bool aIsBuiltCertChainRootBuiltInRoot) = 0;
};
// Dispatched to the STS thread to notify the infoObject of the verification
@ -72,7 +73,8 @@ class SSLServerCertVerificationResult final
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus,
bool aSucceeded, PRErrorCode aFinalError,
uint32_t aCollectedErrors) override;
uint32_t aCollectedErrors,
bool aIsBuiltCertChainRootBuiltInRoot) override;
private:
~SSLServerCertVerificationResult() = default;
@ -86,6 +88,7 @@ class SSLServerCertVerificationResult final
bool mSucceeded;
PRErrorCode mFinalError;
uint32_t mCollectedErrors;
bool mIsBuiltCertChainRootBuiltInRoot;
};
class SSLServerCertVerificationJob : public Runnable {

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

@ -36,6 +36,12 @@ class SharedSSLState {
void SetSignedCertTimestampsEnabled(bool signedCertTimestampsEnabled) {
mSignedCertTimestampsEnabled = signedCertTimestampsEnabled;
}
void SetPinningMode(CertVerifier::PinningMode aPinningMode) {
mPinningMode = aPinningMode;
}
void SetNameMatchingMode(BRNameMatchingPolicy::Mode aMode) {
mNameMatchingMode = aMode;
}
// The following methods may be called from any thread
bool SocketCreated();
@ -46,6 +52,8 @@ class SharedSSLState {
bool IsSignedCertTimestampsEnabled() const {
return mSignedCertTimestampsEnabled;
}
CertVerifier::PinningMode PinningMode() { return mPinningMode; }
BRNameMatchingPolicy::Mode NameMatchingMode() { return mNameMatchingMode; }
private:
~SharedSSLState();
@ -63,6 +71,8 @@ class SharedSSLState {
bool mOCSPStaplingEnabled;
bool mOCSPMustStapleEnabled;
bool mSignedCertTimestampsEnabled;
CertVerifier::PinningMode mPinningMode;
BRNameMatchingPolicy::Mode mNameMatchingMode;
};
SharedSSLState* PublicSSLState();

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

@ -58,6 +58,7 @@ TransportSecurityInfo::TransportSecurityInfo()
mMutex("TransportSecurityInfo::mMutex"),
mNPNCompleted(false),
mResumed(false),
mIsBuiltCertChainRootBuiltInRoot(false),
mSecurityState(nsIWebProgressListener::STATE_IS_INSECURE),
mErrorCode(0),
mPort(0) {}
@ -193,7 +194,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("4").get());
rv = aStream->WriteWStringZ(NS_ConvertUTF8toUTF16("5").get());
if (NS_FAILED(rv)) {
return rv;
}
@ -273,6 +274,11 @@ TransportSecurityInfo::Write(nsIObjectOutputStream* aStream) {
return rv;
}
rv = aStream->WriteBoolean(mIsBuiltCertChainRootBuiltInRoot);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
@ -532,7 +538,8 @@ TransportSecurityInfo::Read(nsIObjectInputStream* aStream) {
// moved from nsISSLStatus
if (!serVersion.EqualsASCII("1") && !serVersion.EqualsASCII("2") &&
!serVersion.EqualsASCII("3") && !serVersion.EqualsASCII("4")) {
!serVersion.EqualsASCII("3") && !serVersion.EqualsASCII("4") &&
!serVersion.EqualsASCII("5")) {
// nsISSLStatus may be present
rv = ReadSSLStatus(aStream);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
@ -608,7 +615,8 @@ TransportSecurityInfo::Read(nsIObjectInputStream* aStream) {
"Deserialization should not fail");
NS_ENSURE_SUCCESS(rv, rv);
if (!serVersion.EqualsASCII("3") && !serVersion.EqualsASCII("4")) {
if (!serVersion.EqualsASCII("3") && !serVersion.EqualsASCII("4") &&
!serVersion.EqualsASCII("5")) {
// The old data structure of certList(nsIX509CertList) presents
rv = ReadCertList(aStream, mSucceededCertChain);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
@ -626,7 +634,8 @@ TransportSecurityInfo::Read(nsIObjectInputStream* aStream) {
}
}
// END moved from nsISSLStatus
if (!serVersion.EqualsASCII("3") && !serVersion.EqualsASCII("4")) {
if (!serVersion.EqualsASCII("3") && !serVersion.EqualsASCII("4") &&
!serVersion.EqualsASCII("5")) {
// The old data structure of certList(nsIX509CertList) presents
rv = ReadCertList(aStream, mFailedCertChain);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
@ -645,7 +654,7 @@ TransportSecurityInfo::Read(nsIObjectInputStream* aStream) {
// mIsDelegatedCredential added in bug 1562773
if (serVersion.EqualsASCII("2") || serVersion.EqualsASCII("3") ||
serVersion.EqualsASCII("4")) {
serVersion.EqualsASCII("4") || serVersion.EqualsASCII("5")) {
rv = aStream->ReadBoolean(&mIsDelegatedCredential);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
"Deserialization should not fail");
@ -655,7 +664,7 @@ TransportSecurityInfo::Read(nsIObjectInputStream* aStream) {
}
// mNPNCompleted, mNegotiatedNPN, mResumed added in bug 1584104
if (serVersion.EqualsASCII("4")) {
if (serVersion.EqualsASCII("4") || serVersion.EqualsASCII("5")) {
rv = aStream->ReadBoolean(&mNPNCompleted);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
"Deserialization should not fail");
@ -678,6 +687,16 @@ TransportSecurityInfo::Read(nsIObjectInputStream* aStream) {
}
}
// mIsBuiltCertChainRootBuiltInRoot added in bug 1485652
if (serVersion.EqualsASCII("5")) {
rv = aStream->ReadBoolean(&mIsBuiltCertChainRootBuiltInRoot);
CHILD_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
"Deserialization should not fail");
if (NS_FAILED(rv)) {
return rv;
}
}
return NS_OK;
}
@ -709,6 +728,7 @@ void TransportSecurityInfo::SerializeToIPC(IPC::Message* aMsg) {
WriteParam(aMsg, mNPNCompleted);
WriteParam(aMsg, mNegotiatedNPN);
WriteParam(aMsg, mResumed);
WriteParam(aMsg, mIsBuiltCertChainRootBuiltInRoot);
}
bool TransportSecurityInfo::DeserializeFromIPC(const IPC::Message* aMsg,
@ -737,7 +757,8 @@ bool TransportSecurityInfo::DeserializeFromIPC(const IPC::Message* aMsg,
!ReadParam(aMsg, aIter, &mIsDelegatedCredential) ||
!ReadParam(aMsg, aIter, &mNPNCompleted) ||
!ReadParam(aMsg, aIter, &mNegotiatedNPN) ||
!ReadParam(aMsg, aIter, &mResumed)) {
!ReadParam(aMsg, aIter, &mResumed) ||
!ReadParam(aMsg, aIter, &mIsBuiltCertChainRootBuiltInRoot)) {
return false;
}
@ -956,6 +977,19 @@ nsresult TransportSecurityInfo::SetSucceededCertChain(
return CreateCertChain(mSucceededCertChain, std::move(aCertList));
}
NS_IMETHODIMP TransportSecurityInfo::SetIsBuiltCertChainRootBuiltInRoot(
bool aIsBuiltInRoot) {
mIsBuiltCertChainRootBuiltInRoot = aIsBuiltInRoot;
return NS_OK;
}
NS_IMETHODIMP TransportSecurityInfo::GetIsBuiltCertChainRootBuiltInRoot(
bool* aIsBuiltInRoot) {
NS_ENSURE_ARG_POINTER(aIsBuiltInRoot);
*aIsBuiltInRoot = mIsBuiltCertChainRootBuiltInRoot;
return NS_OK;
}
NS_IMETHODIMP
TransportSecurityInfo::GetCipherName(nsACString& aCipherName) {
if (!mHaveCipherSuiteAndProtocol) {

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

@ -130,6 +130,7 @@ class TransportSecurityInfo : public nsITransportSecurityInfo,
bool mNPNCompleted;
nsCString mNegotiatedNPN;
bool mResumed;
bool mIsBuiltCertChainRootBuiltInRoot;
private:
uint32_t mSecurityState;

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

@ -28,7 +28,8 @@ VerifySSLServerCertChild::VerifySSLServerCertChild(
ipc::IPCResult VerifySSLServerCertChild::RecvOnVerifiedSSLServerCertSuccess(
nsTArray<ByteArray>&& aBuiltCertChain,
const uint16_t& aCertTransparencyStatus, const uint8_t& aEVStatus) {
const uint16_t& aCertTransparencyStatus, const uint8_t& aEVStatus,
const bool& aIsBuiltCertChainRootBuiltInRoot) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("[%p] VerifySSLServerCertChild::RecvOnVerifiedSSLServerCertSuccess",
this));
@ -41,7 +42,8 @@ ipc::IPCResult VerifySSLServerCertChild::RecvOnVerifiedSSLServerCertSuccess(
mResultTask->Dispatch(nsc, std::move(certBytesArray),
std::move(mPeerCertChain), aCertTransparencyStatus,
static_cast<EVStatus>(aEVStatus), true, 0, 0);
static_cast<EVStatus>(aEVStatus), true, 0, 0,
aIsBuiltCertChainRootBuiltInRoot);
return IPC_OK();
}
@ -57,7 +59,7 @@ ipc::IPCResult VerifySSLServerCertChild::RecvOnVerifiedSSLServerCertFailure(
mResultTask->Dispatch(
nsc, nsTArray<nsTArray<uint8_t>>(), std::move(mPeerCertChain),
nsITransportSecurityInfo::CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE,
EVStatus::NotEV, false, aFinalError, aCollectedErrors);
EVStatus::NotEV, false, aFinalError, aCollectedErrors, false);
return IPC_OK();
}

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

@ -33,7 +33,8 @@ class VerifySSLServerCertChild : public PVerifySSLServerCertChild {
ipc::IPCResult RecvOnVerifiedSSLServerCertSuccess(
nsTArray<ByteArray>&& aBuiltCertChain,
const uint16_t& aCertTransparencyStatus, const uint8_t& aEVStatus);
const uint16_t& aCertTransparencyStatus, const uint8_t& aEVStatus,
const bool& aIsBuiltCertChainRootBuiltInRoot);
ipc::IPCResult RecvOnVerifiedSSLServerCertFailure(
const uint32_t& aFinalError, const uint32_t& aCollectedErrors);

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

@ -31,7 +31,8 @@ VerifySSLServerCertParent::VerifySSLServerCertParent() {}
void VerifySSLServerCertParent::OnVerifiedSSLServerCert(
const nsTArray<ByteArray>& aBuiltCertChain,
uint16_t aCertificateTransparencyStatus, uint8_t aEVStatus, bool aSucceeded,
PRErrorCode aFinalError, uint32_t aCollectedErrors) {
PRErrorCode aFinalError, uint32_t aCollectedErrors,
bool aIsBuiltCertChainRootBuiltInRoot) {
AssertIsOnBackgroundThread();
if (!CanSend()) {
@ -40,7 +41,8 @@ void VerifySSLServerCertParent::OnVerifiedSSLServerCert(
if (aSucceeded) {
Unused << SendOnVerifiedSSLServerCertSuccess(
aBuiltCertChain, aCertificateTransparencyStatus, aEVStatus);
aBuiltCertChain, aCertificateTransparencyStatus, aEVStatus,
aIsBuiltCertChainRootBuiltInRoot);
} else {
Unused << SendOnVerifiedSSLServerCertFailure(aFinalError, aCollectedErrors);
}
@ -64,7 +66,8 @@ class IPCServerCertVerificationResult final
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus,
bool aSucceeded, PRErrorCode aFinalError,
uint32_t aCollectedErrors) override;
uint32_t aCollectedErrors,
bool aIsBuiltCertChainRootBuiltInRoot) override;
private:
~IPCServerCertVerificationResult() = default;
@ -77,7 +80,8 @@ void IPCServerCertVerificationResult::Dispatch(
nsNSSCertificate* aCert, nsTArray<nsTArray<uint8_t>>&& aBuiltChain,
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus,
bool aSucceeded, PRErrorCode aFinalError, uint32_t aCollectedErrors) {
bool aSucceeded, PRErrorCode aFinalError, uint32_t aCollectedErrors,
bool aIsBuiltCertChainRootBuiltInRoot) {
nsTArray<ByteArray> builtCertChain;
if (aSucceeded) {
for (auto& cert : aBuiltChain) {
@ -90,11 +94,11 @@ void IPCServerCertVerificationResult::Dispatch(
"psm::VerifySSLServerCertParent::OnVerifiedSSLServerCert",
[parent(mParent), builtCertChain{std::move(builtCertChain)},
aCertificateTransparencyStatus, aEVStatus, aSucceeded, aFinalError,
aCollectedErrors]() {
aCollectedErrors, aIsBuiltCertChainRootBuiltInRoot]() {
parent->OnVerifiedSSLServerCert(
builtCertChain, aCertificateTransparencyStatus,
static_cast<uint8_t>(aEVStatus), aSucceeded, aFinalError,
aCollectedErrors);
aCollectedErrors, aIsBuiltCertChainRootBuiltInRoot);
}),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(nrv));

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

@ -44,7 +44,8 @@ class VerifySSLServerCertParent : public PVerifySSLServerCertParent {
uint16_t aCertificateTransparencyStatus,
uint8_t aEVStatus, bool aSucceeded,
PRErrorCode aFinalError,
uint32_t aCollectedErrors);
uint32_t aCollectedErrors,
bool aIsBuiltCertChainRootBuiltInRoot);
private:
virtual ~VerifySSLServerCertParent();

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

@ -1106,6 +1106,7 @@ static void RebuildVerifiedCertificateInformation(PRFileDesc* fd,
CertificateTransparencyInfo certificateTransparencyInfo;
UniqueCERTCertList builtChain;
const bool saveIntermediates = false;
bool isBuiltCertChainRootBuiltInRoot = false;
mozilla::pkix::Result rv = certVerifier->VerifySSLServerCert(
cert, mozilla::pkix::Now(), infoObject, infoObject->GetHostName(),
builtChain, flags, maybePeerCertsBytes, stapledOCSPResponse,
@ -1115,7 +1116,9 @@ static void RebuildVerifiedCertificateInformation(PRFileDesc* fd,
nullptr, // key size telemetry
nullptr, // SHA-1 telemetry
nullptr, // pinning telemetry
&certificateTransparencyInfo);
&certificateTransparencyInfo,
nullptr, // CRLite telemetry,
&isBuiltCertChainRootBuiltInRoot);
if (rv != Success) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
@ -1141,6 +1144,8 @@ static void RebuildVerifiedCertificateInformation(PRFileDesc* fd,
nsTArray<nsTArray<uint8_t>> certBytesArray =
TransportSecurityInfo::CreateCertBytesArray(builtChain);
infoObject->SetSucceededCertChain(std::move(certBytesArray));
infoObject->SetIsBuiltCertChainRootBuiltInRoot(
isBuiltCertChainRootBuiltInRoot);
}
}
@ -1232,6 +1237,11 @@ static void RebuildCertificateInfoFromSSLTokenCache(
aInfoObject->SetSucceededCertChain(
std::move(*info.mSucceededCertChainBytes));
}
if (info.mIsBuiltCertChainRootBuiltInRoot) {
aInfoObject->SetIsBuiltCertChainRootBuiltInRoot(
*info.mIsBuiltCertChainRootBuiltInRoot);
}
}
void HandshakeCallback(PRFileDesc* fd, void* client_data) {

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

@ -1262,6 +1262,33 @@ void SetValidationOptionsCommon() {
ctMode != CertVerifier::CertificateTransparencyMode::Disabled;
PublicSSLState()->SetSignedCertTimestampsEnabled(sctsEnabled);
PrivateSSLState()->SetSignedCertTimestampsEnabled(sctsEnabled);
CertVerifier::PinningMode pinningMode =
static_cast<CertVerifier::PinningMode>(
Preferences::GetInt("security.cert_pinning.enforcement_level",
CertVerifier::pinningDisabled));
if (pinningMode > CertVerifier::pinningEnforceTestMode) {
pinningMode = CertVerifier::pinningDisabled;
}
PublicSSLState()->SetPinningMode(pinningMode);
PrivateSSLState()->SetPinningMode(pinningMode);
BRNameMatchingPolicy::Mode nameMatchingMode =
static_cast<BRNameMatchingPolicy::Mode>(Preferences::GetInt(
"security.pki.name_matching_mode",
static_cast<int32_t>(BRNameMatchingPolicy::Mode::DoNotEnforce)));
switch (nameMatchingMode) {
case BRNameMatchingPolicy::Mode::Enforce:
case BRNameMatchingPolicy::Mode::EnforceAfter23August2015:
case BRNameMatchingPolicy::Mode::EnforceAfter23August2016:
case BRNameMatchingPolicy::Mode::DoNotEnforce:
break;
default:
nameMatchingMode = BRNameMatchingPolicy::Mode::DoNotEnforce;
break;
}
PublicSSLState()->SetNameMatchingMode(nameMatchingMode);
PrivateSSLState()->SetNameMatchingMode(nameMatchingMode);
}
namespace {
@ -1383,14 +1410,6 @@ void nsNSSComponent::setValidationOptions(
Telemetry::Accumulate(Telemetry::CERT_OCSP_REQUIRED, ocspRequired);
}
CertVerifier::PinningMode pinningMode =
static_cast<CertVerifier::PinningMode>(
Preferences::GetInt("security.cert_pinning.enforcement_level",
CertVerifier::pinningDisabled));
if (pinningMode > CertVerifier::pinningEnforceTestMode) {
pinningMode = CertVerifier::pinningDisabled;
}
CertVerifier::SHA1Mode sha1Mode =
static_cast<CertVerifier::SHA1Mode>(Preferences::GetInt(
"security.pki.sha1_enforcement_level",
@ -1412,21 +1431,6 @@ void nsNSSComponent::setValidationOptions(
sha1Mode = CertVerifier::SHA1Mode::Forbidden;
}
BRNameMatchingPolicy::Mode nameMatchingMode =
static_cast<BRNameMatchingPolicy::Mode>(Preferences::GetInt(
"security.pki.name_matching_mode",
static_cast<int32_t>(BRNameMatchingPolicy::Mode::DoNotEnforce)));
switch (nameMatchingMode) {
case BRNameMatchingPolicy::Mode::Enforce:
case BRNameMatchingPolicy::Mode::EnforceAfter23August2015:
case BRNameMatchingPolicy::Mode::EnforceAfter23August2016:
case BRNameMatchingPolicy::Mode::DoNotEnforce:
break;
default:
nameMatchingMode = BRNameMatchingPolicy::Mode::DoNotEnforce;
break;
}
NetscapeStepUpPolicy netscapeStepUpPolicy =
static_cast<NetscapeStepUpPolicy>(Preferences::GetUint(
"security.pki.netscape_step_up_policy",
@ -1476,8 +1480,9 @@ void nsNSSComponent::setValidationOptions(
softTimeout, hardTimeout, proofOfLock);
mDefaultCertVerifier = new SharedCertVerifier(
odc, osc, softTimeout, hardTimeout, certShortLifetimeInDays, pinningMode,
sha1Mode, nameMatchingMode, netscapeStepUpPolicy, ctMode,
odc, osc, softTimeout, hardTimeout, certShortLifetimeInDays,
PublicSSLState()->PinningMode(), sha1Mode,
PublicSSLState()->NameMatchingMode(), netscapeStepUpPolicy, ctMode,
distrustedCAPolicy, crliteMode, mEnterpriseCerts);
}