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 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 string16& app_container_sid, 53 const std::vector<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 string16& sid, const string16& name) { 98 PSID local_sid; 99 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) 100 return SBOX_ERROR_INVALID_APP_CONTAINER; 101 102 typedef HRESULT (WINAPI* AppContainerRegisterSidPtr)(PSID sid, 103 LPCWSTR moniker, 104 LPCWSTR display_name); 105 static AppContainerRegisterSidPtr AppContainerRegisterSid = NULL; 106 107 if (!AppContainerRegisterSid) { 108 AppContainerRegisterSid = 109 BindFunction<AppContainerRegisterSidPtr>("AppContainerRegisterSid"); 110 } 111 112 ResultCode operation_result = SBOX_ERROR_GENERIC; 113 if (AppContainerRegisterSid) { 114 HRESULT rv = AppContainerRegisterSid(local_sid, name.c_str(), name.c_str()); 115 if (SUCCEEDED(rv)) 116 operation_result = SBOX_ALL_OK; 117 else 118 DLOG(ERROR) << "AppContainerRegisterSid error:" << std::hex << rv; 119 } 120 LocalFree(local_sid); 121 return operation_result; 122 } 123 124 ResultCode DeleteAppContainer(const string16& sid) { 125 PSID local_sid; 126 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) 127 return SBOX_ERROR_INVALID_APP_CONTAINER; 128 129 typedef HRESULT (WINAPI* AppContainerUnregisterSidPtr)(PSID sid); 130 static AppContainerUnregisterSidPtr AppContainerUnregisterSid = NULL; 131 132 if (!AppContainerUnregisterSid) { 133 AppContainerUnregisterSid = 134 BindFunction<AppContainerUnregisterSidPtr>("AppContainerUnregisterSid"); 135 } 136 137 ResultCode operation_result = SBOX_ERROR_GENERIC; 138 if (AppContainerUnregisterSid) { 139 HRESULT rv = AppContainerUnregisterSid(local_sid); 140 if (SUCCEEDED(rv)) 141 operation_result = SBOX_ALL_OK; 142 else 143 DLOG(ERROR) << "AppContainerUnregisterSid error:" << std::hex << rv; 144 } 145 LocalFree(local_sid); 146 return operation_result; 147 } 148 149 string16 LookupAppContainer(const string16& sid) { 150 PSID local_sid; 151 if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) 152 return string16(); 153 154 typedef HRESULT (WINAPI* AppContainerLookupMonikerPtr)(PSID sid, 155 LPWSTR* moniker); 156 typedef BOOLEAN (WINAPI* AppContainerFreeMemoryPtr)(void* ptr); 157 158 static AppContainerLookupMonikerPtr AppContainerLookupMoniker = NULL; 159 static AppContainerFreeMemoryPtr AppContainerFreeMemory = NULL; 160 161 if (!AppContainerLookupMoniker || !AppContainerFreeMemory) { 162 AppContainerLookupMoniker = 163 BindFunction<AppContainerLookupMonikerPtr>("AppContainerLookupMoniker"); 164 AppContainerFreeMemory = 165 BindFunction<AppContainerFreeMemoryPtr>("AppContainerFreeMemory"); 166 } 167 168 if (!AppContainerLookupMoniker || !AppContainerFreeMemory) 169 return string16(); 170 171 wchar_t* buffer = NULL; 172 HRESULT rv = AppContainerLookupMoniker(local_sid, &buffer); 173 if (FAILED(rv)) 174 return string16(); 175 176 string16 name(buffer); 177 if (!AppContainerFreeMemory(buffer)) 178 NOTREACHED(); 179 return name; 180 } 181 182 } // namespace sandbox 183