• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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