security/sandbox/win/src/registry_policy.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #include <string>
michael@0 6
michael@0 7 #include "sandbox/win/src/registry_policy.h"
michael@0 8
michael@0 9 #include "base/logging.h"
michael@0 10 #include "sandbox/win/src/ipc_tags.h"
michael@0 11 #include "sandbox/win/src/policy_engine_opcodes.h"
michael@0 12 #include "sandbox/win/src/policy_params.h"
michael@0 13 #include "sandbox/win/src/sandbox_utils.h"
michael@0 14 #include "sandbox/win/src/sandbox_types.h"
michael@0 15 #include "sandbox/win/src/win_utils.h"
michael@0 16
michael@0 17 namespace {
michael@0 18
michael@0 19 static const DWORD kAllowedRegFlags = KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS |
michael@0 20 KEY_NOTIFY | KEY_READ | GENERIC_READ |
michael@0 21 GENERIC_EXECUTE | READ_CONTROL;
michael@0 22
michael@0 23 // Opens the key referenced by |obj_attributes| with |access| and
michael@0 24 // checks what permission was given. Remove the WRITE flags and update
michael@0 25 // |access| with the new value.
michael@0 26 NTSTATUS TranslateMaximumAllowed(OBJECT_ATTRIBUTES* obj_attributes,
michael@0 27 DWORD* access) {
michael@0 28 NtOpenKeyFunction NtOpenKey = NULL;
michael@0 29 ResolveNTFunctionPtr("NtOpenKey", &NtOpenKey);
michael@0 30
michael@0 31 NtCloseFunction NtClose = NULL;
michael@0 32 ResolveNTFunctionPtr("NtClose", &NtClose);
michael@0 33
michael@0 34 NtQueryObjectFunction NtQueryObject = NULL;
michael@0 35 ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject);
michael@0 36
michael@0 37 // Open the key.
michael@0 38 HANDLE handle;
michael@0 39 NTSTATUS status = NtOpenKey(&handle, *access, obj_attributes);
michael@0 40 if (!NT_SUCCESS(status))
michael@0 41 return status;
michael@0 42
michael@0 43 OBJECT_BASIC_INFORMATION info = {0};
michael@0 44 status = NtQueryObject(handle, ObjectBasicInformation, &info, sizeof(info),
michael@0 45 NULL);
michael@0 46 NtClose(handle);
michael@0 47 if (!NT_SUCCESS(status))
michael@0 48 return status;
michael@0 49
michael@0 50 *access = info.GrantedAccess & kAllowedRegFlags;
michael@0 51 return STATUS_SUCCESS;
michael@0 52 }
michael@0 53
michael@0 54 NTSTATUS NtCreateKeyInTarget(HANDLE* target_key_handle,
michael@0 55 ACCESS_MASK desired_access,
michael@0 56 OBJECT_ATTRIBUTES* obj_attributes,
michael@0 57 ULONG title_index,
michael@0 58 UNICODE_STRING* class_name,
michael@0 59 ULONG create_options,
michael@0 60 ULONG* disposition,
michael@0 61 HANDLE target_process) {
michael@0 62 NtCreateKeyFunction NtCreateKey = NULL;
michael@0 63 ResolveNTFunctionPtr("NtCreateKey", &NtCreateKey);
michael@0 64
michael@0 65 if (MAXIMUM_ALLOWED & desired_access) {
michael@0 66 NTSTATUS status = TranslateMaximumAllowed(obj_attributes, &desired_access);
michael@0 67 if (!NT_SUCCESS(status))
michael@0 68 return STATUS_ACCESS_DENIED;
michael@0 69 }
michael@0 70
michael@0 71 HANDLE local_handle = INVALID_HANDLE_VALUE;
michael@0 72 NTSTATUS status = NtCreateKey(&local_handle, desired_access, obj_attributes,
michael@0 73 title_index, class_name, create_options,
michael@0 74 disposition);
michael@0 75 if (!NT_SUCCESS(status))
michael@0 76 return status;
michael@0 77
michael@0 78 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
michael@0 79 target_process, target_key_handle, 0, FALSE,
michael@0 80 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
michael@0 81 return STATUS_ACCESS_DENIED;
michael@0 82 }
michael@0 83 return STATUS_SUCCESS;
michael@0 84 }
michael@0 85
michael@0 86 NTSTATUS NtOpenKeyInTarget(HANDLE* target_key_handle,
michael@0 87 ACCESS_MASK desired_access,
michael@0 88 OBJECT_ATTRIBUTES* obj_attributes,
michael@0 89 HANDLE target_process) {
michael@0 90 NtOpenKeyFunction NtOpenKey = NULL;
michael@0 91 ResolveNTFunctionPtr("NtOpenKey", &NtOpenKey);
michael@0 92
michael@0 93 if (MAXIMUM_ALLOWED & desired_access) {
michael@0 94 NTSTATUS status = TranslateMaximumAllowed(obj_attributes, &desired_access);
michael@0 95 if (!NT_SUCCESS(status))
michael@0 96 return STATUS_ACCESS_DENIED;
michael@0 97 }
michael@0 98
michael@0 99 HANDLE local_handle = INVALID_HANDLE_VALUE;
michael@0 100 NTSTATUS status = NtOpenKey(&local_handle, desired_access, obj_attributes);
michael@0 101
michael@0 102 if (!NT_SUCCESS(status))
michael@0 103 return status;
michael@0 104
michael@0 105 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
michael@0 106 target_process, target_key_handle, 0, FALSE,
michael@0 107 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
michael@0 108 return STATUS_ACCESS_DENIED;
michael@0 109 }
michael@0 110 return STATUS_SUCCESS;
michael@0 111 }
michael@0 112
michael@0 113 }
michael@0 114
michael@0 115 namespace sandbox {
michael@0 116
michael@0 117 bool RegistryPolicy::GenerateRules(const wchar_t* name,
michael@0 118 TargetPolicy::Semantics semantics,
michael@0 119 LowLevelPolicy* policy) {
michael@0 120 std::wstring resovled_name(name);
michael@0 121 if (resovled_name.empty()) {
michael@0 122 return false;
michael@0 123 }
michael@0 124
michael@0 125 if (!ResolveRegistryName(resovled_name, &resovled_name))
michael@0 126 return false;
michael@0 127
michael@0 128 name = resovled_name.c_str();
michael@0 129
michael@0 130 EvalResult result = ASK_BROKER;
michael@0 131
michael@0 132 PolicyRule open(result);
michael@0 133 PolicyRule create(result);
michael@0 134
michael@0 135 switch (semantics) {
michael@0 136 case TargetPolicy::REG_ALLOW_READONLY: {
michael@0 137 // We consider all flags that are not known to be readonly as potentially
michael@0 138 // used for write. Here we also support MAXIMUM_ALLOWED, but we are going
michael@0 139 // to expand it to read-only before the call.
michael@0 140 DWORD restricted_flags = ~(kAllowedRegFlags | MAXIMUM_ALLOWED);
michael@0 141 open.AddNumberMatch(IF_NOT, OpenKey::ACCESS, restricted_flags, AND);
michael@0 142 create.AddNumberMatch(IF_NOT, OpenKey::ACCESS, restricted_flags, AND);
michael@0 143 break;
michael@0 144 }
michael@0 145 case TargetPolicy::REG_ALLOW_ANY: {
michael@0 146 break;
michael@0 147 }
michael@0 148 default: {
michael@0 149 NOTREACHED();
michael@0 150 return false;
michael@0 151 }
michael@0 152 }
michael@0 153
michael@0 154 if (!create.AddStringMatch(IF, OpenKey::NAME, name, CASE_INSENSITIVE) ||
michael@0 155 !policy->AddRule(IPC_NTCREATEKEY_TAG, &create)) {
michael@0 156 return false;
michael@0 157 }
michael@0 158
michael@0 159 if (!open.AddStringMatch(IF, OpenKey::NAME, name, CASE_INSENSITIVE) ||
michael@0 160 !policy->AddRule(IPC_NTOPENKEY_TAG, &open)) {
michael@0 161 return false;
michael@0 162 }
michael@0 163
michael@0 164 return true;
michael@0 165 }
michael@0 166
michael@0 167 bool RegistryPolicy::CreateKeyAction(EvalResult eval_result,
michael@0 168 const ClientInfo& client_info,
michael@0 169 const std::wstring &key,
michael@0 170 uint32 attributes,
michael@0 171 HANDLE root_directory,
michael@0 172 uint32 desired_access,
michael@0 173 uint32 title_index,
michael@0 174 uint32 create_options,
michael@0 175 HANDLE* handle,
michael@0 176 NTSTATUS* nt_status,
michael@0 177 ULONG* disposition) {
michael@0 178 // The only action supported is ASK_BROKER which means create the requested
michael@0 179 // file as specified.
michael@0 180 if (ASK_BROKER != eval_result) {
michael@0 181 *nt_status = STATUS_ACCESS_DENIED;
michael@0 182 return false;
michael@0 183 }
michael@0 184
michael@0 185 // We don't support creating link keys, volatile keys or backup/restore.
michael@0 186 if (create_options) {
michael@0 187 *nt_status = STATUS_ACCESS_DENIED;
michael@0 188 return false;
michael@0 189 }
michael@0 190
michael@0 191 UNICODE_STRING uni_name = {0};
michael@0 192 OBJECT_ATTRIBUTES obj_attributes = {0};
michael@0 193 InitObjectAttribs(key, attributes, root_directory, &obj_attributes,
michael@0 194 &uni_name);
michael@0 195 *nt_status = NtCreateKeyInTarget(handle, desired_access, &obj_attributes,
michael@0 196 title_index, NULL, create_options,
michael@0 197 disposition, client_info.process);
michael@0 198 return true;
michael@0 199 }
michael@0 200
michael@0 201 bool RegistryPolicy::OpenKeyAction(EvalResult eval_result,
michael@0 202 const ClientInfo& client_info,
michael@0 203 const std::wstring &key,
michael@0 204 uint32 attributes,
michael@0 205 HANDLE root_directory,
michael@0 206 uint32 desired_access,
michael@0 207 HANDLE* handle,
michael@0 208 NTSTATUS* nt_status) {
michael@0 209 // The only action supported is ASK_BROKER which means open the requested
michael@0 210 // file as specified.
michael@0 211 if (ASK_BROKER != eval_result) {
michael@0 212 *nt_status = STATUS_ACCESS_DENIED;
michael@0 213 return true;
michael@0 214 }
michael@0 215
michael@0 216 UNICODE_STRING uni_name = {0};
michael@0 217 OBJECT_ATTRIBUTES obj_attributes = {0};
michael@0 218 InitObjectAttribs(key, attributes, root_directory, &obj_attributes,
michael@0 219 &uni_name);
michael@0 220 *nt_status = NtOpenKeyInTarget(handle, desired_access, &obj_attributes,
michael@0 221 client_info.process);
michael@0 222 return true;
michael@0 223 }
michael@0 224
michael@0 225 } // namespace sandbox

mercurial