diff options
author | victorhsieh@chromium.org <victorhsieh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-29 20:29:40 +0000 |
---|---|---|
committer | victorhsieh@chromium.org <victorhsieh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-29 20:29:40 +0000 |
commit | 93f7206a5283807e3f72917204c3f8152c633bba (patch) | |
tree | b5bed48454ed2dfe077596ba1a24e2126f97563f | |
parent | 081b544067287a9fc1ed42c0acb693a9a8b914d3 (diff) | |
download | chromium_src-93f7206a5283807e3f72917204c3f8152c633bba.zip chromium_src-93f7206a5283807e3f72917204c3f8152c633bba.tar.gz chromium_src-93f7206a5283807e3f72917204c3f8152c633bba.tar.bz2 |
Flag and whitelist to allow crxfs api in NaCl
This is pretty much the same as existing Pepper Socket API. Since the
original code for socket is in chrome_content_browser_client.h for
crossing chrome-content boundary, it's moved to the new file
pepper_util.cc, so that PepperCrxFileSystemMessageFilter can access
directory inside chrome space.
BUG=240865
Review URL: https://chromiumcodereview.appspot.com/15521002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202951 0039d316-1c4b-4281-b951-d872f2087c98
11 files changed, 206 insertions, 82 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 87f22e9..f84a527 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -13,9 +13,7 @@ #include "base/lazy_instance.h" #include "base/path_service.h" #include "base/prefs/pref_service.h" -#include "base/sha1.h" #include "base/string_number_conversions.h" -#include "base/strings/string_tokenizer.h" #include "base/utf_string_conversions.h" #include "chrome/app/breakpad_mac.h" #include "chrome/browser/app_mode/app_mode_utils.h" @@ -51,6 +49,7 @@ #include "chrome/browser/net/chrome_net_log.h" #include "chrome/browser/notifications/desktop_notification_service.h" #include "chrome/browser/notifications/desktop_notification_service_factory.h" +#include "chrome/browser/pepper_permission_util.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/plugins/plugin_info_message_filter.h" #include "chrome/browser/prefs/scoped_user_pref_update.h" @@ -203,6 +202,7 @@ namespace { // thread. base::LazyInstance<std::string> g_io_thread_application_locale; +#if defined(ENABLE_PLUGINS) const char* kPredefinedAllowedSocketOrigins[] = { "okddffdblfhhnmhodogpojmfkjmhinfp", // Test SSH Client "pnhechapfaindjhompbnflcldabbghjo", // HTerm App (SSH Client) @@ -225,6 +225,7 @@ const char* kPredefinedAllowedSocketOrigins[] = { "0B549507088E1564D672F7942EB87CA4DAD73972", // see crbug.com/238084 "864288364E239573E777D3E0E36864E590E95C74" // see crbug.com/238084 }; +#endif // Returns a copy of the given url with its host set to given host and path set // to given path. Other parts of the url will be the same. @@ -464,23 +465,15 @@ void SetApplicationLocaleOnIOThread(const std::string& locale) { g_io_thread_application_locale.Get() = locale; } -std::string HashHost(const std::string& host) { - const std::string id_hash = base::SHA1HashString(host); - DCHECK(id_hash.length() == base::kSHA1Length); - return base::HexEncode(id_hash.c_str(), id_hash.length()); -} - -bool HostIsInSet(const std::string& host, const std::set<std::string>& set) { - return set.count(host) > 0 || set.count(HashHost(host)) > 0; -} - } // namespace namespace chrome { ChromeContentBrowserClient::ChromeContentBrowserClient() { +#if defined(ENABLE_PLUGINS) for (size_t i = 0; i < arraysize(kPredefinedAllowedSocketOrigins); ++i) allowed_socket_origins_.insert(kPredefinedAllowedSocketOrigins[i]); +#endif permissions_policy_delegate_.reset( new extensions::BrowserPermissionsPolicyDelegate()); @@ -2143,60 +2136,15 @@ bool ChromeContentBrowserClient::AllowPepperSocketAPI( content::BrowserContext* browser_context, const GURL& url, const content::SocketPermissionRequest& params) { - if (!url.is_valid()) - return false; - - std::string host = url.host(); - if (url.SchemeIs(extensions::kExtensionScheme) && - HostIsInSet(host, allowed_socket_origins_)) { - return true; - } - - Profile* profile = Profile::FromBrowserContext(browser_context); - const Extension* extension = NULL; - ExtensionService* extension_service = !profile ? NULL : - extensions::ExtensionSystem::Get(profile)->extension_service(); - if (extension_service) { - extension = extension_service->extensions()-> - GetExtensionOrAppByURL(ExtensionURLInfo(url)); - } - - // Check the modules that are imported by this extension to see if any of them - // is whitelisted. - if (extension) { - const std::vector<extensions::SharedModuleInfo::ImportInfo>& imports = - extensions::SharedModuleInfo::GetImports(extension); - std::vector<extensions::SharedModuleInfo::ImportInfo>::const_iterator it; - for (it = imports.begin(); it != imports.end(); ++it) { - const Extension* imported_extension = extension_service-> - GetExtensionById(it->extension_id, false); - if (imported_extension && - extensions::SharedModuleInfo::IsSharedModule(imported_extension) && - HostIsInSet(it->extension_id, allowed_socket_origins_)) { - return true; - } - } - } - - // Need to check this now and not on construction because otherwise it won't - // work with browser_tests. - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - std::string allowed_list = - command_line.GetSwitchValueASCII(switches::kAllowNaClSocketAPI); - if (allowed_list == "*") { - // The wildcard allows socket API only for packaged and platform apps. - return extension && - (extension->GetType() == Manifest::TYPE_LEGACY_PACKAGED_APP || - extension->GetType() == Manifest::TYPE_PLATFORM_APP); - } else if (!allowed_list.empty()) { - base::StringTokenizer t(allowed_list, ","); - while (t.GetNext()) { - if (t.token() == host) - return true; - } - } - +#if defined(ENABLE_PLUGINS) + return IsExtensionOrSharedModuleWhitelisted( + Profile::FromBrowserContext(browser_context), + url, + allowed_socket_origins_, + switches::kAllowNaClSocketAPI); +#else return false; +#endif } base::FilePath ChromeContentBrowserClient::GetHyphenDictionaryDirectory() { diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 8cb0b83..6472748 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h @@ -22,7 +22,6 @@ class QuotaPermissionContext; } namespace extensions { -class Extension; class BrowserPermissionsPolicyDelegate; } @@ -257,8 +256,10 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient { #endif private: +#if defined(ENABLE_PLUGINS) // Set of origins that can use TCP/UDP private APIs from NaCl. std::set<std::string> allowed_socket_origins_; +#endif scoped_ptr<extensions::BrowserPermissionsPolicyDelegate> permissions_policy_delegate_; diff --git a/chrome/browser/pepper_permission_util.cc b/chrome/browser/pepper_permission_util.cc new file mode 100644 index 0000000..00976de --- /dev/null +++ b/chrome/browser/pepper_permission_util.cc @@ -0,0 +1,103 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/pepper_permission_util.h" + +#include <vector> + +#include "base/command_line.h" +#include "base/sha1.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_tokenizer.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_system.h" +#include "chrome/browser/google/google_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_set.h" +#include "chrome/common/extensions/manifest_handlers/shared_module_info.h" +#include "extensions/common/constants.h" + +using extensions::Extension; +using extensions::Manifest; + +namespace chrome { + +namespace { + +std::string HashHost(const std::string& host) { + const std::string id_hash = base::SHA1HashString(host); + DCHECK_EQ(id_hash.length(), base::kSHA1Length); + return base::HexEncode(id_hash.c_str(), id_hash.length()); +} + +bool HostIsInSet(const std::string& host, const std::set<std::string>& set) { + return set.count(host) > 0 || set.count(HashHost(host)) > 0; +} + +} // namespace + +bool IsExtensionOrSharedModuleWhitelisted( + Profile* profile, + const GURL& url, + const std::set<std::string>& whitelist, + const char* command_line_switch) { + if (!url.is_valid()) + return false; + + const std::string host = url.host(); + if (url.SchemeIs(extensions::kExtensionScheme) && + HostIsInSet(host, whitelist)) { + return true; + } + + const Extension* extension = NULL; + ExtensionService* extension_service = !profile ? NULL : + extensions::ExtensionSystem::Get(profile)->extension_service(); + if (extension_service) { + extension = extension_service->extensions()-> + GetExtensionOrAppByURL(ExtensionURLInfo(url)); + } + + // Check the modules that are imported by this extension to see if any of them + // is whitelisted. + if (extension) { + typedef std::vector<extensions::SharedModuleInfo::ImportInfo> + ImportInfoVector; + const ImportInfoVector& imports = + extensions::SharedModuleInfo::GetImports(extension); + for (ImportInfoVector::const_iterator it = imports.begin(); + it != imports.end(); ++it) { + const Extension* imported_extension = extension_service-> + GetExtensionById(it->extension_id, false); + if (imported_extension && + extensions::SharedModuleInfo::IsSharedModule(imported_extension) && + HostIsInSet(it->extension_id, whitelist)) { + return true; + } + } + } + + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + const std::string allowed_list = + command_line.GetSwitchValueASCII(command_line_switch); + if (allowed_list == "*") { + // The wildcard allows socket API only for packaged and platform apps. + return extension && + (extension->GetType() == Manifest::TYPE_LEGACY_PACKAGED_APP || + extension->GetType() == Manifest::TYPE_PLATFORM_APP); + } + + if (!allowed_list.empty()) { + base::StringTokenizer t(allowed_list, ","); + while (t.GetNext()) { + if (t.token() == host) + return true; + } + } + + return false; +} + +} // namespace chrome diff --git a/chrome/browser/pepper_permission_util.h b/chrome/browser/pepper_permission_util.h new file mode 100644 index 0000000..a717b42 --- /dev/null +++ b/chrome/browser/pepper_permission_util.h @@ -0,0 +1,26 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PEPPER_PERMISSION_UTIL_H_ +#define CHROME_BROWSER_PEPPER_PERMISSION_UTIL_H_ + +#include <set> +#include <string> + +class GURL; +class Profile; + +namespace chrome { + +// Returns true if the extension or it's shared module is whitelisted, or +// appears in command_line_switch. +bool IsExtensionOrSharedModuleWhitelisted( + Profile* profile, + const GURL& url, + const std::set<std::string>& whitelist, + const char* command_line_switch); + +} // namespace chrome + +#endif // CHROME_BROWSER_PEPPER_PERMISSION_UTIL_H_ diff --git a/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc b/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc index 83434df..f7b48f7 100644 --- a/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc +++ b/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc @@ -70,14 +70,6 @@ scoped_ptr<ResourceHost> ChromeBrowserPepperHostFactory::CreateResourceHost( host_->GetPpapiHost(), instance, params.pp_resource(), broker_filter)); } - case PpapiHostMsg_Ext_CrxFileSystem_Create::ID: { - PepperCrxFileSystemMessageFilter* crxfs_filter = - PepperCrxFileSystemMessageFilter::Create(instance, host_); - if (!crxfs_filter) - return scoped_ptr<ResourceHost>(); - return scoped_ptr<ResourceHost>(new MessageFilterHost( - host, instance, params.pp_resource(), crxfs_filter)); - } case PpapiHostMsg_Talk_Create::ID: return scoped_ptr<ResourceHost>(new PepperTalkHost( host_, instance, params.pp_resource())); @@ -103,6 +95,22 @@ scoped_ptr<ResourceHost> ChromeBrowserPepperHostFactory::CreateResourceHost( host_, instance, params.pp_resource())); } } + + // Permissions for the following interfaces will be checked at the + // time of the corresponding instance's methods calls (because + // permission check can be performed only on the UI + // thread). Currently these interfaces are available only for + // whitelisted apps which may not have access to the other private + // interfaces. + if (message.type() == PpapiHostMsg_Ext_CrxFileSystem_Create::ID) { + PepperCrxFileSystemMessageFilter* crxfs_filter = + PepperCrxFileSystemMessageFilter::Create(instance, host_); + if (!crxfs_filter) + return scoped_ptr<ResourceHost>(); + return scoped_ptr<ResourceHost>(new MessageFilterHost( + host, instance, params.pp_resource(), crxfs_filter)); + } + return scoped_ptr<ResourceHost>(); } diff --git a/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.cc b/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.cc index 276b79d..67a3284 100644 --- a/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.cc +++ b/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.cc @@ -7,11 +7,14 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" +#include "chrome/browser/pepper_permission_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" #include "content/public/browser/browser_ppapi_host.h" #include "content/public/browser/child_process_security_policy.h" +#include "content/public/browser/render_view_host.h" #include "extensions/common/constants.h" #include "ppapi/c/pp_errors.h" #include "ppapi/host/dispatch_host_message.h" @@ -22,6 +25,14 @@ namespace chrome { +namespace { + +const char* kPredefinedAllowedCrxFsOrigins[] = { + "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F" // see crbug.com/234789 +}; + +} // namespace + // static PepperCrxFileSystemMessageFilter* PepperCrxFileSystemMessageFilter::Create( PP_Instance instance, content::BrowserPpapiHost* host) { @@ -45,6 +56,8 @@ PepperCrxFileSystemMessageFilter::PepperCrxFileSystemMessageFilter( : render_process_id_(render_process_id), profile_directory_(profile_directory), document_url_(document_url) { + for (size_t i = 0; i < arraysize(kPredefinedAllowedCrxFsOrigins); ++i) + allowed_crxfs_origins_.insert(kPredefinedAllowedCrxFsOrigins[i]); } PepperCrxFileSystemMessageFilter::~PepperCrxFileSystemMessageFilter() { @@ -68,13 +81,14 @@ int32_t PepperCrxFileSystemMessageFilter::OnResourceMessageReceived( return PP_ERROR_FAILED; } -std::string PepperCrxFileSystemMessageFilter::CreateIsolatedFileSystem() { +Profile* PepperCrxFileSystemMessageFilter::GetProfile() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!document_url_.SchemeIs(extensions::kExtensionScheme)) - return std::string(); - ProfileManager* profile_manager = g_browser_process->profile_manager(); - Profile* profile = profile_manager->GetProfile(profile_directory_); + return profile_manager->GetProfile(profile_directory_); +} + +std::string PepperCrxFileSystemMessageFilter::CreateIsolatedFileSystem( + Profile* profile) { extensions::ExtensionSystem* extension_system = extensions::ExtensionSystem::Get(profile); if (!extension_system) @@ -100,7 +114,16 @@ std::string PepperCrxFileSystemMessageFilter::CreateIsolatedFileSystem() { int32_t PepperCrxFileSystemMessageFilter::OnOpenFileSystem( ppapi::host::HostMessageContext* context) { - const std::string fsid = CreateIsolatedFileSystem(); + Profile* profile = GetProfile(); + if (!IsExtensionOrSharedModuleWhitelisted(profile, + document_url_, + allowed_crxfs_origins_, + switches::kAllowNaClCrxFsAPI)) { + LOG(ERROR) << "Host " << document_url_.host() << " cannot use CrxFs API."; + return PP_ERROR_NOACCESS; + } + + const std::string fsid = CreateIsolatedFileSystem(profile); if (fsid.empty()) { context->reply_msg = PpapiPluginMsg_Ext_CrxFileSystem_BrowserOpenReply(std::string()); diff --git a/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.h b/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.h index 53669e1..b970d11 100644 --- a/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.h +++ b/chrome/browser/renderer_host/pepper/pepper_crx_file_system_message_filter.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_CRX_FILE_SYSTEM_MESSAGE_FILTER_H_ #define CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_CRX_FILE_SYSTEM_MESSAGE_FILTER_H_ +#include <set> #include <string> #include "base/files/file_path.h" @@ -14,6 +15,8 @@ #include "ppapi/host/resource_host.h" #include "ppapi/host/resource_message_filter.h" +class Profile; + namespace content { class BrowserPpapiHost; } @@ -48,10 +51,12 @@ class PepperCrxFileSystemMessageFilter virtual ~PepperCrxFileSystemMessageFilter(); + Profile* GetProfile(); + // Returns filesystem id of isolated filesystem if valid, or empty string // otherwise. This must run on the UI thread because ProfileManager only // allows access on that thread. - std::string CreateIsolatedFileSystem(); + std::string CreateIsolatedFileSystem(Profile* profile); int32_t OnOpenFileSystem(ppapi::host::HostMessageContext* context); @@ -59,6 +64,9 @@ class PepperCrxFileSystemMessageFilter const base::FilePath& profile_directory_; const GURL document_url_; + // Set of origins that can use CrxFs private APIs from NaCl. + std::set<std::string> allowed_crxfs_origins_; + DISALLOW_COPY_AND_ASSIGN(PepperCrxFileSystemMessageFilter); }; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 0011f12..979337d 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1280,6 +1280,8 @@ 'browser/pepper_broker_infobar_delegate.h', 'browser/pepper_flash_settings_manager.cc', 'browser/pepper_flash_settings_manager.h', + 'browser/pepper_permission_util.cc', + 'browser/pepper_permission_util.h', 'browser/performance_monitor/constants.cc', 'browser/performance_monitor/constants.h', 'browser/performance_monitor/database.cc', diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index d0d5109..9ba69d2 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -44,6 +44,10 @@ const char kAllowLegacyExtensionManifests[] = "allow-legacy-extension-manifests"; // Specifies comma-separated list of extension ids or hosts to grant +// access to CRX file system APIs. +const char kAllowNaClCrxFsAPI[] = "allow-nacl-crxfs-api"; + +// Specifies comma-separated list of extension ids or hosts to grant // access to TCP/UDP socket APIs. const char kAllowNaClSocketAPI[] = "allow-nacl-socket-api"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 9610a1f..67f5516 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -30,6 +30,7 @@ extern const char kAllowFileAccess[]; extern const char kAllowHTTPBackgroundPage[]; extern const char kAllowHttpScreenCapture[]; extern const char kAllowLegacyExtensionManifests[]; +extern const char kAllowNaClCrxFsAPI[]; extern const char kAllowNaClSocketAPI[]; extern const char kAllowOutdatedPlugins[]; extern const char kAllowRunningInsecureContent[]; diff --git a/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc b/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc index 4f586ca..3ed14d12 100644 --- a/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc +++ b/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc @@ -80,7 +80,7 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost( // Permissions for the following interfaces will be checked at the // time of the corresponding instance's methods calls (because // permission check can be performed only on the UI - // thread). Currently thise interfaces are available only for + // thread). Currently these interfaces are available only for // whitelisted apps which may not have access to the other private // interfaces. if (message.type() == PpapiHostMsg_HostResolverPrivate_Create::ID) { |