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
ObAssignObjectSecurityDescriptor(IN PVOID Object,IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,IN POOL_TYPE PoolType)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
ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR * SecurityDescriptor)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
ObQuerySecurityDescriptorInfo(IN PVOID Object,IN PSECURITY_INFORMATION SecurityInformation,OUT PSECURITY_DESCRIPTOR SecurityDescriptor,IN OUT PULONG Length,IN PSECURITY_DESCRIPTOR * OutputSecurityDescriptor)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
ObSetSecurityDescriptorInfo(IN PVOID Object,IN PSECURITY_INFORMATION SecurityInformation,IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,IN OUT PSECURITY_DESCRIPTOR * OutputSecurityDescriptor,IN POOL_TYPE PoolType,IN PGENERIC_MAPPING GenericMapping)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
ObCheckCreateObjectAccess(IN PVOID Object,IN ACCESS_MASK CreateAccess,IN PACCESS_STATE AccessState,IN PUNICODE_STRING ComponentName,IN BOOLEAN LockHeld,IN KPROCESSOR_MODE AccessMode,OUT PNTSTATUS AccessStatus)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
ObpCheckTraverseAccess(IN PVOID Object,IN ACCESS_MASK TraverseAccess,IN PACCESS_STATE AccessState OPTIONAL,IN BOOLEAN LockHeld,IN KPROCESSOR_MODE AccessMode,OUT PNTSTATUS AccessStatus)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
ObpCheckObjectReference(IN PVOID Object,IN OUT PACCESS_STATE AccessState,IN BOOLEAN LockHeld,IN KPROCESSOR_MODE AccessMode,OUT PNTSTATUS AccessStatus)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
ObCheckObjectAccess(IN PVOID Object,IN OUT PACCESS_STATE AccessState,IN BOOLEAN LockHeld,IN KPROCESSOR_MODE AccessMode,OUT PNTSTATUS ReturnedStatus)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
ObAssignSecurity(IN PACCESS_STATE AccessState,IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN PVOID Object,IN POBJECT_TYPE Type)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,
5642c909db2STimo 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
ObGetObjectSecurity(IN PVOID Object,OUT PSECURITY_DESCRIPTOR * SecurityDescriptor,OUT PBOOLEAN MemoryAllocated)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
ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN BOOLEAN MemoryAllocated)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 */
721*9f8fbe14SGeorge Bișoc ExFreePoolWithTag(SecurityDescriptor, TAG_SEC_QUERY);
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
ObSetSecurityObjectByPointer(IN PVOID Object,IN SECURITY_INFORMATION SecurityInformation,IN PSECURITY_DESCRIPTOR SecurityDescriptor)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
NtQuerySecurityObject(IN HANDLE Handle,IN SECURITY_INFORMATION SecurityInformation,OUT PSECURITY_DESCRIPTOR SecurityDescriptor,IN ULONG Length,OUT PULONG ResultLength)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
NtSetSecurityObject(IN HANDLE Handle,IN SECURITY_INFORMATION SecurityInformation,IN PSECURITY_DESCRIPTOR SecurityDescriptor)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
ObQueryObjectAuditingByHandle(IN HANDLE Handle,OUT PBOOLEAN GenerateOnClose)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