mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[NTOS:PS] Do not reference the copied token twice and properly assign the impersonation level in case the server can't impersonate
As it currently stands the PsImpersonateClient routine does the following approach. If impersonation couldn't be granted to a client the routine will make a copy of the client's access token. As it makes a copy of the said token PsImpersonateClient will reference the copied token after impersonation info have been filled out. In the same code path we are assigning the desired level for impersonation to thread impersonation info. This is wrong for two reasons: - On a copy situation the SeCopyClientToken routine holds a reference as the object has been created. Referencing it at the bottom of the PsImpersonateClient routine will make it that the token is referenced twice and whenever a server stops impersonation the token still has an extra reference count which keeps the token still alive in object database and memory space. - If client impersonation is not possible the thread impersonation info should have been assigned SecurityIdentification level to further indicate that the actual impersonation of the thread is not currently in force but instead we are assigning the impersonation level that is supplied by the caller. For instance if the requested level is SecurityDelegation but impersonation is not possible the level will be assigned that of SecurityDelegation yet the token has an impersonation level of SecurityIdentification. This could lead to erratic behaviors as well as potential impersonation escalation. Fix the aforementioned issues by avoiding a double reference and properly assign the impersonation level to SecurityIdentification if the server is not able to impersonate the target client.
This commit is contained in:
parent
f483e42f89
commit
8e2fe925f2
1 changed files with 24 additions and 2 deletions
|
@ -615,6 +615,7 @@ PsImpersonateClient(IN PETHREAD Thread,
|
|||
{
|
||||
PPS_IMPERSONATION_INFORMATION Impersonation, OldData;
|
||||
PTOKEN OldToken = NULL, ProcessToken = NULL;
|
||||
BOOLEAN CopiedToken = FALSE;
|
||||
PACCESS_TOKEN NewToken, ImpersonationToken;
|
||||
PEJOB Job;
|
||||
NTSTATUS Status;
|
||||
|
@ -706,7 +707,13 @@ PsImpersonateClient(IN PETHREAD Thread,
|
|||
return Status;
|
||||
}
|
||||
|
||||
/* Since we cannot impersonate, assign the newly copied token */
|
||||
/*
|
||||
* Since we cannot impersonate, assign the newly copied token.
|
||||
* SeCopyClientToken already holds a reference to the copied token,
|
||||
* let the code path below know that it must not reference it twice.
|
||||
*/
|
||||
CopiedToken = TRUE;
|
||||
ImpersonationLevel = SecurityIdentification;
|
||||
ImpersonationToken = NewToken;
|
||||
}
|
||||
|
||||
|
@ -721,6 +728,11 @@ PsImpersonateClient(IN PETHREAD Thread,
|
|||
if ((Job->SecurityLimitFlags & JOB_OBJECT_SECURITY_NO_ADMIN) &&
|
||||
SeTokenIsAdmin(ImpersonationToken))
|
||||
{
|
||||
if (CopiedToken)
|
||||
{
|
||||
ObDereferenceObject(ImpersonationToken);
|
||||
}
|
||||
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
|
@ -728,6 +740,11 @@ PsImpersonateClient(IN PETHREAD Thread,
|
|||
if ((Job->SecurityLimitFlags & JOB_OBJECT_SECURITY_RESTRICTED_TOKEN) &&
|
||||
SeTokenIsRestricted(ImpersonationToken))
|
||||
{
|
||||
if (CopiedToken)
|
||||
{
|
||||
ObDereferenceObject(ImpersonationToken);
|
||||
}
|
||||
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
|
@ -758,7 +775,12 @@ PsImpersonateClient(IN PETHREAD Thread,
|
|||
Impersonation->CopyOnOpen = CopyOnOpen;
|
||||
Impersonation->EffectiveOnly = EffectiveOnly;
|
||||
Impersonation->Token = ImpersonationToken;
|
||||
ObReferenceObject(ImpersonationToken);
|
||||
|
||||
/* Do not reference the token again if we copied it */
|
||||
if (!CopiedToken)
|
||||
{
|
||||
ObReferenceObject(ImpersonationToken);
|
||||
}
|
||||
|
||||
/* Unlock the thread */
|
||||
PspUnlockThreadSecurityExclusive(Thread);
|
||||
|
|
Loading…
Reference in a new issue