1 // Copyright 2020 The Chromium Authors. All rights reserved.
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 "base/optional.h"
9 #include "net/base/net_export.h"
10 #include "net/base/network_isolation_key.h"
11 #include "net/cookies/site_for_cookies.h"
12 #include "url/origin.h"
13 
14 namespace net {
15 
16 // Class to store information about network stack requests based on the context
17 // in which they are made. It provides NetworkIsolationKeys, used to shard
18 // storage, and SiteForCookies, used determine when to send same site cookies.
19 // The IsolationInfo is typically the same for all subresource requests made in
20 // the context of the same frame, but may be different for different frames
21 // within a page. The IsolationInfo associated with requests for frames may
22 // change as redirects are followed, and this class also contains the logic on
23 // how to do that.
24 //
25 // The SiteForCookies logic in this class is currently unused, but will
26 // eventually replace the logic in URLRequest/RedirectInfo for tracking and
27 // updating that value.
28 class NET_EXPORT IsolationInfo {
29  public:
30   // The update-on-redirect patterns.
31   //
32   // In general, almost everything should use kOther, as a
33   // kMainFrame request accidentally sent or redirected to an attacker
34   // allows cross-site tracking, and kSubFrame allows information
35   // leaks between sites that iframe each other. Anything that uses
36   // kMainFrame should be user triggered and user visible, like a main
37   // frame navigation or downloads.
38   //
39   // The RequestType is a core part of an IsolationInfo, and using an
40   // IsolationInfo with one value to create an IsolationInfo with another
41   // RequestType is generally not a good idea, unless the RequestType of the
42   // new IsolationInfo is kOther.
43   enum class RequestType {
44     // Updates top level origin, frame origin, and SiteForCookies on redirect.
45     // These requests allow users to be recognized across sites on redirect, so
46     // should not generally be used for anything other than navigations.
47     kMainFrame,
48 
49     // Only updates frame origin on redirect.
50     kSubFrame,
51 
52     // Updates nothing on redirect.
53     kOther,
54   };
55 
56   // Default constructor returns an IsolationInfo with empty origins, a null
57   // SiteForCookies(), and a RequestType of kOther.
58   IsolationInfo();
59   IsolationInfo(const IsolationInfo&);
60   IsolationInfo(IsolationInfo&&);
61   ~IsolationInfo();
62 
63   IsolationInfo& operator=(const IsolationInfo&);
64   IsolationInfo& operator=(IsolationInfo&&);
65 
66   // Simple constructor for internal requests. Sets |frame_origin| and
67   // |site_for_cookies| match |top_frame_origin|. Sets |request_type| to
68   // kOther. Will only send SameSite cookies to the site associated with
69   // the passed in origin.
70   static IsolationInfo CreateForInternalRequest(
71       const url::Origin& top_frame_origin);
72 
73   // Creates a transient IsolationInfo. A transient IsolationInfo will not save
74   // data to disk and not send SameSite cookies. Equivalent to calling
75   // CreateForInternalRequest with a fresh opaque origin.
76   static IsolationInfo CreateTransient();
77 
78   // Creates a non-transient IsolationInfo. Just like a transient IsolationInfo
79   // (no SameSite cookies, opaque Origins), but does write data to disk, so this
80   // allows use of the disk cache with a transient NIK.
81   static IsolationInfo CreateOpaqueAndNonTransient();
82 
83   // Creates an IsolationInfo with the provided parameters. If the parameters
84   // are inconsistent, DCHECKs. In particular:
85   // * If |request_type| is kMainFrame, |top_frame_origin| must equal
86   //   |frame_origin|, and |site_for_cookies| must be either null or first party
87   //   with respect to them.
88   // * If |request_type| is kSubFrame, |top_frame_origin| must be
89   //   first party with respect to |site_for_cookies|, or |site_for_cookies|
90   //   must be null.
91   // * If |request_type| is kOther, |top_frame_origin| and
92   //   |frame_origin| must be first party with respect to |site_for_cookies|, or
93   //   |site_for_cookies| must be null.
94   //
95   // Note that the |site_for_cookies| consistency checks are skipped when
96   // |site_for_cookies| is not HTTP/HTTPS.
97   static IsolationInfo Create(RequestType request_type,
98                               const url::Origin& top_frame_origin,
99                               const url::Origin& frame_origin,
100                               const SiteForCookies& site_for_cookies);
101 
102   // Create an IsolationInfos that may not be fully correct - in particular,
103   // the SiteForCookies will always set to null, and if the NetworkIsolationKey
104   // only has a top frame origin, the frame origin will either be set to the top
105   // frame origin, in the kMainFrame case, or be replaced by an opaque
106   // origin in all other cases. If the NetworkIsolationKey is not fully
107   // populated, will create an empty IsolationInfo. This is intended for use
108   // while transitioning from NIKs being set on only some requests to
109   // IsolationInfos being set on all requests.
110   //
111   // TODO(https://crbug.com/1060631): Remove this once no longer needed.
112   static IsolationInfo CreatePartial(
113       RequestType request_type,
114       const net::NetworkIsolationKey& network_isolation_key);
115 
116   // Returns nullopt if the arguments are not consistent. Otherwise, returns a
117   // fully populated IsolationInfo. Any IsolationInfo that can be created by
118   // the other construction methods, including the 0-argument constructor, is
119   // considered consistent.
120   //
121   // Intended for use by cross-process deserialization.
122   static base::Optional<IsolationInfo> CreateIfConsistent(
123       RequestType request_type,
124       const base::Optional<url::Origin>& top_frame_origin,
125       const base::Optional<url::Origin>& frame_origin,
126       const SiteForCookies& site_for_cookies,
127       bool opaque_and_non_transient);
128 
129   // Create a new IsolationInfo for a redirect to the supplied origin. |this| is
130   // unmodified.
131   IsolationInfo CreateForRedirect(const url::Origin& new_origin) const;
132 
request_type()133   RequestType request_type() const { return request_type_; }
134 
IsEmpty()135   bool IsEmpty() const { return !top_frame_origin_; }
136 
137   // These may only be nullopt if created by the empty constructor. If one is
138   // nullopt, both are, and SiteForCookies is null.
139   //
140   // Note that these are the values the IsolationInfo was created with. In the
141   // case an IsolationInfo was created from a NetworkIsolationKey, they may be
142   // scheme + eTLD+1 instead of actual origins.
top_frame_origin()143   const base::Optional<url::Origin>& top_frame_origin() const {
144     return top_frame_origin_;
145   }
frame_origin()146   const base::Optional<url::Origin>& frame_origin() const {
147     return frame_origin_;
148   }
149 
network_isolation_key()150   const NetworkIsolationKey& network_isolation_key() const {
151     return network_isolation_key_;
152   }
153 
154   // The value that should be consulted for the third-party cookie blocking
155   // policy, as defined in Section 2.1.1 and 2.1.2 of
156   // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site.
157   //
158   // WARNING: This value must only be used for the third-party cookie blocking
159   //          policy. It MUST NEVER be used for any kind of SECURITY check.
site_for_cookies()160   const SiteForCookies& site_for_cookies() const { return site_for_cookies_; }
161 
opaque_and_non_transient()162   bool opaque_and_non_transient() const { return opaque_and_non_transient_; }
163 
164   bool IsEqualForTesting(const IsolationInfo& other) const;
165 
166  private:
167   IsolationInfo(RequestType request_type,
168                 const base::Optional<url::Origin>& top_frame_origin,
169                 const base::Optional<url::Origin>& frame_origin,
170                 const SiteForCookies& site_for_cookies,
171                 bool opaque_and_non_transient);
172 
173   RequestType request_type_;
174 
175   base::Optional<url::Origin> top_frame_origin_;
176   base::Optional<url::Origin> frame_origin_;
177 
178   // This can be deduced from the two origins above, but keep a cached version
179   // to avoid repeated eTLD+1 calculations, when this is using eTLD+1.
180   net::NetworkIsolationKey network_isolation_key_;
181 
182   SiteForCookies site_for_cookies_;
183 
184   bool opaque_and_non_transient_ = false;
185 };
186 
187 }  // namespace net
188 
189 #endif  // NET_BASE_ISOLATION_INFO_H_
190