Home | History | Annotate | Download | only in browser
      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
      3 // found in the LICENSE file.
      4 
      5 #include <set>
      6 #include <string>
      7 
      8 #include "base/basictypes.h"
      9 #include "base/files/file_path.h"
     10 #include "base/platform_file.h"
     11 #include "content/browser/child_process_security_policy_impl.h"
     12 #include "content/public/common/url_constants.h"
     13 #include "content/test/test_content_browser_client.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 #include "url/gurl.h"
     16 #include "webkit/browser/fileapi/file_permission_policy.h"
     17 #include "webkit/browser/fileapi/file_system_url.h"
     18 #include "webkit/browser/fileapi/isolated_context.h"
     19 #include "webkit/common/fileapi/file_system_types.h"
     20 
     21 namespace content {
     22 namespace {
     23 
     24 const int kRendererID = 42;
     25 const int kWorkerRendererID = kRendererID + 1;
     26 
     27 #if defined(FILE_PATH_USES_DRIVE_LETTERS)
     28 #define TEST_PATH(x) FILE_PATH_LITERAL("c:") FILE_PATH_LITERAL(x)
     29 #else
     30 #define TEST_PATH(x) FILE_PATH_LITERAL(x)
     31 #endif
     32 
     33 class ChildProcessSecurityPolicyTestBrowserClient
     34     : public TestContentBrowserClient {
     35  public:
     36   ChildProcessSecurityPolicyTestBrowserClient() {}
     37 
     38   virtual bool IsHandledURL(const GURL& url) OVERRIDE {
     39     return schemes_.find(url.scheme()) != schemes_.end();
     40   }
     41 
     42   void ClearSchemes() {
     43     schemes_.clear();
     44   }
     45 
     46   void AddScheme(const std::string& scheme) {
     47     schemes_.insert(scheme);
     48   }
     49 
     50  private:
     51   std::set<std::string> schemes_;
     52 };
     53 
     54 }  // namespace
     55 
     56 class ChildProcessSecurityPolicyTest : public testing::Test {
     57  public:
     58   ChildProcessSecurityPolicyTest() : old_browser_client_(NULL) {
     59   }
     60 
     61   virtual void SetUp() {
     62     old_browser_client_ = SetBrowserClientForTesting(&test_browser_client_);
     63 
     64     // Claim to always handle chrome:// URLs because the CPSP's notion of
     65     // allowing WebUI bindings is hard-wired to this particular scheme.
     66     test_browser_client_.AddScheme(chrome::kChromeUIScheme);
     67 
     68     // Claim to always handle file:// URLs like the browser would.
     69     // net::URLRequest::IsHandledURL() no longer claims support for default
     70     // protocols as this is the responsibility of the browser (which is
     71     // responsible for adding the appropriate ProtocolHandler).
     72     test_browser_client_.AddScheme(chrome::kFileScheme);
     73   }
     74 
     75   virtual void TearDown() {
     76     test_browser_client_.ClearSchemes();
     77     SetBrowserClientForTesting(old_browser_client_);
     78   }
     79 
     80  protected:
     81   void RegisterTestScheme(const std::string& scheme) {
     82     test_browser_client_.AddScheme(scheme);
     83   }
     84 
     85   void GrantPermissionsForFile(ChildProcessSecurityPolicyImpl* p,
     86                                int child_id,
     87                                const base::FilePath& file,
     88                                int permissions) {
     89     p->GrantPermissionsForFile(child_id, file, permissions);
     90   }
     91 
     92   void CheckHasNoFileSystemPermission(ChildProcessSecurityPolicyImpl* p,
     93                                       const std::string& child_id) {
     94     EXPECT_FALSE(p->CanReadFileSystem(kRendererID, child_id));
     95     EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, child_id));
     96     EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, child_id));
     97     EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, child_id));
     98   }
     99 
    100   void CheckHasNoFileSystemFilePermission(ChildProcessSecurityPolicyImpl* p,
    101                                           const base::FilePath& file,
    102                                           const fileapi::FileSystemURL& url) {
    103     EXPECT_FALSE(p->CanReadFile(kRendererID, file));
    104     EXPECT_FALSE(p->CanCreateReadWriteFile(kRendererID, file));
    105     EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
    106     EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
    107     EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
    108     EXPECT_FALSE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
    109     EXPECT_FALSE(p->CanCopyIntoFileSystemFile(kRendererID, url));
    110     EXPECT_FALSE(p->CanDeleteFileSystemFile(kRendererID, url));
    111   }
    112 
    113  private:
    114   ChildProcessSecurityPolicyTestBrowserClient test_browser_client_;
    115   ContentBrowserClient* old_browser_client_;
    116 };
    117 
    118 
    119 TEST_F(ChildProcessSecurityPolicyTest, IsWebSafeSchemeTest) {
    120   ChildProcessSecurityPolicyImpl* p =
    121       ChildProcessSecurityPolicyImpl::GetInstance();
    122 
    123   EXPECT_TRUE(p->IsWebSafeScheme(kHttpScheme));
    124   EXPECT_TRUE(p->IsWebSafeScheme(kHttpsScheme));
    125   EXPECT_TRUE(p->IsWebSafeScheme(kFtpScheme));
    126   EXPECT_TRUE(p->IsWebSafeScheme(chrome::kDataScheme));
    127   EXPECT_TRUE(p->IsWebSafeScheme("feed"));
    128   EXPECT_TRUE(p->IsWebSafeScheme(chrome::kBlobScheme));
    129   EXPECT_TRUE(p->IsWebSafeScheme(chrome::kFileSystemScheme));
    130 
    131   EXPECT_FALSE(p->IsWebSafeScheme("registered-web-safe-scheme"));
    132   p->RegisterWebSafeScheme("registered-web-safe-scheme");
    133   EXPECT_TRUE(p->IsWebSafeScheme("registered-web-safe-scheme"));
    134 
    135   EXPECT_FALSE(p->IsWebSafeScheme(chrome::kChromeUIScheme));
    136 }
    137 
    138 TEST_F(ChildProcessSecurityPolicyTest, IsPseudoSchemeTest) {
    139   ChildProcessSecurityPolicyImpl* p =
    140       ChildProcessSecurityPolicyImpl::GetInstance();
    141 
    142   EXPECT_TRUE(p->IsPseudoScheme(chrome::kAboutScheme));
    143   EXPECT_TRUE(p->IsPseudoScheme(kJavaScriptScheme));
    144   EXPECT_TRUE(p->IsPseudoScheme(kViewSourceScheme));
    145 
    146   EXPECT_FALSE(p->IsPseudoScheme("registered-pseudo-scheme"));
    147   p->RegisterPseudoScheme("registered-pseudo-scheme");
    148   EXPECT_TRUE(p->IsPseudoScheme("registered-pseudo-scheme"));
    149 
    150   EXPECT_FALSE(p->IsPseudoScheme(chrome::kChromeUIScheme));
    151 }
    152 
    153 TEST_F(ChildProcessSecurityPolicyTest, StandardSchemesTest) {
    154   ChildProcessSecurityPolicyImpl* p =
    155       ChildProcessSecurityPolicyImpl::GetInstance();
    156 
    157   p->Add(kRendererID);
    158 
    159   // Safe
    160   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("http://www.google.com/")));
    161   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("https://www.paypal.com/")));
    162   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("ftp://ftp.gnu.org/")));
    163   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("data:text/html,<b>Hi</b>")));
    164   EXPECT_TRUE(p->CanRequestURL(kRendererID,
    165                                GURL("view-source:http://www.google.com/")));
    166   EXPECT_TRUE(p->CanRequestURL(
    167       kRendererID, GURL("filesystem:http://localhost/temporary/a.gif")));
    168 
    169   // Dangerous
    170   EXPECT_FALSE(p->CanRequestURL(kRendererID,
    171                                 GURL("file:///etc/passwd")));
    172   EXPECT_FALSE(p->CanRequestURL(kRendererID,
    173                                 GURL("chrome://foo/bar")));
    174 
    175   p->Remove(kRendererID);
    176 }
    177 
    178 TEST_F(ChildProcessSecurityPolicyTest, AboutTest) {
    179   ChildProcessSecurityPolicyImpl* p =
    180       ChildProcessSecurityPolicyImpl::GetInstance();
    181 
    182   p->Add(kRendererID);
    183 
    184   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("about:blank")));
    185   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("about:BlAnK")));
    186   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("aBouT:BlAnK")));
    187   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("aBouT:blank")));
    188 
    189   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:memory")));
    190   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:crash")));
    191   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:cache")));
    192   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:hang")));
    193 
    194   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("aBoUt:memory")));
    195   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:CrASh")));
    196   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("abOuT:cAChe")));
    197 
    198   // Requests for about: pages should be denied.
    199   p->GrantRequestURL(kRendererID, GURL("about:crash"));
    200   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:crash")));
    201 
    202   // These requests for chrome:// pages should be granted.
    203   GURL chrome_url("chrome://foo");
    204   p->GrantRequestURL(kRendererID, chrome_url);
    205   EXPECT_TRUE(p->CanRequestURL(kRendererID, chrome_url));
    206 
    207   p->Remove(kRendererID);
    208 }
    209 
    210 TEST_F(ChildProcessSecurityPolicyTest, JavaScriptTest) {
    211   ChildProcessSecurityPolicyImpl* p =
    212       ChildProcessSecurityPolicyImpl::GetInstance();
    213 
    214   p->Add(kRendererID);
    215 
    216   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("javascript:alert('xss')")));
    217   p->GrantRequestURL(kRendererID, GURL("javascript:alert('xss')"));
    218   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("javascript:alert('xss')")));
    219 
    220   p->Remove(kRendererID);
    221 }
    222 
    223 TEST_F(ChildProcessSecurityPolicyTest, RegisterWebSafeSchemeTest) {
    224   ChildProcessSecurityPolicyImpl* p =
    225       ChildProcessSecurityPolicyImpl::GetInstance();
    226 
    227   p->Add(kRendererID);
    228 
    229   // Currently, "asdf" is destined for ShellExecute, so it is allowed.
    230   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("asdf:rockers")));
    231 
    232   // Once we register "asdf", we default to deny.
    233   RegisterTestScheme("asdf");
    234   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("asdf:rockers")));
    235 
    236   // We can allow new schemes by adding them to the whitelist.
    237   p->RegisterWebSafeScheme("asdf");
    238   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("asdf:rockers")));
    239 
    240   // Cleanup.
    241   p->Remove(kRendererID);
    242 }
    243 
    244 TEST_F(ChildProcessSecurityPolicyTest, CanServiceCommandsTest) {
    245   ChildProcessSecurityPolicyImpl* p =
    246       ChildProcessSecurityPolicyImpl::GetInstance();
    247 
    248   p->Add(kRendererID);
    249 
    250   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
    251   p->GrantRequestURL(kRendererID, GURL("file:///etc/passwd"));
    252   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
    253 
    254   // We should forget our state if we repeat a renderer id.
    255   p->Remove(kRendererID);
    256   p->Add(kRendererID);
    257   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
    258   p->Remove(kRendererID);
    259 }
    260 
    261 TEST_F(ChildProcessSecurityPolicyTest, ViewSource) {
    262   ChildProcessSecurityPolicyImpl* p =
    263       ChildProcessSecurityPolicyImpl::GetInstance();
    264 
    265   p->Add(kRendererID);
    266 
    267   // View source is determined by the embedded scheme.
    268   EXPECT_TRUE(p->CanRequestURL(kRendererID,
    269                                GURL("view-source:http://www.google.com/")));
    270   EXPECT_FALSE(p->CanRequestURL(kRendererID,
    271                                 GURL("view-source:file:///etc/passwd")));
    272   EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
    273   EXPECT_FALSE(p->CanRequestURL(
    274       kRendererID, GURL("view-source:view-source:http://www.google.com/")));
    275 
    276   p->GrantRequestURL(kRendererID, GURL("view-source:file:///etc/passwd"));
    277   // View source needs to be able to request the embedded scheme.
    278   EXPECT_TRUE(p->CanRequestURL(kRendererID,
    279                                GURL("view-source:file:///etc/passwd")));
    280   EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
    281 
    282   p->Remove(kRendererID);
    283 }
    284 
    285 TEST_F(ChildProcessSecurityPolicyTest, SpecificFile) {
    286   ChildProcessSecurityPolicyImpl* p =
    287       ChildProcessSecurityPolicyImpl::GetInstance();
    288 
    289   p->Add(kRendererID);
    290 
    291   GURL icon_url("file:///tmp/foo.png");
    292   GURL sensitive_url("file:///etc/passwd");
    293   EXPECT_FALSE(p->CanRequestURL(kRendererID, icon_url));
    294   EXPECT_FALSE(p->CanRequestURL(kRendererID, sensitive_url));
    295 
    296   p->GrantRequestSpecificFileURL(kRendererID, icon_url);
    297   EXPECT_TRUE(p->CanRequestURL(kRendererID, icon_url));
    298   EXPECT_FALSE(p->CanRequestURL(kRendererID, sensitive_url));
    299 
    300   p->GrantRequestURL(kRendererID, icon_url);
    301   EXPECT_TRUE(p->CanRequestURL(kRendererID, icon_url));
    302   EXPECT_TRUE(p->CanRequestURL(kRendererID, sensitive_url));
    303 
    304   p->Remove(kRendererID);
    305 }
    306 
    307 TEST_F(ChildProcessSecurityPolicyTest, FileSystemGrantsTest) {
    308   ChildProcessSecurityPolicyImpl* p =
    309       ChildProcessSecurityPolicyImpl::GetInstance();
    310 
    311   p->Add(kRendererID);
    312   std::string read_id = fileapi::IsolatedContext::GetInstance()->
    313       RegisterFileSystemForVirtualPath(fileapi::kFileSystemTypeTest,
    314                                        "read_filesystem",
    315                                        base::FilePath());
    316   std::string read_write_id = fileapi::IsolatedContext::GetInstance()->
    317       RegisterFileSystemForVirtualPath(fileapi::kFileSystemTypeTest,
    318                                        "read_write_filesystem",
    319                                        base::FilePath());
    320   std::string copy_into_id = fileapi::IsolatedContext::GetInstance()->
    321       RegisterFileSystemForVirtualPath(fileapi::kFileSystemTypeTest,
    322                                        "copy_into_filesystem",
    323                                        base::FilePath());
    324   std::string delete_from_id = fileapi::IsolatedContext::GetInstance()->
    325       RegisterFileSystemForVirtualPath(fileapi::kFileSystemTypeTest,
    326                                        "delete_from_filesystem",
    327                                        base::FilePath());
    328 
    329   // Test initially having no permissions.
    330   CheckHasNoFileSystemPermission(p, read_id);
    331   CheckHasNoFileSystemPermission(p, read_write_id);
    332   CheckHasNoFileSystemPermission(p, copy_into_id);
    333   CheckHasNoFileSystemPermission(p, delete_from_id);
    334 
    335   // Testing varying combinations of grants and checks.
    336   p->GrantReadFileSystem(kRendererID, read_id);
    337   EXPECT_TRUE(p->CanReadFileSystem(kRendererID, read_id));
    338   EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, read_id));
    339   EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_id));
    340   EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, read_id));
    341 
    342   p->GrantReadFileSystem(kRendererID, read_write_id);
    343   p->GrantWriteFileSystem(kRendererID, read_write_id);
    344   EXPECT_TRUE(p->CanReadFileSystem(kRendererID, read_write_id));
    345   EXPECT_TRUE(p->CanReadWriteFileSystem(kRendererID, read_write_id));
    346   EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_write_id));
    347   EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, read_write_id));
    348 
    349   p->GrantCopyIntoFileSystem(kRendererID, copy_into_id);
    350   EXPECT_FALSE(p->CanReadFileSystem(kRendererID, copy_into_id));
    351   EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, copy_into_id));
    352   EXPECT_TRUE(p->CanCopyIntoFileSystem(kRendererID, copy_into_id));
    353   EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, copy_into_id));
    354 
    355   p->GrantDeleteFromFileSystem(kRendererID, delete_from_id);
    356   EXPECT_FALSE(p->CanReadFileSystem(kRendererID, delete_from_id));
    357   EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, delete_from_id));
    358   EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, delete_from_id));
    359   EXPECT_TRUE(p->CanDeleteFromFileSystem(kRendererID, delete_from_id));
    360 
    361   // Test revoke permissions on renderer ID removal.
    362   p->Remove(kRendererID);
    363   CheckHasNoFileSystemPermission(p, read_id);
    364   CheckHasNoFileSystemPermission(p, read_write_id);
    365   CheckHasNoFileSystemPermission(p, copy_into_id);
    366   CheckHasNoFileSystemPermission(p, delete_from_id);
    367 
    368   // Test having no permissions upon re-adding same renderer ID.
    369   p->Add(kRendererID);
    370   CheckHasNoFileSystemPermission(p, read_id);
    371   CheckHasNoFileSystemPermission(p, read_write_id);
    372   CheckHasNoFileSystemPermission(p, copy_into_id);
    373   CheckHasNoFileSystemPermission(p, delete_from_id);
    374 
    375   // Cleanup.
    376   p->Remove(kRendererID);
    377   fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(read_id);
    378   fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(read_write_id);
    379   fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(copy_into_id);
    380   fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(delete_from_id);
    381 }
    382 
    383 TEST_F(ChildProcessSecurityPolicyTest, FilePermissionGrantingAndRevoking) {
    384   ChildProcessSecurityPolicyImpl* p =
    385       ChildProcessSecurityPolicyImpl::GetInstance();
    386 
    387   p->RegisterFileSystemPermissionPolicy(
    388       fileapi::kFileSystemTypeTest,
    389       fileapi::FILE_PERMISSION_USE_FILE_PERMISSION);
    390 
    391   p->Add(kRendererID);
    392   base::FilePath file(TEST_PATH("/dir/testfile"));
    393   file = file.NormalizePathSeparators();
    394   fileapi::FileSystemURL url = fileapi::FileSystemURL::CreateForTest(
    395       GURL("http://foo/"), fileapi::kFileSystemTypeTest, file);
    396 
    397   // Test initially having no permissions.
    398   CheckHasNoFileSystemFilePermission(p, file, url);
    399 
    400   // Testing every combination of permissions granting and revoking.
    401   p->GrantReadFile(kRendererID, file);
    402   EXPECT_TRUE(p->CanReadFile(kRendererID, file));
    403   EXPECT_FALSE(p->CanCreateReadWriteFile(kRendererID, file));
    404   EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url));
    405   EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
    406   EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
    407   EXPECT_FALSE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
    408   EXPECT_FALSE(p->CanCopyIntoFileSystemFile(kRendererID, url));
    409   EXPECT_FALSE(p->CanDeleteFileSystemFile(kRendererID, url));
    410   p->RevokeAllPermissionsForFile(kRendererID, file);
    411   CheckHasNoFileSystemFilePermission(p, file, url);
    412 
    413   p->GrantCreateReadWriteFile(kRendererID, file);
    414   EXPECT_TRUE(p->CanReadFile(kRendererID, file));
    415   EXPECT_TRUE(p->CanCreateReadWriteFile(kRendererID, file));
    416   EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url));
    417   EXPECT_TRUE(p->CanWriteFileSystemFile(kRendererID, url));
    418   EXPECT_TRUE(p->CanCreateFileSystemFile(kRendererID, url));
    419   EXPECT_TRUE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
    420   EXPECT_TRUE(p->CanCopyIntoFileSystemFile(kRendererID, url));
    421   EXPECT_TRUE(p->CanDeleteFileSystemFile(kRendererID, url));
    422   p->RevokeAllPermissionsForFile(kRendererID, file);
    423   CheckHasNoFileSystemFilePermission(p, file, url);
    424 
    425   // Test revoke permissions on renderer ID removal.
    426   p->GrantCreateReadWriteFile(kRendererID, file);
    427   EXPECT_TRUE(p->CanReadFile(kRendererID, file));
    428   EXPECT_TRUE(p->CanCreateReadWriteFile(kRendererID, file));
    429   EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url));
    430   EXPECT_TRUE(p->CanWriteFileSystemFile(kRendererID, url));
    431   EXPECT_TRUE(p->CanCreateFileSystemFile(kRendererID, url));
    432   EXPECT_TRUE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
    433   EXPECT_TRUE(p->CanCopyIntoFileSystemFile(kRendererID, url));
    434   EXPECT_TRUE(p->CanDeleteFileSystemFile(kRendererID, url));
    435   p->Remove(kRendererID);
    436   CheckHasNoFileSystemFilePermission(p, file, url);
    437 
    438   // Test having no permissions upon re-adding same renderer ID.
    439   p->Add(kRendererID);
    440   CheckHasNoFileSystemFilePermission(p, file, url);
    441 
    442   // Cleanup.
    443   p->Remove(kRendererID);
    444 }
    445 
    446 TEST_F(ChildProcessSecurityPolicyTest, FilePermissions) {
    447   base::FilePath granted_file = base::FilePath(TEST_PATH("/home/joe"));
    448   base::FilePath sibling_file = base::FilePath(TEST_PATH("/home/bob"));
    449   base::FilePath child_file = base::FilePath(TEST_PATH("/home/joe/file"));
    450   base::FilePath parent_file = base::FilePath(TEST_PATH("/home"));
    451   base::FilePath parent_slash_file = base::FilePath(TEST_PATH("/home/"));
    452   base::FilePath child_traversal1 =
    453       base::FilePath(TEST_PATH("/home/joe/././file"));
    454   base::FilePath child_traversal2 = base::FilePath(
    455       TEST_PATH("/home/joe/file/../otherfile"));
    456   base::FilePath evil_traversal1 =
    457       base::FilePath(TEST_PATH("/home/joe/../../etc/passwd"));
    458   base::FilePath evil_traversal2 = base::FilePath(
    459       TEST_PATH("/home/joe/./.././../etc/passwd"));
    460   base::FilePath self_traversal =
    461       base::FilePath(TEST_PATH("/home/joe/../joe/file"));
    462   base::FilePath relative_file = base::FilePath(FILE_PATH_LITERAL("home/joe"));
    463 
    464   ChildProcessSecurityPolicyImpl* p =
    465       ChildProcessSecurityPolicyImpl::GetInstance();
    466 
    467   // Grant permissions for a file.
    468   p->Add(kRendererID);
    469   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
    470                                         base::PLATFORM_FILE_OPEN));
    471 
    472   GrantPermissionsForFile(p, kRendererID, granted_file,
    473                              base::PLATFORM_FILE_OPEN |
    474                              base::PLATFORM_FILE_OPEN_TRUNCATED |
    475                              base::PLATFORM_FILE_READ |
    476                              base::PLATFORM_FILE_WRITE);
    477   EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
    478                                        base::PLATFORM_FILE_OPEN |
    479                                        base::PLATFORM_FILE_OPEN_TRUNCATED |
    480                                        base::PLATFORM_FILE_READ |
    481                                        base::PLATFORM_FILE_WRITE));
    482   EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
    483                                        base::PLATFORM_FILE_OPEN |
    484                                        base::PLATFORM_FILE_READ));
    485   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
    486                                         base::PLATFORM_FILE_CREATE));
    487   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 0));
    488   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
    489                                         base::PLATFORM_FILE_CREATE |
    490                                         base::PLATFORM_FILE_OPEN_TRUNCATED |
    491                                         base::PLATFORM_FILE_READ |
    492                                         base::PLATFORM_FILE_WRITE));
    493   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, sibling_file,
    494                                         base::PLATFORM_FILE_OPEN |
    495                                         base::PLATFORM_FILE_READ));
    496   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, parent_file,
    497                                         base::PLATFORM_FILE_OPEN |
    498                                         base::PLATFORM_FILE_READ));
    499   EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, child_file,
    500                                         base::PLATFORM_FILE_OPEN |
    501                                         base::PLATFORM_FILE_READ));
    502   EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, child_traversal1,
    503                                         base::PLATFORM_FILE_OPEN |
    504                                         base::PLATFORM_FILE_READ));
    505   EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, child_traversal2,
    506                                         base::PLATFORM_FILE_OPEN |
    507                                         base::PLATFORM_FILE_READ));
    508   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, evil_traversal1,
    509                                         base::PLATFORM_FILE_OPEN |
    510                                         base::PLATFORM_FILE_READ));
    511   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, evil_traversal2,
    512                                         base::PLATFORM_FILE_OPEN |
    513                                         base::PLATFORM_FILE_READ));
    514   // CPSP doesn't allow this case for the sake of simplicity.
    515   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, self_traversal,
    516                                         base::PLATFORM_FILE_OPEN |
    517                                         base::PLATFORM_FILE_READ));
    518   p->Remove(kRendererID);
    519 
    520   // Grant permissions for the directory the file is in.
    521   p->Add(kRendererID);
    522   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
    523                                         base::PLATFORM_FILE_OPEN));
    524   GrantPermissionsForFile(p, kRendererID, parent_file,
    525                              base::PLATFORM_FILE_OPEN |
    526                              base::PLATFORM_FILE_READ);
    527   EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
    528                                         base::PLATFORM_FILE_OPEN));
    529   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
    530                                         base::PLATFORM_FILE_READ |
    531                                         base::PLATFORM_FILE_WRITE));
    532   p->Remove(kRendererID);
    533 
    534   // Grant permissions for the directory the file is in (with trailing '/').
    535   p->Add(kRendererID);
    536   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
    537                                         base::PLATFORM_FILE_OPEN));
    538   GrantPermissionsForFile(p, kRendererID, parent_slash_file,
    539                              base::PLATFORM_FILE_OPEN |
    540                              base::PLATFORM_FILE_READ);
    541   EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
    542                                         base::PLATFORM_FILE_OPEN));
    543   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
    544                                         base::PLATFORM_FILE_READ |
    545                                         base::PLATFORM_FILE_WRITE));
    546 
    547   // Grant permissions for the file (should overwrite the permissions granted
    548   // for the directory).
    549   GrantPermissionsForFile(p, kRendererID, granted_file,
    550                              base::PLATFORM_FILE_TEMPORARY);
    551   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
    552                                         base::PLATFORM_FILE_OPEN));
    553   EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
    554                                        base::PLATFORM_FILE_TEMPORARY));
    555 
    556   // Revoke all permissions for the file (it should inherit its permissions
    557   // from the directory again).
    558   p->RevokeAllPermissionsForFile(kRendererID, granted_file);
    559   EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
    560                                        base::PLATFORM_FILE_OPEN |
    561                                        base::PLATFORM_FILE_READ));
    562   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
    563                                         base::PLATFORM_FILE_TEMPORARY));
    564   p->Remove(kRendererID);
    565 
    566   // Grant file permissions for the file to main thread renderer process,
    567   // make sure its worker thread renderer process inherits those.
    568   p->Add(kRendererID);
    569   GrantPermissionsForFile(p, kRendererID, granted_file,
    570                              base::PLATFORM_FILE_OPEN |
    571                              base::PLATFORM_FILE_READ);
    572   EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
    573                                        base::PLATFORM_FILE_OPEN |
    574                                        base::PLATFORM_FILE_READ));
    575   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
    576                                        base::PLATFORM_FILE_WRITE));
    577   p->AddWorker(kWorkerRendererID, kRendererID);
    578   EXPECT_TRUE(p->HasPermissionsForFile(kWorkerRendererID, granted_file,
    579                                        base::PLATFORM_FILE_OPEN |
    580                                        base::PLATFORM_FILE_READ));
    581   EXPECT_FALSE(p->HasPermissionsForFile(kWorkerRendererID, granted_file,
    582                                         base::PLATFORM_FILE_WRITE));
    583   p->Remove(kRendererID);
    584   EXPECT_FALSE(p->HasPermissionsForFile(kWorkerRendererID, granted_file,
    585                                         base::PLATFORM_FILE_OPEN |
    586                                         base::PLATFORM_FILE_READ));
    587   p->Remove(kWorkerRendererID);
    588 
    589   p->Add(kRendererID);
    590   GrantPermissionsForFile(p, kRendererID, relative_file,
    591                              base::PLATFORM_FILE_OPEN);
    592   EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, relative_file,
    593                                         base::PLATFORM_FILE_OPEN));
    594   p->Remove(kRendererID);
    595 }
    596 
    597 TEST_F(ChildProcessSecurityPolicyTest, CanServiceWebUIBindings) {
    598   ChildProcessSecurityPolicyImpl* p =
    599       ChildProcessSecurityPolicyImpl::GetInstance();
    600 
    601   GURL url("chrome://thumb/http://www.google.com/");
    602 
    603   p->Add(kRendererID);
    604 
    605   EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
    606   EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
    607   p->GrantWebUIBindings(kRendererID);
    608   EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
    609   EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
    610 
    611   p->Remove(kRendererID);
    612 }
    613 
    614 TEST_F(ChildProcessSecurityPolicyTest, RemoveRace) {
    615   ChildProcessSecurityPolicyImpl* p =
    616       ChildProcessSecurityPolicyImpl::GetInstance();
    617 
    618   GURL url("file:///etc/passwd");
    619   base::FilePath file(TEST_PATH("/etc/passwd"));
    620 
    621   p->Add(kRendererID);
    622 
    623   p->GrantRequestURL(kRendererID, url);
    624   p->GrantReadFile(kRendererID, file);
    625   p->GrantWebUIBindings(kRendererID);
    626 
    627   EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
    628   EXPECT_TRUE(p->CanReadFile(kRendererID, file));
    629   EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
    630 
    631   p->Remove(kRendererID);
    632 
    633   // Renderers are added and removed on the UI thread, but the policy can be
    634   // queried on the IO thread.  The ChildProcessSecurityPolicy needs to be
    635   // prepared to answer policy questions about renderers who no longer exist.
    636 
    637   // In this case, we default to secure behavior.
    638   EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
    639   EXPECT_FALSE(p->CanReadFile(kRendererID, file));
    640   EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
    641 }
    642 
    643 }  // namespace content
    644