| OLD | NEW | 
|---|
|  | (Empty) | 
| 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. |  | 
| 4 |  | 
| 5 #include "sandbox/win/src/registry_dispatcher.h" |  | 
| 6 |  | 
| 7 #include <stdint.h> |  | 
| 8 |  | 
| 9 #include "base/win/scoped_handle.h" |  | 
| 10 #include "base/win/windows_version.h" |  | 
| 11 #include "sandbox/win/src/crosscall_client.h" |  | 
| 12 #include "sandbox/win/src/interception.h" |  | 
| 13 #include "sandbox/win/src/interceptors.h" |  | 
| 14 #include "sandbox/win/src/ipc_tags.h" |  | 
| 15 #include "sandbox/win/src/policy_broker.h" |  | 
| 16 #include "sandbox/win/src/policy_params.h" |  | 
| 17 #include "sandbox/win/src/registry_interception.h" |  | 
| 18 #include "sandbox/win/src/registry_policy.h" |  | 
| 19 #include "sandbox/win/src/sandbox.h" |  | 
| 20 #include "sandbox/win/src/sandbox_nt_util.h" |  | 
| 21 |  | 
| 22 namespace { |  | 
| 23 |  | 
| 24 // Builds a path using the root directory and the name. |  | 
| 25 bool GetCompletePath(HANDLE root, const base::string16& name, |  | 
| 26                      base::string16* complete_name) { |  | 
| 27   if (root) { |  | 
| 28     if (!sandbox::GetPathFromHandle(root, complete_name)) |  | 
| 29       return false; |  | 
| 30 |  | 
| 31     *complete_name += L"\\"; |  | 
| 32     *complete_name += name; |  | 
| 33   } else { |  | 
| 34     *complete_name = name; |  | 
| 35   } |  | 
| 36 |  | 
| 37   return true; |  | 
| 38 } |  | 
| 39 |  | 
| 40 } |  | 
| 41 |  | 
| 42 namespace sandbox { |  | 
| 43 |  | 
| 44 RegistryDispatcher::RegistryDispatcher(PolicyBase* policy_base) |  | 
| 45     : policy_base_(policy_base) { |  | 
| 46   static const IPCCall create_params = { |  | 
| 47       {IPC_NTCREATEKEY_TAG, |  | 
| 48        {WCHAR_TYPE, |  | 
| 49         UINT32_TYPE, |  | 
| 50         VOIDPTR_TYPE, |  | 
| 51         UINT32_TYPE, |  | 
| 52         UINT32_TYPE, |  | 
| 53         UINT32_TYPE}}, |  | 
| 54       reinterpret_cast<CallbackGeneric>(&RegistryDispatcher::NtCreateKey)}; |  | 
| 55 |  | 
| 56   static const IPCCall open_params = { |  | 
| 57       {IPC_NTOPENKEY_TAG, {WCHAR_TYPE, UINT32_TYPE, VOIDPTR_TYPE, UINT32_TYPE}}, |  | 
| 58       reinterpret_cast<CallbackGeneric>(&RegistryDispatcher::NtOpenKey)}; |  | 
| 59 |  | 
| 60   ipc_calls_.push_back(create_params); |  | 
| 61   ipc_calls_.push_back(open_params); |  | 
| 62 } |  | 
| 63 |  | 
| 64 bool RegistryDispatcher::SetupService(InterceptionManager* manager, |  | 
| 65                                       int service) { |  | 
| 66   if (IPC_NTCREATEKEY_TAG == service) |  | 
| 67     return INTERCEPT_NT(manager, NtCreateKey, CREATE_KEY_ID, 32); |  | 
| 68 |  | 
| 69   if (IPC_NTOPENKEY_TAG == service) { |  | 
| 70     bool result = INTERCEPT_NT(manager, NtOpenKey, OPEN_KEY_ID, 16); |  | 
| 71     result &= INTERCEPT_NT(manager, NtOpenKeyEx, OPEN_KEY_EX_ID, 20); |  | 
| 72     return result; |  | 
| 73   } |  | 
| 74 |  | 
| 75   return false; |  | 
| 76 } |  | 
| 77 |  | 
| 78 bool RegistryDispatcher::NtCreateKey(IPCInfo* ipc, |  | 
| 79                                      base::string16* name, |  | 
| 80                                      uint32_t attributes, |  | 
| 81                                      HANDLE root, |  | 
| 82                                      uint32_t desired_access, |  | 
| 83                                      uint32_t title_index, |  | 
| 84                                      uint32_t create_options) { |  | 
| 85   base::win::ScopedHandle root_handle; |  | 
| 86   base::string16 real_path = *name; |  | 
| 87 |  | 
| 88   // If there is a root directory, we need to duplicate the handle to make |  | 
| 89   // it valid in this process. |  | 
| 90   if (root) { |  | 
| 91     if (!::DuplicateHandle(ipc->client_info->process, root, |  | 
| 92                            ::GetCurrentProcess(), &root, 0, FALSE, |  | 
| 93                            DUPLICATE_SAME_ACCESS)) |  | 
| 94       return false; |  | 
| 95 |  | 
| 96     root_handle.Set(root); |  | 
| 97   } |  | 
| 98 |  | 
| 99   if (!GetCompletePath(root, *name, &real_path)) |  | 
| 100     return false; |  | 
| 101 |  | 
| 102   const wchar_t* regname = real_path.c_str(); |  | 
| 103   CountedParameterSet<OpenKey> params; |  | 
| 104   params[OpenKey::NAME] = ParamPickerMake(regname); |  | 
| 105   params[OpenKey::ACCESS] = ParamPickerMake(desired_access); |  | 
| 106 |  | 
| 107   EvalResult result = policy_base_->EvalPolicy(IPC_NTCREATEKEY_TAG, |  | 
| 108                                                params.GetBase()); |  | 
| 109 |  | 
| 110   HANDLE handle; |  | 
| 111   NTSTATUS nt_status; |  | 
| 112   ULONG disposition = 0; |  | 
| 113   if (!RegistryPolicy::CreateKeyAction(result, *ipc->client_info, *name, |  | 
| 114                                        attributes, root, desired_access, |  | 
| 115                                        title_index, create_options, &handle, |  | 
| 116                                        &nt_status, &disposition)) { |  | 
| 117     ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |  | 
| 118     return true; |  | 
| 119   } |  | 
| 120 |  | 
| 121   // Return operation status on the IPC. |  | 
| 122   ipc->return_info.extended[0].unsigned_int = disposition; |  | 
| 123   ipc->return_info.nt_status = nt_status; |  | 
| 124   ipc->return_info.handle = handle; |  | 
| 125   return true; |  | 
| 126 } |  | 
| 127 |  | 
| 128 bool RegistryDispatcher::NtOpenKey(IPCInfo* ipc, |  | 
| 129                                    base::string16* name, |  | 
| 130                                    uint32_t attributes, |  | 
| 131                                    HANDLE root, |  | 
| 132                                    uint32_t desired_access) { |  | 
| 133   base::win::ScopedHandle root_handle; |  | 
| 134   base::string16 real_path = *name; |  | 
| 135 |  | 
| 136   // If there is a root directory, we need to duplicate the handle to make |  | 
| 137   // it valid in this process. |  | 
| 138   if (root) { |  | 
| 139     if (!::DuplicateHandle(ipc->client_info->process, root, |  | 
| 140                            ::GetCurrentProcess(), &root, 0, FALSE, |  | 
| 141                            DUPLICATE_SAME_ACCESS)) |  | 
| 142       return false; |  | 
| 143       root_handle.Set(root); |  | 
| 144   } |  | 
| 145 |  | 
| 146   if (!GetCompletePath(root, *name, &real_path)) |  | 
| 147     return false; |  | 
| 148 |  | 
| 149   const wchar_t* regname = real_path.c_str(); |  | 
| 150   CountedParameterSet<OpenKey> params; |  | 
| 151   params[OpenKey::NAME] = ParamPickerMake(regname); |  | 
| 152   params[OpenKey::ACCESS] = ParamPickerMake(desired_access); |  | 
| 153 |  | 
| 154   EvalResult result = policy_base_->EvalPolicy(IPC_NTOPENKEY_TAG, |  | 
| 155                                                params.GetBase()); |  | 
| 156   HANDLE handle; |  | 
| 157   NTSTATUS nt_status; |  | 
| 158   if (!RegistryPolicy::OpenKeyAction(result, *ipc->client_info, *name, |  | 
| 159                                      attributes, root, desired_access, &handle, |  | 
| 160                                      &nt_status)) { |  | 
| 161     ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |  | 
| 162     return true; |  | 
| 163   } |  | 
| 164 |  | 
| 165   // Return operation status on the IPC. |  | 
| 166   ipc->return_info.nt_status = nt_status; |  | 
| 167   ipc->return_info.handle = handle; |  | 
| 168   return true; |  | 
| 169 } |  | 
| 170 |  | 
| 171 }  // namespace sandbox |  | 
| OLD | NEW | 
|---|