canonical_cookie.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef NET_COOKIES_CANONICAL_COOKIE_H_
  5. #define NET_COOKIES_CANONICAL_COOKIE_H_
  6. #include <memory>
  7. #include <string>
  8. #include <tuple>
  9. #include <vector>
  10. #include "base/gtest_prod_util.h"
  11. #include "base/strings/string_piece.h"
  12. #include "base/time/time.h"
  13. #include "net/base/net_export.h"
  14. #include "net/cookies/cookie_access_result.h"
  15. #include "net/cookies/cookie_constants.h"
  16. #include "net/cookies/cookie_inclusion_status.h"
  17. #include "net/cookies/cookie_options.h"
  18. #include "net/cookies/cookie_partition_key.h"
  19. #include "third_party/abseil-cpp/absl/types/optional.h"
  20. #include "url/third_party/mozilla/url_parse.h"
  21. class GURL;
  22. namespace net {
  23. class ParsedCookie;
  24. class CanonicalCookie;
  25. struct CookieWithAccessResult;
  26. struct CookieAndLineWithAccessResult;
  27. using CookieList = std::vector<CanonicalCookie>;
  28. using CookieAndLineAccessResultList =
  29. std::vector<CookieAndLineWithAccessResult>;
  30. using CookieAccessResultList = std::vector<CookieWithAccessResult>;
  31. struct NET_EXPORT CookieAccessParams {
  32. CookieAccessParams() = delete;
  33. CookieAccessParams(CookieAccessSemantics access_semantics,
  34. bool delegate_treats_url_as_trustworthy,
  35. CookieSamePartyStatus same_party_status);
  36. // |access_semantics| is the access mode of the cookie access check.
  37. CookieAccessSemantics access_semantics = CookieAccessSemantics::UNKNOWN;
  38. // |delegate_treats_url_as_trustworthy| should be true iff the
  39. // CookieAccessDelegate has authorized access to secure cookies from URLs
  40. // which might not otherwise be able to do so.
  41. bool delegate_treats_url_as_trustworthy = false;
  42. // |same_party_status| indicates whether, and how, SameParty restrictions
  43. // should be enforced.
  44. CookieSamePartyStatus same_party_status =
  45. CookieSamePartyStatus::kNoSamePartyEnforcement;
  46. };
  47. class NET_EXPORT CanonicalCookie {
  48. public:
  49. using UniqueCookieKey = std::tuple<absl::optional<CookiePartitionKey>,
  50. std::string,
  51. std::string,
  52. std::string>;
  53. CanonicalCookie();
  54. CanonicalCookie(const CanonicalCookie& other);
  55. CanonicalCookie(CanonicalCookie&& other);
  56. CanonicalCookie& operator=(const CanonicalCookie& other);
  57. CanonicalCookie& operator=(CanonicalCookie&& other);
  58. ~CanonicalCookie();
  59. // Creates a new |CanonicalCookie| from the |cookie_line| and the
  60. // |creation_time|. Canonicalizes inputs. May return nullptr if
  61. // an attribute value is invalid. |url| must be valid. |creation_time| may
  62. // not be null. Sets optional |status| to the relevant CookieInclusionStatus
  63. // if provided. |server_time| indicates what the server sending us the Cookie
  64. // thought the current time was when the cookie was produced. This is used to
  65. // adjust for clock skew between server and host.
  66. //
  67. // SameSite and HttpOnly related parameters are not checked here,
  68. // so creation of CanonicalCookies with e.g. SameSite=Strict from a cross-site
  69. // context is allowed. Create() also does not check whether |url| has a secure
  70. // scheme if attempting to create a Secure cookie. The Secure, SameSite, and
  71. // HttpOnly related parameters should be checked when setting the cookie in
  72. // the CookieStore.
  73. //
  74. // The partition_key argument only needs to be present if the cookie line
  75. // contains the Partitioned attribute. If the cookie line will never contain
  76. // that attribute, you should use absl::nullopt to indicate you intend to
  77. // always create an unpartitioned cookie. If partition_key has a value but the
  78. // cookie line does not contain the Partitioned attribute, the resulting
  79. // cookie will be unpartitioned. If the partition_key is null, then the cookie
  80. // will be unpartitioned even when the cookie line has the Partitioned
  81. // attribute.
  82. //
  83. // If a cookie is returned, |cookie->IsCanonical()| will be true.
  84. static std::unique_ptr<CanonicalCookie> Create(
  85. const GURL& url,
  86. const std::string& cookie_line,
  87. const base::Time& creation_time,
  88. absl::optional<base::Time> server_time,
  89. absl::optional<CookiePartitionKey> cookie_partition_key,
  90. CookieInclusionStatus* status = nullptr);
  91. // Create a canonical cookie based on sanitizing the passed inputs in the
  92. // context of the passed URL. Returns a null unique pointer if the inputs
  93. // cannot be sanitized. If `status` is provided it will have any relevant
  94. // CookieInclusionStatus rejection reasons set. If a cookie is created,
  95. // `cookie->IsCanonical()` will be true.
  96. static std::unique_ptr<CanonicalCookie> CreateSanitizedCookie(
  97. const GURL& url,
  98. const std::string& name,
  99. const std::string& value,
  100. const std::string& domain,
  101. const std::string& path,
  102. base::Time creation_time,
  103. base::Time expiration_time,
  104. base::Time last_access_time,
  105. bool secure,
  106. bool http_only,
  107. CookieSameSite same_site,
  108. CookiePriority priority,
  109. bool same_party,
  110. absl::optional<CookiePartitionKey> partition_key,
  111. CookieInclusionStatus* status = nullptr);
  112. // FromStorage is a factory method which is meant for creating a new
  113. // CanonicalCookie using properties of a previously existing cookie
  114. // that was already ingested into the cookie store.
  115. // This should NOT be used to create a new CanonicalCookie that was not
  116. // already in the store.
  117. // Returns nullptr if the resulting cookie is not canonical,
  118. // i.e. cc->IsCanonical() returns false.
  119. static std::unique_ptr<CanonicalCookie> FromStorage(
  120. std::string name,
  121. std::string value,
  122. std::string domain,
  123. std::string path,
  124. base::Time creation,
  125. base::Time expiration,
  126. base::Time last_access,
  127. base::Time last_update,
  128. bool secure,
  129. bool httponly,
  130. CookieSameSite same_site,
  131. CookiePriority priority,
  132. bool same_party,
  133. absl::optional<CookiePartitionKey> partition_key,
  134. CookieSourceScheme source_scheme,
  135. int source_port);
  136. // Create a CanonicalCookie that is not guaranteed to actually be Canonical
  137. // for tests. This factory should NOT be used in production.
  138. static std::unique_ptr<CanonicalCookie> CreateUnsafeCookieForTesting(
  139. const std::string& name,
  140. const std::string& value,
  141. const std::string& domain,
  142. const std::string& path,
  143. const base::Time& creation,
  144. const base::Time& expiration,
  145. const base::Time& last_access,
  146. const base::Time& last_update,
  147. bool secure,
  148. bool httponly,
  149. CookieSameSite same_site,
  150. CookiePriority priority,
  151. bool same_party,
  152. absl::optional<CookiePartitionKey> partition_key = absl::nullopt,
  153. CookieSourceScheme scheme_secure = CookieSourceScheme::kUnset,
  154. int source_port = url::PORT_UNSPECIFIED);
  155. bool operator<(const CanonicalCookie& other) const {
  156. // Use the cookie properties that uniquely identify a cookie to determine
  157. // ordering.
  158. return UniqueKey() < other.UniqueKey();
  159. }
  160. const std::string& Name() const { return name_; }
  161. const std::string& Value() const { return value_; }
  162. // We represent the cookie's host-only-flag as the absence of a leading dot in
  163. // Domain(). See IsDomainCookie() and IsHostCookie() below.
  164. // If you want the "cookie's domain" as described in RFC 6265bis, use
  165. // DomainWithoutDot().
  166. const std::string& Domain() const { return domain_; }
  167. const std::string& Path() const { return path_; }
  168. const base::Time& CreationDate() const { return creation_date_; }
  169. const base::Time& ExpiryDate() const { return expiry_date_; }
  170. const base::Time& LastAccessDate() const { return last_access_date_; }
  171. const base::Time& LastUpdateDate() const { return last_update_date_; }
  172. bool IsPersistent() const { return !expiry_date_.is_null(); }
  173. bool IsSecure() const { return secure_; }
  174. bool IsHttpOnly() const { return httponly_; }
  175. CookieSameSite SameSite() const { return same_site_; }
  176. CookiePriority Priority() const { return priority_; }
  177. bool IsSameParty() const { return same_party_; }
  178. bool IsPartitioned() const { return partition_key_.has_value(); }
  179. const absl::optional<CookiePartitionKey>& PartitionKey() const {
  180. return partition_key_;
  181. }
  182. // Returns an enum indicating the scheme of the origin that
  183. // set this cookie. This is not part of the cookie spec but is being used to
  184. // collect metrics for a potential change to the cookie spec
  185. // (https://tools.ietf.org/html/draft-west-cookie-incrementalism-01#section-3.4)
  186. CookieSourceScheme SourceScheme() const { return source_scheme_; }
  187. // Returns the port of the origin that originally set this cookie (the
  188. // source port). This is not part of the cookie spec but is being used to
  189. // collect metrics for a potential change to the cookie spec.
  190. int SourcePort() const { return source_port_; }
  191. bool IsDomainCookie() const {
  192. return !domain_.empty() && domain_[0] == '.'; }
  193. bool IsHostCookie() const { return !IsDomainCookie(); }
  194. // Returns the cookie's domain, with the leading dot removed, if present.
  195. // This corresponds to the "cookie's domain" as described in RFC 6265bis.
  196. std::string DomainWithoutDot() const;
  197. bool IsExpired(const base::Time& current) const {
  198. return !expiry_date_.is_null() && current >= expiry_date_;
  199. }
  200. // Are the cookies considered equivalent in the eyes of RFC 2965.
  201. // The RFC says that name must match (case-sensitive), domain must
  202. // match (case insensitive), and path must match (case sensitive).
  203. // For the case insensitive domain compare, we rely on the domain
  204. // having been canonicalized (in
  205. // GetCookieDomainWithString->CanonicalizeHost).
  206. // If partitioned cookies are enabled, then we check the cookies have the same
  207. // partition key in addition to the checks in RFC 2965.
  208. bool IsEquivalent(const CanonicalCookie& ecc) const {
  209. // It seems like it would make sense to take secure, httponly, and samesite
  210. // into account, but the RFC doesn't specify this.
  211. // NOTE: Keep this logic in-sync with TrimDuplicateCookiesForKey().
  212. return UniqueKey() == ecc.UniqueKey();
  213. }
  214. // Returns a key such that two cookies with the same UniqueKey() are
  215. // guaranteed to be equivalent in the sense of IsEquivalent().
  216. // The `partition_key_` field will always be nullopt when partitioned cookies
  217. // are not enabled.
  218. UniqueCookieKey UniqueKey() const {
  219. return std::make_tuple(partition_key_, name_, domain_, path_);
  220. }
  221. // Checks a looser set of equivalency rules than 'IsEquivalent()' in order
  222. // to support the stricter 'Secure' behaviors specified in Step 12 of
  223. // https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-05#section-5.4
  224. // which originated from the proposal in
  225. // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone#section-3
  226. //
  227. // Returns 'true' if this cookie's name matches |secure_cookie|, and this
  228. // cookie is a domain-match for |secure_cookie| (or vice versa), and
  229. // |secure_cookie|'s path is "on" this cookie's path (as per 'IsOnPath()').
  230. // If partitioned cookies are enabled, it also checks that the cookie has
  231. // the same partition key as |secure_cookie|.
  232. //
  233. // Note that while the domain-match cuts both ways (e.g. 'example.com'
  234. // matches 'www.example.com' in either direction), the path-match is
  235. // unidirectional (e.g. '/login/en' matches '/login' and '/', but
  236. // '/login' and '/' do not match '/login/en').
  237. //
  238. // Conceptually:
  239. // If new_cookie.IsEquivalentForSecureCookieMatching(secure_cookie) is true,
  240. // this means that new_cookie would "shadow" secure_cookie: they would would
  241. // be indistinguishable when serialized into a Cookie header. This is
  242. // important because, if an attacker is attempting to set new_cookie, it
  243. // should not be allowed to mislead the server into using new_cookie's value
  244. // instead of secure_cookie's.
  245. //
  246. // The reason for the asymmetric path comparison ("cookie1=bad; path=/a/b"
  247. // from an insecure source is not allowed if "cookie1=good; secure; path=/a"
  248. // exists, but "cookie2=bad; path=/a" from an insecure source is allowed if
  249. // "cookie2=good; secure; path=/a/b" exists) is because cookies in the Cookie
  250. // header are serialized with longer path first. (See CookieSorter in
  251. // cookie_monster.cc.) That is, they would be serialized as "Cookie:
  252. // cookie1=bad; cookie1=good" in one case, and "Cookie: cookie2=good;
  253. // cookie2=bad" in the other case. The first scenario is not allowed because
  254. // the attacker injects the bad value, whereas the second scenario is ok
  255. // because the good value is still listed first.
  256. bool IsEquivalentForSecureCookieMatching(
  257. const CanonicalCookie& secure_cookie) const;
  258. // Returns true if the |other| cookie's data members (instance variables)
  259. // match, for comparing cookies in colletions.
  260. bool HasEquivalentDataMembers(const CanonicalCookie& other) const {
  261. return creation_date_ == other.creation_date_ &&
  262. last_access_date_ == other.last_access_date_ &&
  263. expiry_date_ == other.expiry_date_ && secure_ == other.secure_ &&
  264. httponly_ == other.httponly_ && same_site_ == other.same_site_ &&
  265. priority_ == other.priority_ && same_party_ == other.same_party_ &&
  266. partition_key_ == other.partition_key_ && name_ == other.name_ &&
  267. value_ == other.value_ && domain_ == other.domain_ &&
  268. path_ == other.path_ && last_update_date_ == other.last_update_date_;
  269. }
  270. void SetSourceScheme(CookieSourceScheme source_scheme) {
  271. source_scheme_ = source_scheme;
  272. }
  273. // Set the source port value. Performs a range check and sets the port to
  274. // url::PORT_INVALID if value isn't in [0,65535] or url::PORT_UNSPECIFIED.
  275. void SetSourcePort(int port);
  276. void SetLastAccessDate(const base::Time& date) {
  277. last_access_date_ = date;
  278. }
  279. void SetCreationDate(const base::Time& date) { creation_date_ = date; }
  280. // Returns true if the given |url_path| path-matches this cookie's cookie-path
  281. // as described in section 5.1.4 in RFC 6265. This returns true if |path_| and
  282. // |url_path| are identical, or if |url_path| is a subdirectory of |path_|.
  283. bool IsOnPath(const std::string& url_path) const;
  284. // This returns true if this cookie's |domain_| indicates that it can be
  285. // accessed by |host|.
  286. //
  287. // In the case where |domain_| has no leading dot, this is a host cookie and
  288. // will only domain match if |host| is identical to |domain_|.
  289. //
  290. // In the case where |domain_| has a leading dot, this is a domain cookie. It
  291. // will match |host| if |domain_| is a suffix of |host|, or if |domain_| is
  292. // exactly equal to |host| plus a leading dot.
  293. //
  294. // Note that this isn't quite the same as the "domain-match" algorithm in RFC
  295. // 6265bis, since our implementation uses the presence of a leading dot in the
  296. // |domain_| string in place of the spec's host-only-flag. That is, if
  297. // |domain_| has no leading dot, then we only consider it matching if |host|
  298. // is identical (which reflects the intended behavior when the cookie has a
  299. // host-only-flag), whereas the RFC also treats them as domain-matching if
  300. // |domain_| is a subdomain of |host|.
  301. bool IsDomainMatch(const std::string& host) const;
  302. // Returns if the cookie should be included (and if not, why) for the given
  303. // request |url| using the CookieInclusionStatus enum. HTTP only cookies can
  304. // be filter by using appropriate cookie |options|.
  305. //
  306. // PLEASE NOTE that this method does not check whether a cookie is expired or
  307. // not!
  308. CookieAccessResult IncludeForRequestURL(
  309. const GURL& url,
  310. const CookieOptions& options,
  311. const CookieAccessParams& params) const;
  312. // Returns if the cookie with given attributes can be set in context described
  313. // by |options| and |params|, and if no, describes why.
  314. //
  315. // |cookie_access_result| is an optional input status, to allow for status
  316. // chaining from callers. It helps callers provide the status of a
  317. // canonical cookie that may have warnings associated with it.
  318. CookieAccessResult IsSetPermittedInContext(
  319. const GURL& source_url,
  320. const CookieOptions& options,
  321. const CookieAccessParams& params,
  322. const std::vector<std::string>& cookieable_schemes,
  323. const absl::optional<CookieAccessResult>& cookie_access_result =
  324. absl::nullopt) const;
  325. std::string DebugString() const;
  326. // Returns the canonical path based on the specified url and path attribute
  327. // value. Note that this method does not enforce character set or size
  328. // checks on `path_string`.
  329. static std::string CanonPathWithString(const GURL& url,
  330. const std::string& path_string);
  331. // Returns a "null" time if expiration was unspecified or invalid.
  332. static base::Time ParseExpiration(const ParsedCookie& pc,
  333. const base::Time& current,
  334. const base::Time& server_time);
  335. // Per rfc6265bis the maximum expiry date is no further than 400 days in the
  336. // future. Clamping only occurs when kClampCookieExpiryTo400Days is enabled.
  337. static base::Time ValidateAndAdjustExpiryDate(
  338. const base::Time& expiry_date,
  339. const base::Time& creation_date);
  340. // Cookie ordering methods.
  341. // Returns true if the cookie is less than |other|, considering only name,
  342. // domain and path. In particular, two equivalent cookies (see IsEquivalent())
  343. // are identical for PartialCompare().
  344. bool PartialCompare(const CanonicalCookie& other) const;
  345. // Return whether this object is a valid CanonicalCookie(). Invalid
  346. // cookies may be constructed by the detailed constructor.
  347. // A cookie is considered canonical if-and-only-if:
  348. // * It can be created by CanonicalCookie::Create, or
  349. // * It is identical to a cookie created by CanonicalCookie::Create except
  350. // that the creation time is null, or
  351. // * It can be derived from a cookie created by CanonicalCookie::Create by
  352. // entry into and retrieval from a cookie store (specifically, this means
  353. // by the setting of an creation time in place of a null creation time, and
  354. // the setting of a last access time).
  355. // An additional requirement on a CanonicalCookie is that if the last
  356. // access time is non-null, the creation time must also be non-null and
  357. // greater than the last access time.
  358. bool IsCanonical() const;
  359. // Return whether this object is a valid CanonicalCookie() when retrieving the
  360. // cookie from the persistent store. Cookie that exist in the persistent store
  361. // may have been created before more recent changes to the definition of
  362. // "canonical". To ease the transition to the new definitions, and to prevent
  363. // users from having their cookies deleted, this function supports the older
  364. // definition of canonical. This function is intended to be temporary because
  365. // as the number of older cookies (which are non-compliant with the newer
  366. // definition of canonical) decay toward zero it can eventually be replaced
  367. // by `IsCanonical()` to enforce the newer definition of canonical.
  368. //
  369. // A cookie is considered canonical by this function if-and-only-if:
  370. // * It is considered canonical by IsCanonical()
  371. // * TODO(crbug.com/1244172): Add exceptions once IsCanonical() starts
  372. // enforcing them.
  373. bool IsCanonicalForFromStorage() const;
  374. // Returns whether the effective SameSite mode is SameSite=None (i.e. no
  375. // SameSite restrictions).
  376. bool IsEffectivelySameSiteNone(CookieAccessSemantics access_semantics =
  377. CookieAccessSemantics::UNKNOWN) const;
  378. CookieEffectiveSameSite GetEffectiveSameSiteForTesting(
  379. CookieAccessSemantics access_semantics =
  380. CookieAccessSemantics::UNKNOWN) const;
  381. // Returns the cookie line (e.g. "cookie1=value1; cookie2=value2") represented
  382. // by |cookies|. The string is built in the same order as the given list.
  383. static std::string BuildCookieLine(const CookieList& cookies);
  384. // Same as above but takes a CookieAccessResultList
  385. // (ignores the access result).
  386. static std::string BuildCookieLine(const CookieAccessResultList& cookies);
  387. // Takes a single CanonicalCookie and returns a cookie line containing the
  388. // attributes of |cookie| formatted like a http set cookie header.
  389. // (e.g. "cookie1=value1; domain=abc.com; path=/; secure").
  390. static std::string BuildCookieAttributesLine(const CanonicalCookie& cookie);
  391. private:
  392. FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestPrefixHistograms);
  393. FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestHasHiddenPrefixName);
  394. // This constructor does not validate or canonicalize their inputs;
  395. // the resulting CanonicalCookies should not be relied on to be canonical
  396. // unless the caller has done appropriate validation and canonicalization
  397. // themselves.
  398. // NOTE: Prefer using CreateSanitizedCookie() over directly using this
  399. // constructor.
  400. CanonicalCookie(std::string name,
  401. std::string value,
  402. std::string domain,
  403. std::string path,
  404. base::Time creation,
  405. base::Time expiration,
  406. base::Time last_access,
  407. base::Time last_update,
  408. bool secure,
  409. bool httponly,
  410. CookieSameSite same_site,
  411. CookiePriority priority,
  412. bool same_party,
  413. absl::optional<CookiePartitionKey> partition_key,
  414. CookieSourceScheme scheme_secure = CookieSourceScheme::kUnset,
  415. int source_port = url::PORT_UNSPECIFIED);
  416. // The special cookie prefixes as defined in
  417. // https://tools.ietf.org/html/draft-west-cookie-prefixes
  418. //
  419. // This enum is being histogrammed; do not reorder or remove values.
  420. enum CookiePrefix {
  421. COOKIE_PREFIX_NONE = 0,
  422. COOKIE_PREFIX_SECURE,
  423. COOKIE_PREFIX_HOST,
  424. COOKIE_PREFIX_LAST
  425. };
  426. // Returns the CookiePrefix (or COOKIE_PREFIX_NONE if none) that
  427. // applies to the given cookie |name|.
  428. static CookiePrefix GetCookiePrefix(const std::string& name);
  429. // Records histograms to measure how often cookie prefixes appear in
  430. // the wild and how often they would be blocked.
  431. static void RecordCookiePrefixMetrics(CookiePrefix prefix,
  432. bool is_cookie_valid);
  433. // Returns true if a prefixed cookie does not violate any of the rules
  434. // for that cookie.
  435. static bool IsCookiePrefixValid(CookiePrefix prefix,
  436. const GURL& url,
  437. const ParsedCookie& parsed_cookie);
  438. static bool IsCookiePrefixValid(CookiePrefix prefix,
  439. const GURL& url,
  440. bool secure,
  441. const std::string& domain,
  442. const std::string& path);
  443. // Returns the effective SameSite mode to apply to this cookie. Depends on the
  444. // value of the given SameSite attribute and the access semantics of the
  445. // cookie.
  446. // Note: If you are converting to a different representation of a cookie, you
  447. // probably want to use SameSite() instead of this method. Otherwise, if you
  448. // are considering using this method, consider whether you should use
  449. // IncludeForRequestURL() or IsSetPermittedInContext() instead of doing the
  450. // SameSite computation yourself.
  451. CookieEffectiveSameSite GetEffectiveSameSite(
  452. CookieAccessSemantics access_semantics) const;
  453. // Checks for values that could be misinterpreted as a cookie name prefix.
  454. static bool HasHiddenPrefixName(const base::StringPiece cookie_value);
  455. // Returns whether the cookie was created at most |age_threshold| ago.
  456. bool IsRecentlyCreated(base::TimeDelta age_threshold) const;
  457. // Returns true iff the cookie does not violate any rules associated with
  458. // creating a cookie with the SameParty attribute. In particular, if a cookie
  459. // has SameParty, then it must be Secure and must not be SameSite=Strict.
  460. static bool IsCookieSamePartyValid(const ParsedCookie& parsed_cookie);
  461. static bool IsCookieSamePartyValid(bool is_same_party,
  462. bool is_secure,
  463. CookieSameSite same_site);
  464. // Returns true iff the cookie is a partitioned cookie with a nonce or that
  465. // does not violate the semantics of the Partitioned attribute:
  466. // - Must have the Secure attribute OR the cookie partition contains a nonce.
  467. static bool IsCookiePartitionedValid(const GURL& url,
  468. const ParsedCookie& parsed_cookie,
  469. bool partition_has_nonce);
  470. static bool IsCookiePartitionedValid(const GURL& url,
  471. bool secure,
  472. bool is_partitioned,
  473. bool partition_has_nonce);
  474. // Keep defaults here in sync with
  475. // services/network/public/interfaces/cookie_manager.mojom.
  476. std::string name_;
  477. std::string value_;
  478. std::string domain_;
  479. std::string path_;
  480. base::Time creation_date_;
  481. base::Time expiry_date_;
  482. base::Time last_access_date_;
  483. base::Time last_update_date_;
  484. bool secure_{false};
  485. bool httponly_{false};
  486. CookieSameSite same_site_{CookieSameSite::NO_RESTRICTION};
  487. CookiePriority priority_{COOKIE_PRIORITY_MEDIUM};
  488. bool same_party_{false};
  489. // This will be absl::nullopt for all cookies not set with the Partitioned
  490. // attribute or without a nonce. If the value is non-null, then the cookie
  491. // will only be delivered when the top-frame site matches the partition key
  492. // and the nonce (if present). If the partition key is non-null and opaque,
  493. // this means the Partitioned cookie was created on an opaque origin or with
  494. // a nonce.
  495. absl::optional<CookiePartitionKey> partition_key_;
  496. CookieSourceScheme source_scheme_{CookieSourceScheme::kUnset};
  497. // This can be [0,65535], PORT_UNSPECIFIED, or PORT_INVALID.
  498. // PORT_UNSPECIFIED is used for cookies which already existed in the cookie
  499. // store prior to this change and therefore their port is unknown.
  500. // PORT_INVALID is an error for when an out of range port is provided.
  501. int source_port_{url::PORT_UNSPECIFIED};
  502. };
  503. // Used to pass excluded cookie information when it's possible that the
  504. // canonical cookie object may not be available.
  505. struct NET_EXPORT CookieAndLineWithAccessResult {
  506. CookieAndLineWithAccessResult();
  507. CookieAndLineWithAccessResult(absl::optional<CanonicalCookie> cookie,
  508. std::string cookie_string,
  509. CookieAccessResult access_result);
  510. CookieAndLineWithAccessResult(
  511. const CookieAndLineWithAccessResult& cookie_and_line_with_access_result);
  512. CookieAndLineWithAccessResult& operator=(
  513. const CookieAndLineWithAccessResult& cookie_and_line_with_access_result);
  514. CookieAndLineWithAccessResult(
  515. CookieAndLineWithAccessResult&& cookie_and_line_with_access_result);
  516. ~CookieAndLineWithAccessResult();
  517. absl::optional<CanonicalCookie> cookie;
  518. std::string cookie_string;
  519. CookieAccessResult access_result;
  520. };
  521. struct CookieWithAccessResult {
  522. CanonicalCookie cookie;
  523. CookieAccessResult access_result;
  524. };
  525. // Provided to allow gtest to create more helpful error messages, instead of
  526. // printing hex.
  527. inline void PrintTo(const CanonicalCookie& cc, std::ostream* os) {
  528. *os << "{ name=" << cc.Name() << ", value=" << cc.Value() << " }";
  529. }
  530. inline void PrintTo(const CookieWithAccessResult& cwar, std::ostream* os) {
  531. *os << "{ ";
  532. PrintTo(cwar.cookie, os);
  533. *os << ", ";
  534. PrintTo(cwar.access_result, os);
  535. *os << " }";
  536. }
  537. inline void PrintTo(const CookieAndLineWithAccessResult& calwar,
  538. std::ostream* os) {
  539. *os << "{ ";
  540. if (calwar.cookie) {
  541. PrintTo(*calwar.cookie, os);
  542. } else {
  543. *os << "nullopt";
  544. }
  545. *os << ", " << calwar.cookie_string << ", ";
  546. PrintTo(calwar.access_result, os);
  547. *os << " }";
  548. }
  549. } // namespace net
  550. #endif // NET_COOKIES_CANONICAL_COOKIE_H_