Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / sandbox / win / tests / validation_tests / commands.cc
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 <Aclapi.h>
6 #include <windows.h>
7 #include <string>
8
9 #include "sandbox/win/tests/validation_tests/commands.h"
10
11 #include "sandbox/win/tests/common/controller.h"
12
13 namespace {
14
15 // Returns the HKEY corresponding to name. If there is no HKEY corresponding
16 // to the name it returns NULL.
17 HKEY GetHKEYFromString(const base::string16 &name) {
18   if (L"HKLM" == name)
19     return HKEY_LOCAL_MACHINE;
20   else if (L"HKCR" == name)
21     return HKEY_CLASSES_ROOT;
22   else if (L"HKCC" == name)
23     return HKEY_CURRENT_CONFIG;
24   else if (L"HKCU" == name)
25     return HKEY_CURRENT_USER;
26   else if (L"HKU" == name)
27     return HKEY_USERS;
28
29   return NULL;
30 }
31
32 // Modifies string to remove the leading and trailing quotes.
33 void trim_quote(base::string16* string) {
34   base::string16::size_type pos1 = string->find_first_not_of(L'"');
35   base::string16::size_type pos2 = string->find_last_not_of(L'"');
36
37   if (base::string16::npos == pos1 || base::string16::npos == pos2)
38     (*string) = L"";
39   else
40     (*string) = string->substr(pos1, pos2 + 1);
41 }
42
43 int TestOpenFile(base::string16 path, bool for_write) {
44   wchar_t path_expanded[MAX_PATH + 1] = {0};
45   DWORD size = ::ExpandEnvironmentStrings(path.c_str(), path_expanded,
46                                           MAX_PATH);
47   if (!size)
48     return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
49
50   HANDLE file;
51   file = ::CreateFile(path_expanded,
52                       for_write ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ,
53                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
54                       NULL,  // No security attributes.
55                       OPEN_EXISTING,
56                       FILE_FLAG_BACKUP_SEMANTICS,
57                       NULL);  // No template.
58
59   if (INVALID_HANDLE_VALUE != file) {
60     ::CloseHandle(file);
61     return sandbox::SBOX_TEST_SUCCEEDED;
62   } else {
63     if (ERROR_ACCESS_DENIED == ::GetLastError()) {
64       return sandbox::SBOX_TEST_DENIED;
65     } else {
66       return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
67     }
68   }
69 }
70
71 }  // namespace
72
73 namespace sandbox {
74
75 SBOX_TESTS_COMMAND int ValidWindow(int argc, wchar_t **argv) {
76   if (1 != argc)
77     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
78
79   HWND window = reinterpret_cast<HWND>(static_cast<ULONG_PTR>(_wtoi(argv[0])));
80
81   return TestValidWindow(window);
82 }
83
84 int TestValidWindow(HWND window) {
85   if (::IsWindow(window))
86     return SBOX_TEST_SUCCEEDED;
87
88   return SBOX_TEST_DENIED;
89 }
90
91 SBOX_TESTS_COMMAND int OpenProcessCmd(int argc, wchar_t **argv) {
92   if (2 != argc)
93     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
94
95   DWORD process_id = _wtol(argv[0]);
96   DWORD access_mask = _wtol(argv[1]);
97   return TestOpenProcess(process_id, access_mask);
98 }
99
100 int TestOpenProcess(DWORD process_id, DWORD access_mask) {
101   HANDLE process = ::OpenProcess(access_mask,
102                                  FALSE,  // Do not inherit handle.
103                                  process_id);
104   if (NULL == process) {
105     if (ERROR_ACCESS_DENIED == ::GetLastError()) {
106       return SBOX_TEST_DENIED;
107     } else {
108       return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
109     }
110   } else {
111     ::CloseHandle(process);
112     return SBOX_TEST_SUCCEEDED;
113   }
114 }
115
116 SBOX_TESTS_COMMAND int OpenThreadCmd(int argc, wchar_t **argv) {
117   if (1 != argc)
118     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
119
120   DWORD thread_id = _wtoi(argv[0]);
121   return TestOpenThread(thread_id);
122 }
123
124 int TestOpenThread(DWORD thread_id) {
125
126   HANDLE thread = ::OpenThread(THREAD_QUERY_INFORMATION,
127                                FALSE,  // Do not inherit handles.
128                                thread_id);
129
130   if (NULL == thread) {
131     if (ERROR_ACCESS_DENIED == ::GetLastError()) {
132       return SBOX_TEST_DENIED;
133     } else {
134       return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
135     }
136   } else {
137     ::CloseHandle(thread);
138     return SBOX_TEST_SUCCEEDED;
139   }
140 }
141
142 SBOX_TESTS_COMMAND int OpenFileCmd(int argc, wchar_t **argv) {
143   if (1 != argc)
144     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
145
146   base::string16 path = argv[0];
147   trim_quote(&path);
148
149   return TestOpenReadFile(path);
150 }
151
152 int TestOpenReadFile(const base::string16& path) {
153   return TestOpenFile(path, false);
154 }
155
156 int TestOpenWriteFile(int argc, wchar_t **argv) {
157   if (1 != argc)
158     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
159
160   base::string16 path = argv[0];
161   trim_quote(&path);
162
163   return TestOpenWriteFile(path);
164 }
165
166 int TestOpenWriteFile(const base::string16& path) {
167   return TestOpenFile(path, true);
168 }
169
170 SBOX_TESTS_COMMAND int OpenKey(int argc, wchar_t **argv) {
171   if (0 == argc || argc > 2)
172     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
173
174   // Get the hive.
175   HKEY base_key = GetHKEYFromString(argv[0]);
176
177   // Get the subkey.
178   base::string16 subkey;
179   if (2 == argc) {
180     subkey = argv[1];
181     trim_quote(&subkey);
182   }
183
184   return TestOpenKey(base_key, subkey);
185 }
186
187 int TestOpenKey(HKEY base_key, base::string16 subkey) {
188   HKEY key;
189   LONG err_code = ::RegOpenKeyEx(base_key,
190                                  subkey.c_str(),
191                                  0,  // Reserved, must be 0.
192                                  MAXIMUM_ALLOWED,
193                                  &key);
194   if (ERROR_SUCCESS == err_code) {
195     ::RegCloseKey(key);
196     return SBOX_TEST_SUCCEEDED;
197   } else if (ERROR_INVALID_HANDLE == err_code ||
198              ERROR_ACCESS_DENIED  == err_code) {
199     return SBOX_TEST_DENIED;
200   } else {
201     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
202   }
203 }
204
205 // Returns true if the current's thread desktop is the interactive desktop.
206 // In Vista there is a more direct test but for XP and w2k we need to check
207 // the object name.
208 bool IsInteractiveDesktop(bool* is_interactive) {
209   HDESK current_desk = ::GetThreadDesktop(::GetCurrentThreadId());
210   if (NULL == current_desk) {
211     return false;
212   }
213   wchar_t current_desk_name[256] = {0};
214   if (!::GetUserObjectInformationW(current_desk, UOI_NAME, current_desk_name,
215                                   sizeof(current_desk_name), NULL)) {
216     return false;
217   }
218   *is_interactive = (0 == _wcsicmp(L"default", current_desk_name));
219   return true;
220 }
221
222 SBOX_TESTS_COMMAND int OpenInteractiveDesktop(int, wchar_t **) {
223   return TestOpenInputDesktop();
224 }
225
226 int TestOpenInputDesktop() {
227   bool is_interactive = false;
228   if (IsInteractiveDesktop(&is_interactive) && is_interactive) {
229     return SBOX_TEST_SUCCEEDED;
230   }
231   HDESK desk = ::OpenInputDesktop(0, FALSE, DESKTOP_CREATEWINDOW);
232   if (desk) {
233     ::CloseDesktop(desk);
234     return SBOX_TEST_SUCCEEDED;
235   }
236   return SBOX_TEST_DENIED;
237 }
238
239 SBOX_TESTS_COMMAND int SwitchToSboxDesktop(int, wchar_t **) {
240   return TestSwitchDesktop();
241 }
242
243 int TestSwitchDesktop() {
244   HDESK desktop = ::GetThreadDesktop(::GetCurrentThreadId());
245   if (NULL == desktop) {
246     return SBOX_TEST_FAILED;
247   }
248   if (::SwitchDesktop(desktop)) {
249     return SBOX_TEST_SUCCEEDED;
250   }
251   return SBOX_TEST_DENIED;
252 }
253
254 SBOX_TESTS_COMMAND int OpenAlternateDesktop(int, wchar_t **argv) {
255   return TestOpenAlternateDesktop(argv[0]);
256 }
257
258 int TestOpenAlternateDesktop(wchar_t *desktop_name) {
259   // Test for WRITE_DAC permission on the handle.
260   HDESK desktop = ::GetThreadDesktop(::GetCurrentThreadId());
261   if (desktop) {
262     HANDLE test_handle;
263     if (::DuplicateHandle(::GetCurrentProcess(), desktop,
264                           ::GetCurrentProcess(), &test_handle,
265                           WRITE_DAC, FALSE, 0)) {
266       DWORD result = ::SetSecurityInfo(test_handle, SE_WINDOW_OBJECT,
267                                        DACL_SECURITY_INFORMATION, NULL, NULL,
268                                        NULL, NULL);
269       ::CloseHandle(test_handle);
270       if (result != ERROR_ACCESS_DENIED) {
271         return SBOX_TEST_SUCCEEDED;
272       }
273     } else if (::GetLastError() != ERROR_ACCESS_DENIED) {
274       return SBOX_TEST_FAILED;
275     }
276   }
277
278   // Open by name with WRITE_DAC.
279   desktop = ::OpenDesktop(desktop_name, 0, FALSE, WRITE_DAC);
280   if (desktop || ::GetLastError() != ERROR_ACCESS_DENIED) {
281     ::CloseDesktop(desktop);
282     return SBOX_TEST_SUCCEEDED;
283   }
284
285   return SBOX_TEST_DENIED;
286 }
287
288 BOOL CALLBACK DesktopTestEnumProc(LPTSTR desktop_name, LPARAM result) {
289   return TRUE;
290 }
291
292 SBOX_TESTS_COMMAND int EnumAlternateWinsta(int, wchar_t **) {
293   return TestEnumAlternateWinsta();
294 }
295
296 int TestEnumAlternateWinsta() {
297   int result = SBOX_TEST_DENIED;
298   // Try to enumerate the destops on the alternate windowstation.
299   if (::EnumDesktopsW(NULL, DesktopTestEnumProc, 0)) {
300     return SBOX_TEST_SUCCEEDED;
301   }
302   return SBOX_TEST_DENIED;
303 }
304
305 SBOX_TESTS_COMMAND int SleepCmd(int argc, wchar_t **argv) {
306   if (1 != argc)
307     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
308
309   ::Sleep(_wtoi(argv[0]));
310   return SBOX_TEST_SUCCEEDED;
311 }
312
313 SBOX_TESTS_COMMAND int AllocateCmd(int argc, wchar_t **argv) {
314   if (argc != 1)
315     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
316
317   size_t mem_size = static_cast<size_t>(_wtoll(argv[0]));
318   void* memory = ::VirtualAlloc(NULL, mem_size, MEM_COMMIT | MEM_RESERVE,
319                                 PAGE_READWRITE);
320   if (!memory) {
321     // We need to give the broker a chance to kill our process on failure.
322     ::Sleep(5000);
323     return SBOX_TEST_DENIED;
324   }
325
326   if (!::VirtualFree(memory, 0, MEM_RELEASE))
327     return SBOX_TEST_FAILED;
328
329   return SBOX_TEST_SUCCEEDED;
330 }
331
332
333 }  // namespace sandbox