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