xref: /reactos/sdk/lib/rtl/sd.c (revision df053d4e)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:         See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:           ReactOS system libraries
4c2c66affSColin Finck  * PURPOSE:           Security descriptor functions
5c2c66affSColin Finck  * FILE:              lib/rtl/sd.c
6c2c66affSColin Finck  * PROGRAMER:         David Welch <welch@cwcom.net>
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck /* INCLUDES *****************************************************************/
10c2c66affSColin Finck 
11c2c66affSColin Finck #include <rtl.h>
12c2c66affSColin Finck #include "../../ntoskrnl/include/internal/se.h"
13c2c66affSColin Finck #define NDEBUG
14c2c66affSColin Finck #include <debug.h>
15c2c66affSColin Finck 
16c2c66affSColin Finck /* PRIVATE FUNCTIONS **********************************************************/
17c2c66affSColin Finck 
18c2c66affSColin Finck BOOLEAN
19c2c66affSColin Finck NTAPI
RtlpValidateSDOffsetAndSize(IN ULONG Offset,IN ULONG Length,IN ULONG MinLength,OUT PULONG MaxLength)20c2c66affSColin Finck RtlpValidateSDOffsetAndSize(IN ULONG Offset,
21c2c66affSColin Finck                             IN ULONG Length,
22c2c66affSColin Finck                             IN ULONG MinLength,
23c2c66affSColin Finck                             OUT PULONG MaxLength)
24c2c66affSColin Finck {
25c2c66affSColin Finck     /* Assume failure */
26c2c66affSColin Finck     *MaxLength = 0;
27c2c66affSColin Finck 
28c2c66affSColin Finck     /* Reject out of bounds lengths */
29c2c66affSColin Finck     if (Offset < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) return FALSE;
30c2c66affSColin Finck     if (Offset >= Length) return FALSE;
31c2c66affSColin Finck 
32c2c66affSColin Finck     /* Reject insufficient lengths */
33c2c66affSColin Finck     if ((Length - Offset) < MinLength) return FALSE;
34c2c66affSColin Finck 
35c2c66affSColin Finck     /* Reject unaligned offsets */
36c2c66affSColin Finck     if (ALIGN_DOWN(Offset, ULONG) != Offset) return FALSE;
37c2c66affSColin Finck 
38c2c66affSColin Finck     /* Return length that is safe to read */
39c2c66affSColin Finck     *MaxLength = Length - Offset;
40c2c66affSColin Finck     return TRUE;
41c2c66affSColin Finck }
42c2c66affSColin Finck 
43c2c66affSColin Finck VOID
44c2c66affSColin Finck NTAPI
RtlpQuerySecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,OUT PSID * Owner,OUT PULONG OwnerSize,OUT PSID * PrimaryGroup,OUT PULONG PrimaryGroupSize,OUT PACL * Dacl,OUT PULONG DaclSize,OUT PACL * Sacl,OUT PULONG SaclSize)45*df053d4eSTimo Kreuzer RtlpQuerySecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
46c2c66affSColin Finck                             OUT PSID *Owner,
47c2c66affSColin Finck                             OUT PULONG OwnerSize,
48c2c66affSColin Finck                             OUT PSID *PrimaryGroup,
49c2c66affSColin Finck                             OUT PULONG PrimaryGroupSize,
50c2c66affSColin Finck                             OUT PACL *Dacl,
51c2c66affSColin Finck                             OUT PULONG DaclSize,
52c2c66affSColin Finck                             OUT PACL *Sacl,
53c2c66affSColin Finck                             OUT PULONG SaclSize)
54c2c66affSColin Finck {
55c2c66affSColin Finck     PAGED_CODE_RTL();
56c2c66affSColin Finck 
57c2c66affSColin Finck     /* Get the owner */
58c2c66affSColin Finck     *Owner = SepGetOwnerFromDescriptor(SecurityDescriptor);
59c2c66affSColin Finck     if (*Owner)
60c2c66affSColin Finck     {
61c2c66affSColin Finck         /* There's an owner, so align the size */
62c2c66affSColin Finck         *OwnerSize = ROUND_UP(RtlLengthSid(*Owner), sizeof(ULONG));
63c2c66affSColin Finck     }
64c2c66affSColin Finck     else
65c2c66affSColin Finck     {
66c2c66affSColin Finck         /* No owner, no size */
67c2c66affSColin Finck         *OwnerSize = 0;
68c2c66affSColin Finck     }
69c2c66affSColin Finck 
70c2c66affSColin Finck     /* Get the group */
71c2c66affSColin Finck     *PrimaryGroup = SepGetGroupFromDescriptor(SecurityDescriptor);
72c2c66affSColin Finck     if (*PrimaryGroup)
73c2c66affSColin Finck     {
74c2c66affSColin Finck         /* There's a group, so align the size */
75c2c66affSColin Finck         *PrimaryGroupSize = ROUND_UP(RtlLengthSid(*PrimaryGroup), sizeof(ULONG));
76c2c66affSColin Finck     }
77c2c66affSColin Finck     else
78c2c66affSColin Finck     {
79c2c66affSColin Finck         /* No group, no size */
80c2c66affSColin Finck         *PrimaryGroupSize = 0;
81c2c66affSColin Finck     }
82c2c66affSColin Finck 
83c2c66affSColin Finck     /* Get the DACL */
84c2c66affSColin Finck     *Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
85c2c66affSColin Finck     if (*Dacl)
86c2c66affSColin Finck     {
87c2c66affSColin Finck         /* There's a DACL, align the size */
88c2c66affSColin Finck         *DaclSize = ROUND_UP((*Dacl)->AclSize, sizeof(ULONG));
89c2c66affSColin Finck     }
90c2c66affSColin Finck     else
91c2c66affSColin Finck     {
92c2c66affSColin Finck         /* No DACL, no size */
93c2c66affSColin Finck         *DaclSize = 0;
94c2c66affSColin Finck     }
95c2c66affSColin Finck 
96c2c66affSColin Finck     /* Get the SACL */
97c2c66affSColin Finck     *Sacl = SepGetSaclFromDescriptor(SecurityDescriptor);
98c2c66affSColin Finck     if (*Sacl)
99c2c66affSColin Finck     {
100c2c66affSColin Finck         /* There's a SACL, align the size */
101c2c66affSColin Finck         *SaclSize = ROUND_UP((*Sacl)->AclSize, sizeof(ULONG));
102c2c66affSColin Finck     }
103c2c66affSColin Finck     else
104c2c66affSColin Finck     {
105c2c66affSColin Finck         /* No SACL, no size */
106c2c66affSColin Finck         *SaclSize = 0;
107c2c66affSColin Finck     }
108c2c66affSColin Finck }
109c2c66affSColin Finck 
110c2c66affSColin Finck /* PUBLIC FUNCTIONS ***********************************************************/
111c2c66affSColin Finck 
112c2c66affSColin Finck /*
113c2c66affSColin Finck  * @implemented
114c2c66affSColin Finck  */
115c2c66affSColin Finck NTSTATUS
116c2c66affSColin Finck NTAPI
RtlCreateSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN ULONG Revision)117c2c66affSColin Finck RtlCreateSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
118c2c66affSColin Finck                             IN ULONG Revision)
119c2c66affSColin Finck {
120c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
121c2c66affSColin Finck     PAGED_CODE_RTL();
122c2c66affSColin Finck 
123c2c66affSColin Finck     /* Fail on invalid revisions */
124c2c66affSColin Finck     if (Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
125c2c66affSColin Finck 
126c2c66affSColin Finck     /* Setup an empty SD */
127c2c66affSColin Finck     RtlZeroMemory(Sd, sizeof(*Sd));
128c2c66affSColin Finck     Sd->Revision = SECURITY_DESCRIPTOR_REVISION;
129c2c66affSColin Finck 
130c2c66affSColin Finck     /* All good */
131c2c66affSColin Finck     return STATUS_SUCCESS;
132c2c66affSColin Finck }
133c2c66affSColin Finck 
134c2c66affSColin Finck /*
135c2c66affSColin Finck  * @implemented
136c2c66affSColin Finck  */
137c2c66affSColin Finck NTSTATUS
138c2c66affSColin Finck NTAPI
RtlCreateSecurityDescriptorRelative(IN PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor,IN ULONG Revision)139c2c66affSColin Finck RtlCreateSecurityDescriptorRelative(IN PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor,
140c2c66affSColin Finck                                     IN ULONG Revision)
141c2c66affSColin Finck {
142c2c66affSColin Finck     PAGED_CODE_RTL();
143c2c66affSColin Finck 
144c2c66affSColin Finck     /* Fail on invalid revisions */
145c2c66affSColin Finck     if (Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
146c2c66affSColin Finck 
147c2c66affSColin Finck     /* Setup an empty SD */
148c2c66affSColin Finck     RtlZeroMemory(SecurityDescriptor, sizeof(*SecurityDescriptor));
149c2c66affSColin Finck     SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
150c2c66affSColin Finck     SecurityDescriptor->Control = SE_SELF_RELATIVE;
151c2c66affSColin Finck 
152c2c66affSColin Finck     /* All good */
153c2c66affSColin Finck     return STATUS_SUCCESS;
154c2c66affSColin Finck }
155c2c66affSColin Finck 
156c2c66affSColin Finck /*
157c2c66affSColin Finck  * @implemented
158c2c66affSColin Finck  */
159c2c66affSColin Finck ULONG
160c2c66affSColin Finck NTAPI
RtlLengthSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)161c2c66affSColin Finck RtlLengthSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
162c2c66affSColin Finck {
163c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd;
164c2c66affSColin Finck     PSID Owner, Group;
165c2c66affSColin Finck     PACL Sacl, Dacl;
166c2c66affSColin Finck     ULONG Length;
167c2c66affSColin Finck     PAGED_CODE_RTL();
168c2c66affSColin Finck 
169c2c66affSColin Finck     /* Start with the initial length of the SD itself */
170c2c66affSColin Finck     Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
171c2c66affSColin Finck     if (Sd->Control & SE_SELF_RELATIVE)
172c2c66affSColin Finck     {
173c2c66affSColin Finck         Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
174c2c66affSColin Finck     }
175c2c66affSColin Finck     else
176c2c66affSColin Finck     {
177c2c66affSColin Finck         Length = sizeof(SECURITY_DESCRIPTOR);
178c2c66affSColin Finck     }
179c2c66affSColin Finck 
180c2c66affSColin Finck     /* Add the length of the individual subcomponents */
181c2c66affSColin Finck     Owner = SepGetOwnerFromDescriptor(Sd);
182c2c66affSColin Finck     if (Owner) Length += ROUND_UP(RtlLengthSid(Owner), sizeof(ULONG));
183c2c66affSColin Finck     Group = SepGetGroupFromDescriptor(Sd);
184c2c66affSColin Finck     if (Group) Length += ROUND_UP(RtlLengthSid(Group), sizeof(ULONG));
185c2c66affSColin Finck     Dacl = SepGetDaclFromDescriptor(Sd);
186c2c66affSColin Finck     if (Dacl) Length += ROUND_UP(Dacl->AclSize, sizeof(ULONG));
187c2c66affSColin Finck     Sacl = SepGetSaclFromDescriptor(Sd);
188c2c66affSColin Finck     if (Sacl) Length += ROUND_UP(Sacl->AclSize, sizeof(ULONG));
189c2c66affSColin Finck 
190c2c66affSColin Finck     /* Return the final length */
191c2c66affSColin Finck     return Length;
192c2c66affSColin Finck }
193c2c66affSColin Finck 
194c2c66affSColin Finck /*
195c2c66affSColin Finck  * @implemented
196c2c66affSColin Finck  */
197c2c66affSColin Finck NTSTATUS
198c2c66affSColin Finck NTAPI
RtlGetDaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,OUT PBOOLEAN DaclPresent,OUT PACL * Dacl,OUT PBOOLEAN DaclDefaulted)199c2c66affSColin Finck RtlGetDaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
200c2c66affSColin Finck                              OUT PBOOLEAN DaclPresent,
201c2c66affSColin Finck                              OUT PACL* Dacl,
202c2c66affSColin Finck                              OUT PBOOLEAN DaclDefaulted)
203c2c66affSColin Finck {
204c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
205c2c66affSColin Finck     PAGED_CODE_RTL();
206c2c66affSColin Finck 
207c2c66affSColin Finck     /* Fail on invalid revisions */
208c2c66affSColin Finck     if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
209c2c66affSColin Finck 
210c2c66affSColin Finck     /* Is there a DACL? */
211c2c66affSColin Finck     *DaclPresent = (Sd->Control & SE_DACL_PRESENT) == SE_DACL_PRESENT;
212c2c66affSColin Finck     if (*DaclPresent)
213c2c66affSColin Finck     {
214c2c66affSColin Finck         /* Yes, return it, and check if defaulted */
215c2c66affSColin Finck         *Dacl = SepGetDaclFromDescriptor(Sd);
216c2c66affSColin Finck         *DaclDefaulted = (Sd->Control & SE_DACL_DEFAULTED) == SE_DACL_DEFAULTED;
217c2c66affSColin Finck     }
218c2c66affSColin Finck 
219c2c66affSColin Finck     /* All good */
220c2c66affSColin Finck     return STATUS_SUCCESS;
221c2c66affSColin Finck }
222c2c66affSColin Finck 
223c2c66affSColin Finck /*
224c2c66affSColin Finck  * @implemented
225c2c66affSColin Finck  */
226c2c66affSColin Finck NTSTATUS
227c2c66affSColin Finck NTAPI
RtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,OUT PBOOLEAN SaclPresent,OUT PACL * Sacl,OUT PBOOLEAN SaclDefaulted)228c2c66affSColin Finck RtlGetSaclSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
229c2c66affSColin Finck                              OUT PBOOLEAN SaclPresent,
230c2c66affSColin Finck                              OUT PACL* Sacl,
231c2c66affSColin Finck                              OUT PBOOLEAN SaclDefaulted)
232c2c66affSColin Finck {
233c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
234c2c66affSColin Finck     PAGED_CODE_RTL();
235c2c66affSColin Finck 
236c2c66affSColin Finck     /* Fail on invalid revisions */
237c2c66affSColin Finck     if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
238c2c66affSColin Finck 
239c2c66affSColin Finck     /* Is there a SACL? */
240c2c66affSColin Finck     *SaclPresent = (Sd->Control & SE_SACL_PRESENT) == SE_SACL_PRESENT;
241c2c66affSColin Finck     if (*SaclPresent)
242c2c66affSColin Finck     {
243c2c66affSColin Finck         /* Yes, return it, and check if defaulted */
244c2c66affSColin Finck         *Sacl = SepGetSaclFromDescriptor(Sd);
245c2c66affSColin Finck         *SaclDefaulted = (Sd->Control & SE_SACL_DEFAULTED) == SE_SACL_DEFAULTED;
246c2c66affSColin Finck     }
247c2c66affSColin Finck 
248c2c66affSColin Finck     /* All good */
249c2c66affSColin Finck     return STATUS_SUCCESS;
250c2c66affSColin Finck }
251c2c66affSColin Finck 
252c2c66affSColin Finck /*
253c2c66affSColin Finck  * @implemented
254c2c66affSColin Finck  */
255c2c66affSColin Finck NTSTATUS
256c2c66affSColin Finck NTAPI
RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,OUT PSID * Owner,OUT PBOOLEAN OwnerDefaulted)257c2c66affSColin Finck RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
258c2c66affSColin Finck                               OUT PSID* Owner,
259c2c66affSColin Finck                               OUT PBOOLEAN OwnerDefaulted)
260c2c66affSColin Finck {
261c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
262c2c66affSColin Finck     PAGED_CODE_RTL();
263c2c66affSColin Finck 
264c2c66affSColin Finck     /* Fail on invalid revision */
265c2c66affSColin Finck     if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
266c2c66affSColin Finck 
267c2c66affSColin Finck     /* Get the owner and if defaulted */
268c2c66affSColin Finck     *Owner = SepGetOwnerFromDescriptor(Sd);
269c2c66affSColin Finck     *OwnerDefaulted = (Sd->Control & SE_OWNER_DEFAULTED) == SE_OWNER_DEFAULTED;
270c2c66affSColin Finck 
271c2c66affSColin Finck     /* All good */
272c2c66affSColin Finck     return STATUS_SUCCESS;
273c2c66affSColin Finck }
274c2c66affSColin Finck 
275c2c66affSColin Finck /*
276c2c66affSColin Finck  * @implemented
277c2c66affSColin Finck  */
278c2c66affSColin Finck NTSTATUS
279c2c66affSColin Finck NTAPI
RtlGetGroupSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,OUT PSID * Group,OUT PBOOLEAN GroupDefaulted)280c2c66affSColin Finck RtlGetGroupSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
281c2c66affSColin Finck                               OUT PSID* Group,
282c2c66affSColin Finck                               OUT PBOOLEAN GroupDefaulted)
283c2c66affSColin Finck {
284c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
285c2c66affSColin Finck     PAGED_CODE_RTL();
286c2c66affSColin Finck 
287c2c66affSColin Finck     /* Fail on invalid revision */
288c2c66affSColin Finck     if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
289c2c66affSColin Finck 
290c2c66affSColin Finck     /* Get the group and if defaulted */
291c2c66affSColin Finck     *Group = SepGetGroupFromDescriptor(Sd);
292c2c66affSColin Finck     *GroupDefaulted = (Sd->Control & SE_GROUP_DEFAULTED) == SE_GROUP_DEFAULTED;
293c2c66affSColin Finck 
294c2c66affSColin Finck     /* All good */
295c2c66affSColin Finck     return STATUS_SUCCESS;
296c2c66affSColin Finck }
297c2c66affSColin Finck 
298c2c66affSColin Finck /*
299c2c66affSColin Finck  * @implemented
300c2c66affSColin Finck  */
301c2c66affSColin Finck NTSTATUS
302c2c66affSColin Finck NTAPI
RtlSetDaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,IN BOOLEAN DaclPresent,IN PACL Dacl,IN BOOLEAN DaclDefaulted)303c2c66affSColin Finck RtlSetDaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
304c2c66affSColin Finck                              IN BOOLEAN DaclPresent,
305c2c66affSColin Finck                              IN PACL Dacl,
306c2c66affSColin Finck                              IN BOOLEAN DaclDefaulted)
307c2c66affSColin Finck {
308c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
309c2c66affSColin Finck     PAGED_CODE_RTL();
310c2c66affSColin Finck 
311c2c66affSColin Finck     /* Fail on invalid revision */
312c2c66affSColin Finck     if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
313c2c66affSColin Finck 
314c2c66affSColin Finck     /* Fail on relative descriptors */
315c2c66affSColin Finck     if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
316c2c66affSColin Finck 
317c2c66affSColin Finck     /* Is there a DACL? */
318c2c66affSColin Finck     if (!DaclPresent)
319c2c66affSColin Finck     {
320c2c66affSColin Finck         /* Caller is destroying the DACL, unset the flag and we're done */
321c2c66affSColin Finck         Sd->Control = Sd->Control & ~SE_DACL_PRESENT;
322c2c66affSColin Finck         return STATUS_SUCCESS;
323c2c66affSColin Finck     }
324c2c66affSColin Finck 
325c2c66affSColin Finck     /* Caller is setting a new DACL, set the pointer and flag */
326c2c66affSColin Finck     Sd->Dacl = Dacl;
327c2c66affSColin Finck     Sd->Control |= SE_DACL_PRESENT;
328c2c66affSColin Finck 
329c2c66affSColin Finck     /* Set if defaulted */
330c2c66affSColin Finck     Sd->Control &= ~SE_DACL_DEFAULTED;
331c2c66affSColin Finck     if (DaclDefaulted) Sd->Control |= SE_DACL_DEFAULTED;
332c2c66affSColin Finck 
333c2c66affSColin Finck     /* All good */
334c2c66affSColin Finck     return STATUS_SUCCESS;
335c2c66affSColin Finck }
336c2c66affSColin Finck 
337c2c66affSColin Finck /*
338c2c66affSColin Finck  * @implemented
339c2c66affSColin Finck  */
340c2c66affSColin Finck NTSTATUS
341c2c66affSColin Finck NTAPI
RtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,IN BOOLEAN SaclPresent,IN PACL Sacl,IN BOOLEAN SaclDefaulted)342c2c66affSColin Finck RtlSetSaclSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
343c2c66affSColin Finck                              IN BOOLEAN SaclPresent,
344c2c66affSColin Finck                              IN PACL Sacl,
345c2c66affSColin Finck                              IN BOOLEAN SaclDefaulted)
346c2c66affSColin Finck {
347c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
348c2c66affSColin Finck     PAGED_CODE_RTL();
349c2c66affSColin Finck 
350c2c66affSColin Finck     /* Fail on invalid revision */
351c2c66affSColin Finck     if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
352c2c66affSColin Finck 
353c2c66affSColin Finck     /* Fail on relative descriptors */
354c2c66affSColin Finck     if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
355c2c66affSColin Finck 
356c2c66affSColin Finck     /* Is there a SACL? */
357c2c66affSColin Finck     if (!SaclPresent)
358c2c66affSColin Finck     {
359c2c66affSColin Finck         /* Caller is clearing the SACL, unset the flag and we're done */
360c2c66affSColin Finck         Sd->Control = Sd->Control & ~SE_SACL_PRESENT;
361c2c66affSColin Finck         return STATUS_SUCCESS;
362c2c66affSColin Finck     }
363c2c66affSColin Finck 
364c2c66affSColin Finck     /* Caller is setting a new SACL, set it and the flag */
365c2c66affSColin Finck     Sd->Sacl = Sacl;
366c2c66affSColin Finck     Sd->Control |= SE_SACL_PRESENT;
367c2c66affSColin Finck 
368c2c66affSColin Finck     /* Set if defaulted */
369c2c66affSColin Finck     Sd->Control &= ~SE_SACL_DEFAULTED;
370c2c66affSColin Finck     if (SaclDefaulted) Sd->Control |= SE_SACL_DEFAULTED;
371c2c66affSColin Finck 
372c2c66affSColin Finck     /* All good */
373c2c66affSColin Finck     return STATUS_SUCCESS;
374c2c66affSColin Finck }
375c2c66affSColin Finck 
376c2c66affSColin Finck /*
377c2c66affSColin Finck  * @implemented
378c2c66affSColin Finck  */
379c2c66affSColin Finck NTSTATUS
380c2c66affSColin Finck NTAPI
RtlSetOwnerSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,IN PSID Owner,IN BOOLEAN OwnerDefaulted)381c2c66affSColin Finck RtlSetOwnerSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
382c2c66affSColin Finck                               IN PSID Owner,
383c2c66affSColin Finck                               IN BOOLEAN OwnerDefaulted)
384c2c66affSColin Finck {
385c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
386c2c66affSColin Finck     PAGED_CODE_RTL();
387c2c66affSColin Finck 
388c2c66affSColin Finck     /* Fail on invalid revision */
389c2c66affSColin Finck     if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
390c2c66affSColin Finck 
391c2c66affSColin Finck     /* Fail on relative descriptors */
392c2c66affSColin Finck     if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
393c2c66affSColin Finck 
394c2c66affSColin Finck     /* Owner being set or cleared */
395c2c66affSColin Finck     Sd->Owner = Owner;
396c2c66affSColin Finck 
397c2c66affSColin Finck     /* Set if defaulted */
398c2c66affSColin Finck     Sd->Control &= ~SE_OWNER_DEFAULTED;
399c2c66affSColin Finck     if (OwnerDefaulted) Sd->Control |= SE_OWNER_DEFAULTED;
400c2c66affSColin Finck 
401c2c66affSColin Finck     /* All good */
402c2c66affSColin Finck     return STATUS_SUCCESS;
403c2c66affSColin Finck }
404c2c66affSColin Finck 
405c2c66affSColin Finck /*
406c2c66affSColin Finck  * @implemented
407c2c66affSColin Finck  */
408c2c66affSColin Finck NTSTATUS
409c2c66affSColin Finck NTAPI
RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,IN PSID Group,IN BOOLEAN GroupDefaulted)410c2c66affSColin Finck RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
411c2c66affSColin Finck                               IN PSID Group,
412c2c66affSColin Finck                               IN BOOLEAN GroupDefaulted)
413c2c66affSColin Finck {
414c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
415c2c66affSColin Finck     PAGED_CODE_RTL();
416c2c66affSColin Finck 
417c2c66affSColin Finck     /* Fail on invalid revision */
418c2c66affSColin Finck     if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
419c2c66affSColin Finck 
420c2c66affSColin Finck     /* Fail on relative descriptors */
421c2c66affSColin Finck     if (Sd->Control & SE_SELF_RELATIVE) return STATUS_INVALID_SECURITY_DESCR;
422c2c66affSColin Finck 
423c2c66affSColin Finck     /* Group being set or cleared */
424c2c66affSColin Finck     Sd->Group = Group;
425c2c66affSColin Finck 
426c2c66affSColin Finck     /* Set if defaulted */
427c2c66affSColin Finck     Sd->Control &= ~SE_GROUP_DEFAULTED;
428c2c66affSColin Finck     if (GroupDefaulted) Sd->Control |= SE_GROUP_DEFAULTED;
429c2c66affSColin Finck 
430c2c66affSColin Finck     /* All good */
431c2c66affSColin Finck     return STATUS_SUCCESS;
432c2c66affSColin Finck }
433c2c66affSColin Finck 
434c2c66affSColin Finck /*
435c2c66affSColin Finck  * @implemented
436c2c66affSColin Finck  */
437c2c66affSColin Finck NTSTATUS
438c2c66affSColin Finck NTAPI
RtlGetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,OUT PSECURITY_DESCRIPTOR_CONTROL Control,OUT PULONG Revision)439c2c66affSColin Finck RtlGetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
440c2c66affSColin Finck                                 OUT PSECURITY_DESCRIPTOR_CONTROL Control,
441c2c66affSColin Finck                                 OUT PULONG Revision)
442c2c66affSColin Finck {
443c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
444c2c66affSColin Finck     PAGED_CODE_RTL();
445c2c66affSColin Finck 
446c2c66affSColin Finck     /* Read current revision, even if invalid */
447c2c66affSColin Finck     *Revision = Sd->Revision;
448c2c66affSColin Finck 
449c2c66affSColin Finck     /* Fail on invalid revision */
450c2c66affSColin Finck     if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
451c2c66affSColin Finck 
452c2c66affSColin Finck     /* Read current control */
453c2c66affSColin Finck     *Control = Sd->Control;
454c2c66affSColin Finck 
455c2c66affSColin Finck     /* All good */
456c2c66affSColin Finck     return STATUS_SUCCESS;
457c2c66affSColin Finck }
458c2c66affSColin Finck 
459c2c66affSColin Finck /*
460c2c66affSColin Finck  * @implemented
461c2c66affSColin Finck  */
462c2c66affSColin Finck NTSTATUS
463c2c66affSColin Finck NTAPI
RtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)464c2c66affSColin Finck RtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
465c2c66affSColin Finck                                 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
466c2c66affSColin Finck                                 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
467c2c66affSColin Finck {
468c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
469c2c66affSColin Finck 
470c2c66affSColin Finck     /* Check for invalid bits */
471c2c66affSColin Finck     if ((ControlBitsOfInterest & ~(SE_DACL_UNTRUSTED |
472c2c66affSColin Finck                                    SE_SERVER_SECURITY |
473c2c66affSColin Finck                                    SE_DACL_AUTO_INHERIT_REQ |
474c2c66affSColin Finck                                    SE_SACL_AUTO_INHERIT_REQ |
475c2c66affSColin Finck                                    SE_DACL_AUTO_INHERITED |
476c2c66affSColin Finck                                    SE_SACL_AUTO_INHERITED |
477c2c66affSColin Finck                                    SE_DACL_PROTECTED |
478c2c66affSColin Finck                                    SE_SACL_PROTECTED)) ||
479c2c66affSColin Finck         (ControlBitsToSet & ~ControlBitsOfInterest))
480c2c66affSColin Finck     {
481c2c66affSColin Finck         /* Fail */
482c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
483c2c66affSColin Finck     }
484c2c66affSColin Finck 
485c2c66affSColin Finck     /* Zero the 'bits of interest' */
486c2c66affSColin Finck     Sd->Control &= ~ControlBitsOfInterest;
487c2c66affSColin Finck 
488c2c66affSColin Finck     /* Set the 'bits to set' */
489c2c66affSColin Finck     Sd->Control |= (ControlBitsToSet & ControlBitsOfInterest);
490c2c66affSColin Finck 
491c2c66affSColin Finck     /* All good */
492c2c66affSColin Finck     return STATUS_SUCCESS;
493c2c66affSColin Finck }
494c2c66affSColin Finck 
495c2c66affSColin Finck /*
496c2c66affSColin Finck  * @implemented
497c2c66affSColin Finck  */
498c2c66affSColin Finck BOOLEAN
499c2c66affSColin Finck NTAPI
RtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor,OUT PUCHAR RMControl)500c2c66affSColin Finck RtlGetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
501c2c66affSColin Finck                                   OUT PUCHAR RMControl)
502c2c66affSColin Finck {
503c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
504c2c66affSColin Finck     PAGED_CODE_RTL();
505c2c66affSColin Finck 
506c2c66affSColin Finck     /* Check if there's no valid RM control */
507c2c66affSColin Finck     if (!(Sd->Control & SE_RM_CONTROL_VALID))
508c2c66affSColin Finck     {
509c2c66affSColin Finck         /* Fail and return nothing */
510c2c66affSColin Finck         *RMControl = 0;
511c2c66affSColin Finck         return FALSE;
512c2c66affSColin Finck     }
513c2c66affSColin Finck 
514c2c66affSColin Finck     /* Return it, ironically the member is "should be zero" */
515c2c66affSColin Finck     *RMControl = Sd->Sbz1;
516c2c66affSColin Finck     return TRUE;
517c2c66affSColin Finck }
518c2c66affSColin Finck 
519c2c66affSColin Finck /*
520c2c66affSColin Finck  * @implemented
521c2c66affSColin Finck  */
522c2c66affSColin Finck VOID
523c2c66affSColin Finck NTAPI
RtlSetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN PUCHAR RMControl)524c2c66affSColin Finck RtlSetSecurityDescriptorRMControl(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
525c2c66affSColin Finck                                   IN PUCHAR RMControl)
526c2c66affSColin Finck {
527c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
528c2c66affSColin Finck     PAGED_CODE_RTL();
529c2c66affSColin Finck 
530c2c66affSColin Finck     /* RM Control is being cleared or set */
531c2c66affSColin Finck     if (!RMControl)
532c2c66affSColin Finck     {
533c2c66affSColin Finck         /* Clear it */
534c2c66affSColin Finck         Sd->Control &= ~SE_RM_CONTROL_VALID;
535c2c66affSColin Finck         Sd->Sbz1 = 0;
536c2c66affSColin Finck     }
537c2c66affSColin Finck     else
538c2c66affSColin Finck     {
539c2c66affSColin Finck         /* Set it */
540c2c66affSColin Finck         Sd->Control |= SE_RM_CONTROL_VALID;
541c2c66affSColin Finck         Sd->Sbz1 = *RMControl;
542c2c66affSColin Finck     }
543c2c66affSColin Finck }
544c2c66affSColin Finck 
545c2c66affSColin Finck /*
546c2c66affSColin Finck  * @implemented
547c2c66affSColin Finck  */
548c2c66affSColin Finck NTSTATUS
549c2c66affSColin Finck NTAPI
RtlSetAttributesSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN SECURITY_DESCRIPTOR_CONTROL Control,OUT PULONG Revision)550c2c66affSColin Finck RtlSetAttributesSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
551c2c66affSColin Finck                                    IN SECURITY_DESCRIPTOR_CONTROL Control,
552c2c66affSColin Finck                                    OUT PULONG Revision)
553c2c66affSColin Finck {
554c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
555c2c66affSColin Finck     PAGED_CODE_RTL();
556c2c66affSColin Finck 
557c2c66affSColin Finck     /* Always return revision, even if invalid */
558c2c66affSColin Finck     *Revision = Sd->Revision;
559c2c66affSColin Finck 
560c2c66affSColin Finck     /* Fail on invalid revision */
561c2c66affSColin Finck     if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) return STATUS_UNKNOWN_REVISION;
562c2c66affSColin Finck 
563c2c66affSColin Finck     /* Mask out flags which are not attributes */
564c2c66affSColin Finck     Control &= SE_DACL_UNTRUSTED |
565c2c66affSColin Finck                SE_SERVER_SECURITY |
566c2c66affSColin Finck                SE_DACL_AUTO_INHERIT_REQ |
567c2c66affSColin Finck                SE_SACL_AUTO_INHERIT_REQ |
568c2c66affSColin Finck                SE_DACL_AUTO_INHERITED |
569c2c66affSColin Finck                SE_SACL_AUTO_INHERITED |
570c2c66affSColin Finck                SE_DACL_PROTECTED |
571c2c66affSColin Finck                SE_SACL_PROTECTED;
572c2c66affSColin Finck 
573c2c66affSColin Finck     /* Call the newer API */
574c2c66affSColin Finck     return RtlSetControlSecurityDescriptor(SecurityDescriptor, Control, Control);
575c2c66affSColin Finck }
576c2c66affSColin Finck 
577c2c66affSColin Finck /*
578c2c66affSColin Finck  * @implemented
579c2c66affSColin Finck  */
580c2c66affSColin Finck NTSTATUS
581c2c66affSColin Finck NTAPI
RtlCopySecurityDescriptor(IN PSECURITY_DESCRIPTOR pSourceSecurityDescriptor,OUT PSECURITY_DESCRIPTOR * pDestinationSecurityDescriptor)582c2c66affSColin Finck RtlCopySecurityDescriptor(IN PSECURITY_DESCRIPTOR pSourceSecurityDescriptor,
583c2c66affSColin Finck                           OUT PSECURITY_DESCRIPTOR *pDestinationSecurityDescriptor)
584c2c66affSColin Finck {
585c2c66affSColin Finck     PSID Owner, Group;
586c2c66affSColin Finck     PACL Dacl, Sacl;
587c2c66affSColin Finck     DWORD OwnerLength, GroupLength, DaclLength, SaclLength, TotalLength;
588c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = pSourceSecurityDescriptor;
589c2c66affSColin Finck 
590c2c66affSColin Finck     /* Get all the components */
591c2c66affSColin Finck     RtlpQuerySecurityDescriptor(Sd,
592c2c66affSColin Finck                                 &Owner,
593c2c66affSColin Finck                                 &OwnerLength,
594c2c66affSColin Finck                                 &Group,
595c2c66affSColin Finck                                 &GroupLength,
596c2c66affSColin Finck                                 &Dacl,
597c2c66affSColin Finck                                 &DaclLength,
598c2c66affSColin Finck                                 &Sacl,
599c2c66affSColin Finck                                 &SaclLength);
600c2c66affSColin Finck 
601c2c66affSColin Finck     /* Add up their lengths */
602c2c66affSColin Finck     TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
603c2c66affSColin Finck                   OwnerLength +
604c2c66affSColin Finck                   GroupLength +
605c2c66affSColin Finck                   DaclLength +
606c2c66affSColin Finck                   SaclLength;
607c2c66affSColin Finck 
608c2c66affSColin Finck     /* Allocate a copy */
609c2c66affSColin Finck     *pDestinationSecurityDescriptor = RtlAllocateHeap(RtlGetProcessHeap(),
610c2c66affSColin Finck                                                       0,
611c2c66affSColin Finck                                                           TotalLength);
612c2c66affSColin Finck     if (*pDestinationSecurityDescriptor == NULL) return STATUS_NO_MEMORY;
613c2c66affSColin Finck 
614c2c66affSColin Finck     /* Copy the old in the new */
615c2c66affSColin Finck     RtlCopyMemory(*pDestinationSecurityDescriptor, Sd, TotalLength);
616c2c66affSColin Finck 
617c2c66affSColin Finck     /* All good */
618c2c66affSColin Finck     return STATUS_SUCCESS;
619c2c66affSColin Finck }
620c2c66affSColin Finck 
621c2c66affSColin Finck /*
622c2c66affSColin Finck  * @implemented
623c2c66affSColin Finck  */
624c2c66affSColin Finck NTSTATUS
625c2c66affSColin Finck NTAPI
RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,IN PULONG BufferLength)626c2c66affSColin Finck RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
627c2c66affSColin Finck                             IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
628c2c66affSColin Finck                             IN PULONG BufferLength)
629c2c66affSColin Finck {
630c2c66affSColin Finck    PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)AbsoluteSecurityDescriptor;
631c2c66affSColin Finck    PAGED_CODE_RTL();
632c2c66affSColin Finck 
633c2c66affSColin Finck    /* Can't already be relative */
634c2c66affSColin Finck    if (Sd->Control & SE_SELF_RELATIVE) return STATUS_BAD_DESCRIPTOR_FORMAT;
635c2c66affSColin Finck 
636c2c66affSColin Finck    /* Call the other API */
637c2c66affSColin Finck    return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
638c2c66affSColin Finck                                 SelfRelativeSecurityDescriptor,
639c2c66affSColin Finck                                 BufferLength);
640c2c66affSColin Finck }
641c2c66affSColin Finck 
642c2c66affSColin Finck /*
643c2c66affSColin Finck  * @implemented
644c2c66affSColin Finck  */
645c2c66affSColin Finck NTSTATUS
646c2c66affSColin Finck NTAPI
RtlMakeSelfRelativeSD(IN PSECURITY_DESCRIPTOR SecurityDescriptor,OUT PSECURITY_DESCRIPTOR SelfRelativeSD,IN OUT PULONG BufferLength)647*df053d4eSTimo Kreuzer RtlMakeSelfRelativeSD(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
648c2c66affSColin Finck                       OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
649c2c66affSColin Finck                       IN OUT PULONG BufferLength)
650c2c66affSColin Finck {
651c2c66affSColin Finck     PSID Owner, Group;
652c2c66affSColin Finck     PACL Sacl, Dacl;
653c2c66affSColin Finck     ULONG OwnerLength, GroupLength, SaclLength, DaclLength, TotalLength;
654c2c66affSColin Finck     ULONG_PTR Current;
655c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE RelSd = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
656c2c66affSColin Finck     PAGED_CODE_RTL();
657c2c66affSColin Finck 
658c2c66affSColin Finck     /* Query all components */
659*df053d4eSTimo Kreuzer     RtlpQuerySecurityDescriptor(SecurityDescriptor,
660c2c66affSColin Finck                                 &Owner,
661c2c66affSColin Finck                                 &OwnerLength,
662c2c66affSColin Finck                                 &Group,
663c2c66affSColin Finck                                 &GroupLength,
664c2c66affSColin Finck                                 &Dacl,
665c2c66affSColin Finck                                 &DaclLength,
666c2c66affSColin Finck                                 &Sacl,
667c2c66affSColin Finck                                 &SaclLength);
668c2c66affSColin Finck 
669c2c66affSColin Finck     /* Calculate final length */
670c2c66affSColin Finck     TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
671c2c66affSColin Finck                   OwnerLength +
672c2c66affSColin Finck                   GroupLength +
673c2c66affSColin Finck                   SaclLength +
674c2c66affSColin Finck                   DaclLength;
675c2c66affSColin Finck 
676c2c66affSColin Finck     /* Is there enough space? */
677c2c66affSColin Finck     if (*BufferLength < TotalLength)
678c2c66affSColin Finck     {
679c2c66affSColin Finck         /* Nope, return how much is needed */
680c2c66affSColin Finck         *BufferLength = TotalLength;
681c2c66affSColin Finck         return STATUS_BUFFER_TOO_SMALL;
682c2c66affSColin Finck     }
683c2c66affSColin Finck 
684c2c66affSColin Finck     /* Start fresh */
685c2c66affSColin Finck     RtlZeroMemory(RelSd, TotalLength);
686c2c66affSColin Finck 
687c2c66affSColin Finck     /* Copy the header fields */
688c2c66affSColin Finck     RtlCopyMemory(RelSd,
689*df053d4eSTimo Kreuzer                   SecurityDescriptor,
690c2c66affSColin Finck                   FIELD_OFFSET(SECURITY_DESCRIPTOR_RELATIVE, Owner));
691c2c66affSColin Finck 
692c2c66affSColin Finck     /* Set the current copy pointer */
693c2c66affSColin Finck     Current = (ULONG_PTR)(RelSd + 1);
694c2c66affSColin Finck 
695c2c66affSColin Finck     /* Is there a SACL? */
696c2c66affSColin Finck     if (SaclLength)
697c2c66affSColin Finck     {
698c2c66affSColin Finck         /* Copy it */
699c2c66affSColin Finck         RtlCopyMemory((PVOID)Current, Sacl, SaclLength);
700c2c66affSColin Finck         RelSd->Sacl = (ULONG_PTR)Current - (ULONG_PTR)RelSd;
701c2c66affSColin Finck         Current += SaclLength;
702c2c66affSColin Finck     }
703c2c66affSColin Finck 
704c2c66affSColin Finck     /* Is there a DACL? */
705c2c66affSColin Finck     if (DaclLength)
706c2c66affSColin Finck     {
707c2c66affSColin Finck         /* Copy it */
708c2c66affSColin Finck         RtlCopyMemory((PVOID)Current, Dacl, DaclLength);
709c2c66affSColin Finck         RelSd->Dacl = (ULONG_PTR)Current - (ULONG_PTR)RelSd;
710c2c66affSColin Finck         Current += DaclLength;
711c2c66affSColin Finck     }
712c2c66affSColin Finck 
713c2c66affSColin Finck     /* Is there an owner? */
714c2c66affSColin Finck     if (OwnerLength)
715c2c66affSColin Finck     {
716c2c66affSColin Finck         /* Copy it */
717c2c66affSColin Finck         RtlCopyMemory((PVOID)Current, Owner, OwnerLength);
718c2c66affSColin Finck         RelSd->Owner = (ULONG_PTR)Current - (ULONG_PTR)RelSd;
719c2c66affSColin Finck         Current += OwnerLength;
720c2c66affSColin Finck     }
721c2c66affSColin Finck 
722c2c66affSColin Finck     /* Is there a group? */
723c2c66affSColin Finck     if (GroupLength)
724c2c66affSColin Finck     {
725c2c66affSColin Finck         /* Copy it */
726c2c66affSColin Finck         RtlCopyMemory((PVOID)Current, Group, GroupLength);
727c2c66affSColin Finck         RelSd->Group = (ULONG_PTR)Current - (ULONG_PTR)RelSd;
728c2c66affSColin Finck     }
729c2c66affSColin Finck 
730c2c66affSColin Finck     /* Mark it as relative */
731c2c66affSColin Finck     RelSd->Control |= SE_SELF_RELATIVE;
732c2c66affSColin Finck 
733c2c66affSColin Finck     /* All good */
734c2c66affSColin Finck     return STATUS_SUCCESS;
735c2c66affSColin Finck }
736c2c66affSColin Finck 
737c2c66affSColin Finck /*
738c2c66affSColin Finck  * @implemented
739c2c66affSColin Finck  */
740c2c66affSColin Finck NTSTATUS
741c2c66affSColin Finck NTAPI
RtlSelfRelativeToAbsoluteSD(IN PSECURITY_DESCRIPTOR SelfRelativeSD,OUT PSECURITY_DESCRIPTOR AbsoluteSD,IN PULONG AbsoluteSDSize,IN PACL Dacl,IN PULONG DaclSize,IN PACL Sacl,IN PULONG SaclSize,IN PSID Owner,IN PULONG OwnerSize,IN PSID PrimaryGroup,IN PULONG PrimaryGroupSize)742c2c66affSColin Finck RtlSelfRelativeToAbsoluteSD(IN PSECURITY_DESCRIPTOR SelfRelativeSD,
743c2c66affSColin Finck                             OUT PSECURITY_DESCRIPTOR AbsoluteSD,
744c2c66affSColin Finck                             IN PULONG AbsoluteSDSize,
745c2c66affSColin Finck                             IN PACL Dacl,
746c2c66affSColin Finck                             IN PULONG DaclSize,
747c2c66affSColin Finck                             IN PACL Sacl,
748c2c66affSColin Finck                             IN PULONG SaclSize,
749c2c66affSColin Finck                             IN PSID Owner,
750c2c66affSColin Finck                             IN PULONG OwnerSize,
751c2c66affSColin Finck                             IN PSID PrimaryGroup,
752c2c66affSColin Finck                             IN PULONG PrimaryGroupSize)
753c2c66affSColin Finck {
754c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)AbsoluteSD;
755c2c66affSColin Finck     PISECURITY_DESCRIPTOR RelSd = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
756c2c66affSColin Finck     ULONG OwnerLength, GroupLength, DaclLength, SaclLength;
757c2c66affSColin Finck     PSID pOwner, pGroup;
758c2c66affSColin Finck     PACL pDacl, pSacl;
759c2c66affSColin Finck     PAGED_CODE_RTL();
760c2c66affSColin Finck 
761c2c66affSColin Finck     /* Must be relative, otherwiise fail */
762c2c66affSColin Finck     if (!(RelSd->Control & SE_SELF_RELATIVE)) return STATUS_BAD_DESCRIPTOR_FORMAT;
763c2c66affSColin Finck 
764c2c66affSColin Finck     /* Get all the components */
765c2c66affSColin Finck     RtlpQuerySecurityDescriptor(RelSd,
766c2c66affSColin Finck                                 &pOwner,
767c2c66affSColin Finck                                 &OwnerLength,
768c2c66affSColin Finck                                 &pGroup,
769c2c66affSColin Finck                                 &GroupLength,
770c2c66affSColin Finck                                 &pDacl,
771c2c66affSColin Finck                                 &DaclLength,
772c2c66affSColin Finck                                 &pSacl,
773c2c66affSColin Finck                                 &SaclLength);
774c2c66affSColin Finck 
775c2c66affSColin Finck     /* Fail if there's not enough space */
776c2c66affSColin Finck     if (!(Sd) ||
777c2c66affSColin Finck         (sizeof(SECURITY_DESCRIPTOR) > *AbsoluteSDSize) ||
778c2c66affSColin Finck         (OwnerLength > *OwnerSize) ||
779c2c66affSColin Finck         (GroupLength > *PrimaryGroupSize) ||
780c2c66affSColin Finck         (DaclLength > *DaclSize) ||
781c2c66affSColin Finck         (SaclLength > *SaclSize))
782c2c66affSColin Finck     {
783c2c66affSColin Finck         /* Return how much space is needed for each components */
784c2c66affSColin Finck         *AbsoluteSDSize = sizeof(SECURITY_DESCRIPTOR);
785c2c66affSColin Finck         *OwnerSize = OwnerLength;
786c2c66affSColin Finck         *PrimaryGroupSize = GroupLength;
787c2c66affSColin Finck         *DaclSize = DaclLength;
788c2c66affSColin Finck         *SaclSize = SaclLength;
789c2c66affSColin Finck         return STATUS_BUFFER_TOO_SMALL;
790c2c66affSColin Finck     }
791c2c66affSColin Finck 
792c2c66affSColin Finck     /* Copy the header fields */
793c2c66affSColin Finck     RtlMoveMemory(Sd, RelSd, sizeof(SECURITY_DESCRIPTOR_RELATIVE));
794c2c66affSColin Finck 
795c2c66affSColin Finck     /* Wipe out the pointers and the relative flag */
796c2c66affSColin Finck     Sd->Owner = NULL;
797c2c66affSColin Finck     Sd->Group = NULL;
798c2c66affSColin Finck     Sd->Sacl = NULL;
799c2c66affSColin Finck     Sd->Dacl = NULL;
800c2c66affSColin Finck     Sd->Control &= ~SE_SELF_RELATIVE;
801c2c66affSColin Finck 
802c2c66affSColin Finck     /* Is there an owner? */
803c2c66affSColin Finck     if (pOwner)
804c2c66affSColin Finck     {
805c2c66affSColin Finck         /* Copy it */
806c2c66affSColin Finck         RtlMoveMemory(Owner, pOwner, RtlLengthSid(pOwner));
807c2c66affSColin Finck         Sd->Owner = Owner;
808c2c66affSColin Finck     }
809c2c66affSColin Finck 
810c2c66affSColin Finck     /* Is there a group? */
811c2c66affSColin Finck     if (pGroup)
812c2c66affSColin Finck     {
813c2c66affSColin Finck         /* Copy it */
814c2c66affSColin Finck         RtlMoveMemory(PrimaryGroup, pGroup, RtlLengthSid(pGroup));
815c2c66affSColin Finck         Sd->Group = PrimaryGroup;
816c2c66affSColin Finck     }
817c2c66affSColin Finck 
818c2c66affSColin Finck     /* Is there a DACL? */
819c2c66affSColin Finck     if (pDacl)
820c2c66affSColin Finck     {
821c2c66affSColin Finck         /* Copy it */
822c2c66affSColin Finck         RtlMoveMemory(Dacl, pDacl, pDacl->AclSize);
823c2c66affSColin Finck         Sd->Dacl = Dacl;
824c2c66affSColin Finck     }
825c2c66affSColin Finck 
826c2c66affSColin Finck     /* Is there a SACL? */
827c2c66affSColin Finck     if (pSacl)
828c2c66affSColin Finck     {
829c2c66affSColin Finck         /* Copy it */
830c2c66affSColin Finck         RtlMoveMemory(Sacl, pSacl, pSacl->AclSize);
831c2c66affSColin Finck         Sd->Sacl = Sacl;
832c2c66affSColin Finck     }
833c2c66affSColin Finck 
834c2c66affSColin Finck     /* All good */
835c2c66affSColin Finck     return STATUS_SUCCESS;
836c2c66affSColin Finck }
837c2c66affSColin Finck 
838c2c66affSColin Finck /*
839c2c66affSColin Finck  * @implemented
840c2c66affSColin Finck  */
841c2c66affSColin Finck NTSTATUS
842c2c66affSColin Finck NTAPI
RtlSelfRelativeToAbsoluteSD2(IN OUT PSECURITY_DESCRIPTOR SelfRelativeSD,OUT PULONG BufferSize)843c2c66affSColin Finck RtlSelfRelativeToAbsoluteSD2(IN OUT PSECURITY_DESCRIPTOR SelfRelativeSD,
844c2c66affSColin Finck                              OUT PULONG BufferSize)
845c2c66affSColin Finck {
846c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SelfRelativeSD;
847c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE RelSd = (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSD;
848c2c66affSColin Finck     PVOID DataStart, DataEnd;
849c2c66affSColin Finck     LONG MoveDelta;
850c2c66affSColin Finck     ULONG DataSize, OwnerLength, GroupLength, DaclLength, SaclLength;
851c2c66affSColin Finck     PSID pOwner, pGroup;
852c2c66affSColin Finck     PACL pDacl, pSacl;
853c2c66affSColin Finck     PAGED_CODE_RTL();
854c2c66affSColin Finck 
855c2c66affSColin Finck     /* Need input */
856c2c66affSColin Finck     if (!RelSd) return STATUS_INVALID_PARAMETER_1;
857c2c66affSColin Finck 
858c2c66affSColin Finck     /* Need to know how much space we have */
859c2c66affSColin Finck     if (!BufferSize) return STATUS_INVALID_PARAMETER_2;
860c2c66affSColin Finck 
861c2c66affSColin Finck     /* Input must be relative */
862c2c66affSColin Finck     if (!(RelSd->Control & SE_SELF_RELATIVE)) return STATUS_BAD_DESCRIPTOR_FORMAT;
863c2c66affSColin Finck 
864c2c66affSColin Finck     /* Query all the component sizes */
865c2c66affSColin Finck     RtlpQuerySecurityDescriptor(Sd,
866c2c66affSColin Finck                                 &pOwner,
867c2c66affSColin Finck                                 &OwnerLength,
868c2c66affSColin Finck                                 &pGroup,
869c2c66affSColin Finck                                 &GroupLength,
870c2c66affSColin Finck                                 &pDacl,
871c2c66affSColin Finck                                 &DaclLength,
872c2c66affSColin Finck                                 &pSacl,
873c2c66affSColin Finck                                 &SaclLength);
874c2c66affSColin Finck 
875c2c66affSColin Finck     /*
876c2c66affSColin Finck      * Check if there's a difference in structure layout between relatiev and
877c2c66affSColin Finck      * absolute descriptors. On 32-bit, there won't be, since an offset is the
878c2c66affSColin Finck      * same size as a pointer (32-bit), but on 64-bit, the offsets remain 32-bit
879c2c66affSColin Finck      * as they are not SIZE_T, but ULONG, while the pointers now become 64-bit
880c2c66affSColin Finck      * and thus the structure is different */
881c2c66affSColin Finck     MoveDelta = sizeof(SECURITY_DESCRIPTOR) - sizeof(SECURITY_DESCRIPTOR_RELATIVE);
882c2c66affSColin Finck     if (!MoveDelta)
883c2c66affSColin Finck     {
884c2c66affSColin Finck         /* So on 32-bit, simply clear the flag... */
885c2c66affSColin Finck         Sd->Control &= ~SE_SELF_RELATIVE;
886c2c66affSColin Finck 
887c2c66affSColin Finck         /* Ensure we're *really* on 32-bit */
888c2c66affSColin Finck         ASSERT(sizeof(Sd->Owner) == sizeof(RelSd->Owner));
889c2c66affSColin Finck         ASSERT(sizeof(Sd->Group) == sizeof(RelSd->Group));
890c2c66affSColin Finck         ASSERT(sizeof(Sd->Sacl) == sizeof(RelSd->Sacl));
891c2c66affSColin Finck         ASSERT(sizeof(Sd->Dacl) == sizeof(RelSd->Dacl));
892c2c66affSColin Finck 
893c2c66affSColin Finck         /* And simply set pointers where there used to be offsets */
894c2c66affSColin Finck         Sd->Owner = pOwner;
895c2c66affSColin Finck         Sd->Group = pGroup;
896c2c66affSColin Finck         Sd->Sacl = pSacl;
897c2c66affSColin Finck         Sd->Dacl = pDacl;
898c2c66affSColin Finck         return STATUS_SUCCESS;
899c2c66affSColin Finck     }
900c2c66affSColin Finck 
901c2c66affSColin Finck     /*
902c2c66affSColin Finck      * Calculate the start and end of the data area, we simply just move the
903c2c66affSColin Finck      * data by the difference between the size of the relative and absolute
904c2c66affSColin Finck      * security descriptor structure
905c2c66affSColin Finck      */
906c2c66affSColin Finck     DataStart = pOwner;
907c2c66affSColin Finck     DataEnd = (PVOID)((ULONG_PTR)pOwner + OwnerLength);
908c2c66affSColin Finck 
909c2c66affSColin Finck     /* Is there a group? */
910c2c66affSColin Finck     if (pGroup)
911c2c66affSColin Finck     {
912c2c66affSColin Finck         /* Is the group higher than where we started? */
913c2c66affSColin Finck         if (((ULONG_PTR)pGroup < (ULONG_PTR)DataStart) || !DataStart)
914c2c66affSColin Finck         {
915c2c66affSColin Finck             /* Update the start pointer */
916c2c66affSColin Finck             DataStart = pGroup;
917c2c66affSColin Finck         }
918c2c66affSColin Finck 
919c2c66affSColin Finck         /* Is the group beyond where we ended? */
920c2c66affSColin Finck         if (((ULONG_PTR)pGroup + GroupLength > (ULONG_PTR)DataEnd) || !DataEnd)
921c2c66affSColin Finck         {
922c2c66affSColin Finck             /* Update the end pointer */
923c2c66affSColin Finck             DataEnd = (PVOID)((ULONG_PTR)pGroup + GroupLength);
924c2c66affSColin Finck         }
925c2c66affSColin Finck     }
926c2c66affSColin Finck 
927c2c66affSColin Finck     /* Is there a DACL? */
928c2c66affSColin Finck     if (pDacl)
929c2c66affSColin Finck     {
930c2c66affSColin Finck         /* Is the DACL higher than where we started? */
931c2c66affSColin Finck         if (((ULONG_PTR)pDacl < (ULONG_PTR)DataStart) || !DataStart)
932c2c66affSColin Finck         {
933c2c66affSColin Finck             /* Update the start pointer */
934c2c66affSColin Finck             DataStart = pDacl;
935c2c66affSColin Finck         }
936c2c66affSColin Finck 
937c2c66affSColin Finck         /* Is the DACL beyond where we ended? */
938c2c66affSColin Finck         if (((ULONG_PTR)pDacl + DaclLength > (ULONG_PTR)DataEnd) || !DataEnd)
939c2c66affSColin Finck         {
940c2c66affSColin Finck             /* Update the end pointer */
941c2c66affSColin Finck             DataEnd = (PVOID)((ULONG_PTR)pDacl + DaclLength);
942c2c66affSColin Finck         }
943c2c66affSColin Finck     }
944c2c66affSColin Finck 
945c2c66affSColin Finck     /* Is there a SACL? */
946c2c66affSColin Finck     if (pSacl)
947c2c66affSColin Finck     {
948c2c66affSColin Finck         /* Is the SACL higher than where we started? */
949c2c66affSColin Finck         if (((ULONG_PTR)pSacl < (ULONG_PTR)DataStart) || !DataStart)
950c2c66affSColin Finck         {
951c2c66affSColin Finck             /* Update the start pointer */
952c2c66affSColin Finck             DataStart = pSacl;
953c2c66affSColin Finck         }
954c2c66affSColin Finck 
955c2c66affSColin Finck         /* Is the SACL beyond where we ended? */
956c2c66affSColin Finck         if (((ULONG_PTR)pSacl + SaclLength > (ULONG_PTR)DataEnd) || !DataEnd)
957c2c66affSColin Finck         {
958c2c66affSColin Finck             /* Update the end pointer */
959c2c66affSColin Finck             DataEnd = (PVOID)((ULONG_PTR)pSacl + SaclLength);
960c2c66affSColin Finck         }
961c2c66affSColin Finck     }
962c2c66affSColin Finck 
963c2c66affSColin Finck     /* Sanity check */
964c2c66affSColin Finck     ASSERT((ULONG_PTR)DataEnd >= (ULONG_PTR)DataStart);
965c2c66affSColin Finck 
966c2c66affSColin Finck     /* Now compute the difference between relative and absolute */
967c2c66affSColin Finck     DataSize = (ULONG)((ULONG_PTR)DataEnd - (ULONG_PTR)DataStart);
968c2c66affSColin Finck 
969c2c66affSColin Finck     /* Is the new buffer large enough for this difference? */
970c2c66affSColin Finck     if (*BufferSize < sizeof(SECURITY_DESCRIPTOR) + DataSize)
971c2c66affSColin Finck     {
972c2c66affSColin Finck         /* Nope, bail out */
973c2c66affSColin Finck         *BufferSize = sizeof(SECURITY_DESCRIPTOR) + DataSize;
974c2c66affSColin Finck         return STATUS_BUFFER_TOO_SMALL;
975c2c66affSColin Finck     }
976c2c66affSColin Finck 
977c2c66affSColin Finck     /* Is there anything actually to copy? */
978c2c66affSColin Finck     if (DataSize)
979c2c66affSColin Finck     {
980c2c66affSColin Finck         /*
981c2c66affSColin Finck          * There must be at least one SID or ACL in the security descriptor!
982c2c66affSColin Finck          * Also the data area must be located somewhere after the end of the
983c2c66affSColin Finck          * SECURITY_DESCRIPTOR_RELATIVE structure
984c2c66affSColin Finck          */
985c2c66affSColin Finck         ASSERT(DataStart != NULL);
986c2c66affSColin Finck         ASSERT((ULONG_PTR)DataStart >= (ULONG_PTR)(RelSd + 1));
987c2c66affSColin Finck 
988c2c66affSColin Finck         /* It's time to move the data */
989c2c66affSColin Finck         RtlMoveMemory((PVOID)(Sd + 1),
990c2c66affSColin Finck                       DataStart,
991c2c66affSColin Finck                       DataSize);
992c2c66affSColin Finck     }
993c2c66affSColin Finck 
994c2c66affSColin Finck     /* Is there an owner? */
995c2c66affSColin Finck     if (pOwner)
996c2c66affSColin Finck     {
997c2c66affSColin Finck         /* Set the pointer to the relative position */
998c2c66affSColin Finck         Sd->Owner = (PSID)((LONG_PTR)pOwner + MoveDelta);
999c2c66affSColin Finck     }
1000c2c66affSColin Finck     else
1001c2c66affSColin Finck     {
1002c2c66affSColin Finck         /* No owner, clear the pointer */
1003c2c66affSColin Finck         Sd->Owner = NULL;
1004c2c66affSColin Finck     }
1005c2c66affSColin Finck 
1006c2c66affSColin Finck     /* Is there a group */
1007c2c66affSColin Finck     if (pGroup)
1008c2c66affSColin Finck     {
1009c2c66affSColin Finck         /* Set the pointer to the relative position */
1010c2c66affSColin Finck         Sd->Group = (PSID)((LONG_PTR)pGroup + MoveDelta);
1011c2c66affSColin Finck     }
1012c2c66affSColin Finck     else
1013c2c66affSColin Finck     {
1014c2c66affSColin Finck         /* No group, clear the pointer */
1015c2c66affSColin Finck         Sd->Group = NULL;
1016c2c66affSColin Finck     }
1017c2c66affSColin Finck 
1018c2c66affSColin Finck     /* Is there a SACL? */
1019c2c66affSColin Finck     if (pSacl)
1020c2c66affSColin Finck     {
1021c2c66affSColin Finck         /* Set the pointer to the relative position */
1022c2c66affSColin Finck         Sd->Sacl = (PACL)((LONG_PTR)pSacl + MoveDelta);
1023c2c66affSColin Finck     }
1024c2c66affSColin Finck     else
1025c2c66affSColin Finck     {
1026c2c66affSColin Finck         /* No SACL, clear the pointer */
1027c2c66affSColin Finck         Sd->Sacl = NULL;
1028c2c66affSColin Finck     }
1029c2c66affSColin Finck 
1030c2c66affSColin Finck     /* Is there a DACL? */
1031c2c66affSColin Finck     if (pDacl)
1032c2c66affSColin Finck     {
1033c2c66affSColin Finck         /* Set the pointer to the relative position */
1034c2c66affSColin Finck         Sd->Dacl = (PACL)((LONG_PTR)pDacl + MoveDelta);
1035c2c66affSColin Finck     }
1036c2c66affSColin Finck     else
1037c2c66affSColin Finck     {
1038c2c66affSColin Finck         /* No DACL, clear the pointer */
1039c2c66affSColin Finck         Sd->Dacl = NULL;
1040c2c66affSColin Finck     }
1041c2c66affSColin Finck 
1042c2c66affSColin Finck     /* Clear the self-relative flag */
1043c2c66affSColin Finck     Sd->Control &= ~SE_SELF_RELATIVE;
1044c2c66affSColin Finck 
1045c2c66affSColin Finck     /* All good */
1046c2c66affSColin Finck     return STATUS_SUCCESS;
1047c2c66affSColin Finck }
1048c2c66affSColin Finck 
1049c2c66affSColin Finck /*
1050c2c66affSColin Finck  * @implemented
1051c2c66affSColin Finck  */
1052c2c66affSColin Finck BOOLEAN
1053c2c66affSColin Finck NTAPI
RtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)1054c2c66affSColin Finck RtlValidSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1055c2c66affSColin Finck {
1056c2c66affSColin Finck     PISECURITY_DESCRIPTOR Sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
1057c2c66affSColin Finck     PSID Owner, Group;
1058c2c66affSColin Finck     PACL Sacl, Dacl;
1059c2c66affSColin Finck     PAGED_CODE_RTL();
1060c2c66affSColin Finck 
1061c2c66affSColin Finck     _SEH2_TRY
1062c2c66affSColin Finck     {
1063c2c66affSColin Finck         /* Fail on bad revisions */
1064c2c66affSColin Finck         if (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) _SEH2_YIELD(return FALSE);
1065c2c66affSColin Finck 
1066c2c66affSColin Finck         /* Owner SID must be valid if present */
1067c2c66affSColin Finck         Owner = SepGetOwnerFromDescriptor(Sd);
1068c2c66affSColin Finck         if ((Owner) && (!RtlValidSid(Owner))) _SEH2_YIELD(return FALSE);
1069c2c66affSColin Finck 
1070c2c66affSColin Finck         /* Group SID must be valid if present */
1071c2c66affSColin Finck         Group = SepGetGroupFromDescriptor(Sd);
1072c2c66affSColin Finck         if ((Group) && (!RtlValidSid(Group))) _SEH2_YIELD(return FALSE);
1073c2c66affSColin Finck 
1074c2c66affSColin Finck         /* DACL must be valid if present */
1075c2c66affSColin Finck         Dacl = SepGetDaclFromDescriptor(Sd);
1076c2c66affSColin Finck         if ((Dacl) && (!RtlValidAcl(Dacl))) _SEH2_YIELD(return FALSE);
1077c2c66affSColin Finck 
1078c2c66affSColin Finck         /* SACL must be valid if present */
1079c2c66affSColin Finck         Sacl = SepGetSaclFromDescriptor(Sd);
1080c2c66affSColin Finck         if ((Sacl) && (!RtlValidAcl(Sacl))) _SEH2_YIELD(return FALSE);
1081c2c66affSColin Finck     }
1082c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1083c2c66affSColin Finck     {
1084c2c66affSColin Finck         /* Access fault, bail out */
1085c2c66affSColin Finck         _SEH2_YIELD(return FALSE);
1086c2c66affSColin Finck     }
1087c2c66affSColin Finck     _SEH2_END;
1088c2c66affSColin Finck 
1089c2c66affSColin Finck     /* All good */
1090c2c66affSColin Finck     return TRUE;
1091c2c66affSColin Finck }
1092c2c66affSColin Finck 
1093c2c66affSColin Finck /*
1094c2c66affSColin Finck  * @implemented
1095c2c66affSColin Finck  */
1096c2c66affSColin Finck BOOLEAN
1097c2c66affSColin Finck NTAPI
RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInput,IN ULONG SecurityDescriptorLength,IN SECURITY_INFORMATION RequiredInformation)1098c2c66affSColin Finck RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInput,
1099c2c66affSColin Finck                                    IN ULONG SecurityDescriptorLength,
1100c2c66affSColin Finck                                    IN SECURITY_INFORMATION RequiredInformation)
1101c2c66affSColin Finck {
1102c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE Sd = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptorInput;
1103c2c66affSColin Finck     PSID Owner, Group;
1104c2c66affSColin Finck     PACL Dacl, Sacl;
1105c2c66affSColin Finck     ULONG Length;
1106c2c66affSColin Finck     PAGED_CODE_RTL();
1107c2c66affSColin Finck 
1108c2c66affSColin Finck     /* Note that Windows allows no DACL/SACL even if RequiredInfo wants it */
1109c2c66affSColin Finck 
1110c2c66affSColin Finck     /* Do we have enough space, is the revision vaild, and is this SD relative? */
1111c2c66affSColin Finck     if ((SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) ||
1112c2c66affSColin Finck         (Sd->Revision != SECURITY_DESCRIPTOR_REVISION) ||
1113c2c66affSColin Finck         !(Sd->Control & SE_SELF_RELATIVE))
1114c2c66affSColin Finck     {
1115c2c66affSColin Finck         /* Nope, bail out */
1116c2c66affSColin Finck         return FALSE;
1117c2c66affSColin Finck     }
1118c2c66affSColin Finck 
1119c2c66affSColin Finck     /* Is there an owner? */
1120c2c66affSColin Finck     if (Sd->Owner)
1121c2c66affSColin Finck     {
1122c2c66affSColin Finck         /* Try to access it */
1123c2c66affSColin Finck         if (!RtlpValidateSDOffsetAndSize(Sd->Owner,
1124c2c66affSColin Finck                                          SecurityDescriptorLength,
1125c2c66affSColin Finck                                          sizeof(SID),
1126c2c66affSColin Finck                                          &Length))
1127c2c66affSColin Finck         {
1128c2c66affSColin Finck             /* It's beyond the buffer, fail */
1129c2c66affSColin Finck             return FALSE;
1130c2c66affSColin Finck         }
1131c2c66affSColin Finck 
1132c2c66affSColin Finck         /* Read the owner, check if it's valid and if the buffer contains it */
1133c2c66affSColin Finck         Owner = (PSID)((ULONG_PTR)Sd->Owner + (ULONG_PTR)Sd);
1134c2c66affSColin Finck         if (!RtlValidSid(Owner) || (Length < RtlLengthSid(Owner))) return FALSE;
1135c2c66affSColin Finck     }
1136c2c66affSColin Finck     else if (RequiredInformation & OWNER_SECURITY_INFORMATION)
1137c2c66affSColin Finck     {
1138c2c66affSColin Finck         /* No owner but the caller expects one, fail */
1139c2c66affSColin Finck         return FALSE;
1140c2c66affSColin Finck     }
1141c2c66affSColin Finck 
1142c2c66affSColin Finck     /* Is there a group? */
1143c2c66affSColin Finck     if (Sd->Group)
1144c2c66affSColin Finck     {
1145c2c66affSColin Finck         /* Try to access it */
1146c2c66affSColin Finck         if (!RtlpValidateSDOffsetAndSize(Sd->Group,
1147c2c66affSColin Finck                                          SecurityDescriptorLength,
1148c2c66affSColin Finck                                          sizeof(SID),
1149c2c66affSColin Finck                                          &Length))
1150c2c66affSColin Finck         {
1151c2c66affSColin Finck             /* It's beyond the buffer, fail */
1152c2c66affSColin Finck             return FALSE;
1153c2c66affSColin Finck         }
1154c2c66affSColin Finck 
1155c2c66affSColin Finck         /* Read the group, check if it's valid and if the buffer contains it */
1156c2c66affSColin Finck         Group = (PSID)((ULONG_PTR)Sd->Group + (ULONG_PTR)Sd);
1157c2c66affSColin Finck         if (!RtlValidSid(Group) || (Length < RtlLengthSid(Group))) return FALSE;
1158c2c66affSColin Finck     }
1159c2c66affSColin Finck     else if (RequiredInformation & GROUP_SECURITY_INFORMATION)
1160c2c66affSColin Finck     {
1161c2c66affSColin Finck         /* No group, but the caller expects one, fail */
1162c2c66affSColin Finck         return FALSE;
1163c2c66affSColin Finck     }
1164c2c66affSColin Finck 
1165c2c66affSColin Finck     /* Is there a DACL? */
1166c2c66affSColin Finck     if ((Sd->Control & SE_DACL_PRESENT) == SE_DACL_PRESENT)
1167c2c66affSColin Finck     {
1168c2c66affSColin Finck         /* Try to access it */
1169c2c66affSColin Finck         if (!RtlpValidateSDOffsetAndSize(Sd->Dacl,
1170c2c66affSColin Finck                                          SecurityDescriptorLength,
1171c2c66affSColin Finck                                          sizeof(ACL),
1172c2c66affSColin Finck                                          &Length))
1173c2c66affSColin Finck         {
1174c2c66affSColin Finck             /* It's beyond the buffer, fail */
1175c2c66affSColin Finck             return FALSE;
1176c2c66affSColin Finck         }
1177c2c66affSColin Finck 
1178c2c66affSColin Finck         /* Read the DACL, check if it's valid and if the buffer contains it */
1179c2c66affSColin Finck         Dacl = (PSID)((ULONG_PTR)Sd->Dacl + (ULONG_PTR)Sd);
1180c2c66affSColin Finck         if (!(RtlValidAcl(Dacl)) || (Length < Dacl->AclSize)) return FALSE;
1181c2c66affSColin Finck     }
1182c2c66affSColin Finck 
1183c2c66affSColin Finck     /* Is there a SACL? */
1184c2c66affSColin Finck     if ((Sd->Control & SE_SACL_PRESENT) == SE_SACL_PRESENT)
1185c2c66affSColin Finck     {
1186c2c66affSColin Finck         /* Try to access it */
1187c2c66affSColin Finck         if (!RtlpValidateSDOffsetAndSize(Sd->Sacl,
1188c2c66affSColin Finck                                          SecurityDescriptorLength,
1189c2c66affSColin Finck                                          sizeof(ACL),
1190c2c66affSColin Finck                                          &Length))
1191c2c66affSColin Finck         {
1192c2c66affSColin Finck             /* It's beyond the buffer, fail */
1193c2c66affSColin Finck             return FALSE;
1194c2c66affSColin Finck         }
1195c2c66affSColin Finck 
1196c2c66affSColin Finck         /* Read the SACL, check if it's valid and if the buffer contains it */
1197c2c66affSColin Finck         Sacl = (PSID)((ULONG_PTR)Sd->Sacl + (ULONG_PTR)Sd);
1198c2c66affSColin Finck         if (!(RtlValidAcl(Sacl)) || (Length < Sacl->AclSize)) return FALSE;
1199c2c66affSColin Finck     }
1200c2c66affSColin Finck 
1201c2c66affSColin Finck     /* All good */
1202c2c66affSColin Finck     return TRUE;
1203c2c66affSColin Finck }
1204c2c66affSColin Finck 
1205c2c66affSColin Finck /* EOF */
1206