1 // Copyright (c) 2012 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/app_container.h" 6 7 #include <Sddl.h> 8 #include <vector> 9 10 #include "base/logging.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/win/startup_information.h" 13 #include "sandbox/win/src/internal_types.h" 14 15 namespace { 16 17 // Converts the passed in sid string to a PSID that must be relased with 18 // LocalFree. 19 PSID ConvertSid(const base::string16& sid) { 20 PSID local_sid; 21 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) 22 return NULL; 23 return local_sid; 24 } 25 26 template <typename T> 27 T BindFunction(const char* name) { 28 HMODULE module = GetModuleHandle(sandbox::kKerneldllName); 29 void* function = GetProcAddress(module, name); 30 if (!function) { 31 module = GetModuleHandle(sandbox::kKernelBasedllName); 32 function = GetProcAddress(module, name); 33 } 34 return reinterpret_cast<T>(function); 35 } 36 37 } // namespace 38 39 namespace sandbox { 40 41 AppContainerAttributes::AppContainerAttributes() { 42 memset(&capabilities_, 0, sizeof(capabilities_)); 43 } 44 45 AppContainerAttributes::~AppContainerAttributes() { 46 for (size_t i = 0; i < attributes_.size(); i++) 47 LocalFree(attributes_[i].Sid); 48 LocalFree(capabilities_.AppContainerSid); 49 } 50 51 ResultCode AppContainerAttributes::SetAppContainer( 52 const base::string16& app_container_sid, 53 const std::vector<base::string16>& capabilities) { 54 DCHECK(!capabilities_.AppContainerSid); 55 DCHECK(attributes_.empty()); 56 capabilities_.AppContainerSid = ConvertSid(app_container_sid); 57 if (!capabilities_.AppContainerSid) 58 return SBOX_ERROR_INVALID_APP_CONTAINER; 59 60 for (size_t i = 0; i < capabilities.size(); i++) { 61 SID_AND_ATTRIBUTES sid_and_attributes; 62 sid_and_attributes.Sid = ConvertSid(capabilities[i]); 63 if (!sid_and_attributes.Sid) 64 return SBOX_ERROR_INVALID_CAPABILITY; 65 66 sid_and_attributes.Attributes = SE_GROUP_ENABLED; 67 attributes_.push_back(sid_and_attributes); 68 } 69 70 if (capabilities.size()) { 71 capabilities_.CapabilityCount = static_cast<DWORD>(capabilities.size()); 72 capabilities_.Capabilities = &attributes_[0]; 73 } 74 return SBOX_ALL_OK; 75 } 76 77 ResultCode AppContainerAttributes::ShareForStartup( 78 base::win::StartupInformation* startup_information) const { 79 // The only thing we support so far is an AppContainer. 80 if (!capabilities_.AppContainerSid) 81 return SBOX_ERROR_INVALID_APP_CONTAINER; 82 83 if (!startup_information->UpdateProcThreadAttribute( 84 PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, 85 const_cast<SECURITY_CAPABILITIES*>(&capabilities_), 86 sizeof(capabilities_))) { 87 DPLOG(ERROR) << "Failed UpdateProcThreadAttribute"; 88 return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; 89 } 90 return SBOX_ALL_OK; 91 } 92 93 bool AppContainerAttributes::HasAppContainer() const { 94 return (capabilities_.AppContainerSid != NULL); 95 } 96 97 ResultCode CreateAppContainer(const base::string16& sid, 98 const base::string16& name) { 99 PSID local_sid; 100 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) 101 return SBOX_ERROR_INVALID_APP_CONTAINER; 102 103 typedef HRESULT (WINAPI* AppContainerRegisterSidPtr)(PSID sid, 104 LPCWSTR moniker, 105 LPCWSTR display_name); 106 static AppContainerRegisterSidPtr AppContainerRegisterSid = NULL; 107 108 if (!AppContainerRegisterSid) { 109 AppContainerRegisterSid = 110 BindFunction<AppContainerRegisterSidPtr>("AppContainerRegisterSid"); 111 } 112 113 ResultCode operation_result = SBOX_ERROR_GENERIC; 114 if (AppContainerRegisterSid) { 115 HRESULT rv = AppContainerRegisterSid(local_sid, name.c_str(), name.c_str()); 116 if (SUCCEEDED(rv)) 117 operation_result = SBOX_ALL_OK; 118 else 119 DLOG(ERROR) << "AppContainerRegisterSid error:" << std::hex << rv; 120 } 121 LocalFree(local_sid); 122 return operation_result; 123 } 124 125 ResultCode DeleteAppContainer(const base::string16& sid) { 126 PSID local_sid; 127 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) 128 return SBOX_ERROR_INVALID_APP_CONTAINER; 129 130 typedef HRESULT (WINAPI* AppContainerUnregisterSidPtr)(PSID sid); 131 static AppContainerUnregisterSidPtr AppContainerUnregisterSid = NULL; 132 133 if (!AppContainerUnregisterSid) { 134 AppContainerUnregisterSid = 135 BindFunction<AppContainerUnregisterSidPtr>("AppContainerUnregisterSid"); 136 } 137 138 ResultCode operation_result = SBOX_ERROR_GENERIC; 139 if (AppContainerUnregisterSid) { 140 HRESULT rv = AppContainerUnregisterSid(local_sid); 141 if (SUCCEEDED(rv)) 142 operation_result = SBOX_ALL_OK; 143 else 144 DLOG(ERROR) << "AppContainerUnregisterSid error:" << std::hex << rv; 145 } 146 LocalFree(local_sid); 147 return operation_result; 148 } 149 150 base::string16 LookupAppContainer(const base::string16& sid) { 151 PSID local_sid; 152 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) 153 return base::string16(); 154 155 typedef HRESULT (WINAPI* AppContainerLookupMonikerPtr)(PSID sid, 156 LPWSTR* moniker); 157 typedef BOOLEAN (WINAPI* AppContainerFreeMemoryPtr)(void* ptr); 158 159 static AppContainerLookupMonikerPtr AppContainerLookupMoniker = NULL; 160 static AppContainerFreeMemoryPtr AppContainerFreeMemory = NULL; 161 162 if (!AppContainerLookupMoniker || !AppContainerFreeMemory) { 163 AppContainerLookupMoniker = 164 BindFunction<AppContainerLookupMonikerPtr>("AppContainerLookupMoniker"); 165 AppContainerFreeMemory = 166 BindFunction<AppContainerFreeMemoryPtr>("AppContainerFreeMemory"); 167 } 168 169 if (!AppContainerLookupMoniker || !AppContainerFreeMemory) 170 return base::string16(); 171 172 wchar_t* buffer = NULL; 173 HRESULT rv = AppContainerLookupMoniker(local_sid, &buffer); 174 if (FAILED(rv)) 175 return base::string16(); 176 177 base::string16 name(buffer); 178 if (!AppContainerFreeMemory(buffer)) 179 NOTREACHED(); 180 return name; 181 } 182 183 } // namespace sandbox 184