Fix GCC build
[reactos.git] / reactos / ntoskrnl / se / audit.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/audit.c
5 * PURPOSE: Audit functions
6 *
7 * PROGRAMMERS: Eric Kohl
8 * Timo Kreuzer (timo.kreuzer@reactos.org)
9 */
10
11 /* INCLUDES *******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 #define SEP_PRIVILEGE_SET_MAX_COUNT 60
18
19 /* PRIVATE FUNCTIONS***********************************************************/
20
21 BOOLEAN
22 NTAPI
23 SeDetailedAuditingWithToken(IN PTOKEN Token)
24 {
25 /* FIXME */
26 return FALSE;
27 }
28
29 VOID
30 NTAPI
31 SeAuditProcessCreate(IN PEPROCESS Process)
32 {
33 /* FIXME */
34 }
35
36 VOID
37 NTAPI
38 SeAuditProcessExit(IN PEPROCESS Process)
39 {
40 /* FIXME */
41 }
42
43 NTSTATUS
44 NTAPI
45 SeInitializeProcessAuditName(IN PFILE_OBJECT FileObject,
46 IN BOOLEAN DoAudit,
47 OUT POBJECT_NAME_INFORMATION *AuditInfo)
48 {
49 OBJECT_NAME_INFORMATION LocalNameInfo;
50 POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
51 ULONG ReturnLength = 8;
52 NTSTATUS Status;
53
54 PAGED_CODE();
55 ASSERT(AuditInfo);
56
57 /* Check if we should do auditing */
58 if (DoAudit)
59 {
60 /* FIXME: TODO */
61 }
62
63 /* Now query the name */
64 Status = ObQueryNameString(FileObject,
65 &LocalNameInfo,
66 sizeof(LocalNameInfo),
67 &ReturnLength);
68 if (((Status == STATUS_BUFFER_OVERFLOW) ||
69 (Status == STATUS_BUFFER_TOO_SMALL) ||
70 (Status == STATUS_INFO_LENGTH_MISMATCH)) &&
71 (ReturnLength != sizeof(LocalNameInfo)))
72 {
73 /* Allocate required size */
74 ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool,
75 ReturnLength,
76 TAG_SEPA);
77 if (ObjectNameInfo)
78 {
79 /* Query the name again */
80 Status = ObQueryNameString(FileObject,
81 ObjectNameInfo,
82 ReturnLength,
83 &ReturnLength);
84 }
85 }
86
87 /* Check if we got here due to failure */
88 if ((ObjectNameInfo) &&
89 (!(NT_SUCCESS(Status)) || (ReturnLength == sizeof(LocalNameInfo))))
90 {
91 /* First, free any buffer we might've allocated */
92 ASSERT(FALSE);
93 if (ObjectNameInfo) ExFreePool(ObjectNameInfo);
94
95 /* Now allocate a temporary one */
96 ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
97 ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool,
98 sizeof(OBJECT_NAME_INFORMATION),
99 TAG_SEPA);
100 if (ObjectNameInfo)
101 {
102 /* Clear it */
103 RtlZeroMemory(ObjectNameInfo, ReturnLength);
104 Status = STATUS_SUCCESS;
105 }
106 }
107
108 /* Check if memory allocation failed */
109 if (!ObjectNameInfo) Status = STATUS_NO_MEMORY;
110
111 /* Return the audit name */
112 *AuditInfo = ObjectNameInfo;
113
114 /* Return status */
115 return Status;
116 }
117
118 NTSTATUS
119 NTAPI
120 SeLocateProcessImageName(IN PEPROCESS Process,
121 OUT PUNICODE_STRING *ProcessImageName)
122 {
123 POBJECT_NAME_INFORMATION AuditName;
124 PUNICODE_STRING ImageName;
125 PFILE_OBJECT FileObject;
126 NTSTATUS Status = STATUS_SUCCESS;
127
128 PAGED_CODE();
129
130 /* Assume failure */
131 *ProcessImageName = NULL;
132
133 /* Check if we have audit info */
134 AuditName = Process->SeAuditProcessCreationInfo.ImageFileName;
135 if (!AuditName)
136 {
137 /* Get the file object */
138 Status = PsReferenceProcessFilePointer(Process, &FileObject);
139 if (!NT_SUCCESS(Status)) return Status;
140
141 /* Initialize the audit structure */
142 Status = SeInitializeProcessAuditName(FileObject, TRUE, &AuditName);
143 if (NT_SUCCESS(Status))
144 {
145 /* Set it */
146 if (InterlockedCompareExchangePointer((PVOID*)&Process->
147 SeAuditProcessCreationInfo.ImageFileName,
148 AuditName,
149 NULL))
150 {
151 /* Someone beat us to it, deallocate our copy */
152 ExFreePool(AuditName);
153 }
154 }
155
156 /* Dereference the file object */
157 ObDereferenceObject(FileObject);
158 if (!NT_SUCCESS(Status)) return Status;
159 }
160
161 /* Get audit info again, now we have it for sure */
162 AuditName = Process->SeAuditProcessCreationInfo.ImageFileName;
163
164 /* Allocate the output string */
165 ImageName = ExAllocatePoolWithTag(NonPagedPool,
166 AuditName->Name.MaximumLength +
167 sizeof(UNICODE_STRING),
168 TAG_SEPA);
169 if (!ImageName) return STATUS_NO_MEMORY;
170
171 /* Make a copy of it */
172 RtlCopyMemory(ImageName,
173 &AuditName->Name,
174 AuditName->Name.MaximumLength + sizeof(UNICODE_STRING));
175
176 /* Fix up the buffer */
177 ImageName->Buffer = (PWSTR)(ImageName + 1);
178
179 /* Return it */
180 *ProcessImageName = ImageName;
181
182 /* Return status */
183 return Status;
184 }
185
186 VOID
187 NTAPI
188 SepAdtCloseObjectAuditAlarm(
189 PUNICODE_STRING SubsystemName,
190 PVOID HandleId,
191 PSID Sid)
192 {
193 UNIMPLEMENTED;
194 }
195
196 VOID
197 NTAPI
198 SepAdtPrivilegedServiceAuditAlarm(
199 PSECURITY_SUBJECT_CONTEXT SubjectContext,
200 _In_opt_ PUNICODE_STRING SubsystemName,
201 _In_opt_ PUNICODE_STRING ServiceName,
202 _In_ PTOKEN Token,
203 _In_ PTOKEN PrimaryToken,
204 _In_ PPRIVILEGE_SET Privileges,
205 _In_ BOOLEAN AccessGranted )
206 {
207 UNIMPLEMENTED;
208 }
209
210 static
211 NTSTATUS
212 SeCaptureObjectTypeList(
213 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
214 _In_ ULONG ObjectTypeListLength,
215 _In_ KPROCESSOR_MODE PreviousMode,
216 _Out_ POBJECT_TYPE_LIST *CapturedObjectTypeList)
217 {
218 SIZE_T Size;
219
220 if (PreviousMode == KernelMode)
221 {
222 return STATUS_NOT_IMPLEMENTED;
223 }
224
225 if (ObjectTypeListLength == 0)
226 {
227 *CapturedObjectTypeList = NULL;
228 return STATUS_SUCCESS;
229 }
230
231 if (ObjectTypeList == NULL)
232 {
233 return STATUS_INVALID_PARAMETER;
234 }
235
236 /* Calculate the list size and check for integer overflow */
237 Size = ObjectTypeListLength * sizeof(OBJECT_TYPE_LIST);
238 if (Size == 0)
239 {
240 return STATUS_INVALID_PARAMETER;
241 }
242
243 /* Allocate a new list */
244 *CapturedObjectTypeList = ExAllocatePoolWithTag(PagedPool, Size, TAG_SEPA);
245 if (*CapturedObjectTypeList == NULL)
246 {
247 return STATUS_INSUFFICIENT_RESOURCES;
248 }
249
250 _SEH2_TRY
251 {
252 ProbeForRead(ObjectTypeList, Size, sizeof(ULONG));
253 RtlCopyMemory(*CapturedObjectTypeList, ObjectTypeList, Size);
254 }
255 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
256 {
257 ExFreePoolWithTag(*CapturedObjectTypeList, TAG_SEPA);
258 *CapturedObjectTypeList = NULL;
259 return _SEH2_GetExceptionCode();
260 }
261 _SEH2_END;
262
263 return STATUS_SUCCESS;
264 }
265
266 static
267 VOID
268 SeReleaseObjectTypeList(
269 _In_ _Post_invalid_ POBJECT_TYPE_LIST CapturedObjectTypeList,
270 _In_ KPROCESSOR_MODE PreviousMode)
271 {
272 if ((PreviousMode != KernelMode) && (CapturedObjectTypeList != NULL))
273 ExFreePoolWithTag(CapturedObjectTypeList, TAG_SEPA);
274 }
275
276 _Must_inspect_result_
277 static
278 NTSTATUS
279 SepAccessCheckAndAuditAlarmWorker(
280 _In_ PUNICODE_STRING SubsystemName,
281 _In_opt_ PVOID HandleId,
282 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
283 _In_ PUNICODE_STRING ObjectTypeName,
284 _In_ PUNICODE_STRING ObjectName,
285 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
286 _In_opt_ PSID PrincipalSelfSid,
287 _In_ ACCESS_MASK DesiredAccess,
288 _In_ AUDIT_EVENT_TYPE AuditType,
289 _In_ BOOLEAN HaveAuditPrivilege,
290 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
291 _In_ ULONG ObjectTypeListLength,
292 _In_ PGENERIC_MAPPING GenericMapping,
293 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
294 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
295 _Out_ PBOOLEAN GenerateOnClose,
296 _In_ BOOLEAN UseResultList)
297 {
298 ULONG ResultListLength, i;
299
300 /* Get the length of the result list */
301 ResultListLength = UseResultList ? ObjectTypeListLength : 1;
302
303 /// FIXME: we should do some real work here...
304 UNIMPLEMENTED;
305
306 /// HACK: we just pretend all access is granted!
307 for (i = 0; i < ResultListLength; i++)
308 {
309 GrantedAccessList[i] = DesiredAccess;
310 AccessStatusList[i] = STATUS_SUCCESS;
311 }
312
313 *GenerateOnClose = FALSE;
314
315 return STATUS_SUCCESS;
316 }
317
318 _Must_inspect_result_
319 NTSTATUS
320 NTAPI
321 SepAccessCheckAndAuditAlarm(
322 _In_ PUNICODE_STRING SubsystemName,
323 _In_opt_ PVOID HandleId,
324 _In_ PHANDLE ClientTokenHandle,
325 _In_ PUNICODE_STRING ObjectTypeName,
326 _In_ PUNICODE_STRING ObjectName,
327 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
328 _In_opt_ PSID PrincipalSelfSid,
329 _In_ ACCESS_MASK DesiredAccess,
330 _In_ AUDIT_EVENT_TYPE AuditType,
331 _In_ ULONG Flags,
332 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
333 _In_ ULONG ObjectTypeListLength,
334 _In_ PGENERIC_MAPPING GenericMapping,
335 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
336 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
337 _Out_ PBOOLEAN GenerateOnClose,
338 _In_ BOOLEAN UseResultList)
339 {
340 SECURITY_SUBJECT_CONTEXT SubjectContext;
341 ULONG ResultListLength;
342 GENERIC_MAPPING LocalGenericMapping;
343 PTOKEN SubjectContextToken, ClientToken;
344 BOOLEAN AllocatedResultLists;
345 BOOLEAN HaveAuditPrivilege;
346 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor;
347 UNICODE_STRING CapturedSubsystemName, CapturedObjectTypeName, CapturedObjectName;
348 ACCESS_MASK GrantedAccess, *SafeGrantedAccessList;
349 NTSTATUS AccessStatus, *SafeAccessStatusList;
350 PSID CapturedPrincipalSelfSid;
351 POBJECT_TYPE_LIST CapturedObjectTypeList;
352 ULONG i;
353 BOOLEAN LocalGenerateOnClose;
354 NTSTATUS Status;
355 PAGED_CODE();
356
357 /* Only user mode is supported! */
358 ASSERT(ExGetPreviousMode() != KernelMode);
359
360 /* Start clean */
361 AllocatedResultLists = FALSE;
362 ClientToken = NULL;
363 CapturedSecurityDescriptor = NULL;
364 CapturedSubsystemName.Buffer = NULL;
365 CapturedObjectTypeName.Buffer = NULL;
366 CapturedObjectName.Buffer = NULL;
367 CapturedPrincipalSelfSid = NULL;
368 CapturedObjectTypeList = NULL;
369
370 /* Validate AuditType */
371 if ((AuditType != AuditEventObjectAccess) &&
372 (AuditType != AuditEventDirectoryServiceAccess))
373 {
374 DPRINT1("Invalid audit type: %u\n", AuditType);
375 return STATUS_INVALID_PARAMETER;
376 }
377
378 /* Capture the security subject context */
379 SeCaptureSubjectContext(&SubjectContext);
380
381 /* Did the caller pass a token handle? */
382 if (ClientTokenHandle == NULL)
383 {
384 /* Check if we have a token in the subject context */
385 if (SubjectContext.ClientToken == NULL)
386 {
387 Status = STATUS_NO_IMPERSONATION_TOKEN;
388 DPRINT1("No token\n");
389 goto Cleanup;
390 }
391
392 /* Check if we have a valid impersonation level */
393 if (SubjectContext.ImpersonationLevel < SecurityIdentification)
394 {
395 Status = STATUS_BAD_IMPERSONATION_LEVEL;
396 DPRINT1("Invalid impersonation level 0x%lx\n",
397 SubjectContext.ImpersonationLevel);
398 goto Cleanup;
399 }
400 }
401
402 /* Are we using a result list? */
403 if (UseResultList)
404 {
405 /* The list length equals the object type list length */
406 ResultListLength = ObjectTypeListLength;
407 if ((ResultListLength == 0) || (ResultListLength > 0x1000))
408 {
409 Status = STATUS_INVALID_PARAMETER;
410 DPRINT1("Invalud ResultListLength: 0x%lx\n", ResultListLength);
411 goto Cleanup;
412 }
413
414 /* Allocate a safe buffer from paged pool */
415 SafeGrantedAccessList = ExAllocatePoolWithTag(PagedPool,
416 2 * ResultListLength * sizeof(ULONG),
417 TAG_SEPA);
418 if (SafeGrantedAccessList == NULL)
419 {
420 Status = STATUS_INSUFFICIENT_RESOURCES;
421 DPRINT1("Failed to allocate access lists\n");
422 goto Cleanup;
423 }
424
425 SafeAccessStatusList = (PNTSTATUS)&SafeGrantedAccessList[ResultListLength];
426 AllocatedResultLists = TRUE;
427 }
428 else
429 {
430 /* List length is 1 */
431 ResultListLength = 1;
432 SafeGrantedAccessList = &GrantedAccess;
433 SafeAccessStatusList = &AccessStatus;
434 }
435
436 _SEH2_TRY
437 {
438 /* Probe output buffers */
439 ProbeForWrite(AccessStatusList,
440 ResultListLength * sizeof(*AccessStatusList),
441 sizeof(*AccessStatusList));
442 ProbeForWrite(GrantedAccessList,
443 ResultListLength * sizeof(*GrantedAccessList),
444 sizeof(*GrantedAccessList));
445
446 /* Probe generic mapping and make a local copy */
447 ProbeForRead(GenericMapping, sizeof(*GenericMapping), sizeof(ULONG));
448 LocalGenericMapping = * GenericMapping;
449 }
450 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
451 {
452 Status = _SEH2_GetExceptionCode();
453 DPRINT1("Exception while probing parameters: 0x%lx\n", Status);
454 goto Cleanup;
455 }
456 _SEH2_END;
457
458 /* Do we have a client token? */
459 if (ClientTokenHandle != NULL)
460 {
461 /* Reference the client token */
462 Status = ObReferenceObjectByHandle(*ClientTokenHandle,
463 TOKEN_QUERY,
464 SeTokenObjectType,
465 UserMode,
466 (PVOID*)&ClientToken,
467 NULL);
468 if (!NT_SUCCESS(Status))
469 {
470 DPRINT1("Failed to reference token handle %p: %lx\n",
471 *ClientTokenHandle, Status);
472 goto Cleanup;
473 }
474
475 SubjectContextToken = SubjectContext.ClientToken;
476 SubjectContext.ClientToken = ClientToken;
477 }
478
479 /* Check for audit privilege */
480 HaveAuditPrivilege = SeSinglePrivilegeCheck(SeAuditPrivilege, UserMode);
481 if (!HaveAuditPrivilege && !(Flags & AUDIT_ALLOW_NO_PRIVILEGE))
482 {
483 DPRINT1("Caller does not have SeAuditPrivilege\n");
484 Status = STATUS_PRIVILEGE_NOT_HELD;
485 goto Cleanup;
486 }
487
488 /* Generic access must already be mapped to non-generic access types! */
489 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
490 {
491 DPRINT1("Generic access rights requested: 0x%lx\n", DesiredAccess);
492 Status = STATUS_GENERIC_NOT_MAPPED;
493 goto Cleanup;
494 }
495
496 /* Capture the security descriptor */
497 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
498 UserMode,
499 PagedPool,
500 FALSE,
501 &CapturedSecurityDescriptor);
502 if (!NT_SUCCESS(Status))
503 {
504 DPRINT1("Failed to capture security descriptor!\n");
505 goto Cleanup;
506 }
507
508 /* Validate the Security descriptor */
509 if ((SepGetOwnerFromDescriptor(CapturedSecurityDescriptor) == NULL) ||
510 (SepGetGroupFromDescriptor(CapturedSecurityDescriptor) == NULL))
511 {
512 Status = STATUS_INVALID_SECURITY_DESCR;
513 DPRINT1("Invalid security descriptor\n");
514 goto Cleanup;
515 }
516
517 /* Probe and capture the subsystem name */
518 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
519 UserMode,
520 SubsystemName);
521 if (!NT_SUCCESS(Status))
522 {
523 DPRINT1("Failed to capture subsystem name!\n");
524 goto Cleanup;
525 }
526
527 /* Probe and capture the object type name */
528 Status = ProbeAndCaptureUnicodeString(&CapturedObjectTypeName,
529 UserMode,
530 ObjectTypeName);
531 if (!NT_SUCCESS(Status))
532 {
533 DPRINT1("Failed to capture object type name!\n");
534 goto Cleanup;
535 }
536
537 /* Probe and capture the object name */
538 Status = ProbeAndCaptureUnicodeString(&CapturedObjectName,
539 UserMode,
540 ObjectName);
541 if (!NT_SUCCESS(Status))
542 {
543 DPRINT1("Failed to capture object name!\n");
544 goto Cleanup;
545 }
546
547 /* Check if we have a PrincipalSelfSid */
548 if (PrincipalSelfSid != NULL)
549 {
550 /* Capture it */
551 Status = SepCaptureSid(PrincipalSelfSid,
552 UserMode,
553 PagedPool,
554 FALSE,
555 &CapturedPrincipalSelfSid);
556 if (!NT_SUCCESS(Status))
557 {
558 DPRINT1("Failed to capture PrincipalSelfSid!\n");
559 goto Cleanup;
560 }
561 }
562
563 /* Capture the object type list */
564 Status = SeCaptureObjectTypeList(ObjectTypeList,
565 ObjectTypeListLength,
566 UserMode,
567 &CapturedObjectTypeList);
568 if (!NT_SUCCESS(Status))
569 {
570 DPRINT1("Failed to capture object type list!\n");
571 goto Cleanup;
572 }
573
574 /* Call the worker routine with the captured buffers */
575 SepAccessCheckAndAuditAlarmWorker(&CapturedSubsystemName,
576 HandleId,
577 &SubjectContext,
578 &CapturedObjectTypeName,
579 &CapturedObjectName,
580 CapturedSecurityDescriptor,
581 CapturedPrincipalSelfSid,
582 DesiredAccess,
583 AuditType,
584 HaveAuditPrivilege,
585 CapturedObjectTypeList,
586 ObjectTypeListLength,
587 &LocalGenericMapping,
588 SafeGrantedAccessList,
589 SafeAccessStatusList,
590 &LocalGenerateOnClose,
591 UseResultList);
592
593 /* Enter SEH to copy the data back to user mode */
594 _SEH2_TRY
595 {
596 /* Loop all result entries (only 1 when no list was requested) */
597 NT_ASSERT(UseResultList || (ResultListLength == 1));
598 for (i = 0; i < ResultListLength; i++)
599 {
600 AccessStatusList[i] = SafeAccessStatusList[i];
601 GrantedAccessList[i] = SafeGrantedAccessList[i];
602 }
603
604 *GenerateOnClose = LocalGenerateOnClose;
605 }
606 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
607 {
608 Status = _SEH2_GetExceptionCode();
609 DPRINT1("Exception while copying back data: 0x%lx\n", Status);
610 }
611 _SEH2_END;
612
613 Cleanup:
614
615 if (CapturedObjectTypeList != NULL)
616 SeReleaseObjectTypeList(CapturedObjectTypeList, UserMode);
617
618 if (CapturedPrincipalSelfSid != NULL)
619 SepReleaseSid(CapturedPrincipalSelfSid, UserMode, FALSE);
620
621 if (CapturedObjectName.Buffer != NULL)
622 ReleaseCapturedUnicodeString(&CapturedObjectName, UserMode);
623
624 if (CapturedObjectTypeName.Buffer != NULL)
625 ReleaseCapturedUnicodeString(&CapturedObjectTypeName, UserMode);
626
627 if (CapturedSubsystemName.Buffer != NULL)
628 ReleaseCapturedUnicodeString(&CapturedSubsystemName, UserMode);
629
630 if (CapturedSecurityDescriptor != NULL)
631 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor, UserMode, FALSE);
632
633 if (ClientToken != NULL)
634 {
635 ObDereferenceObject(ClientToken);
636 SubjectContext.ClientToken = SubjectContextToken;
637 }
638
639 if (AllocatedResultLists)
640 ExFreePoolWithTag(SafeGrantedAccessList, TAG_SEPA);
641
642 /* Release the security subject context */
643 SeReleaseSubjectContext(&SubjectContext);
644
645 return Status;
646 }
647
648
649 /* PUBLIC FUNCTIONS ***********************************************************/
650
651 /*
652 * @unimplemented
653 */
654 VOID
655 NTAPI
656 SeAuditHardLinkCreation(IN PUNICODE_STRING FileName,
657 IN PUNICODE_STRING LinkName,
658 IN BOOLEAN bSuccess)
659 {
660 UNIMPLEMENTED;
661 }
662
663 /*
664 * @unimplemented
665 */
666 BOOLEAN
667 NTAPI
668 SeAuditingFileEvents(IN BOOLEAN AccessGranted,
669 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
670 {
671 UNIMPLEMENTED;
672 return FALSE;
673 }
674
675 /*
676 * @unimplemented
677 */
678 BOOLEAN
679 NTAPI
680 SeAuditingFileEventsWithContext(IN BOOLEAN AccessGranted,
681 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
682 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL)
683 {
684 UNIMPLEMENTED;
685 return FALSE;
686 }
687
688 /*
689 * @unimplemented
690 */
691 BOOLEAN
692 NTAPI
693 SeAuditingHardLinkEvents(IN BOOLEAN AccessGranted,
694 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
695 {
696 UNIMPLEMENTED;
697 return FALSE;
698 }
699
700 /*
701 * @unimplemented
702 */
703 BOOLEAN
704 NTAPI
705 SeAuditingHardLinkEventsWithContext(IN BOOLEAN AccessGranted,
706 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
707 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL)
708 {
709 UNIMPLEMENTED;
710 return FALSE;
711 }
712
713 /*
714 * @unimplemented
715 */
716 BOOLEAN
717 NTAPI
718 SeAuditingFileOrGlobalEvents(IN BOOLEAN AccessGranted,
719 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
720 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext)
721 {
722 UNIMPLEMENTED;
723 return FALSE;
724 }
725
726 /*
727 * @unimplemented
728 */
729 VOID
730 NTAPI
731 SeCloseObjectAuditAlarm(IN PVOID Object,
732 IN HANDLE Handle,
733 IN BOOLEAN PerformAction)
734 {
735 UNIMPLEMENTED;
736 }
737
738 /*
739 * @unimplemented
740 */
741 VOID NTAPI
742 SeDeleteObjectAuditAlarm(IN PVOID Object,
743 IN HANDLE Handle)
744 {
745 UNIMPLEMENTED;
746 }
747
748 /*
749 * @unimplemented
750 */
751 VOID
752 NTAPI
753 SeOpenObjectAuditAlarm(IN PUNICODE_STRING ObjectTypeName,
754 IN PVOID Object OPTIONAL,
755 IN PUNICODE_STRING AbsoluteObjectName OPTIONAL,
756 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
757 IN PACCESS_STATE AccessState,
758 IN BOOLEAN ObjectCreated,
759 IN BOOLEAN AccessGranted,
760 IN KPROCESSOR_MODE AccessMode,
761 OUT PBOOLEAN GenerateOnClose)
762 {
763 PAGED_CODE();
764
765 /* Audits aren't done on kernel-mode access */
766 if (AccessMode == KernelMode) return;
767
768 /* Otherwise, unimplemented! */
769 //UNIMPLEMENTED;
770 return;
771 }
772
773 /*
774 * @unimplemented
775 */
776 VOID NTAPI
777 SeOpenObjectForDeleteAuditAlarm(IN PUNICODE_STRING ObjectTypeName,
778 IN PVOID Object OPTIONAL,
779 IN PUNICODE_STRING AbsoluteObjectName OPTIONAL,
780 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
781 IN PACCESS_STATE AccessState,
782 IN BOOLEAN ObjectCreated,
783 IN BOOLEAN AccessGranted,
784 IN KPROCESSOR_MODE AccessMode,
785 OUT PBOOLEAN GenerateOnClose)
786 {
787 UNIMPLEMENTED;
788 }
789
790 /*
791 * @unimplemented
792 */
793 VOID
794 NTAPI
795 SePrivilegeObjectAuditAlarm(IN HANDLE Handle,
796 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
797 IN ACCESS_MASK DesiredAccess,
798 IN PPRIVILEGE_SET Privileges,
799 IN BOOLEAN AccessGranted,
800 IN KPROCESSOR_MODE CurrentMode)
801 {
802 UNIMPLEMENTED;
803 }
804
805 /* SYSTEM CALLS ***************************************************************/
806
807 NTSTATUS
808 NTAPI
809 NtCloseObjectAuditAlarm(
810 PUNICODE_STRING SubsystemName,
811 PVOID HandleId,
812 BOOLEAN GenerateOnClose)
813 {
814 UNICODE_STRING CapturedSubsystemName;
815 KPROCESSOR_MODE PreviousMode;
816 BOOLEAN UseImpersonationToken;
817 PETHREAD CurrentThread;
818 BOOLEAN CopyOnOpen, EffectiveOnly;
819 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
820 NTSTATUS Status;
821 PTOKEN Token;
822 PAGED_CODE();
823
824 /* Get the previous mode (only user mode is supported!) */
825 PreviousMode = ExGetPreviousMode();
826 ASSERT(PreviousMode != KernelMode);
827
828 /* Do we even need to do anything? */
829 if (!GenerateOnClose)
830 {
831 /* Nothing to do, return success */
832 return STATUS_SUCCESS;
833 }
834
835 /* Validate privilege */
836 if (!SeSinglePrivilegeCheck(SeAuditPrivilege, PreviousMode))
837 {
838 DPRINT1("Caller does not have SeAuditPrivilege\n");
839 return STATUS_PRIVILEGE_NOT_HELD;
840 }
841
842 /* Probe and capture the subsystem name */
843 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
844 PreviousMode,
845 SubsystemName);
846 if (!NT_SUCCESS(Status))
847 {
848 DPRINT1("Failed to capture subsystem name!\n");
849 return Status;
850 }
851
852 /* Get the current thread and check if it's impersonating */
853 CurrentThread = PsGetCurrentThread();
854 if (PsIsThreadImpersonating(CurrentThread))
855 {
856 /* Get the impersonation token */
857 Token = PsReferenceImpersonationToken(CurrentThread,
858 &CopyOnOpen,
859 &EffectiveOnly,
860 &ImpersonationLevel);
861 UseImpersonationToken = TRUE;
862 }
863 else
864 {
865 /* Get the primary token */
866 Token = PsReferencePrimaryToken(PsGetCurrentProcess());
867 UseImpersonationToken = FALSE;
868 }
869
870 /* Call the internal function */
871 SepAdtCloseObjectAuditAlarm(&CapturedSubsystemName,
872 HandleId,
873 Token->UserAndGroups->Sid);
874
875 /* Release the captured subsystem name */
876 ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode);
877
878 /* Check what token we used */
879 if (UseImpersonationToken)
880 {
881 /* Release impersonation token */
882 PsDereferenceImpersonationToken(Token);
883 }
884 else
885 {
886 /* Release primary token */
887 PsDereferencePrimaryToken(Token);
888 }
889
890 return STATUS_SUCCESS;
891 }
892
893
894 NTSTATUS NTAPI
895 NtDeleteObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
896 IN PVOID HandleId,
897 IN BOOLEAN GenerateOnClose)
898 {
899 UNIMPLEMENTED;
900 return STATUS_NOT_IMPLEMENTED;
901 }
902
903
904 NTSTATUS NTAPI
905 NtOpenObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
906 IN PVOID HandleId,
907 IN PUNICODE_STRING ObjectTypeName,
908 IN PUNICODE_STRING ObjectName,
909 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
910 IN HANDLE ClientToken,
911 IN ULONG DesiredAccess,
912 IN ULONG GrantedAccess,
913 IN PPRIVILEGE_SET Privileges,
914 IN BOOLEAN ObjectCreation,
915 IN BOOLEAN AccessGranted,
916 OUT PBOOLEAN GenerateOnClose)
917 {
918 UNIMPLEMENTED;
919 return STATUS_NOT_IMPLEMENTED;
920 }
921
922
923 __kernel_entry
924 NTSTATUS
925 NTAPI
926 NtPrivilegedServiceAuditAlarm(
927 _In_opt_ PUNICODE_STRING SubsystemName,
928 _In_opt_ PUNICODE_STRING ServiceName,
929 _In_ HANDLE ClientToken,
930 _In_ PPRIVILEGE_SET Privileges,
931 _In_ BOOLEAN AccessGranted )
932 {
933 KPROCESSOR_MODE PreviousMode;
934 PTOKEN Token;
935 volatile PPRIVILEGE_SET CapturedPrivileges = NULL;
936 UNICODE_STRING CapturedSubsystemName;
937 UNICODE_STRING CapturedServiceName;
938 ULONG PrivilegeCount, PrivilegesSize;
939 SECURITY_SUBJECT_CONTEXT SubjectContext;
940 NTSTATUS Status;
941 PAGED_CODE();
942
943 /* Get the previous mode (only user mode is supported!) */
944 PreviousMode = ExGetPreviousMode();
945 ASSERT(PreviousMode != KernelMode);
946
947 CapturedSubsystemName.Buffer = NULL;
948 CapturedServiceName.Buffer = NULL;
949
950 /* Reference the client token */
951 Status = ObReferenceObjectByHandle(ClientToken,
952 TOKEN_QUERY,
953 SeTokenObjectType,
954 PreviousMode,
955 (PVOID*)&Token,
956 NULL);
957 if (!NT_SUCCESS(Status))
958 {
959 DPRINT1("Failed to reference client token: 0x%lx\n", Status);
960 return Status;
961 }
962
963 /* Validate the token's impersonation level */
964 if ((Token->TokenType == TokenImpersonation) &&
965 (Token->ImpersonationLevel < SecurityIdentification))
966 {
967 DPRINT1("Invalid impersonation level (%u)\n", Token->ImpersonationLevel);
968 ObfDereferenceObject(Token);
969 return STATUS_BAD_IMPERSONATION_LEVEL;
970 }
971
972 /* Validate privilege */
973 if (!SeSinglePrivilegeCheck(SeAuditPrivilege, PreviousMode))
974 {
975 DPRINT1("Caller does not have SeAuditPrivilege\n");
976 ObfDereferenceObject(Token);
977 return STATUS_PRIVILEGE_NOT_HELD;
978 }
979
980 /* Do we have a subsystem name? */
981 if (SubsystemName != NULL)
982 {
983 /* Probe and capture the subsystem name */
984 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
985 PreviousMode,
986 SubsystemName);
987 if (!NT_SUCCESS(Status))
988 {
989 DPRINT1("Failed to capture subsystem name!\n");
990 goto Cleanup;
991 }
992 }
993
994 /* Do we have a service name? */
995 if (ServiceName != NULL)
996 {
997 /* Probe and capture the service name */
998 Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
999 PreviousMode,
1000 ServiceName);
1001 if (!NT_SUCCESS(Status))
1002 {
1003 DPRINT1("Failed to capture service name!\n");
1004 goto Cleanup;
1005 }
1006 }
1007
1008 _SEH2_TRY
1009 {
1010 /* Probe the basic privilege set structure */
1011 ProbeForRead(Privileges, sizeof(PRIVILEGE_SET), sizeof(ULONG));
1012
1013 /* Validate privilege count */
1014 PrivilegeCount = Privileges->PrivilegeCount;
1015 if (PrivilegeCount > SEP_PRIVILEGE_SET_MAX_COUNT)
1016 {
1017 Status = STATUS_INVALID_PARAMETER;
1018 goto Cleanup;
1019 }
1020
1021 /* Calculate the size of the Privileges structure */
1022 PrivilegesSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]);
1023
1024 /* Probe the whole structure */
1025 ProbeForRead(Privileges, PrivilegesSize, sizeof(ULONG));
1026
1027 /* Allocate a temp buffer */
1028 CapturedPrivileges = ExAllocatePoolWithTag(PagedPool,
1029 PrivilegesSize,
1030 'rPeS');
1031 if (CapturedPrivileges == NULL)
1032 {
1033 DPRINT1("Failed to allocate %u bytes\n", PrivilegesSize);
1034 Status = STATUS_INSUFFICIENT_RESOURCES;
1035 goto Cleanup;
1036 }
1037
1038 /* Copy the privileges */
1039 RtlCopyMemory(CapturedPrivileges, Privileges, PrivilegesSize);
1040 }
1041 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1042 {
1043 Status = _SEH2_GetExceptionCode();
1044 DPRINT1("Got exception 0x%lx\n", Status);
1045 goto Cleanup;
1046 }
1047 _SEH2_END;
1048
1049 /* Capture the security subject context */
1050 SeCaptureSubjectContext(&SubjectContext);
1051
1052 /* Call the internal function */
1053 SepAdtPrivilegedServiceAuditAlarm(&SubjectContext,
1054 SubsystemName ? &CapturedSubsystemName : NULL,
1055 ServiceName ? &CapturedServiceName : NULL,
1056 Token,
1057 SubjectContext.PrimaryToken,
1058 CapturedPrivileges,
1059 AccessGranted);
1060
1061 /* Release the security subject context */
1062 SeReleaseSubjectContext(&SubjectContext);
1063
1064 Status = STATUS_SUCCESS;
1065
1066 Cleanup:
1067 /* Cleanup resources */
1068 if (CapturedSubsystemName.Buffer != NULL)
1069 ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode);
1070 if (CapturedServiceName.Buffer != NULL)
1071 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1072 if (CapturedPrivileges != NULL)
1073 ExFreePoolWithTag(CapturedPrivileges, 0);
1074 ObDereferenceObject(Token);
1075
1076 return Status;
1077 }
1078
1079
1080 NTSTATUS NTAPI
1081 NtPrivilegeObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
1082 IN PVOID HandleId,
1083 IN HANDLE ClientToken,
1084 IN ULONG DesiredAccess,
1085 IN PPRIVILEGE_SET Privileges,
1086 IN BOOLEAN AccessGranted)
1087 {
1088 UNIMPLEMENTED;
1089 return STATUS_NOT_IMPLEMENTED;
1090 }
1091
1092
1093 _Must_inspect_result_
1094 __kernel_entry
1095 NTSTATUS
1096 NTAPI
1097 NtAccessCheckAndAuditAlarm(
1098 _In_ PUNICODE_STRING SubsystemName,
1099 _In_opt_ PVOID HandleId,
1100 _In_ PUNICODE_STRING ObjectTypeName,
1101 _In_ PUNICODE_STRING ObjectName,
1102 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1103 _In_ ACCESS_MASK DesiredAccess,
1104 _In_ PGENERIC_MAPPING GenericMapping,
1105 _In_ BOOLEAN ObjectCreation,
1106 _Out_ PACCESS_MASK GrantedAccess,
1107 _Out_ PNTSTATUS AccessStatus,
1108 _Out_ PBOOLEAN GenerateOnClose)
1109 {
1110 /* Call the internal function */
1111 return SepAccessCheckAndAuditAlarm(SubsystemName,
1112 HandleId,
1113 NULL,
1114 ObjectTypeName,
1115 ObjectName,
1116 SecurityDescriptor,
1117 NULL,
1118 DesiredAccess,
1119 AuditEventObjectAccess,
1120 0,
1121 NULL,
1122 0,
1123 GenericMapping,
1124 GrantedAccess,
1125 AccessStatus,
1126 GenerateOnClose,
1127 FALSE);
1128 }
1129
1130 _Must_inspect_result_
1131 __kernel_entry
1132 NTSTATUS
1133 NTAPI
1134 NtAccessCheckByTypeAndAuditAlarm(
1135 _In_ PUNICODE_STRING SubsystemName,
1136 _In_opt_ PVOID HandleId,
1137 _In_ PUNICODE_STRING ObjectTypeName,
1138 _In_ PUNICODE_STRING ObjectName,
1139 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1140 _In_opt_ PSID PrincipalSelfSid,
1141 _In_ ACCESS_MASK DesiredAccess,
1142 _In_ AUDIT_EVENT_TYPE AuditType,
1143 _In_ ULONG Flags,
1144 _In_reads_opt_(ObjectTypeLength) POBJECT_TYPE_LIST ObjectTypeList,
1145 _In_ ULONG ObjectTypeLength,
1146 _In_ PGENERIC_MAPPING GenericMapping,
1147 _In_ BOOLEAN ObjectCreation,
1148 _Out_ PACCESS_MASK GrantedAccess,
1149 _Out_ PNTSTATUS AccessStatus,
1150 _Out_ PBOOLEAN GenerateOnClose)
1151 {
1152 /* Call the internal function */
1153 return SepAccessCheckAndAuditAlarm(SubsystemName,
1154 HandleId,
1155 NULL,
1156 ObjectTypeName,
1157 ObjectName,
1158 SecurityDescriptor,
1159 PrincipalSelfSid,
1160 DesiredAccess,
1161 AuditType,
1162 Flags,
1163 ObjectTypeList,
1164 ObjectTypeLength,
1165 GenericMapping,
1166 GrantedAccess,
1167 AccessStatus,
1168 GenerateOnClose,
1169 FALSE);
1170 }
1171
1172 _Must_inspect_result_
1173 __kernel_entry
1174 NTSTATUS
1175 NTAPI
1176 NtAccessCheckByTypeResultListAndAuditAlarm(
1177 _In_ PUNICODE_STRING SubsystemName,
1178 _In_opt_ PVOID HandleId,
1179 _In_ PUNICODE_STRING ObjectTypeName,
1180 _In_ PUNICODE_STRING ObjectName,
1181 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1182 _In_opt_ PSID PrincipalSelfSid,
1183 _In_ ACCESS_MASK DesiredAccess,
1184 _In_ AUDIT_EVENT_TYPE AuditType,
1185 _In_ ULONG Flags,
1186 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
1187 _In_ ULONG ObjectTypeListLength,
1188 _In_ PGENERIC_MAPPING GenericMapping,
1189 _In_ BOOLEAN ObjectCreation,
1190 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
1191 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
1192 _Out_ PBOOLEAN GenerateOnClose)
1193 {
1194 /* Call the internal function */
1195 return SepAccessCheckAndAuditAlarm(SubsystemName,
1196 HandleId,
1197 NULL,
1198 ObjectTypeName,
1199 ObjectName,
1200 SecurityDescriptor,
1201 PrincipalSelfSid,
1202 DesiredAccess,
1203 AuditType,
1204 Flags,
1205 ObjectTypeList,
1206 ObjectTypeListLength,
1207 GenericMapping,
1208 GrantedAccessList,
1209 AccessStatusList,
1210 GenerateOnClose,
1211 TRUE);
1212 }
1213
1214 _Must_inspect_result_
1215 __kernel_entry
1216 NTSTATUS
1217 NTAPI
1218 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(
1219 _In_ PUNICODE_STRING SubsystemName,
1220 _In_opt_ PVOID HandleId,
1221 _In_ HANDLE ClientToken,
1222 _In_ PUNICODE_STRING ObjectTypeName,
1223 _In_ PUNICODE_STRING ObjectName,
1224 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1225 _In_opt_ PSID PrincipalSelfSid,
1226 _In_ ACCESS_MASK DesiredAccess,
1227 _In_ AUDIT_EVENT_TYPE AuditType,
1228 _In_ ULONG Flags,
1229 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
1230 _In_ ULONG ObjectTypeListLength,
1231 _In_ PGENERIC_MAPPING GenericMapping,
1232 _In_ BOOLEAN ObjectCreation,
1233 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
1234 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
1235 _Out_ PBOOLEAN GenerateOnClose)
1236 {
1237 UNREFERENCED_PARAMETER(ObjectCreation);
1238
1239 /* Call the internal function */
1240 return SepAccessCheckAndAuditAlarm(SubsystemName,
1241 HandleId,
1242 &ClientToken,
1243 ObjectTypeName,
1244 ObjectName,
1245 SecurityDescriptor,
1246 PrincipalSelfSid,
1247 DesiredAccess,
1248 AuditType,
1249 Flags,
1250 ObjectTypeList,
1251 ObjectTypeListLength,
1252 GenericMapping,
1253 GrantedAccessList,
1254 AccessStatusList,
1255 GenerateOnClose,
1256 TRUE);
1257 }
1258
1259 /* EOF */