// Copyright (c) 2012 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 CONTENT_BROWSER_CHILD_PROCESS_SECURITY_POLICY_IMPL_H_ #define CONTENT_BROWSER_CHILD_PROCESS_SECURITY_POLICY_IMPL_H_ #include #include #include #include #include #include "base/compiler_specific.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/singleton.h" #include "base/synchronization/lock.h" #include "base/thread_annotations.h" #include "content/browser/isolation_context.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/common/resource_type.h" #include "storage/common/fileapi/file_system_types.h" #include "url/origin.h" class GURL; namespace base { class FilePath; } namespace network { class ResourceRequestBody; } namespace storage { class FileSystemContext; class FileSystemURL; } namespace content { class IsolationContext; class SiteInstance; class CONTENT_EXPORT ChildProcessSecurityPolicyImpl : public ChildProcessSecurityPolicy { public: // Object can only be created through GetInstance() so the constructor is // private. ~ChildProcessSecurityPolicyImpl() override; static ChildProcessSecurityPolicyImpl* GetInstance(); // ChildProcessSecurityPolicy implementation. void RegisterWebSafeScheme(const std::string& scheme) override; void RegisterWebSafeIsolatedScheme( const std::string& scheme, bool always_allow_in_origin_headers) override; bool IsWebSafeScheme(const std::string& scheme) override; void GrantReadFile(int child_id, const base::FilePath& file) override; void GrantCreateReadWriteFile(int child_id, const base::FilePath& file) override; void GrantCopyInto(int child_id, const base::FilePath& dir) override; void GrantDeleteFrom(int child_id, const base::FilePath& dir) override; void GrantReadFileSystem(int child_id, const std::string& filesystem_id) override; void GrantWriteFileSystem(int child_id, const std::string& filesystem_id) override; void GrantCreateFileForFileSystem(int child_id, const std::string& filesystem_id) override; void GrantCreateReadWriteFileSystem( int child_id, const std::string& filesystem_id) override; void GrantCopyIntoFileSystem(int child_id, const std::string& filesystem_id) override; void GrantDeleteFromFileSystem(int child_id, const std::string& filesystem_id) override; void GrantCommitOrigin(int child_id, const url::Origin& origin) override; void GrantRequestOrigin(int child_id, const url::Origin& origin) override; void GrantRequestScheme(int child_id, const std::string& scheme) override; bool CanRequestURL(int child_id, const GURL& url) override; bool CanCommitURL(int child_id, const GURL& url) override; bool CanReadFile(int child_id, const base::FilePath& file) override; bool CanCreateReadWriteFile(int child_id, const base::FilePath& file) override; bool CanReadFileSystem(int child_id, const std::string& filesystem_id) override; bool CanReadWriteFileSystem(int child_id, const std::string& filesystem_id) override; bool CanCopyIntoFileSystem(int child_id, const std::string& filesystem_id) override; bool CanDeleteFromFileSystem(int child_id, const std::string& filesystem_id) override; bool HasWebUIBindings(int child_id) override; void GrantSendMidiSysExMessage(int child_id) override; bool CanAccessDataForOrigin(int child_id, const GURL& url) override; // This function will check whether |origin| requires process isolation // within |isolation_context|, and if so, it will return true and put the // most specific matching isolated origin into |result|. // // Such origins may be registered with the --isolate-origins command-line // flag, via features::IsolateOrigins, via an IsolateOrigins enterprise // policy, or by a content/ embedder using // ContentBrowserClient::GetOriginsRequiringDedicatedProcess(). // // If |origin| does not require process isolation, this function will return // false, and |result| will be a unique origin. This means that neither // |origin|, nor any origins for which |origin| is a subdomain, have been // registered as isolated origins. // // For example, if both https://isolated.com/ and // https://bar.foo.isolated.com/ are registered as isolated origins, then the // values returned in |result| are: // https://isolated.com/ --> https://isolated.com/ // https://foo.isolated.com/ --> https://isolated.com/ // https://bar.foo.isolated.com/ --> https://bar.foo.isolated.com/ // https://baz.bar.foo.isolated.com/ --> https://bar.foo.isolated.com/ // https://unisolated.com/ --> (unique origin) // // |isolation_context| is used to determine which origins are isolated in // this context. For example, isolated origins that are dynamically added // will only affect future BrowsingInstances. bool GetMatchingIsolatedOrigin(const IsolationContext& isolation_context, const url::Origin& origin, url::Origin* result); // A version of GetMatchingIsolatedOrigin that takes in both the |origin| and // the |site_url| that |origin| corresponds to. |site_url| is the key by // which |origin| will be looked up in |isolated_origins_| within // |isolation_context|; this function allows it to be passed in when it is // already known to avoid recomputing it internally. bool GetMatchingIsolatedOrigin(const IsolationContext& isolation_context, const url::Origin& origin, const GURL& site_url, url::Origin* result); // Returns if |child_id| can read all of the |files|. bool CanReadAllFiles(int child_id, const std::vector& files); // Validate that |child_id| in |file_system_context| is allowed to access // data in the POST body specified by |body|. Can be called on any thread. bool CanReadRequestBody( int child_id, const storage::FileSystemContext* file_system_context, const scoped_refptr& body); // Validate that the renderer process for |site_instance| is allowed to access // data in the POST body specified by |body|. Has to be called on the UI // thread. bool CanReadRequestBody( SiteInstance* site_instance, const scoped_refptr& body); // Pseudo schemes are treated differently than other schemes because they // cannot be requested like normal URLs. There is no mechanism for revoking // pseudo schemes. void RegisterPseudoScheme(const std::string& scheme); // Returns true iff |scheme| has been registered as pseudo scheme. bool IsPseudoScheme(const std::string& scheme); // Upon creation, child processes should register themselves by calling this // this method exactly once. void Add(int child_id); // Upon destruction, child processes should unregister themselves by calling // this method exactly once. // // Note: Pre-Remove() permissions remain in effect on the IO thread until // the task posted to the IO thread by this call runs and removes the entry // from |pending_remove_state_|. // This UI -> IO task sequence ensures that any pending tasks, on the IO // thread, for this |child_id| are allowed to run before access is completely // revoked. void Remove(int child_id); // Whenever the browser processes commands the child process to commit a URL, // it should call this method to grant the child process the capability to // commit anything from the URL's origin, along with permission to request all // URLs of the same scheme. void GrantCommitURL(int child_id, const GURL& url); // Whenever the browser process drops a file icon on a tab, it should call // this method to grant the child process the capability to request this one // file:// URL, but not all urls of the file:// scheme. void GrantRequestSpecificFileURL(int child_id, const GURL& url); // Revokes all permissions granted to the given file. void RevokeAllPermissionsForFile(int child_id, const base::FilePath& file); // Grant the child process the ability to use Web UI Bindings where |bindings| // is either BINDINGS_POLICY_WEB_UI or BINDINGS_POLICY_MOJO_WEB_UI or both. void GrantWebUIBindings(int child_id, int bindings); // Grant the child process the ability to read raw cookies. void GrantReadRawCookies(int child_id); // Revoke read raw cookies permission. void RevokeReadRawCookies(int child_id); // A version of the public ChildProcessSecurityPolicy::CanCommitURL() which // takes an additional bool |check_origin_lock|, specifying whether to // reject |url| if it does not match the origin lock on process |child_id|. // Passing true for |check_origin_lock| provides stronger enforcement with // strict site isolation; it is only set to false by features (e.g., Origin // header validation) that aren't yet ready for this enforcement. This // function should *not* be used by new features; use the public // ChildProcessSecurityPolicy::CanCommitURL() instead, which internally calls // this with |check_origin_lock| being true. // // TODO(alexmos): Remove |check_origin_lock| and check origin locks // unconditionally once https://crbug.com/515309 is fixed. bool CanCommitURL(int child_id, const GURL& url, bool check_origin_lock); // Whether the given origin is valid for an origin header. Valid origin // headers are commitable URLs. bool CanSetAsOriginHeader(int child_id, const GURL& url); // Explicit permissions checks for FileSystemURL specified files. bool CanReadFileSystemFile(int child_id, const storage::FileSystemURL& filesystem_url); bool CanWriteFileSystemFile(int child_id, const storage::FileSystemURL& filesystem_url); bool CanCreateFileSystemFile(int child_id, const storage::FileSystemURL& filesystem_url); bool CanCreateReadWriteFileSystemFile( int child_id, const storage::FileSystemURL& filesystem_url); bool CanCopyIntoFileSystemFile(int child_id, const storage::FileSystemURL& filesystem_url); bool CanDeleteFileSystemFile(int child_id, const storage::FileSystemURL& filesystem_url); // True if cookie headers may be exposed to renderer |child_id| for |url| for // display in DevTools. |url| should be a WebSocket URL. bool CanAccessDataForWebSocket(int child_id, const GURL& url); // Returns true if the specified child_id has been granted ReadRawCookies. bool CanReadRawCookies(int child_id); // Sets the process identified by |child_id| as only permitted to access data // for the origin specified by |lock_url|. Most callers should use // RenderProcessHostImpl::LockToOrigin instead of calling this directly. // |isolation_context| provides the context, such as BrowsingInstance, from // which this process was locked to origin. This information is used when // making isolation decisions for this process, such as determining which // isolated origins pertain to it. void LockToOrigin(const IsolationContext& isolation_context, int child_id, const GURL& lock_url); // Used to indicate the result of comparing a process's origin lock to // another value: enum class CheckOriginLockResult { // The process does not exist, or it has no origin lock. NO_LOCK, // The process has an origin lock and it matches the passed-in value. HAS_EQUAL_LOCK, // The process has an origin lock and it does not match the passed-in // value. HAS_WRONG_LOCK, }; // Check the origin lock of the process specified by |child_id| against // |site_url|. See the definition of |CheckOriginLockResult| for possible // returned values. CheckOriginLockResult CheckOriginLock(int child_id, const GURL& site_url); // Retrieves the current origin lock of process |child_id|. Returns an empty // GURL if the process does not exist or if it is not locked to an origin. GURL GetOriginLock(int child_id); // Register FileSystem type and permission policy which should be used // for the type. The |policy| must be a bitwise-or'd value of // storage::FilePermissionPolicy. void RegisterFileSystemPermissionPolicy(storage::FileSystemType type, int policy); // Returns true if sending system exclusive messages is allowed. bool CanSendMidiSysExMessage(int child_id); // Add |origins| to the list of origins that require process isolation. When // making process model decisions for such origins, the scheme+host tuple // rather than scheme and eTLD+1 will be used. SiteInstances for these // origins will also use the full host of the isolated origin as site URL. // // Subdomains of an isolated origin are considered to be part of that // origin's site. For example, if https://isolated.foo.com is added as an // isolated origin, then https://bar.isolated.foo.com will be considered part // of the site for https://isolated.foo.com. // // Note that origins from |origins| must not be unique - URLs that render with // unique origins, such as data: URLs, are not supported. Non-standard // schemes are also not supported. Sandboxed frames (e.g.,