1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/certificate_reporting/error_report.h"
9 #include "base/stl_util.h"
10 #include "base/strings/string_util.h"
11 #include "base/time/time.h"
12 #include "components/certificate_reporting/cert_logger.pb.h"
13 #include "net/cert/cert_status_flags.h"
14 #include "net/cert/x509_certificate.h"
15 #include "net/ssl/ssl_info.h"
17 namespace certificate_reporting
{
21 void AddCertStatusToReportErrors(net::CertStatus cert_status
,
22 CertLoggerRequest
* report
) {
23 #define COPY_CERT_STATUS(error) RENAME_CERT_STATUS(error, CERT_##error)
24 #define RENAME_CERT_STATUS(status_error, logger_error) \
25 if (cert_status & net::CERT_STATUS_##status_error) \
26 report->add_cert_error(CertLoggerRequest::ERR_##logger_error);
28 COPY_CERT_STATUS(REVOKED
)
29 COPY_CERT_STATUS(INVALID
)
30 RENAME_CERT_STATUS(PINNED_KEY_MISSING
, SSL_PINNED_KEY_NOT_IN_CERT_CHAIN
)
31 COPY_CERT_STATUS(AUTHORITY_INVALID
)
32 COPY_CERT_STATUS(COMMON_NAME_INVALID
)
33 COPY_CERT_STATUS(NON_UNIQUE_NAME
)
34 COPY_CERT_STATUS(NAME_CONSTRAINT_VIOLATION
)
35 COPY_CERT_STATUS(WEAK_SIGNATURE_ALGORITHM
)
36 COPY_CERT_STATUS(WEAK_KEY
)
37 COPY_CERT_STATUS(DATE_INVALID
)
38 COPY_CERT_STATUS(VALIDITY_TOO_LONG
)
39 COPY_CERT_STATUS(UNABLE_TO_CHECK_REVOCATION
)
40 COPY_CERT_STATUS(NO_REVOCATION_MECHANISM
)
42 #undef RENAME_CERT_STATUS
43 #undef COPY_CERT_STATUS
46 bool CertificateChainToString(scoped_refptr
<net::X509Certificate
> cert
,
47 std::string
* result
) {
48 std::vector
<std::string
> pem_encoded_chain
;
49 if (!cert
->GetPEMEncodedChain(&pem_encoded_chain
))
52 *result
= base::JoinString(pem_encoded_chain
, "");
58 ErrorReport::ErrorReport() : cert_report_(new CertLoggerRequest()) {}
60 ErrorReport::ErrorReport(const std::string
& hostname
,
61 const net::SSLInfo
& ssl_info
)
62 : cert_report_(new CertLoggerRequest()) {
63 base::Time now
= base::Time::Now();
64 cert_report_
->set_time_usec(now
.ToInternalValue());
65 cert_report_
->set_hostname(hostname
);
67 if (!CertificateChainToString(ssl_info
.cert
,
68 cert_report_
->mutable_cert_chain())) {
69 LOG(ERROR
) << "Could not get PEM encoded chain.";
72 if (ssl_info
.unverified_cert
&&
73 !CertificateChainToString(
74 ssl_info
.unverified_cert
,
75 cert_report_
->mutable_unverified_cert_chain())) {
76 LOG(ERROR
) << "Could not get PEM encoded unverified certificate chain.";
79 cert_report_
->add_pin(ssl_info
.pinning_failure_log
);
81 AddCertStatusToReportErrors(ssl_info
.cert_status
, cert_report_
.get());
84 ErrorReport::~ErrorReport() {}
86 bool ErrorReport::InitializeFromString(const std::string
& serialized_report
) {
87 return cert_report_
->ParseFromString(serialized_report
);
90 bool ErrorReport::Serialize(std::string
* output
) const {
91 return cert_report_
->SerializeToString(output
);
94 void ErrorReport::SetInterstitialInfo(
95 const InterstitialReason
& interstitial_reason
,
96 const ProceedDecision
& proceed_decision
,
97 const Overridable
& overridable
) {
98 CertLoggerInterstitialInfo
* interstitial_info
=
99 cert_report_
->mutable_interstitial_info();
101 switch (interstitial_reason
) {
102 case INTERSTITIAL_SSL
:
103 interstitial_info
->set_interstitial_reason(
104 CertLoggerInterstitialInfo::INTERSTITIAL_SSL
);
106 case INTERSTITIAL_CAPTIVE_PORTAL
:
107 interstitial_info
->set_interstitial_reason(
108 CertLoggerInterstitialInfo::INTERSTITIAL_CAPTIVE_PORTAL
);
110 case INTERSTITIAL_CLOCK
:
111 interstitial_info
->set_interstitial_reason(
112 CertLoggerInterstitialInfo::INTERSTITIAL_CLOCK
);
116 interstitial_info
->set_user_proceeded(proceed_decision
== USER_PROCEEDED
);
117 interstitial_info
->set_overridable(overridable
== INTERSTITIAL_OVERRIDABLE
);
120 const std::string
& ErrorReport::hostname() const {
121 return cert_report_
->hostname();
124 } // namespace certificate_reporting