1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntoskrnl/se/priv.c 5 * PURPOSE: Security manager 6 * 7 * PROGRAMMERS: No programmer listed. 8 */ 9 10 /* INCLUDES ******************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 #if defined (ALLOC_PRAGMA) 17 #pragma alloc_text(INIT, SepInitPrivileges) 18 #endif 19 20 /* GLOBALS ********************************************************************/ 21 22 #define CONST_LUID(x1, x2) {x1, x2} 23 const LUID SeCreateTokenPrivilege = CONST_LUID(SE_CREATE_TOKEN_PRIVILEGE, 0); 24 const LUID SeAssignPrimaryTokenPrivilege = CONST_LUID(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0); 25 const LUID SeLockMemoryPrivilege = CONST_LUID(SE_LOCK_MEMORY_PRIVILEGE, 0); 26 const LUID SeIncreaseQuotaPrivilege = CONST_LUID(SE_INCREASE_QUOTA_PRIVILEGE, 0); 27 const LUID SeUnsolicitedInputPrivilege = CONST_LUID(6, 0); 28 const LUID SeTcbPrivilege = CONST_LUID(SE_TCB_PRIVILEGE, 0); 29 const LUID SeSecurityPrivilege = CONST_LUID(SE_SECURITY_PRIVILEGE, 0); 30 const LUID SeTakeOwnershipPrivilege = CONST_LUID(SE_TAKE_OWNERSHIP_PRIVILEGE, 0); 31 const LUID SeLoadDriverPrivilege = CONST_LUID(SE_LOAD_DRIVER_PRIVILEGE, 0); 32 const LUID SeSystemProfilePrivilege = CONST_LUID(SE_SYSTEM_PROFILE_PRIVILEGE, 0); 33 const LUID SeSystemtimePrivilege = CONST_LUID(SE_SYSTEMTIME_PRIVILEGE, 0); 34 const LUID SeProfileSingleProcessPrivilege = CONST_LUID(SE_PROF_SINGLE_PROCESS_PRIVILEGE, 0); 35 const LUID SeIncreaseBasePriorityPrivilege = CONST_LUID(SE_INC_BASE_PRIORITY_PRIVILEGE, 0); 36 const LUID SeCreatePagefilePrivilege = CONST_LUID(SE_CREATE_PAGEFILE_PRIVILEGE, 0); 37 const LUID SeCreatePermanentPrivilege = CONST_LUID(SE_CREATE_PERMANENT_PRIVILEGE, 0); 38 const LUID SeBackupPrivilege = CONST_LUID(SE_BACKUP_PRIVILEGE, 0); 39 const LUID SeRestorePrivilege = CONST_LUID(SE_RESTORE_PRIVILEGE, 0); 40 const LUID SeShutdownPrivilege = CONST_LUID(SE_SHUTDOWN_PRIVILEGE, 0); 41 const LUID SeDebugPrivilege = CONST_LUID(SE_DEBUG_PRIVILEGE, 0); 42 const LUID SeAuditPrivilege = CONST_LUID(SE_AUDIT_PRIVILEGE, 0); 43 const LUID SeSystemEnvironmentPrivilege = CONST_LUID(SE_SYSTEM_ENVIRONMENT_PRIVILEGE, 0); 44 const LUID SeChangeNotifyPrivilege = CONST_LUID(SE_CHANGE_NOTIFY_PRIVILEGE, 0); 45 const LUID SeRemoteShutdownPrivilege = CONST_LUID(SE_REMOTE_SHUTDOWN_PRIVILEGE, 0); 46 const LUID SeUndockPrivilege = CONST_LUID(SE_UNDOCK_PRIVILEGE, 0); 47 const LUID SeSyncAgentPrivilege = CONST_LUID(SE_SYNC_AGENT_PRIVILEGE, 0); 48 const LUID SeEnableDelegationPrivilege = CONST_LUID(SE_ENABLE_DELEGATION_PRIVILEGE, 0); 49 const LUID SeManageVolumePrivilege = CONST_LUID(SE_MANAGE_VOLUME_PRIVILEGE, 0); 50 const LUID SeImpersonatePrivilege = CONST_LUID(SE_IMPERSONATE_PRIVILEGE, 0); 51 const LUID SeCreateGlobalPrivilege = CONST_LUID(SE_CREATE_GLOBAL_PRIVILEGE, 0); 52 const LUID SeTrustedCredmanPrivilege = CONST_LUID(SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE, 0); 53 const LUID SeRelabelPrivilege = CONST_LUID(SE_RELABEL_PRIVILEGE, 0); 54 const LUID SeIncreaseWorkingSetPrivilege = CONST_LUID(SE_INC_WORKING_SET_PRIVILEGE, 0); 55 const LUID SeTimeZonePrivilege = CONST_LUID(SE_TIME_ZONE_PRIVILEGE, 0); 56 const LUID SeCreateSymbolicLinkPrivilege = CONST_LUID(SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, 0); 57 58 59 /* PRIVATE FUNCTIONS **********************************************************/ 60 61 INIT_FUNCTION 62 VOID 63 NTAPI 64 SepInitPrivileges(VOID) 65 { 66 67 } 68 69 70 BOOLEAN 71 NTAPI 72 SepPrivilegeCheck(PTOKEN Token, 73 PLUID_AND_ATTRIBUTES Privileges, 74 ULONG PrivilegeCount, 75 ULONG PrivilegeControl, 76 KPROCESSOR_MODE PreviousMode) 77 { 78 ULONG i; 79 ULONG j; 80 ULONG Required; 81 82 DPRINT("SepPrivilegeCheck() called\n"); 83 84 PAGED_CODE(); 85 86 if (PreviousMode == KernelMode) 87 return TRUE; 88 89 /* Get the number of privileges that are required to match */ 90 Required = (PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) ? PrivilegeCount : 1; 91 92 /* Acquire a shared token lock */ 93 SepAcquireTokenLockShared(Token); 94 95 /* Loop all requested privileges until we found the required ones */ 96 for (i = 0; i < PrivilegeCount; i++) 97 { 98 /* Loop the privileges of the token */ 99 for (j = 0; j < Token->PrivilegeCount; j++) 100 { 101 /* Check if the LUIDs match */ 102 if (RtlEqualLuid(&Token->Privileges[j].Luid, &Privileges[i].Luid)) 103 { 104 DPRINT("Found privilege. Attributes: %lx\n", 105 Token->Privileges[j].Attributes); 106 107 /* Check if the privilege is enabled */ 108 if (Token->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED) 109 { 110 Privileges[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS; 111 Required--; 112 113 /* Check if we have found all privileges */ 114 if (Required == 0) 115 { 116 /* We're done! */ 117 SepReleaseTokenLock(Token); 118 return TRUE; 119 } 120 } 121 122 /* Leave the inner loop */ 123 break; 124 } 125 } 126 } 127 128 /* Release the token lock */ 129 SepReleaseTokenLock(Token); 130 131 /* When we reached this point, we did not find all privileges */ 132 ASSERT(Required > 0); 133 return FALSE; 134 } 135 136 NTSTATUS 137 NTAPI 138 SepSinglePrivilegeCheck( 139 LUID PrivilegeValue, 140 PTOKEN Token, 141 KPROCESSOR_MODE PreviousMode) 142 { 143 LUID_AND_ATTRIBUTES Privilege; 144 PAGED_CODE(); 145 ASSERT(!RtlEqualLuid(&PrivilegeValue, &SeTcbPrivilege)); 146 147 Privilege.Luid = PrivilegeValue; 148 Privilege.Attributes = SE_PRIVILEGE_ENABLED; 149 return SepPrivilegeCheck(Token, 150 &Privilege, 151 1, 152 PRIVILEGE_SET_ALL_NECESSARY, 153 PreviousMode); 154 } 155 156 NTSTATUS 157 NTAPI 158 SePrivilegePolicyCheck( 159 _Inout_ PACCESS_MASK DesiredAccess, 160 _Inout_ PACCESS_MASK GrantedAccess, 161 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 162 _In_ PTOKEN Token, 163 _Out_opt_ PPRIVILEGE_SET *OutPrivilegeSet, 164 _In_ KPROCESSOR_MODE PreviousMode) 165 { 166 SIZE_T PrivilegeSize; 167 PPRIVILEGE_SET PrivilegeSet; 168 ULONG PrivilegeCount = 0, Index = 0; 169 ACCESS_MASK AccessMask = 0; 170 PAGED_CODE(); 171 172 /* Check if we have a security subject context */ 173 if (SubjectContext != NULL) 174 { 175 /* Check if there is a client impersonation token */ 176 if (SubjectContext->ClientToken != NULL) 177 Token = SubjectContext->ClientToken; 178 else 179 Token = SubjectContext->PrimaryToken; 180 } 181 182 /* Check if the caller wants ACCESS_SYSTEM_SECURITY access */ 183 if (*DesiredAccess & ACCESS_SYSTEM_SECURITY) 184 { 185 /* Do the privilege check */ 186 if (SepSinglePrivilegeCheck(SeSecurityPrivilege, Token, PreviousMode)) 187 { 188 /* Remember this access flag */ 189 AccessMask |= ACCESS_SYSTEM_SECURITY; 190 PrivilegeCount++; 191 } 192 else 193 { 194 return STATUS_PRIVILEGE_NOT_HELD; 195 } 196 } 197 198 /* Check if the caller wants WRITE_OWNER access */ 199 if (*DesiredAccess & WRITE_OWNER) 200 { 201 /* Do the privilege check */ 202 if (SepSinglePrivilegeCheck(SeTakeOwnershipPrivilege, Token, PreviousMode)) 203 { 204 /* Remember this access flag */ 205 AccessMask |= WRITE_OWNER; 206 PrivilegeCount++; 207 } 208 } 209 210 /* Update the access masks */ 211 *GrantedAccess |= AccessMask; 212 *DesiredAccess &= ~AccessMask; 213 214 /* Does the caller want a privilege set? */ 215 if (OutPrivilegeSet != NULL) 216 { 217 /* Do we have any privileges to report? */ 218 if (PrivilegeCount > 0) 219 { 220 /* Calculate size and allocate the structure */ 221 PrivilegeSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]); 222 PrivilegeSet = ExAllocatePoolWithTag(PagedPool, PrivilegeSize, TAG_PRIVILEGE_SET); 223 *OutPrivilegeSet = PrivilegeSet; 224 if (PrivilegeSet == NULL) 225 { 226 return STATUS_INSUFFICIENT_RESOURCES; 227 } 228 229 PrivilegeSet->PrivilegeCount = PrivilegeCount; 230 PrivilegeSet->Control = 0; 231 232 if (AccessMask & WRITE_OWNER) 233 { 234 PrivilegeSet->Privilege[Index].Luid = SeTakeOwnershipPrivilege; 235 PrivilegeSet->Privilege[Index].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS; 236 Index++; 237 } 238 239 if (AccessMask & ACCESS_SYSTEM_SECURITY) 240 { 241 PrivilegeSet->Privilege[Index].Luid = SeSecurityPrivilege; 242 PrivilegeSet->Privilege[Index].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS; 243 } 244 } 245 else 246 { 247 /* No privileges, no structure */ 248 *OutPrivilegeSet = NULL; 249 } 250 } 251 252 return STATUS_SUCCESS; 253 } 254 255 BOOLEAN 256 NTAPI 257 SeCheckAuditPrivilege( 258 _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, 259 _In_ KPROCESSOR_MODE PreviousMode) 260 { 261 PRIVILEGE_SET PrivilegeSet; 262 BOOLEAN Result; 263 PAGED_CODE(); 264 265 /* Initialize the privilege set with the single privilege */ 266 PrivilegeSet.PrivilegeCount = 1; 267 PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY; 268 PrivilegeSet.Privilege[0].Luid = SeAuditPrivilege; 269 PrivilegeSet.Privilege[0].Attributes = 0; 270 271 /* Check against the primary token! */ 272 Result = SepPrivilegeCheck(SubjectContext->PrimaryToken, 273 &PrivilegeSet.Privilege[0], 274 1, 275 PRIVILEGE_SET_ALL_NECESSARY, 276 PreviousMode); 277 278 if (PreviousMode != KernelMode) 279 { 280 SePrivilegedServiceAuditAlarm(NULL, 281 SubjectContext, 282 &PrivilegeSet, 283 Result); 284 } 285 286 return Result; 287 } 288 289 NTSTATUS 290 NTAPI 291 SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src, 292 ULONG PrivilegeCount, 293 KPROCESSOR_MODE PreviousMode, 294 PLUID_AND_ATTRIBUTES AllocatedMem, 295 ULONG AllocatedLength, 296 POOL_TYPE PoolType, 297 BOOLEAN CaptureIfKernel, 298 PLUID_AND_ATTRIBUTES *Dest, 299 PULONG Length) 300 { 301 ULONG BufferSize; 302 NTSTATUS Status = STATUS_SUCCESS; 303 304 PAGED_CODE(); 305 306 if (PrivilegeCount == 0) 307 { 308 *Dest = 0; 309 *Length = 0; 310 return STATUS_SUCCESS; 311 } 312 313 if (PreviousMode == KernelMode && !CaptureIfKernel) 314 { 315 *Dest = Src; 316 return STATUS_SUCCESS; 317 } 318 319 /* FIXME - check PrivilegeCount for a valid number so we don't 320 cause an integer overflow or exhaust system resources! */ 321 322 BufferSize = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES); 323 *Length = ROUND_UP(BufferSize, 4); /* round up to a 4 byte alignment */ 324 325 /* probe the buffer */ 326 if (PreviousMode != KernelMode) 327 { 328 _SEH2_TRY 329 { 330 ProbeForRead(Src, 331 BufferSize, 332 sizeof(ULONG)); 333 } 334 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 335 { 336 /* Return the exception code */ 337 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 338 } 339 _SEH2_END; 340 } 341 342 /* allocate enough memory or check if the provided buffer is 343 large enough to hold the array */ 344 if (AllocatedMem != NULL) 345 { 346 if (AllocatedLength < BufferSize) 347 { 348 return STATUS_BUFFER_TOO_SMALL; 349 } 350 351 *Dest = AllocatedMem; 352 } 353 else 354 { 355 *Dest = ExAllocatePoolWithTag(PoolType, 356 BufferSize, 357 TAG_LUID); 358 if (*Dest == NULL) 359 { 360 return STATUS_INSUFFICIENT_RESOURCES; 361 } 362 } 363 364 /* copy the array to the buffer */ 365 _SEH2_TRY 366 { 367 RtlCopyMemory(*Dest, 368 Src, 369 BufferSize); 370 } 371 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 372 { 373 Status = _SEH2_GetExceptionCode(); 374 } 375 _SEH2_END; 376 377 if (!NT_SUCCESS(Status) && AllocatedMem == NULL) 378 { 379 ExFreePoolWithTag(*Dest, TAG_LUID); 380 } 381 382 return Status; 383 } 384 385 VOID 386 NTAPI 387 SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege, 388 KPROCESSOR_MODE PreviousMode, 389 BOOLEAN CaptureIfKernel) 390 { 391 PAGED_CODE(); 392 393 if (Privilege != NULL && 394 (PreviousMode != KernelMode || CaptureIfKernel)) 395 { 396 ExFreePoolWithTag(Privilege, TAG_LUID); 397 } 398 } 399 400 /* PUBLIC FUNCTIONS ***********************************************************/ 401 402 /* 403 * @implemented 404 */ 405 NTSTATUS 406 NTAPI 407 SeAppendPrivileges(IN OUT PACCESS_STATE AccessState, 408 IN PPRIVILEGE_SET Privileges) 409 { 410 PAUX_ACCESS_DATA AuxData; 411 ULONG OldPrivilegeSetSize; 412 ULONG NewPrivilegeSetSize; 413 PPRIVILEGE_SET PrivilegeSet; 414 415 PAGED_CODE(); 416 417 /* Get the Auxiliary Data */ 418 AuxData = AccessState->AuxData; 419 420 /* Calculate the size of the old privilege set */ 421 OldPrivilegeSetSize = sizeof(PRIVILEGE_SET) + 422 (AuxData->PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES); 423 424 if (AuxData->PrivilegeSet->PrivilegeCount + 425 Privileges->PrivilegeCount > INITIAL_PRIVILEGE_COUNT) 426 { 427 /* Calculate the size of the new privilege set */ 428 NewPrivilegeSetSize = OldPrivilegeSetSize + 429 Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES); 430 431 /* Allocate a new privilege set */ 432 PrivilegeSet = ExAllocatePoolWithTag(PagedPool, 433 NewPrivilegeSetSize, 434 TAG_PRIVILEGE_SET); 435 if (PrivilegeSet == NULL) 436 return STATUS_INSUFFICIENT_RESOURCES; 437 438 /* Copy original privileges from the acess state */ 439 RtlCopyMemory(PrivilegeSet, 440 AuxData->PrivilegeSet, 441 OldPrivilegeSetSize); 442 443 /* Append privileges from the privilege set*/ 444 RtlCopyMemory((PVOID)((ULONG_PTR)PrivilegeSet + OldPrivilegeSetSize), 445 (PVOID)((ULONG_PTR)Privileges + sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES)), 446 Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)); 447 448 /* Adjust the number of privileges in the new privilege set */ 449 PrivilegeSet->PrivilegeCount += Privileges->PrivilegeCount; 450 451 /* Free the old privilege set if it was allocated */ 452 if (AccessState->PrivilegesAllocated != FALSE) 453 ExFreePoolWithTag(AuxData->PrivilegeSet, TAG_PRIVILEGE_SET); 454 455 /* Now we are using an allocated privilege set */ 456 AccessState->PrivilegesAllocated = TRUE; 457 458 /* Assign the new privileges to the access state */ 459 AuxData->PrivilegeSet = PrivilegeSet; 460 } 461 else 462 { 463 /* Append privileges */ 464 RtlCopyMemory((PVOID)((ULONG_PTR)AuxData->PrivilegeSet + OldPrivilegeSetSize), 465 (PVOID)((ULONG_PTR)Privileges + sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES)), 466 Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)); 467 468 /* Adjust the number of privileges in the target privilege set */ 469 AuxData->PrivilegeSet->PrivilegeCount += Privileges->PrivilegeCount; 470 } 471 472 return STATUS_SUCCESS; 473 } 474 475 /* 476 * @implemented 477 */ 478 VOID 479 NTAPI 480 SeFreePrivileges(IN PPRIVILEGE_SET Privileges) 481 { 482 PAGED_CODE(); 483 ExFreePoolWithTag(Privileges, TAG_PRIVILEGE_SET); 484 } 485 486 /* 487 * @implemented 488 */ 489 BOOLEAN 490 NTAPI 491 SePrivilegeCheck(PPRIVILEGE_SET Privileges, 492 PSECURITY_SUBJECT_CONTEXT SubjectContext, 493 KPROCESSOR_MODE PreviousMode) 494 { 495 PACCESS_TOKEN Token = NULL; 496 497 PAGED_CODE(); 498 499 if (SubjectContext->ClientToken == NULL) 500 { 501 Token = SubjectContext->PrimaryToken; 502 } 503 else 504 { 505 Token = SubjectContext->ClientToken; 506 if (SubjectContext->ImpersonationLevel < 2) 507 { 508 return FALSE; 509 } 510 } 511 512 return SepPrivilegeCheck(Token, 513 Privileges->Privilege, 514 Privileges->PrivilegeCount, 515 Privileges->Control, 516 PreviousMode); 517 } 518 519 /* 520 * @implemented 521 */ 522 BOOLEAN 523 NTAPI 524 SeSinglePrivilegeCheck(IN LUID PrivilegeValue, 525 IN KPROCESSOR_MODE PreviousMode) 526 { 527 SECURITY_SUBJECT_CONTEXT SubjectContext; 528 PRIVILEGE_SET Priv; 529 BOOLEAN Result; 530 531 PAGED_CODE(); 532 533 SeCaptureSubjectContext(&SubjectContext); 534 535 Priv.PrivilegeCount = 1; 536 Priv.Control = PRIVILEGE_SET_ALL_NECESSARY; 537 Priv.Privilege[0].Luid = PrivilegeValue; 538 Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; 539 540 Result = SePrivilegeCheck(&Priv, 541 &SubjectContext, 542 PreviousMode); 543 544 if (PreviousMode != KernelMode) 545 { 546 SePrivilegedServiceAuditAlarm(NULL, 547 &SubjectContext, 548 &Priv, 549 Result); 550 551 } 552 553 SeReleaseSubjectContext(&SubjectContext); 554 555 return Result; 556 } 557 558 BOOLEAN 559 NTAPI 560 SeCheckPrivilegedObject(IN LUID PrivilegeValue, 561 IN HANDLE ObjectHandle, 562 IN ACCESS_MASK DesiredAccess, 563 IN KPROCESSOR_MODE PreviousMode) 564 { 565 SECURITY_SUBJECT_CONTEXT SubjectContext; 566 PRIVILEGE_SET Priv; 567 BOOLEAN Result; 568 569 PAGED_CODE(); 570 571 SeCaptureSubjectContext(&SubjectContext); 572 573 Priv.PrivilegeCount = 1; 574 Priv.Control = PRIVILEGE_SET_ALL_NECESSARY; 575 Priv.Privilege[0].Luid = PrivilegeValue; 576 Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; 577 578 Result = SePrivilegeCheck(&Priv, &SubjectContext, PreviousMode); 579 if (PreviousMode != KernelMode) 580 { 581 #if 0 582 SePrivilegeObjectAuditAlarm(ObjectHandle, 583 &SubjectContext, 584 DesiredAccess, 585 &PrivilegeValue, 586 Result, 587 PreviousMode); 588 #endif 589 } 590 591 SeReleaseSubjectContext(&SubjectContext); 592 593 return Result; 594 } 595 596 /* SYSTEM CALLS ***************************************************************/ 597 598 NTSTATUS 599 NTAPI 600 NtPrivilegeCheck(IN HANDLE ClientToken, 601 IN PPRIVILEGE_SET RequiredPrivileges, 602 OUT PBOOLEAN Result) 603 { 604 PLUID_AND_ATTRIBUTES Privileges; 605 PTOKEN Token; 606 ULONG PrivilegeCount = 0; 607 ULONG PrivilegeControl = 0; 608 ULONG Length; 609 BOOLEAN CheckResult; 610 KPROCESSOR_MODE PreviousMode; 611 NTSTATUS Status; 612 613 PAGED_CODE(); 614 615 PreviousMode = KeGetPreviousMode(); 616 617 /* probe the buffers */ 618 if (PreviousMode != KernelMode) 619 { 620 _SEH2_TRY 621 { 622 ProbeForWrite(RequiredPrivileges, 623 FIELD_OFFSET(PRIVILEGE_SET, 624 Privilege), 625 sizeof(ULONG)); 626 627 PrivilegeCount = RequiredPrivileges->PrivilegeCount; 628 PrivilegeControl = RequiredPrivileges->Control; 629 630 /* Check PrivilegeCount to avoid an integer overflow! */ 631 if (FIELD_OFFSET(PRIVILEGE_SET, 632 Privilege[PrivilegeCount]) / 633 sizeof(RequiredPrivileges->Privilege[0]) != PrivilegeCount) 634 { 635 _SEH2_YIELD(return STATUS_INVALID_PARAMETER); 636 } 637 638 /* probe all of the array */ 639 ProbeForWrite(RequiredPrivileges, 640 FIELD_OFFSET(PRIVILEGE_SET, 641 Privilege[PrivilegeCount]), 642 sizeof(ULONG)); 643 644 ProbeForWriteBoolean(Result); 645 } 646 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 647 { 648 /* Return the exception code */ 649 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 650 } 651 _SEH2_END; 652 } 653 else 654 { 655 PrivilegeCount = RequiredPrivileges->PrivilegeCount; 656 PrivilegeControl = RequiredPrivileges->Control; 657 } 658 659 /* reference the token and make sure we're 660 not doing an anonymous impersonation */ 661 Status = ObReferenceObjectByHandle(ClientToken, 662 TOKEN_QUERY, 663 SeTokenObjectType, 664 PreviousMode, 665 (PVOID*)&Token, 666 NULL); 667 if (!NT_SUCCESS(Status)) 668 { 669 return Status; 670 } 671 672 if (Token->TokenType == TokenImpersonation && 673 Token->ImpersonationLevel < SecurityIdentification) 674 { 675 ObDereferenceObject(Token); 676 return STATUS_BAD_IMPERSONATION_LEVEL; 677 } 678 679 /* capture the privileges */ 680 Status = SeCaptureLuidAndAttributesArray(RequiredPrivileges->Privilege, 681 PrivilegeCount, 682 PreviousMode, 683 NULL, 684 0, 685 PagedPool, 686 TRUE, 687 &Privileges, 688 &Length); 689 if (!NT_SUCCESS(Status)) 690 { 691 ObDereferenceObject (Token); 692 return Status; 693 } 694 695 CheckResult = SepPrivilegeCheck(Token, 696 Privileges, 697 PrivilegeCount, 698 PrivilegeControl, 699 PreviousMode); 700 701 ObDereferenceObject(Token); 702 703 /* return the array */ 704 _SEH2_TRY 705 { 706 RtlCopyMemory(RequiredPrivileges->Privilege, 707 Privileges, 708 PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)); 709 *Result = CheckResult; 710 Status = STATUS_SUCCESS; 711 } 712 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 713 { 714 Status = _SEH2_GetExceptionCode(); 715 } 716 _SEH2_END; 717 718 SeReleaseLuidAndAttributesArray(Privileges, 719 PreviousMode, 720 TRUE); 721 722 return Status; 723 } 724 725 /* EOF */ 726