/* PRIVATE FUNCTIONS **********************************************************/
+/*
+ * FIXME: Incomplete!
+ */
BOOLEAN NTAPI
-SepAccessCheckEx(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_TYPE_LIST ObjectTypeList,
NTSTATUS Status;
PAGED_CODE();
- DPRINT("SepAccessCheckEx()\n");
+ DPRINT("SepAccessCheck()\n");
/* Check for no access desired */
if (!DesiredAccess)
/* Fail if some rights have not been granted */
if (RemainingAccess != 0)
{
- DPRINT1("HACK: RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", RemainingAccess, DesiredAccess);
+ DPRINT("HACK: RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", RemainingAccess, DesiredAccess);
#if 0
/* HACK HACK HACK */
Status = STATUS_ACCESS_DENIED;
return NT_SUCCESS(Status);
}
-BOOLEAN NTAPI
-SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
- IN ACCESS_MASK DesiredAccess,
- IN ACCESS_MASK PreviouslyGrantedAccess,
- OUT PPRIVILEGE_SET* Privileges,
- IN PGENERIC_MAPPING GenericMapping,
- IN KPROCESSOR_MODE AccessMode,
- OUT PACCESS_MASK GrantedAccess,
- OUT PNTSTATUS AccessStatus)
-{
- return SepAccessCheckEx(SecurityDescriptor,
- SubjectSecurityContext,
- DesiredAccess,
- NULL,
- 0,
- PreviouslyGrantedAccess,
- Privileges,
- GenericMapping,
- AccessMode,
- GrantedAccess,
- AccessStatus,
- FALSE);
-}
-
static PSID
SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
{
return Group;
}
+static
+ULONG
+SepGetPrivilegeSetLength(IN PPRIVILEGE_SET PrivilegeSet)
+{
+ if (PrivilegeSet == NULL)
+ return 0;
+
+ if (PrivilegeSet->PrivilegeCount == 0)
+ return (ULONG)(sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES));
+
+ return (ULONG)(sizeof(PRIVILEGE_SET) +
+ (PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES));
+}
/* PUBLIC FUNCTIONS ***********************************************************/
if (DesiredAccess == 0)
{
*GrantedAccess = PreviouslyGrantedAccess;
- *AccessStatus = STATUS_SUCCESS;
- ret = TRUE;
+ if (PreviouslyGrantedAccess == 0)
+ {
+ DPRINT1("Request for zero access to an object. Denying.\n");
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ ret = FALSE;
+ }
+ else
+ {
+ *AccessStatus = STATUS_SUCCESS;
+ ret = TRUE;
+ }
}
else
{
ret = SepAccessCheck(SecurityDescriptor,
SubjectSecurityContext,
DesiredAccess,
+ NULL,
+ 0,
PreviouslyGrantedAccess,
Privileges,
GenericMapping,
AccessMode,
GrantedAccess,
- AccessStatus);
+ AccessStatus,
+ FALSE);
}
/* Release the lock if needed */
PAGED_CODE();
- NT_ASSERT(AccessMode != KernelMode);
+ ASSERT(AccessMode != KernelMode);
if (SecurityDescriptor == NULL)
return FALSE;
continue;
/* If access-allowed ACE */
- if (Ace->Header.AceType & ACCESS_ALLOWED_ACE_TYPE)
+ if (Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
{
/* Check if all accesses are granted */
if (!(Ace->Mask & DesiredAccess))
return TRUE;
}
/* If access-denied ACE */
- else if (Ace->Header.AceType & ACCESS_DENIED_ACE_TYPE)
+ else if (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
{
- /* Here, only check if it denies all the access wanted and deny if so */
+ /* Here, only check if it denies any access wanted and deny if so */
if (Ace->Mask & DesiredAccess)
return FALSE;
}
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
ACCESS_MASK PreviouslyGrantedAccess = 0;
+ PPRIVILEGE_SET Privileges = NULL;
+ ULONG CapturedPrivilegeSetLength, RequiredPrivilegeSetLength;
PTOKEN Token;
NTSTATUS Status;
PAGED_CODE();
ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
- /* Initialize the privilege set */
- PrivilegeSet->PrivilegeCount = 0;
+ /* Capture the privilege set length and the mapping */
+ CapturedPrivilegeSetLength = *PrivilegeSetLength;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
return STATUS_BAD_IMPERSONATION_LEVEL;
}
+ /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
+ Status = SePrivilegePolicyCheck(&DesiredAccess,
+ &PreviouslyGrantedAccess,
+ NULL,
+ Token,
+ &Privileges,
+ PreviousMode);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("SePrivilegePolicyCheck failed (Status 0x%08lx)\n", Status);
+ ObDereferenceObject(Token);
+ *AccessStatus = Status;
+ *GrantedAccess = 0;
+ return STATUS_SUCCESS;
+ }
+
+ /* Check the size of the privilege set and return the privileges */
+ if (Privileges != NULL)
+ {
+ DPRINT("Privileges != NULL\n");
+
+ /* Calculate the required privilege set buffer size */
+ RequiredPrivilegeSetLength = SepGetPrivilegeSetLength(Privileges);
+
+ /* Fail if the privilege set buffer is too small */
+ if (CapturedPrivilegeSetLength < RequiredPrivilegeSetLength)
+ {
+ ObDereferenceObject(Token);
+ SeFreePrivileges(Privileges);
+ *PrivilegeSetLength = RequiredPrivilegeSetLength;
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ /* Copy the privilege set to the caller */
+ RtlCopyMemory(PrivilegeSet,
+ Privileges,
+ RequiredPrivilegeSetLength);
+
+ /* Free the local privilege set */
+ SeFreePrivileges(Privileges);
+ }
+ else
+ {
+ DPRINT("Privileges == NULL\n");
+
+ /* Fail if the privilege set buffer is too small */
+ if (CapturedPrivilegeSetLength < sizeof(PRIVILEGE_SET))
+ {
+ ObDereferenceObject(Token);
+ *PrivilegeSetLength = sizeof(PRIVILEGE_SET);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ /* Initialize the privilege set */
+ PrivilegeSet->PrivilegeCount = 0;
+ PrivilegeSet->Control = 0;
+ }
+
/* Capture the security descriptor */
Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
PreviousMode,
SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
&SubjectSecurityContext,
DesiredAccess,
+ NULL,
+ 0,
PreviouslyGrantedAccess,
&PrivilegeSet, //FIXME
GenericMapping,
PreviousMode,
GrantedAccess,
- AccessStatus);
+ AccessStatus,
+ FALSE);
}
/* Release subject context and unlock the token */