ash: Extend launcher first button to include leading inset.
[chromium-blink-merge.git] / sandbox / src / registry_policy.cc
blob497636fa72fb4fcbad20f290bf723096663baec6
1 // Copyright (c) 2006-2008 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 <string>
7 #include "sandbox/src/registry_policy.h"
9 #include "base/logging.h"
10 #include "sandbox/src/ipc_tags.h"
11 #include "sandbox/src/policy_engine_opcodes.h"
12 #include "sandbox/src/policy_params.h"
13 #include "sandbox/src/sandbox_utils.h"
14 #include "sandbox/src/sandbox_types.h"
15 #include "sandbox/src/win_utils.h"
17 namespace {
19 static const DWORD kAllowedRegFlags = KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS |
20 KEY_NOTIFY | KEY_READ | GENERIC_READ |
21 GENERIC_EXECUTE | READ_CONTROL;
23 // Opens the key referenced by |obj_attributes| with |access| and
24 // checks what permission was given. Remove the WRITE flags and update
25 // |access| with the new value.
26 NTSTATUS TranslateMaximumAllowed(OBJECT_ATTRIBUTES* obj_attributes,
27 DWORD* access) {
28 NtOpenKeyFunction NtOpenKey = NULL;
29 ResolveNTFunctionPtr("NtOpenKey", &NtOpenKey);
31 NtCloseFunction NtClose = NULL;
32 ResolveNTFunctionPtr("NtClose", &NtClose);
34 NtQueryObjectFunction NtQueryObject = NULL;
35 ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject);
37 // Open the key.
38 HANDLE handle;
39 NTSTATUS status = NtOpenKey(&handle, *access, obj_attributes);
40 if (!NT_SUCCESS(status))
41 return status;
43 OBJECT_BASIC_INFORMATION info = {0};
44 status = NtQueryObject(handle, ObjectBasicInformation, &info, sizeof(info),
45 NULL);
46 NtClose(handle);
47 if (!NT_SUCCESS(status))
48 return status;
50 *access = info.GrantedAccess & kAllowedRegFlags;
51 return STATUS_SUCCESS;
54 NTSTATUS NtCreateKeyInTarget(HANDLE* target_key_handle,
55 ACCESS_MASK desired_access,
56 OBJECT_ATTRIBUTES* obj_attributes,
57 ULONG title_index,
58 UNICODE_STRING* class_name,
59 ULONG create_options,
60 ULONG* disposition,
61 HANDLE target_process) {
62 NtCreateKeyFunction NtCreateKey = NULL;
63 ResolveNTFunctionPtr("NtCreateKey", &NtCreateKey);
65 if (MAXIMUM_ALLOWED & desired_access) {
66 NTSTATUS status = TranslateMaximumAllowed(obj_attributes, &desired_access);
67 if (!NT_SUCCESS(status))
68 return STATUS_ACCESS_DENIED;
71 HANDLE local_handle = INVALID_HANDLE_VALUE;
72 NTSTATUS status = NtCreateKey(&local_handle, desired_access, obj_attributes,
73 title_index, class_name, create_options,
74 disposition);
75 if (!NT_SUCCESS(status))
76 return status;
78 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
79 target_process, target_key_handle, 0, FALSE,
80 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
81 ::CloseHandle(local_handle);
82 return STATUS_ACCESS_DENIED;
84 return STATUS_SUCCESS;
87 NTSTATUS NtOpenKeyInTarget(HANDLE* target_key_handle,
88 ACCESS_MASK desired_access,
89 OBJECT_ATTRIBUTES* obj_attributes,
90 HANDLE target_process) {
91 NtOpenKeyFunction NtOpenKey = NULL;
92 ResolveNTFunctionPtr("NtOpenKey", &NtOpenKey);
94 if (MAXIMUM_ALLOWED & desired_access) {
95 NTSTATUS status = TranslateMaximumAllowed(obj_attributes, &desired_access);
96 if (!NT_SUCCESS(status))
97 return STATUS_ACCESS_DENIED;
100 HANDLE local_handle = INVALID_HANDLE_VALUE;
101 NTSTATUS status = NtOpenKey(&local_handle, desired_access, obj_attributes);
103 if (!NT_SUCCESS(status))
104 return status;
106 if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
107 target_process, target_key_handle, 0, FALSE,
108 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
109 ::CloseHandle(local_handle);
110 return STATUS_ACCESS_DENIED;
112 return STATUS_SUCCESS;
117 namespace sandbox {
119 bool RegistryPolicy::GenerateRules(const wchar_t* name,
120 TargetPolicy::Semantics semantics,
121 LowLevelPolicy* policy) {
122 std::wstring resovled_name(name);
123 if (resovled_name.empty()) {
124 return false;
127 if (!ResolveRegistryName(resovled_name, &resovled_name))
128 return false;
130 name = resovled_name.c_str();
132 EvalResult result = ASK_BROKER;
134 PolicyRule open(result);
135 PolicyRule create(result);
137 switch (semantics) {
138 case TargetPolicy::REG_ALLOW_READONLY: {
139 // We consider all flags that are not known to be readonly as potentially
140 // used for write. Here we also support MAXIMUM_ALLOWED, but we are going
141 // to expand it to read-only before the call.
142 DWORD restricted_flags = ~(kAllowedRegFlags | MAXIMUM_ALLOWED);
143 open.AddNumberMatch(IF_NOT, OpenKey::ACCESS, restricted_flags, AND);
144 create.AddNumberMatch(IF_NOT, OpenKey::ACCESS, restricted_flags, AND);
145 break;
147 case TargetPolicy::REG_ALLOW_ANY: {
148 break;
150 default: {
151 NOTREACHED();
152 return false;
156 if (!create.AddStringMatch(IF, OpenKey::NAME, name, CASE_INSENSITIVE) ||
157 !policy->AddRule(IPC_NTCREATEKEY_TAG, &create)) {
158 return false;
161 if (!open.AddStringMatch(IF, OpenKey::NAME, name, CASE_INSENSITIVE) ||
162 !policy->AddRule(IPC_NTOPENKEY_TAG, &open)) {
163 return false;
166 return true;
169 bool RegistryPolicy::CreateKeyAction(EvalResult eval_result,
170 const ClientInfo& client_info,
171 const std::wstring &key,
172 uint32 attributes,
173 HANDLE root_directory,
174 uint32 desired_access,
175 uint32 title_index,
176 uint32 create_options,
177 HANDLE* handle,
178 NTSTATUS* nt_status,
179 ULONG* disposition) {
180 // The only action supported is ASK_BROKER which means create the requested
181 // file as specified.
182 if (ASK_BROKER != eval_result) {
183 *nt_status = STATUS_ACCESS_DENIED;
184 return false;
187 // We don't support creating link keys, volatile keys or backup/restore.
188 if (create_options) {
189 *nt_status = STATUS_ACCESS_DENIED;
190 return false;
193 UNICODE_STRING uni_name = {0};
194 OBJECT_ATTRIBUTES obj_attributes = {0};
195 InitObjectAttribs(key, attributes, root_directory, &obj_attributes,
196 &uni_name);
197 *nt_status = NtCreateKeyInTarget(handle, desired_access, &obj_attributes,
198 title_index, NULL, create_options,
199 disposition, client_info.process);
200 return true;
203 bool RegistryPolicy::OpenKeyAction(EvalResult eval_result,
204 const ClientInfo& client_info,
205 const std::wstring &key,
206 uint32 attributes,
207 HANDLE root_directory,
208 uint32 desired_access,
209 HANDLE* handle,
210 NTSTATUS* nt_status) {
211 // The only action supported is ASK_BROKER which means open the requested
212 // file as specified.
213 if (ASK_BROKER != eval_result) {
214 *nt_status = STATUS_ACCESS_DENIED;
215 return true;
218 UNICODE_STRING uni_name = {0};
219 OBJECT_ATTRIBUTES obj_attributes = {0};
220 InitObjectAttribs(key, attributes, root_directory, &obj_attributes,
221 &uni_name);
222 *nt_status = NtOpenKeyInTarget(handle, desired_access, &obj_attributes,
223 client_info.process);
224 return true;
227 } // namespace sandbox