1 // Copyright (c) 2017 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 #ifndef CONTENT_BROWSER_ISOLATED_ORIGIN_UTIL_H_
5 #define CONTENT_BROWSER_ISOLATED_ORIGIN_UTIL_H_
6 
7 #include <string>
8 
9 #include "base/gtest_prod_util.h"
10 #include "base/strings/string_util.h"
11 #include "content/common/content_export.h"
12 #include "url/origin.h"
13 
14 namespace content {
15 
16 // This class holds isolated origin patterns, providing support for double
17 // wildcard origins, e.g. https://[*.]foo.com indicates that all domains under
18 // foo.com are to be treated as if they are distinct isolated
19 // origins. Non-wildcard origins to be isolated are also supported, e.g.
20 // https://bar.com.
21 class CONTENT_EXPORT IsolatedOriginPattern {
22  public:
23   explicit IsolatedOriginPattern(base::StringPiece pattern);
24   explicit IsolatedOriginPattern(const url::Origin& origin);
25   ~IsolatedOriginPattern();
26 
27   // Copying and moving supported.
28   IsolatedOriginPattern(const IsolatedOriginPattern& other);
29   IsolatedOriginPattern& operator=(const IsolatedOriginPattern& other);
30 
31   IsolatedOriginPattern(IsolatedOriginPattern&& other);
32   IsolatedOriginPattern& operator=(IsolatedOriginPattern&& other);
33 
34   bool operator==(const IsolatedOriginPattern& other) const {
35     // |pattern_| is deliberately not considered during equality comparison as
36     // it stores the pattern as supplied at construction time, before
37     // normalisation. This leads to erroneous cases of mismatch where
38     // IsolatedOriginPattern("foo.com") and IsolatedOriginPattern("foo.com/")
39     // will fail equality comparison, despite both resolving to the same origin.
40     return origin_ == other.origin_ &&
41            isolate_all_subdomains_ == other.isolate_all_subdomains_ &&
42            is_valid_ == other.is_valid_;
43   }
44 
45   // Returns the url::Origin corresponding to the pattern supplied at
46   // construction time or via a call to Parse. In the event of parsing failure
47   // this oriqin will be opaque.
origin()48   const url::Origin& origin() const { return origin_; }
49 
50   // True if the supplied pattern was of the form https://[*.]foo.com,
51   // indicating all subdomains of foo.com are to be isolated.
isolate_all_subdomains()52   bool isolate_all_subdomains() const { return isolate_all_subdomains_; }
53 
54   // Return the original pattern used to construct this instance.
pattern()55   const base::StringPiece pattern() const { return pattern_; }
56 
57   // Return if this origin is valid for isolation purposes.
is_valid()58   bool is_valid() const { return is_valid_; }
59 
60  private:
61   friend class ChildProcessSecurityPolicyTest;
62   FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest,
63                            IsolatedOriginPattern);
64 
65   // Checks if |pattern| is a wildcard pattern, checks the scheme is one of
66   // {http, https} and constructs a url::Origin() that can be retrieved if
67   // parsing is successful. Returns true on successful parsing.
68   bool Parse(const base::StringPiece& pattern);
69 
70   std::string pattern_;
71   url::Origin origin_;
72   bool isolate_all_subdomains_;
73   bool is_valid_;
74 };
75 
76 class CONTENT_EXPORT IsolatedOriginUtil {
77  public:
78   // Checks whether |origin| matches the isolated origin specified by
79   // |isolated_origin|.  Subdomains are considered to match isolated origins,
80   // so this will be true if
81   // (1) |origin| has the same scheme, host, and port as |isolated_origin|, or
82   // (2) |origin| has the same scheme and port as |isolated_origin|, and its
83   //     host is a subdomain of |isolated_origin|'s host.
84   // This does not consider site URLs, which don't care about port.
85   //
86   // For example, if |isolated_origin| is https://isolated.foo.com, this will
87   // return true if |origin| is https://isolated.foo.com or
88   // https://bar.isolated.foo.com, but it will return false for an |origin| of
89   // https://unisolated.foo.com or https://foo.com.
90   static bool DoesOriginMatchIsolatedOrigin(const url::Origin& origin,
91                                             const url::Origin& isolated_origin);
92 
93   // Check if |origin| is a valid isolated origin.  Invalid isolated origins
94   // include unique origins, origins that don't have an HTTP or HTTPS scheme,
95   // and origins without a valid registry-controlled domain.  IP addresses are
96   // allowed.
97   static bool IsValidIsolatedOrigin(const url::Origin& origin);
98 
99   // Returns |true| if the two arguments have the same scheme and port, and
100   // |sub_origin|'s host is a strict subdomain of |base_origin|'s.
101   static bool IsStrictSubdomain(const url::Origin& sub_origin,
102                                 const url::Origin& base_origin);
103 };
104 
105 }  // namespace content
106 
107 #endif  // CONTENT_BROWSER_ISOLATED_ORIGIN_UTIL_H_
108