IN PACCESS_TOKEN Token OPTIONAL)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- BOOLEAN IsChild;
+ BOOLEAN IsChildOrSibling;
PACCESS_TOKEN NewToken = Token;
NTSTATUS Status, AccessStatus;
BOOLEAN Result, SdAllocated;
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
SECURITY_SUBJECT_CONTEXT SubjectContext;
+
PSTRACE(PS_SECURITY_DEBUG, "Process: %p Token: %p\n", Process, Token);
- /* Make sure we got a handle */
- if (TokenHandle)
+ /* Reference the token by handle if we don't already have a token object */
+ if (!Token)
{
- /* Reference it */
Status = ObReferenceObjectByHandle(TokenHandle,
TOKEN_ASSIGN_PRIMARY,
SeTokenObjectType,
if (!NT_SUCCESS(Status)) return Status;
}
- /* Check if this is a child */
- Status = SeIsTokenChild(NewToken, &IsChild);
+ /*
+ * Check whether this token is a child or sibling of the current process token.
+ * NOTE: On Windows Vista+ both of these checks (together with extra steps)
+ * are now performed by a new SeIsTokenAssignableToProcess() helper.
+ */
+ Status = SeIsTokenChild(NewToken, &IsChildOrSibling);
if (!NT_SUCCESS(Status))
{
/* Failed, dereference */
- if (TokenHandle) ObDereferenceObject(NewToken);
+ if (!Token) ObDereferenceObject(NewToken);
return Status;
}
+ if (!IsChildOrSibling)
+ {
+ Status = SeIsTokenSibling(NewToken, &IsChildOrSibling);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed, dereference */
+ if (!Token) ObDereferenceObject(NewToken);
+ return Status;
+ }
+ }
/* Check if this was an independent token */
- if (!IsChild)
+ if (!IsChildOrSibling)
{
/* Make sure we have the privilege to assign a new one */
if (!SeSinglePrivilegeCheck(SeAssignPrimaryTokenPrivilege,
PreviousMode))
{
/* Failed, dereference */
- if (TokenHandle) ObDereferenceObject(NewToken);
+ if (!Token) ObDereferenceObject(NewToken);
return STATUS_PRIVILEGE_NOT_HELD;
}
}
}
/* Dereference the token */
- if (TokenHandle) ObDereferenceObject(NewToken);
+ if (!Token) ObDereferenceObject(NewToken);
return Status;
}
_SEH2_END;
}
+ /* Validate object attributes */
+ HandleAttributes = ObpValidateAttributes(HandleAttributes, PreviousMode);
+
/* Open the process token */
Status = PsOpenTokenOfProcess(ProcessHandle, &Token);
if (NT_SUCCESS(Status))
PsReferenceEffectiveToken(IN PETHREAD Thread,
OUT IN PTOKEN_TYPE TokenType,
OUT PBOOLEAN EffectiveOnly,
- OUT PSECURITY_IMPERSONATION_LEVEL Level)
+ OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
{
PEPROCESS Process;
PACCESS_TOKEN Token = NULL;
+
PAGED_CODE();
+
PSTRACE(PS_SECURITY_DEBUG,
"Thread: %p, TokenType: %p\n", Thread, TokenType);
/* Check if we don't have impersonation info */
Process = Thread->ThreadsProcess;
- if (!Thread->ActiveImpersonationInfo)
- {
- /* Fast Reference the Token */
- Token = ObFastReferenceObject(&Process->Token);
-
- /* Check if we got the Token or if we got locked */
- if (!Token)
- {
- /* Lock the Process */
- PspLockProcessSecurityShared(Process);
-
- /* Do a Locked Fast Reference */
- Token = ObFastReferenceObjectLocked(&Process->Token);
-
- /* Unlock the Process */
- PspUnlockProcessSecurityShared(Process);
- }
- }
- else
+ if (Thread->ActiveImpersonationInfo)
{
/* Lock the Process */
PspLockProcessSecurityShared(Process);
/* Return data to caller */
*TokenType = TokenImpersonation;
*EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
- *Level = Thread->ImpersonationInfo->ImpersonationLevel;
+ *ImpersonationLevel = Thread->ImpersonationInfo->ImpersonationLevel;
/* Unlock the Process */
PspUnlockProcessSecurityShared(Process);
PspUnlockProcessSecurityShared(Process);
}
+ /* Fast Reference the Token */
+ Token = ObFastReferenceObject(&Process->Token);
+
+ /* Check if we got the Token or if we got locked */
+ if (!Token)
+ {
+ /* Lock the Process */
+ PspLockProcessSecurityShared(Process);
+
+ /* Do a Locked Fast Reference */
+ Token = ObFastReferenceObjectLocked(&Process->Token);
+
+ /* Unlock the Process */
+ PspUnlockProcessSecurityShared(Process);
+ }
+
/* Return the token */
*TokenType = TokenPrimary;
*EffectiveOnly = FALSE;
+ // NOTE: ImpersonationLevel is left untouched on purpose!
return Token;
}
BOOLEAN
NTAPI
PsDisableImpersonation(IN PETHREAD Thread,
- IN PSE_IMPERSONATION_STATE ImpersonationState)
+ OUT PSE_IMPERSONATION_STATE ImpersonationState)
{
PPS_IMPERSONATION_INFORMATION Impersonation = NULL;
- LONG NewValue, OldValue;
+ LONG OldFlags;
PAGED_CODE();
PSTRACE(PS_SECURITY_DEBUG,
"Thread: %p State: %p\n", Thread, ImpersonationState);
PspLockThreadSecurityExclusive(Thread);
/* Disable impersonation */
- OldValue = Thread->CrossThreadFlags;
- do
- {
- /* Attempt to change the flag */
- NewValue =
- InterlockedCompareExchange((PLONG)&Thread->CrossThreadFlags,
- OldValue &~
- CT_ACTIVE_IMPERSONATION_INFO_BIT,
- OldValue);
- } while (NewValue != OldValue);
+ OldFlags = PspClearCrossThreadFlag(Thread,
+ CT_ACTIVE_IMPERSONATION_INFO_BIT);
/* Make sure nobody disabled it behind our back */
- if (NewValue & CT_ACTIVE_IMPERSONATION_INFO_BIT)
+ if (OldFlags & CT_ACTIVE_IMPERSONATION_INFO_BIT)
{
/* Copy the old state */
Impersonation = Thread->ImpersonationInfo;