• 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 <set>
9 #include <string>
10 
11 #include "base/unguessable_token.h"
12 #include "net/base/net_export.h"
13 #include "net/base/network_anonymization_key.h"
14 #include "net/base/network_isolation_key.h"
15 #include "net/cookies/site_for_cookies.h"
16 #include "third_party/abseil-cpp/absl/types/optional.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   // Bound the party_context size with a reasonable number.
71   static constexpr size_t kPartyContextMaxSize = 20;
72 
73   // Default constructor returns an IsolationInfo with empty origins, a null
74   // SiteForCookies(), null |party_context|, and a RequestType of kOther.
75   IsolationInfo();
76   IsolationInfo(const IsolationInfo&);
77   IsolationInfo(IsolationInfo&&);
78   ~IsolationInfo();
79 
80   IsolationInfo& operator=(const IsolationInfo&);
81   IsolationInfo& operator=(IsolationInfo&&);
82 
83   // Simple constructor for internal requests. Sets |frame_origin| and
84   // |site_for_cookies| match |top_frame_origin|. Sets |request_type| to
85   // kOther. Will only send SameSite cookies to the site associated with
86   // the passed in origin. |party_context| is set to be an empty set.
87   static IsolationInfo CreateForInternalRequest(
88       const url::Origin& top_frame_origin);
89 
90   // Creates a transient IsolationInfo. A transient IsolationInfo will not save
91   // data to disk and not send SameSite cookies. Equivalent to calling
92   // CreateForInternalRequest with a fresh opaque origin.
93   static IsolationInfo CreateTransient();
94 
95   // Creates an IsolationInfo from the serialized contents. Returns a nullopt
96   // if deserialization fails or if data is inconsistent.
97   static absl::optional<IsolationInfo> Deserialize(
98       const std::string& serialized);
99 
100   // Creates an IsolationInfo with the provided parameters. If the parameters
101   // are inconsistent, DCHECKs. In particular:
102   // * If |request_type| is kMainFrame, |top_frame_origin| must equal
103   //   |frame_origin|, and |site_for_cookies| must be either null or first party
104   //   with respect to them.
105   // * If |request_type| is kSubFrame, |top_frame_origin| must be
106   //   first party with respect to |site_for_cookies|, or |site_for_cookies|
107   //   must be null.
108   // * If |request_type| is kOther, |top_frame_origin| and
109   //   |frame_origin| must be first party with respect to |site_for_cookies|, or
110   //   |site_for_cookies| must be null.
111   // * If |party_context| is not empty, |top_frame_origin| must not be null.
112   // * If |nonce| is specified, then |top_frame_origin| must not be null.
113   //
114   // Note that the |site_for_cookies| consistency checks are skipped when
115   // |site_for_cookies| is not HTTP/HTTPS.
116   static IsolationInfo Create(
117       RequestType request_type,
118       const url::Origin& top_frame_origin,
119       const url::Origin& frame_origin,
120       const SiteForCookies& site_for_cookies,
121       absl::optional<std::set<SchemefulSite>> party_context = absl::nullopt,
122       const absl::optional<base::UnguessableToken>& nonce = absl::nullopt);
123 
124   // TODO(crbug/1372769): Remove this and create a safer way to ensure NIKs
125   // created from NAKs aren't used by accident.
126   static IsolationInfo DoNotUseCreatePartialFromNak(
127       const net::NetworkAnonymizationKey& network_anonymization_key);
128 
129   // Returns nullopt if the arguments are not consistent. Otherwise, returns a
130   // fully populated IsolationInfo. Any IsolationInfo that can be created by
131   // the other construction methods, including the 0-argument constructor, is
132   // considered consistent.
133   //
134   // Intended for use by cross-process deserialization.
135   static absl::optional<IsolationInfo> CreateIfConsistent(
136       RequestType request_type,
137       const absl::optional<url::Origin>& top_frame_origin,
138       const absl::optional<url::Origin>& frame_origin,
139       const SiteForCookies& site_for_cookies,
140       absl::optional<std::set<SchemefulSite>> party_context = absl::nullopt,
141       const absl::optional<base::UnguessableToken>& nonce = absl::nullopt);
142 
143   // Create a new IsolationInfo for a redirect to the supplied origin. |this| is
144   // unmodified.
145   IsolationInfo CreateForRedirect(const url::Origin& new_origin) const;
146 
147   // Intended for temporary use in locations that should be using main frame and
148   // frame origin, but are currently only using frame origin, because the
149   // creating object may be shared across main frame objects. Having a special
150   // constructor for these methods makes it easier to keep track of locating
151   // callsites that need to have their IsolationInfo filled in.
152   static IsolationInfo ToDoUseTopFrameOriginAsWell(
153       const url::Origin& incorrectly_used_frame_origin);
154 
request_type()155   RequestType request_type() const { return request_type_; }
156 
IsEmpty()157   bool IsEmpty() const { return !top_frame_origin_; }
158 
159   // These may only be nullopt if created by the empty constructor. If one is
160   // nullopt, both are, and SiteForCookies is null.
161   //
162   // Note that these are the values the IsolationInfo was created with. In the
163   // case an IsolationInfo was created from a NetworkIsolationKey, they may be
164   // scheme + eTLD+1 instead of actual origins.
top_frame_origin()165   const absl::optional<url::Origin>& top_frame_origin() const {
166     return top_frame_origin_;
167   }
168   const absl::optional<url::Origin>& frame_origin() const;
169 
network_isolation_key()170   const NetworkIsolationKey& network_isolation_key() const {
171     return network_isolation_key_;
172   }
173 
network_anonymization_key()174   const NetworkAnonymizationKey& network_anonymization_key() const {
175     return network_anonymization_key_;
176   }
177 
nonce()178   const absl::optional<base::UnguessableToken>& nonce() const { return nonce_; }
179 
180   // The value that should be consulted for the third-party cookie blocking
181   // policy, as defined in Section 2.1.1 and 2.1.2 of
182   // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site.
183   //
184   // WARNING: This value must only be used for the third-party cookie blocking
185   //          policy. It MUST NEVER be used for any kind of SECURITY check.
site_for_cookies()186   const SiteForCookies& site_for_cookies() const { return site_for_cookies_; }
187 
188   // Do not use outside of testing. Returns the `frame_origin_`.
189   const absl::optional<url::Origin>& frame_origin_for_testing() const;
190 
191   // Return |party_context| which exclude the top frame origin and the frame
192   // origin.
193   // TODO(mmenke): Make this function PartyContextForTesting() after switching
194   // RenderFrameHostImpl to use the parent IsolationInfo to create the child
195   // IsolationInfo instead of walking through all parent frames.
party_context()196   const absl::optional<std::set<SchemefulSite>>& party_context() const {
197     return party_context_;
198   }
199 
200   bool IsEqualForTesting(const IsolationInfo& other) const;
201 
202   NetworkAnonymizationKey CreateNetworkAnonymizationKeyForIsolationInfo(
203       const absl::optional<url::Origin>& top_frame_origin,
204       const absl::optional<url::Origin>& frame_origin,
205       const absl::optional<base::UnguessableToken>& nonce) const;
206 
207   // Serialize the `IsolationInfo` into a string. Fails if transient, returning
208   // an empty string.
209   std::string Serialize() const;
210 
211   std::string DebugString() const;
212 
213  private:
214   IsolationInfo(RequestType request_type,
215                 const absl::optional<url::Origin>& top_frame_origin,
216                 const absl::optional<url::Origin>& frame_origin,
217                 const SiteForCookies& site_for_cookies,
218                 const absl::optional<base::UnguessableToken>& nonce,
219                 absl::optional<std::set<SchemefulSite>> party_context);
220 
221   RequestType request_type_;
222 
223   absl::optional<url::Origin> top_frame_origin_;
224   absl::optional<url::Origin> frame_origin_;
225 
226   // This can be deduced from the two origins above, but keep a cached version
227   // to avoid repeated eTLD+1 calculations, when this is using eTLD+1.
228   NetworkIsolationKey network_isolation_key_;
229 
230   NetworkAnonymizationKey network_anonymization_key_;
231 
232   SiteForCookies site_for_cookies_;
233 
234   // Having a nonce is a way to force a transient opaque `IsolationInfo`
235   // for non-opaque origins.
236   absl::optional<base::UnguessableToken> nonce_;
237 
238   // This will hold the list of distinct sites in the form of SchemefulSite to
239   // be used for First-Party-Sets check.
240   //
241   // For |request_type_| being either RequestType::kMainFrame or
242   // RequestType::kSubFrame, |party_context| holds the set of the sites
243   // of the frames in between the current frame and the top frame (i.e. not
244   // considering the current frame or the top frame).
245   //
246   // For |request_type_| being RequestType::kOther, |party_context_| holds the
247   // above, and also the site of the current frame.
248   //
249   // Note that if an intermediate frame shares a site with the top frame, that
250   // frame's site is not reflected in the |party_context_|. Also note that if an
251   // intermediate frame shares a site with the current frame, that frame's site
252   // is still included in the set. The top frame's site is excluded because it
253   // is redundant with the |top_frame_origin_| field. The current frame is
254   // excluded to make it easier to update on subframe redirects.
255   absl::optional<std::set<SchemefulSite>> party_context_;
256 
257   // Mojo serialization code needs to access internal party_context_ field.
258   friend struct mojo::StructTraits<network::mojom::IsolationInfoDataView,
259                                    IsolationInfo>;
260 };
261 
262 }  // namespace net
263 
264 #endif  // NET_BASE_ISOLATION_INFO_H_
265