1 // Copyright (c) 2011 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 "sandbox/win/src/registry_dispatcher.h"
7 #include "base/win/scoped_handle.h"
8 #include "base/win/windows_version.h"
9 #include "sandbox/win/src/crosscall_client.h"
10 #include "sandbox/win/src/interception.h"
11 #include "sandbox/win/src/interceptors.h"
12 #include "sandbox/win/src/ipc_tags.h"
13 #include "sandbox/win/src/sandbox_nt_util.h"
14 #include "sandbox/win/src/policy_broker.h"
15 #include "sandbox/win/src/policy_params.h"
16 #include "sandbox/win/src/sandbox.h"
17 #include "sandbox/win/src/registry_interception.h"
18 #include "sandbox/win/src/registry_policy.h"
22 // Builds a path using the root directory and the name.
23 bool GetCompletePath(HANDLE root
, const base::string16
& name
,
24 base::string16
* complete_name
) {
26 if (!sandbox::GetPathFromHandle(root
, complete_name
))
29 *complete_name
+= L
"\\";
30 *complete_name
+= name
;
32 *complete_name
= name
;
42 RegistryDispatcher::RegistryDispatcher(PolicyBase
* policy_base
)
43 : policy_base_(policy_base
) {
44 static const IPCCall create_params
= {
45 {IPC_NTCREATEKEY_TAG
, WCHAR_TYPE
, ULONG_TYPE
, VOIDPTR_TYPE
, ULONG_TYPE
,
46 ULONG_TYPE
, ULONG_TYPE
},
47 reinterpret_cast<CallbackGeneric
>(&RegistryDispatcher::NtCreateKey
)
50 static const IPCCall open_params
= {
51 {IPC_NTOPENKEY_TAG
, WCHAR_TYPE
, ULONG_TYPE
, VOIDPTR_TYPE
, ULONG_TYPE
},
52 reinterpret_cast<CallbackGeneric
>(&RegistryDispatcher::NtOpenKey
)
55 ipc_calls_
.push_back(create_params
);
56 ipc_calls_
.push_back(open_params
);
59 bool RegistryDispatcher::SetupService(InterceptionManager
* manager
,
61 if (IPC_NTCREATEKEY_TAG
== service
)
62 return INTERCEPT_NT(manager
, NtCreateKey
, CREATE_KEY_ID
, 32);
64 if (IPC_NTOPENKEY_TAG
== service
) {
65 bool result
= INTERCEPT_NT(manager
, NtOpenKey
, OPEN_KEY_ID
, 16);
66 if (base::win::GetVersion() >= base::win::VERSION_WIN7
||
67 (base::win::GetVersion() == base::win::VERSION_VISTA
&&
68 base::win::OSInfo::GetInstance()->version_type() ==
69 base::win::SUITE_SERVER
))
70 result
&= INTERCEPT_NT(manager
, NtOpenKeyEx
, OPEN_KEY_EX_ID
, 20);
77 bool RegistryDispatcher::NtCreateKey(
78 IPCInfo
* ipc
, base::string16
* name
, DWORD attributes
, HANDLE root
,
79 DWORD desired_access
, DWORD title_index
, DWORD create_options
) {
80 base::win::ScopedHandle root_handle
;
81 base::string16 real_path
= *name
;
83 // If there is a root directory, we need to duplicate the handle to make
84 // it valid in this process.
86 if (!::DuplicateHandle(ipc
->client_info
->process
, root
,
87 ::GetCurrentProcess(), &root
, 0, FALSE
,
88 DUPLICATE_SAME_ACCESS
))
91 root_handle
.Set(root
);
94 if (!GetCompletePath(root
, *name
, &real_path
))
97 const wchar_t* regname
= real_path
.c_str();
98 CountedParameterSet
<OpenKey
> params
;
99 params
[OpenKey::NAME
] = ParamPickerMake(regname
);
100 params
[OpenKey::ACCESS
] = ParamPickerMake(desired_access
);
102 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTCREATEKEY_TAG
,
107 ULONG disposition
= 0;
108 if (!RegistryPolicy::CreateKeyAction(result
, *ipc
->client_info
, *name
,
109 attributes
, root
, desired_access
,
110 title_index
, create_options
, &handle
,
111 &nt_status
, &disposition
)) {
112 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
116 // Return operation status on the IPC.
117 ipc
->return_info
.extended
[0].unsigned_int
= disposition
;
118 ipc
->return_info
.nt_status
= nt_status
;
119 ipc
->return_info
.handle
= handle
;
123 bool RegistryDispatcher::NtOpenKey(IPCInfo
* ipc
, base::string16
* name
,
124 DWORD attributes
, HANDLE root
,
125 DWORD desired_access
) {
126 base::win::ScopedHandle root_handle
;
127 base::string16 real_path
= *name
;
129 // If there is a root directory, we need to duplicate the handle to make
130 // it valid in this process.
132 if (!::DuplicateHandle(ipc
->client_info
->process
, root
,
133 ::GetCurrentProcess(), &root
, 0, FALSE
,
134 DUPLICATE_SAME_ACCESS
))
136 root_handle
.Set(root
);
139 if (!GetCompletePath(root
, *name
, &real_path
))
142 const wchar_t* regname
= real_path
.c_str();
143 CountedParameterSet
<OpenKey
> params
;
144 params
[OpenKey::NAME
] = ParamPickerMake(regname
);
145 params
[OpenKey::ACCESS
] = ParamPickerMake(desired_access
);
147 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTOPENKEY_TAG
,
151 if (!RegistryPolicy::OpenKeyAction(result
, *ipc
->client_info
, *name
,
152 attributes
, root
, desired_access
, &handle
,
154 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
158 // Return operation status on the IPC.
159 ipc
->return_info
.nt_status
= nt_status
;
160 ipc
->return_info
.handle
= handle
;
164 } // namespace sandbox