1 // Copyright (c) 2014 Intel Corporation. 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.
5 #include "xwalk/application/common/security_policy.h"
10 #include "content/public/browser/render_process_host.h"
11 #include "xwalk/application/browser/application.h"
12 #include "xwalk/application/common/application_manifest_constants.h"
13 #include "xwalk/application/common/constants.h"
14 #include "xwalk/application/common/manifest_handlers/csp_handler.h"
15 #include "xwalk/application/common/manifest_handlers/navigation_handler.h"
16 #include "xwalk/application/common/manifest_handlers/warp_handler.h"
17 #include "xwalk/runtime/common/xwalk_common_messages.h"
21 namespace keys = application_manifest_keys;
22 namespace widget_keys = application_widget_keys;
24 namespace application {
27 const char kAsterisk[] = "*";
29 const char kDirectiveValueSelf[] = "'self'";
30 const char kDirectiveValueNone[] = "'none'";
32 const char kDirectiveNameDefault[] = "default-src";
33 const char kDirectiveNameScript[] = "script-src";
34 const char kDirectiveNameStyle[] = "style-src";
35 const char kDirectiveNameObject[] = "object-src";
38 // default-src * ; script-src 'self' ; style-src 'self' ; object-src 'none'
39 CSPInfo* GetDefaultCSPInfo() {
40 static CSPInfo default_csp_info;
41 if (default_csp_info.GetDirectives().empty()) {
42 std::vector<std::string> directive_all;
43 std::vector<std::string> directive_self;
44 std::vector<std::string> directive_none;
45 directive_all.push_back(kAsterisk);
46 directive_self.push_back(kDirectiveValueSelf);
47 directive_none.push_back(kDirectiveValueNone);
49 default_csp_info.SetDirective(kDirectiveNameDefault, directive_all);
50 default_csp_info.SetDirective(kDirectiveNameScript, directive_self);
51 default_csp_info.SetDirective(kDirectiveNameStyle, directive_self);
52 default_csp_info.SetDirective(kDirectiveNameObject, directive_none);
55 return (new CSPInfo(default_csp_info));
60 SecurityPolicy::WhitelistEntry::WhitelistEntry(const GURL& url, bool subdomains)
62 subdomains(subdomains) {
65 SecurityPolicy::SecurityPolicy(Application* app)
70 SecurityPolicy::~SecurityPolicy() {
73 bool SecurityPolicy::IsAccessAllowed(const GURL& url) const {
77 // Accessing own resources is always allowed.
78 if (url.SchemeIs(application::kApplicationScheme) &&
79 url.host() == app_->id())
82 for (std::vector<WhitelistEntry>::const_iterator it =
83 whitelist_entries_.begin(); it != whitelist_entries_.end(); ++it) {
84 const GURL& policy = it->url;
85 bool subdomains = it->subdomains;
86 bool is_host_matched = subdomains ?
87 url.DomainIs(policy.host().c_str()) : url.host() == policy.host();
88 if (url.scheme() == policy.scheme() && is_host_matched)
94 void SecurityPolicy::Enforce() {
97 void SecurityPolicy::AddWhitelistEntry(const GURL& url, bool subdomains) {
98 GURL app_url = app_->data()->URL();
99 DCHECK(app_->render_process_host());
100 WhitelistEntry entry = WhitelistEntry(url, subdomains);
102 std::vector<WhitelistEntry>::iterator it =
103 std::find(whitelist_entries_.begin(), whitelist_entries_.end(), entry);
104 if (it != whitelist_entries_.end())
107 app_->render_process_host()->Send(new ViewMsg_SetAccessWhiteList(
108 app_url, url, subdomains));
109 whitelist_entries_.push_back(entry);
112 SecurityPolicyWARP::SecurityPolicyWARP(Application* app)
113 : SecurityPolicy(app) {
116 SecurityPolicyWARP::~SecurityPolicyWARP() {
119 void SecurityPolicyWARP::Enforce() {
120 const WARPInfo* info = static_cast<WARPInfo*>(
121 app_->data()->GetManifestData(widget_keys::kAccessKey));
124 DCHECK(app_->render_process_host());
125 app_->render_process_host()->Send(
126 new ViewMsg_EnableSecurityMode(
127 ApplicationData::GetBaseURLFromApplicationId(app_->id()),
128 SecurityPolicy::WARP));
132 const base::ListValue* whitelist = info->GetWARP();
133 for (base::ListValue::const_iterator it = whitelist->begin();
134 it != whitelist->end(); ++it) {
135 base::DictionaryValue* value = NULL;
136 (*it)->GetAsDictionary(&value);
138 if (!value || !value->GetString(widget_keys::kAccessOriginKey, &dest) ||
147 // The default subdomains attribute should be "false".
148 std::string subdomains = "false";
149 value->GetString(widget_keys::kAccessSubdomainsKey, &subdomains);
150 AddWhitelistEntry(dest_url, (subdomains == "true"));
155 DCHECK(app_->render_process_host());
156 app_->render_process_host()->Send(
157 new ViewMsg_EnableSecurityMode(
158 ApplicationData::GetBaseURLFromApplicationId(app_->id()),
159 SecurityPolicy::WARP));
163 SecurityPolicyCSP::SecurityPolicyCSP(Application* app)
164 : SecurityPolicy(app) {
167 SecurityPolicyCSP::~SecurityPolicyCSP() {
170 void SecurityPolicyCSP::Enforce() {
171 Manifest::Type manifest_type = app_->data()->manifest_type();
172 const char* scp_key = GetCSPKey(manifest_type);
174 static_cast<CSPInfo*>(app_->data()->GetManifestData(scp_key));
175 if (manifest_type == Manifest::TYPE_WIDGET) {
176 #if defined(OS_TIZEN)
177 if (!csp_info || csp_info->GetDirectives().empty())
178 app_->data()->SetManifestData(scp_key, GetDefaultCSPInfo());
179 // Always enable security mode when under CSP mode.
181 NavigationInfo* info = static_cast<NavigationInfo*>(
182 app_->data()->GetManifestData(widget_keys::kAllowNavigationKey));
184 const std::vector<std::string>& allowed_list = info->GetAllowedDomains();
185 for (std::vector<std::string>::const_iterator it = allowed_list.begin();
186 it != allowed_list.end(); ++it) {
187 // If the policy is "*", it represents that any external link is allowed
189 if ((*it) == kAsterisk) {
194 // If the policy start with "*.", like this: *.domain,
195 // means that can access to all subdomains for 'domain',
196 // otherwise, the host of request url should exactly the same
198 bool subdomains = ((*it).find("*.") == 0);
199 std::string host = subdomains ? (*it).substr(2) : (*it);
200 AddWhitelistEntry(GURL("http://" + host), subdomains);
201 AddWhitelistEntry(GURL("https://" + host), subdomains);
206 if (!csp_info || csp_info->GetDirectives().empty()) {
207 LOG(ERROR) << "Failed to obtain CSP directives from the manifest";
211 const std::map<std::string, std::vector<std::string> >& policies =
212 csp_info->GetDirectives();
213 std::map<std::string, std::vector<std::string> >::const_iterator it =
215 for (; it != policies.end(); ++it) {
216 const std::vector<std::string>& allowed_list = it->second;
217 for (std::vector<std::string>::const_iterator it = allowed_list.begin();
218 it != allowed_list.end(); ++it) {
221 AddWhitelistEntry(url, false);
227 DCHECK(app_->render_process_host());
228 app_->render_process_host()->Send(
229 new ViewMsg_EnableSecurityMode(
230 ApplicationData::GetBaseURLFromApplicationId(app_->id()),
231 SecurityPolicy::CSP));
235 } // namespace application