1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Security auditing functions 5 * COPYRIGHT: Copyright Eric Kohl 6 * Copyright Timo Kreuzer <timo.kreuzer@reactos.org> 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 #define SEP_PRIVILEGE_SET_MAX_COUNT 60 16 17 UNICODE_STRING SeSubsystemName = RTL_CONSTANT_STRING(L"Security"); 18 19 /* PRIVATE FUNCTIONS ***********************************************************/ 20 21 /** 22 * @unimplemented 23 * @brief 24 * Peforms a detailed security auditing with an access token. 25 * 26 * @param[in] Token 27 * A valid token object. 28 * 29 * @return 30 * To be added... 31 */ 32 BOOLEAN 33 NTAPI 34 SeDetailedAuditingWithToken( 35 _In_ PTOKEN Token) 36 { 37 /* FIXME */ 38 return FALSE; 39 } 40 41 /** 42 * @unimplemented 43 * @brief 44 * Peforms a security auditing against a process that is about to 45 * be created. 46 * 47 * @param[in] Process 48 * An object that points to a process which is in process of 49 * creation. 50 * 51 * @return 52 * Nothing. 53 */ 54 VOID 55 NTAPI 56 SeAuditProcessCreate( 57 _In_ PEPROCESS Process) 58 { 59 /* FIXME */ 60 } 61 62 /** 63 * @unimplemented 64 * @brief 65 * Peforms a security auditing against a process that is about to 66 * be terminated. 67 * 68 * @param[in] Process 69 * An object that points to a process which is in process of 70 * termination. 71 * 72 * @return 73 * Nothing. 74 */ 75 VOID 76 NTAPI 77 SeAuditProcessExit( 78 _In_ PEPROCESS Process) 79 { 80 /* FIXME */ 81 } 82 83 /** 84 * @brief 85 * Initializes a process audit name and returns it to the caller. 86 * 87 * @param[in] FileObject 88 * File object that points to a name to be queried. 89 * 90 * @param[in] DoAudit 91 * If set to TRUE, the function will perform various security 92 * auditing onto the audit name. 93 * 94 * @param[out] AuditInfo 95 * The returned audit info data. 96 * 97 * @return 98 * Returns STATUS_SUCCESS if process audit name initialization 99 * has completed successfully. STATUS_NO_MEMORY is returned if 100 * pool allocation for object name info has failed. A failure 101 * NTSTATUS code is returned otherwise. 102 */ 103 NTSTATUS 104 NTAPI 105 SeInitializeProcessAuditName( 106 _In_ PFILE_OBJECT FileObject, 107 _In_ BOOLEAN DoAudit, 108 _Out_ POBJECT_NAME_INFORMATION *AuditInfo) 109 { 110 OBJECT_NAME_INFORMATION LocalNameInfo; 111 POBJECT_NAME_INFORMATION ObjectNameInfo = NULL; 112 ULONG ReturnLength = 8; 113 NTSTATUS Status; 114 115 PAGED_CODE(); 116 ASSERT(AuditInfo); 117 118 /* Check if we should do auditing */ 119 if (DoAudit) 120 { 121 /* FIXME: TODO */ 122 } 123 124 /* Now query the name */ 125 Status = ObQueryNameString(FileObject, 126 &LocalNameInfo, 127 sizeof(LocalNameInfo), 128 &ReturnLength); 129 if (((Status == STATUS_BUFFER_OVERFLOW) || 130 (Status == STATUS_BUFFER_TOO_SMALL) || 131 (Status == STATUS_INFO_LENGTH_MISMATCH)) && 132 (ReturnLength != sizeof(LocalNameInfo))) 133 { 134 /* Allocate required size */ 135 ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool, 136 ReturnLength, 137 TAG_SEPA); 138 if (ObjectNameInfo) 139 { 140 /* Query the name again */ 141 Status = ObQueryNameString(FileObject, 142 ObjectNameInfo, 143 ReturnLength, 144 &ReturnLength); 145 } 146 } 147 148 /* Check if we got here due to failure */ 149 if ((ObjectNameInfo) && 150 (!(NT_SUCCESS(Status)) || (ReturnLength == sizeof(LocalNameInfo)))) 151 { 152 /* First, free any buffer we might've allocated */ 153 ASSERT(FALSE); 154 if (ObjectNameInfo) ExFreePool(ObjectNameInfo); 155 156 /* Now allocate a temporary one */ 157 ReturnLength = sizeof(OBJECT_NAME_INFORMATION); 158 ObjectNameInfo = ExAllocatePoolWithTag(NonPagedPool, 159 sizeof(OBJECT_NAME_INFORMATION), 160 TAG_SEPA); 161 if (ObjectNameInfo) 162 { 163 /* Clear it */ 164 RtlZeroMemory(ObjectNameInfo, ReturnLength); 165 Status = STATUS_SUCCESS; 166 } 167 } 168 169 /* Check if memory allocation failed */ 170 if (!ObjectNameInfo) Status = STATUS_NO_MEMORY; 171 172 /* Return the audit name */ 173 *AuditInfo = ObjectNameInfo; 174 175 /* Return status */ 176 return Status; 177 } 178 179 /** 180 * @brief 181 * Finds the process image name of a specific process. 182 * 183 * @param[in] Process 184 * Process object submitted by the caller, where the image name 185 * is to be located. 186 * 187 * @param[out] ProcessImageName 188 * An output Unicode string structure with the located process 189 * image name. 190 * 191 * @return 192 * Returns STATUS_SUCCESS if process image name has been located 193 * successfully. STATUS_NO_MEMORY is returned if pool allocation 194 * for the image name has failed. A failure NTSTATUS code is 195 * returned otherwise. 196 */ 197 NTSTATUS 198 NTAPI 199 SeLocateProcessImageName( 200 _In_ PEPROCESS Process, 201 _Out_ PUNICODE_STRING *ProcessImageName) 202 { 203 POBJECT_NAME_INFORMATION AuditName; 204 PUNICODE_STRING ImageName; 205 PFILE_OBJECT FileObject; 206 NTSTATUS Status = STATUS_SUCCESS; 207 208 PAGED_CODE(); 209 210 /* Assume failure */ 211 *ProcessImageName = NULL; 212 213 /* Check if we have audit info */ 214 AuditName = Process->SeAuditProcessCreationInfo.ImageFileName; 215 if (!AuditName) 216 { 217 /* Get the file object */ 218 Status = PsReferenceProcessFilePointer(Process, &FileObject); 219 if (!NT_SUCCESS(Status)) return Status; 220 221 /* Initialize the audit structure */ 222 Status = SeInitializeProcessAuditName(FileObject, TRUE, &AuditName); 223 if (NT_SUCCESS(Status)) 224 { 225 /* Set it */ 226 if (InterlockedCompareExchangePointer((PVOID*)&Process-> 227 SeAuditProcessCreationInfo.ImageFileName, 228 AuditName, 229 NULL)) 230 { 231 /* Someone beat us to it, deallocate our copy */ 232 ExFreePool(AuditName); 233 } 234 } 235 236 /* Dereference the file object */ 237 ObDereferenceObject(FileObject); 238 if (!NT_SUCCESS(Status)) return Status; 239 } 240 241 /* Get audit info again, now we have it for sure */ 242 AuditName = Process->SeAuditProcessCreationInfo.ImageFileName; 243 244 /* Allocate the output string */ 245 ImageName = ExAllocatePoolWithTag(NonPagedPool, 246 AuditName->Name.MaximumLength + 247 sizeof(UNICODE_STRING), 248 TAG_SEPA); 249 if (!ImageName) return STATUS_NO_MEMORY; 250 251 /* Make a copy of it */ 252 RtlCopyMemory(ImageName, 253 &AuditName->Name, 254 AuditName->Name.MaximumLength + sizeof(UNICODE_STRING)); 255 256 /* Fix up the buffer */ 257 ImageName->Buffer = (PWSTR)(ImageName + 1); 258 259 /* Return it */ 260 *ProcessImageName = ImageName; 261 262 /* Return status */ 263 return Status; 264 } 265 266 /** 267 * @brief 268 * Closes an audit alarm event of an object. 269 * 270 * @param[in] SubsystemName 271 * A Unicode string pointing to the name of the subsystem where auditing 272 * alarm event has to be closed. 273 * 274 * @param[in] HandleId 275 * A handle to an ID where such ID represents the identification of the 276 * object where audit alarm is to be closed. 277 * 278 * @param[in] Sid 279 * A SID that represents the user who attempted to close the audit 280 * alarm. 281 * 282 * @return 283 * Nothing. 284 */ 285 VOID 286 NTAPI 287 SepAdtCloseObjectAuditAlarm( 288 _In_ PUNICODE_STRING SubsystemName, 289 _In_ PVOID HandleId, 290 _In_ PSID Sid) 291 { 292 UNIMPLEMENTED; 293 } 294 295 /** 296 * @brief 297 * Performs an audit alarm to a privileged service request. 298 * This is a worker function. 299 * 300 * @param[in] SubjectContext 301 * A security subject context used for the auditing process. 302 * 303 * @param[in] SubsystemName 304 * A Unicode string that represents the name of a subsystem that 305 * actuated the procedure of alarm auditing of a privileged 306 * service. 307 * 308 * @param[in] ServiceName 309 * A Unicode string that represents the name of a privileged 310 * service request for auditing. 311 * 312 * @param[in] Token 313 * An access token. 314 * 315 * @param[in] PrimaryToken 316 * A primary access token. 317 * 318 * @param[in] Privileges 319 * An array set of privileges used to check if the privileged 320 * service does actually have all the required set of privileges 321 * for security access. 322 * 323 * @param[in] AccessGranted 324 * When auditing is done, the function will return TRUE to the caller 325 * if access is granted, FALSE otherwise. 326 * 327 * @return 328 * Nothing. 329 */ 330 VOID 331 NTAPI 332 SepAdtPrivilegedServiceAuditAlarm( 333 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 334 _In_opt_ PUNICODE_STRING SubsystemName, 335 _In_opt_ PUNICODE_STRING ServiceName, 336 _In_ PTOKEN Token, 337 _In_ PTOKEN PrimaryToken, 338 _In_ PPRIVILEGE_SET Privileges, 339 _In_ BOOLEAN AccessGranted) 340 { 341 DPRINT("SepAdtPrivilegedServiceAuditAlarm is unimplemented\n"); 342 } 343 344 /** 345 * @brief 346 * Performs an audit alarm to a privileged service request. 347 * 348 * @param[in] ServiceName 349 * A Unicode string that represents the name of a privileged 350 * service request for auditing. 351 * 352 * @param[in] SubjectContext 353 * A security subject context used for the auditing process. 354 * 355 * @param[in] PrivilegeSet 356 * An array set of privileges used to check if the privileged 357 * service does actually have all the required set of privileges 358 * for security access. 359 * 360 * @param[in] AccessGranted 361 * When auditing is done, the function will return TRUE to the caller 362 * if access is granted, FALSE otherwise. 363 * 364 * @return 365 * Nothing. 366 */ 367 VOID 368 NTAPI 369 SePrivilegedServiceAuditAlarm( 370 _In_opt_ PUNICODE_STRING ServiceName, 371 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 372 _In_ PPRIVILEGE_SET PrivilegeSet, 373 _In_ BOOLEAN AccessGranted) 374 { 375 PTOKEN EffectiveToken; 376 PSID UserSid; 377 PAGED_CODE(); 378 379 /* Get the effective token */ 380 if (SubjectContext->ClientToken != NULL) 381 EffectiveToken = SubjectContext->ClientToken; 382 else 383 EffectiveToken = SubjectContext->PrimaryToken; 384 385 /* Get the user SID */ 386 UserSid = EffectiveToken->UserAndGroups->Sid; 387 388 /* Check if this is the local system SID */ 389 if (RtlEqualSid(UserSid, SeLocalSystemSid)) 390 { 391 /* Nothing to do */ 392 return; 393 } 394 395 /* Check if this is the network service or local service SID */ 396 if (RtlEqualSid(UserSid, SeExports->SeNetworkServiceSid) || 397 RtlEqualSid(UserSid, SeExports->SeLocalServiceSid)) 398 { 399 // FIXME: should continue for a certain set of privileges 400 return; 401 } 402 403 /* Call the worker function */ 404 SepAdtPrivilegedServiceAuditAlarm(SubjectContext, 405 &SeSubsystemName, 406 ServiceName, 407 SubjectContext->ClientToken, 408 SubjectContext->PrimaryToken, 409 PrivilegeSet, 410 AccessGranted); 411 412 } 413 414 /** 415 * @unimplemented 416 * @brief 417 * Worker function that serves as the main heart and brain of the whole 418 * concept and implementation of auditing in the kernel. 419 * 420 * @param[in] SubsystemName 421 * A Unicode string that represents the name of a subsystem that 422 * actuates the auditing process. 423 * 424 * @param[in] HandleId 425 * A handle to an ID used to identify an object where auditing 426 * is to be done. 427 * 428 * @param[in] SubjectContext 429 * Security subject context. 430 * 431 * @param[in] ObjectTypeName 432 * A Unicode string that represents the name of an object type. 433 * 434 * @param[in] ObjectName 435 * The name of the object. 436 * 437 * @param[in] SecurityDescriptor 438 * A security descriptor with internal security information details 439 * for audit. 440 * 441 * @param[in] PrincipalSelfSid 442 * A principal self user SID. 443 * 444 * @param[in] DesiredAccess 445 * The desired access rights masks requested by the caller. 446 * 447 * @param[in] AuditType 448 * Type of audit to start. This parameter influences how an audit 449 * should be done. 450 * 451 * @param[in] HaveAuditPrivilege 452 * If set to TRUE, the security subject context has the audit privilege thus 453 * it is allowed the ability to perform the audit. 454 * 455 * @param[in] ObjectTypeList 456 * A list of object types. 457 * 458 * @param[in] ObjectTypeListLength 459 * The length size of the list. 460 * 461 * @param[in] GenericMapping 462 * The generic mapping table of access rights used whilst performing auditing 463 * sequence procedure. 464 * 465 * @param[out] GrantedAccessList 466 * This parameter is used to return to the caller a list of actual granted access 467 * rights masks that the audited object has. 468 * 469 * @param[out] AccessStatusList 470 * This parameter is used to return to the caller a list of status return codes. 471 * The function may actually return a single NTSTATUS code if the calling thread 472 * sets UseResultList parameter to FALSE. 473 * 474 * @param[out] GenerateOnClose 475 * Returns TRUE if the function has generated a list of granted access rights and 476 * status codes on termination, FALSE otherwise. 477 * 478 * @param[in] UseResultList 479 * If set to TRUE, the caller wants that the function should only return a single 480 * NTSTATUS code. 481 * 482 * @return 483 * Returns STATUS_SUCCESS if the function has completed the whole internal 484 * auditing procedure mechanism with success. 485 */ 486 _Must_inspect_result_ 487 static 488 NTSTATUS 489 SepAccessCheckAndAuditAlarmWorker( 490 _In_ PUNICODE_STRING SubsystemName, 491 _In_opt_ PVOID HandleId, 492 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 493 _In_ PUNICODE_STRING ObjectTypeName, 494 _In_ PUNICODE_STRING ObjectName, 495 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 496 _In_opt_ PSID PrincipalSelfSid, 497 _In_ ACCESS_MASK DesiredAccess, 498 _In_ AUDIT_EVENT_TYPE AuditType, 499 _In_ BOOLEAN HaveAuditPrivilege, 500 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, 501 _In_ ULONG ObjectTypeListLength, 502 _In_ PGENERIC_MAPPING GenericMapping, 503 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList, 504 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList, 505 _Out_ PBOOLEAN GenerateOnClose, 506 _In_ BOOLEAN UseResultList) 507 { 508 ULONG ResultListLength, i; 509 510 /* Get the length of the result list */ 511 ResultListLength = UseResultList ? ObjectTypeListLength : 1; 512 513 /// FIXME: we should do some real work here... 514 UNIMPLEMENTED; 515 516 /// HACK: we just pretend all access is granted! 517 for (i = 0; i < ResultListLength; i++) 518 { 519 GrantedAccessList[i] = DesiredAccess; 520 AccessStatusList[i] = STATUS_SUCCESS; 521 } 522 523 *GenerateOnClose = FALSE; 524 525 return STATUS_SUCCESS; 526 } 527 528 /** 529 * @brief 530 * Performs security auditing, if the specific object can be granted 531 * security access or not. 532 * 533 * @param[in] SubsystemName 534 * A Unicode string that represents the name of a subsystem that 535 * actuates the auditing process. 536 * 537 * @param[in] HandleId 538 * A handle to an ID used to identify an object where auditing 539 * is to be done. 540 * 541 * @param[in] SubjectContext 542 * Security subject context. 543 * 544 * @param[in] ObjectTypeName 545 * A Unicode string that represents the name of an object type. 546 * 547 * @param[in] ObjectName 548 * The name of the object. 549 * 550 * @param[in] SecurityDescriptor 551 * A security descriptor with internal security information details 552 * for audit. 553 * 554 * @param[in] PrincipalSelfSid 555 * A principal self user SID. 556 * 557 * @param[in] DesiredAccess 558 * The desired access rights masks requested by the caller. 559 * 560 * @param[in] AuditType 561 * Type of audit to start. This parameter influences how an audit 562 * should be done. 563 * 564 * @param[in] Flags 565 * Flag bitmask parameter. 566 * 567 * @param[in] HaveAuditPrivilege 568 * If set to TRUE, the security subject context has the audit privilege thus 569 * it is allowed the ability to perform the audit. 570 * 571 * @param[in] ObjectTypeList 572 * A list of object types. 573 * 574 * @param[in] ObjectTypeListLength 575 * The length size of the list. 576 * 577 * @param[in] GenericMapping 578 * The generic mapping table of access rights used whilst performing auditing 579 * sequence procedure. 580 * 581 * @param[out] GrantedAccessList 582 * This parameter is used to return to the caller a list of actual granted access 583 * rights masks that the audited object has. 584 * 585 * @param[out] AccessStatusList 586 * This parameter is used to return to the caller a list of status return codes. 587 * The function may actually return a single NTSTATUS code if the calling thread 588 * sets UseResultList parameter to FALSE. 589 * 590 * @param[out] GenerateOnClose 591 * Returns TRUE if the function has generated a list of granted access rights and 592 * status codes on termination, FALSE otherwise. 593 * 594 * @param[in] UseResultList 595 * If set to TRUE, the caller wants that the function should only return a single 596 * NTSTATUS code. 597 * 598 * @return 599 * Returns STATUS_SUCCESS if the function has completed the whole internal 600 * auditing procedure mechanism with success. STATUS_INVALID_PARAMETER is 601 * returned if one of the parameters do not satisfy the general requirements 602 * by the function. STATUS_INSUFFICIENT_RESOURCES is returned if pool memory 603 * allocation has failed. STATUS_PRIVILEGE_NOT_HELD is returned if the current 604 * security subject context does not have the required audit privilege to actually 605 * perform auditing in the first place. STATUS_INVALID_SECURITY_DESCR is returned 606 * if the security descriptor provided by the caller is not valid, that is, such 607 * descriptor doesn't belong to the main user (owner) and current group. 608 * STATUS_GENERIC_NOT_MAPPED is returned if the access rights masks aren't actually 609 * mapped. A failure NTSTATUS code is returned otherwise. 610 */ 611 _Must_inspect_result_ 612 NTSTATUS 613 NTAPI 614 SepAccessCheckAndAuditAlarm( 615 _In_ PUNICODE_STRING SubsystemName, 616 _In_opt_ PVOID HandleId, 617 _In_ PHANDLE ClientTokenHandle, 618 _In_ PUNICODE_STRING ObjectTypeName, 619 _In_ PUNICODE_STRING ObjectName, 620 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 621 _In_opt_ PSID PrincipalSelfSid, 622 _In_ ACCESS_MASK DesiredAccess, 623 _In_ AUDIT_EVENT_TYPE AuditType, 624 _In_ ULONG Flags, 625 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, 626 _In_ ULONG ObjectTypeListLength, 627 _In_ PGENERIC_MAPPING GenericMapping, 628 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList, 629 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList, 630 _Out_ PBOOLEAN GenerateOnClose, 631 _In_ BOOLEAN UseResultList) 632 { 633 SECURITY_SUBJECT_CONTEXT SubjectContext; 634 ULONG ResultListLength; 635 GENERIC_MAPPING LocalGenericMapping; 636 PTOKEN SubjectContextToken, ClientToken; 637 BOOLEAN AllocatedResultLists; 638 BOOLEAN HaveAuditPrivilege; 639 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor; 640 UNICODE_STRING CapturedSubsystemName, CapturedObjectTypeName, CapturedObjectName; 641 ACCESS_MASK GrantedAccess, *SafeGrantedAccessList; 642 NTSTATUS AccessStatus, *SafeAccessStatusList; 643 PSID CapturedPrincipalSelfSid; 644 POBJECT_TYPE_LIST CapturedObjectTypeList; 645 ULONG i; 646 BOOLEAN LocalGenerateOnClose; 647 NTSTATUS Status; 648 PAGED_CODE(); 649 650 /* Only user mode is supported! */ 651 ASSERT(ExGetPreviousMode() != KernelMode); 652 653 /* Start clean */ 654 AllocatedResultLists = FALSE; 655 ClientToken = NULL; 656 CapturedSecurityDescriptor = NULL; 657 CapturedSubsystemName.Buffer = NULL; 658 CapturedObjectTypeName.Buffer = NULL; 659 CapturedObjectName.Buffer = NULL; 660 CapturedPrincipalSelfSid = NULL; 661 CapturedObjectTypeList = NULL; 662 663 /* Validate AuditType */ 664 if ((AuditType != AuditEventObjectAccess) && 665 (AuditType != AuditEventDirectoryServiceAccess)) 666 { 667 DPRINT1("Invalid audit type: %u\n", AuditType); 668 return STATUS_INVALID_PARAMETER; 669 } 670 671 /* Capture the security subject context */ 672 SeCaptureSubjectContext(&SubjectContext); 673 674 /* Did the caller pass a token handle? */ 675 if (ClientTokenHandle == NULL) 676 { 677 /* Check if we have a token in the subject context */ 678 if (SubjectContext.ClientToken == NULL) 679 { 680 Status = STATUS_NO_IMPERSONATION_TOKEN; 681 DPRINT1("No token\n"); 682 goto Cleanup; 683 } 684 685 /* Check if we have a valid impersonation level */ 686 if (SubjectContext.ImpersonationLevel < SecurityIdentification) 687 { 688 Status = STATUS_BAD_IMPERSONATION_LEVEL; 689 DPRINT1("Invalid impersonation level 0x%lx\n", 690 SubjectContext.ImpersonationLevel); 691 goto Cleanup; 692 } 693 } 694 695 /* Are we using a result list? */ 696 if (UseResultList) 697 { 698 /* The list length equals the object type list length */ 699 ResultListLength = ObjectTypeListLength; 700 if ((ResultListLength == 0) || (ResultListLength > 0x1000)) 701 { 702 Status = STATUS_INVALID_PARAMETER; 703 DPRINT1("Invalid ResultListLength: 0x%lx\n", ResultListLength); 704 goto Cleanup; 705 } 706 707 /* Allocate a safe buffer from paged pool */ 708 SafeGrantedAccessList = ExAllocatePoolWithTag(PagedPool, 709 2 * ResultListLength * sizeof(ULONG), 710 TAG_SEPA); 711 if (SafeGrantedAccessList == NULL) 712 { 713 Status = STATUS_INSUFFICIENT_RESOURCES; 714 DPRINT1("Failed to allocate access lists\n"); 715 goto Cleanup; 716 } 717 718 SafeAccessStatusList = (PNTSTATUS)&SafeGrantedAccessList[ResultListLength]; 719 AllocatedResultLists = TRUE; 720 } 721 else 722 { 723 /* List length is 1 */ 724 ResultListLength = 1; 725 SafeGrantedAccessList = &GrantedAccess; 726 SafeAccessStatusList = &AccessStatus; 727 } 728 729 _SEH2_TRY 730 { 731 /* Probe output buffers */ 732 ProbeForWrite(AccessStatusList, 733 ResultListLength * sizeof(*AccessStatusList), 734 sizeof(*AccessStatusList)); 735 ProbeForWrite(GrantedAccessList, 736 ResultListLength * sizeof(*GrantedAccessList), 737 sizeof(*GrantedAccessList)); 738 739 /* Probe generic mapping and make a local copy */ 740 ProbeForRead(GenericMapping, sizeof(*GenericMapping), sizeof(ULONG)); 741 LocalGenericMapping = * GenericMapping; 742 } 743 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 744 { 745 Status = _SEH2_GetExceptionCode(); 746 DPRINT1("Exception while probing parameters: 0x%lx\n", Status); 747 _SEH2_YIELD(goto Cleanup); 748 } 749 _SEH2_END; 750 751 /* Do we have a client token? */ 752 if (ClientTokenHandle != NULL) 753 { 754 /* Reference the client token */ 755 Status = ObReferenceObjectByHandle(*ClientTokenHandle, 756 TOKEN_QUERY, 757 SeTokenObjectType, 758 UserMode, 759 (PVOID*)&ClientToken, 760 NULL); 761 if (!NT_SUCCESS(Status)) 762 { 763 DPRINT1("Failed to reference token handle %p: %lx\n", 764 *ClientTokenHandle, Status); 765 goto Cleanup; 766 } 767 768 SubjectContextToken = SubjectContext.ClientToken; 769 SubjectContext.ClientToken = ClientToken; 770 } 771 772 /* Check for audit privilege */ 773 HaveAuditPrivilege = SeCheckAuditPrivilege(&SubjectContext, UserMode); 774 if (!HaveAuditPrivilege && !(Flags & AUDIT_ALLOW_NO_PRIVILEGE)) 775 { 776 DPRINT1("Caller does not have SeAuditPrivilege\n"); 777 Status = STATUS_PRIVILEGE_NOT_HELD; 778 goto Cleanup; 779 } 780 781 /* Generic access must already be mapped to non-generic access types! */ 782 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)) 783 { 784 DPRINT1("Generic access rights requested: 0x%lx\n", DesiredAccess); 785 Status = STATUS_GENERIC_NOT_MAPPED; 786 goto Cleanup; 787 } 788 789 /* Capture the security descriptor */ 790 Status = SeCaptureSecurityDescriptor(SecurityDescriptor, 791 UserMode, 792 PagedPool, 793 FALSE, 794 &CapturedSecurityDescriptor); 795 if (!NT_SUCCESS(Status)) 796 { 797 DPRINT1("Failed to capture security descriptor!\n"); 798 goto Cleanup; 799 } 800 801 /* Validate the Security descriptor */ 802 if ((SepGetOwnerFromDescriptor(CapturedSecurityDescriptor) == NULL) || 803 (SepGetGroupFromDescriptor(CapturedSecurityDescriptor) == NULL)) 804 { 805 Status = STATUS_INVALID_SECURITY_DESCR; 806 DPRINT1("Invalid security descriptor\n"); 807 goto Cleanup; 808 } 809 810 /* Probe and capture the subsystem name */ 811 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName, 812 UserMode, 813 SubsystemName); 814 if (!NT_SUCCESS(Status)) 815 { 816 DPRINT1("Failed to capture subsystem name!\n"); 817 goto Cleanup; 818 } 819 820 /* Probe and capture the object type name */ 821 Status = ProbeAndCaptureUnicodeString(&CapturedObjectTypeName, 822 UserMode, 823 ObjectTypeName); 824 if (!NT_SUCCESS(Status)) 825 { 826 DPRINT1("Failed to capture object type name!\n"); 827 goto Cleanup; 828 } 829 830 /* Probe and capture the object name */ 831 Status = ProbeAndCaptureUnicodeString(&CapturedObjectName, 832 UserMode, 833 ObjectName); 834 if (!NT_SUCCESS(Status)) 835 { 836 DPRINT1("Failed to capture object name!\n"); 837 goto Cleanup; 838 } 839 840 /* Check if we have a PrincipalSelfSid */ 841 if (PrincipalSelfSid != NULL) 842 { 843 /* Capture it */ 844 Status = SepCaptureSid(PrincipalSelfSid, 845 UserMode, 846 PagedPool, 847 FALSE, 848 &CapturedPrincipalSelfSid); 849 if (!NT_SUCCESS(Status)) 850 { 851 DPRINT1("Failed to capture PrincipalSelfSid!\n"); 852 goto Cleanup; 853 } 854 } 855 856 /* Capture the object type list */ 857 Status = SeCaptureObjectTypeList(ObjectTypeList, 858 ObjectTypeListLength, 859 UserMode, 860 &CapturedObjectTypeList); 861 if (!NT_SUCCESS(Status)) 862 { 863 DPRINT1("Failed to capture object type list!\n"); 864 goto Cleanup; 865 } 866 867 /* Call the worker routine with the captured buffers */ 868 Status = SepAccessCheckAndAuditAlarmWorker(&CapturedSubsystemName, 869 HandleId, 870 &SubjectContext, 871 &CapturedObjectTypeName, 872 &CapturedObjectName, 873 CapturedSecurityDescriptor, 874 CapturedPrincipalSelfSid, 875 DesiredAccess, 876 AuditType, 877 HaveAuditPrivilege, 878 CapturedObjectTypeList, 879 ObjectTypeListLength, 880 &LocalGenericMapping, 881 SafeGrantedAccessList, 882 SafeAccessStatusList, 883 &LocalGenerateOnClose, 884 UseResultList); 885 if (!NT_SUCCESS(Status)) 886 goto Cleanup; 887 888 /* Enter SEH to copy the data back to user mode */ 889 _SEH2_TRY 890 { 891 /* Loop all result entries (only 1 when no list was requested) */ 892 ASSERT(UseResultList || (ResultListLength == 1)); 893 for (i = 0; i < ResultListLength; i++) 894 { 895 AccessStatusList[i] = SafeAccessStatusList[i]; 896 GrantedAccessList[i] = SafeGrantedAccessList[i]; 897 } 898 899 *GenerateOnClose = LocalGenerateOnClose; 900 } 901 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 902 { 903 Status = _SEH2_GetExceptionCode(); 904 DPRINT1("Exception while copying back data: 0x%lx\n", Status); 905 } 906 _SEH2_END; 907 908 Cleanup: 909 910 if (CapturedObjectTypeList != NULL) 911 SeReleaseObjectTypeList(CapturedObjectTypeList, UserMode); 912 913 if (CapturedPrincipalSelfSid != NULL) 914 SepReleaseSid(CapturedPrincipalSelfSid, UserMode, FALSE); 915 916 if (CapturedObjectName.Buffer != NULL) 917 ReleaseCapturedUnicodeString(&CapturedObjectName, UserMode); 918 919 if (CapturedObjectTypeName.Buffer != NULL) 920 ReleaseCapturedUnicodeString(&CapturedObjectTypeName, UserMode); 921 922 if (CapturedSubsystemName.Buffer != NULL) 923 ReleaseCapturedUnicodeString(&CapturedSubsystemName, UserMode); 924 925 if (CapturedSecurityDescriptor != NULL) 926 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor, UserMode, FALSE); 927 928 if (ClientToken != NULL) 929 { 930 ObDereferenceObject(ClientToken); 931 SubjectContext.ClientToken = SubjectContextToken; 932 } 933 934 if (AllocatedResultLists) 935 ExFreePoolWithTag(SafeGrantedAccessList, TAG_SEPA); 936 937 /* Release the security subject context */ 938 SeReleaseSubjectContext(&SubjectContext); 939 940 return Status; 941 } 942 943 944 /* PUBLIC FUNCTIONS ***********************************************************/ 945 946 /** 947 * @unimplemented 948 * @brief 949 * Performs an audit against a hard link creation. 950 * 951 * @param[in] FileName 952 * A Unicode string that points to the name of the file. 953 * 954 * @param[in] LinkName 955 * A Unicode string that points to a link. 956 * 957 * @param[out] bSuccess 958 * If TRUE, the function has successfully audited 959 * the hard link and security access can be granted, 960 * FALSE otherwise. 961 * 962 * @return 963 * Nothing. 964 */ 965 VOID 966 NTAPI 967 SeAuditHardLinkCreation( 968 _In_ PUNICODE_STRING FileName, 969 _In_ PUNICODE_STRING LinkName, 970 _In_ BOOLEAN bSuccess) 971 { 972 UNIMPLEMENTED; 973 } 974 975 /** 976 * @unimplemented 977 * @brief 978 * Determines whether auditing against file events is being 979 * done or not. 980 * 981 * @param[in] AccessGranted 982 * If set to TRUE, the access attempt is deemed as successful 983 * otherwise set it to FALSE. 984 * 985 * @param[in] SecurityDescriptor 986 * A security descriptor. 987 * 988 * @return 989 * Returns TRUE if auditing is being currently done, FALSE otherwise. 990 */ 991 BOOLEAN 992 NTAPI 993 SeAuditingFileEvents( 994 _In_ BOOLEAN AccessGranted, 995 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor) 996 { 997 UNIMPLEMENTED; 998 return FALSE; 999 } 1000 1001 /** 1002 * @unimplemented 1003 * @brief 1004 * Determines whether auditing against file events with subject context 1005 * is being done or not. 1006 * 1007 * @param[in] AccessGranted 1008 * If set to TRUE, the access attempt is deemed as successful 1009 * otherwise set it to FALSE. 1010 * 1011 * @param[in] SecurityDescriptor 1012 * A security descriptor. 1013 * 1014 * @param[in] SubjectSecurityContext 1015 * If specified, the function will check if security auditing is currently 1016 * being done with this context. 1017 * 1018 * @return 1019 * Returns TRUE if auditing is being currently done, FALSE otherwise. 1020 */ 1021 BOOLEAN 1022 NTAPI 1023 SeAuditingFileEventsWithContext( 1024 _In_ BOOLEAN AccessGranted, 1025 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 1026 _In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext) 1027 { 1028 UNIMPLEMENTED_ONCE; 1029 return FALSE; 1030 } 1031 1032 /** 1033 * @unimplemented 1034 * @brief 1035 * Determines whether auditing against hard links events is being 1036 * done or not. 1037 * 1038 * @param[in] AccessGranted 1039 * If set to TRUE, the access attempt is deemed as successful 1040 * otherwise set it to FALSE. 1041 * 1042 * @param[in] SecurityDescriptor 1043 * A security descriptor. 1044 * 1045 * @return 1046 * Returns TRUE if auditing is being currently done, FALSE otherwise. 1047 */ 1048 BOOLEAN 1049 NTAPI 1050 SeAuditingHardLinkEvents( 1051 _In_ BOOLEAN AccessGranted, 1052 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor) 1053 { 1054 UNIMPLEMENTED; 1055 return FALSE; 1056 } 1057 1058 /** 1059 * @unimplemented 1060 * @brief 1061 * Determines whether auditing against hard links events with subject context 1062 * is being done or not. 1063 * 1064 * @param[in] AccessGranted 1065 * If set to TRUE, the access attempt is deemed as successful 1066 * otherwise set it to FALSE. 1067 * 1068 * @param[in] SecurityDescriptor 1069 * A security descriptor. 1070 * 1071 * @param[in] SubjectSecurityContext 1072 * If specified, the function will check if security auditing is currently 1073 * being done with this context. 1074 * 1075 * @return 1076 * Returns TRUE if auditing is being currently done, FALSE otherwise. 1077 */ 1078 BOOLEAN 1079 NTAPI 1080 SeAuditingHardLinkEventsWithContext( 1081 _In_ BOOLEAN AccessGranted, 1082 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 1083 _In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext) 1084 { 1085 UNIMPLEMENTED; 1086 return FALSE; 1087 } 1088 1089 /** 1090 * @unimplemented 1091 * @brief 1092 * Determines whether auditing against files or global events with 1093 * subject context is being done or not. 1094 * 1095 * @param[in] AccessGranted 1096 * If set to TRUE, the access attempt is deemed as successful 1097 * otherwise set it to FALSE. 1098 * 1099 * @param[in] SecurityDescriptor 1100 * A security descriptor. 1101 * 1102 * @param[in] SubjectSecurityContext 1103 * If specified, the function will check if security auditing is currently 1104 * being done with this context. 1105 * 1106 * @return 1107 * Returns TRUE if auditing is being currently done, FALSE otherwise. 1108 */ 1109 BOOLEAN 1110 NTAPI 1111 SeAuditingFileOrGlobalEvents( 1112 _In_ BOOLEAN AccessGranted, 1113 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 1114 _In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext) 1115 { 1116 UNIMPLEMENTED; 1117 return FALSE; 1118 } 1119 1120 /** 1121 * @unimplemented 1122 * @brief 1123 * Closes an alarm audit of an object. 1124 * 1125 * @param[in] Object 1126 * An arbitrary pointer data that points to the object. 1127 * 1128 * @param[in] Handle 1129 * A handle of the said object. 1130 * 1131 * @param[in] PerformAction 1132 * Set this to TRUE to perform any auxiliary action, otherwise 1133 * set to FALSE. 1134 * 1135 * @return 1136 * Nothing. 1137 */ 1138 VOID 1139 NTAPI 1140 SeCloseObjectAuditAlarm( 1141 _In_ PVOID Object, 1142 _In_ HANDLE Handle, 1143 _In_ BOOLEAN PerformAction) 1144 { 1145 UNIMPLEMENTED; 1146 } 1147 1148 /** 1149 * @unimplemented 1150 * @brief 1151 * Deletes an alarm audit of an object. 1152 * 1153 * @param[in] Object 1154 * An arbitrary pointer data that points to the object. 1155 * 1156 * @param[in] Handle 1157 * A handle of the said object. 1158 * 1159 * @return 1160 * Nothing. 1161 */ 1162 VOID NTAPI 1163 SeDeleteObjectAuditAlarm( 1164 _In_ PVOID Object, 1165 _In_ HANDLE Handle) 1166 { 1167 UNIMPLEMENTED; 1168 } 1169 1170 /** 1171 * @unimplemented 1172 * @brief 1173 * Creates an audit with alarm notification of an object 1174 * that is being opened. 1175 * 1176 * @param[in] ObjectTypeName 1177 * A Unicode string that points to the object type name. 1178 * 1179 * @param[in] Object 1180 * If specified, the function will use this parameter to 1181 * directly open the object. 1182 * 1183 * @param[in] AbsoluteObjectName 1184 * If specified, the function will use this parameter to 1185 * directly open the object through the absolute name 1186 * of the object. 1187 * 1188 * @param[in] SecurityDescriptor 1189 * A security descriptor. 1190 * 1191 * @param[in] AccessState 1192 * An access state right mask when opening the object. 1193 * 1194 * @param[in] ObjectCreated 1195 * Set this to TRUE if the object has been fully created, 1196 * FALSE otherwise. 1197 * 1198 * @param[in] AccessGranted 1199 * Set this to TRUE if access was deemed as granted. 1200 * 1201 * @param[in] AccessMode 1202 * Processor level access mode. 1203 * 1204 * @param[out] GenerateOnClose 1205 * A boolean flag returned to the caller once audit generation procedure 1206 * finishes. 1207 * 1208 * @return 1209 * Nothing. 1210 */ 1211 VOID 1212 NTAPI 1213 SeOpenObjectAuditAlarm( 1214 _In_ PUNICODE_STRING ObjectTypeName, 1215 _In_opt_ PVOID Object, 1216 _In_opt_ PUNICODE_STRING AbsoluteObjectName, 1217 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 1218 _In_ PACCESS_STATE AccessState, 1219 _In_ BOOLEAN ObjectCreated, 1220 _In_ BOOLEAN AccessGranted, 1221 _In_ KPROCESSOR_MODE AccessMode, 1222 _Out_ PBOOLEAN GenerateOnClose) 1223 { 1224 PAGED_CODE(); 1225 1226 /* Audits aren't done on kernel-mode access */ 1227 if (AccessMode == KernelMode) return; 1228 1229 /* Otherwise, unimplemented! */ 1230 //UNIMPLEMENTED; 1231 return; 1232 } 1233 1234 /** 1235 * @unimplemented 1236 * @brief 1237 * Creates an audit with alarm notification of an object 1238 * that is being opened for deletion. 1239 * 1240 * @param[in] ObjectTypeName 1241 * A Unicode string that points to the object type name. 1242 * 1243 * @param[in] Object 1244 * If specified, the function will use this parameter to 1245 * directly open the object. 1246 * 1247 * @param[in] AbsoluteObjectName 1248 * If specified, the function will use this parameter to 1249 * directly open the object through the absolute name 1250 * of the object. 1251 * 1252 * @param[in] SecurityDescriptor 1253 * A security descriptor. 1254 * 1255 * @param[in] AccessState 1256 * An access state right mask when opening the object. 1257 * 1258 * @param[in] ObjectCreated 1259 * Set this to TRUE if the object has been fully created, 1260 * FALSE otherwise. 1261 * 1262 * @param[in] AccessGranted 1263 * Set this to TRUE if access was deemed as granted. 1264 * 1265 * @param[in] AccessMode 1266 * Processor level access mode. 1267 * 1268 * @param[out] GenerateOnClose 1269 * A boolean flag returned to the caller once audit generation procedure 1270 * finishes. 1271 * 1272 * @return 1273 * Nothing. 1274 */ 1275 VOID NTAPI 1276 SeOpenObjectForDeleteAuditAlarm( 1277 _In_ PUNICODE_STRING ObjectTypeName, 1278 _In_opt_ PVOID Object, 1279 _In_opt_ PUNICODE_STRING AbsoluteObjectName, 1280 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 1281 _In_ PACCESS_STATE AccessState, 1282 _In_ BOOLEAN ObjectCreated, 1283 _In_ BOOLEAN AccessGranted, 1284 _In_ KPROCESSOR_MODE AccessMode, 1285 _Out_ PBOOLEAN GenerateOnClose) 1286 { 1287 UNIMPLEMENTED; 1288 } 1289 1290 /** 1291 * @unimplemented 1292 * @brief 1293 * Raises an audit with alarm notification message 1294 * when an object tries to acquire this privilege. 1295 * 1296 * @param[in] Handle 1297 * A handle to an object. 1298 * 1299 * @param[in] SubjectContext 1300 * The security subject context for auditing. 1301 * 1302 * @param[in] DesiredAccess 1303 * The desired right access masks requested by the caller. 1304 * 1305 * @param[in] Privileges 1306 * An array set of privileges for auditing. 1307 * 1308 * @param[out] AccessGranted 1309 * When the auditing procedure routine ends, it returns TRUE to the 1310 * caller if the object has the required privileges for access, 1311 * FALSE otherwise. 1312 * 1313 * @param[in] CurrentMode 1314 * Processor level access mode. 1315 * 1316 * @return 1317 * Nothing. 1318 */ 1319 VOID 1320 NTAPI 1321 SePrivilegeObjectAuditAlarm( 1322 _In_ HANDLE Handle, 1323 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 1324 _In_ ACCESS_MASK DesiredAccess, 1325 _In_ PPRIVILEGE_SET Privileges, 1326 _In_ BOOLEAN AccessGranted, 1327 _In_ KPROCESSOR_MODE CurrentMode) 1328 { 1329 UNIMPLEMENTED; 1330 } 1331 1332 /* SYSTEM CALLS ***************************************************************/ 1333 1334 /** 1335 * @brief 1336 * Raises an alarm audit message when an object is about 1337 * to be closed. 1338 * 1339 * @param[in] SubsystemName 1340 * A Unicode string that points to the name of the subsystem. 1341 * 1342 * @param[in] HandleId 1343 * A handle of an ID used for identification instance for auditing. 1344 * 1345 * @param[in] GenerateOnClose 1346 * A boolean value previously created by the "open" equivalent of this 1347 * function. If the caller explicitly sets this to FALSE, the function 1348 * assumes that the object is not opened. 1349 * 1350 * @return 1351 * Returns STATUS_SUCCESS if all the operations have completed successfully. 1352 * STATUS_PRIVILEGE_NOT_HELD is returned if the security subject context 1353 * does not have the audit privilege to actually begin auditing procedures 1354 * in the first place. 1355 */ 1356 NTSTATUS 1357 NTAPI 1358 NtCloseObjectAuditAlarm( 1359 _In_ PUNICODE_STRING SubsystemName, 1360 _In_ PVOID HandleId, 1361 _In_ BOOLEAN GenerateOnClose) 1362 { 1363 SECURITY_SUBJECT_CONTEXT SubjectContext; 1364 UNICODE_STRING CapturedSubsystemName; 1365 KPROCESSOR_MODE PreviousMode; 1366 BOOLEAN UseImpersonationToken; 1367 PETHREAD CurrentThread; 1368 BOOLEAN CopyOnOpen, EffectiveOnly; 1369 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; 1370 NTSTATUS Status; 1371 PTOKEN Token; 1372 PAGED_CODE(); 1373 1374 /* Get the previous mode (only user mode is supported!) */ 1375 PreviousMode = ExGetPreviousMode(); 1376 ASSERT(PreviousMode != KernelMode); 1377 1378 /* Do we even need to do anything? */ 1379 if (!GenerateOnClose) 1380 { 1381 /* Nothing to do, return success */ 1382 return STATUS_SUCCESS; 1383 } 1384 1385 /* Capture the security subject context */ 1386 SeCaptureSubjectContext(&SubjectContext); 1387 1388 /* Check for audit privilege */ 1389 if (!SeCheckAuditPrivilege(&SubjectContext, PreviousMode)) 1390 { 1391 DPRINT1("Caller does not have SeAuditPrivilege\n"); 1392 Status = STATUS_PRIVILEGE_NOT_HELD; 1393 goto Cleanup; 1394 } 1395 1396 /* Probe and capture the subsystem name */ 1397 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName, 1398 PreviousMode, 1399 SubsystemName); 1400 if (!NT_SUCCESS(Status)) 1401 { 1402 DPRINT1("Failed to capture subsystem name!\n"); 1403 goto Cleanup; 1404 } 1405 1406 /* Get the current thread and check if it's impersonating */ 1407 CurrentThread = PsGetCurrentThread(); 1408 if (PsIsThreadImpersonating(CurrentThread)) 1409 { 1410 /* Get the impersonation token */ 1411 Token = PsReferenceImpersonationToken(CurrentThread, 1412 &CopyOnOpen, 1413 &EffectiveOnly, 1414 &ImpersonationLevel); 1415 UseImpersonationToken = TRUE; 1416 } 1417 else 1418 { 1419 /* Get the primary token */ 1420 Token = PsReferencePrimaryToken(PsGetCurrentProcess()); 1421 UseImpersonationToken = FALSE; 1422 } 1423 1424 /* Call the internal function */ 1425 SepAdtCloseObjectAuditAlarm(&CapturedSubsystemName, 1426 HandleId, 1427 Token->UserAndGroups->Sid); 1428 1429 /* Release the captured subsystem name */ 1430 ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode); 1431 1432 /* Check what token we used */ 1433 if (UseImpersonationToken) 1434 { 1435 /* Release impersonation token */ 1436 PsDereferenceImpersonationToken(Token); 1437 } 1438 else 1439 { 1440 /* Release primary token */ 1441 PsDereferencePrimaryToken(Token); 1442 } 1443 1444 Status = STATUS_SUCCESS; 1445 1446 Cleanup: 1447 1448 /* Release the security subject context */ 1449 SeReleaseSubjectContext(&SubjectContext); 1450 1451 return Status; 1452 } 1453 1454 /** 1455 * @unimplemented 1456 * @brief 1457 * Raises an alarm audit message when an object is about 1458 * to be deleted. 1459 * 1460 * @param[in] SubsystemName 1461 * A Unicode string that points to the name of the subsystem. 1462 * 1463 * @param[in] HandleId 1464 * A handle of an ID used for identification instance for auditing. 1465 * 1466 * @param[in] GenerateOnClose 1467 * A boolean value previously created by the "open" equivalent of this 1468 * function. If the caller explicitly sets this to FALSE, the function 1469 * assumes that the object is not opened. 1470 * 1471 * @return 1472 * To be added... 1473 */ 1474 NTSTATUS NTAPI 1475 NtDeleteObjectAuditAlarm( 1476 _In_ PUNICODE_STRING SubsystemName, 1477 _In_ PVOID HandleId, 1478 _In_ BOOLEAN GenerateOnClose) 1479 { 1480 UNIMPLEMENTED; 1481 return STATUS_NOT_IMPLEMENTED; 1482 } 1483 1484 /** 1485 * @unimplemented 1486 * @brief 1487 * Raises an alarm audit message when an object is about 1488 * to be opened. 1489 * 1490 * @param[in] SubjectContext 1491 * A security subject context for auditing. 1492 * 1493 * @param[in] SubsystemName 1494 * A Unicode string that points to a name of the subsystem. 1495 * 1496 * @param[in] HandleId 1497 * A handle to an ID used for identification instance for auditing. 1498 * 1499 * @param[in] ObjectTypeName 1500 * A Unicode string that points to an object type name. 1501 * 1502 * @param[in] ObjectName 1503 * The name of the object. 1504 * 1505 * @param[in] SecurityDescriptor 1506 * A security descriptor. 1507 * 1508 * @param[in] ClientToken 1509 * A client access token, representing the client we want to impersonate. 1510 * 1511 * @param[in] DesiredAccess 1512 * The desired access rights masks requested by the caller. 1513 * 1514 * @param[in] GrantedAccess 1515 * The granted access mask rights. 1516 * 1517 * @param[in] Privileges 1518 * If specified, the function will use this set of privileges to audit. 1519 * 1520 * @param[in] ObjectCreation 1521 * Set this to TRUE if the object has just been created. 1522 * 1523 * @param[in] AccessGranted 1524 * Set this to TRUE if the access attempt was deemed as granted. 1525 * 1526 * @param[out] GenerateOnClose 1527 * A boolean flag returned to the caller once audit generation procedure 1528 * finishes. 1529 * 1530 * @return 1531 * Nothing. 1532 */ 1533 VOID 1534 NTAPI 1535 SepOpenObjectAuditAlarm( 1536 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 1537 _In_ PUNICODE_STRING SubsystemName, 1538 _In_opt_ PVOID HandleId, 1539 _In_ PUNICODE_STRING ObjectTypeName, 1540 _In_ PUNICODE_STRING ObjectName, 1541 _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor, 1542 _In_ PTOKEN ClientToken, 1543 _In_ ACCESS_MASK DesiredAccess, 1544 _In_ ACCESS_MASK GrantedAccess, 1545 _In_opt_ PPRIVILEGE_SET Privileges, 1546 _In_ BOOLEAN ObjectCreation, 1547 _In_ BOOLEAN AccessGranted, 1548 _Out_ PBOOLEAN GenerateOnClose) 1549 { 1550 DBG_UNREFERENCED_PARAMETER(SubjectContext); 1551 DBG_UNREFERENCED_PARAMETER(SubsystemName); 1552 DBG_UNREFERENCED_PARAMETER(HandleId); 1553 DBG_UNREFERENCED_PARAMETER(ObjectTypeName); 1554 DBG_UNREFERENCED_PARAMETER(ObjectName); 1555 DBG_UNREFERENCED_PARAMETER(SecurityDescriptor); 1556 DBG_UNREFERENCED_PARAMETER(ClientToken); 1557 DBG_UNREFERENCED_PARAMETER(DesiredAccess); 1558 DBG_UNREFERENCED_PARAMETER(GrantedAccess); 1559 DBG_UNREFERENCED_PARAMETER(Privileges); 1560 DBG_UNREFERENCED_PARAMETER(ObjectCreation); 1561 DBG_UNREFERENCED_PARAMETER(AccessGranted); 1562 UNIMPLEMENTED; 1563 *GenerateOnClose = FALSE; 1564 } 1565 1566 /** 1567 * @brief 1568 * Raises an alarm audit message when an object is about 1569 * to be opened. 1570 * 1571 * @param[in] SubsystemName 1572 * A Unicode string that points to a name of the subsystem. 1573 * 1574 * @param[in] HandleId 1575 * A handle to an ID used for identification instance for auditing. 1576 * 1577 * @param[in] ObjectTypeName 1578 * A Unicode string that points to an object type name. 1579 * 1580 * @param[in] ObjectName 1581 * The name of the object. 1582 * 1583 * @param[in] SecurityDescriptor 1584 * A security descriptor. 1585 * 1586 * @param[in] ClientTokenHandle 1587 * A handle to a client access token. 1588 * 1589 * @param[in] DesiredAccess 1590 * The desired access rights masks requested by the caller. 1591 * 1592 * @param[in] GrantedAccess 1593 * The granted access mask rights. 1594 * 1595 * @param[in] PrivilegeSet 1596 * If specified, the function will use this set of privileges to audit. 1597 * 1598 * @param[in] ObjectCreation 1599 * Set this to TRUE if the object has just been created. 1600 * 1601 * @param[in] AccessGranted 1602 * Set this to TRUE if the access attempt was deemed as granted. 1603 * 1604 * @param[out] GenerateOnClose 1605 * A boolean flag returned to the caller once audit generation procedure 1606 * finishes. 1607 * 1608 * @return 1609 * Returns STATUS_SUCCESS if all the operations have been completed successfully. 1610 * STATUS_PRIVILEGE_NOT_HELD is returned if the given subject context does not 1611 * hold the required audit privilege to actually begin auditing in the first place. 1612 * STATUS_BAD_IMPERSONATION_LEVEL is returned if the security impersonation level 1613 * of the client token is not on par with the impersonation level that alllows 1614 * impersonation. STATUS_INVALID_PARAMETER is returned if the caller has 1615 * submitted a bogus set of privileges as such array set exceeds the maximum 1616 * count of privileges that the kernel can accept. A failure NTSTATUS code 1617 * is returned otherwise. 1618 */ 1619 __kernel_entry 1620 NTSTATUS 1621 NTAPI 1622 NtOpenObjectAuditAlarm( 1623 _In_ PUNICODE_STRING SubsystemName, 1624 _In_opt_ PVOID HandleId, 1625 _In_ PUNICODE_STRING ObjectTypeName, 1626 _In_ PUNICODE_STRING ObjectName, 1627 _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor, 1628 _In_ HANDLE ClientTokenHandle, 1629 _In_ ACCESS_MASK DesiredAccess, 1630 _In_ ACCESS_MASK GrantedAccess, 1631 _In_opt_ PPRIVILEGE_SET PrivilegeSet, 1632 _In_ BOOLEAN ObjectCreation, 1633 _In_ BOOLEAN AccessGranted, 1634 _Out_ PBOOLEAN GenerateOnClose) 1635 { 1636 PTOKEN ClientToken; 1637 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor; 1638 UNICODE_STRING CapturedSubsystemName, CapturedObjectTypeName, CapturedObjectName; 1639 ULONG PrivilegeCount, PrivilegeSetSize; 1640 volatile PPRIVILEGE_SET CapturedPrivilegeSet; 1641 BOOLEAN LocalGenerateOnClose; 1642 PVOID CapturedHandleId; 1643 SECURITY_SUBJECT_CONTEXT SubjectContext; 1644 NTSTATUS Status; 1645 PAGED_CODE(); 1646 1647 /* Only user mode is supported! */ 1648 ASSERT(ExGetPreviousMode() != KernelMode); 1649 1650 /* Start clean */ 1651 ClientToken = NULL; 1652 CapturedSecurityDescriptor = NULL; 1653 CapturedPrivilegeSet = NULL; 1654 CapturedSubsystemName.Buffer = NULL; 1655 CapturedObjectTypeName.Buffer = NULL; 1656 CapturedObjectName.Buffer = NULL; 1657 1658 /* Reference the client token */ 1659 Status = ObReferenceObjectByHandle(ClientTokenHandle, 1660 TOKEN_QUERY, 1661 SeTokenObjectType, 1662 UserMode, 1663 (PVOID*)&ClientToken, 1664 NULL); 1665 if (!NT_SUCCESS(Status)) 1666 { 1667 DPRINT1("Failed to reference token handle %p: %lx\n", 1668 ClientTokenHandle, Status); 1669 return Status; 1670 } 1671 1672 /* Capture the security subject context */ 1673 SeCaptureSubjectContext(&SubjectContext); 1674 1675 /* Validate the token's impersonation level */ 1676 if ((ClientToken->TokenType == TokenImpersonation) && 1677 (ClientToken->ImpersonationLevel < SecurityIdentification)) 1678 { 1679 DPRINT1("Invalid impersonation level (%u)\n", ClientToken->ImpersonationLevel); 1680 Status = STATUS_BAD_IMPERSONATION_LEVEL; 1681 goto Cleanup; 1682 } 1683 1684 /* Check for audit privilege */ 1685 if (!SeCheckAuditPrivilege(&SubjectContext, UserMode)) 1686 { 1687 DPRINT1("Caller does not have SeAuditPrivilege\n"); 1688 Status = STATUS_PRIVILEGE_NOT_HELD; 1689 goto Cleanup; 1690 } 1691 1692 /* Check for NULL SecurityDescriptor */ 1693 if (SecurityDescriptor == NULL) 1694 { 1695 /* Nothing to do */ 1696 Status = STATUS_SUCCESS; 1697 goto Cleanup; 1698 } 1699 1700 /* Capture the security descriptor */ 1701 Status = SeCaptureSecurityDescriptor(SecurityDescriptor, 1702 UserMode, 1703 PagedPool, 1704 FALSE, 1705 &CapturedSecurityDescriptor); 1706 if (!NT_SUCCESS(Status)) 1707 { 1708 DPRINT1("Failed to capture security descriptor!\n"); 1709 goto Cleanup; 1710 } 1711 1712 _SEH2_TRY 1713 { 1714 /* Check if we have a privilege set */ 1715 if (PrivilegeSet != NULL) 1716 { 1717 /* Probe the basic privilege set structure */ 1718 ProbeForRead(PrivilegeSet, sizeof(PRIVILEGE_SET), sizeof(ULONG)); 1719 1720 /* Validate privilege count */ 1721 PrivilegeCount = PrivilegeSet->PrivilegeCount; 1722 if (PrivilegeCount > SEP_PRIVILEGE_SET_MAX_COUNT) 1723 { 1724 Status = STATUS_INVALID_PARAMETER; 1725 _SEH2_YIELD(goto Cleanup); 1726 } 1727 1728 /* Calculate the size of the PrivilegeSet structure */ 1729 PrivilegeSetSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]); 1730 1731 /* Probe the whole structure */ 1732 ProbeForRead(PrivilegeSet, PrivilegeSetSize, sizeof(ULONG)); 1733 1734 /* Allocate a temp buffer */ 1735 CapturedPrivilegeSet = ExAllocatePoolWithTag(PagedPool, 1736 PrivilegeSetSize, 1737 TAG_PRIVILEGE_SET); 1738 if (CapturedPrivilegeSet == NULL) 1739 { 1740 DPRINT1("Failed to allocate %u bytes\n", PrivilegeSetSize); 1741 Status = STATUS_INSUFFICIENT_RESOURCES; 1742 _SEH2_YIELD(goto Cleanup); 1743 } 1744 1745 /* Copy the privileges */ 1746 RtlCopyMemory(CapturedPrivilegeSet, PrivilegeSet, PrivilegeSetSize); 1747 } 1748 1749 if (HandleId != NULL) 1750 { 1751 ProbeForRead(HandleId, sizeof(PVOID), sizeof(PVOID)); 1752 CapturedHandleId = *(PVOID*)HandleId; 1753 } 1754 1755 ProbeForWrite(GenerateOnClose, sizeof(BOOLEAN), sizeof(BOOLEAN)); 1756 } 1757 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1758 { 1759 Status = _SEH2_GetExceptionCode(); 1760 DPRINT1("Exception while probing parameters: 0x%lx\n", Status); 1761 _SEH2_YIELD(goto Cleanup); 1762 } 1763 _SEH2_END; 1764 1765 /* Probe and capture the subsystem name */ 1766 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName, 1767 UserMode, 1768 SubsystemName); 1769 if (!NT_SUCCESS(Status)) 1770 { 1771 DPRINT1("Failed to capture subsystem name!\n"); 1772 goto Cleanup; 1773 } 1774 1775 /* Probe and capture the object type name */ 1776 Status = ProbeAndCaptureUnicodeString(&CapturedObjectTypeName, 1777 UserMode, 1778 ObjectTypeName); 1779 if (!NT_SUCCESS(Status)) 1780 { 1781 DPRINT1("Failed to capture object type name!\n"); 1782 goto Cleanup; 1783 } 1784 1785 /* Probe and capture the object name */ 1786 Status = ProbeAndCaptureUnicodeString(&CapturedObjectName, 1787 UserMode, 1788 ObjectName); 1789 if (!NT_SUCCESS(Status)) 1790 { 1791 DPRINT1("Failed to capture object name!\n"); 1792 goto Cleanup; 1793 } 1794 1795 /* Call the internal function */ 1796 SepOpenObjectAuditAlarm(&SubjectContext, 1797 &CapturedSubsystemName, 1798 CapturedHandleId, 1799 &CapturedObjectTypeName, 1800 &CapturedObjectName, 1801 CapturedSecurityDescriptor, 1802 ClientToken, 1803 DesiredAccess, 1804 GrantedAccess, 1805 CapturedPrivilegeSet, 1806 ObjectCreation, 1807 AccessGranted, 1808 &LocalGenerateOnClose); 1809 1810 Status = STATUS_SUCCESS; 1811 1812 /* Enter SEH to copy the data back to user mode */ 1813 _SEH2_TRY 1814 { 1815 *GenerateOnClose = LocalGenerateOnClose; 1816 } 1817 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1818 { 1819 Status = _SEH2_GetExceptionCode(); 1820 DPRINT1("Exception while copying back data: 0x%lx\n", Status); 1821 } 1822 _SEH2_END; 1823 1824 Cleanup: 1825 1826 if (CapturedObjectName.Buffer != NULL) 1827 ReleaseCapturedUnicodeString(&CapturedObjectName, UserMode); 1828 1829 if (CapturedObjectTypeName.Buffer != NULL) 1830 ReleaseCapturedUnicodeString(&CapturedObjectTypeName, UserMode); 1831 1832 if (CapturedSubsystemName.Buffer != NULL) 1833 ReleaseCapturedUnicodeString(&CapturedSubsystemName, UserMode); 1834 1835 if (CapturedSecurityDescriptor != NULL) 1836 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor, UserMode, FALSE); 1837 1838 if (CapturedPrivilegeSet != NULL) 1839 ExFreePoolWithTag(CapturedPrivilegeSet, TAG_PRIVILEGE_SET); 1840 1841 /* Release the security subject context */ 1842 SeReleaseSubjectContext(&SubjectContext); 1843 1844 ObDereferenceObject(ClientToken); 1845 1846 return Status; 1847 } 1848 1849 /** 1850 * @brief 1851 * Raises an alarm audit message when a caller attempts to request 1852 * a privileged service call. 1853 * 1854 * @param[in] SubsystemName 1855 * A Unicode string that points to a name of the subsystem. 1856 * 1857 * @param[in] ServiceName 1858 * A Unicode string that points to a name of the privileged service. 1859 * 1860 * @param[in] ClientTokenHandle 1861 * A handle to a client access token. 1862 * 1863 * @param[in] Privileges 1864 * An array set of privileges. 1865 * 1866 * @param[in] AccessGranted 1867 * Set this to TRUE if the access attempt was deemed as granted. 1868 * 1869 * @return 1870 * Returns STATUS_SUCCESS if all the operations have been completed successfully. 1871 * STATUS_PRIVILEGE_NOT_HELD is returned if the given subject context does not 1872 * hold the required audit privilege to actually begin auditing in the first place. 1873 * STATUS_BAD_IMPERSONATION_LEVEL is returned if the security impersonation level 1874 * of the client token is not on par with the impersonation level that alllows 1875 * impersonation. STATUS_INVALID_PARAMETER is returned if the caller has 1876 * submitted a bogus set of privileges as such array set exceeds the maximum 1877 * count of privileges that the kernel can accept. A failure NTSTATUS code 1878 * is returned otherwise. 1879 */ 1880 __kernel_entry 1881 NTSTATUS 1882 NTAPI 1883 NtPrivilegedServiceAuditAlarm( 1884 _In_opt_ PUNICODE_STRING SubsystemName, 1885 _In_opt_ PUNICODE_STRING ServiceName, 1886 _In_ HANDLE ClientTokenHandle, 1887 _In_ PPRIVILEGE_SET Privileges, 1888 _In_ BOOLEAN AccessGranted) 1889 { 1890 KPROCESSOR_MODE PreviousMode; 1891 PTOKEN ClientToken; 1892 volatile PPRIVILEGE_SET CapturedPrivileges = NULL; 1893 UNICODE_STRING CapturedSubsystemName; 1894 UNICODE_STRING CapturedServiceName; 1895 ULONG PrivilegeCount, PrivilegesSize; 1896 SECURITY_SUBJECT_CONTEXT SubjectContext; 1897 NTSTATUS Status; 1898 PAGED_CODE(); 1899 1900 /* Get the previous mode (only user mode is supported!) */ 1901 PreviousMode = ExGetPreviousMode(); 1902 ASSERT(PreviousMode != KernelMode); 1903 1904 CapturedSubsystemName.Buffer = NULL; 1905 CapturedServiceName.Buffer = NULL; 1906 1907 /* Reference the client token */ 1908 Status = ObReferenceObjectByHandle(ClientTokenHandle, 1909 TOKEN_QUERY, 1910 SeTokenObjectType, 1911 PreviousMode, 1912 (PVOID*)&ClientToken, 1913 NULL); 1914 if (!NT_SUCCESS(Status)) 1915 { 1916 DPRINT1("Failed to reference client token: 0x%lx\n", Status); 1917 return Status; 1918 } 1919 1920 /* Validate the token's impersonation level */ 1921 if ((ClientToken->TokenType == TokenImpersonation) && 1922 (ClientToken->ImpersonationLevel < SecurityIdentification)) 1923 { 1924 DPRINT1("Invalid impersonation level (%u)\n", ClientToken->ImpersonationLevel); 1925 ObDereferenceObject(ClientToken); 1926 return STATUS_BAD_IMPERSONATION_LEVEL; 1927 } 1928 1929 /* Capture the security subject context */ 1930 SeCaptureSubjectContext(&SubjectContext); 1931 1932 /* Check for audit privilege */ 1933 if (!SeCheckAuditPrivilege(&SubjectContext, PreviousMode)) 1934 { 1935 DPRINT1("Caller does not have SeAuditPrivilege\n"); 1936 Status = STATUS_PRIVILEGE_NOT_HELD; 1937 goto Cleanup; 1938 } 1939 1940 /* Do we have a subsystem name? */ 1941 if (SubsystemName != NULL) 1942 { 1943 /* Probe and capture the subsystem name */ 1944 Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName, 1945 PreviousMode, 1946 SubsystemName); 1947 if (!NT_SUCCESS(Status)) 1948 { 1949 DPRINT1("Failed to capture subsystem name!\n"); 1950 goto Cleanup; 1951 } 1952 } 1953 1954 /* Do we have a service name? */ 1955 if (ServiceName != NULL) 1956 { 1957 /* Probe and capture the service name */ 1958 Status = ProbeAndCaptureUnicodeString(&CapturedServiceName, 1959 PreviousMode, 1960 ServiceName); 1961 if (!NT_SUCCESS(Status)) 1962 { 1963 DPRINT1("Failed to capture service name!\n"); 1964 goto Cleanup; 1965 } 1966 } 1967 1968 _SEH2_TRY 1969 { 1970 /* Probe the basic privilege set structure */ 1971 ProbeForRead(Privileges, sizeof(PRIVILEGE_SET), sizeof(ULONG)); 1972 1973 /* Validate privilege count */ 1974 PrivilegeCount = Privileges->PrivilegeCount; 1975 if (PrivilegeCount > SEP_PRIVILEGE_SET_MAX_COUNT) 1976 { 1977 Status = STATUS_INVALID_PARAMETER; 1978 _SEH2_YIELD(goto Cleanup); 1979 } 1980 1981 /* Calculate the size of the Privileges structure */ 1982 PrivilegesSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]); 1983 1984 /* Probe the whole structure */ 1985 ProbeForRead(Privileges, PrivilegesSize, sizeof(ULONG)); 1986 1987 /* Allocate a temp buffer */ 1988 CapturedPrivileges = ExAllocatePoolWithTag(PagedPool, 1989 PrivilegesSize, 1990 TAG_PRIVILEGE_SET); 1991 if (CapturedPrivileges == NULL) 1992 { 1993 DPRINT1("Failed to allocate %u bytes\n", PrivilegesSize); 1994 Status = STATUS_INSUFFICIENT_RESOURCES; 1995 _SEH2_YIELD(goto Cleanup); 1996 } 1997 1998 /* Copy the privileges */ 1999 RtlCopyMemory(CapturedPrivileges, Privileges, PrivilegesSize); 2000 } 2001 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2002 { 2003 Status = _SEH2_GetExceptionCode(); 2004 DPRINT1("Got exception 0x%lx\n", Status); 2005 _SEH2_YIELD(goto Cleanup); 2006 } 2007 _SEH2_END; 2008 2009 /* Call the internal function */ 2010 SepAdtPrivilegedServiceAuditAlarm(&SubjectContext, 2011 SubsystemName ? &CapturedSubsystemName : NULL, 2012 ServiceName ? &CapturedServiceName : NULL, 2013 ClientToken, 2014 SubjectContext.PrimaryToken, 2015 CapturedPrivileges, 2016 AccessGranted); 2017 2018 Status = STATUS_SUCCESS; 2019 2020 Cleanup: 2021 /* Cleanup resources */ 2022 if (CapturedSubsystemName.Buffer != NULL) 2023 ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode); 2024 2025 if (CapturedServiceName.Buffer != NULL) 2026 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 2027 2028 if (CapturedPrivileges != NULL) 2029 ExFreePoolWithTag(CapturedPrivileges, TAG_PRIVILEGE_SET); 2030 2031 /* Release the security subject context */ 2032 SeReleaseSubjectContext(&SubjectContext); 2033 2034 ObDereferenceObject(ClientToken); 2035 2036 return Status; 2037 } 2038 2039 /** 2040 * @brief 2041 * Raises an alarm audit message when a caller attempts to access a 2042 * privileged object. 2043 * 2044 * @param[in] SubsystemName 2045 * A Unicode string that points to a name of the subsystem. 2046 * 2047 * @param[in] HandleId 2048 * A handle to an ID that is used as identification instance for auditing. 2049 * 2050 * @param[in] ClientToken 2051 * A handle to a client access token. 2052 * 2053 * @param[in] DesiredAccess 2054 * A handle to a client access token. 2055 * 2056 * @param[in] Privileges 2057 * An array set of privileges. 2058 * 2059 * @param[in] AccessGranted 2060 * Set this to TRUE if the access attempt was deemed as granted. 2061 * 2062 * @return 2063 * To be added... 2064 */ 2065 NTSTATUS NTAPI 2066 NtPrivilegeObjectAuditAlarm( 2067 _In_ PUNICODE_STRING SubsystemName, 2068 _In_ PVOID HandleId, 2069 _In_ HANDLE ClientToken, 2070 _In_ ULONG DesiredAccess, 2071 _In_ PPRIVILEGE_SET Privileges, 2072 _In_ BOOLEAN AccessGranted) 2073 { 2074 UNIMPLEMENTED; 2075 return STATUS_NOT_IMPLEMENTED; 2076 } 2077 2078 /** 2079 * @brief 2080 * Raises an alarm audit message when a caller attempts to access an 2081 * object and determine if the access can be made. 2082 * 2083 * @param[in] SubsystemName 2084 * A Unicode string that points to a name of the subsystem. 2085 * 2086 * @param[in] HandleId 2087 * A handle to an ID that is used as identification instance for auditing. 2088 * 2089 * @param[in] ObjectTypeName 2090 * The name of the object type. 2091 * 2092 * @param[in] ObjectName 2093 * The object name. 2094 * 2095 * @param[in] SecurityDescriptor 2096 * A security descriptor. 2097 * 2098 * @param[in] DesiredAccess 2099 * The desired access rights masks requested by the caller. 2100 * 2101 * @param[in] GenericMapping 2102 * The generic mapping of access mask rights. 2103 * 2104 * @param[in] ObjectCreation 2105 * Set this to TRUE if the object has just been created. 2106 * 2107 * @param[out] GrantedAccess 2108 * Returns the granted access rights. 2109 * 2110 * @param[out] AccessStatus 2111 * Returns a NTSTATUS status code indicating whether access check 2112 * can be granted or not. 2113 * 2114 * @param[out] GenerateOnClose 2115 * Returns TRUE if the function has generated a list of granted access rights and 2116 * status codes on termination, FALSE otherwise. 2117 * 2118 * @return 2119 * See SepAccessCheckAndAuditAlarm. 2120 */ 2121 _Must_inspect_result_ 2122 __kernel_entry 2123 NTSTATUS 2124 NTAPI 2125 NtAccessCheckAndAuditAlarm( 2126 _In_ PUNICODE_STRING SubsystemName, 2127 _In_opt_ PVOID HandleId, 2128 _In_ PUNICODE_STRING ObjectTypeName, 2129 _In_ PUNICODE_STRING ObjectName, 2130 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 2131 _In_ ACCESS_MASK DesiredAccess, 2132 _In_ PGENERIC_MAPPING GenericMapping, 2133 _In_ BOOLEAN ObjectCreation, 2134 _Out_ PACCESS_MASK GrantedAccess, 2135 _Out_ PNTSTATUS AccessStatus, 2136 _Out_ PBOOLEAN GenerateOnClose) 2137 { 2138 /* Call the internal function */ 2139 return SepAccessCheckAndAuditAlarm(SubsystemName, 2140 HandleId, 2141 NULL, 2142 ObjectTypeName, 2143 ObjectName, 2144 SecurityDescriptor, 2145 NULL, 2146 DesiredAccess, 2147 AuditEventObjectAccess, 2148 0, 2149 NULL, 2150 0, 2151 GenericMapping, 2152 GrantedAccess, 2153 AccessStatus, 2154 GenerateOnClose, 2155 FALSE); 2156 } 2157 2158 /** 2159 * @brief 2160 * Raises an alarm audit message when a caller attempts to access an 2161 * object and determine if the access can be made by type. 2162 * 2163 * @param[in] SubsystemName 2164 * A Unicode string that points to a name of the subsystem. 2165 * 2166 * @param[in] HandleId 2167 * A handle to an ID that is used as identification instance for auditing. 2168 * 2169 * @param[in] ObjectTypeName 2170 * The name of the object type. 2171 * 2172 * @param[in] ObjectName 2173 * The object name. 2174 * 2175 * @param[in] SecurityDescriptor 2176 * A security descriptor. 2177 * 2178 * @param[in] PrincipalSelfSid 2179 * A principal self user SID. 2180 * 2181 * @param[in] DesiredAccess 2182 * The desired access rights masks requested by the caller. 2183 * 2184 * @param[in] AuditType 2185 * Type of audit to start, influencing how the audit should 2186 * be done. 2187 * 2188 * @param[in] Flags 2189 * Flag bitmask, used to check if auditing can be done 2190 * without privileges. 2191 * 2192 * @param[in] ObjectTypeList 2193 * A list of object types. 2194 * 2195 * @param[in] ObjectTypeLength 2196 * The length size of the list. 2197 * 2198 * @param[in] GenericMapping 2199 * The generic mapping of access mask rights. 2200 * 2201 * @param[in] ObjectCreation 2202 * Set this to TRUE if the object has just been created. 2203 * 2204 * @param[out] GrantedAccess 2205 * Returns the granted access rights. 2206 * 2207 * @param[out] AccessStatus 2208 * Returns a NTSTATUS status code indicating whether access check 2209 * can be granted or not. 2210 * 2211 * @param[out] GenerateOnClose 2212 * Returns TRUE if the function has generated a list of granted access rights and 2213 * status codes on termination, FALSE otherwise. 2214 * 2215 * @return 2216 * See SepAccessCheckAndAuditAlarm. 2217 */ 2218 _Must_inspect_result_ 2219 __kernel_entry 2220 NTSTATUS 2221 NTAPI 2222 NtAccessCheckByTypeAndAuditAlarm( 2223 _In_ PUNICODE_STRING SubsystemName, 2224 _In_opt_ PVOID HandleId, 2225 _In_ PUNICODE_STRING ObjectTypeName, 2226 _In_ PUNICODE_STRING ObjectName, 2227 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 2228 _In_opt_ PSID PrincipalSelfSid, 2229 _In_ ACCESS_MASK DesiredAccess, 2230 _In_ AUDIT_EVENT_TYPE AuditType, 2231 _In_ ULONG Flags, 2232 _In_reads_opt_(ObjectTypeLength) POBJECT_TYPE_LIST ObjectTypeList, 2233 _In_ ULONG ObjectTypeLength, 2234 _In_ PGENERIC_MAPPING GenericMapping, 2235 _In_ BOOLEAN ObjectCreation, 2236 _Out_ PACCESS_MASK GrantedAccess, 2237 _Out_ PNTSTATUS AccessStatus, 2238 _Out_ PBOOLEAN GenerateOnClose) 2239 { 2240 /* Call the internal function */ 2241 return SepAccessCheckAndAuditAlarm(SubsystemName, 2242 HandleId, 2243 NULL, 2244 ObjectTypeName, 2245 ObjectName, 2246 SecurityDescriptor, 2247 PrincipalSelfSid, 2248 DesiredAccess, 2249 AuditType, 2250 Flags, 2251 ObjectTypeList, 2252 ObjectTypeLength, 2253 GenericMapping, 2254 GrantedAccess, 2255 AccessStatus, 2256 GenerateOnClose, 2257 FALSE); 2258 } 2259 2260 /** 2261 * @brief 2262 * Raises an alarm audit message when a caller attempts to access an 2263 * object and determine if the access can be made by given type result. 2264 * 2265 * @param[in] SubsystemName 2266 * A Unicode string that points to a name of the subsystem. 2267 * 2268 * @param[in] HandleId 2269 * A handle to an ID that is used as identification instance for auditing. 2270 * 2271 * @param[in] ObjectTypeName 2272 * The name of the object type. 2273 * 2274 * @param[in] ObjectName 2275 * The object name. 2276 * 2277 * @param[in] SecurityDescriptor 2278 * A security descriptor. 2279 * 2280 * @param[in] PrincipalSelfSid 2281 * A principal self user SID. 2282 * 2283 * @param[in] DesiredAccess 2284 * The desired access rights masks requested by the caller. 2285 * 2286 * @param[in] AuditType 2287 * Type of audit to start, influencing how the audit should 2288 * be done. 2289 * 2290 * @param[in] Flags 2291 * Flag bitmask, used to check if auditing can be done 2292 * without privileges. 2293 * 2294 * @param[in] ObjectTypeList 2295 * A list of object types. 2296 * 2297 * @param[in] ObjectTypeLength 2298 * The length size of the list. 2299 * 2300 * @param[in] GenericMapping 2301 * The generic mapping of access mask rights. 2302 * 2303 * @param[in] ObjectCreation 2304 * Set this to TRUE if the object has just been created. 2305 * 2306 * @param[out] GrantedAccessList 2307 * Returns the granted access rights. 2308 * 2309 * @param[out] AccessStatusList 2310 * Returns a NTSTATUS status code indicating whether access check 2311 * can be granted or not. 2312 * 2313 * @param[out] GenerateOnClose 2314 * Returns TRUE if the function has generated a list of granted access rights and 2315 * status codes on termination, FALSE otherwise. 2316 * 2317 * @return 2318 * See SepAccessCheckAndAuditAlarm. 2319 */ 2320 _Must_inspect_result_ 2321 __kernel_entry 2322 NTSTATUS 2323 NTAPI 2324 NtAccessCheckByTypeResultListAndAuditAlarm( 2325 _In_ PUNICODE_STRING SubsystemName, 2326 _In_opt_ PVOID HandleId, 2327 _In_ PUNICODE_STRING ObjectTypeName, 2328 _In_ PUNICODE_STRING ObjectName, 2329 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 2330 _In_opt_ PSID PrincipalSelfSid, 2331 _In_ ACCESS_MASK DesiredAccess, 2332 _In_ AUDIT_EVENT_TYPE AuditType, 2333 _In_ ULONG Flags, 2334 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, 2335 _In_ ULONG ObjectTypeListLength, 2336 _In_ PGENERIC_MAPPING GenericMapping, 2337 _In_ BOOLEAN ObjectCreation, 2338 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList, 2339 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList, 2340 _Out_ PBOOLEAN GenerateOnClose) 2341 { 2342 /* Call the internal function */ 2343 return SepAccessCheckAndAuditAlarm(SubsystemName, 2344 HandleId, 2345 NULL, 2346 ObjectTypeName, 2347 ObjectName, 2348 SecurityDescriptor, 2349 PrincipalSelfSid, 2350 DesiredAccess, 2351 AuditType, 2352 Flags, 2353 ObjectTypeList, 2354 ObjectTypeListLength, 2355 GenericMapping, 2356 GrantedAccessList, 2357 AccessStatusList, 2358 GenerateOnClose, 2359 TRUE); 2360 } 2361 2362 /** 2363 * @brief 2364 * Raises an alarm audit message when a caller attempts to access an 2365 * object and determine if the access can be made by given type result 2366 * and a token handle. 2367 * 2368 * @param[in] SubsystemName 2369 * A Unicode string that points to a name of the subsystem. 2370 * 2371 * @param[in] HandleId 2372 * A handle to an ID that is used as identification instance for auditing. 2373 * 2374 * @param[in] ClientToken 2375 * A handle to a client access token. 2376 * 2377 * @param[in] ObjectTypeName 2378 * The name of the object type. 2379 * 2380 * @param[in] ObjectName 2381 * The object name. 2382 * 2383 * @param[in] SecurityDescriptor 2384 * A security descriptor. 2385 * 2386 * @param[in] PrincipalSelfSid 2387 * A principal self user SID. 2388 * 2389 * @param[in] DesiredAccess 2390 * The desired access rights masks requested by the caller. 2391 * 2392 * @param[in] AuditType 2393 * Type of audit to start, influencing how the audit should 2394 * be done. 2395 * 2396 * @param[in] Flags 2397 * Flag bitmask, used to check if auditing can be done 2398 * without privileges. 2399 * 2400 * @param[in] ObjectTypeList 2401 * A list of object types. 2402 * 2403 * @param[in] ObjectTypeLength 2404 * The length size of the list. 2405 * 2406 * @param[in] GenericMapping 2407 * The generic mapping of access mask rights. 2408 * 2409 * @param[in] ObjectCreation 2410 * Set this to TRUE if the object has just been created. 2411 * 2412 * @param[out] GrantedAccessList 2413 * Returns the granted access rights. 2414 * 2415 * @param[out] AccessStatusList 2416 * Returns a NTSTATUS status code indicating whether access check 2417 * can be granted or not. 2418 * 2419 * @param[out] GenerateOnClose 2420 * Returns TRUE if the function has generated a list of granted access rights and 2421 * status codes on termination, FALSE otherwise. 2422 * 2423 * @return 2424 * See SepAccessCheckAndAuditAlarm. 2425 */ 2426 _Must_inspect_result_ 2427 __kernel_entry 2428 NTSTATUS 2429 NTAPI 2430 NtAccessCheckByTypeResultListAndAuditAlarmByHandle( 2431 _In_ PUNICODE_STRING SubsystemName, 2432 _In_opt_ PVOID HandleId, 2433 _In_ HANDLE ClientToken, 2434 _In_ PUNICODE_STRING ObjectTypeName, 2435 _In_ PUNICODE_STRING ObjectName, 2436 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, 2437 _In_opt_ PSID PrincipalSelfSid, 2438 _In_ ACCESS_MASK DesiredAccess, 2439 _In_ AUDIT_EVENT_TYPE AuditType, 2440 _In_ ULONG Flags, 2441 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, 2442 _In_ ULONG ObjectTypeListLength, 2443 _In_ PGENERIC_MAPPING GenericMapping, 2444 _In_ BOOLEAN ObjectCreation, 2445 _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList, 2446 _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList, 2447 _Out_ PBOOLEAN GenerateOnClose) 2448 { 2449 UNREFERENCED_PARAMETER(ObjectCreation); 2450 2451 /* Call the internal function */ 2452 return SepAccessCheckAndAuditAlarm(SubsystemName, 2453 HandleId, 2454 &ClientToken, 2455 ObjectTypeName, 2456 ObjectName, 2457 SecurityDescriptor, 2458 PrincipalSelfSid, 2459 DesiredAccess, 2460 AuditType, 2461 Flags, 2462 ObjectTypeList, 2463 ObjectTypeListLength, 2464 GenericMapping, 2465 GrantedAccessList, 2466 AccessStatusList, 2467 GenerateOnClose, 2468 TRUE); 2469 } 2470 2471 /* EOF */ 2472