mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1107666: Fix OCSP stapling telemetry (SSL_OCSP_STAPLING), r=keeler
--HG-- extra : rebase_source : 926f091b2a361d7dce30bee918d6659259f1b3e4
This commit is contained in:
parent
5cfa302167
commit
746ee1cc1d
@ -123,20 +123,25 @@ CertListContainsExpectedKeys(const CERTCertList* certList,
|
||||
}
|
||||
|
||||
static Result
|
||||
BuildCertChainForOneKeyUsage(TrustDomain& trustDomain, Input certDER,
|
||||
BuildCertChainForOneKeyUsage(NSSCertDBTrustDomain& trustDomain, Input certDER,
|
||||
Time time, KeyUsage ku1, KeyUsage ku2,
|
||||
KeyUsage ku3, KeyPurposeId eku,
|
||||
const CertPolicyId& requiredPolicy,
|
||||
const Input* stapledOCSPResponse)
|
||||
const Input* stapledOCSPResponse,
|
||||
/*optional out*/ CertVerifier::OCSPStaplingStatus*
|
||||
ocspStaplingStatus)
|
||||
{
|
||||
trustDomain.ResetOCSPStaplingStatus();
|
||||
Result rv = BuildCertChain(trustDomain, certDER, time,
|
||||
EndEntityOrCA::MustBeEndEntity, ku1,
|
||||
eku, requiredPolicy, stapledOCSPResponse);
|
||||
if (rv == Result::ERROR_INADEQUATE_KEY_USAGE) {
|
||||
trustDomain.ResetOCSPStaplingStatus();
|
||||
rv = BuildCertChain(trustDomain, certDER, time,
|
||||
EndEntityOrCA::MustBeEndEntity, ku2,
|
||||
eku, requiredPolicy, stapledOCSPResponse);
|
||||
if (rv == Result::ERROR_INADEQUATE_KEY_USAGE) {
|
||||
trustDomain.ResetOCSPStaplingStatus();
|
||||
rv = BuildCertChain(trustDomain, certDER, time,
|
||||
EndEntityOrCA::MustBeEndEntity, ku3,
|
||||
eku, requiredPolicy, stapledOCSPResponse);
|
||||
@ -145,6 +150,9 @@ BuildCertChainForOneKeyUsage(TrustDomain& trustDomain, Input certDER,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ocspStaplingStatus) {
|
||||
*ocspStaplingStatus = trustDomain.GetOCSPStaplingStatus();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -154,7 +162,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
||||
const Flags flags,
|
||||
/*optional*/ const SECItem* stapledOCSPResponseSECItem,
|
||||
/*optional out*/ ScopedCERTCertList* builtChain,
|
||||
/*optional out*/ SECOidTag* evOidPolicy)
|
||||
/*optional out*/ SECOidTag* evOidPolicy,
|
||||
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus)
|
||||
{
|
||||
PR_LOG(gCertVerifierLog, PR_LOG_DEBUG, ("Top of VerifyCert\n"));
|
||||
|
||||
@ -167,6 +176,13 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
||||
if (evOidPolicy) {
|
||||
*evOidPolicy = SEC_OID_UNKNOWN;
|
||||
}
|
||||
if (ocspStaplingStatus) {
|
||||
if (usage != certificateUsageSSLServer) {
|
||||
PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
|
||||
return SECFailure;
|
||||
}
|
||||
*ocspStaplingStatus = OCSP_STAPLING_NEVER_CHECKED;
|
||||
}
|
||||
|
||||
if (!cert ||
|
||||
(usage != certificateUsageSSLServer && (flags & FLAG_MUST_BE_EV))) {
|
||||
@ -243,7 +259,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
||||
KeyUsage::keyEncipherment, // RSA
|
||||
KeyUsage::keyAgreement, // (EC)DH
|
||||
KeyPurposeId::id_kp_serverAuth,
|
||||
evPolicy, stapledOCSPResponse);
|
||||
evPolicy, stapledOCSPResponse,
|
||||
ocspStaplingStatus);
|
||||
if (rv == Success) {
|
||||
if (evOidPolicy) {
|
||||
*evOidPolicy = evPolicyOidTag;
|
||||
@ -268,7 +285,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
|
||||
KeyUsage::keyAgreement, // (EC)DH
|
||||
KeyPurposeId::id_kp_serverAuth,
|
||||
CertPolicyId::anyPolicy,
|
||||
stapledOCSPResponse);
|
||||
stapledOCSPResponse,
|
||||
ocspStaplingStatus);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -418,7 +436,8 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert,
|
||||
bool saveIntermediatesInPermanentDatabase,
|
||||
Flags flags,
|
||||
/*optional out*/ ScopedCERTCertList* builtChain,
|
||||
/*optional out*/ SECOidTag* evOidPolicy)
|
||||
/*optional out*/ SECOidTag* evOidPolicy,
|
||||
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus)
|
||||
{
|
||||
PR_ASSERT(peerCert);
|
||||
// XXX: PR_ASSERT(pinarg)
|
||||
@ -442,7 +461,7 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert,
|
||||
// if VerifyCert succeeded.
|
||||
SECStatus rv = VerifyCert(peerCert, certificateUsageSSLServer, time, pinarg,
|
||||
hostname, flags, stapledOCSPResponse,
|
||||
&builtChainTemp, evOidPolicy);
|
||||
&builtChainTemp, evOidPolicy, ocspStaplingStatus);
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -24,6 +24,15 @@ public:
|
||||
// Don't perform fallback DV validation on EV validation failure.
|
||||
static const Flags FLAG_MUST_BE_EV;
|
||||
|
||||
// These values correspond to the SSL_OCSP_STAPLING telemetry.
|
||||
enum OCSPStaplingStatus {
|
||||
OCSP_STAPLING_NEVER_CHECKED = 0,
|
||||
OCSP_STAPLING_GOOD = 1,
|
||||
OCSP_STAPLING_NONE = 2,
|
||||
OCSP_STAPLING_EXPIRED = 3,
|
||||
OCSP_STAPLING_INVALID = 4,
|
||||
};
|
||||
|
||||
// *evOidPolicy == SEC_OID_UNKNOWN means the cert is NOT EV
|
||||
// Only one usage per verification is supported.
|
||||
SECStatus VerifyCert(CERTCertificate* cert,
|
||||
@ -34,7 +43,8 @@ public:
|
||||
Flags flags = 0,
|
||||
/*optional in*/ const SECItem* stapledOCSPResponse = nullptr,
|
||||
/*optional out*/ ScopedCERTCertList* builtChain = nullptr,
|
||||
/*optional out*/ SECOidTag* evOidPolicy = nullptr);
|
||||
/*optional out*/ SECOidTag* evOidPolicy = nullptr,
|
||||
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr);
|
||||
|
||||
SECStatus VerifySSLServerCert(
|
||||
CERTCertificate* peerCert,
|
||||
@ -45,7 +55,8 @@ public:
|
||||
bool saveIntermediatesInPermanentDatabase = false,
|
||||
Flags flags = 0,
|
||||
/*optional out*/ ScopedCERTCertList* builtChain = nullptr,
|
||||
/*optional out*/ SECOidTag* evOidPolicy = nullptr);
|
||||
/*optional out*/ SECOidTag* evOidPolicy = nullptr,
|
||||
/*optional out*/ OCSPStaplingStatus* ocspStaplingStatus = nullptr);
|
||||
|
||||
enum PinningMode {
|
||||
pinningDisabled = 0,
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "NSSErrorsService.h"
|
||||
#include "OCSPRequestor.h"
|
||||
#include "certdb.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nss.h"
|
||||
#include "pk11pub.h"
|
||||
#include "pkix/pkix.h"
|
||||
@ -68,6 +67,7 @@ NSSCertDBTrustDomain::NSSCertDBTrustDomain(SECTrustType certDBTrustType,
|
||||
, mMinimumNonECCBits(forEV ? MINIMUM_NON_ECC_BITS_EV : MINIMUM_NON_ECC_BITS_DV)
|
||||
, mHostname(hostname)
|
||||
, mBuiltChain(builtChain)
|
||||
, mOCSPStaplingStatus(CertVerifier::OCSP_STAPLING_NEVER_CHECKED)
|
||||
{
|
||||
}
|
||||
|
||||
@ -383,7 +383,7 @@ NSSCertDBTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||
ResponseWasStapled, expired);
|
||||
if (stapledOCSPResponseResult == Success) {
|
||||
// stapled OCSP response present and good
|
||||
Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 1);
|
||||
mOCSPStaplingStatus = CertVerifier::OCSP_STAPLING_GOOD;
|
||||
PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
|
||||
("NSSCertDBTrustDomain: stapled OCSP response: good"));
|
||||
return Success;
|
||||
@ -391,19 +391,19 @@ NSSCertDBTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA,
|
||||
if (stapledOCSPResponseResult == Result::ERROR_OCSP_OLD_RESPONSE ||
|
||||
expired) {
|
||||
// stapled OCSP response present but expired
|
||||
Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 3);
|
||||
mOCSPStaplingStatus = CertVerifier::OCSP_STAPLING_EXPIRED;
|
||||
PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
|
||||
("NSSCertDBTrustDomain: expired stapled OCSP response"));
|
||||
} else {
|
||||
// stapled OCSP response present but invalid for some reason
|
||||
Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 4);
|
||||
mOCSPStaplingStatus = CertVerifier::OCSP_STAPLING_INVALID;
|
||||
PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
|
||||
("NSSCertDBTrustDomain: stapled OCSP response: failure"));
|
||||
return stapledOCSPResponseResult;
|
||||
}
|
||||
} else {
|
||||
// no stapled OCSP response
|
||||
Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 2);
|
||||
mOCSPStaplingStatus = CertVerifier::OCSP_STAPLING_NONE;
|
||||
PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
|
||||
("NSSCertDBTrustDomain: no stapled OCSP response"));
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
FetchOCSPForEV = 3,
|
||||
LocalOnlyOCSPForEV = 4,
|
||||
};
|
||||
|
||||
NSSCertDBTrustDomain(SECTrustType certDBTrustType, OCSPFetching ocspFetching,
|
||||
OCSPCache& ocspCache, void* pinArg,
|
||||
CertVerifier::ocsp_get_config ocspGETConfig,
|
||||
@ -91,6 +92,15 @@ public:
|
||||
virtual Result IsChainValid(const mozilla::pkix::DERArray& certChain,
|
||||
mozilla::pkix::Time time) MOZ_OVERRIDE;
|
||||
|
||||
CertVerifier::OCSPStaplingStatus GetOCSPStaplingStatus() const
|
||||
{
|
||||
return mOCSPStaplingStatus;
|
||||
}
|
||||
void ResetOCSPStaplingStatus()
|
||||
{
|
||||
mOCSPStaplingStatus = CertVerifier::OCSP_STAPLING_NEVER_CHECKED;
|
||||
}
|
||||
|
||||
private:
|
||||
enum EncodedResponseSource {
|
||||
ResponseIsFromNetwork = 1,
|
||||
@ -110,6 +120,7 @@ private:
|
||||
const unsigned int mMinimumNonECCBits;
|
||||
const char* mHostname; // non-owning - only used for pinning checks
|
||||
ScopedCERTCertList* mBuiltChain; // non-owning
|
||||
CertVerifier::OCSPStaplingStatus mOCSPStaplingStatus;
|
||||
};
|
||||
|
||||
} } // namespace mozilla::psm
|
||||
|
@ -1085,11 +1085,22 @@ AuthCertificate(CertVerifier& certVerifier,
|
||||
|
||||
SECOidTag evOidPolicy;
|
||||
ScopedCERTCertList certList;
|
||||
CertVerifier::OCSPStaplingStatus ocspStaplingStatus =
|
||||
CertVerifier::OCSP_STAPLING_NEVER_CHECKED;
|
||||
|
||||
rv = certVerifier.VerifySSLServerCert(cert, stapledOCSPResponse,
|
||||
time, infoObject,
|
||||
infoObject->GetHostNameRaw(),
|
||||
saveIntermediates, 0, &certList,
|
||||
&evOidPolicy);
|
||||
&evOidPolicy, &ocspStaplingStatus);
|
||||
PRErrorCode savedErrorCode;
|
||||
if (rv != SECSuccess) {
|
||||
savedErrorCode = PR_GetError();
|
||||
}
|
||||
|
||||
if (ocspStaplingStatus != CertVerifier::OCSP_STAPLING_NEVER_CHECKED) {
|
||||
Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, ocspStaplingStatus);
|
||||
}
|
||||
|
||||
// We want to remember the CA certs in the temp db, so that the application can find the
|
||||
// complete chain at any time it might need it.
|
||||
@ -1142,6 +1153,7 @@ AuthCertificate(CertVerifier& certVerifier,
|
||||
// infoObject so it can be used for error reporting. Note: infoObject
|
||||
// indirectly takes ownership of peerCertChain.
|
||||
infoObject->SetFailedCertChain(peerCertChain);
|
||||
PR_SetError(savedErrorCode, 0);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
Loading…
Reference in New Issue
Block a user