1 // Copyright 2012 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/logging.h"
8 #include "base/numerics/safe_conversions.h"
9 #include "base/pickle.h"
10 #include "base/time/time.h"
11 #include "net/base/net_errors.h"
12 #include "net/cert/sct_status_flags.h"
13 #include "net/cert/signed_certificate_timestamp.h"
14 #include "net/cert/x509_certificate.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/ssl/ssl_cert_request_info.h"
17 #include "net/ssl/ssl_connection_status_flags.h"
18 #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h"
19 #include "third_party/abseil-cpp/absl/types/optional.h"
20 #include "third_party/boringssl/src/include/openssl/ssl.h"
21
22 using base::Time;
23
24 namespace net {
25
26 namespace {
27
KeyExchangeGroupIsValid(int ssl_connection_status)28 bool KeyExchangeGroupIsValid(int ssl_connection_status) {
29 // TLS 1.3 and later always treat the field correctly.
30 if (SSLConnectionStatusToVersion(ssl_connection_status) >=
31 SSL_CONNECTION_VERSION_TLS1_3) {
32 return true;
33 }
34
35 // Prior to TLS 1.3, only ECDHE ciphers have groups.
36 const SSL_CIPHER* cipher = SSL_get_cipher_by_value(
37 SSLConnectionStatusToCipherSuite(ssl_connection_status));
38 return cipher && SSL_CIPHER_get_kx_nid(cipher) == NID_kx_ecdhe;
39 }
40
41 } // namespace
42
43 // These values can be bit-wise combined to form the flags field of the
44 // serialized HttpResponseInfo.
45 enum {
46 // The version of the response info used when persisting response info.
47 RESPONSE_INFO_VERSION = 3,
48
49 // The minimum version supported for deserializing response info.
50 RESPONSE_INFO_MINIMUM_VERSION = 3,
51
52 // We reserve up to 8 bits for the version number.
53 RESPONSE_INFO_VERSION_MASK = 0xFF,
54
55 // This bit is set if the response info has a cert at the end.
56 // Version 1 serialized only the end-entity certificate, while subsequent
57 // versions include the available certificate chain.
58 RESPONSE_INFO_HAS_CERT = 1 << 8,
59
60 // This bit was historically set if the response info had a security-bits
61 // field (security strength, in bits, of the SSL connection) at the end.
62 RESPONSE_INFO_HAS_SECURITY_BITS = 1 << 9,
63
64 // This bit is set if the response info has a cert status at the end.
65 RESPONSE_INFO_HAS_CERT_STATUS = 1 << 10,
66
67 // This bit is set if the response info has vary header data.
68 RESPONSE_INFO_HAS_VARY_DATA = 1 << 11,
69
70 // This bit is set if the request was cancelled before completion.
71 RESPONSE_INFO_TRUNCATED = 1 << 12,
72
73 // This bit is set if the response was received via SPDY.
74 RESPONSE_INFO_WAS_SPDY = 1 << 13,
75
76 // This bit is set if the request has ALPN negotiated.
77 RESPONSE_INFO_WAS_ALPN = 1 << 14,
78
79 // This bit is set if the request was fetched via an explicit proxy.
80 RESPONSE_INFO_WAS_PROXY = 1 << 15,
81
82 // This bit is set if the response info has an SSL connection status field.
83 // This contains the ciphersuite used to fetch the resource as well as the
84 // protocol version, compression method and whether SSLv3 fallback was used.
85 RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS = 1 << 16,
86
87 // This bit is set if the response info has protocol version.
88 RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL = 1 << 17,
89
90 // This bit is set if the response info has connection info.
91 RESPONSE_INFO_HAS_CONNECTION_INFO = 1 << 18,
92
93 // This bit is set if the request has http authentication.
94 RESPONSE_INFO_USE_HTTP_AUTHENTICATION = 1 << 19,
95
96 // This bit is set if ssl_info has SCTs.
97 RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS = 1 << 20,
98
99 RESPONSE_INFO_UNUSED_SINCE_PREFETCH = 1 << 21,
100
101 // This bit is set if the response has a key exchange group.
102 RESPONSE_INFO_HAS_KEY_EXCHANGE_GROUP = 1 << 22,
103
104 // This bit is set if ssl_info recorded that PKP was bypassed due to a local
105 // trust anchor.
106 RESPONSE_INFO_PKP_BYPASSED = 1 << 23,
107
108 // This bit is set if stale_revalidate_time is stored.
109 RESPONSE_INFO_HAS_STALENESS = 1 << 24,
110
111 // This bit is set if the response has a peer signature algorithm.
112 RESPONSE_INFO_HAS_PEER_SIGNATURE_ALGORITHM = 1 << 25,
113
114 // This bit is set if the response is a prefetch whose reuse should be
115 // restricted in some way.
116 RESPONSE_INFO_RESTRICTED_PREFETCH = 1 << 26,
117
118 // This bit is set if the response has a nonempty `dns_aliases` entry.
119 RESPONSE_INFO_HAS_DNS_ALIASES = 1 << 27,
120
121 // This bit is now unused. It may be set on existing entries. Previously it
122 // was set for an entry in the single-keyed cache that had been marked
123 // unusable due to the cache transparency checksum not matching.
124 RESPONSE_INFO_UNUSED_WAS_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE = 1 << 28,
125
126 // This bit is set if the response has `encrypted_client_hello` set.
127 RESPONSE_INFO_ENCRYPTED_CLIENT_HELLO = 1 << 29,
128
129 // This bit is set if the response has `browser_run_id` set.
130 RESPONSE_INFO_BROWSER_RUN_ID = 1 << 30,
131
132 // This bit is set if the response has extra bit set.
133 RESPONSE_INFO_HAS_EXTRA_FLAGS = 1 << 31,
134 };
135
136 // These values can be bit-wise combined to form the extra flags field of the
137 // serialized HttpResponseInfo.
138 enum {
139 // This bit is set if the request usd a shared dictionary for decoding its
140 // body.
141 RESPONSE_EXTRA_INFO_DID_USE_SHARED_DICTIONARY = 1,
142 };
143
144 HttpResponseInfo::HttpResponseInfo() = default;
145
146 HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs) = default;
147
148 HttpResponseInfo::~HttpResponseInfo() = default;
149
150 HttpResponseInfo& HttpResponseInfo::operator=(const HttpResponseInfo& rhs) =
151 default;
152
InitFromPickle(const base::Pickle & pickle,bool * response_truncated)153 bool HttpResponseInfo::InitFromPickle(const base::Pickle& pickle,
154 bool* response_truncated) {
155 base::PickleIterator iter(pickle);
156
157 // Read flags and verify version
158 int flags;
159 int extra_flags = 0;
160 if (!iter.ReadInt(&flags))
161 return false;
162 if (flags & RESPONSE_INFO_HAS_EXTRA_FLAGS) {
163 if (!iter.ReadInt(&extra_flags)) {
164 return false;
165 }
166 }
167 int version = flags & RESPONSE_INFO_VERSION_MASK;
168 if (version < RESPONSE_INFO_MINIMUM_VERSION ||
169 version > RESPONSE_INFO_VERSION) {
170 DLOG(ERROR) << "unexpected response info version: " << version;
171 return false;
172 }
173
174 // Read request-time
175 int64_t time_val;
176 if (!iter.ReadInt64(&time_val))
177 return false;
178 request_time = Time::FromInternalValue(time_val);
179 was_cached = true; // Set status to show cache resurrection.
180
181 // Read response-time
182 if (!iter.ReadInt64(&time_val))
183 return false;
184 response_time = Time::FromInternalValue(time_val);
185
186 // Read response-headers
187 headers = base::MakeRefCounted<HttpResponseHeaders>(&iter);
188 if (headers->response_code() == -1)
189 return false;
190
191 // Read ssl-info
192 if (flags & RESPONSE_INFO_HAS_CERT) {
193 ssl_info.cert = X509Certificate::CreateFromPickle(&iter);
194 if (!ssl_info.cert.get())
195 return false;
196 }
197 if (flags & RESPONSE_INFO_HAS_CERT_STATUS) {
198 CertStatus cert_status;
199 if (!iter.ReadUInt32(&cert_status))
200 return false;
201 ssl_info.cert_status = cert_status;
202 }
203 if (flags & RESPONSE_INFO_HAS_SECURITY_BITS) {
204 // The security_bits field has been removed from ssl_info. For backwards
205 // compatibility, we should still read the value out of iter.
206 int security_bits;
207 if (!iter.ReadInt(&security_bits))
208 return false;
209 }
210
211 if (flags & RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS) {
212 int connection_status;
213 if (!iter.ReadInt(&connection_status))
214 return false;
215
216 // SSLv3 is gone, so drop cached entries that were loaded over SSLv3.
217 if (SSLConnectionStatusToVersion(connection_status) ==
218 SSL_CONNECTION_VERSION_SSL3) {
219 return false;
220 }
221 ssl_info.connection_status = connection_status;
222 }
223
224 // Signed Certificate Timestamps are no longer persisted to the cache, so
225 // ignore them when reading them out.
226 if (flags & RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS) {
227 int num_scts;
228 if (!iter.ReadInt(&num_scts))
229 return false;
230 for (int i = 0; i < num_scts; ++i) {
231 scoped_refptr<ct::SignedCertificateTimestamp> sct(
232 ct::SignedCertificateTimestamp::CreateFromPickle(&iter));
233 uint16_t status;
234 if (!sct.get() || !iter.ReadUInt16(&status))
235 return false;
236 }
237 }
238
239 // Read vary-data
240 if (flags & RESPONSE_INFO_HAS_VARY_DATA) {
241 if (!vary_data.InitFromPickle(&iter))
242 return false;
243 }
244
245 // Read socket_address.
246 std::string socket_address_host;
247 if (!iter.ReadString(&socket_address_host))
248 return false;
249 // If the host was written, we always expect the port to follow.
250 uint16_t socket_address_port;
251 if (!iter.ReadUInt16(&socket_address_port))
252 return false;
253
254 IPAddress ip_address;
255 if (ip_address.AssignFromIPLiteral(socket_address_host)) {
256 remote_endpoint = IPEndPoint(ip_address, socket_address_port);
257 } else if (ParseURLHostnameToAddress(socket_address_host, &ip_address)) {
258 remote_endpoint = IPEndPoint(ip_address, socket_address_port);
259 }
260
261 // Read protocol-version.
262 if (flags & RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL) {
263 if (!iter.ReadString(&alpn_negotiated_protocol))
264 return false;
265 }
266
267 // Read connection info.
268 if (flags & RESPONSE_INFO_HAS_CONNECTION_INFO) {
269 int value;
270 if (!iter.ReadInt(&value))
271 return false;
272
273 if (value > static_cast<int>(HttpConnectionInfo::kUNKNOWN) &&
274 value <= static_cast<int>(HttpConnectionInfo::kMaxValue)) {
275 connection_info = static_cast<HttpConnectionInfo>(value);
276 }
277 }
278
279 // Read key_exchange_group
280 if (flags & RESPONSE_INFO_HAS_KEY_EXCHANGE_GROUP) {
281 int key_exchange_group;
282 if (!iter.ReadInt(&key_exchange_group))
283 return false;
284
285 // Historically, the key_exchange_group field was key_exchange_info which
286 // conflated a number of different values based on the cipher suite, so some
287 // values must be discarded. See https://crbug.com/639421.
288 if (KeyExchangeGroupIsValid(ssl_info.connection_status))
289 ssl_info.key_exchange_group = key_exchange_group;
290 }
291
292 // Read staleness time.
293 if (flags & RESPONSE_INFO_HAS_STALENESS) {
294 if (!iter.ReadInt64(&time_val))
295 return false;
296 stale_revalidate_timeout = base::Time() + base::Microseconds(time_val);
297 }
298
299 was_fetched_via_spdy = (flags & RESPONSE_INFO_WAS_SPDY) != 0;
300
301 was_alpn_negotiated = (flags & RESPONSE_INFO_WAS_ALPN) != 0;
302
303 was_fetched_via_proxy = (flags & RESPONSE_INFO_WAS_PROXY) != 0;
304
305 *response_truncated = (flags & RESPONSE_INFO_TRUNCATED) != 0;
306
307 did_use_http_auth = (flags & RESPONSE_INFO_USE_HTTP_AUTHENTICATION) != 0;
308
309 unused_since_prefetch = (flags & RESPONSE_INFO_UNUSED_SINCE_PREFETCH) != 0;
310
311 restricted_prefetch = (flags & RESPONSE_INFO_RESTRICTED_PREFETCH) != 0;
312
313 // RESPONSE_INFO_UNUSED_WAS_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE is unused.
314
315 ssl_info.pkp_bypassed = (flags & RESPONSE_INFO_PKP_BYPASSED) != 0;
316
317 // Read peer_signature_algorithm.
318 if (flags & RESPONSE_INFO_HAS_PEER_SIGNATURE_ALGORITHM) {
319 int peer_signature_algorithm;
320 if (!iter.ReadInt(&peer_signature_algorithm) ||
321 !base::IsValueInRangeForNumericType<uint16_t>(
322 peer_signature_algorithm)) {
323 return false;
324 }
325 ssl_info.peer_signature_algorithm =
326 base::checked_cast<uint16_t>(peer_signature_algorithm);
327 }
328
329 // Read DNS aliases.
330 if (flags & RESPONSE_INFO_HAS_DNS_ALIASES) {
331 int num_aliases;
332 if (!iter.ReadInt(&num_aliases))
333 return false;
334
335 std::string alias;
336 for (int i = 0; i < num_aliases; i++) {
337 if (!iter.ReadString(&alias))
338 return false;
339 dns_aliases.insert(alias);
340 }
341 }
342
343 ssl_info.encrypted_client_hello =
344 (flags & RESPONSE_INFO_ENCRYPTED_CLIENT_HELLO) != 0;
345
346 // Read browser_run_id.
347 if (flags & RESPONSE_INFO_BROWSER_RUN_ID) {
348 int64_t id;
349 if (!iter.ReadInt64(&id))
350 return false;
351 browser_run_id = absl::make_optional(id);
352 }
353
354 did_use_shared_dictionary =
355 (extra_flags & RESPONSE_EXTRA_INFO_DID_USE_SHARED_DICTIONARY) != 0;
356 return true;
357 }
358
Persist(base::Pickle * pickle,bool skip_transient_headers,bool response_truncated) const359 void HttpResponseInfo::Persist(base::Pickle* pickle,
360 bool skip_transient_headers,
361 bool response_truncated) const {
362 int flags = RESPONSE_INFO_VERSION;
363 int extra_flags = 0;
364 if (ssl_info.is_valid()) {
365 flags |= RESPONSE_INFO_HAS_CERT;
366 flags |= RESPONSE_INFO_HAS_CERT_STATUS;
367 if (ssl_info.key_exchange_group != 0)
368 flags |= RESPONSE_INFO_HAS_KEY_EXCHANGE_GROUP;
369 if (ssl_info.connection_status != 0)
370 flags |= RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS;
371 if (ssl_info.peer_signature_algorithm != 0)
372 flags |= RESPONSE_INFO_HAS_PEER_SIGNATURE_ALGORITHM;
373 }
374 if (vary_data.is_valid())
375 flags |= RESPONSE_INFO_HAS_VARY_DATA;
376 if (response_truncated)
377 flags |= RESPONSE_INFO_TRUNCATED;
378 if (was_fetched_via_spdy)
379 flags |= RESPONSE_INFO_WAS_SPDY;
380 if (was_alpn_negotiated) {
381 flags |= RESPONSE_INFO_WAS_ALPN;
382 flags |= RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL;
383 }
384 if (was_fetched_via_proxy)
385 flags |= RESPONSE_INFO_WAS_PROXY;
386 if (connection_info != HttpConnectionInfo::kUNKNOWN) {
387 flags |= RESPONSE_INFO_HAS_CONNECTION_INFO;
388 }
389 if (did_use_http_auth)
390 flags |= RESPONSE_INFO_USE_HTTP_AUTHENTICATION;
391 if (unused_since_prefetch)
392 flags |= RESPONSE_INFO_UNUSED_SINCE_PREFETCH;
393 if (restricted_prefetch)
394 flags |= RESPONSE_INFO_RESTRICTED_PREFETCH;
395 // RESPONSE_INFO_UNUSED_WAS_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE is not used.
396 if (ssl_info.pkp_bypassed)
397 flags |= RESPONSE_INFO_PKP_BYPASSED;
398 if (!stale_revalidate_timeout.is_null())
399 flags |= RESPONSE_INFO_HAS_STALENESS;
400 if (!dns_aliases.empty())
401 flags |= RESPONSE_INFO_HAS_DNS_ALIASES;
402 if (ssl_info.encrypted_client_hello)
403 flags |= RESPONSE_INFO_ENCRYPTED_CLIENT_HELLO;
404 if (browser_run_id.has_value())
405 flags |= RESPONSE_INFO_BROWSER_RUN_ID;
406
407 if (did_use_shared_dictionary) {
408 extra_flags |= RESPONSE_EXTRA_INFO_DID_USE_SHARED_DICTIONARY;
409 }
410
411 if (extra_flags) {
412 flags |= RESPONSE_INFO_HAS_EXTRA_FLAGS;
413 }
414
415 pickle->WriteInt(flags);
416 if (extra_flags) {
417 pickle->WriteInt(extra_flags);
418 }
419 pickle->WriteInt64(request_time.ToInternalValue());
420 pickle->WriteInt64(response_time.ToInternalValue());
421
422 HttpResponseHeaders::PersistOptions persist_options =
423 HttpResponseHeaders::PERSIST_RAW;
424
425 if (skip_transient_headers) {
426 persist_options = HttpResponseHeaders::PERSIST_SANS_COOKIES |
427 HttpResponseHeaders::PERSIST_SANS_CHALLENGES |
428 HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP |
429 HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE |
430 HttpResponseHeaders::PERSIST_SANS_RANGES |
431 HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE;
432 }
433
434 headers->Persist(pickle, persist_options);
435
436 if (ssl_info.is_valid()) {
437 ssl_info.cert->Persist(pickle);
438 pickle->WriteUInt32(ssl_info.cert_status);
439 if (ssl_info.connection_status != 0)
440 pickle->WriteInt(ssl_info.connection_status);
441 }
442
443 if (vary_data.is_valid())
444 vary_data.Persist(pickle);
445
446 pickle->WriteString(remote_endpoint.ToStringWithoutPort());
447 pickle->WriteUInt16(remote_endpoint.port());
448
449 if (was_alpn_negotiated)
450 pickle->WriteString(alpn_negotiated_protocol);
451
452 if (connection_info != HttpConnectionInfo::kUNKNOWN) {
453 pickle->WriteInt(static_cast<int>(connection_info));
454 }
455
456 if (ssl_info.is_valid() && ssl_info.key_exchange_group != 0)
457 pickle->WriteInt(ssl_info.key_exchange_group);
458
459 if (flags & RESPONSE_INFO_HAS_STALENESS) {
460 pickle->WriteInt64(
461 (stale_revalidate_timeout - base::Time()).InMicroseconds());
462 }
463
464 if (ssl_info.is_valid() && ssl_info.peer_signature_algorithm != 0)
465 pickle->WriteInt(ssl_info.peer_signature_algorithm);
466
467 if (!dns_aliases.empty()) {
468 pickle->WriteInt(dns_aliases.size());
469 for (const auto& alias : dns_aliases)
470 pickle->WriteString(alias);
471 }
472
473 if (browser_run_id.has_value()) {
474 pickle->WriteInt64(browser_run_id.value());
475 }
476 }
477
DidUseQuic() const478 bool HttpResponseInfo::DidUseQuic() const {
479 switch (connection_info) {
480 case HttpConnectionInfo::kUNKNOWN:
481 case HttpConnectionInfo::kHTTP1_1:
482 case HttpConnectionInfo::kDEPRECATED_SPDY2:
483 case HttpConnectionInfo::kDEPRECATED_SPDY3:
484 case HttpConnectionInfo::kHTTP2:
485 case HttpConnectionInfo::kDEPRECATED_HTTP2_14:
486 case HttpConnectionInfo::kDEPRECATED_HTTP2_15:
487 case HttpConnectionInfo::kHTTP0_9:
488 case HttpConnectionInfo::kHTTP1_0:
489 return false;
490 case HttpConnectionInfo::kQUIC_UNKNOWN_VERSION:
491 case HttpConnectionInfo::kQUIC_32:
492 case HttpConnectionInfo::kQUIC_33:
493 case HttpConnectionInfo::kQUIC_34:
494 case HttpConnectionInfo::kQUIC_35:
495 case HttpConnectionInfo::kQUIC_36:
496 case HttpConnectionInfo::kQUIC_37:
497 case HttpConnectionInfo::kQUIC_38:
498 case HttpConnectionInfo::kQUIC_39:
499 case HttpConnectionInfo::kQUIC_40:
500 case HttpConnectionInfo::kQUIC_41:
501 case HttpConnectionInfo::kQUIC_42:
502 case HttpConnectionInfo::kQUIC_43:
503 case HttpConnectionInfo::kQUIC_44:
504 case HttpConnectionInfo::kQUIC_45:
505 case HttpConnectionInfo::kQUIC_46:
506 case HttpConnectionInfo::kQUIC_47:
507 case HttpConnectionInfo::kQUIC_Q048:
508 case HttpConnectionInfo::kQUIC_T048:
509 case HttpConnectionInfo::kQUIC_Q049:
510 case HttpConnectionInfo::kQUIC_T049:
511 case HttpConnectionInfo::kQUIC_Q050:
512 case HttpConnectionInfo::kQUIC_T050:
513 case HttpConnectionInfo::kQUIC_Q099:
514 case HttpConnectionInfo::kQUIC_T099:
515 case HttpConnectionInfo::kQUIC_999:
516 case HttpConnectionInfo::kQUIC_DRAFT_25:
517 case HttpConnectionInfo::kQUIC_DRAFT_27:
518 case HttpConnectionInfo::kQUIC_DRAFT_28:
519 case HttpConnectionInfo::kQUIC_DRAFT_29:
520 case HttpConnectionInfo::kQUIC_T051:
521 case HttpConnectionInfo::kQUIC_RFC_V1:
522 case HttpConnectionInfo::kDEPRECATED_QUIC_2_DRAFT_1:
523 case HttpConnectionInfo::kQUIC_2_DRAFT_8:
524 return true;
525 }
526 }
527
528 } // namespace net
529