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
;
21 return HKEY_CLASSES_ROOT
;
23 return HKEY_CURRENT_CONFIG
;
25 return HKEY_CURRENT_USER
;
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 (pos1
== base::string16::npos
|| pos2
== base::string16::npos
)
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 (file
!= INVALID_HANDLE_VALUE
) {
61 return sandbox::SBOX_TEST_SUCCEEDED
;
63 return (::GetLastError() == ERROR_ACCESS_DENIED
) ?
64 sandbox::SBOX_TEST_DENIED
: sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
71 SBOX_TESTS_COMMAND
int ValidWindow(int argc
, wchar_t **argv
) {
74 reinterpret_cast<HWND
>(static_cast<ULONG_PTR
>(_wtoi(argv
[0])))) :
75 SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
78 int TestValidWindow(HWND window
) {
79 return ::IsWindow(window
) ? SBOX_TEST_SUCCEEDED
: SBOX_TEST_DENIED
;
82 SBOX_TESTS_COMMAND
int OpenProcessCmd(int argc
, wchar_t **argv
) {
84 TestOpenProcess(_wtol(argv
[0]), _wtol(argv
[1])) :
85 SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
88 int TestOpenProcess(DWORD process_id
, DWORD access_mask
) {
89 HANDLE process
= ::OpenProcess(access_mask
,
90 FALSE
, // Do not inherit handle.
92 if (process
!= NULL
) {
93 ::CloseHandle(process
);
94 return SBOX_TEST_SUCCEEDED
;
96 return (::GetLastError() == ERROR_ACCESS_DENIED
) ?
97 sandbox::SBOX_TEST_DENIED
: sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
100 SBOX_TESTS_COMMAND
int OpenThreadCmd(int argc
, wchar_t **argv
) {
102 TestOpenThread(_wtoi(argv
[0])) : SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
105 int TestOpenThread(DWORD thread_id
) {
106 HANDLE thread
= ::OpenThread(THREAD_QUERY_INFORMATION
,
107 FALSE
, // Do not inherit handles.
109 if (thread
!= NULL
) {
110 ::CloseHandle(thread
);
111 return SBOX_TEST_SUCCEEDED
;
113 return (::GetLastError() == ERROR_ACCESS_DENIED
) ?
114 sandbox::SBOX_TEST_DENIED
: sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
117 SBOX_TESTS_COMMAND
int OpenFileCmd(int argc
, wchar_t **argv
) {
119 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
121 base::string16 path
= argv
[0];
124 return TestOpenReadFile(path
);
127 int TestOpenReadFile(const base::string16
& path
) {
128 return TestOpenFile(path
, false);
131 int TestOpenWriteFile(int argc
, wchar_t **argv
) {
133 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
135 base::string16 path
= argv
[0];
137 return TestOpenWriteFile(path
);
140 int TestOpenWriteFile(const base::string16
& path
) {
141 return TestOpenFile(path
, true);
144 SBOX_TESTS_COMMAND
int OpenKey(int argc
, wchar_t **argv
) {
145 if (argc
!= 1 && argc
!= 2)
146 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
149 HKEY base_key
= GetHKEYFromString(argv
[0]);
152 base::string16 subkey
;
158 return TestOpenKey(base_key
, subkey
);
161 int TestOpenKey(HKEY base_key
, base::string16 subkey
) {
163 LONG err_code
= ::RegOpenKeyEx(base_key
,
165 0, // Reserved, must be 0.
168 if (err_code
== ERROR_SUCCESS
) {
170 return SBOX_TEST_SUCCEEDED
;
172 return (err_code
== ERROR_INVALID_HANDLE
|| err_code
== ERROR_ACCESS_DENIED
) ?
173 SBOX_TEST_DENIED
: SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
176 // Returns true if the current's thread desktop is the interactive desktop.
177 // In Vista there is a more direct test but for XP and w2k we need to check
179 bool IsInteractiveDesktop(bool* is_interactive
) {
180 HDESK current_desk
= ::GetThreadDesktop(::GetCurrentThreadId());
181 if (current_desk
== NULL
)
183 wchar_t current_desk_name
[256] = {0};
184 if (!::GetUserObjectInformationW(current_desk
, UOI_NAME
, current_desk_name
,
185 sizeof(current_desk_name
), NULL
))
187 *is_interactive
= (0 == _wcsicmp(L
"default", current_desk_name
));
191 SBOX_TESTS_COMMAND
int OpenInteractiveDesktop(int, wchar_t **) {
192 return TestOpenInputDesktop();
195 int TestOpenInputDesktop() {
196 bool is_interactive
= false;
197 if (IsInteractiveDesktop(&is_interactive
) && is_interactive
)
198 return SBOX_TEST_SUCCEEDED
;
199 HDESK desk
= ::OpenInputDesktop(0, FALSE
, DESKTOP_CREATEWINDOW
);
201 ::CloseDesktop(desk
);
202 return SBOX_TEST_SUCCEEDED
;
204 return SBOX_TEST_DENIED
;
207 SBOX_TESTS_COMMAND
int SwitchToSboxDesktop(int, wchar_t **) {
208 return TestSwitchDesktop();
211 int TestSwitchDesktop() {
212 HDESK desktop
= ::GetThreadDesktop(::GetCurrentThreadId());
214 return SBOX_TEST_FAILED
;
215 return ::SwitchDesktop(desktop
) ? SBOX_TEST_SUCCEEDED
: SBOX_TEST_DENIED
;
218 SBOX_TESTS_COMMAND
int OpenAlternateDesktop(int, wchar_t **argv
) {
219 return TestOpenAlternateDesktop(argv
[0]);
222 int TestOpenAlternateDesktop(wchar_t *desktop_name
) {
223 // Test for WRITE_DAC permission on the handle.
224 HDESK desktop
= ::GetThreadDesktop(::GetCurrentThreadId());
227 if (::DuplicateHandle(::GetCurrentProcess(), desktop
,
228 ::GetCurrentProcess(), &test_handle
,
229 WRITE_DAC
, FALSE
, 0)) {
230 DWORD result
= ::SetSecurityInfo(test_handle
, SE_WINDOW_OBJECT
,
231 DACL_SECURITY_INFORMATION
, NULL
, NULL
,
233 ::CloseHandle(test_handle
);
234 if (result
== ERROR_SUCCESS
)
235 return SBOX_TEST_SUCCEEDED
;
236 } else if (::GetLastError() != ERROR_ACCESS_DENIED
) {
237 return SBOX_TEST_FAILED
;
241 // Open by name with WRITE_DAC.
242 desktop
= ::OpenDesktop(desktop_name
, 0, FALSE
, WRITE_DAC
);
243 if (!desktop
&& ::GetLastError() == ERROR_ACCESS_DENIED
)
244 return SBOX_TEST_DENIED
;
245 ::CloseDesktop(desktop
);
246 return SBOX_TEST_SUCCEEDED
;
249 BOOL CALLBACK
DesktopTestEnumProc(LPTSTR desktop_name
, LPARAM result
) {
253 SBOX_TESTS_COMMAND
int EnumAlternateWinsta(int, wchar_t **) {
254 return TestEnumAlternateWinsta();
257 int TestEnumAlternateWinsta() {
258 // Try to enumerate the destops on the alternate windowstation.
259 return ::EnumDesktopsW(NULL
, DesktopTestEnumProc
, 0) ?
260 SBOX_TEST_SUCCEEDED
: SBOX_TEST_DENIED
;
263 SBOX_TESTS_COMMAND
int SleepCmd(int argc
, wchar_t **argv
) {
265 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
267 ::Sleep(_wtoi(argv
[0]));
268 return SBOX_TEST_SUCCEEDED
;
271 SBOX_TESTS_COMMAND
int AllocateCmd(int argc
, wchar_t **argv
) {
273 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND
;
275 size_t mem_size
= static_cast<size_t>(_wtoll(argv
[0]));
276 void* memory
= ::VirtualAlloc(NULL
, mem_size
, MEM_COMMIT
| MEM_RESERVE
,
279 // We need to give the broker a chance to kill our process on failure.
281 return SBOX_TEST_DENIED
;
284 return ::VirtualFree(memory
, 0, MEM_RELEASE
) ?
285 SBOX_TEST_SUCCEEDED
: SBOX_TEST_FAILED
;
289 } // namespace sandbox