xref: /reactos/ntoskrnl/se/sd.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3*c2c66affSColin Finck  * PROJECT:         ReactOS kernel
4*c2c66affSColin Finck  * FILE:            ntoskrnl/se/sd.c
5*c2c66affSColin Finck  * PURPOSE:         Security manager
6*c2c66affSColin Finck  *
7*c2c66affSColin Finck  * PROGRAMMERS:     David Welch <welch@cwcom.net>
8*c2c66affSColin Finck  */
9*c2c66affSColin Finck 
10*c2c66affSColin Finck /* INCLUDES *******************************************************************/
11*c2c66affSColin Finck 
12*c2c66affSColin Finck #include <ntoskrnl.h>
13*c2c66affSColin Finck #define NDEBUG
14*c2c66affSColin Finck #include <debug.h>
15*c2c66affSColin Finck 
16*c2c66affSColin Finck #if defined (ALLOC_PRAGMA)
17*c2c66affSColin Finck #pragma alloc_text(INIT, SepInitSDs)
18*c2c66affSColin Finck #endif
19*c2c66affSColin Finck 
20*c2c66affSColin Finck /* GLOBALS ********************************************************************/
21*c2c66affSColin Finck 
22*c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL;
23*c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL;
24*c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicOpenSd = NULL;
25*c2c66affSColin Finck PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL;
26*c2c66affSColin Finck PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL;
27*c2c66affSColin Finck PSECURITY_DESCRIPTOR SeUnrestrictedSd = NULL;
28*c2c66affSColin Finck 
29*c2c66affSColin Finck /* PRIVATE FUNCTIONS **********************************************************/
30*c2c66affSColin Finck 
31*c2c66affSColin Finck BOOLEAN
32*c2c66affSColin Finck INIT_FUNCTION
33*c2c66affSColin Finck NTAPI
34*c2c66affSColin Finck SepInitSDs(VOID)
35*c2c66affSColin Finck {
36*c2c66affSColin Finck     /* Create PublicDefaultSd */
37*c2c66affSColin Finck     SePublicDefaultSd = ExAllocatePoolWithTag(PagedPool,
38*c2c66affSColin Finck                                               sizeof(SECURITY_DESCRIPTOR), TAG_SD);
39*c2c66affSColin Finck     if (SePublicDefaultSd == NULL)
40*c2c66affSColin Finck         return FALSE;
41*c2c66affSColin Finck 
42*c2c66affSColin Finck     RtlCreateSecurityDescriptor(SePublicDefaultSd,
43*c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
44*c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SePublicDefaultSd,
45*c2c66affSColin Finck                                  TRUE,
46*c2c66affSColin Finck                                  SePublicDefaultDacl,
47*c2c66affSColin Finck                                  FALSE);
48*c2c66affSColin Finck 
49*c2c66affSColin Finck     /* Create PublicDefaultUnrestrictedSd */
50*c2c66affSColin Finck     SePublicDefaultUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
51*c2c66affSColin Finck                                                           sizeof(SECURITY_DESCRIPTOR), TAG_SD);
52*c2c66affSColin Finck     if (SePublicDefaultUnrestrictedSd == NULL)
53*c2c66affSColin Finck         return FALSE;
54*c2c66affSColin Finck 
55*c2c66affSColin Finck     RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd,
56*c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
57*c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd,
58*c2c66affSColin Finck                                  TRUE,
59*c2c66affSColin Finck                                  SePublicDefaultUnrestrictedDacl,
60*c2c66affSColin Finck                                  FALSE);
61*c2c66affSColin Finck 
62*c2c66affSColin Finck     /* Create PublicOpenSd */
63*c2c66affSColin Finck     SePublicOpenSd = ExAllocatePoolWithTag(PagedPool,
64*c2c66affSColin Finck                                            sizeof(SECURITY_DESCRIPTOR), TAG_SD);
65*c2c66affSColin Finck     if (SePublicOpenSd == NULL)
66*c2c66affSColin Finck         return FALSE;
67*c2c66affSColin Finck 
68*c2c66affSColin Finck     RtlCreateSecurityDescriptor(SePublicOpenSd,
69*c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
70*c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SePublicOpenSd,
71*c2c66affSColin Finck                                  TRUE,
72*c2c66affSColin Finck                                  SePublicOpenDacl,
73*c2c66affSColin Finck                                  FALSE);
74*c2c66affSColin Finck 
75*c2c66affSColin Finck     /* Create PublicOpenUnrestrictedSd */
76*c2c66affSColin Finck     SePublicOpenUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
77*c2c66affSColin Finck                                                        sizeof(SECURITY_DESCRIPTOR), TAG_SD);
78*c2c66affSColin Finck     if (SePublicOpenUnrestrictedSd == NULL)
79*c2c66affSColin Finck         return FALSE;
80*c2c66affSColin Finck 
81*c2c66affSColin Finck     RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd,
82*c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
83*c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd,
84*c2c66affSColin Finck                                  TRUE,
85*c2c66affSColin Finck                                  SePublicOpenUnrestrictedDacl,
86*c2c66affSColin Finck                                  FALSE);
87*c2c66affSColin Finck 
88*c2c66affSColin Finck     /* Create SystemDefaultSd */
89*c2c66affSColin Finck     SeSystemDefaultSd = ExAllocatePoolWithTag(PagedPool,
90*c2c66affSColin Finck                                               sizeof(SECURITY_DESCRIPTOR), TAG_SD);
91*c2c66affSColin Finck     if (SeSystemDefaultSd == NULL)
92*c2c66affSColin Finck         return FALSE;
93*c2c66affSColin Finck 
94*c2c66affSColin Finck     RtlCreateSecurityDescriptor(SeSystemDefaultSd,
95*c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
96*c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SeSystemDefaultSd,
97*c2c66affSColin Finck                                  TRUE,
98*c2c66affSColin Finck                                  SeSystemDefaultDacl,
99*c2c66affSColin Finck                                  FALSE);
100*c2c66affSColin Finck 
101*c2c66affSColin Finck     /* Create UnrestrictedSd */
102*c2c66affSColin Finck     SeUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
103*c2c66affSColin Finck                                              sizeof(SECURITY_DESCRIPTOR), TAG_SD);
104*c2c66affSColin Finck     if (SeUnrestrictedSd == NULL)
105*c2c66affSColin Finck         return FALSE;
106*c2c66affSColin Finck 
107*c2c66affSColin Finck     RtlCreateSecurityDescriptor(SeUnrestrictedSd,
108*c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION);
109*c2c66affSColin Finck     RtlSetDaclSecurityDescriptor(SeUnrestrictedSd,
110*c2c66affSColin Finck                                  TRUE,
111*c2c66affSColin Finck                                  SeUnrestrictedDacl,
112*c2c66affSColin Finck                                  FALSE);
113*c2c66affSColin Finck 
114*c2c66affSColin Finck     return TRUE;
115*c2c66affSColin Finck }
116*c2c66affSColin Finck 
117*c2c66affSColin Finck NTSTATUS
118*c2c66affSColin Finck NTAPI
119*c2c66affSColin Finck SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
120*c2c66affSColin Finck                              PISECURITY_DESCRIPTOR SecurityDescriptor,
121*c2c66affSColin Finck                              PULONG BufferLength)
122*c2c66affSColin Finck {
123*c2c66affSColin Finck     ULONG Current;
124*c2c66affSColin Finck     ULONG SidSize;
125*c2c66affSColin Finck     ULONG SdSize;
126*c2c66affSColin Finck     NTSTATUS Status;
127*c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
128*c2c66affSColin Finck 
129*c2c66affSColin Finck     DPRINT("SeSetWorldSecurityDescriptor() called\n");
130*c2c66affSColin Finck 
131*c2c66affSColin Finck     if (SecurityInformation == 0)
132*c2c66affSColin Finck     {
133*c2c66affSColin Finck         return STATUS_ACCESS_DENIED;
134*c2c66affSColin Finck     }
135*c2c66affSColin Finck 
136*c2c66affSColin Finck     /* calculate the minimum size of the buffer */
137*c2c66affSColin Finck     SidSize = RtlLengthSid(SeWorldSid);
138*c2c66affSColin Finck     SdSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
139*c2c66affSColin Finck     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
140*c2c66affSColin Finck         SdSize += SidSize;
141*c2c66affSColin Finck     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
142*c2c66affSColin Finck         SdSize += SidSize;
143*c2c66affSColin Finck     if (SecurityInformation & DACL_SECURITY_INFORMATION)
144*c2c66affSColin Finck     {
145*c2c66affSColin Finck         SdSize += sizeof(ACL) + sizeof(ACE) + SidSize;
146*c2c66affSColin Finck     }
147*c2c66affSColin Finck 
148*c2c66affSColin Finck     if (*BufferLength < SdSize)
149*c2c66affSColin Finck     {
150*c2c66affSColin Finck         *BufferLength = SdSize;
151*c2c66affSColin Finck         return STATUS_BUFFER_TOO_SMALL;
152*c2c66affSColin Finck     }
153*c2c66affSColin Finck 
154*c2c66affSColin Finck     *BufferLength = SdSize;
155*c2c66affSColin Finck 
156*c2c66affSColin Finck     Status = RtlCreateSecurityDescriptorRelative(SdRel,
157*c2c66affSColin Finck                                                  SECURITY_DESCRIPTOR_REVISION);
158*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
159*c2c66affSColin Finck     {
160*c2c66affSColin Finck         return Status;
161*c2c66affSColin Finck     }
162*c2c66affSColin Finck 
163*c2c66affSColin Finck     Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
164*c2c66affSColin Finck 
165*c2c66affSColin Finck     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
166*c2c66affSColin Finck     {
167*c2c66affSColin Finck         RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize);
168*c2c66affSColin Finck         SdRel->Owner = Current;
169*c2c66affSColin Finck         Current += SidSize;
170*c2c66affSColin Finck     }
171*c2c66affSColin Finck 
172*c2c66affSColin Finck     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
173*c2c66affSColin Finck     {
174*c2c66affSColin Finck         RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize);
175*c2c66affSColin Finck         SdRel->Group = Current;
176*c2c66affSColin Finck         Current += SidSize;
177*c2c66affSColin Finck     }
178*c2c66affSColin Finck 
179*c2c66affSColin Finck     if (SecurityInformation & DACL_SECURITY_INFORMATION)
180*c2c66affSColin Finck     {
181*c2c66affSColin Finck         PACL Dacl = (PACL)((PUCHAR)SdRel + Current);
182*c2c66affSColin Finck         SdRel->Control |= SE_DACL_PRESENT;
183*c2c66affSColin Finck 
184*c2c66affSColin Finck         Status = RtlCreateAcl(Dacl,
185*c2c66affSColin Finck                               sizeof(ACL) + sizeof(ACE) + SidSize,
186*c2c66affSColin Finck                               ACL_REVISION);
187*c2c66affSColin Finck         if (!NT_SUCCESS(Status))
188*c2c66affSColin Finck             return Status;
189*c2c66affSColin Finck 
190*c2c66affSColin Finck         Status = RtlAddAccessAllowedAce(Dacl,
191*c2c66affSColin Finck                                         ACL_REVISION,
192*c2c66affSColin Finck                                         GENERIC_ALL,
193*c2c66affSColin Finck                                         SeWorldSid);
194*c2c66affSColin Finck         if (!NT_SUCCESS(Status))
195*c2c66affSColin Finck             return Status;
196*c2c66affSColin Finck 
197*c2c66affSColin Finck         SdRel->Dacl = Current;
198*c2c66affSColin Finck     }
199*c2c66affSColin Finck 
200*c2c66affSColin Finck     if (SecurityInformation & SACL_SECURITY_INFORMATION)
201*c2c66affSColin Finck     {
202*c2c66affSColin Finck         /* FIXME - SdRel->Control |= SE_SACL_PRESENT; */
203*c2c66affSColin Finck     }
204*c2c66affSColin Finck 
205*c2c66affSColin Finck     return STATUS_SUCCESS;
206*c2c66affSColin Finck }
207*c2c66affSColin Finck 
208*c2c66affSColin Finck 
209*c2c66affSColin Finck NTSTATUS
210*c2c66affSColin Finck NTAPI
211*c2c66affSColin Finck SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
212*c2c66affSColin Finck                                    IN KPROCESSOR_MODE AccessMode,
213*c2c66affSColin Finck                                    IN POOL_TYPE PoolType,
214*c2c66affSColin Finck                                    IN BOOLEAN CaptureIfKernel,
215*c2c66affSColin Finck                                    OUT PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService,
216*c2c66affSColin Finck                                    OUT PBOOLEAN Present)
217*c2c66affSColin Finck {
218*c2c66affSColin Finck     PSECURITY_QUALITY_OF_SERVICE CapturedQos;
219*c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
220*c2c66affSColin Finck 
221*c2c66affSColin Finck     PAGED_CODE();
222*c2c66affSColin Finck 
223*c2c66affSColin Finck     ASSERT(CapturedSecurityQualityOfService);
224*c2c66affSColin Finck     ASSERT(Present);
225*c2c66affSColin Finck 
226*c2c66affSColin Finck     if (ObjectAttributes != NULL)
227*c2c66affSColin Finck     {
228*c2c66affSColin Finck         if (AccessMode != KernelMode)
229*c2c66affSColin Finck         {
230*c2c66affSColin Finck             SECURITY_QUALITY_OF_SERVICE SafeQos;
231*c2c66affSColin Finck 
232*c2c66affSColin Finck             _SEH2_TRY
233*c2c66affSColin Finck             {
234*c2c66affSColin Finck                 ProbeForRead(ObjectAttributes,
235*c2c66affSColin Finck                              sizeof(OBJECT_ATTRIBUTES),
236*c2c66affSColin Finck                              sizeof(ULONG));
237*c2c66affSColin Finck                 if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
238*c2c66affSColin Finck                 {
239*c2c66affSColin Finck                     if (ObjectAttributes->SecurityQualityOfService != NULL)
240*c2c66affSColin Finck                     {
241*c2c66affSColin Finck                         ProbeForRead(ObjectAttributes->SecurityQualityOfService,
242*c2c66affSColin Finck                                      sizeof(SECURITY_QUALITY_OF_SERVICE),
243*c2c66affSColin Finck                                      sizeof(ULONG));
244*c2c66affSColin Finck 
245*c2c66affSColin Finck                         if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
246*c2c66affSColin Finck                             sizeof(SECURITY_QUALITY_OF_SERVICE))
247*c2c66affSColin Finck                         {
248*c2c66affSColin Finck                             /*
249*c2c66affSColin Finck                              * Don't allocate memory here because ExAllocate should bugcheck
250*c2c66affSColin Finck                              * the system if it's buggy, SEH would catch that! So make a local
251*c2c66affSColin Finck                              * copy of the qos structure.
252*c2c66affSColin Finck                              */
253*c2c66affSColin Finck                             RtlCopyMemory(&SafeQos,
254*c2c66affSColin Finck                                           ObjectAttributes->SecurityQualityOfService,
255*c2c66affSColin Finck                                           sizeof(SECURITY_QUALITY_OF_SERVICE));
256*c2c66affSColin Finck                             *Present = TRUE;
257*c2c66affSColin Finck                         }
258*c2c66affSColin Finck                         else
259*c2c66affSColin Finck                         {
260*c2c66affSColin Finck                             Status = STATUS_INVALID_PARAMETER;
261*c2c66affSColin Finck                         }
262*c2c66affSColin Finck                     }
263*c2c66affSColin Finck                     else
264*c2c66affSColin Finck                     {
265*c2c66affSColin Finck                         *CapturedSecurityQualityOfService = NULL;
266*c2c66affSColin Finck                         *Present = FALSE;
267*c2c66affSColin Finck                     }
268*c2c66affSColin Finck                 }
269*c2c66affSColin Finck                 else
270*c2c66affSColin Finck                 {
271*c2c66affSColin Finck                     Status = STATUS_INVALID_PARAMETER;
272*c2c66affSColin Finck                 }
273*c2c66affSColin Finck             }
274*c2c66affSColin Finck             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
275*c2c66affSColin Finck             {
276*c2c66affSColin Finck                 Status = _SEH2_GetExceptionCode();
277*c2c66affSColin Finck             }
278*c2c66affSColin Finck             _SEH2_END;
279*c2c66affSColin Finck 
280*c2c66affSColin Finck             if (NT_SUCCESS(Status))
281*c2c66affSColin Finck             {
282*c2c66affSColin Finck                 if (*Present)
283*c2c66affSColin Finck                 {
284*c2c66affSColin Finck                     CapturedQos = ExAllocatePoolWithTag(PoolType,
285*c2c66affSColin Finck                                                         sizeof(SECURITY_QUALITY_OF_SERVICE),
286*c2c66affSColin Finck                                                         TAG_QOS);
287*c2c66affSColin Finck                     if (CapturedQos != NULL)
288*c2c66affSColin Finck                     {
289*c2c66affSColin Finck                         RtlCopyMemory(CapturedQos,
290*c2c66affSColin Finck                                       &SafeQos,
291*c2c66affSColin Finck                                       sizeof(SECURITY_QUALITY_OF_SERVICE));
292*c2c66affSColin Finck                         *CapturedSecurityQualityOfService = CapturedQos;
293*c2c66affSColin Finck                     }
294*c2c66affSColin Finck                     else
295*c2c66affSColin Finck                     {
296*c2c66affSColin Finck                         Status = STATUS_INSUFFICIENT_RESOURCES;
297*c2c66affSColin Finck                     }
298*c2c66affSColin Finck                 }
299*c2c66affSColin Finck                 else
300*c2c66affSColin Finck                 {
301*c2c66affSColin Finck                     *CapturedSecurityQualityOfService = NULL;
302*c2c66affSColin Finck                 }
303*c2c66affSColin Finck             }
304*c2c66affSColin Finck         }
305*c2c66affSColin Finck         else
306*c2c66affSColin Finck         {
307*c2c66affSColin Finck             if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
308*c2c66affSColin Finck             {
309*c2c66affSColin Finck                 if (CaptureIfKernel)
310*c2c66affSColin Finck                 {
311*c2c66affSColin Finck                     if (ObjectAttributes->SecurityQualityOfService != NULL)
312*c2c66affSColin Finck                     {
313*c2c66affSColin Finck                         if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
314*c2c66affSColin Finck                             sizeof(SECURITY_QUALITY_OF_SERVICE))
315*c2c66affSColin Finck                         {
316*c2c66affSColin Finck                             CapturedQos = ExAllocatePoolWithTag(PoolType,
317*c2c66affSColin Finck                                                                 sizeof(SECURITY_QUALITY_OF_SERVICE),
318*c2c66affSColin Finck                                                                 TAG_QOS);
319*c2c66affSColin Finck                             if (CapturedQos != NULL)
320*c2c66affSColin Finck                             {
321*c2c66affSColin Finck                                 RtlCopyMemory(CapturedQos,
322*c2c66affSColin Finck                                               ObjectAttributes->SecurityQualityOfService,
323*c2c66affSColin Finck                                               sizeof(SECURITY_QUALITY_OF_SERVICE));
324*c2c66affSColin Finck                                 *CapturedSecurityQualityOfService = CapturedQos;
325*c2c66affSColin Finck                                 *Present = TRUE;
326*c2c66affSColin Finck                             }
327*c2c66affSColin Finck                             else
328*c2c66affSColin Finck                             {
329*c2c66affSColin Finck                                 Status = STATUS_INSUFFICIENT_RESOURCES;
330*c2c66affSColin Finck                             }
331*c2c66affSColin Finck                         }
332*c2c66affSColin Finck                         else
333*c2c66affSColin Finck                         {
334*c2c66affSColin Finck                             Status = STATUS_INVALID_PARAMETER;
335*c2c66affSColin Finck                         }
336*c2c66affSColin Finck                     }
337*c2c66affSColin Finck                     else
338*c2c66affSColin Finck                     {
339*c2c66affSColin Finck                         *CapturedSecurityQualityOfService = NULL;
340*c2c66affSColin Finck                         *Present = FALSE;
341*c2c66affSColin Finck                     }
342*c2c66affSColin Finck                 }
343*c2c66affSColin Finck                 else
344*c2c66affSColin Finck                 {
345*c2c66affSColin Finck                     *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService;
346*c2c66affSColin Finck                     *Present = (ObjectAttributes->SecurityQualityOfService != NULL);
347*c2c66affSColin Finck                 }
348*c2c66affSColin Finck             }
349*c2c66affSColin Finck             else
350*c2c66affSColin Finck             {
351*c2c66affSColin Finck                 Status = STATUS_INVALID_PARAMETER;
352*c2c66affSColin Finck             }
353*c2c66affSColin Finck         }
354*c2c66affSColin Finck     }
355*c2c66affSColin Finck     else
356*c2c66affSColin Finck     {
357*c2c66affSColin Finck         *CapturedSecurityQualityOfService = NULL;
358*c2c66affSColin Finck         *Present = FALSE;
359*c2c66affSColin Finck     }
360*c2c66affSColin Finck 
361*c2c66affSColin Finck     return Status;
362*c2c66affSColin Finck }
363*c2c66affSColin Finck 
364*c2c66affSColin Finck 
365*c2c66affSColin Finck VOID
366*c2c66affSColin Finck NTAPI
367*c2c66affSColin Finck SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService  OPTIONAL,
368*c2c66affSColin Finck                                    IN KPROCESSOR_MODE AccessMode,
369*c2c66affSColin Finck                                    IN BOOLEAN CaptureIfKernel)
370*c2c66affSColin Finck {
371*c2c66affSColin Finck     PAGED_CODE();
372*c2c66affSColin Finck 
373*c2c66affSColin Finck     if (CapturedSecurityQualityOfService != NULL &&
374*c2c66affSColin Finck         (AccessMode != KernelMode || CaptureIfKernel))
375*c2c66affSColin Finck     {
376*c2c66affSColin Finck         ExFreePoolWithTag(CapturedSecurityQualityOfService, TAG_QOS);
377*c2c66affSColin Finck     }
378*c2c66affSColin Finck }
379*c2c66affSColin Finck 
380*c2c66affSColin Finck /* PUBLIC FUNCTIONS ***********************************************************/
381*c2c66affSColin Finck 
382*c2c66affSColin Finck static
383*c2c66affSColin Finck ULONG
384*c2c66affSColin Finck DetermineSIDSize(
385*c2c66affSColin Finck     PISID Sid,
386*c2c66affSColin Finck     PULONG OutSAC,
387*c2c66affSColin Finck     KPROCESSOR_MODE ProcessorMode)
388*c2c66affSColin Finck {
389*c2c66affSColin Finck     ULONG Size;
390*c2c66affSColin Finck 
391*c2c66affSColin Finck     if (!Sid)
392*c2c66affSColin Finck     {
393*c2c66affSColin Finck         *OutSAC = 0;
394*c2c66affSColin Finck         return 0;
395*c2c66affSColin Finck     }
396*c2c66affSColin Finck 
397*c2c66affSColin Finck     if (ProcessorMode != KernelMode)
398*c2c66affSColin Finck     {
399*c2c66affSColin Finck         /* Securely access the buffers! */
400*c2c66affSColin Finck         *OutSAC = ProbeForReadUchar(&Sid->SubAuthorityCount);
401*c2c66affSColin Finck         Size = RtlLengthRequiredSid(*OutSAC);
402*c2c66affSColin Finck         ProbeForRead(Sid, Size, sizeof(ULONG));
403*c2c66affSColin Finck     }
404*c2c66affSColin Finck     else
405*c2c66affSColin Finck     {
406*c2c66affSColin Finck         *OutSAC = Sid->SubAuthorityCount;
407*c2c66affSColin Finck         Size = RtlLengthRequiredSid(*OutSAC);
408*c2c66affSColin Finck     }
409*c2c66affSColin Finck 
410*c2c66affSColin Finck     return Size;
411*c2c66affSColin Finck }
412*c2c66affSColin Finck 
413*c2c66affSColin Finck static
414*c2c66affSColin Finck ULONG
415*c2c66affSColin Finck DetermineACLSize(
416*c2c66affSColin Finck     PACL Acl,
417*c2c66affSColin Finck     KPROCESSOR_MODE ProcessorMode)
418*c2c66affSColin Finck {
419*c2c66affSColin Finck     ULONG Size;
420*c2c66affSColin Finck 
421*c2c66affSColin Finck     if (!Acl) return 0;
422*c2c66affSColin Finck 
423*c2c66affSColin Finck     if (ProcessorMode == KernelMode) return Acl->AclSize;
424*c2c66affSColin Finck 
425*c2c66affSColin Finck     /* Probe the buffers! */
426*c2c66affSColin Finck     Size = ProbeForReadUshort(&Acl->AclSize);
427*c2c66affSColin Finck     ProbeForRead(Acl, Size, sizeof(ULONG));
428*c2c66affSColin Finck 
429*c2c66affSColin Finck     return Size;
430*c2c66affSColin Finck }
431*c2c66affSColin Finck 
432*c2c66affSColin Finck NTSTATUS
433*c2c66affSColin Finck NTAPI
434*c2c66affSColin Finck SeCaptureSecurityDescriptor(
435*c2c66affSColin Finck     IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor,
436*c2c66affSColin Finck     IN KPROCESSOR_MODE CurrentMode,
437*c2c66affSColin Finck     IN POOL_TYPE PoolType,
438*c2c66affSColin Finck     IN BOOLEAN CaptureIfKernel,
439*c2c66affSColin Finck     OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor)
440*c2c66affSColin Finck {
441*c2c66affSColin Finck     PISECURITY_DESCRIPTOR OriginalDescriptor = _OriginalSecurityDescriptor;
442*c2c66affSColin Finck     SECURITY_DESCRIPTOR DescriptorCopy;
443*c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor;
444*c2c66affSColin Finck     ULONG OwnerSAC = 0, GroupSAC = 0;
445*c2c66affSColin Finck     ULONG OwnerSize = 0, GroupSize = 0;
446*c2c66affSColin Finck     ULONG SaclSize = 0, DaclSize = 0;
447*c2c66affSColin Finck     ULONG DescriptorSize = 0;
448*c2c66affSColin Finck     ULONG Offset;
449*c2c66affSColin Finck 
450*c2c66affSColin Finck     if (!OriginalDescriptor)
451*c2c66affSColin Finck     {
452*c2c66affSColin Finck         /* Nothing to do... */
453*c2c66affSColin Finck         *CapturedSecurityDescriptor = NULL;
454*c2c66affSColin Finck         return STATUS_SUCCESS;
455*c2c66affSColin Finck     }
456*c2c66affSColin Finck 
457*c2c66affSColin Finck     /* Quick path */
458*c2c66affSColin Finck     if (CurrentMode == KernelMode && !CaptureIfKernel)
459*c2c66affSColin Finck     {
460*c2c66affSColin Finck         /* Check descriptor version */
461*c2c66affSColin Finck         if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
462*c2c66affSColin Finck         {
463*c2c66affSColin Finck             return STATUS_UNKNOWN_REVISION;
464*c2c66affSColin Finck         }
465*c2c66affSColin Finck 
466*c2c66affSColin Finck         *CapturedSecurityDescriptor = _OriginalSecurityDescriptor;
467*c2c66affSColin Finck         return STATUS_SUCCESS;
468*c2c66affSColin Finck     }
469*c2c66affSColin Finck 
470*c2c66affSColin Finck     _SEH2_TRY
471*c2c66affSColin Finck     {
472*c2c66affSColin Finck         if (CurrentMode != KernelMode)
473*c2c66affSColin Finck         {
474*c2c66affSColin Finck             ProbeForRead(OriginalDescriptor,
475*c2c66affSColin Finck                          sizeof(SECURITY_DESCRIPTOR_RELATIVE),
476*c2c66affSColin Finck                          sizeof(ULONG));
477*c2c66affSColin Finck         }
478*c2c66affSColin Finck 
479*c2c66affSColin Finck         /* Check the descriptor version */
480*c2c66affSColin Finck         if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
481*c2c66affSColin Finck         {
482*c2c66affSColin Finck             _SEH2_YIELD(return STATUS_UNKNOWN_REVISION);
483*c2c66affSColin Finck         }
484*c2c66affSColin Finck 
485*c2c66affSColin Finck         if (CurrentMode != KernelMode)
486*c2c66affSColin Finck         {
487*c2c66affSColin Finck             /* Get the size of the descriptor */
488*c2c66affSColin Finck             DescriptorSize = (OriginalDescriptor->Control & SE_SELF_RELATIVE) ?
489*c2c66affSColin Finck                 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR);
490*c2c66affSColin Finck 
491*c2c66affSColin Finck             /* Probe the entire security descriptor structure. The SIDs
492*c2c66affSColin Finck              * and ACLs will be probed and copied later though */
493*c2c66affSColin Finck             ProbeForRead(OriginalDescriptor, DescriptorSize, sizeof(ULONG));
494*c2c66affSColin Finck         }
495*c2c66affSColin Finck 
496*c2c66affSColin Finck         /* Now capture all fields and convert to an absolute descriptor */
497*c2c66affSColin Finck         DescriptorCopy.Revision = OriginalDescriptor->Revision;
498*c2c66affSColin Finck         DescriptorCopy.Sbz1 = OriginalDescriptor->Sbz1;
499*c2c66affSColin Finck         DescriptorCopy.Control = OriginalDescriptor->Control & ~SE_SELF_RELATIVE;
500*c2c66affSColin Finck         DescriptorCopy.Owner = SepGetOwnerFromDescriptor(OriginalDescriptor);
501*c2c66affSColin Finck         DescriptorCopy.Group = SepGetGroupFromDescriptor(OriginalDescriptor);
502*c2c66affSColin Finck         DescriptorCopy.Sacl = SepGetSaclFromDescriptor(OriginalDescriptor);
503*c2c66affSColin Finck         DescriptorCopy.Dacl = SepGetDaclFromDescriptor(OriginalDescriptor);
504*c2c66affSColin Finck         DescriptorSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
505*c2c66affSColin Finck 
506*c2c66affSColin Finck         /* Determine owner and group sizes */
507*c2c66affSColin Finck         OwnerSize = DetermineSIDSize(DescriptorCopy.Owner, &OwnerSAC, CurrentMode);
508*c2c66affSColin Finck         DescriptorSize += ROUND_UP(OwnerSize, sizeof(ULONG));
509*c2c66affSColin Finck         GroupSize = DetermineSIDSize(DescriptorCopy.Group, &GroupSAC, CurrentMode);
510*c2c66affSColin Finck         DescriptorSize += ROUND_UP(GroupSize, sizeof(ULONG));
511*c2c66affSColin Finck 
512*c2c66affSColin Finck         /* Determine the size of the ACLs */
513*c2c66affSColin Finck         if (DescriptorCopy.Control & SE_SACL_PRESENT)
514*c2c66affSColin Finck         {
515*c2c66affSColin Finck             /* Get the size and probe if user mode */
516*c2c66affSColin Finck             SaclSize = DetermineACLSize(DescriptorCopy.Sacl, CurrentMode);
517*c2c66affSColin Finck             DescriptorSize += ROUND_UP(SaclSize, sizeof(ULONG));
518*c2c66affSColin Finck         }
519*c2c66affSColin Finck 
520*c2c66affSColin Finck         if (DescriptorCopy.Control & SE_DACL_PRESENT)
521*c2c66affSColin Finck         {
522*c2c66affSColin Finck             /* Get the size and probe if user mode */
523*c2c66affSColin Finck             DaclSize = DetermineACLSize(DescriptorCopy.Dacl, CurrentMode);
524*c2c66affSColin Finck             DescriptorSize += ROUND_UP(DaclSize, sizeof(ULONG));
525*c2c66affSColin Finck         }
526*c2c66affSColin Finck     }
527*c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
528*c2c66affSColin Finck     {
529*c2c66affSColin Finck         _SEH2_YIELD(return _SEH2_GetExceptionCode());
530*c2c66affSColin Finck     }
531*c2c66affSColin Finck     _SEH2_END;
532*c2c66affSColin Finck 
533*c2c66affSColin Finck     /*
534*c2c66affSColin Finck      * Allocate enough memory to store a complete copy of a self-relative
535*c2c66affSColin Finck      * security descriptor
536*c2c66affSColin Finck      */
537*c2c66affSColin Finck     NewDescriptor = ExAllocatePoolWithTag(PoolType,
538*c2c66affSColin Finck                                           DescriptorSize,
539*c2c66affSColin Finck                                           TAG_SD);
540*c2c66affSColin Finck     if (!NewDescriptor) return STATUS_INSUFFICIENT_RESOURCES;
541*c2c66affSColin Finck 
542*c2c66affSColin Finck     RtlZeroMemory(NewDescriptor, DescriptorSize);
543*c2c66affSColin Finck     NewDescriptor->Revision = DescriptorCopy.Revision;
544*c2c66affSColin Finck     NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
545*c2c66affSColin Finck     NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
546*c2c66affSColin Finck 
547*c2c66affSColin Finck     _SEH2_TRY
548*c2c66affSColin Finck     {
549*c2c66affSColin Finck         /*
550*c2c66affSColin Finck          * Setup the offsets and copy the SIDs and ACLs to the new
551*c2c66affSColin Finck          * self-relative security descriptor. Probing the pointers is not
552*c2c66affSColin Finck          * neccessary anymore as we did that when collecting the sizes!
553*c2c66affSColin Finck          * Make sure to validate the SIDs and ACLs *again* as they could have
554*c2c66affSColin Finck          * been modified in the meanwhile!
555*c2c66affSColin Finck          */
556*c2c66affSColin Finck         Offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
557*c2c66affSColin Finck 
558*c2c66affSColin Finck         if (DescriptorCopy.Owner)
559*c2c66affSColin Finck         {
560*c2c66affSColin Finck             if (!RtlValidSid(DescriptorCopy.Owner)) RtlRaiseStatus(STATUS_INVALID_SID);
561*c2c66affSColin Finck             NewDescriptor->Owner = Offset;
562*c2c66affSColin Finck             RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
563*c2c66affSColin Finck                           DescriptorCopy.Owner,
564*c2c66affSColin Finck                           OwnerSize);
565*c2c66affSColin Finck             Offset += ROUND_UP(OwnerSize, sizeof(ULONG));
566*c2c66affSColin Finck         }
567*c2c66affSColin Finck 
568*c2c66affSColin Finck         if (DescriptorCopy.Group)
569*c2c66affSColin Finck         {
570*c2c66affSColin Finck             if (!RtlValidSid(DescriptorCopy.Group)) RtlRaiseStatus(STATUS_INVALID_SID);
571*c2c66affSColin Finck             NewDescriptor->Group = Offset;
572*c2c66affSColin Finck             RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
573*c2c66affSColin Finck                           DescriptorCopy.Group,
574*c2c66affSColin Finck                           GroupSize);
575*c2c66affSColin Finck             Offset += ROUND_UP(GroupSize, sizeof(ULONG));
576*c2c66affSColin Finck         }
577*c2c66affSColin Finck 
578*c2c66affSColin Finck         if (DescriptorCopy.Sacl)
579*c2c66affSColin Finck         {
580*c2c66affSColin Finck             if (!RtlValidAcl(DescriptorCopy.Sacl)) RtlRaiseStatus(STATUS_INVALID_ACL);
581*c2c66affSColin Finck             NewDescriptor->Sacl = Offset;
582*c2c66affSColin Finck             RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
583*c2c66affSColin Finck                           DescriptorCopy.Sacl,
584*c2c66affSColin Finck                           SaclSize);
585*c2c66affSColin Finck             Offset += ROUND_UP(SaclSize, sizeof(ULONG));
586*c2c66affSColin Finck         }
587*c2c66affSColin Finck 
588*c2c66affSColin Finck         if (DescriptorCopy.Dacl)
589*c2c66affSColin Finck         {
590*c2c66affSColin Finck             if (!RtlValidAcl(DescriptorCopy.Dacl)) RtlRaiseStatus(STATUS_INVALID_ACL);
591*c2c66affSColin Finck             NewDescriptor->Dacl = Offset;
592*c2c66affSColin Finck             RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
593*c2c66affSColin Finck                           DescriptorCopy.Dacl,
594*c2c66affSColin Finck                           DaclSize);
595*c2c66affSColin Finck             Offset += ROUND_UP(DaclSize, sizeof(ULONG));
596*c2c66affSColin Finck         }
597*c2c66affSColin Finck 
598*c2c66affSColin Finck         /* Make sure the size was correct */
599*c2c66affSColin Finck         ASSERT(Offset == DescriptorSize);
600*c2c66affSColin Finck     }
601*c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
602*c2c66affSColin Finck     {
603*c2c66affSColin Finck         /* We failed to copy the data to the new descriptor */
604*c2c66affSColin Finck         ExFreePoolWithTag(NewDescriptor, TAG_SD);
605*c2c66affSColin Finck         _SEH2_YIELD(return _SEH2_GetExceptionCode());
606*c2c66affSColin Finck     }
607*c2c66affSColin Finck     _SEH2_END;
608*c2c66affSColin Finck 
609*c2c66affSColin Finck     /*
610*c2c66affSColin Finck      * We're finally done!
611*c2c66affSColin Finck      * Copy the pointer to the captured descriptor to to the caller.
612*c2c66affSColin Finck      */
613*c2c66affSColin Finck     *CapturedSecurityDescriptor = NewDescriptor;
614*c2c66affSColin Finck     return STATUS_SUCCESS;
615*c2c66affSColin Finck }
616*c2c66affSColin Finck 
617*c2c66affSColin Finck /*
618*c2c66affSColin Finck  * @implemented
619*c2c66affSColin Finck  */
620*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
621*c2c66affSColin Finck NTSTATUS
622*c2c66affSColin Finck NTAPI
623*c2c66affSColin Finck SeQuerySecurityDescriptorInfo(
624*c2c66affSColin Finck     _In_ PSECURITY_INFORMATION SecurityInformation,
625*c2c66affSColin Finck     _Out_writes_bytes_(*Length) PSECURITY_DESCRIPTOR SecurityDescriptor,
626*c2c66affSColin Finck     _Inout_ PULONG Length,
627*c2c66affSColin Finck     _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor)
628*c2c66affSColin Finck {
629*c2c66affSColin Finck     PISECURITY_DESCRIPTOR ObjectSd;
630*c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE RelSD;
631*c2c66affSColin Finck     PSID Owner = NULL;
632*c2c66affSColin Finck     PSID Group = NULL;
633*c2c66affSColin Finck     PACL Dacl = NULL;
634*c2c66affSColin Finck     PACL Sacl = NULL;
635*c2c66affSColin Finck     ULONG OwnerLength = 0;
636*c2c66affSColin Finck     ULONG GroupLength = 0;
637*c2c66affSColin Finck     ULONG DaclLength = 0;
638*c2c66affSColin Finck     ULONG SaclLength = 0;
639*c2c66affSColin Finck     SECURITY_DESCRIPTOR_CONTROL Control = 0;
640*c2c66affSColin Finck     ULONG_PTR Current;
641*c2c66affSColin Finck     ULONG SdLength;
642*c2c66affSColin Finck 
643*c2c66affSColin Finck     PAGED_CODE();
644*c2c66affSColin Finck 
645*c2c66affSColin Finck     RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
646*c2c66affSColin Finck 
647*c2c66affSColin Finck     if (*ObjectsSecurityDescriptor == NULL)
648*c2c66affSColin Finck     {
649*c2c66affSColin Finck         if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
650*c2c66affSColin Finck         {
651*c2c66affSColin Finck             *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
652*c2c66affSColin Finck             return STATUS_BUFFER_TOO_SMALL;
653*c2c66affSColin Finck         }
654*c2c66affSColin Finck 
655*c2c66affSColin Finck         *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
656*c2c66affSColin Finck         RtlCreateSecurityDescriptorRelative(RelSD,
657*c2c66affSColin Finck                                             SECURITY_DESCRIPTOR_REVISION);
658*c2c66affSColin Finck         return STATUS_SUCCESS;
659*c2c66affSColin Finck     }
660*c2c66affSColin Finck 
661*c2c66affSColin Finck     ObjectSd = *ObjectsSecurityDescriptor;
662*c2c66affSColin Finck 
663*c2c66affSColin Finck     /* Calculate the required security descriptor length */
664*c2c66affSColin Finck     Control = SE_SELF_RELATIVE;
665*c2c66affSColin Finck     if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
666*c2c66affSColin Finck         (ObjectSd->Owner != NULL))
667*c2c66affSColin Finck     {
668*c2c66affSColin Finck         Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
669*c2c66affSColin Finck         OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
670*c2c66affSColin Finck         Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
671*c2c66affSColin Finck     }
672*c2c66affSColin Finck 
673*c2c66affSColin Finck     if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
674*c2c66affSColin Finck         (ObjectSd->Group != NULL))
675*c2c66affSColin Finck     {
676*c2c66affSColin Finck         Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
677*c2c66affSColin Finck         GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
678*c2c66affSColin Finck         Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
679*c2c66affSColin Finck     }
680*c2c66affSColin Finck 
681*c2c66affSColin Finck     if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
682*c2c66affSColin Finck         (ObjectSd->Control & SE_DACL_PRESENT))
683*c2c66affSColin Finck     {
684*c2c66affSColin Finck         if (ObjectSd->Dacl != NULL)
685*c2c66affSColin Finck         {
686*c2c66affSColin Finck             Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
687*c2c66affSColin Finck             DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
688*c2c66affSColin Finck         }
689*c2c66affSColin Finck 
690*c2c66affSColin Finck         Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
691*c2c66affSColin Finck     }
692*c2c66affSColin Finck 
693*c2c66affSColin Finck     if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
694*c2c66affSColin Finck         (ObjectSd->Control & SE_SACL_PRESENT))
695*c2c66affSColin Finck     {
696*c2c66affSColin Finck         if (ObjectSd->Sacl != NULL)
697*c2c66affSColin Finck         {
698*c2c66affSColin Finck             Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
699*c2c66affSColin Finck             SaclLength = ROUND_UP(Sacl->AclSize, 4);
700*c2c66affSColin Finck         }
701*c2c66affSColin Finck 
702*c2c66affSColin Finck         Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
703*c2c66affSColin Finck     }
704*c2c66affSColin Finck 
705*c2c66affSColin Finck     SdLength = OwnerLength + GroupLength + DaclLength +
706*c2c66affSColin Finck     SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
707*c2c66affSColin Finck     if (*Length < SdLength)
708*c2c66affSColin Finck     {
709*c2c66affSColin Finck         *Length = SdLength;
710*c2c66affSColin Finck         return STATUS_BUFFER_TOO_SMALL;
711*c2c66affSColin Finck     }
712*c2c66affSColin Finck 
713*c2c66affSColin Finck     /* Build the new security descrtiptor */
714*c2c66affSColin Finck     RtlCreateSecurityDescriptorRelative(RelSD,
715*c2c66affSColin Finck                                         SECURITY_DESCRIPTOR_REVISION);
716*c2c66affSColin Finck     RelSD->Control = Control;
717*c2c66affSColin Finck 
718*c2c66affSColin Finck     Current = (ULONG_PTR)(RelSD + 1);
719*c2c66affSColin Finck 
720*c2c66affSColin Finck     if (OwnerLength != 0)
721*c2c66affSColin Finck     {
722*c2c66affSColin Finck         RtlCopyMemory((PVOID)Current,
723*c2c66affSColin Finck                       Owner,
724*c2c66affSColin Finck                       OwnerLength);
725*c2c66affSColin Finck         RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
726*c2c66affSColin Finck         Current += OwnerLength;
727*c2c66affSColin Finck     }
728*c2c66affSColin Finck 
729*c2c66affSColin Finck     if (GroupLength != 0)
730*c2c66affSColin Finck     {
731*c2c66affSColin Finck         RtlCopyMemory((PVOID)Current,
732*c2c66affSColin Finck                       Group,
733*c2c66affSColin Finck                       GroupLength);
734*c2c66affSColin Finck         RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
735*c2c66affSColin Finck         Current += GroupLength;
736*c2c66affSColin Finck     }
737*c2c66affSColin Finck 
738*c2c66affSColin Finck     if (DaclLength != 0)
739*c2c66affSColin Finck     {
740*c2c66affSColin Finck         RtlCopyMemory((PVOID)Current,
741*c2c66affSColin Finck                       Dacl,
742*c2c66affSColin Finck                       DaclLength);
743*c2c66affSColin Finck         RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
744*c2c66affSColin Finck         Current += DaclLength;
745*c2c66affSColin Finck     }
746*c2c66affSColin Finck 
747*c2c66affSColin Finck     if (SaclLength != 0)
748*c2c66affSColin Finck     {
749*c2c66affSColin Finck         RtlCopyMemory((PVOID)Current,
750*c2c66affSColin Finck                       Sacl,
751*c2c66affSColin Finck                       SaclLength);
752*c2c66affSColin Finck         RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
753*c2c66affSColin Finck         Current += SaclLength;
754*c2c66affSColin Finck     }
755*c2c66affSColin Finck 
756*c2c66affSColin Finck     *Length = SdLength;
757*c2c66affSColin Finck 
758*c2c66affSColin Finck     return STATUS_SUCCESS;
759*c2c66affSColin Finck }
760*c2c66affSColin Finck 
761*c2c66affSColin Finck /*
762*c2c66affSColin Finck  * @implemented
763*c2c66affSColin Finck  */
764*c2c66affSColin Finck NTSTATUS
765*c2c66affSColin Finck NTAPI
766*c2c66affSColin Finck SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
767*c2c66affSColin Finck                             IN KPROCESSOR_MODE CurrentMode,
768*c2c66affSColin Finck                             IN BOOLEAN CaptureIfKernelMode)
769*c2c66affSColin Finck {
770*c2c66affSColin Finck     PAGED_CODE();
771*c2c66affSColin Finck 
772*c2c66affSColin Finck     /*
773*c2c66affSColin Finck      * WARNING! You need to call this function with the same value for CurrentMode
774*c2c66affSColin Finck      * and CaptureIfKernelMode that you previously passed to
775*c2c66affSColin Finck      * SeCaptureSecurityDescriptor() in order to avoid memory leaks!
776*c2c66affSColin Finck      */
777*c2c66affSColin Finck     if (CapturedSecurityDescriptor != NULL &&
778*c2c66affSColin Finck         (CurrentMode != KernelMode ||
779*c2c66affSColin Finck          (CurrentMode == KernelMode && CaptureIfKernelMode)))
780*c2c66affSColin Finck     {
781*c2c66affSColin Finck         /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
782*c2c66affSColin Finck         ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD);
783*c2c66affSColin Finck     }
784*c2c66affSColin Finck 
785*c2c66affSColin Finck     return STATUS_SUCCESS;
786*c2c66affSColin Finck }
787*c2c66affSColin Finck 
788*c2c66affSColin Finck /*
789*c2c66affSColin Finck  * @implemented
790*c2c66affSColin Finck  */
791*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
792*c2c66affSColin Finck NTSTATUS
793*c2c66affSColin Finck NTAPI
794*c2c66affSColin Finck SeSetSecurityDescriptorInfo(
795*c2c66affSColin Finck     _In_opt_ PVOID Object,
796*c2c66affSColin Finck     _In_ PSECURITY_INFORMATION SecurityInformation,
797*c2c66affSColin Finck     _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
798*c2c66affSColin Finck     _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
799*c2c66affSColin Finck     _In_ POOL_TYPE PoolType,
800*c2c66affSColin Finck     _In_ PGENERIC_MAPPING GenericMapping)
801*c2c66affSColin Finck {
802*c2c66affSColin Finck     PAGED_CODE();
803*c2c66affSColin Finck 
804*c2c66affSColin Finck     return SeSetSecurityDescriptorInfoEx(Object,
805*c2c66affSColin Finck                                          SecurityInformation,
806*c2c66affSColin Finck                                          SecurityDescriptor,
807*c2c66affSColin Finck                                          ObjectsSecurityDescriptor,
808*c2c66affSColin Finck                                          0,
809*c2c66affSColin Finck                                          PoolType,
810*c2c66affSColin Finck                                          GenericMapping);
811*c2c66affSColin Finck }
812*c2c66affSColin Finck 
813*c2c66affSColin Finck /*
814*c2c66affSColin Finck  * @implemented
815*c2c66affSColin Finck  */
816*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
817*c2c66affSColin Finck NTSTATUS
818*c2c66affSColin Finck NTAPI
819*c2c66affSColin Finck SeSetSecurityDescriptorInfoEx(
820*c2c66affSColin Finck     _In_opt_ PVOID Object,
821*c2c66affSColin Finck     _In_ PSECURITY_INFORMATION _SecurityInformation,
822*c2c66affSColin Finck     _In_ PSECURITY_DESCRIPTOR _SecurityDescriptor,
823*c2c66affSColin Finck     _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
824*c2c66affSColin Finck     _In_ ULONG AutoInheritFlags,
825*c2c66affSColin Finck     _In_ POOL_TYPE PoolType,
826*c2c66affSColin Finck     _In_ PGENERIC_MAPPING GenericMapping)
827*c2c66affSColin Finck {
828*c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE ObjectSd;
829*c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE NewSd;
830*c2c66affSColin Finck     PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
831*c2c66affSColin Finck     PSID Owner;
832*c2c66affSColin Finck     PSID Group;
833*c2c66affSColin Finck     PACL Dacl;
834*c2c66affSColin Finck     PACL Sacl;
835*c2c66affSColin Finck     ULONG OwnerLength;
836*c2c66affSColin Finck     ULONG GroupLength;
837*c2c66affSColin Finck     ULONG DaclLength;
838*c2c66affSColin Finck     ULONG SaclLength;
839*c2c66affSColin Finck     SECURITY_DESCRIPTOR_CONTROL Control = 0;
840*c2c66affSColin Finck     ULONG Current;
841*c2c66affSColin Finck     SECURITY_INFORMATION SecurityInformation;
842*c2c66affSColin Finck 
843*c2c66affSColin Finck     PAGED_CODE();
844*c2c66affSColin Finck 
845*c2c66affSColin Finck     ObjectSd = *ObjectsSecurityDescriptor;
846*c2c66affSColin Finck 
847*c2c66affSColin Finck     /* The object does not have a security descriptor. */
848*c2c66affSColin Finck     if (!ObjectSd)
849*c2c66affSColin Finck         return STATUS_NO_SECURITY_ON_OBJECT;
850*c2c66affSColin Finck 
851*c2c66affSColin Finck     ASSERT(ObjectSd->Control & SE_SELF_RELATIVE);
852*c2c66affSColin Finck 
853*c2c66affSColin Finck     SecurityInformation = *_SecurityInformation;
854*c2c66affSColin Finck 
855*c2c66affSColin Finck     /* Get owner and owner size */
856*c2c66affSColin Finck     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
857*c2c66affSColin Finck     {
858*c2c66affSColin Finck         Owner = SepGetOwnerFromDescriptor(SecurityDescriptor);
859*c2c66affSColin Finck         Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
860*c2c66affSColin Finck     }
861*c2c66affSColin Finck     else
862*c2c66affSColin Finck     {
863*c2c66affSColin Finck         Owner = SepGetOwnerFromDescriptor(ObjectSd);
864*c2c66affSColin Finck         Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
865*c2c66affSColin Finck     }
866*c2c66affSColin Finck     OwnerLength = Owner ? RtlLengthSid(Owner) : 0;
867*c2c66affSColin Finck     ASSERT(OwnerLength % sizeof(ULONG) == 0);
868*c2c66affSColin Finck 
869*c2c66affSColin Finck     /* Get group and group size */
870*c2c66affSColin Finck     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
871*c2c66affSColin Finck     {
872*c2c66affSColin Finck         Group = SepGetGroupFromDescriptor(SecurityDescriptor);
873*c2c66affSColin Finck         Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
874*c2c66affSColin Finck     }
875*c2c66affSColin Finck     else
876*c2c66affSColin Finck     {
877*c2c66affSColin Finck         Group = SepGetGroupFromDescriptor(ObjectSd);
878*c2c66affSColin Finck         Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
879*c2c66affSColin Finck     }
880*c2c66affSColin Finck     GroupLength = Group ? RtlLengthSid(Group) : 0;
881*c2c66affSColin Finck     ASSERT(GroupLength % sizeof(ULONG) == 0);
882*c2c66affSColin Finck 
883*c2c66affSColin Finck     /* Get DACL and DACL size */
884*c2c66affSColin Finck     if (SecurityInformation & DACL_SECURITY_INFORMATION)
885*c2c66affSColin Finck     {
886*c2c66affSColin Finck         Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
887*c2c66affSColin Finck         Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
888*c2c66affSColin Finck     }
889*c2c66affSColin Finck     else
890*c2c66affSColin Finck     {
891*c2c66affSColin Finck         Dacl = SepGetDaclFromDescriptor(ObjectSd);
892*c2c66affSColin Finck         Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
893*c2c66affSColin Finck     }
894*c2c66affSColin Finck     DaclLength = Dacl ? ROUND_UP((ULONG)Dacl->AclSize, 4) : 0;
895*c2c66affSColin Finck 
896*c2c66affSColin Finck     /* Get SACL and SACL size */
897*c2c66affSColin Finck     if (SecurityInformation & SACL_SECURITY_INFORMATION)
898*c2c66affSColin Finck     {
899*c2c66affSColin Finck         Sacl = SepGetSaclFromDescriptor(SecurityDescriptor);
900*c2c66affSColin Finck         Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
901*c2c66affSColin Finck     }
902*c2c66affSColin Finck     else
903*c2c66affSColin Finck     {
904*c2c66affSColin Finck         Sacl = SepGetSaclFromDescriptor(ObjectSd);
905*c2c66affSColin Finck         Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
906*c2c66affSColin Finck     }
907*c2c66affSColin Finck     SaclLength = Sacl ? ROUND_UP((ULONG)Sacl->AclSize, 4) : 0;
908*c2c66affSColin Finck 
909*c2c66affSColin Finck     NewSd = ExAllocatePoolWithTag(NonPagedPool,
910*c2c66affSColin Finck                                   sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
911*c2c66affSColin Finck                                   OwnerLength + GroupLength +
912*c2c66affSColin Finck                                   DaclLength + SaclLength,
913*c2c66affSColin Finck                                   TAG_SD);
914*c2c66affSColin Finck     if (NewSd == NULL)
915*c2c66affSColin Finck     {
916*c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
917*c2c66affSColin Finck     }
918*c2c66affSColin Finck 
919*c2c66affSColin Finck     RtlCreateSecurityDescriptor(NewSd,
920*c2c66affSColin Finck                                 SECURITY_DESCRIPTOR_REVISION1);
921*c2c66affSColin Finck 
922*c2c66affSColin Finck     /* We always build a self-relative descriptor */
923*c2c66affSColin Finck     NewSd->Control = Control | SE_SELF_RELATIVE;
924*c2c66affSColin Finck 
925*c2c66affSColin Finck     Current = sizeof(SECURITY_DESCRIPTOR);
926*c2c66affSColin Finck 
927*c2c66affSColin Finck     if (OwnerLength != 0)
928*c2c66affSColin Finck     {
929*c2c66affSColin Finck         RtlCopyMemory((PUCHAR)NewSd + Current, Owner, OwnerLength);
930*c2c66affSColin Finck         NewSd->Owner = Current;
931*c2c66affSColin Finck         Current += OwnerLength;
932*c2c66affSColin Finck     }
933*c2c66affSColin Finck 
934*c2c66affSColin Finck     if (GroupLength != 0)
935*c2c66affSColin Finck     {
936*c2c66affSColin Finck         RtlCopyMemory((PUCHAR)NewSd + Current, Group, GroupLength);
937*c2c66affSColin Finck         NewSd->Group = Current;
938*c2c66affSColin Finck         Current += GroupLength;
939*c2c66affSColin Finck     }
940*c2c66affSColin Finck 
941*c2c66affSColin Finck     if (DaclLength != 0)
942*c2c66affSColin Finck     {
943*c2c66affSColin Finck         RtlCopyMemory((PUCHAR)NewSd + Current, Dacl, DaclLength);
944*c2c66affSColin Finck         NewSd->Dacl = Current;
945*c2c66affSColin Finck         Current += DaclLength;
946*c2c66affSColin Finck     }
947*c2c66affSColin Finck 
948*c2c66affSColin Finck     if (SaclLength != 0)
949*c2c66affSColin Finck     {
950*c2c66affSColin Finck         RtlCopyMemory((PUCHAR)NewSd + Current, Sacl, SaclLength);
951*c2c66affSColin Finck         NewSd->Sacl = Current;
952*c2c66affSColin Finck         Current += SaclLength;
953*c2c66affSColin Finck     }
954*c2c66affSColin Finck 
955*c2c66affSColin Finck     *ObjectsSecurityDescriptor = NewSd;
956*c2c66affSColin Finck     return STATUS_SUCCESS;
957*c2c66affSColin Finck }
958*c2c66affSColin Finck 
959*c2c66affSColin Finck 
960*c2c66affSColin Finck /*
961*c2c66affSColin Finck  * @implemented
962*c2c66affSColin Finck  */
963*c2c66affSColin Finck BOOLEAN NTAPI
964*c2c66affSColin Finck SeValidSecurityDescriptor(IN ULONG Length,
965*c2c66affSColin Finck                           IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
966*c2c66affSColin Finck {
967*c2c66affSColin Finck     ULONG SdLength;
968*c2c66affSColin Finck     PISID Sid;
969*c2c66affSColin Finck     PACL Acl;
970*c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor = _SecurityDescriptor;
971*c2c66affSColin Finck 
972*c2c66affSColin Finck     if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
973*c2c66affSColin Finck     {
974*c2c66affSColin Finck         DPRINT1("Invalid Security Descriptor revision\n");
975*c2c66affSColin Finck         return FALSE;
976*c2c66affSColin Finck     }
977*c2c66affSColin Finck 
978*c2c66affSColin Finck     if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
979*c2c66affSColin Finck     {
980*c2c66affSColin Finck         DPRINT1("Invalid Security Descriptor revision\n");
981*c2c66affSColin Finck         return FALSE;
982*c2c66affSColin Finck     }
983*c2c66affSColin Finck 
984*c2c66affSColin Finck     if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
985*c2c66affSColin Finck     {
986*c2c66affSColin Finck         DPRINT1("No self-relative Security Descriptor\n");
987*c2c66affSColin Finck         return FALSE;
988*c2c66affSColin Finck     }
989*c2c66affSColin Finck 
990*c2c66affSColin Finck     SdLength = sizeof(SECURITY_DESCRIPTOR);
991*c2c66affSColin Finck 
992*c2c66affSColin Finck     /* Check Owner SID */
993*c2c66affSColin Finck     if (!SecurityDescriptor->Owner)
994*c2c66affSColin Finck     {
995*c2c66affSColin Finck         DPRINT1("No Owner SID\n");
996*c2c66affSColin Finck         return FALSE;
997*c2c66affSColin Finck     }
998*c2c66affSColin Finck 
999*c2c66affSColin Finck     if (SecurityDescriptor->Owner % sizeof(ULONG))
1000*c2c66affSColin Finck     {
1001*c2c66affSColin Finck         DPRINT1("Invalid Owner SID alignment\n");
1002*c2c66affSColin Finck         return FALSE;
1003*c2c66affSColin Finck     }
1004*c2c66affSColin Finck 
1005*c2c66affSColin Finck     Sid = (PISID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Owner);
1006*c2c66affSColin Finck     if (Sid->Revision != SID_REVISION)
1007*c2c66affSColin Finck     {
1008*c2c66affSColin Finck         DPRINT1("Invalid Owner SID revision\n");
1009*c2c66affSColin Finck         return FALSE;
1010*c2c66affSColin Finck     }
1011*c2c66affSColin Finck 
1012*c2c66affSColin Finck     SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1013*c2c66affSColin Finck     if (Length < SdLength)
1014*c2c66affSColin Finck     {
1015*c2c66affSColin Finck         DPRINT1("Invalid Owner SID size\n");
1016*c2c66affSColin Finck         return FALSE;
1017*c2c66affSColin Finck     }
1018*c2c66affSColin Finck 
1019*c2c66affSColin Finck     /* Check Group SID */
1020*c2c66affSColin Finck     if (SecurityDescriptor->Group)
1021*c2c66affSColin Finck     {
1022*c2c66affSColin Finck         if (SecurityDescriptor->Group % sizeof(ULONG))
1023*c2c66affSColin Finck         {
1024*c2c66affSColin Finck             DPRINT1("Invalid Group SID alignment\n");
1025*c2c66affSColin Finck             return FALSE;
1026*c2c66affSColin Finck         }
1027*c2c66affSColin Finck 
1028*c2c66affSColin Finck         Sid = (PSID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Group);
1029*c2c66affSColin Finck         if (Sid->Revision != SID_REVISION)
1030*c2c66affSColin Finck         {
1031*c2c66affSColin Finck             DPRINT1("Invalid Group SID revision\n");
1032*c2c66affSColin Finck             return FALSE;
1033*c2c66affSColin Finck         }
1034*c2c66affSColin Finck 
1035*c2c66affSColin Finck         SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1036*c2c66affSColin Finck         if (Length < SdLength)
1037*c2c66affSColin Finck         {
1038*c2c66affSColin Finck             DPRINT1("Invalid Group SID size\n");
1039*c2c66affSColin Finck             return FALSE;
1040*c2c66affSColin Finck         }
1041*c2c66affSColin Finck     }
1042*c2c66affSColin Finck 
1043*c2c66affSColin Finck     /* Check DACL */
1044*c2c66affSColin Finck     if (SecurityDescriptor->Dacl)
1045*c2c66affSColin Finck     {
1046*c2c66affSColin Finck         if (SecurityDescriptor->Dacl % sizeof(ULONG))
1047*c2c66affSColin Finck         {
1048*c2c66affSColin Finck             DPRINT1("Invalid DACL alignment\n");
1049*c2c66affSColin Finck             return FALSE;
1050*c2c66affSColin Finck         }
1051*c2c66affSColin Finck 
1052*c2c66affSColin Finck         Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl);
1053*c2c66affSColin Finck         if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1054*c2c66affSColin Finck             (Acl->AclRevision > MAX_ACL_REVISION))
1055*c2c66affSColin Finck         {
1056*c2c66affSColin Finck             DPRINT1("Invalid DACL revision\n");
1057*c2c66affSColin Finck             return FALSE;
1058*c2c66affSColin Finck         }
1059*c2c66affSColin Finck 
1060*c2c66affSColin Finck         SdLength += Acl->AclSize;
1061*c2c66affSColin Finck         if (Length < SdLength)
1062*c2c66affSColin Finck         {
1063*c2c66affSColin Finck             DPRINT1("Invalid DACL size\n");
1064*c2c66affSColin Finck             return FALSE;
1065*c2c66affSColin Finck         }
1066*c2c66affSColin Finck     }
1067*c2c66affSColin Finck 
1068*c2c66affSColin Finck     /* Check SACL */
1069*c2c66affSColin Finck     if (SecurityDescriptor->Sacl)
1070*c2c66affSColin Finck     {
1071*c2c66affSColin Finck         if (SecurityDescriptor->Sacl % sizeof(ULONG))
1072*c2c66affSColin Finck         {
1073*c2c66affSColin Finck             DPRINT1("Invalid SACL alignment\n");
1074*c2c66affSColin Finck             return FALSE;
1075*c2c66affSColin Finck         }
1076*c2c66affSColin Finck 
1077*c2c66affSColin Finck         Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl);
1078*c2c66affSColin Finck         if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1079*c2c66affSColin Finck             (Acl->AclRevision > MAX_ACL_REVISION))
1080*c2c66affSColin Finck         {
1081*c2c66affSColin Finck             DPRINT1("Invalid SACL revision\n");
1082*c2c66affSColin Finck             return FALSE;
1083*c2c66affSColin Finck         }
1084*c2c66affSColin Finck 
1085*c2c66affSColin Finck         SdLength += Acl->AclSize;
1086*c2c66affSColin Finck         if (Length < SdLength)
1087*c2c66affSColin Finck         {
1088*c2c66affSColin Finck             DPRINT1("Invalid SACL size\n");
1089*c2c66affSColin Finck             return FALSE;
1090*c2c66affSColin Finck         }
1091*c2c66affSColin Finck     }
1092*c2c66affSColin Finck 
1093*c2c66affSColin Finck     return TRUE;
1094*c2c66affSColin Finck }
1095*c2c66affSColin Finck 
1096*c2c66affSColin Finck /*
1097*c2c66affSColin Finck  * @implemented
1098*c2c66affSColin Finck  */
1099*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
1100*c2c66affSColin Finck NTSTATUS
1101*c2c66affSColin Finck NTAPI
1102*c2c66affSColin Finck SeDeassignSecurity(
1103*c2c66affSColin Finck     _Inout_ PSECURITY_DESCRIPTOR *SecurityDescriptor)
1104*c2c66affSColin Finck {
1105*c2c66affSColin Finck     PAGED_CODE();
1106*c2c66affSColin Finck 
1107*c2c66affSColin Finck     if (*SecurityDescriptor != NULL)
1108*c2c66affSColin Finck     {
1109*c2c66affSColin Finck         ExFreePoolWithTag(*SecurityDescriptor, TAG_SD);
1110*c2c66affSColin Finck         *SecurityDescriptor = NULL;
1111*c2c66affSColin Finck     }
1112*c2c66affSColin Finck 
1113*c2c66affSColin Finck     return STATUS_SUCCESS;
1114*c2c66affSColin Finck }
1115*c2c66affSColin Finck 
1116*c2c66affSColin Finck /*
1117*c2c66affSColin Finck  * @implemented
1118*c2c66affSColin Finck  */
1119*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
1120*c2c66affSColin Finck NTSTATUS
1121*c2c66affSColin Finck NTAPI
1122*c2c66affSColin Finck SeAssignSecurityEx(
1123*c2c66affSColin Finck     _In_opt_ PSECURITY_DESCRIPTOR _ParentDescriptor,
1124*c2c66affSColin Finck     _In_opt_ PSECURITY_DESCRIPTOR _ExplicitDescriptor,
1125*c2c66affSColin Finck     _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1126*c2c66affSColin Finck     _In_opt_ GUID *ObjectType,
1127*c2c66affSColin Finck     _In_ BOOLEAN IsDirectoryObject,
1128*c2c66affSColin Finck     _In_ ULONG AutoInheritFlags,
1129*c2c66affSColin Finck     _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1130*c2c66affSColin Finck     _In_ PGENERIC_MAPPING GenericMapping,
1131*c2c66affSColin Finck     _In_ POOL_TYPE PoolType)
1132*c2c66affSColin Finck {
1133*c2c66affSColin Finck     PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
1134*c2c66affSColin Finck     PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
1135*c2c66affSColin Finck     PISECURITY_DESCRIPTOR_RELATIVE Descriptor;
1136*c2c66affSColin Finck     PTOKEN Token;
1137*c2c66affSColin Finck     ULONG OwnerLength;
1138*c2c66affSColin Finck     ULONG GroupLength;
1139*c2c66affSColin Finck     ULONG DaclLength;
1140*c2c66affSColin Finck     ULONG SaclLength;
1141*c2c66affSColin Finck     ULONG Length;
1142*c2c66affSColin Finck     SECURITY_DESCRIPTOR_CONTROL Control = 0;
1143*c2c66affSColin Finck     ULONG Current;
1144*c2c66affSColin Finck     PSID Owner = NULL;
1145*c2c66affSColin Finck     PSID Group = NULL;
1146*c2c66affSColin Finck     PACL ExplicitAcl;
1147*c2c66affSColin Finck     BOOLEAN ExplicitPresent;
1148*c2c66affSColin Finck     BOOLEAN ExplicitDefaulted;
1149*c2c66affSColin Finck     PACL ParentAcl;
1150*c2c66affSColin Finck     PACL Dacl = NULL;
1151*c2c66affSColin Finck     PACL Sacl = NULL;
1152*c2c66affSColin Finck     BOOLEAN DaclIsInherited;
1153*c2c66affSColin Finck     BOOLEAN SaclIsInherited;
1154*c2c66affSColin Finck     BOOLEAN DaclPresent;
1155*c2c66affSColin Finck     BOOLEAN SaclPresent;
1156*c2c66affSColin Finck     NTSTATUS Status;
1157*c2c66affSColin Finck 
1158*c2c66affSColin Finck     DBG_UNREFERENCED_PARAMETER(ObjectType);
1159*c2c66affSColin Finck     DBG_UNREFERENCED_PARAMETER(AutoInheritFlags);
1160*c2c66affSColin Finck     UNREFERENCED_PARAMETER(PoolType);
1161*c2c66affSColin Finck 
1162*c2c66affSColin Finck     PAGED_CODE();
1163*c2c66affSColin Finck 
1164*c2c66affSColin Finck     *NewDescriptor = NULL;
1165*c2c66affSColin Finck 
1166*c2c66affSColin Finck     if (!ARGUMENT_PRESENT(SubjectContext))
1167*c2c66affSColin Finck     {
1168*c2c66affSColin Finck         return STATUS_NO_TOKEN;
1169*c2c66affSColin Finck     }
1170*c2c66affSColin Finck 
1171*c2c66affSColin Finck     /* Lock subject context */
1172*c2c66affSColin Finck     SeLockSubjectContext(SubjectContext);
1173*c2c66affSColin Finck 
1174*c2c66affSColin Finck     if (SubjectContext->ClientToken != NULL)
1175*c2c66affSColin Finck     {
1176*c2c66affSColin Finck         Token = SubjectContext->ClientToken;
1177*c2c66affSColin Finck     }
1178*c2c66affSColin Finck     else
1179*c2c66affSColin Finck     {
1180*c2c66affSColin Finck         Token = SubjectContext->PrimaryToken;
1181*c2c66affSColin Finck     }
1182*c2c66affSColin Finck 
1183*c2c66affSColin Finck     /* Inherit the Owner SID */
1184*c2c66affSColin Finck     if (ExplicitDescriptor != NULL)
1185*c2c66affSColin Finck     {
1186*c2c66affSColin Finck         DPRINT("Use explicit owner sid!\n");
1187*c2c66affSColin Finck         Owner = SepGetOwnerFromDescriptor(ExplicitDescriptor);
1188*c2c66affSColin Finck     }
1189*c2c66affSColin Finck     if (!Owner)
1190*c2c66affSColin Finck     {
1191*c2c66affSColin Finck         if (AutoInheritFlags & 0x20 /* FIXME: SEF_DEFAULT_OWNER_FROM_PARENT */)
1192*c2c66affSColin Finck         {
1193*c2c66affSColin Finck             DPRINT("Use parent owner sid!\n");
1194*c2c66affSColin Finck             if (!ARGUMENT_PRESENT(ParentDescriptor))
1195*c2c66affSColin Finck             {
1196*c2c66affSColin Finck                 SeUnlockSubjectContext(SubjectContext);
1197*c2c66affSColin Finck                 return STATUS_INVALID_OWNER;
1198*c2c66affSColin Finck             }
1199*c2c66affSColin Finck 
1200*c2c66affSColin Finck             Owner = SepGetOwnerFromDescriptor(ParentDescriptor);
1201*c2c66affSColin Finck             if (!Owner)
1202*c2c66affSColin Finck             {
1203*c2c66affSColin Finck                 SeUnlockSubjectContext(SubjectContext);
1204*c2c66affSColin Finck                 return STATUS_INVALID_OWNER;
1205*c2c66affSColin Finck             }
1206*c2c66affSColin Finck         }
1207*c2c66affSColin Finck         else
1208*c2c66affSColin Finck         {
1209*c2c66affSColin Finck             DPRINT("Use token owner sid!\n");
1210*c2c66affSColin Finck             Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1211*c2c66affSColin Finck         }
1212*c2c66affSColin Finck     }
1213*c2c66affSColin Finck     OwnerLength = RtlLengthSid(Owner);
1214*c2c66affSColin Finck     ASSERT(OwnerLength % sizeof(ULONG) == 0);
1215*c2c66affSColin Finck 
1216*c2c66affSColin Finck     /* Inherit the Group SID */
1217*c2c66affSColin Finck     if (ExplicitDescriptor != NULL)
1218*c2c66affSColin Finck     {
1219*c2c66affSColin Finck         Group = SepGetGroupFromDescriptor(ExplicitDescriptor);
1220*c2c66affSColin Finck     }
1221*c2c66affSColin Finck     if (!Group)
1222*c2c66affSColin Finck     {
1223*c2c66affSColin Finck         if (AutoInheritFlags & 0x40 /* FIXME: SEF_DEFAULT_GROUP_FROM_PARENT */)
1224*c2c66affSColin Finck         {
1225*c2c66affSColin Finck             DPRINT("Use parent group sid!\n");
1226*c2c66affSColin Finck             if (!ARGUMENT_PRESENT(ParentDescriptor))
1227*c2c66affSColin Finck             {
1228*c2c66affSColin Finck                 SeUnlockSubjectContext(SubjectContext);
1229*c2c66affSColin Finck                 return STATUS_INVALID_PRIMARY_GROUP;
1230*c2c66affSColin Finck             }
1231*c2c66affSColin Finck 
1232*c2c66affSColin Finck             Group = SepGetGroupFromDescriptor(ParentDescriptor);
1233*c2c66affSColin Finck             if (!Group)
1234*c2c66affSColin Finck             {
1235*c2c66affSColin Finck                 SeUnlockSubjectContext(SubjectContext);
1236*c2c66affSColin Finck                 return STATUS_INVALID_PRIMARY_GROUP;
1237*c2c66affSColin Finck             }
1238*c2c66affSColin Finck         }
1239*c2c66affSColin Finck         else
1240*c2c66affSColin Finck         {
1241*c2c66affSColin Finck             DPRINT("Use token group sid!\n");
1242*c2c66affSColin Finck             Group = Token->PrimaryGroup;
1243*c2c66affSColin Finck         }
1244*c2c66affSColin Finck     }
1245*c2c66affSColin Finck     if (!Group)
1246*c2c66affSColin Finck     {
1247*c2c66affSColin Finck         SeUnlockSubjectContext(SubjectContext);
1248*c2c66affSColin Finck         return STATUS_INVALID_PRIMARY_GROUP;
1249*c2c66affSColin Finck     }
1250*c2c66affSColin Finck     GroupLength = RtlLengthSid(Group);
1251*c2c66affSColin Finck     ASSERT(GroupLength % sizeof(ULONG) == 0);
1252*c2c66affSColin Finck 
1253*c2c66affSColin Finck     /* Inherit the DACL */
1254*c2c66affSColin Finck     DaclLength = 0;
1255*c2c66affSColin Finck     ExplicitAcl = NULL;
1256*c2c66affSColin Finck     ExplicitPresent = FALSE;
1257*c2c66affSColin Finck     ExplicitDefaulted = FALSE;
1258*c2c66affSColin Finck     if (ExplicitDescriptor != NULL &&
1259*c2c66affSColin Finck         (ExplicitDescriptor->Control & SE_DACL_PRESENT))
1260*c2c66affSColin Finck     {
1261*c2c66affSColin Finck         ExplicitAcl = SepGetDaclFromDescriptor(ExplicitDescriptor);
1262*c2c66affSColin Finck         ExplicitPresent = TRUE;
1263*c2c66affSColin Finck         if (ExplicitDescriptor->Control & SE_DACL_DEFAULTED)
1264*c2c66affSColin Finck             ExplicitDefaulted = TRUE;
1265*c2c66affSColin Finck     }
1266*c2c66affSColin Finck     ParentAcl = NULL;
1267*c2c66affSColin Finck     if (ParentDescriptor != NULL &&
1268*c2c66affSColin Finck         (ParentDescriptor->Control & SE_DACL_PRESENT))
1269*c2c66affSColin Finck     {
1270*c2c66affSColin Finck         ParentAcl = SepGetDaclFromDescriptor(ParentDescriptor);
1271*c2c66affSColin Finck     }
1272*c2c66affSColin Finck     Dacl = SepSelectAcl(ExplicitAcl,
1273*c2c66affSColin Finck                         ExplicitPresent,
1274*c2c66affSColin Finck                         ExplicitDefaulted,
1275*c2c66affSColin Finck                         ParentAcl,
1276*c2c66affSColin Finck                         Token->DefaultDacl,
1277*c2c66affSColin Finck                         &DaclLength,
1278*c2c66affSColin Finck                         Owner,
1279*c2c66affSColin Finck                         Group,
1280*c2c66affSColin Finck                         &DaclPresent,
1281*c2c66affSColin Finck                         &DaclIsInherited,
1282*c2c66affSColin Finck                         IsDirectoryObject,
1283*c2c66affSColin Finck                         GenericMapping);
1284*c2c66affSColin Finck     if (DaclPresent)
1285*c2c66affSColin Finck         Control |= SE_DACL_PRESENT;
1286*c2c66affSColin Finck     ASSERT(DaclLength % sizeof(ULONG) == 0);
1287*c2c66affSColin Finck 
1288*c2c66affSColin Finck     /* Inherit the SACL */
1289*c2c66affSColin Finck     SaclLength = 0;
1290*c2c66affSColin Finck     ExplicitAcl = NULL;
1291*c2c66affSColin Finck     ExplicitPresent = FALSE;
1292*c2c66affSColin Finck     ExplicitDefaulted = FALSE;
1293*c2c66affSColin Finck     if (ExplicitDescriptor != NULL &&
1294*c2c66affSColin Finck         (ExplicitDescriptor->Control & SE_SACL_PRESENT))
1295*c2c66affSColin Finck     {
1296*c2c66affSColin Finck         ExplicitAcl = SepGetSaclFromDescriptor(ExplicitDescriptor);
1297*c2c66affSColin Finck         ExplicitPresent = TRUE;
1298*c2c66affSColin Finck         if (ExplicitDescriptor->Control & SE_SACL_DEFAULTED)
1299*c2c66affSColin Finck             ExplicitDefaulted = TRUE;
1300*c2c66affSColin Finck     }
1301*c2c66affSColin Finck     ParentAcl = NULL;
1302*c2c66affSColin Finck     if (ParentDescriptor != NULL &&
1303*c2c66affSColin Finck         (ParentDescriptor->Control & SE_SACL_PRESENT))
1304*c2c66affSColin Finck     {
1305*c2c66affSColin Finck         ParentAcl = SepGetSaclFromDescriptor(ParentDescriptor);
1306*c2c66affSColin Finck     }
1307*c2c66affSColin Finck     Sacl = SepSelectAcl(ExplicitAcl,
1308*c2c66affSColin Finck                         ExplicitPresent,
1309*c2c66affSColin Finck                         ExplicitDefaulted,
1310*c2c66affSColin Finck                         ParentAcl,
1311*c2c66affSColin Finck                         NULL,
1312*c2c66affSColin Finck                         &SaclLength,
1313*c2c66affSColin Finck                         Owner,
1314*c2c66affSColin Finck                         Group,
1315*c2c66affSColin Finck                         &SaclPresent,
1316*c2c66affSColin Finck                         &SaclIsInherited,
1317*c2c66affSColin Finck                         IsDirectoryObject,
1318*c2c66affSColin Finck                         GenericMapping);
1319*c2c66affSColin Finck     if (SaclPresent)
1320*c2c66affSColin Finck         Control |= SE_SACL_PRESENT;
1321*c2c66affSColin Finck     ASSERT(SaclLength % sizeof(ULONG) == 0);
1322*c2c66affSColin Finck 
1323*c2c66affSColin Finck     /* Allocate and initialize the new security descriptor */
1324*c2c66affSColin Finck     Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
1325*c2c66affSColin Finck         OwnerLength + GroupLength + DaclLength + SaclLength;
1326*c2c66affSColin Finck 
1327*c2c66affSColin Finck     DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %u OwnerLength %lu GroupLength %lu DaclLength %lu SaclLength %lu\n",
1328*c2c66affSColin Finck            sizeof(SECURITY_DESCRIPTOR),
1329*c2c66affSColin Finck            OwnerLength,
1330*c2c66affSColin Finck            GroupLength,
1331*c2c66affSColin Finck            DaclLength,
1332*c2c66affSColin Finck            SaclLength);
1333*c2c66affSColin Finck 
1334*c2c66affSColin Finck     Descriptor = ExAllocatePoolWithTag(PagedPool, Length, TAG_SD);
1335*c2c66affSColin Finck     if (Descriptor == NULL)
1336*c2c66affSColin Finck     {
1337*c2c66affSColin Finck         DPRINT1("ExAlloctePool() failed\n");
1338*c2c66affSColin Finck         SeUnlockSubjectContext(SubjectContext);
1339*c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
1340*c2c66affSColin Finck     }
1341*c2c66affSColin Finck 
1342*c2c66affSColin Finck     RtlZeroMemory(Descriptor, Length);
1343*c2c66affSColin Finck     RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION);
1344*c2c66affSColin Finck 
1345*c2c66affSColin Finck     Descriptor->Control = Control | SE_SELF_RELATIVE;
1346*c2c66affSColin Finck 
1347*c2c66affSColin Finck     Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1348*c2c66affSColin Finck 
1349*c2c66affSColin Finck     if (SaclLength != 0)
1350*c2c66affSColin Finck     {
1351*c2c66affSColin Finck         Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
1352*c2c66affSColin Finck                                  &SaclLength,
1353*c2c66affSColin Finck                                  Sacl,
1354*c2c66affSColin Finck                                  Owner,
1355*c2c66affSColin Finck                                  Group,
1356*c2c66affSColin Finck                                  SaclIsInherited,
1357*c2c66affSColin Finck                                  IsDirectoryObject,
1358*c2c66affSColin Finck                                  GenericMapping);
1359*c2c66affSColin Finck         ASSERT(Status == STATUS_SUCCESS);
1360*c2c66affSColin Finck         Descriptor->Sacl = Current;
1361*c2c66affSColin Finck         Current += SaclLength;
1362*c2c66affSColin Finck     }
1363*c2c66affSColin Finck 
1364*c2c66affSColin Finck     if (DaclLength != 0)
1365*c2c66affSColin Finck     {
1366*c2c66affSColin Finck         Status = SepPropagateAcl((PACL)((PUCHAR)Descriptor + Current),
1367*c2c66affSColin Finck                                  &DaclLength,
1368*c2c66affSColin Finck                                  Dacl,
1369*c2c66affSColin Finck                                  Owner,
1370*c2c66affSColin Finck                                  Group,
1371*c2c66affSColin Finck                                  DaclIsInherited,
1372*c2c66affSColin Finck                                  IsDirectoryObject,
1373*c2c66affSColin Finck                                  GenericMapping);
1374*c2c66affSColin Finck         ASSERT(Status == STATUS_SUCCESS);
1375*c2c66affSColin Finck         Descriptor->Dacl = Current;
1376*c2c66affSColin Finck         Current += DaclLength;
1377*c2c66affSColin Finck     }
1378*c2c66affSColin Finck 
1379*c2c66affSColin Finck     if (OwnerLength != 0)
1380*c2c66affSColin Finck     {
1381*c2c66affSColin Finck         RtlCopyMemory((PUCHAR)Descriptor + Current, Owner, OwnerLength);
1382*c2c66affSColin Finck         Descriptor->Owner = Current;
1383*c2c66affSColin Finck         Current += OwnerLength;
1384*c2c66affSColin Finck         DPRINT("Owner of %p at %x\n", Descriptor, Descriptor->Owner);
1385*c2c66affSColin Finck     }
1386*c2c66affSColin Finck     else
1387*c2c66affSColin Finck     {
1388*c2c66affSColin Finck         DPRINT("Owner of %p is zero length\n", Descriptor);
1389*c2c66affSColin Finck     }
1390*c2c66affSColin Finck 
1391*c2c66affSColin Finck     if (GroupLength != 0)
1392*c2c66affSColin Finck     {
1393*c2c66affSColin Finck         RtlCopyMemory((PUCHAR)Descriptor + Current, Group, GroupLength);
1394*c2c66affSColin Finck         Descriptor->Group = Current;
1395*c2c66affSColin Finck     }
1396*c2c66affSColin Finck 
1397*c2c66affSColin Finck     /* Unlock subject context */
1398*c2c66affSColin Finck     SeUnlockSubjectContext(SubjectContext);
1399*c2c66affSColin Finck 
1400*c2c66affSColin Finck     *NewDescriptor = Descriptor;
1401*c2c66affSColin Finck 
1402*c2c66affSColin Finck     DPRINT("Descriptor %p\n", Descriptor);
1403*c2c66affSColin Finck     ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1404*c2c66affSColin Finck 
1405*c2c66affSColin Finck     return STATUS_SUCCESS;
1406*c2c66affSColin Finck }
1407*c2c66affSColin Finck 
1408*c2c66affSColin Finck /*
1409*c2c66affSColin Finck  * @implemented
1410*c2c66affSColin Finck  */
1411*c2c66affSColin Finck _IRQL_requires_max_(PASSIVE_LEVEL)
1412*c2c66affSColin Finck NTSTATUS
1413*c2c66affSColin Finck NTAPI
1414*c2c66affSColin Finck SeAssignSecurity(
1415*c2c66affSColin Finck     _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor,
1416*c2c66affSColin Finck     _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor,
1417*c2c66affSColin Finck     _Out_ PSECURITY_DESCRIPTOR *NewDescriptor,
1418*c2c66affSColin Finck     _In_ BOOLEAN IsDirectoryObject,
1419*c2c66affSColin Finck     _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
1420*c2c66affSColin Finck     _In_ PGENERIC_MAPPING GenericMapping,
1421*c2c66affSColin Finck     _In_ POOL_TYPE PoolType)
1422*c2c66affSColin Finck {
1423*c2c66affSColin Finck     PAGED_CODE();
1424*c2c66affSColin Finck 
1425*c2c66affSColin Finck     return SeAssignSecurityEx(ParentDescriptor,
1426*c2c66affSColin Finck                               ExplicitDescriptor,
1427*c2c66affSColin Finck                               NewDescriptor,
1428*c2c66affSColin Finck                               NULL,
1429*c2c66affSColin Finck                               IsDirectoryObject,
1430*c2c66affSColin Finck                               0,
1431*c2c66affSColin Finck                               SubjectContext,
1432*c2c66affSColin Finck                               GenericMapping,
1433*c2c66affSColin Finck                               PoolType);
1434*c2c66affSColin Finck }
1435*c2c66affSColin Finck 
1436*c2c66affSColin Finck /* EOF */
1437