1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_response_info.h"
6
7 #include "base/pickle.h"
8 #include "net/cert/signed_certificate_timestamp.h"
9 #include "net/cert/signed_certificate_timestamp_and_status.h"
10 #include "net/http/http_response_headers.h"
11 #include "net/ssl/ssl_connection_status_flags.h"
12 #include "net/test/cert_test_util.h"
13 #include "net/test/ct_test_util.h"
14 #include "net/test/test_data_directory.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace net {
19
20 namespace {
21
22 class HttpResponseInfoTest : public testing::Test {
23 protected:
SetUp()24 void SetUp() override {
25 response_info_.headers = base::MakeRefCounted<HttpResponseHeaders>("");
26 }
27
PickleAndRestore(const HttpResponseInfo & response_info,HttpResponseInfo * restored_response_info) const28 void PickleAndRestore(const HttpResponseInfo& response_info,
29 HttpResponseInfo* restored_response_info) const {
30 base::Pickle pickle;
31 response_info.Persist(&pickle, false, false);
32 bool truncated = false;
33 EXPECT_TRUE(restored_response_info->InitFromPickle(pickle, &truncated));
34 }
35
36 HttpResponseInfo response_info_;
37 };
38
TEST_F(HttpResponseInfoTest,UnusedSincePrefetchDefault)39 TEST_F(HttpResponseInfoTest, UnusedSincePrefetchDefault) {
40 EXPECT_FALSE(response_info_.unused_since_prefetch);
41 }
42
TEST_F(HttpResponseInfoTest,UnusedSincePrefetchCopy)43 TEST_F(HttpResponseInfoTest, UnusedSincePrefetchCopy) {
44 response_info_.unused_since_prefetch = true;
45 HttpResponseInfo response_info_clone(response_info_);
46 EXPECT_TRUE(response_info_clone.unused_since_prefetch);
47 }
48
TEST_F(HttpResponseInfoTest,UnusedSincePrefetchPersistFalse)49 TEST_F(HttpResponseInfoTest, UnusedSincePrefetchPersistFalse) {
50 HttpResponseInfo restored_response_info;
51 PickleAndRestore(response_info_, &restored_response_info);
52 EXPECT_FALSE(restored_response_info.unused_since_prefetch);
53 }
54
TEST_F(HttpResponseInfoTest,UnusedSincePrefetchPersistTrue)55 TEST_F(HttpResponseInfoTest, UnusedSincePrefetchPersistTrue) {
56 response_info_.unused_since_prefetch = true;
57 HttpResponseInfo restored_response_info;
58 PickleAndRestore(response_info_, &restored_response_info);
59 EXPECT_TRUE(restored_response_info.unused_since_prefetch);
60 }
61
TEST_F(HttpResponseInfoTest,PKPBypassPersistTrue)62 TEST_F(HttpResponseInfoTest, PKPBypassPersistTrue) {
63 response_info_.ssl_info.pkp_bypassed = true;
64 HttpResponseInfo restored_response_info;
65 PickleAndRestore(response_info_, &restored_response_info);
66 EXPECT_TRUE(restored_response_info.ssl_info.pkp_bypassed);
67 }
68
TEST_F(HttpResponseInfoTest,PKPBypassPersistFalse)69 TEST_F(HttpResponseInfoTest, PKPBypassPersistFalse) {
70 response_info_.ssl_info.pkp_bypassed = false;
71 HttpResponseInfo restored_response_info;
72 PickleAndRestore(response_info_, &restored_response_info);
73 EXPECT_FALSE(restored_response_info.ssl_info.pkp_bypassed);
74 }
75
TEST_F(HttpResponseInfoTest,AsyncRevalidationRequestedDefault)76 TEST_F(HttpResponseInfoTest, AsyncRevalidationRequestedDefault) {
77 EXPECT_FALSE(response_info_.async_revalidation_requested);
78 }
79
TEST_F(HttpResponseInfoTest,AsyncRevalidationRequestedCopy)80 TEST_F(HttpResponseInfoTest, AsyncRevalidationRequestedCopy) {
81 response_info_.async_revalidation_requested = true;
82 net::HttpResponseInfo response_info_clone(response_info_);
83 EXPECT_TRUE(response_info_clone.async_revalidation_requested);
84 }
85
TEST_F(HttpResponseInfoTest,AsyncRevalidationRequestedAssign)86 TEST_F(HttpResponseInfoTest, AsyncRevalidationRequestedAssign) {
87 response_info_.async_revalidation_requested = true;
88 net::HttpResponseInfo response_info_clone;
89 response_info_clone = response_info_;
90 EXPECT_TRUE(response_info_clone.async_revalidation_requested);
91 }
92
TEST_F(HttpResponseInfoTest,AsyncRevalidationRequestedNotPersisted)93 TEST_F(HttpResponseInfoTest, AsyncRevalidationRequestedNotPersisted) {
94 response_info_.async_revalidation_requested = true;
95 net::HttpResponseInfo restored_response_info;
96 PickleAndRestore(response_info_, &restored_response_info);
97 EXPECT_FALSE(restored_response_info.async_revalidation_requested);
98 }
99
TEST_F(HttpResponseInfoTest,StaleRevalidationTimeoutDefault)100 TEST_F(HttpResponseInfoTest, StaleRevalidationTimeoutDefault) {
101 EXPECT_TRUE(response_info_.stale_revalidate_timeout.is_null());
102 }
103
TEST_F(HttpResponseInfoTest,StaleRevalidationTimeoutCopy)104 TEST_F(HttpResponseInfoTest, StaleRevalidationTimeoutCopy) {
105 base::Time test_time = base::Time::FromSecondsSinceUnixEpoch(1000);
106 response_info_.stale_revalidate_timeout = test_time;
107 HttpResponseInfo response_info_clone(response_info_);
108 EXPECT_EQ(test_time, response_info_clone.stale_revalidate_timeout);
109 }
110
TEST_F(HttpResponseInfoTest,StaleRevalidationTimeoutRestoreValue)111 TEST_F(HttpResponseInfoTest, StaleRevalidationTimeoutRestoreValue) {
112 base::Time test_time = base::Time::FromSecondsSinceUnixEpoch(1000);
113 response_info_.stale_revalidate_timeout = test_time;
114 HttpResponseInfo restored_response_info;
115 PickleAndRestore(response_info_, &restored_response_info);
116 EXPECT_EQ(test_time, restored_response_info.stale_revalidate_timeout);
117 }
118
TEST_F(HttpResponseInfoTest,StaleRevalidationTimeoutRestoreNoValue)119 TEST_F(HttpResponseInfoTest, StaleRevalidationTimeoutRestoreNoValue) {
120 EXPECT_TRUE(response_info_.stale_revalidate_timeout.is_null());
121 HttpResponseInfo restored_response_info;
122 PickleAndRestore(response_info_, &restored_response_info);
123 EXPECT_TRUE(restored_response_info.stale_revalidate_timeout.is_null());
124 }
125
126 // Test that key_exchange_group is preserved for ECDHE ciphers.
TEST_F(HttpResponseInfoTest,KeyExchangeGroupECDHE)127 TEST_F(HttpResponseInfoTest, KeyExchangeGroupECDHE) {
128 response_info_.ssl_info.cert =
129 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
130 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2,
131 &response_info_.ssl_info.connection_status);
132 SSLConnectionStatusSetCipherSuite(
133 0xcca8 /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */,
134 &response_info_.ssl_info.connection_status);
135 response_info_.ssl_info.key_exchange_group = 23; // X25519
136 net::HttpResponseInfo restored_response_info;
137 PickleAndRestore(response_info_, &restored_response_info);
138 EXPECT_EQ(23, restored_response_info.ssl_info.key_exchange_group);
139 }
140
141 // Test that key_exchange_group is preserved for TLS 1.3.
TEST_F(HttpResponseInfoTest,KeyExchangeGroupTLS13)142 TEST_F(HttpResponseInfoTest, KeyExchangeGroupTLS13) {
143 response_info_.ssl_info.cert =
144 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
145 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_3,
146 &response_info_.ssl_info.connection_status);
147 SSLConnectionStatusSetCipherSuite(0x1303 /* TLS_CHACHA20_POLY1305_SHA256 */,
148 &response_info_.ssl_info.connection_status);
149 response_info_.ssl_info.key_exchange_group = 23; // X25519
150 net::HttpResponseInfo restored_response_info;
151 PickleAndRestore(response_info_, &restored_response_info);
152 EXPECT_EQ(23, restored_response_info.ssl_info.key_exchange_group);
153 }
154
155 // Test that key_exchange_group is discarded for non-ECDHE ciphers prior to TLS
156 // 1.3, to account for the historical key_exchange_info field. See
157 // https://crbug.com/639421.
TEST_F(HttpResponseInfoTest,LegacyKeyExchangeInfoDHE)158 TEST_F(HttpResponseInfoTest, LegacyKeyExchangeInfoDHE) {
159 response_info_.ssl_info.cert =
160 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
161 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2,
162 &response_info_.ssl_info.connection_status);
163 SSLConnectionStatusSetCipherSuite(
164 0x0093 /* TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 */,
165 &response_info_.ssl_info.connection_status);
166 response_info_.ssl_info.key_exchange_group = 1024;
167 net::HttpResponseInfo restored_response_info;
168 PickleAndRestore(response_info_, &restored_response_info);
169 EXPECT_EQ(0, restored_response_info.ssl_info.key_exchange_group);
170 }
171
172 // Test that key_exchange_group is discarded for unknown ciphers prior to TLS
173 // 1.3, to account for the historical key_exchange_info field. See
174 // https://crbug.com/639421.
TEST_F(HttpResponseInfoTest,LegacyKeyExchangeInfoUnknown)175 TEST_F(HttpResponseInfoTest, LegacyKeyExchangeInfoUnknown) {
176 response_info_.ssl_info.cert =
177 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
178 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2,
179 &response_info_.ssl_info.connection_status);
180 SSLConnectionStatusSetCipherSuite(0xffff,
181 &response_info_.ssl_info.connection_status);
182 response_info_.ssl_info.key_exchange_group = 1024;
183 net::HttpResponseInfo restored_response_info;
184 PickleAndRestore(response_info_, &restored_response_info);
185 EXPECT_EQ(0, restored_response_info.ssl_info.key_exchange_group);
186 }
187
188 // Test that peer_signature_algorithm is preserved.
TEST_F(HttpResponseInfoTest,PeerSignatureAlgorithm)189 TEST_F(HttpResponseInfoTest, PeerSignatureAlgorithm) {
190 response_info_.ssl_info.cert =
191 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
192 response_info_.ssl_info.peer_signature_algorithm =
193 0x0804; // rsa_pss_rsae_sha256
194 net::HttpResponseInfo restored_response_info;
195 PickleAndRestore(response_info_, &restored_response_info);
196 EXPECT_EQ(0x0804, restored_response_info.ssl_info.peer_signature_algorithm);
197 }
198
199 // Test that encrypted_client_hello is preserved.
TEST_F(HttpResponseInfoTest,EncryptedClientHello)200 TEST_F(HttpResponseInfoTest, EncryptedClientHello) {
201 response_info_.ssl_info.cert =
202 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
203 {
204 net::HttpResponseInfo restored_response_info;
205 PickleAndRestore(response_info_, &restored_response_info);
206 EXPECT_FALSE(restored_response_info.ssl_info.encrypted_client_hello);
207 }
208
209 response_info_.ssl_info.encrypted_client_hello = true;
210 {
211 net::HttpResponseInfo restored_response_info;
212 PickleAndRestore(response_info_, &restored_response_info);
213 EXPECT_TRUE(restored_response_info.ssl_info.encrypted_client_hello);
214 }
215 }
216
217 // Tests that cache entries loaded over SSLv3 (no longer supported) are dropped.
TEST_F(HttpResponseInfoTest,FailsInitFromPickleWithSSLV3)218 TEST_F(HttpResponseInfoTest, FailsInitFromPickleWithSSLV3) {
219 // A valid certificate is needed for ssl_info.is_valid() to be true.
220 response_info_.ssl_info.cert =
221 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
222
223 // Non-SSLv3 versions should succeed.
224 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2,
225 &response_info_.ssl_info.connection_status);
226 base::Pickle tls12_pickle;
227 response_info_.Persist(&tls12_pickle, false, false);
228 bool truncated = false;
229 net::HttpResponseInfo restored_tls12_response_info;
230 EXPECT_TRUE(
231 restored_tls12_response_info.InitFromPickle(tls12_pickle, &truncated));
232 EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_2,
233 SSLConnectionStatusToVersion(
234 restored_tls12_response_info.ssl_info.connection_status));
235 EXPECT_FALSE(truncated);
236
237 // SSLv3 should fail.
238 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
239 &response_info_.ssl_info.connection_status);
240 base::Pickle ssl3_pickle;
241 response_info_.Persist(&ssl3_pickle, false, false);
242 net::HttpResponseInfo restored_ssl3_response_info;
243 EXPECT_FALSE(
244 restored_ssl3_response_info.InitFromPickle(ssl3_pickle, &truncated));
245 }
246
247 // Test that `dns_aliases` is preserved.
TEST_F(HttpResponseInfoTest,DnsAliases)248 TEST_F(HttpResponseInfoTest, DnsAliases) {
249 response_info_.dns_aliases = {"alias1", "alias2", "alias3"};
250 net::HttpResponseInfo restored_response_info;
251 PickleAndRestore(response_info_, &restored_response_info);
252 EXPECT_THAT(restored_response_info.dns_aliases,
253 testing::ElementsAre("alias1", "alias2", "alias3"));
254 }
255
256 // Test that an empty `dns_aliases` is preserved and doesn't throw an error.
TEST_F(HttpResponseInfoTest,EmptyDnsAliases)257 TEST_F(HttpResponseInfoTest, EmptyDnsAliases) {
258 response_info_.dns_aliases = {};
259 net::HttpResponseInfo restored_response_info;
260 PickleAndRestore(response_info_, &restored_response_info);
261 EXPECT_TRUE(restored_response_info.dns_aliases.empty());
262 }
263
264 // Test that `browser_run_id` is preserved.
TEST_F(HttpResponseInfoTest,BrowserRunId)265 TEST_F(HttpResponseInfoTest, BrowserRunId) {
266 response_info_.browser_run_id = 1;
267 net::HttpResponseInfo restored_response_info;
268 PickleAndRestore(response_info_, &restored_response_info);
269 EXPECT_EQ(1, restored_response_info.browser_run_id);
270 }
271
272 // Test that an empty `browser_run_id` is preserved and doesn't throw an error.
TEST_F(HttpResponseInfoTest,EmptyBrowserRunId)273 TEST_F(HttpResponseInfoTest, EmptyBrowserRunId) {
274 response_info_.browser_run_id = std::nullopt;
275 net::HttpResponseInfo restored_response_info;
276 PickleAndRestore(response_info_, &restored_response_info);
277 EXPECT_FALSE(restored_response_info.browser_run_id.has_value());
278 }
279
280 // Test that did_use_shared_dictionary is preserved .
TEST_F(HttpResponseInfoTest,DidUseSharedDictionary)281 TEST_F(HttpResponseInfoTest, DidUseSharedDictionary) {
282 response_info_.did_use_shared_dictionary = true;
283 net::HttpResponseInfo restored_response_info;
284 PickleAndRestore(response_info_, &restored_response_info);
285 EXPECT_TRUE(restored_response_info.did_use_shared_dictionary);
286 }
287
288 } // namespace
289
290 } // namespace net
291