| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_COOKIES_COOKIE_INCLUSION_STATUS_H_ |
| #define NET_COOKIES_COOKIE_INCLUSION_STATUS_H_ |
| |
| #include <string> |
| #include <vector> |
| |
| #include "net/base/net_export.h" |
| |
| class GURL; |
| |
| namespace net { |
| |
| // This class represents if a cookie was included or excluded in a cookie get or |
| // set operation, and if excluded why. It holds a vector of reasons for |
| // exclusion, where cookie inclusion is represented by the absence of any |
| // exclusion reasons. Also marks whether a cookie should be warned about, e.g. |
| // for deprecation or intervention reasons. |
| class NET_EXPORT CookieInclusionStatus { |
| public: |
| // Types of reasons why a cookie might be excluded. |
| // If adding a ExclusionReason, please also update the GetDebugString() |
| // method. |
| enum ExclusionReason { |
| EXCLUDE_UNKNOWN_ERROR = 0, |
| |
| EXCLUDE_HTTP_ONLY = 1, |
| EXCLUDE_SECURE_ONLY = 2, |
| EXCLUDE_DOMAIN_MISMATCH = 3, |
| EXCLUDE_NOT_ON_PATH = 4, |
| EXCLUDE_SAMESITE_STRICT = 5, |
| EXCLUDE_SAMESITE_LAX = 6, |
| |
| // The following two are used for the SameSiteByDefaultCookies experiment, |
| // where if the SameSite attribute is not specified, it will be treated as |
| // SameSite=Lax by default. |
| EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX = 7, |
| // This is used if SameSite=None is specified, but the cookie is not |
| // Secure. |
| EXCLUDE_SAMESITE_NONE_INSECURE = 8, |
| EXCLUDE_USER_PREFERENCES = 9, |
| |
| // Statuses specific to setting cookies |
| EXCLUDE_FAILURE_TO_STORE = 10, |
| EXCLUDE_NONCOOKIEABLE_SCHEME = 11, |
| EXCLUDE_OVERWRITE_SECURE = 12, |
| EXCLUDE_OVERWRITE_HTTP_ONLY = 13, |
| EXCLUDE_INVALID_DOMAIN = 14, |
| EXCLUDE_INVALID_PREFIX = 15, |
| |
| // This should be kept last. |
| NUM_EXCLUSION_REASONS |
| }; |
| |
| // Reason to warn about a cookie. Any information contained in WarningReason |
| // of an included cookie may be passed to an untrusted renderer. |
| // If you add one, please update GetDebugString(). |
| enum WarningReason { |
| // Of the following 3 SameSite warnings, there will be, at most, a single |
| // active one. |
| |
| // Warn if a cookie with unspecified SameSite attribute is used in a |
| // cross-site context. |
| WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT = 0, |
| // Warn if a cookie with SameSite=None is not Secure. |
| WARN_SAMESITE_NONE_INSECURE = 1, |
| // Warn if a cookie with unspecified SameSite attribute is defaulted into |
| // Lax and is sent on a request with unsafe method, only because it is new |
| // enough to activate the Lax-allow-unsafe intervention. |
| WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE = 2, |
| |
| // The following warnings indicate that an included cookie with an effective |
| // SameSite is experiencing a SameSiteCookieContext::|context| -> |
| // SameSiteCookieContext::|schemeful_context| downgrade that will prevent |
| // its access schemefully. |
| // This situation means that a cookie is accessible when the |
| // SchemefulSameSite feature is disabled but not when it's enabled, |
| // indicating changed behavior and potential breakage. |
| // |
| // For example, a Strict to Lax downgrade for an effective SameSite=Strict |
| // cookie: |
| // This cookie would be accessible in the Strict context as its SameSite |
| // value is Strict. However its context for schemeful same-site becomes Lax. |
| // A strict cookie cannot be accessed in a Lax context and therefore the |
| // behavior has changed. |
| // As a counterexample, a Strict to Lax downgrade for an effective |
| // SameSite=Lax cookie: A Lax cookie can be accessed in both Strict and Lax |
| // contexts so there is no behavior change (and we don't warn about it). |
| // |
| // The warnings are in the following format: |
| // WARN_{context}_{schemeful_context}_DOWNGRADE_{samesite_value}_SAMESITE |
| // |
| // Of the following 5 SameSite warnings, there will be, at most, a single |
| // active one. |
| |
| // Strict to Lax downgrade for an effective SameSite=Strict cookie. |
| // This warning is only applicable for cookies being sent because a Strict |
| // cookie will be set in both Strict and Lax Contexts so the downgrade will |
| // not affect it. |
| WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE = 3, |
| // Strict to Cross-site downgrade for an effective SameSite=Strict cookie. |
| // This also applies to Strict to Lax Unsafe downgrades due to Lax Unsafe |
| // behaving like Cross-site. |
| WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE = 4, |
| // Strict to Cross-site downgrade for an effective SameSite=Lax cookie. |
| // This also applies to Strict to Lax Unsafe downgrades due to Lax Unsafe |
| // behaving like Cross-site. |
| WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE = 5, |
| // Lax to Cross-site downgrade for an effective SameSite=Strict cookie. |
| // This warning is only applicable for cookies being set because a Strict |
| // cookie will not be sent in a Lax context so the downgrade would not |
| // affect it. |
| WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE = 6, |
| // Lax to Cross-site downgrade for an effective SameSite=Lax cookie. |
| WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE = 7, |
| |
| // This is applied to a cookie that may be part of a "double cookie" pair |
| // used for compatibility reasons. These pairs consist of one cookie that |
| // has "SameSite=None; Secure" and a duplicate cookie that leaves SameSite |
| // unspecified to maintain compatibility with browsers that do not support |
| // the "SameSite=None" attribute. This warning is applied to both |
| // members of the pair. See cookie_util::IsSameSiteCompatPair(). |
| // |
| // If computing this for a cookie access attempt from a non-network context |
| // (i.e. script), this should not be applied if either member of the pair is |
| // HttpOnly, to avoid leaking information about the name and value of |
| // HttpOnly cookies to an untrusted renderer. |
| // |
| // This is only relevant if WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT is |
| // present on the same status or a status for a cookie accessed at the same |
| // time, so it may not be applied at other times (e.g. when the context is |
| // same-site). |
| WARN_SAMESITE_COMPAT_PAIR = 8, |
| |
| // This should be kept last. |
| NUM_WARNING_REASONS |
| }; |
| |
| // These enums encode the context downgrade warnings + the secureness of the |
| // url sending/setting the cookie. They're used for metrics only. The format |
| // is {context}_{schemeful_context}_{samesite_value}_{securness}. |
| // NO_DOWNGRADE_{securness} indicates that a cookie didn't have a breaking |
| // context downgrade and was A) included B) excluded only due to insufficient |
| // same-site context. I.e. the cookie wasn't excluded due to other reasons |
| // such as third-party cookie blocking. Keep this in line with |
| // SameSiteCookieContextBreakingDowngradeWithSecureness in enums.xml. |
| enum ContextDowngradeMetricValues { |
| NO_DOWNGRADE_INSECURE = 0, |
| NO_DOWNGRADE_SECURE = 1, |
| |
| STRICT_LAX_STRICT_INSECURE = 2, |
| STRICT_CROSS_STRICT_INSECURE = 3, |
| STRICT_CROSS_LAX_INSECURE = 4, |
| LAX_CROSS_STRICT_INSECURE = 5, |
| LAX_CROSS_LAX_INSECURE = 6, |
| |
| STRICT_LAX_STRICT_SECURE = 7, |
| STRICT_CROSS_STRICT_SECURE = 8, |
| STRICT_CROSS_LAX_SECURE = 9, |
| LAX_CROSS_STRICT_SECURE = 10, |
| LAX_CROSS_LAX_SECURE = 11, |
| |
| // Keep last. |
| kMaxValue = LAX_CROSS_LAX_SECURE |
| }; |
| // Makes a status that says include and should not warn. |
| CookieInclusionStatus(); |
| |
| // Make a status that contains the given exclusion reason. |
| explicit CookieInclusionStatus(ExclusionReason reason); |
| // Makes a status that contains the given exclusion reason and warning. |
| CookieInclusionStatus(ExclusionReason reason, WarningReason warning); |
| |
| bool operator==(const CookieInclusionStatus& other) const; |
| bool operator!=(const CookieInclusionStatus& other) const; |
| |
| // Whether the status is to include the cookie, and has no other reasons for |
| // exclusion. |
| bool IsInclude() const; |
| |
| // Whether the given reason for exclusion is present. |
| bool HasExclusionReason(ExclusionReason status_type) const; |
| |
| // Whether the given reason for exclusion is present, and is the ONLY reason |
| // for exclusion. |
| bool HasOnlyExclusionReason(ExclusionReason status_type) const; |
| |
| // Add an exclusion reason. |
| void AddExclusionReason(ExclusionReason status_type); |
| |
| // Remove an exclusion reason. |
| void RemoveExclusionReason(ExclusionReason reason); |
| |
| // If the cookie would have been excluded for reasons other than |
| // SAMESITE_UNSPECIFIED_TREATED_AS_LAX or SAMESITE_NONE_INSECURE, don't bother |
| // warning about it (clear the warning). |
| void MaybeClearSameSiteWarning(); |
| |
| // Whether to record the breaking downgrade metrics if the cookie is included |
| // or if it's only excluded because of insufficient same-site context. |
| bool ShouldRecordDowngradeMetrics() const; |
| |
| // Whether the cookie should be warned about. |
| bool ShouldWarn() const; |
| |
| // Whether the given reason for warning is present. |
| bool HasWarningReason(WarningReason reason) const; |
| |
| // Whether a schemeful downgrade warning is present. |
| // A schemeful downgrade means that an included cookie with an effective |
| // SameSite is experiencing a SameSiteCookieContext::|context| -> |
| // SameSiteCookieContext::|schemeful_context| downgrade that will prevent its |
| // access schemefully. If the function returns true and |reason| is valid then |
| // |reason| will contain which warning was found. |
| bool HasDowngradeWarning( |
| CookieInclusionStatus::WarningReason* reason = nullptr) const; |
| |
| // Add an warning reason. |
| void AddWarningReason(WarningReason reason); |
| |
| // Remove an warning reason. |
| void RemoveWarningReason(WarningReason reason); |
| |
| // Used for serialization/deserialization. |
| uint32_t exclusion_reasons() const { return exclusion_reasons_; } |
| void set_exclusion_reasons(uint32_t exclusion_reasons) { |
| exclusion_reasons_ = exclusion_reasons; |
| } |
| |
| uint32_t warning_reasons() const { return warning_reasons_; } |
| void set_warning_reasons(uint32_t warning_reasons) { |
| warning_reasons_ = warning_reasons; |
| } |
| |
| ContextDowngradeMetricValues GetBreakingDowngradeMetricsEnumValue( |
| const GURL& url) const; |
| |
| // Get exclusion reason(s) and warning in string format. |
| std::string GetDebugString() const; |
| |
| // Checks that the underlying bit vector representation doesn't contain any |
| // extraneous bits that are not mapped to any enum values. Does not check |
| // for reasons which semantically cannot coexist. |
| bool IsValid() const; |
| |
| // Checks whether the exclusion reasons are exactly the set of exclusion |
| // reasons in the vector. (Ignores warnings.) |
| bool HasExactlyExclusionReasonsForTesting( |
| std::vector<ExclusionReason> reasons) const; |
| |
| // Checks whether the warning reasons are exactly the set of warning |
| // reasons in the vector. (Ignores exclusions.) |
| bool HasExactlyWarningReasonsForTesting( |
| std::vector<WarningReason> reasons) const; |
| |
| // Makes a status that contains the given exclusion reasons and warning. |
| static CookieInclusionStatus MakeFromReasonsForTesting( |
| std::vector<ExclusionReason> reasons, |
| std::vector<WarningReason> warnings = std::vector<WarningReason>()); |
| |
| private: |
| // A bit vector of the applicable exclusion reasons. |
| uint32_t exclusion_reasons_ = 0u; |
| |
| // A bit vector of the applicable warning reasons. |
| uint32_t warning_reasons_ = 0u; |
| }; |
| |
| NET_EXPORT inline std::ostream& operator<<(std::ostream& os, |
| const CookieInclusionStatus status) { |
| return os << status.GetDebugString(); |
| } |
| |
| } // namespace net |
| |
| #endif // NET_COOKIES_COOKIE_INCLUSION_STATUS_H_ |