1c2c66affSColin Finck /*
26413009cSGeorge Bișoc * PROJECT: ReactOS Kernel
36413009cSGeorge Bișoc * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
46413009cSGeorge Bișoc * PURPOSE: Access control lists (ACLs) implementation
56413009cSGeorge Bișoc * COPYRIGHT: Copyright David Welch <welch@cwcom.net>
6c2c66affSColin Finck */
7c2c66affSColin Finck
8c2c66affSColin Finck /* INCLUDES *******************************************************************/
9c2c66affSColin Finck
10c2c66affSColin Finck #include <ntoskrnl.h>
11c2c66affSColin Finck #define NDEBUG
12c2c66affSColin Finck #include <debug.h>
13c2c66affSColin Finck
14c2c66affSColin Finck /* GLOBALS ********************************************************************/
15c2c66affSColin Finck
16c2c66affSColin Finck PACL SePublicDefaultDacl = NULL;
17c2c66affSColin Finck PACL SeSystemDefaultDacl = NULL;
18c2c66affSColin Finck PACL SePublicDefaultUnrestrictedDacl = NULL;
19c2c66affSColin Finck PACL SePublicOpenDacl = NULL;
20c2c66affSColin Finck PACL SePublicOpenUnrestrictedDacl = NULL;
21c2c66affSColin Finck PACL SeUnrestrictedDacl = NULL;
22b28530d4SGeorge Bișoc PACL SeSystemAnonymousLogonDacl = NULL;
23c2c66affSColin Finck
24c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
25c2c66affSColin Finck
266413009cSGeorge Bișoc /**
276413009cSGeorge Bișoc * @brief
286413009cSGeorge Bișoc * Initializes known discretionary access control lists in the system upon
296413009cSGeorge Bișoc * kernel and Executive initialization procedure.
306413009cSGeorge Bișoc *
316413009cSGeorge Bișoc * @return
326413009cSGeorge Bișoc * Returns TRUE if all the DACLs have been successfully initialized,
336413009cSGeorge Bișoc * FALSE otherwise.
346413009cSGeorge Bișoc */
355c7ce447SVictor Perevertkin CODE_SEG("INIT")
36b20f8151SSerge Gautherie BOOLEAN
37c2c66affSColin Finck NTAPI
SepInitDACLs(VOID)38c2c66affSColin Finck SepInitDACLs(VOID)
39c2c66affSColin Finck {
40c2c66affSColin Finck ULONG AclLength;
41c2c66affSColin Finck
42c2c66affSColin Finck /* create PublicDefaultDacl */
43c2c66affSColin Finck AclLength = sizeof(ACL) +
44c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeWorldSid)) +
45c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) +
46c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid));
47c2c66affSColin Finck
48c2c66affSColin Finck SePublicDefaultDacl = ExAllocatePoolWithTag(PagedPool,
49c2c66affSColin Finck AclLength,
50c2c66affSColin Finck TAG_ACL);
51c2c66affSColin Finck if (SePublicDefaultDacl == NULL)
52c2c66affSColin Finck return FALSE;
53c2c66affSColin Finck
54c2c66affSColin Finck RtlCreateAcl(SePublicDefaultDacl,
55c2c66affSColin Finck AclLength,
56c2c66affSColin Finck ACL_REVISION);
57c2c66affSColin Finck
58c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicDefaultDacl,
59c2c66affSColin Finck ACL_REVISION,
60c2c66affSColin Finck GENERIC_EXECUTE,
61c2c66affSColin Finck SeWorldSid);
62c2c66affSColin Finck
63c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicDefaultDacl,
64c2c66affSColin Finck ACL_REVISION,
65c2c66affSColin Finck GENERIC_ALL,
66c2c66affSColin Finck SeLocalSystemSid);
67c2c66affSColin Finck
68c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicDefaultDacl,
69c2c66affSColin Finck ACL_REVISION,
70c2c66affSColin Finck GENERIC_ALL,
71c2c66affSColin Finck SeAliasAdminsSid);
72c2c66affSColin Finck
73c2c66affSColin Finck /* create PublicDefaultUnrestrictedDacl */
74c2c66affSColin Finck AclLength = sizeof(ACL) +
75c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeWorldSid)) +
76c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) +
77c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)) +
78c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeRestrictedCodeSid));
79c2c66affSColin Finck
80c2c66affSColin Finck SePublicDefaultUnrestrictedDacl = ExAllocatePoolWithTag(PagedPool,
81c2c66affSColin Finck AclLength,
82c2c66affSColin Finck TAG_ACL);
83c2c66affSColin Finck if (SePublicDefaultUnrestrictedDacl == NULL)
84c2c66affSColin Finck return FALSE;
85c2c66affSColin Finck
86c2c66affSColin Finck RtlCreateAcl(SePublicDefaultUnrestrictedDacl,
87c2c66affSColin Finck AclLength,
88c2c66affSColin Finck ACL_REVISION);
89c2c66affSColin Finck
90c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl,
91c2c66affSColin Finck ACL_REVISION,
92c2c66affSColin Finck GENERIC_EXECUTE,
93c2c66affSColin Finck SeWorldSid);
94c2c66affSColin Finck
95c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl,
96c2c66affSColin Finck ACL_REVISION,
97c2c66affSColin Finck GENERIC_ALL,
98c2c66affSColin Finck SeLocalSystemSid);
99c2c66affSColin Finck
100c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl,
101c2c66affSColin Finck ACL_REVISION,
102c2c66affSColin Finck GENERIC_ALL,
103c2c66affSColin Finck SeAliasAdminsSid);
104c2c66affSColin Finck
105c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl,
106c2c66affSColin Finck ACL_REVISION,
107c2c66affSColin Finck GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL,
108c2c66affSColin Finck SeRestrictedCodeSid);
109c2c66affSColin Finck
110c2c66affSColin Finck /* create PublicOpenDacl */
111c2c66affSColin Finck AclLength = sizeof(ACL) +
112c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeWorldSid)) +
113c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) +
114c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid));
115c2c66affSColin Finck
116c2c66affSColin Finck SePublicOpenDacl = ExAllocatePoolWithTag(PagedPool,
117c2c66affSColin Finck AclLength,
118c2c66affSColin Finck TAG_ACL);
119c2c66affSColin Finck if (SePublicOpenDacl == NULL)
120c2c66affSColin Finck return FALSE;
121c2c66affSColin Finck
122c2c66affSColin Finck RtlCreateAcl(SePublicOpenDacl,
123c2c66affSColin Finck AclLength,
124c2c66affSColin Finck ACL_REVISION);
125c2c66affSColin Finck
126c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicOpenDacl,
127c2c66affSColin Finck ACL_REVISION,
128c2c66affSColin Finck GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
129c2c66affSColin Finck SeWorldSid);
130c2c66affSColin Finck
131c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicOpenDacl,
132c2c66affSColin Finck ACL_REVISION,
133c2c66affSColin Finck GENERIC_ALL,
134c2c66affSColin Finck SeLocalSystemSid);
135c2c66affSColin Finck
136c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicOpenDacl,
137c2c66affSColin Finck ACL_REVISION,
138c2c66affSColin Finck GENERIC_ALL,
139c2c66affSColin Finck SeAliasAdminsSid);
140c2c66affSColin Finck
141c2c66affSColin Finck /* create PublicOpenUnrestrictedDacl */
142c2c66affSColin Finck AclLength = sizeof(ACL) +
143c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeWorldSid)) +
144c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) +
145c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)) +
146c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeRestrictedCodeSid));
147c2c66affSColin Finck
148c2c66affSColin Finck SePublicOpenUnrestrictedDacl = ExAllocatePoolWithTag(PagedPool,
149c2c66affSColin Finck AclLength,
150c2c66affSColin Finck TAG_ACL);
151c2c66affSColin Finck if (SePublicOpenUnrestrictedDacl == NULL)
152c2c66affSColin Finck return FALSE;
153c2c66affSColin Finck
154c2c66affSColin Finck RtlCreateAcl(SePublicOpenUnrestrictedDacl,
155c2c66affSColin Finck AclLength,
156c2c66affSColin Finck ACL_REVISION);
157c2c66affSColin Finck
158c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicOpenUnrestrictedDacl,
159c2c66affSColin Finck ACL_REVISION,
160c2c66affSColin Finck GENERIC_ALL,
161c2c66affSColin Finck SeWorldSid);
162c2c66affSColin Finck
163c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicOpenUnrestrictedDacl,
164c2c66affSColin Finck ACL_REVISION,
165c2c66affSColin Finck GENERIC_ALL,
166c2c66affSColin Finck SeLocalSystemSid);
167c2c66affSColin Finck
168c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicOpenUnrestrictedDacl,
169c2c66affSColin Finck ACL_REVISION,
170c2c66affSColin Finck GENERIC_ALL,
171c2c66affSColin Finck SeAliasAdminsSid);
172c2c66affSColin Finck
173c2c66affSColin Finck RtlAddAccessAllowedAce(SePublicOpenUnrestrictedDacl,
174c2c66affSColin Finck ACL_REVISION,
175c2c66affSColin Finck GENERIC_READ | GENERIC_EXECUTE,
176c2c66affSColin Finck SeRestrictedCodeSid);
177c2c66affSColin Finck
178c2c66affSColin Finck /* create SystemDefaultDacl */
179c2c66affSColin Finck AclLength = sizeof(ACL) +
180c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) +
181c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid));
182c2c66affSColin Finck
183c2c66affSColin Finck SeSystemDefaultDacl = ExAllocatePoolWithTag(PagedPool,
184c2c66affSColin Finck AclLength,
185c2c66affSColin Finck TAG_ACL);
186c2c66affSColin Finck if (SeSystemDefaultDacl == NULL)
187c2c66affSColin Finck return FALSE;
188c2c66affSColin Finck
189c2c66affSColin Finck RtlCreateAcl(SeSystemDefaultDacl,
190c2c66affSColin Finck AclLength,
191c2c66affSColin Finck ACL_REVISION);
192c2c66affSColin Finck
193c2c66affSColin Finck RtlAddAccessAllowedAce(SeSystemDefaultDacl,
194c2c66affSColin Finck ACL_REVISION,
195c2c66affSColin Finck GENERIC_ALL,
196c2c66affSColin Finck SeLocalSystemSid);
197c2c66affSColin Finck
198c2c66affSColin Finck RtlAddAccessAllowedAce(SeSystemDefaultDacl,
199c2c66affSColin Finck ACL_REVISION,
200c2c66affSColin Finck GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL,
201c2c66affSColin Finck SeAliasAdminsSid);
202c2c66affSColin Finck
203c2c66affSColin Finck /* create UnrestrictedDacl */
204c2c66affSColin Finck AclLength = sizeof(ACL) +
205c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeWorldSid)) +
206c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeRestrictedCodeSid));
207c2c66affSColin Finck
208c2c66affSColin Finck SeUnrestrictedDacl = ExAllocatePoolWithTag(PagedPool,
209c2c66affSColin Finck AclLength,
210c2c66affSColin Finck TAG_ACL);
211c2c66affSColin Finck if (SeUnrestrictedDacl == NULL)
212c2c66affSColin Finck return FALSE;
213c2c66affSColin Finck
214c2c66affSColin Finck RtlCreateAcl(SeUnrestrictedDacl,
215c2c66affSColin Finck AclLength,
216c2c66affSColin Finck ACL_REVISION);
217c2c66affSColin Finck
218c2c66affSColin Finck RtlAddAccessAllowedAce(SeUnrestrictedDacl,
219c2c66affSColin Finck ACL_REVISION,
220c2c66affSColin Finck GENERIC_ALL,
221c2c66affSColin Finck SeWorldSid);
222c2c66affSColin Finck
223c2c66affSColin Finck RtlAddAccessAllowedAce(SeUnrestrictedDacl,
224c2c66affSColin Finck ACL_REVISION,
225c2c66affSColin Finck GENERIC_READ | GENERIC_EXECUTE,
226c2c66affSColin Finck SeRestrictedCodeSid);
227c2c66affSColin Finck
228b28530d4SGeorge Bișoc /* create SystemAnonymousLogonDacl */
229b28530d4SGeorge Bișoc AclLength = sizeof(ACL) +
230b28530d4SGeorge Bișoc (sizeof(ACE) + RtlLengthSid(SeWorldSid)) +
231b28530d4SGeorge Bișoc (sizeof(ACE) + RtlLengthSid(SeAnonymousLogonSid));
232b28530d4SGeorge Bișoc
233b28530d4SGeorge Bișoc SeSystemAnonymousLogonDacl = ExAllocatePoolWithTag(PagedPool,
234b28530d4SGeorge Bișoc AclLength,
235b28530d4SGeorge Bișoc TAG_ACL);
236b28530d4SGeorge Bișoc if (SeSystemAnonymousLogonDacl == NULL)
237b28530d4SGeorge Bișoc return FALSE;
238b28530d4SGeorge Bișoc
239b28530d4SGeorge Bișoc RtlCreateAcl(SeSystemAnonymousLogonDacl,
240b28530d4SGeorge Bișoc AclLength,
241b28530d4SGeorge Bișoc ACL_REVISION);
242b28530d4SGeorge Bișoc
243b28530d4SGeorge Bișoc RtlAddAccessAllowedAce(SeSystemAnonymousLogonDacl,
244b28530d4SGeorge Bișoc ACL_REVISION,
245b28530d4SGeorge Bișoc GENERIC_ALL,
246b28530d4SGeorge Bișoc SeWorldSid);
247b28530d4SGeorge Bișoc
248b28530d4SGeorge Bișoc RtlAddAccessAllowedAce(SeSystemAnonymousLogonDacl,
249b28530d4SGeorge Bișoc ACL_REVISION,
250b28530d4SGeorge Bișoc GENERIC_ALL,
251b28530d4SGeorge Bișoc SeAnonymousLogonSid);
252b28530d4SGeorge Bișoc
253c2c66affSColin Finck return TRUE;
254c2c66affSColin Finck }
255c2c66affSColin Finck
2566413009cSGeorge Bișoc /**
2576413009cSGeorge Bișoc * @brief
2586413009cSGeorge Bișoc * Allocates a discretionary access control list based on certain properties
2596413009cSGeorge Bișoc * of a regular and primary access tokens.
2606413009cSGeorge Bișoc *
2616413009cSGeorge Bișoc * @param[in] Token
2626413009cSGeorge Bișoc * An access token.
2636413009cSGeorge Bișoc *
2646413009cSGeorge Bișoc * @param[in] PrimaryToken
2656413009cSGeorge Bișoc * A primary access token.
2666413009cSGeorge Bișoc *
2676413009cSGeorge Bișoc * @param[out] Dacl
2686413009cSGeorge Bișoc * The returned allocated DACL.
2696413009cSGeorge Bișoc *
2706413009cSGeorge Bișoc * @return
2716413009cSGeorge Bișoc * Returns STATUS_SUCCESS if DACL creation from tokens has completed
2726413009cSGeorge Bișoc * successfully. STATUS_INSUFFICIENT_RESOURCES is returned if DACL
2736413009cSGeorge Bișoc * allocation from memory pool fails otherwise.
2746413009cSGeorge Bișoc */
2755b2dda91SHermès Bélusca-Maïto NTSTATUS
2765b2dda91SHermès Bélusca-Maïto NTAPI
SepCreateImpersonationTokenDacl(_In_ PTOKEN Token,_In_ PTOKEN PrimaryToken,_Out_ PACL * Dacl)2775b2dda91SHermès Bélusca-Maïto SepCreateImpersonationTokenDacl(
2785b2dda91SHermès Bélusca-Maïto _In_ PTOKEN Token,
2795b2dda91SHermès Bélusca-Maïto _In_ PTOKEN PrimaryToken,
2805b2dda91SHermès Bélusca-Maïto _Out_ PACL* Dacl)
281c2c66affSColin Finck {
282c2c66affSColin Finck ULONG AclLength;
2835b2dda91SHermès Bélusca-Maïto PACL TokenDacl;
284c2c66affSColin Finck
285c2c66affSColin Finck PAGED_CODE();
286c2c66affSColin Finck
2875b2dda91SHermès Bélusca-Maïto *Dacl = NULL;
2885b2dda91SHermès Bélusca-Maïto
289c2c66affSColin Finck AclLength = sizeof(ACL) +
290c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid)) +
291c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(SeLocalSystemSid)) +
2925b2dda91SHermès Bélusca-Maïto (sizeof(ACE) + RtlLengthSid(SeRestrictedCodeSid)) +
293c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(Token->UserAndGroups->Sid)) +
294c2c66affSColin Finck (sizeof(ACE) + RtlLengthSid(PrimaryToken->UserAndGroups->Sid));
295c2c66affSColin Finck
296c2c66affSColin Finck TokenDacl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_ACL);
297c2c66affSColin Finck if (TokenDacl == NULL)
298c2c66affSColin Finck {
299c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
300c2c66affSColin Finck }
301c2c66affSColin Finck
302c2c66affSColin Finck RtlCreateAcl(TokenDacl, AclLength, ACL_REVISION);
303c2c66affSColin Finck RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL,
304c2c66affSColin Finck Token->UserAndGroups->Sid);
305c2c66affSColin Finck RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL,
306c2c66affSColin Finck PrimaryToken->UserAndGroups->Sid);
307c2c66affSColin Finck RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL,
308c2c66affSColin Finck SeAliasAdminsSid);
309c2c66affSColin Finck RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL,
310c2c66affSColin Finck SeLocalSystemSid);
311c2c66affSColin Finck
312c2c66affSColin Finck if (Token->RestrictedSids != NULL || PrimaryToken->RestrictedSids != NULL)
313c2c66affSColin Finck {
314c2c66affSColin Finck RtlAddAccessAllowedAce(TokenDacl, ACL_REVISION, GENERIC_ALL,
315c2c66affSColin Finck SeRestrictedCodeSid);
316c2c66affSColin Finck }
3175b2dda91SHermès Bélusca-Maïto
3185b2dda91SHermès Bélusca-Maïto *Dacl = TokenDacl;
319c2c66affSColin Finck
320c2c66affSColin Finck return STATUS_SUCCESS;
321c2c66affSColin Finck }
322c2c66affSColin Finck
3236413009cSGeorge Bișoc /**
3246413009cSGeorge Bișoc * @brief
3256413009cSGeorge Bișoc * Captures an access control list from an already valid input ACL.
3266413009cSGeorge Bișoc *
3276413009cSGeorge Bișoc * @param[in] InputAcl
3286413009cSGeorge Bișoc * A valid ACL.
3296413009cSGeorge Bișoc *
3306413009cSGeorge Bișoc * @param[in] AccessMode
3316413009cSGeorge Bișoc * Processor level access mode. The processor mode determines how
332*389a2da7SHermès Bélusca-Maïto * the input arguments are probed.
3336413009cSGeorge Bișoc *
3346413009cSGeorge Bișoc * @param[in] PoolType
3356413009cSGeorge Bișoc * Pool type for new captured ACL for creation. The pool type determines
336*389a2da7SHermès Bélusca-Maïto * in which memory pool the ACL data should reside.
3376413009cSGeorge Bișoc *
3386413009cSGeorge Bișoc * @param[in] CaptureIfKernel
339*389a2da7SHermès Bélusca-Maïto * If set to TRUE and the processor access mode being KernelMode, we are
340*389a2da7SHermès Bélusca-Maïto * capturing an ACL directly in the kernel. Otherwise we are capturing
3416413009cSGeorge Bișoc * within a kernel mode driver.
3426413009cSGeorge Bișoc *
3436413009cSGeorge Bișoc * @param[out] CapturedAcl
3446413009cSGeorge Bișoc * The returned and allocated captured ACL.
3456413009cSGeorge Bișoc *
3466413009cSGeorge Bișoc * @return
3476413009cSGeorge Bișoc * Returns STATUS_SUCCESS if the ACL has been successfully captured.
3486413009cSGeorge Bișoc * STATUS_INSUFFICIENT_RESOURCES is returned otherwise.
3496413009cSGeorge Bișoc */
350c2c66affSColin Finck NTSTATUS
351c2c66affSColin Finck NTAPI
SepCaptureAcl(_In_ PACL InputAcl,_In_ KPROCESSOR_MODE AccessMode,_In_ POOL_TYPE PoolType,_In_ BOOLEAN CaptureIfKernel,_Out_ PACL * CapturedAcl)3528567d814SGeorge Bișoc SepCaptureAcl(
3538567d814SGeorge Bișoc _In_ PACL InputAcl,
3548567d814SGeorge Bișoc _In_ KPROCESSOR_MODE AccessMode,
3558567d814SGeorge Bișoc _In_ POOL_TYPE PoolType,
3568567d814SGeorge Bișoc _In_ BOOLEAN CaptureIfKernel,
3578567d814SGeorge Bișoc _Out_ PACL *CapturedAcl)
358c2c66affSColin Finck {
359c2c66affSColin Finck PACL NewAcl;
360*389a2da7SHermès Bélusca-Maïto ULONG AclSize;
361c2c66affSColin Finck
362c2c66affSColin Finck PAGED_CODE();
363c2c66affSColin Finck
364*389a2da7SHermès Bélusca-Maïto /* If in kernel mode and we do not capture, just
365*389a2da7SHermès Bélusca-Maïto * return the given ACL and don't validate it. */
366*389a2da7SHermès Bélusca-Maïto if ((AccessMode == KernelMode) && !CaptureIfKernel)
367*389a2da7SHermès Bélusca-Maïto {
368*389a2da7SHermès Bélusca-Maïto *CapturedAcl = InputAcl;
369*389a2da7SHermès Bélusca-Maïto return STATUS_SUCCESS;
370*389a2da7SHermès Bélusca-Maïto }
371*389a2da7SHermès Bélusca-Maïto
372*389a2da7SHermès Bélusca-Maïto /* Otherwise, capture and validate the ACL, depending on the access mode */
373c2c66affSColin Finck if (AccessMode != KernelMode)
374c2c66affSColin Finck {
375c2c66affSColin Finck _SEH2_TRY
376c2c66affSColin Finck {
377c2c66affSColin Finck ProbeForRead(InputAcl,
378c2c66affSColin Finck sizeof(ACL),
379c2c66affSColin Finck sizeof(ULONG));
380c2c66affSColin Finck AclSize = InputAcl->AclSize;
381c2c66affSColin Finck ProbeForRead(InputAcl,
382c2c66affSColin Finck AclSize,
383c2c66affSColin Finck sizeof(ULONG));
384c2c66affSColin Finck }
385c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
386c2c66affSColin Finck {
387c2c66affSColin Finck /* Return the exception code */
388c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode());
389c2c66affSColin Finck }
390c2c66affSColin Finck _SEH2_END;
391c2c66affSColin Finck
392*389a2da7SHermès Bélusca-Maïto /* Validate the minimal size an ACL can have */
393*389a2da7SHermès Bélusca-Maïto if (AclSize < sizeof(ACL))
394*389a2da7SHermès Bélusca-Maïto return STATUS_INVALID_ACL;
395*389a2da7SHermès Bélusca-Maïto
396c2c66affSColin Finck NewAcl = ExAllocatePoolWithTag(PoolType,
397c2c66affSColin Finck AclSize,
398c2c66affSColin Finck TAG_ACL);
399*389a2da7SHermès Bélusca-Maïto if (!NewAcl)
400*389a2da7SHermès Bélusca-Maïto return STATUS_INSUFFICIENT_RESOURCES;
401*389a2da7SHermès Bélusca-Maïto
402c2c66affSColin Finck _SEH2_TRY
403c2c66affSColin Finck {
404*389a2da7SHermès Bélusca-Maïto RtlCopyMemory(NewAcl, InputAcl, AclSize);
405c2c66affSColin Finck }
406c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
407c2c66affSColin Finck {
408c2c66affSColin Finck /* Free the ACL and return the exception code */
409c2c66affSColin Finck ExFreePoolWithTag(NewAcl, TAG_ACL);
410c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode());
411c2c66affSColin Finck }
412c2c66affSColin Finck _SEH2_END;
413c2c66affSColin Finck }
414c2c66affSColin Finck else
415c2c66affSColin Finck {
416c2c66affSColin Finck AclSize = InputAcl->AclSize;
417c2c66affSColin Finck
418*389a2da7SHermès Bélusca-Maïto /* Validate the minimal size an ACL can have */
419*389a2da7SHermès Bélusca-Maïto if (AclSize < sizeof(ACL))
420*389a2da7SHermès Bélusca-Maïto return STATUS_INVALID_ACL;
421*389a2da7SHermès Bélusca-Maïto
422c2c66affSColin Finck NewAcl = ExAllocatePoolWithTag(PoolType,
423c2c66affSColin Finck AclSize,
424c2c66affSColin Finck TAG_ACL);
425*389a2da7SHermès Bélusca-Maïto if (!NewAcl)
426*389a2da7SHermès Bélusca-Maïto return STATUS_INSUFFICIENT_RESOURCES;
427c2c66affSColin Finck
428*389a2da7SHermès Bélusca-Maïto RtlCopyMemory(NewAcl, InputAcl, AclSize);
429*389a2da7SHermès Bélusca-Maïto }
430*389a2da7SHermès Bélusca-Maïto
431*389a2da7SHermès Bélusca-Maïto /* Validate the captured ACL */
432*389a2da7SHermès Bélusca-Maïto if (!RtlValidAcl(NewAcl))
433c2c66affSColin Finck {
434*389a2da7SHermès Bélusca-Maïto /* Free the ACL and fail */
435*389a2da7SHermès Bélusca-Maïto ExFreePoolWithTag(NewAcl, TAG_ACL);
436*389a2da7SHermès Bélusca-Maïto return STATUS_INVALID_ACL;
437*389a2da7SHermès Bélusca-Maïto }
438c2c66affSColin Finck
439*389a2da7SHermès Bélusca-Maïto /* It's valid, return it */
440c2c66affSColin Finck *CapturedAcl = NewAcl;
441*389a2da7SHermès Bélusca-Maïto return STATUS_SUCCESS;
442c2c66affSColin Finck }
443c2c66affSColin Finck
4446413009cSGeorge Bișoc /**
4456413009cSGeorge Bișoc * @brief
4466413009cSGeorge Bișoc * Releases (frees) a captured ACL from the memory pool.
4476413009cSGeorge Bișoc *
4486413009cSGeorge Bișoc * @param[in] CapturedAcl
4496413009cSGeorge Bișoc * A valid captured ACL to free.
4506413009cSGeorge Bișoc *
4516413009cSGeorge Bișoc * @param[in] AccessMode
4526413009cSGeorge Bișoc * Processor level access mode.
4536413009cSGeorge Bișoc *
4546413009cSGeorge Bișoc * @param[in] CaptureIfKernel
4556413009cSGeorge Bișoc * If set to TRUE and the processor access mode being KernelMode, we're
4566413009cSGeorge Bișoc * releasing an ACL directly in the kernel. Otherwise we're releasing
4576413009cSGeorge Bișoc * within a kernel mode driver.
4586413009cSGeorge Bișoc *
4596413009cSGeorge Bișoc * @return
4606413009cSGeorge Bișoc * Nothing.
4616413009cSGeorge Bișoc */
462c2c66affSColin Finck VOID
463c2c66affSColin Finck NTAPI
SepReleaseAcl(_In_ PACL CapturedAcl,_In_ KPROCESSOR_MODE AccessMode,_In_ BOOLEAN CaptureIfKernel)4648567d814SGeorge Bișoc SepReleaseAcl(
4658567d814SGeorge Bișoc _In_ PACL CapturedAcl,
4668567d814SGeorge Bișoc _In_ KPROCESSOR_MODE AccessMode,
4678567d814SGeorge Bișoc _In_ BOOLEAN CaptureIfKernel)
468c2c66affSColin Finck {
469c2c66affSColin Finck PAGED_CODE();
470c2c66affSColin Finck
471c2c66affSColin Finck if (CapturedAcl != NULL &&
472c2c66affSColin Finck (AccessMode != KernelMode ||
473c2c66affSColin Finck (AccessMode == KernelMode && CaptureIfKernel)))
474c2c66affSColin Finck {
475c2c66affSColin Finck ExFreePoolWithTag(CapturedAcl, TAG_ACL);
476c2c66affSColin Finck }
477c2c66affSColin Finck }
478c2c66affSColin Finck
4796413009cSGeorge Bișoc /**
4806413009cSGeorge Bișoc * @brief
4816413009cSGeorge Bișoc * Determines if a certain ACE can or cannot be propagated based on
4826413009cSGeorge Bișoc * ACE inheritation flags and whatnot.
4836413009cSGeorge Bișoc *
4846413009cSGeorge Bișoc * @param[in] AceFlags
4856413009cSGeorge Bișoc * Bit flags of an ACE to perform propagation checks.
4866413009cSGeorge Bișoc *
4876413009cSGeorge Bișoc * @param[out] NewAceFlags
4886413009cSGeorge Bișoc * New ACE bit blags based on the specific ACE flags of the first
4896413009cSGeorge Bișoc * argument parameter.
4906413009cSGeorge Bișoc *
4916413009cSGeorge Bișoc * @param[in] IsInherited
4926413009cSGeorge Bișoc * If set to TRUE, an ACE is deemed as directly inherited from another
4936413009cSGeorge Bișoc * instance. In that case we're allowed to propagate.
4946413009cSGeorge Bișoc *
4956413009cSGeorge Bișoc * @param[in] IsDirectoryObject
4966413009cSGeorge Bișoc * If set to TRUE, an object directly inherits this ACE so we can propagate
4976413009cSGeorge Bișoc * it.
4986413009cSGeorge Bișoc *
4996413009cSGeorge Bișoc * @return
5006413009cSGeorge Bișoc * Returns TRUE if an ACE can be propagated, FALSE otherwise.
5016413009cSGeorge Bișoc */
502c2c66affSColin Finck BOOLEAN
SepShouldPropagateAce(_In_ UCHAR AceFlags,_Out_ PUCHAR NewAceFlags,_In_ BOOLEAN IsInherited,_In_ BOOLEAN IsDirectoryObject)503c2c66affSColin Finck SepShouldPropagateAce(
504c2c66affSColin Finck _In_ UCHAR AceFlags,
505c2c66affSColin Finck _Out_ PUCHAR NewAceFlags,
506c2c66affSColin Finck _In_ BOOLEAN IsInherited,
507c2c66affSColin Finck _In_ BOOLEAN IsDirectoryObject)
508c2c66affSColin Finck {
509c2c66affSColin Finck if (!IsInherited)
510c2c66affSColin Finck {
511c2c66affSColin Finck *NewAceFlags = AceFlags;
512c2c66affSColin Finck return TRUE;
513c2c66affSColin Finck }
514c2c66affSColin Finck
515c2c66affSColin Finck if (!IsDirectoryObject)
516c2c66affSColin Finck {
517c2c66affSColin Finck if (AceFlags & OBJECT_INHERIT_ACE)
518c2c66affSColin Finck {
519c2c66affSColin Finck *NewAceFlags = AceFlags & ~VALID_INHERIT_FLAGS;
520c2c66affSColin Finck return TRUE;
521c2c66affSColin Finck }
522c2c66affSColin Finck return FALSE;
523c2c66affSColin Finck }
524c2c66affSColin Finck
525c2c66affSColin Finck if (AceFlags & NO_PROPAGATE_INHERIT_ACE)
526c2c66affSColin Finck {
527c2c66affSColin Finck if (AceFlags & CONTAINER_INHERIT_ACE)
528c2c66affSColin Finck {
529c2c66affSColin Finck *NewAceFlags = AceFlags & ~VALID_INHERIT_FLAGS;
530c2c66affSColin Finck return TRUE;
531c2c66affSColin Finck }
532c2c66affSColin Finck return FALSE;
533c2c66affSColin Finck }
534c2c66affSColin Finck
535c2c66affSColin Finck if (AceFlags & CONTAINER_INHERIT_ACE)
536c2c66affSColin Finck {
537c2c66affSColin Finck *NewAceFlags = CONTAINER_INHERIT_ACE | (AceFlags & OBJECT_INHERIT_ACE) | (AceFlags & ~VALID_INHERIT_FLAGS);
538c2c66affSColin Finck return TRUE;
539c2c66affSColin Finck }
540c2c66affSColin Finck
541c2c66affSColin Finck if (AceFlags & OBJECT_INHERIT_ACE)
542c2c66affSColin Finck {
543c2c66affSColin Finck *NewAceFlags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | (AceFlags & ~VALID_INHERIT_FLAGS);
544c2c66affSColin Finck return TRUE;
545c2c66affSColin Finck }
546c2c66affSColin Finck
547c2c66affSColin Finck return FALSE;
548c2c66affSColin Finck }
549c2c66affSColin Finck
5506413009cSGeorge Bișoc /**
5516413009cSGeorge Bișoc * @brief
5526413009cSGeorge Bișoc * Propagates (copies) an access control list.
5536413009cSGeorge Bișoc *
5546413009cSGeorge Bișoc * @param[out] AclDest
5556413009cSGeorge Bișoc * The destination parameter with propagated ACL.
5566413009cSGeorge Bișoc *
5576413009cSGeorge Bișoc * @param[in,out] AclLength
5586413009cSGeorge Bișoc * The length of the ACL that we propagate.
5596413009cSGeorge Bișoc *
5606413009cSGeorge Bișoc * @param[in] AclSource
5616413009cSGeorge Bișoc * The source instance of a valid ACL.
5626413009cSGeorge Bișoc *
5636413009cSGeorge Bișoc * @param[in] Owner
5646413009cSGeorge Bișoc * A SID that represents the main user that identifies the ACL.
5656413009cSGeorge Bișoc *
5666413009cSGeorge Bișoc * @param[in] Group
5676413009cSGeorge Bișoc * A SID that represents a group that identifies the ACL.
5686413009cSGeorge Bișoc *
5696413009cSGeorge Bișoc * @param[in] IsInherited
5706413009cSGeorge Bișoc * If set to TRUE, that means the ACL is directly inherited.
5716413009cSGeorge Bișoc *
5726413009cSGeorge Bișoc * @param[in] IsDirectoryObject
5736413009cSGeorge Bișoc * If set to TRUE, that means the ACL is directly inherited because
5746413009cSGeorge Bișoc * of the object that inherits it.
5756413009cSGeorge Bișoc *
5766413009cSGeorge Bișoc * @param[in] GenericMapping
5776413009cSGeorge Bișoc * Generic mapping of access rights to map only certain effective
5786413009cSGeorge Bișoc * ACEs.
5796413009cSGeorge Bișoc *
5806413009cSGeorge Bișoc * @return
5816413009cSGeorge Bișoc * Returns STATUS_SUCCESS if ACL has been propagated successfully.
5826413009cSGeorge Bișoc * STATUS_BUFFER_TOO_SMALL is returned if the ACL length is not greater
5836413009cSGeorge Bișoc * than the maximum written size of the buffer for ACL propagation
5846413009cSGeorge Bișoc * otherwise.
5856413009cSGeorge Bișoc */
586c2c66affSColin Finck NTSTATUS
587c2c66affSColin Finck SepPropagateAcl(
_Out_writes_bytes_opt_(AclLength)588c2c66affSColin Finck _Out_writes_bytes_opt_(AclLength) PACL AclDest,
589c2c66affSColin Finck _Inout_ PULONG AclLength,
590c2c66affSColin Finck _In_reads_bytes_(AclSource->AclSize) PACL AclSource,
591c2c66affSColin Finck _In_ PSID Owner,
592c2c66affSColin Finck _In_ PSID Group,
593c2c66affSColin Finck _In_ BOOLEAN IsInherited,
594c2c66affSColin Finck _In_ BOOLEAN IsDirectoryObject,
595c2c66affSColin Finck _In_ PGENERIC_MAPPING GenericMapping)
596c2c66affSColin Finck {
597c2c66affSColin Finck ACCESS_MASK Mask;
598c2c66affSColin Finck PACCESS_ALLOWED_ACE AceSource;
599c2c66affSColin Finck PACCESS_ALLOWED_ACE AceDest;
600c2c66affSColin Finck PUCHAR CurrentDest;
601c2c66affSColin Finck PUCHAR CurrentSource;
602c2c66affSColin Finck ULONG i;
603c2c66affSColin Finck ULONG Written;
604c2c66affSColin Finck UCHAR AceFlags;
605c2c66affSColin Finck USHORT AceSize;
606c2c66affSColin Finck USHORT AceCount = 0;
607c2c66affSColin Finck PSID Sid;
608c2c66affSColin Finck BOOLEAN WriteTwoAces;
609c2c66affSColin Finck
610c2c66affSColin Finck ASSERT(RtlValidAcl(AclSource));
611c2c66affSColin Finck ASSERT(AclSource->AclSize % sizeof(ULONG) == 0);
612c2c66affSColin Finck ASSERT(AclSource->Sbz1 == 0);
613c2c66affSColin Finck ASSERT(AclSource->Sbz2 == 0);
614c2c66affSColin Finck
615c2c66affSColin Finck Written = 0;
616c2c66affSColin Finck if (*AclLength >= Written + sizeof(ACL))
617c2c66affSColin Finck {
618c2c66affSColin Finck RtlCopyMemory(AclDest,
619c2c66affSColin Finck AclSource,
620c2c66affSColin Finck sizeof(ACL));
621c2c66affSColin Finck }
622c2c66affSColin Finck Written += sizeof(ACL);
623c2c66affSColin Finck
624c2c66affSColin Finck CurrentDest = (PUCHAR)(AclDest + 1);
625c2c66affSColin Finck CurrentSource = (PUCHAR)(AclSource + 1);
626c2c66affSColin Finck for (i = 0; i < AclSource->AceCount; i++)
627c2c66affSColin Finck {
628c2c66affSColin Finck ASSERT((ULONG_PTR)CurrentDest % sizeof(ULONG) == 0);
629c2c66affSColin Finck ASSERT((ULONG_PTR)CurrentSource % sizeof(ULONG) == 0);
630c2c66affSColin Finck AceDest = (PACCESS_ALLOWED_ACE)CurrentDest;
631c2c66affSColin Finck AceSource = (PACCESS_ALLOWED_ACE)CurrentSource;
632c2c66affSColin Finck
633c2c66affSColin Finck if (AceSource->Header.AceType > ACCESS_MAX_MS_V2_ACE_TYPE)
634c2c66affSColin Finck {
635c2c66affSColin Finck /* FIXME: handle object & compound ACEs */
636c2c66affSColin Finck AceSize = AceSource->Header.AceSize;
637c2c66affSColin Finck
638c2c66affSColin Finck if (*AclLength >= Written + AceSize)
639c2c66affSColin Finck {
640c2c66affSColin Finck RtlCopyMemory(AceDest, AceSource, AceSize);
641c2c66affSColin Finck }
642c2c66affSColin Finck CurrentDest += AceSize;
643c2c66affSColin Finck CurrentSource += AceSize;
644c2c66affSColin Finck Written += AceSize;
645c2c66affSColin Finck AceCount++;
646c2c66affSColin Finck continue;
647c2c66affSColin Finck }
648c2c66affSColin Finck
649c2c66affSColin Finck /* These all have the same structure */
650c2c66affSColin Finck ASSERT(AceSource->Header.AceType == ACCESS_ALLOWED_ACE_TYPE ||
651c2c66affSColin Finck AceSource->Header.AceType == ACCESS_DENIED_ACE_TYPE ||
652c2c66affSColin Finck AceSource->Header.AceType == SYSTEM_AUDIT_ACE_TYPE ||
653c2c66affSColin Finck AceSource->Header.AceType == SYSTEM_ALARM_ACE_TYPE);
654c2c66affSColin Finck
655c2c66affSColin Finck ASSERT(AceSource->Header.AceSize % sizeof(ULONG) == 0);
656c2c66affSColin Finck ASSERT(AceSource->Header.AceSize >= sizeof(*AceSource));
657c2c66affSColin Finck if (!SepShouldPropagateAce(AceSource->Header.AceFlags,
658c2c66affSColin Finck &AceFlags,
659c2c66affSColin Finck IsInherited,
660c2c66affSColin Finck IsDirectoryObject))
661c2c66affSColin Finck {
662c2c66affSColin Finck CurrentSource += AceSource->Header.AceSize;
663c2c66affSColin Finck continue;
664c2c66affSColin Finck }
665c2c66affSColin Finck
666c2c66affSColin Finck /* FIXME: filter out duplicate ACEs */
667c2c66affSColin Finck AceSize = AceSource->Header.AceSize;
668c2c66affSColin Finck Mask = AceSource->Mask;
669c2c66affSColin Finck Sid = (PSID)&AceSource->SidStart;
670c2c66affSColin Finck ASSERT(AceSize >= FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + RtlLengthSid(Sid));
671c2c66affSColin Finck
672c2c66affSColin Finck WriteTwoAces = FALSE;
673c2c66affSColin Finck /* Map effective ACE to specific rights */
674c2c66affSColin Finck if (!(AceFlags & INHERIT_ONLY_ACE))
675c2c66affSColin Finck {
676c2c66affSColin Finck RtlMapGenericMask(&Mask, GenericMapping);
677c2c66affSColin Finck Mask &= GenericMapping->GenericAll;
678c2c66affSColin Finck
679c2c66affSColin Finck if (IsInherited)
680c2c66affSColin Finck {
681c2c66affSColin Finck if (RtlEqualSid(Sid, SeCreatorOwnerSid))
682c2c66affSColin Finck Sid = Owner;
683c2c66affSColin Finck else if (RtlEqualSid(Sid, SeCreatorGroupSid))
684c2c66affSColin Finck Sid = Group;
685c2c66affSColin Finck AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + RtlLengthSid(Sid);
686c2c66affSColin Finck
687c2c66affSColin Finck /*
688c2c66affSColin Finck * A generic container ACE becomes two ACEs:
689c2c66affSColin Finck * - a specific effective ACE with no inheritance flags
690c2c66affSColin Finck * - an inherit-only ACE that keeps the generic rights
691c2c66affSColin Finck */
692c2c66affSColin Finck if (IsDirectoryObject &&
693c2c66affSColin Finck (AceFlags & CONTAINER_INHERIT_ACE) &&
694c2c66affSColin Finck (Mask != AceSource->Mask || Sid != (PSID)&AceSource->SidStart))
695c2c66affSColin Finck {
696c2c66affSColin Finck WriteTwoAces = TRUE;
697c2c66affSColin Finck }
698c2c66affSColin Finck }
699c2c66affSColin Finck }
700c2c66affSColin Finck
701c2c66affSColin Finck while (1)
702c2c66affSColin Finck {
703c2c66affSColin Finck if (*AclLength >= Written + AceSize)
704c2c66affSColin Finck {
705c2c66affSColin Finck AceDest->Header.AceType = AceSource->Header.AceType;
706c2c66affSColin Finck AceDest->Header.AceFlags = WriteTwoAces ? AceFlags & ~VALID_INHERIT_FLAGS
707c2c66affSColin Finck : AceFlags;
708c2c66affSColin Finck AceDest->Header.AceSize = AceSize;
709c2c66affSColin Finck AceDest->Mask = Mask;
710c2c66affSColin Finck RtlCopySid(AceSize - FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart),
711c2c66affSColin Finck (PSID)&AceDest->SidStart,
712c2c66affSColin Finck Sid);
713c2c66affSColin Finck }
714c2c66affSColin Finck Written += AceSize;
715c2c66affSColin Finck
716c2c66affSColin Finck AceCount++;
717c2c66affSColin Finck CurrentDest += AceSize;
718c2c66affSColin Finck
719c2c66affSColin Finck if (!WriteTwoAces)
720c2c66affSColin Finck break;
721c2c66affSColin Finck
722c2c66affSColin Finck /* Second ACE keeps all the generics from the source ACE */
723c2c66affSColin Finck WriteTwoAces = FALSE;
724c2c66affSColin Finck AceDest = (PACCESS_ALLOWED_ACE)CurrentDest;
725c2c66affSColin Finck AceSize = AceSource->Header.AceSize;
726c2c66affSColin Finck Mask = AceSource->Mask;
727c2c66affSColin Finck Sid = (PSID)&AceSource->SidStart;
728c2c66affSColin Finck AceFlags |= INHERIT_ONLY_ACE;
729c2c66affSColin Finck }
730c2c66affSColin Finck
731c2c66affSColin Finck CurrentSource += AceSource->Header.AceSize;
732c2c66affSColin Finck }
733c2c66affSColin Finck
734c2c66affSColin Finck if (*AclLength >= sizeof(ACL))
735c2c66affSColin Finck {
736c2c66affSColin Finck AclDest->AceCount = AceCount;
737c2c66affSColin Finck AclDest->AclSize = Written;
738c2c66affSColin Finck }
739c2c66affSColin Finck
740c2c66affSColin Finck if (Written > *AclLength)
741c2c66affSColin Finck {
742c2c66affSColin Finck *AclLength = Written;
743c2c66affSColin Finck return STATUS_BUFFER_TOO_SMALL;
744c2c66affSColin Finck }
745c2c66affSColin Finck *AclLength = Written;
746c2c66affSColin Finck return STATUS_SUCCESS;
747c2c66affSColin Finck }
748c2c66affSColin Finck
7496413009cSGeorge Bișoc /**
7506413009cSGeorge Bișoc * @brief
7516413009cSGeorge Bișoc * Selects an ACL and returns it to the caller.
7526413009cSGeorge Bișoc *
7536413009cSGeorge Bișoc * @param[in] ExplicitAcl
7546413009cSGeorge Bișoc * If specified, the specified ACL to the call will be
7556413009cSGeorge Bișoc * the selected ACL for the caller.
7566413009cSGeorge Bișoc *
7576413009cSGeorge Bișoc * @param[in] ExplicitPresent
7586413009cSGeorge Bișoc * If set to TRUE and with specific ACL filled to the call, the
7596413009cSGeorge Bișoc * function will immediately return the specific ACL as the selected
7606413009cSGeorge Bișoc * ACL for the caller.
7616413009cSGeorge Bișoc *
7626413009cSGeorge Bișoc * @param[in] ExplicitDefaulted
7636413009cSGeorge Bișoc * If set to FALSE and with specific ACL filled to the call, the ACL
7646413009cSGeorge Bișoc * is not a default ACL. Otherwise it's a default ACL that we cannot
7656413009cSGeorge Bișoc * select it as is.
7666413009cSGeorge Bișoc *
7676413009cSGeorge Bișoc * @param[in] ParentAcl
7686413009cSGeorge Bișoc * If specified, the parent ACL will be used to determine the exact ACL
7696413009cSGeorge Bișoc * length to check if the ACL in question is not empty. If the list
7706413009cSGeorge Bișoc * is not empty then the function will select such ACL to the caller.
7716413009cSGeorge Bișoc *
7726413009cSGeorge Bișoc * @param[in] DefaultAcl
7736413009cSGeorge Bișoc * If specified, the default ACL will be the selected one for the caller.
7746413009cSGeorge Bișoc *
7756413009cSGeorge Bișoc * @param[out] AclLength
7766413009cSGeorge Bișoc * The size length of an ACL.
7776413009cSGeorge Bișoc *
7786413009cSGeorge Bișoc * @param[in] Owner
7796413009cSGeorge Bișoc * A SID that represents the main user that identifies the ACL.
7806413009cSGeorge Bișoc *
7816413009cSGeorge Bișoc * @param[in] Group
7826413009cSGeorge Bișoc * A SID that represents a group that identifies the ACL.
7836413009cSGeorge Bișoc *
7846413009cSGeorge Bișoc * @param[out] AclPresent
7856413009cSGeorge Bișoc * The returned boolean value, indicating if the ACL that we want to select
7866413009cSGeorge Bișoc * does actually exist.
7876413009cSGeorge Bișoc *
7886413009cSGeorge Bișoc * @param[out] IsInherited
7896413009cSGeorge Bișoc * The returned boolean value, indicating if the ACL we want to select it
7906413009cSGeorge Bișoc * is actually inherited or not.
7916413009cSGeorge Bișoc *
7926413009cSGeorge Bișoc * @param[in] IsDirectoryObject
7936413009cSGeorge Bișoc * If set to TRUE, the object inherits this ACL.
7946413009cSGeorge Bișoc *
7956413009cSGeorge Bișoc * @param[in] GenericMapping
7966413009cSGeorge Bișoc * Generic mapping of access rights to map only certain effective
7976413009cSGeorge Bișoc * ACEs of an ACL that we want to select it.
7986413009cSGeorge Bișoc *
7996413009cSGeorge Bișoc * @return
8006413009cSGeorge Bișoc * Returns the selected access control list (ACL) to the caller,
8016413009cSGeorge Bișoc * NULL otherwise.
8026413009cSGeorge Bișoc */
803c2c66affSColin Finck PACL
SepSelectAcl(_In_opt_ PACL ExplicitAcl,_In_ BOOLEAN ExplicitPresent,_In_ BOOLEAN ExplicitDefaulted,_In_opt_ PACL ParentAcl,_In_opt_ PACL DefaultAcl,_Out_ PULONG AclLength,_In_ PSID Owner,_In_ PSID Group,_Out_ PBOOLEAN AclPresent,_Out_ PBOOLEAN IsInherited,_In_ BOOLEAN IsDirectoryObject,_In_ PGENERIC_MAPPING GenericMapping)804c2c66affSColin Finck SepSelectAcl(
805c2c66affSColin Finck _In_opt_ PACL ExplicitAcl,
806c2c66affSColin Finck _In_ BOOLEAN ExplicitPresent,
807c2c66affSColin Finck _In_ BOOLEAN ExplicitDefaulted,
808c2c66affSColin Finck _In_opt_ PACL ParentAcl,
809c2c66affSColin Finck _In_opt_ PACL DefaultAcl,
810c2c66affSColin Finck _Out_ PULONG AclLength,
811c2c66affSColin Finck _In_ PSID Owner,
812c2c66affSColin Finck _In_ PSID Group,
813c2c66affSColin Finck _Out_ PBOOLEAN AclPresent,
814c2c66affSColin Finck _Out_ PBOOLEAN IsInherited,
815c2c66affSColin Finck _In_ BOOLEAN IsDirectoryObject,
816c2c66affSColin Finck _In_ PGENERIC_MAPPING GenericMapping)
817c2c66affSColin Finck {
818c2c66affSColin Finck PACL Acl;
819c2c66affSColin Finck NTSTATUS Status;
820c2c66affSColin Finck
821c2c66affSColin Finck *AclPresent = TRUE;
822c2c66affSColin Finck if (ExplicitPresent && !ExplicitDefaulted)
823c2c66affSColin Finck {
824c2c66affSColin Finck Acl = ExplicitAcl;
825c2c66affSColin Finck }
826c2c66affSColin Finck else
827c2c66affSColin Finck {
828c2c66affSColin Finck if (ParentAcl)
829c2c66affSColin Finck {
830c2c66affSColin Finck *IsInherited = TRUE;
831c2c66affSColin Finck *AclLength = 0;
832c2c66affSColin Finck Status = SepPropagateAcl(NULL,
833c2c66affSColin Finck AclLength,
834c2c66affSColin Finck ParentAcl,
835c2c66affSColin Finck Owner,
836c2c66affSColin Finck Group,
837c2c66affSColin Finck *IsInherited,
838c2c66affSColin Finck IsDirectoryObject,
839c2c66affSColin Finck GenericMapping);
840c2c66affSColin Finck ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
841c2c66affSColin Finck
842c2c66affSColin Finck /* Use the parent ACL only if it's not empty */
843c2c66affSColin Finck if (*AclLength != sizeof(ACL))
844c2c66affSColin Finck return ParentAcl;
845c2c66affSColin Finck }
846c2c66affSColin Finck
847c2c66affSColin Finck if (ExplicitPresent)
848c2c66affSColin Finck {
849c2c66affSColin Finck Acl = ExplicitAcl;
850c2c66affSColin Finck }
851c2c66affSColin Finck else if (DefaultAcl)
852c2c66affSColin Finck {
853c2c66affSColin Finck Acl = DefaultAcl;
854c2c66affSColin Finck }
855c2c66affSColin Finck else
856c2c66affSColin Finck {
857c2c66affSColin Finck *AclPresent = FALSE;
858c2c66affSColin Finck Acl = NULL;
859c2c66affSColin Finck }
860c2c66affSColin Finck }
861c2c66affSColin Finck
862c2c66affSColin Finck *IsInherited = FALSE;
863c2c66affSColin Finck *AclLength = 0;
864c2c66affSColin Finck if (Acl)
865c2c66affSColin Finck {
866c2c66affSColin Finck /* Get the length */
867c2c66affSColin Finck Status = SepPropagateAcl(NULL,
868c2c66affSColin Finck AclLength,
869c2c66affSColin Finck Acl,
870c2c66affSColin Finck Owner,
871c2c66affSColin Finck Group,
872c2c66affSColin Finck *IsInherited,
873c2c66affSColin Finck IsDirectoryObject,
874c2c66affSColin Finck GenericMapping);
875c2c66affSColin Finck ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
876c2c66affSColin Finck }
877c2c66affSColin Finck return Acl;
878c2c66affSColin Finck }
879c2c66affSColin Finck
880c2c66affSColin Finck /* EOF */
881