cm/regfile.c, ldr/init.c, ldr/loader.c: OBJ_CASE_INSENSITIVE patch I proposed
on the list. This makes the registry, and dll loading case insensitive when
we are on a case preserving filesystem.
ntoskrnl/ex/power.c: My own contributions to the poweroff message list.
ntoskrnl/mm/npool.c: Fixed bit-rot in whole page alloc. That's how i found
the bug below.
se/semgr.c, lib/rtl/sd.c:
semgr, when creating a SECURITY_DESCRIPTOR, anded the PRESENT and DEFAULT
flags rather than oring them for group, dacl, and sacl, leading to
RtlLengthSecurityDescriptor giving the wrong length to sdcache. When
sdcache would copy the security descriptor, it would be too short, and
the bound check from the whole-page allocator would go off. I fixed this
and made rtl/sd.c use the ROUND_UP macro and RtlLengthSid. This is cleaner.
It may not be completely correct yet but it no-longer truncates security
descriptors into the cache, which means that the Owner, Group and etc
SIDs should now actually work right when coming from the cache, no matter
what happens in the heap. They probably seemed to work before simply
because they trashed the ends of their blocks and never moved in the
cache.
svn path=/trunk/; revision=11040
2004-09-25 06:41:16 +00:00
|
|
|
/* $Id: semgr.c,v 1.45 2004/09/25 06:41:16 arty Exp $
|
1999-12-26 17:22:19 +00:00
|
|
|
*
|
1998-08-25 04:27:26 +00:00
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
2004-08-29 15:50:53 +00:00
|
|
|
#define NDEBUG
|
1998-08-25 04:27:26 +00:00
|
|
|
#include <internal/debug.h>
|
|
|
|
|
2002-02-20 20:16:49 +00:00
|
|
|
#define TAG_SXPT TAG('S', 'X', 'P', 'T')
|
|
|
|
|
|
|
|
|
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
2002-09-08 10:23:54 +00:00
|
|
|
PSE_EXPORTS EXPORTED SeExports = NULL;
|
2002-02-20 20:16:49 +00:00
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
static ERESOURCE SepSubjectContextLock;
|
|
|
|
|
2002-02-20 20:16:49 +00:00
|
|
|
|
|
|
|
/* PROTOTYPES ***************************************************************/
|
|
|
|
|
|
|
|
static BOOLEAN SepInitExports(VOID);
|
|
|
|
|
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
2002-02-20 20:16:49 +00:00
|
|
|
|
2003-10-12 17:05:50 +00:00
|
|
|
BOOLEAN INIT_FUNCTION
|
2002-02-20 20:16:49 +00:00
|
|
|
SeInit1(VOID)
|
|
|
|
{
|
|
|
|
SepInitLuid();
|
|
|
|
|
|
|
|
if (!SepInitSecurityIDs())
|
2004-05-20 12:42:51 +00:00
|
|
|
return FALSE;
|
2002-02-20 20:16:49 +00:00
|
|
|
|
|
|
|
if (!SepInitDACLs())
|
2004-05-20 12:42:51 +00:00
|
|
|
return FALSE;
|
2002-02-20 20:16:49 +00:00
|
|
|
|
|
|
|
if (!SepInitSDs())
|
2004-05-20 12:42:51 +00:00
|
|
|
return FALSE;
|
2002-02-20 20:16:49 +00:00
|
|
|
|
|
|
|
SepInitPrivileges();
|
|
|
|
|
|
|
|
if (!SepInitExports())
|
2004-05-20 12:42:51 +00:00
|
|
|
return FALSE;
|
2002-02-20 20:16:49 +00:00
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
/* Initialize the subject context lock */
|
|
|
|
ExInitializeResource(&SepSubjectContextLock);
|
|
|
|
|
2004-05-20 12:42:51 +00:00
|
|
|
return TRUE;
|
2002-02-20 20:16:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-12 17:05:50 +00:00
|
|
|
BOOLEAN INIT_FUNCTION
|
2002-02-20 20:16:49 +00:00
|
|
|
SeInit2(VOID)
|
|
|
|
{
|
2002-06-04 14:14:07 +00:00
|
|
|
SepInitializeTokenImplementation();
|
2002-06-04 13:44:06 +00:00
|
|
|
|
2004-05-20 12:42:51 +00:00
|
|
|
return TRUE;
|
2002-02-20 20:16:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 21:07:49 +00:00
|
|
|
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");
|
2004-05-20 12:42:51 +00:00
|
|
|
return FALSE;
|
2003-02-15 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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))
|
|
|
|
{
|
2004-05-20 12:42:51 +00:00
|
|
|
DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
|
2003-02-15 21:07:49 +00:00
|
|
|
NtClose(DirectoryHandle);
|
2004-05-20 12:42:51 +00:00
|
|
|
return FALSE;
|
2003-02-15 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NtClose(EventHandle);
|
|
|
|
NtClose(DirectoryHandle);
|
|
|
|
|
|
|
|
/* FIXME: Create SRM port and listener thread */
|
|
|
|
|
2004-05-20 12:42:51 +00:00
|
|
|
return TRUE;
|
2003-02-15 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-12 17:05:50 +00:00
|
|
|
static BOOLEAN INIT_FUNCTION
|
2002-02-20 20:16:49 +00:00
|
|
|
SepInitExports(VOID)
|
|
|
|
{
|
|
|
|
SeExports = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
sizeof(SE_EXPORTS),
|
|
|
|
TAG_SXPT);
|
|
|
|
if (SeExports == NULL)
|
2004-05-20 12:42:51 +00:00
|
|
|
return FALSE;
|
2002-02-20 20:16:49 +00:00
|
|
|
|
|
|
|
SeExports->SeCreateTokenPrivilege = SeCreateTokenPrivilege;
|
|
|
|
SeExports->SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
|
|
|
|
SeExports->SeLockMemoryPrivilege = SeLockMemoryPrivilege;
|
|
|
|
SeExports->SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
|
|
|
|
SeExports->SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
|
|
|
|
SeExports->SeTcbPrivilege = SeTcbPrivilege;
|
|
|
|
SeExports->SeSecurityPrivilege = SeSecurityPrivilege;
|
|
|
|
SeExports->SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
|
|
|
|
SeExports->SeLoadDriverPrivilege = SeLoadDriverPrivilege;
|
|
|
|
SeExports->SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
|
|
|
|
SeExports->SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
|
|
|
|
SeExports->SeSystemProfilePrivilege = SeSystemProfilePrivilege;
|
|
|
|
SeExports->SeSystemtimePrivilege = SeSystemtimePrivilege;
|
|
|
|
SeExports->SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
|
|
|
|
SeExports->SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
|
|
|
|
SeExports->SeBackupPrivilege = SeBackupPrivilege;
|
|
|
|
SeExports->SeRestorePrivilege = SeRestorePrivilege;
|
|
|
|
SeExports->SeShutdownPrivilege = SeShutdownPrivilege;
|
|
|
|
SeExports->SeDebugPrivilege = SeDebugPrivilege;
|
|
|
|
SeExports->SeAuditPrivilege = SeAuditPrivilege;
|
|
|
|
SeExports->SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
|
|
|
|
SeExports->SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
|
|
|
|
SeExports->SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
|
|
|
|
|
|
|
|
SeExports->SeNullSid = SeNullSid;
|
|
|
|
SeExports->SeWorldSid = SeWorldSid;
|
|
|
|
SeExports->SeLocalSid = SeLocalSid;
|
|
|
|
SeExports->SeCreatorOwnerSid = SeCreatorOwnerSid;
|
|
|
|
SeExports->SeCreatorGroupSid = SeCreatorGroupSid;
|
|
|
|
SeExports->SeNtAuthoritySid = SeNtAuthoritySid;
|
|
|
|
SeExports->SeDialupSid = SeDialupSid;
|
|
|
|
SeExports->SeNetworkSid = SeNetworkSid;
|
|
|
|
SeExports->SeBatchSid = SeBatchSid;
|
|
|
|
SeExports->SeInteractiveSid = SeInteractiveSid;
|
|
|
|
SeExports->SeLocalSystemSid = SeLocalSystemSid;
|
|
|
|
SeExports->SeAliasAdminsSid = SeAliasAdminsSid;
|
|
|
|
SeExports->SeAliasUsersSid = SeAliasUsersSid;
|
|
|
|
SeExports->SeAliasGuestsSid = SeAliasGuestsSid;
|
|
|
|
SeExports->SeAliasPowerUsersSid = SeAliasPowerUsersSid;
|
|
|
|
SeExports->SeAliasAccountOpsSid = SeAliasAccountOpsSid;
|
|
|
|
SeExports->SeAliasSystemOpsSid = SeAliasSystemOpsSid;
|
|
|
|
SeExports->SeAliasPrintOpsSid = SeAliasPrintOpsSid;
|
|
|
|
SeExports->SeAliasBackupOpsSid = SeAliasBackupOpsSid;
|
|
|
|
|
2004-05-20 12:42:51 +00:00
|
|
|
return TRUE;
|
2002-02-20 20:16:49 +00:00
|
|
|
}
|
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2000-01-05 21:57:00 +00:00
|
|
|
VOID SepReferenceLogonSession(PLUID AuthenticationId)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
1998-10-05 04:01:30 +00:00
|
|
|
|
1999-06-18 22:11:21 +00:00
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2002-02-20 20:16:49 +00:00
|
|
|
NTSTATUS STDCALL
|
2002-09-08 10:23:54 +00:00
|
|
|
NtAllocateUuids(PULARGE_INTEGER Time,
|
|
|
|
PULONG Range,
|
|
|
|
PULONG Sequence)
|
1998-10-05 04:01:30 +00:00
|
|
|
{
|
2002-02-20 20:16:49 +00:00
|
|
|
UNIMPLEMENTED;
|
2003-12-14 17:44:02 +00:00
|
|
|
return(STATUS_NOT_IMPLEMENTED);
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
1999-06-18 22:11:21 +00:00
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-03-14 18:13:19 +00:00
|
|
|
VOID STDCALL
|
2004-05-20 12:42:51 +00:00
|
|
|
SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2004-07-19 12:45:56 +00:00
|
|
|
PETHREAD Thread;
|
2004-03-14 18:13:19 +00:00
|
|
|
BOOLEAN CopyOnOpen;
|
|
|
|
BOOLEAN EffectiveOnly;
|
|
|
|
|
2004-07-19 12:45:56 +00:00
|
|
|
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);
|
|
|
|
}
|
2004-05-20 12:42:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2004-09-14 11:04:48 +00:00
|
|
|
* @implemented
|
2004-05-20 12:42:51 +00:00
|
|
|
*/
|
|
|
|
VOID STDCALL
|
|
|
|
SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
|
|
|
|
{
|
2004-09-14 11:04:48 +00:00
|
|
|
ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
VOID STDCALL
|
|
|
|
SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
|
|
|
|
{
|
|
|
|
ExReleaseResourceLite(&SepSubjectContextLock);
|
2004-05-20 12:42:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
VOID STDCALL
|
|
|
|
SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
|
|
|
|
{
|
2004-07-19 12:45:56 +00:00
|
|
|
if (SubjectContext->PrimaryToken != NULL)
|
|
|
|
{
|
|
|
|
ObDereferenceObject(SubjectContext->PrimaryToken);
|
|
|
|
}
|
|
|
|
|
2004-05-20 12:42:51 +00:00
|
|
|
if (SubjectContext->ClientToken != NULL)
|
|
|
|
{
|
2004-07-19 12:45:56 +00:00
|
|
|
ObDereferenceObject(SubjectContext->ClientToken);
|
2004-05-20 12:42:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-02-20 20:16:49 +00:00
|
|
|
NTSTATUS STDCALL
|
2004-07-19 12:45:56 +00:00
|
|
|
SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
|
2000-01-26 10:07:30 +00:00
|
|
|
{
|
2004-07-19 12:45:56 +00:00
|
|
|
if (*SecurityDescriptor != NULL)
|
2002-02-20 20:16:49 +00:00
|
|
|
{
|
|
|
|
ExFreePool(*SecurityDescriptor);
|
2004-07-19 12:45:56 +00:00
|
|
|
*SecurityDescriptor = NULL;
|
2002-02-20 20:16:49 +00:00
|
|
|
}
|
2004-07-19 12:45:56 +00:00
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
2000-01-26 10:07:30 +00:00
|
|
|
|
2004-09-08 11:39:59 +00:00
|
|
|
|
2004-08-03 19:20:39 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2004-09-08 11:39:59 +00:00
|
|
|
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)
|
2004-08-03 19:20:39 +00:00
|
|
|
{
|
2004-09-08 11:39:59 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
2004-08-03 19:20:39 +00:00
|
|
|
}
|
2002-02-20 20:16:49 +00:00
|
|
|
|
2004-09-08 11:39:59 +00:00
|
|
|
|
2003-07-11 01:23:16 +00:00
|
|
|
/*
|
2004-08-03 13:58:56 +00:00
|
|
|
* FUNCTION: Creates a security descriptor for a new object.
|
|
|
|
* ARGUMENTS:
|
|
|
|
* ParentDescriptor =
|
|
|
|
* ExplicitDescriptor =
|
|
|
|
* NewDescriptor =
|
|
|
|
* IsDirectoryObject =
|
|
|
|
* SubjectContext =
|
|
|
|
* GeneralMapping =
|
|
|
|
* PoolType =
|
|
|
|
* RETURNS: Status
|
|
|
|
*
|
|
|
|
* @implemented
|
2003-07-11 01:23:16 +00:00
|
|
|
*/
|
2002-02-20 20:16:49 +00:00
|
|
|
NTSTATUS STDCALL
|
2004-07-18 13:02:28 +00:00
|
|
|
SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
|
|
|
|
PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
|
|
|
|
PSECURITY_DESCRIPTOR *NewDescriptor,
|
2002-02-20 20:16:49 +00:00
|
|
|
BOOLEAN IsDirectoryObject,
|
|
|
|
PSECURITY_SUBJECT_CONTEXT SubjectContext,
|
|
|
|
PGENERIC_MAPPING GenericMapping,
|
|
|
|
POOL_TYPE PoolType)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2004-07-18 13:02:28 +00:00
|
|
|
PSECURITY_DESCRIPTOR Descriptor;
|
2004-07-20 12:08:04 +00:00
|
|
|
PACCESS_TOKEN Token;
|
|
|
|
ULONG OwnerLength = 0;
|
|
|
|
ULONG GroupLength = 0;
|
|
|
|
ULONG DaclLength = 0;
|
|
|
|
ULONG SaclLength = 0;
|
|
|
|
ULONG Length = 0;
|
|
|
|
ULONG Control = 0;
|
2004-08-28 22:22:39 +00:00
|
|
|
ULONG_PTR Current;
|
2004-07-20 12:08:04 +00:00
|
|
|
PSID Owner = NULL;
|
|
|
|
PSID Group = NULL;
|
|
|
|
PACL Dacl = NULL;
|
|
|
|
PACL Sacl = NULL;
|
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
/* Lock subject context */
|
|
|
|
SeLockSubjectContext(SubjectContext);
|
2004-07-18 13:02:28 +00:00
|
|
|
|
2004-07-20 12:08:04 +00:00
|
|
|
if (SubjectContext->ClientToken != NULL)
|
2004-07-18 13:02:28 +00:00
|
|
|
{
|
2004-07-20 12:08:04 +00:00
|
|
|
Token = SubjectContext->ClientToken;
|
2004-07-18 13:02:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-07-20 12:08:04 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2004-08-03 13:58:56 +00:00
|
|
|
OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
|
2004-07-20 12:08:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2004-08-03 13:58:56 +00:00
|
|
|
GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
|
2004-07-20 12:08:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Inherit the DACL */
|
2004-07-21 23:38:15 +00:00
|
|
|
if (ExplicitDescriptor != NULL &&
|
|
|
|
(ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
|
|
|
|
!(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
|
2004-07-20 12:08:04 +00:00
|
|
|
{
|
|
|
|
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;
|
2004-07-21 23:38:15 +00:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
cm/regfile.c, ldr/init.c, ldr/loader.c: OBJ_CASE_INSENSITIVE patch I proposed
on the list. This makes the registry, and dll loading case insensitive when
we are on a case preserving filesystem.
ntoskrnl/ex/power.c: My own contributions to the poweroff message list.
ntoskrnl/mm/npool.c: Fixed bit-rot in whole page alloc. That's how i found
the bug below.
se/semgr.c, lib/rtl/sd.c:
semgr, when creating a SECURITY_DESCRIPTOR, anded the PRESENT and DEFAULT
flags rather than oring them for group, dacl, and sacl, leading to
RtlLengthSecurityDescriptor giving the wrong length to sdcache. When
sdcache would copy the security descriptor, it would be too short, and
the bound check from the whole-page allocator would go off. I fixed this
and made rtl/sd.c use the ROUND_UP macro and RtlLengthSid. This is cleaner.
It may not be completely correct yet but it no-longer truncates security
descriptors into the cache, which means that the Owner, Group and etc
SIDs should now actually work right when coming from the cache, no matter
what happens in the heap. They probably seemed to work before simply
because they trashed the ends of their blocks and never moved in the
cache.
svn path=/trunk/; revision=11040
2004-09-25 06:41:16 +00:00
|
|
|
Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
|
2004-07-21 23:38:15 +00:00
|
|
|
}
|
|
|
|
else if (Token != NULL && Token->DefaultDacl != NULL)
|
|
|
|
{
|
|
|
|
DPRINT("Use token default DACL!\n");
|
|
|
|
/* FIXME: Inherit */
|
|
|
|
Dacl = Token->DefaultDacl;
|
cm/regfile.c, ldr/init.c, ldr/loader.c: OBJ_CASE_INSENSITIVE patch I proposed
on the list. This makes the registry, and dll loading case insensitive when
we are on a case preserving filesystem.
ntoskrnl/ex/power.c: My own contributions to the poweroff message list.
ntoskrnl/mm/npool.c: Fixed bit-rot in whole page alloc. That's how i found
the bug below.
se/semgr.c, lib/rtl/sd.c:
semgr, when creating a SECURITY_DESCRIPTOR, anded the PRESENT and DEFAULT
flags rather than oring them for group, dacl, and sacl, leading to
RtlLengthSecurityDescriptor giving the wrong length to sdcache. When
sdcache would copy the security descriptor, it would be too short, and
the bound check from the whole-page allocator would go off. I fixed this
and made rtl/sd.c use the ROUND_UP macro and RtlLengthSid. This is cleaner.
It may not be completely correct yet but it no-longer truncates security
descriptors into the cache, which means that the Owner, Group and etc
SIDs should now actually work right when coming from the cache, no matter
what happens in the heap. They probably seemed to work before simply
because they trashed the ends of their blocks and never moved in the
cache.
svn path=/trunk/; revision=11040
2004-09-25 06:41:16 +00:00
|
|
|
Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
|
2004-07-20 12:08:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-07-21 23:38:15 +00:00
|
|
|
DPRINT("Use NULL DACL!\n");
|
|
|
|
Dacl = NULL;
|
cm/regfile.c, ldr/init.c, ldr/loader.c: OBJ_CASE_INSENSITIVE patch I proposed
on the list. This makes the registry, and dll loading case insensitive when
we are on a case preserving filesystem.
ntoskrnl/ex/power.c: My own contributions to the poweroff message list.
ntoskrnl/mm/npool.c: Fixed bit-rot in whole page alloc. That's how i found
the bug below.
se/semgr.c, lib/rtl/sd.c:
semgr, when creating a SECURITY_DESCRIPTOR, anded the PRESENT and DEFAULT
flags rather than oring them for group, dacl, and sacl, leading to
RtlLengthSecurityDescriptor giving the wrong length to sdcache. When
sdcache would copy the security descriptor, it would be too short, and
the bound check from the whole-page allocator would go off. I fixed this
and made rtl/sd.c use the ROUND_UP macro and RtlLengthSid. This is cleaner.
It may not be completely correct yet but it no-longer truncates security
descriptors into the cache, which means that the Owner, Group and etc
SIDs should now actually work right when coming from the cache, no matter
what happens in the heap. They probably seemed to work before simply
because they trashed the ends of their blocks and never moved in the
cache.
svn path=/trunk/; revision=11040
2004-09-25 06:41:16 +00:00
|
|
|
Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
|
2004-07-18 13:02:28 +00:00
|
|
|
}
|
|
|
|
|
2004-08-03 13:58:56 +00:00
|
|
|
DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
|
2004-07-21 23:38:15 +00:00
|
|
|
|
2004-07-20 12:08:04 +00:00
|
|
|
|
|
|
|
/* Inherit the SACL */
|
2004-08-03 13:58:56 +00:00
|
|
|
if (ExplicitDescriptor != NULL &&
|
|
|
|
(ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
|
|
|
|
!(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
|
2004-07-20 12:08:04 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2004-08-03 13:58:56 +00:00
|
|
|
else if (ParentDescriptor != NULL &&
|
|
|
|
(ParentDescriptor->Control & SE_SACL_PRESENT))
|
2004-07-20 12:08:04 +00:00
|
|
|
{
|
2004-08-03 13:58:56 +00:00
|
|
|
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);
|
|
|
|
}
|
cm/regfile.c, ldr/init.c, ldr/loader.c: OBJ_CASE_INSENSITIVE patch I proposed
on the list. This makes the registry, and dll loading case insensitive when
we are on a case preserving filesystem.
ntoskrnl/ex/power.c: My own contributions to the poweroff message list.
ntoskrnl/mm/npool.c: Fixed bit-rot in whole page alloc. That's how i found
the bug below.
se/semgr.c, lib/rtl/sd.c:
semgr, when creating a SECURITY_DESCRIPTOR, anded the PRESENT and DEFAULT
flags rather than oring them for group, dacl, and sacl, leading to
RtlLengthSecurityDescriptor giving the wrong length to sdcache. When
sdcache would copy the security descriptor, it would be too short, and
the bound check from the whole-page allocator would go off. I fixed this
and made rtl/sd.c use the ROUND_UP macro and RtlLengthSid. This is cleaner.
It may not be completely correct yet but it no-longer truncates security
descriptors into the cache, which means that the Owner, Group and etc
SIDs should now actually work right when coming from the cache, no matter
what happens in the heap. They probably seemed to work before simply
because they trashed the ends of their blocks and never moved in the
cache.
svn path=/trunk/; revision=11040
2004-09-25 06:41:16 +00:00
|
|
|
Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
|
2004-07-20 12:08:04 +00:00
|
|
|
}
|
2004-08-03 13:58:56 +00:00
|
|
|
|
|
|
|
SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
|
2004-07-20 12:08:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Allocate and initialize the new security descriptor */
|
cm/regfile.c, ldr/init.c, ldr/loader.c: OBJ_CASE_INSENSITIVE patch I proposed
on the list. This makes the registry, and dll loading case insensitive when
we are on a case preserving filesystem.
ntoskrnl/ex/power.c: My own contributions to the poweroff message list.
ntoskrnl/mm/npool.c: Fixed bit-rot in whole page alloc. That's how i found
the bug below.
se/semgr.c, lib/rtl/sd.c:
semgr, when creating a SECURITY_DESCRIPTOR, anded the PRESENT and DEFAULT
flags rather than oring them for group, dacl, and sacl, leading to
RtlLengthSecurityDescriptor giving the wrong length to sdcache. When
sdcache would copy the security descriptor, it would be too short, and
the bound check from the whole-page allocator would go off. I fixed this
and made rtl/sd.c use the ROUND_UP macro and RtlLengthSid. This is cleaner.
It may not be completely correct yet but it no-longer truncates security
descriptors into the cache, which means that the Owner, Group and etc
SIDs should now actually work right when coming from the cache, no matter
what happens in the heap. They probably seemed to work before simply
because they trashed the ends of their blocks and never moved in the
cache.
svn path=/trunk/; revision=11040
2004-09-25 06:41:16 +00:00
|
|
|
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);
|
2004-07-20 12:08:04 +00:00
|
|
|
|
2004-07-18 13:02:28 +00:00
|
|
|
Descriptor = ExAllocatePool(NonPagedPool,
|
|
|
|
Length);
|
|
|
|
if (Descriptor == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("ExAlloctePool() failed\n");
|
2004-07-20 12:08:04 +00:00
|
|
|
/* FIXME: Unlock subject context */
|
2004-07-21 23:38:15 +00:00
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
2004-07-18 13:02:28 +00:00
|
|
|
}
|
|
|
|
|
2004-07-20 12:08:04 +00:00
|
|
|
RtlCreateSecurityDescriptor(Descriptor,
|
|
|
|
SECURITY_DESCRIPTOR_REVISION);
|
|
|
|
|
|
|
|
Descriptor->Control = Control | SE_SELF_RELATIVE;
|
|
|
|
|
2004-08-28 22:22:39 +00:00
|
|
|
Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
|
2004-07-20 12:08:04 +00:00
|
|
|
|
|
|
|
if (SaclLength != 0)
|
2004-07-18 13:02:28 +00:00
|
|
|
{
|
2004-07-20 12:08:04 +00:00
|
|
|
RtlCopyMemory((PVOID)Current,
|
|
|
|
Sacl,
|
|
|
|
SaclLength);
|
2004-08-28 22:22:39 +00:00
|
|
|
Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
|
2004-07-20 12:08:04 +00:00
|
|
|
Current += SaclLength;
|
2004-07-18 13:02:28 +00:00
|
|
|
}
|
|
|
|
|
2004-07-20 12:08:04 +00:00
|
|
|
if (DaclLength != 0)
|
|
|
|
{
|
|
|
|
RtlCopyMemory((PVOID)Current,
|
|
|
|
Dacl,
|
|
|
|
DaclLength);
|
2004-08-28 22:22:39 +00:00
|
|
|
Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
|
2004-07-20 12:08:04 +00:00
|
|
|
Current += DaclLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OwnerLength != 0)
|
|
|
|
{
|
|
|
|
RtlCopyMemory((PVOID)Current,
|
|
|
|
Owner,
|
|
|
|
OwnerLength);
|
2004-08-28 22:22:39 +00:00
|
|
|
Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
|
2004-07-20 12:08:04 +00:00
|
|
|
Current += OwnerLength;
|
cm/regfile.c, ldr/init.c, ldr/loader.c: OBJ_CASE_INSENSITIVE patch I proposed
on the list. This makes the registry, and dll loading case insensitive when
we are on a case preserving filesystem.
ntoskrnl/ex/power.c: My own contributions to the poweroff message list.
ntoskrnl/mm/npool.c: Fixed bit-rot in whole page alloc. That's how i found
the bug below.
se/semgr.c, lib/rtl/sd.c:
semgr, when creating a SECURITY_DESCRIPTOR, anded the PRESENT and DEFAULT
flags rather than oring them for group, dacl, and sacl, leading to
RtlLengthSecurityDescriptor giving the wrong length to sdcache. When
sdcache would copy the security descriptor, it would be too short, and
the bound check from the whole-page allocator would go off. I fixed this
and made rtl/sd.c use the ROUND_UP macro and RtlLengthSid. This is cleaner.
It may not be completely correct yet but it no-longer truncates security
descriptors into the cache, which means that the Owner, Group and etc
SIDs should now actually work right when coming from the cache, no matter
what happens in the heap. They probably seemed to work before simply
because they trashed the ends of their blocks and never moved in the
cache.
svn path=/trunk/; revision=11040
2004-09-25 06:41:16 +00:00
|
|
|
DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
|
2004-07-20 12:08:04 +00:00
|
|
|
}
|
cm/regfile.c, ldr/init.c, ldr/loader.c: OBJ_CASE_INSENSITIVE patch I proposed
on the list. This makes the registry, and dll loading case insensitive when
we are on a case preserving filesystem.
ntoskrnl/ex/power.c: My own contributions to the poweroff message list.
ntoskrnl/mm/npool.c: Fixed bit-rot in whole page alloc. That's how i found
the bug below.
se/semgr.c, lib/rtl/sd.c:
semgr, when creating a SECURITY_DESCRIPTOR, anded the PRESENT and DEFAULT
flags rather than oring them for group, dacl, and sacl, leading to
RtlLengthSecurityDescriptor giving the wrong length to sdcache. When
sdcache would copy the security descriptor, it would be too short, and
the bound check from the whole-page allocator would go off. I fixed this
and made rtl/sd.c use the ROUND_UP macro and RtlLengthSid. This is cleaner.
It may not be completely correct yet but it no-longer truncates security
descriptors into the cache, which means that the Owner, Group and etc
SIDs should now actually work right when coming from the cache, no matter
what happens in the heap. They probably seemed to work before simply
because they trashed the ends of their blocks and never moved in the
cache.
svn path=/trunk/; revision=11040
2004-09-25 06:41:16 +00:00
|
|
|
else
|
|
|
|
DPRINT("Owner of %x is zero length\n", Descriptor);
|
2004-07-20 12:08:04 +00:00
|
|
|
|
|
|
|
if (GroupLength != 0)
|
|
|
|
{
|
|
|
|
memmove((PVOID)Current,
|
|
|
|
Group,
|
|
|
|
GroupLength);
|
2004-08-28 22:22:39 +00:00
|
|
|
Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
|
2004-07-20 12:08:04 +00:00
|
|
|
}
|
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
/* Unlock subject context */
|
|
|
|
SeUnlockSubjectContext(SubjectContext);
|
2004-07-20 12:08:04 +00:00
|
|
|
|
2004-07-18 13:02:28 +00:00
|
|
|
*NewDescriptor = Descriptor;
|
|
|
|
|
cm/regfile.c, ldr/init.c, ldr/loader.c: OBJ_CASE_INSENSITIVE patch I proposed
on the list. This makes the registry, and dll loading case insensitive when
we are on a case preserving filesystem.
ntoskrnl/ex/power.c: My own contributions to the poweroff message list.
ntoskrnl/mm/npool.c: Fixed bit-rot in whole page alloc. That's how i found
the bug below.
se/semgr.c, lib/rtl/sd.c:
semgr, when creating a SECURITY_DESCRIPTOR, anded the PRESENT and DEFAULT
flags rather than oring them for group, dacl, and sacl, leading to
RtlLengthSecurityDescriptor giving the wrong length to sdcache. When
sdcache would copy the security descriptor, it would be too short, and
the bound check from the whole-page allocator would go off. I fixed this
and made rtl/sd.c use the ROUND_UP macro and RtlLengthSid. This is cleaner.
It may not be completely correct yet but it no-longer truncates security
descriptors into the cache, which means that the Owner, Group and etc
SIDs should now actually work right when coming from the cache, no matter
what happens in the heap. They probably seemed to work before simply
because they trashed the ends of their blocks and never moved in the
cache.
svn path=/trunk/; revision=11040
2004-09-25 06:41:16 +00:00
|
|
|
DPRINT("Descrptor %x\n", Descriptor);
|
|
|
|
assert( RtlLengthSecurityDescriptor( Descriptor ) );
|
|
|
|
|
2004-07-18 13:02:28 +00:00
|
|
|
return STATUS_SUCCESS;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2004-07-13 16:59:35 +00:00
|
|
|
|
|
|
|
static BOOLEAN
|
|
|
|
SepSidInToken(PACCESS_TOKEN Token,
|
|
|
|
PSID Sid)
|
2000-01-05 21:57:00 +00:00
|
|
|
{
|
2004-07-13 16:59:35 +00:00
|
|
|
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;
|
2000-01-05 21:57:00 +00:00
|
|
|
}
|
|
|
|
|
2002-02-20 20:16:49 +00:00
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Determines whether the requested access rights can be granted
|
|
|
|
* to an object protected by a security descriptor and an object owner
|
|
|
|
* ARGUMENTS:
|
1999-12-26 15:50:53 +00:00
|
|
|
* SecurityDescriptor = Security descriptor protecting the object
|
1998-08-25 04:27:26 +00:00
|
|
|
* 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
|
1999-12-26 15:50:53 +00:00
|
|
|
* Privileges = ?
|
1998-08-25 04:27:26 +00:00
|
|
|
* 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
|
2004-07-13 16:59:35 +00:00
|
|
|
*
|
|
|
|
* @implemented
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
2004-07-13 16:59:35 +00:00
|
|
|
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)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2004-07-14 14:25:31 +00:00
|
|
|
LUID_AND_ATTRIBUTES Privilege;
|
|
|
|
ACCESS_MASK CurrentAccess;
|
2004-07-13 16:59:35 +00:00
|
|
|
PACCESS_TOKEN Token;
|
2004-07-14 14:25:31 +00:00
|
|
|
ULONG i;
|
|
|
|
PACL Dacl;
|
2004-07-13 16:59:35 +00:00
|
|
|
BOOLEAN Present;
|
|
|
|
BOOLEAN Defaulted;
|
|
|
|
PACE CurrentAce;
|
|
|
|
PSID Sid;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2004-07-14 14:25:31 +00:00
|
|
|
CurrentAccess = PreviouslyGrantedAccess;
|
2004-07-13 16:59:35 +00:00
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
if (SubjectContextLocked == FALSE)
|
|
|
|
{
|
|
|
|
SeLockSubjectContext(SubjectSecurityContext);
|
|
|
|
}
|
|
|
|
|
2004-07-14 14:25:31 +00:00
|
|
|
Token = SubjectSecurityContext->ClientToken ?
|
|
|
|
SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
|
2004-07-13 16:59:35 +00:00
|
|
|
|
|
|
|
/* Get the DACL */
|
|
|
|
Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
|
|
|
|
&Present,
|
|
|
|
&Dacl,
|
|
|
|
&Defaulted);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2004-09-14 11:04:48 +00:00
|
|
|
if (SubjectContextLocked == FALSE)
|
|
|
|
{
|
|
|
|
SeUnlockSubjectContext(SubjectSecurityContext);
|
|
|
|
}
|
|
|
|
|
2004-07-14 14:25:31 +00:00
|
|
|
*AccessStatus = Status;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-07-13 16:59:35 +00:00
|
|
|
|
|
|
|
/* RULE 1: Grant desired access if the object is unprotected */
|
2004-09-14 11:04:48 +00:00
|
|
|
if (Present == TRUE && Dacl == NULL)
|
2004-07-13 16:59:35 +00:00
|
|
|
{
|
2004-09-14 11:04:48 +00:00
|
|
|
if (SubjectContextLocked == FALSE)
|
|
|
|
{
|
|
|
|
SeUnlockSubjectContext(SubjectSecurityContext);
|
|
|
|
}
|
|
|
|
|
2004-07-13 16:59:35 +00:00
|
|
|
*GrantedAccess = DesiredAccess;
|
|
|
|
*AccessStatus = STATUS_SUCCESS;
|
2004-07-14 14:25:31 +00:00
|
|
|
return TRUE;
|
2004-07-13 16:59:35 +00:00
|
|
|
}
|
|
|
|
|
2004-07-14 14:25:31 +00:00
|
|
|
CurrentAccess = PreviouslyGrantedAccess;
|
|
|
|
|
|
|
|
/* RULE 2: Check token for 'take ownership' privilege */
|
|
|
|
Privilege.Luid = SeTakeOwnershipPrivilege;
|
|
|
|
Privilege.Attributes = SE_PRIVILEGE_ENABLED;
|
2004-07-13 16:59:35 +00:00
|
|
|
|
2004-07-14 14:25:31 +00:00
|
|
|
if (SepPrivilegeCheck(Token,
|
|
|
|
&Privilege,
|
|
|
|
1,
|
|
|
|
PRIVILEGE_SET_ALL_NECESSARY,
|
|
|
|
AccessMode))
|
|
|
|
{
|
|
|
|
CurrentAccess |= WRITE_OWNER;
|
|
|
|
if (DesiredAccess == CurrentAccess)
|
|
|
|
{
|
2004-09-14 11:04:48 +00:00
|
|
|
if (SubjectContextLocked == FALSE)
|
|
|
|
{
|
|
|
|
SeUnlockSubjectContext(SubjectSecurityContext);
|
|
|
|
}
|
|
|
|
|
2004-07-14 14:25:31 +00:00
|
|
|
*GrantedAccess = CurrentAccess;
|
|
|
|
*AccessStatus = STATUS_SUCCESS;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2004-07-13 16:59:35 +00:00
|
|
|
|
|
|
|
/* RULE 3: Check whether the token is the owner */
|
|
|
|
Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
|
|
|
|
&Sid,
|
|
|
|
&Defaulted);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
|
2004-09-14 11:04:48 +00:00
|
|
|
if (SubjectContextLocked == FALSE)
|
|
|
|
{
|
|
|
|
SeUnlockSubjectContext(SubjectSecurityContext);
|
|
|
|
}
|
|
|
|
|
2004-07-14 14:25:31 +00:00
|
|
|
*AccessStatus = Status;
|
|
|
|
return FALSE;
|
2004-07-13 16:59:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (SepSidInToken(Token, Sid))
|
|
|
|
{
|
|
|
|
CurrentAccess |= (READ_CONTROL | WRITE_DAC);
|
|
|
|
if (DesiredAccess == CurrentAccess)
|
|
|
|
{
|
2004-09-14 11:04:48 +00:00
|
|
|
if (SubjectContextLocked == FALSE)
|
|
|
|
{
|
|
|
|
SeUnlockSubjectContext(SubjectSecurityContext);
|
|
|
|
}
|
|
|
|
|
2004-07-13 16:59:35 +00:00
|
|
|
*GrantedAccess = CurrentAccess;
|
2004-07-14 14:25:31 +00:00
|
|
|
*AccessStatus = STATUS_SUCCESS;
|
|
|
|
return TRUE;
|
2004-07-13 16:59:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
/* Fail if DACL is absent */
|
|
|
|
if (Present == FALSE)
|
|
|
|
{
|
|
|
|
if (SubjectContextLocked == FALSE)
|
|
|
|
{
|
|
|
|
SeUnlockSubjectContext(SubjectSecurityContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
*GrantedAccess = 0;
|
|
|
|
*AccessStatus = STATUS_ACCESS_DENIED;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2004-07-13 16:59:35 +00:00
|
|
|
/* 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))
|
|
|
|
{
|
2004-09-14 11:04:48 +00:00
|
|
|
if (SubjectContextLocked == FALSE)
|
|
|
|
{
|
|
|
|
SeUnlockSubjectContext(SubjectSecurityContext);
|
|
|
|
}
|
|
|
|
|
2004-07-13 16:59:35 +00:00
|
|
|
*GrantedAccess = 0;
|
2004-07-14 14:25:31 +00:00
|
|
|
*AccessStatus = STATUS_ACCESS_DENIED;
|
|
|
|
return TRUE;
|
2004-07-13 16:59:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
|
|
|
|
{
|
|
|
|
if (SepSidInToken(Token, Sid))
|
|
|
|
{
|
|
|
|
CurrentAccess |= CurrentAce->AccessMask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
if (SubjectContextLocked == FALSE)
|
|
|
|
{
|
|
|
|
SeUnlockSubjectContext(SubjectSecurityContext);
|
|
|
|
}
|
|
|
|
|
2004-07-13 16:59:35 +00:00
|
|
|
DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
|
|
|
|
CurrentAccess, DesiredAccess);
|
|
|
|
|
|
|
|
*GrantedAccess = CurrentAccess & DesiredAccess;
|
|
|
|
|
|
|
|
*AccessStatus =
|
|
|
|
(*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
|
|
|
|
|
2004-07-14 14:25:31 +00:00
|
|
|
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;
|
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
/* Lock subject context */
|
|
|
|
SeLockSubjectContext(&SubjectSecurityContext);
|
2004-07-14 14:25:31 +00:00
|
|
|
|
|
|
|
if (!SeAccessCheck(SecurityDescriptor,
|
|
|
|
&SubjectSecurityContext,
|
|
|
|
TRUE,
|
|
|
|
DesiredAccess,
|
|
|
|
0,
|
|
|
|
&PrivilegeSet,
|
|
|
|
GenericMapping,
|
|
|
|
PreviousMode,
|
|
|
|
GrantedAccess,
|
|
|
|
AccessStatus))
|
|
|
|
{
|
|
|
|
Status = *AccessStatus;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-08-03 13:58:56 +00:00
|
|
|
Status = STATUS_ACCESS_DENIED;
|
2004-07-14 14:25:31 +00:00
|
|
|
}
|
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
/* Unlock subject context */
|
|
|
|
SeUnlockSubjectContext(&SubjectSecurityContext);
|
2004-07-14 14:25:31 +00:00
|
|
|
|
|
|
|
ObDereferenceObject(Token);
|
|
|
|
|
2004-07-13 16:59:35 +00:00
|
|
|
DPRINT("NtAccessCheck() done\n");
|
|
|
|
|
2004-07-14 14:25:31 +00:00
|
|
|
return Status;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
1999-12-26 17:22:19 +00:00
|
|
|
/* EOF */
|