[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:
Timo Kreuzer
2014-02-08 20:01:09 +00:00
parent 530512f17e
commit 4a8d13c7e3
3 changed files with 155 additions and 62 deletions
+10
View File
@@ -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(
+18 -60
View File
@@ -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
View File
@@ -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,