2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/audit.c
5 * PURPOSE: Audit functions
7 * PROGRAMMERS: Eric Kohl
8 * Timo Kreuzer (timo.kreuzer@reactos.org)
11 /* INCLUDES *******************************************************************/
17 #define SEP_PRIVILEGE_SET_MAX_COUNT 60
19 UNICODE_STRING SeSubsystemName
= RTL_CONSTANT_STRING(L
"Security");
21 /* PRIVATE FUNCTIONS***********************************************************/
25 SeDetailedAuditingWithToken(IN PTOKEN Token
)
33 SeAuditProcessCreate(IN PEPROCESS Process
)
40 SeAuditProcessExit(IN PEPROCESS Process
)
47 SeInitializeProcessAuditName(IN PFILE_OBJECT FileObject
,
49 OUT POBJECT_NAME_INFORMATION
*AuditInfo
)
51 OBJECT_NAME_INFORMATION LocalNameInfo
;
52 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
53 ULONG ReturnLength
= 8;
59 /* Check if we should do auditing */
65 /* Now query the name */
66 Status
= ObQueryNameString(FileObject
,
68 sizeof(LocalNameInfo
),
70 if (((Status
== STATUS_BUFFER_OVERFLOW
) ||
71 (Status
== STATUS_BUFFER_TOO_SMALL
) ||
72 (Status
== STATUS_INFO_LENGTH_MISMATCH
)) &&
73 (ReturnLength
!= sizeof(LocalNameInfo
)))
75 /* Allocate required size */
76 ObjectNameInfo
= ExAllocatePoolWithTag(NonPagedPool
,
81 /* Query the name again */
82 Status
= ObQueryNameString(FileObject
,
89 /* Check if we got here due to failure */
90 if ((ObjectNameInfo
) &&
91 (!(NT_SUCCESS(Status
)) || (ReturnLength
== sizeof(LocalNameInfo
))))
93 /* First, free any buffer we might've allocated */
95 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
97 /* Now allocate a temporary one */
98 ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
99 ObjectNameInfo
= ExAllocatePoolWithTag(NonPagedPool
,
100 sizeof(OBJECT_NAME_INFORMATION
),
105 RtlZeroMemory(ObjectNameInfo
, ReturnLength
);
106 Status
= STATUS_SUCCESS
;
110 /* Check if memory allocation failed */
111 if (!ObjectNameInfo
) Status
= STATUS_NO_MEMORY
;
113 /* Return the audit name */
114 *AuditInfo
= ObjectNameInfo
;
122 SeLocateProcessImageName(IN PEPROCESS Process
,
123 OUT PUNICODE_STRING
*ProcessImageName
)
125 POBJECT_NAME_INFORMATION AuditName
;
126 PUNICODE_STRING ImageName
;
127 PFILE_OBJECT FileObject
;
128 NTSTATUS Status
= STATUS_SUCCESS
;
133 *ProcessImageName
= NULL
;
135 /* Check if we have audit info */
136 AuditName
= Process
->SeAuditProcessCreationInfo
.ImageFileName
;
139 /* Get the file object */
140 Status
= PsReferenceProcessFilePointer(Process
, &FileObject
);
141 if (!NT_SUCCESS(Status
)) return Status
;
143 /* Initialize the audit structure */
144 Status
= SeInitializeProcessAuditName(FileObject
, TRUE
, &AuditName
);
145 if (NT_SUCCESS(Status
))
148 if (InterlockedCompareExchangePointer((PVOID
*)&Process
->
149 SeAuditProcessCreationInfo
.ImageFileName
,
153 /* Someone beat us to it, deallocate our copy */
154 ExFreePool(AuditName
);
158 /* Dereference the file object */
159 ObDereferenceObject(FileObject
);
160 if (!NT_SUCCESS(Status
)) return Status
;
163 /* Get audit info again, now we have it for sure */
164 AuditName
= Process
->SeAuditProcessCreationInfo
.ImageFileName
;
166 /* Allocate the output string */
167 ImageName
= ExAllocatePoolWithTag(NonPagedPool
,
168 AuditName
->Name
.MaximumLength
+
169 sizeof(UNICODE_STRING
),
171 if (!ImageName
) return STATUS_NO_MEMORY
;
173 /* Make a copy of it */
174 RtlCopyMemory(ImageName
,
176 AuditName
->Name
.MaximumLength
+ sizeof(UNICODE_STRING
));
178 /* Fix up the buffer */
179 ImageName
->Buffer
= (PWSTR
)(ImageName
+ 1);
182 *ProcessImageName
= ImageName
;
190 SepAdtCloseObjectAuditAlarm(
191 PUNICODE_STRING SubsystemName
,
200 SepAdtPrivilegedServiceAuditAlarm(
201 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
202 _In_opt_ PUNICODE_STRING SubsystemName
,
203 _In_opt_ PUNICODE_STRING ServiceName
,
205 _In_ PTOKEN PrimaryToken
,
206 _In_ PPRIVILEGE_SET Privileges
,
207 _In_ BOOLEAN AccessGranted
)
209 DPRINT("SepAdtPrivilegedServiceAuditAlarm is unimplemented\n");
214 SePrivilegedServiceAuditAlarm(
215 _In_opt_ PUNICODE_STRING ServiceName
,
216 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext
,
217 _In_ PPRIVILEGE_SET PrivilegeSet
,
218 _In_ BOOLEAN AccessGranted
)
220 PTOKEN EffectiveToken
;
224 /* Get the effective token */
225 if (SubjectContext
->ClientToken
!= NULL
)
226 EffectiveToken
= SubjectContext
->ClientToken
;
228 EffectiveToken
= SubjectContext
->PrimaryToken
;
230 /* Get the user SID */
231 UserSid
= EffectiveToken
->UserAndGroups
->Sid
;
233 /* Check if this is the local system SID */
234 if (RtlEqualSid(UserSid
, SeLocalSystemSid
))
240 /* Check if this is the network service or local service SID */
241 if (RtlEqualSid(UserSid
, SeExports
->SeNetworkServiceSid
) ||
242 RtlEqualSid(UserSid
, SeExports
->SeLocalServiceSid
))
244 // FIXME: should continue for a certain set of privileges
248 /* Call the worker function */
249 SepAdtPrivilegedServiceAuditAlarm(SubjectContext
,
252 SubjectContext
->ClientToken
,
253 SubjectContext
->PrimaryToken
,
262 SeCaptureObjectTypeList(
263 _In_reads_opt_(ObjectTypeListLength
) POBJECT_TYPE_LIST ObjectTypeList
,
264 _In_ ULONG ObjectTypeListLength
,
265 _In_ KPROCESSOR_MODE PreviousMode
,
266 _Out_ POBJECT_TYPE_LIST
*CapturedObjectTypeList
)
270 if (PreviousMode
== KernelMode
)
272 return STATUS_NOT_IMPLEMENTED
;
275 if (ObjectTypeListLength
== 0)
277 *CapturedObjectTypeList
= NULL
;
278 return STATUS_SUCCESS
;
281 if (ObjectTypeList
== NULL
)
283 return STATUS_INVALID_PARAMETER
;
286 /* Calculate the list size and check for integer overflow */
287 Size
= ObjectTypeListLength
* sizeof(OBJECT_TYPE_LIST
);
290 return STATUS_INVALID_PARAMETER
;
293 /* Allocate a new list */
294 *CapturedObjectTypeList
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_SEPA
);
295 if (*CapturedObjectTypeList
== NULL
)
297 return STATUS_INSUFFICIENT_RESOURCES
;
302 ProbeForRead(ObjectTypeList
, Size
, sizeof(ULONG
));
303 RtlCopyMemory(*CapturedObjectTypeList
, ObjectTypeList
, Size
);
305 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
307 ExFreePoolWithTag(*CapturedObjectTypeList
, TAG_SEPA
);
308 *CapturedObjectTypeList
= NULL
;
309 return _SEH2_GetExceptionCode();
313 return STATUS_SUCCESS
;
318 SeReleaseObjectTypeList(
319 _In_ _Post_invalid_ POBJECT_TYPE_LIST CapturedObjectTypeList
,
320 _In_ KPROCESSOR_MODE PreviousMode
)
322 if ((PreviousMode
!= KernelMode
) && (CapturedObjectTypeList
!= NULL
))
323 ExFreePoolWithTag(CapturedObjectTypeList
, TAG_SEPA
);
326 _Must_inspect_result_
329 SepAccessCheckAndAuditAlarmWorker(
330 _In_ PUNICODE_STRING SubsystemName
,
331 _In_opt_ PVOID HandleId
,
332 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext
,
333 _In_ PUNICODE_STRING ObjectTypeName
,
334 _In_ PUNICODE_STRING ObjectName
,
335 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
336 _In_opt_ PSID PrincipalSelfSid
,
337 _In_ ACCESS_MASK DesiredAccess
,
338 _In_ AUDIT_EVENT_TYPE AuditType
,
339 _In_ BOOLEAN HaveAuditPrivilege
,
340 _In_reads_opt_(ObjectTypeListLength
) POBJECT_TYPE_LIST ObjectTypeList
,
341 _In_ ULONG ObjectTypeListLength
,
342 _In_ PGENERIC_MAPPING GenericMapping
,
343 _Out_writes_(ObjectTypeListLength
) PACCESS_MASK GrantedAccessList
,
344 _Out_writes_(ObjectTypeListLength
) PNTSTATUS AccessStatusList
,
345 _Out_ PBOOLEAN GenerateOnClose
,
346 _In_ BOOLEAN UseResultList
)
348 ULONG ResultListLength
, i
;
350 /* Get the length of the result list */
351 ResultListLength
= UseResultList
? ObjectTypeListLength
: 1;
353 /// FIXME: we should do some real work here...
356 /// HACK: we just pretend all access is granted!
357 for (i
= 0; i
< ResultListLength
; i
++)
359 GrantedAccessList
[i
] = DesiredAccess
;
360 AccessStatusList
[i
] = STATUS_SUCCESS
;
363 *GenerateOnClose
= FALSE
;
365 return STATUS_SUCCESS
;
368 _Must_inspect_result_
371 SepAccessCheckAndAuditAlarm(
372 _In_ PUNICODE_STRING SubsystemName
,
373 _In_opt_ PVOID HandleId
,
374 _In_ PHANDLE ClientTokenHandle
,
375 _In_ PUNICODE_STRING ObjectTypeName
,
376 _In_ PUNICODE_STRING ObjectName
,
377 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
378 _In_opt_ PSID PrincipalSelfSid
,
379 _In_ ACCESS_MASK DesiredAccess
,
380 _In_ AUDIT_EVENT_TYPE AuditType
,
382 _In_reads_opt_(ObjectTypeListLength
) POBJECT_TYPE_LIST ObjectTypeList
,
383 _In_ ULONG ObjectTypeListLength
,
384 _In_ PGENERIC_MAPPING GenericMapping
,
385 _Out_writes_(ObjectTypeListLength
) PACCESS_MASK GrantedAccessList
,
386 _Out_writes_(ObjectTypeListLength
) PNTSTATUS AccessStatusList
,
387 _Out_ PBOOLEAN GenerateOnClose
,
388 _In_ BOOLEAN UseResultList
)
390 SECURITY_SUBJECT_CONTEXT SubjectContext
;
391 ULONG ResultListLength
;
392 GENERIC_MAPPING LocalGenericMapping
;
393 PTOKEN SubjectContextToken
, ClientToken
;
394 BOOLEAN AllocatedResultLists
;
395 BOOLEAN HaveAuditPrivilege
;
396 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
;
397 UNICODE_STRING CapturedSubsystemName
, CapturedObjectTypeName
, CapturedObjectName
;
398 ACCESS_MASK GrantedAccess
, *SafeGrantedAccessList
;
399 NTSTATUS AccessStatus
, *SafeAccessStatusList
;
400 PSID CapturedPrincipalSelfSid
;
401 POBJECT_TYPE_LIST CapturedObjectTypeList
;
403 BOOLEAN LocalGenerateOnClose
;
407 /* Only user mode is supported! */
408 ASSERT(ExGetPreviousMode() != KernelMode
);
411 AllocatedResultLists
= FALSE
;
413 CapturedSecurityDescriptor
= NULL
;
414 CapturedSubsystemName
.Buffer
= NULL
;
415 CapturedObjectTypeName
.Buffer
= NULL
;
416 CapturedObjectName
.Buffer
= NULL
;
417 CapturedPrincipalSelfSid
= NULL
;
418 CapturedObjectTypeList
= NULL
;
420 /* Validate AuditType */
421 if ((AuditType
!= AuditEventObjectAccess
) &&
422 (AuditType
!= AuditEventDirectoryServiceAccess
))
424 DPRINT1("Invalid audit type: %u\n", AuditType
);
425 return STATUS_INVALID_PARAMETER
;
428 /* Capture the security subject context */
429 SeCaptureSubjectContext(&SubjectContext
);
431 /* Did the caller pass a token handle? */
432 if (ClientTokenHandle
== NULL
)
434 /* Check if we have a token in the subject context */
435 if (SubjectContext
.ClientToken
== NULL
)
437 Status
= STATUS_NO_IMPERSONATION_TOKEN
;
438 DPRINT1("No token\n");
442 /* Check if we have a valid impersonation level */
443 if (SubjectContext
.ImpersonationLevel
< SecurityIdentification
)
445 Status
= STATUS_BAD_IMPERSONATION_LEVEL
;
446 DPRINT1("Invalid impersonation level 0x%lx\n",
447 SubjectContext
.ImpersonationLevel
);
452 /* Are we using a result list? */
455 /* The list length equals the object type list length */
456 ResultListLength
= ObjectTypeListLength
;
457 if ((ResultListLength
== 0) || (ResultListLength
> 0x1000))
459 Status
= STATUS_INVALID_PARAMETER
;
460 DPRINT1("Invalud ResultListLength: 0x%lx\n", ResultListLength
);
464 /* Allocate a safe buffer from paged pool */
465 SafeGrantedAccessList
= ExAllocatePoolWithTag(PagedPool
,
466 2 * ResultListLength
* sizeof(ULONG
),
468 if (SafeGrantedAccessList
== NULL
)
470 Status
= STATUS_INSUFFICIENT_RESOURCES
;
471 DPRINT1("Failed to allocate access lists\n");
475 SafeAccessStatusList
= (PNTSTATUS
)&SafeGrantedAccessList
[ResultListLength
];
476 AllocatedResultLists
= TRUE
;
480 /* List length is 1 */
481 ResultListLength
= 1;
482 SafeGrantedAccessList
= &GrantedAccess
;
483 SafeAccessStatusList
= &AccessStatus
;
488 /* Probe output buffers */
489 ProbeForWrite(AccessStatusList
,
490 ResultListLength
* sizeof(*AccessStatusList
),
491 sizeof(*AccessStatusList
));
492 ProbeForWrite(GrantedAccessList
,
493 ResultListLength
* sizeof(*GrantedAccessList
),
494 sizeof(*GrantedAccessList
));
496 /* Probe generic mapping and make a local copy */
497 ProbeForRead(GenericMapping
, sizeof(*GenericMapping
), sizeof(ULONG
));
498 LocalGenericMapping
= * GenericMapping
;
500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
502 Status
= _SEH2_GetExceptionCode();
503 DPRINT1("Exception while probing parameters: 0x%lx\n", Status
);
508 /* Do we have a client token? */
509 if (ClientTokenHandle
!= NULL
)
511 /* Reference the client token */
512 Status
= ObReferenceObjectByHandle(*ClientTokenHandle
,
516 (PVOID
*)&ClientToken
,
518 if (!NT_SUCCESS(Status
))
520 DPRINT1("Failed to reference token handle %p: %lx\n",
521 *ClientTokenHandle
, Status
);
525 SubjectContextToken
= SubjectContext
.ClientToken
;
526 SubjectContext
.ClientToken
= ClientToken
;
529 /* Check for audit privilege */
530 HaveAuditPrivilege
= SeCheckAuditPrivilege(&SubjectContext
, UserMode
);
531 if (!HaveAuditPrivilege
&& !(Flags
& AUDIT_ALLOW_NO_PRIVILEGE
))
533 DPRINT1("Caller does not have SeAuditPrivilege\n");
534 Status
= STATUS_PRIVILEGE_NOT_HELD
;
538 /* Generic access must already be mapped to non-generic access types! */
539 if (DesiredAccess
& (GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
| GENERIC_ALL
))
541 DPRINT1("Generic access rights requested: 0x%lx\n", DesiredAccess
);
542 Status
= STATUS_GENERIC_NOT_MAPPED
;
546 /* Capture the security descriptor */
547 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
551 &CapturedSecurityDescriptor
);
552 if (!NT_SUCCESS(Status
))
554 DPRINT1("Failed to capture security descriptor!\n");
558 /* Validate the Security descriptor */
559 if ((SepGetOwnerFromDescriptor(CapturedSecurityDescriptor
) == NULL
) ||
560 (SepGetGroupFromDescriptor(CapturedSecurityDescriptor
) == NULL
))
562 Status
= STATUS_INVALID_SECURITY_DESCR
;
563 DPRINT1("Invalid security descriptor\n");
567 /* Probe and capture the subsystem name */
568 Status
= ProbeAndCaptureUnicodeString(&CapturedSubsystemName
,
571 if (!NT_SUCCESS(Status
))
573 DPRINT1("Failed to capture subsystem name!\n");
577 /* Probe and capture the object type name */
578 Status
= ProbeAndCaptureUnicodeString(&CapturedObjectTypeName
,
581 if (!NT_SUCCESS(Status
))
583 DPRINT1("Failed to capture object type name!\n");
587 /* Probe and capture the object name */
588 Status
= ProbeAndCaptureUnicodeString(&CapturedObjectName
,
591 if (!NT_SUCCESS(Status
))
593 DPRINT1("Failed to capture object name!\n");
597 /* Check if we have a PrincipalSelfSid */
598 if (PrincipalSelfSid
!= NULL
)
601 Status
= SepCaptureSid(PrincipalSelfSid
,
605 &CapturedPrincipalSelfSid
);
606 if (!NT_SUCCESS(Status
))
608 DPRINT1("Failed to capture PrincipalSelfSid!\n");
613 /* Capture the object type list */
614 Status
= SeCaptureObjectTypeList(ObjectTypeList
,
615 ObjectTypeListLength
,
617 &CapturedObjectTypeList
);
618 if (!NT_SUCCESS(Status
))
620 DPRINT1("Failed to capture object type list!\n");
624 /* Call the worker routine with the captured buffers */
625 SepAccessCheckAndAuditAlarmWorker(&CapturedSubsystemName
,
628 &CapturedObjectTypeName
,
630 CapturedSecurityDescriptor
,
631 CapturedPrincipalSelfSid
,
635 CapturedObjectTypeList
,
636 ObjectTypeListLength
,
637 &LocalGenericMapping
,
638 SafeGrantedAccessList
,
639 SafeAccessStatusList
,
640 &LocalGenerateOnClose
,
643 /* Enter SEH to copy the data back to user mode */
646 /* Loop all result entries (only 1 when no list was requested) */
647 NT_ASSERT(UseResultList
|| (ResultListLength
== 1));
648 for (i
= 0; i
< ResultListLength
; i
++)
650 AccessStatusList
[i
] = SafeAccessStatusList
[i
];
651 GrantedAccessList
[i
] = SafeGrantedAccessList
[i
];
654 *GenerateOnClose
= LocalGenerateOnClose
;
656 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
658 Status
= _SEH2_GetExceptionCode();
659 DPRINT1("Exception while copying back data: 0x%lx\n", Status
);
665 if (CapturedObjectTypeList
!= NULL
)
666 SeReleaseObjectTypeList(CapturedObjectTypeList
, UserMode
);
668 if (CapturedPrincipalSelfSid
!= NULL
)
669 SepReleaseSid(CapturedPrincipalSelfSid
, UserMode
, FALSE
);
671 if (CapturedObjectName
.Buffer
!= NULL
)
672 ReleaseCapturedUnicodeString(&CapturedObjectName
, UserMode
);
674 if (CapturedObjectTypeName
.Buffer
!= NULL
)
675 ReleaseCapturedUnicodeString(&CapturedObjectTypeName
, UserMode
);
677 if (CapturedSubsystemName
.Buffer
!= NULL
)
678 ReleaseCapturedUnicodeString(&CapturedSubsystemName
, UserMode
);
680 if (CapturedSecurityDescriptor
!= NULL
)
681 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
, UserMode
, FALSE
);
683 if (ClientToken
!= NULL
)
685 ObDereferenceObject(ClientToken
);
686 SubjectContext
.ClientToken
= SubjectContextToken
;
689 if (AllocatedResultLists
)
690 ExFreePoolWithTag(SafeGrantedAccessList
, TAG_SEPA
);
692 /* Release the security subject context */
693 SeReleaseSubjectContext(&SubjectContext
);
699 /* PUBLIC FUNCTIONS ***********************************************************/
706 SeAuditHardLinkCreation(IN PUNICODE_STRING FileName
,
707 IN PUNICODE_STRING LinkName
,
718 SeAuditingFileEvents(IN BOOLEAN AccessGranted
,
719 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
730 SeAuditingFileEventsWithContext(IN BOOLEAN AccessGranted
,
731 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
732 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL
)
743 SeAuditingHardLinkEvents(IN BOOLEAN AccessGranted
,
744 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
755 SeAuditingHardLinkEventsWithContext(IN BOOLEAN AccessGranted
,
756 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
757 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL
)
768 SeAuditingFileOrGlobalEvents(IN BOOLEAN AccessGranted
,
769 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
770 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
)
781 SeCloseObjectAuditAlarm(IN PVOID Object
,
783 IN BOOLEAN PerformAction
)
792 SeDeleteObjectAuditAlarm(IN PVOID Object
,
803 SeOpenObjectAuditAlarm(IN PUNICODE_STRING ObjectTypeName
,
804 IN PVOID Object OPTIONAL
,
805 IN PUNICODE_STRING AbsoluteObjectName OPTIONAL
,
806 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
807 IN PACCESS_STATE AccessState
,
808 IN BOOLEAN ObjectCreated
,
809 IN BOOLEAN AccessGranted
,
810 IN KPROCESSOR_MODE AccessMode
,
811 OUT PBOOLEAN GenerateOnClose
)
815 /* Audits aren't done on kernel-mode access */
816 if (AccessMode
== KernelMode
) return;
818 /* Otherwise, unimplemented! */
827 SeOpenObjectForDeleteAuditAlarm(IN PUNICODE_STRING ObjectTypeName
,
828 IN PVOID Object OPTIONAL
,
829 IN PUNICODE_STRING AbsoluteObjectName OPTIONAL
,
830 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
831 IN PACCESS_STATE AccessState
,
832 IN BOOLEAN ObjectCreated
,
833 IN BOOLEAN AccessGranted
,
834 IN KPROCESSOR_MODE AccessMode
,
835 OUT PBOOLEAN GenerateOnClose
)
845 SePrivilegeObjectAuditAlarm(IN HANDLE Handle
,
846 IN PSECURITY_SUBJECT_CONTEXT SubjectContext
,
847 IN ACCESS_MASK DesiredAccess
,
848 IN PPRIVILEGE_SET Privileges
,
849 IN BOOLEAN AccessGranted
,
850 IN KPROCESSOR_MODE CurrentMode
)
855 /* SYSTEM CALLS ***************************************************************/
859 NtCloseObjectAuditAlarm(
860 PUNICODE_STRING SubsystemName
,
862 BOOLEAN GenerateOnClose
)
864 SECURITY_SUBJECT_CONTEXT SubjectContext
;
865 UNICODE_STRING CapturedSubsystemName
;
866 KPROCESSOR_MODE PreviousMode
;
867 BOOLEAN UseImpersonationToken
;
868 PETHREAD CurrentThread
;
869 BOOLEAN CopyOnOpen
, EffectiveOnly
;
870 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
875 /* Get the previous mode (only user mode is supported!) */
876 PreviousMode
= ExGetPreviousMode();
877 ASSERT(PreviousMode
!= KernelMode
);
879 /* Do we even need to do anything? */
880 if (!GenerateOnClose
)
882 /* Nothing to do, return success */
883 return STATUS_SUCCESS
;
886 /* Capture the security subject context */
887 SeCaptureSubjectContext(&SubjectContext
);
889 /* Check for audit privilege */
890 if (!SeCheckAuditPrivilege(&SubjectContext
, PreviousMode
))
892 DPRINT1("Caller does not have SeAuditPrivilege\n");
893 Status
= STATUS_PRIVILEGE_NOT_HELD
;
897 /* Probe and capture the subsystem name */
898 Status
= ProbeAndCaptureUnicodeString(&CapturedSubsystemName
,
901 if (!NT_SUCCESS(Status
))
903 DPRINT1("Failed to capture subsystem name!\n");
907 /* Get the current thread and check if it's impersonating */
908 CurrentThread
= PsGetCurrentThread();
909 if (PsIsThreadImpersonating(CurrentThread
))
911 /* Get the impersonation token */
912 Token
= PsReferenceImpersonationToken(CurrentThread
,
915 &ImpersonationLevel
);
916 UseImpersonationToken
= TRUE
;
920 /* Get the primary token */
921 Token
= PsReferencePrimaryToken(PsGetCurrentProcess());
922 UseImpersonationToken
= FALSE
;
925 /* Call the internal function */
926 SepAdtCloseObjectAuditAlarm(&CapturedSubsystemName
,
928 Token
->UserAndGroups
->Sid
);
930 /* Release the captured subsystem name */
931 ReleaseCapturedUnicodeString(&CapturedSubsystemName
, PreviousMode
);
933 /* Check what token we used */
934 if (UseImpersonationToken
)
936 /* Release impersonation token */
937 PsDereferenceImpersonationToken(Token
);
941 /* Release primary token */
942 PsDereferencePrimaryToken(Token
);
945 Status
= STATUS_SUCCESS
;
949 /* Release the security subject context */
950 SeReleaseSubjectContext(&SubjectContext
);
957 NtDeleteObjectAuditAlarm(IN PUNICODE_STRING SubsystemName
,
959 IN BOOLEAN GenerateOnClose
)
962 return STATUS_NOT_IMPLEMENTED
;
967 SepOpenObjectAuditAlarm(
968 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext
,
969 _In_ PUNICODE_STRING SubsystemName
,
970 _In_opt_ PVOID HandleId
,
971 _In_ PUNICODE_STRING ObjectTypeName
,
972 _In_ PUNICODE_STRING ObjectName
,
973 _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
974 _In_ PTOKEN ClientToken
,
975 _In_ ACCESS_MASK DesiredAccess
,
976 _In_ ACCESS_MASK GrantedAccess
,
977 _In_opt_ PPRIVILEGE_SET Privileges
,
978 _In_ BOOLEAN ObjectCreation
,
979 _In_ BOOLEAN AccessGranted
,
980 _Out_ PBOOLEAN GenerateOnClose
)
982 DBG_UNREFERENCED_PARAMETER(SubjectContext
);
983 DBG_UNREFERENCED_PARAMETER(SubsystemName
);
984 DBG_UNREFERENCED_PARAMETER(HandleId
);
985 DBG_UNREFERENCED_PARAMETER(ObjectTypeName
);
986 DBG_UNREFERENCED_PARAMETER(ObjectName
);
987 DBG_UNREFERENCED_PARAMETER(SecurityDescriptor
);
988 DBG_UNREFERENCED_PARAMETER(ClientToken
);
989 DBG_UNREFERENCED_PARAMETER(DesiredAccess
);
990 DBG_UNREFERENCED_PARAMETER(GrantedAccess
);
991 DBG_UNREFERENCED_PARAMETER(Privileges
);
992 DBG_UNREFERENCED_PARAMETER(ObjectCreation
);
993 DBG_UNREFERENCED_PARAMETER(AccessGranted
);
995 *GenerateOnClose
= FALSE
;
1001 NtOpenObjectAuditAlarm(
1002 _In_ PUNICODE_STRING SubsystemName
,
1003 _In_opt_ PVOID HandleId
,
1004 _In_ PUNICODE_STRING ObjectTypeName
,
1005 _In_ PUNICODE_STRING ObjectName
,
1006 _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
1007 _In_ HANDLE ClientTokenHandle
,
1008 _In_ ACCESS_MASK DesiredAccess
,
1009 _In_ ACCESS_MASK GrantedAccess
,
1010 _In_opt_ PPRIVILEGE_SET PrivilegeSet
,
1011 _In_ BOOLEAN ObjectCreation
,
1012 _In_ BOOLEAN AccessGranted
,
1013 _Out_ PBOOLEAN GenerateOnClose
)
1016 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
;
1017 UNICODE_STRING CapturedSubsystemName
, CapturedObjectTypeName
, CapturedObjectName
;
1018 ULONG PrivilegeCount
, PrivilegeSetSize
;
1019 volatile PPRIVILEGE_SET CapturedPrivilegeSet
;
1020 BOOLEAN LocalGenerateOnClose
;
1021 PVOID CapturedHandleId
;
1022 SECURITY_SUBJECT_CONTEXT SubjectContext
;
1026 /* Only user mode is supported! */
1027 ASSERT(ExGetPreviousMode() != KernelMode
);
1031 CapturedSecurityDescriptor
= NULL
;
1032 CapturedPrivilegeSet
= NULL
;
1033 CapturedSubsystemName
.Buffer
= NULL
;
1034 CapturedObjectTypeName
.Buffer
= NULL
;
1035 CapturedObjectName
.Buffer
= NULL
;
1037 /* Reference the client token */
1038 Status
= ObReferenceObjectByHandle(ClientTokenHandle
,
1042 (PVOID
*)&ClientToken
,
1044 if (!NT_SUCCESS(Status
))
1046 DPRINT1("Failed to reference token handle %p: %lx\n",
1047 ClientTokenHandle
, Status
);
1051 /* Capture the security subject context */
1052 SeCaptureSubjectContext(&SubjectContext
);
1054 /* Validate the token's impersonation level */
1055 if ((ClientToken
->TokenType
== TokenImpersonation
) &&
1056 (ClientToken
->ImpersonationLevel
< SecurityIdentification
))
1058 DPRINT1("Invalid impersonation level (%u)\n", ClientToken
->ImpersonationLevel
);
1059 Status
= STATUS_BAD_IMPERSONATION_LEVEL
;
1063 /* Check for audit privilege */
1064 if (!SeCheckAuditPrivilege(&SubjectContext
, UserMode
))
1066 DPRINT1("Caller does not have SeAuditPrivilege\n");
1067 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1071 /* Check for NULL SecurityDescriptor */
1072 if (SecurityDescriptor
== NULL
)
1075 Status
= STATUS_SUCCESS
;
1079 /* Capture the security descriptor */
1080 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
1084 &CapturedSecurityDescriptor
);
1085 if (!NT_SUCCESS(Status
))
1087 DPRINT1("Failed to capture security descriptor!\n");
1093 /* Check if we have a privilege set */
1094 if (PrivilegeSet
!= NULL
)
1096 /* Probe the basic privilege set structure */
1097 ProbeForRead(PrivilegeSet
, sizeof(PRIVILEGE_SET
), sizeof(ULONG
));
1099 /* Validate privilege count */
1100 PrivilegeCount
= PrivilegeSet
->PrivilegeCount
;
1101 if (PrivilegeCount
> SEP_PRIVILEGE_SET_MAX_COUNT
)
1103 Status
= STATUS_INVALID_PARAMETER
;
1107 /* Calculate the size of the PrivilegeSet structure */
1108 PrivilegeSetSize
= FIELD_OFFSET(PRIVILEGE_SET
, Privilege
[PrivilegeCount
]);
1110 /* Probe the whole structure */
1111 ProbeForRead(PrivilegeSet
, PrivilegeSetSize
, sizeof(ULONG
));
1113 /* Allocate a temp buffer */
1114 CapturedPrivilegeSet
= ExAllocatePoolWithTag(PagedPool
,
1117 if (CapturedPrivilegeSet
== NULL
)
1119 DPRINT1("Failed to allocate %u bytes\n", PrivilegeSetSize
);
1120 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1124 /* Copy the privileges */
1125 RtlCopyMemory(CapturedPrivilegeSet
, PrivilegeSet
, PrivilegeSetSize
);
1128 if (HandleId
!= NULL
)
1130 ProbeForRead(HandleId
, sizeof(PVOID
), sizeof(PVOID
));
1131 CapturedHandleId
= *(PVOID
*)HandleId
;
1134 ProbeForWrite(GenerateOnClose
, sizeof(BOOLEAN
), sizeof(BOOLEAN
));
1136 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1138 Status
= _SEH2_GetExceptionCode();
1139 DPRINT1("Exception while probing parameters: 0x%lx\n", Status
);
1144 /* Probe and capture the subsystem name */
1145 Status
= ProbeAndCaptureUnicodeString(&CapturedSubsystemName
,
1148 if (!NT_SUCCESS(Status
))
1150 DPRINT1("Failed to capture subsystem name!\n");
1154 /* Probe and capture the object type name */
1155 Status
= ProbeAndCaptureUnicodeString(&CapturedObjectTypeName
,
1158 if (!NT_SUCCESS(Status
))
1160 DPRINT1("Failed to capture object type name!\n");
1164 /* Probe and capture the object name */
1165 Status
= ProbeAndCaptureUnicodeString(&CapturedObjectName
,
1168 if (!NT_SUCCESS(Status
))
1170 DPRINT1("Failed to capture object name!\n");
1174 /* Call the internal function */
1175 SepOpenObjectAuditAlarm(&SubjectContext
,
1176 &CapturedSubsystemName
,
1178 &CapturedObjectTypeName
,
1179 &CapturedObjectName
,
1180 CapturedSecurityDescriptor
,
1184 CapturedPrivilegeSet
,
1187 &LocalGenerateOnClose
);
1189 Status
= STATUS_SUCCESS
;
1191 /* Enter SEH to copy the data back to user mode */
1194 *GenerateOnClose
= LocalGenerateOnClose
;
1196 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1198 Status
= _SEH2_GetExceptionCode();
1199 DPRINT1("Exception while copying back data: 0x%lx\n", Status
);
1205 if (CapturedObjectName
.Buffer
!= NULL
)
1206 ReleaseCapturedUnicodeString(&CapturedObjectName
, UserMode
);
1208 if (CapturedObjectTypeName
.Buffer
!= NULL
)
1209 ReleaseCapturedUnicodeString(&CapturedObjectTypeName
, UserMode
);
1211 if (CapturedSubsystemName
.Buffer
!= NULL
)
1212 ReleaseCapturedUnicodeString(&CapturedSubsystemName
, UserMode
);
1214 if (CapturedSecurityDescriptor
!= NULL
)
1215 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
, UserMode
, FALSE
);
1217 if (CapturedPrivilegeSet
!= NULL
)
1218 ExFreePoolWithTag(CapturedPrivilegeSet
, 'rPeS');
1220 /* Release the security subject context */
1221 SeReleaseSubjectContext(&SubjectContext
);
1223 ObDereferenceObject(ClientToken
);
1232 NtPrivilegedServiceAuditAlarm(
1233 _In_opt_ PUNICODE_STRING SubsystemName
,
1234 _In_opt_ PUNICODE_STRING ServiceName
,
1235 _In_ HANDLE ClientTokenHandle
,
1236 _In_ PPRIVILEGE_SET Privileges
,
1237 _In_ BOOLEAN AccessGranted
)
1239 KPROCESSOR_MODE PreviousMode
;
1241 volatile PPRIVILEGE_SET CapturedPrivileges
= NULL
;
1242 UNICODE_STRING CapturedSubsystemName
;
1243 UNICODE_STRING CapturedServiceName
;
1244 ULONG PrivilegeCount
, PrivilegesSize
;
1245 SECURITY_SUBJECT_CONTEXT SubjectContext
;
1249 /* Get the previous mode (only user mode is supported!) */
1250 PreviousMode
= ExGetPreviousMode();
1251 ASSERT(PreviousMode
!= KernelMode
);
1253 CapturedSubsystemName
.Buffer
= NULL
;
1254 CapturedServiceName
.Buffer
= NULL
;
1256 /* Reference the client token */
1257 Status
= ObReferenceObjectByHandle(ClientTokenHandle
,
1261 (PVOID
*)&ClientToken
,
1263 if (!NT_SUCCESS(Status
))
1265 DPRINT1("Failed to reference client token: 0x%lx\n", Status
);
1269 /* Validate the token's impersonation level */
1270 if ((ClientToken
->TokenType
== TokenImpersonation
) &&
1271 (ClientToken
->ImpersonationLevel
< SecurityIdentification
))
1273 DPRINT1("Invalid impersonation level (%u)\n", ClientToken
->ImpersonationLevel
);
1274 ObDereferenceObject(ClientToken
);
1275 return STATUS_BAD_IMPERSONATION_LEVEL
;
1278 /* Capture the security subject context */
1279 SeCaptureSubjectContext(&SubjectContext
);
1281 /* Check for audit privilege */
1282 if (!SeCheckAuditPrivilege(&SubjectContext
, PreviousMode
))
1284 DPRINT1("Caller does not have SeAuditPrivilege\n");
1285 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1289 /* Do we have a subsystem name? */
1290 if (SubsystemName
!= NULL
)
1292 /* Probe and capture the subsystem name */
1293 Status
= ProbeAndCaptureUnicodeString(&CapturedSubsystemName
,
1296 if (!NT_SUCCESS(Status
))
1298 DPRINT1("Failed to capture subsystem name!\n");
1303 /* Do we have a service name? */
1304 if (ServiceName
!= NULL
)
1306 /* Probe and capture the service name */
1307 Status
= ProbeAndCaptureUnicodeString(&CapturedServiceName
,
1310 if (!NT_SUCCESS(Status
))
1312 DPRINT1("Failed to capture service name!\n");
1319 /* Probe the basic privilege set structure */
1320 ProbeForRead(Privileges
, sizeof(PRIVILEGE_SET
), sizeof(ULONG
));
1322 /* Validate privilege count */
1323 PrivilegeCount
= Privileges
->PrivilegeCount
;
1324 if (PrivilegeCount
> SEP_PRIVILEGE_SET_MAX_COUNT
)
1326 Status
= STATUS_INVALID_PARAMETER
;
1330 /* Calculate the size of the Privileges structure */
1331 PrivilegesSize
= FIELD_OFFSET(PRIVILEGE_SET
, Privilege
[PrivilegeCount
]);
1333 /* Probe the whole structure */
1334 ProbeForRead(Privileges
, PrivilegesSize
, sizeof(ULONG
));
1336 /* Allocate a temp buffer */
1337 CapturedPrivileges
= ExAllocatePoolWithTag(PagedPool
,
1340 if (CapturedPrivileges
== NULL
)
1342 DPRINT1("Failed to allocate %u bytes\n", PrivilegesSize
);
1343 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1347 /* Copy the privileges */
1348 RtlCopyMemory(CapturedPrivileges
, Privileges
, PrivilegesSize
);
1350 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1352 Status
= _SEH2_GetExceptionCode();
1353 DPRINT1("Got exception 0x%lx\n", Status
);
1358 /* Call the internal function */
1359 SepAdtPrivilegedServiceAuditAlarm(&SubjectContext
,
1360 SubsystemName
? &CapturedSubsystemName
: NULL
,
1361 ServiceName
? &CapturedServiceName
: NULL
,
1363 SubjectContext
.PrimaryToken
,
1367 Status
= STATUS_SUCCESS
;
1370 /* Cleanup resources */
1371 if (CapturedSubsystemName
.Buffer
!= NULL
)
1372 ReleaseCapturedUnicodeString(&CapturedSubsystemName
, PreviousMode
);
1374 if (CapturedServiceName
.Buffer
!= NULL
)
1375 ReleaseCapturedUnicodeString(&CapturedServiceName
, PreviousMode
);
1377 if (CapturedPrivileges
!= NULL
)
1378 ExFreePoolWithTag(CapturedPrivileges
, 'rPeS');
1380 /* Release the security subject context */
1381 SeReleaseSubjectContext(&SubjectContext
);
1383 ObDereferenceObject(ClientToken
);
1390 NtPrivilegeObjectAuditAlarm(IN PUNICODE_STRING SubsystemName
,
1392 IN HANDLE ClientToken
,
1393 IN ULONG DesiredAccess
,
1394 IN PPRIVILEGE_SET Privileges
,
1395 IN BOOLEAN AccessGranted
)
1398 return STATUS_NOT_IMPLEMENTED
;
1402 _Must_inspect_result_
1406 NtAccessCheckAndAuditAlarm(
1407 _In_ PUNICODE_STRING SubsystemName
,
1408 _In_opt_ PVOID HandleId
,
1409 _In_ PUNICODE_STRING ObjectTypeName
,
1410 _In_ PUNICODE_STRING ObjectName
,
1411 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
1412 _In_ ACCESS_MASK DesiredAccess
,
1413 _In_ PGENERIC_MAPPING GenericMapping
,
1414 _In_ BOOLEAN ObjectCreation
,
1415 _Out_ PACCESS_MASK GrantedAccess
,
1416 _Out_ PNTSTATUS AccessStatus
,
1417 _Out_ PBOOLEAN GenerateOnClose
)
1419 /* Call the internal function */
1420 return SepAccessCheckAndAuditAlarm(SubsystemName
,
1428 AuditEventObjectAccess
,
1439 _Must_inspect_result_
1443 NtAccessCheckByTypeAndAuditAlarm(
1444 _In_ PUNICODE_STRING SubsystemName
,
1445 _In_opt_ PVOID HandleId
,
1446 _In_ PUNICODE_STRING ObjectTypeName
,
1447 _In_ PUNICODE_STRING ObjectName
,
1448 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
1449 _In_opt_ PSID PrincipalSelfSid
,
1450 _In_ ACCESS_MASK DesiredAccess
,
1451 _In_ AUDIT_EVENT_TYPE AuditType
,
1453 _In_reads_opt_(ObjectTypeLength
) POBJECT_TYPE_LIST ObjectTypeList
,
1454 _In_ ULONG ObjectTypeLength
,
1455 _In_ PGENERIC_MAPPING GenericMapping
,
1456 _In_ BOOLEAN ObjectCreation
,
1457 _Out_ PACCESS_MASK GrantedAccess
,
1458 _Out_ PNTSTATUS AccessStatus
,
1459 _Out_ PBOOLEAN GenerateOnClose
)
1461 /* Call the internal function */
1462 return SepAccessCheckAndAuditAlarm(SubsystemName
,
1481 _Must_inspect_result_
1485 NtAccessCheckByTypeResultListAndAuditAlarm(
1486 _In_ PUNICODE_STRING SubsystemName
,
1487 _In_opt_ PVOID HandleId
,
1488 _In_ PUNICODE_STRING ObjectTypeName
,
1489 _In_ PUNICODE_STRING ObjectName
,
1490 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
1491 _In_opt_ PSID PrincipalSelfSid
,
1492 _In_ ACCESS_MASK DesiredAccess
,
1493 _In_ AUDIT_EVENT_TYPE AuditType
,
1495 _In_reads_opt_(ObjectTypeListLength
) POBJECT_TYPE_LIST ObjectTypeList
,
1496 _In_ ULONG ObjectTypeListLength
,
1497 _In_ PGENERIC_MAPPING GenericMapping
,
1498 _In_ BOOLEAN ObjectCreation
,
1499 _Out_writes_(ObjectTypeListLength
) PACCESS_MASK GrantedAccessList
,
1500 _Out_writes_(ObjectTypeListLength
) PNTSTATUS AccessStatusList
,
1501 _Out_ PBOOLEAN GenerateOnClose
)
1503 /* Call the internal function */
1504 return SepAccessCheckAndAuditAlarm(SubsystemName
,
1515 ObjectTypeListLength
,
1523 _Must_inspect_result_
1527 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(
1528 _In_ PUNICODE_STRING SubsystemName
,
1529 _In_opt_ PVOID HandleId
,
1530 _In_ HANDLE ClientToken
,
1531 _In_ PUNICODE_STRING ObjectTypeName
,
1532 _In_ PUNICODE_STRING ObjectName
,
1533 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
,
1534 _In_opt_ PSID PrincipalSelfSid
,
1535 _In_ ACCESS_MASK DesiredAccess
,
1536 _In_ AUDIT_EVENT_TYPE AuditType
,
1538 _In_reads_opt_(ObjectTypeListLength
) POBJECT_TYPE_LIST ObjectTypeList
,
1539 _In_ ULONG ObjectTypeListLength
,
1540 _In_ PGENERIC_MAPPING GenericMapping
,
1541 _In_ BOOLEAN ObjectCreation
,
1542 _Out_writes_(ObjectTypeListLength
) PACCESS_MASK GrantedAccessList
,
1543 _Out_writes_(ObjectTypeListLength
) PNTSTATUS AccessStatusList
,
1544 _Out_ PBOOLEAN GenerateOnClose
)
1546 UNREFERENCED_PARAMETER(ObjectCreation
);
1548 /* Call the internal function */
1549 return SepAccessCheckAndAuditAlarm(SubsystemName
,
1560 ObjectTypeListLength
,