xref: /reactos/ntoskrnl/se/sd.c (revision 8b75dce4)
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:     Security descriptors (SDs) implementation support
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 PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL;
17c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL;
18c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicOpenSd = NULL;
19c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL;
20c2c66affSColin Finck PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL;
21c2c66affSColin Finck PSECURITY_DESCRIPTOR SeUnrestrictedSd = NULL;
22b28530d4SGeorge Bișoc PSECURITY_DESCRIPTOR SeSystemAnonymousLogonSd = NULL;
23c2c66affSColin Finck 
24c2c66affSColin Finck /* PRIVATE FUNCTIONS **********************************************************/
25c2c66affSColin Finck 
266413009cSGeorge Bișoc /**
276413009cSGeorge Bișoc  * @brief
286413009cSGeorge Bișoc  * Initializes the known security descriptors in the system.
296413009cSGeorge Bișoc  *
306413009cSGeorge Bișoc  * @return
316413009cSGeorge Bișoc  * Returns TRUE if all the security descriptors have been initialized,
326413009cSGeorge Bișoc  * FALSE otherwise.
336413009cSGeorge Bișoc  */
345c7ce447SVictor Perevertkin CODE_SEG("INIT")
35b20f8151SSerge Gautherie BOOLEAN
36c2c66affSColin Finck NTAPI
SepInitSDs(VOID)37c2c66affSColin Finck SepInitSDs(VOID)
38c2c66affSColin Finck {
39c2c66affSColin Finck     /* Create PublicDefaultSd */
40c2c66affSColin Finck     SePublicDefaultSd = ExAllocatePoolWithTag(PagedPool,
41c2c66affSColin Finck                                               sizeof(SECURITY_DESCRIPTOR), TAG_SD);
42c2c66affSColin Finck     if (SePublicDefaultSd == NULL)
43c2c66affSColin Finck         return FALSE;
44c2c66affSColin Finck 
45c2c66affSColin Finck     RtlCreateSecurityDescriptor(SePublicDefaultSd,
46c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
47c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SePublicDefaultSd,
48c2c66affSColin Finck                                  TRUE,
49c2c66affSColin Finck                                  SePublicDefaultDacl,
50c2c66affSColin Finck                                  FALSE);
51c2c66affSColin Finck 
52c2c66affSColin Finck     /* Create PublicDefaultUnrestrictedSd */
53c2c66affSColin Finck     SePublicDefaultUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
54c2c66affSColin Finck                                                           sizeof(SECURITY_DESCRIPTOR), TAG_SD);
55c2c66affSColin Finck     if (SePublicDefaultUnrestrictedSd == NULL)
56c2c66affSColin Finck         return FALSE;
57c2c66affSColin Finck 
58c2c66affSColin Finck     RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd,
59c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
60c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd,
61c2c66affSColin Finck                                  TRUE,
62c2c66affSColin Finck                                  SePublicDefaultUnrestrictedDacl,
63c2c66affSColin Finck                                  FALSE);
64c2c66affSColin Finck 
65c2c66affSColin Finck     /* Create PublicOpenSd */
66c2c66affSColin Finck     SePublicOpenSd = ExAllocatePoolWithTag(PagedPool,
67c2c66affSColin Finck                                            sizeof(SECURITY_DESCRIPTOR), TAG_SD);
68c2c66affSColin Finck     if (SePublicOpenSd == NULL)
69c2c66affSColin Finck         return FALSE;
70c2c66affSColin Finck 
71c2c66affSColin Finck     RtlCreateSecurityDescriptor(SePublicOpenSd,
72c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
73c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SePublicOpenSd,
74c2c66affSColin Finck                                  TRUE,
75c2c66affSColin Finck                                  SePublicOpenDacl,
76c2c66affSColin Finck                                  FALSE);
77c2c66affSColin Finck 
78c2c66affSColin Finck     /* Create PublicOpenUnrestrictedSd */
79c2c66affSColin Finck     SePublicOpenUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
80c2c66affSColin Finck                                                        sizeof(SECURITY_DESCRIPTOR), TAG_SD);
81c2c66affSColin Finck     if (SePublicOpenUnrestrictedSd == NULL)
82c2c66affSColin Finck         return FALSE;
83c2c66affSColin Finck 
84c2c66affSColin Finck     RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd,
85c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
86c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd,
87c2c66affSColin Finck                                  TRUE,
88c2c66affSColin Finck                                  SePublicOpenUnrestrictedDacl,
89c2c66affSColin Finck                                  FALSE);
90c2c66affSColin Finck 
91c2c66affSColin Finck     /* Create SystemDefaultSd */
92c2c66affSColin Finck     SeSystemDefaultSd = ExAllocatePoolWithTag(PagedPool,
93c2c66affSColin Finck                                               sizeof(SECURITY_DESCRIPTOR), TAG_SD);
94c2c66affSColin Finck     if (SeSystemDefaultSd == NULL)
95c2c66affSColin Finck         return FALSE;
96c2c66affSColin Finck 
97c2c66affSColin Finck     RtlCreateSecurityDescriptor(SeSystemDefaultSd,
98c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
99c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SeSystemDefaultSd,
100c2c66affSColin Finck                                  TRUE,
101c2c66affSColin Finck                                  SeSystemDefaultDacl,
102c2c66affSColin Finck                                  FALSE);
103c2c66affSColin Finck 
104c2c66affSColin Finck     /* Create UnrestrictedSd */
105c2c66affSColin Finck     SeUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
106c2c66affSColin Finck                                              sizeof(SECURITY_DESCRIPTOR), TAG_SD);
107c2c66affSColin Finck     if (SeUnrestrictedSd == NULL)
108c2c66affSColin Finck         return FALSE;
109c2c66affSColin Finck 
110c2c66affSColin Finck     RtlCreateSecurityDescriptor(SeUnrestrictedSd,
111c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
112c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SeUnrestrictedSd,
113c2c66affSColin Finck                                  TRUE,
114c2c66affSColin Finck                                  SeUnrestrictedDacl,
115c2c66affSColin Finck                                  FALSE);
116c2c66affSColin Finck 
117b28530d4SGeorge Bișoc     /* Create SystemAnonymousLogonSd */
118b28530d4SGeorge Bișoc     SeSystemAnonymousLogonSd = ExAllocatePoolWithTag(PagedPool,
119b28530d4SGeorge Bișoc                                                      sizeof(SECURITY_DESCRIPTOR), TAG_SD);
120b28530d4SGeorge Bișoc     if (SeSystemAnonymousLogonSd == NULL)
121b28530d4SGeorge Bișoc         return FALSE;
122b28530d4SGeorge Bișoc 
123b28530d4SGeorge Bișoc     RtlCreateSecurityDescriptor(SeSystemAnonymousLogonSd,
124b28530d4SGeorge Bișoc                                 SECURITY_DESCRIPTOR_REVISION);
125b28530d4SGeorge Bișoc     RtlSetDaclSecurityDescriptor(SeSystemAnonymousLogonSd,
126b28530d4SGeorge Bișoc                                  TRUE,
127b28530d4SGeorge Bișoc                                  SeSystemAnonymousLogonDacl,
128b28530d4SGeorge Bișoc                                  FALSE);
129b28530d4SGeorge Bișoc 
130c2c66affSColin Finck     return TRUE;
131c2c66affSColin Finck }
132c2c66affSColin Finck 
1336413009cSGeorge Bișoc /**
1346413009cSGeorge Bișoc  * @brief
1356413009cSGeorge Bișoc  * Sets a "World" security descriptor.
1366413009cSGeorge Bișoc  *
1376413009cSGeorge Bișoc  * @param[in] SecurityInformation
1386413009cSGeorge Bișoc  * Security information details, alongside with the security
1396413009cSGeorge Bișoc  * descriptor to set the World SD.
1406413009cSGeorge Bișoc  *
1416413009cSGeorge Bișoc  * @param[in] SecurityDescriptor
1426413009cSGeorge Bișoc  * A security descriptor buffer.
1436413009cSGeorge Bișoc  *
1446413009cSGeorge Bișoc  * @param[in] BufferLength
1456413009cSGeorge Bișoc  * Length size of the buffer.
1466413009cSGeorge Bișoc  *
1476413009cSGeorge Bișoc  * @return
1486413009cSGeorge Bișoc  * Returns STATUS_SUCCESS if the World security descriptor has been
1496413009cSGeorge Bișoc  * set. STATUS_ACCESS_DENIED is returned if the caller hasn't
1506413009cSGeorge Bișoc  * provided security information details thus the SD cannot
1516413009cSGeorge Bișoc  * be set.
1526413009cSGeorge Bișoc  */
153c2c66affSColin Finck NTSTATUS
154c2c66affSColin Finck NTAPI
SeSetWorldSecurityDescriptor(_In_ SECURITY_INFORMATION SecurityInformation,_In_ PISECURITY_DESCRIPTOR SecurityDescriptor,_In_ PULONG BufferLength)1558567d814SGeorge Bișoc SeSetWorldSecurityDescriptor(
1568567d814SGeorge Bișoc     _In_ SECURITY_INFORMATION SecurityInformation,
1578567d814SGeorge Bișoc     _In_ PISECURITY_DESCRIPTOR SecurityDescriptor,
1588567d814SGeorge Bișoc     _In_ PULONG BufferLength)
159c2c66affSColin Finck {
160c2c66affSColin Finck     ULONG Current;
161c2c66affSColin Finck     ULONG SidSize;
162c2c66affSColin Finck     ULONG SdSize;
163c2c66affSColin Finck     NTSTATUS Status;
164c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
165c2c66affSColin Finck 
166c2c66affSColin Finck     DPRINT("SeSetWorldSecurityDescriptor() called\n");
167c2c66affSColin Finck 
168c2c66affSColin Finck     if (SecurityInformation == 0)
169c2c66affSColin Finck     {
170c2c66affSColin Finck         return STATUS_ACCESS_DENIED;
171c2c66affSColin Finck     }
172c2c66affSColin Finck 
173c2c66affSColin Finck     /* calculate the minimum size of the buffer */
174c2c66affSColin Finck     SidSize = RtlLengthSid(SeWorldSid);
175c2c66affSColin Finck     SdSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
176c2c66affSColin Finck     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
177c2c66affSColin Finck         SdSize += SidSize;
178c2c66affSColin Finck     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
179c2c66affSColin Finck         SdSize += SidSize;
180c2c66affSColin Finck     if (SecurityInformation & DACL_SECURITY_INFORMATION)
181c2c66affSColin Finck     {
182c2c66affSColin Finck         SdSize += sizeof(ACL) + sizeof(ACE) + SidSize;
183c2c66affSColin Finck     }
184f341b908SGeorge Bișoc     if (SecurityInformation & SACL_SECURITY_INFORMATION)
185f341b908SGeorge Bișoc     {
186f341b908SGeorge Bișoc         SdSize += sizeof(ACL) + sizeof(ACE) + SidSize;
187f341b908SGeorge Bișoc     }
188c2c66affSColin Finck 
189c2c66affSColin Finck     if (*BufferLength < SdSize)
190c2c66affSColin Finck     {
191c2c66affSColin Finck         *BufferLength = SdSize;
192c2c66affSColin Finck         return STATUS_BUFFER_TOO_SMALL;
193c2c66affSColin Finck     }
194c2c66affSColin Finck 
195c2c66affSColin Finck     *BufferLength = SdSize;
196c2c66affSColin Finck 
197c2c66affSColin Finck     Status = RtlCreateSecurityDescriptorRelative(SdRel,
198c2c66affSColin Finck                                                  SECURITY_DESCRIPTOR_REVISION);
199c2c66affSColin Finck     if (!NT_SUCCESS(Status))
200c2c66affSColin Finck     {
201c2c66affSColin Finck         return Status;
202c2c66affSColin Finck     }
203c2c66affSColin Finck 
204c2c66affSColin Finck     Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
205c2c66affSColin Finck 
206c2c66affSColin Finck     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
207c2c66affSColin Finck     {
208c2c66affSColin Finck         RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize);
209c2c66affSColin Finck         SdRel->Owner = Current;
210c2c66affSColin Finck         Current += SidSize;
211c2c66affSColin Finck     }
212c2c66affSColin Finck 
213c2c66affSColin Finck     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
214c2c66affSColin Finck     {
215c2c66affSColin Finck         RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize);
216c2c66affSColin Finck         SdRel->Group = Current;
217c2c66affSColin Finck         Current += SidSize;
218c2c66affSColin Finck     }
219c2c66affSColin Finck 
220c2c66affSColin Finck     if (SecurityInformation & DACL_SECURITY_INFORMATION)
221c2c66affSColin Finck     {
222c2c66affSColin Finck         PACL Dacl = (PACL)((PUCHAR)SdRel + Current);
223c2c66affSColin Finck 
224c2c66affSColin Finck         Status = RtlCreateAcl(Dacl,
225c2c66affSColin Finck                               sizeof(ACL) + sizeof(ACE) + SidSize,
226c2c66affSColin Finck                               ACL_REVISION);
227c2c66affSColin Finck         if (!NT_SUCCESS(Status))
228c2c66affSColin Finck             return Status;
229c2c66affSColin Finck 
230c2c66affSColin Finck         Status = RtlAddAccessAllowedAce(Dacl,
231c2c66affSColin Finck                                         ACL_REVISION,
232c2c66affSColin Finck                                         GENERIC_ALL,
233c2c66affSColin Finck                                         SeWorldSid);
234c2c66affSColin Finck         if (!NT_SUCCESS(Status))
235c2c66affSColin Finck             return Status;
236c2c66affSColin Finck 
2370b4763f1SGeorge Bișoc         SdRel->Control |= SE_DACL_PRESENT;
238c2c66affSColin Finck         SdRel->Dacl = Current;
2390b4763f1SGeorge Bișoc         Current += SidSize;
240c2c66affSColin Finck     }
241c2c66affSColin Finck 
242c2c66affSColin Finck     if (SecurityInformation & SACL_SECURITY_INFORMATION)
243c2c66affSColin Finck     {
244f341b908SGeorge Bișoc         PACL Sacl = (PACL)((PUCHAR)SdRel + Current);
245f341b908SGeorge Bișoc 
246f341b908SGeorge Bișoc         Status = RtlCreateAcl(Sacl,
247f341b908SGeorge Bișoc                               sizeof(ACL) + sizeof(ACE) + SidSize,
248f341b908SGeorge Bișoc                               ACL_REVISION);
249f341b908SGeorge Bișoc         if (!NT_SUCCESS(Status))
250f341b908SGeorge Bișoc             return Status;
251f341b908SGeorge Bișoc 
252f341b908SGeorge Bișoc         Status = RtlAddAuditAccessAce(Sacl,
253f341b908SGeorge Bișoc                                       ACL_REVISION,
254f341b908SGeorge Bișoc                                       ACCESS_SYSTEM_SECURITY | STANDARD_RIGHTS_ALL,
255f341b908SGeorge Bișoc                                       SeWorldSid,
256f341b908SGeorge Bișoc                                       TRUE,
257f341b908SGeorge Bișoc                                       TRUE);
258f341b908SGeorge Bișoc         if (!NT_SUCCESS(Status))
259f341b908SGeorge Bișoc             return Status;
260f341b908SGeorge Bișoc 
261f341b908SGeorge Bișoc         SdRel->Control |= SE_SACL_PRESENT;
262f341b908SGeorge Bișoc         SdRel->Sacl = Current;
263f341b908SGeorge Bișoc         Current += SidSize;
264c2c66affSColin Finck     }
265c2c66affSColin Finck 
266c2c66affSColin Finck     return STATUS_SUCCESS;
267c2c66affSColin Finck }
268c2c66affSColin Finck 
269c2c66affSColin Finck /* PUBLIC FUNCTIONS ***********************************************************/
270c2c66affSColin Finck 
2716413009cSGeorge Bișoc /**
2726413009cSGeorge Bișoc  * @brief
2736413009cSGeorge Bișoc  * Determines the size of a SID.
2746413009cSGeorge Bișoc  *
2756413009cSGeorge Bișoc  * @param[in] Sid
2766413009cSGeorge Bișoc  * A security identifier where its size is to be determined.
2776413009cSGeorge Bișoc  *
2786413009cSGeorge Bișoc  * @param[in,out] OutSAC
2796413009cSGeorge Bișoc  * The returned sub authority count of the security
2806413009cSGeorge Bișoc  * identifier.
2816413009cSGeorge Bișoc  *
2826413009cSGeorge Bișoc  * @param[in] ProcessorMode
2836413009cSGeorge Bișoc  * Processor level access mode.
2846413009cSGeorge Bișoc  *
2856413009cSGeorge Bișoc  * @return
2866413009cSGeorge Bișoc  * Returns the size length of a security identifier (SID).
2876413009cSGeorge Bișoc  */
288c2c66affSColin Finck static
289c2c66affSColin Finck ULONG
DetermineSIDSize(_In_ PISID Sid,_Inout_ PULONG OutSAC,_In_ KPROCESSOR_MODE ProcessorMode)290c2c66affSColin Finck DetermineSIDSize(
2918567d814SGeorge Bișoc     _In_ PISID Sid,
2928567d814SGeorge Bișoc     _Inout_ PULONG OutSAC,
2938567d814SGeorge Bișoc     _In_ KPROCESSOR_MODE ProcessorMode)
294c2c66affSColin Finck {
295c2c66affSColin Finck     ULONG Size;
296c2c66affSColin Finck 
297c2c66affSColin Finck     if (!Sid)
298c2c66affSColin Finck     {
299c2c66affSColin Finck         *OutSAC = 0;
300c2c66affSColin Finck         return 0;
301c2c66affSColin Finck     }
302c2c66affSColin Finck 
303c2c66affSColin Finck     if (ProcessorMode != KernelMode)
304c2c66affSColin Finck     {
305c2c66affSColin Finck         /* Securely access the buffers! */
306c2c66affSColin Finck         *OutSAC = ProbeForReadUchar(&Sid->SubAuthorityCount);
307c2c66affSColin Finck         Size = RtlLengthRequiredSid(*OutSAC);
308c2c66affSColin Finck         ProbeForRead(Sid, Size, sizeof(ULONG));
309c2c66affSColin Finck     }
310c2c66affSColin Finck     else
311c2c66affSColin Finck     {
312c2c66affSColin Finck         *OutSAC = Sid->SubAuthorityCount;
313c2c66affSColin Finck         Size = RtlLengthRequiredSid(*OutSAC);
314c2c66affSColin Finck     }
315c2c66affSColin Finck 
316c2c66affSColin Finck     return Size;
317c2c66affSColin Finck }
318c2c66affSColin Finck 
3196413009cSGeorge Bișoc /**
3206413009cSGeorge Bișoc  * @brief
3216413009cSGeorge Bișoc  * Determines the size of an ACL.
3226413009cSGeorge Bișoc  *
3236413009cSGeorge Bișoc  * @param[in] Acl
3246413009cSGeorge Bișoc  * An access control list where its size is to be
3256413009cSGeorge Bișoc  * determined.
3266413009cSGeorge Bișoc  *
3276413009cSGeorge Bișoc  * @param[in] ProcessorMode
3286413009cSGeorge Bișoc  * Processor level access mode.
3296413009cSGeorge Bișoc  *
3306413009cSGeorge Bișoc  * @return
3316413009cSGeorge Bișoc  * Returns the size length of a an access control
3326413009cSGeorge Bișoc  * list (ACL).
3336413009cSGeorge Bișoc  */
334c2c66affSColin Finck static
335c2c66affSColin Finck ULONG
DetermineACLSize(_In_ PACL Acl,_In_ KPROCESSOR_MODE ProcessorMode)336c2c66affSColin Finck DetermineACLSize(
3378567d814SGeorge Bișoc     _In_ PACL Acl,
3388567d814SGeorge Bișoc     _In_ KPROCESSOR_MODE ProcessorMode)
339c2c66affSColin Finck {
340c2c66affSColin Finck     ULONG Size;
341c2c66affSColin Finck 
342c2c66affSColin Finck     if (!Acl) return 0;
343c2c66affSColin Finck 
344c2c66affSColin Finck     if (ProcessorMode == KernelMode) return Acl->AclSize;
345c2c66affSColin Finck 
346c2c66affSColin Finck     /* Probe the buffers! */
347c2c66affSColin Finck     Size = ProbeForReadUshort(&Acl->AclSize);
348c2c66affSColin Finck     ProbeForRead(Acl, Size, sizeof(ULONG));
349c2c66affSColin Finck 
350c2c66affSColin Finck     return Size;
351c2c66affSColin Finck }
352c2c66affSColin Finck 
3536413009cSGeorge Bișoc /**
3546413009cSGeorge Bișoc  * @brief
3556413009cSGeorge Bișoc  * Captures a security descriptor.
3566413009cSGeorge Bișoc  *
3576413009cSGeorge Bișoc  * @param[in] _OriginalSecurityDescriptor
3586413009cSGeorge Bișoc  * An already existing and valid security descriptor
3596413009cSGeorge Bișoc  * to be captured.
3606413009cSGeorge Bișoc  *
3616413009cSGeorge Bișoc  * @param[in] CurrentMode
3626413009cSGeorge Bișoc  * Processor level access mode.
3636413009cSGeorge Bișoc  *
3646413009cSGeorge Bișoc  * @param[in] PoolType
3656413009cSGeorge Bișoc  * Pool type to be used when allocating the captured
3666413009cSGeorge Bișoc  * buffer.
3676413009cSGeorge Bișoc  *
3686413009cSGeorge Bișoc  * @param[in] CaptureIfKernel
3696413009cSGeorge Bișoc  * Set this to TRUE if capturing is done within the
3706413009cSGeorge Bișoc  * kernel.
3716413009cSGeorge Bișoc  *
3726413009cSGeorge Bișoc  * @param[out] CapturedSecurityDescriptor
3736413009cSGeorge Bișoc  * The captured security descriptor.
3746413009cSGeorge Bișoc  *
3756413009cSGeorge Bișoc  * @return
3766413009cSGeorge Bișoc  * Returns STATUS_SUCCESS if the operations have been
3776413009cSGeorge Bișoc  * completed successfully and that the security descriptor
3786413009cSGeorge Bișoc  * has been captured. STATUS_UNKNOWN_REVISION is returned
3796413009cSGeorge Bișoc  * if the security descriptor has an unknown revision.
3806413009cSGeorge Bișoc  * STATUS_INSUFFICIENT_RESOURCES is returned if memory
3816413009cSGeorge Bișoc  * pool allocation for the captured buffer has failed.
3826413009cSGeorge Bișoc  * A failure NTSTATUS code is returned otherwise.
3836413009cSGeorge Bișoc  */
384c2c66affSColin Finck NTSTATUS
385c2c66affSColin Finck NTAPI
SeCaptureSecurityDescriptor(_In_ PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor,_In_ KPROCESSOR_MODE CurrentMode,_In_ POOL_TYPE PoolType,_In_ BOOLEAN CaptureIfKernel,_Out_ PSECURITY_DESCRIPTOR * CapturedSecurityDescriptor)386c2c66affSColin Finck SeCaptureSecurityDescriptor(
3878567d814SGeorge Bișoc     _In_ PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor,
3888567d814SGeorge Bișoc     _In_ KPROCESSOR_MODE CurrentMode,
3898567d814SGeorge Bișoc     _In_ POOL_TYPE PoolType,
3908567d814SGeorge Bișoc     _In_ BOOLEAN CaptureIfKernel,
3918567d814SGeorge Bișoc     _Out_ PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor)
392c2c66affSColin Finck {
393c2c66affSColin Finck     PISECURITY_DESCRIPTOR OriginalDescriptor = _OriginalSecurityDescriptor;
394c2c66affSColin Finck     SECURITY_DESCRIPTOR DescriptorCopy;
395c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor;
396c2c66affSColin Finck     ULONG OwnerSAC = 0, GroupSAC = 0;
397c2c66affSColin Finck     ULONG OwnerSize = 0, GroupSize = 0;
398c2c66affSColin Finck     ULONG SaclSize = 0, DaclSize = 0;
399c2c66affSColin Finck     ULONG DescriptorSize = 0;
400c2c66affSColin Finck     ULONG Offset;
401c2c66affSColin Finck 
402c2c66affSColin Finck     if (!OriginalDescriptor)
403c2c66affSColin Finck     {
404c2c66affSColin Finck         /* Nothing to do... */
405c2c66affSColin Finck         *CapturedSecurityDescriptor = NULL;
406c2c66affSColin Finck         return STATUS_SUCCESS;
407c2c66affSColin Finck     }
408c2c66affSColin Finck 
409c2c66affSColin Finck     /* Quick path */
410c2c66affSColin Finck     if (CurrentMode == KernelMode && !CaptureIfKernel)
411c2c66affSColin Finck     {
412c2c66affSColin Finck         /* Check descriptor version */
413c2c66affSColin Finck         if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
414c2c66affSColin Finck         {
415c2c66affSColin Finck             return STATUS_UNKNOWN_REVISION;
416c2c66affSColin Finck         }
417c2c66affSColin Finck 
418c2c66affSColin Finck         *CapturedSecurityDescriptor = _OriginalSecurityDescriptor;
419c2c66affSColin Finck         return STATUS_SUCCESS;
420c2c66affSColin Finck     }
421c2c66affSColin Finck 
422c2c66affSColin Finck     _SEH2_TRY
423c2c66affSColin Finck     {
424c2c66affSColin Finck         if (CurrentMode != KernelMode)
425c2c66affSColin Finck         {
426c2c66affSColin Finck             ProbeForRead(OriginalDescriptor,
427c2c66affSColin Finck                          sizeof(SECURITY_DESCRIPTOR_RELATIVE),
428c2c66affSColin Finck                          sizeof(ULONG));
429c2c66affSColin Finck         }
430c2c66affSColin Finck 
431c2c66affSColin Finck         /* Check the descriptor version */
432c2c66affSColin Finck         if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
433c2c66affSColin Finck         {
434c2c66affSColin Finck             _SEH2_YIELD(return STATUS_UNKNOWN_REVISION);
435c2c66affSColin Finck         }
436c2c66affSColin Finck 
437c2c66affSColin Finck         if (CurrentMode != KernelMode)
438c2c66affSColin Finck         {
439c2c66affSColin Finck             /* Get the size of the descriptor */
440c2c66affSColin Finck             DescriptorSize = (OriginalDescriptor->Control & SE_SELF_RELATIVE) ?
441c2c66affSColin Finck                 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR);
442c2c66affSColin Finck 
443c2c66affSColin Finck             /* Probe the entire security descriptor structure. The SIDs
444c2c66affSColin Finck              * and ACLs will be probed and copied later though */
445c2c66affSColin Finck             ProbeForRead(OriginalDescriptor, DescriptorSize, sizeof(ULONG));
446c2c66affSColin Finck         }
447c2c66affSColin Finck 
448c2c66affSColin Finck         /* Now capture all fields and convert to an absolute descriptor */
449c2c66affSColin Finck         DescriptorCopy.Revision = OriginalDescriptor->Revision;
450c2c66affSColin Finck         DescriptorCopy.Sbz1 = OriginalDescriptor->Sbz1;
451c2c66affSColin Finck         DescriptorCopy.Control = OriginalDescriptor->Control & ~SE_SELF_RELATIVE;
452c2c66affSColin Finck         DescriptorCopy.Owner = SepGetOwnerFromDescriptor(OriginalDescriptor);
453c2c66affSColin Finck         DescriptorCopy.Group = SepGetGroupFromDescriptor(OriginalDescriptor);
454c2c66affSColin Finck         DescriptorCopy.Sacl = SepGetSaclFromDescriptor(OriginalDescriptor);
455c2c66affSColin Finck         DescriptorCopy.Dacl = SepGetDaclFromDescriptor(OriginalDescriptor);
456c2c66affSColin Finck         DescriptorSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
457c2c66affSColin Finck 
458c2c66affSColin Finck         /* Determine owner and group sizes */
459c2c66affSColin Finck         OwnerSize = DetermineSIDSize(DescriptorCopy.Owner, &OwnerSAC, CurrentMode);
460c2c66affSColin Finck         DescriptorSize += ROUND_UP(OwnerSize, sizeof(ULONG));
461c2c66affSColin Finck         GroupSize = DetermineSIDSize(DescriptorCopy.Group, &GroupSAC, CurrentMode);
462c2c66affSColin Finck         DescriptorSize += ROUND_UP(GroupSize, sizeof(ULONG));
463c2c66affSColin Finck 
464c2c66affSColin Finck         /* Determine the size of the ACLs */
465c2c66affSColin Finck         if (DescriptorCopy.Control & SE_SACL_PRESENT)
466c2c66affSColin Finck         {
467c2c66affSColin Finck             /* Get the size and probe if user mode */
468c2c66affSColin Finck             SaclSize = DetermineACLSize(DescriptorCopy.Sacl, CurrentMode);
469c2c66affSColin Finck             DescriptorSize += ROUND_UP(SaclSize, sizeof(ULONG));
470c2c66affSColin Finck         }
471c2c66affSColin Finck 
472c2c66affSColin Finck         if (DescriptorCopy.Control & SE_DACL_PRESENT)
473c2c66affSColin Finck         {
474c2c66affSColin Finck             /* Get the size and probe if user mode */
475c2c66affSColin Finck             DaclSize = DetermineACLSize(DescriptorCopy.Dacl, CurrentMode);
476c2c66affSColin Finck             DescriptorSize += ROUND_UP(DaclSize, sizeof(ULONG));
477c2c66affSColin Finck         }
478c2c66affSColin Finck     }
479c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
480c2c66affSColin Finck     {
481c2c66affSColin Finck         _SEH2_YIELD(return _SEH2_GetExceptionCode());
482c2c66affSColin Finck     }
483c2c66affSColin Finck     _SEH2_END;
484c2c66affSColin Finck 
485c2c66affSColin Finck     /*
486c2c66affSColin Finck      * Allocate enough memory to store a complete copy of a self-relative
487c2c66affSColin Finck      * security descriptor
488c2c66affSColin Finck      */
489c2c66affSColin Finck     NewDescriptor = ExAllocatePoolWithTag(PoolType,
490c2c66affSColin Finck                                           DescriptorSize,
491c2c66affSColin Finck                                           TAG_SD);
492c2c66affSColin Finck     if (!NewDescriptor) return STATUS_INSUFFICIENT_RESOURCES;
493c2c66affSColin Finck 
494c2c66affSColin Finck     RtlZeroMemory(NewDescriptor, DescriptorSize);
495c2c66affSColin Finck     NewDescriptor->Revision = DescriptorCopy.Revision;
496c2c66affSColin Finck     NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
497c2c66affSColin Finck     NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
498c2c66affSColin Finck 
499c2c66affSColin Finck     _SEH2_TRY
500c2c66affSColin Finck     {
501c2c66affSColin Finck         /*
502c2c66affSColin Finck          * Setup the offsets and copy the SIDs and ACLs to the new
503c2c66affSColin Finck          * self-relative security descriptor. Probing the pointers is not
504c2c66affSColin Finck          * neccessary anymore as we did that when collecting the sizes!
505c2c66affSColin Finck          * Make sure to validate the SIDs and ACLs *again* as they could have
506c2c66affSColin Finck          * been modified in the meanwhile!
507c2c66affSColin Finck          */
508c2c66affSColin Finck         Offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
509c2c66affSColin Finck 
510c2c66affSColin Finck         if (DescriptorCopy.Owner)
511c2c66affSColin Finck         {
512c2c66affSColin Finck             if (!RtlValidSid(DescriptorCopy.Owner)) RtlRaiseStatus(STATUS_INVALID_SID);
513c2c66affSColin Finck             NewDescriptor->Owner = Offset;
514c2c66affSColin Finck             RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
515c2c66affSColin Finck                           DescriptorCopy.Owner,
516c2c66affSColin Finck                           OwnerSize);
517c2c66affSColin Finck             Offset += ROUND_UP(OwnerSize, sizeof(ULONG));
518c2c66affSColin Finck         }
519c2c66affSColin Finck 
520c2c66affSColin Finck         if (DescriptorCopy.Group)
521c2c66affSColin Finck         {
522c2c66affSColin Finck             if (!RtlValidSid(DescriptorCopy.Group)) RtlRaiseStatus(STATUS_INVALID_SID);
523c2c66affSColin Finck             NewDescriptor->Group = Offset;
524c2c66affSColin Finck             RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
525c2c66affSColin Finck                           DescriptorCopy.Group,
526c2c66affSColin Finck                           GroupSize);
527c2c66affSColin Finck             Offset += ROUND_UP(GroupSize, sizeof(ULONG));
528c2c66affSColin Finck         }
529c2c66affSColin Finck 
530c2c66affSColin Finck         if (DescriptorCopy.Sacl)
531c2c66affSColin Finck         {
532c2c66affSColin Finck             if (!RtlValidAcl(DescriptorCopy.Sacl)) RtlRaiseStatus(STATUS_INVALID_ACL);
533c2c66affSColin Finck             NewDescriptor->Sacl = Offset;
534c2c66affSColin Finck             RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
535c2c66affSColin Finck                           DescriptorCopy.Sacl,
536c2c66affSColin Finck                           SaclSize);
537c2c66affSColin Finck             Offset += ROUND_UP(SaclSize, sizeof(ULONG));
538c2c66affSColin Finck         }
539c2c66affSColin Finck 
540c2c66affSColin Finck         if (DescriptorCopy.Dacl)
541c2c66affSColin Finck         {
542c2c66affSColin Finck             if (!RtlValidAcl(DescriptorCopy.Dacl)) RtlRaiseStatus(STATUS_INVALID_ACL);
543c2c66affSColin Finck             NewDescriptor->Dacl = Offset;
544c2c66affSColin Finck             RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
545c2c66affSColin Finck                           DescriptorCopy.Dacl,
546c2c66affSColin Finck                           DaclSize);
547c2c66affSColin Finck             Offset += ROUND_UP(DaclSize, sizeof(ULONG));
548c2c66affSColin Finck         }
549c2c66affSColin Finck 
550c2c66affSColin Finck         /* Make sure the size was correct */
551c2c66affSColin Finck         ASSERT(Offset == DescriptorSize);
552c2c66affSColin Finck     }
553c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
554c2c66affSColin Finck     {
555c2c66affSColin Finck         /* We failed to copy the data to the new descriptor */
556c2c66affSColin Finck         ExFreePoolWithTag(NewDescriptor, TAG_SD);
557c2c66affSColin Finck         _SEH2_YIELD(return _SEH2_GetExceptionCode());
558c2c66affSColin Finck     }
559c2c66affSColin Finck     _SEH2_END;
560c2c66affSColin Finck 
561c2c66affSColin Finck     /*
562c2c66affSColin Finck      * We're finally done!
563c2c66affSColin Finck      * Copy the pointer to the captured descriptor to to the caller.
564c2c66affSColin Finck      */
565c2c66affSColin Finck     *CapturedSecurityDescriptor = NewDescriptor;
566c2c66affSColin Finck     return STATUS_SUCCESS;
567c2c66affSColin Finck }
568c2c66affSColin Finck 
5696413009cSGeorge Bișoc /**
5706413009cSGeorge Bișoc  * @brief
5716413009cSGeorge Bișoc  * Queries information details about a security
5726413009cSGeorge Bișoc  * descriptor.
5736413009cSGeorge Bișoc  *
5746413009cSGeorge Bișoc  * @param[in] SecurityInformation
5756413009cSGeorge Bișoc  * Security information details to be queried
5766413009cSGeorge Bișoc  * from a security descriptor.
5776413009cSGeorge Bișoc  *
5786413009cSGeorge Bișoc  * @param[out] SecurityDescriptor
5796413009cSGeorge Bișoc  * The returned security descriptor with security information
5806413009cSGeorge Bișoc  * data.
5816413009cSGeorge Bișoc  *
5826413009cSGeorge Bișoc  * @param[in,out] Length
5836413009cSGeorge Bișoc  * The returned length of a security descriptor.
5846413009cSGeorge Bișoc  *
5856413009cSGeorge Bișoc  * @param[in,out] ObjectsSecurityDescriptor
5866413009cSGeorge Bișoc  * The returned object security descriptor.
5876413009cSGeorge Bișoc  *
5886413009cSGeorge Bișoc  * @return
5896413009cSGeorge Bișoc  * Returns STATUS_SUCCESS if the operations have been
5906413009cSGeorge Bișoc  * completed successfully and that the specific information
5916413009cSGeorge Bișoc  * about the security descriptor has been queried.
5926413009cSGeorge Bișoc  * STATUS_BUFFER_TOO_SMALL is returned if the buffer size
5936413009cSGeorge Bișoc  * is too small to contain the queried info about the
5946413009cSGeorge Bișoc  * security descriptor.
595c2c66affSColin Finck  */
_IRQL_requires_max_(PASSIVE_LEVEL)596c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
597c2c66affSColin Finck NTSTATUS
598c2c66affSColin Finck NTAPI
599c2c66affSColin Finck SeQuerySecurityDescriptorInfo(
600c2c66affSColin Finck     _In_ PSECURITY_INFORMATION SecurityInformation,
601c2c66affSColin Finck     _Out_writes_bytes_(*Length) PSECURITY_DESCRIPTOR SecurityDescriptor,
602c2c66affSColin Finck     _Inout_ PULONG Length,
603c2c66affSColin Finck     _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor)
604c2c66affSColin Finck {
605c2c66affSColin Finck     PISECURITY_DESCRIPTOR ObjectSd;
606c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE RelSD;
607c2c66affSColin Finck     PSID Owner = NULL;
608c2c66affSColin Finck     PSID Group = NULL;
609c2c66affSColin Finck     PACL Dacl = NULL;
610c2c66affSColin Finck     PACL Sacl = NULL;
611c2c66affSColin Finck     ULONG OwnerLength = 0;
612c2c66affSColin Finck     ULONG GroupLength = 0;
613c2c66affSColin Finck     ULONG DaclLength = 0;
614c2c66affSColin Finck     ULONG SaclLength = 0;
615c2c66affSColin Finck     SECURITY_DESCRIPTOR_CONTROL Control = 0;
616c2c66affSColin Finck     ULONG_PTR Current;
617c2c66affSColin Finck     ULONG SdLength;
618c2c66affSColin Finck 
619c2c66affSColin Finck     PAGED_CODE();
620c2c66affSColin Finck 
621c2c66affSColin Finck     RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
622c2c66affSColin Finck 
623c2c66affSColin Finck     if (*ObjectsSecurityDescriptor == NULL)
624c2c66affSColin Finck     {
625c2c66affSColin Finck         if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
626c2c66affSColin Finck         {
627c2c66affSColin Finck             *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
628c2c66affSColin Finck             return STATUS_BUFFER_TOO_SMALL;
629c2c66affSColin Finck         }
630c2c66affSColin Finck 
631c2c66affSColin Finck         *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
632c2c66affSColin Finck         RtlCreateSecurityDescriptorRelative(RelSD,
633c2c66affSColin Finck                                             SECURITY_DESCRIPTOR_REVISION);
634c2c66affSColin Finck         return STATUS_SUCCESS;
635c2c66affSColin Finck     }
636c2c66affSColin Finck 
637c2c66affSColin Finck     ObjectSd = *ObjectsSecurityDescriptor;
638c2c66affSColin Finck 
639c2c66affSColin Finck     /* Calculate the required security descriptor length */
640c2c66affSColin Finck     Control = SE_SELF_RELATIVE;
641274bc4deSTimo Kreuzer     if (*SecurityInformation & OWNER_SECURITY_INFORMATION)
642c2c66affSColin Finck     {
643274bc4deSTimo Kreuzer         Owner = SepGetOwnerFromDescriptor(ObjectSd);
644274bc4deSTimo Kreuzer         if (Owner != NULL)
645274bc4deSTimo Kreuzer         {
646c2c66affSColin Finck             OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
647c2c66affSColin Finck             Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
648c2c66affSColin Finck         }
649274bc4deSTimo Kreuzer     }
650c2c66affSColin Finck 
651274bc4deSTimo Kreuzer     if (*SecurityInformation & GROUP_SECURITY_INFORMATION)
652c2c66affSColin Finck     {
653274bc4deSTimo Kreuzer         Group = SepGetGroupFromDescriptor(ObjectSd);
654274bc4deSTimo Kreuzer         if (Group != NULL)
655274bc4deSTimo Kreuzer         {
656c2c66affSColin Finck             GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
657c2c66affSColin Finck             Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
658c2c66affSColin Finck         }
659274bc4deSTimo Kreuzer     }
660c2c66affSColin Finck 
661c2c66affSColin Finck     if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
662c2c66affSColin Finck         (ObjectSd->Control & SE_DACL_PRESENT))
663c2c66affSColin Finck     {
664274bc4deSTimo Kreuzer         Dacl = SepGetDaclFromDescriptor(ObjectSd);
665274bc4deSTimo Kreuzer         if (Dacl != NULL)
666c2c66affSColin Finck         {
667c2c66affSColin Finck             DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
668c2c66affSColin Finck         }
669c2c66affSColin Finck 
670c2c66affSColin Finck         Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
671c2c66affSColin Finck     }
672c2c66affSColin Finck 
673c2c66affSColin Finck     if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
674c2c66affSColin Finck         (ObjectSd->Control & SE_SACL_PRESENT))
675c2c66affSColin Finck     {
676274bc4deSTimo Kreuzer         Sacl = SepGetSaclFromDescriptor(ObjectSd);
677274bc4deSTimo Kreuzer         if (Sacl != NULL)
678c2c66affSColin Finck         {
679c2c66affSColin Finck             SaclLength = ROUND_UP(Sacl->AclSize, 4);
680c2c66affSColin Finck         }
681c2c66affSColin Finck 
682c2c66affSColin Finck         Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
683c2c66affSColin Finck     }
684c2c66affSColin Finck 
685c2c66affSColin Finck     SdLength = OwnerLength + GroupLength + DaclLength +
686c2c66affSColin Finck     SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
687c2c66affSColin Finck     if (*Length < SdLength)
688c2c66affSColin Finck     {
689c2c66affSColin Finck         *Length = SdLength;
690c2c66affSColin Finck         return STATUS_BUFFER_TOO_SMALL;
691c2c66affSColin Finck     }
692c2c66affSColin Finck 
693c2c66affSColin Finck     /* Build the new security descrtiptor */
694c2c66affSColin Finck     RtlCreateSecurityDescriptorRelative(RelSD,
695c2c66affSColin Finck                                         SECURITY_DESCRIPTOR_REVISION);
696c2c66affSColin Finck     RelSD->Control = Control;
697c2c66affSColin Finck 
698c2c66affSColin Finck     Current = (ULONG_PTR)(RelSD + 1);
699c2c66affSColin Finck 
700c2c66affSColin Finck     if (OwnerLength != 0)
701c2c66affSColin Finck     {
702c2c66affSColin Finck         RtlCopyMemory((PVOID)Current,
703c2c66affSColin Finck                       Owner,
704c2c66affSColin Finck                       OwnerLength);
705c2c66affSColin Finck         RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
706c2c66affSColin Finck         Current += OwnerLength;
707c2c66affSColin Finck     }
708c2c66affSColin Finck 
709c2c66affSColin Finck     if (GroupLength != 0)
710c2c66affSColin Finck     {
711c2c66affSColin Finck         RtlCopyMemory((PVOID)Current,
712c2c66affSColin Finck                       Group,
713c2c66affSColin Finck                       GroupLength);
714c2c66affSColin Finck         RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
715c2c66affSColin Finck         Current += GroupLength;
716c2c66affSColin Finck     }
717c2c66affSColin Finck 
718c2c66affSColin Finck     if (DaclLength != 0)
719c2c66affSColin Finck     {
720c2c66affSColin Finck         RtlCopyMemory((PVOID)Current,
721c2c66affSColin Finck                       Dacl,
722c2c66affSColin Finck                       DaclLength);
723c2c66affSColin Finck         RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
724c2c66affSColin Finck         Current += DaclLength;
725c2c66affSColin Finck     }
726c2c66affSColin Finck 
727c2c66affSColin Finck     if (SaclLength != 0)
728c2c66affSColin Finck     {
729c2c66affSColin Finck         RtlCopyMemory((PVOID)Current,
730c2c66affSColin Finck                       Sacl,
731c2c66affSColin Finck                       SaclLength);
732c2c66affSColin Finck         RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
733c2c66affSColin Finck         Current += SaclLength;
734c2c66affSColin Finck     }
735c2c66affSColin Finck 
736c2c66affSColin Finck     *Length = SdLength;
737c2c66affSColin Finck 
738c2c66affSColin Finck     return STATUS_SUCCESS;
739c2c66affSColin Finck }
740c2c66affSColin Finck 
7416413009cSGeorge Bișoc /**
7426413009cSGeorge Bișoc  * @brief
7436413009cSGeorge Bișoc  * Releases a captured security descriptor buffer.
7446413009cSGeorge Bișoc  *
7456413009cSGeorge Bișoc  * @param[in] CapturedSecurityDescriptor
7466413009cSGeorge Bișoc  * The captured security descriptor to be freed.
7476413009cSGeorge Bișoc  *
7486413009cSGeorge Bișoc  * @param[in] CurrentMode
7496413009cSGeorge Bișoc  * Processor level access mode.
7506413009cSGeorge Bișoc  *
7516413009cSGeorge Bișoc  * @param[in] CaptureIfKernelMode
7526413009cSGeorge Bișoc  * Set this to TRUE if the releasing is to be done within
7536413009cSGeorge Bișoc  * the kernel.
7546413009cSGeorge Bișoc  *
7556413009cSGeorge Bișoc  * @return
7566413009cSGeorge Bișoc  * Returns STATUS_SUCCESS.
757c2c66affSColin Finck  */
758c2c66affSColin Finck NTSTATUS
759c2c66affSColin Finck NTAPI
SeReleaseSecurityDescriptor(_In_ PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,_In_ KPROCESSOR_MODE CurrentMode,_In_ BOOLEAN CaptureIfKernelMode)7608567d814SGeorge Bișoc SeReleaseSecurityDescriptor(
7618567d814SGeorge Bișoc     _In_ PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
7628567d814SGeorge Bișoc     _In_ KPROCESSOR_MODE CurrentMode,
7638567d814SGeorge Bișoc     _In_ BOOLEAN CaptureIfKernelMode)
764c2c66affSColin Finck {
765c2c66affSColin Finck     PAGED_CODE();
766c2c66affSColin Finck 
767c2c66affSColin Finck     /*
768c2c66affSColin Finck      * WARNING! You need to call this function with the same value for CurrentMode
769c2c66affSColin Finck      * and CaptureIfKernelMode that you previously passed to
770c2c66affSColin Finck      * SeCaptureSecurityDescriptor() in order to avoid memory leaks!
771c2c66affSColin Finck      */
772c2c66affSColin Finck     if (CapturedSecurityDescriptor != NULL &&
773c2c66affSColin Finck         (CurrentMode != KernelMode ||
774c2c66affSColin Finck          (CurrentMode == KernelMode && CaptureIfKernelMode)))
775c2c66affSColin Finck     {
776c2c66affSColin Finck         /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
777c2c66affSColin Finck         ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD);
778c2c66affSColin Finck     }
779c2c66affSColin Finck 
780c2c66affSColin Finck     return STATUS_SUCCESS;
781c2c66affSColin Finck }
782c2c66affSColin Finck 
7836413009cSGeorge Bișoc /**
7846413009cSGeorge Bișoc  * @brief
7856413009cSGeorge Bișoc  * Modifies some information data about a security
7866413009cSGeorge Bișoc  * descriptor.
7876413009cSGeorge Bișoc  *
7886413009cSGeorge Bișoc  * @param[in] Object
7896413009cSGeorge Bișoc  * If specified, the function will use this arbitrary
7906413009cSGeorge Bișoc  * object that points to an object security descriptor.
7916413009cSGeorge Bișoc  *
7926413009cSGeorge Bișoc  * @param[in] SecurityInformation
7936413009cSGeorge Bișoc  * Security information details to be set.
7946413009cSGeorge Bișoc  *
7956413009cSGeorge Bișoc  * @param[in] SecurityDescriptor
7966413009cSGeorge Bișoc  * A security descriptor where its info is to be changed.
7976413009cSGeorge Bișoc  *
7986413009cSGeorge Bișoc  * @param[in,out] ObjectsSecurityDescriptor
7996413009cSGeorge Bișoc  * The returned pointer to security descriptor objects.
8006413009cSGeorge Bișoc  *
8016413009cSGeorge Bișoc  * @param[in] PoolType
8026413009cSGeorge Bișoc  * Pool type for the new security descriptor to allocate.
8036413009cSGeorge Bișoc  *
8046413009cSGeorge Bișoc  * @param[in] GenericMapping
8056413009cSGeorge Bișoc  * The generic mapping of access rights masks.
8066413009cSGeorge Bișoc  *
8076413009cSGeorge Bișoc  * @return
8086413009cSGeorge Bișoc  * See SeSetSecurityDescriptorInfoEx.
809c2c66affSColin Finck  */
_IRQL_requires_max_(PASSIVE_LEVEL)810c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
811c2c66affSColin Finck NTSTATUS
812c2c66affSColin Finck NTAPI
813c2c66affSColin Finck SeSetSecurityDescriptorInfo(
814c2c66affSColin Finck     _In_opt_ PVOID Object,
815c2c66affSColin Finck     _In_ PSECURITY_INFORMATION SecurityInformation,
816c2c66affSColin Finck     _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
817c2c66affSColin Finck     _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
818c2c66affSColin Finck     _In_ POOL_TYPE PoolType,
819c2c66affSColin Finck     _In_ PGENERIC_MAPPING GenericMapping)
820c2c66affSColin Finck {
821c2c66affSColin Finck     PAGED_CODE();
822c2c66affSColin Finck 
823c2c66affSColin Finck     return SeSetSecurityDescriptorInfoEx(Object,
824c2c66affSColin Finck                                          SecurityInformation,
825c2c66affSColin Finck                                          SecurityDescriptor,
826c2c66affSColin Finck                                          ObjectsSecurityDescriptor,
827c2c66affSColin Finck                                          0,
828c2c66affSColin Finck                                          PoolType,
829c2c66affSColin Finck                                          GenericMapping);
830c2c66affSColin Finck }
831c2c66affSColin Finck 
8326413009cSGeorge Bișoc /**
8336413009cSGeorge Bișoc  * @brief
8346413009cSGeorge Bișoc  * An extended function that sets new information data to
8356413009cSGeorge Bișoc  * a security descriptor.
8366413009cSGeorge Bișoc  *
8376413009cSGeorge Bișoc  * @param[in] Object
8386413009cSGeorge Bișoc  * If specified, the function will use this arbitrary
8396413009cSGeorge Bișoc  * object that points to an object security descriptor.
8406413009cSGeorge Bișoc  *
8416413009cSGeorge Bișoc  * @param[in] SecurityInformation
8426413009cSGeorge Bișoc  * Security information details to be set.
8436413009cSGeorge Bișoc  *
8446413009cSGeorge Bișoc  * @param[in] SecurityDescriptor
8456413009cSGeorge Bișoc  * A security descriptor where its info is to be changed.
8466413009cSGeorge Bișoc  *
8476413009cSGeorge Bișoc  * @param[in,out] ObjectsSecurityDescriptor
8486413009cSGeorge Bișoc  * The returned pointer to security descriptor objects.
8496413009cSGeorge Bișoc  *
8506413009cSGeorge Bișoc  * @param[in] AutoInheritFlags
8516413009cSGeorge Bișoc  * Flags bitmask inheritation, influencing how the security
8526413009cSGeorge Bișoc  * descriptor can be inherited and if it can be in the first
8536413009cSGeorge Bișoc  * place.
8546413009cSGeorge Bișoc  *
8556413009cSGeorge Bișoc  * @param[in] PoolType
8566413009cSGeorge Bișoc  * Pool type for the new security descriptor to allocate.
8576413009cSGeorge Bișoc  *
8586413009cSGeorge Bișoc  * @param[in] GenericMapping
8596413009cSGeorge Bișoc  * The generic mapping of access rights masks.
8606413009cSGeorge Bișoc  *
8616413009cSGeorge Bișoc  * @return
8626413009cSGeorge Bișoc  * Returns STATUS_SUCCESS if the operations have been
8636413009cSGeorge Bișoc  * completed without problems and that new info has been
8646413009cSGeorge Bișoc  * set to the security descriptor. STATUS_NO_SECURITY_ON_OBJECT
8656413009cSGeorge Bișoc  * is returned if the object does not have a security descriptor.
8666413009cSGeorge Bișoc  * STATUS_INSUFFICIENT_RESOURCES is returned if memory pool allocation
8676413009cSGeorge Bișoc  * for the new security descriptor with new info set has failed.
868c2c66affSColin Finck  */
_IRQL_requires_max_(PASSIVE_LEVEL)869c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
870c2c66affSColin Finck NTSTATUS
871c2c66affSColin Finck NTAPI
872c2c66affSColin Finck SeSetSecurityDescriptorInfoEx(
873c2c66affSColin Finck     _In_opt_ PVOID Object,
874c2c66affSColin Finck     _In_ PSECURITY_INFORMATION _SecurityInformation,
875c2c66affSColin Finck     _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor,
876c2c66affSColin Finck     _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
877c2c66affSColin Finck     _In_ ULONG AutoInheritFlags,
878c2c66affSColin Finck     _In_ POOL_TYPE PoolType,
879c2c66affSColin Finck     _In_ PGENERIC_MAPPING GenericMapping)
880c2c66affSColin Finck {
881c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE ObjectSd;
882c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE NewSd;
883c2c66affSColin Finck     PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
884c2c66affSColin Finck     PSID Owner;
885c2c66affSColin Finck     PSID Group;
886c2c66affSColin Finck     PACL Dacl;
887c2c66affSColin Finck     PACL Sacl;
888c2c66affSColin Finck     ULONG OwnerLength;
889c2c66affSColin Finck     ULONG GroupLength;
890c2c66affSColin Finck     ULONG DaclLength;
891c2c66affSColin Finck     ULONG SaclLength;
892c2c66affSColin Finck     SECURITY_DESCRIPTOR_CONTROL Control = 0;
893c2c66affSColin Finck     ULONG Current;
894c2c66affSColin Finck     SECURITY_INFORMATION SecurityInformation;
895c2c66affSColin Finck 
896c2c66affSColin Finck     PAGED_CODE();
897c2c66affSColin Finck 
898c2c66affSColin Finck     ObjectSd = *ObjectsSecurityDescriptor;
899c2c66affSColin Finck 
900c2c66affSColin Finck     /* The object does not have a security descriptor. */
901c2c66affSColin Finck     if (!ObjectSd)
902c2c66affSColin Finck         return STATUS_NO_SECURITY_ON_OBJECT;
903c2c66affSColin Finck 
904c2c66affSColin Finck     ASSERT(ObjectSd->Control & SE_SELF_RELATIVE);
905c2c66affSColin Finck 
906c2c66affSColin Finck     SecurityInformation = *_SecurityInformation;
907c2c66affSColin Finck 
908c2c66affSColin Finck     /* Get owner and owner size */
909c2c66affSColin Finck     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
910c2c66affSColin Finck     {
911c2c66affSColin Finck         Owner = SepGetOwnerFromDescriptor(SecurityDescriptor);
912c2c66affSColin Finck         Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
913c2c66affSColin Finck     }
914c2c66affSColin Finck     else
915c2c66affSColin Finck     {
916c2c66affSColin Finck         Owner = SepGetOwnerFromDescriptor(ObjectSd);
917c2c66affSColin Finck         Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
918c2c66affSColin Finck     }
919c2c66affSColin Finck     OwnerLength = Owner ? RtlLengthSid(Owner) : 0;
920c2c66affSColin Finck     ASSERT(OwnerLength % sizeof(ULONG) == 0);
921c2c66affSColin Finck 
922c2c66affSColin Finck     /* Get group and group size */
923c2c66affSColin Finck     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
924c2c66affSColin Finck     {
925c2c66affSColin Finck         Group = SepGetGroupFromDescriptor(SecurityDescriptor);
926c2c66affSColin Finck         Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
927c2c66affSColin Finck     }
928c2c66affSColin Finck     else
929c2c66affSColin Finck     {
930c2c66affSColin Finck         Group = SepGetGroupFromDescriptor(ObjectSd);
931c2c66affSColin Finck         Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
932c2c66affSColin Finck     }
933c2c66affSColin Finck     GroupLength = Group ? RtlLengthSid(Group) : 0;
934c2c66affSColin Finck     ASSERT(GroupLength % sizeof(ULONG) == 0);
935c2c66affSColin Finck 
936c2c66affSColin Finck     /* Get DACL and DACL size */
937c2c66affSColin Finck     if (SecurityInformation & DACL_SECURITY_INFORMATION)
938c2c66affSColin Finck     {
939c2c66affSColin Finck         Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
940c2c66affSColin Finck         Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
941c2c66affSColin Finck     }
942c2c66affSColin Finck     else
943c2c66affSColin Finck     {
944c2c66affSColin Finck         Dacl = SepGetDaclFromDescriptor(ObjectSd);
945c2c66affSColin Finck         Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
946c2c66affSColin Finck     }
947c2c66affSColin Finck     DaclLength = Dacl ? ROUND_UP((ULONG)Dacl->AclSize, 4) : 0;
948c2c66affSColin Finck 
949c2c66affSColin Finck     /* Get SACL and SACL size */
950c2c66affSColin Finck     if (SecurityInformation & SACL_SECURITY_INFORMATION)
951c2c66affSColin Finck     {
952c2c66affSColin Finck         Sacl = SepGetSaclFromDescriptor(SecurityDescriptor);
953c2c66affSColin Finck         Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
954c2c66affSColin Finck     }
955c2c66affSColin Finck     else
956c2c66affSColin Finck     {
957c2c66affSColin Finck         Sacl = SepGetSaclFromDescriptor(ObjectSd);
958c2c66affSColin Finck         Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
959c2c66affSColin Finck     }
960c2c66affSColin Finck     SaclLength = Sacl ? ROUND_UP((ULONG)Sacl->AclSize, 4) : 0;
961c2c66affSColin Finck 
962ff0a3251SGeorge Bișoc     NewSd = ExAllocatePoolWithTag(PoolType,
963c2c66affSColin Finck                                   sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
964c2c66affSColin Finck                                   OwnerLength + GroupLength +
965c2c66affSColin Finck                                   DaclLength + SaclLength,
966c2c66affSColin Finck                                   TAG_SD);
967c2c66affSColin Finck     if (NewSd == NULL)
968c2c66affSColin Finck     {
969c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
970c2c66affSColin Finck     }
971c2c66affSColin Finck 
9726c154c06STimo Kreuzer     RtlCreateSecurityDescriptorRelative(NewSd, SECURITY_DESCRIPTOR_REVISION1);
973c2c66affSColin Finck 
9746c154c06STimo Kreuzer     Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
975c2c66affSColin Finck 
976c2c66affSColin Finck     if (OwnerLength != 0)
977c2c66affSColin Finck     {
978c2c66affSColin Finck         RtlCopyMemory((PUCHAR)NewSd + Current, Owner, OwnerLength);
979c2c66affSColin Finck         NewSd->Owner = Current;
980c2c66affSColin Finck         Current += OwnerLength;
981c2c66affSColin Finck     }
982c2c66affSColin Finck 
983c2c66affSColin Finck     if (GroupLength != 0)
984c2c66affSColin Finck     {
985c2c66affSColin Finck         RtlCopyMemory((PUCHAR)NewSd + Current, Group, GroupLength);
986c2c66affSColin Finck         NewSd->Group = Current;
987c2c66affSColin Finck         Current += GroupLength;
988c2c66affSColin Finck     }
989c2c66affSColin Finck 
990c2c66affSColin Finck     if (DaclLength != 0)
991c2c66affSColin Finck     {
992c2c66affSColin Finck         RtlCopyMemory((PUCHAR)NewSd + Current, Dacl, DaclLength);
993c2c66affSColin Finck         NewSd->Dacl = Current;
994c2c66affSColin Finck         Current += DaclLength;
995c2c66affSColin Finck     }
996c2c66affSColin Finck 
997c2c66affSColin Finck     if (SaclLength != 0)
998c2c66affSColin Finck     {
999c2c66affSColin Finck         RtlCopyMemory((PUCHAR)NewSd + Current, Sacl, SaclLength);
1000c2c66affSColin Finck         NewSd->Sacl = Current;
1001c2c66affSColin Finck         Current += SaclLength;
1002c2c66affSColin Finck     }
1003c2c66affSColin Finck 
1004c869c477SGeorge Bișoc     NewSd->Control |= Control;
1005c2c66affSColin Finck     *ObjectsSecurityDescriptor = NewSd;
1006c2c66affSColin Finck     return STATUS_SUCCESS;
1007c2c66affSColin Finck }
1008c2c66affSColin Finck 
10096413009cSGeorge Bișoc /**
10106413009cSGeorge Bișoc  * @brief
10116413009cSGeorge Bișoc  * Determines if a security descriptor is valid according
10126413009cSGeorge Bișoc  * to the general security requirements and conditions
10136413009cSGeorge Bișoc  * set by the kernel.
10146413009cSGeorge Bișoc  *
10156413009cSGeorge Bișoc  * @param[in] Length
10166413009cSGeorge Bișoc  * The length of a security descriptor.
10176413009cSGeorge Bișoc  *
10186413009cSGeorge Bișoc  * @param[in] _SecurityDescriptor
10196413009cSGeorge Bișoc  * A security descriptor where its properties are to be
10206413009cSGeorge Bișoc  * checked for validity.
10216413009cSGeorge Bișoc  *
10226413009cSGeorge Bișoc  * @return
10236413009cSGeorge Bișoc  * Returns TRUE if the given security descriptor is valid,
10246413009cSGeorge Bișoc  * FALSE otherwise.
1025c2c66affSColin Finck  */
1026c2c66affSColin Finck BOOLEAN NTAPI
SeValidSecurityDescriptor(_In_ ULONG Length,_In_ PSECURITY_DESCRIPTOR _SecurityDescriptor)10278567d814SGeorge Bișoc SeValidSecurityDescriptor(
10288567d814SGeorge Bișoc     _In_ ULONG Length,
10298567d814SGeorge Bișoc     _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor)
1030c2c66affSColin Finck {
1031c2c66affSColin Finck     ULONG SdLength;
1032c2c66affSColin Finck     PISID Sid;
1033c2c66affSColin Finck     PACL Acl;
1034c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor = _SecurityDescriptor;
1035c2c66affSColin Finck 
1036c2c66affSColin Finck     if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
1037c2c66affSColin Finck     {
1038c2c66affSColin Finck         DPRINT1("Invalid Security Descriptor revision\n");
1039c2c66affSColin Finck         return FALSE;
1040c2c66affSColin Finck     }
1041c2c66affSColin Finck 
1042c2c66affSColin Finck     if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
1043c2c66affSColin Finck     {
1044c2c66affSColin Finck         DPRINT1("Invalid Security Descriptor revision\n");
1045c2c66affSColin Finck         return FALSE;
1046c2c66affSColin Finck     }
1047c2c66affSColin Finck 
1048c2c66affSColin Finck     if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
1049c2c66affSColin Finck     {
1050c2c66affSColin Finck         DPRINT1("No self-relative Security Descriptor\n");
1051c2c66affSColin Finck         return FALSE;
1052c2c66affSColin Finck     }
1053c2c66affSColin Finck 
1054c2c66affSColin Finck     SdLength = sizeof(SECURITY_DESCRIPTOR);
1055c2c66affSColin Finck 
1056c2c66affSColin Finck     /* Check Owner SID */
1057c2c66affSColin Finck     if (!SecurityDescriptor->Owner)
1058c2c66affSColin Finck     {
1059c2c66affSColin Finck         DPRINT1("No Owner SID\n");
1060c2c66affSColin Finck         return FALSE;
1061c2c66affSColin Finck     }
1062c2c66affSColin Finck 
1063c2c66affSColin Finck     if (SecurityDescriptor->Owner % sizeof(ULONG))
1064c2c66affSColin Finck     {
1065c2c66affSColin Finck         DPRINT1("Invalid Owner SID alignment\n");
1066c2c66affSColin Finck         return FALSE;
1067c2c66affSColin Finck     }
1068c2c66affSColin Finck 
1069*a0bcf90fSHermès Bélusca-Maïto     /* Ensure the Owner SID is within the bounds of the security descriptor */
1070*a0bcf90fSHermès Bélusca-Maïto     if ((SecurityDescriptor->Owner > Length) ||
1071*a0bcf90fSHermès Bélusca-Maïto         (Length - SecurityDescriptor->Owner < sizeof(SID)))
1072*a0bcf90fSHermès Bélusca-Maïto     {
1073*a0bcf90fSHermès Bélusca-Maïto         DPRINT1("Owner SID not within bounds\n");
1074*a0bcf90fSHermès Bélusca-Maïto         return FALSE;
1075*a0bcf90fSHermès Bélusca-Maïto     }
1076*a0bcf90fSHermès Bélusca-Maïto 
1077*a0bcf90fSHermès Bélusca-Maïto     /* Reference it */
1078c2c66affSColin Finck     Sid = (PISID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Owner);
1079c2c66affSColin Finck     if (Sid->Revision != SID_REVISION)
1080c2c66affSColin Finck     {
1081c2c66affSColin Finck         DPRINT1("Invalid Owner SID revision\n");
1082c2c66affSColin Finck         return FALSE;
1083c2c66affSColin Finck     }
1084c2c66affSColin Finck 
1085*a0bcf90fSHermès Bélusca-Maïto     // NOTE: Same as SeLengthSid(Sid); but doesn't use hardcoded values.
1086c2c66affSColin Finck     SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1087c2c66affSColin Finck     if (Length < SdLength)
1088c2c66affSColin Finck     {
1089c2c66affSColin Finck         DPRINT1("Invalid Owner SID size\n");
1090c2c66affSColin Finck         return FALSE;
1091c2c66affSColin Finck     }
1092c2c66affSColin Finck 
1093c2c66affSColin Finck     /* Check Group SID */
1094c2c66affSColin Finck     if (SecurityDescriptor->Group)
1095c2c66affSColin Finck     {
1096c2c66affSColin Finck         if (SecurityDescriptor->Group % sizeof(ULONG))
1097c2c66affSColin Finck         {
1098c2c66affSColin Finck             DPRINT1("Invalid Group SID alignment\n");
1099c2c66affSColin Finck             return FALSE;
1100c2c66affSColin Finck         }
1101c2c66affSColin Finck 
1102*a0bcf90fSHermès Bélusca-Maïto         /* Ensure the Group SID is within the bounds of the security descriptor */
1103*a0bcf90fSHermès Bélusca-Maïto         if ((SecurityDescriptor->Group > Length) ||
1104*a0bcf90fSHermès Bélusca-Maïto             (Length - SecurityDescriptor->Group < sizeof(SID)))
1105*a0bcf90fSHermès Bélusca-Maïto         {
1106*a0bcf90fSHermès Bélusca-Maïto             DPRINT1("Group SID not within bounds\n");
1107*a0bcf90fSHermès Bélusca-Maïto             return FALSE;
1108*a0bcf90fSHermès Bélusca-Maïto         }
1109*a0bcf90fSHermès Bélusca-Maïto 
1110*a0bcf90fSHermès Bélusca-Maïto         /* Reference it */
1111c2c66affSColin Finck         Sid = (PSID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Group);
1112c2c66affSColin Finck         if (Sid->Revision != SID_REVISION)
1113c2c66affSColin Finck         {
1114c2c66affSColin Finck             DPRINT1("Invalid Group SID revision\n");
1115c2c66affSColin Finck             return FALSE;
1116c2c66affSColin Finck         }
1117c2c66affSColin Finck 
1118*a0bcf90fSHermès Bélusca-Maïto         // NOTE: Same as SeLengthSid(Sid); but doesn't use hardcoded values.
1119c2c66affSColin Finck         SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1120c2c66affSColin Finck         if (Length < SdLength)
1121c2c66affSColin Finck         {
1122c2c66affSColin Finck             DPRINT1("Invalid Group SID size\n");
1123c2c66affSColin Finck             return FALSE;
1124c2c66affSColin Finck         }
1125c2c66affSColin Finck     }
1126c2c66affSColin Finck 
1127c2c66affSColin Finck     /* Check DACL */
1128c2c66affSColin Finck     if (SecurityDescriptor->Dacl)
1129c2c66affSColin Finck     {
1130c2c66affSColin Finck         if (SecurityDescriptor->Dacl % sizeof(ULONG))
1131c2c66affSColin Finck         {
1132c2c66affSColin Finck             DPRINT1("Invalid DACL alignment\n");
1133c2c66affSColin Finck             return FALSE;
1134c2c66affSColin Finck         }
1135c2c66affSColin Finck 
1136*a0bcf90fSHermès Bélusca-Maïto         /* Ensure the DACL is within the bounds of the security descriptor */
1137*a0bcf90fSHermès Bélusca-Maïto         if ((SecurityDescriptor->Dacl > Length) ||
1138*a0bcf90fSHermès Bélusca-Maïto             (Length - SecurityDescriptor->Dacl < sizeof(ACL)))
1139c2c66affSColin Finck         {
1140*a0bcf90fSHermès Bélusca-Maïto             DPRINT1("DACL not within bounds\n");
1141c2c66affSColin Finck             return FALSE;
1142c2c66affSColin Finck         }
1143c2c66affSColin Finck 
1144*a0bcf90fSHermès Bélusca-Maïto         /* Reference it */
1145*a0bcf90fSHermès Bélusca-Maïto         Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl);
1146*a0bcf90fSHermès Bélusca-Maïto 
1147c2c66affSColin Finck         SdLength += Acl->AclSize;
1148c2c66affSColin Finck         if (Length < SdLength)
1149c2c66affSColin Finck         {
1150c2c66affSColin Finck             DPRINT1("Invalid DACL size\n");
1151c2c66affSColin Finck             return FALSE;
1152c2c66affSColin Finck         }
1153*a0bcf90fSHermès Bélusca-Maïto 
1154*a0bcf90fSHermès Bélusca-Maïto         if (!RtlValidAcl(Acl))
1155*a0bcf90fSHermès Bélusca-Maïto         {
1156*a0bcf90fSHermès Bélusca-Maïto             DPRINT1("Invalid DACL\n");
1157*a0bcf90fSHermès Bélusca-Maïto             return FALSE;
1158*a0bcf90fSHermès Bélusca-Maïto         }
1159c2c66affSColin Finck     }
1160c2c66affSColin Finck 
1161c2c66affSColin Finck     /* Check SACL */
1162c2c66affSColin Finck     if (SecurityDescriptor->Sacl)
1163c2c66affSColin Finck     {
1164c2c66affSColin Finck         if (SecurityDescriptor->Sacl % sizeof(ULONG))
1165c2c66affSColin Finck         {
1166c2c66affSColin Finck             DPRINT1("Invalid SACL alignment\n");
1167c2c66affSColin Finck             return FALSE;
1168c2c66affSColin Finck         }
1169c2c66affSColin Finck 
1170*a0bcf90fSHermès Bélusca-Maïto         /* Ensure the SACL is within the bounds of the security descriptor */
1171*a0bcf90fSHermès Bélusca-Maïto         if ((SecurityDescriptor->Sacl > Length) ||
1172*a0bcf90fSHermès Bélusca-Maïto             (Length - SecurityDescriptor->Sacl < sizeof(ACL)))
1173c2c66affSColin Finck         {
1174*a0bcf90fSHermès Bélusca-Maïto             DPRINT1("SACL not within bounds\n");
1175c2c66affSColin Finck             return FALSE;
1176c2c66affSColin Finck         }
1177c2c66affSColin Finck 
1178*a0bcf90fSHermès Bélusca-Maïto         /* Reference it */
1179*a0bcf90fSHermès Bélusca-Maïto         Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl);
1180*a0bcf90fSHermès Bélusca-Maïto 
1181c2c66affSColin Finck         SdLength += Acl->AclSize;
1182c2c66affSColin Finck         if (Length < SdLength)
1183c2c66affSColin Finck         {
1184c2c66affSColin Finck             DPRINT1("Invalid SACL size\n");
1185c2c66affSColin Finck             return FALSE;
1186c2c66affSColin Finck         }
1187*a0bcf90fSHermès Bélusca-Maïto 
1188*a0bcf90fSHermès Bélusca-Maïto         if (!RtlValidAcl(Acl))
1189*a0bcf90fSHermès Bélusca-Maïto         {
1190*a0bcf90fSHermès Bélusca-Maïto             DPRINT1("Invalid SACL\n");
1191*a0bcf90fSHermès Bélusca-Maïto             return FALSE;
1192*a0bcf90fSHermès Bélusca-Maïto         }
1193c2c66affSColin Finck     }
1194c2c66affSColin Finck 
1195c2c66affSColin Finck     return TRUE;
1196c2c66affSColin Finck }
1197c2c66affSColin Finck 
11986413009cSGeorge Bișoc /**
11996413009cSGeorge Bișoc  * @brief
12006413009cSGeorge Bișoc  * Frees a security descriptor.
12016413009cSGeorge Bișoc  *
12026413009cSGeorge Bișoc  * @param[in] SecurityDescriptor
12036413009cSGeorge Bișoc  * A security descriptor to be freed from memory.
12046413009cSGeorge Bișoc  *
12056413009cSGeorge Bișoc  * @return
12066413009cSGeorge Bișoc  * Returns STATUS_SUCCESS.
1207c2c66affSColin Finck  */
_IRQL_requires_max_(PASSIVE_LEVEL)1208c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
1209c2c66affSColin Finck NTSTATUS
1210c2c66affSColin Finck NTAPI
1211c2c66affSColin Finck SeDeassignSecurity(
1212c2c66affSColin Finck     _Inout_ PSECURITY_DESCRIPTOR *SecurityDescriptor)
1213c2c66affSColin Finck {
1214c2c66affSColin Finck     PAGED_CODE();
1215c2c66affSColin Finck 
1216c2c66affSColin Finck     if (*SecurityDescriptor != NULL)
1217c2c66affSColin Finck     {
1218c2c66affSColin Finck         ExFreePoolWithTag(*SecurityDescriptor, TAG_SD);
1219c2c66affSColin Finck         *SecurityDescriptor = NULL;
1220c2c66affSColin Finck     }
1221c2c66affSColin Finck 
1222c2c66affSColin Finck     return STATUS_SUCCESS;
1223c2c66affSColin Finck }
1224c2c66affSColin Finck 
12256413009cSGeorge Bișoc /**
12266413009cSGeorge Bișoc  * @brief
12276413009cSGeorge Bișoc  * An extended function that assigns a security descriptor for a new
12286413009cSGeorge Bișoc  * object.
12296413009cSGeorge Bișoc  *
12306413009cSGeorge Bișoc  * @param[in] _ParentDescriptor
12316413009cSGeorge Bișoc  * A security descriptor of the parent object that is being
12326413009cSGeorge Bișoc  * created.
12336413009cSGeorge Bișoc  *
12346413009cSGeorge Bișoc  * @param[in] _ExplicitDescriptor
12356413009cSGeorge Bișoc  * An explicit security descriptor that is applied to a new
12366413009cSGeorge Bișoc  * object.
12376413009cSGeorge Bișoc  *
12386413009cSGeorge Bișoc  * @param[out] NewDescriptor
12396413009cSGeorge Bișoc  * The new allocated security descriptor.
12406413009cSGeorge Bișoc  *
12416413009cSGeorge Bișoc  * @param[in] ObjectType
12426413009cSGeorge Bișoc  * The type of the new object.
12436413009cSGeorge Bișoc  *
12446413009cSGeorge Bișoc  * @param[in] IsDirectoryObject
12456413009cSGeorge Bișoc  * Set this to TRUE if the newly created object is a directory
12466413009cSGeorge Bișoc  * object, otherwise set this to FALSE.
12476413009cSGeorge Bișoc  *
12486413009cSGeorge Bișoc  * @param[in] AutoInheritFlags
12496413009cSGeorge Bișoc  * Automatic inheritance flags that influence how access control
12506413009cSGeorge Bișoc  * entries within ACLs from security descriptors are inherited.
12516413009cSGeorge Bișoc  *
12526413009cSGeorge Bișoc  * @param[in] SubjectContext
12536413009cSGeorge Bișoc  * Security subject context of the new object.
12546413009cSGeorge Bișoc  *
12556413009cSGeorge Bișoc  * @param[in] GenericMapping
12566413009cSGeorge Bișoc  * Generic mapping of access mask rights.
12576413009cSGeorge Bișoc  *
12586413009cSGeorge Bișoc  * @param[in] PoolType
12596413009cSGeorge Bișoc  * This parameter is unused.
12606413009cSGeorge Bișoc  *
12616413009cSGeorge Bișoc  * @return
12626413009cSGeorge Bișoc  * Returns STATUS_SUCCESS if the operations have been completed
12636413009cSGeorge Bișoc  * successfully and that the security descriptor has been
12646413009cSGeorge Bișoc  * assigned to the new object. STATUS_NO_TOKEN is returned
12656413009cSGeorge Bișoc  * if the caller hasn't supplied a valid argument to a security
12666413009cSGeorge Bișoc  * subject context. STATUS_INVALID_OWNER is returned if the caller
12676413009cSGeorge Bișoc  * hasn't supplied a parent descriptor that belongs to the main
12686413009cSGeorge Bișoc  * user (owner). STATUS_INVALID_PRIMARY_GROUP is returned
12696413009cSGeorge Bișoc  * by the same reason as with the previous NTSTATUS code.
12706413009cSGeorge Bișoc  * The two NTSTATUS codes are returned if the calling thread
12716413009cSGeorge Bișoc  * stated that the owner and/or group is defaulted to the
12726413009cSGeorge Bișoc  * parent descriptor (SEF_DEFAULT_OWNER_FROM_PARENT and/or
12736413009cSGeorge Bișoc  * SEF_DEFAULT_GROUP_FROM_PARENT respectively).
12746413009cSGeorge Bișoc  * STATUS_INSUFFICIENT_RESOURCES is returned if memory pool allocation
12756413009cSGeorge Bișoc  * for the descriptor buffer has failed. A failure NTSTATUS is returned
12766413009cSGeorge Bișoc  * otherwise.
1277c2c66affSColin Finck  */
_IRQL_requires_max_(PASSIVE_LEVEL)1278c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
1279c2c66affSColin Finck NTSTATUS
1280c2c66affSColin Finck NTAPI
1281c2c66affSColin Finck SeAssignSecurityEx(
1282c2c66affSColin Finck     _In_opt_ PSECURITY_DESCRIPTOR _ParentDescriptor,
1283c2c66affSColin Finck     _In_opt_ PSECURITY_DESCRIPTOR _ExplicitDescriptor,
1284c2c66affSColin Finck     _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1285c2c66affSColin Finck     _In_opt_ GUID *ObjectType,
1286c2c66affSColin Finck     _In_ BOOLEAN IsDirectoryObject,
1287c2c66affSColin Finck     _In_ ULONG AutoInheritFlags,
1288c2c66affSColin Finck     _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1289c2c66affSColin Finck     _In_ PGENERIC_MAPPING GenericMapping,
1290c2c66affSColin Finck     _In_ POOL_TYPE PoolType)
1291c2c66affSColin Finck {
1292c2c66affSColin Finck     PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
1293c2c66affSColin Finck     PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
1294c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE Descriptor;
1295c2c66affSColin Finck     PTOKEN Token;
1296c2c66affSColin Finck     ULONG OwnerLength;
1297c2c66affSColin Finck     ULONG GroupLength;
1298c2c66affSColin Finck     ULONG DaclLength;
1299c2c66affSColin Finck     ULONG SaclLength;
1300c2c66affSColin Finck     ULONG Length;
1301c2c66affSColin Finck     SECURITY_DESCRIPTOR_CONTROL Control = 0;
1302c2c66affSColin Finck     ULONG Current;
1303c2c66affSColin Finck     PSID Owner = NULL;
1304c2c66affSColin Finck     PSID Group = NULL;
1305c2c66affSColin Finck     PACL ExplicitAcl;
1306c2c66affSColin Finck     BOOLEAN ExplicitPresent;
1307c2c66affSColin Finck     BOOLEAN ExplicitDefaulted;
1308c2c66affSColin Finck     PACL ParentAcl;
1309c2c66affSColin Finck     PACL Dacl = NULL;
1310c2c66affSColin Finck     PACL Sacl = NULL;
1311c2c66affSColin Finck     BOOLEAN DaclIsInherited;
1312c2c66affSColin Finck     BOOLEAN SaclIsInherited;
1313c2c66affSColin Finck     BOOLEAN DaclPresent;
1314c2c66affSColin Finck     BOOLEAN SaclPresent;
1315c2c66affSColin Finck     NTSTATUS Status;
1316c2c66affSColin Finck 
1317c2c66affSColin Finck     DBG_UNREFERENCED_PARAMETER(ObjectType);
1318c2c66affSColin Finck     DBG_UNREFERENCED_PARAMETER(AutoInheritFlags);
1319c2c66affSColin Finck     UNREFERENCED_PARAMETER(PoolType);
1320c2c66affSColin Finck 
1321c2c66affSColin Finck     PAGED_CODE();
1322c2c66affSColin Finck 
1323c2c66affSColin Finck     *NewDescriptor = NULL;
1324c2c66affSColin Finck 
1325c2c66affSColin Finck     if (!ARGUMENT_PRESENT(SubjectContext))
1326c2c66affSColin Finck     {
1327c2c66affSColin Finck         return STATUS_NO_TOKEN;
1328c2c66affSColin Finck     }
1329c2c66affSColin Finck 
1330c2c66affSColin Finck     /* Lock subject context */
1331c2c66affSColin Finck     SeLockSubjectContext(SubjectContext);
1332c2c66affSColin Finck 
1333c2c66affSColin Finck     if (SubjectContext->ClientToken != NULL)
1334c2c66affSColin Finck     {
1335c2c66affSColin Finck         Token = SubjectContext->ClientToken;
1336c2c66affSColin Finck     }
1337c2c66affSColin Finck     else
1338c2c66affSColin Finck     {
1339c2c66affSColin Finck         Token = SubjectContext->PrimaryToken;
1340c2c66affSColin Finck     }
1341c2c66affSColin Finck 
1342c2c66affSColin Finck     /* Inherit the Owner SID */
1343c2c66affSColin Finck     if (ExplicitDescriptor != NULL)
1344c2c66affSColin Finck     {
1345c2c66affSColin Finck         DPRINT("Use explicit owner sid!\n");
1346c2c66affSColin Finck         Owner = SepGetOwnerFromDescriptor(ExplicitDescriptor);
1347c2c66affSColin Finck     }
1348c2c66affSColin Finck     if (!Owner)
1349c2c66affSColin Finck     {
1350d7255f15SGeorge Bișoc         if (AutoInheritFlags & SEF_DEFAULT_OWNER_FROM_PARENT)
1351c2c66affSColin Finck         {
1352c2c66affSColin Finck             DPRINT("Use parent owner sid!\n");
1353c2c66affSColin Finck             if (!ARGUMENT_PRESENT(ParentDescriptor))
1354c2c66affSColin Finck             {
1355c2c66affSColin Finck                 SeUnlockSubjectContext(SubjectContext);
1356c2c66affSColin Finck                 return STATUS_INVALID_OWNER;
1357c2c66affSColin Finck             }
1358c2c66affSColin Finck 
1359c2c66affSColin Finck             Owner = SepGetOwnerFromDescriptor(ParentDescriptor);
1360c2c66affSColin Finck             if (!Owner)
1361c2c66affSColin Finck             {
1362c2c66affSColin Finck                 SeUnlockSubjectContext(SubjectContext);
1363c2c66affSColin Finck                 return STATUS_INVALID_OWNER;
1364c2c66affSColin Finck             }
1365c2c66affSColin Finck         }
1366c2c66affSColin Finck         else
1367c2c66affSColin Finck         {
1368c2c66affSColin Finck             DPRINT("Use token owner sid!\n");
1369c2c66affSColin Finck             Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1370c2c66affSColin Finck         }
1371c2c66affSColin Finck     }
1372c2c66affSColin Finck     OwnerLength = RtlLengthSid(Owner);
1373c2c66affSColin Finck     ASSERT(OwnerLength % sizeof(ULONG) == 0);
1374c2c66affSColin Finck 
1375c2c66affSColin Finck     /* Inherit the Group SID */
1376c2c66affSColin Finck     if (ExplicitDescriptor != NULL)
1377c2c66affSColin Finck     {
1378c2c66affSColin Finck         Group = SepGetGroupFromDescriptor(ExplicitDescriptor);
1379c2c66affSColin Finck     }
1380c2c66affSColin Finck     if (!Group)
1381c2c66affSColin Finck     {
1382d7255f15SGeorge Bișoc         if (AutoInheritFlags & SEF_DEFAULT_GROUP_FROM_PARENT)
1383c2c66affSColin Finck         {
1384c2c66affSColin Finck             DPRINT("Use parent group sid!\n");
1385c2c66affSColin Finck             if (!ARGUMENT_PRESENT(ParentDescriptor))
1386c2c66affSColin Finck             {
1387c2c66affSColin Finck                 SeUnlockSubjectContext(SubjectContext);
1388c2c66affSColin Finck                 return STATUS_INVALID_PRIMARY_GROUP;
1389c2c66affSColin Finck             }
1390c2c66affSColin Finck 
1391c2c66affSColin Finck             Group = SepGetGroupFromDescriptor(ParentDescriptor);
1392c2c66affSColin Finck             if (!Group)
1393c2c66affSColin Finck             {
1394c2c66affSColin Finck                 SeUnlockSubjectContext(SubjectContext);
1395c2c66affSColin Finck                 return STATUS_INVALID_PRIMARY_GROUP;
1396c2c66affSColin Finck             }
1397c2c66affSColin Finck         }
1398c2c66affSColin Finck         else
1399c2c66affSColin Finck         {
1400c2c66affSColin Finck             DPRINT("Use token group sid!\n");
1401c2c66affSColin Finck             Group = Token->PrimaryGroup;
1402c2c66affSColin Finck         }
1403c2c66affSColin Finck     }
1404c2c66affSColin Finck     if (!Group)
1405c2c66affSColin Finck     {
1406c2c66affSColin Finck         SeUnlockSubjectContext(SubjectContext);
1407c2c66affSColin Finck         return STATUS_INVALID_PRIMARY_GROUP;
1408c2c66affSColin Finck     }
1409c2c66affSColin Finck     GroupLength = RtlLengthSid(Group);
1410c2c66affSColin Finck     ASSERT(GroupLength % sizeof(ULONG) == 0);
1411c2c66affSColin Finck 
1412c2c66affSColin Finck     /* Inherit the DACL */
1413c2c66affSColin Finck     DaclLength = 0;
1414c2c66affSColin Finck     ExplicitAcl = NULL;
1415c2c66affSColin Finck     ExplicitPresent = FALSE;
1416c2c66affSColin Finck     ExplicitDefaulted = FALSE;
1417c2c66affSColin Finck     if (ExplicitDescriptor != NULL &&
1418c2c66affSColin Finck         (ExplicitDescriptor->Control & SE_DACL_PRESENT))
1419c2c66affSColin Finck     {
1420c2c66affSColin Finck         ExplicitAcl = SepGetDaclFromDescriptor(ExplicitDescriptor);
1421c2c66affSColin Finck         ExplicitPresent = TRUE;
1422c2c66affSColin Finck         if (ExplicitDescriptor->Control & SE_DACL_DEFAULTED)
1423c2c66affSColin Finck             ExplicitDefaulted = TRUE;
1424c2c66affSColin Finck     }
1425c2c66affSColin Finck     ParentAcl = NULL;
1426c2c66affSColin Finck     if (ParentDescriptor != NULL &&
1427c2c66affSColin Finck         (ParentDescriptor->Control & SE_DACL_PRESENT))
1428c2c66affSColin Finck     {
1429c2c66affSColin Finck         ParentAcl = SepGetDaclFromDescriptor(ParentDescriptor);
1430c2c66affSColin Finck     }
1431c2c66affSColin Finck     Dacl = SepSelectAcl(ExplicitAcl,
1432c2c66affSColin Finck                         ExplicitPresent,
1433c2c66affSColin Finck                         ExplicitDefaulted,
1434c2c66affSColin Finck                         ParentAcl,
1435c2c66affSColin Finck                         Token->DefaultDacl,
1436c2c66affSColin Finck                         &DaclLength,
1437c2c66affSColin Finck                         Owner,
1438c2c66affSColin Finck                         Group,
1439c2c66affSColin Finck                         &DaclPresent,
1440c2c66affSColin Finck                         &DaclIsInherited,
1441c2c66affSColin Finck                         IsDirectoryObject,
1442c2c66affSColin Finck                         GenericMapping);
1443c2c66affSColin Finck     if (DaclPresent)
1444c2c66affSColin Finck         Control |= SE_DACL_PRESENT;
1445c2c66affSColin Finck     ASSERT(DaclLength % sizeof(ULONG) == 0);
1446c2c66affSColin Finck 
1447c2c66affSColin Finck     /* Inherit the SACL */
1448c2c66affSColin Finck     SaclLength = 0;
1449c2c66affSColin Finck     ExplicitAcl = NULL;
1450c2c66affSColin Finck     ExplicitPresent = FALSE;
1451c2c66affSColin Finck     ExplicitDefaulted = FALSE;
1452c2c66affSColin Finck     if (ExplicitDescriptor != NULL &&
1453c2c66affSColin Finck         (ExplicitDescriptor->Control & SE_SACL_PRESENT))
1454c2c66affSColin Finck     {
1455c2c66affSColin Finck         ExplicitAcl = SepGetSaclFromDescriptor(ExplicitDescriptor);
1456c2c66affSColin Finck         ExplicitPresent = TRUE;
1457c2c66affSColin Finck         if (ExplicitDescriptor->Control & SE_SACL_DEFAULTED)
1458c2c66affSColin Finck             ExplicitDefaulted = TRUE;
1459c2c66affSColin Finck     }
1460c2c66affSColin Finck     ParentAcl = NULL;
1461c2c66affSColin Finck     if (ParentDescriptor != NULL &&
1462c2c66affSColin Finck         (ParentDescriptor->Control & SE_SACL_PRESENT))
1463c2c66affSColin Finck     {
1464c2c66affSColin Finck         ParentAcl = SepGetSaclFromDescriptor(ParentDescriptor);
1465c2c66affSColin Finck     }
1466c2c66affSColin Finck     Sacl = SepSelectAcl(ExplicitAcl,
1467c2c66affSColin Finck                         ExplicitPresent,
1468c2c66affSColin Finck                         ExplicitDefaulted,
1469c2c66affSColin Finck                         ParentAcl,
1470c2c66affSColin Finck                         NULL,
1471c2c66affSColin Finck                         &SaclLength,
1472c2c66affSColin Finck                         Owner,
1473c2c66affSColin Finck                         Group,
1474c2c66affSColin Finck                         &SaclPresent,
1475c2c66affSColin Finck                         &SaclIsInherited,
1476c2c66affSColin Finck                         IsDirectoryObject,
1477c2c66affSColin Finck                         GenericMapping);
1478c2c66affSColin Finck     if (SaclPresent)
1479c2c66affSColin Finck         Control |= SE_SACL_PRESENT;
1480c2c66affSColin Finck     ASSERT(SaclLength % sizeof(ULONG) == 0);
1481c2c66affSColin Finck 
1482c2c66affSColin Finck     /* Allocate and initialize the new security descriptor */
1483c2c66affSColin Finck     Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
1484c2c66affSColin Finck         OwnerLength + GroupLength + DaclLength + SaclLength;
1485c2c66affSColin Finck 
1486c2c66affSColin Finck     DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n",
1487c2c66affSColin Finck            sizeof(SECURITY_DESCRIPTOR),
1488c2c66affSColin Finck            OwnerLength,
1489c2c66affSColin Finck            GroupLength,
1490c2c66affSColin Finck            DaclLength,
1491c2c66affSColin Finck            SaclLength);
1492c2c66affSColin Finck 
1493c2c66affSColin Finck     Descriptor = ExAllocatePoolWithTag(PagedPool, Length, TAG_SD);
1494c2c66affSColin Finck     if (Descriptor == NULL)
1495c2c66affSColin Finck     {
1496c2c66affSColin Finck         DPRINT1("ExAlloctePool() failed\n");
1497c2c66affSColin Finck         SeUnlockSubjectContext(SubjectContext);
1498c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
1499c2c66affSColin Finck     }
1500c2c66affSColin Finck 
1501c2c66affSColin Finck     RtlZeroMemory(Descriptor, Length);
1502c2c66affSColin Finck     RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION);
1503c2c66affSColin Finck 
1504c2c66affSColin Finck     Descriptor->Control = Control | SE_SELF_RELATIVE;
1505c2c66affSColin Finck 
1506c2c66affSColin Finck     Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1507c2c66affSColin Finck 
1508c2c66affSColin Finck     if (SaclLength != 0)
1509c2c66affSColin Finck     {
1510c2c66affSColin Finck         Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
1511c2c66affSColin Finck                                  &SaclLength,
1512c2c66affSColin Finck                                  Sacl,
1513c2c66affSColin Finck                                  Owner,
1514c2c66affSColin Finck                                  Group,
1515c2c66affSColin Finck                                  SaclIsInherited,
1516c2c66affSColin Finck                                  IsDirectoryObject,
1517c2c66affSColin Finck                                  GenericMapping);
1518c2c66affSColin Finck         ASSERT(Status == STATUS_SUCCESS);
1519c2c66affSColin Finck         Descriptor->Sacl = Current;
1520c2c66affSColin Finck         Current += SaclLength;
1521c2c66affSColin Finck     }
1522c2c66affSColin Finck 
1523c2c66affSColin Finck     if (DaclLength != 0)
1524c2c66affSColin Finck     {
1525c2c66affSColin Finck         Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
1526c2c66affSColin Finck                                  &DaclLength,
1527c2c66affSColin Finck                                  Dacl,
1528c2c66affSColin Finck                                  Owner,
1529c2c66affSColin Finck                                  Group,
1530c2c66affSColin Finck                                  DaclIsInherited,
1531c2c66affSColin Finck                                  IsDirectoryObject,
1532c2c66affSColin Finck                                  GenericMapping);
1533c2c66affSColin Finck         ASSERT(Status == STATUS_SUCCESS);
1534c2c66affSColin Finck         Descriptor->Dacl = Current;
1535c2c66affSColin Finck         Current += DaclLength;
1536c2c66affSColin Finck     }
1537c2c66affSColin Finck 
1538c2c66affSColin Finck     if (OwnerLength != 0)
1539c2c66affSColin Finck     {
1540c2c66affSColin Finck         RtlCopyMemory((PUCHAR)Descriptor + Current, Owner, OwnerLength);
1541c2c66affSColin Finck         Descriptor->Owner = Current;
1542c2c66affSColin Finck         Current += OwnerLength;
1543c2c66affSColin Finck         DPRINT("Owner of %p at %x\n", Descriptor, Descriptor->Owner);
1544c2c66affSColin Finck     }
1545c2c66affSColin Finck     else
1546c2c66affSColin Finck     {
1547c2c66affSColin Finck         DPRINT("Owner of %p is zero length\n", Descriptor);
1548c2c66affSColin Finck     }
1549c2c66affSColin Finck 
1550c2c66affSColin Finck     if (GroupLength != 0)
1551c2c66affSColin Finck     {
1552c2c66affSColin Finck         RtlCopyMemory((PUCHAR)Descriptor + Current, Group, GroupLength);
1553c2c66affSColin Finck         Descriptor->Group = Current;
1554c2c66affSColin Finck     }
1555c2c66affSColin Finck 
1556c2c66affSColin Finck     /* Unlock subject context */
1557c2c66affSColin Finck     SeUnlockSubjectContext(SubjectContext);
1558c2c66affSColin Finck 
1559c2c66affSColin Finck     *NewDescriptor = Descriptor;
1560c2c66affSColin Finck 
1561c2c66affSColin Finck     DPRINT("Descriptor %p\n", Descriptor);
1562c2c66affSColin Finck     ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1563c2c66affSColin Finck 
1564c2c66affSColin Finck     return STATUS_SUCCESS;
1565c2c66affSColin Finck }
1566c2c66affSColin Finck 
15676413009cSGeorge Bișoc /**
15686413009cSGeorge Bișoc  * @brief
15696413009cSGeorge Bișoc  * Assigns a security descriptor for a new object.
15706413009cSGeorge Bișoc  *
15716413009cSGeorge Bișoc  * @param[in] ParentDescriptor
15726413009cSGeorge Bișoc  * A security descriptor of the parent object that is being
15736413009cSGeorge Bișoc  * created.
15746413009cSGeorge Bișoc  *
15756413009cSGeorge Bișoc  * @param[in] ExplicitDescriptor
15766413009cSGeorge Bișoc  * An explicit security descriptor that is applied to a new
15776413009cSGeorge Bișoc  * object.
15786413009cSGeorge Bișoc  *
15796413009cSGeorge Bișoc  * @param[out] NewDescriptor
15806413009cSGeorge Bișoc  * The new allocated security descriptor.
15816413009cSGeorge Bișoc  *
15826413009cSGeorge Bișoc  * @param[in] IsDirectoryObject
15836413009cSGeorge Bișoc  * Set this to TRUE if the newly created object is a directory
15846413009cSGeorge Bișoc  * object, otherwise set this to FALSE.
15856413009cSGeorge Bișoc  *
15866413009cSGeorge Bișoc  * @param[in] SubjectContext
15876413009cSGeorge Bișoc  * Security subject context of the new object.
15886413009cSGeorge Bișoc  *
15896413009cSGeorge Bișoc  * @param[in] GenericMapping
15906413009cSGeorge Bișoc  * Generic mapping of access mask rights.
15916413009cSGeorge Bișoc  *
15926413009cSGeorge Bișoc  * @param[in] PoolType
15936413009cSGeorge Bișoc  * This parameter is unused.
15946413009cSGeorge Bișoc  *
15956413009cSGeorge Bișoc  * @return
15966413009cSGeorge Bișoc  * See SeAssignSecurityEx.
1597c2c66affSColin Finck  */
_IRQL_requires_max_(PASSIVE_LEVEL)1598c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
1599c2c66affSColin Finck NTSTATUS
1600c2c66affSColin Finck NTAPI
1601c2c66affSColin Finck SeAssignSecurity(
1602c2c66affSColin Finck     _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor,
1603c2c66affSColin Finck     _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor,
1604c2c66affSColin Finck     _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1605c2c66affSColin Finck     _In_ BOOLEAN IsDirectoryObject,
1606c2c66affSColin Finck     _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1607c2c66affSColin Finck     _In_ PGENERIC_MAPPING GenericMapping,
1608c2c66affSColin Finck     _In_ POOL_TYPE PoolType)
1609c2c66affSColin Finck {
1610c2c66affSColin Finck     PAGED_CODE();
1611c2c66affSColin Finck 
1612c2c66affSColin Finck     return SeAssignSecurityEx(ParentDescriptor,
1613c2c66affSColin Finck                               ExplicitDescriptor,
1614c2c66affSColin Finck                               NewDescriptor,
1615c2c66affSColin Finck                               NULL,
1616c2c66affSColin Finck                               IsDirectoryObject,
1617c2c66affSColin Finck                               0,
1618c2c66affSColin Finck                               SubjectContext,
1619c2c66affSColin Finck                               GenericMapping,
1620c2c66affSColin Finck                               PoolType);
1621c2c66affSColin Finck }
1622c2c66affSColin Finck 
16236413009cSGeorge Bișoc /**
16246413009cSGeorge Bișoc  * @brief
16256413009cSGeorge Bișoc  * Computes the quota size of a security descriptor.
16266413009cSGeorge Bișoc  *
16276413009cSGeorge Bișoc  * @param[in] SecurityDescriptor
16286413009cSGeorge Bișoc  * A security descriptor.
16296413009cSGeorge Bișoc  *
16306413009cSGeorge Bișoc  * @param[out] QuotaInfoSize
16316413009cSGeorge Bișoc  * The returned quota size of the given security descriptor to
16326413009cSGeorge Bișoc  * the caller. The function may return 0 to this parameter if
16336413009cSGeorge Bișoc  * the descriptor doesn't have a group or a discretionary
16346413009cSGeorge Bișoc  * access control list (DACL) even.
16356413009cSGeorge Bișoc  *
16366413009cSGeorge Bișoc  * @return
16376413009cSGeorge Bișoc  * Returns STATUS_SUCCESS if the quota size of a security
16386413009cSGeorge Bișoc  * descriptor has been computed successfully. STATUS_UNKNOWN_REVISION
16396413009cSGeorge Bișoc  * is returned if the security descriptor has an invalid revision.
16402ce071d1SPierre Schweitzer  */
_IRQL_requires_max_(PASSIVE_LEVEL)16412ce071d1SPierre Schweitzer _IRQL_requires_max_(PASSIVE_LEVEL)
16422ce071d1SPierre Schweitzer NTSTATUS
16432ce071d1SPierre Schweitzer NTAPI
16442ce071d1SPierre Schweitzer SeComputeQuotaInformationSize(
16452ce071d1SPierre Schweitzer     _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
16462ce071d1SPierre Schweitzer     _Out_ PULONG QuotaInfoSize)
16472ce071d1SPierre Schweitzer {
16482ce071d1SPierre Schweitzer     PSID Group;
16492ce071d1SPierre Schweitzer     PACL Dacl;
16502ce071d1SPierre Schweitzer 
16512ce071d1SPierre Schweitzer     PAGED_CODE();
16522ce071d1SPierre Schweitzer 
16532ce071d1SPierre Schweitzer     *QuotaInfoSize = 0;
16542ce071d1SPierre Schweitzer 
16552ce071d1SPierre Schweitzer     /* Validate security descriptor revision */
16562ce071d1SPierre Schweitzer     if (((PISECURITY_DESCRIPTOR)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION1)
16572ce071d1SPierre Schweitzer     {
16582ce071d1SPierre Schweitzer         return STATUS_UNKNOWN_REVISION;
16592ce071d1SPierre Schweitzer     }
16602ce071d1SPierre Schweitzer 
16612ce071d1SPierre Schweitzer     /* Get group and DACL, if any */
16622ce071d1SPierre Schweitzer     Group = SepGetGroupFromDescriptor(SecurityDescriptor);
16632ce071d1SPierre Schweitzer     Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
16642ce071d1SPierre Schweitzer 
16652ce071d1SPierre Schweitzer     /* Return SID length if any */
16662ce071d1SPierre Schweitzer     if (Group != NULL)
16672ce071d1SPierre Schweitzer     {
16682ce071d1SPierre Schweitzer         *QuotaInfoSize = ALIGN_UP_BY(RtlLengthSid(Group), sizeof(ULONG));
16692ce071d1SPierre Schweitzer     }
16702ce071d1SPierre Schweitzer 
16712ce071d1SPierre Schweitzer     /* Return DACL if any */
16722ce071d1SPierre Schweitzer     if (Dacl != NULL)
16732ce071d1SPierre Schweitzer     {
16742ce071d1SPierre Schweitzer         *QuotaInfoSize += ALIGN_UP_BY(Dacl->AclSize, sizeof(ULONG));
16752ce071d1SPierre Schweitzer     }
16762ce071d1SPierre Schweitzer 
16772ce071d1SPierre Schweitzer     return STATUS_SUCCESS;
16782ce071d1SPierre Schweitzer }
16792ce071d1SPierre Schweitzer 
1680c2c66affSColin Finck /* EOF */
1681