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