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