}
/* FIXME: Check if every privilege that is present in either token is also present in the other one */
+ DPRINT1("FIXME: Pretending tokens are equal!\n");
+ IsEqual = TRUE;
}
*Equal = IsEqual;
_In_ ULONG Index)
{
ULONG TokenFlag;
- NT_ASSERT(Index < Token->PrivilegeCount);
+ ASSERT(Index < Token->PrivilegeCount);
/* The high part of all values we are interested in is 0 */
if (Token->Privileges[Index].Luid.HighPart != 0)
_In_ ULONG Index)
{
ULONG MoveCount;
- NT_ASSERT(Index < Token->PrivilegeCount);
+ ASSERT(Index < Token->PrivilegeCount);
/* Calculate the number of trailing privileges */
MoveCount = Token->PrivilegeCount - Index - 1;
PAGED_CODE();
if (NewToken->TokenType != TokenPrimary) return(STATUS_BAD_TOKEN_TYPE);
- if (NewToken->TokenInUse) return(STATUS_TOKEN_ALREADY_IN_USE);
+ if (NewToken->TokenInUse)
+ {
+ BOOLEAN IsEqual;
+ NTSTATUS Status;
+
+ /* Maybe we're trying to set the same token */
+ OldToken = PsReferencePrimaryToken(Process);
+ if (OldToken == NewToken)
+ {
+ /* So it's a nop. */
+ *OldTokenP = OldToken;
+ return STATUS_SUCCESS;
+ }
+
+ Status = SepCompareTokens(OldToken, NewToken, &IsEqual);
+ if (!NT_SUCCESS(Status))
+ {
+ *OldTokenP = NULL;
+ PsDereferencePrimaryToken(OldToken);
+ return Status;
+ }
+
+ if (!IsEqual)
+ {
+ *OldTokenP = NULL;
+ PsDereferencePrimaryToken(OldToken);
+ return STATUS_TOKEN_ALREADY_IN_USE;
+ }
+ /* Silently return STATUS_SUCCESS but do not set the new token,
+ * as it's already in use elsewhere. */
+ *OldTokenP = OldToken;
+ return STATUS_SUCCESS;
+ }
/* Mark new token in use */
NewToken->TokenInUse = 1;
/* Mark the Old Token as free */
OldToken->TokenInUse = 0;
+
+ /* Dereference the Token */
+ ObDereferenceObject(OldToken);
}
static ULONG
/* Zero out the buffer */
RtlZeroMemory(AccessToken, sizeof(TOKEN));
- Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(AccessToken);
- return Status;
- }
-
- Status = ZwAllocateLocallyUniqueId(&AccessToken->ModifiedId);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(AccessToken);
- return Status;
- }
+ ExAllocateLocallyUniqueId(&AccessToken->TokenId);
AccessToken->TokenLock = &SepTokenLock;
AccessToken->TokenType = TokenType;
AccessToken->ImpersonationLevel = Level;
RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId);
+ RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId);
AccessToken->TokenSource.SourceIdentifier.LowPart = Token->TokenSource.SourceIdentifier.LowPart;
AccessToken->TokenSource.SourceIdentifier.HighPart = Token->TokenSource.SourceIdentifier.HighPart;
*NewAccessToken = AccessToken;
+ /* Reference the logon session */
+ SepRmReferenceLogonSession(&AccessToken->AuthenticationId);
+
done:
if (!NT_SUCCESS(Status))
{
ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess());
/* Get the ID */
- ProcessLuid = ProcessToken->TokenId;
+ ProcessLuid = ProcessToken->AuthenticationId;
/* Dereference the token */
ObFastDereferenceObject(&PsGetCurrentProcess()->Token, ProcessToken);
/* Get our LUID */
- CallerLuid = Token->TokenId;
+ CallerLuid = Token->AuthenticationId;
/* Compare the LUIDs */
if (RtlEqualLuid(&CallerLuid, &ProcessLuid)) *IsChild = TRUE;
{
PTOKEN AccessToken = (PTOKEN)ObjectBody;
+ DPRINT("SepDeleteToken()\n");
+
+ /* Dereference the logon session */
+ SepRmDereferenceLogonSession(&AccessToken->AuthenticationId);
+
if (AccessToken->UserAndGroups)
ExFreePoolWithTag(AccessToken->UserAndGroups, TAG_TOKEN_USERS);
NTSTATUS Status;
ULONG TokenFlags = 0;
+ PAGED_CODE();
+
/* Loop all groups */
for (i = 0; i < GroupCount; i++)
{
}
}
- Status = ZwAllocateLocallyUniqueId(&TokenId);
- if (!NT_SUCCESS(Status))
- return Status;
-
- Status = ZwAllocateLocallyUniqueId(&ModifiedId);
- if (!NT_SUCCESS(Status))
- return Status;
+ ExAllocateLocallyUniqueId(&TokenId);
+ ExAllocateLocallyUniqueId(&ModifiedId);
Status = ObCreateObject(PreviousMode,
SeTokenObjectType,
*TokenHandle = (HANDLE)AccessToken;
}
+ /* Reference the logon session */
+ SepRmReferenceLogonSession(AuthenticationId);
+
done:
if (!NT_SUCCESS(Status))
{
IN TOKEN_INFORMATION_CLASS TokenInformationClass,
OUT PVOID *TokenInformation)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+ PSECURITY_IMPERSONATION_LEVEL SeImpersonationLvl;
+ PAGED_CODE();
+
+ if (TokenInformationClass >= MaxTokenInfoClass)
+ {
+ DPRINT1("SeQueryInformationToken(%d) invalid information class\n", TokenInformationClass);
+ return STATUS_INVALID_INFO_CLASS;
+ }
+
+ switch (TokenInformationClass)
+ {
+ case TokenImpersonationLevel:
+ /* It is mandatory to have an impersonation token */
+ if (((PTOKEN)Token)->TokenType != TokenImpersonation)
+ {
+ Status = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ /* Allocate the output buffer */
+ SeImpersonationLvl = ExAllocatePoolWithTag(PagedPool, sizeof(SECURITY_IMPERSONATION_LEVEL), TAG_SE);
+ if (SeImpersonationLvl == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ /* Set impersonation level and return the structure */
+ *SeImpersonationLvl = ((PTOKEN)Token)->ImpersonationLevel;
+ *TokenInformation = SeImpersonationLvl;
+ Status = STATUS_SUCCESS;
+ break;
+
+ default:
+ UNIMPLEMENTED;
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+
+ return Status;
}
/*
ExFreePoolWithTag(Token->DefaultDacl, TAG_TOKEN_ACL);
}
- /* Set the new dacl */
- Token->DefaultDacl = CapturedAcl;
+ Token->DefaultDacl = ExAllocatePoolWithTag(PagedPool,
+ CapturedAcl->AclSize,
+ TAG_TOKEN_ACL);
+ if (!Token->DefaultDacl)
+ {
+ ExFreePoolWithTag(CapturedAcl, TAG_ACL);
+ Status = STATUS_NO_MEMORY;
+ }
+ else
+ {
+ /* Set the new dacl */
+ RtlCopyMemory(Token->DefaultDacl, CapturedAcl, CapturedAcl->AclSize);
+ ExFreePoolWithTag(CapturedAcl, TAG_ACL);
+ }
}
}
else
NonPagedPool,
FALSE,
&CapturedDefaultDacl);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
}
/* Call the internal function */
_SEH2_END;
}
+ /* Validate object attributes */
+ HandleAttributes = ObpValidateAttributes(HandleAttributes, PreviousMode);
+
/*
* At first open the thread token for information access and verify
- * that the token associated with thread is valid.
- */
+ * that the token associated with thread is valid. */
Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_QUERY_INFORMATION,
PsThreadType, PreviousMode, (PVOID*)&Thread,
if (CopyOnOpen && NewThread) ObDereferenceObject(NewThread);
+ ObDereferenceObject(Thread);
+
if (NT_SUCCESS(Status))
{
_SEH2_TRY