Home | History | Annotate | Download | only in src
      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