OLD | NEW |
| (Empty) |
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 <windows.h> | |
6 #include <string> | |
7 | |
8 #include "sandbox/tests/validation_tests/commands.h" | |
9 | |
10 #include "sandbox/tests/common/controller.h" | |
11 | |
12 namespace { | |
13 | |
14 // Returns the HKEY corresponding to name. If there is no HKEY corresponding | |
15 // to the name it returns NULL. | |
16 HKEY GetHKEYFromString(const std::wstring &name) { | |
17 if (L"HKLM" == name) | |
18 return HKEY_LOCAL_MACHINE; | |
19 else if (L"HKCR" == name) | |
20 return HKEY_CLASSES_ROOT; | |
21 else if (L"HKCC" == name) | |
22 return HKEY_CURRENT_CONFIG; | |
23 else if (L"HKCU" == name) | |
24 return HKEY_CURRENT_USER; | |
25 else if (L"HKU" == name) | |
26 return HKEY_USERS; | |
27 | |
28 return NULL; | |
29 } | |
30 | |
31 // Modifies string to remove the leading and trailing quotes. | |
32 void trim_quote(std::wstring* string) { | |
33 std::wstring::size_type pos1 = string->find_first_not_of(L'"'); | |
34 std::wstring::size_type pos2 = string->find_last_not_of(L'"'); | |
35 | |
36 if (std::wstring::npos == pos1 || std::wstring::npos == pos2) | |
37 (*string) = L""; | |
38 else | |
39 (*string) = string->substr(pos1, pos2 + 1); | |
40 } | |
41 | |
42 int TestOpenFile(std::wstring path, bool for_write) { | |
43 wchar_t path_expanded[MAX_PATH + 1] = {0}; | |
44 DWORD size = ::ExpandEnvironmentStrings(path.c_str(), path_expanded, | |
45 MAX_PATH); | |
46 if (!size) | |
47 return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
48 | |
49 HANDLE file; | |
50 file = ::CreateFile(path_expanded, | |
51 for_write ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ, | |
52 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | |
53 NULL, // No security attributes. | |
54 OPEN_EXISTING, | |
55 FILE_FLAG_BACKUP_SEMANTICS, | |
56 NULL); // No template. | |
57 | |
58 if (INVALID_HANDLE_VALUE != file) { | |
59 ::CloseHandle(file); | |
60 return sandbox::SBOX_TEST_SUCCEEDED; | |
61 } else { | |
62 if (ERROR_ACCESS_DENIED == ::GetLastError()) { | |
63 return sandbox::SBOX_TEST_DENIED; | |
64 } else { | |
65 return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
66 } | |
67 } | |
68 } | |
69 | |
70 } // namespace | |
71 | |
72 namespace sandbox { | |
73 | |
74 SBOX_TESTS_COMMAND int ValidWindow(int argc, wchar_t **argv) { | |
75 if (1 != argc) | |
76 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
77 | |
78 HWND window = reinterpret_cast<HWND>(static_cast<ULONG_PTR>(_wtoi(argv[0]))); | |
79 | |
80 return TestValidWindow(window); | |
81 } | |
82 | |
83 int TestValidWindow(HWND window) { | |
84 if (::IsWindow(window)) | |
85 return SBOX_TEST_SUCCEEDED; | |
86 | |
87 return SBOX_TEST_DENIED; | |
88 } | |
89 | |
90 SBOX_TESTS_COMMAND int OpenProcessCmd(int argc, wchar_t **argv) { | |
91 if (2 != argc) | |
92 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
93 | |
94 DWORD process_id = _wtol(argv[0]); | |
95 DWORD access_mask = _wtol(argv[1]); | |
96 return TestOpenProcess(process_id, access_mask); | |
97 } | |
98 | |
99 int TestOpenProcess(DWORD process_id, DWORD access_mask) { | |
100 HANDLE process = ::OpenProcess(access_mask, | |
101 FALSE, // Do not inherit handle. | |
102 process_id); | |
103 if (NULL == process) { | |
104 if (ERROR_ACCESS_DENIED == ::GetLastError()) { | |
105 return SBOX_TEST_DENIED; | |
106 } else { | |
107 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
108 } | |
109 } else { | |
110 ::CloseHandle(process); | |
111 return SBOX_TEST_SUCCEEDED; | |
112 } | |
113 } | |
114 | |
115 SBOX_TESTS_COMMAND int OpenThreadCmd(int argc, wchar_t **argv) { | |
116 if (1 != argc) | |
117 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
118 | |
119 DWORD thread_id = _wtoi(argv[0]); | |
120 return TestOpenThread(thread_id); | |
121 } | |
122 | |
123 int TestOpenThread(DWORD thread_id) { | |
124 | |
125 HANDLE thread = ::OpenThread(THREAD_QUERY_INFORMATION, | |
126 FALSE, // Do not inherit handles. | |
127 thread_id); | |
128 | |
129 if (NULL == thread) { | |
130 if (ERROR_ACCESS_DENIED == ::GetLastError()) { | |
131 return SBOX_TEST_DENIED; | |
132 } else { | |
133 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
134 } | |
135 } else { | |
136 ::CloseHandle(thread); | |
137 return SBOX_TEST_SUCCEEDED; | |
138 } | |
139 } | |
140 | |
141 SBOX_TESTS_COMMAND int OpenFile(int argc, wchar_t **argv) { | |
142 if (1 != argc) | |
143 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
144 | |
145 std::wstring path = argv[0]; | |
146 trim_quote(&path); | |
147 | |
148 return TestOpenReadFile(path); | |
149 } | |
150 | |
151 int TestOpenReadFile(const std::wstring& path) { | |
152 return TestOpenFile(path, false); | |
153 } | |
154 | |
155 int TestOpenWriteFile(int argc, wchar_t **argv) { | |
156 if (1 != argc) | |
157 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
158 | |
159 std::wstring path = argv[0]; | |
160 trim_quote(&path); | |
161 | |
162 return TestOpenWriteFile(path); | |
163 } | |
164 | |
165 int TestOpenWriteFile(const std::wstring& path) { | |
166 return TestOpenFile(path, true); | |
167 } | |
168 | |
169 SBOX_TESTS_COMMAND int OpenKey(int argc, wchar_t **argv) { | |
170 if (0 == argc || argc > 2) | |
171 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
172 | |
173 // Get the hive. | |
174 HKEY base_key = GetHKEYFromString(argv[0]); | |
175 | |
176 // Get the subkey. | |
177 std::wstring subkey; | |
178 if (2 == argc) { | |
179 subkey = argv[1]; | |
180 trim_quote(&subkey); | |
181 } | |
182 | |
183 return TestOpenKey(base_key, subkey); | |
184 } | |
185 | |
186 int TestOpenKey(HKEY base_key, std::wstring subkey) { | |
187 HKEY key; | |
188 LONG err_code = ::RegOpenKeyEx(base_key, | |
189 subkey.c_str(), | |
190 0, // Reserved, must be 0. | |
191 MAXIMUM_ALLOWED, | |
192 &key); | |
193 if (ERROR_SUCCESS == err_code) { | |
194 ::RegCloseKey(key); | |
195 return SBOX_TEST_SUCCEEDED; | |
196 } else if (ERROR_INVALID_HANDLE == err_code || | |
197 ERROR_ACCESS_DENIED == err_code) { | |
198 return SBOX_TEST_DENIED; | |
199 } else { | |
200 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
201 } | |
202 } | |
203 | |
204 // Returns true if the current's thread desktop is the interactive desktop. | |
205 // In Vista there is a more direct test but for XP and w2k we need to check | |
206 // the object name. | |
207 bool IsInteractiveDesktop(bool* is_interactive) { | |
208 HDESK current_desk = ::GetThreadDesktop(::GetCurrentThreadId()); | |
209 if (NULL == current_desk) { | |
210 return false; | |
211 } | |
212 wchar_t current_desk_name[256] = {0}; | |
213 if (!::GetUserObjectInformationW(current_desk, UOI_NAME, current_desk_name, | |
214 sizeof(current_desk_name), NULL)) { | |
215 return false; | |
216 } | |
217 *is_interactive = (0 == _wcsicmp(L"default", current_desk_name)); | |
218 return true; | |
219 } | |
220 | |
221 SBOX_TESTS_COMMAND int OpenInteractiveDesktop(int, wchar_t **) { | |
222 return TestOpenInputDesktop(); | |
223 } | |
224 | |
225 int TestOpenInputDesktop() { | |
226 bool is_interactive = false; | |
227 if (IsInteractiveDesktop(&is_interactive) && is_interactive) { | |
228 return SBOX_TEST_SUCCEEDED; | |
229 } | |
230 HDESK desk = ::OpenInputDesktop(0, FALSE, DESKTOP_CREATEWINDOW); | |
231 if (desk) { | |
232 ::CloseDesktop(desk); | |
233 return SBOX_TEST_SUCCEEDED; | |
234 } | |
235 return SBOX_TEST_DENIED; | |
236 } | |
237 | |
238 SBOX_TESTS_COMMAND int SwitchToSboxDesktop(int, wchar_t **) { | |
239 return TestSwitchDesktop(); | |
240 } | |
241 | |
242 int TestSwitchDesktop() { | |
243 HDESK sbox_desk = ::GetThreadDesktop(::GetCurrentThreadId()); | |
244 if (NULL == sbox_desk) { | |
245 return SBOX_TEST_FAILED; | |
246 } | |
247 if (::SwitchDesktop(sbox_desk)) { | |
248 return SBOX_TEST_SUCCEEDED; | |
249 } | |
250 return SBOX_TEST_DENIED; | |
251 } | |
252 | |
253 SBOX_TESTS_COMMAND int SleepCmd(int argc, wchar_t **argv) { | |
254 if (1 != argc) | |
255 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | |
256 | |
257 ::Sleep(_wtoi(argv[0])); | |
258 return SBOX_TEST_SUCCEEDED; | |
259 } | |
260 | |
261 | |
262 } // namespace sandbox | |
OLD | NEW |