mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 01:12:06 +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,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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* 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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -404,46 +389,35 @@ SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN SepSidInToken(PACCESS_TOKEN Token,
|
|
||||||
PSID Sid)
|
static BOOLEAN
|
||||||
|
SepSidInToken(PACCESS_TOKEN Token,
|
||||||
|
PSID Sid)
|
||||||
{
|
{
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
|
||||||
if (Token->UserAndGroupCount == 0)
|
if (Token->UserAndGroupCount == 0)
|
||||||
{
|
{
|
||||||
return(FALSE);
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<Token->UserAndGroupCount; i++)
|
for (i=0; i<Token->UserAndGroupCount; i++)
|
||||||
{
|
{
|
||||||
if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
|
if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
|
||||||
{
|
{
|
||||||
if (i == 0 ||
|
if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
|
||||||
(!(Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)))
|
{
|
||||||
{
|
return TRUE;
|
||||||
return(TRUE);
|
}
|
||||||
}
|
|
||||||
return(FALSE);
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
* FUNCTION: Determines whether the requested access rights can be granted
|
||||||
* to an object protected by a security descriptor and an object owner
|
* 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
|
* GrantedAccess (OUT) = On return specifies the access granted
|
||||||
* AccessStatus (OUT) = Status indicating why access was denied
|
* AccessStatus (OUT) = Status indicating why access was denied
|
||||||
* RETURNS: If access was granted, returns TRUE
|
* 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;
|
ULONG i;
|
||||||
PACL Dacl;
|
PACL Dacl;
|
||||||
|
@ -472,10 +459,6 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
|
|
||||||
CurrentAccess = PreviouslyGrantedAccess;
|
CurrentAccess = PreviouslyGrantedAccess;
|
||||||
|
|
||||||
/*
|
|
||||||
* Ignore the SACL for now
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the DACL
|
* Check the DACL
|
||||||
*/
|
*/
|
||||||
|
@ -485,7 +468,8 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
&Defaulted);
|
&Defaulted);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return(Status);
|
*AccessStatus = Status;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentAce = (PACE)(Dacl + 1);
|
CurrentAce = (PACE)(Dacl + 1);
|
||||||
|
@ -501,12 +485,12 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
|
if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
|
||||||
{
|
{
|
||||||
if (SepSidInToken(SubjectSecurityContext->ClientToken, Sid))
|
if (SepSidInToken(SubjectSecurityContext->ClientToken, Sid))
|
||||||
{
|
{
|
||||||
CurrentAccess = CurrentAccess |
|
CurrentAccess |= CurrentAce->AccessMask;
|
||||||
CurrentAce->AccessMask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -521,7 +505,152 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
}
|
}
|
||||||
*GrantedAccess = CurrentAccess;
|
*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 */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue