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=44…
==============================================================================
--- 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);