mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
First experimental implementstion of NtAccessCheck().
This should fix bug #362. svn path=/trunk/; revision=10108
This commit is contained in:
parent
4cc77e37cc
commit
91946de006
1 changed files with 189 additions and 60 deletions
|
@ -1,4 +1,4 @@
|
|||
/* $Id: semgr.c,v 1.31 2004/07/12 12:04:17 ekohl Exp $
|
||||
/* $Id: semgr.c,v 1.32 2004/07/13 16:59:35 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -201,21 +201,6 @@ NtAllocateUuids(PULARGE_INTEGER Time,
|
|||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
IN HANDLE ClientToken,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN PGENERIC_MAPPING GenericMapping,
|
||||
OUT PPRIVILEGE_SET PrivilegeSet,
|
||||
OUT PULONG ReturnLength,
|
||||
OUT PACCESS_MASK GrantedAccess,
|
||||
OUT PNTSTATUS AccessStatus)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return(STATUS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -404,46 +389,35 @@ SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor,
|
|||
#endif
|
||||
}
|
||||
|
||||
BOOLEAN SepSidInToken(PACCESS_TOKEN Token,
|
||||
PSID Sid)
|
||||
|
||||
static BOOLEAN
|
||||
SepSidInToken(PACCESS_TOKEN Token,
|
||||
PSID Sid)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
if (Token->UserAndGroupCount == 0)
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
for (i=0; i<Token->UserAndGroupCount; i++)
|
||||
{
|
||||
if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
|
||||
{
|
||||
if (i == 0 ||
|
||||
(!(Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)))
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
return(FALSE);
|
||||
ULONG i;
|
||||
|
||||
if (Token->UserAndGroupCount == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i=0; i<Token->UserAndGroupCount; i++)
|
||||
{
|
||||
if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
|
||||
{
|
||||
if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN STDCALL
|
||||
SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
|
||||
IN BOOLEAN SubjectContextLocked,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN ACCESS_MASK PreviouslyGrantedAccess,
|
||||
OUT PPRIVILEGE_SET* Privileges,
|
||||
IN PGENERIC_MAPPING GenericMapping,
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
OUT PACCESS_MODE GrantedAccess,
|
||||
OUT PNTSTATUS AccessStatus)
|
||||
/*
|
||||
* FUNCTION: Determines whether the requested access rights can be granted
|
||||
* to an object protected by a security descriptor and an object owner
|
||||
|
@ -459,7 +433,20 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|||
* GrantedAccess (OUT) = On return specifies the access granted
|
||||
* AccessStatus (OUT) = Status indicating why access was denied
|
||||
* RETURNS: If access was granted, returns TRUE
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN STDCALL
|
||||
SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
|
||||
IN BOOLEAN SubjectContextLocked,
|
||||
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)
|
||||
{
|
||||
ULONG i;
|
||||
PACL Dacl;
|
||||
|
@ -472,10 +459,6 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|||
|
||||
CurrentAccess = PreviouslyGrantedAccess;
|
||||
|
||||
/*
|
||||
* Ignore the SACL for now
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check the DACL
|
||||
*/
|
||||
|
@ -485,7 +468,8 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|||
&Defaulted);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
*AccessStatus = Status;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CurrentAce = (PACE)(Dacl + 1);
|
||||
|
@ -501,12 +485,12 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|||
return(STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
|
||||
{
|
||||
if (SepSidInToken(SubjectSecurityContext->ClientToken, Sid))
|
||||
{
|
||||
CurrentAccess = CurrentAccess |
|
||||
CurrentAce->AccessMask;
|
||||
CurrentAccess |= CurrentAce->AccessMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -521,7 +505,152 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|||
}
|
||||
*GrantedAccess = CurrentAccess;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
IN HANDLE TokenHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN PGENERIC_MAPPING GenericMapping,
|
||||
OUT PPRIVILEGE_SET PrivilegeSet,
|
||||
OUT PULONG ReturnLength,
|
||||
OUT PACCESS_MASK GrantedAccess,
|
||||
OUT PNTSTATUS AccessStatus)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PACCESS_TOKEN Token;
|
||||
BOOLEAN Present;
|
||||
BOOLEAN Defaulted;
|
||||
PACE CurrentAce;
|
||||
PACL Dacl;
|
||||
PSID Sid;
|
||||
ACCESS_MASK CurrentAccess;
|
||||
ULONG i;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("NtAccessCheck() called\n");
|
||||
|
||||
PreviousMode = KeGetPreviousMode();
|
||||
if (PreviousMode == KernelMode)
|
||||
{
|
||||
*GrantedAccess = DesiredAccess;
|
||||
*AccessStatus = STATUS_SUCCESS;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle(TokenHandle,
|
||||
TOKEN_QUERY,
|
||||
SepTokenObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Token,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to reference token (Status %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check token type */
|
||||
if (Token->TokenType != TokenImpersonation)
|
||||
{
|
||||
DPRINT1("No impersonation token\n");
|
||||
ObDereferenceObject(Token);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
/* Check impersonation level */
|
||||
if (Token->ImpersonationLevel < SecurityAnonymous)
|
||||
{
|
||||
DPRINT1("Invalid impersonation level\n");
|
||||
ObDereferenceObject(Token);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
/* Get the DACL */
|
||||
Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
|
||||
&Present,
|
||||
&Dacl,
|
||||
&Defaulted);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("RtlGetDaclSecurityDescriptor() failed (Status %lx)\n", Status);
|
||||
ObDereferenceObject(Token);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* RULE 1: Grant desired access if the object is unprotected */
|
||||
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);
|
||||
|
||||
*GrantedAccess = CurrentAccess & DesiredAccess;
|
||||
|
||||
*AccessStatus =
|
||||
(*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
|
||||
|
||||
DPRINT("NtAccessCheck() done\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue