blob: cfcba14ea721b74a2082be24c498da119f93de71 [file] [log] [blame]
mkwst9f2cc892015-07-22 06:03:251// Copyright 2015 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#ifndef URL_ORIGIN_H_
6#define URL_ORIGIN_H_
7
avic0c60312015-12-21 21:03:508#include <stdint.h>
9
mkwst9f2cc892015-07-22 06:03:2510#include <string>
11
Staphany Park6fd74a22018-12-04 21:15:4112#include "base/component_export.h"
Lukasz Anforowicz3d58b9392018-01-05 20:56:2213#include "base/debug/alias.h"
Daniel Cheng62ff0182018-08-25 07:59:3314#include "base/optional.h"
mkwst9f2cc892015-07-22 06:03:2515#include "base/strings/string16.h"
mkwstd8335d982015-07-25 05:18:4816#include "base/strings/string_piece.h"
Daniel Cheng62ff0182018-08-25 07:59:3317#include "base/strings/string_util.h"
18#include "base/unguessable_token.h"
Nasko Oskovd9e41d52018-09-27 23:12:4219#include "ipc/ipc_param_traits.h"
mkwst9f2cc892015-07-22 06:03:2520#include "url/scheme_host_port.h"
21#include "url/third_party/mozilla/url_parse.h"
22#include "url/url_canon.h"
23#include "url/url_constants.h"
mkwst9f2cc892015-07-22 06:03:2524
25class GURL;
26
Nasko Oskov99445acd2018-10-10 16:46:0027namespace blink {
28class SecurityOrigin;
29} // namespace blink
30
Nasko Oskov9277dfc2018-09-17 23:20:5431namespace ipc_fuzzer {
32template <class T>
33struct FuzzTraits;
34} // namespace ipc_fuzzer
35
Nasko Oskovd9e41d52018-09-27 23:12:4236namespace mojo {
37template <typename DataViewType, typename T>
38struct StructTraits;
Nasko Oskov99445acd2018-10-10 16:46:0039struct UrlOriginAdapter;
Nasko Oskovd9e41d52018-09-27 23:12:4240} // namespace mojo
41
mkwst9f2cc892015-07-22 06:03:2542namespace url {
43
Nasko Oskovd9e41d52018-09-27 23:12:4244namespace mojom {
45class OriginDataView;
46} // namespace mojom
47
Daniel Cheng62ff0182018-08-25 07:59:3348// Per https://html.spec.whatwg.org/multipage/origin.html#origin, an origin is
49// either:
50// - a tuple origin of (scheme, host, port) as described in RFC 6454.
Nasko Oskov9277dfc2018-09-17 23:20:5451// - an opaque origin with an internal value, and a memory of the tuple origin
52// from which it was derived.
mkwst9f2cc892015-07-22 06:03:2553//
54// TL;DR: If you need to make a security-relevant decision, use 'url::Origin'.
55// If you only need to extract the bits of a URL which are relevant for a
56// network connection, use 'url::SchemeHostPort'.
57//
58// STL;SDR: If you aren't making actual network connections, use 'url::Origin'.
59//
mkwst9f2cc892015-07-22 06:03:2560// This class ought to be used when code needs to determine if two resources
61// are "same-origin", and when a canonical serialization of an origin is
Daniel Cheng62ff0182018-08-25 07:59:3362// required. Note that the canonical serialization of an origin *must not* be
63// used to determine if two resources are same-origin.
64//
65// A tuple origin, like 'SchemeHostPort', is composed of a tuple of (scheme,
66// host, port), but contains a number of additional concepts which make it
67// appropriate for use as a security boundary and access control mechanism
68// between contexts. Two tuple origins are same-origin if the tuples are equal.
69// A tuple origin may also be re-created from its serialization.
70//
Nasko Oskov9277dfc2018-09-17 23:20:5471// An opaque origin has an internal globally unique identifier. When creating a
72// new opaque origin from a URL, a fresh globally unique identifier is
73// generated. However, if an opaque origin is copied or moved, the internal
74// globally unique identifier is preserved. Two opaque origins are same-origin
75// iff the globally unique identifiers match. Unlike tuple origins, an opaque
76// origin cannot be re-created from its serialization, which is always the
77// string "null".
Daniel Cheng62ff0182018-08-25 07:59:3378//
79// IMPORTANT: Since opaque origins always serialize as the string "null", it is
80// *never* safe to use the serialization for security checks!
81//
82// A tuple origin and an opaque origin are never same-origin.
mkwst9f2cc892015-07-22 06:03:2583//
84// There are a few subtleties to note:
85//
Nasko Oskov9277dfc2018-09-17 23:20:5486// * A default constructed Origin is opaque, with no precursor origin.
Daniel Cheng62ff0182018-08-25 07:59:3387//
88// * Invalid and non-standard GURLs are parsed as opaque origins. This includes
mkwst9f2cc892015-07-22 06:03:2589// non-hierarchical URLs like 'data:text/html,...' and 'javascript:alert(1)'.
90//
91// * GURLs with schemes of 'filesystem' or 'blob' parse the origin out of the
92// internals of the URL. That is, 'filesystem:https://example.com/temporary/f'
93// is parsed as ('https', 'example.com', 443).
94//
mkwst9f2cc892015-07-22 06:03:2595// * GURLs with a 'file' scheme are tricky. They are parsed as ('file', '', 0),
96// but their behavior may differ from embedder to embedder.
Daniel Cheng62ff0182018-08-25 07:59:3397// TODO(dcheng): This behavior is not consistent with Blink's notion of file
98// URLs, which always creates an opaque origin.
mkwst9f2cc892015-07-22 06:03:2599//
100// * The host component of an IPv6 address includes brackets, just like the URL
101// representation.
102//
103// Usage:
104//
105// * Origins are generally constructed from an already-canonicalized GURL:
106//
107// GURL url("https://example.com/");
Daniel Vogelheimdf4cf9e2018-06-14 11:42:40108// url::Origin origin = Origin::Create(url);
mkwst9f2cc892015-07-22 06:03:25109// origin.scheme(); // "https"
110// origin.host(); // "example.com"
111// origin.port(); // 443
Chris Palmerab5e5b52018-09-28 19:19:30112// origin.opaque(); // false
mkwst9f2cc892015-07-22 06:03:25113//
114// * To answer the question "Are |this| and |that| "same-origin" with each
115// other?", use |Origin::IsSameOriginWith|:
116//
117// if (this.IsSameOriginWith(that)) {
118// // Amazingness goes here.
119// }
Staphany Park6fd74a22018-12-04 21:15:41120class COMPONENT_EXPORT(URL) Origin {
mkwst9f2cc892015-07-22 06:03:25121 public:
Nasko Oskov9277dfc2018-09-17 23:20:54122 // Creates an opaque Origin with a nonce that is different from all previously
123 // existing origins.
mkwst9f2cc892015-07-22 06:03:25124 Origin();
125
126 // Creates an Origin from |url|, as described at
127 // https://url.spec.whatwg.org/#origin, with the following additions:
128 //
Daniel Cheng62ff0182018-08-25 07:59:33129 // 1. If |url| is invalid or non-standard, an opaque Origin is constructed.
mkwst9f2cc892015-07-22 06:03:25130 // 2. 'filesystem' URLs behave as 'blob' URLs (that is, the origin is parsed
131 // out of everything in the URL which follows the scheme).
132 // 3. 'file' URLs all parse as ("file", "", 0).
Daniel Cheng88186bd52017-10-20 08:14:46133 static Origin Create(const GURL& url);
mkwst9f2cc892015-07-22 06:03:25134
Nasko Oskov9277dfc2018-09-17 23:20:54135 // Creates an Origin for the resource |url| as if it were requested
136 // from the context of |base_origin|. If |url| is standard
137 // (in the sense that it embeds a complete origin, like http/https),
138 // this returns the same value as would Create().
139 //
140 // If |url| is "about:blank", this returns a copy of |base_origin|.
141 //
142 // Otherwise, returns a new opaque origin derived from |base_origin|.
143 // In this case, the resulting opaque origin will inherit the tuple
144 // (or precursor tuple) of |base_origin|, but will not be same origin
145 // with |base_origin|, even if |base_origin| is already opaque.
146 static Origin Resolve(const GURL& url, const Origin& base_origin);
147
John Melloref62bce2017-10-04 11:25:33148 // Copyable and movable.
Daniel Cheng6ae11ad72017-10-17 20:42:33149 Origin(const Origin&);
150 Origin& operator=(const Origin&);
151 Origin(Origin&&);
152 Origin& operator=(Origin&&);
John Melloref62bce2017-10-04 11:25:33153
Takashi Toyoshima5641d7552018-02-09 08:57:52154 // Creates an Origin from a |scheme|, |host|, and |port|. All the parameters
Nasko Oskov9277dfc2018-09-17 23:20:54155 // must be valid and canonicalized. Returns nullopt if any parameter is not
156 // canonical, or if all the parameters are empty.
mkwstd8335d982015-07-25 05:18:48157 //
158 // This constructor should be used in order to pass 'Origin' objects back and
159 // forth over IPC (as transitioning through GURL would risk potentially
160 // dangerous recanonicalization); other potential callers should prefer the
161 // 'GURL'-based constructor.
Nasko Oskov9277dfc2018-09-17 23:20:54162 static base::Optional<Origin> UnsafelyCreateTupleOriginWithoutNormalization(
mkwstd8335d982015-07-25 05:18:48163 base::StringPiece scheme,
164 base::StringPiece host,
Takashi Toyoshima5641d7552018-02-09 08:57:52165 uint16_t port);
mkwstd8335d982015-07-25 05:18:48166
csharrisonedf893f2016-10-12 01:42:56167 // Creates an origin without sanity checking that the host is canonicalized.
168 // This should only be used when converting between already normalized types,
csharrisonf07ac3c2016-12-13 04:15:02169 // and should NOT be used for IPC. Method takes std::strings for use with move
170 // operators to avoid copies.
Takashi Toyoshima5641d7552018-02-09 08:57:52171 static Origin CreateFromNormalizedTuple(std::string scheme,
172 std::string host,
173 uint16_t port);
jww908428c2016-10-26 21:51:46174
mkwst9f2cc892015-07-22 06:03:25175 ~Origin();
176
Daniel Cheng62ff0182018-08-25 07:59:33177 // For opaque origins, these return ("", "", 0).
178 const std::string& scheme() const {
Chris Palmerab5e5b52018-09-28 19:19:30179 return !opaque() ? tuple_.scheme() : base::EmptyString();
Daniel Cheng62ff0182018-08-25 07:59:33180 }
181 const std::string& host() const {
Chris Palmerab5e5b52018-09-28 19:19:30182 return !opaque() ? tuple_.host() : base::EmptyString();
Daniel Cheng62ff0182018-08-25 07:59:33183 }
Chris Palmerab5e5b52018-09-28 19:19:30184 uint16_t port() const { return !opaque() ? tuple_.port() : 0; }
mkwst9f2cc892015-07-22 06:03:25185
Chris Palmerab5e5b52018-09-28 19:19:30186 bool opaque() const { return nonce_.has_value(); }
mkwst9f2cc892015-07-22 06:03:25187
188 // An ASCII serialization of the Origin as per Section 6.2 of RFC 6454, with
189 // the addition that all Origins with a 'file' scheme serialize to "file://".
190 std::string Serialize() const;
191
Nasko Oskov9277dfc2018-09-17 23:20:54192 // Two non-opaque Origins are "same-origin" if their schemes, hosts, and ports
193 // are exact matches. Two opaque origins are same-origin only if their
194 // internal nonce values match. A non-opaque origin is never same-origin with
195 // an opaque origin.
mkwst9f2cc892015-07-22 06:03:25196 bool IsSameOriginWith(const Origin& other) const;
Nasko Oskov9277dfc2018-09-17 23:20:54197 bool operator==(const Origin& other) const { return IsSameOriginWith(other); }
198 bool operator!=(const Origin& other) const {
199 return !IsSameOriginWith(other);
200 }
201
Nasko Oskov97e305f2019-01-05 03:52:10202 // This method returns true for any |url| which if navigated to could result
203 // in an origin compatible with |this|.
204 bool CanBeDerivedFrom(const GURL& url) const;
205
Nasko Oskov9277dfc2018-09-17 23:20:54206 // Get the scheme, host, and port from which this origin derives. For
207 // a tuple Origin, this gives the same values as calling scheme(), host()
208 // and port(). For an opaque Origin that was created by calling
209 // Origin::DeriveNewOpaqueOrigin() on a precursor or Origin::Resolve(),
210 // this returns the tuple inherited from the precursor.
211 //
212 // If this Origin is opaque and was created via the default constructor or
213 // Origin::Create(), the precursor origin is unknown.
214 //
215 // Use with great caution: opaque origins should generally not inherit
216 // privileges from the origins they derive from. However, in some cases
217 // (such as restrictions on process placement, or determining the http lock
218 // icon) this information may be relevant to ensure that entering an
219 // opaque origin does not grant privileges initially denied to the original
220 // non-opaque origin.
221 //
222 // This method has a deliberately obnoxious name to prompt caution in its use.
223 const SchemeHostPort& GetTupleOrPrecursorTupleIfOpaque() const {
224 return tuple_;
mek0126c132016-02-17 23:50:59225 }
mkwst9f2cc892015-07-22 06:03:25226
csharrison048bee12016-10-04 00:08:21227 // Efficiently returns what GURL(Serialize()) would without re-parsing the
228 // URL. This can be used for the (rare) times a GURL representation is needed
229 // for an Origin.
230 // Note: The returned URL will not necessarily be serialized to the same value
231 // as the Origin would. The GURL will have an added "/" path for Origins with
232 // valid SchemeHostPorts and file Origins.
Charles Harrisonc5f8c91b2017-08-22 18:08:24233 //
234 // Try not to use this method under normal circumstances, as it loses type
235 // information. Downstream consumers can mistake the returned GURL with a full
236 // URL (e.g. with a path component).
csharrison048bee12016-10-04 00:08:21237 GURL GetURL() const;
238
Chris Palmerab5e5b52018-09-28 19:19:30239 // Same as GURL::DomainIs. If |this| origin is opaque, then returns false.
Charles Harrison81dc2fb2017-08-30 23:41:12240 bool DomainIs(base::StringPiece canonical_domain) const;
pkalinnikov054f4032016-08-31 10:54:17241
nick1466c842015-11-25 20:08:06242 // Allows Origin to be used as a key in STL (for example, a std::set or
mkwst9f2cc892015-07-22 06:03:25243 // std::map).
244 bool operator<(const Origin& other) const;
245
Daniel Cheng62ff0182018-08-25 07:59:33246 // Creates a new opaque origin that is guaranteed to be cross-origin to all
247 // currently existing origins. An origin created by this method retains its
248 // identity across copies. Copies are guaranteed to be same-origin to each
249 // other, e.g.
250 //
Nasko Oskov9277dfc2018-09-17 23:20:54251 // url::Origin page = Origin::Create(GURL("http://example.com"))
252 // url::Origin a = page.DeriveNewOpaqueOrigin();
253 // url::Origin b = page.DeriveNewOpaqueOrigin();
Daniel Cheng62ff0182018-08-25 07:59:33254 // url::Origin c = a;
255 // url::Origin d = b;
256 //
257 // |a| and |c| are same-origin, since |c| was copied from |a|. |b| and |d| are
258 // same-origin as well, since |d| was copied from |b|. All other combinations
259 // of origins are considered cross-origin, e.g. |a| is cross-origin to |b| and
260 // |d|, |b| is cross-origin to |a| and |c|, |c| is cross-origin to |b| and
261 // |d|, and |d| is cross-origin to |a| and |c|.
Nasko Oskov9277dfc2018-09-17 23:20:54262 Origin DeriveNewOpaqueOrigin() const;
263
Nasko Oskov1ed4e8f2019-02-13 01:39:19264 // Creates a string representation of the object that can be used for logging
265 // and debugging. It serializes the internal state, such as the nonce value
266 // and precursor information.
267 std::string GetDebugString() const;
268
Nasko Oskov9277dfc2018-09-17 23:20:54269 private:
Nasko Oskov99445acd2018-10-10 16:46:00270 friend class blink::SecurityOrigin;
Nasko Oskov9277dfc2018-09-17 23:20:54271 friend class OriginTest;
Nasko Oskov99445acd2018-10-10 16:46:00272 friend struct mojo::UrlOriginAdapter;
Nasko Oskov9277dfc2018-09-17 23:20:54273 friend struct ipc_fuzzer::FuzzTraits<Origin>;
Nasko Oskovd9e41d52018-09-27 23:12:42274 friend struct mojo::StructTraits<url::mojom::OriginDataView, url::Origin>;
Nasko Oskov99445acd2018-10-10 16:46:00275 friend IPC::ParamTraits<url::Origin>;
Staphany Park6fd74a22018-12-04 21:15:41276 friend COMPONENT_EXPORT(URL) std::ostream& operator<<(std::ostream& out,
277 const Origin& origin);
Nasko Oskov9277dfc2018-09-17 23:20:54278
279 // Origin::Nonce is a wrapper around base::UnguessableToken that generates
280 // the random value only when the value is first accessed. The lazy generation
281 // allows Origin to be default-constructed quickly, without spending time
282 // in random number generation.
Daniel Cheng62ff0182018-08-25 07:59:33283 //
Nasko Oskov9277dfc2018-09-17 23:20:54284 // TODO(nick): Should this optimization move into UnguessableToken, once it no
285 // longer treats the Null case specially?
Staphany Park6fd74a22018-12-04 21:15:41286 class COMPONENT_EXPORT(URL) Nonce {
Nasko Oskov9277dfc2018-09-17 23:20:54287 public:
288 // Creates a nonce to hold a newly-generated UnguessableToken. The actual
289 // token value will be generated lazily.
290 Nonce();
Daniel Cheng62ff0182018-08-25 07:59:33291
Nasko Oskov9277dfc2018-09-17 23:20:54292 // Creates a nonce to hold an already-generated UnguessableToken value. This
293 // constructor should only be used for IPC serialization and testing --
294 // regular code should never need to touch the UnguessableTokens directly,
295 // and the default constructor is faster.
296 explicit Nonce(const base::UnguessableToken& token);
Daniel Cheng62ff0182018-08-25 07:59:33297
Nasko Oskov9277dfc2018-09-17 23:20:54298 // Accessor, which lazily initializes the underlying |token_| member.
299 const base::UnguessableToken& token() const;
Daniel Cheng62ff0182018-08-25 07:59:33300
Nasko Oskov9277dfc2018-09-17 23:20:54301 // Do not use in cases where lazy initialization is expected! This
302 // accessor does not initialize the |token_| member.
303 const base::UnguessableToken& raw_token() const;
304
305 // Copyable and movable. Copying a Nonce triggers lazy-initialization,
306 // moving it does not.
307 Nonce(const Nonce&);
308 Nonce& operator=(const Nonce&);
309 Nonce(Nonce&&);
310 Nonce& operator=(Nonce&&);
311
312 // Note that operator<, used by maps type containers, will trigger |token_|
313 // lazy-initialization. Equality comparisons do not.
314 bool operator<(const Nonce& other) const;
315 bool operator==(const Nonce& other) const;
316 bool operator!=(const Nonce& other) const;
317
318 private:
319 friend class OriginTest;
320
321 // mutable to support lazy generation.
322 mutable base::UnguessableToken token_;
323 };
324
325 // This needs to be friended within Origin as well, since Nonce is a private
326 // nested class of Origin.
Staphany Park6fd74a22018-12-04 21:15:41327 friend COMPONENT_EXPORT(URL) std::ostream& operator<<(std::ostream& out,
328 const Nonce& nonce);
Nasko Oskov9277dfc2018-09-17 23:20:54329
330 // Creates an origin without sanity checking that the host is canonicalized.
331 // This should only be used when converting between already normalized types,
332 // and should NOT be used for IPC. Method takes std::strings for use with move
333 // operators to avoid copies.
334 static Origin CreateOpaqueFromNormalizedPrecursorTuple(
335 std::string precursor_scheme,
336 std::string precursor_host,
337 uint16_t precursor_port,
338 const Nonce& nonce);
339
340 // Creates an opaque Origin with the identity given by |nonce|, and an
341 // optional precursor origin given by |precursor_scheme|, |precursor_host| and
342 // |precursor_port|. Returns nullopt if any parameter is not canonical. When
343 // the precursor is unknown, the precursor parameters should be ("", "", 0).
344 //
345 // This factory method should be used in order to pass opaque Origin objects
346 // back and forth over IPC (as transitioning through GURL would risk
347 // potentially dangerous recanonicalization).
348 static base::Optional<Origin> UnsafelyCreateOpaqueOriginWithoutNormalization(
349 base::StringPiece precursor_scheme,
350 base::StringPiece precursor_host,
351 uint16_t precursor_port,
352 const Nonce& nonce);
353
354 // Constructs a non-opaque tuple origin. |tuple| must be valid.
Takashi Toyoshima5641d7552018-02-09 08:57:52355 explicit Origin(SchemeHostPort tuple);
mkwstd8335d982015-07-25 05:18:48356
Nasko Oskov9277dfc2018-09-17 23:20:54357 // Constructs an opaque origin derived from the |precursor| tuple, with the
358 // given |nonce|.
359 Origin(const Nonce& nonce, SchemeHostPort precursor);
360
Chris Palmerab5e5b52018-09-28 19:19:30361 // Get the nonce associated with this origin, if it is opaque. This should be
Nasko Oskov9277dfc2018-09-17 23:20:54362 // used only when trying to send an Origin across an IPC pipe.
363 base::Optional<base::UnguessableToken> GetNonceForSerialization() const;
364
365 // The tuple is used for both tuple origins (e.g. https://example.com:80), as
366 // well as for opaque origins, where it tracks the tuple origin from which
367 // the opaque origin was initially derived (we call this the "precursor"
368 // origin).
mkwst9f2cc892015-07-22 06:03:25369 SchemeHostPort tuple_;
Daniel Cheng62ff0182018-08-25 07:59:33370
371 // The nonce is used for maintaining identity of an opaque origin. This
Nasko Oskov9277dfc2018-09-17 23:20:54372 // nonce is preserved when an opaque origin is copied or moved. An Origin
373 // is considered opaque if and only if |nonce_| holds a value.
374 base::Optional<Nonce> nonce_;
mkwst9f2cc892015-07-22 06:03:25375};
376
Nasko Oskov9277dfc2018-09-17 23:20:54377// Pretty-printers for logging. These expose the internal state of the nonce.
Staphany Park6fd74a22018-12-04 21:15:41378COMPONENT_EXPORT(URL)
379std::ostream& operator<<(std::ostream& out, const Origin& origin);
380COMPONENT_EXPORT(URL)
381std::ostream& operator<<(std::ostream& out, const Origin::Nonce& origin);
palmer5c437bcc2016-02-03 23:21:36382
Staphany Park6fd74a22018-12-04 21:15:41383COMPONENT_EXPORT(URL) bool IsSameOriginWith(const GURL& a, const GURL& b);
mkwst9f2cc892015-07-22 06:03:25384
Lukasz Anforowicz3d58b9392018-01-05 20:56:22385// DEBUG_ALIAS_FOR_ORIGIN(var_name, origin) copies |origin| into a new
386// stack-allocated variable named |<var_name>|. This helps ensure that the
387// value of |origin| gets preserved in crash dumps.
388#define DEBUG_ALIAS_FOR_ORIGIN(var_name, origin) \
Daniel Chengafbf6352018-04-24 23:59:25389 DEBUG_ALIAS_FOR_CSTR(var_name, (origin).Serialize().c_str(), 128)
Lukasz Anforowicz3d58b9392018-01-05 20:56:22390
mkwst9f2cc892015-07-22 06:03:25391} // namespace url
392
qyearsley2bc727d2015-08-14 20:17:15393#endif // URL_ORIGIN_H_