forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcors_util.cc
162 lines (142 loc) · 7.06 KB
/
cors_util.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/common/cors_util.h"
#include <utility>
#include "base/strings/string_number_conversions.h"
#include "build/chromeos_buildflags.h"
#include "content/public/common/url_constants.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/url_pattern_set.h"
namespace extensions {
namespace {
uint16_t GetEffectivePort(const std::string& port_string) {
int port_int = 0;
bool success = base::StringToInt(port_string, &port_int);
// The URLPattern should verify that |port| is a number or "*", so conversion
// should never fail.
DCHECK(success) << port_string;
return port_int;
}
void AddURLPatternSetToList(
const URLPatternSet& pattern_set,
std::vector<network::mojom::CorsOriginPatternPtr>* list,
network::mojom::CorsOriginAccessMatchPriority priority) {
static const char* const kSchemes[] = {
content::kChromeUIScheme,
#if BUILDFLAG(IS_CHROMEOS_ASH)
content::kExternalFileScheme,
#endif
extensions::kExtensionScheme,
url::kFileScheme,
url::kFtpScheme,
url::kHttpScheme,
url::kHttpsScheme,
};
for (const URLPattern& pattern : pattern_set) {
for (const char* const scheme : kSchemes) {
if (!pattern.MatchesScheme(scheme))
continue;
network::mojom::CorsDomainMatchMode domain_match_mode =
pattern.match_subdomains()
? network::mojom::CorsDomainMatchMode::kAllowSubdomains
: network::mojom::CorsDomainMatchMode::kDisallowSubdomains;
network::mojom::CorsPortMatchMode port_match_mode =
(pattern.port() == "*")
? network::mojom::CorsPortMatchMode::kAllowAnyPort
: network::mojom::CorsPortMatchMode::kAllowOnlySpecifiedPort;
uint16_t port =
(port_match_mode ==
network::mojom::CorsPortMatchMode::kAllowOnlySpecifiedPort)
? GetEffectivePort(pattern.port())
: 0u;
list->push_back(network::mojom::CorsOriginPattern::New(
scheme, pattern.host(), port, domain_match_mode, port_match_mode,
priority));
}
}
}
} // namespace
std::vector<network::mojom::CorsOriginPatternPtr>
CreateCorsOriginAccessAllowList(const Extension& extension) {
std::vector<network::mojom::CorsOriginPatternPtr> allow_list;
// Permissions declared by the extension.
URLPatternSet origin_permissions =
extension.permissions_data()->GetEffectiveHostPermissions();
AddURLPatternSetToList(
origin_permissions, &allow_list,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
// Hosts exempted from the enterprise policy blocklist. This allows
// enterprises to add "carve outs" for hosts extensions may be allowed to run
// on. For instance, an enterprise may block "https://*.restricted.example/*",
// but allow "https://not-sensitive.restricted.example". In order for this to
// work, the enterprise allowlist has higher priority than the enterprise
// blocklist.
// The set intersection is necessary to prevent an enterprise policy from
// granting a host permission the extension didn't ask for.
URLPatternSet policy_allowed_host_patterns =
URLPatternSet::CreateIntersection(
extension.permissions_data()->policy_allowed_hosts(),
origin_permissions, URLPatternSet::IntersectionBehavior::kDetailed);
// TODO(https://crbug.com/1268198): For now, there is (theoretically) no
// overlap between user-blocked sites and user-allowed sites. This means that,
// unlike enterprise policy above, we don't need to add in user-allowed sites
// here (they should already be granted to the extension, and won't be blocked
// by user-blocked sites). We should either guarantee this is the case (with
// DCHECKs) or change this to allow "carve outs" in user host permissions.
// The latter would likely require adding more knobs to the network layer
// since we'd need a more complex hierarchy.
AddURLPatternSetToList(
policy_allowed_host_patterns, &allow_list,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
return allow_list;
}
std::vector<network::mojom::CorsOriginPatternPtr>
CreateCorsOriginAccessBlockList(const Extension& extension) {
std::vector<network::mojom::CorsOriginPatternPtr> block_list;
// Hosts blocked by enterprise policy.
AddURLPatternSetToList(
extension.permissions_data()->policy_blocked_hosts(), &block_list,
network::mojom::CorsOriginAccessMatchPriority::kLowPriority);
// Add hosts blocked by the user. Unintuitively, these are granted *higher*
// precedence than enterprise blocked sites. This isn't because they are
// conceptually more important, but rather because we need them to take
// priority over enterprise allowed sites. Consider the following scenario:
// - An enterprise blocks https://*.restricted.example.
// - The enterprise allows https://non-sensitive.restricted.example
// - The user blocks https://non-sensitive.restricted.example
// Here, the extension should *not* be allowed to run on
// https://non-sensitive.restricted.example; the enterprise said it *may*, but
// the user then denies it access.
// Note also that enterprise extensions are exempt from user host
// restrictions, so there's no risk of users blocking enterprise extensions
// from running on sites.
// We add user host restrictions with the same priority level as enterprise
// host allowances; when a block rule and an allow rule have the same
// priority, the blocking rule wins. We don't add these with "High" priority
// in order to keep that reserved for browser-defined restrictions.
// TODO(https://crbug.com/1268198): This is a pretty tenuous setup. We may
// just need to plumb more information to the network service.
AddURLPatternSetToList(
extension.permissions_data()->GetUserBlockedHosts(), &block_list,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
GURL webstore_launch_url = extension_urls::GetWebstoreLaunchURL();
block_list.push_back(network::mojom::CorsOriginPattern::New(
webstore_launch_url.scheme(), webstore_launch_url.host(), /*port=*/0,
network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kHighPriority));
GURL new_webstore_launch_url = extension_urls::GetNewWebstoreLaunchURL();
block_list.push_back(network::mojom::CorsOriginPattern::New(
new_webstore_launch_url.scheme(), new_webstore_launch_url.host(),
/*port=*/0, network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kHighPriority));
// TODO(devlin): Should we also block the webstore update URL here? See
// https://crbug.com/826946 for a related instance.
return block_list;
}
} // namespace extensions