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