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