security/sandbox/win/src/registry_policy_test.cc

changeset 0
6474c204b198
     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

mercurial