801 lines
16 KiB
C
801 lines
16 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
obsdata.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Object Manager Security Descriptor Caching
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Robert Reichel (robertre) 12-Oct-1993
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "obp.h"
|
|||
|
|
|||
|
|
|||
|
#if DBG
|
|||
|
#define OB_DIAGNOSTICS_ENABLED 1
|
|||
|
#endif // DBG
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// These definitions are useful diagnostics aids
|
|||
|
//
|
|||
|
|
|||
|
#if OB_DIAGNOSTICS_ENABLED
|
|||
|
|
|||
|
ULONG ObDebugFlags = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Test for enabled diagnostic
|
|||
|
//
|
|||
|
|
|||
|
#define IF_OB_GLOBAL( FlagName ) \
|
|||
|
if (ObDebugFlags & (OB_DEBUG_##FlagName))
|
|||
|
|
|||
|
//
|
|||
|
// Diagnostics print statement
|
|||
|
//
|
|||
|
|
|||
|
#define ObPrint( FlagName, _Text_ ) \
|
|||
|
IF_OB_GLOBAL( FlagName ) \
|
|||
|
DbgPrint _Text_
|
|||
|
|
|||
|
|
|||
|
#else
|
|||
|
|
|||
|
//
|
|||
|
// diagnostics not enabled - No diagnostics included in build
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Test for diagnostics enabled
|
|||
|
//
|
|||
|
|
|||
|
#define IF_OB_GLOBAL( FlagName ) if (FALSE)
|
|||
|
|
|||
|
//
|
|||
|
// Diagnostics print statement (expands to no-op)
|
|||
|
//
|
|||
|
|
|||
|
#define ObPrint( FlagName, _Text_ ) ;
|
|||
|
|
|||
|
#endif // OB_DIAGNOSTICS_ENABLED
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#if OB_DIAGNOSTICS_ENABLED
|
|||
|
|
|||
|
ULONG TotalCacheEntries = 0;
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// The following flags enable or disable various diagnostic
|
|||
|
// capabilities within OB code. These flags are set in
|
|||
|
// ObGlobalFlag (only available within a DBG system).
|
|||
|
//
|
|||
|
//
|
|||
|
|
|||
|
#define OB_DEBUG_ALLOC_TRACKING ((ULONG) 0x00000001L)
|
|||
|
#define OB_DEBUG_CACHE_FREES ((ULONG) 0x00000002L)
|
|||
|
#define OB_DEBUG_BREAK_ON_INIT ((ULONG) 0x00000004L)
|
|||
|
#define OB_DEBUG_SHOW_COLLISIONS ((ULONG) 0x00000008L)
|
|||
|
#define OB_DEBUG_SHOW_STATISTICS ((ULONG) 0x00000010L)
|
|||
|
#define OB_DEBUG_SHOW_REFERENCES ((ULONG) 0x00000020L)
|
|||
|
#define OB_DEBUG_SHOW_DEASSIGN ((ULONG) 0x00000040L)
|
|||
|
#define OB_DEBUG_STOP_INVALID_DESCRIPTOR ((ULONG) 0x00000080L)
|
|||
|
#define OB_DEBUG_SHOW_HEADER_FREE ((ULONG) 0x00000100L)
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Array of pointers to security descriptor entries
|
|||
|
//
|
|||
|
|
|||
|
PLIST_ENTRY *SecurityDescriptorCache = NULL;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Resource used to protect the security descriptor cache
|
|||
|
//
|
|||
|
|
|||
|
ERESOURCE SecurityDescriptorCacheLock;
|
|||
|
|
|||
|
|
|||
|
#if defined (ALLOC_PRAGMA)
|
|||
|
#pragma alloc_text(PAGE,ObpDereferenceSecurityDescriptor)
|
|||
|
#pragma alloc_text(PAGE,ObpDestroySecurityDescriptorHeader)
|
|||
|
#pragma alloc_text(PAGE,ObpHashBuffer)
|
|||
|
#pragma alloc_text(PAGE,ObpHashSecurityDescriptor)
|
|||
|
#pragma alloc_text(PAGE,ObpInitSecurityDescriptorCache)
|
|||
|
#pragma alloc_text(PAGE,ObpLogSecurityDescriptor)
|
|||
|
#pragma alloc_text(PAGE,ObpReferenceSecurityDescriptor)
|
|||
|
#pragma alloc_text(PAGE,OpbCreateCacheEntry)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ObpInitSecurityDescriptorCache(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allocates and initializes the Security Descriptor Cache
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS on success, NTSTATUS on failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Size;
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
IF_OB_GLOBAL( BREAK_ON_INIT ) {
|
|||
|
DbgBreakPoint();
|
|||
|
}
|
|||
|
|
|||
|
Size = SECURITY_DESCRIPTOR_CACHE_ENTRIES * sizeof(PLIST_ENTRY);
|
|||
|
SecurityDescriptorCache = ExAllocatePoolWithTag( PagedPool, Size, 'cCdS' );
|
|||
|
|
|||
|
if (SecurityDescriptorCache == NULL ) {
|
|||
|
return( STATUS_INSUFFICIENT_RESOURCES );
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory( SecurityDescriptorCache, Size );
|
|||
|
|
|||
|
Status = ExInitializeResource ( &SecurityDescriptorCacheLock );
|
|||
|
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
ExFreePool( SecurityDescriptorCache );
|
|||
|
return( Status );
|
|||
|
}
|
|||
|
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
ObpHashSecurityDescriptor(
|
|||
|
PSECURITY_DESCRIPTOR SecurityDescriptor
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Hashes a security descriptor to a 32 bit value
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SecurityDescriptor - Provides the security descriptor to be hashed
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ULONG - a 32 bit hash value.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PSID Owner = NULL;
|
|||
|
PSID Group = NULL;
|
|||
|
|
|||
|
PACL Dacl;
|
|||
|
PACL Sacl;
|
|||
|
|
|||
|
ULONG Hash = 0;
|
|||
|
BOOLEAN Junk;
|
|||
|
NTSTATUS Status;
|
|||
|
BOOLEAN DaclPresent = FALSE;
|
|||
|
BOOLEAN SaclPresent = FALSE;
|
|||
|
PISECURITY_DESCRIPTOR sd;
|
|||
|
|
|||
|
sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
|
|||
|
|
|||
|
Status = RtlGetOwnerSecurityDescriptor ( sd, &Owner, &Junk );
|
|||
|
Status = RtlGetGroupSecurityDescriptor( sd, &Group, &Junk );
|
|||
|
Status = RtlGetDaclSecurityDescriptor ( sd, &DaclPresent, &Dacl, &Junk );
|
|||
|
Status = RtlGetSaclSecurityDescriptor ( sd, &SaclPresent, &Sacl, &Junk );
|
|||
|
|
|||
|
if ( Owner != NULL ) {
|
|||
|
Hash = ObpHashBuffer( Owner, RtlLengthSid( Owner ));
|
|||
|
}
|
|||
|
|
|||
|
if ( Group != NULL ) {
|
|||
|
Hash += ObpHashBuffer( Group, RtlLengthSid( Group));
|
|||
|
}
|
|||
|
|
|||
|
if ( DaclPresent && (Dacl != NULL)) {
|
|||
|
Hash += ObpHashBuffer( Dacl, Dacl->AclSize);
|
|||
|
}
|
|||
|
|
|||
|
if ( SaclPresent && (Sacl != NULL)) {
|
|||
|
Hash += ObpHashBuffer( Sacl, Sacl->AclSize);
|
|||
|
}
|
|||
|
|
|||
|
return( Hash );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
ObpHashBuffer(
|
|||
|
PVOID Data,
|
|||
|
ULONG Length
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Hashes a buffer into a 32 bit value
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Data - Buffer containing the data to be hashed.
|
|||
|
|
|||
|
Length - The length in bytes of the buffer
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ULONG - a 32 bit hash value.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCHAR Buffer;
|
|||
|
ULONG Result = 0;
|
|||
|
LONG i;
|
|||
|
|
|||
|
Buffer = (PCHAR)Data;
|
|||
|
|
|||
|
for (i=0 ; i<=(LONG)((Length-3)-sizeof(ULONG)) ; i++) {
|
|||
|
|
|||
|
ULONG Tmp;
|
|||
|
|
|||
|
Tmp = *((ULONG UNALIGNED *)(Buffer + i));
|
|||
|
Result += Tmp;
|
|||
|
}
|
|||
|
|
|||
|
return( Result );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ObpLogSecurityDescriptor(
|
|||
|
IN PSECURITY_DESCRIPTOR InputSecurityDescriptor,
|
|||
|
OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Takes a passed security descriptor and registers it into the
|
|||
|
security descriptor database.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InputSecurityDescriptor - The new security descriptor to be logged into the database.
|
|||
|
|
|||
|
OutputSecurityDescriptor - Output security descriptor to be used by the caller.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT_STATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG FullHash;
|
|||
|
UCHAR SmallHash;
|
|||
|
PSECURITY_DESCRIPTOR_HEADER NewDescriptor;
|
|||
|
PLIST_ENTRY Front;
|
|||
|
PLIST_ENTRY Back;
|
|||
|
PSECURITY_DESCRIPTOR_HEADER Header;
|
|||
|
BOOLEAN Match;
|
|||
|
|
|||
|
|
|||
|
FullHash = ObpHashSecurityDescriptor( InputSecurityDescriptor );
|
|||
|
SmallHash = (UCHAR)FullHash;
|
|||
|
|
|||
|
//
|
|||
|
// See if the entry matching SmallHash is in use.
|
|||
|
// Lock the table first, unlock if if we don't need it.
|
|||
|
//
|
|||
|
|
|||
|
ObpAcquireDescriptorCacheWriteLock();
|
|||
|
|
|||
|
Front = SecurityDescriptorCache[SmallHash];
|
|||
|
Back = NULL;
|
|||
|
Match = FALSE;
|
|||
|
|
|||
|
while ( Front != NULL ) {
|
|||
|
|
|||
|
Header = LINK_TO_SD_HEADER( Front );
|
|||
|
|
|||
|
if ( Header->FullHash > FullHash ) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if ( Header->FullHash == FullHash ) {
|
|||
|
|
|||
|
Match = ObpCompareSecurityDescriptors( InputSecurityDescriptor,
|
|||
|
&Header->SecurityDescriptor
|
|||
|
);
|
|||
|
|
|||
|
if ( Match ) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
ObPrint( SHOW_COLLISIONS,("Got a collision on %d, no match\n",SmallHash));
|
|||
|
}
|
|||
|
|
|||
|
Back = Front;
|
|||
|
Front = Front->Flink;
|
|||
|
}
|
|||
|
|
|||
|
if ( Match ) {
|
|||
|
|
|||
|
Header->RefCount++;
|
|||
|
|
|||
|
ObPrint( SHOW_REFERENCES, ("Reference Index = %d, New RefCount = %d\n",Header->Index,Header->RefCount));
|
|||
|
|
|||
|
*OutputSecurityDescriptor = &Header->SecurityDescriptor;
|
|||
|
ExFreePool( InputSecurityDescriptor );
|
|||
|
ObpReleaseDescriptorCacheLock();
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Can't use an existing one, create a new entry
|
|||
|
// and insert it into the list.
|
|||
|
//
|
|||
|
|
|||
|
NewDescriptor = OpbCreateCacheEntry( InputSecurityDescriptor,
|
|||
|
FullHash,
|
|||
|
SmallHash
|
|||
|
);
|
|||
|
|
|||
|
if ( NewDescriptor == NULL ) {
|
|||
|
ObpReleaseDescriptorCacheLock();
|
|||
|
return( STATUS_INSUFFICIENT_RESOURCES );
|
|||
|
}
|
|||
|
|
|||
|
#if OB_DIAGNOSTICS_ENABLED
|
|||
|
|
|||
|
TotalCacheEntries++;
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
ObPrint( SHOW_STATISTICS, ("TotalCacheEntries = %d \n",TotalCacheEntries));
|
|||
|
ObPrint( SHOW_COLLISIONS, ("Adding new entry for index #%d \n",SmallHash));
|
|||
|
|
|||
|
//
|
|||
|
// We don't need the old security descriptor any more.
|
|||
|
//
|
|||
|
|
|||
|
ExFreePool( InputSecurityDescriptor );
|
|||
|
|
|||
|
if ( Back == NULL ) {
|
|||
|
|
|||
|
//
|
|||
|
// We're inserting at the beginning of the list for this
|
|||
|
// minor index
|
|||
|
//
|
|||
|
|
|||
|
NewDescriptor->Link.Flink = SecurityDescriptorCache[SmallHash];
|
|||
|
SecurityDescriptorCache[SmallHash] = &NewDescriptor->Link;
|
|||
|
|
|||
|
if ( NewDescriptor->Link.Flink != NULL ) {
|
|||
|
NewDescriptor->Link.Flink->Blink = &NewDescriptor->Link;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Hook new descriptor entry into list.
|
|||
|
//
|
|||
|
|
|||
|
NewDescriptor->Link.Flink = Front;
|
|||
|
|
|||
|
NewDescriptor->Link.Blink = Back;
|
|||
|
|
|||
|
Back->Flink = &NewDescriptor->Link;
|
|||
|
|
|||
|
if (Front != NULL) {
|
|||
|
Front->Blink = &NewDescriptor->Link;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*OutputSecurityDescriptor = &NewDescriptor->SecurityDescriptor;
|
|||
|
ObpReleaseDescriptorCacheLock();
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PSECURITY_DESCRIPTOR_HEADER
|
|||
|
OpbCreateCacheEntry(
|
|||
|
PSECURITY_DESCRIPTOR InputSecurityDescriptor,
|
|||
|
ULONG FullHash,
|
|||
|
UCHAR SmallHash
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allocates and initializes a new cache entry.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InputSecurityDescriptor - The security descriptor to be cached.
|
|||
|
|
|||
|
FullHash - Full 32 bit hash of the security descriptor.
|
|||
|
|
|||
|
SmallHash - Index into the cache table.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A pointer to the newly allocated cache entry, or NULL
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
ULONG SecurityDescriptorLength;
|
|||
|
ULONG CacheEntrySize;
|
|||
|
PSECURITY_DESCRIPTOR_HEADER NewDescriptor;
|
|||
|
|
|||
|
SecurityDescriptorLength = RtlLengthSecurityDescriptor ( InputSecurityDescriptor );
|
|||
|
CacheEntrySize = SecurityDescriptorLength + (sizeof(SECURITY_DESCRIPTOR_HEADER) - sizeof( QUAD ));
|
|||
|
|
|||
|
NewDescriptor = ExAllocatePoolWithTag( PagedPool, CacheEntrySize, 'dSeS');
|
|||
|
|
|||
|
if ( NewDescriptor == NULL ) {
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
|
|||
|
NewDescriptor->Index = SmallHash;
|
|||
|
NewDescriptor->RefCount = 1;
|
|||
|
NewDescriptor->FullHash = FullHash;
|
|||
|
NewDescriptor->Link.Flink = NULL;
|
|||
|
NewDescriptor->Link.Blink = NULL;
|
|||
|
|
|||
|
RtlCopyMemory( &NewDescriptor->SecurityDescriptor, InputSecurityDescriptor, SecurityDescriptorLength );
|
|||
|
|
|||
|
return( NewDescriptor );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
PSECURITY_DESCRIPTOR
|
|||
|
ObpReferenceSecurityDescriptor(
|
|||
|
PVOID Object
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
References the security descriptor of the passed object.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Object - Object being access validated.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The security descriptor of the object.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PSECURITY_DESCRIPTOR_HEADER SecurityDescriptorHeader;
|
|||
|
POBJECT_HEADER ObjectHeader;
|
|||
|
POBJECT_TYPE ObjectType;
|
|||
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
|||
|
|
|||
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
|
|||
|
ObjectType = ObjectHeader->Type;
|
|||
|
ASSERT( ObpCentralizedSecurity(ObjectType) );
|
|||
|
|
|||
|
ObpAcquireDescriptorCacheWriteLock();
|
|||
|
|
|||
|
SecurityDescriptor = OBJECT_TO_OBJECT_HEADER( Object )->SecurityDescriptor;
|
|||
|
|
|||
|
IF_OB_GLOBAL( STOP_INVALID_DESCRIPTOR ) {
|
|||
|
if( !RtlValidSecurityDescriptor ( SecurityDescriptor )) {
|
|||
|
DbgBreakPoint();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( SecurityDescriptor != NULL ) {
|
|||
|
|
|||
|
SecurityDescriptorHeader = SD_TO_SD_HEADER( SecurityDescriptor );
|
|||
|
ObPrint( SHOW_REFERENCES, ("Referencing index #%d, Refcount = %d \n",SecurityDescriptorHeader->Index,SecurityDescriptorHeader->RefCount));
|
|||
|
SecurityDescriptorHeader->RefCount++;
|
|||
|
}
|
|||
|
|
|||
|
ObpReleaseDescriptorCacheLock();
|
|||
|
|
|||
|
return( SecurityDescriptor );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ObDeassignSecurity (
|
|||
|
IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor
|
|||
|
)
|
|||
|
{
|
|||
|
PSECURITY_DESCRIPTOR_HEADER Header;
|
|||
|
|
|||
|
Header = SD_TO_SD_HEADER( *SecurityDescriptor );
|
|||
|
ObPrint( SHOW_DEASSIGN,("Deassigning security descriptor %x, Index = %d\n",*SecurityDescriptor, Header->Index));
|
|||
|
|
|||
|
ObpDereferenceSecurityDescriptor( *SecurityDescriptor );
|
|||
|
|
|||
|
//
|
|||
|
// NULL out the SecurityDescriptor in the object's
|
|||
|
// header so we don't try to free it again.
|
|||
|
//
|
|||
|
|
|||
|
*SecurityDescriptor = NULL;
|
|||
|
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ObpDereferenceSecurityDescriptor(
|
|||
|
PSECURITY_DESCRIPTOR SecurityDescriptor
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Decrements the refcount of a cached security descriptor
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SecurityDescriptor - Points to a cached security descriptor
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PSECURITY_DESCRIPTOR_HEADER SecurityDescriptorHeader;
|
|||
|
|
|||
|
|
|||
|
ObpAcquireDescriptorCacheWriteLock();
|
|||
|
|
|||
|
SecurityDescriptorHeader = SD_TO_SD_HEADER( SecurityDescriptor );
|
|||
|
|
|||
|
ObPrint( SHOW_REFERENCES, ("Dereferencing SecurityDescriptor %x, index #%d, refcount = %d \n", SecurityDescriptor, SecurityDescriptorHeader->Index,SecurityDescriptorHeader->RefCount));
|
|||
|
|
|||
|
// DbgPrint("Dereferencing SecurityDescriptor %x, index #%d, refcount = %d \n", SecurityDescriptor, SecurityDescriptorHeader->Index,SecurityDescriptorHeader->RefCount);
|
|||
|
|
|||
|
ASSERT(SecurityDescriptorHeader->RefCount != 0);
|
|||
|
|
|||
|
if (--SecurityDescriptorHeader->RefCount == 0) {
|
|||
|
ObpDestroySecurityDescriptorHeader( SecurityDescriptorHeader );
|
|||
|
}
|
|||
|
|
|||
|
ObpReleaseDescriptorCacheLock();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ObpDestroySecurityDescriptorHeader(
|
|||
|
IN PSECURITY_DESCRIPTOR_HEADER Header
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Frees a cached security descriptor and unlinks it from the chain.
|
|||
|
Does nothing if it's being reused.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Header - Pointer to a security descriptor header (cached security descriptor)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY Forward;
|
|||
|
PLIST_ENTRY Rear;
|
|||
|
UCHAR Index;
|
|||
|
|
|||
|
ASSERT ( Header->RefCount == 0 );
|
|||
|
|
|||
|
#if OB_DIAGNOSTICS_ENABLED
|
|||
|
|
|||
|
TotalCacheEntries--;
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
ObPrint( SHOW_STATISTICS, ("TotalCacheEntries = %d \n",TotalCacheEntries));
|
|||
|
|
|||
|
Index = Header->Index;
|
|||
|
|
|||
|
Forward = Header->Link.Flink;
|
|||
|
Rear = Header->Link.Blink;
|
|||
|
|
|||
|
if ( Forward != NULL ) {
|
|||
|
Forward->Blink = Rear;
|
|||
|
}
|
|||
|
|
|||
|
if ( Rear != NULL ) {
|
|||
|
Rear->Flink = Forward;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// if Rear is NULL, we're deleting the head of the list
|
|||
|
//
|
|||
|
|
|||
|
SecurityDescriptorCache[Index] = Forward;
|
|||
|
}
|
|||
|
|
|||
|
ObPrint( SHOW_HEADER_FREE, ("Freeing memory at %x \n",Header));
|
|||
|
|
|||
|
ExFreePool( Header );
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
ObpCompareSecurityDescriptors(
|
|||
|
IN PSECURITY_DESCRIPTOR SD1,
|
|||
|
IN PSECURITY_DESCRIPTOR SD2
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Performs a byte by byte comparison of two self relative security descriptors
|
|||
|
to determine if they are identical.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SD1, SD2 - Security descriptors to be compared.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - They are the same.
|
|||
|
|
|||
|
FALSE - They are different.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG Length1;
|
|||
|
ULONG Length2;
|
|||
|
ULONG Compare;
|
|||
|
|
|||
|
//
|
|||
|
// Calculating the lenght is pretty fast, see if we
|
|||
|
// can get away with doing only that.
|
|||
|
//
|
|||
|
|
|||
|
Length1 = RtlLengthSecurityDescriptor ( SD1 );
|
|||
|
Length2 = RtlLengthSecurityDescriptor ( SD2 );
|
|||
|
|
|||
|
if (Length1 != Length2) {
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
return (BOOLEAN)RtlEqualMemory ( SD1, SD2, Length1 );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ObpAcquireDescriptorCacheWriteLock(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Takes a write lock on the security descriptor cache.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
KeEnterCriticalRegion();
|
|||
|
(VOID) ExAcquireResourceExclusive( &SecurityDescriptorCacheLock, TRUE );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
ObpAcquireDescriptorCacheReadLock(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Takes a read lock on the security descriptor cache.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
KeEnterCriticalRegion();
|
|||
|
(VOID)ExAcquireResourceShared( &SecurityDescriptorCacheLock,TRUE);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
ObpReleaseDescriptorCacheLock(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Releases a lock on the security descriptor cache.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
(VOID) ExReleaseResource( &SecurityDescriptorCacheLock );
|
|||
|
KeLeaveCriticalRegion ();
|
|||
|
return;
|
|||
|
}
|