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.
9 #include "sandbox/win/tests/validation_tests/commands.h"
11 #include "sandbox/win/tests/common/controller.h"
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) {
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)
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'"');
37 if (base::string16::npos == pos1 || base::string16::npos == pos2)
40 (*string) = string->substr(pos1, pos2 + 1);
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,
48 return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
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.
56 FILE_FLAG_BACKUP_SEMANTICS,
57 NULL); // No template.
59 if (INVALID_HANDLE_VALUE != file) {
61 return sandbox::SBOX_TEST_SUCCEEDED;
63 if (ERROR_ACCESS_DENIED == ::GetLastError()) {
64 return sandbox::SBOX_TEST_DENIED;
66 return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
75 SBOX_TESTS_COMMAND int ValidWindow(int argc, wchar_t **argv) {
77 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
79 HWND window = reinterpret_cast<HWND>(static_cast<ULONG_PTR>(_wtoi(argv[0])));
81 return TestValidWindow(window);
84 int TestValidWindow(HWND window) {
85 if (::IsWindow(window))
86 return SBOX_TEST_SUCCEEDED;
88 return SBOX_TEST_DENIED;
91 SBOX_TESTS_COMMAND int OpenProcessCmd(int argc, wchar_t **argv) {
93 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
95 DWORD process_id = _wtol(argv[0]);
96 DWORD access_mask = _wtol(argv[1]);
97 return TestOpenProcess(process_id, access_mask);
100 int TestOpenProcess(DWORD process_id, DWORD access_mask) {
101 HANDLE process = ::OpenProcess(access_mask,
102 FALSE, // Do not inherit handle.
104 if (NULL == process) {
105 if (ERROR_ACCESS_DENIED == ::GetLastError()) {
106 return SBOX_TEST_DENIED;
108 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
111 ::CloseHandle(process);
112 return SBOX_TEST_SUCCEEDED;
116 SBOX_TESTS_COMMAND int OpenThreadCmd(int argc, wchar_t **argv) {
118 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
120 DWORD thread_id = _wtoi(argv[0]);
121 return TestOpenThread(thread_id);
124 int TestOpenThread(DWORD thread_id) {
126 HANDLE thread = ::OpenThread(THREAD_QUERY_INFORMATION,
127 FALSE, // Do not inherit handles.
130 if (NULL == thread) {
131 if (ERROR_ACCESS_DENIED == ::GetLastError()) {
132 return SBOX_TEST_DENIED;
134 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
137 ::CloseHandle(thread);
138 return SBOX_TEST_SUCCEEDED;
142 SBOX_TESTS_COMMAND int OpenFileCmd(int argc, wchar_t **argv) {
144 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
146 base::string16 path = argv[0];
149 return TestOpenReadFile(path);
152 int TestOpenReadFile(const base::string16& path) {
153 return TestOpenFile(path, false);
156 int TestOpenWriteFile(int argc, wchar_t **argv) {
158 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
160 base::string16 path = argv[0];
163 return TestOpenWriteFile(path);
166 int TestOpenWriteFile(const base::string16& path) {
167 return TestOpenFile(path, true);
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;
175 HKEY base_key = GetHKEYFromString(argv[0]);
178 base::string16 subkey;
184 return TestOpenKey(base_key, subkey);
187 int TestOpenKey(HKEY base_key, base::string16 subkey) {
189 LONG err_code = ::RegOpenKeyEx(base_key,
191 0, // Reserved, must be 0.
194 if (ERROR_SUCCESS == err_code) {
196 return SBOX_TEST_SUCCEEDED;
197 } else if (ERROR_INVALID_HANDLE == err_code ||
198 ERROR_ACCESS_DENIED == err_code) {
199 return SBOX_TEST_DENIED;
201 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
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
208 bool IsInteractiveDesktop(bool* is_interactive) {
209 HDESK current_desk = ::GetThreadDesktop(::GetCurrentThreadId());
210 if (NULL == current_desk) {
213 wchar_t current_desk_name[256] = {0};
214 if (!::GetUserObjectInformationW(current_desk, UOI_NAME, current_desk_name,
215 sizeof(current_desk_name), NULL)) {
218 *is_interactive = (0 == _wcsicmp(L"default", current_desk_name));
222 SBOX_TESTS_COMMAND int OpenInteractiveDesktop(int, wchar_t **) {
223 return TestOpenInputDesktop();
226 int TestOpenInputDesktop() {
227 bool is_interactive = false;
228 if (IsInteractiveDesktop(&is_interactive) && is_interactive) {
229 return SBOX_TEST_SUCCEEDED;
231 HDESK desk = ::OpenInputDesktop(0, FALSE, DESKTOP_CREATEWINDOW);
233 ::CloseDesktop(desk);
234 return SBOX_TEST_SUCCEEDED;
236 return SBOX_TEST_DENIED;
239 SBOX_TESTS_COMMAND int SwitchToSboxDesktop(int, wchar_t **) {
240 return TestSwitchDesktop();
243 int TestSwitchDesktop() {
244 HDESK desktop = ::GetThreadDesktop(::GetCurrentThreadId());
245 if (NULL == desktop) {
246 return SBOX_TEST_FAILED;
248 if (::SwitchDesktop(desktop)) {
249 return SBOX_TEST_SUCCEEDED;
251 return SBOX_TEST_DENIED;
254 SBOX_TESTS_COMMAND int OpenAlternateDesktop(int, wchar_t **argv) {
255 return TestOpenAlternateDesktop(argv[0]);
258 int TestOpenAlternateDesktop(wchar_t *desktop_name) {
259 // Test for WRITE_DAC permission on the handle.
260 HDESK desktop = ::GetThreadDesktop(::GetCurrentThreadId());
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,
269 ::CloseHandle(test_handle);
270 if (result != ERROR_ACCESS_DENIED) {
271 return SBOX_TEST_SUCCEEDED;
273 } else if (::GetLastError() != ERROR_ACCESS_DENIED) {
274 return SBOX_TEST_FAILED;
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;
285 return SBOX_TEST_DENIED;
288 BOOL CALLBACK DesktopTestEnumProc(LPTSTR desktop_name, LPARAM result) {
292 SBOX_TESTS_COMMAND int EnumAlternateWinsta(int, wchar_t **) {
293 return TestEnumAlternateWinsta();
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;
302 return SBOX_TEST_DENIED;
305 SBOX_TESTS_COMMAND int SleepCmd(int argc, wchar_t **argv) {
307 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
309 ::Sleep(_wtoi(argv[0]));
310 return SBOX_TEST_SUCCEEDED;
313 SBOX_TESTS_COMMAND int AllocateCmd(int argc, wchar_t **argv) {
315 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
317 size_t mem_size = static_cast<size_t>(_wtoll(argv[0]));
318 void* memory = ::VirtualAlloc(NULL, mem_size, MEM_COMMIT | MEM_RESERVE,
321 // We need to give the broker a chance to kill our process on failure.
323 return SBOX_TEST_DENIED;
326 if (!::VirtualFree(memory, 0, MEM_RELEASE))
327 return SBOX_TEST_FAILED;
329 return SBOX_TEST_SUCCEEDED;
333 } // namespace sandbox