• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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_COOKIES_COOKIE_UTIL_H_
6 #define NET_COOKIES_COOKIE_UTIL_H_
7 
8 #include <optional>
9 #include <string>
10 #include <vector>
11 
12 #include "base/functional/callback_forward.h"
13 #include "base/time/time.h"
14 #include "base/types/optional_ref.h"
15 #include "net/base/net_export.h"
16 #include "net/cookies/canonical_cookie.h"
17 #include "net/cookies/cookie_access_result.h"
18 #include "net/cookies/cookie_constants.h"
19 #include "net/cookies/cookie_options.h"
20 #include "net/cookies/cookie_setting_override.h"
21 #include "net/cookies/site_for_cookies.h"
22 #include "net/first_party_sets/first_party_set_metadata.h"
23 #include "net/first_party_sets/first_party_sets_cache_filter.h"
24 #include "net/storage_access_api/status.h"
25 #include "url/origin.h"
26 
27 class GURL;
28 
29 namespace net {
30 
31 class IsolationInfo;
32 class SchemefulSite;
33 class CookieAccessDelegate;
34 class CookieInclusionStatus;
35 class ParsedCookie;
36 
37 namespace cookie_util {
38 
39 // Constants for use in VLOG
40 const int kVlogPerCookieMonster = 1;
41 const int kVlogSetCookies = 7;
42 const int kVlogGarbageCollection = 5;
43 
44 // This enum must match the numbering for StorageAccessResult in
45 // histograms/metadata/storage/enums.xml. Do not reorder or remove items, only
46 // add new items at the end.
47 enum class StorageAccessResult {
48   ACCESS_BLOCKED = 0,
49   ACCESS_ALLOWED = 1,
50   ACCESS_ALLOWED_STORAGE_ACCESS_GRANT = 2,
51   OBSOLETE_ACCESS_ALLOWED_FORCED = 3 /*(DEPRECATED)*/,
52   ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT = 4,
53   ACCESS_ALLOWED_3PCD_TRIAL = 5,
54   ACCESS_ALLOWED_3PCD_METADATA_GRANT = 6,
55   ACCESS_ALLOWED_3PCD_HEURISTICS_GRANT = 7,
56   // ACCESS_ALLOWED_CORS_EXCEPTION = 8,  // Deprecated
57   ACCESS_ALLOWED_TOP_LEVEL_3PCD_TRIAL = 9,
58   ACCESS_ALLOWED_SCHEME = 10,
59   kMaxValue = ACCESS_ALLOWED_SCHEME,
60 };
61 
62 // This enum's values correspond to the values of the HTTP request header
63 // `Sec-Fetch-Storage-Access`, which is applied to cross-site requests.
64 enum class StorageAccessStatus {
65   // Applies to context that does not have unpartitioned cookie access, and does
66   // not have the `storage-access` permission.
67   kNone = 0,
68   // Applies to context that has `storage-access` permission, but has not opted
69   // into using it; the context also does not have unpartitioned cookie access
70   // through some other means.
71   kInactive = 1,
72   // Applies to context that has unpartitioned cookie access.
73   kActive = 2
74 };
75 
76 // These values are persisted to logs. Entries should not be renumbered and
77 // numeric values should never be reused.
78 // The values of this enum correspond to possible reasons a request's
79 // StorageAccessStatus may be absent (nullopt), as well as the possible values
80 // when it is non-nullopt.
81 //
82 // LINT.IfChange(StorageAccessStatusOutcome)
83 enum class StorageAccessStatusOutcome {
84   // The feature is disabled.
85   kOmittedFeatureDisabled = 0,
86   // The request is same-site.
87   kOmittedSameSite = 1,
88   // The storage access status is `none`.
89   kValueNone = 2,
90   // The storage access status is `inactive`.
91   kValueInactive = 3,
92   // The storage access status is `active`.
93   kValueActive = 4,
94   kMaxValue = kValueActive
95 };
96 // LINT.ThenChange(//tools/metrics/histograms/metadata/storage/enums.xml:StorageAccessStatusOutcome)
97 
98 // These values are persisted to logs. Entries should not be renumbered and
99 // numeric values should never be reused.
100 // The values of this enum correspond to possible reasons the
101 // `Sec-Fetch-Storage-Access` header may be omitted from a request, as well as
102 // the possible values of the header when it is included.
103 enum class SecFetchStorageAccessOutcome {
104   // The request's storage access status is nullopt.
105   kOmittedStatusMissing = 0,
106   // The request's credentials mode is not "include".
107   kOmittedRequestOmitsCredentials = 1,
108   // The `Sec-Fetch-Storage-Access` header is included and has the value `none`.
109   kValueNone = 2,
110   // The `Sec-Fetch-Storage-Access` header is included and has the value
111   // `inactive`.
112   kValueInactive = 3,
113   // The `Sec-Fetch-Storage-Access` header is included and has the value
114   // `active`.
115   kValueActive = 4,
116   kMaxValue = kValueActive
117 };
118 
119 // These values are persisted to logs. Entries should not be renumbered and
120 // numeric values should never be reused.
121 // The values of this enum correspond to the possible outcomes of a call to
122 // URLRequest::ShouldSetLoadWithStorageAccess().
123 //
124 // LINT.IfChange(ActivateStorageAccessLoadOutcome)
125 enum class ActivateStorageAccessLoadOutcome {
126   // Applies when the `Activate-Storage-Access` header behavior is not enabled
127   // under the existing feature flags or content settings.
128   kFailureHeaderDisabled = 0,
129   // Applies when a response includes the `Activate-Storage-Access: load`
130   // header, but its corresponding request either has an omitted storage access
131   // status, or has a storage access status of `none`.
132   kFailureInvalidStatus = 1,
133   // Applies when a response includes the `Activate-Storage-Access: load`
134   // header, and that header is honored by the browser.
135   kSuccess = 2,
136   kMaxValue = kSuccess
137 };
138 // LINT.ThenChange(//tools/metrics/histograms/metadata/storage/enums.xml:ActivateStorageAccessLoadOutcome)
139 
140 // These values are persisted to logs. Entries should not be renumbered and
141 // numeric values should never be reused.
142 // The values of this enum correspond to the possible outcomes of a call to
143 // URLRequestHttpJob::NeedsRetryWithStorageAccess().
144 //
145 // LINT.IfChange(ActivateStorageAccessRetryOutcome)
146 enum class ActivateStorageAccessRetryOutcome {
147   // Applies when the `Activate-Storage-Access` header behavior is not enabled
148   // under the existing feature flags or content settings.
149   kFailureHeaderDisabled = 0,
150   // Applies when a response includes a well-formed
151   // `Activate-Storage-Access: retry; ..." header, but the corresponding
152   // request's `Sec-Fetch-Storage-Access` header is not `inactive`.
153   kFailureIneffectiveRetry = 1,
154   // Applies when a response includes a well-formed
155   // "Activate-Storage-Access: retry; ..." header, and that header is honored
156   // by the browser.
157   kSuccess = 2,
158   kMaxValue = kSuccess
159 };
160 // LINT.ThenChange(//tools/metrics/histograms/metadata/storage/enums.xml:ActivateStorageAccessRetryOutcome)
161 
162 // Helper to fire telemetry indicating if a given request for storage was
163 // allowed or not by the provided |result|.
164 NET_EXPORT void FireStorageAccessHistogram(StorageAccessResult result);
165 
166 // Returns the effective TLD+1 for a given host. This only makes sense for http
167 // and https schemes. For other schemes, the host will be returned unchanged
168 // (minus any leading period).
169 NET_EXPORT std::string GetEffectiveDomain(const std::string& scheme,
170                                           const std::string& host);
171 
172 // Determine the actual cookie domain based on the domain string passed
173 // (if any) and the URL from which the cookie came.
174 // On success returns true, and sets cookie_domain to either a
175 //   -host cookie domain (ex: "google.com")
176 //   -domain cookie domain (ex: ".google.com")
177 // On success, DomainIsHostOnly(url.host()) is DCHECKed. The URL's host must not
178 // begin with a '.' character.
179 NET_EXPORT bool GetCookieDomainWithString(const GURL& url,
180                                           const std::string& domain_string,
181                                           CookieInclusionStatus& status,
182                                           std::string* result);
183 
184 // Returns true if a domain string represents a host-only cookie,
185 // i.e. it doesn't begin with a leading '.' character.
186 NET_EXPORT bool DomainIsHostOnly(const std::string& domain_string);
187 
188 // If |cookie_domain| is nonempty and starts with a "." character, this returns
189 // the substring of |cookie_domain| without the leading dot. (Note only one
190 // leading dot is stripped, if there are multiple.) Otherwise it returns
191 // |cookie_domain|. This is useful for converting from CanonicalCookie's
192 // representation of a cookie domain to the RFC's notion of a cookie's domain.
193 NET_EXPORT std::string CookieDomainAsHost(const std::string& cookie_domain);
194 
195 // Parses the string with the cookie expiration time (very forgivingly).
196 // Returns the "null" time on failure.
197 //
198 // If the expiration date is below or above the platform-specific range
199 // supported by Time::FromUTCExplodeded(), then this will return Time(1) or
200 // Time::Max(), respectively.
201 NET_EXPORT base::Time ParseCookieExpirationTime(const std::string& time_string);
202 
203 // Returns the canonical path based on the specified url and path attribute
204 // value. Note that this method does not enforce character set or size
205 // checks on `path_string`.
206 NET_EXPORT std::string CanonPathWithString(const GURL& url,
207                                            const std::string& path_string);
208 
209 // Get a cookie's URL from it's domain, path, and source scheme.
210 // The first field can be the combined domain-and-host-only-flag (e.g. the
211 // string returned by CanonicalCookie::Domain()) as opposed to the domain
212 // attribute per RFC6265bis. The GURL is constructed after stripping off any
213 // leading dot.
214 // Note: the GURL returned by this method is not guaranteed to be valid.
215 NET_EXPORT GURL CookieDomainAndPathToURL(const std::string& domain,
216                                          const std::string& path,
217                                          const std::string& source_scheme);
218 NET_EXPORT GURL CookieDomainAndPathToURL(const std::string& domain,
219                                          const std::string& path,
220                                          bool is_https);
221 NET_EXPORT GURL CookieDomainAndPathToURL(const std::string& domain,
222                                          const std::string& path,
223                                          CookieSourceScheme source_scheme);
224 
225 // Convenience for converting a cookie origin (domain and https pair) to a URL.
226 NET_EXPORT GURL CookieOriginToURL(const std::string& domain, bool is_https);
227 
228 // Returns a URL that could have been the cookie's source.
229 // Not guaranteed to actually be the URL that set the cookie. Not guaranteed to
230 // be a valid GURL. Intended as a shim for SetCanonicalCookieAsync calls, where
231 // a source URL is required but only a source scheme may be available.
232 NET_EXPORT GURL SimulatedCookieSource(const CanonicalCookie& cookie,
233                                       const std::string& source_scheme);
234 
235 // Provisional evaluation of acceptability of setting secure cookies on
236 // `source_url` based only on the `source_url`'s scheme and whether it
237 // is a localhost URL.  If this returns kNonCryptographic, it may be upgraded to
238 // kTrustworthy by a CookieAccessDelegate when the cookie operation is being
239 // performed, as the delegate may have access to user settings like manually
240 // configured test domains which declare additional things trustworthy.
241 NET_EXPORT CookieAccessScheme ProvisionalAccessScheme(const GURL& source_url);
242 
243 // |domain| is the output of cookie.Domain() for some cookie. This returns true
244 // if a |domain| indicates that the cookie can be accessed by |host|.
245 // See comment on CanonicalCookie::IsDomainMatch().
246 NET_EXPORT bool IsDomainMatch(const std::string& domain,
247                               const std::string& host);
248 
249 // Returns true if the given |url_path| path-matches |cookie_path|
250 // as described in section 5.1.4 in RFC 6265. This returns true if |cookie_path|
251 // and |url_path| are identical, or if |url_path| is a subdirectory of
252 // |cookie_path|.
253 NET_EXPORT bool IsOnPath(const std::string& cookie_path,
254                          const std::string& url_path);
255 
256 // Returns the CookiePrefix (or COOKIE_PREFIX_NONE if none) that
257 // applies to the given cookie |name|.
258 CookiePrefix GetCookiePrefix(const std::string& name);
259 
260 // Returns true if the cookie does not violate any constraints imposed
261 // by the cookie name's prefix, as described in
262 // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-13#name-cookie-name-prefixes
263 bool IsCookiePrefixValid(CookiePrefix prefix,
264                          const GURL& url,
265                          const ParsedCookie& parsed_cookie);
266 // As above. `secure`, `domain`, and `path` are the raw attribute values (i.e.
267 // as taken from a ParsedCookie), NOT in normalized form as represented in
268 // CookieBase.
269 bool IsCookiePrefixValid(CookiePrefix prefix,
270                          const GURL& url,
271                          bool secure,
272                          const std::string& domain,
273                          const std::string& path);
274 
275 // Returns true iff the cookie is a partitioned cookie with a nonce or that
276 // does not violate the semantics of the Partitioned attribute:
277 // - Must have the Secure attribute OR the cookie partition contains a nonce.
278 bool IsCookiePartitionedValid(const GURL& url,
279                               const ParsedCookie& parsed_cookie,
280                               bool partition_has_nonce);
281 bool IsCookiePartitionedValid(const GURL& url,
282                               bool secure,
283                               bool is_partitioned,
284                               bool partition_has_nonce);
285 
286 // A ParsedRequestCookie consists of the key and value of the cookie.
287 using ParsedRequestCookie = std::pair<std::string, std::string>;
288 using ParsedRequestCookies = std::vector<ParsedRequestCookie>;
289 
290 // Assumes that |header_value| is the cookie header value of a HTTP Request
291 // following the cookie-string schema of RFC 6265, section 4.2.1, and returns
292 // cookie name/value pairs. If cookie values are presented in double quotes,
293 // these will appear in |parsed_cookies| as well. The cookie header can be
294 // written by non-Chromium consumers (such as extensions), so the header may not
295 // be well-formed.
296 NET_EXPORT void ParseRequestCookieLine(const std::string& header_value,
297                                        ParsedRequestCookies* parsed_cookies);
298 
299 // Writes all cookies of |parsed_cookies| into a HTTP Request header value
300 // that belongs to the "Cookie" header. The entries of |parsed_cookies| must
301 // already be appropriately escaped.
302 NET_EXPORT std::string SerializeRequestCookieLine(
303     const ParsedRequestCookies& parsed_cookies);
304 
305 // Determines which of the cookies for the request URL can be accessed, with
306 // respect to the SameSite attribute. This applies to looking up existing
307 // cookies for HTTP requests. For looking up cookies for non-HTTP APIs (i.e.,
308 // JavaScript), see ComputeSameSiteContextForScriptGet. For setting new cookies,
309 // see ComputeSameSiteContextForResponse and ComputeSameSiteContextForScriptSet.
310 //
311 // `url_chain` is a non-empty vector of URLs, the last of which is the current
312 // request URL. It represents the redirect chain of the current request. The
313 // redirect chain is used to calculate whether there has been a cross-site
314 // redirect. In order for a context to be deemed strictly same-site, there must
315 // not have been any cross-site redirects.
316 //
317 // `site_for_cookies` is the currently navigated to site that should be
318 // considered "first-party" for cookies.
319 //
320 // `initiator` is the origin ultimately responsible for getting the request
321 // issued. It may be different from `site_for_cookies`.
322 //
323 // std::nullopt for `initiator` denotes that the navigation was initiated by
324 // the user directly interacting with the browser UI, e.g. entering a URL
325 // or selecting a bookmark.
326 //
327 // `is_main_frame_navigation` is whether the request is for a navigation that
328 // targets the main frame or top-level browsing context. These requests may
329 // sometimes send SameSite=Lax cookies but not SameSite=Strict cookies.
330 //
331 // If `force_ignore_site_for_cookies` is specified, all SameSite cookies will be
332 // attached, i.e. this will return SAME_SITE_STRICT. This flag is set to true
333 // when the `site_for_cookies` is a chrome:// URL embedding a secure origin,
334 // among other scenarios.
335 // This is *not* set when the *initiator* is chrome-extension://,
336 // which is intentional, since it would be bad to let an extension arbitrarily
337 // redirect anywhere and bypass SameSite=Strict rules.
338 //
339 // See also documentation for corresponding methods on net::URLRequest.
340 //
341 // `http_method` is used to enforce the requirement that, in a context that's
342 // lax same-site but not strict same-site, SameSite=lax cookies be only sent
343 // when the method is "safe" in the RFC7231 section 4.2.1 sense.
344 NET_EXPORT CookieOptions::SameSiteCookieContext
345 ComputeSameSiteContextForRequest(const std::string& http_method,
346                                  const std::vector<GURL>& url_chain,
347                                  const SiteForCookies& site_for_cookies,
348                                  const std::optional<url::Origin>& initiator,
349                                  bool is_main_frame_navigation,
350                                  bool force_ignore_site_for_cookies);
351 
352 // As above, but applying for scripts. `initiator` here should be the initiator
353 // used when fetching the document.
354 // If `force_ignore_site_for_cookies` is true, this returns SAME_SITE_STRICT.
355 NET_EXPORT CookieOptions::SameSiteCookieContext
356 ComputeSameSiteContextForScriptGet(const GURL& url,
357                                    const SiteForCookies& site_for_cookies,
358                                    const std::optional<url::Origin>& initiator,
359                                    bool force_ignore_site_for_cookies);
360 
361 // Determines which of the cookies for the request URL can be set from a network
362 // response, with respect to the SameSite attribute. This will only return
363 // CROSS_SITE or SAME_SITE_LAX (cookie sets of SameSite=strict cookies are
364 // permitted in same contexts that sets of SameSite=lax cookies are).
365 // `url_chain` is a non-empty vector of URLs, the last of which is the current
366 // request URL. It represents the redirect chain of the current request. The
367 // redirect chain is used to calculate whether there has been a cross-site
368 // redirect.
369 // `is_main_frame_navigation` is whether the request was for a navigation that
370 // targets the main frame or top-level browsing context. Both SameSite=Lax and
371 // SameSite=Strict cookies may be set by any main frame navigation.
372 // If `force_ignore_site_for_cookies` is true, this returns SAME_SITE_LAX.
373 NET_EXPORT CookieOptions::SameSiteCookieContext
374 ComputeSameSiteContextForResponse(const std::vector<GURL>& url_chain,
375                                   const SiteForCookies& site_for_cookies,
376                                   const std::optional<url::Origin>& initiator,
377                                   bool is_main_frame_navigation,
378                                   bool force_ignore_site_for_cookies);
379 
380 // Determines which of the cookies for `url` can be set from a script context,
381 // with respect to the SameSite attribute. This will only return CROSS_SITE or
382 // SAME_SITE_LAX (cookie sets of SameSite=strict cookies are permitted in same
383 // contexts that sets of SameSite=lax cookies are).
384 // If `force_ignore_site_for_cookies` is true, this returns SAME_SITE_LAX.
385 NET_EXPORT CookieOptions::SameSiteCookieContext
386 ComputeSameSiteContextForScriptSet(const GURL& url,
387                                    const SiteForCookies& site_for_cookies,
388                                    bool force_ignore_site_for_cookies);
389 
390 // Determines which of the cookies for |url| can be accessed when fetching a
391 // subresources. This is either CROSS_SITE or SAME_SITE_STRICT,
392 // since the initiator for a subresource is the frame loading it.
393 NET_EXPORT CookieOptions::SameSiteCookieContext
394 // If |force_ignore_site_for_cookies| is true, this returns SAME_SITE_STRICT.
395 ComputeSameSiteContextForSubresource(const GURL& url,
396                                      const SiteForCookies& site_for_cookies,
397                                      bool force_ignore_site_for_cookies);
398 
399 NET_EXPORT bool IsPortBoundCookiesEnabled();
400 
401 NET_EXPORT bool IsSchemeBoundCookiesEnabled();
402 
403 // Returns true if either portion of OBC is enabled.
404 NET_EXPORT bool IsOriginBoundCookiesPartiallyEnabled();
405 
406 NET_EXPORT bool IsTimeLimitedInsecureCookiesEnabled();
407 
408 // Returns whether the respective feature is enabled.
409 NET_EXPORT bool IsSchemefulSameSiteEnabled();
410 
411 // Computes the First-Party Sets metadata and cache match information.
412 // `isolation_info` must be fully populated.
413 //
414 // The result may be returned synchronously, or `callback` may be invoked
415 // asynchronously with the result. The callback will be invoked iff the return
416 // value is nullopt; i.e. a result will be provided via return value or
417 // callback, but not both, and not neither.
418 [[nodiscard]] NET_EXPORT std::optional<
419     std::pair<FirstPartySetMetadata, FirstPartySetsCacheFilter::MatchInfo>>
420 ComputeFirstPartySetMetadataMaybeAsync(
421     const SchemefulSite& request_site,
422     const IsolationInfo& isolation_info,
423     const CookieAccessDelegate* cookie_access_delegate,
424     base::OnceCallback<void(FirstPartySetMetadata,
425                             FirstPartySetsCacheFilter::MatchInfo)> callback);
426 
427 // Converts a string representing the http request method to its enum
428 // representation.
429 NET_EXPORT CookieOptions::SameSiteCookieContext::ContextMetadata::HttpMethod
430 HttpMethodStringToEnum(const std::string& in);
431 
432 // Takes a CookieAccessResult and returns a bool, returning true if the
433 // CookieInclusionStatus in CookieAccessResult was set to "include", else
434 // returning false.
435 //
436 // Can be used with SetCanonicalCookie when you don't need to know why a cookie
437 // was blocked, only whether it was blocked.
438 NET_EXPORT bool IsCookieAccessResultInclude(
439     CookieAccessResult cookie_access_result);
440 
441 // Turn a CookieAccessResultList into a CookieList by stripping out access
442 // results (for callers who only care about cookies).
443 NET_EXPORT CookieList
444 StripAccessResults(const CookieAccessResultList& cookie_access_result_list);
445 
446 // Records port related metrics from Omnibox navigations.
447 NET_EXPORT void RecordCookiePortOmniboxHistograms(const GURL& url);
448 
449 // Checks invariants that should be upheld w.r.t. the included and excluded
450 // cookies. Namely: the included cookies should be elements of
451 // `included_cookies`; excluded cookies should be elements of
452 // `excluded_cookies`; and included cookies should be in the correct sorted
453 // order.
454 NET_EXPORT void DCheckIncludedAndExcludedCookieLists(
455     const CookieAccessResultList& included_cookies,
456     const CookieAccessResultList& excluded_cookies);
457 
458 // Returns the default third-party cookie blocking setting, which is false
459 // unless you enable ForceThirdPartyCookieBlocking with the command line switch
460 // --test-third-party-cookie-phaseout.
461 NET_EXPORT bool IsForceThirdPartyCookieBlockingEnabled();
462 
463 NET_EXPORT bool PartitionedCookiesDisabledByCommandLine();
464 
465 // Adds or removes the kStorageAccessGrantEligible override, as appropriate.
466 // Mutates `overrides` in place.
467 NET_EXPORT void AddOrRemoveStorageAccessApiOverride(
468     const GURL& url,
469     StorageAccessApiStatus api_status,
470     base::optional_ref<const url::Origin> request_initiator,
471     CookieSettingOverrides& overrides);
472 
473 }  // namespace cookie_util
474 
475 }  // namespace net
476 
477 #endif  // NET_COOKIES_COOKIE_UTIL_H_
478