Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: chrome/browser/extensions/extension_protocols.cc

Issue 12457042: Non-web-accessible extension URLs should not load in non-extension processes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixing nits. Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/chrome_security_exploit_browsertest.cc ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_protocols.h" 5 #include "chrome/browser/extensions/extension_protocols.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/weak_ptr.h" 12 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop.h" 13 #include "base/message_loop.h"
14 #include "base/path_service.h" 14 #include "base/path_service.h"
15 #include "base/string_util.h" 15 #include "base/string_util.h"
16 #include "base/stringprintf.h" 16 #include "base/stringprintf.h"
17 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
18 #include "base/threading/worker_pool.h" 18 #include "base/threading/worker_pool.h"
19 #include "build/build_config.h" 19 #include "build/build_config.h"
20 #include "chrome/browser/extensions/extension_info_map.h" 20 #include "chrome/browser/extensions/extension_info_map.h"
21 #include "chrome/browser/extensions/image_loader.h" 21 #include "chrome/browser/extensions/image_loader.h"
22 #include "chrome/common/chrome_paths.h" 22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/extensions/api/icons/icons_handler.h" 23 #include "chrome/common/extensions/api/icons/icons_handler.h"
24 #include "chrome/common/extensions/background_info.h" 24 #include "chrome/common/extensions/background_info.h"
25 #include "chrome/common/extensions/csp_handler.h" 25 #include "chrome/common/extensions/csp_handler.h"
26 #include "chrome/common/extensions/extension.h" 26 #include "chrome/common/extensions/extension.h"
27 #include "chrome/common/extensions/extension_file_util.h" 27 #include "chrome/common/extensions/extension_file_util.h"
28 #include "chrome/common/extensions/incognito_handler.h" 28 #include "chrome/common/extensions/incognito_handler.h"
29 #include "chrome/common/extensions/manifest_url_handler.h"
29 #include "chrome/common/extensions/web_accessible_resources_handler.h" 30 #include "chrome/common/extensions/web_accessible_resources_handler.h"
30 #include "chrome/common/url_constants.h" 31 #include "chrome/common/url_constants.h"
31 #include "content/public/browser/resource_request_info.h" 32 #include "content/public/browser/resource_request_info.h"
32 #include "extensions/common/constants.h" 33 #include "extensions/common/constants.h"
33 #include "extensions/common/extension_resource.h" 34 #include "extensions/common/extension_resource.h"
34 #include "googleurl/src/url_util.h" 35 #include "googleurl/src/url_util.h"
35 #include "grit/component_extension_resources_map.h" 36 #include "grit/component_extension_resources_map.h"
36 #include "net/base/mime_util.h" 37 #include "net/base/mime_util.h"
37 #include "net/base/net_errors.h" 38 #include "net/base/net_errors.h"
38 #include "net/http/http_response_headers.h" 39 #include "net/http/http_response_headers.h"
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 } 264 }
264 265
265 return true; 266 return true;
266 } 267 }
267 268
268 // Returns true if an chrome-extension:// resource should be allowed to load. 269 // Returns true if an chrome-extension:// resource should be allowed to load.
269 // TODO(aa): This should be moved into ExtensionResourceRequestPolicy, but we 270 // TODO(aa): This should be moved into ExtensionResourceRequestPolicy, but we
270 // first need to find a way to get CanLoadInIncognito state into the renderers. 271 // first need to find a way to get CanLoadInIncognito state into the renderers.
271 bool AllowExtensionResourceLoad(net::URLRequest* request, 272 bool AllowExtensionResourceLoad(net::URLRequest* request,
272 bool is_incognito, 273 bool is_incognito,
274 const Extension* extension,
273 ExtensionInfoMap* extension_info_map) { 275 ExtensionInfoMap* extension_info_map) {
274 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); 276 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
275 277
276 // We have seen crashes where info is NULL: crbug.com/52374. 278 // We have seen crashes where info is NULL: crbug.com/52374.
277 if (!info) { 279 if (!info) {
278 LOG(ERROR) << "Allowing load of " << request->url().spec() 280 LOG(ERROR) << "Allowing load of " << request->url().spec()
279 << "from unknown origin. Could not find user data for " 281 << "from unknown origin. Could not find user data for "
280 << "request."; 282 << "request.";
281 return true; 283 return true;
282 } 284 }
283 285
284 if (is_incognito && !ExtensionCanLoadInIncognito(info, request->url().host(), 286 if (is_incognito && !ExtensionCanLoadInIncognito(info, request->url().host(),
285 extension_info_map)) { 287 extension_info_map)) {
286 return false; 288 return false;
287 } 289 }
288 290
291 // The following checks are meant to replicate similar set of checks in the
292 // renderer process, performed by ResourceRequestPolicy::CanRequestResource.
293 // These are not exactly equivalent, because we don't have the same bits of
294 // information. The two checks need to be kept in sync as much as possible, as
295 // an exploited renderer can bypass the checks in ResourceRequestPolicy.
296
297 // Check if the extension for which this request is made is indeed loaded in
298 // the process sending the request. If not, we need to explicitly check if
299 // the resource is explicitly accessible or fits in a set of exception cases.
300 // Note: This allows a case where two extensions execute in the same renderer
301 // process to request each other's resources. We can't do a more precise
302 // check, since the renderer can lie about which extension has made the
303 // request.
304 if (extension_info_map->process_map().Contains(
305 request->url().host(), info->GetChildID())) {
306 return true;
307 }
308
309 if (!content::PageTransitionIsWebTriggerable(info->GetPageTransition()))
310 return false;
311
312 // The following checks require that we have an actual extension object. If we
313 // don't have it, allow the request handling to continue with the rest of the
314 // checks.
315 if (!extension)
316 return true;
317
318 // Disallow loading of packaged resources for hosted apps. We don't allow
319 // hybrid hosted/packaged apps. The one exception is access to icons, since
320 // some extensions want to be able to do things like create their own
321 // launchers.
322 std::string resource_root_relative_path =
323 request->url().path().empty() ? "" : request->url().path().substr(1);
324 if (extension->is_hosted_app() &&
325 !extensions::IconsInfo::GetIcons(extension)
326 .ContainsPath(resource_root_relative_path)) {
327 LOG(ERROR) << "Denying load of " << request->url().spec() << " from "
328 << "hosted app.";
329 return false;
330 }
331
332 // Extensions with web_accessible_resources: allow loading by regular
333 // renderers. Since not all subresources are required to be listed in a v2
334 // manifest, we must allow all loads if there are any web accessible
335 // resources. See http://crbug.com/179127.
336 if (extension->manifest_version() < 2 ||
337 extensions::WebAccessibleResourcesInfo::HasWebAccessibleResources(
338 extension)) {
339 return true;
340 }
341
342 // If there aren't any explicitly marked web accessible resources, the
343 // load should be allowed only if it is by DevTools. A close approximation is
344 // checking if the extension contains a DevTools page.
345 if (extensions::ManifestURL::GetDevToolsPage(extension).is_empty())
346 return false;
347
289 return true; 348 return true;
290 } 349 }
291 350
292 // Returns true if the given URL references an icon in the given extension. 351 // Returns true if the given URL references an icon in the given extension.
293 bool URLIsForExtensionIcon(const GURL& url, const Extension* extension) { 352 bool URLIsForExtensionIcon(const GURL& url, const Extension* extension) {
294 DCHECK(url.SchemeIs(extensions::kExtensionScheme)); 353 DCHECK(url.SchemeIs(extensions::kExtensionScheme));
295 354
296 if (!extension) 355 if (!extension)
297 return false; 356 return false;
298 357
(...skipping 21 matching lines...) Expand all
320 private: 379 private:
321 const bool is_incognito_; 380 const bool is_incognito_;
322 ExtensionInfoMap* const extension_info_map_; 381 ExtensionInfoMap* const extension_info_map_;
323 DISALLOW_COPY_AND_ASSIGN(ExtensionProtocolHandler); 382 DISALLOW_COPY_AND_ASSIGN(ExtensionProtocolHandler);
324 }; 383 };
325 384
326 // Creates URLRequestJobs for extension:// URLs. 385 // Creates URLRequestJobs for extension:// URLs.
327 net::URLRequestJob* 386 net::URLRequestJob*
328 ExtensionProtocolHandler::MaybeCreateJob( 387 ExtensionProtocolHandler::MaybeCreateJob(
329 net::URLRequest* request, net::NetworkDelegate* network_delegate) const { 388 net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
389 // chrome-extension://extension-id/resource/path.js
390 const std::string& extension_id = request->url().host();
391 const Extension* extension =
392 extension_info_map_->extensions().GetByID(extension_id);
393
330 // TODO(mpcomplete): better error code. 394 // TODO(mpcomplete): better error code.
331 if (!AllowExtensionResourceLoad( 395 if (!AllowExtensionResourceLoad(
332 request, is_incognito_, extension_info_map_)) { 396 request, is_incognito_, extension, extension_info_map_)) {
333 return new net::URLRequestErrorJob( 397 return new net::URLRequestErrorJob(
334 request, network_delegate, net::ERR_ADDRESS_UNREACHABLE); 398 request, network_delegate, net::ERR_ADDRESS_UNREACHABLE);
335 } 399 }
336 400
337 // chrome-extension://extension-id/resource/path.js
338 const std::string& extension_id = request->url().host();
339 const Extension* extension =
340 extension_info_map_->extensions().GetByID(extension_id);
341 base::FilePath directory_path; 401 base::FilePath directory_path;
342 if (extension) 402 if (extension)
343 directory_path = extension->path(); 403 directory_path = extension->path();
344 if (directory_path.value().empty()) { 404 if (directory_path.value().empty()) {
345 const Extension* disabled_extension = 405 const Extension* disabled_extension =
346 extension_info_map_->disabled_extensions().GetByID(extension_id); 406 extension_info_map_->disabled_extensions().GetByID(extension_id);
347 if (URLIsForExtensionIcon(request->url(), disabled_extension)) 407 if (URLIsForExtensionIcon(request->url(), disabled_extension))
348 directory_path = disabled_extension->path(); 408 directory_path = disabled_extension->path();
349 if (directory_path.value().empty()) { 409 if (directory_path.value().empty()) {
350 LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id; 410 LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 send_cors_header); 469 send_cors_header);
410 } 470 }
411 471
412 } // namespace 472 } // namespace
413 473
414 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( 474 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler(
415 bool is_incognito, 475 bool is_incognito,
416 ExtensionInfoMap* extension_info_map) { 476 ExtensionInfoMap* extension_info_map) {
417 return new ExtensionProtocolHandler(is_incognito, extension_info_map); 477 return new ExtensionProtocolHandler(is_incognito, extension_info_map);
418 } 478 }
OLDNEW
« no previous file with comments | « chrome/browser/chrome_security_exploit_browsertest.cc ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698