[NTOS:SE]
[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 UNICODE_STRING SeSubsystemName = RTL_CONSTANT_STRING(L"Security");
20
21 /* PRIVATE FUNCTIONS***********************************************************/
22
23 BOOLEAN
24 NTAPI
25 SeDetailedAuditingWithToken(IN PTOKEN Token)
26 {
27 /* FIXME */
28 return FALSE;
29 }
30
31 VOID
32 NTAPI
33 SeAuditProcessCreate(IN PEPROCESS Process)
34 {
35 /* FIXME */
36 }
37
38 VOID
39 NTAPI
40 SeAuditProcessExit(IN PEPROCESS Process)
41 {
42 /* FIXME */
43 }
44
45 NTSTATUS
46 NTAPI
47 SeInitializeProcessAuditName(IN PFILE_OBJECT FileObject,
48 IN BOOLEAN DoAudit,
49 OUT POBJECT_NAME_INFORMATION *AuditInfo)
50 {
51 OBJECT_NAME_INFORMATION LocalNameInfo;
52 POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
53 ULONG ReturnLength = 8;
54 NTSTATUS Status;
55
56 PAGED_CODE();
57 ASSERT(AuditInfo);
58
59 /* Check if we should do auditing */
60 if (DoAudit)
61 {
62 /* FIXME: TODO */
63 }
64
65 /* Now query the name */
66 Status = ObQueryNameString(FileObject,
67 &LocalNameInfo,
68 sizeof(LocalNameInfo),
69 &ReturnLength);
70 if (((Status == STATUS_BUFFER_OVERFLOW) ||
71 (Status == STATUS_BUFFER_TOO_SMALL) ||
72 (Status == STATUS_INFO_LENGTH_MISMATCH)) &&
73 (ReturnLength != sizeof(LocalNameInfo)))
74 {
75 /* Allocate required size */
76 ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool,
77 ReturnLength,
78 TAG_SEPA);
79 if (ObjectNameInfo)
80 {
81 /* Query the name again */
82 Status = ObQueryNameString(FileObject,
83 ObjectNameInfo,
84 ReturnLength,
85 &ReturnLength);
86 }
87 }
88
89 /* Check if we got here due to failure */
90 if ((ObjectNameInfo) &&
91 (!(NT_SUCCESS(Status)) || (ReturnLength == sizeof(LocalNameInfo))))
92 {
93 /* First, free any buffer we might've allocated */
94 ASSERT(FALSE);
95 if (ObjectNameInfo) ExFreePool(ObjectNameInfo);
96
97 /* Now allocate a temporary one */
98 ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
99 ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool,
100 sizeof(OBJECT_NAME_INFORMATION),
101 TAG_SEPA);
102 if (ObjectNameInfo)
103 {
104 /* Clear it */
105 RtlZeroMemory(ObjectNameInfo, ReturnLength);
106 Status = STATUS_SUCCESS;
107 }
108 }
109
110 /* Check if memory allocation failed */
111 if (!ObjectNameInfo) Status = STATUS_NO_MEMORY;
112
113 /* Return the audit name */
114 *AuditInfo = ObjectNameInfo;
115
116 /* Return status */
117 return Status;
118 }
119
120 NTSTATUS
121 NTAPI
122 SeLocateProcessImageName(IN PEPROCESS Process,
123 OUT PUNICODE_STRING *ProcessImageName)
124 {
125 POBJECT_NAME_INFORMATION AuditName;
126 PUNICODE_STRING ImageName;
127 PFILE_OBJECT FileObject;
128 NTSTATUS Status = STATUS_SUCCESS;
129
130 PAGED_CODE();
131
132 /* Assume failure */
133 *ProcessImageName = NULL;
134
135 /* Check if we have audit info */
136 AuditName = Process->SeAuditProcessCreationInfo.ImageFileName;
137 if (!AuditName)
138 {
139 /* Get the file object */
140 Status = PsReferenceProcessFilePointer(Process, &FileObject);
141 if (!NT_SUCCESS(Status)) return Status;
142
143 /* Initialize the audit structure */
144 Status = SeInitializeProcessAuditName(FileObject, TRUE, &AuditName);
145 if (NT_SUCCESS(Status))
146 {
147 /* Set it */
148 if (InterlockedCompareExchangePointer((PVOID*)&Process->
149 SeAuditProcessCreationInfo.ImageFileName,
150 AuditName,
151 NULL))
152 {
153 /* Someone beat us to it, deallocate our copy */
154 ExFreePool(AuditName);
155 }
156 }
157
158 /* Dereference the file object */
159 ObDereferenceObject(FileObject);
160 if (!NT_SUCCESS(Status)) return Status;
161 }
162
163 /* Get audit info again, now we have it for sure */
164 AuditName = Process->SeAuditProcessCreationInfo.ImageFileName;
165
166 /* Allocate the output string */
167 ImageName = ExAllocatePoolWithTag(NonPagedPool,
168 AuditName->Name.MaximumLength +
169 sizeof(UNICODE_STRING),
170 TAG_SEPA);
171 if (!ImageName) return STATUS_NO_MEMORY;
172
173 /* Make a copy of it */
174 RtlCopyMemory(ImageName,
175 &AuditName->Name,
176 AuditName->Name.MaximumLength + sizeof(UNICODE_STRING));
177
178 /* Fix up the buffer */
179 ImageName->Buffer = (PWSTR)(ImageName + 1);
180
181 /* Return it */
182 *ProcessImageName = ImageName;
183
184 /* Return status */
185 return Status;
186 }
187
188 VOID
189 NTAPI
190 SepAdtCloseObjectAuditAlarm(
191 PUNICODE_STRING SubsystemName,
192 PVOID HandleId,
193 PSID Sid)
194 {
195 UNIMPLEMENTED;
196 }
197
198 VOID
199 NTAPI
200 SepAdtPrivilegedServiceAuditAlarm(
201 PSECURITY_SUBJECT_CONTEXT SubjectContext,
202 _In_opt_ PUNICODE_STRING SubsystemName,
203 _In_opt_ PUNICODE_STRING ServiceName,
204 _In_ PTOKEN Token,
205 _In_ PTOKEN PrimaryToken,
206 _In_ PPRIVILEGE_SET Privileges,
207 _In_ BOOLEAN AccessGranted)
208 {
209 DPRINT("SepAdtPrivilegedServiceAuditAlarm is unimplemented\n");
210 }
211
212 VOID
213 NTAPI
214 SePrivilegedServiceAuditAlarm(
215 _In_opt_ PUNICODE_STRING ServiceName,
216 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
217 _In_ PPRIVILEGE_SET PrivilegeSet,
218 _In_ BOOLEAN AccessGranted)
219 {
220 PTOKEN EffectiveToken;
221 PSID UserSid;
222 PAGED_CODE();
223
224 /* Get the effective token */
225 if (SubjectContext->ClientToken != NULL)
226 EffectiveToken = SubjectContext->ClientToken;
227 else
228 EffectiveToken = SubjectContext->PrimaryToken;
229
230 /* Get the user SID */
231 UserSid = EffectiveToken->UserAndGroups->Sid;
232
233 /* Check if this is the local system SID */
234 if (RtlEqualSid(UserSid, SeLocalSystemSid))
235 {
236 /* Nothing to do */
237 return;
238 }
239
240 /* Check if this is the network service or local service SID */
241 if (RtlEqualSid(UserSid, SeExports->SeNetworkServiceSid) ||
242 RtlEqualSid(UserSid, SeExports->SeLocalServiceSid))
243 {
244 // FIXME: should continue for a certain set of privileges
245 return;
246 }
247
248 /* Call the worker function */
249 SepAdtPrivilegedServiceAuditAlarm(SubjectContext,
250 &SeSubsystemName,
251 ServiceName,
252 SubjectContext->ClientToken,
253 SubjectContext->PrimaryToken,
254 PrivilegeSet,
255 AccessGranted);
256
257 }
258
259
260 static
261 NTSTATUS
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)
267 {
268 SIZE_T Size;
269
270 if (PreviousMode == KernelMode)
271 {
272 return STATUS_NOT_IMPLEMENTED;
273 }
274
275 if (ObjectTypeListLength == 0)
276 {
277 *CapturedObjectTypeList = NULL;
278 return STATUS_SUCCESS;
279 }
280
281 if (ObjectTypeList == NULL)
282 {
283 return STATUS_INVALID_PARAMETER;
284 }
285
286 /* Calculate the list size and check for integer overflow */
287 Size = ObjectTypeListLength * sizeof(OBJECT_TYPE_LIST);
288 if (Size == 0)
289 {
290 return STATUS_INVALID_PARAMETER;
291 }
292
293 /* Allocate a new list */
294 *CapturedObjectTypeList = ExAllocatePoolWithTag(PagedPool, Size, TAG_SEPA);
295 if (*CapturedObjectTypeList == NULL)
296 {
297 return STATUS_INSUFFICIENT_RESOURCES;
298 }
299
300 _SEH2_TRY
301 {
302 ProbeForRead(ObjectTypeList, Size, sizeof(ULONG));
303 RtlCopyMemory(*CapturedObjectTypeList, ObjectTypeList, Size);
304 }
305 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
306 {
307 ExFreePoolWithTag(*CapturedObjectTypeList, TAG_SEPA);
308 *CapturedObjectTypeList = NULL;
309 return _SEH2_GetExceptionCode();
310 }
311 _SEH2_END;
312
313 return STATUS_SUCCESS;
314 }
315
316 static
317 VOID
318 SeReleaseObjectTypeList(
319 _In_ _Post_invalid_ POBJECT_TYPE_LIST CapturedObjectTypeList,
320 _In_ KPROCESSOR_MODE PreviousMode)
321 {
322 if ((PreviousMode != KernelMode) && (CapturedObjectTypeList != NULL))
323 ExFreePoolWithTag(CapturedObjectTypeList, TAG_SEPA);
324 }
325
326 _Must_inspect_result_
327 static
328 NTSTATUS
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)
347 {
348 ULONG ResultListLength, i;
349
350 /* Get the length of the result list */
351 ResultListLength = UseResultList ? ObjectTypeListLength : 1;
352
353 /// FIXME: we should do some real work here...
354 UNIMPLEMENTED;
355
356 /// HACK: we just pretend all access is granted!
357 for (i = 0; i < ResultListLength; i++)
358 {
359 GrantedAccessList[i] = DesiredAccess;
360 AccessStatusList[i] = STATUS_SUCCESS;
361 }
362
363 *GenerateOnClose = FALSE;
364
365 return STATUS_SUCCESS;
366 }
367
368 _Must_inspect_result_
369 NTSTATUS
370 NTAPI
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,
381 _In_ ULONG Flags,
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)
389 {
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;
402 ULONG i;
403 BOOLEAN LocalGenerateOnClose;
404 NTSTATUS Status;
405 PAGED_CODE();
406
407 /* Only user mode is supported! */
408 ASSERT(ExGetPreviousMode() != KernelMode);
409
410 /* Start clean */
411 AllocatedResultLists = FALSE;
412 ClientToken = NULL;
413 CapturedSecurityDescriptor = NULL;
414 CapturedSubsystemName.Buffer = NULL;
415 CapturedObjectTypeName.Buffer = NULL;
416 CapturedObjectName.Buffer = NULL;
417 CapturedPrincipalSelfSid = NULL;
418 CapturedObjectTypeList = NULL;
419
420 /* Validate AuditType */
421 if ((AuditType != AuditEventObjectAccess) &&
422 (AuditType != AuditEventDirectoryServiceAccess))
423 {
424 DPRINT1("Invalid audit type: %u\n", AuditType);
425 return STATUS_INVALID_PARAMETER;
426 }
427
428 /* Capture the security subject context */
429 SeCaptureSubjectContext(&SubjectContext);
430
431 /* Did the caller pass a token handle? */
432 if (ClientTokenHandle == NULL)
433 {
434 /* Check if we have a token in the subject context */
435 if (SubjectContext.ClientToken == NULL)
436 {
437 Status = STATUS_NO_IMPERSONATION_TOKEN;
438 DPRINT1("No token\n");
439 goto Cleanup;
440 }
441
442 /* Check if we have a valid impersonation level */
443 if (SubjectContext.ImpersonationLevel < SecurityIdentification)
444 {
445 Status = STATUS_BAD_IMPERSONATION_LEVEL;
446 DPRINT1("Invalid impersonation level 0x%lx\n",
447 SubjectContext.ImpersonationLevel);
448 goto Cleanup;
449 }
450 }
451
452 /* Are we using a result list? */
453 if (UseResultList)
454 {
455 /* The list length equals the object type list length */
456 ResultListLength = ObjectTypeListLength;
457 if ((ResultListLength == 0) || (ResultListLength > 0x1000))
458 {
459 Status = STATUS_INVALID_PARAMETER;
460 DPRINT1("Invalud ResultListLength: 0x%lx\n", ResultListLength);
461 goto Cleanup;
462 }
463
464 /* Allocate a safe buffer from paged pool */
465 SafeGrantedAccessList = ExAllocatePoolWithTag(PagedPool,
466 2 * ResultListLength * sizeof(ULONG),
467 TAG_SEPA);
468 if (SafeGrantedAccessList == NULL)
469 {
470 Status = STATUS_INSUFFICIENT_RESOURCES;
471 DPRINT1("Failed to allocate access lists\n");
472 goto Cleanup;
473 }
474
475 SafeAccessStatusList = (PNTSTATUS)&SafeGrantedAccessList[ResultListLength];
476 AllocatedResultLists = TRUE;
477 }
478 else
479 {
480 /* List length is 1 */
481 ResultListLength = 1;
482 SafeGrantedAccessList = &GrantedAccess;
483 SafeAccessStatusList = &AccessStatus;
484 }
485
486 _SEH2_TRY
487 {
488 /* Probe output buffers */
489 ProbeForWrite(AccessStatusList,
490 ResultListLength * sizeof(*AccessStatusList),
491 sizeof(*AccessStatusList));
492 ProbeForWrite(GrantedAccessList,
493 ResultListLength * sizeof(*GrantedAccessList),
494 sizeof(*GrantedAccessList));
495
496 /* Probe generic mapping and make a local copy */
497 ProbeForRead(GenericMapping, sizeof(*GenericMapping), sizeof(ULONG));
498 LocalGenericMapping = * GenericMapping;
499 }
500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
501 {
502 Status = _SEH2_GetExceptionCode();
503 DPRINT1("Exception while probing parameters: 0x%lx\n", Status);
504 goto Cleanup;
505 }
506 _SEH2_END;
507
508 /* Do we have a client token? */
509 if (ClientTokenHandle != NULL)
510 {
511 /* Reference the client token */
512 Status = ObReferenceObjectByHandle(*ClientTokenHandle,
513 TOKEN_QUERY,
514 SeTokenObjectType,
515 UserMode,
516 (PVOID*)&ClientToken,
517 NULL);
518 if (!NT_SUCCESS(Status))
519 {
520 DPRINT1("Failed to reference token handle %p: %lx\n",
521 *ClientTokenHandle, Status);
522 goto Cleanup;
523 }
524
525 SubjectContextToken = SubjectContext.ClientToken;
526 SubjectContext.ClientToken = ClientToken;
527 }
528
529 /* Check for audit privilege */
530 HaveAuditPrivilege = SeCheckAuditPrivilege(&SubjectContext, UserMode);
531 if (!HaveAuditPrivilege && !(Flags & AUDIT_ALLOW_NO_PRIVILEGE))
532 {
533 DPRINT1("Caller does not have SeAuditPrivilege\n");
534 Status = STATUS_PRIVILEGE_NOT_HELD;
535 goto Cleanup;
536 }
537
538 /* Generic access must already be mapped to non-generic access types! */
539 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
540 {
541 DPRINT1("Generic access rights requested: 0x%lx\n", DesiredAccess);
542 Status = STATUS_GENERIC_NOT_MAPPED;
543 goto Cleanup;
544 }
545
546 /* Capture the security descriptor */
547 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
548 UserMode,
549 PagedPool,
550 FALSE,
551 &CapturedSecurityDescriptor);
552 if (!NT_SUCCESS(Status))
553 {
554 DPRINT1("Failed to capture security descriptor!\n");
555 goto Cleanup;
556 }
557
558 /* Validate the Security descriptor */
559 if ((SepGetOwnerFromDescriptor(CapturedSecurityDescriptor) == NULL) ||
560 (SepGetGroupFromDescriptor(CapturedSecurityDescriptor) == NULL))
561 {
562 Status = STATUS_INVALID_SECURITY_DESCR;
563 DPRINT1("Invalid security descriptor\n");
564 goto Cleanup;
565 }
566
567 /* Probe and capture the subsystem name */
568 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
569 UserMode,
570 SubsystemName);
571 if (!NT_SUCCESS(Status))
572 {
573 DPRINT1("Failed to capture subsystem name!\n");
574 goto Cleanup;
575 }
576
577 /* Probe and capture the object type name */
578 Status = ProbeAndCaptureUnicodeString(&CapturedObjectTypeName,
579 UserMode,
580 ObjectTypeName);
581 if (!NT_SUCCESS(Status))
582 {
583 DPRINT1("Failed to capture object type name!\n");
584 goto Cleanup;
585 }
586
587 /* Probe and capture the object name */
588 Status = ProbeAndCaptureUnicodeString(&CapturedObjectName,
589 UserMode,
590 ObjectName);
591 if (!NT_SUCCESS(Status))
592 {
593 DPRINT1("Failed to capture object name!\n");
594 goto Cleanup;
595 }
596
597 /* Check if we have a PrincipalSelfSid */
598 if (PrincipalSelfSid != NULL)
599 {
600 /* Capture it */
601 Status = SepCaptureSid(PrincipalSelfSid,
602 UserMode,
603 PagedPool,
604 FALSE,
605 &CapturedPrincipalSelfSid);
606 if (!NT_SUCCESS(Status))
607 {
608 DPRINT1("Failed to capture PrincipalSelfSid!\n");
609 goto Cleanup;
610 }
611 }
612
613 /* Capture the object type list */
614 Status = SeCaptureObjectTypeList(ObjectTypeList,
615 ObjectTypeListLength,
616 UserMode,
617 &CapturedObjectTypeList);
618 if (!NT_SUCCESS(Status))
619 {
620 DPRINT1("Failed to capture object type list!\n");
621 goto Cleanup;
622 }
623
624 /* Call the worker routine with the captured buffers */
625 SepAccessCheckAndAuditAlarmWorker(&CapturedSubsystemName,
626 HandleId,
627 &SubjectContext,
628 &CapturedObjectTypeName,
629 &CapturedObjectName,
630 CapturedSecurityDescriptor,
631 CapturedPrincipalSelfSid,
632 DesiredAccess,
633 AuditType,
634 HaveAuditPrivilege,
635 CapturedObjectTypeList,
636 ObjectTypeListLength,
637 &LocalGenericMapping,
638 SafeGrantedAccessList,
639 SafeAccessStatusList,
640 &LocalGenerateOnClose,
641 UseResultList);
642
643 /* Enter SEH to copy the data back to user mode */
644 _SEH2_TRY
645 {
646 /* Loop all result entries (only 1 when no list was requested) */
647 ASSERT(UseResultList || (ResultListLength == 1));
648 for (i = 0; i < ResultListLength; i++)
649 {
650 AccessStatusList[i] = SafeAccessStatusList[i];
651 GrantedAccessList[i] = SafeGrantedAccessList[i];
652 }
653
654 *GenerateOnClose = LocalGenerateOnClose;
655 }
656 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
657 {
658 Status = _SEH2_GetExceptionCode();
659 DPRINT1("Exception while copying back data: 0x%lx\n", Status);
660 }
661 _SEH2_END;
662
663 Cleanup:
664
665 if (CapturedObjectTypeList != NULL)
666 SeReleaseObjectTypeList(CapturedObjectTypeList, UserMode);
667
668 if (CapturedPrincipalSelfSid != NULL)
669 SepReleaseSid(CapturedPrincipalSelfSid, UserMode, FALSE);
670
671 if (CapturedObjectName.Buffer != NULL)
672 ReleaseCapturedUnicodeString(&CapturedObjectName, UserMode);
673
674 if (CapturedObjectTypeName.Buffer != NULL)
675 ReleaseCapturedUnicodeString(&CapturedObjectTypeName, UserMode);
676
677 if (CapturedSubsystemName.Buffer != NULL)
678 ReleaseCapturedUnicodeString(&CapturedSubsystemName, UserMode);
679
680 if (CapturedSecurityDescriptor != NULL)
681 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor, UserMode, FALSE);
682
683 if (ClientToken != NULL)
684 {
685 ObDereferenceObject(ClientToken);
686 SubjectContext.ClientToken = SubjectContextToken;
687 }
688
689 if (AllocatedResultLists)
690 ExFreePoolWithTag(SafeGrantedAccessList, TAG_SEPA);
691
692 /* Release the security subject context */
693 SeReleaseSubjectContext(&SubjectContext);
694
695 return Status;
696 }
697
698
699 /* PUBLIC FUNCTIONS ***********************************************************/
700
701 /*
702 * @unimplemented
703 */
704 VOID
705 NTAPI
706 SeAuditHardLinkCreation(IN PUNICODE_STRING FileName,
707 IN PUNICODE_STRING LinkName,
708 IN BOOLEAN bSuccess)
709 {
710 UNIMPLEMENTED;
711 }
712
713 /*
714 * @unimplemented
715 */
716 BOOLEAN
717 NTAPI
718 SeAuditingFileEvents(IN BOOLEAN AccessGranted,
719 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
720 {
721 UNIMPLEMENTED;
722 return FALSE;
723 }
724
725 /*
726 * @unimplemented
727 */
728 BOOLEAN
729 NTAPI
730 SeAuditingFileEventsWithContext(IN BOOLEAN AccessGranted,
731 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
732 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL)
733 {
734 UNIMPLEMENTED;
735 return FALSE;
736 }
737
738 /*
739 * @unimplemented
740 */
741 BOOLEAN
742 NTAPI
743 SeAuditingHardLinkEvents(IN BOOLEAN AccessGranted,
744 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
745 {
746 UNIMPLEMENTED;
747 return FALSE;
748 }
749
750 /*
751 * @unimplemented
752 */
753 BOOLEAN
754 NTAPI
755 SeAuditingHardLinkEventsWithContext(IN BOOLEAN AccessGranted,
756 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
757 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL)
758 {
759 UNIMPLEMENTED;
760 return FALSE;
761 }
762
763 /*
764 * @unimplemented
765 */
766 BOOLEAN
767 NTAPI
768 SeAuditingFileOrGlobalEvents(IN BOOLEAN AccessGranted,
769 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
770 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext)
771 {
772 UNIMPLEMENTED;
773 return FALSE;
774 }
775
776 /*
777 * @unimplemented
778 */
779 VOID
780 NTAPI
781 SeCloseObjectAuditAlarm(IN PVOID Object,
782 IN HANDLE Handle,
783 IN BOOLEAN PerformAction)
784 {
785 UNIMPLEMENTED;
786 }
787
788 /*
789 * @unimplemented
790 */
791 VOID NTAPI
792 SeDeleteObjectAuditAlarm(IN PVOID Object,
793 IN HANDLE Handle)
794 {
795 UNIMPLEMENTED;
796 }
797
798 /*
799 * @unimplemented
800 */
801 VOID
802 NTAPI
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)
812 {
813 PAGED_CODE();
814
815 /* Audits aren't done on kernel-mode access */
816 if (AccessMode == KernelMode) return;
817
818 /* Otherwise, unimplemented! */
819 //UNIMPLEMENTED;
820 return;
821 }
822
823 /*
824 * @unimplemented
825 */
826 VOID NTAPI
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)
836 {
837 UNIMPLEMENTED;
838 }
839
840 /*
841 * @unimplemented
842 */
843 VOID
844 NTAPI
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)
851 {
852 UNIMPLEMENTED;
853 }
854
855 /* SYSTEM CALLS ***************************************************************/
856
857 NTSTATUS
858 NTAPI
859 NtCloseObjectAuditAlarm(
860 PUNICODE_STRING SubsystemName,
861 PVOID HandleId,
862 BOOLEAN GenerateOnClose)
863 {
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;
871 NTSTATUS Status;
872 PTOKEN Token;
873 PAGED_CODE();
874
875 /* Get the previous mode (only user mode is supported!) */
876 PreviousMode = ExGetPreviousMode();
877 ASSERT(PreviousMode != KernelMode);
878
879 /* Do we even need to do anything? */
880 if (!GenerateOnClose)
881 {
882 /* Nothing to do, return success */
883 return STATUS_SUCCESS;
884 }
885
886 /* Capture the security subject context */
887 SeCaptureSubjectContext(&SubjectContext);
888
889 /* Check for audit privilege */
890 if (!SeCheckAuditPrivilege(&SubjectContext, PreviousMode))
891 {
892 DPRINT1("Caller does not have SeAuditPrivilege\n");
893 Status = STATUS_PRIVILEGE_NOT_HELD;
894 goto Cleanup;
895 }
896
897 /* Probe and capture the subsystem name */
898 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
899 PreviousMode,
900 SubsystemName);
901 if (!NT_SUCCESS(Status))
902 {
903 DPRINT1("Failed to capture subsystem name!\n");
904 goto Cleanup;
905 }
906
907 /* Get the current thread and check if it's impersonating */
908 CurrentThread = PsGetCurrentThread();
909 if (PsIsThreadImpersonating(CurrentThread))
910 {
911 /* Get the impersonation token */
912 Token = PsReferenceImpersonationToken(CurrentThread,
913 &CopyOnOpen,
914 &EffectiveOnly,
915 &ImpersonationLevel);
916 UseImpersonationToken = TRUE;
917 }
918 else
919 {
920 /* Get the primary token */
921 Token = PsReferencePrimaryToken(PsGetCurrentProcess());
922 UseImpersonationToken = FALSE;
923 }
924
925 /* Call the internal function */
926 SepAdtCloseObjectAuditAlarm(&CapturedSubsystemName,
927 HandleId,
928 Token->UserAndGroups->Sid);
929
930 /* Release the captured subsystem name */
931 ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode);
932
933 /* Check what token we used */
934 if (UseImpersonationToken)
935 {
936 /* Release impersonation token */
937 PsDereferenceImpersonationToken(Token);
938 }
939 else
940 {
941 /* Release primary token */
942 PsDereferencePrimaryToken(Token);
943 }
944
945 Status = STATUS_SUCCESS;
946
947 Cleanup:
948
949 /* Release the security subject context */
950 SeReleaseSubjectContext(&SubjectContext);
951
952 return Status;
953 }
954
955
956 NTSTATUS NTAPI
957 NtDeleteObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
958 IN PVOID HandleId,
959 IN BOOLEAN GenerateOnClose)
960 {
961 UNIMPLEMENTED;
962 return STATUS_NOT_IMPLEMENTED;
963 }
964
965 VOID
966 NTAPI
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)
981 {
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);
994 UNIMPLEMENTED;
995 *GenerateOnClose = FALSE;
996 }
997
998 __kernel_entry
999 NTSTATUS
1000 NTAPI
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)
1014 {
1015 PTOKEN ClientToken;
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;
1023 NTSTATUS Status;
1024 PAGED_CODE();
1025
1026 /* Only user mode is supported! */
1027 ASSERT(ExGetPreviousMode() != KernelMode);
1028
1029 /* Start clean */
1030 ClientToken = NULL;
1031 CapturedSecurityDescriptor = NULL;
1032 CapturedPrivilegeSet = NULL;
1033 CapturedSubsystemName.Buffer = NULL;
1034 CapturedObjectTypeName.Buffer = NULL;
1035 CapturedObjectName.Buffer = NULL;
1036
1037 /* Reference the client token */
1038 Status = ObReferenceObjectByHandle(ClientTokenHandle,
1039 TOKEN_QUERY,
1040 SeTokenObjectType,
1041 UserMode,
1042 (PVOID*)&ClientToken,
1043 NULL);
1044 if (!NT_SUCCESS(Status))
1045 {
1046 DPRINT1("Failed to reference token handle %p: %lx\n",
1047 ClientTokenHandle, Status);
1048 return Status;
1049 }
1050
1051 /* Capture the security subject context */
1052 SeCaptureSubjectContext(&SubjectContext);
1053
1054 /* Validate the token's impersonation level */
1055 if ((ClientToken->TokenType == TokenImpersonation) &&
1056 (ClientToken->ImpersonationLevel < SecurityIdentification))
1057 {
1058 DPRINT1("Invalid impersonation level (%u)\n", ClientToken->ImpersonationLevel);
1059 Status = STATUS_BAD_IMPERSONATION_LEVEL;
1060 goto Cleanup;
1061 }
1062
1063 /* Check for audit privilege */
1064 if (!SeCheckAuditPrivilege(&SubjectContext, UserMode))
1065 {
1066 DPRINT1("Caller does not have SeAuditPrivilege\n");
1067 Status = STATUS_PRIVILEGE_NOT_HELD;
1068 goto Cleanup;
1069 }
1070
1071 /* Check for NULL SecurityDescriptor */
1072 if (SecurityDescriptor == NULL)
1073 {
1074 /* Nothing to do */
1075 Status = STATUS_SUCCESS;
1076 goto Cleanup;
1077 }
1078
1079 /* Capture the security descriptor */
1080 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
1081 UserMode,
1082 PagedPool,
1083 FALSE,
1084 &CapturedSecurityDescriptor);
1085 if (!NT_SUCCESS(Status))
1086 {
1087 DPRINT1("Failed to capture security descriptor!\n");
1088 goto Cleanup;
1089 }
1090
1091 _SEH2_TRY
1092 {
1093 /* Check if we have a privilege set */
1094 if (PrivilegeSet != NULL)
1095 {
1096 /* Probe the basic privilege set structure */
1097 ProbeForRead(PrivilegeSet, sizeof(PRIVILEGE_SET), sizeof(ULONG));
1098
1099 /* Validate privilege count */
1100 PrivilegeCount = PrivilegeSet->PrivilegeCount;
1101 if (PrivilegeCount > SEP_PRIVILEGE_SET_MAX_COUNT)
1102 {
1103 Status = STATUS_INVALID_PARAMETER;
1104 goto Cleanup;
1105 }
1106
1107 /* Calculate the size of the PrivilegeSet structure */
1108 PrivilegeSetSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]);
1109
1110 /* Probe the whole structure */
1111 ProbeForRead(PrivilegeSet, PrivilegeSetSize, sizeof(ULONG));
1112
1113 /* Allocate a temp buffer */
1114 CapturedPrivilegeSet = ExAllocatePoolWithTag(PagedPool,
1115 PrivilegeSetSize,
1116 TAG_PRIVILEGE_SET);
1117 if (CapturedPrivilegeSet == NULL)
1118 {
1119 DPRINT1("Failed to allocate %u bytes\n", PrivilegeSetSize);
1120 Status = STATUS_INSUFFICIENT_RESOURCES;
1121 goto Cleanup;
1122 }
1123
1124 /* Copy the privileges */
1125 RtlCopyMemory(CapturedPrivilegeSet, PrivilegeSet, PrivilegeSetSize);
1126 }
1127
1128 if (HandleId != NULL)
1129 {
1130 ProbeForRead(HandleId, sizeof(PVOID), sizeof(PVOID));
1131 CapturedHandleId = *(PVOID*)HandleId;
1132 }
1133
1134 ProbeForWrite(GenerateOnClose, sizeof(BOOLEAN), sizeof(BOOLEAN));
1135 }
1136 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1137 {
1138 Status = _SEH2_GetExceptionCode();
1139 DPRINT1("Exception while probing parameters: 0x%lx\n", Status);
1140 goto Cleanup;
1141 }
1142 _SEH2_END;
1143
1144 /* Probe and capture the subsystem name */
1145 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
1146 UserMode,
1147 SubsystemName);
1148 if (!NT_SUCCESS(Status))
1149 {
1150 DPRINT1("Failed to capture subsystem name!\n");
1151 goto Cleanup;
1152 }
1153
1154 /* Probe and capture the object type name */
1155 Status = ProbeAndCaptureUnicodeString(&CapturedObjectTypeName,
1156 UserMode,
1157 ObjectTypeName);
1158 if (!NT_SUCCESS(Status))
1159 {
1160 DPRINT1("Failed to capture object type name!\n");
1161 goto Cleanup;
1162 }
1163
1164 /* Probe and capture the object name */
1165 Status = ProbeAndCaptureUnicodeString(&CapturedObjectName,
1166 UserMode,
1167 ObjectName);
1168 if (!NT_SUCCESS(Status))
1169 {
1170 DPRINT1("Failed to capture object name!\n");
1171 goto Cleanup;
1172 }
1173
1174 /* Call the internal function */
1175 SepOpenObjectAuditAlarm(&SubjectContext,
1176 &CapturedSubsystemName,
1177 CapturedHandleId,
1178 &CapturedObjectTypeName,
1179 &CapturedObjectName,
1180 CapturedSecurityDescriptor,
1181 ClientToken,
1182 DesiredAccess,
1183 GrantedAccess,
1184 CapturedPrivilegeSet,
1185 ObjectCreation,
1186 AccessGranted,
1187 &LocalGenerateOnClose);
1188
1189 Status = STATUS_SUCCESS;
1190
1191 /* Enter SEH to copy the data back to user mode */
1192 _SEH2_TRY
1193 {
1194 *GenerateOnClose = LocalGenerateOnClose;
1195 }
1196 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1197 {
1198 Status = _SEH2_GetExceptionCode();
1199 DPRINT1("Exception while copying back data: 0x%lx\n", Status);
1200 }
1201 _SEH2_END;
1202
1203 Cleanup:
1204
1205 if (CapturedObjectName.Buffer != NULL)
1206 ReleaseCapturedUnicodeString(&CapturedObjectName, UserMode);
1207
1208 if (CapturedObjectTypeName.Buffer != NULL)
1209 ReleaseCapturedUnicodeString(&CapturedObjectTypeName, UserMode);
1210
1211 if (CapturedSubsystemName.Buffer != NULL)
1212 ReleaseCapturedUnicodeString(&CapturedSubsystemName, UserMode);
1213
1214 if (CapturedSecurityDescriptor != NULL)
1215 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor, UserMode, FALSE);
1216
1217 if (CapturedPrivilegeSet != NULL)
1218 ExFreePoolWithTag(CapturedPrivilegeSet, TAG_PRIVILEGE_SET);
1219
1220 /* Release the security subject context */
1221 SeReleaseSubjectContext(&SubjectContext);
1222
1223 ObDereferenceObject(ClientToken);
1224
1225 return Status;
1226 }
1227
1228
1229 __kernel_entry
1230 NTSTATUS
1231 NTAPI
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 )
1238 {
1239 KPROCESSOR_MODE PreviousMode;
1240 PTOKEN ClientToken;
1241 volatile PPRIVILEGE_SET CapturedPrivileges = NULL;
1242 UNICODE_STRING CapturedSubsystemName;
1243 UNICODE_STRING CapturedServiceName;
1244 ULONG PrivilegeCount, PrivilegesSize;
1245 SECURITY_SUBJECT_CONTEXT SubjectContext;
1246 NTSTATUS Status;
1247 PAGED_CODE();
1248
1249 /* Get the previous mode (only user mode is supported!) */
1250 PreviousMode = ExGetPreviousMode();
1251 ASSERT(PreviousMode != KernelMode);
1252
1253 CapturedSubsystemName.Buffer = NULL;
1254 CapturedServiceName.Buffer = NULL;
1255
1256 /* Reference the client token */
1257 Status = ObReferenceObjectByHandle(ClientTokenHandle,
1258 TOKEN_QUERY,
1259 SeTokenObjectType,
1260 PreviousMode,
1261 (PVOID*)&ClientToken,
1262 NULL);
1263 if (!NT_SUCCESS(Status))
1264 {
1265 DPRINT1("Failed to reference client token: 0x%lx\n", Status);
1266 return Status;
1267 }
1268
1269 /* Validate the token's impersonation level */
1270 if ((ClientToken->TokenType == TokenImpersonation) &&
1271 (ClientToken->ImpersonationLevel < SecurityIdentification))
1272 {
1273 DPRINT1("Invalid impersonation level (%u)\n", ClientToken->ImpersonationLevel);
1274 ObDereferenceObject(ClientToken);
1275 return STATUS_BAD_IMPERSONATION_LEVEL;
1276 }
1277
1278 /* Capture the security subject context */
1279 SeCaptureSubjectContext(&SubjectContext);
1280
1281 /* Check for audit privilege */
1282 if (!SeCheckAuditPrivilege(&SubjectContext, PreviousMode))
1283 {
1284 DPRINT1("Caller does not have SeAuditPrivilege\n");
1285 Status = STATUS_PRIVILEGE_NOT_HELD;
1286 goto Cleanup;
1287 }
1288
1289 /* Do we have a subsystem name? */
1290 if (SubsystemName != NULL)
1291 {
1292 /* Probe and capture the subsystem name */
1293 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
1294 PreviousMode,
1295 SubsystemName);
1296 if (!NT_SUCCESS(Status))
1297 {
1298 DPRINT1("Failed to capture subsystem name!\n");
1299 goto Cleanup;
1300 }
1301 }
1302
1303 /* Do we have a service name? */
1304 if (ServiceName != NULL)
1305 {
1306 /* Probe and capture the service name */
1307 Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
1308 PreviousMode,
1309 ServiceName);
1310 if (!NT_SUCCESS(Status))
1311 {
1312 DPRINT1("Failed to capture service name!\n");
1313 goto Cleanup;
1314 }
1315 }
1316
1317 _SEH2_TRY
1318 {
1319 /* Probe the basic privilege set structure */
1320 ProbeForRead(Privileges, sizeof(PRIVILEGE_SET), sizeof(ULONG));
1321
1322 /* Validate privilege count */
1323 PrivilegeCount = Privileges->PrivilegeCount;
1324 if (PrivilegeCount > SEP_PRIVILEGE_SET_MAX_COUNT)
1325 {
1326 Status = STATUS_INVALID_PARAMETER;
1327 goto Cleanup;
1328 }
1329
1330 /* Calculate the size of the Privileges structure */
1331 PrivilegesSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]);
1332
1333 /* Probe the whole structure */
1334 ProbeForRead(Privileges, PrivilegesSize, sizeof(ULONG));
1335
1336 /* Allocate a temp buffer */
1337 CapturedPrivileges = ExAllocatePoolWithTag(PagedPool,
1338 PrivilegesSize,
1339 TAG_PRIVILEGE_SET);
1340 if (CapturedPrivileges == NULL)
1341 {
1342 DPRINT1("Failed to allocate %u bytes\n", PrivilegesSize);
1343 Status = STATUS_INSUFFICIENT_RESOURCES;
1344 goto Cleanup;
1345 }
1346
1347 /* Copy the privileges */
1348 RtlCopyMemory(CapturedPrivileges, Privileges, PrivilegesSize);
1349 }
1350 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1351 {
1352 Status = _SEH2_GetExceptionCode();
1353 DPRINT1("Got exception 0x%lx\n", Status);
1354 goto Cleanup;
1355 }
1356 _SEH2_END;
1357
1358 /* Call the internal function */
1359 SepAdtPrivilegedServiceAuditAlarm(&SubjectContext,
1360 SubsystemName ? &CapturedSubsystemName : NULL,
1361 ServiceName ? &CapturedServiceName : NULL,
1362 ClientToken,
1363 SubjectContext.PrimaryToken,
1364 CapturedPrivileges,
1365 AccessGranted);
1366
1367 Status = STATUS_SUCCESS;
1368
1369 Cleanup:
1370 /* Cleanup resources */
1371 if (CapturedSubsystemName.Buffer != NULL)
1372 ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode);
1373
1374 if (CapturedServiceName.Buffer != NULL)
1375 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1376
1377 if (CapturedPrivileges != NULL)
1378 ExFreePoolWithTag(CapturedPrivileges, TAG_PRIVILEGE_SET);
1379
1380 /* Release the security subject context */
1381 SeReleaseSubjectContext(&SubjectContext);
1382
1383 ObDereferenceObject(ClientToken);
1384
1385 return Status;
1386 }
1387
1388
1389 NTSTATUS NTAPI
1390 NtPrivilegeObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
1391 IN PVOID HandleId,
1392 IN HANDLE ClientToken,
1393 IN ULONG DesiredAccess,
1394 IN PPRIVILEGE_SET Privileges,
1395 IN BOOLEAN AccessGranted)
1396 {
1397 UNIMPLEMENTED;
1398 return STATUS_NOT_IMPLEMENTED;
1399 }
1400
1401
1402 _Must_inspect_result_
1403 __kernel_entry
1404 NTSTATUS
1405 NTAPI
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)
1418 {
1419 /* Call the internal function */
1420 return SepAccessCheckAndAuditAlarm(SubsystemName,
1421 HandleId,
1422 NULL,
1423 ObjectTypeName,
1424 ObjectName,
1425 SecurityDescriptor,
1426 NULL,
1427 DesiredAccess,
1428 AuditEventObjectAccess,
1429 0,
1430 NULL,
1431 0,
1432 GenericMapping,
1433 GrantedAccess,
1434 AccessStatus,
1435 GenerateOnClose,
1436 FALSE);
1437 }
1438
1439 _Must_inspect_result_
1440 __kernel_entry
1441 NTSTATUS
1442 NTAPI
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,
1452 _In_ ULONG Flags,
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)
1460 {
1461 /* Call the internal function */
1462 return SepAccessCheckAndAuditAlarm(SubsystemName,
1463 HandleId,
1464 NULL,
1465 ObjectTypeName,
1466 ObjectName,
1467 SecurityDescriptor,
1468 PrincipalSelfSid,
1469 DesiredAccess,
1470 AuditType,
1471 Flags,
1472 ObjectTypeList,
1473 ObjectTypeLength,
1474 GenericMapping,
1475 GrantedAccess,
1476 AccessStatus,
1477 GenerateOnClose,
1478 FALSE);
1479 }
1480
1481 _Must_inspect_result_
1482 __kernel_entry
1483 NTSTATUS
1484 NTAPI
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,
1494 _In_ ULONG Flags,
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)
1502 {
1503 /* Call the internal function */
1504 return SepAccessCheckAndAuditAlarm(SubsystemName,
1505 HandleId,
1506 NULL,
1507 ObjectTypeName,
1508 ObjectName,
1509 SecurityDescriptor,
1510 PrincipalSelfSid,
1511 DesiredAccess,
1512 AuditType,
1513 Flags,
1514 ObjectTypeList,
1515 ObjectTypeListLength,
1516 GenericMapping,
1517 GrantedAccessList,
1518 AccessStatusList,
1519 GenerateOnClose,
1520 TRUE);
1521 }
1522
1523 _Must_inspect_result_
1524 __kernel_entry
1525 NTSTATUS
1526 NTAPI
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,
1537 _In_ ULONG Flags,
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)
1545 {
1546 UNREFERENCED_PARAMETER(ObjectCreation);
1547
1548 /* Call the internal function */
1549 return SepAccessCheckAndAuditAlarm(SubsystemName,
1550 HandleId,
1551 &ClientToken,
1552 ObjectTypeName,
1553 ObjectName,
1554 SecurityDescriptor,
1555 PrincipalSelfSid,
1556 DesiredAccess,
1557 AuditType,
1558 Flags,
1559 ObjectTypeList,
1560 ObjectTypeListLength,
1561 GenericMapping,
1562 GrantedAccessList,
1563 AccessStatusList,
1564 GenerateOnClose,
1565 TRUE);
1566 }
1567
1568 /* EOF */