xref: /reactos/ntoskrnl/ob/obsecure.c (revision 2c909db2)
1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT:         ReactOS Kernel
3c2c66affSColin Finck * LICENSE:         GPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE:            ntoskrnl/ob/obsecure.c
5c2c66affSColin Finck * PURPOSE:         SRM Interface of the Object Manager
6c2c66affSColin Finck * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
7c2c66affSColin Finck *                  Eric Kohl
8c2c66affSColin Finck */
9c2c66affSColin Finck 
10c2c66affSColin Finck /* INCLUDES *****************************************************************/
11c2c66affSColin Finck 
12c2c66affSColin Finck #include <ntoskrnl.h>
13c2c66affSColin Finck #define NDEBUG
14c2c66affSColin Finck #include <debug.h>
15c2c66affSColin Finck 
16c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/
17c2c66affSColin Finck 
18c2c66affSColin Finck NTSTATUS
19c2c66affSColin Finck NTAPI
20c2c66affSColin Finck ObAssignObjectSecurityDescriptor(IN PVOID Object,
21c2c66affSColin Finck                                  IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
22c2c66affSColin Finck                                  IN POOL_TYPE PoolType)
23c2c66affSColin Finck {
24c2c66affSColin Finck     POBJECT_HEADER ObjectHeader;
25c2c66affSColin Finck     NTSTATUS Status;
26c2c66affSColin Finck     PSECURITY_DESCRIPTOR NewSd;
27c2c66affSColin Finck     PEX_FAST_REF FastRef;
28c2c66affSColin Finck     PAGED_CODE();
29c2c66affSColin Finck 
30c2c66affSColin Finck     /* Get the object header */
31c2c66affSColin Finck     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
32c2c66affSColin Finck     FastRef = (PEX_FAST_REF)&ObjectHeader->SecurityDescriptor;
33c2c66affSColin Finck     if (!SecurityDescriptor)
34c2c66affSColin Finck     {
35c2c66affSColin Finck         /* Nothing to assign */
36c2c66affSColin Finck         ExInitializeFastReference(FastRef, NULL);
37c2c66affSColin Finck         return STATUS_SUCCESS;
38c2c66affSColin Finck     }
39c2c66affSColin Finck 
40c2c66affSColin Finck     /* Add it to our internal cache */
41c2c66affSColin Finck     Status = ObLogSecurityDescriptor(SecurityDescriptor,
42c2c66affSColin Finck                                      &NewSd,
43c2c66affSColin Finck                                      MAX_FAST_REFS + 1);
44c2c66affSColin Finck     if (NT_SUCCESS(Status))
45c2c66affSColin Finck     {
46c2c66affSColin Finck         /* Free the old copy */
47c2c66affSColin Finck         ExFreePoolWithTag(SecurityDescriptor, TAG_SD);
48c2c66affSColin Finck 
49c2c66affSColin Finck         /* Set the new pointer */
50c2c66affSColin Finck         ASSERT(NewSd);
51c2c66affSColin Finck         ExInitializeFastReference(FastRef, NewSd);
52c2c66affSColin Finck     }
53c2c66affSColin Finck 
54c2c66affSColin Finck     /* Return status */
55c2c66affSColin Finck     return Status;
56c2c66affSColin Finck }
57c2c66affSColin Finck 
58c2c66affSColin Finck NTSTATUS
59c2c66affSColin Finck NTAPI
60c2c66affSColin Finck ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
61c2c66affSColin Finck {
62c2c66affSColin Finck     EX_FAST_REF FastRef;
63c2c66affSColin Finck     ULONG Count;
64c2c66affSColin Finck     PSECURITY_DESCRIPTOR OldSecurityDescriptor;
65c2c66affSColin Finck 
66c2c66affSColin Finck     /* Get the fast reference and capture it */
67c2c66affSColin Finck     FastRef = *(PEX_FAST_REF)SecurityDescriptor;
68c2c66affSColin Finck 
69c2c66affSColin Finck     /* Don't free again later */
70c2c66affSColin Finck     *SecurityDescriptor = NULL;
71c2c66affSColin Finck 
72c2c66affSColin Finck     /* Get the descriptor and reference count */
73c2c66affSColin Finck     OldSecurityDescriptor = ExGetObjectFastReference(FastRef);
74c2c66affSColin Finck     Count = ExGetCountFastReference(FastRef);
75c2c66affSColin Finck 
76c2c66affSColin Finck     /* Dereference the descriptor */
77c2c66affSColin Finck     ObDereferenceSecurityDescriptor(OldSecurityDescriptor, Count + 1);
78c2c66affSColin Finck 
79c2c66affSColin Finck     /* All done */
80c2c66affSColin Finck     return STATUS_SUCCESS;
81c2c66affSColin Finck }
82c2c66affSColin Finck 
83c2c66affSColin Finck NTSTATUS
84c2c66affSColin Finck NTAPI
85c2c66affSColin Finck ObQuerySecurityDescriptorInfo(IN PVOID Object,
86c2c66affSColin Finck                               IN PSECURITY_INFORMATION SecurityInformation,
87c2c66affSColin Finck                               OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
88c2c66affSColin Finck                               IN OUT PULONG Length,
89c2c66affSColin Finck                               IN PSECURITY_DESCRIPTOR *OutputSecurityDescriptor)
90c2c66affSColin Finck {
91c2c66affSColin Finck     POBJECT_HEADER ObjectHeader;
92c2c66affSColin Finck     NTSTATUS Status;
93c2c66affSColin Finck     PSECURITY_DESCRIPTOR ObjectSd;
94c2c66affSColin Finck     PAGED_CODE();
95c2c66affSColin Finck 
96c2c66affSColin Finck     /* Get the object header */
97c2c66affSColin Finck     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
98c2c66affSColin Finck 
99c2c66affSColin Finck     /* Get the SD */
100c2c66affSColin Finck     ObjectSd = ObpReferenceSecurityDescriptor(ObjectHeader);
101c2c66affSColin Finck 
102c2c66affSColin Finck     /* Query the information */
103c2c66affSColin Finck     Status = SeQuerySecurityDescriptorInfo(SecurityInformation,
104c2c66affSColin Finck                                            SecurityDescriptor,
105c2c66affSColin Finck                                            Length,
106c2c66affSColin Finck                                            &ObjectSd);
107c2c66affSColin Finck 
108c2c66affSColin Finck     /* Check if we have an object SD and dereference it, if so */
109c2c66affSColin Finck     if (ObjectSd) ObDereferenceSecurityDescriptor(ObjectSd, 1);
110c2c66affSColin Finck 
111c2c66affSColin Finck     /* Return status */
112c2c66affSColin Finck     return Status;
113c2c66affSColin Finck }
114c2c66affSColin Finck 
115c2c66affSColin Finck NTSTATUS
116c2c66affSColin Finck NTAPI
117c2c66affSColin Finck ObSetSecurityDescriptorInfo(IN PVOID Object,
118c2c66affSColin Finck                             IN PSECURITY_INFORMATION SecurityInformation,
119c2c66affSColin Finck                             IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
120c2c66affSColin Finck                             IN OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor,
121c2c66affSColin Finck                             IN POOL_TYPE PoolType,
122c2c66affSColin Finck                             IN PGENERIC_MAPPING GenericMapping)
123c2c66affSColin Finck {
124c2c66affSColin Finck     NTSTATUS Status;
125c2c66affSColin Finck     POBJECT_HEADER ObjectHeader;
126c2c66affSColin Finck     PSECURITY_DESCRIPTOR OldDescriptor, NewDescriptor, CachedDescriptor;
127c2c66affSColin Finck     PEX_FAST_REF FastRef;
128c2c66affSColin Finck     EX_FAST_REF OldValue;
129c2c66affSColin Finck     ULONG Count;
130c2c66affSColin Finck     PAGED_CODE();
131c2c66affSColin Finck 
132c2c66affSColin Finck     /* Get the object header */
133c2c66affSColin Finck     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
134c2c66affSColin Finck     while (TRUE)
135c2c66affSColin Finck     {
136c2c66affSColin Finck         /* Reference the old descriptor */
137c2c66affSColin Finck         OldDescriptor = ObpReferenceSecurityDescriptor(ObjectHeader);
138c2c66affSColin Finck         NewDescriptor = OldDescriptor;
139c2c66affSColin Finck 
140c2c66affSColin Finck         /* Set the SD information */
141c2c66affSColin Finck         Status = SeSetSecurityDescriptorInfo(Object,
142c2c66affSColin Finck                                              SecurityInformation,
143c2c66affSColin Finck                                              SecurityDescriptor,
144c2c66affSColin Finck                                              &NewDescriptor,
145c2c66affSColin Finck                                              PoolType,
146c2c66affSColin Finck                                              GenericMapping);
147c2c66affSColin Finck         if (!NT_SUCCESS(Status))
148c2c66affSColin Finck         {
149c2c66affSColin Finck             /* We failed, dereference the old one */
150c2c66affSColin Finck             if (OldDescriptor) ObDereferenceSecurityDescriptor(OldDescriptor, 1);
151c2c66affSColin Finck             break;
152c2c66affSColin Finck         }
153c2c66affSColin Finck 
154c2c66affSColin Finck         /* Now add this to the cache */
155c2c66affSColin Finck         Status = ObLogSecurityDescriptor(NewDescriptor,
156c2c66affSColin Finck                                          &CachedDescriptor,
157c2c66affSColin Finck                                          MAX_FAST_REFS + 1);
158c2c66affSColin Finck 
159c2c66affSColin Finck         /* Let go of our uncached copy */
160c2c66affSColin Finck         ExFreePool(NewDescriptor);
161c2c66affSColin Finck 
162c2c66affSColin Finck         /* Check for success */
163c2c66affSColin Finck         if (!NT_SUCCESS(Status))
164c2c66affSColin Finck         {
165c2c66affSColin Finck             /* We failed, dereference the old one */
166c2c66affSColin Finck             ObDereferenceSecurityDescriptor(OldDescriptor, 1);
167c2c66affSColin Finck             break;
168c2c66affSColin Finck         }
169c2c66affSColin Finck 
170c2c66affSColin Finck         /* Do the swap */
171c2c66affSColin Finck         FastRef = (PEX_FAST_REF)OutputSecurityDescriptor;
172c2c66affSColin Finck         OldValue = ExCompareSwapFastReference(FastRef,
173c2c66affSColin Finck                                               CachedDescriptor,
174c2c66affSColin Finck                                               OldDescriptor);
175c2c66affSColin Finck 
176c2c66affSColin Finck         /* Make sure the swap worked */
177c2c66affSColin Finck         if (ExGetObjectFastReference(OldValue) == OldDescriptor)
178c2c66affSColin Finck         {
179c2c66affSColin Finck             /* Flush waiters */
180c2c66affSColin Finck             ObpAcquireObjectLock(ObjectHeader);
181c2c66affSColin Finck             ObpReleaseObjectLock(ObjectHeader);
182c2c66affSColin Finck 
183c2c66affSColin Finck             /* And dereference the old one */
184c2c66affSColin Finck             Count = ExGetCountFastReference(OldValue);
185c2c66affSColin Finck             ObDereferenceSecurityDescriptor(OldDescriptor, Count + 2);
186c2c66affSColin Finck             break;
187c2c66affSColin Finck         }
188c2c66affSColin Finck         else
189c2c66affSColin Finck         {
190c2c66affSColin Finck             /* Someone changed it behind our back -- try again */
191c2c66affSColin Finck             ObDereferenceSecurityDescriptor(OldDescriptor, 1);
192c2c66affSColin Finck             ObDereferenceSecurityDescriptor(CachedDescriptor,
193c2c66affSColin Finck                                             MAX_FAST_REFS + 1);
194c2c66affSColin Finck         }
195c2c66affSColin Finck     }
196c2c66affSColin Finck 
197c2c66affSColin Finck     /* Return status */
198c2c66affSColin Finck     return Status;
199c2c66affSColin Finck }
200c2c66affSColin Finck 
201c2c66affSColin Finck BOOLEAN
202c2c66affSColin Finck NTAPI
203c2c66affSColin Finck ObCheckCreateObjectAccess(IN PVOID Object,
204c2c66affSColin Finck                           IN ACCESS_MASK CreateAccess,
205c2c66affSColin Finck                           IN PACCESS_STATE AccessState,
206c2c66affSColin Finck                           IN PUNICODE_STRING ComponentName,
207c2c66affSColin Finck                           IN BOOLEAN LockHeld,
208c2c66affSColin Finck                           IN KPROCESSOR_MODE AccessMode,
209c2c66affSColin Finck                           OUT PNTSTATUS AccessStatus)
210c2c66affSColin Finck {
211c2c66affSColin Finck     POBJECT_HEADER ObjectHeader;
212c2c66affSColin Finck     POBJECT_TYPE ObjectType;
213c2c66affSColin Finck     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
214c2c66affSColin Finck     BOOLEAN SdAllocated;
215c2c66affSColin Finck     BOOLEAN Result = TRUE;
216c2c66affSColin Finck     ACCESS_MASK GrantedAccess = 0;
217c2c66affSColin Finck     PPRIVILEGE_SET Privileges = NULL;
218c2c66affSColin Finck     NTSTATUS Status;
219c2c66affSColin Finck     PAGED_CODE();
220c2c66affSColin Finck 
221c2c66affSColin Finck     /* Get the header and type */
222c2c66affSColin Finck     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
223c2c66affSColin Finck     ObjectType = ObjectHeader->Type;
224c2c66affSColin Finck 
225c2c66affSColin Finck     /* Get the security descriptor */
226c2c66affSColin Finck     Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
227c2c66affSColin Finck     if (!NT_SUCCESS(Status))
228c2c66affSColin Finck     {
229c2c66affSColin Finck         /* We failed */
230c2c66affSColin Finck         *AccessStatus = Status;
231c2c66affSColin Finck         return FALSE;
232c2c66affSColin Finck     }
233c2c66affSColin Finck 
234c2c66affSColin Finck     /* Lock the security context */
235c2c66affSColin Finck     SeLockSubjectContext(&AccessState->SubjectSecurityContext);
236c2c66affSColin Finck 
237c2c66affSColin Finck     /* Check if we have an SD */
238c2c66affSColin Finck     if (SecurityDescriptor)
239c2c66affSColin Finck     {
240c2c66affSColin Finck         /* Now do the entire access check */
241c2c66affSColin Finck         Result = SeAccessCheck(SecurityDescriptor,
242c2c66affSColin Finck                                &AccessState->SubjectSecurityContext,
243c2c66affSColin Finck                                TRUE,
244c2c66affSColin Finck                                CreateAccess,
245c2c66affSColin Finck                                0,
246c2c66affSColin Finck                                &Privileges,
247c2c66affSColin Finck                                &ObjectType->TypeInfo.GenericMapping,
248c2c66affSColin Finck                                AccessMode,
249c2c66affSColin Finck                                &GrantedAccess,
250c2c66affSColin Finck                                AccessStatus);
251c2c66affSColin Finck         if (Privileges)
252c2c66affSColin Finck         {
253c2c66affSColin Finck             /* We got privileges, append them to the access state and free them */
254c2c66affSColin Finck             Status = SeAppendPrivileges(AccessState, Privileges);
255c2c66affSColin Finck             SeFreePrivileges(Privileges);
256c2c66affSColin Finck         }
257c2c66affSColin Finck     }
258c2c66affSColin Finck 
259c2c66affSColin Finck     /* We're done, unlock the context and release security */
260c2c66affSColin Finck     SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
261c2c66affSColin Finck     ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
262c2c66affSColin Finck     return Result;
263c2c66affSColin Finck }
264c2c66affSColin Finck 
265c2c66affSColin Finck BOOLEAN
266c2c66affSColin Finck NTAPI
267c2c66affSColin Finck ObpCheckTraverseAccess(IN PVOID Object,
268c2c66affSColin Finck                        IN ACCESS_MASK TraverseAccess,
269c2c66affSColin Finck                        IN PACCESS_STATE AccessState OPTIONAL,
270c2c66affSColin Finck                        IN BOOLEAN LockHeld,
271c2c66affSColin Finck                        IN KPROCESSOR_MODE AccessMode,
272c2c66affSColin Finck                        OUT PNTSTATUS AccessStatus)
273c2c66affSColin Finck {
274c2c66affSColin Finck     POBJECT_HEADER ObjectHeader;
275c2c66affSColin Finck     POBJECT_TYPE ObjectType;
276c2c66affSColin Finck     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
277c2c66affSColin Finck     BOOLEAN SdAllocated;
278c2c66affSColin Finck     BOOLEAN Result;
279c2c66affSColin Finck     ACCESS_MASK GrantedAccess = 0;
280c2c66affSColin Finck     PPRIVILEGE_SET Privileges = NULL;
281c2c66affSColin Finck     NTSTATUS Status;
282c2c66affSColin Finck     PAGED_CODE();
283c2c66affSColin Finck 
284c2c66affSColin Finck     /* Get the header and type */
285c2c66affSColin Finck     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
286c2c66affSColin Finck     ObjectType = ObjectHeader->Type;
287c2c66affSColin Finck 
288c2c66affSColin Finck     /* Get the security descriptor */
289c2c66affSColin Finck     Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
290c2c66affSColin Finck     if (!NT_SUCCESS(Status))
291c2c66affSColin Finck     {
292c2c66affSColin Finck         /* We failed */
293c2c66affSColin Finck         *AccessStatus = Status;
294c2c66affSColin Finck         return FALSE;
295c2c66affSColin Finck     }
296c2c66affSColin Finck 
297c2c66affSColin Finck     /* First try to perform a fast traverse check
298c2c66affSColin Finck      * If it fails, then the entire access check will
299c2c66affSColin Finck      * have to be done.
300c2c66affSColin Finck      */
301c2c66affSColin Finck     Result = SeFastTraverseCheck(SecurityDescriptor,
302c2c66affSColin Finck                                  AccessState,
303c2c66affSColin Finck                                  FILE_WRITE_DATA,
304c2c66affSColin Finck                                  AccessMode);
305c2c66affSColin Finck     if (Result)
306c2c66affSColin Finck     {
307c2c66affSColin Finck         ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
308c2c66affSColin Finck         return TRUE;
309c2c66affSColin Finck     }
310c2c66affSColin Finck 
311c2c66affSColin Finck     /* Lock the security context */
312c2c66affSColin Finck     SeLockSubjectContext(&AccessState->SubjectSecurityContext);
313c2c66affSColin Finck 
314c2c66affSColin Finck     /* Now do the entire access check */
315c2c66affSColin Finck     Result = SeAccessCheck(SecurityDescriptor,
316c2c66affSColin Finck                            &AccessState->SubjectSecurityContext,
317c2c66affSColin Finck                            TRUE,
318c2c66affSColin Finck                            TraverseAccess,
319c2c66affSColin Finck                            0,
320c2c66affSColin Finck                            &Privileges,
321c2c66affSColin Finck                            &ObjectType->TypeInfo.GenericMapping,
322c2c66affSColin Finck                            AccessMode,
323c2c66affSColin Finck                            &GrantedAccess,
324c2c66affSColin Finck                            AccessStatus);
325c2c66affSColin Finck     if (Privileges)
326c2c66affSColin Finck     {
327c2c66affSColin Finck         /* We got privileges, append them to the access state and free them */
328c2c66affSColin Finck         Status = SeAppendPrivileges(AccessState, Privileges);
329c2c66affSColin Finck         SeFreePrivileges(Privileges);
330c2c66affSColin Finck     }
331c2c66affSColin Finck 
332c2c66affSColin Finck     /* We're done, unlock the context and release security */
333c2c66affSColin Finck     SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
334c2c66affSColin Finck     ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
335c2c66affSColin Finck     return Result;
336c2c66affSColin Finck }
337c2c66affSColin Finck 
338c2c66affSColin Finck BOOLEAN
339c2c66affSColin Finck NTAPI
340c2c66affSColin Finck ObpCheckObjectReference(IN PVOID Object,
341c2c66affSColin Finck                         IN OUT PACCESS_STATE AccessState,
342c2c66affSColin Finck                         IN BOOLEAN LockHeld,
343c2c66affSColin Finck                         IN KPROCESSOR_MODE AccessMode,
344c2c66affSColin Finck                         OUT PNTSTATUS AccessStatus)
345c2c66affSColin Finck {
346c2c66affSColin Finck     POBJECT_HEADER ObjectHeader;
347c2c66affSColin Finck     POBJECT_TYPE ObjectType;
348c2c66affSColin Finck     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
349c2c66affSColin Finck     BOOLEAN SdAllocated;
350c2c66affSColin Finck     BOOLEAN Result;
351c2c66affSColin Finck     ACCESS_MASK GrantedAccess = 0;
352c2c66affSColin Finck     PPRIVILEGE_SET Privileges = NULL;
353c2c66affSColin Finck     NTSTATUS Status;
354c2c66affSColin Finck     PAGED_CODE();
355c2c66affSColin Finck 
356c2c66affSColin Finck     /* Get the header and type */
357c2c66affSColin Finck     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
358c2c66affSColin Finck     ObjectType = ObjectHeader->Type;
359c2c66affSColin Finck 
360c2c66affSColin Finck     /* Get the security descriptor */
361c2c66affSColin Finck     Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
362c2c66affSColin Finck     if (!NT_SUCCESS(Status))
363c2c66affSColin Finck     {
364c2c66affSColin Finck         /* We failed */
365c2c66affSColin Finck         *AccessStatus = Status;
366c2c66affSColin Finck         return FALSE;
367c2c66affSColin Finck     }
368c2c66affSColin Finck 
369c2c66affSColin Finck     /* Lock the security context */
370c2c66affSColin Finck     SeLockSubjectContext(&AccessState->SubjectSecurityContext);
371c2c66affSColin Finck 
372c2c66affSColin Finck     /* Now do the entire access check */
373c2c66affSColin Finck     Result = SeAccessCheck(SecurityDescriptor,
374c2c66affSColin Finck                            &AccessState->SubjectSecurityContext,
375c2c66affSColin Finck                            TRUE,
376c2c66affSColin Finck                            AccessState->RemainingDesiredAccess,
377c2c66affSColin Finck                            AccessState->PreviouslyGrantedAccess,
378c2c66affSColin Finck                            &Privileges,
379c2c66affSColin Finck                            &ObjectType->TypeInfo.GenericMapping,
380c2c66affSColin Finck                            AccessMode,
381c2c66affSColin Finck                            &GrantedAccess,
382c2c66affSColin Finck                            AccessStatus);
383c2c66affSColin Finck     if (Result)
384c2c66affSColin Finck     {
385c2c66affSColin Finck         /* Update the access state */
386c2c66affSColin Finck         AccessState->RemainingDesiredAccess &= ~GrantedAccess;
387c2c66affSColin Finck         AccessState->PreviouslyGrantedAccess |= GrantedAccess;
388c2c66affSColin Finck     }
389c2c66affSColin Finck 
390c2c66affSColin Finck     /* Check if we have an SD */
391c2c66affSColin Finck     if (SecurityDescriptor)
392c2c66affSColin Finck     {
393c2c66affSColin Finck         /* Do audit alarm */
394c2c66affSColin Finck #if 0
395c2c66affSColin Finck         SeObjectReferenceAuditAlarm(&AccessState->OperationID,
396c2c66affSColin Finck                                     Object,
397c2c66affSColin Finck                                     SecurityDescriptor,
398c2c66affSColin Finck                                     &AccessState->SubjectSecurityContext,
399c2c66affSColin Finck                                     AccessState->RemainingDesiredAccess |
400c2c66affSColin Finck                                     AccessState->PreviouslyGrantedAccess,
401c2c66affSColin Finck                                     ((PAUX_ACCESS_DATA)(AccessState->AuxData))->
402c2c66affSColin Finck                                     PrivilegeSet,
403c2c66affSColin Finck                                     Result,
404c2c66affSColin Finck                                     AccessMode);
405c2c66affSColin Finck #endif
406c2c66affSColin Finck     }
407c2c66affSColin Finck 
408c2c66affSColin Finck     /* We're done, unlock the context and release security */
409c2c66affSColin Finck     SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
410c2c66affSColin Finck     ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
411c2c66affSColin Finck     return Result;
412c2c66affSColin Finck }
413c2c66affSColin Finck 
414c2c66affSColin Finck /*++
415c2c66affSColin Finck * @name ObCheckObjectAccess
416c2c66affSColin Finck *
417c2c66affSColin Finck *     The ObCheckObjectAccess routine <FILLMEIN>
418c2c66affSColin Finck *
419c2c66affSColin Finck * @param Object
420c2c66affSColin Finck *        <FILLMEIN>
421c2c66affSColin Finck *
422c2c66affSColin Finck * @param AccessState
423c2c66affSColin Finck *        <FILLMEIN>
424c2c66affSColin Finck *
425c2c66affSColin Finck * @param LockHeld
426c2c66affSColin Finck *        <FILLMEIN>
427c2c66affSColin Finck *
428c2c66affSColin Finck * @param AccessMode
429c2c66affSColin Finck *        <FILLMEIN>
430c2c66affSColin Finck *
431c2c66affSColin Finck * @param ReturnedStatus
432c2c66affSColin Finck *        <FILLMEIN>
433c2c66affSColin Finck *
434c2c66affSColin Finck * @return TRUE if access was granted, FALSE otherwise.
435c2c66affSColin Finck *
436c2c66affSColin Finck * @remarks None.
437c2c66affSColin Finck *
438c2c66affSColin Finck *--*/
439c2c66affSColin Finck BOOLEAN
440c2c66affSColin Finck NTAPI
441c2c66affSColin Finck ObCheckObjectAccess(IN PVOID Object,
442c2c66affSColin Finck                     IN OUT PACCESS_STATE AccessState,
443c2c66affSColin Finck                     IN BOOLEAN LockHeld,
444c2c66affSColin Finck                     IN KPROCESSOR_MODE AccessMode,
445c2c66affSColin Finck                     OUT PNTSTATUS ReturnedStatus)
446c2c66affSColin Finck {
447c2c66affSColin Finck     POBJECT_HEADER ObjectHeader;
448c2c66affSColin Finck     POBJECT_TYPE ObjectType;
449c2c66affSColin Finck     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
450c2c66affSColin Finck     BOOLEAN SdAllocated;
451c2c66affSColin Finck     NTSTATUS Status;
452c2c66affSColin Finck     BOOLEAN Result;
453c2c66affSColin Finck     ACCESS_MASK GrantedAccess;
454c2c66affSColin Finck     PPRIVILEGE_SET Privileges = NULL;
455c2c66affSColin Finck     PAGED_CODE();
456c2c66affSColin Finck 
457c2c66affSColin Finck     /* Get the object header and type */
458c2c66affSColin Finck     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
459c2c66affSColin Finck     ObjectType = ObjectHeader->Type;
460c2c66affSColin Finck 
461c2c66affSColin Finck     /* Get security information */
462c2c66affSColin Finck     Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
463c2c66affSColin Finck     if (!NT_SUCCESS(Status))
464c2c66affSColin Finck     {
465c2c66affSColin Finck         /* Return failure */
466c2c66affSColin Finck         *ReturnedStatus = Status;
467c2c66affSColin Finck         return FALSE;
468c2c66affSColin Finck     }
469c2c66affSColin Finck     else if (!SecurityDescriptor)
470c2c66affSColin Finck     {
471c2c66affSColin Finck         /* Otherwise, if we don't actually have an SD, return success */
472c2c66affSColin Finck         *ReturnedStatus = Status;
473c2c66affSColin Finck         return TRUE;
474c2c66affSColin Finck     }
475c2c66affSColin Finck 
476c2c66affSColin Finck     /* Lock the security context */
477c2c66affSColin Finck     SeLockSubjectContext(&AccessState->SubjectSecurityContext);
478c2c66affSColin Finck 
479c2c66affSColin Finck     /* Now do the entire access check */
480c2c66affSColin Finck     Result = SeAccessCheck(SecurityDescriptor,
481c2c66affSColin Finck                            &AccessState->SubjectSecurityContext,
482c2c66affSColin Finck                            TRUE,
483c2c66affSColin Finck                            AccessState->RemainingDesiredAccess,
484c2c66affSColin Finck                            AccessState->PreviouslyGrantedAccess,
485c2c66affSColin Finck                            &Privileges,
486c2c66affSColin Finck                            &ObjectType->TypeInfo.GenericMapping,
487c2c66affSColin Finck                            AccessMode,
488c2c66affSColin Finck                            &GrantedAccess,
489c2c66affSColin Finck                            ReturnedStatus);
490c2c66affSColin Finck     if (Privileges)
491c2c66affSColin Finck     {
492c2c66affSColin Finck         /* We got privileges, append them to the access state and free them */
493c2c66affSColin Finck         Status = SeAppendPrivileges(AccessState, Privileges);
494c2c66affSColin Finck         SeFreePrivileges(Privileges);
495c2c66affSColin Finck     }
496c2c66affSColin Finck 
497c2c66affSColin Finck     /* Check if access was granted */
498c2c66affSColin Finck     if (Result)
499c2c66affSColin Finck     {
500c2c66affSColin Finck         /* Update the access state */
501c2c66affSColin Finck         AccessState->RemainingDesiredAccess &= ~(GrantedAccess |
502c2c66affSColin Finck                                                  MAXIMUM_ALLOWED);
503c2c66affSColin Finck         AccessState->PreviouslyGrantedAccess |= GrantedAccess;
504c2c66affSColin Finck     }
505c2c66affSColin Finck 
506c2c66affSColin Finck     /* Do audit alarm */
507c2c66affSColin Finck     SeOpenObjectAuditAlarm(&ObjectType->Name,
508c2c66affSColin Finck                            Object,
509c2c66affSColin Finck                            NULL,
510c2c66affSColin Finck                            SecurityDescriptor,
511c2c66affSColin Finck                            AccessState,
512c2c66affSColin Finck                            FALSE,
513c2c66affSColin Finck                            Result,
514c2c66affSColin Finck                            AccessMode,
515c2c66affSColin Finck                            &AccessState->GenerateOnClose);
516c2c66affSColin Finck 
517c2c66affSColin Finck     /* We're done, unlock the context and release security */
518c2c66affSColin Finck     SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
519c2c66affSColin Finck     ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
520c2c66affSColin Finck     return Result;
521c2c66affSColin Finck }
522c2c66affSColin Finck 
523c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/
524c2c66affSColin Finck 
525c2c66affSColin Finck /*++
526c2c66affSColin Finck * @name ObAssignSecurity
527c2c66affSColin Finck * @implemented NT4
528c2c66affSColin Finck *
529c2c66affSColin Finck *     The ObAssignSecurity routine <FILLMEIN>
530c2c66affSColin Finck *
531c2c66affSColin Finck * @param AccessState
532c2c66affSColin Finck *        <FILLMEIN>
533c2c66affSColin Finck *
534c2c66affSColin Finck * @param SecurityDescriptor
535c2c66affSColin Finck *        <FILLMEIN>
536c2c66affSColin Finck *
537c2c66affSColin Finck * @param Object
538c2c66affSColin Finck *        <FILLMEIN>
539c2c66affSColin Finck *
540c2c66affSColin Finck * @param Type
541c2c66affSColin Finck *        <FILLMEIN>
542c2c66affSColin Finck *
543c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value.
544c2c66affSColin Finck *
545c2c66affSColin Finck * @remarks None.
546c2c66affSColin Finck *
547c2c66affSColin Finck *--*/
548c2c66affSColin Finck NTSTATUS
549c2c66affSColin Finck NTAPI
550c2c66affSColin Finck ObAssignSecurity(IN PACCESS_STATE AccessState,
551c2c66affSColin Finck                  IN PSECURITY_DESCRIPTOR SecurityDescriptor,
552c2c66affSColin Finck                  IN PVOID Object,
553c2c66affSColin Finck                  IN POBJECT_TYPE Type)
554c2c66affSColin Finck {
555c2c66affSColin Finck     PSECURITY_DESCRIPTOR NewDescriptor;
556c2c66affSColin Finck     NTSTATUS Status;
557c2c66affSColin Finck     KIRQL CalloutIrql;
558c2c66affSColin Finck     PAGED_CODE();
559c2c66affSColin Finck 
560c2c66affSColin Finck     /* Build the new security descriptor */
561c2c66affSColin Finck     Status = SeAssignSecurity(SecurityDescriptor,
562c2c66affSColin Finck                               AccessState->SecurityDescriptor,
563c2c66affSColin Finck                               &NewDescriptor,
564*2c909db2STimo Kreuzer                               (Type == ObpDirectoryObjectType),
565c2c66affSColin Finck                               &AccessState->SubjectSecurityContext,
566c2c66affSColin Finck                               &Type->TypeInfo.GenericMapping,
567c2c66affSColin Finck                               PagedPool);
568c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
569c2c66affSColin Finck 
570c2c66affSColin Finck     /* Call the security method */
571c2c66affSColin Finck     ObpCalloutStart(&CalloutIrql);
572c2c66affSColin Finck     Status = Type->TypeInfo.SecurityProcedure(Object,
573c2c66affSColin Finck                                               AssignSecurityDescriptor,
574c2c66affSColin Finck                                               NULL,
575c2c66affSColin Finck                                               NewDescriptor,
576c2c66affSColin Finck                                               NULL,
577c2c66affSColin Finck                                               NULL,
578c2c66affSColin Finck                                               PagedPool,
579c2c66affSColin Finck                                               &Type->TypeInfo.GenericMapping);
580c2c66affSColin Finck     ObpCalloutEnd(CalloutIrql, "Security", Type, Object);
581c2c66affSColin Finck 
582c2c66affSColin Finck     /* Check for failure and deassign security if so */
583c2c66affSColin Finck     if (!NT_SUCCESS(Status)) SeDeassignSecurity(&NewDescriptor);
584c2c66affSColin Finck 
585c2c66affSColin Finck     /* Return to caller */
586c2c66affSColin Finck     return Status;
587c2c66affSColin Finck }
588c2c66affSColin Finck 
589c2c66affSColin Finck /*++
590c2c66affSColin Finck * @name ObGetObjectSecurity
591c2c66affSColin Finck * @implemented NT4
592c2c66affSColin Finck *
593c2c66affSColin Finck *     The ObGetObjectSecurity routine <FILLMEIN>
594c2c66affSColin Finck *
595c2c66affSColin Finck * @param Object
596c2c66affSColin Finck *        <FILLMEIN>
597c2c66affSColin Finck *
598c2c66affSColin Finck * @param SecurityDescriptor
599c2c66affSColin Finck *        <FILLMEIN>
600c2c66affSColin Finck *
601c2c66affSColin Finck * @param MemoryAllocated
602c2c66affSColin Finck *        <FILLMEIN>
603c2c66affSColin Finck *
604c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value.
605c2c66affSColin Finck *
606c2c66affSColin Finck * @remarks None.
607c2c66affSColin Finck *
608c2c66affSColin Finck *--*/
609c2c66affSColin Finck NTSTATUS
610c2c66affSColin Finck NTAPI
611c2c66affSColin Finck ObGetObjectSecurity(IN PVOID Object,
612c2c66affSColin Finck                     OUT PSECURITY_DESCRIPTOR *SecurityDescriptor,
613c2c66affSColin Finck                     OUT PBOOLEAN MemoryAllocated)
614c2c66affSColin Finck {
615c2c66affSColin Finck     POBJECT_HEADER Header;
616c2c66affSColin Finck     POBJECT_TYPE Type;
617c2c66affSColin Finck     ULONG Length = 0;
618c2c66affSColin Finck     NTSTATUS Status;
619c2c66affSColin Finck     SECURITY_INFORMATION SecurityInformation;
620c2c66affSColin Finck     KIRQL CalloutIrql;
621c2c66affSColin Finck     PAGED_CODE();
622c2c66affSColin Finck 
623c2c66affSColin Finck     /* Get the object header and type */
624c2c66affSColin Finck     Header = OBJECT_TO_OBJECT_HEADER(Object);
625c2c66affSColin Finck     Type = Header->Type;
626c2c66affSColin Finck 
627c2c66affSColin Finck     /* Tell the caller that we didn't have to allocate anything yet */
628c2c66affSColin Finck     *MemoryAllocated = FALSE;
629c2c66affSColin Finck 
630c2c66affSColin Finck     /* Check if the object uses default security */
631c2c66affSColin Finck     if (Type->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
632c2c66affSColin Finck     {
633c2c66affSColin Finck         /* Reference the descriptor */
634c2c66affSColin Finck         *SecurityDescriptor = ObpReferenceSecurityDescriptor(Header);
635c2c66affSColin Finck         return STATUS_SUCCESS;
636c2c66affSColin Finck     }
637c2c66affSColin Finck 
638c2c66affSColin Finck     /* Set mask to query */
639c2c66affSColin Finck     SecurityInformation =  OWNER_SECURITY_INFORMATION |
640c2c66affSColin Finck                            GROUP_SECURITY_INFORMATION |
641c2c66affSColin Finck                            DACL_SECURITY_INFORMATION |
642c2c66affSColin Finck                            SACL_SECURITY_INFORMATION;
643c2c66affSColin Finck 
644c2c66affSColin Finck     /* Get the security descriptor size */
645c2c66affSColin Finck     ObpCalloutStart(&CalloutIrql);
646c2c66affSColin Finck     Status = Type->TypeInfo.SecurityProcedure(Object,
647c2c66affSColin Finck                                               QuerySecurityDescriptor,
648c2c66affSColin Finck                                               &SecurityInformation,
649c2c66affSColin Finck                                               *SecurityDescriptor,
650c2c66affSColin Finck                                               &Length,
651c2c66affSColin Finck                                               &Header->SecurityDescriptor,
652c2c66affSColin Finck                                               Type->TypeInfo.PoolType,
653c2c66affSColin Finck                                               &Type->TypeInfo.GenericMapping);
654c2c66affSColin Finck     ObpCalloutEnd(CalloutIrql, "Security", Type, Object);
655c2c66affSColin Finck 
656c2c66affSColin Finck     /* Check for failure */
657c2c66affSColin Finck     if (Status != STATUS_BUFFER_TOO_SMALL) return Status;
658c2c66affSColin Finck 
659c2c66affSColin Finck     /* Allocate security descriptor */
660c2c66affSColin Finck     *SecurityDescriptor = ExAllocatePoolWithTag(PagedPool,
661c2c66affSColin Finck                                                 Length,
662c2c66affSColin Finck                                                 TAG_SEC_QUERY);
663c2c66affSColin Finck     if (!(*SecurityDescriptor)) return STATUS_INSUFFICIENT_RESOURCES;
664c2c66affSColin Finck     *MemoryAllocated = TRUE;
665c2c66affSColin Finck 
666c2c66affSColin Finck     /* Query security descriptor */
667c2c66affSColin Finck     ObpCalloutStart(&CalloutIrql);
668c2c66affSColin Finck     Status = Type->TypeInfo.SecurityProcedure(Object,
669c2c66affSColin Finck                                               QuerySecurityDescriptor,
670c2c66affSColin Finck                                               &SecurityInformation,
671c2c66affSColin Finck                                               *SecurityDescriptor,
672c2c66affSColin Finck                                               &Length,
673c2c66affSColin Finck                                               &Header->SecurityDescriptor,
674c2c66affSColin Finck                                               Type->TypeInfo.PoolType,
675c2c66affSColin Finck                                               &Type->TypeInfo.GenericMapping);
676c2c66affSColin Finck     ObpCalloutEnd(CalloutIrql, "Security", Type, Object);
677c2c66affSColin Finck 
678c2c66affSColin Finck     /* Check for failure */
679c2c66affSColin Finck     if (!NT_SUCCESS(Status))
680c2c66affSColin Finck     {
681c2c66affSColin Finck         /* Free the descriptor and tell the caller we failed */
682c2c66affSColin Finck         ExFreePoolWithTag(*SecurityDescriptor, TAG_SEC_QUERY);
683c2c66affSColin Finck         *MemoryAllocated = FALSE;
684c2c66affSColin Finck     }
685c2c66affSColin Finck 
686c2c66affSColin Finck     /* Return status */
687c2c66affSColin Finck     return Status;
688c2c66affSColin Finck }
689c2c66affSColin Finck 
690c2c66affSColin Finck /*++
691c2c66affSColin Finck * @name ObReleaseObjectSecurity
692c2c66affSColin Finck * @implemented NT4
693c2c66affSColin Finck *
694c2c66affSColin Finck *     The ObReleaseObjectSecurity routine <FILLMEIN>
695c2c66affSColin Finck *
696c2c66affSColin Finck * @param SecurityDescriptor
697c2c66affSColin Finck *        <FILLMEIN>
698c2c66affSColin Finck *
699c2c66affSColin Finck * @param MemoryAllocated
700c2c66affSColin Finck *        <FILLMEIN>
701c2c66affSColin Finck *
702c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value.
703c2c66affSColin Finck *
704c2c66affSColin Finck * @remarks None.
705c2c66affSColin Finck *
706c2c66affSColin Finck *--*/
707c2c66affSColin Finck VOID
708c2c66affSColin Finck NTAPI
709c2c66affSColin Finck ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
710c2c66affSColin Finck                         IN BOOLEAN MemoryAllocated)
711c2c66affSColin Finck {
712c2c66affSColin Finck     PAGED_CODE();
713c2c66affSColin Finck 
714c2c66affSColin Finck     /* Nothing to do in this case */
715c2c66affSColin Finck     if (!SecurityDescriptor) return;
716c2c66affSColin Finck 
717c2c66affSColin Finck     /* Check if we had allocated it from memory */
718c2c66affSColin Finck     if (MemoryAllocated)
719c2c66affSColin Finck     {
720c2c66affSColin Finck         /* Free it */
721c2c66affSColin Finck         ExFreePool(SecurityDescriptor);
722c2c66affSColin Finck     }
723c2c66affSColin Finck     else
724c2c66affSColin Finck     {
725c2c66affSColin Finck         /* Otherwise this means we used an internal descriptor */
726c2c66affSColin Finck         ObDereferenceSecurityDescriptor(SecurityDescriptor, 1);
727c2c66affSColin Finck     }
728c2c66affSColin Finck }
729c2c66affSColin Finck 
730c2c66affSColin Finck /*++
731c2c66affSColin Finck * @name ObSetSecurityObjectByPointer
732c2c66affSColin Finck * @implemented NT5.1
733c2c66affSColin Finck *
734c2c66affSColin Finck *     The ObSetSecurityObjectByPointer routine <FILLMEIN>
735c2c66affSColin Finck *
736c2c66affSColin Finck * @param SecurityDescriptor
737c2c66affSColin Finck *        <FILLMEIN>
738c2c66affSColin Finck *
739c2c66affSColin Finck * @param MemoryAllocated
740c2c66affSColin Finck *        <FILLMEIN>
741c2c66affSColin Finck *
742c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value.
743c2c66affSColin Finck *
744c2c66affSColin Finck * @remarks None.
745c2c66affSColin Finck *
746c2c66affSColin Finck *--*/
747c2c66affSColin Finck NTSTATUS
748c2c66affSColin Finck NTAPI
749c2c66affSColin Finck ObSetSecurityObjectByPointer(IN PVOID Object,
750c2c66affSColin Finck                              IN SECURITY_INFORMATION SecurityInformation,
751c2c66affSColin Finck                              IN PSECURITY_DESCRIPTOR SecurityDescriptor)
752c2c66affSColin Finck {
753c2c66affSColin Finck     POBJECT_TYPE Type;
754c2c66affSColin Finck     POBJECT_HEADER Header;
755c2c66affSColin Finck     PAGED_CODE();
756c2c66affSColin Finck 
757c2c66affSColin Finck     /* Get the header and type */
758c2c66affSColin Finck     Header = OBJECT_TO_OBJECT_HEADER(Object);
759c2c66affSColin Finck     Type = Header->Type;
760c2c66affSColin Finck 
761c2c66affSColin Finck     /* Sanity check */
762c2c66affSColin Finck     ASSERT(SecurityDescriptor);
763c2c66affSColin Finck 
764c2c66affSColin Finck     /* Call the security procedure */
765c2c66affSColin Finck     return Type->TypeInfo.SecurityProcedure(Object,
766c2c66affSColin Finck                                             SetSecurityDescriptor,
767c2c66affSColin Finck                                             &SecurityInformation,
768c2c66affSColin Finck                                             SecurityDescriptor,
769c2c66affSColin Finck                                             NULL,
770c2c66affSColin Finck                                             &Header->SecurityDescriptor,
771c2c66affSColin Finck                                             Type->TypeInfo.PoolType,
772c2c66affSColin Finck                                             &Type->TypeInfo.GenericMapping);
773c2c66affSColin Finck }
774c2c66affSColin Finck 
775c2c66affSColin Finck /*++
776c2c66affSColin Finck * @name NtQuerySecurityObject
777c2c66affSColin Finck * @implemented NT4
778c2c66affSColin Finck *
779c2c66affSColin Finck *     The NtQuerySecurityObject routine <FILLMEIN>
780c2c66affSColin Finck *
781c2c66affSColin Finck * @param Handle
782c2c66affSColin Finck *        <FILLMEIN>
783c2c66affSColin Finck *
784c2c66affSColin Finck * @param SecurityInformation
785c2c66affSColin Finck *        <FILLMEIN>
786c2c66affSColin Finck *
787c2c66affSColin Finck * @param SecurityDescriptor
788c2c66affSColin Finck *        <FILLMEIN>
789c2c66affSColin Finck *
790c2c66affSColin Finck * @param Length
791c2c66affSColin Finck *        <FILLMEIN>
792c2c66affSColin Finck *
793c2c66affSColin Finck * @param ResultLength
794c2c66affSColin Finck *        <FILLMEIN>
795c2c66affSColin Finck *
796c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value.
797c2c66affSColin Finck *
798c2c66affSColin Finck * @remarks None.
799c2c66affSColin Finck *
800c2c66affSColin Finck *--*/
801c2c66affSColin Finck NTSTATUS
802c2c66affSColin Finck NTAPI
803c2c66affSColin Finck NtQuerySecurityObject(IN HANDLE Handle,
804c2c66affSColin Finck                       IN SECURITY_INFORMATION SecurityInformation,
805c2c66affSColin Finck                       OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
806c2c66affSColin Finck                       IN ULONG Length,
807c2c66affSColin Finck                       OUT PULONG ResultLength)
808c2c66affSColin Finck {
809c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
810c2c66affSColin Finck     PVOID Object;
811c2c66affSColin Finck     POBJECT_HEADER Header;
812c2c66affSColin Finck     POBJECT_TYPE Type;
813c2c66affSColin Finck     ACCESS_MASK DesiredAccess;
814c2c66affSColin Finck     NTSTATUS Status;
815c2c66affSColin Finck     PAGED_CODE();
816c2c66affSColin Finck 
817c2c66affSColin Finck     /* Check if we came from user mode */
818c2c66affSColin Finck     if (PreviousMode != KernelMode)
819c2c66affSColin Finck     {
820c2c66affSColin Finck         /* Enter SEH */
821c2c66affSColin Finck         _SEH2_TRY
822c2c66affSColin Finck         {
823c2c66affSColin Finck             /* Probe the SD and the length pointer */
824c2c66affSColin Finck             ProbeForWrite(SecurityDescriptor, Length, sizeof(ULONG));
825c2c66affSColin Finck             ProbeForWriteUlong(ResultLength);
826c2c66affSColin Finck         }
827c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
828c2c66affSColin Finck         {
829c2c66affSColin Finck             /* Return the exception code */
830c2c66affSColin Finck             _SEH2_YIELD(return _SEH2_GetExceptionCode());
831c2c66affSColin Finck         }
832c2c66affSColin Finck         _SEH2_END;
833c2c66affSColin Finck     }
834c2c66affSColin Finck 
835c2c66affSColin Finck     /* Get the required access rights for the operation */
836c2c66affSColin Finck     SeQuerySecurityAccessMask(SecurityInformation, &DesiredAccess);
837c2c66affSColin Finck 
838c2c66affSColin Finck     /* Reference the object */
839c2c66affSColin Finck     Status = ObReferenceObjectByHandle(Handle,
840c2c66affSColin Finck                                        DesiredAccess,
841c2c66affSColin Finck                                        NULL,
842c2c66affSColin Finck                                        PreviousMode,
843c2c66affSColin Finck                                        &Object,
844c2c66affSColin Finck                                        NULL);
845c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
846c2c66affSColin Finck 
847c2c66affSColin Finck     /* Get the Object Header and Type */
848c2c66affSColin Finck     Header = OBJECT_TO_OBJECT_HEADER(Object);
849c2c66affSColin Finck     Type = Header->Type;
850c2c66affSColin Finck 
851c2c66affSColin Finck     /* Call the security procedure's query function */
852c2c66affSColin Finck     Status = Type->TypeInfo.SecurityProcedure(Object,
853c2c66affSColin Finck                                               QuerySecurityDescriptor,
854c2c66affSColin Finck                                               &SecurityInformation,
855c2c66affSColin Finck                                               SecurityDescriptor,
856c2c66affSColin Finck                                               &Length,
857c2c66affSColin Finck                                               &Header->SecurityDescriptor,
858c2c66affSColin Finck                                               Type->TypeInfo.PoolType,
859c2c66affSColin Finck                                               &Type->TypeInfo.GenericMapping);
860c2c66affSColin Finck 
861c2c66affSColin Finck     /* Dereference the object */
862c2c66affSColin Finck     ObDereferenceObject(Object);
863c2c66affSColin Finck 
864c2c66affSColin Finck     /* Protect write with SEH */
865c2c66affSColin Finck     _SEH2_TRY
866c2c66affSColin Finck     {
867c2c66affSColin Finck         /* Return the needed length */
868c2c66affSColin Finck         *ResultLength = Length;
869c2c66affSColin Finck     }
870c2c66affSColin Finck     _SEH2_EXCEPT(ExSystemExceptionFilter())
871c2c66affSColin Finck     {
872c2c66affSColin Finck         /* Get the exception code */
873c2c66affSColin Finck         Status = _SEH2_GetExceptionCode();
874c2c66affSColin Finck     }
875c2c66affSColin Finck     _SEH2_END;
876c2c66affSColin Finck 
877c2c66affSColin Finck     /* Return status */
878c2c66affSColin Finck     return Status;
879c2c66affSColin Finck }
880c2c66affSColin Finck 
881c2c66affSColin Finck /*++
882c2c66affSColin Finck * @name NtSetSecurityObject
883c2c66affSColin Finck * @implemented NT4
884c2c66affSColin Finck *
885c2c66affSColin Finck *     The NtSetSecurityObject routine <FILLMEIN>
886c2c66affSColin Finck *
887c2c66affSColin Finck * @param Handle
888c2c66affSColin Finck *        <FILLMEIN>
889c2c66affSColin Finck *
890c2c66affSColin Finck * @param SecurityInformation
891c2c66affSColin Finck *        <FILLMEIN>
892c2c66affSColin Finck *
893c2c66affSColin Finck * @param SecurityDescriptor
894c2c66affSColin Finck *        <FILLMEIN>
895c2c66affSColin Finck *
896c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value.
897c2c66affSColin Finck *
898c2c66affSColin Finck * @remarks None.
899c2c66affSColin Finck *
900c2c66affSColin Finck *--*/
901c2c66affSColin Finck NTSTATUS
902c2c66affSColin Finck NTAPI
903c2c66affSColin Finck NtSetSecurityObject(IN HANDLE Handle,
904c2c66affSColin Finck                     IN SECURITY_INFORMATION SecurityInformation,
905c2c66affSColin Finck                     IN PSECURITY_DESCRIPTOR SecurityDescriptor)
906c2c66affSColin Finck {
907c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
908c2c66affSColin Finck     PVOID Object;
909c2c66affSColin Finck     SECURITY_DESCRIPTOR_RELATIVE *CapturedDescriptor;
910c2c66affSColin Finck     ACCESS_MASK DesiredAccess = 0;
911c2c66affSColin Finck     NTSTATUS Status;
912c2c66affSColin Finck     PAGED_CODE();
913c2c66affSColin Finck 
914c2c66affSColin Finck     /* Make sure the caller doesn't pass a NULL security descriptor! */
915c2c66affSColin Finck     if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
916c2c66affSColin Finck 
917c2c66affSColin Finck     /* Set the required access rights for the operation */
918c2c66affSColin Finck     SeSetSecurityAccessMask(SecurityInformation, &DesiredAccess);
919c2c66affSColin Finck 
920c2c66affSColin Finck     /* Reference the object */
921c2c66affSColin Finck     Status = ObReferenceObjectByHandle(Handle,
922c2c66affSColin Finck                                        DesiredAccess,
923c2c66affSColin Finck                                        NULL,
924c2c66affSColin Finck                                        PreviousMode,
925c2c66affSColin Finck                                        &Object,
926c2c66affSColin Finck                                        NULL);
927c2c66affSColin Finck     if (NT_SUCCESS(Status))
928c2c66affSColin Finck     {
929c2c66affSColin Finck         /* Capture and make a copy of the security descriptor */
930c2c66affSColin Finck         Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
931c2c66affSColin Finck                                              PreviousMode,
932c2c66affSColin Finck                                              PagedPool,
933c2c66affSColin Finck                                              TRUE,
934c2c66affSColin Finck                                              (PSECURITY_DESCRIPTOR*)
935c2c66affSColin Finck                                              &CapturedDescriptor);
936c2c66affSColin Finck         if (!NT_SUCCESS(Status))
937c2c66affSColin Finck         {
938c2c66affSColin Finck             /* Fail */
939c2c66affSColin Finck             ObDereferenceObject(Object);
940c2c66affSColin Finck             return Status;
941c2c66affSColin Finck         }
942c2c66affSColin Finck 
943c2c66affSColin Finck         /* Sanity check */
944c2c66affSColin Finck         ASSERT(CapturedDescriptor->Control & SE_SELF_RELATIVE);
945c2c66affSColin Finck 
946c2c66affSColin Finck         /*
947c2c66affSColin Finck          * Make sure the security descriptor passed by the caller
948c2c66affSColin Finck          * is valid for the operation we're about to perform
949c2c66affSColin Finck          */
950c2c66affSColin Finck         if (((SecurityInformation & OWNER_SECURITY_INFORMATION) &&
951c2c66affSColin Finck              !(CapturedDescriptor->Owner)) ||
952c2c66affSColin Finck             ((SecurityInformation & GROUP_SECURITY_INFORMATION) &&
953c2c66affSColin Finck              !(CapturedDescriptor->Group)))
954c2c66affSColin Finck         {
955c2c66affSColin Finck             /* Set the failure status */
956c2c66affSColin Finck             Status = STATUS_INVALID_SECURITY_DESCR;
957c2c66affSColin Finck         }
958c2c66affSColin Finck         else
959c2c66affSColin Finck         {
960c2c66affSColin Finck             /* Set security */
961c2c66affSColin Finck             Status = ObSetSecurityObjectByPointer(Object,
962c2c66affSColin Finck                                                   SecurityInformation,
963c2c66affSColin Finck                                                   CapturedDescriptor);
964c2c66affSColin Finck         }
965c2c66affSColin Finck 
966c2c66affSColin Finck         /* Release the descriptor and return status */
967c2c66affSColin Finck         SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR)CapturedDescriptor,
968c2c66affSColin Finck                                     PreviousMode,
969c2c66affSColin Finck                                     TRUE);
970c2c66affSColin Finck 
971c2c66affSColin Finck         /* Now we can dereference the object */
972c2c66affSColin Finck         ObDereferenceObject(Object);
973c2c66affSColin Finck     }
974c2c66affSColin Finck 
975c2c66affSColin Finck     return Status;
976c2c66affSColin Finck }
977c2c66affSColin Finck 
978c2c66affSColin Finck /*++
979c2c66affSColin Finck * @name ObQueryObjectAuditingByHandle
980c2c66affSColin Finck * @implemented NT5
981c2c66affSColin Finck *
982c2c66affSColin Finck *     The ObDereferenceSecurityDescriptor routine <FILLMEIN>
983c2c66affSColin Finck *
984c2c66affSColin Finck * @param SecurityDescriptor
985c2c66affSColin Finck *        <FILLMEIN>
986c2c66affSColin Finck *
987c2c66affSColin Finck * @param Count
988c2c66affSColin Finck *        <FILLMEIN>
989c2c66affSColin Finck *
990c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value.
991c2c66affSColin Finck *
992c2c66affSColin Finck * @remarks None.
993c2c66affSColin Finck *
994c2c66affSColin Finck *--*/
995c2c66affSColin Finck NTSTATUS
996c2c66affSColin Finck NTAPI
997c2c66affSColin Finck ObQueryObjectAuditingByHandle(IN HANDLE Handle,
998c2c66affSColin Finck                               OUT PBOOLEAN GenerateOnClose)
999c2c66affSColin Finck {
1000c2c66affSColin Finck     PHANDLE_TABLE_ENTRY HandleEntry;
1001c2c66affSColin Finck     PVOID HandleTable;
1002c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
1003c2c66affSColin Finck     PAGED_CODE();
1004c2c66affSColin Finck 
1005c2c66affSColin Finck     /* Check if we're dealing with a kernel handle */
1006c2c66affSColin Finck     if (ObpIsKernelHandle(Handle, ExGetPreviousMode()))
1007c2c66affSColin Finck     {
1008c2c66affSColin Finck         /* Use the kernel table and convert the handle */
1009c2c66affSColin Finck         HandleTable = ObpKernelHandleTable;
1010c2c66affSColin Finck         Handle = ObKernelHandleToHandle(Handle);
1011c2c66affSColin Finck     }
1012c2c66affSColin Finck     else
1013c2c66affSColin Finck     {
1014c2c66affSColin Finck         /* Use the process's handle table */
1015c2c66affSColin Finck         HandleTable = PsGetCurrentProcess()->ObjectTable;
1016c2c66affSColin Finck     }
1017c2c66affSColin Finck 
1018c2c66affSColin Finck     /* Enter a critical region while we touch the handle table */
1019c2c66affSColin Finck     KeEnterCriticalRegion();
1020c2c66affSColin Finck 
1021c2c66affSColin Finck     /* Map the handle */
1022c2c66affSColin Finck     HandleEntry = ExMapHandleToPointer(HandleTable, Handle);
1023c2c66affSColin Finck     if(HandleEntry)
1024c2c66affSColin Finck     {
1025c2c66affSColin Finck         /* Check if the flag is set */
1026c2c66affSColin Finck         *GenerateOnClose = HandleEntry->ObAttributes & OBJ_AUDIT_OBJECT_CLOSE;
1027c2c66affSColin Finck 
1028c2c66affSColin Finck         /* Unlock the entry */
1029c2c66affSColin Finck         ExUnlockHandleTableEntry(HandleTable, HandleEntry);
1030c2c66affSColin Finck     }
1031c2c66affSColin Finck     else
1032c2c66affSColin Finck     {
1033c2c66affSColin Finck         /* Otherwise, fail */
1034c2c66affSColin Finck         Status = STATUS_INVALID_HANDLE;
1035c2c66affSColin Finck     }
1036c2c66affSColin Finck 
1037c2c66affSColin Finck     /* Leave the critical region and return the status */
1038c2c66affSColin Finck     KeLeaveCriticalRegion();
1039c2c66affSColin Finck     return Status;
1040c2c66affSColin Finck }
1041c2c66affSColin Finck 
1042c2c66affSColin Finck /* EOF */
1043