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