Bug 1546816 - Part 2: Change nsNSSCallback to prepare for moving cert verifications to the parent process if the socket process performs network access. r=keeler

Differential Revision: https://phabricator.services.mozilla.com/D28742

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Dragana Damjanovic 2019-06-04 22:20:30 +00:00
Родитель 7eedf007fd
Коммит 4c2b903df4
1 изменённых файлов: 46 добавлений и 32 удалений

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

@ -1013,6 +1013,12 @@ static void AccumulateCipherSuite(Telemetry::HistogramID probe,
Telemetry::Accumulate(probe, value);
}
void RebuildVerifiedCertificateInformationResults(
nsNSSSocketInfo* aInfoObject, const UniqueCERTCertificate& aCert,
UniqueCERTCertList& aBuiltChain,
const CertificateTransparencyInfo& aCertificateTransparencyInfo,
SECOidTag aEvOidPolicy, bool aSucceeded);
// In the case of session resumption, the AuthCertificate hook has been bypassed
// (because we've previously successfully connected to our peer). That being the
// case, we unfortunately don't know what the verified certificate chain was, if
@ -1079,26 +1085,36 @@ static void RebuildVerifiedCertificateInformation(PRFileDesc* fd,
nullptr, // pinning telemetry
&certificateTransparencyInfo);
if (rv != Success) {
RebuildVerifiedCertificateInformationResults(infoObject, cert, builtChain,
certificateTransparencyInfo,
evOidPolicy, rv == Success);
}
void RebuildVerifiedCertificateInformationResults(
nsNSSSocketInfo* aInfoObject, const UniqueCERTCertificate& aCert,
UniqueCERTCertList& aBuiltChain,
const CertificateTransparencyInfo& aCertificateTransparencyInfo,
SECOidTag aEvOidPolicy, bool aSucceeded) {
if (!aSucceeded) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("HandshakeCallback: couldn't rebuild verified certificate info"));
}
RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(cert.get()));
if (rv == Success && evOidPolicy != SEC_OID_UNKNOWN) {
infoObject->SetCertificateTransparencyInfo(certificateTransparencyInfo);
RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(aCert.get()));
if (aSucceeded && aEvOidPolicy != SEC_OID_UNKNOWN) {
aInfoObject->SetCertificateTransparencyInfo(aCertificateTransparencyInfo);
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("HandshakeCallback using NEW cert %p (is EV)", nssc.get()));
infoObject->SetServerCert(nssc, EVStatus::EV);
aInfoObject->SetServerCert(nssc, EVStatus::EV);
} else {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("HandshakeCallback using NEW cert %p (is not EV)", nssc.get()));
infoObject->SetServerCert(nssc, EVStatus::NotEV);
aInfoObject->SetServerCert(nssc, EVStatus::NotEV);
}
if (rv == Success) {
infoObject->SetCertificateTransparencyInfo(certificateTransparencyInfo);
infoObject->SetSucceededCertChain(std::move(builtChain));
if (aSucceeded) {
aInfoObject->SetCertificateTransparencyInfo(aCertificateTransparencyInfo);
aInfoObject->SetSucceededCertChain(std::move(aBuiltChain));
}
}
@ -1154,6 +1170,10 @@ static nsresult IsCertificateDistrustImminent(nsIX509CertList* aCertList,
return NS_OK;
}
void CallAfterRebuildVerifiedCertificateInformation(
nsNSSSocketInfo* aInfoObject, uint32_t aCumulativeSecurityState,
PRBool aSiteSupportsSafeRenego);
void HandshakeCallback(PRFileDesc* fd, void* client_data) {
SECStatus rv;
@ -1294,48 +1314,42 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
RebuildVerifiedCertificateInformation(fd, infoObject);
}
CallAfterRebuildVerifiedCertificateInformation(infoObject, state,
siteSupportsSafeRenego);
}
void CallAfterRebuildVerifiedCertificateInformation(
nsNSSSocketInfo* aInfoObject, uint32_t aCumulativeSecurityState,
PRBool aSiteSupportsSafeRenego) {
nsCOMPtr<nsIX509CertList> succeededCertChain;
// This always returns NS_OK, but the list could be empty. This is a
// best-effort check for now. Bug 731478 will reduce the incidence of empty
// succeeded cert chains through better caching.
Unused << infoObject->GetSucceededCertChain(
Unused << aInfoObject->GetSucceededCertChain(
getter_AddRefs(succeededCertChain));
bool distrustImminent;
nsresult srv =
IsCertificateDistrustImminent(succeededCertChain, distrustImminent);
if (NS_SUCCEEDED(srv) && distrustImminent) {
state |= nsIWebProgressListener::STATE_CERT_DISTRUST_IMMINENT;
aCumulativeSecurityState |= nsIWebProgressListener::STATE_CERT_DISTRUST_IMMINENT;
}
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);
Unused << aInfoObject->GetIsDomainMismatch(&domainMismatch);
Unused << aInfoObject->GetIsUntrusted(&untrusted);
Unused << aInfoObject->GetIsNotValidAtThisTime(&notValidAtThisTime);
// 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) {
state |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
aCumulativeSecurityState |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
}
infoObject->SetSecurityState(state);
aInfoObject->SetSecurityState(aCumulativeSecurityState);
// XXX Bug 883674: We shouldn't be formatting messages here in PSM; instead,
// we should set a flag on the channel that higher (UI) level code can check
// to log the warning. In particular, these warnings should go to the web
// console instead of to the error console. Also, the warning is not
// localized.
if (!siteSupportsSafeRenego) {
NS_ConvertASCIItoUTF16 msg(infoObject->GetHostName());
msg.AppendLiteral(" : server does not support RFC 5746, see CVE-2009-3555");
nsContentUtils::LogSimpleConsoleError(
msg, "SSL", !!infoObject->GetOriginAttributes().mPrivateBrowsingId,
true /* from chrome context */);
}
infoObject->NoteTimeUntilReady();
infoObject->SetHandshakeCompleted();
aInfoObject->NoteTimeUntilReady();
aInfoObject->SetHandshakeCompleted();
}