Commit 34ed01a8 authored by cfredric's avatar cfredric Committed by Chromium LUCI CQ

Move Secure cookie check into CanonicalCookie::IsSetPermittedInContext.

This cl also converts a portion of CanonicalCookie unit tests to use
matcher-based code, in order to be able to more easily assert multiple
things about multiple parts of the return value of
IsSetPermittedInContext. (E.g., being able to make assertions about both
the |status| and the |is_allowed_to_access_secure_cookies| fields of the
|CookieAccessResult|. This also has the benefit of being more
declarative and avoiding declaring temp variables, which are
error-prone. In particular, this fixes bugs where the wrong temp
variable was accidentally used (lines 2785, 2899).

This cl also fixes a bug (in test) where the LEGACY access semantics
were accidentally unused, with UNKNOWN being redundantly used instead
(lines 2967-2987).

Change-Id: I09b981f5f0819807ff5dd769022e4d6baa5f50a4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2571806Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarLily Chen <chlily@chromium.org>
Commit-Queue: Chris Fredrickson <cfredric@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834578}
parent 61f36a70
...@@ -662,19 +662,29 @@ CookieAccessResult CanonicalCookie::IncludeForRequestURL( ...@@ -662,19 +662,29 @@ CookieAccessResult CanonicalCookie::IncludeForRequestURL(
// insecure scheme, unless it is a localhost url, or the CookieAccessDelegate // insecure scheme, unless it is a localhost url, or the CookieAccessDelegate
// otherwise denotes them as trustworthy // otherwise denotes them as trustworthy
// (`delegate_treats_url_as_trustworthy`). // (`delegate_treats_url_as_trustworthy`).
if (IsSecure()) { bool is_allowed_to_access_secure_cookies = false;
CookieAccessScheme cookie_access_scheme = CookieAccessScheme cookie_access_scheme =
cookie_util::ProvisionalAccessScheme(url); cookie_util::ProvisionalAccessScheme(url);
if (cookie_access_scheme == CookieAccessScheme::kNonCryptographic && if (cookie_access_scheme == CookieAccessScheme::kNonCryptographic &&
params.delegate_treats_url_as_trustworthy) { params.delegate_treats_url_as_trustworthy) {
cookie_access_scheme = CookieAccessScheme::kTrustworthy; cookie_access_scheme = CookieAccessScheme::kTrustworthy;
} }
if (cookie_access_scheme == CookieAccessScheme::kNonCryptographic) { switch (cookie_access_scheme) {
case CookieAccessScheme::kNonCryptographic:
if (IsSecure())
status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_SECURE_ONLY); status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
} else if (cookie_access_scheme == CookieAccessScheme::kTrustworthy) { break;
case CookieAccessScheme::kTrustworthy:
is_allowed_to_access_secure_cookies = true;
if (IsSecure()) {
status.AddWarningReason( status.AddWarningReason(
CookieInclusionStatus::WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC); CookieInclusionStatus::
WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC);
} }
break;
case CookieAccessScheme::kCryptographic:
is_allowed_to_access_secure_cookies = true;
break;
} }
// Don't include cookies for requests that don't apply to the cookie domain. // Don't include cookies for requests that don't apply to the cookie domain.
if (!IsDomainMatch(url.host())) if (!IsDomainMatch(url.host()))
...@@ -771,21 +781,56 @@ CookieAccessResult CanonicalCookie::IncludeForRequestURL( ...@@ -771,21 +781,56 @@ CookieAccessResult CanonicalCookie::IncludeForRequestURL(
// TODO(chlily): Log metrics. // TODO(chlily): Log metrics.
return CookieAccessResult(effective_same_site, status, return CookieAccessResult(effective_same_site, status,
params.access_semantics); params.access_semantics,
is_allowed_to_access_secure_cookies);
} }
CookieAccessResult CanonicalCookie::IsSetPermittedInContext( CookieAccessResult CanonicalCookie::IsSetPermittedInContext(
const GURL& source_url,
const CookieOptions& options, const CookieOptions& options,
const CookieAccessParams& params) const { const CookieAccessParams& params) const {
CookieAccessResult access_result; CookieAccessResult access_result;
IsSetPermittedInContext(options, params, &access_result); IsSetPermittedInContext(source_url, options, params, &access_result);
return access_result; return access_result;
} }
void CanonicalCookie::IsSetPermittedInContext( void CanonicalCookie::IsSetPermittedInContext(
const GURL& source_url,
const CookieOptions& options, const CookieOptions& options,
const CookieAccessParams& params, const CookieAccessParams& params,
CookieAccessResult* access_result) const { CookieAccessResult* access_result) const {
CookieAccessScheme access_scheme =
cookie_util::ProvisionalAccessScheme(source_url);
if (access_scheme == CookieAccessScheme::kNonCryptographic &&
params.delegate_treats_url_as_trustworthy) {
access_scheme = CookieAccessScheme::kTrustworthy;
}
switch (access_scheme) {
case CookieAccessScheme::kNonCryptographic:
access_result->is_allowed_to_access_secure_cookies = false;
if (IsSecure()) {
access_result->status.AddExclusionReason(
CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
}
break;
case CookieAccessScheme::kCryptographic:
// All cool!
access_result->is_allowed_to_access_secure_cookies = true;
break;
case CookieAccessScheme::kTrustworthy:
access_result->is_allowed_to_access_secure_cookies = true;
if (IsSecure()) {
// OK, but want people aware of this.
access_result->status.AddWarningReason(
CookieInclusionStatus::
WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC);
}
break;
}
access_result->access_semantics = params.access_semantics; access_result->access_semantics = params.access_semantics;
if (options.exclude_httponly() && IsHttpOnly()) { if (options.exclude_httponly() && IsHttpOnly()) {
DVLOG(net::cookie_util::kVlogSetCookies) DVLOG(net::cookie_util::kVlogSetCookies)
......
...@@ -312,11 +312,13 @@ class NET_EXPORT CanonicalCookie { ...@@ -312,11 +312,13 @@ class NET_EXPORT CanonicalCookie {
// in a secure scheme, since whether the scheme is secure isn't part of // in a secure scheme, since whether the scheme is secure isn't part of
// |options|. // |options|.
CookieAccessResult IsSetPermittedInContext( CookieAccessResult IsSetPermittedInContext(
const GURL& source_url,
const CookieOptions& options, const CookieOptions& options,
const CookieAccessParams& params) const; const CookieAccessParams& params) const;
// Overload that updates an existing |status| rather than returning a new one. // Overload that updates an existing |status| rather than returning a new one.
void IsSetPermittedInContext(const CookieOptions& options, void IsSetPermittedInContext(const GURL& source_url,
const CookieOptions& options,
const CookieAccessParams& params, const CookieAccessParams& params,
CookieAccessResult* access_result) const; CookieAccessResult* access_result) const;
......
This diff is collapsed.
...@@ -11,10 +11,13 @@ CookieAccessResult::CookieAccessResult() = default; ...@@ -11,10 +11,13 @@ CookieAccessResult::CookieAccessResult() = default;
CookieAccessResult::CookieAccessResult( CookieAccessResult::CookieAccessResult(
CookieEffectiveSameSite effective_same_site, CookieEffectiveSameSite effective_same_site,
CookieInclusionStatus status, CookieInclusionStatus status,
CookieAccessSemantics access_semantics) CookieAccessSemantics access_semantics,
bool is_allowed_to_access_secure_cookies)
: status(status), : status(status),
effective_same_site(effective_same_site), effective_same_site(effective_same_site),
access_semantics(access_semantics) {} access_semantics(access_semantics),
is_allowed_to_access_secure_cookies(is_allowed_to_access_secure_cookies) {
}
CookieAccessResult::CookieAccessResult(CookieInclusionStatus status) CookieAccessResult::CookieAccessResult(CookieInclusionStatus status)
: status(status) {} : status(status) {}
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef NET_COOKIES_COOKIE_ACCESS_RESULT_H_ #ifndef NET_COOKIES_COOKIE_ACCESS_RESULT_H_
#define NET_COOKIES_COOKIE_ACCESS_RESULT_H_ #define NET_COOKIES_COOKIE_ACCESS_RESULT_H_
#include <ostream>
#include "net/base/net_export.h" #include "net/base/net_export.h"
#include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_inclusion_status.h" #include "net/cookies/cookie_inclusion_status.h"
...@@ -18,7 +20,8 @@ struct NET_EXPORT CookieAccessResult { ...@@ -18,7 +20,8 @@ struct NET_EXPORT CookieAccessResult {
CookieAccessResult(); CookieAccessResult();
CookieAccessResult(CookieEffectiveSameSite effective_same_site, CookieAccessResult(CookieEffectiveSameSite effective_same_site,
CookieInclusionStatus status, CookieInclusionStatus status,
CookieAccessSemantics access_semantics); CookieAccessSemantics access_semantics,
bool is_allowed_to_access_secure_cookie);
explicit CookieAccessResult(CookieInclusionStatus status); explicit CookieAccessResult(CookieInclusionStatus status);
...@@ -34,8 +37,21 @@ struct NET_EXPORT CookieAccessResult { ...@@ -34,8 +37,21 @@ struct NET_EXPORT CookieAccessResult {
CookieEffectiveSameSite effective_same_site = CookieEffectiveSameSite effective_same_site =
CookieEffectiveSameSite::UNDEFINED; CookieEffectiveSameSite::UNDEFINED;
CookieAccessSemantics access_semantics = CookieAccessSemantics::UNKNOWN; CookieAccessSemantics access_semantics = CookieAccessSemantics::UNKNOWN;
// Whether access to Secure cookies should be allowed. This is expected to be
// set based on the scheme of the source URL.
bool is_allowed_to_access_secure_cookies = false;
}; };
// Provided to allow gtest to create more helpful error messages, instead of
// printing hex.
inline void PrintTo(const CookieAccessResult& car, std::ostream* os) {
*os << "{ { ";
PrintTo(car.status, os);
*os << " }, " << static_cast<int>(car.effective_same_site) << ", "
<< static_cast<int>(car.access_semantics) << ", "
<< car.is_allowed_to_access_secure_cookies << " }";
}
} // namespace net } // namespace net
#endif // NET_COOKIES_COOKIE_ACCESS_RESULT_H_ #endif // NET_COOKIES_COOKIE_ACCESS_RESULT_H_
...@@ -292,6 +292,12 @@ NET_EXPORT inline std::ostream& operator<<(std::ostream& os, ...@@ -292,6 +292,12 @@ NET_EXPORT inline std::ostream& operator<<(std::ostream& os,
return os << status.GetDebugString(); return os << status.GetDebugString();
} }
// Provided to allow gtest to create more helpful error messages, instead of
// printing hex.
inline void PrintTo(const CookieInclusionStatus& cis, std::ostream* os) {
*os << cis;
}
} // namespace net } // namespace net
#endif // NET_COOKIES_COOKIE_INCLUSION_STATUS_H_ #endif // NET_COOKIES_COOKIE_INCLUSION_STATUS_H_
...@@ -1190,37 +1190,6 @@ void CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc, ...@@ -1190,37 +1190,6 @@ void CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc,
bool delegate_treats_url_as_trustworthy = bool delegate_treats_url_as_trustworthy =
cookie_access_delegate() && cookie_access_delegate() &&
cookie_access_delegate()->ShouldTreatUrlAsTrustworthy(source_url); cookie_access_delegate()->ShouldTreatUrlAsTrustworthy(source_url);
CookieAccessScheme access_scheme =
cookie_util::ProvisionalAccessScheme(source_url);
if (access_scheme == CookieAccessScheme::kNonCryptographic &&
delegate_treats_url_as_trustworthy) {
access_scheme = CookieAccessScheme::kTrustworthy;
}
bool allowed_to_set_secure_cookie = false;
switch (access_scheme) {
case CookieAccessScheme::kNonCryptographic:
if (cc->IsSecure()) {
access_result.status.AddExclusionReason(
CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
}
break;
case CookieAccessScheme::kCryptographic:
// All cool!
allowed_to_set_secure_cookie = true;
break;
case CookieAccessScheme::kTrustworthy:
allowed_to_set_secure_cookie = true;
if (cc->IsSecure()) {
// OK, but want people aware of this.
access_result.status.AddWarningReason(
CookieInclusionStatus::
WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC);
}
break;
}
if (!IsCookieableScheme(source_url.scheme())) { if (!IsCookieableScheme(source_url.scheme())) {
access_result.status.AddExclusionReason( access_result.status.AddExclusionReason(
...@@ -1230,7 +1199,7 @@ void CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc, ...@@ -1230,7 +1199,7 @@ void CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc,
const std::string key(GetKey(cc->Domain())); const std::string key(GetKey(cc->Domain()));
cc->IsSetPermittedInContext( cc->IsSetPermittedInContext(
options, source_url, options,
CookieAccessParams(GetAccessSemanticsForCookie(*cc), CookieAccessParams(GetAccessSemanticsForCookie(*cc),
delegate_treats_url_as_trustworthy), delegate_treats_url_as_trustworthy),
&access_result); &access_result);
...@@ -1248,8 +1217,9 @@ void CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc, ...@@ -1248,8 +1217,9 @@ void CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc,
// deletes an existing cookie, so any ExclusionReasons in |status| that would // deletes an existing cookie, so any ExclusionReasons in |status| that would
// prevent such deletion should be finalized beforehand. // prevent such deletion should be finalized beforehand.
MaybeDeleteEquivalentCookieAndUpdateStatus( MaybeDeleteEquivalentCookieAndUpdateStatus(
key, *cc, allowed_to_set_secure_cookie, options.exclude_httponly(), key, *cc, access_result.is_allowed_to_access_secure_cookies,
already_expired, &creation_date_to_inherit, &access_result.status); options.exclude_httponly(), already_expired, &creation_date_to_inherit,
&access_result.status);
if (access_result.status.HasExclusionReason( if (access_result.status.HasExclusionReason(
CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE) || CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE) ||
...@@ -1427,10 +1397,12 @@ void CookieMonster::InternalDeleteCookie(CookieMap::iterator it, ...@@ -1427,10 +1397,12 @@ void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
store_->DeleteCookie(*cc); store_->DeleteCookie(*cc);
} }
change_dispatcher_.DispatchChange( change_dispatcher_.DispatchChange(
CookieChangeInfo(*cc, CookieChangeInfo(
*cc,
CookieAccessResult(CookieEffectiveSameSite::UNDEFINED, CookieAccessResult(CookieEffectiveSameSite::UNDEFINED,
CookieInclusionStatus(), CookieInclusionStatus(),
GetAccessSemanticsForCookie(*cc)), GetAccessSemanticsForCookie(*cc),
true /* is_allowed_to_access_secure_cookies */),
mapping.cause), mapping.cause),
mapping.notify); mapping.notify);
......
...@@ -457,7 +457,8 @@ bool StructTraits< ...@@ -457,7 +457,8 @@ bool StructTraits<
if (!c.ReadAccessSemantics(&access_semantics)) if (!c.ReadAccessSemantics(&access_semantics))
return false; return false;
*out = {effective_same_site, status, access_semantics}; *out = {effective_same_site, status, access_semantics,
c.is_allowed_to_access_secure_cookies()};
return true; return true;
} }
......
...@@ -217,6 +217,10 @@ struct StructTraits<network::mojom::CookieAccessResultDataView, ...@@ -217,6 +217,10 @@ struct StructTraits<network::mojom::CookieAccessResultDataView,
const net::CookieAccessResult& c) { const net::CookieAccessResult& c) {
return c.access_semantics; return c.access_semantics;
} }
static bool is_allowed_to_access_secure_cookies(
const net::CookieAccessResult& c) {
return c.is_allowed_to_access_secure_cookies;
}
static bool Read(network::mojom::CookieAccessResultDataView access_result, static bool Read(network::mojom::CookieAccessResultDataView access_result,
net::CookieAccessResult* out); net::CookieAccessResult* out);
}; };
......
...@@ -118,7 +118,7 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatus) { ...@@ -118,7 +118,7 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatus) {
invalid, copied)); invalid, copied));
} }
TEST(CookieManagerTraitsTest, Rountrips_CookieAccessResult) { TEST(CookieManagerTraitsTest, Roundtrips_CookieAccessResult) {
net::CookieAccessResult original = net::CookieAccessResult( net::CookieAccessResult original = net::CookieAccessResult(
net::CookieEffectiveSameSite::LAX_MODE, net::CookieEffectiveSameSite::LAX_MODE,
net::CookieInclusionStatus( net::CookieInclusionStatus(
...@@ -126,7 +126,8 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieAccessResult) { ...@@ -126,7 +126,8 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieAccessResult) {
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX, EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
net::CookieInclusionStatus:: net::CookieInclusionStatus::
WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT), WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
net::CookieAccessSemantics::LEGACY); net::CookieAccessSemantics::LEGACY,
true /* is_allowed_to_access_secure_cookies */);
net::CookieAccessResult copied; net::CookieAccessResult copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieAccessResult>( EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieAccessResult>(
...@@ -139,12 +140,14 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieAccessResult) { ...@@ -139,12 +140,14 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieAccessResult) {
EXPECT_TRUE(copied.status.HasExactlyWarningReasonsForTesting( EXPECT_TRUE(copied.status.HasExactlyWarningReasonsForTesting(
{net::CookieInclusionStatus:: {net::CookieInclusionStatus::
WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT})); WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
EXPECT_EQ(original.is_allowed_to_access_secure_cookies,
copied.is_allowed_to_access_secure_cookies);
} }
TEST(CookieManagerTraitsTest, Rountrips_CookieWithAccessResult) { TEST(CookieManagerTraitsTest, Rountrips_CookieWithAccessResult) {
net::CanonicalCookie original_cookie( net::CanonicalCookie original_cookie(
"A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
/* secure = */ true, /* http_only = */ false, /* secure = */ true, /* httponly = */ false,
net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, false); net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, false);
net::CookieWithAccessResult original = {original_cookie, net::CookieWithAccessResult original = {original_cookie,
...@@ -172,10 +175,10 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieWithAccessResult) { ...@@ -172,10 +175,10 @@ TEST(CookieManagerTraitsTest, Rountrips_CookieWithAccessResult) {
EXPECT_EQ(original.access_result.status, copied.access_result.status); EXPECT_EQ(original.access_result.status, copied.access_result.status);
} }
TEST(CookieManagerTraitsTest, Rountrips_CookieAndLineWithAccessResult) { TEST(CookieManagerTraitsTest, Roundtrips_CookieAndLineWithAccessResult) {
net::CanonicalCookie original_cookie( net::CanonicalCookie original_cookie(
"A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
/* secure = */ true, /* http_only = */ false, /* secure = */ true, /* httponly = */ false,
net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, false); net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW, false);
net::CookieAndLineWithAccessResult original(original_cookie, "cookie-string", net::CookieAndLineWithAccessResult original(original_cookie, "cookie-string",
...@@ -374,14 +377,15 @@ TEST(CookieManagerTraitsTest, Roundtrips_FullPartyContext) { ...@@ -374,14 +377,15 @@ TEST(CookieManagerTraitsTest, Roundtrips_FullPartyContext) {
TEST(CookieManagerTraitsTest, Roundtrips_CookieChangeInfo) { TEST(CookieManagerTraitsTest, Roundtrips_CookieChangeInfo) {
net::CanonicalCookie original_cookie( net::CanonicalCookie original_cookie(
"A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
/* secure = */ false, /* http_only = */ false, /* secure = */ false, /* httponly = */ false,
net::CookieSameSite::UNSPECIFIED, net::COOKIE_PRIORITY_LOW, false); net::CookieSameSite::UNSPECIFIED, net::COOKIE_PRIORITY_LOW, false);
net::CookieChangeInfo original( net::CookieChangeInfo original(
original_cookie, original_cookie,
net::CookieAccessResult(net::CookieEffectiveSameSite::UNDEFINED, net::CookieAccessResult(net::CookieEffectiveSameSite::UNDEFINED,
net::CookieInclusionStatus(), net::CookieInclusionStatus(),
net::CookieAccessSemantics::LEGACY), net::CookieAccessSemantics::LEGACY,
false /* is_allowed_to_access_secure_cookies */),
net::CookieChangeCause::EXPLICIT); net::CookieChangeCause::EXPLICIT);
net::CookieChangeInfo copied; net::CookieChangeInfo copied;
......
...@@ -156,10 +156,12 @@ struct CookieAndLineWithAccessResult { ...@@ -156,10 +156,12 @@ struct CookieAndLineWithAccessResult {
CookieAccessResult access_result; CookieAccessResult access_result;
}; };
// See net/cookies/cookie_access_result.{cc,h} for documentation.
struct CookieAccessResult { struct CookieAccessResult {
CookieEffectiveSameSite effective_same_site; CookieEffectiveSameSite effective_same_site;
CookieAccessSemantics access_semantics; CookieAccessSemantics access_semantics;
CookieInclusionStatus status; CookieInclusionStatus status;
bool is_allowed_to_access_secure_cookies;
}; };
struct CookieWithAccessResult { struct CookieWithAccessResult {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment