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