File: isolation_info.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (331 lines) | stat: -rw-r--r-- 14,665 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_BASE_ISOLATION_INFO_H_
#define NET_BASE_ISOLATION_INFO_H_

#include <optional>
#include <set>
#include <string>

#include "base/unguessable_token.h"
#include "net/base/net_export.h"
#include "net/base/network_anonymization_key.h"
#include "net/base/network_isolation_key.h"
#include "net/base/network_isolation_partition.h"
#include "net/base/url_util.h"
#include "net/cookies/site_for_cookies.h"
#include "url/origin.h"

namespace network::mojom {
class IsolationInfoDataView;
}  // namespace network::mojom

namespace mojo {
template <typename DataViewType, typename T>
struct StructTraits;
}  // namespace mojo

namespace net {

// Class to store information about network stack requests based on the context
// in which they are made. It provides NetworkIsolationKeys, used to shard the
// HTTP cache, NetworkAnonymizationKeys, used to shard other network state, and
// SiteForCookies, used determine when to send same site cookies. The
// IsolationInfo is typically the same for all subresource requests made in the
// context of the same frame, but may be different for different frames within a
// page. The IsolationInfo associated with requests for frames may change as
// redirects are followed, and this class also contains the logic on how to do
// that.
//
// TODO(crbug.com/40093296): The SiteForCookies logic in this class is currently
// unused, but will eventually replace the logic in URLRequest/RedirectInfo for
// tracking and updating that value.
//
// IsolationInfo has an optional `frame_ancestor_relation_` member, whose value
// represents the relationship between the request's `frame_origin`,
// `top_frame_origin`, and all other ancestor frame origins. A
// `frame_ancestor_relation` with a value of nullopt is used for requests where
// we do not know the requesting frame's relation to its ancestors. Note that
// this does not consider the origin of request itself in the computation, even
// if request is for a frame's root document.
//
// IsolationInfo has a `nonce_` member, which can be used to force a particular
// "shard" based upon that nonce. An IsolationInfo with an opaque origin will
// also have its own shard, but the nonce enables this behavior even for non-
// opaque origins. If multiple documents share the same nonce, they can
// therefore share the same shard, so it is possible to leak information between
// them via partitioned cookies, etc. This nonce is provided to many of the
// constructor/factory methods of this class; if an IsolationInfo is created in
// the context of a document with a partition nonce, then that partition nonce
// should be provided, to ensure information is only visible within the same
// partition. Currently, only fenced frames and credentailless iframes use a
// partition nonce.
//
// Even if full third-party cookie access is enabled, the `nonce` will force a
// cookie partition keyed using that nonce. Keep this in mind when using a
// nonced IsolationInfo for credentialed requests.
//
// In addition to the sharding described above, `IsolationInfo::nonce()` is also
// used to check if a given network request should be disallowed because the
// initiating fenced frame has revoked network access. More context on
// network revocation is in network_context.mojom in the comment for
// `NetworkContext::RevokeNetworkForNonces()`. Not providing the correct
// `nonce` will therefore lead to sending network requests that should
// have been blocked. See `RenderFrameHostImpl::ComputeNonce()` which
// computes the correct nonce for a given frame.
class NET_EXPORT IsolationInfo {
 public:
  // The update-on-redirect patterns.
  //
  // In general, almost everything should use kOther, as a
  // kMainFrame request accidentally sent or redirected to an attacker
  // allows cross-site tracking, and kSubFrame allows information
  // leaks between sites that iframe each other. Anything that uses
  // kMainFrame should be user triggered and user visible, like a main
  // frame navigation or downloads.
  //
  // The RequestType is a core part of an IsolationInfo, and using an
  // IsolationInfo with one value to create an IsolationInfo with another
  // RequestType is generally not a good idea, unless the RequestType of the
  // new IsolationInfo is kOther.
  enum class RequestType {
    // Updates top level origin, frame origin, and SiteForCookies on redirect.
    // These requests allow users to be recognized across sites on redirect, so
    // should not generally be used for anything other than navigations.
    kMainFrame,

    // Only updates frame origin on redirect.
    kSubFrame,

    // Updates nothing on redirect.
    kOther,
    kMax = kOther
  };

  // The FrameAncestorRelation describes the relationship that all the frame
  // ancestors (and ONLY the frame ancestors) of the current request have to
  // each other.
  //
  // Consumers of this class must construct an IsolationInfo with a nullopt
  // FrameAncestorRelation unless they have explicit knowledge of all of the
  // current frame's ancestors.  Note that kMainFrame RequestTypes will always
  // have a kSameOrigin FrameAncestorRelation.
  enum class FrameAncestorRelation {
    // Value for requests whose ancestor frames' origins all have a same-origin
    // relationship.
    kSameOrigin,
    // Value for requests whose ancestor frames' origins do not have a
    // same-origin relationship, but all share a common a scheme and site.
    kSameSite,
    // Value for requests whose ancestor frames' origins do not all share a
    // scheme and/or site.
    kCrossSite,
  };

  // Default constructor returns an IsolationInfo with empty origins, a null
  // SiteForCookies(), and a RequestType of kOther.
  IsolationInfo();
  IsolationInfo(const IsolationInfo&);
  IsolationInfo(IsolationInfo&&);
  ~IsolationInfo();

  IsolationInfo& operator=(const IsolationInfo&);
  IsolationInfo& operator=(IsolationInfo&&);

  // Returns the equivalent FrameAncestorRelation for a given
  // OriginRelationValue. The value returned is the same as finding the
  // FrameAncestorRelation for a set of two frame ancestors having the
  // OriginRelationValue of `origin_relation_value`.
  static std::optional<FrameAncestorRelation>
  OriginRelationToFrameAncestorRelation(
      std::optional<OriginRelation> origin_relation_value);

  // Returns the greater value of `cur_relation` and the FrameAncestorRelation
  // corresponding to the set of frame ancestors whose members are
  // `frame_origin` and `top_frame_origin`. If `cur_relation` is nullopt, a
  // nullopt will be returned.
  static std::optional<FrameAncestorRelation> ComputeNewFrameAncestorRelation(
      std::optional<FrameAncestorRelation> cur_relation,
      const url::Origin& frame_origin,
      const url::Origin& top_frame_origin);

  static std::string_view FrameAncestorRelationString(
      FrameAncestorRelation frame_ancestor_relation);

  // Simple constructor for internal requests. Sets |frame_origin| and
  // |site_for_cookies| match |top_frame_origin|. Sets |request_type| to
  // kOther. Will only send SameSite cookies to the site associated with
  // the passed in origin.
  static IsolationInfo CreateForInternalRequest(
      const url::Origin& top_frame_origin);

  // Creates a transient IsolationInfo. A transient IsolationInfo will not save
  // data to disk and not send SameSite cookies. When `nonce` is std::nullopt,
  // this is equivalent to calling CreateForInternalRequest with a fresh opaque
  // origin.

  // Because the origin of the returned IsolationInfo is opaque, all network
  // state partitioning outside of cookies will be unique (see the class
  // meta-comment for how cookies are affected).

  // Note: error pages resulting from a failed navigation should always use a
  // transient IsolationInfo with no nonce.
  static IsolationInfo CreateTransient(
      const std::optional<base::UnguessableToken>& nonce);

  // Creates an IsolationInfo from the serialized contents. Returns a nullopt
  // if deserialization fails or if data is inconsistent.
  static std::optional<IsolationInfo> Deserialize(
      const std::string& serialized);

  // Creates an IsolationInfo with the provided parameters. If the parameters
  // are inconsistent, DCHECKs. In particular:
  // * If `request_type` is kMainFrame, `top_frame_origin` must equal
  //   `frame_origin`, `site_for_cookies` must be either null or first party
  //   with respect to them, and `frame_ancestor_relation` must be kSameOrigin.
  // * If `request_type` is kSubFrame, `top_frame_origin` must be
  //   first party with respect to |site_for_cookies|, or `site_for_cookies`
  //   must be null.
  // * If `request_type` is kOther, `top_frame_origin` and
  //   `frame_origin` must be first party with respect to `site_for_cookies`, or
  //   `site_for_cookies` must be null. If `frame_ancestor_relation` is non-null
  //   and not kCrossSite, then the FrameAncestorRelation between
  //   `top_frame_origin` and `frame_origin` must not supersede.
  // * If `nonce` is specified, then `top_frame_origin` must not be null.
  //   Please see the meta-comment for this class for the `nonce` to provide.
  //
  // Note that the `site_for_cookies` consistency checks are skipped when
  // `site_for_cookies` is not HTTP/HTTPS.
  static IsolationInfo Create(
      RequestType request_type,
      const url::Origin& top_frame_origin,
      const url::Origin& frame_origin,
      const SiteForCookies& site_for_cookies,
      const std::optional<base::UnguessableToken>& nonce = std::nullopt,
      NetworkIsolationPartition network_isolation_partition =
          NetworkIsolationPartition::kGeneral,
      std::optional<FrameAncestorRelation> frame_ancestor_relation =
          std::nullopt);

  // TODO(crbug.com/344943210): Remove this and create a safer way to ensure
  // NIKs created from NAKs aren't used by accident.
  static IsolationInfo DoNotUseCreatePartialFromNak(
      const net::NetworkAnonymizationKey& network_anonymization_key);

  // Returns nullopt if the arguments are not consistent. Otherwise, returns a
  // fully populated IsolationInfo. Any IsolationInfo that can be created by
  // the other construction methods, including the 0-argument constructor, is
  // considered consistent.
  //
  // Intended for use by cross-process deserialization.
  static std::optional<IsolationInfo> CreateIfConsistent(
      RequestType request_type,
      const std::optional<url::Origin>& top_frame_origin,
      const std::optional<url::Origin>& frame_origin,
      const SiteForCookies& site_for_cookies,
      const std::optional<base::UnguessableToken>& nonce = std::nullopt,
      NetworkIsolationPartition network_isolation_partition =
          NetworkIsolationPartition::kGeneral,
      std::optional<FrameAncestorRelation> frame_ancestor_relation =
          std::nullopt);

  // Create a new IsolationInfo for a redirect to the supplied origin. |this| is
  // unmodified.
  IsolationInfo CreateForRedirect(const url::Origin& new_origin) const;

  RequestType request_type() const { return request_type_; }

  std::optional<FrameAncestorRelation> frame_ancestor_relation() const {
    return frame_ancestor_relation_;
  }

  bool IsMainFrameRequest() const {
    return RequestType::kMainFrame == request_type_;
  }

  // If this request is associated with a outer most main frame. See
  // `RenderFrameHost::GetOutermostMainFrame` for more information.
  bool IsOutermostMainFrameRequest() const {
    return IsMainFrameRequest() && !nonce();
  }

  bool IsEmpty() const { return !top_frame_origin_; }

  // These may only be nullopt if created by the empty constructor. If one is
  // nullopt, both are, and SiteForCookies is null.
  //
  // Note that these are the values the IsolationInfo was created with. In the
  // case an IsolationInfo was created from a NetworkIsolationKey, they may be
  // scheme + eTLD+1 instead of actual origins.
  const std::optional<url::Origin>& top_frame_origin() const {
    return top_frame_origin_;
  }
  const std::optional<url::Origin>& frame_origin() const;

  const NetworkIsolationKey& network_isolation_key() const {
    return network_isolation_key_;
  }

  const NetworkAnonymizationKey& network_anonymization_key() const {
    return network_anonymization_key_;
  }

  const std::optional<base::UnguessableToken>& nonce() const { return nonce_; }

  NetworkIsolationPartition GetNetworkIsolationPartition() const {
    return network_isolation_key_.GetNetworkIsolationPartition();
  }

  // The value that should be consulted for the third-party cookie blocking
  // policy, as defined in Section 2.1.1 and 2.1.2 of
  // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site.
  //
  // WARNING: This value must only be used for the third-party cookie blocking
  //          policy. It MUST NEVER be used for any kind of SECURITY check.
  const SiteForCookies& site_for_cookies() const { return site_for_cookies_; }

  bool IsEqualForTesting(const IsolationInfo& other) const;

  // Serialize the `IsolationInfo` into a string. Fails if transient, returning
  // an empty string.
  std::string Serialize() const;

  std::string DebugString() const;

 private:
  IsolationInfo(RequestType request_type,
                const std::optional<url::Origin>& top_frame_origin,
                const std::optional<url::Origin>& frame_origin,
                const SiteForCookies& site_for_cookies,
                const std::optional<base::UnguessableToken>& nonce,
                NetworkIsolationPartition network_isolation_partition,
                std::optional<FrameAncestorRelation> frame_ancestor_relation);

  RequestType request_type_;

  std::optional<url::Origin> top_frame_origin_;
  std::optional<url::Origin> frame_origin_;
  std::optional<FrameAncestorRelation> frame_ancestor_relation_;

  // This can be deduced from the two origins above, but keep a cached version
  // to avoid repeated eTLD+1 calculations, when this is using eTLD+1.
  NetworkIsolationKey network_isolation_key_;

  NetworkAnonymizationKey network_anonymization_key_;

  SiteForCookies site_for_cookies_;

  // Having a nonce is a way to force a transient opaque `IsolationInfo`
  // for non-opaque origins.
  std::optional<base::UnguessableToken> nonce_;

  // Mojo serialization code needs to access internal fields.
  friend struct mojo::StructTraits<network::mojom::IsolationInfoDataView,
                                   IsolationInfo>;
};

}  // namespace net

#endif  // NET_BASE_ISOLATION_INFO_H_