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