blob: 32e933bf829df96fdf6bcf979b75e42851995867 [file] [log] [blame]
Avi Drissman64595482022-09-14 20:52:291// Copyright 2020 The Chromium Authors
Matt Menke3ab9c7b2020-04-01 22:39:572// 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
David Benjamin506122dc2023-11-07 01:32:188#include <optional>
Shuran Huang0e0aaa52020-12-02 22:24:549#include <set>
Rayan Kanso0f21e4d2021-10-06 09:40:3910#include <string>
Shuran Huang0e0aaa52020-12-02 22:24:5411
Antonio Sartoric718b4b2021-07-30 09:29:0112#include "base/unguessable_token.h"
Matt Menke3ab9c7b2020-04-01 22:39:5713#include "net/base/net_export.h"
Brianna Goldstein32eacb0b2022-08-29 08:52:1914#include "net/base/network_anonymization_key.h"
Matt Menke3ab9c7b2020-04-01 22:39:5715#include "net/base/network_isolation_key.h"
Abigail Katcoffe0bf36202025-02-25 22:13:2416#include "net/base/network_isolation_partition.h"
Joshua Thomasbffd4e32025-05-28 19:05:4317#include "net/base/url_util.h"
Matt Menke3ab9c7b2020-04-01 22:39:5718#include "net/cookies/site_for_cookies.h"
19#include "url/origin.h"
20
Tsuyoshi Horo4f516be2022-06-14 11:53:1321namespace network::mojom {
Shuran Huang0e0aaa52020-12-02 22:24:5422class IsolationInfoDataView;
Tsuyoshi Horo4f516be2022-06-14 11:53:1323} // namespace network::mojom
Shuran Huang0e0aaa52020-12-02 22:24:5424
25namespace mojo {
26template <typename DataViewType, typename T>
27struct StructTraits;
28} // namespace mojo
29
Matt Menke3ab9c7b2020-04-01 22:39:5730namespace net {
31
32// Class to store information about network stack requests based on the context
Andrew Williamsf6bb3532024-06-12 16:20:0133// in which they are made. It provides NetworkIsolationKeys, used to shard the
34// HTTP cache, NetworkAnonymizationKeys, used to shard other network state, and
35// SiteForCookies, used determine when to send same site cookies. The
36// IsolationInfo is typically the same for all subresource requests made in the
37// context of the same frame, but may be different for different frames within a
38// page. The IsolationInfo associated with requests for frames may change as
39// redirects are followed, and this class also contains the logic on how to do
40// that.
Matt Menke3ab9c7b2020-04-01 22:39:5741//
Andrew Williamsf6bb3532024-06-12 16:20:0142// TODO(crbug.com/40093296): The SiteForCookies logic in this class is currently
43// unused, but will eventually replace the logic in URLRequest/RedirectInfo for
44// tracking and updating that value.
Shivani Sharmaf3c42ab52024-12-20 21:24:5545//
Joshua Thomasbffd4e32025-05-28 19:05:4346// IsolationInfo has an optional `frame_ancestor_relation_` member, whose value
47// represents the relationship between the request's `frame_origin`,
48// `top_frame_origin`, and all other ancestor frame origins. A
49// `frame_ancestor_relation` with a value of nullopt is used for requests where
50// we do not know the requesting frame's relation to its ancestors. Note that
51// this does not consider the origin of request itself in the computation, even
52// if request is for a frame's root document.
53//
Andrew Vergedd2518e2025-01-14 17:37:2754// IsolationInfo has a `nonce_` member, which can be used to force a particular
55// "shard" based upon that nonce. An IsolationInfo with an opaque origin will
56// also have its own shard, but the nonce enables this behavior even for non-
57// opaque origins. If multiple documents share the same nonce, they can
58// therefore share the same shard, so it is possible to leak information between
59// them via partitioned cookies, etc. This nonce is provided to many of the
60// constructor/factory methods of this class; if an IsolationInfo is created in
61// the context of a document with a partition nonce, then that partition nonce
62// should be provided, to ensure information is only visible within the same
63// partition. Currently, only fenced frames and credentailless iframes use a
64// partition nonce.
65//
66// Even if full third-party cookie access is enabled, the `nonce` will force a
67// cookie partition keyed using that nonce. Keep this in mind when using a
68// nonced IsolationInfo for credentialed requests.
69//
70// In addition to the sharding described above, `IsolationInfo::nonce()` is also
71// used to check if a given network request should be disallowed because the
Shivani Sharmaf3c42ab52024-12-20 21:24:5572// initiating fenced frame has revoked network access. More context on
73// network revocation is in network_context.mojom in the comment for
74// `NetworkContext::RevokeNetworkForNonces()`. Not providing the correct
75// `nonce` will therefore lead to sending network requests that should
Andrew Vergedd2518e2025-01-14 17:37:2776// have been blocked. See `RenderFrameHostImpl::ComputeNonce()` which
Shivani Sharmaf3c42ab52024-12-20 21:24:5577// computes the correct nonce for a given frame.
Matt Menke3ab9c7b2020-04-01 22:39:5778class NET_EXPORT IsolationInfo {
79 public:
80 // The update-on-redirect patterns.
81 //
shivanigithub4e78015f592020-10-21 13:26:2382 // In general, almost everything should use kOther, as a
83 // kMainFrame request accidentally sent or redirected to an attacker
84 // allows cross-site tracking, and kSubFrame allows information
Matt Menke3ab9c7b2020-04-01 22:39:5785 // leaks between sites that iframe each other. Anything that uses
shivanigithub4e78015f592020-10-21 13:26:2386 // kMainFrame should be user triggered and user visible, like a main
Matt Menke3ab9c7b2020-04-01 22:39:5787 // frame navigation or downloads.
88 //
shivanigithub4e78015f592020-10-21 13:26:2389 // The RequestType is a core part of an IsolationInfo, and using an
Matt Menke3ab9c7b2020-04-01 22:39:5790 // IsolationInfo with one value to create an IsolationInfo with another
shivanigithub4e78015f592020-10-21 13:26:2391 // RequestType is generally not a good idea, unless the RequestType of the
92 // new IsolationInfo is kOther.
93 enum class RequestType {
94 // Updates top level origin, frame origin, and SiteForCookies on redirect.
Matt Menke3ab9c7b2020-04-01 22:39:5795 // These requests allow users to be recognized across sites on redirect, so
96 // should not generally be used for anything other than navigations.
shivanigithub4e78015f592020-10-21 13:26:2397 kMainFrame,
Matt Menke3ab9c7b2020-04-01 22:39:5798
shivanigithub4e78015f592020-10-21 13:26:2399 // Only updates frame origin on redirect.
100 kSubFrame,
Matt Menke3ab9c7b2020-04-01 22:39:57101
shivanigithub4e78015f592020-10-21 13:26:23102 // Updates nothing on redirect.
103 kOther,
Chris Fredrickson7f97f1d2025-05-22 20:59:04104 kMax = kOther
Matt Menke3ab9c7b2020-04-01 22:39:57105 };
106
Joshua Thomasbffd4e32025-05-28 19:05:43107 // The FrameAncestorRelation describes the relationship that all the frame
108 // ancestors (and ONLY the frame ancestors) of the current request have to
109 // each other.
110 //
111 // Consumers of this class must construct an IsolationInfo with a nullopt
112 // FrameAncestorRelation unless they have explicit knowledge of all of the
113 // current frame's ancestors. Note that kMainFrame RequestTypes will always
114 // have a kSameOrigin FrameAncestorRelation.
115 enum class FrameAncestorRelation {
116 // Value for requests whose ancestor frames' origins all have a same-origin
117 // relationship.
118 kSameOrigin,
119 // Value for requests whose ancestor frames' origins do not have a
120 // same-origin relationship, but all share a common a scheme and site.
121 kSameSite,
122 // Value for requests whose ancestor frames' origins do not all share a
123 // scheme and/or site.
124 kCrossSite,
125 };
126
Matt Menke3ab9c7b2020-04-01 22:39:57127 // Default constructor returns an IsolationInfo with empty origins, a null
Chris Fredricksone7ba5212023-09-26 14:54:42128 // SiteForCookies(), and a RequestType of kOther.
Matt Menke3ab9c7b2020-04-01 22:39:57129 IsolationInfo();
130 IsolationInfo(const IsolationInfo&);
131 IsolationInfo(IsolationInfo&&);
132 ~IsolationInfo();
133
134 IsolationInfo& operator=(const IsolationInfo&);
135 IsolationInfo& operator=(IsolationInfo&&);
136
Joshua Thomasbffd4e32025-05-28 19:05:43137 // Returns the equivalent FrameAncestorRelation for a given
138 // OriginRelationValue. The value returned is the same as finding the
139 // FrameAncestorRelation for a set of two frame ancestors having the
140 // OriginRelationValue of `origin_relation_value`.
Joshua Thomas81febb32025-06-17 18:16:32141 static std::optional<FrameAncestorRelation>
142 OriginRelationToFrameAncestorRelation(
143 std::optional<OriginRelation> origin_relation_value);
Joshua Thomasbffd4e32025-05-28 19:05:43144
145 // Returns the greater value of `cur_relation` and the FrameAncestorRelation
146 // corresponding to the set of frame ancestors whose members are
147 // `frame_origin` and `top_frame_origin`. If `cur_relation` is nullopt, a
148 // nullopt will be returned.
149 static std::optional<FrameAncestorRelation> ComputeNewFrameAncestorRelation(
150 std::optional<FrameAncestorRelation> cur_relation,
151 const url::Origin& frame_origin,
152 const url::Origin& top_frame_origin);
153
154 static std::string_view FrameAncestorRelationString(
155 FrameAncestorRelation frame_ancestor_relation);
156
Matt Menke3ab9c7b2020-04-01 22:39:57157 // Simple constructor for internal requests. Sets |frame_origin| and
shivanigithub4e78015f592020-10-21 13:26:23158 // |site_for_cookies| match |top_frame_origin|. Sets |request_type| to
159 // kOther. Will only send SameSite cookies to the site associated with
Chris Fredricksone7ba5212023-09-26 14:54:42160 // the passed in origin.
Matt Menke3ab9c7b2020-04-01 22:39:57161 static IsolationInfo CreateForInternalRequest(
162 const url::Origin& top_frame_origin);
163
164 // Creates a transient IsolationInfo. A transient IsolationInfo will not save
Andrew Vergedd2518e2025-01-14 17:37:27165 // data to disk and not send SameSite cookies. When `nonce` is std::nullopt,
166 // this is equivalent to calling CreateForInternalRequest with a fresh opaque
167 // origin.
Matt Menke3ab9c7b2020-04-01 22:39:57168
Andrew Vergedd2518e2025-01-14 17:37:27169 // Because the origin of the returned IsolationInfo is opaque, all network
170 // state partitioning outside of cookies will be unique (see the class
171 // meta-comment for how cookies are affected).
172
173 // Note: error pages resulting from a failed navigation should always use a
174 // transient IsolationInfo with no nonce.
175 static IsolationInfo CreateTransient(
Chris Fredrickson31cea0f22025-07-02 19:08:52176 std::optional<base::UnguessableToken> nonce);
Andrew Verge898c2af2024-02-15 19:04:11177
Rayan Kanso0f21e4d2021-10-06 09:40:39178 // Creates an IsolationInfo from the serialized contents. Returns a nullopt
179 // if deserialization fails or if data is inconsistent.
David Benjamin506122dc2023-11-07 01:32:18180 static std::optional<IsolationInfo> Deserialize(
Rayan Kanso0f21e4d2021-10-06 09:40:39181 const std::string& serialized);
182
Matt Menke3ab9c7b2020-04-01 22:39:57183 // Creates an IsolationInfo with the provided parameters. If the parameters
184 // are inconsistent, DCHECKs. In particular:
Joshua Thomasbffd4e32025-05-28 19:05:43185 // * If `request_type` is kMainFrame, `top_frame_origin` must equal
186 // `frame_origin`, `site_for_cookies` must be either null or first party
187 // with respect to them, and `frame_ancestor_relation` must be kSameOrigin.
188 // * If `request_type` is kSubFrame, `top_frame_origin` must be
189 // first party with respect to |site_for_cookies|, or `site_for_cookies`
Matt Menke3ab9c7b2020-04-01 22:39:57190 // must be null.
Joshua Thomasbffd4e32025-05-28 19:05:43191 // * If `request_type` is kOther, `top_frame_origin` and
192 // `frame_origin` must be first party with respect to `site_for_cookies`, or
193 // `site_for_cookies` must be null. If `frame_ancestor_relation` is non-null
194 // and not kCrossSite, then the FrameAncestorRelation between
195 // `top_frame_origin` and `frame_origin` must not supersede.
196 // * If `nonce` is specified, then `top_frame_origin` must not be null.
197 // Please see the meta-comment for this class for the `nonce` to provide.
Matt Menke3ab9c7b2020-04-01 22:39:57198 //
Joshua Thomasbffd4e32025-05-28 19:05:43199 // Note that the `site_for_cookies` consistency checks are skipped when
200 // `site_for_cookies` is not HTTP/HTTPS.
Shuran Huang0e0aaa52020-12-02 22:24:54201 static IsolationInfo Create(
202 RequestType request_type,
Chris Fredrickson31cea0f22025-07-02 19:08:52203 url::Origin top_frame_origin,
204 url::Origin frame_origin,
205 SiteForCookies site_for_cookies,
206 std::optional<base::UnguessableToken> nonce = std::nullopt,
Abigail Katcoffe0bf36202025-02-25 22:13:24207 NetworkIsolationPartition network_isolation_partition =
Joshua Thomasbffd4e32025-05-28 19:05:43208 NetworkIsolationPartition::kGeneral,
209 std::optional<FrameAncestorRelation> frame_ancestor_relation =
210 std::nullopt);
Matt Menke3ab9c7b2020-04-01 22:39:57211
Andrew Williamsf6bb3532024-06-12 16:20:01212 // TODO(crbug.com/344943210): Remove this and create a safer way to ensure
213 // NIKs created from NAKs aren't used by accident.
Brianna Goldsteind22b0642022-10-11 16:30:50214 static IsolationInfo DoNotUseCreatePartialFromNak(
215 const net::NetworkAnonymizationKey& network_anonymization_key);
216
Matt Menke3ab9c7b2020-04-01 22:39:57217 // Returns nullopt if the arguments are not consistent. Otherwise, returns a
218 // fully populated IsolationInfo. Any IsolationInfo that can be created by
219 // the other construction methods, including the 0-argument constructor, is
220 // considered consistent.
221 //
222 // Intended for use by cross-process deserialization.
David Benjamin506122dc2023-11-07 01:32:18223 static std::optional<IsolationInfo> CreateIfConsistent(
shivanigithub4e78015f592020-10-21 13:26:23224 RequestType request_type,
Chris Fredrickson31cea0f22025-07-02 19:08:52225 std::optional<url::Origin> top_frame_origin,
226 std::optional<url::Origin> frame_origin,
227 SiteForCookies site_for_cookies,
228 std::optional<base::UnguessableToken> nonce = std::nullopt,
Abigail Katcoffe0bf36202025-02-25 22:13:24229 NetworkIsolationPartition network_isolation_partition =
Joshua Thomasbffd4e32025-05-28 19:05:43230 NetworkIsolationPartition::kGeneral,
231 std::optional<FrameAncestorRelation> frame_ancestor_relation =
232 std::nullopt);
Matt Menke3ab9c7b2020-04-01 22:39:57233
234 // Create a new IsolationInfo for a redirect to the supplied origin. |this| is
235 // unmodified.
236 IsolationInfo CreateForRedirect(const url::Origin& new_origin) const;
237
shivanigithub4e78015f592020-10-21 13:26:23238 RequestType request_type() const { return request_type_; }
Matt Menke3ab9c7b2020-04-01 22:39:57239
Joshua Thomasbffd4e32025-05-28 19:05:43240 std::optional<FrameAncestorRelation> frame_ancestor_relation() const {
241 return frame_ancestor_relation_;
242 }
243
selyad1565b12024-05-10 19:06:15244 bool IsMainFrameRequest() const {
245 return RequestType::kMainFrame == request_type_;
246 }
247
sbingler365ef822025-02-04 21:08:50248 // If this request is associated with a outer most main frame. See
249 // `RenderFrameHost::GetOutermostMainFrame` for more information.
250 bool IsOutermostMainFrameRequest() const {
251 return IsMainFrameRequest() && !nonce();
252 }
253
Matt Menke3ab9c7b2020-04-01 22:39:57254 bool IsEmpty() const { return !top_frame_origin_; }
255
256 // These may only be nullopt if created by the empty constructor. If one is
257 // nullopt, both are, and SiteForCookies is null.
Matt Menkee6e4f392020-10-08 11:41:29258 //
259 // Note that these are the values the IsolationInfo was created with. In the
260 // case an IsolationInfo was created from a NetworkIsolationKey, they may be
261 // scheme + eTLD+1 instead of actual origins.
David Benjamin506122dc2023-11-07 01:32:18262 const std::optional<url::Origin>& top_frame_origin() const {
Matt Menke3ab9c7b2020-04-01 22:39:57263 return top_frame_origin_;
264 }
David Benjamin506122dc2023-11-07 01:32:18265 const std::optional<url::Origin>& frame_origin() const;
Matt Menke3ab9c7b2020-04-01 22:39:57266
267 const NetworkIsolationKey& network_isolation_key() const {
268 return network_isolation_key_;
269 }
270
Brianna Goldstein32eacb0b2022-08-29 08:52:19271 const NetworkAnonymizationKey& network_anonymization_key() const {
272 return network_anonymization_key_;
273 }
274
David Benjamin506122dc2023-11-07 01:32:18275 const std::optional<base::UnguessableToken>& nonce() const { return nonce_; }
Antonio Sartoric718b4b2021-07-30 09:29:01276
Abigail Katcoffe0bf36202025-02-25 22:13:24277 NetworkIsolationPartition GetNetworkIsolationPartition() const {
278 return network_isolation_key_.GetNetworkIsolationPartition();
279 }
280
Matt Menke3ab9c7b2020-04-01 22:39:57281 // The value that should be consulted for the third-party cookie blocking
282 // policy, as defined in Section 2.1.1 and 2.1.2 of
283 // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site.
284 //
285 // WARNING: This value must only be used for the third-party cookie blocking
286 // policy. It MUST NEVER be used for any kind of SECURITY check.
287 const SiteForCookies& site_for_cookies() const { return site_for_cookies_; }
288
Matt Menke3ab9c7b2020-04-01 22:39:57289 bool IsEqualForTesting(const IsolationInfo& other) const;
290
Rayan Kanso0f21e4d2021-10-06 09:40:39291 // Serialize the `IsolationInfo` into a string. Fails if transient, returning
292 // an empty string.
293 std::string Serialize() const;
294
Dustin J. Mitchell6943af4a2023-02-16 14:37:44295 std::string DebugString() const;
296
Matt Menke3ab9c7b2020-04-01 22:39:57297 private:
shivanigithub4e78015f592020-10-21 13:26:23298 IsolationInfo(RequestType request_type,
Chris Fredrickson31cea0f22025-07-02 19:08:52299 std::optional<url::Origin> top_frame_origin,
300 std::optional<url::Origin> frame_origin,
301 SiteForCookies site_for_cookies,
302 std::optional<base::UnguessableToken> nonce,
Joshua Thomasbffd4e32025-05-28 19:05:43303 NetworkIsolationPartition network_isolation_partition,
304 std::optional<FrameAncestorRelation> frame_ancestor_relation);
Matt Menke3ab9c7b2020-04-01 22:39:57305
shivanigithub4e78015f592020-10-21 13:26:23306 RequestType request_type_;
Matt Menke3ab9c7b2020-04-01 22:39:57307
David Benjamin506122dc2023-11-07 01:32:18308 std::optional<url::Origin> top_frame_origin_;
309 std::optional<url::Origin> frame_origin_;
Joshua Thomasbffd4e32025-05-28 19:05:43310 std::optional<FrameAncestorRelation> frame_ancestor_relation_;
Matt Menke3ab9c7b2020-04-01 22:39:57311
312 // This can be deduced from the two origins above, but keep a cached version
313 // to avoid repeated eTLD+1 calculations, when this is using eTLD+1.
Brianna Goldstein32eacb0b2022-08-29 08:52:19314 NetworkIsolationKey network_isolation_key_;
315
316 NetworkAnonymizationKey network_anonymization_key_;
Matt Menke3ab9c7b2020-04-01 22:39:57317
318 SiteForCookies site_for_cookies_;
319
Antonio Sartoric718b4b2021-07-30 09:29:01320 // Having a nonce is a way to force a transient opaque `IsolationInfo`
321 // for non-opaque origins.
David Benjamin506122dc2023-11-07 01:32:18322 std::optional<base::UnguessableToken> nonce_;
Antonio Sartoric718b4b2021-07-30 09:29:01323
Chris Fredrickson0a466bef2023-09-07 17:34:35324 // Mojo serialization code needs to access internal fields.
Shuran Huang0e0aaa52020-12-02 22:24:54325 friend struct mojo::StructTraits<network::mojom::IsolationInfoDataView,
326 IsolationInfo>;
Matt Menke3ab9c7b2020-04-01 22:39:57327};
328
329} // namespace net
330
331#endif // NET_BASE_ISOLATION_INFO_H_