-/* $Id: semgr.c,v 1.14 2000/01/05 21:57:00 dwelch Exp $
+/* $Id$
*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * PURPOSE: Security manager
- * FILE: kernel/se/semgr.c
- * PROGRAMER: ?
- * REVISION HISTORY:
- * 26/07/98: Added stubs for security functions
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/se/semgr.c
+ * PURPOSE: Security manager
+ *
+ * PROGRAMMERS: No programmer listed.
*/
/* INCLUDES *****************************************************************/
-#include <ddk/ntddk.h>
-
+#include <ntoskrnl.h>
+#define NDEBUG
#include <internal/debug.h>
-/* FUNCTIONS ***************************************************************/
+/* GLOBALS ******************************************************************/
-VOID SepReferenceLogonSession(PLUID AuthenticationId)
-{
- UNIMPLEMENTED;
-}
+PSE_EXPORTS SeExports = NULL;
+SE_EXPORTS SepExports;
-VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
-{
- UNIMPLEMENTED;
-}
+static ERESOURCE SepSubjectContextLock;
-VOID SepFreeProxyData(PVOID ProxyData)
-{
- UNIMPLEMENTED;
-}
-NTSTATUS SepCopyProxyData(PVOID* Dest, PVOID Src)
-{
- UNIMPLEMENTED;
-}
+/* PROTOTYPES ***************************************************************/
-NTSTATUS SepDuplicationToken(PACCESS_TOKEN Token,
- PULONG a,
- ULONG b,
- TOKEN_TYPE TokenType,
- SECURITY_IMPERSONATION_LEVEL Level,
- ULONG d,
- PACCESS_TOKEN* e)
-{
-#if 0
- PVOID mem1;
- PVOID mem2;
- PVOID f;
- PACCESS_TOKEN g;
- NTSTATUS Status;
-
- if (TokenType == 2 &&
- (Level > 3 || Level < 0))
- {
- return(STATUS_UNSUCCESSFUL);
- }
-
- SepReferenceLogonSession(&Token->AuthenticationId);
-
- mem1 = ExAllocatePool(NonPagedPool, Token->DynamicCharged);
- if (mem1 == NULL)
- {
- SepDeReferenceLogonSession(&Token->AuthenticationId);
- return(STATUS_UNSUCCESSFUL);
- }
- if (Token->ProxyData != NULL)
- {
- Status = SepCopyProxyData(&f, Token->ProxyData);
- if (!NT_SUCCESS(Status))
- {
- SepDeReferenceLogonSession(&Token->AuthenticationId);
- ExFreePool(mem1);
- return(Status);
- }
- }
- else
- {
- f = 0;
- }
- if (Token->AuditData != NULL)
- {
- mem2 = ExAllocatePool(NonPagedPool, 0xc);
- if (mem2 == NULL)
- {
- SepFreeProxyData(f);
- SepDeReferenceLogonSession(&Token->AuthenticationId);
- ExFreePool(mem1);
- return(STATUS_UNSUCCESSFUL);
- }
- memcpy(mem2, Token->AuditData, 0xc);
- }
- else
- {
- mem2 = NULL;
- }
-
- Status = ObCreateObject(d,
- SeTokenType,
- b,
- d,
- 0,
- Token->VariableLength + 0x78,
- Token->DynamicCharged,
- Token->VariableLength + 0x78,
- &g);
- if (!NT_SUCCESS(Status))
- {
- SepDeReferenceLogonSession(Token->AuthenticationId);
- ExFreePool(mem1);
- SepFreeProxyData(f);
- if (mem2 != NULL)
- {
- ExFreePool(mem2);
- }
- return(Status);
- }
-
- g->TokenId = Token->TokenId;
- g->ModifiedId = Token->ModifiedId;
- g->ExpirationTime = Token->ExpirationTime;
- memcpy(&g->TokenSource, &Token->TokenSource, sizeof(TOKEN_SOURCE));
- g->DynamicCharged = Token->DynamicCharged;
- g->DynamicAvailable = Token->DynamicAvailable;
- g->DefaultOwnerIndex = Token->DefaultOwnerIndex;
- g->UserAndGroupCount = Token->UserAndGroupCount;
- g->PrivilegeCount = Token->PrivilegeCount;
- g->VariableLength = Token->VariableLength;
- g->TokenFlags = Token->TokenFlags;
- g->ProxyData = f;
- g->AuditData = mem2;
- //g->TokenId = ExInterlockedExchangeAdd();
- g->TokenInUse = 0;
- g->TokenType = TokenType;
- g->ImpersonationLevel = Level;
- memmove(g->VariablePart, Token->VariablePart, Token->VariableLength);
- /* ... */
- *e = g;
- return(STATUS_SUCCESS);
+static BOOLEAN SepInitExports(VOID);
+
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, SeInit1)
+#pragma alloc_text(INIT, SeInit2)
+#pragma alloc_text(INIT, SepInitExports)
#endif
- UNIMPLEMENTED;
-}
-NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token,
- SECURITY_IMPERSONATION_LEVEL Level,
- ULONG a,
- PACCESS_TOKEN* b)
-{
- ULONG c;
- PACCESS_TOKEN d;
- NTSTATUS Status;
-
- c = 18;
- Status = SepDuplicationToken(Token,
- &c,
- 0,
- TokenImpersonation,
- Level,
- a,
- &d);
- *b = d;
- return(Status);
-}
+/* FUNCTIONS ****************************************************************/
-NTSTATUS SeCreateClientSecurity(PETHREAD Thread,
- PSECURITY_QUALITY_OF_SERVICE Qos,
- ULONG e,
- PSE_SOME_STRUCT2 f)
+BOOLEAN
+INIT_FUNCTION
+NTAPI
+SeInit1(VOID)
{
- TOKEN_TYPE TokenType;
- UCHAR b;
- SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
- PACCESS_TOKEN Token;
- ULONG g;
- PACCESS_TOKEN NewToken;
-
- Token = PsReferenceEffectiveToken(Thread,
- &TokenType,
- &b,
- &ImpersonationLevel);
- if (TokenType != 2)
- {
- f->Unknown9 = Qos->EffectiveOnly;
- }
- else
- {
- if (Qos->ImpersonationLevel > ImpersonationLevel)
- {
- if (Token != NULL)
- {
- ObDereferenceObject(Token);
- }
- return(STATUS_UNSUCCESSFUL);
- }
- if (ImpersonationLevel == 0 ||
- ImpersonationLevel == 1 ||
- (e != 0 && ImpersonationLevel != 3))
- {
- if (Token != NULL)
- {
- ObDereferenceObject(Token);
- }
- return(STATUS_UNSUCCESSFUL);
- }
- if (b != 0 ||
- Qos->EffectiveOnly != 0)
- {
- f->Unknown9 = 1;
- }
- else
- {
- f->Unknown9 = 0;
- }
- }
-
- if (Qos->ContextTrackingMode == 0)
- {
- f->Unknown8 = 0;
- g = SeCopyClientToken(Token, ImpersonationLevel, 0, &NewToken);
- if (g >= 0)
- {
-// ObDeleteCapturedInsertInfo(NewToken);
- }
- if (TokenType == TokenPrimary || Token != NULL)
- {
- ObDereferenceObject(Token);
- }
- if (g < 0)
- {
- return(g);
- }
- }
- else
- {
- f->Unknown8 = 1;
- if (e != 0)
- {
-// SeGetTokenControlInformation(Token, &f->Unknown11);
- }
- NewToken = Token;
- }
- f->Unknown1 = 0xc;
- f->Level = Qos->ImpersonationLevel;
- f->ContextTrackingMode = Qos->ContextTrackingMode;
- f->EffectiveOnly = Qos->EffectiveOnly;
- f->Unknown10 = e;
- f->Token = NewToken;
-
- return(STATUS_SUCCESS);
-}
+ SepInitLuid();
+ if (!SepInitSecurityIDs())
+ return FALSE;
-VOID SeImpersonateClient(PSE_SOME_STRUCT2 a,
- PETHREAD Thread)
-{
- UCHAR b;
-
- if (a->Unknown8 == 0)
- {
- b = a->EffectiveOnly;
- }
- else
- {
- b = a->Unknown9;
- }
- if (Thread == NULL)
- {
- Thread = PsGetCurrentThread();
- }
- PsImpersonateClient(Thread,
- a->Token,
- 1,
- (ULONG)b,
- a->Level);
-}
+ if (!SepInitDACLs())
+ return FALSE;
+ if (!SepInitSDs())
+ return FALSE;
+ SepInitPrivileges();
+ if (!SepInitExports())
+ return FALSE;
-NTSTATUS STDCALL NtPrivilegeCheck (IN HANDLE ClientToken,
- IN PPRIVILEGE_SET RequiredPrivileges,
- IN PBOOLEAN Result)
-{
- UNIMPLEMENTED;
+ /* Initialize the subject context lock */
+ ExInitializeResource(&SepSubjectContextLock);
+
+ return TRUE;
}
-NTSTATUS STDCALL NtPrivilegedServiceAuditAlarm(
- IN PUNICODE_STRING SubsystemName,
- IN PUNICODE_STRING ServiceName,
- IN HANDLE ClientToken,
- IN PPRIVILEGE_SET Privileges,
- IN BOOLEAN AccessGranted)
+BOOLEAN
+INIT_FUNCTION
+NTAPI
+SeInit2(VOID)
{
- UNIMPLEMENTED;
+ SepInitializeTokenImplementation();
+
+ return TRUE;
}
-NTSTATUS
-STDCALL
-NtPrivilegeObjectAuditAlarm (
- IN PUNICODE_STRING SubsystemName,
- IN PVOID HandleId,
- IN HANDLE ClientToken,
- IN ULONG DesiredAccess,
- IN PPRIVILEGE_SET Privileges,
- IN BOOLEAN AccessGranted
- )
+BOOLEAN
+NTAPI
+SeInitSRM(VOID)
{
- UNIMPLEMENTED;
-}
+ 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;
+ }
-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;
-}
+ /* 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;
+ }
-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;
+ ZwClose(EventHandle);
+ ZwClose(DirectoryHandle);
+
+ /* FIXME: Create SRM port and listener thread */
+
+ return TRUE;
}
-NTSTATUS
-STDCALL
-NtAllocateUuids (
- PLARGE_INTEGER Time,
- PULONG Version, // ???
- PULONG ClockCycle
- )
+static BOOLEAN INIT_FUNCTION
+SepInitExports(VOID)
{
- UNIMPLEMENTED;
+ 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;
}
-NTSTATUS STDCALL NtCloseObjectAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN PVOID HandleId,
- IN BOOLEAN GenerateOnClose)
+VOID SepReferenceLogonSession(PLUID AuthenticationId)
{
UNIMPLEMENTED;
}
-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)
+VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
{
UNIMPLEMENTED;
}
-
NTSTATUS
STDCALL
-NtDeleteObjectAuditAlarm (
- IN PUNICODE_STRING SubsystemName,
- IN PVOID HandleId,
- IN BOOLEAN GenerateOnClose
- )
+SeDefaultObjectMethod(PVOID Object,
+ SECURITY_OPERATION_CODE OperationType,
+ SECURITY_INFORMATION SecurityInformation,
+ PSECURITY_DESCRIPTOR _SecurityDescriptor,
+ PULONG ReturnLength,
+ PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
+ POOL_TYPE PoolType,
+ PGENERIC_MAPPING GenericMapping)
{
- UNIMPLEMENTED;
+ PISECURITY_DESCRIPTOR ObjectSd;
+ PISECURITY_DESCRIPTOR NewSd;
+ PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
+ POBJECT_HEADER Header = BODY_TO_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;
+
+ if (OperationType == SetSecurityDescriptor)
+ {
+ ObjectSd = Header->SecurityDescriptor;
+
+ /* 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 = 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,
+ SecurityDescriptor,
+ ReturnLength,
+ &Header->SecurityDescriptor);
+ }
+ else if (OperationType == AssignSecurityDescriptor)
+ {
+ /* Assign the security descriptor to the object header */
+ Status = ObpAddSecurityDescriptor(SecurityDescriptor,
+ &Header->SecurityDescriptor);
+ }
+
+
+ return STATUS_SUCCESS;
}
-VOID STDCALL SeReleaseSubjectContext (PSECURITY_SUBJECT_CONTEXT SubjectContext)
+/*
+ * @implemented
+ */
+VOID STDCALL
+SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
{
- ObDereferenceObject(SubjectContext->PrimaryToken);
- if (SubjectContext->ClientToken != NULL)
- {
- ObDereferenceObject(SubjectContext->ClientToken);
- }
+ PETHREAD Thread;
+ BOOLEAN CopyOnOpen;
+ BOOLEAN EffectiveOnly;
+
+ PAGED_CODE();
+
+ 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);
+ }
}
-VOID STDCALL SeCaptureSubjectContext (PSECURITY_SUBJECT_CONTEXT SubjectContext)
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+SeLockSubjectContext(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);
+ PAGED_CODE();
+
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
}
-BOOLEAN SepPrivilegeCheck(PACCESS_TOKEN Token,
- PLUID_AND_ATTRIBUTES Privileges,
- ULONG PrivilegeCount,
- ULONG PrivilegeControl,
- KPROCESSOR_MODE PreviousMode)
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
{
- ULONG i;
- PLUID_AND_ATTRIBUTES Current;
- ULONG j;
- ULONG k;
-
- if (PreviousMode == KernelMode)
- {
- return(TRUE);
- }
-
- j = 0;
- if (PrivilegeCount != 0)
- {
- k = PrivilegeCount;
- do
- {
- i = Token->PrivilegeCount;
- Current = Token->Privileges;
- for (i = 0; i < Token->PrivilegeCount; i++)
- {
- if (!(Current[i].Attributes & 2) &&
- Privileges[i].Luid.u.LowPart ==
- Current[i].Luid.u.LowPart &&
- Privileges[i].Luid.u.HighPart ==
- Current[i].Luid.u.HighPart)
- {
- Privileges[i].Attributes =
- Privileges[i].Attributes | 0x80;
- j++;
- break;
- }
- }
- k--;
- } while (k > 0);
- }
-
- if ((PrivilegeControl & 0x2) && PrivilegeCount == j)
- {
- return(TRUE);
- }
-
- if (j > 0 && !(PrivilegeControl & 0x2))
- {
- return(TRUE);
- }
-
- return(FALSE);
+ PAGED_CODE();
+
+ ExReleaseResourceLite(&SepSubjectContextLock);
+ KeLeaveCriticalRegion();
}
-
-BOOLEAN STDCALL SePrivilegeCheck(PPRIVILEGE_SET Privileges,
- PSECURITY_SUBJECT_CONTEXT SubjectContext,
- KPROCESSOR_MODE PreviousMode)
+
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
{
- PACCESS_TOKEN Token = NULL;
-
- if (SubjectContext->ClientToken == NULL)
- {
- Token = SubjectContext->PrimaryToken;
- }
- else
- {
- Token = SubjectContext->ClientToken;
- if (SubjectContext->ImpersonationLevel < 2)
- {
- return(FALSE);
- }
- }
-
- return(SepPrivilegeCheck(Token,
- Privileges->Privilege,
- Privileges->PrivilegeCount,
- Privileges->Control,
- PreviousMode));
+ PAGED_CODE();
+
+ if (SubjectContext->PrimaryToken != NULL)
+ {
+ ObDereferenceObject(SubjectContext->PrimaryToken);
+ }
+
+ if (SubjectContext->ClientToken != NULL)
+ {
+ ObDereferenceObject(SubjectContext->ClientToken);
+ }
}
-BOOLEAN STDCALL SeSinglePrivilegeCheck(LUID PrivilegeValue,
- KPROCESSOR_MODE PreviousMode)
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
{
- SECURITY_SUBJECT_CONTEXT SubjectContext;
- BOOLEAN r;
- PRIVILEGE_SET Priv;
-
- SeCaptureSubjectContext(&SubjectContext);
-
- Priv.PrivilegeCount = 1;
- Priv.Control = 1;
- Priv.Privilege[0].Luid = PrivilegeValue;
- Priv.Privilege[0].Attributes = 0;
-
- r = SePrivilegeCheck(&Priv,
- &SubjectContext,
- PreviousMode);
-
- if (PreviousMode != KernelMode)
- {
-/* SePrivilegeServiceAuditAlarm(0,
- &SubjectContext,
- &PrivilegeValue);*/
- }
- SeReleaseSubjectContext(&SubjectContext);
- return(r);
+ PAGED_CODE();
+
+ if (*SecurityDescriptor != NULL)
+ {
+ ExFreePool(*SecurityDescriptor);
+ *SecurityDescriptor = NULL;
+ }
+
+ return STATUS_SUCCESS;
}
-NTSTATUS STDCALL SeDeassignSecurity(PSECURITY_DESCRIPTOR* SecurityDescriptor)
+
+/*
+ * @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)
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
}
-NTSTATUS STDCALL SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor,
- PSECURITY_DESCRIPTOR ExplicitDescriptor,
- BOOLEAN IsDirectoryObject,
- PSECURITY_SUBJECT_CONTEXT SubjectContext,
- PGENERIC_MAPPING GenericMapping,
- POOL_TYPE PoolType)
+
+/*
+ * 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)
{
- UNIMPLEMENTED;
+ 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)
+ {
+ Token = SubjectContext->ClientToken;
+ }
+ else
+ {
+ Token = SubjectContext->PrimaryToken;
+ }
+
+
+ /* Inherit the Owner SID */
+ if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
+ {
+ DPRINT("Use explicit owner sid!\n");
+ Owner = ExplicitDescriptor->Owner;
+
+ if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
+ {
+ Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
+
+ }
+ }
+ else
+ {
+ 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;
+ }
+
+ OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
+
+
+ /* 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
+ {
+ 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;
+ }
+
+ GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
+
+
+ /* 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))
+ {
+ 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);
+ }
+ else if (Token != NULL && Token->DefaultDacl != NULL)
+ {
+ DPRINT("Use token default DACL!\n");
+ /* FIXME: Inherit */
+ Dacl = Token->DefaultDacl;
+ Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
+ }
+ else
+ {
+ DPRINT("Use NULL DACL!\n");
+ Dacl = NULL;
+ Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
+ }
+
+ DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
+
+
+ /* Inherit the SACL */
+ if (ExplicitDescriptor != NULL &&
+ (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
+ !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
+ {
+ 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;
+ }
+ else if (ParentDescriptor != NULL &&
+ (ParentDescriptor->Control & SE_SACL_PRESENT))
+ {
+ 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);
+ }
+
+ 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)
+ {
+ DPRINT1("ExAlloctePool() failed\n");
+ /* FIXME: Unlock subject context */
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory( Descriptor, Length );
+ RtlCreateSecurityDescriptor(Descriptor,
+ SECURITY_DESCRIPTOR_REVISION);
+
+ Descriptor->Control = Control | SE_SELF_RELATIVE;
+
+ Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
+
+ if (SaclLength != 0)
+ {
+ RtlCopyMemory((PVOID)Current,
+ Sacl,
+ SaclLength);
+ Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
+ Current += SaclLength;
+ }
+
+ if (DaclLength != 0)
+ {
+ RtlCopyMemory((PVOID)Current,
+ Dacl,
+ DaclLength);
+ Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
+ Current += DaclLength;
+ }
+
+ if (OwnerLength != 0)
+ {
+ 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);
+ }
+ else
+ DPRINT("Owner of %x is zero length\n", Descriptor);
+
+ if (GroupLength != 0)
+ {
+ memmove((PVOID)Current,
+ Group,
+ GroupLength);
+ Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
+ }
+
+ /* Unlock subject context */
+ SeUnlockSubjectContext(SubjectContext);
+
+ *NewDescriptor = Descriptor;
+
+ DPRINT("Descrptor %x\n", Descriptor);
+ ASSERT(RtlLengthSecurityDescriptor(Descriptor));
+
+ return STATUS_SUCCESS;
}
-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 & 0x4)))
- {
- return(TRUE);
- }
- return(FALSE);
- }
- }
- return(FALSE);
+ ULONG i;
+ PTOKEN Token = (PTOKEN)_Token;
+
+ PAGED_CODE();
+
+ 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;
+
+ PAGED_CODE();
+
+ CurrentAccess = PreviouslyGrantedAccess;
+
+ if (SubjectContextLocked == FALSE)
+ {
+ SeLockSubjectContext(SubjectSecurityContext);
+ }
+
+ 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 == CurrentAccess)
+ {
+ 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))
- {
- 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);
+ if (SubjectContextLocked == FALSE)
+ {
+ SeUnlockSubjectContext(SubjectSecurityContext);
+ }
+
+ *AccessStatus = Status;
+ return FALSE;
+ }
+
+ if (SepSidInToken(Token, Sid))
+ {
+ CurrentAccess |= (READ_CONTROL | WRITE_DAC);
+ if (DesiredAccess == CurrentAccess)
+ {
+ 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 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))
+ {
+ if (SubjectContextLocked == FALSE)
+ {
+ SeUnlockSubjectContext(SubjectSecurityContext);
+ }
+
+ *GrantedAccess = 0;
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return TRUE;
+ }
+ }
+
+ if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
+ {
+ if (SepSidInToken(Token, Sid))
+ {
+ CurrentAccess |= CurrentAce->AccessMask;
+ }
+ }
+ }
+
+ if (SubjectContextLocked == FALSE)
+ {
+ SeUnlockSubjectContext(SubjectSecurityContext);
+ }
+
+ 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 = {0};
+ KPROCESSOR_MODE PreviousMode;
+ PTOKEN Token;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ 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;
+ }
+
+ SubjectSecurityContext.ClientToken = Token;
+ SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
+
+ /* Lock subject context */
+ SeLockSubjectContext(&SubjectSecurityContext);
+
+ if (SeAccessCheck(SecurityDescriptor,
+ &SubjectSecurityContext,
+ TRUE,
+ DesiredAccess,
+ 0,
+ &PrivilegeSet,
+ GenericMapping,
+ PreviousMode,
+ GrantedAccess,
+ AccessStatus))
+ {
+ Status = *AccessStatus;
+ }
+ else
+ {
+ Status = STATUS_ACCESS_DENIED;
+ }
+
+ /* Unlock subject context */
+ SeUnlockSubjectContext(&SubjectSecurityContext);
+
+ ObDereferenceObject(Token);
+
+ DPRINT("NtAccessCheck() done\n");
+
+ return Status;
}
+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 */