blob: 86f431e5170c1af28af6fea3caf9051e5af5807d [file] [log] [blame]
Matt Menke3ab9c7b2020-04-01 22:39:571// 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/base/isolation_info.h"
6
Hans Wennborg0924470b2020-04-27 21:08:057#include "base/check_op.h"
Matt Menke3ab9c7b2020-04-01 22:39:578
9namespace net {
10
11namespace {
12
13// Checks that |origin| is consistent with |site_for_cookies|.
14bool ValidateSameSite(const url::Origin& origin,
15 const SiteForCookies& site_for_cookies) {
16 // If not sending SameSite cookies, or sending them for a non-scheme, consider
17 // all origins consistent. Note that SiteForCookies should never be created
18 // for websocket schemes for valid navigations, since frames can't be
19 // navigated to those schemes.
20 if (site_for_cookies.IsNull() ||
21 (site_for_cookies.scheme() != url::kHttpScheme &&
22 site_for_cookies.scheme() != url::kHttpsScheme)) {
23 return true;
24 }
25
26 // Shouldn't send cookies for opaque origins.
27 if (origin.opaque())
28 return false;
29
30 // TODO(https://crbug.com/1060631): GetURL() is expensive. Maybe make a
31 // version of IsFirstParty that works on origins?
32 return site_for_cookies.IsFirstParty(origin.GetURL());
33}
34
35// Checks if these values are consistent. See IsolationInfo::Create() for
36// descriptions of consistent sets of values. Also allows values used by the
37// 0-argument constructor. Additionally, |opaque_and_non_transient| can only be
38// true if both origins are opaque and |site_for_cookies| is null.
shivanigithub4e78015f592020-10-21 13:26:2339bool IsConsistent(IsolationInfo::RequestType request_type,
Matt Menke3ab9c7b2020-04-01 22:39:5740 const base::Optional<url::Origin>& top_frame_origin,
41 const base::Optional<url::Origin>& frame_origin,
42 const SiteForCookies& site_for_cookies,
Shuran Huang0e0aaa52020-12-02 22:24:5443 bool opaque_and_non_transient,
44 base::Optional<std::set<SchemefulSite>> party_context) {
Matt Menke3ab9c7b2020-04-01 22:39:5745 // Check for the default-constructed case.
46 if (!top_frame_origin) {
shivanigithub4e78015f592020-10-21 13:26:2347 return request_type == IsolationInfo::RequestType::kOther &&
Matt Menke3ab9c7b2020-04-01 22:39:5748 !frame_origin && site_for_cookies.IsNull() &&
Shuran Huang0e0aaa52020-12-02 22:24:5449 !opaque_and_non_transient && !party_context;
Matt Menke3ab9c7b2020-04-01 22:39:5750 }
51
52 // |frame_origin| may only be nullopt is |top_frame_origin| is as well.
53 if (!frame_origin)
54 return false;
55
56 // As long as there is a |top_frame_origin|, |site_for_cookies| must be
57 // consistent with the |top_frame_origin|.
58 if (!ValidateSameSite(*top_frame_origin, site_for_cookies))
59 return false;
60
61 if (opaque_and_non_transient) {
shivanigithub4e78015f592020-10-21 13:26:2362 return (request_type == IsolationInfo::RequestType::kOther &&
Matt Menke3ab9c7b2020-04-01 22:39:5763 top_frame_origin->opaque() && top_frame_origin == frame_origin &&
64 site_for_cookies.IsNull());
65 }
66
shivanigithub4e78015f592020-10-21 13:26:2367 switch (request_type) {
68 case IsolationInfo::RequestType::kMainFrame:
Matt Menke3ab9c7b2020-04-01 22:39:5769 // TODO(https://crbug.com/1056706): Check that |top_frame_origin| and
70 // |frame_origin| are the same, once the ViewSource code creates a
71 // consistent IsolationInfo object.
72 //
73 // TODO(https://crbug.com/1060631): Once CreatePartial() is removed, check
74 // if SiteForCookies is non-null if the scheme is HTTP or HTTPS.
Shuran Huang0e0aaa52020-12-02 22:24:5475 //
76 // TODO(https://crbug.com/1151947): Once CreatePartial() is removed, check
77 // if party_context is non-null and empty.
Matt Menke3ab9c7b2020-04-01 22:39:5778 return true;
shivanigithub4e78015f592020-10-21 13:26:2379 case IsolationInfo::RequestType::kSubFrame:
Matt Menke3ab9c7b2020-04-01 22:39:5780 // For subframe navigations, the subframe's origin may not be consistent
81 // with the SiteForCookies, so SameSite cookies may be sent if there's a
82 // redirect to main frames site.
83 return true;
shivanigithub4e78015f592020-10-21 13:26:2384 case IsolationInfo::RequestType::kOther:
Matt Menke3ab9c7b2020-04-01 22:39:5785 // SiteForCookies must consistent with the frame origin as well for
86 // subresources.
87 return ValidateSameSite(*frame_origin, site_for_cookies);
88 }
89}
90
91} // namespace
92
93IsolationInfo::IsolationInfo()
shivanigithub4e78015f592020-10-21 13:26:2394 : IsolationInfo(RequestType::kOther,
Matt Menke3ab9c7b2020-04-01 22:39:5795 base::nullopt,
96 base::nullopt,
97 SiteForCookies(),
Shuran Huang0e0aaa52020-12-02 22:24:5498 false /* opaque_and_non_transient */,
99 base::nullopt) {}
Matt Menke3ab9c7b2020-04-01 22:39:57100
101IsolationInfo::IsolationInfo(const IsolationInfo&) = default;
102IsolationInfo::IsolationInfo(IsolationInfo&&) = default;
103IsolationInfo::~IsolationInfo() = default;
104IsolationInfo& IsolationInfo::operator=(const IsolationInfo&) = default;
105IsolationInfo& IsolationInfo::operator=(IsolationInfo&&) = default;
106
107IsolationInfo IsolationInfo::CreateForInternalRequest(
108 const url::Origin& top_frame_origin) {
shivanigithub4e78015f592020-10-21 13:26:23109 return IsolationInfo(RequestType::kOther, top_frame_origin, top_frame_origin,
Matt Menke3ab9c7b2020-04-01 22:39:57110 SiteForCookies::FromOrigin(top_frame_origin),
Shuran Huang0e0aaa52020-12-02 22:24:54111 false /* opaque_and_non_transient */,
112 std::set<SchemefulSite>() /* party_context */);
Matt Menke3ab9c7b2020-04-01 22:39:57113}
114
115IsolationInfo IsolationInfo::CreateTransient() {
Shuran Huang0e0aaa52020-12-02 22:24:54116 url::Origin opaque_origin;
117 return IsolationInfo(RequestType::kOther, opaque_origin, opaque_origin,
118 SiteForCookies(), false /* opaque_and_non_transient */,
119 base::nullopt /* party_context */);
Matt Menke3ab9c7b2020-04-01 22:39:57120}
121
122IsolationInfo IsolationInfo::CreateOpaqueAndNonTransient() {
123 url::Origin opaque_origin;
shivanigithub4e78015f592020-10-21 13:26:23124 return IsolationInfo(RequestType::kOther, opaque_origin, opaque_origin,
Shuran Huang0e0aaa52020-12-02 22:24:54125 SiteForCookies(), true /* opaque_and_non_transient */,
126 base::nullopt /* party_context */);
Matt Menke3ab9c7b2020-04-01 22:39:57127}
128
Shuran Huang0e0aaa52020-12-02 22:24:54129IsolationInfo IsolationInfo::Create(
130 RequestType request_type,
131 const url::Origin& top_frame_origin,
132 const url::Origin& frame_origin,
133 const SiteForCookies& site_for_cookies,
134 base::Optional<std::set<SchemefulSite>> party_context) {
shivanigithub4e78015f592020-10-21 13:26:23135 return IsolationInfo(request_type, top_frame_origin, frame_origin,
Shuran Huang0e0aaa52020-12-02 22:24:54136 site_for_cookies, false /* opaque_and_non_transient */,
137 std::move(party_context));
Matt Menke3ab9c7b2020-04-01 22:39:57138}
139
140IsolationInfo IsolationInfo::CreatePartial(
shivanigithub4e78015f592020-10-21 13:26:23141 RequestType request_type,
Matt Menke3ab9c7b2020-04-01 22:39:57142 const net::NetworkIsolationKey& network_isolation_key) {
143 if (!network_isolation_key.IsFullyPopulated())
144 return IsolationInfo();
145
Matt Menkef8d36fd2020-11-20 03:56:13146 // TODO(https://crbug.com/1148927): Use null origins in this case.
147 url::Origin top_frame_origin =
148 network_isolation_key.GetTopFrameSite()->site_as_origin_;
Matt Menke3ab9c7b2020-04-01 22:39:57149 url::Origin frame_origin;
Matt Menkee6e4f392020-10-08 11:41:29150 if (network_isolation_key.GetFrameSite().has_value()) {
Matt Menkef8d36fd2020-11-20 03:56:13151 frame_origin = network_isolation_key.GetFrameSite()->site_as_origin_;
shivanigithub4e78015f592020-10-21 13:26:23152 } else if (request_type == RequestType::kMainFrame) {
Matt Menke3ab9c7b2020-04-01 22:39:57153 frame_origin = top_frame_origin;
154 } else {
155 frame_origin = url::Origin();
156 }
157
158 bool opaque_and_non_transient = top_frame_origin.opaque() &&
159 frame_origin.opaque() &&
160 !network_isolation_key.IsTransient();
161
shivanigithub4e78015f592020-10-21 13:26:23162 return IsolationInfo(request_type, top_frame_origin, frame_origin,
Shuran Huang0e0aaa52020-12-02 22:24:54163 SiteForCookies(), opaque_and_non_transient,
164 base::nullopt /* party_context */);
Matt Menke3ab9c7b2020-04-01 22:39:57165}
166
167base::Optional<IsolationInfo> IsolationInfo::CreateIfConsistent(
shivanigithub4e78015f592020-10-21 13:26:23168 RequestType request_type,
Matt Menke3ab9c7b2020-04-01 22:39:57169 const base::Optional<url::Origin>& top_frame_origin,
170 const base::Optional<url::Origin>& frame_origin,
171 const SiteForCookies& site_for_cookies,
Shuran Huang0e0aaa52020-12-02 22:24:54172 bool opaque_and_non_transient,
173 base::Optional<std::set<SchemefulSite>> party_context) {
shivanigithub4e78015f592020-10-21 13:26:23174 if (!IsConsistent(request_type, top_frame_origin, frame_origin,
Shuran Huang0e0aaa52020-12-02 22:24:54175 site_for_cookies, opaque_and_non_transient,
176 party_context)) {
Matt Menke3ab9c7b2020-04-01 22:39:57177 return base::nullopt;
178 }
shivanigithub4e78015f592020-10-21 13:26:23179 return IsolationInfo(request_type, top_frame_origin, frame_origin,
Shuran Huang0e0aaa52020-12-02 22:24:54180 site_for_cookies, opaque_and_non_transient,
181 std::move(party_context));
Matt Menke3ab9c7b2020-04-01 22:39:57182}
183
184IsolationInfo IsolationInfo::CreateForRedirect(
185 const url::Origin& new_origin) const {
shivanigithub4e78015f592020-10-21 13:26:23186 if (request_type_ == RequestType::kOther)
Matt Menke3ab9c7b2020-04-01 22:39:57187 return *this;
188
shivanigithub4e78015f592020-10-21 13:26:23189 if (request_type_ == RequestType::kSubFrame) {
190 return IsolationInfo(request_type_, top_frame_origin_, new_origin,
Shuran Huang0e0aaa52020-12-02 22:24:54191 site_for_cookies_, opaque_and_non_transient_,
192 party_context_);
Matt Menke3ab9c7b2020-04-01 22:39:57193 }
194
shivanigithub4e78015f592020-10-21 13:26:23195 DCHECK_EQ(RequestType::kMainFrame, request_type_);
Shuran Huang0e0aaa52020-12-02 22:24:54196 DCHECK(!party_context_ || party_context_->empty());
shivanigithub4e78015f592020-10-21 13:26:23197 return IsolationInfo(request_type_, new_origin, new_origin,
Matt Menke3ab9c7b2020-04-01 22:39:57198 SiteForCookies::FromOrigin(new_origin),
Shuran Huang0e0aaa52020-12-02 22:24:54199 opaque_and_non_transient_, party_context_);
Matt Menke3ab9c7b2020-04-01 22:39:57200}
201
202bool IsolationInfo::IsEqualForTesting(const IsolationInfo& other) const {
shivanigithub4e78015f592020-10-21 13:26:23203 return (request_type_ == other.request_type_ &&
Matt Menke3ab9c7b2020-04-01 22:39:57204 top_frame_origin_ == other.top_frame_origin_ &&
205 frame_origin_ == other.frame_origin_ &&
206 network_isolation_key_ == other.network_isolation_key_ &&
207 opaque_and_non_transient_ == other.opaque_and_non_transient_ &&
Shuran Huang0e0aaa52020-12-02 22:24:54208 site_for_cookies_.IsEquivalent(other.site_for_cookies_) &&
209 party_context_ == other.party_context_);
Matt Menke3ab9c7b2020-04-01 22:39:57210}
211
212IsolationInfo::IsolationInfo(
shivanigithub4e78015f592020-10-21 13:26:23213 RequestType request_type,
Matt Menke3ab9c7b2020-04-01 22:39:57214 const base::Optional<url::Origin>& top_frame_origin,
215 const base::Optional<url::Origin>& frame_origin,
216 const SiteForCookies& site_for_cookies,
Shuran Huang0e0aaa52020-12-02 22:24:54217 bool opaque_and_non_transient,
218 base::Optional<std::set<SchemefulSite>> party_context)
shivanigithub4e78015f592020-10-21 13:26:23219 : request_type_(request_type),
Matt Menke3ab9c7b2020-04-01 22:39:57220 top_frame_origin_(top_frame_origin),
221 frame_origin_(frame_origin),
222 network_isolation_key_(
Matt Menkef8d36fd2020-11-20 03:56:13223 !top_frame_origin
224 ? NetworkIsolationKey()
225 : NetworkIsolationKey(SchemefulSite(*top_frame_origin),
226 SchemefulSite(*frame_origin),
227 opaque_and_non_transient)),
Matt Menke3ab9c7b2020-04-01 22:39:57228 site_for_cookies_(site_for_cookies),
Shuran Huang0e0aaa52020-12-02 22:24:54229 opaque_and_non_transient_(opaque_and_non_transient),
230 party_context_(party_context.has_value() &&
231 party_context->size() > kPartyContextMaxSize
232 ? base::nullopt
233 : party_context) {
shivanigithub4e78015f592020-10-21 13:26:23234 DCHECK(IsConsistent(request_type_, top_frame_origin_, frame_origin_,
Shuran Huang0e0aaa52020-12-02 22:24:54235 site_for_cookies_, opaque_and_non_transient_,
236 party_context_));
Matt Menke3ab9c7b2020-04-01 22:39:57237}
238
239} // namespace net