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 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