Implement security descriptor cache.
authorEric Kohl <eric.kohl@reactos.org>
Fri, 16 Jul 2004 17:20:23 +0000 (17:20 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Fri, 16 Jul 2004 17:20:23 +0000 (17:20 +0000)
svn path=/trunk/; revision=10142

reactos/ntoskrnl/Makefile
reactos/ntoskrnl/include/internal/ob.h
reactos/ntoskrnl/ob/namespc.c
reactos/ntoskrnl/ob/object.c
reactos/ntoskrnl/ob/sdcache.c [new file with mode: 0644]
reactos/ntoskrnl/ob/security.c

index ddfb1ed..8a4523c 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.129 2004/07/02 21:02:54 royce Exp $
+# $Id: Makefile,v 1.130 2004/07/16 17:20:23 ekohl Exp $
 #
 # ReactOS Operating System
 #
@@ -130,7 +130,7 @@ OBJECTS_KE = \
        ke/catch.o \
        ke/critical.o \
        ke/dpc.o \
-        ke/device.o \
+       ke/device.o \
        ke/error.o \
        ke/event.o \
        ke/kqueue.o \
@@ -138,7 +138,7 @@ OBJECTS_KE = \
        ke/main.o \
        ke/mutex.o \
        ke/process.o \
-        ke/profile.o \
+       ke/profile.o \
        ke/queue.o \
        ke/sem.o \
        ke/spinlock.o \
@@ -223,9 +223,9 @@ OBJECTS_IO = \
        io/timer.o \
        io/vpb.o \
        io/wdm.o \
+       io/wmi.o \
        io/xhaldisp.o \
-        io/xhaldrv.o \
-        io/wmi.o
+       io/xhaldrv.o
 
 # Object Manager (Ob)
 OBJECTS_OB = \
@@ -234,6 +234,7 @@ OBJECTS_OB = \
        ob/namespc.o \
        ob/ntobj.o \
        ob/object.o \
+       ob/sdcache.o \
        ob/security.o \
        ob/symlink.o
 
@@ -265,12 +266,12 @@ OBJECTS_EX = \
        ex/napi.o \
        ex/power.o \
        ex/resource.o \
-        ex/rundown.o \
+       ex/rundown.o \
        ex/stree.o \
-        ex/synch.o \
+       ex/synch.o \
        ex/sysinfo.o \
-        ex/time.o \
-        ex/util.o \
+       ex/time.o \
+       ex/util.o \
        ex/win32k.o \
        ex/work.o \
        ex/zone.o
@@ -359,9 +360,9 @@ OBJECTS_CC = \
 # Kernel Debugger Support (Kd)
 OBJECTS_KD = \
        kd/dlog.o \
-    kd/gdbstub.o \
+       kd/gdbstub.o \
        kd/kdebug.o \
-    kd/mda.o \
+       kd/mda.o \
        kd/service.o
 
 # Boot video (Inbv)
index fc061e3..e6184dc 100644 (file)
@@ -133,8 +133,21 @@ ObDuplicateObject(PEPROCESS SourceProcess,
                  BOOLEAN InheritHandle,
                  ULONG Options);
 
-ULONG 
-ObpGetHandleCountbyHandleTable(PHANDLE_TABLE HandleTable);
+ULONG
+ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable);
+
+
+/* Security descriptor cache functions */
+
+NTSTATUS
+ObpInitSdCache(VOID);
+
+NTSTATUS
+ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD,
+                        OUT PSECURITY_DESCRIPTOR *DestinationSD);
+
+NTSTATUS
+ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
 
 
 #endif /* __INCLUDE_INTERNAL_OBJMGR_H */
index f374c95..0c18f2e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: namespc.c,v 1.44 2003/11/17 02:12:51 hyperion Exp $
+/* $Id: namespc.c,v 1.45 2004/07/16 17:19:15 ekohl Exp $
  *
  * COPYRIGHT:      See COPYING in the top level directory
  * PROJECT:        ReactOS kernel
@@ -349,6 +349,9 @@ ObInit(VOID)
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING Name;
 
+  /* Initialize the security descriptor cache */
+  ObpInitSdCache();
+
   /* create 'directory' object type */
   ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
   
index 81eabe9..a83d29e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: object.c,v 1.77 2004/03/12 00:46:35 dwelch Exp $
+/* $Id: object.c,v 1.78 2004/07/16 17:19:15 ekohl Exp $
  * 
  * COPYRIGHT:     See COPYING in the top level directory
  * PROJECT:       ReactOS kernel
@@ -36,14 +36,14 @@ typedef struct _RETENTION_CHECK_PARAMS
 
 PVOID HEADER_TO_BODY(POBJECT_HEADER obj)
 {
-   return(((char*)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER));
+  return(((char*)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER));
 }
 
 
 POBJECT_HEADER BODY_TO_HEADER(PVOID body)
 {
-   PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body;
-   return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type));
+  PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body;
+  return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type));
 }
 
 
@@ -76,44 +76,44 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
             PUNICODE_STRING RemainingPath,
             POBJECT_TYPE ObjectType)
 {
-   PVOID NextObject;
-   PVOID CurrentObject;
-   PVOID RootObject;
-   POBJECT_HEADER CurrentHeader;
-   NTSTATUS Status;
-   PWSTR current;
-   UNICODE_STRING PathString;
-   ULONG Attributes;
-   PUNICODE_STRING ObjectName;
+  PVOID NextObject;
+  PVOID CurrentObject;
+  PVOID RootObject;
+  POBJECT_HEADER CurrentHeader;
+  NTSTATUS Status;
+  PWSTR current;
+  UNICODE_STRING PathString;
+  ULONG Attributes;
+  PUNICODE_STRING ObjectName;
 
-   DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
-         "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
-   DPRINT("ObjectAttributes->ObjectName %wZ\n",
-         ObjectAttributes->ObjectName);
+  DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
+        "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
+  DPRINT("ObjectAttributes->ObjectName %wZ\n",
+        ObjectAttributes->ObjectName);
 
-   RtlInitUnicodeString (RemainingPath, NULL);
+  RtlInitUnicodeString (RemainingPath, NULL);
 
-   if (ObjectAttributes->RootDirectory == NULL)
-     {
-       ObReferenceObjectByPointer(NameSpaceRoot,
-                                  DIRECTORY_TRAVERSE,
-                                  NULL,
-                                  UserMode);
-       CurrentObject = NameSpaceRoot;
-     }
-   else
-     {
-       Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
-                                          DIRECTORY_TRAVERSE,
-                                          NULL,
-                                          UserMode,
-                                          &CurrentObject,
-                                          NULL);
-       if (!NT_SUCCESS(Status))
-         {
-            return(Status);
-         }
-     }
+  if (ObjectAttributes->RootDirectory == NULL)
+    {
+      ObReferenceObjectByPointer(NameSpaceRoot,
+                                DIRECTORY_TRAVERSE,
+                                NULL,
+                                UserMode);
+      CurrentObject = NameSpaceRoot;
+    }
+  else
+    {
+      Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
+                                        DIRECTORY_TRAVERSE,
+                                        NULL,
+                                        UserMode,
+                                        &CurrentObject,
+                                        NULL);
+      if (!NT_SUCCESS(Status))
+       {
+         return Status;
+       }
+    }
 
   ObjectName = ObjectAttributes->ObjectName;
   if (ObjectName->Length == 0 ||
@@ -148,13 +148,13 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
 
   current = PathString.Buffer;
 
-   RootObject = CurrentObject;
-   Attributes = ObjectAttributes->Attributes;
-   if (ObjectType == ObSymbolicLinkType)
-     Attributes |= OBJ_OPENLINK;
+  RootObject = CurrentObject;
+  Attributes = ObjectAttributes->Attributes;
+  if (ObjectType == ObSymbolicLinkType)
+    Attributes |= OBJ_OPENLINK;
 
-   while (TRUE)
-     {
+  while (TRUE)
+    {
        DPRINT("current %S\n",current);
        CurrentHeader = BODY_TO_HEADER(CurrentObject);
 
@@ -189,14 +189,14 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
          }
        ObDereferenceObject(CurrentObject);
        CurrentObject = NextObject;
-     }
-   
-   if (current)
-      RtlCreateUnicodeString (RemainingPath, current);
-   RtlFreeUnicodeString (&PathString);
-   *ReturnedObject = CurrentObject;
-   
-   return(STATUS_SUCCESS);
+    }
+
+  if (current)
+     RtlCreateUnicodeString (RemainingPath, current);
+  RtlFreeUnicodeString (&PathString);
+  *ReturnedObject = CurrentObject;
+
+  return STATUS_SUCCESS;
 }
 
 
@@ -451,6 +451,30 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
     }
   RtlFreeUnicodeString( &RemainingPath );
 
+  if (Header->ObjectType != NULL)
+    {
+      /* FIXME: Call SeAssignSecurity() to create a new security descriptor */
+
+      if (Header->ObjectType->Security != NULL)
+       {
+         /* FIXME: Call the security method */
+         Status = STATUS_SUCCESS;
+       }
+      else
+       {
+         /* Assign the security descriptor to the object header */
+         if (ObjectAttributes != NULL && ObjectAttributes->SecurityDescriptor != NULL)
+           {
+             Status = ObpAddSecurityDescriptor(ObjectAttributes->SecurityDescriptor,
+                                               &Header->SecurityDescriptor);
+           }
+         else
+           {
+             Status = STATUS_SUCCESS;
+           }
+       }
+    }
+
   if (Object != NULL)
     {
       *Object = HEADER_TO_BODY(Header);
@@ -574,6 +598,11 @@ ObpDeleteObject(POBJECT_HEADER Header)
       KEBUGCHECK(0);
     }
 
+  if (Header->SecurityDescriptor != NULL)
+    {
+      ObpRemoveSecurityDescriptor(Header->SecurityDescriptor);
+    }
+
   if (Header->ObjectType != NULL &&
       Header->ObjectType->Delete != NULL)
     {
diff --git a/reactos/ntoskrnl/ob/sdcache.c b/reactos/ntoskrnl/ob/sdcache.c
new file mode 100644 (file)
index 0000000..0b26490
--- /dev/null
@@ -0,0 +1,312 @@
+/* $Id: sdcache.c,v 1.1 2004/07/16 17:19:15 ekohl Exp $
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ps/kill.c
+ * PURPOSE:         Terminating a thread
+ * PROGRAMMER:      David Welch (welch@cwcom.net)
+ * UPDATE HISTORY:
+ *                  Created 22/05/98
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <internal/ob.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+
+/* TYPES ********************************************************************/
+
+typedef struct _SD_CACHE_ENTRY
+{
+  LIST_ENTRY ListEntry;
+  ULONG HashValue;
+  ULONG Index;
+  ULONG RefCount;
+} SD_CACHE_ENTRY, *PSD_CACHE_ENTRY;
+
+
+/* GLOBALS ******************************************************************/
+
+PLIST_ENTRY ObpSdCache;
+KSPIN_LOCK ObpSdCacheSpinLock;
+KIRQL ObpSdCacheIrql;
+
+
+#define SD_CACHE_ENTRIES 0x100
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS
+ObpInitSdCache(VOID)
+{
+  ULONG i;
+
+  ObpSdCache = ExAllocatePool(NonPagedPool,
+                             SD_CACHE_ENTRIES * sizeof(LIST_ENTRY));
+  if (ObpSdCache == NULL)
+    {
+      return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+  for (i = 0; i < SD_CACHE_ENTRIES; i++)
+    {
+      InitializeListHead(&ObpSdCache[i]);
+    }
+
+  KeInitializeSpinLock(&ObpSdCacheSpinLock);
+
+  return STATUS_SUCCESS;
+}
+
+
+static VOID
+ObpSdCacheLock(VOID)
+{
+  KeAcquireSpinLock(&ObpSdCacheSpinLock,
+                   &ObpSdCacheIrql);
+}
+
+
+static VOID
+ObpSdCacheUnlock(VOID)
+{
+  KeReleaseSpinLock(&ObpSdCacheSpinLock,
+                   ObpSdCacheIrql);
+}
+
+
+static ULONG
+ObpHash(PVOID Buffer,
+       ULONG Length)
+{
+  PUCHAR Ptr;
+  ULONG Value;
+  ULONG i;
+
+  Ptr = (PUCHAR)Buffer;
+  Value = 0;
+  for (i = 0; i < Length; i++)
+    {
+      Value += *Ptr;
+      Ptr++;
+    }
+
+  return Value;
+}
+
+
+static ULONG
+ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
+{
+  ULONG Value;
+  BOOLEAN Defaulted;
+  BOOLEAN DaclPresent;
+  BOOLEAN SaclPresent;
+  PSID Owner = NULL;
+  PSID Group = NULL;
+  PACL Dacl = NULL;
+  PACL Sacl = NULL;
+
+  RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
+                               &Owner,
+                               &Defaulted);
+
+  RtlGetGroupSecurityDescriptor(SecurityDescriptor,
+                               &Group,
+                               &Defaulted);
+
+  RtlGetDaclSecurityDescriptor(SecurityDescriptor,
+                              &DaclPresent,
+                              &Dacl,
+                              &Defaulted);
+
+  RtlGetSaclSecurityDescriptor(SecurityDescriptor,
+                              &SaclPresent,
+                              &Sacl,
+                              &Defaulted);
+
+  Value = 0;
+  if (Owner != NULL)
+    {
+      Value += ObpHash(Owner, RtlLengthSid(Owner));
+    }
+
+  if (Group != NULL)
+    {
+      Value += ObpHash(Group, RtlLengthSid(Group));
+    }
+
+  if (DaclPresent == TRUE && Dacl != NULL)
+    {
+      Value += ObpHash(Dacl, Dacl->AclSize);
+    }
+
+  if (SaclPresent == TRUE && Sacl != NULL)
+    {
+      Value += ObpHash(Sacl, Sacl->AclSize);
+    }
+
+  return Value;
+}
+
+
+static PSD_CACHE_ENTRY
+ObpCreateCacheEntry(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+                   IN ULONG HashValue,
+                   IN ULONG Index,
+                   OUT PSECURITY_DESCRIPTOR *NewSD)
+{
+  PSECURITY_DESCRIPTOR Sd;
+  PSD_CACHE_ENTRY CacheEntry;
+  ULONG Length;
+
+  DPRINT("ObpCreateCacheEntry() called\n");
+
+  Length = RtlLengthSecurityDescriptor(SecurityDescriptor);
+
+  CacheEntry = ExAllocatePool(NonPagedPool,
+                             sizeof(SD_CACHE_ENTRY) + Length);
+  if (CacheEntry == NULL)
+    {
+      DPRINT1("ExAllocatePool() failed\n");
+      return NULL;
+    }
+
+  CacheEntry->HashValue = HashValue;
+  CacheEntry->Index = Index;
+  CacheEntry->RefCount = 1;
+
+  Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1);
+  RtlCopyMemory(Sd,
+               SecurityDescriptor,
+               Length);
+
+  *NewSD = Sd;
+
+  DPRINT("ObpCreateCacheEntry() done\n");
+
+  return CacheEntry;
+}
+
+
+static BOOLEAN
+ObpCompareSecurityDescriptors(IN PSECURITY_DESCRIPTOR Sd1,
+                             IN PSECURITY_DESCRIPTOR Sd2)
+{
+  ULONG Length1;
+  ULONG Length2;
+
+  Length1 = RtlLengthSecurityDescriptor(Sd1);
+  Length2 = RtlLengthSecurityDescriptor(Sd2);
+  if (Length1 != Length2)
+    return FALSE;
+
+  if (RtlCompareMemory(Sd1, Sd2, Length1) != Length1)
+    return FALSE;
+
+  return TRUE;
+}
+
+
+NTSTATUS
+ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD,
+                        OUT PSECURITY_DESCRIPTOR *DestinationSD)
+{
+  PSECURITY_DESCRIPTOR Sd;
+  PLIST_ENTRY CurrentEntry;
+  PSD_CACHE_ENTRY CacheEntry;
+  ULONG HashValue;
+  ULONG Index;
+  NTSTATUS Status;
+
+  DPRINT("ObpAddSecurityDescriptor() called\n");
+
+  HashValue = ObpHashSecurityDescriptor(SourceSD);
+  Index = HashValue & 0xFF;
+
+  ObpSdCacheLock();
+
+  if (!IsListEmpty(&ObpSdCache[Index]))
+    {
+      CurrentEntry = ObpSdCache[Index].Flink;
+      while (CurrentEntry != &ObpSdCache[Index])
+       {
+         CacheEntry = CONTAINING_RECORD(CurrentEntry,
+                                        SD_CACHE_ENTRY,
+                                        ListEntry);
+         Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1);
+
+         if (CacheEntry->HashValue == HashValue &&
+             ObpCompareSecurityDescriptors(SourceSD, Sd))
+           {
+             CacheEntry->RefCount++;
+             DPRINT("RefCount %lu\n", CacheEntry->RefCount);
+             *DestinationSD = Sd;
+
+             ObpSdCacheUnlock();
+
+             DPRINT("ObpAddSecurityDescriptor() done\n");
+
+             return STATUS_SUCCESS;
+           }
+
+         CurrentEntry = CurrentEntry->Flink;
+       }
+    }
+
+  CacheEntry = ObpCreateCacheEntry(SourceSD,
+                                  HashValue,
+                                  Index,
+                                  DestinationSD);
+  if (CacheEntry == NULL)
+    {
+      DPRINT1("ObpCreateCacheEntry() failed\n");
+      Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+  else
+    {
+      DPRINT("RefCount 1\n");
+      InsertTailList(&ObpSdCache[Index], &CacheEntry->ListEntry);
+      Status = STATUS_SUCCESS;
+    }
+
+  ObpSdCacheUnlock();
+
+  DPRINT("ObpAddSecurityDescriptor() done\n");
+
+  return Status;
+}
+
+
+NTSTATUS
+ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor)
+{
+  PSD_CACHE_ENTRY CacheEntry;
+
+  DPRINT("ObpRemoveSecurityDescriptor() called\n");
+
+  ObpSdCacheLock();
+
+  CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor - sizeof(SD_CACHE_ENTRY));
+
+  CacheEntry->RefCount--;
+  DPRINT("RefCount %lu\n", CacheEntry->RefCount);
+  if (CacheEntry->RefCount == 0)
+    {
+      DPRINT("Remove cache entry\n");
+      RemoveEntryList(&CacheEntry->ListEntry);
+      ExFreePool(CacheEntry);
+    }
+
+  ObpSdCacheUnlock();
+
+  DPRINT("ObpRemoveSecurityDescriptor() done\n");
+
+  return STATUS_SUCCESS;
+}
+
+/* EOF */
index d93165c..b5c00da 100644 (file)
@@ -56,7 +56,7 @@ ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 NTSTATUS STDCALL
 NtQuerySecurityObject(IN HANDLE Handle,
@@ -81,7 +81,7 @@ NtQuerySecurityObject(IN HANDLE Handle,
     }
 
   Header = BODY_TO_HEADER(Object);
-  if (Header->ObjectType != NULL &&
+  if (Header->ObjectType == NULL &&
       Header->ObjectType->Security != NULL)
     {
       Status = Header->ObjectType->Security(Object,
@@ -93,12 +93,33 @@ NtQuerySecurityObject(IN HANDLE Handle,
     }
   else
     {
-      Status = STATUS_NOT_IMPLEMENTED;
+      if (Header->SecurityDescriptor != NULL)
+       {
+         /* FIXME: Use SecurityInformation */
+         *ResultLength = RtlLengthSecurityDescriptor(Header->SecurityDescriptor);
+         if (Length >= *ResultLength)
+           {
+             RtlCopyMemory(SecurityDescriptor,
+                           Header->SecurityDescriptor,
+                           *ResultLength);
+
+             Status = STATUS_SUCCESS;
+           }
+         else
+           {
+             Status = STATUS_BUFFER_TOO_SMALL;
+           }
+       }
+      else
+       {
+         *ResultLength = 0;
+         Status = STATUS_UNSUCCESSFUL;
+       }
     }
 
   ObDereferenceObject(Object);
 
-  return(Status);
+  return Status;
 }