Index: ntoskrnl/include/internal/se.h =================================================================== --- ntoskrnl/include/internal/se.h (revision 61022) +++ ntoskrnl/include/internal/se.h (working copy) @@ -145,32 +145,40 @@ extern PSID SeAnonymousLogonSid; /* Privileges */ -extern LUID SeCreateTokenPrivilege; -extern LUID SeAssignPrimaryTokenPrivilege; -extern LUID SeLockMemoryPrivilege; -extern LUID SeIncreaseQuotaPrivilege; -extern LUID SeUnsolicitedInputPrivilege; -extern LUID SeTcbPrivilege; -extern LUID SeSecurityPrivilege; -extern LUID SeTakeOwnershipPrivilege; -extern LUID SeLoadDriverPrivilege; -extern LUID SeCreatePagefilePrivilege; -extern LUID SeIncreaseBasePriorityPrivilege; -extern LUID SeSystemProfilePrivilege; -extern LUID SeSystemtimePrivilege; -extern LUID SeProfileSingleProcessPrivilege; -extern LUID SeCreatePermanentPrivilege; -extern LUID SeBackupPrivilege; -extern LUID SeRestorePrivilege; -extern LUID SeShutdownPrivilege; -extern LUID SeDebugPrivilege; -extern LUID SeAuditPrivilege; -extern LUID SeSystemEnvironmentPrivilege; -extern LUID SeChangeNotifyPrivilege; -extern LUID SeRemoteShutdownPrivilege; -extern LUID SeUndockPrivilege; -extern LUID SeSyncAgentPrivilege; -extern LUID SeEnableDelegationPrivilege; +extern const LUID SeCreateTokenPrivilege; +extern const LUID SeAssignPrimaryTokenPrivilege; +extern const LUID SeLockMemoryPrivilege; +extern const LUID SeIncreaseQuotaPrivilege; +extern const LUID SeUnsolicitedInputPrivilege; +extern const LUID SeTcbPrivilege; +extern const LUID SeSecurityPrivilege; +extern const LUID SeTakeOwnershipPrivilege; +extern const LUID SeLoadDriverPrivilege; +extern const LUID SeSystemProfilePrivilege; +extern const LUID SeSystemtimePrivilege; +extern const LUID SeProfileSingleProcessPrivilege; +extern const LUID SeIncreaseBasePriorityPrivilege; +extern const LUID SeCreatePagefilePrivilege; +extern const LUID SeCreatePermanentPrivilege; +extern const LUID SeBackupPrivilege; +extern const LUID SeRestorePrivilege; +extern const LUID SeShutdownPrivilege; +extern const LUID SeDebugPrivilege; +extern const LUID SeAuditPrivilege; +extern const LUID SeSystemEnvironmentPrivilege; +extern const LUID SeChangeNotifyPrivilege; +extern const LUID SeRemoteShutdownPrivilege; +extern const LUID SeUndockPrivilege; +extern const LUID SeSyncAgentPrivilege; +extern const LUID SeEnableDelegationPrivilege; +extern const LUID SeManageVolumePrivilege; +extern const LUID SeImpersonatePrivilege; +extern const LUID SeCreateGlobalPrivilege; +extern const LUID SeTrustedCredmanPrivilege; +extern const LUID SeRelabelPrivilege; +extern const LUID SeIncreaseWorkingSetPrivilege; +extern const LUID SeTimeZonePrivilege; +extern const LUID SeCreateSymbolicLinkPrivilege; /* DACLs */ extern PACL SePublicDefaultUnrestrictedDacl; Index: ntoskrnl/se/priv.c =================================================================== --- ntoskrnl/se/priv.c (revision 61022) +++ ntoskrnl/se/priv.c (working copy) @@ -19,33 +19,43 @@ /* GLOBALS ********************************************************************/ -LUID SeCreateTokenPrivilege; -LUID SeAssignPrimaryTokenPrivilege; -LUID SeLockMemoryPrivilege; -LUID SeIncreaseQuotaPrivilege; -LUID SeUnsolicitedInputPrivilege; -LUID SeTcbPrivilege; -LUID SeSecurityPrivilege; -LUID SeTakeOwnershipPrivilege; -LUID SeLoadDriverPrivilege; -LUID SeCreatePagefilePrivilege; -LUID SeIncreaseBasePriorityPrivilege; -LUID SeSystemProfilePrivilege; -LUID SeSystemtimePrivilege; -LUID SeProfileSingleProcessPrivilege; -LUID SeCreatePermanentPrivilege; -LUID SeBackupPrivilege; -LUID SeRestorePrivilege; -LUID SeShutdownPrivilege; -LUID SeDebugPrivilege; -LUID SeAuditPrivilege; -LUID SeSystemEnvironmentPrivilege; -LUID SeChangeNotifyPrivilege; -LUID SeRemoteShutdownPrivilege; -LUID SeUndockPrivilege; -LUID SeSyncAgentPrivilege; -LUID SeEnableDelegationPrivilege; +#define CONST_LUID(x1, x2) {x1, x2} +const LUID SeCreateTokenPrivilege = CONST_LUID(SE_CREATE_TOKEN_PRIVILEGE, 0); +const LUID SeAssignPrimaryTokenPrivilege = CONST_LUID(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0); +const LUID SeLockMemoryPrivilege = CONST_LUID(SE_LOCK_MEMORY_PRIVILEGE, 0); +const LUID SeIncreaseQuotaPrivilege = CONST_LUID(SE_INCREASE_QUOTA_PRIVILEGE, 0); +const LUID SeUnsolicitedInputPrivilege = CONST_LUID(6, 0); +const LUID SeTcbPrivilege = CONST_LUID(SE_TCB_PRIVILEGE, 0); +const LUID SeSecurityPrivilege = CONST_LUID(SE_SECURITY_PRIVILEGE, 0); +const LUID SeTakeOwnershipPrivilege = CONST_LUID(SE_TAKE_OWNERSHIP_PRIVILEGE, 0); +const LUID SeLoadDriverPrivilege = CONST_LUID(SE_LOAD_DRIVER_PRIVILEGE, 0); +const LUID SeSystemProfilePrivilege = CONST_LUID(SE_SYSTEM_PROFILE_PRIVILEGE, 0); +const LUID SeSystemtimePrivilege = CONST_LUID(SE_SYSTEMTIME_PRIVILEGE, 0); +const LUID SeProfileSingleProcessPrivilege = CONST_LUID(SE_PROF_SINGLE_PROCESS_PRIVILEGE, 0); +const LUID SeIncreaseBasePriorityPrivilege = CONST_LUID(SE_INC_BASE_PRIORITY_PRIVILEGE, 0); +const LUID SeCreatePagefilePrivilege = CONST_LUID(SE_CREATE_PAGEFILE_PRIVILEGE, 0); +const LUID SeCreatePermanentPrivilege = CONST_LUID(SE_CREATE_PERMANENT_PRIVILEGE, 0); +const LUID SeBackupPrivilege = CONST_LUID(SE_BACKUP_PRIVILEGE, 0); +const LUID SeRestorePrivilege = CONST_LUID(SE_RESTORE_PRIVILEGE, 0); +const LUID SeShutdownPrivilege = CONST_LUID(SE_SHUTDOWN_PRIVILEGE, 0); +const LUID SeDebugPrivilege = CONST_LUID(SE_DEBUG_PRIVILEGE, 0); +const LUID SeAuditPrivilege = CONST_LUID(SE_AUDIT_PRIVILEGE, 0); +const LUID SeSystemEnvironmentPrivilege = CONST_LUID(SE_SYSTEM_ENVIRONMENT_PRIVILEGE, 0); +const LUID SeChangeNotifyPrivilege = CONST_LUID(SE_CHANGE_NOTIFY_PRIVILEGE, 0); +const LUID SeRemoteShutdownPrivilege = CONST_LUID(SE_REMOTE_SHUTDOWN_PRIVILEGE, 0); +const LUID SeUndockPrivilege = CONST_LUID(SE_UNDOCK_PRIVILEGE, 0); +const LUID SeSyncAgentPrivilege = CONST_LUID(SE_SYNC_AGENT_PRIVILEGE, 0); +const LUID SeEnableDelegationPrivilege = CONST_LUID(SE_ENABLE_DELEGATION_PRIVILEGE, 0); +const LUID SeManageVolumePrivilege = CONST_LUID(SE_MANAGE_VOLUME_PRIVILEGE, 0); +const LUID SeImpersonatePrivilege = CONST_LUID(SE_IMPERSONATE_PRIVILEGE, 0); +const LUID SeCreateGlobalPrivilege = CONST_LUID(SE_CREATE_GLOBAL_PRIVILEGE, 0); +const LUID SeTrustedCredmanPrivilege = CONST_LUID(SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE, 0); +const LUID SeRelabelPrivilege = CONST_LUID(SE_RELABEL_PRIVILEGE, 0); +const LUID SeIncreaseWorkingSetPrivilege = CONST_LUID(SE_INC_WORKING_SET_PRIVILEGE, 0); +const LUID SeTimeZonePrivilege = CONST_LUID(SE_TIME_ZONE_PRIVILEGE, 0); +const LUID SeCreateSymbolicLinkPrivilege = CONST_LUID(SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, 0); + /* PRIVATE FUNCTIONS **********************************************************/ VOID @@ -53,58 +63,7 @@ NTAPI SepInitPrivileges(VOID) { - SeCreateTokenPrivilege.LowPart = SE_CREATE_TOKEN_PRIVILEGE; - SeCreateTokenPrivilege.HighPart = 0; - SeAssignPrimaryTokenPrivilege.LowPart = SE_ASSIGNPRIMARYTOKEN_PRIVILEGE; - SeAssignPrimaryTokenPrivilege.HighPart = 0; - SeLockMemoryPrivilege.LowPart = SE_LOCK_MEMORY_PRIVILEGE; - SeLockMemoryPrivilege.HighPart = 0; - SeIncreaseQuotaPrivilege.LowPart = SE_INCREASE_QUOTA_PRIVILEGE; - SeIncreaseQuotaPrivilege.HighPart = 0; - SeUnsolicitedInputPrivilege.LowPart = SE_UNSOLICITED_INPUT_PRIVILEGE; - SeUnsolicitedInputPrivilege.HighPart = 0; - SeTcbPrivilege.LowPart = SE_TCB_PRIVILEGE; - SeTcbPrivilege.HighPart = 0; - SeSecurityPrivilege.LowPart = SE_SECURITY_PRIVILEGE; - SeSecurityPrivilege.HighPart = 0; - SeTakeOwnershipPrivilege.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE; - SeTakeOwnershipPrivilege.HighPart = 0; - SeLoadDriverPrivilege.LowPart = SE_LOAD_DRIVER_PRIVILEGE; - SeLoadDriverPrivilege.HighPart = 0; - SeSystemProfilePrivilege.LowPart = SE_SYSTEM_PROFILE_PRIVILEGE; - SeSystemProfilePrivilege.HighPart = 0; - SeSystemtimePrivilege.LowPart = SE_SYSTEMTIME_PRIVILEGE; - SeSystemtimePrivilege.HighPart = 0; - SeProfileSingleProcessPrivilege.LowPart = SE_PROF_SINGLE_PROCESS_PRIVILEGE; - SeProfileSingleProcessPrivilege.HighPart = 0; - SeIncreaseBasePriorityPrivilege.LowPart = SE_INC_BASE_PRIORITY_PRIVILEGE; - SeIncreaseBasePriorityPrivilege.HighPart = 0; - SeCreatePagefilePrivilege.LowPart = SE_CREATE_PAGEFILE_PRIVILEGE; - SeCreatePagefilePrivilege.HighPart = 0; - SeCreatePermanentPrivilege.LowPart = SE_CREATE_PERMANENT_PRIVILEGE; - SeCreatePermanentPrivilege.HighPart = 0; - SeBackupPrivilege.LowPart = SE_BACKUP_PRIVILEGE; - SeBackupPrivilege.HighPart = 0; - SeRestorePrivilege.LowPart = SE_RESTORE_PRIVILEGE; - SeRestorePrivilege.HighPart = 0; - SeShutdownPrivilege.LowPart = SE_SHUTDOWN_PRIVILEGE; - SeShutdownPrivilege.HighPart = 0; - SeDebugPrivilege.LowPart = SE_DEBUG_PRIVILEGE; - SeDebugPrivilege.HighPart = 0; - SeAuditPrivilege.LowPart = SE_AUDIT_PRIVILEGE; - SeAuditPrivilege.HighPart = 0; - SeSystemEnvironmentPrivilege.LowPart = SE_SYSTEM_ENVIRONMENT_PRIVILEGE; - SeSystemEnvironmentPrivilege.HighPart = 0; - SeChangeNotifyPrivilege.LowPart = SE_CHANGE_NOTIFY_PRIVILEGE; - SeChangeNotifyPrivilege.HighPart = 0; - SeRemoteShutdownPrivilege.LowPart = SE_REMOTE_SHUTDOWN_PRIVILEGE; - SeRemoteShutdownPrivilege.HighPart = 0; - SeUndockPrivilege.LowPart = SE_UNDOCK_PRIVILEGE; - SeUndockPrivilege.HighPart = 0; - SeSyncAgentPrivilege.LowPart = SE_SYNC_AGENT_PRIVILEGE; - SeSyncAgentPrivilege.HighPart = 0; - SeEnableDelegationPrivilege.LowPart = SE_ENABLE_DELEGATION_PRIVILEGE; - SeEnableDelegationPrivilege.HighPart = 0; + } @@ -233,7 +192,7 @@ return STATUS_INSUFFICIENT_RESOURCES; } } - + /* copy the array to the buffer */ _SEH2_TRY { Index: ntoskrnl/se/token.c =================================================================== --- ntoskrnl/se/token.c (revision 61022) +++ ntoskrnl/se/token.c (working copy) @@ -101,7 +101,96 @@ return STATUS_SUCCESS; } +static VOID +SepUpdateSinglePrivilegeFlagToken( + _Inout_ PTOKEN Token, + _In_ ULONG Index) +{ + ULONG TokenFlag; + NT_ASSERT(Index < Token->PrivilegeCount); + + /* The high part of all values we are interested in is 0 */ + if (Token->Privileges[Index].Luid.HighPart != 0) + { + return; + } + + /* Check for certain privileges to update flags */ + if (Token->Privileges[Index].Luid.LowPart == SE_CHANGE_NOTIFY_PRIVILEGE) + { + TokenFlag = TOKEN_HAS_TRAVERSE_PRIVILEGE; + } + else if (Token->Privileges[Index].Luid.LowPart == SE_BACKUP_PRIVILEGE) + { + TokenFlag = TOKEN_HAS_BACKUP_PRIVILEGE; + } + else if (Token->Privileges[Index].Luid.LowPart == SE_RESTORE_PRIVILEGE) + { + TokenFlag = TOKEN_HAS_RESTORE_PRIVILEGE; + } + else if (Token->Privileges[Index].Luid.LowPart == SE_IMPERSONATE_PRIVILEGE) + { + TokenFlag = TOKEN_HAS_IMPERSONATE_PRIVILEGE; + } + else + { + /* Nothing to do */ + return; + } + + /* Check if the specified privilege is enabled */ + if (Token->Privileges[Index].Attributes & SE_PRIVILEGE_ENABLED) + { + /* It is enabled, so set the flag */ + Token->TokenFlags |= TokenFlag; + } + else + { + /* Is is disabled, so remove the flag */ + Token->TokenFlags &= ~TokenFlag; + } +} + +static +VOID +SepUpdatePrivilegeFlagsToken( + _Inout_ PTOKEN Token) +{ + ULONG i; + + /* Loop all privileges */ + for (i = 0; i < Token->PrivilegeCount; i++) + { + /* Updates the flags dor this privilege */ + SepUpdateSinglePrivilegeFlagToken(Token, i); + } +} + +static +VOID +SepRemovePrivilegeToken( + _Inout_ PTOKEN Token, + _In_ ULONG Index) +{ + ULONG MoveCount; + NT_ASSERT(Index < Token->PrivilegeCount); + + /* Calculate the number of trailing privileges */ + MoveCount = Token->PrivilegeCount - Index - 1; + if (MoveCount != 0) + { + /* Move them one location ahead */ + RtlMoveMemory(&Token->Privileges[Index], + &Token->Privileges[Index + 1], + MoveCount * sizeof(LUID_AND_ATTRIBUTES)); + } + + /* Update privilege count */ + Token->PrivilegeCount--; +} + +VOID NTAPI SepFreeProxyData(PVOID ProxyData) { @@ -592,18 +681,6 @@ } } - /* Loop all privileges */ - for (i = 0; i < PrivilegeCount; i++) - { - /* For optimization, check for change notify and impersonate rights */ - if (((RtlEqualLuid(&Privileges[i].Luid, &SeChangeNotifyPrivilege)) && - (Privileges[i].Attributes & SE_PRIVILEGE_ENABLED))) - { - /* Remember token has traverse */ - TokenFlags |= TOKEN_HAS_TRAVERSE_PRIVILEGE; - } - } - Status = ZwAllocateLocallyUniqueId(&TokenId); if (!NT_SUCCESS(Status)) return Status; @@ -732,6 +809,9 @@ if (!NT_SUCCESS(Status)) goto done; + /* Update privilege flags */ + SepUpdatePrivilegeFlagsToken(AccessToken); + AccessToken->DefaultDacl = ExAllocatePoolWithTag(PagedPool, DefaultDacl->AclSize, TAG_TOKEN_ACL); @@ -769,15 +849,7 @@ { if (AccessToken) { - if (AccessToken->UserAndGroups) - ExFreePoolWithTag(AccessToken->UserAndGroups, TAG_TOKEN_USERS); - - if (AccessToken->Privileges) - ExFreePoolWithTag(AccessToken->Privileges, TAG_TOKEN_PRIVILAGES); - - if (AccessToken->DefaultDacl) - ExFreePoolWithTag(AccessToken->DefaultDacl, TAG_TOKEN_ACL); - + /* Dereference the token, the delete procedure will clean up */ ObDereferenceObject(AccessToken); } } @@ -1995,16 +2067,136 @@ return(STATUS_NOT_IMPLEMENTED); } + +static +ULONG +SepAdjustPrivileges( + _Inout_ PTOKEN Token, + _In_ BOOLEAN DisableAllPrivileges, + _In_opt_ PLUID_AND_ATTRIBUTES NewState, + _In_ ULONG NewStateCount, + _Out_opt_ PTOKEN_PRIVILEGES PreviousState, + _In_ BOOLEAN ApplyChanges, + _Out_ PULONG ChangedPrivileges) +{ + ULONG i, j, PrivilegeCount, ChangeCount, NewAttributes; + + /* Count the found privileges and those that need to be changed */ + PrivilegeCount = 0; + ChangeCount = 0; + + /* Loop all privileges in the token */ + for (i = 0; i < Token->PrivilegeCount; i++) + { + /* Shall all of them be disabled? */ + if (DisableAllPrivileges) + { + /* The new attributes are the old ones, but disabled */ + NewAttributes = Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED; + } + else + { + /* Otherwise loop all provided privileges */ + for (j = 0; j < NewStateCount; j++) + { + /* Check if this is the LUID we are looking for */ + if (RtlEqualLuid(&Token->Privileges[i].Luid, &NewState[j].Luid)) + { + DPRINT("Found privilege\n"); + + /* Copy SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED */ + NewAttributes = NewState[j].Attributes; + NewAttributes &= (SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED); + NewAttributes |= Token->Privileges[i].Attributes & ~SE_PRIVILEGE_ENABLED; + + /* Stop looking */ + break; + } + } + + /* Check if we didn't find the privilege */ + if (j == NewStateCount) + { + /* Continue with the token's next privilege */ + continue; + } + } + + /* We found a privilege, count it */ + PrivilegeCount++; + + /* Does the privilege need to be changed? */ + if (Token->Privileges[i].Attributes != NewAttributes) + { + /* Does the caller want the old privileges? */ + if (PreviousState != NULL) + { + /* Copy the old privilege */ + PreviousState->Privileges[ChangeCount] = Token->Privileges[i]; + } + + /* Does the caller want to apply the changes? */ + if (ApplyChanges) + { + /* Shall we remove the privilege? */ + if (NewAttributes & SE_PRIVILEGE_REMOVED) + { + /* Set the token as disabled and update flags for it */ + Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED; + SepUpdateSinglePrivilegeFlagToken(Token, i); + + /* Remove the privilege */ + SepRemovePrivilegeToken(Token, i); + + /* Fix the running index */ + i--; + + /* Continue with next */ + continue; + } + + /* Set the new attributes and update flags */ + Token->Privileges[i].Attributes = NewAttributes; + SepUpdateSinglePrivilegeFlagToken(Token, i); + } + + /* Increment the change count */ + ChangeCount++; + } + } + + /* Set the number of saved privileges */ + if (PreviousState != NULL) + PreviousState->PrivilegeCount = ChangeCount; + + /* Return the number of changed privileges */ + *ChangedPrivileges = ChangeCount; + + /* Check if we missed some */ + if (!DisableAllPrivileges && (PrivilegeCount < NewStateCount)) + { + return STATUS_NOT_ALL_ASSIGNED; + } + + return STATUS_SUCCESS; +} + + /* * @implemented */ -NTSTATUS NTAPI -NtAdjustPrivilegesToken(IN HANDLE TokenHandle, - IN BOOLEAN DisableAllPrivileges, - IN PTOKEN_PRIVILEGES NewState, - IN ULONG BufferLength, - OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, - OUT PULONG ReturnLength OPTIONAL) +_Must_inspect_result_ +__kernel_entry +NTSTATUS +NTAPI +NtAdjustPrivilegesToken( + _In_ HANDLE TokenHandle, + _In_ BOOLEAN DisableAllPrivileges, + _In_opt_ PTOKEN_PRIVILEGES NewState, + _In_ ULONG BufferLength, + _Out_writes_bytes_to_opt_(BufferLength,*ReturnLength) + PTOKEN_PRIVILEGES PreviousState, + _When_(PreviousState!=NULL, _Out_) PULONG ReturnLength) { PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL; KPROCESSOR_MODE PreviousMode; @@ -2012,14 +2204,12 @@ ULONG CapturedLength = 0; ULONG NewStateSize = 0; ULONG ChangeCount; + ULONG RequiredLength; PTOKEN Token; - ULONG i; - ULONG j; NTSTATUS Status; - PAGED_CODE(); - DPRINT ("NtAdjustPrivilegesToken() called\n"); + DPRINT("NtAdjustPrivilegesToken() called\n"); /* Fail, if we do not disable all privileges but NewState is NULL */ if (DisableAllPrivileges == FALSE && NewState == NULL) @@ -2033,29 +2223,20 @@ /* Probe NewState */ if (DisableAllPrivileges == FALSE) { - ProbeForRead(NewState, - sizeof(TOKEN_PRIVILEGES), - sizeof(ULONG)); + /* First probe the header */ + ProbeForRead(NewState, sizeof(TOKEN_PRIVILEGES), sizeof(ULONG)); CapturedCount = NewState->PrivilegeCount; - NewStateSize = (ULONG)sizeof(TOKEN_PRIVILEGES) + - ((CapturedCount - ANYSIZE_ARRAY) * (ULONG)sizeof(LUID_AND_ATTRIBUTES)); + NewStateSize = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[CapturedCount]); - ProbeForRead(NewState, - NewStateSize, - sizeof(ULONG)); + ProbeForRead(NewState, NewStateSize, sizeof(ULONG)); } /* Probe PreviousState and ReturnLength */ if (PreviousState != NULL) { - ProbeForWrite(PreviousState, - BufferLength, - sizeof(ULONG)); - - ProbeForWrite(ReturnLength, - sizeof(ULONG), - sizeof(ULONG)); + ProbeForWrite(PreviousState, BufferLength, sizeof(ULONG)); + ProbeForWrite(ReturnLength, sizeof(ULONG), sizeof(ULONG)); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) @@ -2067,10 +2248,12 @@ } else { + /* This is kernel mode, we trust the caller */ if (DisableAllPrivileges == FALSE) CapturedCount = NewState->PrivilegeCount; } + /* Do we need to capture the new state? */ if (DisableAllPrivileges == FALSE) { _SEH2_TRY @@ -2089,7 +2272,7 @@ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Return the exception code */ - _SEH2_YIELD(return _SEH2_GetExceptionCode()); + Status = _SEH2_GetExceptionCode(); } _SEH2_END; @@ -2106,7 +2289,7 @@ NULL); if (!NT_SUCCESS(Status)) { - DPRINT1 ("Failed to reference token (Status %lx)\n", Status); + DPRINT1("Failed to reference token (Status %lx)\n", Status); /* Release the captured privileges */ if (CapturedPrivileges != NULL) @@ -2117,51 +2300,23 @@ return Status; } - /* Count the privileges that need to be changed */ - ChangeCount = 0; - for (i = 0; i < Token->PrivilegeCount; i++) - { - if (DisableAllPrivileges) - { - if (Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) - { - DPRINT("Privilege enabled\n"); + /* Lock the token */ + ExEnterCriticalRegionAndAcquireResourceExclusive(Token->TokenLock); - ChangeCount++; - } - } - else - { - for (j = 0; j < CapturedCount; j++) - { - if (Token->Privileges[i].Luid.LowPart == CapturedPrivileges[j].Luid.LowPart && - Token->Privileges[i].Luid.HighPart == CapturedPrivileges[j].Luid.HighPart) - { - DPRINT("Found privilege\n"); + /* Count the privileges that need to be changed, do not apply them yet */ + Status = SepAdjustPrivileges(Token, + DisableAllPrivileges, + CapturedPrivileges, + CapturedCount, + NULL, + FALSE, + &ChangeCount); - if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) != - (CapturedPrivileges[j].Attributes & SE_PRIVILEGE_ENABLED)) - { - DPRINT("Attributes differ\n"); - DPRINT("Current attributes %lx New attributes %lx\n", - Token->Privileges[i].Attributes, - CapturedPrivileges[j].Attributes); - - ChangeCount++; - } - } - } - } - } - - /* - * Return the required buffer size and - * check if the available buffer is large enough - */ + /* Check if the caller asked for the previous state */ if (PreviousState != NULL) { - ULONG RequiredLength = (ULONG)sizeof(TOKEN_PRIVILEGES) + - ((ChangeCount - ANYSIZE_ARRAY) * (ULONG)sizeof(LUID_AND_ATTRIBUTES)); + /* Calculate the required length */ + RequiredLength = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[ChangeCount]); /* Try to return the required buffer length */ _SEH2_TRY @@ -2170,17 +2325,9 @@ } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Dereference the token */ - ObDereferenceObject(Token); - - /* Release the captured privileges */ - if (CapturedPrivileges != NULL) - SeReleaseLuidAndAttributesArray(CapturedPrivileges, - PreviousMode, - TRUE); - - /* Return the exception code */ - _SEH2_YIELD(return _SEH2_GetExceptionCode()); + /* Do cleanup and return the exception code */ + Status = _SEH2_GetExceptionCode(); + goto Cleanup; } _SEH2_END; @@ -2187,109 +2334,36 @@ /* Fail, if the buffer length is smaller than the required length */ if (BufferLength < RequiredLength) { - /* Dereference the token */ - ObDereferenceObject(Token); - - /* Release the captured privileges */ - if (CapturedPrivileges != NULL) - SeReleaseLuidAndAttributesArray(CapturedPrivileges, - PreviousMode, - TRUE); - - return STATUS_BUFFER_TOO_SMALL; + Status = STATUS_BUFFER_TOO_SMALL; + goto Cleanup; } } - /* Change the privilege attributes */ - ChangeCount = 0; + /* Now enter SEH, since we might return the old privileges */ _SEH2_TRY { - for (i = 0; i < Token->PrivilegeCount; i++) - { - if (DisableAllPrivileges == TRUE) - { - if (Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) - { - DPRINT("Privilege enabled\n"); - - /* Save the current privilege */ - if (PreviousState != NULL) - { - PreviousState->Privileges[ChangeCount].Luid = Token->Privileges[i].Luid; - PreviousState->Privileges[ChangeCount].Attributes = Token->Privileges[i].Attributes; - } - - /* Disable the current privlege */ - Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED; - - ChangeCount++; - } - } - else - { - for (j = 0; j < CapturedCount; j++) - { - if (Token->Privileges[i].Luid.LowPart == CapturedPrivileges[j].Luid.LowPart && - Token->Privileges[i].Luid.HighPart == CapturedPrivileges[j].Luid.HighPart) - { - DPRINT("Found privilege\n"); - - /* Check whether the attributes differ */ - if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) != - (CapturedPrivileges[j].Attributes & SE_PRIVILEGE_ENABLED)) - { - DPRINT("Attributes differ\n"); - DPRINT("Current attributes %lx New attributes %lx\n", - Token->Privileges[i].Attributes, - CapturedPrivileges[j].Attributes); - - /* Save the current privilege */ - if (PreviousState != NULL) - { - PreviousState->Privileges[ChangeCount].Luid = Token->Privileges[i].Luid; - PreviousState->Privileges[ChangeCount].Attributes = Token->Privileges[i].Attributes; - } - - /* Update the current privlege */ - Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED; - Token->Privileges[i].Attributes |= - (CapturedPrivileges[j].Attributes & SE_PRIVILEGE_ENABLED); - DPRINT("New attributes %lx\n", - Token->Privileges[i].Attributes); - - ChangeCount++; - } - } - } - } - } - - /* Set the number of saved privileges */ - if (PreviousState != NULL) - PreviousState->PrivilegeCount = ChangeCount; + /* This time apply the changes */ + Status = SepAdjustPrivileges(Token, + DisableAllPrivileges, + CapturedPrivileges, + CapturedCount, + PreviousState, + TRUE, + &ChangeCount); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Dereference the token */ - ObDereferenceObject(Token); - - /* Release the captured privileges */ - if (CapturedPrivileges != NULL) - SeReleaseLuidAndAttributesArray(CapturedPrivileges, - PreviousMode, - TRUE); - - /* Return the exception code */ - _SEH2_YIELD(return _SEH2_GetExceptionCode()); + /* Do cleanup and return the exception code */ + Status = _SEH2_GetExceptionCode(); + goto Cleanup; } _SEH2_END; - /* Set the status */ - Status = (ChangeCount < CapturedCount) ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS; +Cleanup: + /* Unlock and dereference the token */ + ExReleaseResourceAndLeaveCriticalRegion(Token->TokenLock); + ObDereferenceObject(Token); - /* Dereference the token */ - ObDereferenceObject (Token); - /* Release the captured privileges */ if (CapturedPrivileges != NULL) SeReleaseLuidAndAttributesArray(CapturedPrivileges, @@ -2297,7 +2371,6 @@ TRUE); DPRINT ("NtAdjustPrivilegesToken() done\n"); - return Status; }