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 _SEH2_YIELD(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 _SEH2_YIELD(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 _SEH2_YIELD(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 _SEH2_YIELD(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 _SEH2_YIELD(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 _SEH2_YIELD(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 _SEH2_YIELD(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 _SEH2_YIELD(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 */ 1569