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/acl.h"
      6 
      7 #include <aclapi.h>
      8 #include <sddl.h>
      9 
     10 #include "base/logging.h"
     11 
     12 namespace sandbox {
     13 
     14 bool GetDefaultDacl(
     15     HANDLE token,
     16     scoped_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter>* default_dacl) {
     17   if (token == NULL)
     18     return false;
     19 
     20   DCHECK(default_dacl != NULL);
     21 
     22   unsigned long length = 0;
     23   ::GetTokenInformation(token, TokenDefaultDacl, NULL, 0, &length);
     24   if (length == 0) {
     25     NOTREACHED();
     26     return false;
     27   }
     28 
     29   TOKEN_DEFAULT_DACL* acl =
     30       reinterpret_cast<TOKEN_DEFAULT_DACL*>(malloc(length));
     31   default_dacl->reset(acl);
     32 
     33   if (!::GetTokenInformation(token, TokenDefaultDacl, default_dacl->get(),
     34                              length, &length))
     35       return false;
     36 
     37   return true;
     38 }
     39 
     40 bool AddSidToDacl(const Sid& sid, ACL* old_dacl, ACCESS_MODE access_mode,
     41                   ACCESS_MASK access, ACL** new_dacl) {
     42   EXPLICIT_ACCESS new_access = {0};
     43   new_access.grfAccessMode = access_mode;
     44   new_access.grfAccessPermissions = access;
     45   new_access.grfInheritance = NO_INHERITANCE;
     46 
     47   new_access.Trustee.pMultipleTrustee = NULL;
     48   new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
     49   new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
     50   new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(
     51                                     const_cast<SID*>(sid.GetPSID()));
     52 
     53   if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, new_dacl))
     54     return false;
     55 
     56   return true;
     57 }
     58 
     59 bool AddSidToDefaultDacl(HANDLE token, const Sid& sid, ACCESS_MASK access) {
     60   if (token == NULL)
     61     return false;
     62 
     63   scoped_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter> default_dacl;
     64   if (!GetDefaultDacl(token, &default_dacl))
     65     return false;
     66 
     67   ACL* new_dacl = NULL;
     68   if (!AddSidToDacl(sid, default_dacl->DefaultDacl, GRANT_ACCESS, access,
     69                     &new_dacl))
     70     return false;
     71 
     72   TOKEN_DEFAULT_DACL new_token_dacl = {0};
     73   new_token_dacl.DefaultDacl = new_dacl;
     74 
     75   BOOL ret = ::SetTokenInformation(token, TokenDefaultDacl, &new_token_dacl,
     76                                    sizeof(new_token_dacl));
     77   ::LocalFree(new_dacl);
     78   return (TRUE == ret);
     79 }
     80 
     81 bool AddUserSidToDefaultDacl(HANDLE token, ACCESS_MASK access) {
     82   DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
     83   TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(malloc(size));
     84 
     85   scoped_ptr<TOKEN_USER, base::FreeDeleter> token_user_ptr(token_user);
     86 
     87   if (!::GetTokenInformation(token, TokenUser, token_user, size, &size))
     88     return false;
     89 
     90   return AddSidToDefaultDacl(token,
     91                              reinterpret_cast<SID*>(token_user->User.Sid),
     92                              access);
     93 }
     94 
     95 bool AddKnownSidToObject(HANDLE object, SE_OBJECT_TYPE object_type,
     96                          const Sid& sid, ACCESS_MODE access_mode,
     97                          ACCESS_MASK access) {
     98   PSECURITY_DESCRIPTOR descriptor = NULL;
     99   PACL old_dacl = NULL;
    100   PACL new_dacl = NULL;
    101 
    102   if (ERROR_SUCCESS != ::GetSecurityInfo(object, object_type,
    103                                          DACL_SECURITY_INFORMATION, NULL, NULL,
    104                                          &old_dacl, NULL, &descriptor))
    105     return false;
    106 
    107   if (!AddSidToDacl(sid.GetPSID(), old_dacl, access_mode, access, &new_dacl)) {
    108     ::LocalFree(descriptor);
    109     return false;
    110   }
    111 
    112   DWORD result = ::SetSecurityInfo(object, object_type,
    113                                    DACL_SECURITY_INFORMATION, NULL, NULL,
    114                                    new_dacl, NULL);
    115 
    116   ::LocalFree(new_dacl);
    117   ::LocalFree(descriptor);
    118 
    119   if (ERROR_SUCCESS != result)
    120     return false;
    121 
    122   return true;
    123 }
    124 
    125 }  // namespace sandbox
    126