Index: net/cert/ct_policy_enforcer.cc |
diff --git a/net/cert/ct_policy_enforcer.cc b/net/cert/ct_policy_enforcer.cc |
index aa8838b2ff34f9909e66d6b6385ffce89fb9c427..e036087c5cab04ec9b16e33d1f25cf2f17118d50 100644 |
--- a/net/cert/ct_policy_enforcer.cc |
+++ b/net/cert/ct_policy_enforcer.cc |
@@ -130,35 +130,42 @@ bool HasEnoughDiverseSCTs(const ct::SCTList& verified_scts) { |
(verified_scts.size() != num_google_issued_scts); |
} |
-enum CTComplianceStatus { |
- CT_NOT_COMPLIANT = 0, |
- CT_IN_WHITELIST = 1, |
- CT_ENOUGH_SCTS = 2, |
- CT_NOT_ENOUGH_DIVERSE_SCTS = 3, |
- CT_COMPLIANCE_MAX, |
-}; |
- |
-const char* ComplianceStatusToString(CTComplianceStatus status) { |
+const char* EVPolicyComplianceToString(ct::EVPolicyCompliance status) { |
switch (status) { |
- case CT_NOT_COMPLIANT: |
- return "NOT_COMPLIANT"; |
- break; |
- case CT_IN_WHITELIST: |
+ case ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY: |
+ return "POLICY_DOES_NOT_APPLY"; |
+ case ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST: |
return "WHITELISTED"; |
- break; |
- case CT_ENOUGH_SCTS: |
- return "ENOUGH_SCTS"; |
- break; |
- case CT_NOT_ENOUGH_DIVERSE_SCTS: |
- return "NOT_ENOUGH_DIVERSE_SCTS"; |
- break; |
- case CT_COMPLIANCE_MAX: |
+ case ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS: |
+ return "COMPLIES_VIA_SCTS"; |
+ case ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS: |
+ return "NOT_ENOUGH_SCTS"; |
+ case ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS: |
+ return "SCTS_NOT_DIVERSE"; |
+ case ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY: |
+ return "BUILD_NOT_TIMELY"; |
+ case ct::EVPolicyCompliance::EV_POLICY_MAX: |
break; |
} |
return "unknown"; |
} |
+const char* CertPolicyComplianceToString(ct::CertPolicyCompliance status) { |
+ switch (status) { |
+ case ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS: |
+ return "COMPLIES_VIA_SCTS"; |
+ case ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS: |
+ return "NOT_ENOUGH_SCTS"; |
+ case ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS: |
+ return "NOT_DIVERSE_SCTS"; |
+ case ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY: |
+ return "BUILD_NOT_TIMELY"; |
+ } |
+ |
+ return "unknown"; |
+} |
+ |
enum EVWhitelistStatus { |
EV_WHITELIST_NOT_PRESENT = 0, |
EV_WHITELIST_INVALID = 1, |
@@ -166,11 +173,13 @@ enum EVWhitelistStatus { |
EV_WHITELIST_MAX, |
}; |
-void LogCTEVComplianceStatusToUMA(CTComplianceStatus status, |
- const ct::EVCertsWhitelist* ev_whitelist) { |
- UMA_HISTOGRAM_ENUMERATION("Net.SSL_EVCertificateCTCompliance", status, |
- CT_COMPLIANCE_MAX); |
- if (status == CT_NOT_COMPLIANT) { |
+void LogEVPolicyComplianceToUMA(ct::EVPolicyCompliance status, |
+ const ct::EVCertsWhitelist* ev_whitelist) { |
+ UMA_HISTOGRAM_ENUMERATION( |
+ "Net.SSL_EVCTCompliance", static_cast<int>(status), |
+ static_cast<int>(ct::EVPolicyCompliance::EV_POLICY_MAX)); |
+ if (status == ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS || |
+ status == ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS) { |
EVWhitelistStatus ev_whitelist_status = EV_WHITELIST_NOT_PRESENT; |
if (ev_whitelist != NULL) { |
if (ev_whitelist->IsValid()) |
@@ -184,20 +193,22 @@ void LogCTEVComplianceStatusToUMA(CTComplianceStatus status, |
} |
} |
-struct ComplianceDetails { |
- ComplianceDetails() : build_timely(false), status(CT_NOT_COMPLIANT) {} |
+struct EVComplianceDetails { |
+ EVComplianceDetails() |
+ : build_timely(false), |
+ status(ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY) {} |
// Whether the build is not older than 10 weeks. |
bool build_timely; |
// Compliance status - meaningful only if |build_timely| is true. |
- CTComplianceStatus status; |
+ ct::EVPolicyCompliance status; |
// EV whitelist version. |
base::Version whitelist_version; |
}; |
-scoped_ptr<base::Value> NetLogComplianceCheckResultCallback( |
+scoped_ptr<base::Value> NetLogEVComplianceCheckResultCallback( |
X509Certificate* cert, |
- ComplianceDetails* details, |
+ EVComplianceDetails* details, |
NetLogCaptureMode capture_mode) { |
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode)); |
@@ -205,7 +216,7 @@ scoped_ptr<base::Value> NetLogComplianceCheckResultCallback( |
dict->SetBoolean("build_timely", details->build_timely); |
if (details->build_timely) { |
dict->SetString("ct_compliance_status", |
- ComplianceStatusToString(details->status)); |
+ EVPolicyComplianceToString(details->status)); |
if (details->whitelist_version.IsValid()) |
dict->SetString("ev_whitelist_version", |
details->whitelist_version.GetString()); |
@@ -213,6 +224,19 @@ scoped_ptr<base::Value> NetLogComplianceCheckResultCallback( |
return std::move(dict); |
} |
+scoped_ptr<base::Value> NetLogCertComplianceCheckResultCallback( |
+ X509Certificate* cert, |
+ bool build_timely, |
+ ct::CertPolicyCompliance compliance, |
+ NetLogCaptureMode capture_mode) { |
+ scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
+ dict->Set("certificate", NetLogX509CertificateCallback(cert, capture_mode)); |
+ dict->SetBoolean("build_timely", build_timely); |
+ dict->SetString("ct_compliance_status", |
+ CertPolicyComplianceToString(compliance)); |
+ return std::move(dict); |
+} |
+ |
// Returns true if all SCTs in |verified_scts| were issued on, or after, the |
// date specified in kDiverseSCTRequirementStartDate |
bool AllSCTsPastDistinctSCTRequirementEnforcementDate( |
@@ -247,49 +271,100 @@ bool IsCertificateInWhitelist(const X509Certificate& cert, |
return cert_in_ev_whitelist; |
} |
+ct::CertPolicyCompliance CheckCertPolicyCompliance( |
+ X509Certificate* cert, |
+ const ct::SCTList& verified_scts, |
+ const BoundNetLog& net_log) { |
+ if (!HasRequiredNumberOfSCTs(*cert, verified_scts)) |
+ return ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS; |
+ if (AllSCTsPastDistinctSCTRequirementEnforcementDate(verified_scts) && |
+ !HasEnoughDiverseSCTs(verified_scts)) { |
+ return ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS; |
+ } |
+ |
+ return ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS; |
+} |
+ |
+ct::EVPolicyCompliance CertPolicyComplianceToEVPolicyCompliance( |
+ ct::CertPolicyCompliance cert_policy_compliance) { |
+ switch (cert_policy_compliance) { |
+ case ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS: |
+ return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS; |
+ case ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS: |
+ return ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS; |
+ case ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS: |
+ return ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS; |
+ case ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY: |
+ return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY; |
+ } |
+ return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; |
+} |
+ |
void CheckCTEVPolicyCompliance(X509Certificate* cert, |
const ct::EVCertsWhitelist* ev_whitelist, |
const ct::SCTList& verified_scts, |
- ComplianceDetails* result) { |
- if (!IsBuildTimely()) |
- return; |
- result->build_timely = true; |
- |
+ const BoundNetLog& net_log, |
+ EVComplianceDetails* result) { |
+ result->status = CertPolicyComplianceToEVPolicyCompliance( |
+ CheckCertPolicyCompliance(cert, verified_scts, net_log)); |
if (ev_whitelist && ev_whitelist->IsValid()) |
result->whitelist_version = ev_whitelist->Version(); |
- if (IsCertificateInWhitelist(*cert, ev_whitelist)) { |
- result->status = CT_IN_WHITELIST; |
- return; |
+ if (result->status != ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS && |
+ IsCertificateInWhitelist(*cert, ev_whitelist)) { |
+ result->status = ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST; |
} |
+} |
- if (!HasRequiredNumberOfSCTs(*cert, verified_scts)) { |
- result->status = CT_NOT_COMPLIANT; |
- return; |
- } |
+} // namespace |
- if (AllSCTsPastDistinctSCTRequirementEnforcementDate(verified_scts) && |
- !HasEnoughDiverseSCTs(verified_scts)) { |
- result->status = CT_NOT_ENOUGH_DIVERSE_SCTS; |
- return; |
+ct::CertPolicyCompliance CTPolicyEnforcer::DoesConformToCertPolicy( |
+ X509Certificate* cert, |
+ const ct::SCTList& verified_scts, |
+ const BoundNetLog& net_log) { |
+ // If the build is not timely, no certificate is considered compliant |
+ // with CT policy. The reasoning is that, for example, a log might |
+ // have been pulled and is no longer considered valid; thus, a client |
+ // needs up-to-date information about logs to consider certificates to |
+ // be compliant with policy. |
+ bool build_timely = IsBuildTimely(); |
+ ct::CertPolicyCompliance compliance; |
+ if (!build_timely) { |
+ compliance = ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY; |
+ } else { |
+ compliance = CheckCertPolicyCompliance(cert, verified_scts, net_log); |
} |
- result->status = CT_ENOUGH_SCTS; |
-} |
+ NetLog::ParametersCallback net_log_callback = |
+ base::Bind(&NetLogCertComplianceCheckResultCallback, |
+ base::Unretained(cert), build_timely, compliance); |
-} // namespace |
+ net_log.AddEvent(NetLog::TYPE_CERT_CT_COMPLIANCE_CHECKED, net_log_callback); |
+ |
+ return compliance; |
+} |
ct::EVPolicyCompliance CTPolicyEnforcer::DoesConformToCTEVPolicy( |
X509Certificate* cert, |
const ct::EVCertsWhitelist* ev_whitelist, |
const ct::SCTList& verified_scts, |
const BoundNetLog& net_log) { |
- ComplianceDetails details; |
- |
- CheckCTEVPolicyCompliance(cert, ev_whitelist, verified_scts, &details); |
+ EVComplianceDetails details; |
+ // If the build is not timely, no certificate is considered compliant |
+ // with EV policy. The reasoning is that, for example, a log might |
+ // have been pulled and is no longer considered valid; thus, a client |
+ // needs up-to-date information about logs to consider certificates to |
+ // be compliant with policy. |
+ details.build_timely = IsBuildTimely(); |
+ if (!details.build_timely) { |
+ details.status = ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY; |
+ } else { |
+ CheckCTEVPolicyCompliance(cert, ev_whitelist, verified_scts, net_log, |
+ &details); |
+ } |
NetLog::ParametersCallback net_log_callback = |
- base::Bind(&NetLogComplianceCheckResultCallback, base::Unretained(cert), |
+ base::Bind(&NetLogEVComplianceCheckResultCallback, base::Unretained(cert), |
base::Unretained(&details)); |
net_log.AddEvent(NetLog::TYPE_EV_CERT_CT_COMPLIANCE_CHECKED, |
@@ -298,22 +373,9 @@ ct::EVPolicyCompliance CTPolicyEnforcer::DoesConformToCTEVPolicy( |
if (!details.build_timely) |
return ct::EVPolicyCompliance::EV_POLICY_BUILD_NOT_TIMELY; |
- LogCTEVComplianceStatusToUMA(details.status, ev_whitelist); |
+ LogEVPolicyComplianceToUMA(details.status, ev_whitelist); |
- switch (details.status) { |
- case CT_NOT_COMPLIANT: |
- return ct::EVPolicyCompliance::EV_POLICY_NOT_ENOUGH_SCTS; |
- case CT_IN_WHITELIST: |
- return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST; |
- case CT_ENOUGH_SCTS: |
- return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS; |
- case CT_NOT_ENOUGH_DIVERSE_SCTS: |
- return ct::EVPolicyCompliance::EV_POLICY_NOT_DIVERSE_SCTS; |
- case CT_COMPLIANCE_MAX: |
- return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; |
- } |
- |
- return ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; |
+ return details.status; |
} |
} // namespace net |