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
, UINT32_TYPE
, VOIDPTR_TYPE
, UINT32_TYPE
,
46 UINT32_TYPE
, UINT32_TYPE
},
47 reinterpret_cast<CallbackGeneric
>(&RegistryDispatcher::NtCreateKey
)
50 static const IPCCall open_params
= {
51 {IPC_NTOPENKEY_TAG
, WCHAR_TYPE
, UINT32_TYPE
, VOIDPTR_TYPE
, UINT32_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(IPCInfo
* ipc
,
81 uint32 desired_access
,
83 uint32 create_options
) {
84 base::win::ScopedHandle root_handle
;
85 base::string16 real_path
= *name
;
87 // If there is a root directory, we need to duplicate the handle to make
88 // it valid in this process.
90 if (!::DuplicateHandle(ipc
->client_info
->process
, root
,
91 ::GetCurrentProcess(), &root
, 0, FALSE
,
92 DUPLICATE_SAME_ACCESS
))
95 root_handle
.Set(root
);
98 if (!GetCompletePath(root
, *name
, &real_path
))
101 const wchar_t* regname
= real_path
.c_str();
102 CountedParameterSet
<OpenKey
> params
;
103 params
[OpenKey::NAME
] = ParamPickerMake(regname
);
104 params
[OpenKey::ACCESS
] = ParamPickerMake(desired_access
);
106 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTCREATEKEY_TAG
,
111 ULONG disposition
= 0;
112 if (!RegistryPolicy::CreateKeyAction(result
, *ipc
->client_info
, *name
,
113 attributes
, root
, desired_access
,
114 title_index
, create_options
, &handle
,
115 &nt_status
, &disposition
)) {
116 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
120 // Return operation status on the IPC.
121 ipc
->return_info
.extended
[0].unsigned_int
= disposition
;
122 ipc
->return_info
.nt_status
= nt_status
;
123 ipc
->return_info
.handle
= handle
;
127 bool RegistryDispatcher::NtOpenKey(IPCInfo
* ipc
,
128 base::string16
* name
,
131 uint32 desired_access
) {
132 base::win::ScopedHandle root_handle
;
133 base::string16 real_path
= *name
;
135 // If there is a root directory, we need to duplicate the handle to make
136 // it valid in this process.
138 if (!::DuplicateHandle(ipc
->client_info
->process
, root
,
139 ::GetCurrentProcess(), &root
, 0, FALSE
,
140 DUPLICATE_SAME_ACCESS
))
142 root_handle
.Set(root
);
145 if (!GetCompletePath(root
, *name
, &real_path
))
148 const wchar_t* regname
= real_path
.c_str();
149 CountedParameterSet
<OpenKey
> params
;
150 params
[OpenKey::NAME
] = ParamPickerMake(regname
);
151 params
[OpenKey::ACCESS
] = ParamPickerMake(desired_access
);
153 EvalResult result
= policy_base_
->EvalPolicy(IPC_NTOPENKEY_TAG
,
157 if (!RegistryPolicy::OpenKeyAction(result
, *ipc
->client_info
, *name
,
158 attributes
, root
, desired_access
, &handle
,
160 ipc
->return_info
.nt_status
= STATUS_ACCESS_DENIED
;
164 // Return operation status on the IPC.
165 ipc
->return_info
.nt_status
= nt_status
;
166 ipc
->return_info
.handle
= handle
;
170 } // namespace sandbox