Status = SeSubProcessToken(ParentToken,
&NewToken,
TRUE,
- 0);//MmGetSessionId(Process));
+ MmGetSessionId(Process));
/* Dereference the Parent */
ObFastDereferenceObject(&Parent->Token, ParentToken);
/* Reference it from the handle */
Status = ObReferenceObjectByHandle(Token,
TOKEN_ASSIGN_PRIMARY,
- SepTokenObjectType,
+ SeTokenObjectType,
ExGetPreviousMode(),
&NewToken,
NULL);
/* Dereference Tokens and Return */
if (NT_SUCCESS(Status)) ObDereferenceObject(OldToken);
- if (AccessToken) ObDereferenceObject(NewToken);
+ if (!AccessToken) ObDereferenceObject(NewToken);
return Status;
}
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;
+ 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,
- SepTokenObjectType,
+ SeTokenObjectType,
PreviousMode,
(PVOID*)&NewToken,
NULL);
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;
}
}
STANDARD_RIGHTS_ALL |
PROCESS_SET_QUOTA);
}
+
+ /*
+ * In case LUID device maps are enable, we may not be using
+ * system device map for this process, but a logon LUID based
+ * device map. Because we change primary token, this usage is
+ * no longer valid, so dereference the process device map
+ */
+ if (ObIsLUIDDeviceMapsEnabled()) ObDereferenceDeviceMap(Process);
}
/* 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))
HandleAttributes,
NULL,
DesiredAccess,
- SepTokenObjectType,
+ SeTokenObjectType,
PreviousMode,
&hToken);
ObDereferenceObject(Token);
/* Get the token object */
Status = ObReferenceObjectByHandle(TokenHandle,
TOKEN_IMPERSONATE,
- SepTokenObjectType,
+ SeTokenObjectType,
KeGetPreviousMode(),
(PVOID*)&Token,
NULL);
if (OldData)
{
/* Someone beat us to it, free our copy */
- ExFreePool(Impersonation);
+ ExFreePoolWithTag(Impersonation, TAG_PS_IMPERSONATION);
Impersonation = OldData;
}
}
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;
/* Reference the thread */
Status = ObReferenceObjectByHandle(ThreadHandle,
- THREAD_IMPERSONATE,
+ THREAD_DIRECT_IMPERSONATION,
PsThreadType,
PreviousMode,
(PVOID*)&Thread,
NULL);
- if(NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
{
/* Reference the impersonating thead */
Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle,
- THREAD_DIRECT_IMPERSONATION,
+ THREAD_IMPERSONATE,
PsThreadType,
PreviousMode,
(PVOID*)&ThreadToImpersonate,
NULL);
- if(NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
{
/* Create a client security context */
Status = SeCreateClientSecurity(ThreadToImpersonate,
SecurityQualityOfService,
0,
&ClientContext);
- if(NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
{
/* Do the impersonation */
SeImpersonateClient(&ClientContext, Thread);
- if(ClientContext.ClientToken)
+ if (ClientContext.ClientToken)
{
/* Dereference the client token if we had one */
ObDereferenceObject(ClientContext.ClientToken);