- Move access checks from NtAccessCheck() to SeAccessCheck().

- Check for 'take ownership' privilege.

svn path=/trunk/; revision=10111
This commit is contained in:
Eric Kohl 2004-07-14 14:25:31 +00:00
parent 6e17c87e59
commit c6ec21e207
2 changed files with 179 additions and 170 deletions

View file

@ -136,6 +136,13 @@ SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege,
KPROCESSOR_MODE PreviousMode, KPROCESSOR_MODE PreviousMode,
ULONG a); ULONG a);
BOOLEAN
SepPrivilegeCheck(PACCESS_TOKEN Token,
PLUID_AND_ATTRIBUTES Privileges,
ULONG PrivilegeCount,
ULONG PrivilegeControl,
KPROCESSOR_MODE PreviousMode);
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_SE_H */ #endif /* __NTOSKRNL_INCLUDE_INTERNAL_SE_H */

View file

@ -1,4 +1,4 @@
/* $Id: semgr.c,v 1.32 2004/07/13 16:59:35 ekohl Exp $ /* $Id: semgr.c,v 1.33 2004/07/14 14:25:31 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -15,6 +15,7 @@
#include <internal/ps.h> #include <internal/ps.h>
#include <internal/se.h> #include <internal/se.h>
#define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
#define TAG_SXPT TAG('S', 'X', 'P', 'T') #define TAG_SXPT TAG('S', 'X', 'P', 'T')
@ -273,7 +274,8 @@ SeDeassignSecurity(PSECURITY_DESCRIPTOR* SecurityDescriptor)
#if 0 #if 0
VOID SepGetDefaultsSubjectContext(PSECURITY_SUBJECT_CONTEXT SubjectContext, VOID
SepGetDefaultsSubjectContext(PSECURITY_SUBJECT_CONTEXT SubjectContext,
PSID* Owner, PSID* Owner,
PSID* PrimaryGroup, PSID* PrimaryGroup,
PSID* ProcessOwner, PSID* ProcessOwner,
@ -298,7 +300,9 @@ VOID SepGetDefaultsSubjectContext(PSECURITY_SUBJECT_CONTEXT SubjectContext,
*ProcessPrimaryGroup = SubjectContext->PrimaryToken->PrimaryGroup; *ProcessPrimaryGroup = SubjectContext->PrimaryToken->PrimaryGroup;
} }
NTSTATUS SepInheritAcl(PACL Acl,
NTSTATUS
SepInheritAcl(PACL Acl,
BOOLEAN IsDirectoryObject, BOOLEAN IsDirectoryObject,
PSID Owner, PSID Owner,
PSID PrimaryGroup, PSID PrimaryGroup,
@ -311,12 +315,14 @@ NTSTATUS SepInheritAcl(PACL Acl,
{ {
return(STATUS_UNSUCCESSFUL); return(STATUS_UNSUCCESSFUL);
} }
if (Acl->AclRevision != 2 && if (Acl->AclRevision != 2 &&
Acl->AclRevision != 3 ) Acl->AclRevision != 3 )
{ {
return(STATUS_UNSUCCESSFUL); return(STATUS_UNSUCCESSFUL);
} }
} }
#endif #endif
@ -448,20 +454,23 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
OUT PACCESS_MASK GrantedAccess, OUT PACCESS_MASK GrantedAccess,
OUT PNTSTATUS AccessStatus) OUT PNTSTATUS AccessStatus)
{ {
LUID_AND_ATTRIBUTES Privilege;
ACCESS_MASK CurrentAccess;
PACCESS_TOKEN Token;
ULONG i; ULONG i;
PACL Dacl; PACL Dacl;
BOOLEAN Present; BOOLEAN Present;
BOOLEAN Defaulted; BOOLEAN Defaulted;
NTSTATUS Status;
PACE CurrentAce; PACE CurrentAce;
PSID Sid; PSID Sid;
ACCESS_MASK CurrentAccess; NTSTATUS Status;
CurrentAccess = PreviouslyGrantedAccess; CurrentAccess = PreviouslyGrantedAccess;
/* Token = SubjectSecurityContext->ClientToken ?
* Check the DACL SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
*/
/* Get the DACL */
Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
&Present, &Present,
&Dacl, &Dacl,
@ -472,38 +481,88 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
return FALSE; return FALSE;
} }
/* RULE 1: Grant desired access if the object is unprotected */
if (Dacl == NULL)
{
*GrantedAccess = DesiredAccess;
*AccessStatus = STATUS_SUCCESS;
return TRUE;
}
CurrentAccess = PreviouslyGrantedAccess;
/* RULE 2: Check token for 'take ownership' privilege */
Privilege.Luid = SeTakeOwnershipPrivilege;
Privilege.Attributes = SE_PRIVILEGE_ENABLED;
if (SepPrivilegeCheck(Token,
&Privilege,
1,
PRIVILEGE_SET_ALL_NECESSARY,
AccessMode))
{
CurrentAccess |= WRITE_OWNER;
if (DesiredAccess == CurrentAccess)
{
*GrantedAccess = CurrentAccess;
*AccessStatus = STATUS_SUCCESS;
return TRUE;
}
}
/* RULE 3: Check whether the token is the owner */
Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
&Sid,
&Defaulted);
if (!NT_SUCCESS(Status))
{
DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
*AccessStatus = Status;
return FALSE;
}
if (SepSidInToken(Token, Sid))
{
CurrentAccess |= (READ_CONTROL | WRITE_DAC);
if (DesiredAccess == CurrentAccess)
{
*GrantedAccess = CurrentAccess;
*AccessStatus = STATUS_SUCCESS;
return TRUE;
}
}
/* RULE 4: Grant rights according to the DACL */
CurrentAce = (PACE)(Dacl + 1); CurrentAce = (PACE)(Dacl + 1);
for (i = 0; i < Dacl->AceCount; i++) for (i = 0; i < Dacl->AceCount; i++)
{ {
Sid = (PSID)(CurrentAce + 1); Sid = (PSID)(CurrentAce + 1);
if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
{ {
if (SepSidInToken(SubjectSecurityContext->ClientToken, Sid)) if (SepSidInToken(Token, Sid))
{ {
*AccessStatus = STATUS_ACCESS_DENIED;
*GrantedAccess = 0; *GrantedAccess = 0;
return(STATUS_SUCCESS); *AccessStatus = STATUS_ACCESS_DENIED;
return TRUE;
} }
} }
if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
{ {
if (SepSidInToken(SubjectSecurityContext->ClientToken, Sid)) if (SepSidInToken(Token, Sid))
{ {
CurrentAccess |= CurrentAce->AccessMask; CurrentAccess |= CurrentAce->AccessMask;
} }
} }
} }
if (!(CurrentAccess & DesiredAccess) &&
!((~CurrentAccess) & DesiredAccess)) DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
{ CurrentAccess, DesiredAccess);
*AccessStatus = STATUS_ACCESS_DENIED;
} *GrantedAccess = CurrentAccess & DesiredAccess;
else
{ *AccessStatus =
*AccessStatus = STATUS_SUCCESS; (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
}
*GrantedAccess = CurrentAccess;
return TRUE; return TRUE;
} }
@ -519,15 +578,9 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
OUT PACCESS_MASK GrantedAccess, OUT PACCESS_MASK GrantedAccess,
OUT PNTSTATUS AccessStatus) OUT PNTSTATUS AccessStatus)
{ {
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
KPROCESSOR_MODE PreviousMode; KPROCESSOR_MODE PreviousMode;
PACCESS_TOKEN Token; PACCESS_TOKEN Token;
BOOLEAN Present;
BOOLEAN Defaulted;
PACE CurrentAce;
PACL Dacl;
PSID Sid;
ACCESS_MASK CurrentAccess;
ULONG i;
NTSTATUS Status; NTSTATUS Status;
DPRINT("NtAccessCheck() called\n"); DPRINT("NtAccessCheck() called\n");
@ -568,89 +621,38 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
return STATUS_ACCESS_VIOLATION; return STATUS_ACCESS_VIOLATION;
} }
/* Get the DACL */ RtlZeroMemory(&SubjectSecurityContext,
Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, sizeof(SECURITY_SUBJECT_CONTEXT));
&Present, SubjectSecurityContext.ClientToken = Token;
&Dacl, SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
&Defaulted);
if (!NT_SUCCESS(Status)) /* FIXME: Lock subject context */
if (!SeAccessCheck(SecurityDescriptor,
&SubjectSecurityContext,
TRUE,
DesiredAccess,
0,
&PrivilegeSet,
GenericMapping,
PreviousMode,
GrantedAccess,
AccessStatus))
{ {
DPRINT1("RtlGetDaclSecurityDescriptor() failed (Status %lx)\n", Status); Status = *AccessStatus;
ObDereferenceObject(Token); }
return Status; else
{
Status = STATUS_SUCCESS;
} }
/* RULE 1: Grant desired access if the object is unprotected */ /* FIXME: Unlock subject context */
if (Dacl == NULL)
{
*GrantedAccess = DesiredAccess;
*AccessStatus = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
CurrentAccess = 0;
/* FIXME: RULE 2: Check token for 'take ownership' privilege */
/* RULE 3: Check whether the token is the owner */
Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
&Sid,
&Defaulted);
if (!NT_SUCCESS(Status))
{
DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
ObDereferenceObject(Token);
return Status;
}
if (SepSidInToken(Token, Sid))
{
CurrentAccess |= (READ_CONTROL | WRITE_DAC);
if (DesiredAccess == CurrentAccess)
{
*AccessStatus = STATUS_SUCCESS;
*GrantedAccess = CurrentAccess;
return STATUS_SUCCESS;
}
}
/* RULE 4: Grant rights according to the DACL */
CurrentAce = (PACE)(Dacl + 1);
for (i = 0; i < Dacl->AceCount; i++)
{
Sid = (PSID)(CurrentAce + 1);
if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
{
if (SepSidInToken(Token, Sid))
{
*AccessStatus = STATUS_ACCESS_DENIED;
*GrantedAccess = 0;
return STATUS_SUCCESS;
}
}
if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
{
if (SepSidInToken(Token, Sid))
{
CurrentAccess |= CurrentAce->AccessMask;
}
}
}
DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
CurrentAccess, DesiredAccess);
ObDereferenceObject(Token); ObDereferenceObject(Token);
*GrantedAccess = CurrentAccess & DesiredAccess;
*AccessStatus =
(*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
DPRINT("NtAccessCheck() done\n"); DPRINT("NtAccessCheck() done\n");
return STATUS_SUCCESS; return Status;
} }
/* EOF */ /* EOF */