Added GetState, GetManagedProperties, CreateNetwork methods to WiFiService.
[chromium-blink-merge.git] / sandbox / win / src / policy_target_test.cc
blob1e29df2ab455854463acbf94e0db273f8ce09f37
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.
5 #include "base/win/scoped_process_information.h"
6 #include "base/win/windows_version.h"
7 #include "sandbox/win/src/sandbox.h"
8 #include "sandbox/win/src/sandbox_factory.h"
9 #include "sandbox/win/src/sandbox_utils.h"
10 #include "sandbox/win/src/target_services.h"
11 #include "sandbox/win/tests/common/controller.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 namespace sandbox {
16 #define BINDNTDLL(name) \
17 name ## Function name = reinterpret_cast<name ## Function>( \
18 ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name))
20 // Reverts to self and verify that SetInformationToken was faked. Returns
21 // SBOX_TEST_SUCCEEDED if faked and SBOX_TEST_FAILED if not faked.
22 SBOX_TESTS_COMMAND int PolicyTargetTest_token(int argc, wchar_t **argv) {
23 HANDLE thread_token;
24 // Get the thread token, using impersonation.
25 if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE |
26 TOKEN_DUPLICATE, FALSE, &thread_token))
27 return ::GetLastError();
29 ::RevertToSelf();
30 ::CloseHandle(thread_token);
32 int ret = SBOX_TEST_FAILED;
33 if (::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
34 FALSE, &thread_token)) {
35 ret = SBOX_TEST_SUCCEEDED;
36 ::CloseHandle(thread_token);
38 return ret;
41 // Stores the high privilege token on a static variable, change impersonation
42 // again to that one and verify that we are not interfering anymore with
43 // RevertToSelf.
44 SBOX_TESTS_COMMAND int PolicyTargetTest_steal(int argc, wchar_t **argv) {
45 static HANDLE thread_token;
46 if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) {
47 if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE |
48 TOKEN_DUPLICATE, FALSE, &thread_token))
49 return ::GetLastError();
50 } else {
51 if (!::SetThreadToken(NULL, thread_token))
52 return ::GetLastError();
54 // See if we fake the call again.
55 int ret = PolicyTargetTest_token(argc, argv);
56 ::CloseHandle(thread_token);
57 return ret;
59 return 0;
62 // Opens the thread token with and without impersonation.
63 SBOX_TESTS_COMMAND int PolicyTargetTest_token2(int argc, wchar_t **argv) {
64 HANDLE thread_token;
65 // Get the thread token, using impersonation.
66 if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE |
67 TOKEN_DUPLICATE, FALSE, &thread_token))
68 return ::GetLastError();
69 ::CloseHandle(thread_token);
71 // Get the thread token, without impersonation.
72 if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
73 TRUE, &thread_token))
74 return ::GetLastError();
75 ::CloseHandle(thread_token);
76 return SBOX_TEST_SUCCEEDED;
79 // Opens the thread token with and without impersonation, using
80 // NtOpenThreadTokenEX.
81 SBOX_TESTS_COMMAND int PolicyTargetTest_token3(int argc, wchar_t **argv) {
82 BINDNTDLL(NtOpenThreadTokenEx);
83 if (!NtOpenThreadTokenEx)
84 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
86 HANDLE thread_token;
87 // Get the thread token, using impersonation.
88 NTSTATUS status = NtOpenThreadTokenEx(GetCurrentThread(),
89 TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
90 FALSE, 0, &thread_token);
91 if (status == STATUS_NO_TOKEN)
92 return ERROR_NO_TOKEN;
93 if (!NT_SUCCESS(status))
94 return SBOX_TEST_FAILED;
96 ::CloseHandle(thread_token);
98 // Get the thread token, without impersonation.
99 status = NtOpenThreadTokenEx(GetCurrentThread(),
100 TOKEN_IMPERSONATE | TOKEN_DUPLICATE, TRUE, 0,
101 &thread_token);
102 if (!NT_SUCCESS(status))
103 return SBOX_TEST_FAILED;
105 ::CloseHandle(thread_token);
106 return SBOX_TEST_SUCCEEDED;
109 // Tests that we can open the current thread.
110 SBOX_TESTS_COMMAND int PolicyTargetTest_thread(int argc, wchar_t **argv) {
111 DWORD thread_id = ::GetCurrentThreadId();
112 HANDLE thread = ::OpenThread(SYNCHRONIZE, FALSE, thread_id);
113 if (!thread)
114 return ::GetLastError();
115 if (!::CloseHandle(thread))
116 return ::GetLastError();
118 return SBOX_TEST_SUCCEEDED;
121 // New thread entry point: do nothing.
122 DWORD WINAPI PolicyTargetTest_thread_main(void* param) {
123 ::Sleep(INFINITE);
124 return 0;
127 // Tests that we can create a new thread, and open it.
128 SBOX_TESTS_COMMAND int PolicyTargetTest_thread2(int argc, wchar_t **argv) {
129 // Use default values to create a new thread.
130 DWORD thread_id;
131 HANDLE thread = ::CreateThread(NULL, 0, &PolicyTargetTest_thread_main, 0, 0,
132 &thread_id);
133 if (!thread)
134 return ::GetLastError();
135 if (!::CloseHandle(thread))
136 return ::GetLastError();
138 thread = ::OpenThread(SYNCHRONIZE, FALSE, thread_id);
139 if (!thread)
140 return ::GetLastError();
142 if (!::CloseHandle(thread))
143 return ::GetLastError();
145 return SBOX_TEST_SUCCEEDED;
148 // Tests that we can call CreateProcess.
149 SBOX_TESTS_COMMAND int PolicyTargetTest_process(int argc, wchar_t **argv) {
150 // Use default values to create a new process.
151 STARTUPINFO startup_info = {0};
152 startup_info.cb = sizeof(startup_info);
153 PROCESS_INFORMATION temp_process_info = {};
154 if (!::CreateProcessW(L"foo.exe", L"foo.exe", NULL, NULL, FALSE, 0,
155 NULL, NULL, &startup_info, &temp_process_info))
156 return SBOX_TEST_SUCCEEDED;
157 base::win::ScopedProcessInformation process_info(temp_process_info);
158 return SBOX_TEST_FAILED;
161 TEST(PolicyTargetTest, SetInformationThread) {
162 TestRunner runner;
163 if (base::win::GetVersion() >= base::win::VERSION_XP) {
164 runner.SetTestState(BEFORE_REVERT);
165 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token"));
168 runner.SetTestState(AFTER_REVERT);
169 EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token"));
171 runner.SetTestState(EVERY_STATE);
172 if (base::win::GetVersion() >= base::win::VERSION_XP)
173 EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"PolicyTargetTest_steal"));
176 TEST(PolicyTargetTest, OpenThreadToken) {
177 TestRunner runner;
178 if (base::win::GetVersion() >= base::win::VERSION_XP) {
179 runner.SetTestState(BEFORE_REVERT);
180 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token2"));
183 runner.SetTestState(AFTER_REVERT);
184 EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token2"));
187 TEST(PolicyTargetTest, OpenThreadTokenEx) {
188 TestRunner runner;
189 if (base::win::GetVersion() < base::win::VERSION_XP)
190 return;
192 runner.SetTestState(BEFORE_REVERT);
193 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token3"));
195 runner.SetTestState(AFTER_REVERT);
196 EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token3"));
199 TEST(PolicyTargetTest, OpenThread) {
200 TestRunner runner;
201 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread")) <<
202 "Opens the current thread";
204 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread2")) <<
205 "Creates a new thread and opens it";
208 TEST(PolicyTargetTest, OpenProcess) {
209 TestRunner runner;
210 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_process")) <<
211 "Opens a process";
214 // Launches the app in the sandbox and ask it to wait in an
215 // infinite loop. Waits for 2 seconds and then check if the
216 // desktop associated with the app thread is not the same as the
217 // current desktop.
218 TEST(PolicyTargetTest, DesktopPolicy) {
219 BrokerServices* broker = GetBroker();
221 // Precreate the desktop.
222 TargetPolicy* temp_policy = broker->CreatePolicy();
223 temp_policy->CreateAlternateDesktop(false);
224 temp_policy->Release();
226 ASSERT_TRUE(broker != NULL);
228 // Get the path to the sandboxed app.
229 wchar_t prog_name[MAX_PATH];
230 GetModuleFileNameW(NULL, prog_name, MAX_PATH);
232 std::wstring arguments(L"\"");
233 arguments += prog_name;
234 arguments += L"\" -child 0 wait"; // Don't care about the "state" argument.
236 // Launch the app.
237 ResultCode result = SBOX_ALL_OK;
238 base::win::ScopedProcessInformation target;
240 TargetPolicy* policy = broker->CreatePolicy();
241 policy->SetAlternateDesktop(false);
242 policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
243 PROCESS_INFORMATION temp_process_info = {};
244 result = broker->SpawnTarget(prog_name, arguments.c_str(), policy,
245 &temp_process_info);
246 policy->Release();
248 EXPECT_EQ(SBOX_ALL_OK, result);
249 if (result == SBOX_ALL_OK)
250 target.Set(temp_process_info);
252 EXPECT_EQ(1, ::ResumeThread(target.thread_handle()));
254 EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(target.process_handle(), 2000));
256 EXPECT_NE(::GetThreadDesktop(target.thread_id()),
257 ::GetThreadDesktop(::GetCurrentThreadId()));
259 std::wstring desktop_name = policy->GetAlternateDesktop();
260 HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
261 EXPECT_TRUE(NULL != desk);
262 EXPECT_TRUE(::CloseDesktop(desk));
263 EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
265 ::WaitForSingleObject(target.process_handle(), INFINITE);
267 // Close the desktop handle.
268 temp_policy = broker->CreatePolicy();
269 temp_policy->DestroyAlternateDesktop();
270 temp_policy->Release();
272 // Make sure the desktop does not exist anymore.
273 desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
274 EXPECT_TRUE(NULL == desk);
277 // Launches the app in the sandbox and ask it to wait in an
278 // infinite loop. Waits for 2 seconds and then check if the
279 // winstation associated with the app thread is not the same as the
280 // current desktop.
281 TEST(PolicyTargetTest, WinstaPolicy) {
282 BrokerServices* broker = GetBroker();
284 // Precreate the desktop.
285 TargetPolicy* temp_policy = broker->CreatePolicy();
286 temp_policy->CreateAlternateDesktop(true);
287 temp_policy->Release();
289 ASSERT_TRUE(broker != NULL);
291 // Get the path to the sandboxed app.
292 wchar_t prog_name[MAX_PATH];
293 GetModuleFileNameW(NULL, prog_name, MAX_PATH);
295 std::wstring arguments(L"\"");
296 arguments += prog_name;
297 arguments += L"\" -child 0 wait"; // Don't care about the "state" argument.
299 // Launch the app.
300 ResultCode result = SBOX_ALL_OK;
301 base::win::ScopedProcessInformation target;
303 TargetPolicy* policy = broker->CreatePolicy();
304 policy->SetAlternateDesktop(true);
305 policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
306 PROCESS_INFORMATION temp_process_info = {};
307 result = broker->SpawnTarget(prog_name, arguments.c_str(), policy,
308 &temp_process_info);
309 policy->Release();
311 EXPECT_EQ(SBOX_ALL_OK, result);
312 if (result == SBOX_ALL_OK)
313 target.Set(temp_process_info);
315 EXPECT_EQ(1, ::ResumeThread(target.thread_handle()));
317 EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(target.process_handle(), 2000));
319 EXPECT_NE(::GetThreadDesktop(target.thread_id()),
320 ::GetThreadDesktop(::GetCurrentThreadId()));
322 std::wstring desktop_name = policy->GetAlternateDesktop();
323 ASSERT_FALSE(desktop_name.empty());
325 // Make sure there is a backslash, for the window station name.
326 EXPECT_NE(desktop_name.find_first_of(L'\\'), std::wstring::npos);
328 // Isolate the desktop name.
329 desktop_name = desktop_name.substr(desktop_name.find_first_of(L'\\') + 1);
331 HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE);
332 // This should fail if the desktop is really on another window station.
333 EXPECT_FALSE(NULL != desk);
334 EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0));
336 ::WaitForSingleObject(target.process_handle(), INFINITE);
338 // Close the desktop handle.
339 temp_policy = broker->CreatePolicy();
340 temp_policy->DestroyAlternateDesktop();
341 temp_policy->Release();
344 } // namespace sandbox