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 "chrome/browser/ssl/certificate_error_report.h"
9 #include "base/stl_util.h"
10 #include "base/strings/string_util.h"
11 #include "base/time/time.h"
12 #include "chrome/browser/ssl/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"
19 void AddCertStatusToReportErrors(net::CertStatus cert_status
,
20 CertLoggerRequest
* report
) {
21 #define COPY_CERT_STATUS(error) RENAME_CERT_STATUS(error, CERT_##error)
22 #define RENAME_CERT_STATUS(status_error, logger_error) \
23 if (cert_status & net::CERT_STATUS_##status_error) \
24 report->add_cert_error(CertLoggerRequest::ERR_##logger_error);
26 COPY_CERT_STATUS(REVOKED
)
27 COPY_CERT_STATUS(INVALID
)
28 RENAME_CERT_STATUS(PINNED_KEY_MISSING
, SSL_PINNED_KEY_NOT_IN_CERT_CHAIN
)
29 COPY_CERT_STATUS(AUTHORITY_INVALID
)
30 COPY_CERT_STATUS(COMMON_NAME_INVALID
)
31 COPY_CERT_STATUS(NON_UNIQUE_NAME
)
32 COPY_CERT_STATUS(NAME_CONSTRAINT_VIOLATION
)
33 COPY_CERT_STATUS(WEAK_SIGNATURE_ALGORITHM
)
34 COPY_CERT_STATUS(WEAK_KEY
)
35 COPY_CERT_STATUS(DATE_INVALID
)
36 COPY_CERT_STATUS(VALIDITY_TOO_LONG
)
37 COPY_CERT_STATUS(UNABLE_TO_CHECK_REVOCATION
)
38 COPY_CERT_STATUS(NO_REVOCATION_MECHANISM
)
40 #undef RENAME_CERT_STATUS
41 #undef COPY_CERT_STATUS
44 bool CertificateChainToString(scoped_refptr
<net::X509Certificate
> cert
,
45 std::string
* result
) {
46 std::vector
<std::string
> pem_encoded_chain
;
47 if (!cert
->GetPEMEncodedChain(&pem_encoded_chain
))
50 *result
= base::JoinString(pem_encoded_chain
, "");
56 CertificateErrorReport::CertificateErrorReport()
57 : cert_report_(new CertLoggerRequest()) {
60 CertificateErrorReport::CertificateErrorReport(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 CertificateErrorReport::~CertificateErrorReport() {
87 bool CertificateErrorReport::InitializeFromString(
88 const std::string
& serialized_report
) {
89 return cert_report_
->ParseFromString(serialized_report
);
92 bool CertificateErrorReport::Serialize(std::string
* output
) const {
93 return cert_report_
->SerializeToString(output
);
96 void CertificateErrorReport::SetInterstitialInfo(
97 const InterstitialReason
& interstitial_reason
,
98 const ProceedDecision
& proceed_decision
,
99 const Overridable
& overridable
) {
100 CertLoggerInterstitialInfo
* interstitial_info
=
101 cert_report_
->mutable_interstitial_info();
103 switch (interstitial_reason
) {
104 case INTERSTITIAL_SSL
:
105 interstitial_info
->set_interstitial_reason(
106 CertLoggerInterstitialInfo::INTERSTITIAL_SSL
);
108 case INTERSTITIAL_CAPTIVE_PORTAL
:
109 interstitial_info
->set_interstitial_reason(
110 CertLoggerInterstitialInfo::INTERSTITIAL_CAPTIVE_PORTAL
);
112 case INTERSTITIAL_CLOCK
:
113 interstitial_info
->set_interstitial_reason(
114 CertLoggerInterstitialInfo::INTERSTITIAL_CLOCK
);
118 interstitial_info
->set_user_proceeded(proceed_decision
== USER_PROCEEDED
);
119 interstitial_info
->set_overridable(overridable
== INTERSTITIAL_OVERRIDABLE
);
122 const std::string
& CertificateErrorReport::hostname() const {
123 return cert_report_
->hostname();