-/* $Id: semgr.c,v 1.20 2002/06/04 14:14:07 ekohl Exp $
+/* $Id: semgr.c,v 1.35 2004/07/19 12:45:56 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
#include <internal/ps.h>
#include <internal/se.h>
+#define NDEBUG
#include <internal/debug.h>
#define TAG_SXPT TAG('S', 'X', 'P', 'T')
/* FUNCTIONS ****************************************************************/
-BOOLEAN
+BOOLEAN INIT_FUNCTION
SeInit1(VOID)
{
SepInitLuid();
if (!SepInitSecurityIDs())
- return(FALSE);
+ return FALSE;
if (!SepInitDACLs())
- return(FALSE);
+ return FALSE;
if (!SepInitSDs())
- return(FALSE);
+ return FALSE;
SepInitPrivileges();
if (!SepInitExports())
- return(FALSE);
+ return FALSE;
- return(TRUE);
+ return TRUE;
}
-BOOLEAN
+BOOLEAN INIT_FUNCTION
SeInit2(VOID)
{
SepInitializeTokenImplementation();
- return(TRUE);
+ return TRUE;
}
-static BOOLEAN
+BOOLEAN
+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 = NtCreateDirectoryObject(&DirectoryHandle,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ 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 = NtCreateEvent(&EventHandle,
+ EVENT_ALL_ACCESS,
+ &ObjectAttributes,
+ FALSE,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
+ NtClose(DirectoryHandle);
+ return FALSE;
+ }
+
+ NtClose(EventHandle);
+ NtClose(DirectoryHandle);
+
+ /* FIXME: Create SRM port and listener thread */
+
+ return TRUE;
+}
+
+
+static BOOLEAN INIT_FUNCTION
SepInitExports(VOID)
{
SeExports = ExAllocatePoolWithTag(NonPagedPool,
sizeof(SE_EXPORTS),
TAG_SXPT);
if (SeExports == NULL)
- return(FALSE);
+ return FALSE;
SeExports->SeCreateTokenPrivilege = SeCreateTokenPrivilege;
SeExports->SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
SeExports->SeAliasPrintOpsSid = SeAliasPrintOpsSid;
SeExports->SeAliasBackupOpsSid = SeAliasBackupOpsSid;
- return(TRUE);
+ return TRUE;
}
UNIMPLEMENTED;
}
-NTSTATUS STDCALL
-NtPrivilegedServiceAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN PUNICODE_STRING ServiceName,
- IN HANDLE ClientToken,
- IN PPRIVILEGE_SET Privileges,
- IN BOOLEAN AccessGranted)
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS STDCALL
-NtPrivilegeObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN PVOID HandleId,
- IN HANDLE ClientToken,
- IN ULONG DesiredAccess,
- IN PPRIVILEGE_SET Privileges,
- IN BOOLEAN AccessGranted)
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS STDCALL
-NtOpenObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN PVOID HandleId,
- IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN HANDLE ClientToken,
- IN ULONG DesiredAccess,
- IN ULONG GrantedAccess,
- IN PPRIVILEGE_SET Privileges,
- IN BOOLEAN ObjectCreation,
- IN BOOLEAN AccessGranted,
- OUT PBOOLEAN GenerateOnClose)
-{
- UNIMPLEMENTED;
-}
-
-
-NTSTATUS STDCALL
-NtAccessCheckAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN PHANDLE ObjectHandle,
- IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN ACCESS_MASK DesiredAccess,
- IN PGENERIC_MAPPING GenericMapping,
- IN BOOLEAN ObjectCreation,
- OUT PULONG GrantedAccess,
- OUT PBOOLEAN AccessStatus,
- OUT PBOOLEAN GenerateOnClose
- )
-{
- UNIMPLEMENTED;
-}
+/*
+ * @unimplemented
+ */
NTSTATUS STDCALL
NtAllocateUuids(PULARGE_INTEGER Time,
PULONG Range,
PULONG Sequence)
{
UNIMPLEMENTED;
+ return(STATUS_NOT_IMPLEMENTED);
}
-NTSTATUS STDCALL
-NtCloseObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN PVOID HandleId,
- IN BOOLEAN GenerateOnClose)
+/*
+ * @implemented
+ */
+VOID STDCALL
+SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
{
- UNIMPLEMENTED;
-}
-
+ PETHREAD Thread;
+ BOOLEAN CopyOnOpen;
+ BOOLEAN EffectiveOnly;
-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 PULONG GrantedAccess,
- OUT PBOOLEAN AccessStatus)
-{
- UNIMPLEMENTED;
+ Thread = PsGetCurrentThread();
+ if (Thread == NULL)
+ {
+ SubjectContext->ProcessAuditId = 0;
+ SubjectContext->PrimaryToken = NULL;
+ SubjectContext->ClientToken = NULL;
+ SubjectContext->ImpersonationLevel = 0;
+ }
+ else
+ {
+ SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
+ SubjectContext->ClientToken =
+ PsReferenceImpersonationToken(Thread,
+ &CopyOnOpen,
+ &EffectiveOnly,
+ &SubjectContext->ImpersonationLevel);
+ SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
+ }
}
-NTSTATUS STDCALL
-NtDeleteObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN PVOID HandleId,
- IN BOOLEAN GenerateOnClose)
+/*
+ * @unimplemented
+ */
+VOID STDCALL
+SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
{
UNIMPLEMENTED;
}
-
-VOID STDCALL SeReleaseSubjectContext (PSECURITY_SUBJECT_CONTEXT SubjectContext)
+/*
+ * @implemented
+ */
+VOID STDCALL
+SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
{
- ObDereferenceObject(SubjectContext->PrimaryToken);
- if (SubjectContext->ClientToken != NULL)
- {
- ObDereferenceObject(SubjectContext->ClientToken);
- }
+ if (SubjectContext->PrimaryToken != NULL)
+ {
+ ObDereferenceObject(SubjectContext->PrimaryToken);
+ }
+
+ if (SubjectContext->ClientToken != NULL)
+ {
+ ObDereferenceObject(SubjectContext->ClientToken);
+ }
}
-VOID STDCALL SeCaptureSubjectContext (PSECURITY_SUBJECT_CONTEXT SubjectContext)
+
+/*
+ * @unimplemented
+ */
+VOID STDCALL
+SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
{
- PEPROCESS Process;
- ULONG a;
- ULONG b;
-
- Process = PsGetCurrentThread()->ThreadsProcess;
-
- SubjectContext->ProcessAuditId = Process;
- SubjectContext->ClientToken =
- PsReferenceImpersonationToken(PsGetCurrentThread(),
- &a,
- &b,
- &SubjectContext->ImpersonationLevel);
- SubjectContext->PrimaryToken = PsReferencePrimaryToken(Process);
+ UNIMPLEMENTED;
}
+/*
+ * @implemented
+ */
NTSTATUS STDCALL
-SeDeassignSecurity(PSECURITY_DESCRIPTOR* SecurityDescriptor)
+SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
{
- if ((*SecurityDescriptor) != NULL)
+ if (*SecurityDescriptor != NULL)
{
ExFreePool(*SecurityDescriptor);
- (*SecurityDescriptor) = NULL;
+ *SecurityDescriptor = NULL;
}
- return(STATUS_SUCCESS);
+
+ return STATUS_SUCCESS;
}
#if 0
-VOID SepGetDefaultsSubjectContext(PSECURITY_SUBJECT_CONTEXT SubjectContext,
- PSID* Owner,
- PSID* PrimaryGroup,
- PSID* ProcessOwner,
- PSID* ProcessPrimaryGroup,
- PACL* DefaultDacl)
+VOID
+SepGetDefaultsSubjectContext(PSECURITY_SUBJECT_CONTEXT SubjectContext,
+ PSID* Owner,
+ PSID* PrimaryGroup,
+ PSID* ProcessOwner,
+ PSID* ProcessPrimaryGroup,
+ PACL* DefaultDacl)
{
- PACCESS_TOKEN Token;
-
- if (SubjectContext->ClientToken != NULL)
- {
+ PACCESS_TOKEN Token;
+
+ if (SubjectContext->ClientToken != NULL)
+ {
Token = SubjectContext->ClientToken;
- }
- else
- {
+ }
+ else
+ {
Token = SubjectContext->PrimaryToken;
- }
- *Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
- *PrimaryGroup = Token->PrimaryGroup;
- *DefaultDacl = Token->DefaultDacl;
- *ProcessOwner = SubjectContext->PrimaryToken->
- UserAndGroups[Token->DefaultOwnerIndex].Sid;
- *ProcessPrimaryGroup = SubjectContext->PrimaryToken->PrimaryGroup;
+ }
+ *Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
+ *PrimaryGroup = Token->PrimaryGroup;
+ *DefaultDacl = Token->DefaultDacl;
+ *ProcessOwner = SubjectContext->PrimaryToken->
+ UserAndGroups[Token->DefaultOwnerIndex].Sid;
+ *ProcessPrimaryGroup = SubjectContext->PrimaryToken->PrimaryGroup;
}
-NTSTATUS SepInheritAcl(PACL Acl,
- BOOLEAN IsDirectoryObject,
- PSID Owner,
- PSID PrimaryGroup,
- PACL DefaultAcl,
- PSID ProcessOwner,
- PSID ProcessGroup,
- PGENERIC_MAPPING GenericMapping)
+
+NTSTATUS
+SepInheritAcl(PACL Acl,
+ BOOLEAN IsDirectoryObject,
+ PSID Owner,
+ PSID PrimaryGroup,
+ PACL DefaultAcl,
+ PSID ProcessOwner,
+ PSID ProcessGroup,
+ PGENERIC_MAPPING GenericMapping)
{
- if (Acl == NULL)
- {
+ if (Acl == NULL)
+ {
return(STATUS_UNSUCCESSFUL);
- }
- if (Acl->AclRevision != 2 &&
- Acl->AclRevision != 3 )
- {
+ }
+
+ if (Acl->AclRevision != 2 &&
+ Acl->AclRevision != 3 )
+ {
return(STATUS_UNSUCCESSFUL);
- }
-
+ }
+
}
#endif
+
+/*
+ * @unimplemented
+ */
NTSTATUS STDCALL
-SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor,
- PSECURITY_DESCRIPTOR ExplicitDescriptor,
- PSECURITY_DESCRIPTOR* NewDescriptor,
+SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
+ PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
+ PSECURITY_DESCRIPTOR *NewDescriptor,
BOOLEAN IsDirectoryObject,
PSECURITY_SUBJECT_CONTEXT SubjectContext,
PGENERIC_MAPPING GenericMapping,
POOL_TYPE PoolType)
{
+ PSECURITY_DESCRIPTOR Descriptor;
+ ULONG Length;
+ NTSTATUS Status;
+
+ if (ExplicitDescriptor != NULL)
+ {
+ Length = RtlLengthSecurityDescriptor(ExplicitDescriptor);
+ }
+ else
+ {
+ DPRINT("No explicit security descriptor\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Descriptor = ExAllocatePool(NonPagedPool,
+ Length);
+ if (Descriptor == NULL)
+ {
+ DPRINT1("ExAlloctePool() failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Status = RtlMakeSelfRelativeSD(ExplicitDescriptor,
+ Descriptor,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlMakeSelfRelativeSD() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ *NewDescriptor = Descriptor;
+
+ return STATUS_SUCCESS;
+
#if 0
- PSECURITY_DESCRIPTOR Descriptor;
PSID Owner;
PSID PrimaryGroup;
PACL DefaultDacl;
PSID ProcessOwner;
PSID ProcessPrimaryGroup;
PACL Sacl;
-
+
if (ExplicitDescriptor == NULL)
{
RtlCreateSecurityDescriptor(&Descriptor, 1);
{
Descriptor = ExplicitDescriptor;
}
+
SeLockSubjectContext(SubjectContext);
+
SepGetDefaultsSubjectContext(SubjectContext,
&Owner,
&PrimaryGroup,
&DefaultDacl,
&ProcessOwner,
&ProcessPrimaryGroup);
+
if (Descriptor->Control & SE_SACL_PRESENT ||
Descriptor->Control & SE_SACL_DEFAULTED)
{
if (ParentDescriptor == NULL)
{
}
+
if (Descriptor->Control & SE_SACL_PRESENT ||
Descriptor->Sacl == NULL ||)
{
- Sacl = NULL;
+ Sacl = NULL;
}
else
{
Sacl = Descriptor->Sacl;
if (Descriptor->Control & SE_SELF_RELATIVE)
{
- Sacl = (PACL)(((PVOID)Sacl) + (PVOID)Descriptor);
+ Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)Descriptor);
}
}
+
SepInheritAcl(Sacl,
IsDirectoryObject,
Owner,
ProcessOwner,
GenericMapping);
}
-#else
- UNIMPLEMENTED;
#endif
}
-BOOLEAN SepSidInToken(PACCESS_TOKEN Token,
- PSID Sid)
+
+static BOOLEAN
+SepSidInToken(PACCESS_TOKEN Token,
+ PSID Sid)
{
- ULONG i;
-
- if (Token->UserAndGroupCount == 0)
- {
- return(FALSE);
- }
-
- for (i=0; i<Token->UserAndGroupCount; i++)
- {
- if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
- {
- if (i == 0 ||
- (!(Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)))
- {
- return(TRUE);
- }
- return(FALSE);
- }
- }
- return(FALSE);
+ ULONG i;
+
+ if (Token->UserAndGroupCount == 0)
+ {
+ return FALSE;
+ }
+
+ for (i=0; i<Token->UserAndGroupCount; i++)
+ {
+ if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
+ {
+ if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+ }
+
+ return FALSE;
}
-BOOLEAN STDCALL
-SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
- IN BOOLEAN SubjectContextLocked,
- IN ACCESS_MASK DesiredAccess,
- IN ACCESS_MASK PreviouslyGrantedAccess,
- OUT PPRIVILEGE_SET* Privileges,
- IN PGENERIC_MAPPING GenericMapping,
- IN KPROCESSOR_MODE AccessMode,
- OUT PACCESS_MODE GrantedAccess,
- OUT PNTSTATUS AccessStatus)
/*
* FUNCTION: Determines whether the requested access rights can be granted
* to an object protected by a security descriptor and an object owner
* GrantedAccess (OUT) = On return specifies the access granted
* AccessStatus (OUT) = Status indicating why access was denied
* RETURNS: If access was granted, returns TRUE
+ *
+ * @implemented
*/
+BOOLEAN STDCALL
+SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
+ IN BOOLEAN SubjectContextLocked,
+ IN ACCESS_MASK DesiredAccess,
+ IN ACCESS_MASK PreviouslyGrantedAccess,
+ OUT PPRIVILEGE_SET* Privileges,
+ IN PGENERIC_MAPPING GenericMapping,
+ IN KPROCESSOR_MODE AccessMode,
+ OUT PACCESS_MASK GrantedAccess,
+ OUT PNTSTATUS AccessStatus)
{
- ULONG i;
- PACL Dacl;
- BOOLEAN Present;
- BOOLEAN Defaulted;
- NTSTATUS Status;
- PACE CurrentAce;
- PSID Sid;
- ACCESS_MASK CurrentAccess;
-
- CurrentAccess = PreviouslyGrantedAccess;
-
- /*
- * Ignore the SACL for now
- */
-
- /*
- * Check the DACL
- */
- Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
- &Present,
- &Dacl,
+ LUID_AND_ATTRIBUTES Privilege;
+ ACCESS_MASK CurrentAccess;
+ PACCESS_TOKEN Token;
+ ULONG i;
+ PACL Dacl;
+ BOOLEAN Present;
+ BOOLEAN Defaulted;
+ PACE CurrentAce;
+ PSID Sid;
+ NTSTATUS Status;
+
+ CurrentAccess = PreviouslyGrantedAccess;
+
+ Token = SubjectSecurityContext->ClientToken ?
+ SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
+
+ /* Get the DACL */
+ Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
+ &Present,
+ &Dacl,
+ &Defaulted);
+ if (!NT_SUCCESS(Status))
+ {
+ *AccessStatus = Status;
+ return FALSE;
+ }
+
+ /* RULE 1: Grant desired access if the object is unprotected */
+ if (Dacl == NULL)
+ {
+ *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 == CurrentAccess)
+ {
+ *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))
- {
- return(Status);
- }
-
- 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(SubjectSecurityContext->ClientToken, Sid))
- {
- *AccessStatus = STATUS_ACCESS_DENIED;
- *GrantedAccess = 0;
- return(STATUS_SUCCESS);
- }
- }
- if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
- {
- if (SepSidInToken(SubjectSecurityContext->ClientToken, Sid))
- {
- CurrentAccess = CurrentAccess |
- CurrentAce->Header.AccessMask;
- }
- }
- }
- if (!(CurrentAccess & DesiredAccess) &&
- !((~CurrentAccess) & DesiredAccess))
- {
- *AccessStatus = STATUS_ACCESS_DENIED;
- }
- else
- {
- *AccessStatus = STATUS_SUCCESS;
- }
- *GrantedAccess = CurrentAccess;
-
- return(STATUS_SUCCESS);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
+ *AccessStatus = Status;
+ return FALSE;
+ }
+
+ if (SepSidInToken(Token, Sid))
+ {
+ CurrentAccess |= (READ_CONTROL | WRITE_DAC);
+ if (DesiredAccess == CurrentAccess)
+ {
+ *GrantedAccess = CurrentAccess;
+ *AccessStatus = STATUS_SUCCESS;
+ return TRUE;
+ }
+ }
+
+ /* 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))
+ {
+ *GrantedAccess = 0;
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return TRUE;
+ }
+ }
+
+ if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
+ {
+ if (SepSidInToken(Token, Sid))
+ {
+ CurrentAccess |= CurrentAce->AccessMask;
+ }
+ }
+ }
+
+ DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
+ CurrentAccess, DesiredAccess);
+
+ *GrantedAccess = CurrentAccess & DesiredAccess;
+
+ *AccessStatus =
+ (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
+
+ 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)
+{
+ SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
+ KPROCESSOR_MODE PreviousMode;
+ PACCESS_TOKEN Token;
+ 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;
+ }
+
+ RtlZeroMemory(&SubjectSecurityContext,
+ sizeof(SECURITY_SUBJECT_CONTEXT));
+ SubjectSecurityContext.ClientToken = Token;
+ SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
+
+ /* FIXME: Lock subject context */
+
+ if (!SeAccessCheck(SecurityDescriptor,
+ &SubjectSecurityContext,
+ TRUE,
+ DesiredAccess,
+ 0,
+ &PrivilegeSet,
+ GenericMapping,
+ PreviousMode,
+ GrantedAccess,
+ AccessStatus))
+ {
+ Status = *AccessStatus;
+ }
+ else
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ /* FIXME: Unlock subject context */
+
+ ObDereferenceObject(Token);
+
+ DPRINT("NtAccessCheck() done\n");
+
+ return Status;
+}
+
/* EOF */