[NTOSKRNL]
[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 return STATUS_SUCCESS;
314 }
315
316 _Must_inspect_result_
317 NTSTATUS
318 NTAPI
319 SepAccessCheckAndAuditAlarm(
320 _In_ PUNICODE_STRING SubsystemName,
321 _In_opt_ PVOID HandleId,
322 _In_ PHANDLE ClientTokenHandle,
323 _In_ PUNICODE_STRING ObjectTypeName,
324 _In_ PUNICODE_STRING ObjectName,
325 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
326 _In_opt_ PSID PrincipalSelfSid,
327 _In_ ACCESS_MASK DesiredAccess,
328 _In_ AUDIT_EVENT_TYPE AuditType,
329 _In_ ULONG Flags,
330 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
331 _In_ ULONG ObjectTypeListLength,
332 _In_ PGENERIC_MAPPING GenericMapping,
333 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
334 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
335 _Out_ PBOOLEAN GenerateOnClose,
336 _In_ BOOLEAN UseResultList)
337 {
338 SECURITY_SUBJECT_CONTEXT SubjectContext;
339 ULONG ResultListLength;
340 GENERIC_MAPPING LocalGenericMapping;
341 PTOKEN SubjectContextToken, ClientToken;
342 BOOLEAN AllocatedResultLists;
343 BOOLEAN HaveAuditPrivilege;
344 PISECURITY_DESCRIPTOR CapturedSecurityDescriptor;
345 UNICODE_STRING CapturedSubsystemName, CapturedObjectTypeName, CapturedObjectName;
346 ACCESS_MASK GrantedAccess, *SafeGrantedAccessList;
347 NTSTATUS AccessStatus, *SafeAccessStatusList;
348 PSID CapturedPrincipalSelfSid;
349 POBJECT_TYPE_LIST CapturedObjectTypeList;
350 ULONG i;
351 BOOLEAN LocalGenerateOnClose;
352 NTSTATUS Status;
353 PAGED_CODE();
354
355 /* Only user mode is supported! */
356 ASSERT(ExGetPreviousMode() != KernelMode);
357
358 /* Start clean */
359 AllocatedResultLists = FALSE;
360 ClientToken = NULL;
361 CapturedSecurityDescriptor = NULL;
362 CapturedSubsystemName.Buffer = NULL;
363 CapturedObjectTypeName.Buffer = NULL;
364 CapturedObjectName.Buffer = NULL;
365 CapturedPrincipalSelfSid = NULL;
366 CapturedObjectTypeList = NULL;
367
368 /* Validate AuditType */
369 if ((AuditType != AuditEventObjectAccess) &&
370 (AuditType != AuditEventDirectoryServiceAccess))
371 {
372 DPRINT1("Invalid audit type: %u\n", AuditType);
373 return STATUS_INVALID_PARAMETER;
374 }
375
376 /* Capture the security subject context */
377 SeCaptureSubjectContext(&SubjectContext);
378
379 /* Did the caller pass a token handle? */
380 if (ClientTokenHandle == NULL)
381 {
382 /* Check if we have a token in the subject context */
383 if (SubjectContext.ClientToken == NULL)
384 {
385 Status = STATUS_NO_IMPERSONATION_TOKEN;
386 DPRINT1("No token\n");
387 goto Cleanup;
388 }
389
390 /* Check if we have a valid impersonation level */
391 if (SubjectContext.ImpersonationLevel < SecurityIdentification)
392 {
393 Status = STATUS_BAD_IMPERSONATION_LEVEL;
394 DPRINT1("Invalid impersonation level 0x%lx\n",
395 SubjectContext.ImpersonationLevel);
396 goto Cleanup;
397 }
398 }
399
400 /* Are we using a result list? */
401 if (UseResultList)
402 {
403 /* The list length equals the object type list length */
404 ResultListLength = ObjectTypeListLength;
405 if ((ResultListLength == 0) || (ResultListLength > 0x1000))
406 {
407 Status = STATUS_INVALID_PARAMETER;
408 DPRINT1("Invalud ResultListLength: 0x%lx\n", ResultListLength);
409 goto Cleanup;
410 }
411
412 /* Allocate a safe buffer from paged pool */
413 SafeGrantedAccessList = ExAllocatePoolWithTag(PagedPool,
414 2 * ResultListLength * sizeof(ULONG),
415 TAG_SEPA);
416 if (SafeGrantedAccessList == NULL)
417 {
418 Status = STATUS_INSUFFICIENT_RESOURCES;
419 DPRINT1("Failed to allocate access lists\n");
420 goto Cleanup;
421 }
422
423 SafeAccessStatusList = (PNTSTATUS)&SafeGrantedAccessList[ResultListLength];
424 AllocatedResultLists = TRUE;
425 }
426 else
427 {
428 /* List length is 1 */
429 ResultListLength = 1;
430 SafeGrantedAccessList = &GrantedAccess;
431 SafeAccessStatusList = &AccessStatus;
432 }
433
434 _SEH2_TRY
435 {
436 /* Probe output buffers */
437 ProbeForWrite(AccessStatusList,
438 ResultListLength * sizeof(*AccessStatusList),
439 sizeof(*AccessStatusList));
440 ProbeForWrite(GrantedAccessList,
441 ResultListLength * sizeof(*GrantedAccessList),
442 sizeof(*GrantedAccessList));
443
444 /* Probe generic mapping and make a local copy */
445 ProbeForRead(GenericMapping, sizeof(*GenericMapping), sizeof(ULONG));
446 LocalGenericMapping = * GenericMapping;
447 }
448 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
449 {
450 Status = _SEH2_GetExceptionCode();
451 DPRINT1("Exception while probing parameters: 0x%lx\n", Status);
452 goto Cleanup;
453 }
454 _SEH2_END;
455
456 /* Do we have a client token? */
457 if (ClientTokenHandle != NULL)
458 {
459 /* Reference the client token */
460 Status = ObReferenceObjectByHandle(*ClientTokenHandle,
461 TOKEN_QUERY,
462 SeTokenObjectType,
463 UserMode,
464 (PVOID*)&ClientToken,
465 NULL);
466 if (!NT_SUCCESS(Status))
467 {
468 DPRINT1("Failed to reference token handle %p: %lx\n",
469 *ClientTokenHandle, Status);
470 goto Cleanup;
471 }
472
473 SubjectContextToken = SubjectContext.ClientToken;
474 SubjectContext.ClientToken = ClientToken;
475 }
476
477 /* Check for audit privilege */
478 HaveAuditPrivilege = SeSinglePrivilegeCheck(SeAuditPrivilege, UserMode);
479 if (!HaveAuditPrivilege && !(Flags & AUDIT_ALLOW_NO_PRIVILEGE))
480 {
481 DPRINT1("Caller does not have SeAuditPrivilege\n");
482 Status = STATUS_PRIVILEGE_NOT_HELD;
483 goto Cleanup;
484 }
485
486 /* Generic access must already be mapped to non-generic access types! */
487 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
488 {
489 DPRINT1("Generic access rights requested: 0x%lx\n", DesiredAccess);
490 Status = STATUS_GENERIC_NOT_MAPPED;
491 goto Cleanup;
492 }
493
494 /* Capture the security descriptor */
495 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
496 UserMode,
497 PagedPool,
498 FALSE,
499 &CapturedSecurityDescriptor);
500 if (!NT_SUCCESS(Status))
501 {
502 DPRINT1("Failed to capture security descriptor!\n");
503 goto Cleanup;
504 }
505
506 /* Validate the Security descriptor */
507 if ((SepGetOwnerFromDescriptor(CapturedSecurityDescriptor) == NULL) ||
508 (SepGetGroupFromDescriptor(CapturedSecurityDescriptor) == NULL))
509 {
510 Status = STATUS_INVALID_SECURITY_DESCR;
511 DPRINT1("Invalid security descriptor\n");
512 goto Cleanup;
513 }
514
515 /* Probe and capture the subsystem name */
516 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
517 UserMode,
518 SubsystemName);
519 if (!NT_SUCCESS(Status))
520 {
521 DPRINT1("Failed to capture subsystem name!\n");
522 goto Cleanup;
523 }
524
525 /* Probe and capture the object type name */
526 Status = ProbeAndCaptureUnicodeString(&CapturedObjectTypeName,
527 UserMode,
528 ObjectTypeName);
529 if (!NT_SUCCESS(Status))
530 {
531 DPRINT1("Failed to capture object type name!\n");
532 goto Cleanup;
533 }
534
535 /* Probe and capture the object name */
536 Status = ProbeAndCaptureUnicodeString(&CapturedObjectName,
537 UserMode,
538 ObjectName);
539 if (!NT_SUCCESS(Status))
540 {
541 DPRINT1("Failed to capture object name!\n");
542 goto Cleanup;
543 }
544
545 /* Check if we have a PrincipalSelfSid */
546 if (PrincipalSelfSid != NULL)
547 {
548 /* Capture it */
549 Status = SepCaptureSid(PrincipalSelfSid,
550 UserMode,
551 PagedPool,
552 FALSE,
553 &CapturedPrincipalSelfSid);
554 if (!NT_SUCCESS(Status))
555 {
556 DPRINT1("Failed to capture PrincipalSelfSid!\n");
557 goto Cleanup;
558 }
559 }
560
561 /* Capture the object type list */
562 Status = SeCaptureObjectTypeList(ObjectTypeList,
563 ObjectTypeListLength,
564 UserMode,
565 &CapturedObjectTypeList);
566 if (!NT_SUCCESS(Status))
567 {
568 DPRINT1("Failed to capture object type list!\n");
569 goto Cleanup;
570 }
571
572 /* Call the worker routine with the captured buffers */
573 SepAccessCheckAndAuditAlarmWorker(&CapturedSubsystemName,
574 HandleId,
575 &SubjectContext,
576 &CapturedObjectTypeName,
577 &CapturedObjectName,
578 CapturedSecurityDescriptor,
579 CapturedPrincipalSelfSid,
580 DesiredAccess,
581 AuditType,
582 HaveAuditPrivilege,
583 CapturedObjectTypeList,
584 ObjectTypeListLength,
585 &LocalGenericMapping,
586 SafeGrantedAccessList,
587 SafeAccessStatusList,
588 &LocalGenerateOnClose,
589 UseResultList);
590
591 /* Enter SEH to copy the data back to user mode */
592 _SEH2_TRY
593 {
594 /* Loop all result entries (only 1 when no list was requested) */
595 NT_ASSERT(UseResultList || (ResultListLength == 1));
596 for (i = 0; i < ResultListLength; i++)
597 {
598 AccessStatusList[i] = SafeAccessStatusList[i];
599 GrantedAccessList[i] = SafeGrantedAccessList[i];
600 }
601
602 *GenerateOnClose = LocalGenerateOnClose;
603 }
604 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
605 {
606 Status = _SEH2_GetExceptionCode();
607 DPRINT1("Exception while copying back data: 0x%lx\n", Status);
608 }
609
610 Cleanup:
611
612 if (CapturedObjectTypeList != NULL)
613 SeReleaseObjectTypeList(CapturedObjectTypeList, UserMode);
614
615 if (CapturedPrincipalSelfSid != NULL)
616 SepReleaseSid(CapturedPrincipalSelfSid, UserMode, FALSE);
617
618 if (CapturedObjectName.Buffer != NULL)
619 ReleaseCapturedUnicodeString(&CapturedObjectName, UserMode);
620
621 if (CapturedObjectTypeName.Buffer != NULL)
622 ReleaseCapturedUnicodeString(&CapturedObjectTypeName, UserMode);
623
624 if (CapturedSubsystemName.Buffer != NULL)
625 ReleaseCapturedUnicodeString(&CapturedSubsystemName, UserMode);
626
627 if (CapturedSecurityDescriptor != NULL)
628 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor, UserMode, FALSE);
629
630 if (ClientToken != NULL)
631 {
632 ObDereferenceObject(ClientToken);
633 SubjectContext.ClientToken = SubjectContextToken;
634 }
635
636 if (AllocatedResultLists)
637 ExFreePoolWithTag(SafeGrantedAccessList, TAG_SEPA);
638
639 /* Release the security subject context */
640 SeReleaseSubjectContext(&SubjectContext);
641
642 return Status;
643 }
644
645
646 /* PUBLIC FUNCTIONS ***********************************************************/
647
648 /*
649 * @unimplemented
650 */
651 VOID
652 NTAPI
653 SeAuditHardLinkCreation(IN PUNICODE_STRING FileName,
654 IN PUNICODE_STRING LinkName,
655 IN BOOLEAN bSuccess)
656 {
657 UNIMPLEMENTED;
658 }
659
660 /*
661 * @unimplemented
662 */
663 BOOLEAN
664 NTAPI
665 SeAuditingFileEvents(IN BOOLEAN AccessGranted,
666 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
667 {
668 UNIMPLEMENTED;
669 return FALSE;
670 }
671
672 /*
673 * @unimplemented
674 */
675 BOOLEAN
676 NTAPI
677 SeAuditingFileEventsWithContext(IN BOOLEAN AccessGranted,
678 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
679 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL)
680 {
681 UNIMPLEMENTED;
682 return FALSE;
683 }
684
685 /*
686 * @unimplemented
687 */
688 BOOLEAN
689 NTAPI
690 SeAuditingHardLinkEvents(IN BOOLEAN AccessGranted,
691 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
692 {
693 UNIMPLEMENTED;
694 return FALSE;
695 }
696
697 /*
698 * @unimplemented
699 */
700 BOOLEAN
701 NTAPI
702 SeAuditingHardLinkEventsWithContext(IN BOOLEAN AccessGranted,
703 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
704 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL)
705 {
706 UNIMPLEMENTED;
707 return FALSE;
708 }
709
710 /*
711 * @unimplemented
712 */
713 BOOLEAN
714 NTAPI
715 SeAuditingFileOrGlobalEvents(IN BOOLEAN AccessGranted,
716 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
717 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext)
718 {
719 UNIMPLEMENTED;
720 return FALSE;
721 }
722
723 /*
724 * @unimplemented
725 */
726 VOID
727 NTAPI
728 SeCloseObjectAuditAlarm(IN PVOID Object,
729 IN HANDLE Handle,
730 IN BOOLEAN PerformAction)
731 {
732 UNIMPLEMENTED;
733 }
734
735 /*
736 * @unimplemented
737 */
738 VOID NTAPI
739 SeDeleteObjectAuditAlarm(IN PVOID Object,
740 IN HANDLE Handle)
741 {
742 UNIMPLEMENTED;
743 }
744
745 /*
746 * @unimplemented
747 */
748 VOID
749 NTAPI
750 SeOpenObjectAuditAlarm(IN PUNICODE_STRING ObjectTypeName,
751 IN PVOID Object OPTIONAL,
752 IN PUNICODE_STRING AbsoluteObjectName OPTIONAL,
753 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
754 IN PACCESS_STATE AccessState,
755 IN BOOLEAN ObjectCreated,
756 IN BOOLEAN AccessGranted,
757 IN KPROCESSOR_MODE AccessMode,
758 OUT PBOOLEAN GenerateOnClose)
759 {
760 PAGED_CODE();
761
762 /* Audits aren't done on kernel-mode access */
763 if (AccessMode == KernelMode) return;
764
765 /* Otherwise, unimplemented! */
766 //UNIMPLEMENTED;
767 return;
768 }
769
770 /*
771 * @unimplemented
772 */
773 VOID NTAPI
774 SeOpenObjectForDeleteAuditAlarm(IN PUNICODE_STRING ObjectTypeName,
775 IN PVOID Object OPTIONAL,
776 IN PUNICODE_STRING AbsoluteObjectName OPTIONAL,
777 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
778 IN PACCESS_STATE AccessState,
779 IN BOOLEAN ObjectCreated,
780 IN BOOLEAN AccessGranted,
781 IN KPROCESSOR_MODE AccessMode,
782 OUT PBOOLEAN GenerateOnClose)
783 {
784 UNIMPLEMENTED;
785 }
786
787 /*
788 * @unimplemented
789 */
790 VOID
791 NTAPI
792 SePrivilegeObjectAuditAlarm(IN HANDLE Handle,
793 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
794 IN ACCESS_MASK DesiredAccess,
795 IN PPRIVILEGE_SET Privileges,
796 IN BOOLEAN AccessGranted,
797 IN KPROCESSOR_MODE CurrentMode)
798 {
799 UNIMPLEMENTED;
800 }
801
802 /* SYSTEM CALLS ***************************************************************/
803
804 NTSTATUS
805 NTAPI
806 NtCloseObjectAuditAlarm(
807 PUNICODE_STRING SubsystemName,
808 PVOID HandleId,
809 BOOLEAN GenerateOnClose)
810 {
811 UNICODE_STRING CapturedSubsystemName;
812 KPROCESSOR_MODE PreviousMode;
813 BOOLEAN UseImpersonationToken;
814 PETHREAD CurrentThread;
815 BOOLEAN CopyOnOpen, EffectiveOnly;
816 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
817 NTSTATUS Status;
818 PTOKEN Token;
819 PAGED_CODE();
820
821 /* Get the previous mode (only user mode is supported!) */
822 PreviousMode = ExGetPreviousMode();
823 ASSERT(PreviousMode != KernelMode);
824
825 /* Do we even need to do anything? */
826 if (!GenerateOnClose)
827 {
828 /* Nothing to do, return success */
829 return STATUS_SUCCESS;
830 }
831
832 /* Validate privilege */
833 if (!SeSinglePrivilegeCheck(SeAuditPrivilege, PreviousMode))
834 {
835 DPRINT1("Caller does not have SeAuditPrivilege\n");
836 return STATUS_PRIVILEGE_NOT_HELD;
837 }
838
839 /* Probe and capture the subsystem name */
840 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
841 PreviousMode,
842 SubsystemName);
843 if (!NT_SUCCESS(Status))
844 {
845 DPRINT1("Failed to capture subsystem name!\n");
846 return Status;
847 }
848
849 /* Get the current thread and check if it's impersonating */
850 CurrentThread = PsGetCurrentThread();
851 if (PsIsThreadImpersonating(CurrentThread))
852 {
853 /* Get the impersonation token */
854 Token = PsReferenceImpersonationToken(CurrentThread,
855 &CopyOnOpen,
856 &EffectiveOnly,
857 &ImpersonationLevel);
858 UseImpersonationToken = TRUE;
859 }
860 else
861 {
862 /* Get the primary token */
863 Token = PsReferencePrimaryToken(PsGetCurrentProcess());
864 UseImpersonationToken = FALSE;
865 }
866
867 /* Call the internal function */
868 SepAdtCloseObjectAuditAlarm(&CapturedSubsystemName,
869 HandleId,
870 Token->UserAndGroups->Sid);
871
872 /* Release the captured subsystem name */
873 ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode);
874
875 /* Check what token we used */
876 if (UseImpersonationToken)
877 {
878 /* Release impersonation token */
879 PsDereferenceImpersonationToken(Token);
880 }
881 else
882 {
883 /* Release primary token */
884 PsDereferencePrimaryToken(Token);
885 }
886
887 return STATUS_SUCCESS;
888 }
889
890
891 NTSTATUS NTAPI
892 NtDeleteObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
893 IN PVOID HandleId,
894 IN BOOLEAN GenerateOnClose)
895 {
896 UNIMPLEMENTED;
897 return STATUS_NOT_IMPLEMENTED;
898 }
899
900
901 NTSTATUS NTAPI
902 NtOpenObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
903 IN PVOID HandleId,
904 IN PUNICODE_STRING ObjectTypeName,
905 IN PUNICODE_STRING ObjectName,
906 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
907 IN HANDLE ClientToken,
908 IN ULONG DesiredAccess,
909 IN ULONG GrantedAccess,
910 IN PPRIVILEGE_SET Privileges,
911 IN BOOLEAN ObjectCreation,
912 IN BOOLEAN AccessGranted,
913 OUT PBOOLEAN GenerateOnClose)
914 {
915 UNIMPLEMENTED;
916 return STATUS_NOT_IMPLEMENTED;
917 }
918
919
920 __kernel_entry
921 NTSTATUS
922 NTAPI
923 NtPrivilegedServiceAuditAlarm(
924 _In_opt_ PUNICODE_STRING SubsystemName,
925 _In_opt_ PUNICODE_STRING ServiceName,
926 _In_ HANDLE ClientToken,
927 _In_ PPRIVILEGE_SET Privileges,
928 _In_ BOOLEAN AccessGranted )
929 {
930 KPROCESSOR_MODE PreviousMode;
931 PTOKEN Token;
932 volatile PPRIVILEGE_SET CapturedPrivileges = NULL;
933 UNICODE_STRING CapturedSubsystemName;
934 UNICODE_STRING CapturedServiceName;
935 ULONG PrivilegeCount, PrivilegesSize;
936 SECURITY_SUBJECT_CONTEXT SubjectContext;
937 NTSTATUS Status;
938 PAGED_CODE();
939
940 /* Get the previous mode (only user mode is supported!) */
941 PreviousMode = ExGetPreviousMode();
942 ASSERT(PreviousMode != KernelMode);
943
944 CapturedSubsystemName.Buffer = NULL;
945 CapturedServiceName.Buffer = NULL;
946
947 /* Reference the client token */
948 Status = ObReferenceObjectByHandle(ClientToken,
949 TOKEN_QUERY,
950 SeTokenObjectType,
951 PreviousMode,
952 (PVOID*)&Token,
953 NULL);
954 if (!NT_SUCCESS(Status))
955 {
956 DPRINT1("Failed to reference client token: 0x%lx\n", Status);
957 return Status;
958 }
959
960 /* Validate the token's impersonation level */
961 if ((Token->TokenType == TokenImpersonation) &&
962 (Token->ImpersonationLevel < SecurityIdentification))
963 {
964 DPRINT1("Invalid impersonation level (%u)\n", Token->ImpersonationLevel);
965 ObfDereferenceObject(Token);
966 return STATUS_BAD_IMPERSONATION_LEVEL;
967 }
968
969 /* Validate privilege */
970 if (!SeSinglePrivilegeCheck(SeAuditPrivilege, PreviousMode))
971 {
972 DPRINT1("Caller does not have SeAuditPrivilege\n");
973 ObfDereferenceObject(Token);
974 return STATUS_PRIVILEGE_NOT_HELD;
975 }
976
977 /* Do we have a subsystem name? */
978 if (SubsystemName != NULL)
979 {
980 /* Probe and capture the subsystem name */
981 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
982 PreviousMode,
983 SubsystemName);
984 if (!NT_SUCCESS(Status))
985 {
986 DPRINT1("Failed to capture subsystem name!\n");
987 goto Cleanup;
988 }
989 }
990
991 /* Do we have a service name? */
992 if (ServiceName != NULL)
993 {
994 /* Probe and capture the service name */
995 Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
996 PreviousMode,
997 ServiceName);
998 if (!NT_SUCCESS(Status))
999 {
1000 DPRINT1("Failed to capture service name!\n");
1001 goto Cleanup;
1002 }
1003 }
1004
1005 _SEH2_TRY
1006 {
1007 /* Probe the basic privilege set structure */
1008 ProbeForRead(Privileges, sizeof(PRIVILEGE_SET), sizeof(ULONG));
1009
1010 /* Validate privilege count */
1011 PrivilegeCount = Privileges->PrivilegeCount;
1012 if (PrivilegeCount > SEP_PRIVILEGE_SET_MAX_COUNT)
1013 {
1014 Status = STATUS_INVALID_PARAMETER;
1015 goto Cleanup;
1016 }
1017
1018 /* Calculate the size of the Privileges structure */
1019 PrivilegesSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]);
1020
1021 /* Probe the whole structure */
1022 ProbeForRead(Privileges, PrivilegesSize, sizeof(ULONG));
1023
1024 /* Allocate a temp buffer */
1025 CapturedPrivileges = ExAllocatePoolWithTag(PagedPool,
1026 PrivilegesSize,
1027 'rPeS');
1028 if (CapturedPrivileges == NULL)
1029 {
1030 DPRINT1("Failed to allocate %u bytes\n", PrivilegesSize);
1031 Status = STATUS_INSUFFICIENT_RESOURCES;
1032 goto Cleanup;
1033 }
1034
1035 /* Copy the privileges */
1036 RtlCopyMemory(CapturedPrivileges, Privileges, PrivilegesSize);
1037 }
1038 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1039 {
1040 Status = _SEH2_GetExceptionCode();
1041 DPRINT1("Got exception 0x%lx\n", Status);
1042 goto Cleanup;
1043 }
1044 _SEH2_END;
1045
1046 /* Capture the security subject context */
1047 SeCaptureSubjectContext(&SubjectContext);
1048
1049 /* Call the internal function */
1050 SepAdtPrivilegedServiceAuditAlarm(&SubjectContext,
1051 SubsystemName ? &CapturedSubsystemName : NULL,
1052 ServiceName ? &CapturedServiceName : NULL,
1053 Token,
1054 SubjectContext.PrimaryToken,
1055 CapturedPrivileges,
1056 AccessGranted);
1057
1058 /* Release the security subject context */
1059 SeReleaseSubjectContext(&SubjectContext);
1060
1061 Status = STATUS_SUCCESS;
1062
1063 Cleanup:
1064 /* Cleanup resources */
1065 if (CapturedSubsystemName.Buffer != NULL)
1066 ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode);
1067 if (CapturedServiceName.Buffer != NULL)
1068 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1069 if (CapturedPrivileges != NULL)
1070 ExFreePoolWithTag(CapturedPrivileges, 0);
1071 ObDereferenceObject(Token);
1072
1073 return Status;
1074 }
1075
1076
1077 NTSTATUS NTAPI
1078 NtPrivilegeObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
1079 IN PVOID HandleId,
1080 IN HANDLE ClientToken,
1081 IN ULONG DesiredAccess,
1082 IN PPRIVILEGE_SET Privileges,
1083 IN BOOLEAN AccessGranted)
1084 {
1085 UNIMPLEMENTED;
1086 return STATUS_NOT_IMPLEMENTED;
1087 }
1088
1089
1090 _Must_inspect_result_
1091 __kernel_entry
1092 NTSTATUS
1093 NTAPI
1094 NtAccessCheckAndAuditAlarm(
1095 _In_ PUNICODE_STRING SubsystemName,
1096 _In_opt_ PVOID HandleId,
1097 _In_ PUNICODE_STRING ObjectTypeName,
1098 _In_ PUNICODE_STRING ObjectName,
1099 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1100 _In_ ACCESS_MASK DesiredAccess,
1101 _In_ PGENERIC_MAPPING GenericMapping,
1102 _In_ BOOLEAN ObjectCreation,
1103 _Out_ PACCESS_MASK GrantedAccess,
1104 _Out_ PNTSTATUS AccessStatus,
1105 _Out_ PBOOLEAN GenerateOnClose)
1106 {
1107 /* Call the internal function */
1108 return SepAccessCheckAndAuditAlarm(SubsystemName,
1109 HandleId,
1110 NULL,
1111 ObjectTypeName,
1112 ObjectName,
1113 SecurityDescriptor,
1114 NULL,
1115 DesiredAccess,
1116 AuditEventObjectAccess,
1117 0,
1118 NULL,
1119 0,
1120 GenericMapping,
1121 GrantedAccess,
1122 AccessStatus,
1123 GenerateOnClose,
1124 FALSE);
1125 }
1126
1127 _Must_inspect_result_
1128 __kernel_entry
1129 NTSTATUS
1130 NTAPI
1131 NtAccessCheckByTypeAndAuditAlarm(
1132 _In_ PUNICODE_STRING SubsystemName,
1133 _In_opt_ PVOID HandleId,
1134 _In_ PUNICODE_STRING ObjectTypeName,
1135 _In_ PUNICODE_STRING ObjectName,
1136 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1137 _In_opt_ PSID PrincipalSelfSid,
1138 _In_ ACCESS_MASK DesiredAccess,
1139 _In_ AUDIT_EVENT_TYPE AuditType,
1140 _In_ ULONG Flags,
1141 _In_reads_opt_(ObjectTypeLength) POBJECT_TYPE_LIST ObjectTypeList,
1142 _In_ ULONG ObjectTypeLength,
1143 _In_ PGENERIC_MAPPING GenericMapping,
1144 _In_ BOOLEAN ObjectCreation,
1145 _Out_ PACCESS_MASK GrantedAccess,
1146 _Out_ PNTSTATUS AccessStatus,
1147 _Out_ PBOOLEAN GenerateOnClose)
1148 {
1149 /* Call the internal function */
1150 return SepAccessCheckAndAuditAlarm(SubsystemName,
1151 HandleId,
1152 NULL,
1153 ObjectTypeName,
1154 ObjectName,
1155 SecurityDescriptor,
1156 PrincipalSelfSid,
1157 DesiredAccess,
1158 AuditType,
1159 Flags,
1160 ObjectTypeList,
1161 ObjectTypeLength,
1162 GenericMapping,
1163 GrantedAccess,
1164 AccessStatus,
1165 GenerateOnClose,
1166 FALSE);
1167 }
1168
1169 _Must_inspect_result_
1170 __kernel_entry
1171 NTSTATUS
1172 NTAPI
1173 NtAccessCheckByTypeResultListAndAuditAlarm(
1174 _In_ PUNICODE_STRING SubsystemName,
1175 _In_opt_ PVOID HandleId,
1176 _In_ PUNICODE_STRING ObjectTypeName,
1177 _In_ PUNICODE_STRING ObjectName,
1178 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1179 _In_opt_ PSID PrincipalSelfSid,
1180 _In_ ACCESS_MASK DesiredAccess,
1181 _In_ AUDIT_EVENT_TYPE AuditType,
1182 _In_ ULONG Flags,
1183 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
1184 _In_ ULONG ObjectTypeListLength,
1185 _In_ PGENERIC_MAPPING GenericMapping,
1186 _In_ BOOLEAN ObjectCreation,
1187 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
1188 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
1189 _Out_ PBOOLEAN GenerateOnClose)
1190 {
1191 /* Call the internal function */
1192 return SepAccessCheckAndAuditAlarm(SubsystemName,
1193 HandleId,
1194 NULL,
1195 ObjectTypeName,
1196 ObjectName,
1197 SecurityDescriptor,
1198 PrincipalSelfSid,
1199 DesiredAccess,
1200 AuditType,
1201 Flags,
1202 ObjectTypeList,
1203 ObjectTypeListLength,
1204 GenericMapping,
1205 GrantedAccessList,
1206 AccessStatusList,
1207 GenerateOnClose,
1208 TRUE);
1209 }
1210
1211 _Must_inspect_result_
1212 __kernel_entry
1213 NTSTATUS
1214 NTAPI
1215 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(
1216 _In_ PUNICODE_STRING SubsystemName,
1217 _In_opt_ PVOID HandleId,
1218 _In_ HANDLE ClientToken,
1219 _In_ PUNICODE_STRING ObjectTypeName,
1220 _In_ PUNICODE_STRING ObjectName,
1221 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
1222 _In_opt_ PSID PrincipalSelfSid,
1223 _In_ ACCESS_MASK DesiredAccess,
1224 _In_ AUDIT_EVENT_TYPE AuditType,
1225 _In_ ULONG Flags,
1226 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
1227 _In_ ULONG ObjectTypeListLength,
1228 _In_ PGENERIC_MAPPING GenericMapping,
1229 _In_ BOOLEAN ObjectCreation,
1230 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
1231 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
1232 _Out_ PBOOLEAN GenerateOnClose)
1233 {
1234 UNREFERENCED_PARAMETER(ObjectCreation);
1235
1236 /* Call the internal function */
1237 return SepAccessCheckAndAuditAlarm(SubsystemName,
1238 HandleId,
1239 &ClientToken,
1240 ObjectTypeName,
1241 ObjectName,
1242 SecurityDescriptor,
1243 PrincipalSelfSid,
1244 DesiredAccess,
1245 AuditType,
1246 Flags,
1247 ObjectTypeList,
1248 ObjectTypeListLength,
1249 GenericMapping,
1250 GrantedAccessList,
1251 AccessStatusList,
1252 GenerateOnClose,
1253 TRUE);
1254 }
1255
1256 /* EOF */