1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/win/src/registry_policy_test.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,289 @@ 1.4 +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include <shlobj.h> 1.9 + 1.10 +#include "testing/gtest/include/gtest/gtest.h" 1.11 +#include "sandbox/win/src/registry_policy.h" 1.12 +#include "sandbox/win/src/sandbox.h" 1.13 +#include "sandbox/win/src/sandbox_policy.h" 1.14 +#include "sandbox/win/src/sandbox_factory.h" 1.15 +#include "sandbox/win/src/nt_internals.h" 1.16 +#include "sandbox/win/src/win_utils.h" 1.17 +#include "sandbox/win/tests/common/controller.h" 1.18 + 1.19 +namespace { 1.20 + 1.21 +static const DWORD kAllowedRegFlags = KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | 1.22 + KEY_NOTIFY | KEY_READ | GENERIC_READ | 1.23 + GENERIC_EXECUTE | READ_CONTROL; 1.24 + 1.25 +#define BINDNTDLL(name) \ 1.26 + name ## Function name = reinterpret_cast<name ## Function>( \ 1.27 + ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name)) 1.28 + 1.29 +bool IsKeyOpenForRead(HKEY handle) { 1.30 + BINDNTDLL(NtQueryObject); 1.31 + 1.32 + OBJECT_BASIC_INFORMATION info = {0}; 1.33 + NTSTATUS status = NtQueryObject(handle, ObjectBasicInformation, &info, 1.34 + sizeof(info), NULL); 1.35 + 1.36 + if (!NT_SUCCESS(status)) 1.37 + return false; 1.38 + 1.39 + if ((info.GrantedAccess & (~kAllowedRegFlags)) != 0) 1.40 + return false; 1.41 + return true; 1.42 +} 1.43 + 1.44 +} 1.45 + 1.46 +namespace sandbox { 1.47 + 1.48 +SBOX_TESTS_COMMAND int Reg_OpenKey(int argc, wchar_t **argv) { 1.49 + if (argc != 4) 1.50 + return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; 1.51 + 1.52 + REGSAM desired_access = 0; 1.53 + ULONG options = 0; 1.54 + if (wcscmp(argv[1], L"read") == 0) { 1.55 + desired_access = KEY_READ; 1.56 + } else if (wcscmp(argv[1], L"write") == 0) { 1.57 + desired_access = KEY_ALL_ACCESS; 1.58 + } else if (wcscmp(argv[1], L"link") == 0) { 1.59 + options = REG_OPTION_CREATE_LINK; 1.60 + desired_access = KEY_ALL_ACCESS; 1.61 + } else { 1.62 + desired_access = MAXIMUM_ALLOWED; 1.63 + } 1.64 + 1.65 + HKEY root = GetReservedKeyFromName(argv[2]); 1.66 + HKEY key; 1.67 + LRESULT result = 0; 1.68 + 1.69 + if (wcscmp(argv[0], L"create") == 0) 1.70 + result = ::RegCreateKeyEx(root, argv[3], 0, NULL, options, desired_access, 1.71 + NULL, &key, NULL); 1.72 + else 1.73 + result = ::RegOpenKeyEx(root, argv[3], 0, desired_access, &key); 1.74 + 1.75 + if (ERROR_SUCCESS == result) { 1.76 + if (MAXIMUM_ALLOWED == desired_access) { 1.77 + if (!IsKeyOpenForRead(key)) { 1.78 + ::RegCloseKey(key); 1.79 + return SBOX_TEST_FAILED; 1.80 + } 1.81 + } 1.82 + ::RegCloseKey(key); 1.83 + return SBOX_TEST_SUCCEEDED; 1.84 + } else if (ERROR_ACCESS_DENIED == result) { 1.85 + return SBOX_TEST_DENIED; 1.86 + } 1.87 + 1.88 + return SBOX_TEST_FAILED; 1.89 +} 1.90 + 1.91 +TEST(RegistryPolicyTest, TestKeyAnyAccess) { 1.92 + TestRunner runner; 1.93 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.94 + TargetPolicy::REG_ALLOW_READONLY, 1.95 + L"HKEY_LOCAL_MACHINE")); 1.96 + 1.97 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.98 + TargetPolicy::REG_ALLOW_ANY, 1.99 + L"HKEY_LOCAL_MACHINE\\Software\\Microsoft")); 1.100 + 1.101 + // Tests read access on key allowed for read-write. 1.102 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( 1.103 + L"Reg_OpenKey create read HKEY_LOCAL_MACHINE software\\microsoft")); 1.104 + 1.105 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( 1.106 + L"Reg_OpenKey open read HKEY_LOCAL_MACHINE software\\microsoft")); 1.107 + 1.108 + if (::IsUserAnAdmin()) { 1.109 + // Tests write access on key allowed for read-write. 1.110 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( 1.111 + L"Reg_OpenKey create write HKEY_LOCAL_MACHINE software\\microsoft")); 1.112 + 1.113 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( 1.114 + L"Reg_OpenKey open write HKEY_LOCAL_MACHINE software\\microsoft")); 1.115 + } 1.116 + 1.117 + // Tests subdirectory access on keys where we don't have subdirectory acess. 1.118 + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Reg_OpenKey create read " 1.119 + L"HKEY_LOCAL_MACHINE software\\microsoft\\Windows")); 1.120 + 1.121 + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Reg_OpenKey open read " 1.122 + L"HKEY_LOCAL_MACHINE software\\microsoft\\windows")); 1.123 + 1.124 + // Tests to see if we can create keys where we dont have subdirectory access. 1.125 + // This is denied. 1.126 + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Reg_OpenKey create write " 1.127 + L"HKEY_LOCAL_MACHINE software\\Microsoft\\google_unit_tests")); 1.128 + 1.129 + RegDeleteKey(HKEY_LOCAL_MACHINE, L"software\\Microsoft\\google_unit_tests"); 1.130 + 1.131 + // Tests if we need to handle differently the "\\" at the end. 1.132 + // This is denied. We need to add both rules. 1.133 + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( 1.134 + L"Reg_OpenKey create read HKEY_LOCAL_MACHINE software\\microsoft\\")); 1.135 + 1.136 + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( 1.137 + L"Reg_OpenKey open read HKEY_LOCAL_MACHINE software\\microsoft\\")); 1.138 +} 1.139 + 1.140 +TEST(RegistryPolicyTest, TestKeyNoAccess) { 1.141 + TestRunner runner; 1.142 + 1.143 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.144 + TargetPolicy::REG_ALLOW_READONLY, 1.145 + L"HKEY_LOCAL_MACHINE")); 1.146 + 1.147 + // Tests read access where we don't have access at all. 1.148 + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( 1.149 + L"Reg_OpenKey create read HKEY_LOCAL_MACHINE software")); 1.150 + 1.151 + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( 1.152 + L"Reg_OpenKey open read HKEY_LOCAL_MACHINE software")); 1.153 +} 1.154 + 1.155 +TEST(RegistryPolicyTest, TestKeyReadOnlyAccess) { 1.156 + TestRunner runner; 1.157 + 1.158 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.159 + TargetPolicy::REG_ALLOW_READONLY, 1.160 + L"HKEY_LOCAL_MACHINE")); 1.161 + 1.162 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.163 + TargetPolicy::REG_ALLOW_READONLY, 1.164 + L"HKEY_LOCAL_MACHINE\\Software\\Policies")); 1.165 + 1.166 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.167 + TargetPolicy::REG_ALLOW_READONLY, 1.168 + L"HKEY_LOCAL_MACHINE\\Software\\Policies\\*")); 1.169 + 1.170 + // Tests subdirectory acess on keys where we have subdirectory acess. 1.171 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Reg_OpenKey create read " 1.172 + L"HKEY_LOCAL_MACHINE software\\Policies\\microsoft")); 1.173 + 1.174 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Reg_OpenKey open read " 1.175 + L"HKEY_LOCAL_MACHINE software\\Policies\\microsoft")); 1.176 + 1.177 + // Tests to see if we can create keys where we have subdirectory access. 1.178 + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Reg_OpenKey create write " 1.179 + L"HKEY_LOCAL_MACHINE software\\Policies\\google_unit_tests")); 1.180 + 1.181 + RegDeleteKey(HKEY_LOCAL_MACHINE, L"software\\Policies\\google_unit_tests"); 1.182 +} 1.183 + 1.184 +TEST(RegistryPolicyTest, TestKeyAllAccessSubDir) { 1.185 + TestRunner runner; 1.186 + 1.187 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.188 + TargetPolicy::REG_ALLOW_READONLY, 1.189 + L"HKEY_LOCAL_MACHINE")); 1.190 + 1.191 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.192 + TargetPolicy::REG_ALLOW_ANY, 1.193 + L"HKEY_LOCAL_MACHINE\\Software\\Policies")); 1.194 + 1.195 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.196 + TargetPolicy::REG_ALLOW_ANY, 1.197 + L"HKEY_LOCAL_MACHINE\\Software\\Policies\\*")); 1.198 + 1.199 + if (::IsUserAnAdmin()) { 1.200 + // Tests to see if we can create keys where we have subdirectory access. 1.201 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Reg_OpenKey create write " 1.202 + L"HKEY_LOCAL_MACHINE software\\Policies\\google_unit_tests")); 1.203 + 1.204 + RegDeleteKey(HKEY_LOCAL_MACHINE, L"software\\Policies\\google_unit_tests"); 1.205 + } 1.206 +} 1.207 + 1.208 +TEST(RegistryPolicyTest, TestKeyCreateLink) { 1.209 + TestRunner runner; 1.210 + 1.211 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.212 + TargetPolicy::REG_ALLOW_READONLY, 1.213 + L"HKEY_LOCAL_MACHINE")); 1.214 + 1.215 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.216 + TargetPolicy::REG_ALLOW_ANY, 1.217 + L"HKEY_LOCAL_MACHINE\\Software\\Policies")); 1.218 + 1.219 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.220 + TargetPolicy::REG_ALLOW_ANY, 1.221 + L"HKEY_LOCAL_MACHINE\\Software\\Policies\\*")); 1.222 + 1.223 + // Tests to see if we can create a registry link key. 1.224 + // NOTE: In theory here we should make sure to check for SBOX_TEST_DENIED 1.225 + // instead of !SBOX_TEST_SUCCEEDED, but unfortunately the result is not 1.226 + // access denied. Internally RegCreateKeyEx (At least on Vista 64) tries to 1.227 + // create the link, and we return successfully access denied, then, it 1.228 + // decides to try to break the path in multiple chunks, and create the links 1.229 + // one by one. In this scenario, it tries to create "HKLM\Software" as a 1.230 + // link key, which obviously fail with STATUS_OBJECT_NAME_COLLISION, and 1.231 + // this is what is returned to the user. 1.232 + EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Reg_OpenKey create link " 1.233 + L"HKEY_LOCAL_MACHINE software\\Policies\\google_unit_tests")); 1.234 + 1.235 + // In case our code fails, and the call works, we need to delete the new 1.236 + // link. There is no api for this, so we need to use the NT call. 1.237 + HKEY key = NULL; 1.238 + LRESULT result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, 1.239 + L"software\\Policies\\google_unit_tests", 1.240 + REG_OPTION_OPEN_LINK, MAXIMUM_ALLOWED, 1.241 + &key); 1.242 + 1.243 + if (!result) { 1.244 + HMODULE ntdll = GetModuleHandle(L"ntdll.dll"); 1.245 + NtDeleteKeyFunction NtDeleteKey = 1.246 + reinterpret_cast<NtDeleteKeyFunction>(GetProcAddress(ntdll, 1.247 + "NtDeleteKey")); 1.248 + NtDeleteKey(key); 1.249 + } 1.250 +} 1.251 + 1.252 +TEST(RegistryPolicyTest, TestKeyReadOnlyHKCU) { 1.253 + TestRunner runner; 1.254 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.255 + TargetPolicy::REG_ALLOW_READONLY, 1.256 + L"HKEY_CURRENT_USER")); 1.257 + 1.258 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.259 + TargetPolicy::REG_ALLOW_READONLY, 1.260 + L"HKEY_CURRENT_USER\\Software")); 1.261 + 1.262 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.263 + TargetPolicy::REG_ALLOW_READONLY, 1.264 + L"HKEY_USERS\\.default")); 1.265 + 1.266 + EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, 1.267 + TargetPolicy::REG_ALLOW_READONLY, 1.268 + L"HKEY_USERS\\.default\\software")); 1.269 + 1.270 + // Tests read access where we only have read-only access. 1.271 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( 1.272 + L"Reg_OpenKey create read HKEY_CURRENT_USER software")); 1.273 + 1.274 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( 1.275 + L"Reg_OpenKey open read HKEY_CURRENT_USER software")); 1.276 + 1.277 + // Tests write access where we only have read-only acess. 1.278 + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( 1.279 + L"Reg_OpenKey create write HKEY_CURRENT_USER software")); 1.280 + 1.281 + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( 1.282 + L"Reg_OpenKey open write HKEY_CURRENT_USER software")); 1.283 + 1.284 + // Tests maximum allowed access where we only have read-only access. 1.285 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( 1.286 + L"Reg_OpenKey create maximum_allowed HKEY_CURRENT_USER software")); 1.287 + 1.288 + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( 1.289 + L"Reg_OpenKey open maximum_allowed HKEY_CURRENT_USER software")); 1.290 +} 1.291 + 1.292 +} // namespace sandbox