mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-03 12:23:25 +00:00
[NTOSKRNL]
- Lock the token in SepPrivilegeCheck - Make use of RtlEqualLuid instead of manual comparison of fields - Implement SepSinglePrivilegeCheck and SePrivilegePolicyCheck and use the latter in SepAccessCheck svn path=/trunk/; revision=62058
This commit is contained in:
@@ -380,6 +380,16 @@ SepPrivilegeCheck(
|
||||
KPROCESSOR_MODE PreviousMode
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SePrivilegePolicyCheck(
|
||||
_Inout_ PACCESS_MASK DesiredAccess,
|
||||
_Inout_ PACCESS_MASK GrantedAccess,
|
||||
_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
|
||||
_In_ PTOKEN Token,
|
||||
_Out_opt_ PPRIVILEGE_SET *OutPrivilegeSet,
|
||||
_In_ KPROCESSOR_MODE PreviousMode);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
SeCheckPrivilegedObject(
|
||||
|
||||
@@ -31,7 +31,6 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
OUT PACCESS_MASK GrantedAccess,
|
||||
OUT PNTSTATUS AccessStatus)
|
||||
{
|
||||
LUID_AND_ATTRIBUTES Privilege;
|
||||
#ifdef OLD_ACCESS_CHECK
|
||||
ACCESS_MASK CurrentAccess, AccessMask;
|
||||
#endif
|
||||
@@ -72,43 +71,31 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
if (PreviouslyGrantedAccess)
|
||||
RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping);
|
||||
|
||||
#ifdef OLD_ACCESS_CHECK
|
||||
CurrentAccess = PreviouslyGrantedAccess;
|
||||
#endif
|
||||
/* Initialize remaining access rights */
|
||||
RemainingAccess = DesiredAccess;
|
||||
|
||||
Token = SubjectSecurityContext->ClientToken ?
|
||||
SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
|
||||
SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
|
||||
|
||||
/* Check for system security access */
|
||||
if (RemainingAccess & ACCESS_SYSTEM_SECURITY)
|
||||
/* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
|
||||
Status = SePrivilegePolicyCheck(&RemainingAccess,
|
||||
&PreviouslyGrantedAccess,
|
||||
NULL,
|
||||
Token,
|
||||
NULL,
|
||||
UserMode);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
Privilege.Luid = SeSecurityPrivilege;
|
||||
Privilege.Attributes = SE_PRIVILEGE_ENABLED;
|
||||
*AccessStatus = Status;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Fail if we do not the SeSecurityPrivilege */
|
||||
if (!SepPrivilegeCheck(Token,
|
||||
&Privilege,
|
||||
1,
|
||||
PRIVILEGE_SET_ALL_NECESSARY,
|
||||
AccessMode))
|
||||
{
|
||||
*AccessStatus = STATUS_PRIVILEGE_NOT_HELD;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Adjust access rights */
|
||||
RemainingAccess &= ~ACCESS_SYSTEM_SECURITY;
|
||||
PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY;
|
||||
|
||||
/* Succeed if there are no more rights to grant */
|
||||
if (RemainingAccess == 0)
|
||||
{
|
||||
*GrantedAccess = PreviouslyGrantedAccess;
|
||||
*AccessStatus = STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
/* Succeed if there are no more rights to grant */
|
||||
if (RemainingAccess == 0)
|
||||
{
|
||||
*GrantedAccess = PreviouslyGrantedAccess;
|
||||
*AccessStatus = STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Get the DACL */
|
||||
@@ -143,35 +130,6 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
CurrentAccess = PreviouslyGrantedAccess;
|
||||
#endif
|
||||
|
||||
/* RULE 2: Check token for 'take ownership' privilege */
|
||||
if (DesiredAccess & WRITE_OWNER)
|
||||
{
|
||||
Privilege.Luid = SeTakeOwnershipPrivilege;
|
||||
Privilege.Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
if (SepPrivilegeCheck(Token,
|
||||
&Privilege,
|
||||
1,
|
||||
PRIVILEGE_SET_ALL_NECESSARY,
|
||||
AccessMode))
|
||||
{
|
||||
/* Adjust access rights */
|
||||
RemainingAccess &= ~WRITE_OWNER;
|
||||
PreviouslyGrantedAccess |= WRITE_OWNER;
|
||||
#ifdef OLD_ACCESS_CHECK
|
||||
CurrentAccess |= WRITE_OWNER;
|
||||
#endif
|
||||
|
||||
/* Succeed if there are no more rights to grant */
|
||||
if (RemainingAccess == 0)
|
||||
{
|
||||
*GrantedAccess = PreviouslyGrantedAccess;
|
||||
*AccessStatus = STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Deny access if the DACL is empty */
|
||||
if (Dacl->AceCount == 0)
|
||||
{
|
||||
|
||||
+127
-2
@@ -89,6 +89,9 @@ SepPrivilegeCheck(PTOKEN Token,
|
||||
/* Get the number of privileges that are required to match */
|
||||
Required = (PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) ? PrivilegeCount : 1;
|
||||
|
||||
/* Acquire a shared token lock */
|
||||
SepAcquireTokenLockShared(Token);
|
||||
|
||||
/* Loop all requested privileges until we found the required ones */
|
||||
for (i = 0; i < PrivilegeCount; i++)
|
||||
{
|
||||
@@ -96,8 +99,7 @@ SepPrivilegeCheck(PTOKEN Token,
|
||||
for (j = 0; j < Token->PrivilegeCount; j++)
|
||||
{
|
||||
/* Check if the LUIDs match */
|
||||
if (Token->Privileges[j].Luid.LowPart == Privileges[i].Luid.LowPart &&
|
||||
Token->Privileges[j].Luid.HighPart == Privileges[i].Luid.HighPart)
|
||||
if (RtlEqualLuid(&Token->Privileges[j].Luid, &Privileges[i].Luid))
|
||||
{
|
||||
DPRINT("Found privilege. Attributes: %lx\n",
|
||||
Token->Privileges[j].Attributes);
|
||||
@@ -112,6 +114,7 @@ SepPrivilegeCheck(PTOKEN Token,
|
||||
if (Required == 0)
|
||||
{
|
||||
/* We're done! */
|
||||
SepReleaseTokenLock(Token);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -122,11 +125,133 @@ SepPrivilegeCheck(PTOKEN Token,
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the token lock */
|
||||
SepReleaseTokenLock(Token);
|
||||
|
||||
/* When we reached this point, we did not find all privileges */
|
||||
NT_ASSERT(Required > 0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SepSinglePrivilegeCheck(
|
||||
LUID PrivilegeValue,
|
||||
PTOKEN Token,
|
||||
KPROCESSOR_MODE PreviousMode)
|
||||
{
|
||||
LUID_AND_ATTRIBUTES Privilege;
|
||||
PAGED_CODE();
|
||||
ASSERT(!RtlEqualLuid(&PrivilegeValue, &SeTcbPrivilege));
|
||||
|
||||
Privilege.Luid = PrivilegeValue;
|
||||
Privilege.Attributes = SE_PRIVILEGE_ENABLED;
|
||||
return SepPrivilegeCheck(Token,
|
||||
&Privilege,
|
||||
1,
|
||||
PRIVILEGE_SET_ALL_NECESSARY,
|
||||
PreviousMode);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SePrivilegePolicyCheck(
|
||||
_Inout_ PACCESS_MASK DesiredAccess,
|
||||
_Inout_ PACCESS_MASK GrantedAccess,
|
||||
_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext,
|
||||
_In_ PTOKEN Token,
|
||||
_Out_opt_ PPRIVILEGE_SET *OutPrivilegeSet,
|
||||
_In_ KPROCESSOR_MODE PreviousMode)
|
||||
{
|
||||
SIZE_T PrivilegeSize;
|
||||
PPRIVILEGE_SET PrivilegeSet;
|
||||
ULONG PrivilegeCount = 0, Index = 0;
|
||||
ACCESS_MASK AccessMask = 0;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Check if we have a security subject context */
|
||||
if (SubjectContext != NULL)
|
||||
{
|
||||
/* Check if there is a client impersonation token */
|
||||
if (SubjectContext->ClientToken != NULL)
|
||||
Token = SubjectContext->ClientToken;
|
||||
else
|
||||
Token = SubjectContext->PrimaryToken;
|
||||
}
|
||||
|
||||
/* Check if the caller wants ACCESS_SYSTEM_SECURITY access */
|
||||
if (*DesiredAccess & ACCESS_SYSTEM_SECURITY)
|
||||
{
|
||||
/* Do the privilege check */
|
||||
if (SepSinglePrivilegeCheck(SeSecurityPrivilege, Token, PreviousMode))
|
||||
{
|
||||
/* Remember this access flag */
|
||||
AccessMask |= ACCESS_SYSTEM_SECURITY;
|
||||
PrivilegeCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the caller wants WRITE_OWNER access */
|
||||
if (*DesiredAccess & WRITE_OWNER)
|
||||
{
|
||||
/* Do the privilege check */
|
||||
if (SepSinglePrivilegeCheck(SeTakeOwnershipPrivilege, Token, PreviousMode))
|
||||
{
|
||||
/* Remember this access flag */
|
||||
AccessMask |= WRITE_OWNER;
|
||||
PrivilegeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the access masks */
|
||||
*GrantedAccess |= AccessMask;
|
||||
*DesiredAccess &= ~AccessMask;
|
||||
|
||||
/* Does the caller want a privilege set? */
|
||||
if (OutPrivilegeSet != NULL)
|
||||
{
|
||||
/* Do we have any privileges to report? */
|
||||
if (PrivilegeCount > 0)
|
||||
{
|
||||
/* Calculate size and allocate the structure */
|
||||
PrivilegeSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]);
|
||||
PrivilegeSet = ExAllocatePoolWithTag(PagedPool, PrivilegeSize, 'rPeS');
|
||||
*OutPrivilegeSet = PrivilegeSet;
|
||||
if (PrivilegeSet == NULL)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
PrivilegeSet->PrivilegeCount = PrivilegeCount;
|
||||
PrivilegeSet->Control = 0;
|
||||
|
||||
if (AccessMask & WRITE_OWNER)
|
||||
{
|
||||
PrivilegeSet->Privilege[Index].Luid = SeTakeOwnershipPrivilege;
|
||||
PrivilegeSet->Privilege[Index].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;
|
||||
Index++;
|
||||
}
|
||||
|
||||
if (AccessMask & ACCESS_SYSTEM_SECURITY)
|
||||
{
|
||||
PrivilegeSet->Privilege[Index].Luid = SeSecurityPrivilege;
|
||||
PrivilegeSet->Privilege[Index].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No privileges, no structure */
|
||||
*OutPrivilegeSet = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src,
|
||||
|
||||
Reference in New Issue
Block a user