// 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_COMMON_SANDBOX_MAC_H_ #define CONTENT_COMMON_SANDBOX_MAC_H_ #include <string> #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/gtest_prod_util.h" #include "content/common/content_export.h" #include "content/public/common/sandbox_type_mac.h" namespace base { class FilePath; } #if __OBJC__ @class NSArray; @class NSString; #else class NSArray; class NSString; #endif namespace content { // Class representing a substring of the sandbox profile tagged with its type. class SandboxSubstring { public: enum SandboxSubstringType { PLAIN, // Just a plain string, no escaping necessary. LITERAL, // Escape for use in (literal ...) expression. REGEX, // Escape for use in (regex ...) expression. }; SandboxSubstring() {} explicit SandboxSubstring(const std::string& value) : value_(value), type_(PLAIN) {} SandboxSubstring(const std::string& value, SandboxSubstringType type) : value_(value), type_(type) {} const std::string& value() { return value_; } SandboxSubstringType type() { return type_; } private: std::string value_; SandboxSubstringType type_; }; class CONTENT_EXPORT Sandbox { public: // A map of variable name -> string to substitute in its place. typedef base::hash_map<std::string, SandboxSubstring> SandboxVariableSubstitions; // Warm up System APIs that empirically need to be accessed before the // sandbox is turned on. |sandbox_type| is the type of sandbox to warm up. // Valid |sandbox_type| values are defined by the enum SandboxType, or can be // defined by the embedder via // ContentClient::GetSandboxProfileForProcessType(). static void SandboxWarmup(int sandbox_type); // Turns on the OS X sandbox for this process. // |sandbox_type| - type of Sandbox to use. See SandboxWarmup() for legal // values. // |allowed_dir| - directory to allow access to, currently the only sandbox // profile that supports this is SANDBOX_TYPE_UTILITY . // // Returns true on success, false if an error occurred enabling the sandbox. static bool EnableSandbox(int sandbox_type, const base::FilePath& allowed_dir); // Returns true if the sandbox has been enabled for the current process. static bool SandboxIsCurrentlyActive(); // Exposed for testing purposes, used by an accessory function of our tests // so we can't use FRIEND_TEST. // Build the Sandbox command necessary to allow access to a named directory // indicated by |allowed_dir|. // Returns a string containing the sandbox profile commands necessary to allow // access to that directory or nil if an error occured. // The header comment for PostProcessSandboxProfile() explains how variable // substition works in sandbox templates. // The returned string contains embedded variables. The function fills in // |substitutions| to contain the values for these variables. static NSString* BuildAllowDirectoryAccessSandboxString( const base::FilePath& allowed_dir, SandboxVariableSubstitions* substitutions); // Assemble the final sandbox profile from a template by removing comments // and substituting variables. // // |sandbox_template| is a string which contains 2 entitites to operate on: // // - Comments - The sandbox comment syntax is used to make the OS sandbox // optionally ignore commands it doesn't support. e.g. // ;10.6_ONLY (foo) // Where (foo) is some command that is only supported on OS X 10.6. // The ;10.6_ONLY comment can then be removed from the template to enable // (foo) as appropriate. // // - Variables - denoted by @variable_name@ . These are defined in the // sandbox template in cases where another string needs to be substituted at // runtime. e.g. @HOMEDIR_AS_LITERAL@ is substituted at runtime for the user's // home directory escaped appropriately for a (literal ...) expression. // // |comments_to_remove| is a list of NSStrings containing the comments to // remove. // |substitutions| is a hash of "variable name" -> "string to substitute". // Where the replacement string is tagged with information on how it is to be // escaped e.g. used as part of a regex string or a literal. // // On output |final_sandbox_profile_str| contains the final sandbox profile. // Returns true on success, false otherwise. static bool PostProcessSandboxProfile( NSString* in_sandbox_data, NSArray* comments_to_remove, SandboxVariableSubstitions& substitutions, std::string *final_sandbox_profile_str); private: // Returns an (allow file-read-metadata) rule for |allowed_path| and all its // parent directories. static NSString* AllowMetadataForPath(const base::FilePath& allowed_path); // Escape |src_utf8| for use in a plain string variable in a sandbox // configuraton file. On return |dst| is set to the quoted output. // Returns: true on success, false otherwise. static bool QuotePlainString(const std::string& src_utf8, std::string* dst); // Escape |str_utf8| for use in a regex literal in a sandbox // configuraton file. On return |dst| is set to the utf-8 encoded quoted // output. // // The implementation of this function is based on empirical testing of the // OS X sandbox on 10.5.8 & 10.6.2 which is undocumented and subject to // change. // // Note: If str_utf8 contains any characters < 32 || >125 then the function // fails and false is returned. // // Returns: true on success, false otherwise. static bool QuoteStringForRegex(const std::string& str_utf8, std::string* dst); // Convert provided path into a "canonical" path matching what the Sandbox // expects i.e. one without symlinks. // This path is not necessarily unique e.g. in the face of hardlinks. static base::FilePath GetCanonicalSandboxPath(const base::FilePath& path); FRIEND_TEST_ALL_PREFIXES(MacDirAccessSandboxTest, StringEscape); FRIEND_TEST_ALL_PREFIXES(MacDirAccessSandboxTest, RegexEscape); FRIEND_TEST_ALL_PREFIXES(MacDirAccessSandboxTest, SandboxAccess); DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); }; } // namespace content #endif // CONTENT_COMMON_SANDBOX_MAC_H_