mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 17:10:22 +00:00
[NTOS:SE] Complete the SepCompareTokens implementation
* Implement SepCompareSidAndAttributesFromTokens and SepComparePrivilegeAndAttributesFromTokens functions for array elements comparison * Implement the token comparison code in SepCompareTokens function * Add a missing PAGED_CODE() in SepCompareTokens as most of the token comparison code is paged * Use SAL annotations for SepCompareTokens and NtCompareTokens
This commit is contained in:
parent
2282205d13
commit
44b8e5caac
1 changed files with 233 additions and 21 deletions
|
@ -135,12 +135,173 @@ SepDeleteTokenLock(
|
||||||
ExFreePoolWithTag(Token->TokenLock, TAG_SE_TOKEN_LOCK);
|
ExFreePoolWithTag(Token->TokenLock, TAG_SE_TOKEN_LOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS
|
/**
|
||||||
SepCompareTokens(IN PTOKEN FirstToken,
|
* @brief
|
||||||
IN PTOKEN SecondToken,
|
* Compares the elements of SID arrays provided by tokens.
|
||||||
OUT PBOOLEAN Equal)
|
* The elements that are being compared for equality are
|
||||||
|
* the SIDs and their attributes.
|
||||||
|
*
|
||||||
|
* @param[in] SidArrayToken1
|
||||||
|
* SID array from the first token.
|
||||||
|
*
|
||||||
|
* @param[in] CountSidArray1
|
||||||
|
* SID count array from the first token.
|
||||||
|
*
|
||||||
|
* @param[in] SidArrayToken2
|
||||||
|
* SID array from the second token.
|
||||||
|
*
|
||||||
|
* @param[in] CountSidArray2
|
||||||
|
* SID count array from the second token.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Returns TRUE if the elements match from either arrays,
|
||||||
|
* FALSE otherwise.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
BOOLEAN
|
||||||
|
SepCompareSidAndAttributesFromTokens(
|
||||||
|
_In_ PSID_AND_ATTRIBUTES SidArrayToken1,
|
||||||
|
_In_ ULONG CountSidArray1,
|
||||||
|
_In_ PSID_AND_ATTRIBUTES SidArrayToken2,
|
||||||
|
_In_ ULONG CountSidArray2)
|
||||||
|
{
|
||||||
|
ULONG FirstCount, SecondCount;
|
||||||
|
PSID_AND_ATTRIBUTES FirstSidArray, SecondSidArray;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Bail out if index counters provided are not equal */
|
||||||
|
if (CountSidArray1 != CountSidArray2)
|
||||||
|
{
|
||||||
|
DPRINT("SepCompareSidAndAttributesFromTokens(): Index counters are not the same!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop over the SID arrays and compare them */
|
||||||
|
for (FirstCount = 0; FirstCount < CountSidArray1; FirstCount++)
|
||||||
|
{
|
||||||
|
for (SecondCount = 0; SecondCount < CountSidArray2; SecondCount++)
|
||||||
|
{
|
||||||
|
FirstSidArray = &SidArrayToken1[FirstCount];
|
||||||
|
SecondSidArray = &SidArrayToken2[SecondCount];
|
||||||
|
|
||||||
|
if (RtlEqualSid(FirstSidArray->Sid, SecondSidArray->Sid) &&
|
||||||
|
FirstSidArray->Attributes == SecondSidArray->Attributes)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We've exhausted the array of the second token without finding this one */
|
||||||
|
if (SecondCount == CountSidArray2)
|
||||||
|
{
|
||||||
|
DPRINT("SepCompareSidAndAttributesFromTokens(): No matching elements could be found in either token!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Compares the elements of privilege arrays provided by tokens.
|
||||||
|
* The elements that are being compared for equality are
|
||||||
|
* the privileges and their attributes.
|
||||||
|
*
|
||||||
|
* @param[in] PrivArrayToken1
|
||||||
|
* Privilege array from the first token.
|
||||||
|
*
|
||||||
|
* @param[in] CountPrivArray1
|
||||||
|
* Privilege count array from the first token.
|
||||||
|
*
|
||||||
|
* @param[in] PrivArrayToken2
|
||||||
|
* Privilege array from the second token.
|
||||||
|
*
|
||||||
|
* @param[in] CountPrivArray2
|
||||||
|
* Privilege count array from the second token.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Returns TRUE if the elements match from either arrays,
|
||||||
|
* FALSE otherwise.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
BOOLEAN
|
||||||
|
SepComparePrivilegeAndAttributesFromTokens(
|
||||||
|
_In_ PLUID_AND_ATTRIBUTES PrivArrayToken1,
|
||||||
|
_In_ ULONG CountPrivArray1,
|
||||||
|
_In_ PLUID_AND_ATTRIBUTES PrivArrayToken2,
|
||||||
|
_In_ ULONG CountPrivArray2)
|
||||||
|
{
|
||||||
|
ULONG FirstCount, SecondCount;
|
||||||
|
PLUID_AND_ATTRIBUTES FirstPrivArray, SecondPrivArray;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Bail out if index counters provided are not equal */
|
||||||
|
if (CountPrivArray1 != CountPrivArray2)
|
||||||
|
{
|
||||||
|
DPRINT("SepComparePrivilegeAndAttributesFromTokens(): Index counters are not the same!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop over the privilege arrays and compare them */
|
||||||
|
for (FirstCount = 0; FirstCount < CountPrivArray1; FirstCount++)
|
||||||
|
{
|
||||||
|
for (SecondCount = 0; SecondCount < CountPrivArray2; SecondCount++)
|
||||||
|
{
|
||||||
|
FirstPrivArray = &PrivArrayToken1[FirstCount];
|
||||||
|
SecondPrivArray = &PrivArrayToken2[SecondCount];
|
||||||
|
|
||||||
|
if (RtlEqualLuid(&FirstPrivArray->Luid, &SecondPrivArray->Luid) &&
|
||||||
|
FirstPrivArray->Attributes == SecondPrivArray->Attributes)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We've exhausted the array of the second token without finding this one */
|
||||||
|
if (SecondCount == CountPrivArray2)
|
||||||
|
{
|
||||||
|
DPRINT("SepComparePrivilegeAndAttributesFromTokens(): No matching elements could be found in either token!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Compares tokens if they're equal based on all the following properties. If all
|
||||||
|
* of the said conditions are met then the tokens are deemed as equal.
|
||||||
|
*
|
||||||
|
* - Every SID that is present in either token is also present in the other one.
|
||||||
|
* - Both or none of the tokens are restricted.
|
||||||
|
* - If both tokens are restricted, every SID that is restricted in either token is
|
||||||
|
* also restricted in the other one.
|
||||||
|
* - Every privilege present in either token is also present in the other one.
|
||||||
|
*
|
||||||
|
* @param[in] FirstToken
|
||||||
|
* The first token.
|
||||||
|
*
|
||||||
|
* @param[in] SecondToken
|
||||||
|
* The second token.
|
||||||
|
*
|
||||||
|
* @param[out] Equal
|
||||||
|
* The retrieved value which determines if the tokens are
|
||||||
|
* equal or not.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Returns STATUS_SUCCESS.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
SepCompareTokens(
|
||||||
|
_In_ PTOKEN FirstToken,
|
||||||
|
_In_ PTOKEN SecondToken,
|
||||||
|
_Out_ PBOOLEAN Equal)
|
||||||
{
|
{
|
||||||
BOOLEAN Restricted, IsEqual = FALSE;
|
BOOLEAN Restricted, IsEqual = FALSE;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
ASSERT(FirstToken != SecondToken);
|
ASSERT(FirstToken != SecondToken);
|
||||||
|
|
||||||
|
@ -148,21 +309,53 @@ SepCompareTokens(IN PTOKEN FirstToken,
|
||||||
SepAcquireTokenLockShared(FirstToken);
|
SepAcquireTokenLockShared(FirstToken);
|
||||||
SepAcquireTokenLockShared(SecondToken);
|
SepAcquireTokenLockShared(SecondToken);
|
||||||
|
|
||||||
/* FIXME: Check if every SID that is present in either token is also present in the other one */
|
/* Check if every SID that is present in either token is also present in the other one */
|
||||||
|
if (!SepCompareSidAndAttributesFromTokens(FirstToken->UserAndGroups,
|
||||||
Restricted = SeTokenIsRestricted(FirstToken);
|
FirstToken->UserAndGroupCount,
|
||||||
if (Restricted == SeTokenIsRestricted(SecondToken))
|
SecondToken->UserAndGroups,
|
||||||
|
SecondToken->UserAndGroupCount))
|
||||||
{
|
{
|
||||||
if (Restricted)
|
goto Quit;
|
||||||
{
|
|
||||||
/* FIXME: Check if every SID that is restricted in either token is also restricted in the other one */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Is one token restricted but the other isn't? */
|
||||||
|
Restricted = SeTokenIsRestricted(FirstToken);
|
||||||
|
if (Restricted != SeTokenIsRestricted(SecondToken))
|
||||||
|
{
|
||||||
|
/* If that's the case then bail out */
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If both tokens are restricted check if every SID
|
||||||
|
* that is restricted in either token is also restricted
|
||||||
|
* in the other one.
|
||||||
|
*/
|
||||||
|
if (Restricted)
|
||||||
|
{
|
||||||
|
if (!SepCompareSidAndAttributesFromTokens(FirstToken->RestrictedSids,
|
||||||
|
FirstToken->RestrictedSidCount,
|
||||||
|
SecondToken->RestrictedSids,
|
||||||
|
SecondToken->RestrictedSidCount))
|
||||||
|
{
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if every privilege present in either token is also present in the other one */
|
||||||
|
if (!SepComparePrivilegeAndAttributesFromTokens(FirstToken->Privileges,
|
||||||
|
FirstToken->PrivilegeCount,
|
||||||
|
SecondToken->Privileges,
|
||||||
|
SecondToken->PrivilegeCount))
|
||||||
|
{
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're here then the tokens are equal */
|
||||||
|
IsEqual = TRUE;
|
||||||
|
DPRINT("SepCompareTokens(): Tokens are equal!\n");
|
||||||
|
|
||||||
|
Quit:
|
||||||
/* Unlock the tokens */
|
/* Unlock the tokens */
|
||||||
SepReleaseTokenLock(SecondToken);
|
SepReleaseTokenLock(SecondToken);
|
||||||
SepReleaseTokenLock(FirstToken);
|
SepReleaseTokenLock(FirstToken);
|
||||||
|
@ -3921,14 +4114,29 @@ NtOpenThreadToken(IN HANDLE ThreadHandle,
|
||||||
TokenHandle);
|
TokenHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* @unimplemented
|
* @brief
|
||||||
|
* Compares tokens if they're equal or not.
|
||||||
|
*
|
||||||
|
* @param[in] FirstToken
|
||||||
|
* The first token.
|
||||||
|
*
|
||||||
|
* @param[in] SecondToken
|
||||||
|
* The second token.
|
||||||
|
*
|
||||||
|
* @param[out] Equal
|
||||||
|
* The retrieved value which determines if the tokens are
|
||||||
|
* equal or not.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Returns STATUS_SUCCESS, otherwise it returns a failure NTSTATUS code.
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NtCompareTokens(IN HANDLE FirstTokenHandle,
|
NtCompareTokens(
|
||||||
IN HANDLE SecondTokenHandle,
|
_In_ HANDLE FirstTokenHandle,
|
||||||
OUT PBOOLEAN Equal)
|
_In_ HANDLE SecondTokenHandle,
|
||||||
|
_Out_ PBOOLEAN Equal)
|
||||||
{
|
{
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode;
|
||||||
PTOKEN FirstToken, SecondToken;
|
PTOKEN FirstToken, SecondToken;
|
||||||
|
@ -3960,7 +4168,10 @@ NtCompareTokens(IN HANDLE FirstTokenHandle,
|
||||||
(PVOID*)&FirstToken,
|
(PVOID*)&FirstToken,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(SecondTokenHandle,
|
Status = ObReferenceObjectByHandle(SecondTokenHandle,
|
||||||
TOKEN_QUERY,
|
TOKEN_QUERY,
|
||||||
|
@ -3970,6 +4181,7 @@ NtCompareTokens(IN HANDLE FirstTokenHandle,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
DPRINT1("ObReferenceObjectByHandle() failed (Status 0x%lx)\n", Status);
|
||||||
ObDereferenceObject(FirstToken);
|
ObDereferenceObject(FirstToken);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue