• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 #ifndef NET_BASE_ISOLATION_INFO_H_
6 #define NET_BASE_ISOLATION_INFO_H_
7 
8 #include <optional>
9 #include <set>
10 #include <string>
11 
12 #include "base/unguessable_token.h"
13 #include "net/base/net_export.h"
14 #include "net/base/network_anonymization_key.h"
15 #include "net/base/network_isolation_key.h"
16 #include "net/cookies/site_for_cookies.h"
17 #include "url/origin.h"
18 
19 namespace network::mojom {
20 class IsolationInfoDataView;
21 }  // namespace network::mojom
22 
23 namespace mojo {
24 template <typename DataViewType, typename T>
25 struct StructTraits;
26 }  // namespace mojo
27 
28 namespace net {
29 
30 // Class to store information about network stack requests based on the context
31 // in which they are made. It provides NetworkIsolationKeys, used to shard the
32 // HTTP cache, NetworkAnonymizationKeys, used to shard other network state, and
33 // SiteForCookies, used determine when to send same site cookies. The
34 // IsolationInfo is typically the same for all subresource requests made in the
35 // context of the same frame, but may be different for different frames within a
36 // page. The IsolationInfo associated with requests for frames may change as
37 // redirects are followed, and this class also contains the logic on how to do
38 // that.
39 //
40 // TODO(crbug.com/40093296): The SiteForCookies logic in this class is currently
41 // unused, but will eventually replace the logic in URLRequest/RedirectInfo for
42 // tracking and updating that value.
43 class NET_EXPORT IsolationInfo {
44  public:
45   // The update-on-redirect patterns.
46   //
47   // In general, almost everything should use kOther, as a
48   // kMainFrame request accidentally sent or redirected to an attacker
49   // allows cross-site tracking, and kSubFrame allows information
50   // leaks between sites that iframe each other. Anything that uses
51   // kMainFrame should be user triggered and user visible, like a main
52   // frame navigation or downloads.
53   //
54   // The RequestType is a core part of an IsolationInfo, and using an
55   // IsolationInfo with one value to create an IsolationInfo with another
56   // RequestType is generally not a good idea, unless the RequestType of the
57   // new IsolationInfo is kOther.
58   enum class RequestType {
59     // Updates top level origin, frame origin, and SiteForCookies on redirect.
60     // These requests allow users to be recognized across sites on redirect, so
61     // should not generally be used for anything other than navigations.
62     kMainFrame,
63 
64     // Only updates frame origin on redirect.
65     kSubFrame,
66 
67     // Updates nothing on redirect.
68     kOther,
69   };
70 
71   // Default constructor returns an IsolationInfo with empty origins, a null
72   // SiteForCookies(), and a RequestType of kOther.
73   IsolationInfo();
74   IsolationInfo(const IsolationInfo&);
75   IsolationInfo(IsolationInfo&&);
76   ~IsolationInfo();
77 
78   IsolationInfo& operator=(const IsolationInfo&);
79   IsolationInfo& operator=(IsolationInfo&&);
80 
81   // Simple constructor for internal requests. Sets |frame_origin| and
82   // |site_for_cookies| match |top_frame_origin|. Sets |request_type| to
83   // kOther. Will only send SameSite cookies to the site associated with
84   // the passed in origin.
85   static IsolationInfo CreateForInternalRequest(
86       const url::Origin& top_frame_origin);
87 
88   // Creates a transient IsolationInfo. A transient IsolationInfo will not save
89   // data to disk and not send SameSite cookies. Equivalent to calling
90   // CreateForInternalRequest with a fresh opaque origin.
91   static IsolationInfo CreateTransient();
92 
93   // Same as CreateTransient, with a `nonce` used to identify requests tagged
94   // with this IsolationInfo in the network service. The `nonce` provides no
95   // additional resource isolation, because the opaque origin in the resulting
96   // IsolationInfo already represents a unique partition.
97   static IsolationInfo CreateTransientWithNonce(
98       const base::UnguessableToken& nonce);
99 
100   // Creates an IsolationInfo from the serialized contents. Returns a nullopt
101   // if deserialization fails or if data is inconsistent.
102   static std::optional<IsolationInfo> Deserialize(
103       const std::string& serialized);
104 
105   // Creates an IsolationInfo with the provided parameters. If the parameters
106   // are inconsistent, DCHECKs. In particular:
107   // * If |request_type| is kMainFrame, |top_frame_origin| must equal
108   //   |frame_origin|, and |site_for_cookies| must be either null or first party
109   //   with respect to them.
110   // * If |request_type| is kSubFrame, |top_frame_origin| must be
111   //   first party with respect to |site_for_cookies|, or |site_for_cookies|
112   //   must be null.
113   // * If |request_type| is kOther, |top_frame_origin| and
114   //   |frame_origin| must be first party with respect to |site_for_cookies|, or
115   //   |site_for_cookies| must be null.
116   // * If |nonce| is specified, then |top_frame_origin| must not be null.
117   //
118   // Note that the |site_for_cookies| consistency checks are skipped when
119   // |site_for_cookies| is not HTTP/HTTPS.
120   static IsolationInfo Create(
121       RequestType request_type,
122       const url::Origin& top_frame_origin,
123       const url::Origin& frame_origin,
124       const SiteForCookies& site_for_cookies,
125       const std::optional<base::UnguessableToken>& nonce = std::nullopt);
126 
127   // TODO(crbug.com/344943210): Remove this and create a safer way to ensure
128   // NIKs created from NAKs aren't used by accident.
129   static IsolationInfo DoNotUseCreatePartialFromNak(
130       const net::NetworkAnonymizationKey& network_anonymization_key);
131 
132   // Returns nullopt if the arguments are not consistent. Otherwise, returns a
133   // fully populated IsolationInfo. Any IsolationInfo that can be created by
134   // the other construction methods, including the 0-argument constructor, is
135   // considered consistent.
136   //
137   // Intended for use by cross-process deserialization.
138   static std::optional<IsolationInfo> CreateIfConsistent(
139       RequestType request_type,
140       const std::optional<url::Origin>& top_frame_origin,
141       const std::optional<url::Origin>& frame_origin,
142       const SiteForCookies& site_for_cookies,
143       const std::optional<base::UnguessableToken>& nonce = std::nullopt);
144 
145   // Create a new IsolationInfo for a redirect to the supplied origin. |this| is
146   // unmodified.
147   IsolationInfo CreateForRedirect(const url::Origin& new_origin) const;
148 
request_type()149   RequestType request_type() const { return request_type_; }
150 
IsMainFrameRequest()151   bool IsMainFrameRequest() const {
152     return RequestType::kMainFrame == request_type_;
153   }
154 
IsEmpty()155   bool IsEmpty() const { return !top_frame_origin_; }
156 
157   // These may only be nullopt if created by the empty constructor. If one is
158   // nullopt, both are, and SiteForCookies is null.
159   //
160   // Note that these are the values the IsolationInfo was created with. In the
161   // case an IsolationInfo was created from a NetworkIsolationKey, they may be
162   // scheme + eTLD+1 instead of actual origins.
top_frame_origin()163   const std::optional<url::Origin>& top_frame_origin() const {
164     return top_frame_origin_;
165   }
166   const std::optional<url::Origin>& frame_origin() const;
167 
network_isolation_key()168   const NetworkIsolationKey& network_isolation_key() const {
169     return network_isolation_key_;
170   }
171 
network_anonymization_key()172   const NetworkAnonymizationKey& network_anonymization_key() const {
173     return network_anonymization_key_;
174   }
175 
nonce()176   const std::optional<base::UnguessableToken>& nonce() const { return nonce_; }
177 
178   // The value that should be consulted for the third-party cookie blocking
179   // policy, as defined in Section 2.1.1 and 2.1.2 of
180   // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site.
181   //
182   // WARNING: This value must only be used for the third-party cookie blocking
183   //          policy. It MUST NEVER be used for any kind of SECURITY check.
site_for_cookies()184   const SiteForCookies& site_for_cookies() const { return site_for_cookies_; }
185 
186   bool IsEqualForTesting(const IsolationInfo& other) const;
187 
188   // Serialize the `IsolationInfo` into a string. Fails if transient, returning
189   // an empty string.
190   std::string Serialize() const;
191 
192   std::string DebugString() const;
193 
194  private:
195   IsolationInfo(RequestType request_type,
196                 const std::optional<url::Origin>& top_frame_origin,
197                 const std::optional<url::Origin>& frame_origin,
198                 const SiteForCookies& site_for_cookies,
199                 const std::optional<base::UnguessableToken>& nonce);
200 
201   RequestType request_type_;
202 
203   std::optional<url::Origin> top_frame_origin_;
204   std::optional<url::Origin> frame_origin_;
205 
206   // This can be deduced from the two origins above, but keep a cached version
207   // to avoid repeated eTLD+1 calculations, when this is using eTLD+1.
208   NetworkIsolationKey network_isolation_key_;
209 
210   NetworkAnonymizationKey network_anonymization_key_;
211 
212   SiteForCookies site_for_cookies_;
213 
214   // Having a nonce is a way to force a transient opaque `IsolationInfo`
215   // for non-opaque origins.
216   std::optional<base::UnguessableToken> nonce_;
217 
218   // Mojo serialization code needs to access internal fields.
219   friend struct mojo::StructTraits<network::mojom::IsolationInfoDataView,
220                                    IsolationInfo>;
221 };
222 
223 }  // namespace net
224 
225 #endif  // NET_BASE_ISOLATION_INFO_H_
226