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