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