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"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/path_service.h"
13 #include "components/certificate_reporting/cert_logger.pb.h"
14 #include "net/base/test_data_directory.h"
15 #include "net/cert/cert_status_flags.h"
16 #include "net/ssl/ssl_info.h"
17 #include "net/test/cert_test_util.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
22 using testing::UnorderedElementsAre
;
24 namespace certificate_reporting
{
28 const char kDummyHostname
[] = "dummy.hostname.com";
29 const char kDummyFailureLog
[] = "dummy failure log";
30 const char kTestCertFilename
[] = "test_mail_google_com.pem";
32 const net::CertStatus kCertStatus
=
33 net::CERT_STATUS_COMMON_NAME_INVALID
| net::CERT_STATUS_REVOKED
;
35 const CertLoggerRequest::CertError kFirstReportedCertError
=
36 CertLoggerRequest::ERR_CERT_COMMON_NAME_INVALID
;
37 const CertLoggerRequest::CertError kSecondReportedCertError
=
38 CertLoggerRequest::ERR_CERT_REVOKED
;
40 // Whether to include an unverified certificate chain in the test
41 // SSLInfo. In production code, an unverified cert chain will not be
42 // present if the resource was loaded from cache.
43 enum UnverifiedCertChainStatus
{
44 INCLUDE_UNVERIFIED_CERT_CHAIN
,
45 EXCLUDE_UNVERIFIED_CERT_CHAIN
48 void GetTestSSLInfo(UnverifiedCertChainStatus unverified_cert_chain_status
,
51 net::ImportCertFromFile(net::GetTestCertsDirectory(), kTestCertFilename
);
52 ASSERT_TRUE(info
->cert
);
53 if (unverified_cert_chain_status
== INCLUDE_UNVERIFIED_CERT_CHAIN
) {
54 info
->unverified_cert
= net::ImportCertFromFile(
55 net::GetTestCertsDirectory(), kTestCertFilename
);
56 ASSERT_TRUE(info
->unverified_cert
);
58 info
->is_issued_by_known_root
= true;
59 info
->cert_status
= kCertStatus
;
60 info
->pinning_failure_log
= kDummyFailureLog
;
63 std::string
GetPEMEncodedChain() {
64 base::FilePath cert_path
=
65 net::GetTestCertsDirectory().AppendASCII(kTestCertFilename
);
66 std::string cert_data
;
67 EXPECT_TRUE(base::ReadFileToString(cert_path
, &cert_data
));
71 // Test that a serialized ErrorReport can be deserialized as
72 // a CertLoggerRequest protobuf (which is the format that the receiving
73 // server expects it in) with the right data in it.
74 TEST(ErrorReportTest
, SerializedReportAsProtobuf
) {
75 std::string serialized_report
;
77 ASSERT_NO_FATAL_FAILURE(
78 GetTestSSLInfo(INCLUDE_UNVERIFIED_CERT_CHAIN
, &ssl_info
));
79 ErrorReport
report(kDummyHostname
, ssl_info
);
80 ASSERT_TRUE(report
.Serialize(&serialized_report
));
82 CertLoggerRequest deserialized_report
;
83 ASSERT_TRUE(deserialized_report
.ParseFromString(serialized_report
));
84 EXPECT_EQ(kDummyHostname
, deserialized_report
.hostname());
85 EXPECT_EQ(GetPEMEncodedChain(), deserialized_report
.cert_chain());
86 EXPECT_EQ(GetPEMEncodedChain(), deserialized_report
.unverified_cert_chain());
87 EXPECT_EQ(1, deserialized_report
.pin().size());
88 EXPECT_EQ(kDummyFailureLog
, deserialized_report
.pin().Get(0));
91 deserialized_report
.cert_error(),
92 UnorderedElementsAre(kFirstReportedCertError
, kSecondReportedCertError
));
95 TEST(ErrorReportTest
, SerializedReportAsProtobufWithInterstitialInfo
) {
96 std::string serialized_report
;
98 // Use EXCLUDE_UNVERIFIED_CERT_CHAIN here to exercise the code path
99 // where SSLInfo does not contain the unverified cert chain. (The test
100 // above exercises the path where it does.)
101 ASSERT_NO_FATAL_FAILURE(
102 GetTestSSLInfo(EXCLUDE_UNVERIFIED_CERT_CHAIN
, &ssl_info
));
103 ErrorReport
report(kDummyHostname
, ssl_info
);
105 report
.SetInterstitialInfo(ErrorReport::INTERSTITIAL_CLOCK
,
106 ErrorReport::USER_PROCEEDED
,
107 ErrorReport::INTERSTITIAL_OVERRIDABLE
);
109 ASSERT_TRUE(report
.Serialize(&serialized_report
));
111 CertLoggerRequest deserialized_report
;
112 ASSERT_TRUE(deserialized_report
.ParseFromString(serialized_report
));
113 EXPECT_EQ(kDummyHostname
, deserialized_report
.hostname());
114 EXPECT_EQ(GetPEMEncodedChain(), deserialized_report
.cert_chain());
115 EXPECT_EQ(std::string(), deserialized_report
.unverified_cert_chain());
116 EXPECT_EQ(1, deserialized_report
.pin().size());
117 EXPECT_EQ(kDummyFailureLog
, deserialized_report
.pin().Get(0));
119 EXPECT_EQ(CertLoggerInterstitialInfo::INTERSTITIAL_CLOCK
,
120 deserialized_report
.interstitial_info().interstitial_reason());
121 EXPECT_EQ(true, deserialized_report
.interstitial_info().user_proceeded());
122 EXPECT_EQ(true, deserialized_report
.interstitial_info().overridable());
125 deserialized_report
.cert_error(),
126 UnorderedElementsAre(kFirstReportedCertError
, kSecondReportedCertError
));
129 // Test that a serialized report can be parsed.
130 TEST(ErrorReportTest
, ParseSerializedReport
) {
131 std::string serialized_report
;
133 ASSERT_NO_FATAL_FAILURE(
134 GetTestSSLInfo(INCLUDE_UNVERIFIED_CERT_CHAIN
, &ssl_info
));
135 ErrorReport
report(kDummyHostname
, ssl_info
);
136 EXPECT_EQ(kDummyHostname
, report
.hostname());
137 ASSERT_TRUE(report
.Serialize(&serialized_report
));
140 ASSERT_TRUE(parsed
.InitializeFromString(serialized_report
));
141 EXPECT_EQ(report
.hostname(), parsed
.hostname());
146 } // namespace certificate_reporting