michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "sandbox/win/src/app_container.h" michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "base/logging.h" michael@0: #include "base/memory/scoped_ptr.h" michael@0: #include "base/win/startup_information.h" michael@0: #include "sandbox/win/src/internal_types.h" michael@0: michael@0: namespace { michael@0: michael@0: // Converts the passed in sid string to a PSID that must be relased with michael@0: // LocalFree. michael@0: PSID ConvertSid(const string16& sid) { michael@0: PSID local_sid; michael@0: if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) michael@0: return NULL; michael@0: return local_sid; michael@0: } michael@0: michael@0: template michael@0: T BindFunction(const char* name) { michael@0: HMODULE module = GetModuleHandle(sandbox::kKerneldllName); michael@0: void* function = GetProcAddress(module, name); michael@0: if (!function) { michael@0: module = GetModuleHandle(sandbox::kKernelBasedllName); michael@0: function = GetProcAddress(module, name); michael@0: } michael@0: return reinterpret_cast(function); michael@0: } michael@0: michael@0: } // namespace michael@0: michael@0: namespace sandbox { michael@0: michael@0: AppContainerAttributes::AppContainerAttributes() { michael@0: memset(&capabilities_, 0, sizeof(capabilities_)); michael@0: } michael@0: michael@0: AppContainerAttributes::~AppContainerAttributes() { michael@0: for (size_t i = 0; i < attributes_.size(); i++) michael@0: LocalFree(attributes_[i].Sid); michael@0: LocalFree(capabilities_.AppContainerSid); michael@0: } michael@0: michael@0: ResultCode AppContainerAttributes::SetAppContainer( michael@0: const string16& app_container_sid, michael@0: const std::vector& capabilities) { michael@0: DCHECK(!capabilities_.AppContainerSid); michael@0: DCHECK(attributes_.empty()); michael@0: capabilities_.AppContainerSid = ConvertSid(app_container_sid); michael@0: if (!capabilities_.AppContainerSid) michael@0: return SBOX_ERROR_INVALID_APP_CONTAINER; michael@0: michael@0: for (size_t i = 0; i < capabilities.size(); i++) { michael@0: SID_AND_ATTRIBUTES sid_and_attributes; michael@0: sid_and_attributes.Sid = ConvertSid(capabilities[i]); michael@0: if (!sid_and_attributes.Sid) michael@0: return SBOX_ERROR_INVALID_CAPABILITY; michael@0: michael@0: sid_and_attributes.Attributes = SE_GROUP_ENABLED; michael@0: attributes_.push_back(sid_and_attributes); michael@0: } michael@0: michael@0: if (capabilities.size()) { michael@0: capabilities_.CapabilityCount = static_cast(capabilities.size()); michael@0: capabilities_.Capabilities = &attributes_[0]; michael@0: } michael@0: return SBOX_ALL_OK; michael@0: } michael@0: michael@0: ResultCode AppContainerAttributes::ShareForStartup( michael@0: base::win::StartupInformation* startup_information) const { michael@0: // The only thing we support so far is an AppContainer. michael@0: if (!capabilities_.AppContainerSid) michael@0: return SBOX_ERROR_INVALID_APP_CONTAINER; michael@0: michael@0: if (!startup_information->UpdateProcThreadAttribute( michael@0: PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, michael@0: const_cast(&capabilities_), michael@0: sizeof(capabilities_))) { michael@0: DPLOG(ERROR) << "Failed UpdateProcThreadAttribute"; michael@0: return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; michael@0: } michael@0: return SBOX_ALL_OK; michael@0: } michael@0: michael@0: bool AppContainerAttributes::HasAppContainer() const { michael@0: return (capabilities_.AppContainerSid != NULL); michael@0: } michael@0: michael@0: ResultCode CreateAppContainer(const string16& sid, const string16& name) { michael@0: PSID local_sid; michael@0: if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) michael@0: return SBOX_ERROR_INVALID_APP_CONTAINER; michael@0: michael@0: typedef HRESULT (WINAPI* AppContainerRegisterSidPtr)(PSID sid, michael@0: LPCWSTR moniker, michael@0: LPCWSTR display_name); michael@0: static AppContainerRegisterSidPtr AppContainerRegisterSid = NULL; michael@0: michael@0: if (!AppContainerRegisterSid) { michael@0: AppContainerRegisterSid = michael@0: BindFunction("AppContainerRegisterSid"); michael@0: } michael@0: michael@0: ResultCode operation_result = SBOX_ERROR_GENERIC; michael@0: if (AppContainerRegisterSid) { michael@0: HRESULT rv = AppContainerRegisterSid(local_sid, name.c_str(), name.c_str()); michael@0: if (SUCCEEDED(rv)) michael@0: operation_result = SBOX_ALL_OK; michael@0: else michael@0: DLOG(ERROR) << "AppContainerRegisterSid error:" << std::hex << rv; michael@0: } michael@0: LocalFree(local_sid); michael@0: return operation_result; michael@0: } michael@0: michael@0: ResultCode DeleteAppContainer(const string16& sid) { michael@0: PSID local_sid; michael@0: if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) michael@0: return SBOX_ERROR_INVALID_APP_CONTAINER; michael@0: michael@0: typedef HRESULT (WINAPI* AppContainerUnregisterSidPtr)(PSID sid); michael@0: static AppContainerUnregisterSidPtr AppContainerUnregisterSid = NULL; michael@0: michael@0: if (!AppContainerUnregisterSid) { michael@0: AppContainerUnregisterSid = michael@0: BindFunction("AppContainerUnregisterSid"); michael@0: } michael@0: michael@0: ResultCode operation_result = SBOX_ERROR_GENERIC; michael@0: if (AppContainerUnregisterSid) { michael@0: HRESULT rv = AppContainerUnregisterSid(local_sid); michael@0: if (SUCCEEDED(rv)) michael@0: operation_result = SBOX_ALL_OK; michael@0: else michael@0: DLOG(ERROR) << "AppContainerUnregisterSid error:" << std::hex << rv; michael@0: } michael@0: LocalFree(local_sid); michael@0: return operation_result; michael@0: } michael@0: michael@0: string16 LookupAppContainer(const string16& sid) { michael@0: PSID local_sid; michael@0: if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) michael@0: return string16(); michael@0: michael@0: typedef HRESULT (WINAPI* AppContainerLookupMonikerPtr)(PSID sid, michael@0: LPWSTR* moniker); michael@0: typedef BOOLEAN (WINAPI* AppContainerFreeMemoryPtr)(void* ptr); michael@0: michael@0: static AppContainerLookupMonikerPtr AppContainerLookupMoniker = NULL; michael@0: static AppContainerFreeMemoryPtr AppContainerFreeMemory = NULL; michael@0: michael@0: if (!AppContainerLookupMoniker || !AppContainerFreeMemory) { michael@0: AppContainerLookupMoniker = michael@0: BindFunction("AppContainerLookupMoniker"); michael@0: AppContainerFreeMemory = michael@0: BindFunction("AppContainerFreeMemory"); michael@0: } michael@0: michael@0: if (!AppContainerLookupMoniker || !AppContainerFreeMemory) michael@0: return string16(); michael@0: michael@0: wchar_t* buffer = NULL; michael@0: HRESULT rv = AppContainerLookupMoniker(local_sid, &buffer); michael@0: if (FAILED(rv)) michael@0: return string16(); michael@0: michael@0: string16 name(buffer); michael@0: if (!AppContainerFreeMemory(buffer)) michael@0: NOTREACHED(); michael@0: return name; michael@0: } michael@0: michael@0: } // namespace sandbox