Home | History | Annotate | Download | only in validation_tests
      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/win/tests/validation_tests/commands.h"
      9 
     10 #include "sandbox/win/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
    263