-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/se/semgr.c
* PROGRAMMERS: No programmer listed.
*/
-/* INCLUDES *****************************************************************/
+/* INCLUDES *******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
-/* GLOBALS ******************************************************************/
+/* GLOBALS ********************************************************************/
PSE_EXPORTS SeExports = NULL;
SE_EXPORTS SepExports;
-static ERESOURCE SepSubjectContextLock;
-
-
-/* PROTOTYPES ***************************************************************/
+extern ULONG ExpInitializationPhase;
+extern ERESOURCE SepSubjectContextLock;
-static BOOLEAN SepInitExports(VOID);
+/* PRIVATE FUNCTIONS **********************************************************/
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, SeInit)
-#pragma alloc_text(INIT, SepInitExports)
-#endif
+static BOOLEAN INIT_FUNCTION
+SepInitExports(VOID)
+{
+ SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
+ SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
+ SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
+ SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
+ SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
+ SepExports.SeTcbPrivilege = SeTcbPrivilege;
+ SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
+ SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
+ SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
+ SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
+ SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
+ SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
+ SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
+ SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
+ SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
+ SepExports.SeBackupPrivilege = SeBackupPrivilege;
+ SepExports.SeRestorePrivilege = SeRestorePrivilege;
+ SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
+ SepExports.SeDebugPrivilege = SeDebugPrivilege;
+ SepExports.SeAuditPrivilege = SeAuditPrivilege;
+ SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
+ SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
+ SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
+
+ SepExports.SeNullSid = SeNullSid;
+ SepExports.SeWorldSid = SeWorldSid;
+ SepExports.SeLocalSid = SeLocalSid;
+ SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
+ SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
+ SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
+ SepExports.SeDialupSid = SeDialupSid;
+ SepExports.SeNetworkSid = SeNetworkSid;
+ SepExports.SeBatchSid = SeBatchSid;
+ SepExports.SeInteractiveSid = SeInteractiveSid;
+ SepExports.SeLocalSystemSid = SeLocalSystemSid;
+ SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
+ SepExports.SeAliasUsersSid = SeAliasUsersSid;
+ SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
+ SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
+ SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
+ SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
+ SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
+ SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
+ SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
+ SepExports.SeRestrictedSid = SeRestrictedSid;
+ SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
+
+ SepExports.SeUndockPrivilege = SeUndockPrivilege;
+ SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
+ SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
+
+ SeExports = &SepExports;
+ return TRUE;
+}
-/* FUNCTIONS ****************************************************************/
-BOOLEAN
-INIT_FUNCTION
+BOOLEAN
NTAPI
-SeInit(VOID)
+SepInitializationPhase0(VOID)
{
- DPRINT1("FIXME: SeAccessCheck has been HACKED to always grant access!\n");
- DPRINT1("FIXME: Please fix all the code that doesn't get proper rights!\n");
-
- SepInitLuid();
+ PAGED_CODE();
- if (!SepInitSecurityIDs())
- return FALSE;
+ ExpInitLuid();
+ if (!SepInitSecurityIDs()) return FALSE;
+ if (!SepInitDACLs()) return FALSE;
+ if (!SepInitSDs()) return FALSE;
+ SepInitPrivileges();
+ if (!SepInitExports()) return FALSE;
+
+ /* Initialize the subject context lock */
+ ExInitializeResource(&SepSubjectContextLock);
+
+ /* Initialize token objects */
+ SepInitializeTokenImplementation();
+
+ /* Clear impersonation info for the idle thread */
+ PsGetCurrentThread()->ImpersonationInfo = NULL;
+ PspClearCrossThreadFlag(PsGetCurrentThread(),
+ CT_ACTIVE_IMPERSONATION_INFO_BIT);
+
+ /* Initialize the boot token */
+ ObInitializeFastReference(&PsGetCurrentProcess()->Token, NULL);
+ ObInitializeFastReference(&PsGetCurrentProcess()->Token,
+ SepCreateSystemProcessToken());
+ return TRUE;
+}
- if (!SepInitDACLs())
- return FALSE;
+BOOLEAN
+NTAPI
+SepInitializationPhase1(VOID)
+{
+ NTSTATUS Status;
+ PAGED_CODE();
- if (!SepInitSDs())
- return FALSE;
+ /* Insert the system token into the tree */
+ Status = ObInsertObject((PVOID)(PsGetCurrentProcess()->Token.Value &
+ ~MAX_FAST_REFS),
+ NULL,
+ 0,
+ 0,
+ NULL,
+ NULL);
+ ASSERT(NT_SUCCESS(Status));
+
+ /* FIXME: TODO \\ Security directory */
+ return TRUE;
+}
- SepInitPrivileges();
+BOOLEAN
+NTAPI
+SeInitSystem(VOID)
+{
+ /* Check the initialization phase */
+ switch (ExpInitializationPhase)
+ {
+ case 0:
- if (!SepInitExports())
- return FALSE;
+ /* Do Phase 0 */
+ return SepInitializationPhase0();
- /* Initialize the subject context lock */
- ExInitializeResource(&SepSubjectContextLock);
+ case 1:
- /* Initialize token objects */
- SepInitializeTokenImplementation();
+ /* Do Phase 1 */
+ return SepInitializationPhase1();
- /* Clear impersonation info for the idle thread */
- PsGetCurrentThread()->ImpersonationInfo = NULL;
- PspClearCrossThreadFlag(PsGetCurrentThread(), CT_ACTIVE_IMPERSONATION_INFO_BIT);
+ default:
- /* Initailize the boot token */
- ObInitializeFastReference(&PsGetCurrentProcess()->Token, NULL);
- ObInitializeFastReference(&PsGetCurrentProcess()->Token,
- SepCreateSystemProcessToken());
- return TRUE;
+ /* Don't know any other phase! Bugcheck! */
+ KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL,
+ 0,
+ ExpInitializationPhase,
+ 0,
+ 0);
+ return FALSE;
+ }
}
BOOLEAN
NTAPI
SeInitSRM(VOID)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING Name;
- HANDLE DirectoryHandle;
- HANDLE EventHandle;
- NTSTATUS Status;
-
- /* Create '\Security' directory */
- RtlInitUnicodeString(&Name,
- L"\\Security");
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_PERMANENT,
- 0,
- NULL);
- Status = ZwCreateDirectoryObject(&DirectoryHandle,
- DIRECTORY_ALL_ACCESS,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING Name;
+ HANDLE DirectoryHandle;
+ HANDLE EventHandle;
+ NTSTATUS Status;
+
+ /* Create '\Security' directory */
+ RtlInitUnicodeString(&Name,
+ L"\\Security");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_PERMANENT,
+ 0,
+ NULL);
+ Status = ZwCreateDirectoryObject(&DirectoryHandle,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
{
- DPRINT1("Failed to create 'Security' directory!\n");
- return FALSE;
+ DPRINT1("Failed to create 'Security' directory!\n");
+ return FALSE;
}
- /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
- RtlInitUnicodeString(&Name,
- L"\\LSA_AUTHENTICATION_INITALIZED");
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_PERMANENT,
- DirectoryHandle,
- SePublicDefaultSd);
- Status = ZwCreateEvent(&EventHandle,
- EVENT_ALL_ACCESS,
- &ObjectAttributes,
- SynchronizationEvent,
- FALSE);
- if (!NT_SUCCESS(Status))
+ /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
+ RtlInitUnicodeString(&Name,
+ L"\\LSA_AUTHENTICATION_INITALIZED");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_PERMANENT,
+ DirectoryHandle,
+ SePublicDefaultSd);
+ Status = ZwCreateEvent(&EventHandle,
+ EVENT_ALL_ACCESS,
+ &ObjectAttributes,
+ SynchronizationEvent,
+ FALSE);
+ if (!NT_SUCCESS(Status))
{
- DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
- NtClose(DirectoryHandle);
- return FALSE;
+ DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
+ NtClose(DirectoryHandle);
+ return FALSE;
}
- ZwClose(EventHandle);
- ZwClose(DirectoryHandle);
+ ZwClose(EventHandle);
+ ZwClose(DirectoryHandle);
- /* FIXME: Create SRM port and listener thread */
+ /* FIXME: Create SRM port and listener thread */
- return TRUE;
+ return TRUE;
}
-
-static BOOLEAN INIT_FUNCTION
-SepInitExports(VOID)
+NTSTATUS
+NTAPI
+SeDefaultObjectMethod(IN PVOID Object,
+ IN SECURITY_OPERATION_CODE OperationType,
+ IN PSECURITY_INFORMATION SecurityInformation,
+ IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN OUT PULONG ReturnLength OPTIONAL,
+ IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
+ IN POOL_TYPE PoolType,
+ IN PGENERIC_MAPPING GenericMapping)
{
- SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
- SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
- SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
- SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
- SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
- SepExports.SeTcbPrivilege = SeTcbPrivilege;
- SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
- SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
- SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
- SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
- SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
- SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
- SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
- SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
- SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
- SepExports.SeBackupPrivilege = SeBackupPrivilege;
- SepExports.SeRestorePrivilege = SeRestorePrivilege;
- SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
- SepExports.SeDebugPrivilege = SeDebugPrivilege;
- SepExports.SeAuditPrivilege = SeAuditPrivilege;
- SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
- SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
- SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
-
- SepExports.SeNullSid = SeNullSid;
- SepExports.SeWorldSid = SeWorldSid;
- SepExports.SeLocalSid = SeLocalSid;
- SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
- SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
- SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
- SepExports.SeDialupSid = SeDialupSid;
- SepExports.SeNetworkSid = SeNetworkSid;
- SepExports.SeBatchSid = SeBatchSid;
- SepExports.SeInteractiveSid = SeInteractiveSid;
- SepExports.SeLocalSystemSid = SeLocalSystemSid;
- SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
- SepExports.SeAliasUsersSid = SeAliasUsersSid;
- SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
- SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
- SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
- SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
- SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
- SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
- SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
- SepExports.SeRestrictedSid = SeRestrictedSid;
- SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
-
- SepExports.SeUndockPrivilege = SeUndockPrivilege;
- SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
- SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
-
- SeExports = &SepExports;
- return TRUE;
-}
-
+ PAGED_CODE();
-VOID SepReferenceLogonSession(PLUID AuthenticationId)
-{
- UNIMPLEMENTED;
-}
+ /* Select the operation type */
+ switch (OperationType)
+ {
+ /* Setting a new descriptor */
+ case SetSecurityDescriptor:
-VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
-{
- UNIMPLEMENTED;
-}
+ /* Sanity check */
+ ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool));
-NTSTATUS
-STDCALL
-SeDefaultObjectMethod(PVOID Object,
- SECURITY_OPERATION_CODE OperationType,
- PSECURITY_INFORMATION _SecurityInformation,
- PSECURITY_DESCRIPTOR _SecurityDescriptor,
- PULONG ReturnLength,
- PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
- POOL_TYPE PoolType,
- PGENERIC_MAPPING GenericMapping)
-{
- PISECURITY_DESCRIPTOR ObjectSd;
- PISECURITY_DESCRIPTOR NewSd;
- PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
- POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
- PSID Owner = 0;
- PSID Group = 0;
- PACL Dacl = 0;
- PACL Sacl = 0;
- ULONG OwnerLength = 0;
- ULONG GroupLength = 0;
- ULONG DaclLength = 0;
- ULONG SaclLength = 0;
- ULONG Control = 0;
- ULONG_PTR Current;
- NTSTATUS Status;
- SECURITY_INFORMATION SecurityInformation;
-
- if (OperationType == SetSecurityDescriptor)
- {
- ObjectSd = Header->SecurityDescriptor;
- SecurityInformation = *_SecurityInformation;
-
- /* Get owner and owner size */
- if (SecurityInformation & OWNER_SECURITY_INFORMATION)
- {
- if (SecurityDescriptor->Owner != NULL)
- {
- if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
- Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
- (ULONG_PTR)SecurityDescriptor);
- else
- Owner = (PSID)SecurityDescriptor->Owner;
- OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
- }
- Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
- }
- else
- {
- if (ObjectSd->Owner != NULL)
- {
- Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
- OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
- }
- Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
- }
-
- /* Get group and group size */
- if (SecurityInformation & GROUP_SECURITY_INFORMATION)
- {
- if (SecurityDescriptor->Group != NULL)
- {
- if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
- Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
- (ULONG_PTR)SecurityDescriptor);
- else
- Group = (PSID)SecurityDescriptor->Group;
- GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
- }
- Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
- }
- else
- {
- if (ObjectSd->Group != NULL)
- {
- Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
- GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
- }
- Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
- }
-
- /* Get DACL and DACL size */
- if (SecurityInformation & DACL_SECURITY_INFORMATION)
- {
- if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
- (SecurityDescriptor->Dacl != NULL))
- {
- if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
- Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
- (ULONG_PTR)SecurityDescriptor);
- else
- Dacl = (PACL)SecurityDescriptor->Dacl;
-
- DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
- }
- Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
- }
- else
- {
- if ((ObjectSd->Control & SE_DACL_PRESENT) &&
- (ObjectSd->Dacl != NULL))
- {
- Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
- DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
- }
- Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
- }
-
- /* Get SACL and SACL size */
- if (SecurityInformation & SACL_SECURITY_INFORMATION)
- {
- if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
- (SecurityDescriptor->Sacl != NULL))
- {
- if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
- Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
- (ULONG_PTR)SecurityDescriptor);
- else
- Sacl = (PACL)SecurityDescriptor->Sacl;
- SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
- }
- Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
- }
- else
- {
- if ((ObjectSd->Control & SE_SACL_PRESENT) &&
- (ObjectSd->Sacl != NULL))
- {
- Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
- SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
- }
- Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
- }
-
- NewSd = ExAllocatePool(NonPagedPool,
- sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
- DaclLength + SaclLength);
- if (NewSd == NULL)
- {
- ObDereferenceObject(Object);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- RtlCreateSecurityDescriptor(NewSd,
- SECURITY_DESCRIPTOR_REVISION1);
- /* We always build a self-relative descriptor */
- NewSd->Control = (USHORT)Control | SE_SELF_RELATIVE;
-
- Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
-
- if (OwnerLength != 0)
- {
- RtlCopyMemory((PVOID)Current,
- Owner,
- OwnerLength);
- NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
- Current += OwnerLength;
- }
-
- if (GroupLength != 0)
- {
- RtlCopyMemory((PVOID)Current,
- Group,
- GroupLength);
- NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
- Current += GroupLength;
- }
-
- if (DaclLength != 0)
- {
- RtlCopyMemory((PVOID)Current,
- Dacl,
- DaclLength);
- NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
- Current += DaclLength;
- }
-
- if (SaclLength != 0)
- {
- RtlCopyMemory((PVOID)Current,
- Sacl,
- SaclLength);
- NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
- Current += SaclLength;
- }
-
- /* Add the new SD */
- Status = ObpAddSecurityDescriptor(NewSd,
- &Header->SecurityDescriptor);
- if (NT_SUCCESS(Status))
- {
- /* Remove the old security descriptor */
- ObpRemoveSecurityDescriptor(ObjectSd);
- }
- else
- {
- /* Restore the old security descriptor */
- Header->SecurityDescriptor = ObjectSd;
- }
-
- ExFreePool(NewSd);
- }
- else if (OperationType == QuerySecurityDescriptor)
- {
- Status = SeQuerySecurityDescriptorInfo(_SecurityInformation,
+ /* Set the information */
+ return ObSetSecurityDescriptorInfo(Object,
+ SecurityInformation,
SecurityDescriptor,
- ReturnLength,
- &Header->SecurityDescriptor);
- }
- else if (OperationType == AssignSecurityDescriptor)
- {
- /* Assign the security descriptor to the object header */
- Status = ObpAddSecurityDescriptor(SecurityDescriptor,
- &Header->SecurityDescriptor);
- }
+ OldSecurityDescriptor,
+ PoolType,
+ GenericMapping);
+ case QuerySecurityDescriptor:
- return STATUS_SUCCESS;
-}
+ /* Query the information */
+ return ObQuerySecurityDescriptorInfo(Object,
+ SecurityInformation,
+ SecurityDescriptor,
+ ReturnLength,
+ OldSecurityDescriptor);
-VOID
-NTAPI
-SeCaptureSubjectContextEx(IN PETHREAD Thread,
- IN PEPROCESS Process,
- OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
-{
- BOOLEAN CopyOnOpen, EffectiveOnly;
- PAGED_CODE();
+ case DeleteSecurityDescriptor:
- /* Save the unique ID */
- SubjectContext->ProcessAuditId = Process->UniqueProcessId;
+ /* De-assign it */
+ return ObDeassignSecurity(OldSecurityDescriptor);
- /* Check if we have a thread */
- if (!Thread)
- {
- /* We don't, so no token */
- SubjectContext->ClientToken = NULL;
- }
- else
- {
- /* Get the impersonation token */
- SubjectContext->ClientToken =
- PsReferenceImpersonationToken(Thread,
- &CopyOnOpen,
- &EffectiveOnly,
- &SubjectContext->ImpersonationLevel);
- }
+ case AssignSecurityDescriptor:
- /* Get the primary token */
- SubjectContext->PrimaryToken = PsReferencePrimaryToken(Process);
-}
-
-/*
- * @implemented
- */
-VOID
-NTAPI
-SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
-{
- /* Call the internal API */
- SeCaptureSubjectContextEx(PsGetCurrentThread(),
- PsGetCurrentProcess(),
- SubjectContext);
-}
+ /* Assign it */
+ ObAssignObjectSecurityDescriptor(Object, SecurityDescriptor, PoolType);
+ return STATUS_SUCCESS;
+ default:
-/*
- * @implemented
- */
-VOID STDCALL
-SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
-{
- PAGED_CODE();
+ /* Bug check */
+ KeBugCheckEx(SECURITY_SYSTEM, 0, STATUS_INVALID_PARAMETER, 0, 0);
+ }
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
+ /* Should never reach here */
+ ASSERT(FALSE);
+ return STATUS_SUCCESS;
}
+ULONG SidInTokenCalls = 0;
-/*
- * @implemented
- */
-VOID STDCALL
-SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
+static BOOLEAN
+SepSidInToken(PACCESS_TOKEN _Token,
+ PSID Sid)
{
- PAGED_CODE();
+ ULONG i;
+ PTOKEN Token = (PTOKEN)_Token;
- ExReleaseResourceLite(&SepSubjectContextLock);
- KeLeaveCriticalRegion();
-}
-
-
-/*
- * @implemented
- */
-VOID STDCALL
-SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
-{
- PAGED_CODE();
+ PAGED_CODE();
- if (SubjectContext->PrimaryToken != NULL)
+ SidInTokenCalls++;
+ if (!(SidInTokenCalls % 10000)) DPRINT1("SidInToken Calls: %d\n", SidInTokenCalls);
+
+ if (Token->UserAndGroupCount == 0)
{
- ObFastDereferenceObject(&PsGetCurrentProcess()->Token, SubjectContext->PrimaryToken);
+ return FALSE;
}
- if (SubjectContext->ClientToken != NULL)
+ for (i=0; i<Token->UserAndGroupCount; i++)
{
- ObDereferenceObject(SubjectContext->ClientToken);
+ if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
+ {
+ if ((i == 0)|| (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
}
-}
+ return FALSE;
+}
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
+static BOOLEAN
+SepTokenIsOwner(PACCESS_TOKEN Token,
+ PSECURITY_DESCRIPTOR SecurityDescriptor)
{
- PAGED_CODE();
+ NTSTATUS Status;
+ PSID Sid = NULL;
+ BOOLEAN Defaulted;
+
+ Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
+ &Sid,
+ &Defaulted);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
+ return FALSE;
+ }
- if (*SecurityDescriptor != NULL)
+ if (Sid == NULL)
{
- ExFreePool(*SecurityDescriptor);
- *SecurityDescriptor = NULL;
+ DPRINT1("Owner Sid is NULL\n");
+ return FALSE;
}
- return STATUS_SUCCESS;
+ return SepSidInToken(Token, Sid);
}
-
-/*
- * @unimplemented
- */
-NTSTATUS STDCALL
-SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
- IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
- OUT PSECURITY_DESCRIPTOR *NewDescriptor,
- IN GUID *ObjectType OPTIONAL,
- IN BOOLEAN IsDirectoryObject,
- IN ULONG AutoInheritFlags,
- IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
- IN PGENERIC_MAPPING GenericMapping,
- IN POOL_TYPE PoolType)
+VOID NTAPI
+SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
+ OUT PACCESS_MASK DesiredAccess)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
+ *DesiredAccess = 0;
-/*
- * FUNCTION: Creates a security descriptor for a new object.
- * ARGUMENTS:
- * ParentDescriptor =
- * ExplicitDescriptor =
- * NewDescriptor =
- * IsDirectoryObject =
- * SubjectContext =
- * GeneralMapping =
- * PoolType =
- * RETURNS: Status
- *
- * @implemented
- */
-NTSTATUS STDCALL
-SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL,
- PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL,
- PSECURITY_DESCRIPTOR *NewDescriptor,
- BOOLEAN IsDirectoryObject,
- PSECURITY_SUBJECT_CONTEXT SubjectContext,
- PGENERIC_MAPPING GenericMapping,
- POOL_TYPE PoolType)
-{
- PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
- PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
- PISECURITY_DESCRIPTOR Descriptor;
- PTOKEN Token;
- ULONG OwnerLength = 0;
- ULONG GroupLength = 0;
- ULONG DaclLength = 0;
- ULONG SaclLength = 0;
- ULONG Length = 0;
- ULONG Control = 0;
- ULONG_PTR Current;
- PSID Owner = NULL;
- PSID Group = NULL;
- PACL Dacl = NULL;
- PACL Sacl = NULL;
-
- PAGED_CODE();
-
- /* Lock subject context */
- SeLockSubjectContext(SubjectContext);
-
- if (SubjectContext->ClientToken != NULL)
+ if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
{
- Token = SubjectContext->ClientToken;
+ *DesiredAccess |= READ_CONTROL;
}
- else
+ if (SecurityInformation & SACL_SECURITY_INFORMATION)
{
- Token = SubjectContext->PrimaryToken;
+ *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
}
+}
+VOID NTAPI
+SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
+ OUT PACCESS_MASK DesiredAccess)
+{
+ *DesiredAccess = 0;
- /* Inherit the Owner SID */
- if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
+ if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
{
- DPRINT("Use explicit owner sid!\n");
- Owner = ExplicitDescriptor->Owner;
-
- if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
- {
- Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
-
- }
+ *DesiredAccess |= WRITE_OWNER;
}
- else
+ if (SecurityInformation & DACL_SECURITY_INFORMATION)
{
- if (Token != NULL)
- {
- DPRINT("Use token owner sid!\n");
- Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
- }
- else
- {
- DPRINT("Use default owner sid!\n");
- Owner = SeLocalSystemSid;
- }
-
- Control |= SE_OWNER_DEFAULTED;
+ *DesiredAccess |= WRITE_DAC;
+ }
+ if (SecurityInformation & SACL_SECURITY_INFORMATION)
+ {
+ *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
}
+}
- OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
+#define OLD_ACCESS_CHECK
- /* Inherit the Group SID */
- if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
- {
- DPRINT("Use explicit group sid!\n");
- Group = ExplicitDescriptor->Group;
- if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
- {
- Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
- }
- }
- else
+BOOLEAN NTAPI
+SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
+ 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)
+{
+ LUID_AND_ATTRIBUTES Privilege;
+#ifdef OLD_ACCESS_CHECK
+ ACCESS_MASK CurrentAccess, AccessMask;
+#endif
+ ACCESS_MASK RemainingAccess;
+ ACCESS_MASK TempAccess;
+ ACCESS_MASK TempGrantedAccess = 0;
+ ACCESS_MASK TempDeniedAccess = 0;
+ PACCESS_TOKEN Token;
+ ULONG i;
+ PACL Dacl;
+ BOOLEAN Present;
+ BOOLEAN Defaulted;
+ PACE CurrentAce;
+ PSID Sid;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ /* Check for no access desired */
+ if (!DesiredAccess)
{
- if (Token != NULL)
- {
- DPRINT("Use token group sid!\n");
- Group = Token->PrimaryGroup;
- }
- else
- {
- DPRINT("Use default group sid!\n");
- Group = SeLocalSystemSid;
- }
-
- Control |= SE_OWNER_DEFAULTED;
+ /* 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;
}
- GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
+ /* Map given accesses */
+ RtlMapGenericMask(&DesiredAccess, GenericMapping);
+ if (PreviouslyGrantedAccess)
+ RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping);
+#ifdef OLD_ACCESS_CHECK
+ CurrentAccess = PreviouslyGrantedAccess;
+#endif
+ /* Initialize remaining access rights */
+ RemainingAccess = DesiredAccess;
- /* Inherit the DACL */
- if (ExplicitDescriptor != NULL &&
- (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
- !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
- {
- DPRINT("Use explicit DACL!\n");
- Dacl = ExplicitDescriptor->Dacl;
- if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
- {
- Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
- }
-
- Control |= SE_DACL_PRESENT;
- }
- else if (ParentDescriptor != NULL &&
- (ParentDescriptor->Control & SE_DACL_PRESENT))
+ Token = SubjectSecurityContext->ClientToken ?
+ SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
+
+ /* Check for system security access */
+ if (RemainingAccess & ACCESS_SYSTEM_SECURITY)
{
- DPRINT("Use parent DACL!\n");
- /* FIXME: Inherit */
- Dacl = ParentDescriptor->Dacl;
- if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
- {
- Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
- }
- Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
+ Privilege.Luid = SeSecurityPrivilege;
+ Privilege.Attributes = SE_PRIVILEGE_ENABLED;
+
+ /* Fail if we do not the SeSecurityPrivilege */
+ if (!SepPrivilegeCheck(Token,
+ &Privilege,
+ 1,
+ PRIVILEGE_SET_ALL_NECESSARY,
+ AccessMode))
+ {
+ *AccessStatus = STATUS_PRIVILEGE_NOT_HELD;
+ return FALSE;
+ }
+
+ /* Adjust access rights */
+ RemainingAccess &= ~ACCESS_SYSTEM_SECURITY;
+ PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY;
+
+ /* Succeed if there are no more rights to grant */
+ if (RemainingAccess == 0)
+ {
+ *GrantedAccess = PreviouslyGrantedAccess;
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
+ }
}
- else if (Token != NULL && Token->DefaultDacl != NULL)
+
+ /* Get the DACL */
+ Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
+ &Present,
+ &Dacl,
+ &Defaulted);
+ if (!NT_SUCCESS(Status))
{
- DPRINT("Use token default DACL!\n");
- /* FIXME: Inherit */
- Dacl = Token->DefaultDacl;
- Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
+ *AccessStatus = Status;
+ return FALSE;
}
- else
+
+ /* RULE 1: Grant desired access if the object is unprotected */
+ if (Present == FALSE || Dacl == NULL)
{
- DPRINT("Use NULL DACL!\n");
- Dacl = NULL;
- Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
+ if (DesiredAccess & MAXIMUM_ALLOWED)
+ {
+ *GrantedAccess = GenericMapping->GenericAll;
+ *GrantedAccess |= (DesiredAccess & ~MAXIMUM_ALLOWED);
+ }
+ else
+ {
+ *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
+ }
+
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
}
- DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
-
+#ifdef OLD_ACCESS_CHECK
+ CurrentAccess = PreviouslyGrantedAccess;
+#endif
- /* Inherit the SACL */
- if (ExplicitDescriptor != NULL &&
- (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
- !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
+ /* RULE 2: Check token for 'take ownership' privilege */
+ if (DesiredAccess & WRITE_OWNER)
{
- DPRINT("Use explicit SACL!\n");
- Sacl = ExplicitDescriptor->Sacl;
- if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
- {
- Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
- }
-
- Control |= SE_SACL_PRESENT;
+ Privilege.Luid = SeTakeOwnershipPrivilege;
+ Privilege.Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (SepPrivilegeCheck(Token,
+ &Privilege,
+ 1,
+ PRIVILEGE_SET_ALL_NECESSARY,
+ AccessMode))
+ {
+ /* Adjust access rights */
+ RemainingAccess &= ~WRITE_OWNER;
+ PreviouslyGrantedAccess |= WRITE_OWNER;
+#ifdef OLD_ACCESS_CHECK
+ CurrentAccess |= WRITE_OWNER;
+#endif
+
+ /* Succeed if there are no more rights to grant */
+ if (RemainingAccess == 0)
+ {
+ *GrantedAccess = PreviouslyGrantedAccess;
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
+ }
+ }
}
- else if (ParentDescriptor != NULL &&
- (ParentDescriptor->Control & SE_SACL_PRESENT))
+
+ /* Deny access if the DACL is empty */
+ if (Dacl->AceCount == 0)
{
- DPRINT("Use parent SACL!\n");
- /* FIXME: Inherit */
- Sacl = ParentDescriptor->Sacl;
- if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
- {
- Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
- }
- Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
+ if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0)
+ {
+ *GrantedAccess = PreviouslyGrantedAccess;
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
+ }
+ else
+ {
+ *GrantedAccess = 0;
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return FALSE;
+ }
}
- SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
-
-
- /* Allocate and initialize the new security descriptor */
- Length = sizeof(SECURITY_DESCRIPTOR) +
- OwnerLength + GroupLength + DaclLength + SaclLength;
-
- DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
- sizeof(SECURITY_DESCRIPTOR),
- OwnerLength,
- GroupLength,
- DaclLength,
- SaclLength);
-
- Descriptor = ExAllocatePool(PagedPool,
- Length);
- if (Descriptor == NULL)
+ /* Fail if DACL is absent */
+ if (Present == FALSE)
{
- DPRINT1("ExAlloctePool() failed\n");
- /* FIXME: Unlock subject context */
- return STATUS_INSUFFICIENT_RESOURCES;
+ *GrantedAccess = 0;
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return FALSE;
}
- RtlZeroMemory( Descriptor, Length );
- RtlCreateSecurityDescriptor(Descriptor,
- SECURITY_DESCRIPTOR_REVISION);
-
- Descriptor->Control = (USHORT)Control | SE_SELF_RELATIVE;
-
- Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
-
- if (SaclLength != 0)
+ /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
+ if (DesiredAccess & MAXIMUM_ALLOWED)
{
- RtlCopyMemory((PVOID)Current,
- Sacl,
- SaclLength);
- Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
- Current += SaclLength;
+ CurrentAce = (PACE)(Dacl + 1);
+ for (i = 0; i < Dacl->AceCount; i++)
+ {
+ if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
+ {
+ Sid = (PSID)(CurrentAce + 1);
+ if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
+ {
+ if (SepSidInToken(Token, Sid))
+ {
+ /* Map access rights from the ACE */
+ TempAccess = CurrentAce->AccessMask;
+ RtlMapGenericMask(&TempAccess, GenericMapping);
+
+ /* Deny access rights that have not been granted yet */
+ TempDeniedAccess |= (TempAccess & ~TempGrantedAccess);
+ }
+ }
+ else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
+ {
+ if (SepSidInToken(Token, Sid))
+ {
+ /* Map access rights from the ACE */
+ TempAccess = CurrentAce->AccessMask;
+ RtlMapGenericMask(&TempAccess, GenericMapping);
+
+ /* Grant access rights that have not been denied yet */
+ TempGrantedAccess |= (TempAccess & ~TempDeniedAccess);
+ }
+ }
+ else
+ {
+ DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
+ }
+ }
+
+ /* Get the next ACE */
+ CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
+ }
+
+ /* Fail if some rights have not been granted */
+ RemainingAccess &= ~(MAXIMUM_ALLOWED | TempGrantedAccess);
+ if (RemainingAccess != 0)
+ {
+ *GrantedAccess = 0;
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return FALSE;
+ }
+
+ /* Set granted access right and access status */
+ *GrantedAccess = TempGrantedAccess | PreviouslyGrantedAccess;
+ if (*GrantedAccess != 0)
+ {
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
+ }
+ else
+ {
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return FALSE;
+ }
}
- if (DaclLength != 0)
+ /* RULE 4: Grant rights according to the DACL */
+ CurrentAce = (PACE)(Dacl + 1);
+ for (i = 0; i < Dacl->AceCount; i++)
{
- RtlCopyMemory((PVOID)Current,
- Dacl,
- DaclLength);
- Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
- Current += DaclLength;
+ if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
+ {
+ Sid = (PSID)(CurrentAce + 1);
+ if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
+ {
+ if (SepSidInToken(Token, Sid))
+ {
+#ifdef OLD_ACCESS_CHECK
+ *GrantedAccess = 0;
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return FALSE;
+#else
+ /* Map access rights from the ACE */
+ TempAccess = CurrentAce->AccessMask;
+ RtlMapGenericMask(&TempAccess, GenericMapping);
+
+ /* Leave if a remaining right must be denied */
+ if (RemainingAccess & TempAccess)
+ break;
+#endif
+ }
+ }
+ else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
+ {
+ if (SepSidInToken(Token, Sid))
+ {
+#ifdef OLD_ACCESS_CHECK
+ AccessMask = CurrentAce->AccessMask;
+ RtlMapGenericMask(&AccessMask, GenericMapping);
+ CurrentAccess |= AccessMask;
+#else
+ /* Map access rights from the ACE */
+ TempAccess = CurrentAce->AccessMask;
+ RtlMapGenericMask(&TempAccess, GenericMapping);
+
+ /* Remove granted rights */
+ RemainingAccess &= ~TempAccess;
+#endif
+ }
+ }
+ else
+ {
+ DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
+ }
+ }
+
+ /* Get the next ACE */
+ CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
}
- if (OwnerLength != 0)
+#ifdef OLD_ACCESS_CHECK
+ DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
+ CurrentAccess, DesiredAccess);
+
+ *GrantedAccess = CurrentAccess & DesiredAccess;
+
+ if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) ==
+ (DesiredAccess & ~VALID_INHERIT_FLAGS))
{
- RtlCopyMemory((PVOID)Current,
- Owner,
- OwnerLength);
- Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
- Current += OwnerLength;
- DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
+ }
+ else
+ {
+ DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
+ *GrantedAccess, DesiredAccess, GenericMapping);
+ //*AccessStatus = STATUS_ACCESS_DENIED;
+ //return FALSE;
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
}
- else
- DPRINT("Owner of %x is zero length\n", Descriptor);
+#else
+ DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
+ DesiredAccess, PreviouslyGrantedAccess, RemainingAccess);
- if (GroupLength != 0)
+ /* Fail if some rights have not been granted */
+ if (RemainingAccess != 0)
{
- memmove((PVOID)Current,
- Group,
- GroupLength);
- Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
+ *GrantedAccess = 0;
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return FALSE;
}
- /* Unlock subject context */
- SeUnlockSubjectContext(SubjectContext);
+ /* Set granted access rights */
+ *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
- *NewDescriptor = Descriptor;
+ DPRINT("GrantedAccess %08lx\n", *GrantedAccess);
- DPRINT("Descrptor %x\n", Descriptor);
- ASSERT(RtlLengthSecurityDescriptor(Descriptor));
+ /* Fail if no rights have been granted */
+ if (*GrantedAccess == 0)
+ {
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return FALSE;
+ }
- return STATUS_SUCCESS;
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
+#endif
}
-
-static BOOLEAN
-SepSidInToken(PACCESS_TOKEN _Token,
- PSID Sid)
+static PSID
+SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
{
- ULONG i;
- PTOKEN Token = (PTOKEN)_Token;
+ PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
+ PSID Owner;
- PAGED_CODE();
+ if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
+ Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
+ (ULONG_PTR)SecurityDescriptor);
+ else
+ Owner = (PSID)SecurityDescriptor->Owner;
- if (Token->UserAndGroupCount == 0)
- {
- return FALSE;
- }
+ return Owner;
+}
- for (i=0; i<Token->UserAndGroupCount; i++)
- {
- if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
- {
- if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
- {
- return TRUE;
- }
+static PSID
+SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
+{
+ PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
+ PSID Group;
- return FALSE;
- }
- }
+ if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
+ Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
+ (ULONG_PTR)SecurityDescriptor);
+ else
+ Group = (PSID)SecurityDescriptor->Group;
- return FALSE;
+ return Group;
}
+/* PUBLIC FUNCTIONS ***********************************************************/
+
/*
- * FUNCTION: Determines whether the requested access rights can be granted
- * to an object protected by a security descriptor and an object owner
- * ARGUMENTS:
- * SecurityDescriptor = Security descriptor protecting the object
- * SubjectSecurityContext = Subject's captured security context
- * SubjectContextLocked = Indicates the user's subject context is locked
- * DesiredAccess = Access rights the caller is trying to acquire
- * PreviouslyGrantedAccess = Specified the access rights already granted
- * Privileges = ?
- * GenericMapping = Generic mapping associated with the object
- * AccessMode = Access mode used for the check
- * 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
+BOOLEAN NTAPI
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)
+ 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)
{
- LUID_AND_ATTRIBUTES Privilege;
- ACCESS_MASK CurrentAccess;
- PACCESS_TOKEN Token;
- ULONG i;
- PACL Dacl;
- BOOLEAN Present;
- BOOLEAN Defaulted;
- PACE CurrentAce;
- PSID Sid;
- NTSTATUS Status;
-
- PAGED_CODE();
-
- /* Check if we didn't get an SD */
- if (!SecurityDescriptor)
- {
- /* Automatic failure */
- *AccessStatus = STATUS_ACCESS_DENIED;
- return FALSE;
- }
-
- CurrentAccess = PreviouslyGrantedAccess;
-
- if (SubjectContextLocked == FALSE)
- {
- SeLockSubjectContext(SubjectSecurityContext);
- }
+ BOOLEAN ret;
- Token = SubjectSecurityContext->ClientToken ?
- SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
+ PAGED_CODE();
- /* Get the DACL */
- Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
- &Present,
- &Dacl,
- &Defaulted);
- if (!NT_SUCCESS(Status))
+ /* Check if this is kernel mode */
+ if (AccessMode == KernelMode)
{
- if (SubjectContextLocked == FALSE)
- {
- SeUnlockSubjectContext(SubjectSecurityContext);
- }
-
- *AccessStatus = Status;
- return FALSE;
+ /* 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;
}
- /* RULE 1: Grant desired access if the object is unprotected */
- if (Present == TRUE && Dacl == NULL)
+ /* Check if we didn't get an SD */
+ if (!SecurityDescriptor)
{
- if (SubjectContextLocked == FALSE)
- {
- SeUnlockSubjectContext(SubjectSecurityContext);
- }
-
- *GrantedAccess = DesiredAccess;
- *AccessStatus = STATUS_SUCCESS;
- return TRUE;
+ /* Automatic failure */
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return FALSE;
}
- CurrentAccess = PreviouslyGrantedAccess;
+ /* Check for invalid impersonation */
+ if ((SubjectSecurityContext->ClientToken) &&
+ (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation))
+ {
+ *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL;
+ return FALSE;
+ }
- /* RULE 2: Check token for 'take ownership' privilege */
- Privilege.Luid = SeTakeOwnershipPrivilege;
- Privilege.Attributes = SE_PRIVILEGE_ENABLED;
+ /* Acquire the lock if needed */
+ if (!SubjectContextLocked)
+ SeLockSubjectContext(SubjectSecurityContext);
- if (SepPrivilegeCheck(Token,
- &Privilege,
- 1,
- PRIVILEGE_SET_ALL_NECESSARY,
- AccessMode))
+ /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
+ if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
{
- CurrentAccess |= WRITE_OWNER;
- if (DesiredAccess == CurrentAccess)
- {
- if (SubjectContextLocked == FALSE)
- {
- SeUnlockSubjectContext(SubjectSecurityContext);
- }
-
- *GrantedAccess = CurrentAccess;
- *AccessStatus = STATUS_SUCCESS;
- return TRUE;
- }
+ PACCESS_TOKEN Token = SubjectSecurityContext->ClientToken ?
+ SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
+
+ if (SepTokenIsOwner(Token,
+ SecurityDescriptor))
+ {
+ if (DesiredAccess & MAXIMUM_ALLOWED)
+ PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
+ else
+ PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
+
+ DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
+ }
}
- /* RULE 3: Check whether the token is the owner */
- Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
- &Sid,
- &Defaulted);
- if (!NT_SUCCESS(Status))
+ if (DesiredAccess == 0)
+ {
+ *GrantedAccess = PreviouslyGrantedAccess;
+ *AccessStatus = STATUS_SUCCESS;
+ ret = TRUE;
+ }
+ else
{
- DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
- if (SubjectContextLocked == FALSE)
- {
- SeUnlockSubjectContext(SubjectSecurityContext);
- }
+ /* Call the internal function */
+ ret = SepAccessCheck(SecurityDescriptor,
+ SubjectSecurityContext,
+ DesiredAccess,
+ PreviouslyGrantedAccess,
+ Privileges,
+ GenericMapping,
+ AccessMode,
+ GrantedAccess,
+ AccessStatus);
+ }
+
+ /* Release the lock if needed */
+ if (!SubjectContextLocked)
+ SeUnlockSubjectContext(SubjectSecurityContext);
+
+ return ret;
+}
+
+/* SYSTEM CALLS ***************************************************************/
- *AccessStatus = Status;
- return FALSE;
- }
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN HANDLE TokenHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN PGENERIC_MAPPING GenericMapping,
+ OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
+ IN OUT PULONG PrivilegeSetLength,
+ OUT PACCESS_MASK GrantedAccess,
+ OUT PNTSTATUS AccessStatus)
+{
+ PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
+ SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ ACCESS_MASK PreviouslyGrantedAccess = 0;
+ PTOKEN Token;
+ NTSTATUS Status;
+ PAGED_CODE();
- if (Sid && SepSidInToken(Token, Sid))
+ /* Check if this is kernel mode */
+ if (PreviousMode == KernelMode)
{
- CurrentAccess |= (READ_CONTROL | WRITE_DAC);
- if (DesiredAccess == CurrentAccess)
- {
- if (SubjectContextLocked == FALSE)
- {
- SeUnlockSubjectContext(SubjectSecurityContext);
- }
-
- *GrantedAccess = CurrentAccess;
- *AccessStatus = STATUS_SUCCESS;
- return TRUE;
- }
+ /* Check if kernel wants everything */
+ if (DesiredAccess & MAXIMUM_ALLOWED)
+ {
+ /* Give it */
+ *GrantedAccess = GenericMapping->GenericAll;
+ *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
+ }
+ else
+ {
+ /* Just give the desired access */
+ *GrantedAccess = DesiredAccess;
+ }
+
+ /* Success */
+ *AccessStatus = STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
- /* Fail if DACL is absent */
- if (Present == FALSE)
+ /* Protect probe in SEH */
+ _SEH2_TRY
{
- if (SubjectContextLocked == FALSE)
- {
- SeUnlockSubjectContext(SubjectSecurityContext);
- }
-
- *GrantedAccess = 0;
- *AccessStatus = STATUS_ACCESS_DENIED;
- return FALSE;
+ /* Probe all pointers */
+ ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG));
+ ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
+ ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
+ ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
+ ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
}
-
- /* RULE 4: Grant rights according to the DACL */
- CurrentAce = (PACE)(Dacl + 1);
- for (i = 0; i < Dacl->AceCount; i++)
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- 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))
- {
- CurrentAccess |= CurrentAce->AccessMask;
- }
- }
- else
- DPRINT1("Unknown Ace type 0x%lx\n", CurrentAce->Header.AceType);
- CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
}
-
- if (SubjectContextLocked == FALSE)
+ _SEH2_END;
+
+ /* Check for unmapped access rights */
+ if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
+ return STATUS_GENERIC_NOT_MAPPED;
+
+ /* Reference the token */
+ Status = ObReferenceObjectByHandle(TokenHandle,
+ TOKEN_QUERY,
+ SepTokenObjectType,
+ PreviousMode,
+ (PVOID*)&Token,
+ NULL);
+ if (!NT_SUCCESS(Status))
{
- SeUnlockSubjectContext(SubjectSecurityContext);
+ DPRINT("Failed to reference token (Status %lx)\n", Status);
+ return Status;
}
- DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
- CurrentAccess, DesiredAccess);
-
- *GrantedAccess = CurrentAccess & DesiredAccess;
-
- if (*GrantedAccess == DesiredAccess)
+ /* Check token type */
+ if (Token->TokenType != TokenImpersonation)
{
- *AccessStatus = STATUS_SUCCESS;
- return TRUE;
+ DPRINT("No impersonation token\n");
+ ObDereferenceObject(Token);
+ return STATUS_NO_IMPERSONATION_TOKEN;
}
- else
+
+ /* Check the impersonation level */
+ if (Token->ImpersonationLevel < SecurityIdentification)
{
- *AccessStatus = STATUS_SUCCESS;
- DPRINT("FIX caller rights (granted 0x%lx, desired 0x%lx)!\n",
- *GrantedAccess, DesiredAccess);
- return TRUE; /* FIXME: should be FALSE */
+ DPRINT("Impersonation level < SecurityIdentification\n");
+ ObDereferenceObject(Token);
+ return STATUS_BAD_IMPERSONATION_LEVEL;
}
-}
-
-
-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)
-{
- SECURITY_SUBJECT_CONTEXT SubjectSecurityContext = {0};
- KPROCESSOR_MODE PreviousMode;
- PTOKEN Token;
- NTSTATUS Status;
- PAGED_CODE();
-
- DPRINT("NtAccessCheck() called\n");
-
- PreviousMode = KeGetPreviousMode();
- if (PreviousMode == KernelMode)
+ /* Capture the security descriptor */
+ Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
+ PreviousMode,
+ PagedPool,
+ FALSE,
+ &CapturedSecurityDescriptor);
+ if (!NT_SUCCESS(Status))
{
- *GrantedAccess = DesiredAccess;
- *AccessStatus = STATUS_SUCCESS;
- return STATUS_SUCCESS;
+ DPRINT("Failed to capture the Security Descriptor\n");
+ ObDereferenceObject(Token);
+ return Status;
}
- Status = ObReferenceObjectByHandle(TokenHandle,
- TOKEN_QUERY,
- SepTokenObjectType,
- PreviousMode,
- (PVOID*)&Token,
- NULL);
- if (!NT_SUCCESS(Status))
+ /* Check the captured security descriptor */
+ if (CapturedSecurityDescriptor == NULL)
{
- DPRINT1("Failed to reference token (Status %lx)\n", Status);
- return Status;
+ DPRINT("Security Descriptor is NULL\n");
+ ObDereferenceObject(Token);
+ return STATUS_INVALID_SECURITY_DESCR;
}
- /* Check token type */
- if (Token->TokenType != TokenImpersonation)
+ /* Check security descriptor for valid owner and group */
+ if (SepGetSDOwner(SecurityDescriptor) == NULL || // FIXME: use CapturedSecurityDescriptor
+ SepGetSDGroup(SecurityDescriptor) == NULL) // FIXME: use CapturedSecurityDescriptor
{
- DPRINT1("No impersonation token\n");
- ObDereferenceObject(Token);
- return STATUS_ACCESS_VIOLATION;
+ DPRINT("Security Descriptor does not have a valid group or owner\n");
+ SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
+ PreviousMode,
+ FALSE);
+ ObDereferenceObject(Token);
+ return STATUS_INVALID_SECURITY_DESCR;
}
- /* Check impersonation level */
- if (Token->ImpersonationLevel < SecurityAnonymous)
+ /* Set up the subject context, and lock it */
+ SubjectSecurityContext.ClientToken = Token;
+ SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
+ SubjectSecurityContext.PrimaryToken = NULL;
+ SubjectSecurityContext.ProcessAuditId = NULL;
+ SeLockSubjectContext(&SubjectSecurityContext);
+
+ /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
+ if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
{
- DPRINT1("Invalid impersonation level\n");
- ObDereferenceObject(Token);
- return STATUS_ACCESS_VIOLATION;
+ if (SepTokenIsOwner(Token, SecurityDescriptor)) // FIXME: use CapturedSecurityDescriptor
+ {
+ if (DesiredAccess & MAXIMUM_ALLOWED)
+ PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
+ else
+ PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
+
+ DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
+ }
}
- SubjectSecurityContext.ClientToken = Token;
- SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
-
- /* Lock subject context */
- SeLockSubjectContext(&SubjectSecurityContext);
-
- if (SeAccessCheck(SecurityDescriptor,
- &SubjectSecurityContext,
- TRUE,
- DesiredAccess,
- 0,
- &PrivilegeSet,
- GenericMapping,
- PreviousMode,
- GrantedAccess,
- AccessStatus))
+ if (DesiredAccess == 0)
{
- Status = *AccessStatus;
+ *GrantedAccess = PreviouslyGrantedAccess;
+ *AccessStatus = STATUS_SUCCESS;
}
- else
+ else
{
- Status = STATUS_ACCESS_DENIED;
+ /* Now perform the access check */
+ SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
+ &SubjectSecurityContext,
+ DesiredAccess,
+ PreviouslyGrantedAccess,
+ &PrivilegeSet, //FIXME
+ GenericMapping,
+ PreviousMode,
+ GrantedAccess,
+ AccessStatus);
}
- /* Unlock subject context */
- SeUnlockSubjectContext(&SubjectSecurityContext);
+ /* Unlock subject context */
+ SeUnlockSubjectContext(&SubjectSecurityContext);
- ObDereferenceObject(Token);
+ /* Release the captured security descriptor */
+ SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
+ PreviousMode,
+ FALSE);
- DPRINT("NtAccessCheck() done\n");
+ /* Dereference the token */
+ ObDereferenceObject(Token);
- return Status;
+ /* Check succeeded */
+ return STATUS_SUCCESS;
}
+
NTSTATUS
NTAPI
NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
return STATUS_NOT_IMPLEMENTED;
}
-VOID STDCALL
-SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
- OUT PACCESS_MASK DesiredAccess)
-{
- if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
- GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
- {
- *DesiredAccess |= READ_CONTROL;
- }
- if (SecurityInformation & SACL_SECURITY_INFORMATION)
- {
- *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
- }
-}
-
-VOID STDCALL
-SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
- OUT PACCESS_MASK DesiredAccess)
-{
- if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
- {
- *DesiredAccess |= WRITE_OWNER;
- }
- if (SecurityInformation & DACL_SECURITY_INFORMATION)
- {
- *DesiredAccess |= WRITE_DAC;
- }
- if (SecurityInformation & SACL_SECURITY_INFORMATION)
- {
- *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
- }
-}
-
/* EOF */