Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / sandbox / win / src / file_policy_test.cc
1 // Copyright (c) 2011 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 <algorithm>
6 #include <cctype>
7
8 #include <windows.h>
9 #include <winioctl.h>
10
11 #include "base/win/scoped_handle.h"
12 #include "sandbox/win/src/filesystem_policy.h"
13 #include "sandbox/win/src/nt_internals.h"
14 #include "sandbox/win/src/sandbox.h"
15 #include "sandbox/win/src/sandbox_factory.h"
16 #include "sandbox/win/src/sandbox_policy.h"
17 #include "sandbox/win/src/win_utils.h"
18 #include "sandbox/win/tests/common/controller.h"
19 #include "sandbox/win/tests/common/test_utils.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 #define BINDNTDLL(name) \
23   name ## Function name = reinterpret_cast<name ## Function>( \
24     ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name))
25
26 namespace sandbox {
27
28 const ULONG kSharing = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE;
29
30 // Creates a file using different desired access. Returns if the call succeeded
31 // or not.  The first argument in argv is the filename. If the second argument
32 // is "read", we try read only access. Otherwise we try read-write access.
33 SBOX_TESTS_COMMAND int File_Create(int argc, wchar_t **argv) {
34   if (argc != 2)
35     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
36
37   bool read = (_wcsicmp(argv[0], L"Read") == 0);
38
39   if (read) {
40     base::win::ScopedHandle file1(CreateFile(
41         argv[1], GENERIC_READ, kSharing, NULL, OPEN_EXISTING, 0, NULL));
42     base::win::ScopedHandle file2(CreateFile(
43         argv[1], FILE_EXECUTE, kSharing, NULL, OPEN_EXISTING, 0, NULL));
44
45     if (file1.Get() && file2.Get())
46       return SBOX_TEST_SUCCEEDED;
47     return SBOX_TEST_DENIED;
48   } else {
49     base::win::ScopedHandle file1(CreateFile(
50         argv[1], GENERIC_ALL, kSharing, NULL, OPEN_EXISTING, 0, NULL));
51     base::win::ScopedHandle file2(CreateFile(
52         argv[1], GENERIC_READ | FILE_WRITE_DATA, kSharing, NULL, OPEN_EXISTING,
53         0, NULL));
54
55     if (file1.Get() && file2.Get())
56       return SBOX_TEST_SUCCEEDED;
57     return SBOX_TEST_DENIED;
58   }
59 }
60
61 SBOX_TESTS_COMMAND int File_Win32Create(int argc, wchar_t **argv) {
62   if (argc != 1) {
63     SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
64   }
65
66   base::string16 full_path = MakePathToSys(argv[0], false);
67   if (full_path.empty()) {
68     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
69   }
70
71   HANDLE file = ::CreateFileW(full_path.c_str(), GENERIC_READ, kSharing,
72                               NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
73
74   if (INVALID_HANDLE_VALUE != file) {
75     ::CloseHandle(file);
76     return SBOX_TEST_SUCCEEDED;
77   } else {
78     if (ERROR_ACCESS_DENIED == ::GetLastError()) {
79       return SBOX_TEST_DENIED;
80     } else {
81       return SBOX_TEST_FAILED;
82     }
83   }
84   return SBOX_TEST_SUCCEEDED;
85 }
86
87 // Creates the file in parameter using the NtCreateFile api and returns if the
88 // call succeeded or not.
89 SBOX_TESTS_COMMAND int File_CreateSys32(int argc, wchar_t **argv) {
90   BINDNTDLL(NtCreateFile);
91   BINDNTDLL(RtlInitUnicodeString);
92   if (!NtCreateFile || !RtlInitUnicodeString)
93     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
94
95   if (argc != 1)
96     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
97
98   base::string16 file(argv[0]);
99   if (0 != _wcsnicmp(file.c_str(), kNTObjManPrefix, kNTObjManPrefixLen))
100     file = MakePathToSys(argv[0], true);
101
102   UNICODE_STRING object_name;
103   RtlInitUnicodeString(&object_name, file.c_str());
104
105   OBJECT_ATTRIBUTES obj_attributes = {0};
106   InitializeObjectAttributes(&obj_attributes, &object_name,
107                              OBJ_CASE_INSENSITIVE, NULL, NULL);
108
109   HANDLE handle;
110   IO_STATUS_BLOCK io_block = {0};
111   NTSTATUS status = NtCreateFile(&handle, FILE_READ_DATA, &obj_attributes,
112                                  &io_block, NULL, 0, kSharing, FILE_OPEN,
113                                  0, NULL, 0);
114   if (NT_SUCCESS(status)) {
115     ::CloseHandle(handle);
116     return SBOX_TEST_SUCCEEDED;
117   } else if (STATUS_ACCESS_DENIED == status) {
118     return SBOX_TEST_DENIED;
119   } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) {
120     return SBOX_TEST_NOT_FOUND;
121   }
122   return SBOX_TEST_FAILED;
123 }
124
125 // Opens the file in parameter using the NtOpenFile api and returns if the
126 // call succeeded or not.
127 SBOX_TESTS_COMMAND int File_OpenSys32(int argc, wchar_t **argv) {
128   BINDNTDLL(NtOpenFile);
129   BINDNTDLL(RtlInitUnicodeString);
130   if (!NtOpenFile || !RtlInitUnicodeString)
131     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
132
133   if (argc != 1)
134     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
135
136   base::string16 file = MakePathToSys(argv[0], true);
137   UNICODE_STRING object_name;
138   RtlInitUnicodeString(&object_name, file.c_str());
139
140   OBJECT_ATTRIBUTES obj_attributes = {0};
141   InitializeObjectAttributes(&obj_attributes, &object_name,
142                              OBJ_CASE_INSENSITIVE, NULL, NULL);
143
144   HANDLE handle;
145   IO_STATUS_BLOCK io_block = {0};
146   NTSTATUS status = NtOpenFile(&handle, FILE_READ_DATA, &obj_attributes,
147                                &io_block, kSharing, 0);
148   if (NT_SUCCESS(status)) {
149     ::CloseHandle(handle);
150     return SBOX_TEST_SUCCEEDED;
151   } else if (STATUS_ACCESS_DENIED == status) {
152     return SBOX_TEST_DENIED;
153   } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) {
154     return SBOX_TEST_NOT_FOUND;
155   }
156   return SBOX_TEST_FAILED;
157 }
158
159 SBOX_TESTS_COMMAND int File_GetDiskSpace(int argc, wchar_t **argv) {
160   base::string16 sys_path = MakePathToSys(L"", false);
161   if (sys_path.empty()) {
162     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
163   }
164   ULARGE_INTEGER free_user = {0};
165   ULARGE_INTEGER total = {0};
166   ULARGE_INTEGER free_total = {0};
167   if (::GetDiskFreeSpaceExW(sys_path.c_str(), &free_user, &total,
168                             &free_total)) {
169     if ((total.QuadPart != 0) && (free_total.QuadPart !=0)) {
170       return SBOX_TEST_SUCCEEDED;
171     }
172   } else {
173     if (ERROR_ACCESS_DENIED == ::GetLastError()) {
174       return SBOX_TEST_DENIED;
175     } else {
176       return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
177     }
178   }
179   return SBOX_TEST_SUCCEEDED;
180 }
181
182 // Move a file using the MoveFileEx api and returns if the call succeeded or
183 // not.
184 SBOX_TESTS_COMMAND int File_Rename(int argc, wchar_t **argv) {
185   if (argc != 2)
186     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
187
188   if (::MoveFileEx(argv[0], argv[1], 0))
189     return SBOX_TEST_SUCCEEDED;
190
191   if (::GetLastError() != ERROR_ACCESS_DENIED)
192     return SBOX_TEST_FAILED;
193
194   return SBOX_TEST_DENIED;
195 }
196
197 // Query the attributes of file in parameter using the NtQueryAttributesFile api
198 // and NtQueryFullAttributesFile and returns if the call succeeded or not. The
199 // second argument in argv is "d" or "f" telling if we expect the attributes to
200 // specify a file or a directory. The expected attribute has to match the real
201 // attributes for the call to be successful.
202 SBOX_TESTS_COMMAND int File_QueryAttributes(int argc, wchar_t **argv) {
203   BINDNTDLL(NtQueryAttributesFile);
204   BINDNTDLL(NtQueryFullAttributesFile);
205   BINDNTDLL(RtlInitUnicodeString);
206   if (!NtQueryAttributesFile || !NtQueryFullAttributesFile ||
207       !RtlInitUnicodeString)
208     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
209
210   if (argc != 2)
211     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
212
213   bool expect_directory = (L'd' == argv[1][0]);
214
215   UNICODE_STRING object_name;
216   base::string16 file = MakePathToSys(argv[0], true);
217   RtlInitUnicodeString(&object_name, file.c_str());
218
219   OBJECT_ATTRIBUTES obj_attributes = {0};
220   InitializeObjectAttributes(&obj_attributes, &object_name,
221                              OBJ_CASE_INSENSITIVE, NULL, NULL);
222
223   FILE_BASIC_INFORMATION info = {0};
224   FILE_NETWORK_OPEN_INFORMATION full_info = {0};
225   NTSTATUS status1 = NtQueryAttributesFile(&obj_attributes, &info);
226   NTSTATUS status2 = NtQueryFullAttributesFile(&obj_attributes, &full_info);
227
228   if (status1 != status2)
229     return SBOX_TEST_FAILED;
230
231   if (NT_SUCCESS(status1)) {
232     if (info.FileAttributes != full_info.FileAttributes)
233       return SBOX_TEST_FAILED;
234
235     bool is_directory1 = (info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
236     if (expect_directory == is_directory1)
237       return SBOX_TEST_SUCCEEDED;
238   } else if (STATUS_ACCESS_DENIED == status1) {
239     return SBOX_TEST_DENIED;
240   } else if (STATUS_OBJECT_NAME_NOT_FOUND == status1) {
241     return SBOX_TEST_NOT_FOUND;
242   }
243
244   return SBOX_TEST_FAILED;
245 }
246
247 TEST(FilePolicyTest, DenyNtCreateCalc) {
248   TestRunner runner;
249   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY,
250                                   L"calc.exe"));
251
252   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 calc.exe"));
253
254   runner.SetTestState(BEFORE_REVERT);
255   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
256 }
257
258 TEST(FilePolicyTest, AllowNtCreateCalc) {
259   TestRunner runner;
260   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.exe"));
261
262   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
263
264   runner.SetTestState(BEFORE_REVERT);
265   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
266 }
267
268 TEST(FilePolicyTest, AllowNtCreateWithNativePath) {
269   base::string16 calc = MakePathToSys(L"calc.exe", false);
270   base::string16 nt_path;
271   ASSERT_TRUE(GetNtPathFromWin32Path(calc, &nt_path));
272   TestRunner runner;
273   runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, nt_path.c_str());
274
275   wchar_t buff[MAX_PATH];
276   ::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
277   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
278
279   std::transform(nt_path.begin(), nt_path.end(), nt_path.begin(), std::tolower);
280   ::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
281   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
282 }
283
284 TEST(FilePolicyTest, AllowReadOnly) {
285   TestRunner runner;
286
287   // Create a temp file because we need write access to it.
288   wchar_t temp_directory[MAX_PATH];
289   wchar_t temp_file_name[MAX_PATH];
290   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
291   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
292
293   EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
294                                temp_file_name));
295
296   wchar_t command_read[MAX_PATH + 20] = {0};
297   wsprintf(command_read, L"File_Create Read \"%ls\"", temp_file_name);
298   wchar_t command_write[MAX_PATH + 20] = {0};
299   wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name);
300
301   // Verify that we have read access after revert.
302   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_read));
303
304   // Verify that we don't have write access after revert.
305   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write));
306
307   // Verify that we really have write access to the file.
308   runner.SetTestState(BEFORE_REVERT);
309   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write));
310
311   DeleteFile(temp_file_name);
312 }
313
314 TEST(FilePolicyTest, AllowWildcard) {
315   TestRunner runner;
316
317   // Create a temp file because we need write access to it.
318   wchar_t temp_directory[MAX_PATH];
319   wchar_t temp_file_name[MAX_PATH];
320   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
321   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
322
323   wcscat_s(temp_directory, MAX_PATH, L"*");
324   EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_directory));
325
326   wchar_t command_write[MAX_PATH + 20] = {0};
327   wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name);
328
329   // Verify that we have write access after revert.
330   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write));
331
332   DeleteFile(temp_file_name);
333 }
334
335 TEST(FilePolicyTest, AllowNtCreatePatternRule) {
336   TestRunner runner;
337   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"App*.dll"));
338
339   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
340             runner.RunTest(L"File_OpenSys32 appmgmts.dll"));
341   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_OpenSys32 appwiz.cpl"));
342
343   runner.SetTestState(BEFORE_REVERT);
344   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
345             runner.RunTest(L"File_OpenSys32 appmgmts.dll"));
346   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_OpenSys32 appwiz.cpl"));
347 }
348
349 TEST(FilePolicyTest, CheckNotFound) {
350   TestRunner runner;
351   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"n*.dll"));
352
353   EXPECT_EQ(SBOX_TEST_NOT_FOUND,
354             runner.RunTest(L"File_OpenSys32 notfound.dll"));
355 }
356
357 TEST(FilePolicyTest, CheckNoLeak) {
358   TestRunner runner;
359   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 notfound.exe"));
360 }
361
362 TEST(FilePolicyTest, TestQueryAttributesFile) {
363   TestRunner runner;
364   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY,
365                                   L"appmgmts.dll"));
366   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY,
367                                   L"notfound.exe"));
368   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"drivers"));
369   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_QUERY,
370                                   L"ipconfig.exe"));
371
372   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
373             runner.RunTest(L"File_QueryAttributes drivers d"));
374
375   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
376             runner.RunTest(L"File_QueryAttributes appmgmts.dll f"));
377
378   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
379             runner.RunTest(L"File_QueryAttributes ipconfig.exe f"));
380
381   EXPECT_EQ(SBOX_TEST_DENIED,
382             runner.RunTest(L"File_QueryAttributes ftp.exe f"));
383
384   EXPECT_EQ(SBOX_TEST_NOT_FOUND,
385             runner.RunTest(L"File_QueryAttributes notfound.exe f"));
386 }
387
388 // Makes sure that we don't leak information when there is not policy to allow
389 // a path.
390 TEST(FilePolicyTest, TestQueryAttributesFileNoPolicy) {
391   TestRunner runner;
392   EXPECT_EQ(SBOX_TEST_DENIED,
393             runner.RunTest(L"File_QueryAttributes ftp.exe f"));
394
395   EXPECT_EQ(SBOX_TEST_DENIED,
396             runner.RunTest(L"File_QueryAttributes notfound.exe f"));
397 }
398
399 TEST(FilePolicyTest, TestRename) {
400   TestRunner runner;
401
402   // Give access to the temp directory.
403   wchar_t temp_directory[MAX_PATH];
404   wchar_t temp_file_name1[MAX_PATH];
405   wchar_t temp_file_name2[MAX_PATH];
406   wchar_t temp_file_name3[MAX_PATH];
407   wchar_t temp_file_name4[MAX_PATH];
408   wchar_t temp_file_name5[MAX_PATH];
409   wchar_t temp_file_name6[MAX_PATH];
410   wchar_t temp_file_name7[MAX_PATH];
411   wchar_t temp_file_name8[MAX_PATH];
412   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
413   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name1), 0u);
414   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name2), 0u);
415   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name3), 0u);
416   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name4), 0u);
417   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name5), 0u);
418   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name6), 0u);
419   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name7), 0u);
420   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name8), 0u);
421
422
423   // Add rules to make file1->file2 succeed.
424   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name1));
425   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name2));
426
427   // Add rules to make file3->file4 fail.
428   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name3));
429   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
430                                temp_file_name4));
431
432   // Add rules to make file5->file6 fail.
433   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
434                                temp_file_name5));
435   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name6));
436
437   // Add rules to make file7->no_pol_file fail.
438   ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name7));
439
440   // Delete the files where the files are going to be renamed to.
441   ::DeleteFile(temp_file_name2);
442   ::DeleteFile(temp_file_name4);
443   ::DeleteFile(temp_file_name6);
444   ::DeleteFile(temp_file_name8);
445
446
447   wchar_t command[MAX_PATH*2 + 20] = {0};
448   wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name1,
449            temp_file_name2);
450   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command));
451
452   wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name3,
453            temp_file_name4);
454   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
455
456   wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name5,
457            temp_file_name6);
458   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
459
460   wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name7,
461            temp_file_name8);
462   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
463
464
465   // Delete all the files in case they are still there.
466   ::DeleteFile(temp_file_name1);
467   ::DeleteFile(temp_file_name2);
468   ::DeleteFile(temp_file_name3);
469   ::DeleteFile(temp_file_name4);
470   ::DeleteFile(temp_file_name5);
471   ::DeleteFile(temp_file_name6);
472   ::DeleteFile(temp_file_name7);
473   ::DeleteFile(temp_file_name8);
474 }
475
476 TEST(FilePolicyTest, OpenSys32FilesDenyBecauseOfDir) {
477   TestRunner runner;
478   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY,
479                                   L"notepad.exe"));
480
481   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe"));
482
483   runner.SetTestState(BEFORE_REVERT);
484   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
485             runner.RunTest(L"File_Win32Create notepad.exe"));
486 }
487
488 TEST(FilePolicyTest, OpenSys32FilesAllowNotepad) {
489   TestRunner runner;
490   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY,
491                                   L"notepad.exe"));
492
493   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
494             runner.RunTest(L"File_Win32Create notepad.exe"));
495
496   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create calc.exe"));
497
498   runner.SetTestState(BEFORE_REVERT);
499   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
500             runner.RunTest(L"File_Win32Create notepad.exe"));
501   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_Win32Create calc.exe"));
502 }
503
504 TEST(FilePolicyTest, FileGetDiskSpace) {
505   TestRunner runner;
506   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_GetDiskSpace"));
507   runner.SetTestState(BEFORE_REVERT);
508   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
509
510   // Add an 'allow' rule in the windows\system32 such that GetDiskFreeSpaceEx
511   // succeeds (it does an NtOpenFile) but windows\system32\notepad.exe is
512   // denied since there is no wild card in the rule.
513   EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, L""));
514   runner.SetTestState(BEFORE_REVERT);
515   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
516
517   runner.SetTestState(AFTER_REVERT);
518   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
519   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe"));
520 }
521
522 // http://crbug.com/146944
523 TEST(FilePolicyTest, DISABLED_TestReparsePoint) {
524   TestRunner runner;
525
526   // Create a temp file because we need write access to it.
527   wchar_t temp_directory[MAX_PATH];
528   wchar_t temp_file_name[MAX_PATH];
529   ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
530   ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
531
532   // Delete the file and create a directory instead.
533   ASSERT_TRUE(::DeleteFile(temp_file_name));
534   ASSERT_TRUE(::CreateDirectory(temp_file_name, NULL));
535
536   // Create a temporary file in the subfolder.
537   base::string16 subfolder = temp_file_name;
538   base::string16 temp_file_title = subfolder.substr(subfolder.rfind(L"\\") + 1);
539   base::string16 temp_file = subfolder + L"\\file_" + temp_file_title;
540
541   HANDLE file = ::CreateFile(temp_file.c_str(), FILE_ALL_ACCESS,
542                              FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
543                              CREATE_ALWAYS, 0, NULL);
544   ASSERT_TRUE(INVALID_HANDLE_VALUE != file);
545   ASSERT_TRUE(::CloseHandle(file));
546
547   // Create a temporary file in the temp directory.
548   base::string16 temp_dir = temp_directory;
549   base::string16 temp_file_in_temp = temp_dir + L"file_" + temp_file_title;
550   file = ::CreateFile(temp_file_in_temp.c_str(), FILE_ALL_ACCESS,
551                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
552                       CREATE_ALWAYS, 0, NULL);
553   ASSERT_TRUE(file != NULL);
554   ASSERT_TRUE(::CloseHandle(file));
555
556   // Give write access to the temp directory.
557   base::string16 temp_dir_wildcard = temp_dir + L"*";
558   EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY,
559                                temp_dir_wildcard.c_str()));
560
561   // Prepare the command to execute.
562   base::string16 command_write;
563   command_write += L"File_Create Write \"";
564   command_write += temp_file;
565   command_write += L"\"";
566
567   // Verify that we have write access to the original file
568   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write.c_str()));
569
570   // Replace the subfolder by a reparse point to %temp%.
571   ::DeleteFile(temp_file.c_str());
572   HANDLE dir = ::CreateFile(subfolder.c_str(), FILE_ALL_ACCESS,
573                             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
574                             OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
575   EXPECT_TRUE(INVALID_HANDLE_VALUE != dir);
576
577   base::string16 temp_dir_nt;
578   temp_dir_nt += L"\\??\\";
579   temp_dir_nt += temp_dir;
580   EXPECT_TRUE(SetReparsePoint(dir, temp_dir_nt.c_str()));
581   EXPECT_TRUE(::CloseHandle(dir));
582
583   // Try to open the file again.
584   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write.c_str()));
585
586   // Remove the reparse point.
587   dir = ::CreateFile(subfolder.c_str(), FILE_ALL_ACCESS,
588                      FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
589                      FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
590                      NULL);
591   EXPECT_TRUE(INVALID_HANDLE_VALUE != dir);
592   EXPECT_TRUE(DeleteReparsePoint(dir));
593   EXPECT_TRUE(::CloseHandle(dir));
594
595   // Cleanup.
596   EXPECT_TRUE(::DeleteFile(temp_file_in_temp.c_str()));
597   EXPECT_TRUE(::RemoveDirectory(subfolder.c_str()));
598 }
599
600 TEST(FilePolicyTest, CheckExistingNTPrefixEscape) {
601   base::string16 name = L"\\??\\NAME";
602
603   base::string16 result = FixNTPrefixForMatch(name);
604
605   EXPECT_STREQ(result.c_str(), L"\\/?/?\\NAME");
606 }
607
608 TEST(FilePolicyTest, CheckEscapedNTPrefixNoEscape) {
609   base::string16 name = L"\\/?/?\\NAME";
610
611   base::string16 result = FixNTPrefixForMatch(name);
612
613   EXPECT_STREQ(result.c_str(), name.c_str());
614 }
615
616 TEST(FilePolicyTest, CheckMissingNTPrefixEscape) {
617   base::string16 name = L"C:\\NAME";
618
619   base::string16 result = FixNTPrefixForMatch(name);
620
621   EXPECT_STREQ(result.c_str(), L"\\/?/?\\C:\\NAME");
622 }
623
624 }  // namespace sandbox