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 // Same as CreateTransient, with a `nonce` used to identify requests tagged 93 // with this IsolationInfo in the network service. The `nonce` provides no 94 // additional resource isolation, because the opaque origin in the resulting 95 // IsolationInfo already represents a unique partition. 96 static IsolationInfo CreateTransientWithNonce( 97 const base::UnguessableToken& nonce); 98 99 // Creates an IsolationInfo from the serialized contents. Returns a nullopt 100 // if deserialization fails or if data is inconsistent. 101 static std::optional<IsolationInfo> Deserialize( 102 const std::string& serialized); 103 104 // Creates an IsolationInfo with the provided parameters. If the parameters 105 // are inconsistent, DCHECKs. In particular: 106 // * If |request_type| is kMainFrame, |top_frame_origin| must equal 107 // |frame_origin|, and |site_for_cookies| must be either null or first party 108 // with respect to them. 109 // * If |request_type| is kSubFrame, |top_frame_origin| must be 110 // first party with respect to |site_for_cookies|, or |site_for_cookies| 111 // must be null. 112 // * If |request_type| is kOther, |top_frame_origin| and 113 // |frame_origin| must be first party with respect to |site_for_cookies|, or 114 // |site_for_cookies| must be null. 115 // * If |nonce| is specified, then |top_frame_origin| must not be null. 116 // 117 // Note that the |site_for_cookies| consistency checks are skipped when 118 // |site_for_cookies| is not HTTP/HTTPS. 119 static IsolationInfo Create( 120 RequestType request_type, 121 const url::Origin& top_frame_origin, 122 const url::Origin& frame_origin, 123 const SiteForCookies& site_for_cookies, 124 const std::optional<base::UnguessableToken>& nonce = std::nullopt); 125 126 // TODO(crbug/1372769): Remove this and create a safer way to ensure NIKs 127 // created from NAKs aren't used by accident. 128 static IsolationInfo DoNotUseCreatePartialFromNak( 129 const net::NetworkAnonymizationKey& network_anonymization_key); 130 131 // Returns nullopt if the arguments are not consistent. Otherwise, returns a 132 // fully populated IsolationInfo. Any IsolationInfo that can be created by 133 // the other construction methods, including the 0-argument constructor, is 134 // considered consistent. 135 // 136 // Intended for use by cross-process deserialization. 137 static std::optional<IsolationInfo> CreateIfConsistent( 138 RequestType request_type, 139 const std::optional<url::Origin>& top_frame_origin, 140 const std::optional<url::Origin>& frame_origin, 141 const SiteForCookies& site_for_cookies, 142 const std::optional<base::UnguessableToken>& nonce = std::nullopt); 143 144 // Create a new IsolationInfo for a redirect to the supplied origin. |this| is 145 // unmodified. 146 IsolationInfo CreateForRedirect(const url::Origin& new_origin) const; 147 request_type()148 RequestType request_type() const { return request_type_; } 149 IsEmpty()150 bool IsEmpty() const { return !top_frame_origin_; } 151 152 // These may only be nullopt if created by the empty constructor. If one is 153 // nullopt, both are, and SiteForCookies is null. 154 // 155 // Note that these are the values the IsolationInfo was created with. In the 156 // case an IsolationInfo was created from a NetworkIsolationKey, they may be 157 // scheme + eTLD+1 instead of actual origins. top_frame_origin()158 const std::optional<url::Origin>& top_frame_origin() const { 159 return top_frame_origin_; 160 } 161 const std::optional<url::Origin>& frame_origin() const; 162 network_isolation_key()163 const NetworkIsolationKey& network_isolation_key() const { 164 return network_isolation_key_; 165 } 166 network_anonymization_key()167 const NetworkAnonymizationKey& network_anonymization_key() const { 168 return network_anonymization_key_; 169 } 170 nonce()171 const std::optional<base::UnguessableToken>& nonce() const { return nonce_; } 172 173 // The value that should be consulted for the third-party cookie blocking 174 // policy, as defined in Section 2.1.1 and 2.1.2 of 175 // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site. 176 // 177 // WARNING: This value must only be used for the third-party cookie blocking 178 // policy. It MUST NEVER be used for any kind of SECURITY check. site_for_cookies()179 const SiteForCookies& site_for_cookies() const { return site_for_cookies_; } 180 181 // Do not use outside of testing. Returns the `frame_origin_`. 182 const std::optional<url::Origin>& frame_origin_for_testing() const; 183 184 bool IsEqualForTesting(const IsolationInfo& other) const; 185 186 NetworkAnonymizationKey CreateNetworkAnonymizationKeyForIsolationInfo( 187 const std::optional<url::Origin>& top_frame_origin, 188 const std::optional<url::Origin>& frame_origin, 189 const std::optional<base::UnguessableToken>& nonce) const; 190 191 // Serialize the `IsolationInfo` into a string. Fails if transient, returning 192 // an empty string. 193 std::string Serialize() const; 194 195 std::string DebugString() const; 196 197 private: 198 IsolationInfo(RequestType request_type, 199 const std::optional<url::Origin>& top_frame_origin, 200 const std::optional<url::Origin>& frame_origin, 201 const SiteForCookies& site_for_cookies, 202 const std::optional<base::UnguessableToken>& nonce); 203 204 RequestType request_type_; 205 206 std::optional<url::Origin> top_frame_origin_; 207 std::optional<url::Origin> frame_origin_; 208 209 // This can be deduced from the two origins above, but keep a cached version 210 // to avoid repeated eTLD+1 calculations, when this is using eTLD+1. 211 NetworkIsolationKey network_isolation_key_; 212 213 NetworkAnonymizationKey network_anonymization_key_; 214 215 SiteForCookies site_for_cookies_; 216 217 // Having a nonce is a way to force a transient opaque `IsolationInfo` 218 // for non-opaque origins. 219 std::optional<base::UnguessableToken> nonce_; 220 221 // Mojo serialization code needs to access internal fields. 222 friend struct mojo::StructTraits<network::mojom::IsolationInfoDataView, 223 IsolationInfo>; 224 }; 225 226 } // namespace net 227 228 #endif // NET_BASE_ISOLATION_INFO_H_ 229