Author: fireball Date: Sat Nov 21 18:58:33 2009 New Revision: 44260
URL: http://svn.reactos.org/svn/reactos?rev=44260&view=rev Log: [ntoskrnl/se] - Factor out working code from SeAccessCheck into SepAccessCheck, taking out addition parameter - LowerImpersonationLevel. The lowest level for SeAccessCheck remains SecurityImpersonation, but for NtAccessCheck it's lowered to SecurityIdentification. Name of this patch's author has been lost. See issue #4169 for more details.
Modified: trunk/reactos/ntoskrnl/se/semgr.c
Modified: trunk/reactos/ntoskrnl/se/semgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/semgr.c?rev=442... ============================================================================== --- trunk/reactos/ntoskrnl/se/semgr.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/se/semgr.c [iso-8859-1] Sat Nov 21 18:58:33 2009 @@ -348,6 +348,273 @@ } }
+BOOLEAN NTAPI +SepAccessCheck(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, + SECURITY_IMPERSONATION_LEVEL LowestImpersonationLevel) +{ + LUID_AND_ATTRIBUTES Privilege; + ACCESS_MASK CurrentAccess, AccessMask; + PACCESS_TOKEN Token; + ULONG i; + PACL Dacl; + BOOLEAN Present; + BOOLEAN Defaulted; + PACE CurrentAce; + PSID Sid; + NTSTATUS Status; + PAGED_CODE(); + + /* Check if this is kernel mode */ + if (AccessMode == KernelMode) + { + /* Check if kernel wants everything */ + if (DesiredAccess & MAXIMUM_ALLOWED) + { + /* Give it */ + *GrantedAccess = GenericMapping->GenericAll; + *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED); + *GrantedAccess |= PreviouslyGrantedAccess; + } + else + { + /* Give the desired and previous access */ + *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess; + } + + /* Success */ + *AccessStatus = STATUS_SUCCESS; + return TRUE; + } + + /* Check if we didn't get an SD */ + if (!SecurityDescriptor) + { + /* Automatic failure */ + *AccessStatus = STATUS_ACCESS_DENIED; + return FALSE; + } + + /* Check for invalid impersonation */ + if ((SubjectSecurityContext->ClientToken) && + (SubjectSecurityContext->ImpersonationLevel < LowestImpersonationLevel)) + { + *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL; + return FALSE; + } + + /* Check for no access desired */ + if (!DesiredAccess) + { + /* Check if we had no previous access */ + if (!PreviouslyGrantedAccess) + { + /* Then there's nothing to give */ + *AccessStatus = STATUS_ACCESS_DENIED; + return FALSE; + } + + /* Return the previous access only */ + *GrantedAccess = PreviouslyGrantedAccess; + *AccessStatus = STATUS_SUCCESS; + *Privileges = NULL; + return TRUE; + } + + /* Acquire the lock if needed */ + if (!SubjectContextLocked) SeLockSubjectContext(SubjectSecurityContext); + + /* Map given accesses */ + RtlMapGenericMask(&DesiredAccess, GenericMapping); + if (PreviouslyGrantedAccess) + RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping); + + + + CurrentAccess = PreviouslyGrantedAccess; + + + + Token = SubjectSecurityContext->ClientToken ? + SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken; + + /* Get the DACL */ + Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, + &Present, + &Dacl, + &Defaulted); + if (!NT_SUCCESS(Status)) + { + if (SubjectContextLocked == FALSE) + { + SeUnlockSubjectContext(SubjectSecurityContext); + } + + *AccessStatus = Status; + return FALSE; + } + + /* RULE 1: Grant desired access if the object is unprotected */ + if (Present == TRUE && Dacl == NULL) + { + if (SubjectContextLocked == FALSE) + { + SeUnlockSubjectContext(SubjectSecurityContext); + } + + *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 & ~VALID_INHERIT_FLAGS) == + (CurrentAccess & ~VALID_INHERIT_FLAGS)) + { + if (SubjectContextLocked == FALSE) + { + SeUnlockSubjectContext(SubjectSecurityContext); + } + + *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); + if (SubjectContextLocked == FALSE) + { + SeUnlockSubjectContext(SubjectSecurityContext); + } + + *AccessStatus = Status; + return FALSE; + } + + if (Sid && SepSidInToken(Token, Sid)) + { + CurrentAccess |= (READ_CONTROL | WRITE_DAC); + if ((DesiredAccess & ~VALID_INHERIT_FLAGS) == + (CurrentAccess & ~VALID_INHERIT_FLAGS)) + { + if (SubjectContextLocked == FALSE) + { + SeUnlockSubjectContext(SubjectSecurityContext); + } + + *GrantedAccess = CurrentAccess; + *AccessStatus = STATUS_SUCCESS; + return TRUE; + } + } + + /* Fail if DACL is absent */ + if (Present == FALSE) + { + if (SubjectContextLocked == FALSE) + { + SeUnlockSubjectContext(SubjectSecurityContext); + } + + *GrantedAccess = 0; + *AccessStatus = STATUS_ACCESS_DENIED; + return FALSE; + } + + /* 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)) + { + if (SubjectContextLocked == FALSE) + { + SeUnlockSubjectContext(SubjectSecurityContext); + } + + *GrantedAccess = 0; + *AccessStatus = STATUS_ACCESS_DENIED; + return FALSE; + } + } + + else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) + { + if (SepSidInToken(Token, Sid)) + { + AccessMask = CurrentAce->AccessMask; + RtlMapGenericMask(&AccessMask, GenericMapping); + CurrentAccess |= AccessMask; + } + } + else + { + DPRINT1("Unknown Ace type 0x%lx\n", CurrentAce->Header.AceType); + } + CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize); + } + + if (SubjectContextLocked == FALSE) + { + SeUnlockSubjectContext(SubjectSecurityContext); + } + + DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n", + CurrentAccess, DesiredAccess); + + *GrantedAccess = CurrentAccess & DesiredAccess; + + if (DesiredAccess & MAXIMUM_ALLOWED) + { + *GrantedAccess = CurrentAccess; + *AccessStatus = STATUS_SUCCESS; + return TRUE; + } + else if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) == + (DesiredAccess & ~VALID_INHERIT_FLAGS)) + { + *AccessStatus = STATUS_SUCCESS; + return TRUE; + } + else + { + DPRINT1("Denying access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p)\n", + *GrantedAccess, DesiredAccess, GenericMapping); + *AccessStatus = STATUS_ACCESS_DENIED; + return FALSE; + } +} + /* PUBLIC FUNCTIONS ***********************************************************/
/* @@ -365,258 +632,18 @@ OUT PACCESS_MASK GrantedAccess, OUT PNTSTATUS AccessStatus) { - LUID_AND_ATTRIBUTES Privilege; - ACCESS_MASK CurrentAccess, AccessMask; - PACCESS_TOKEN Token; - ULONG i; - PACL Dacl; - BOOLEAN Present; - BOOLEAN Defaulted; - PACE CurrentAce; - PSID Sid; - NTSTATUS Status; - PAGED_CODE(); - - /* Check if this is kernel mode */ - if (AccessMode == KernelMode) - { - /* Check if kernel wants everything */ - if (DesiredAccess & MAXIMUM_ALLOWED) - { - /* Give it */ - *GrantedAccess = GenericMapping->GenericAll; - *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED); - *GrantedAccess |= PreviouslyGrantedAccess; - } - else - { - /* Give the desired and previous access */ - *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess; - } - - /* Success */ - *AccessStatus = STATUS_SUCCESS; - return TRUE; - } - - /* Check if we didn't get an SD */ - if (!SecurityDescriptor) - { - /* Automatic failure */ - *AccessStatus = STATUS_ACCESS_DENIED; - return FALSE; - } - - /* Check for invalid impersonation */ - if ((SubjectSecurityContext->ClientToken) && - (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation)) - { - *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL; - return FALSE; - } - - /* Check for no access desired */ - if (!DesiredAccess) - { - /* Check if we had no previous access */ - if (!PreviouslyGrantedAccess) - { - /* Then there's nothing to give */ - *AccessStatus = STATUS_ACCESS_DENIED; - return FALSE; - } - - /* Return the previous access only */ - *GrantedAccess = PreviouslyGrantedAccess; - *AccessStatus = STATUS_SUCCESS; - *Privileges = NULL; - return TRUE; - } - - /* Acquire the lock if needed */ - if (!SubjectContextLocked) SeLockSubjectContext(SubjectSecurityContext); - - /* Map given accesses */ - RtlMapGenericMask(&DesiredAccess, GenericMapping); - if (PreviouslyGrantedAccess) - RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping); - - - - CurrentAccess = PreviouslyGrantedAccess; - - - - Token = SubjectSecurityContext->ClientToken ? - SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken; - - /* Get the DACL */ - Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, - &Present, - &Dacl, - &Defaulted); - if (!NT_SUCCESS(Status)) - { - if (SubjectContextLocked == FALSE) - { - SeUnlockSubjectContext(SubjectSecurityContext); - } - - *AccessStatus = Status; - return FALSE; - } - - /* RULE 1: Grant desired access if the object is unprotected */ - if (Present == TRUE && Dacl == NULL) - { - if (SubjectContextLocked == FALSE) - { - SeUnlockSubjectContext(SubjectSecurityContext); - } - - *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 & ~VALID_INHERIT_FLAGS) == - (CurrentAccess & ~VALID_INHERIT_FLAGS)) - { - if (SubjectContextLocked == FALSE) - { - SeUnlockSubjectContext(SubjectSecurityContext); - } - - *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); - if (SubjectContextLocked == FALSE) - { - SeUnlockSubjectContext(SubjectSecurityContext); - } - - *AccessStatus = Status; - return FALSE; - } - - if (Sid && SepSidInToken(Token, Sid)) - { - CurrentAccess |= (READ_CONTROL | WRITE_DAC); - if ((DesiredAccess & ~VALID_INHERIT_FLAGS) == - (CurrentAccess & ~VALID_INHERIT_FLAGS)) - { - if (SubjectContextLocked == FALSE) - { - SeUnlockSubjectContext(SubjectSecurityContext); - } - - *GrantedAccess = CurrentAccess; - *AccessStatus = STATUS_SUCCESS; - return TRUE; - } - } - - /* Fail if DACL is absent */ - if (Present == FALSE) - { - if (SubjectContextLocked == FALSE) - { - SeUnlockSubjectContext(SubjectSecurityContext); - } - - *GrantedAccess = 0; - *AccessStatus = STATUS_ACCESS_DENIED; - return FALSE; - } - - /* 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)) - { - if (SubjectContextLocked == FALSE) - { - SeUnlockSubjectContext(SubjectSecurityContext); - } - - *GrantedAccess = 0; - *AccessStatus = STATUS_ACCESS_DENIED; - return FALSE; - } - } - - else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) - { - if (SepSidInToken(Token, Sid)) - { - AccessMask = CurrentAce->AccessMask; - RtlMapGenericMask(&AccessMask, GenericMapping); - CurrentAccess |= AccessMask; - } - } - else - { - DPRINT1("Unknown Ace type 0x%lx\n", CurrentAce->Header.AceType); - } - CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize); - } - - if (SubjectContextLocked == FALSE) - { - SeUnlockSubjectContext(SubjectSecurityContext); - } - - DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n", - CurrentAccess, DesiredAccess); - - *GrantedAccess = CurrentAccess & DesiredAccess; - - if (DesiredAccess & MAXIMUM_ALLOWED) - { - *GrantedAccess = CurrentAccess; - *AccessStatus = STATUS_SUCCESS; - return TRUE; - } - else if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) == - (DesiredAccess & ~VALID_INHERIT_FLAGS)) - { - *AccessStatus = STATUS_SUCCESS; - return TRUE; - } - else - { - DPRINT1("Denying access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p)\n", - *GrantedAccess, DesiredAccess, GenericMapping); - *AccessStatus = STATUS_ACCESS_DENIED; - return FALSE; - } + /* Call the internal function */ + return SepAccessCheck(SecurityDescriptor, + SubjectSecurityContext, + SubjectContextLocked, + DesiredAccess, + PreviouslyGrantedAccess, + Privileges, + GenericMapping, + AccessMode, + GrantedAccess, + AccessStatus, + SecurityImpersonation); }
/* SYSTEM CALLS ***************************************************************/ @@ -691,16 +718,17 @@ SeLockSubjectContext(&SubjectSecurityContext);
/* Now perform the access check */ - SeAccessCheck(SecurityDescriptor, - &SubjectSecurityContext, - TRUE, - DesiredAccess, - 0, - &PrivilegeSet, //FIXME - GenericMapping, - PreviousMode, - GrantedAccess, - AccessStatus); + SepAccessCheck(SecurityDescriptor, + &SubjectSecurityContext, + TRUE, + DesiredAccess, + 0, + &PrivilegeSet, //FIXME + GenericMapping, + PreviousMode, + GrantedAccess, + AccessStatus, + SecurityIdentification);
/* Unlock subject context and dereference the token */ SeUnlockSubjectContext(&SubjectSecurityContext);