• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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