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 "net/base/net_export.h" 15 #include "net/cookies/canonical_cookie.h" 16 #include "net/cookies/cookie_access_result.h" 17 #include "net/cookies/cookie_constants.h" 18 #include "net/cookies/cookie_options.h" 19 #include "net/cookies/site_for_cookies.h" 20 #include "net/first_party_sets/first_party_set_metadata.h" 21 #include "net/first_party_sets/first_party_sets_cache_filter.h" 22 #include "url/origin.h" 23 24 class GURL; 25 26 namespace net { 27 28 class IsolationInfo; 29 class SchemefulSite; 30 class CookieAccessDelegate; 31 class CookieInclusionStatus; 32 33 namespace cookie_util { 34 35 // Constants for use in VLOG 36 const int kVlogPerCookieMonster = 1; 37 const int kVlogSetCookies = 7; 38 const int kVlogGarbageCollection = 5; 39 40 // This enum must match the numbering for StorageAccessResult in 41 // histograms/enums.xml. Do not reorder or remove items, only add new items 42 // at the end. 43 enum class StorageAccessResult { 44 ACCESS_BLOCKED = 0, 45 ACCESS_ALLOWED = 1, 46 ACCESS_ALLOWED_STORAGE_ACCESS_GRANT = 2, 47 OBSOLETE_ACCESS_ALLOWED_FORCED = 3 /*(DEPRECATED)*/, 48 ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT = 4, 49 ACCESS_ALLOWED_3PCD_TRIAL = 5, 50 ACCESS_ALLOWED_3PCD_METADATA_GRANT = 6, 51 ACCESS_ALLOWED_3PCD_HEURISTICS_GRANT = 7, 52 ACCESS_ALLOWED_CORS_EXCEPTION = 8, 53 ACCESS_ALLOWED_TOP_LEVEL_3PCD_TRIAL = 9, 54 kMaxValue = ACCESS_ALLOWED_TOP_LEVEL_3PCD_TRIAL, 55 }; 56 57 // Helper to fire telemetry indicating if a given request for storage was 58 // allowed or not by the provided |result|. 59 NET_EXPORT void FireStorageAccessHistogram(StorageAccessResult result); 60 61 // Returns the effective TLD+1 for a given host. This only makes sense for http 62 // and https schemes. For other schemes, the host will be returned unchanged 63 // (minus any leading period). 64 NET_EXPORT std::string GetEffectiveDomain(const std::string& scheme, 65 const std::string& host); 66 67 // Determine the actual cookie domain based on the domain string passed 68 // (if any) and the URL from which the cookie came. 69 // On success returns true, and sets cookie_domain to either a 70 // -host cookie domain (ex: "google.com") 71 // -domain cookie domain (ex: ".google.com") 72 // On success, DomainIsHostOnly(url.host()) is DCHECKed. The URL's host must not 73 // begin with a '.' character. 74 NET_EXPORT bool GetCookieDomainWithString(const GURL& url, 75 const std::string& domain_string, 76 CookieInclusionStatus& status, 77 std::string* result); 78 79 // Returns true if a domain string represents a host-only cookie, 80 // i.e. it doesn't begin with a leading '.' character. 81 NET_EXPORT bool DomainIsHostOnly(const std::string& domain_string); 82 83 // If |cookie_domain| is nonempty and starts with a "." character, this returns 84 // the substring of |cookie_domain| without the leading dot. (Note only one 85 // leading dot is stripped, if there are multiple.) Otherwise it returns 86 // |cookie_domain|. This is useful for converting from CanonicalCookie's 87 // representation of a cookie domain to the RFC's notion of a cookie's domain. 88 NET_EXPORT std::string CookieDomainAsHost(const std::string& cookie_domain); 89 90 // Parses the string with the cookie expiration time (very forgivingly). 91 // Returns the "null" time on failure. 92 // 93 // If the expiration date is below or above the platform-specific range 94 // supported by Time::FromUTCExplodeded(), then this will return Time(1) or 95 // Time::Max(), respectively. 96 NET_EXPORT base::Time ParseCookieExpirationTime(const std::string& time_string); 97 98 // Get a cookie's URL from it's domain, path, and source scheme. 99 // The first field can be the combined domain-and-host-only-flag (e.g. the 100 // string returned by CanonicalCookie::Domain()) as opposed to the domain 101 // attribute per RFC6265bis. The GURL is constructed after stripping off any 102 // leading dot. 103 // Note: the GURL returned by this method is not guaranteed to be valid. 104 NET_EXPORT GURL CookieDomainAndPathToURL(const std::string& domain, 105 const std::string& path, 106 const std::string& source_scheme); 107 NET_EXPORT GURL CookieDomainAndPathToURL(const std::string& domain, 108 const std::string& path, 109 bool is_https); 110 NET_EXPORT GURL CookieDomainAndPathToURL(const std::string& domain, 111 const std::string& path, 112 CookieSourceScheme source_scheme); 113 114 // Convenience for converting a cookie origin (domain and https pair) to a URL. 115 NET_EXPORT GURL CookieOriginToURL(const std::string& domain, bool is_https); 116 117 // Returns a URL that could have been the cookie's source. 118 // Not guaranteed to actually be the URL that set the cookie. Not guaranteed to 119 // be a valid GURL. Intended as a shim for SetCanonicalCookieAsync calls, where 120 // a source URL is required but only a source scheme may be available. 121 NET_EXPORT GURL SimulatedCookieSource(const CanonicalCookie& cookie, 122 const std::string& source_scheme); 123 124 // Provisional evaluation of acceptability of setting secure cookies on 125 // `source_url` based only on the `source_url`'s scheme and whether it 126 // is a localhost URL. If this returns kNonCryptographic, it may be upgraded to 127 // kTrustworthy by a CookieAccessDelegate when the cookie operation is being 128 // performed, as the delegate may have access to user settings like manually 129 // configured test domains which declare additional things trustworthy. 130 NET_EXPORT CookieAccessScheme ProvisionalAccessScheme(const GURL& source_url); 131 132 // |domain| is the output of cookie.Domain() for some cookie. This returns true 133 // if a |domain| indicates that the cookie can be accessed by |host|. 134 // See comment on CanonicalCookie::IsDomainMatch(). 135 NET_EXPORT bool IsDomainMatch(const std::string& domain, 136 const std::string& host); 137 138 // Returns true if the given |url_path| path-matches |cookie_path| 139 // as described in section 5.1.4 in RFC 6265. This returns true if |cookie_path| 140 // and |url_path| are identical, or if |url_path| is a subdirectory of 141 // |cookie_path|. 142 NET_EXPORT bool IsOnPath(const std::string& cookie_path, 143 const std::string& url_path); 144 145 // A ParsedRequestCookie consists of the key and value of the cookie. 146 using ParsedRequestCookie = std::pair<std::string, std::string>; 147 using ParsedRequestCookies = std::vector<ParsedRequestCookie>; 148 149 // Assumes that |header_value| is the cookie header value of a HTTP Request 150 // following the cookie-string schema of RFC 6265, section 4.2.1, and returns 151 // cookie name/value pairs. If cookie values are presented in double quotes, 152 // these will appear in |parsed_cookies| as well. The cookie header can be 153 // written by non-Chromium consumers (such as extensions), so the header may not 154 // be well-formed. 155 NET_EXPORT void ParseRequestCookieLine(const std::string& header_value, 156 ParsedRequestCookies* parsed_cookies); 157 158 // Writes all cookies of |parsed_cookies| into a HTTP Request header value 159 // that belongs to the "Cookie" header. The entries of |parsed_cookies| must 160 // already be appropriately escaped. 161 NET_EXPORT std::string SerializeRequestCookieLine( 162 const ParsedRequestCookies& parsed_cookies); 163 164 // Determines which of the cookies for the request URL can be accessed, with 165 // respect to the SameSite attribute. This applies to looking up existing 166 // cookies for HTTP requests. For looking up cookies for non-HTTP APIs (i.e., 167 // JavaScript), see ComputeSameSiteContextForScriptGet. For setting new cookies, 168 // see ComputeSameSiteContextForResponse and ComputeSameSiteContextForScriptSet. 169 // 170 // `url_chain` is a non-empty vector of URLs, the last of which is the current 171 // request URL. It represents the redirect chain of the current request. The 172 // redirect chain is used to calculate whether there has been a cross-site 173 // redirect. In order for a context to be deemed strictly same-site, there must 174 // not have been any cross-site redirects. 175 // 176 // `site_for_cookies` is the currently navigated to site that should be 177 // considered "first-party" for cookies. 178 // 179 // `initiator` is the origin ultimately responsible for getting the request 180 // issued. It may be different from `site_for_cookies`. 181 // 182 // std::nullopt for `initiator` denotes that the navigation was initiated by 183 // the user directly interacting with the browser UI, e.g. entering a URL 184 // or selecting a bookmark. 185 // 186 // `is_main_frame_navigation` is whether the request is for a navigation that 187 // targets the main frame or top-level browsing context. These requests may 188 // sometimes send SameSite=Lax cookies but not SameSite=Strict cookies. 189 // 190 // If `force_ignore_site_for_cookies` is specified, all SameSite cookies will be 191 // attached, i.e. this will return SAME_SITE_STRICT. This flag is set to true 192 // when the `site_for_cookies` is a chrome:// URL embedding a secure origin, 193 // among other scenarios. 194 // This is *not* set when the *initiator* is chrome-extension://, 195 // which is intentional, since it would be bad to let an extension arbitrarily 196 // redirect anywhere and bypass SameSite=Strict rules. 197 // 198 // See also documentation for corresponding methods on net::URLRequest. 199 // 200 // `http_method` is used to enforce the requirement that, in a context that's 201 // lax same-site but not strict same-site, SameSite=lax cookies be only sent 202 // when the method is "safe" in the RFC7231 section 4.2.1 sense. 203 NET_EXPORT CookieOptions::SameSiteCookieContext 204 ComputeSameSiteContextForRequest(const std::string& http_method, 205 const std::vector<GURL>& url_chain, 206 const SiteForCookies& site_for_cookies, 207 const std::optional<url::Origin>& initiator, 208 bool is_main_frame_navigation, 209 bool force_ignore_site_for_cookies); 210 211 // As above, but applying for scripts. `initiator` here should be the initiator 212 // used when fetching the document. 213 // If `force_ignore_site_for_cookies` is true, this returns SAME_SITE_STRICT. 214 NET_EXPORT CookieOptions::SameSiteCookieContext 215 ComputeSameSiteContextForScriptGet(const GURL& url, 216 const SiteForCookies& site_for_cookies, 217 const std::optional<url::Origin>& initiator, 218 bool force_ignore_site_for_cookies); 219 220 // Determines which of the cookies for the request URL can be set from a network 221 // response, with respect to the SameSite attribute. This will only return 222 // CROSS_SITE or SAME_SITE_LAX (cookie sets of SameSite=strict cookies are 223 // permitted in same contexts that sets of SameSite=lax cookies are). 224 // `url_chain` is a non-empty vector of URLs, the last of which is the current 225 // request URL. It represents the redirect chain of the current request. The 226 // redirect chain is used to calculate whether there has been a cross-site 227 // redirect. 228 // `is_main_frame_navigation` is whether the request was for a navigation that 229 // targets the main frame or top-level browsing context. Both SameSite=Lax and 230 // SameSite=Strict cookies may be set by any main frame navigation. 231 // If `force_ignore_site_for_cookies` is true, this returns SAME_SITE_LAX. 232 NET_EXPORT CookieOptions::SameSiteCookieContext 233 ComputeSameSiteContextForResponse(const std::vector<GURL>& url_chain, 234 const SiteForCookies& site_for_cookies, 235 const std::optional<url::Origin>& initiator, 236 bool is_main_frame_navigation, 237 bool force_ignore_site_for_cookies); 238 239 // Determines which of the cookies for `url` can be set from a script context, 240 // with respect to the SameSite attribute. This will only return CROSS_SITE or 241 // SAME_SITE_LAX (cookie sets of SameSite=strict cookies are permitted in same 242 // contexts that sets of SameSite=lax cookies are). 243 // If `force_ignore_site_for_cookies` is true, this returns SAME_SITE_LAX. 244 NET_EXPORT CookieOptions::SameSiteCookieContext 245 ComputeSameSiteContextForScriptSet(const GURL& url, 246 const SiteForCookies& site_for_cookies, 247 bool force_ignore_site_for_cookies); 248 249 // Determines which of the cookies for |url| can be accessed when fetching a 250 // subresources. This is either CROSS_SITE or SAME_SITE_STRICT, 251 // since the initiator for a subresource is the frame loading it. 252 NET_EXPORT CookieOptions::SameSiteCookieContext 253 // If |force_ignore_site_for_cookies| is true, this returns SAME_SITE_STRICT. 254 ComputeSameSiteContextForSubresource(const GURL& url, 255 const SiteForCookies& site_for_cookies, 256 bool force_ignore_site_for_cookies); 257 258 NET_EXPORT bool IsPortBoundCookiesEnabled(); 259 260 NET_EXPORT bool IsSchemeBoundCookiesEnabled(); 261 262 // Returns true if either portion of OBC is enabled. 263 NET_EXPORT bool IsOriginBoundCookiesPartiallyEnabled(); 264 265 NET_EXPORT bool IsTimeLimitedInsecureCookiesEnabled(); 266 267 // Returns whether the respective feature is enabled. 268 NET_EXPORT bool IsSchemefulSameSiteEnabled(); 269 270 // Computes the First-Party Sets metadata and cache match information. 271 // `isolation_info` must be fully populated. 272 // 273 // The result may be returned synchronously, or `callback` may be invoked 274 // asynchronously with the result. The callback will be invoked iff the return 275 // value is nullopt; i.e. a result will be provided via return value or 276 // callback, but not both, and not neither. 277 [[nodiscard]] NET_EXPORT std::optional< 278 std::pair<FirstPartySetMetadata, FirstPartySetsCacheFilter::MatchInfo>> 279 ComputeFirstPartySetMetadataMaybeAsync( 280 const SchemefulSite& request_site, 281 const IsolationInfo& isolation_info, 282 const CookieAccessDelegate* cookie_access_delegate, 283 base::OnceCallback<void(FirstPartySetMetadata, 284 FirstPartySetsCacheFilter::MatchInfo)> callback); 285 286 // Converts a string representing the http request method to its enum 287 // representation. 288 NET_EXPORT CookieOptions::SameSiteCookieContext::ContextMetadata::HttpMethod 289 HttpMethodStringToEnum(const std::string& in); 290 291 // Takes a CookieAccessResult and returns a bool, returning true if the 292 // CookieInclusionStatus in CookieAccessResult was set to "include", else 293 // returning false. 294 // 295 // Can be used with SetCanonicalCookie when you don't need to know why a cookie 296 // was blocked, only whether it was blocked. 297 NET_EXPORT bool IsCookieAccessResultInclude( 298 CookieAccessResult cookie_access_result); 299 300 // Turn a CookieAccessResultList into a CookieList by stripping out access 301 // results (for callers who only care about cookies). 302 NET_EXPORT CookieList 303 StripAccessResults(const CookieAccessResultList& cookie_access_result_list); 304 305 // Records port related metrics from Omnibox navigations. 306 NET_EXPORT void RecordCookiePortOmniboxHistograms(const GURL& url); 307 308 // Checks invariants that should be upheld w.r.t. the included and excluded 309 // cookies. Namely: the included cookies should be elements of 310 // `included_cookies`; excluded cookies should be elements of 311 // `excluded_cookies`; and included cookies should be in the correct sorted 312 // order. 313 NET_EXPORT void DCheckIncludedAndExcludedCookieLists( 314 const CookieAccessResultList& included_cookies, 315 const CookieAccessResultList& excluded_cookies); 316 317 // Returns the default third-party cookie blocking setting, which is false 318 // unless you enable ForceThirdPartyCookieBlocking with the command line switch 319 // --test-third-party-cookie-phaseout. 320 NET_EXPORT bool IsForceThirdPartyCookieBlockingEnabled(); 321 322 } // namespace cookie_util 323 324 } // namespace net 325 326 #endif // NET_COOKIES_COOKIE_UTIL_H_ 327