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