michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "sandbox/win/src/acl.h" michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "base/logging.h" michael@0: michael@0: namespace sandbox { michael@0: michael@0: bool GetDefaultDacl(HANDLE token, michael@0: scoped_ptr_malloc* default_dacl) { michael@0: if (token == NULL) michael@0: return false; michael@0: michael@0: DCHECK(default_dacl != NULL); michael@0: michael@0: unsigned long length = 0; michael@0: ::GetTokenInformation(token, TokenDefaultDacl, NULL, 0, &length); michael@0: if (length == 0) { michael@0: NOTREACHED(); michael@0: return false; michael@0: } michael@0: michael@0: TOKEN_DEFAULT_DACL* acl = michael@0: reinterpret_cast(malloc(length)); michael@0: default_dacl->reset(acl); michael@0: michael@0: if (!::GetTokenInformation(token, TokenDefaultDacl, default_dacl->get(), michael@0: length, &length)) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool AddSidToDacl(const Sid& sid, ACL* old_dacl, ACCESS_MASK access, michael@0: ACL** new_dacl) { michael@0: EXPLICIT_ACCESS new_access = {0}; michael@0: new_access.grfAccessMode = GRANT_ACCESS; michael@0: new_access.grfAccessPermissions = access; michael@0: new_access.grfInheritance = NO_INHERITANCE; michael@0: michael@0: new_access.Trustee.pMultipleTrustee = NULL; michael@0: new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; michael@0: new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID; michael@0: new_access.Trustee.ptstrName = reinterpret_cast( michael@0: const_cast(sid.GetPSID())); michael@0: michael@0: if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, new_dacl)) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool AddSidToDefaultDacl(HANDLE token, const Sid& sid, ACCESS_MASK access) { michael@0: if (token == NULL) michael@0: return false; michael@0: michael@0: scoped_ptr_malloc default_dacl; michael@0: if (!GetDefaultDacl(token, &default_dacl)) michael@0: return false; michael@0: michael@0: ACL* new_dacl = NULL; michael@0: if (!AddSidToDacl(sid, default_dacl->DefaultDacl, access, &new_dacl)) michael@0: return false; michael@0: michael@0: TOKEN_DEFAULT_DACL new_token_dacl = {0}; michael@0: new_token_dacl.DefaultDacl = new_dacl; michael@0: michael@0: BOOL ret = ::SetTokenInformation(token, TokenDefaultDacl, &new_token_dacl, michael@0: sizeof(new_token_dacl)); michael@0: ::LocalFree(new_dacl); michael@0: return (TRUE == ret); michael@0: } michael@0: michael@0: bool AddUserSidToDefaultDacl(HANDLE token, ACCESS_MASK access) { michael@0: DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE; michael@0: TOKEN_USER* token_user = reinterpret_cast(malloc(size)); michael@0: michael@0: scoped_ptr_malloc token_user_ptr(token_user); michael@0: michael@0: if (!::GetTokenInformation(token, TokenUser, token_user, size, &size)) michael@0: return false; michael@0: michael@0: return AddSidToDefaultDacl(token, michael@0: reinterpret_cast(token_user->User.Sid), michael@0: access); michael@0: } michael@0: michael@0: bool AddKnownSidToKernelObject(HANDLE object, const Sid& sid, michael@0: ACCESS_MASK access) { michael@0: PSECURITY_DESCRIPTOR descriptor = NULL; michael@0: PACL old_dacl = NULL; michael@0: PACL new_dacl = NULL; michael@0: michael@0: if (ERROR_SUCCESS != ::GetSecurityInfo(object, SE_KERNEL_OBJECT, michael@0: DACL_SECURITY_INFORMATION, NULL, NULL, michael@0: &old_dacl, NULL, &descriptor)) michael@0: return false; michael@0: michael@0: if (!AddSidToDacl(sid.GetPSID(), old_dacl, access, &new_dacl)) { michael@0: ::LocalFree(descriptor); michael@0: return false; michael@0: } michael@0: michael@0: DWORD result = ::SetSecurityInfo(object, SE_KERNEL_OBJECT, michael@0: DACL_SECURITY_INFORMATION, NULL, NULL, michael@0: new_dacl, NULL); michael@0: michael@0: ::LocalFree(new_dacl); michael@0: ::LocalFree(descriptor); michael@0: michael@0: if (ERROR_SUCCESS != result) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: } // namespace sandbox