Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 1 | // Copyright 2020 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 | |
| 5 | #include "net/cookies/cookie_inclusion_status.h" |
| 6 | |
| 7 | #include "base/strings/strcat.h" |
| 8 | #include "url/gurl.h" |
| 9 | |
| 10 | namespace net { |
| 11 | |
| 12 | namespace { |
| 13 | |
| 14 | uint32_t GetExclusionBitmask(CookieInclusionStatus::ExclusionReason reason) { |
| 15 | return 1u << static_cast<uint32_t>(reason); |
| 16 | } |
| 17 | |
| 18 | uint32_t GetWarningBitmask(CookieInclusionStatus::WarningReason reason) { |
| 19 | return 1u << static_cast<uint32_t>(reason); |
| 20 | } |
| 21 | |
| 22 | } // namespace |
| 23 | |
cfredric | 2c5cfa6 | 2020-11-16 19:59:25 | [diff] [blame] | 24 | CookieInclusionStatus::CookieInclusionStatus() = default; |
Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 25 | |
| 26 | CookieInclusionStatus::CookieInclusionStatus(ExclusionReason reason) |
| 27 | : exclusion_reasons_(GetExclusionBitmask(reason)) {} |
| 28 | |
| 29 | CookieInclusionStatus::CookieInclusionStatus(ExclusionReason reason, |
| 30 | WarningReason warning) |
| 31 | : exclusion_reasons_(GetExclusionBitmask(reason)), |
| 32 | warning_reasons_(GetWarningBitmask(warning)) {} |
| 33 | |
cfredric | 362c4a0 | 2021-07-09 22:40:40 | [diff] [blame] | 34 | CookieInclusionStatus::CookieInclusionStatus(WarningReason warning) |
| 35 | : warning_reasons_(GetWarningBitmask(warning)) {} |
| 36 | |
Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 37 | bool CookieInclusionStatus::operator==( |
| 38 | const CookieInclusionStatus& other) const { |
| 39 | return exclusion_reasons_ == other.exclusion_reasons_ && |
| 40 | warning_reasons_ == other.warning_reasons_; |
| 41 | } |
| 42 | |
| 43 | bool CookieInclusionStatus::operator!=( |
| 44 | const CookieInclusionStatus& other) const { |
| 45 | return !operator==(other); |
| 46 | } |
| 47 | |
| 48 | bool CookieInclusionStatus::IsInclude() const { |
| 49 | return exclusion_reasons_ == 0u; |
| 50 | } |
| 51 | |
| 52 | bool CookieInclusionStatus::HasExclusionReason(ExclusionReason reason) const { |
| 53 | return exclusion_reasons_ & GetExclusionBitmask(reason); |
| 54 | } |
| 55 | |
Lily Chen | 70c537a | 2020-07-20 18:02:09 | [diff] [blame] | 56 | bool CookieInclusionStatus::HasOnlyExclusionReason( |
| 57 | ExclusionReason reason) const { |
| 58 | return exclusion_reasons_ == GetExclusionBitmask(reason); |
| 59 | } |
| 60 | |
Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 61 | void CookieInclusionStatus::AddExclusionReason(ExclusionReason reason) { |
| 62 | exclusion_reasons_ |= GetExclusionBitmask(reason); |
| 63 | // If the cookie would be excluded for reasons other than the new SameSite |
| 64 | // rules, don't bother warning about it. |
| 65 | MaybeClearSameSiteWarning(); |
| 66 | } |
| 67 | |
| 68 | void CookieInclusionStatus::RemoveExclusionReason(ExclusionReason reason) { |
| 69 | exclusion_reasons_ &= ~(GetExclusionBitmask(reason)); |
| 70 | } |
| 71 | |
cfredric | 05c78ac | 2021-01-06 18:10:26 | [diff] [blame] | 72 | void CookieInclusionStatus::RemoveExclusionReasons( |
| 73 | const std::vector<ExclusionReason>& reasons) { |
| 74 | exclusion_reasons_ = ExclusionReasonsWithout(reasons); |
| 75 | } |
| 76 | |
cfredric | 2c5cfa6 | 2020-11-16 19:59:25 | [diff] [blame] | 77 | uint32_t CookieInclusionStatus::ExclusionReasonsWithout( |
| 78 | const std::vector<ExclusionReason>& reasons) const { |
| 79 | uint32_t mask = 0u; |
| 80 | for (const ExclusionReason reason : reasons) { |
| 81 | mask |= GetExclusionBitmask(reason); |
| 82 | } |
| 83 | return exclusion_reasons_ & ~mask; |
| 84 | } |
| 85 | |
Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 86 | void CookieInclusionStatus::MaybeClearSameSiteWarning() { |
cfredric | 2c5cfa6 | 2020-11-16 19:59:25 | [diff] [blame] | 87 | if (ExclusionReasonsWithout({ |
| 88 | EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX, |
| 89 | EXCLUDE_SAMESITE_NONE_INSECURE, |
| 90 | }) != 0u) { |
Lily Chen | 2db3a42 | 2021-07-20 18:02:25 | [diff] [blame] | 91 | RemoveWarningReason(WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT); |
| 92 | RemoveWarningReason(WARN_SAMESITE_NONE_INSECURE); |
| 93 | RemoveWarningReason(WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE); |
Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 94 | } |
| 95 | |
cfredric | 2c5cfa6 | 2020-11-16 19:59:25 | [diff] [blame] | 96 | if (!ShouldRecordDowngradeMetrics()) { |
Lily Chen | 2db3a42 | 2021-07-20 18:02:25 | [diff] [blame] | 97 | RemoveWarningReason(WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE); |
| 98 | RemoveWarningReason(WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE); |
| 99 | RemoveWarningReason(WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE); |
| 100 | RemoveWarningReason(WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE); |
| 101 | RemoveWarningReason(WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE); |
| 102 | |
| 103 | RemoveWarningReason(WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION); |
Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 104 | } |
| 105 | } |
| 106 | |
| 107 | bool CookieInclusionStatus::ShouldRecordDowngradeMetrics() const { |
cfredric | 2c5cfa6 | 2020-11-16 19:59:25 | [diff] [blame] | 108 | return ExclusionReasonsWithout({ |
| 109 | EXCLUDE_SAMESITE_STRICT, |
| 110 | EXCLUDE_SAMESITE_LAX, |
| 111 | EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX, |
| 112 | }) == 0u; |
Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 113 | } |
| 114 | |
| 115 | bool CookieInclusionStatus::ShouldWarn() const { |
| 116 | return warning_reasons_ != 0u; |
| 117 | } |
| 118 | |
| 119 | bool CookieInclusionStatus::HasWarningReason(WarningReason reason) const { |
| 120 | return warning_reasons_ & GetWarningBitmask(reason); |
| 121 | } |
| 122 | |
| 123 | bool CookieInclusionStatus::HasDowngradeWarning( |
| 124 | CookieInclusionStatus::WarningReason* reason) const { |
| 125 | if (!ShouldWarn()) |
| 126 | return false; |
| 127 | |
| 128 | const CookieInclusionStatus::WarningReason kDowngradeWarnings[] = { |
| 129 | WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE, |
| 130 | WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE, |
| 131 | WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE, |
| 132 | WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE, |
| 133 | WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE, |
| 134 | }; |
| 135 | |
| 136 | for (auto warning : kDowngradeWarnings) { |
| 137 | if (!HasWarningReason(warning)) |
| 138 | continue; |
| 139 | |
| 140 | if (reason) |
| 141 | *reason = warning; |
| 142 | |
| 143 | return true; |
| 144 | } |
| 145 | |
| 146 | return false; |
| 147 | } |
| 148 | |
| 149 | void CookieInclusionStatus::AddWarningReason(WarningReason reason) { |
| 150 | warning_reasons_ |= GetWarningBitmask(reason); |
| 151 | } |
| 152 | |
| 153 | void CookieInclusionStatus::RemoveWarningReason(WarningReason reason) { |
| 154 | warning_reasons_ &= ~(GetWarningBitmask(reason)); |
| 155 | } |
| 156 | |
| 157 | CookieInclusionStatus::ContextDowngradeMetricValues |
| 158 | CookieInclusionStatus::GetBreakingDowngradeMetricsEnumValue( |
| 159 | const GURL& url) const { |
| 160 | bool url_is_secure = url.SchemeIsCryptographic(); |
| 161 | |
| 162 | // Start the |reason| as something other than the downgrade warnings. |
| 163 | WarningReason reason = WarningReason::NUM_WARNING_REASONS; |
| 164 | |
| 165 | // Don't bother checking the return value because the default switch case |
| 166 | // will handle if no reason was found. |
| 167 | HasDowngradeWarning(&reason); |
| 168 | |
| 169 | switch (reason) { |
| 170 | case WarningReason::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE: |
| 171 | return url_is_secure |
| 172 | ? ContextDowngradeMetricValues::STRICT_LAX_STRICT_SECURE |
| 173 | : ContextDowngradeMetricValues::STRICT_LAX_STRICT_INSECURE; |
| 174 | case WarningReason::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE: |
| 175 | return url_is_secure |
| 176 | ? ContextDowngradeMetricValues::STRICT_CROSS_STRICT_SECURE |
| 177 | : ContextDowngradeMetricValues::STRICT_CROSS_STRICT_INSECURE; |
| 178 | case WarningReason::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE: |
| 179 | return url_is_secure |
| 180 | ? ContextDowngradeMetricValues::STRICT_CROSS_LAX_SECURE |
| 181 | : ContextDowngradeMetricValues::STRICT_CROSS_LAX_INSECURE; |
| 182 | case WarningReason::WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE: |
| 183 | return url_is_secure |
| 184 | ? ContextDowngradeMetricValues::LAX_CROSS_STRICT_SECURE |
| 185 | : ContextDowngradeMetricValues::LAX_CROSS_STRICT_INSECURE; |
| 186 | case WarningReason::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE: |
| 187 | return url_is_secure |
| 188 | ? ContextDowngradeMetricValues::LAX_CROSS_LAX_SECURE |
| 189 | : ContextDowngradeMetricValues::LAX_CROSS_LAX_INSECURE; |
| 190 | default: |
| 191 | return url_is_secure |
| 192 | ? ContextDowngradeMetricValues::NO_DOWNGRADE_SECURE |
| 193 | : ContextDowngradeMetricValues::NO_DOWNGRADE_INSECURE; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | std::string CookieInclusionStatus::GetDebugString() const { |
| 198 | std::string out; |
| 199 | |
Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 200 | if (IsInclude()) |
| 201 | base::StrAppend(&out, {"INCLUDE, "}); |
cfredric | a50e853 | 2021-06-29 19:44:56 | [diff] [blame] | 202 | for (const auto& reason : |
| 203 | std::initializer_list<std::pair<ExclusionReason, std::string>>{ |
| 204 | {EXCLUDE_UNKNOWN_ERROR, "EXCLUDE_UNKNOWN_ERROR"}, |
| 205 | {EXCLUDE_HTTP_ONLY, "EXCLUDE_HTTP_ONLY"}, |
| 206 | {EXCLUDE_SECURE_ONLY, "EXCLUDE_SECURE_ONLY"}, |
| 207 | {EXCLUDE_DOMAIN_MISMATCH, "EXCLUDE_DOMAIN_MISMATCH"}, |
| 208 | {EXCLUDE_NOT_ON_PATH, "EXCLUDE_NOT_ON_PATH"}, |
| 209 | {EXCLUDE_SAMESITE_STRICT, "EXCLUDE_SAMESITE_STRICT"}, |
| 210 | {EXCLUDE_SAMESITE_LAX, "EXCLUDE_SAMESITE_LAX"}, |
| 211 | {EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX, |
| 212 | "EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX"}, |
| 213 | {EXCLUDE_SAMESITE_NONE_INSECURE, "EXCLUDE_SAMESITE_NONE_INSECURE"}, |
| 214 | {EXCLUDE_USER_PREFERENCES, "EXCLUDE_USER_PREFERENCES"}, |
| 215 | {EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT, |
| 216 | "EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT"}, |
| 217 | {EXCLUDE_FAILURE_TO_STORE, "EXCLUDE_FAILURE_TO_STORE"}, |
| 218 | {EXCLUDE_NONCOOKIEABLE_SCHEME, "EXCLUDE_NONCOOKIEABLE_SCHEME"}, |
| 219 | {EXCLUDE_OVERWRITE_SECURE, "EXCLUDE_OVERWRITE_SECURE"}, |
| 220 | {EXCLUDE_OVERWRITE_HTTP_ONLY, "EXCLUDE_OVERWRITE_HTTP_ONLY"}, |
| 221 | {EXCLUDE_INVALID_DOMAIN, "EXCLUDE_INVALID_DOMAIN"}, |
| 222 | {EXCLUDE_INVALID_PREFIX, "EXCLUDE_INVALID_PREFIX"}, |
| 223 | {EXCLUDE_INVALID_SAMEPARTY, "EXCLUDE_INVALID_SAMEPARTY"}, |
Dylan Cutler | 01ca8e3 | 2021-07-16 18:01:35 | [diff] [blame] | 224 | {EXCLUDE_INVALID_PARTITIONED, "EXCLUDE_INVALID_PARTITIONED"}, |
Andrew Williams | e320767e0 | 2021-09-10 04:38:00 | [diff] [blame^] | 225 | {EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE, |
| 226 | "EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE"}, |
| 227 | {EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE, |
| 228 | "EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE"}, |
cfredric | a50e853 | 2021-06-29 19:44:56 | [diff] [blame] | 229 | }) { |
| 230 | if (HasExclusionReason(reason.first)) |
| 231 | base::StrAppend(&out, {reason.second, ", "}); |
| 232 | } |
Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 233 | |
| 234 | // Add warning |
| 235 | if (!ShouldWarn()) { |
| 236 | base::StrAppend(&out, {"DO_NOT_WARN"}); |
| 237 | return out; |
| 238 | } |
| 239 | |
cfredric | a50e853 | 2021-06-29 19:44:56 | [diff] [blame] | 240 | for (const auto& reason : |
| 241 | std::initializer_list<std::pair<WarningReason, std::string>>{ |
| 242 | {WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT, |
| 243 | "WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT"}, |
| 244 | {WARN_SAMESITE_NONE_INSECURE, "WARN_SAMESITE_NONE_INSECURE"}, |
| 245 | {WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE, |
| 246 | "WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE"}, |
| 247 | {WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE, |
| 248 | "WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE"}, |
| 249 | {WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE, |
| 250 | "WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE"}, |
| 251 | {WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE, |
| 252 | "WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE"}, |
| 253 | {WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE, |
| 254 | "WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE"}, |
| 255 | {WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE, |
| 256 | "WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE"}, |
| 257 | {WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC, |
| 258 | "WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC"}, |
| 259 | {WARN_SAMEPARTY_EXCLUSION_OVERRULED_SAMESITE, |
| 260 | "WARN_SAMEPARTY_EXCLUSION_OVERRULED_SAMESITE"}, |
| 261 | {WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE, |
| 262 | "WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE"}, |
cfredric | 362c4a0 | 2021-07-09 22:40:40 | [diff] [blame] | 263 | {WARN_SAMESITE_NONE_REQUIRED, "WARN_SAMESITE_NONE_REQUIRED"}, |
| 264 | {WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE, |
| 265 | "WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE"}, |
| 266 | {WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS, |
| 267 | "WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS"}, |
| 268 | {WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX, |
| 269 | "WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX"}, |
| 270 | {WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT, |
| 271 | "WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT"}, |
Lily Chen | 2db3a42 | 2021-07-20 18:02:25 | [diff] [blame] | 272 | {WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION, |
| 273 | "WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION"}, |
cfredric | a50e853 | 2021-06-29 19:44:56 | [diff] [blame] | 274 | }) { |
| 275 | if (HasWarningReason(reason.first)) |
| 276 | base::StrAppend(&out, {reason.second, ", "}); |
Lily Chen | ef77a17 | 2021-02-22 22:42:26 | [diff] [blame] | 277 | } |
Jihwan Marc Kim | 3e132f1 | 2020-05-20 17:33:19 | [diff] [blame] | 278 | |
| 279 | // Strip trailing comma and space. |
| 280 | out.erase(out.end() - 2, out.end()); |
| 281 | |
| 282 | return out; |
| 283 | } |
| 284 | |
| 285 | bool CookieInclusionStatus::IsValid() const { |
| 286 | // Bit positions where there should not be any true bits. |
| 287 | uint32_t exclusion_mask = ~0u << static_cast<int>(NUM_EXCLUSION_REASONS); |
| 288 | uint32_t warning_mask = ~0u << static_cast<int>(NUM_WARNING_REASONS); |
| 289 | return (exclusion_mask & exclusion_reasons_) == 0u && |
| 290 | (warning_mask & warning_reasons_) == 0u; |
| 291 | } |
| 292 | |
| 293 | bool CookieInclusionStatus::HasExactlyExclusionReasonsForTesting( |
| 294 | std::vector<CookieInclusionStatus::ExclusionReason> reasons) const { |
| 295 | CookieInclusionStatus expected = MakeFromReasonsForTesting(reasons); |
| 296 | return expected.exclusion_reasons_ == exclusion_reasons_; |
| 297 | } |
| 298 | |
| 299 | bool CookieInclusionStatus::HasExactlyWarningReasonsForTesting( |
| 300 | std::vector<WarningReason> reasons) const { |
| 301 | CookieInclusionStatus expected = MakeFromReasonsForTesting({}, reasons); |
| 302 | return expected.warning_reasons_ == warning_reasons_; |
| 303 | } |
| 304 | |
| 305 | // static |
| 306 | CookieInclusionStatus CookieInclusionStatus::MakeFromReasonsForTesting( |
| 307 | std::vector<ExclusionReason> reasons, |
| 308 | std::vector<WarningReason> warnings) { |
| 309 | CookieInclusionStatus status; |
| 310 | for (ExclusionReason reason : reasons) { |
| 311 | status.AddExclusionReason(reason); |
| 312 | } |
| 313 | for (WarningReason warning : warnings) { |
| 314 | status.AddWarningReason(warning); |
| 315 | } |
| 316 | return status; |
| 317 | } |
| 318 | |
| 319 | } // namespace net |