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