1 // Copyright 2022 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_NETWORK_ANONYMIZATION_KEY_H_ 6 #define NET_BASE_NETWORK_ANONYMIZATION_KEY_H_ 7 8 #include <cstddef> 9 #include <optional> 10 #include <ostream> 11 #include <string> 12 #include <tuple> 13 14 #include "base/unguessable_token.h" 15 #include "net/base/net_export.h" 16 #include "net/base/network_isolation_key.h" 17 #include "net/base/schemeful_site.h" 18 19 namespace base { 20 class Value; 21 } 22 23 namespace net { 24 25 // NetworkAnonymizationKey (NAK) is used to partition shared network state based 26 // on the context in which requests were made. Most network state is divided 27 // by NAK, with some instead using NetworkIsolationKey. 28 // 29 // NetworkAnonymizationKey contains the following properties: 30 // 31 // `top_frame_site` represents the SchemefulSite of the pages top level frame. 32 // In order to separate first and third party context from each other this field 33 // will always be populated. 34 // 35 // `is_cross_site` indicates whether the key is cross-site or same-site. A 36 // same-site key indicates that he schemeful site of the top frame and the frame 37 // are the same. Intermediary frames between the two may be cross-site to them. 38 // The effect of this property is to partition first-party and third-party 39 // resources within a given `top_frame_site`. 40 // 41 // The following show how the `is_cross_site` boolean is populated for the 42 // innermost frame in the chain. 43 // a->a => is_cross_site = false 44 // a->b => is_cross_site = true 45 // a->b->a => is_cross_site = false 46 // a->(sandboxed a [has nonce]) => is_cross_site = true 47 // 48 // The `nonce` value creates a key for anonymous iframes by giving them a 49 // temporary `nonce` value which changes per top level navigation. For now, any 50 // NetworkAnonymizationKey with a nonce will be considered transient. This is 51 // being considered to possibly change in the future in an effort to allow 52 // anonymous iframes with the same partition key access to shared resources. 53 // The nonce value will be empty except for anonymous iframes. 54 // 55 // This is referred to as "2.5-keyed", to contrast with "double key" (top frame 56 // site, URL) and "triple key" (top frame site, frame site, and URL). The 57 // `is_cross_site` bit carries more information than a double key, but less than 58 // a triple key. 59 class NET_EXPORT NetworkAnonymizationKey { 60 public: 61 // Construct an empty key. 62 NetworkAnonymizationKey(); 63 64 NetworkAnonymizationKey( 65 const NetworkAnonymizationKey& network_anonymization_key); 66 NetworkAnonymizationKey(NetworkAnonymizationKey&& network_anonymization_key); 67 68 ~NetworkAnonymizationKey(); 69 70 NetworkAnonymizationKey& operator=( 71 const NetworkAnonymizationKey& network_anonymization_key); 72 NetworkAnonymizationKey& operator=( 73 NetworkAnonymizationKey&& network_anonymization_key); 74 75 // Compare keys for equality, true if all enabled fields are equal. 76 bool operator==(const NetworkAnonymizationKey& other) const { 77 return std::tie(top_frame_site_, is_cross_site_, nonce_) == 78 std::tie(other.top_frame_site_, other.is_cross_site_, other.nonce_); 79 } 80 81 // Compare keys for inequality, true if any enabled field varies. 82 bool operator!=(const NetworkAnonymizationKey& other) const { 83 return !(*this == other); 84 } 85 86 // Provide an ordering for keys based on all enabled fields. 87 bool operator<(const NetworkAnonymizationKey& other) const { 88 return std::tie(top_frame_site_, is_cross_site_, nonce_) < 89 std::tie(other.top_frame_site_, other.is_cross_site_, other.nonce_); 90 } 91 92 // Create a `NetworkAnonymizationKey` from a `top_frame_site`, assuming it is 93 // same-site (see comment on the class, above) and has no nonce. CreateSameSite(const SchemefulSite & top_frame_site)94 static NetworkAnonymizationKey CreateSameSite( 95 const SchemefulSite& top_frame_site) { 96 return NetworkAnonymizationKey(top_frame_site, false, std::nullopt); 97 } 98 99 // Create a `NetworkAnonymizationKey` from a `top_frame_site`, assuming it is 100 // cross-site (see comment on the class, above) and has no nonce. CreateCrossSite(const SchemefulSite & top_frame_site)101 static NetworkAnonymizationKey CreateCrossSite( 102 const SchemefulSite& top_frame_site) { 103 return NetworkAnonymizationKey(top_frame_site, true, std::nullopt); 104 } 105 106 // Create a `NetworkAnonymizationKey` from a `top_frame_site` and 107 // `frame_site`. This calculates is_cross_site on the basis of those two 108 // sites. 109 static NetworkAnonymizationKey CreateFromFrameSite( 110 const SchemefulSite& top_frame_site, 111 const SchemefulSite& frame_site, 112 std::optional<base::UnguessableToken> nonce = std::nullopt); 113 114 // Creates a `NetworkAnonymizationKey` from a `NetworkIsolationKey`. This is 115 // possible because a `NetworkIsolationKey` must always be more granular 116 // than a `NetworkAnonymizationKey`. 117 static NetworkAnonymizationKey CreateFromNetworkIsolationKey( 118 const net::NetworkIsolationKey& network_isolation_key); 119 120 // Creates a `NetworkAnonymizationKey` from its constituent parts. This 121 // is intended to be used to build a NAK from Mojo, and for tests. 122 static NetworkAnonymizationKey CreateFromParts( 123 const SchemefulSite& top_frame_site, 124 bool is_cross_site, 125 std::optional<base::UnguessableToken> nonce = std::nullopt) { 126 return NetworkAnonymizationKey(top_frame_site, is_cross_site, nonce); 127 } 128 129 // Creates a transient non-empty NetworkAnonymizationKey by creating an opaque 130 // origin. This prevents the NetworkAnonymizationKey from sharing data with 131 // other NetworkAnonymizationKey. 132 static NetworkAnonymizationKey CreateTransient(); 133 134 // Returns the string representation of the key. 135 std::string ToDebugString() const; 136 137 // Returns true if all parts of the key are empty. 138 bool IsEmpty() const; 139 140 // Returns true if `top_frame_site_` is non-empty. 141 bool IsFullyPopulated() const; 142 143 // Returns true if this key's lifetime is short-lived. It may not make sense 144 // to persist state to disk related to it (e.g., disk cache). 145 // A NetworkAnonymizationKey will be considered transient if 146 // `top_frame_site_` is empty or opaque or if the key has a `nonce_`. 147 bool IsTransient() const; 148 149 // Getters for the top frame, frame site, nonce and is cross site flag. GetTopFrameSite()150 const std::optional<SchemefulSite>& GetTopFrameSite() const { 151 return top_frame_site_; 152 } 153 IsCrossSite()154 bool IsCrossSite() const { return is_cross_site_; } 155 IsSameSite()156 bool IsSameSite() const { return !IsCrossSite(); } 157 GetNonce()158 const std::optional<base::UnguessableToken>& GetNonce() const { 159 return nonce_; 160 } 161 162 // Returns a representation of |this| as a base::Value. Returns false on 163 // failure. Succeeds if either IsEmpty() or !IsTransient(). 164 [[nodiscard]] bool ToValue(base::Value* out_value) const; 165 166 // Inverse of ToValue(). Writes the result to |network_anonymization_key|. 167 // Returns false on failure. Fails on values that could not have been produced 168 // by ToValue(), like transient origins. 169 [[nodiscard]] static bool FromValue( 170 const base::Value& value, 171 NetworkAnonymizationKey* out_network_anonymization_key); 172 173 // Determine whether network state partitioning is enabled. This is true if 174 // the `PartitionConnectionsByNetworkIsolationKey` feature is enabled, or if 175 // `PartitionByDefault()` has been called. 176 static bool IsPartitioningEnabled(); 177 178 // Default partitioning to enabled, regardless of feature settings. This must 179 // be called before any calls to `IsPartitioningEnabled()`. 180 static void PartitionByDefault(); 181 182 // Clear partitioning-related globals. 183 static void ClearGlobalsForTesting(); 184 185 private: 186 NetworkAnonymizationKey( 187 const SchemefulSite& top_frame_site, 188 bool is_cross_site, 189 std::optional<base::UnguessableToken> nonce = std::nullopt); 190 191 std::string GetSiteDebugString( 192 const std::optional<SchemefulSite>& site) const; 193 194 static std::optional<std::string> SerializeSiteWithNonce( 195 const SchemefulSite& site); 196 197 // The origin/etld+1 of the top frame of the page making the request. This 198 // will always be populated unless all other fields are also nullopt. 199 std::optional<SchemefulSite> top_frame_site_; 200 201 // True if the frame site is cross site when compared to the top frame site. 202 // This is always false for a non-fully-populated NAK. 203 bool is_cross_site_; 204 205 // for non-opaque origins. 206 std::optional<base::UnguessableToken> nonce_; 207 }; 208 209 NET_EXPORT std::ostream& operator<<(std::ostream& os, 210 const NetworkAnonymizationKey& nak); 211 212 } // namespace net 213 214 #endif // NET_BASE_NETWORK_ANONYMIZATION_KEY_H_ 215