2005-01-02 23:12:40 +00:00
|
|
|
/* $Id$
|
1999-12-26 17:22:19 +00:00
|
|
|
*
|
2005-01-26 13:58:37 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: ntoskrnl/se/semgr.c
|
|
|
|
* PURPOSE: Security manager
|
2005-05-09 01:38:29 +00:00
|
|
|
*
|
2005-01-26 13:58:37 +00:00
|
|
|
* PROGRAMMERS: No programmer listed.
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* 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
|
|
|
/* 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);
|
2005-01-22 12:20:12 +00:00
|
|
|
Status = ZwCreateDirectoryObject(&DirectoryHandle,
|
2003-02-15 21:07:49 +00:00
|
|
|
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);
|
2005-01-22 12:20:12 +00:00
|
|
|
Status = ZwCreateEvent(&EventHandle,
|
2003-02-15 21:07:49 +00:00
|
|
|
EVENT_ALL_ACCESS,
|
|
|
|
&ObjectAttributes,
|
2004-10-24 15:26:14 +00:00
|
|
|
SynchronizationEvent,
|
2003-02-15 21:07:49 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2005-01-22 12:20:12 +00:00
|
|
|
ZwClose(EventHandle);
|
|
|
|
ZwClose(DirectoryHandle);
|
2003-02-15 21:07:49 +00:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
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;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-22 17:58:19 +00:00
|
|
|
PAGED_CODE();
|
2004-03-14 18:13:19 +00:00
|
|
|
|
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;
|
2005-05-09 01:38:29 +00:00
|
|
|
SubjectContext->ClientToken =
|
2004-07-19 12:45:56 +00:00
|
|
|
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)
|
|
|
|
{
|
2005-02-22 17:58:19 +00:00
|
|
|
PAGED_CODE();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-11-21 18:35:05 +00:00
|
|
|
KeEnterCriticalRegion();
|
2004-09-14 11:04:48 +00:00
|
|
|
ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
VOID STDCALL
|
|
|
|
SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
|
|
|
|
{
|
2005-02-22 17:58:19 +00:00
|
|
|
PAGED_CODE();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-09-14 11:04:48 +00:00
|
|
|
ExReleaseResourceLite(&SepSubjectContextLock);
|
2004-11-21 18:35:05 +00:00
|
|
|
KeLeaveCriticalRegion();
|
2004-05-20 12:42:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
VOID STDCALL
|
|
|
|
SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
|
|
|
|
{
|
2005-02-22 17:58:19 +00:00
|
|
|
PAGED_CODE();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
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
|
|
|
{
|
2005-02-22 17:58:19 +00:00
|
|
|
PAGED_CODE();
|
2005-05-09 01:38:29 +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:
|
2005-05-09 01:38:29 +00:00
|
|
|
* ParentDescriptor =
|
|
|
|
* ExplicitDescriptor =
|
|
|
|
* NewDescriptor =
|
|
|
|
* IsDirectoryObject =
|
|
|
|
* SubjectContext =
|
|
|
|
* GeneralMapping =
|
|
|
|
* PoolType =
|
2004-08-03 13:58:56 +00:00
|
|
|
* 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;
|
2005-01-02 23:12:40 +00:00
|
|
|
PTOKEN Token;
|
2004-07-20 12:08:04 +00:00
|
|
|
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;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-22 17:58:19 +00:00
|
|
|
PAGED_CODE();
|
2004-07-20 12:08:04 +00:00
|
|
|
|
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;
|
Object Manager Patch. This patch continues the work done in the previous patch and makes the following changes in order to support OB 2.0 (it basically temporarily fixes a highly incorrect implementation so that caller code will be ready to work with the OB 2.0 without change):
1) The documented Object Create Information Structure and semantics implemented. All Object Attributes and passed data from user-mode is now probed and saved into this object create structure when ObCreateObject is called.
2) ObCreateObject does NOT PERFORM ANY OTHER OPERATION EXCEPT CREATING THE OBJECT ANYMORE. ObCreateObject will NOT insert the Object into the tree and other operations. These are now done correctly by ObInsertObject. Therefore, the biggest hurdle was changing pieces of code which assumed ObCreateObject would be enough.
3) ObInsertObject uses the captured create info for all operations isntead of the Object Attributes.
4) ObFindObject now uses the captured info as well.
5) The OBject name and directory are now stored in the documented Object Name Information, always allocated and freed from non paged pool.
HACKS:
5) Because the registry code is horribly broken and doesn't use ObFindObjectByName, the old ObFindObject had to be temporarily duplicated into CmpFindObject.
7) Win32k used ObInsertObject in CsrInsertObject as a way to create a handle inside csrss. However, OBInsertObject now does more then this. As a temporary hack, ObpCreateHandle is exported from the kernel and called from win32k. A fix needs to be done for this, but I don't know the design of win32k+csrss well enough to find a solution.
8) SEH has been commented out in some places of the new probing code because it breaks smss and explorer. These need to be investigated (seh did not exist in the previous code, so this is not really a hack)
9) Named objects with a parent directory are NOT allowed. However because of bugs in kernel32, the new check has been temporarily disabled. (this check did not exist in the previous code, so this is not really a hack)
The next patch will add a proper ObFindObject which will support a more complete Parse Procedure with context and security information. This is needed for proper registry access (requested by Eric Kohl) and for proper functionality of the Desktop/File creation, which should use the Parse routine, and not the Create Handle Routine. This will also make it possible to remove some previous hacks and pave the way for a fixed Iop/IoCreateFile
svn path=/trunk/; revision=15395
2005-05-18 19:26:47 +00:00
|
|
|
|
2004-07-20 12:08:04 +00:00
|
|
|
if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
|
|
|
|
{
|
|
|
|
Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
|
Object Manager Patch. This patch continues the work done in the previous patch and makes the following changes in order to support OB 2.0 (it basically temporarily fixes a highly incorrect implementation so that caller code will be ready to work with the OB 2.0 without change):
1) The documented Object Create Information Structure and semantics implemented. All Object Attributes and passed data from user-mode is now probed and saved into this object create structure when ObCreateObject is called.
2) ObCreateObject does NOT PERFORM ANY OTHER OPERATION EXCEPT CREATING THE OBJECT ANYMORE. ObCreateObject will NOT insert the Object into the tree and other operations. These are now done correctly by ObInsertObject. Therefore, the biggest hurdle was changing pieces of code which assumed ObCreateObject would be enough.
3) ObInsertObject uses the captured create info for all operations isntead of the Object Attributes.
4) ObFindObject now uses the captured info as well.
5) The OBject name and directory are now stored in the documented Object Name Information, always allocated and freed from non paged pool.
HACKS:
5) Because the registry code is horribly broken and doesn't use ObFindObjectByName, the old ObFindObject had to be temporarily duplicated into CmpFindObject.
7) Win32k used ObInsertObject in CsrInsertObject as a way to create a handle inside csrss. However, OBInsertObject now does more then this. As a temporary hack, ObpCreateHandle is exported from the kernel and called from win32k. A fix needs to be done for this, but I don't know the design of win32k+csrss well enough to find a solution.
8) SEH has been commented out in some places of the new probing code because it breaks smss and explorer. These need to be investigated (seh did not exist in the previous code, so this is not really a hack)
9) Named objects with a parent directory are NOT allowed. However because of bugs in kernel32, the new check has been temporarily disabled. (this check did not exist in the previous code, so this is not really a hack)
The next patch will add a proper ObFindObject which will support a more complete Parse Procedure with context and security information. This is needed for proper registry access (requested by Eric Kohl) and for proper functionality of the Desktop/File creation, which should use the Parse routine, and not the Create Handle Routine. This will also make it possible to remove some previous hacks and pave the way for a fixed Iop/IoCreateFile
svn path=/trunk/; revision=15395
2005-05-18 19:26:47 +00:00
|
|
|
|
2004-07-20 12:08:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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 */
|
2005-05-09 01:38:29 +00:00
|
|
|
Length = sizeof(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
|
|
|
OwnerLength + GroupLength + DaclLength + SaclLength;
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
|
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
|
|
|
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);
|
2004-10-01 01:28:56 +00:00
|
|
|
RtlZeroMemory( Descriptor, Length );
|
|
|
|
|
2004-07-18 13:02:28 +00:00
|
|
|
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);
|
2004-10-22 20:57:39 +00:00
|
|
|
ASSERT(RtlLengthSecurityDescriptor(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
|
|
|
|
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
|
2005-01-02 23:12:40 +00:00
|
|
|
SepSidInToken(PACCESS_TOKEN _Token,
|
2004-07-13 16:59:35 +00:00
|
|
|
PSID Sid)
|
2000-01-05 21:57:00 +00:00
|
|
|
{
|
2004-07-13 16:59:35 +00:00
|
|
|
ULONG i;
|
2005-01-02 23:12:40 +00:00
|
|
|
PTOKEN Token = (PTOKEN)_Token;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-22 17:58:19 +00:00
|
|
|
PAGED_CODE();
|
2004-07-13 16:59:35 +00:00
|
|
|
|
|
|
|
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;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-22 17:58:19 +00:00
|
|
|
PAGED_CODE();
|
2004-07-13 16:59:35 +00:00
|
|
|
|
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;
|
2005-01-02 23:12:40 +00:00
|
|
|
PTOKEN Token;
|
2004-07-14 14:25:31 +00:00
|
|
|
NTSTATUS Status;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-02-22 17:58:19 +00:00
|
|
|
PAGED_CODE();
|
2004-07-14 14:25:31 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
2004-09-25 08:49:06 +00:00
|
|
|
if (SeAccessCheck(SecurityDescriptor,
|
|
|
|
&SubjectSecurityContext,
|
|
|
|
TRUE,
|
|
|
|
DesiredAccess,
|
|
|
|
0,
|
|
|
|
&PrivilegeSet,
|
|
|
|
GenericMapping,
|
|
|
|
PreviousMode,
|
|
|
|
GrantedAccess,
|
|
|
|
AccessStatus))
|
2004-07-14 14:25:31 +00:00
|
|
|
{
|
|
|
|
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 */
|