[KSECDD]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 14 Sep 2014 19:40:15 +0000 (19:40 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 14 Sep 2014 19:40:15 +0000 (19:40 +0000)
- Fix a typo in KsecQueryFileInformation
- Implement missing ioctls in KsecDeviceControl
- Support METHOD_OUT_DIRECT for IRP_MJ_DEVICE_CONTROL
- Add stubs for KsecEn/DecryptMemory
[ADVAPI32]
- Use ksecdd to handle SystemFunction040 (RtlEncryptMemory) and SystemFunction041 (RtlDecryptMemory) (they still do nothing, but at least they do it in kenrnel mode now ;-))

svn path=/trunk/; revision=64153

reactos/dll/win32/advapi32/CMakeLists.txt
reactos/dll/win32/advapi32/misc/dllmain.c
reactos/dll/win32/advapi32/misc/sysfunc.c
reactos/drivers/crypto/ksecdd/CMakeLists.txt
reactos/drivers/crypto/ksecdd/crypt.c [new file with mode: 0644]
reactos/drivers/crypto/ksecdd/dispatch.c
reactos/drivers/crypto/ksecdd/ksecdd.h
reactos/include/reactos/drivers/ksecdd/ksecioctl.h

index 20cbef3..45f3fea 100644 (file)
@@ -8,6 +8,7 @@ add_definitions(-D_WIN32_WINNT=0x600)
 
 include_directories(
     ${REACTOS_SOURCE_DIR}/include/reactos/idl
+    ${REACTOS_SOURCE_DIR}/include/reactos/drivers/ksecdd
     ${REACTOS_SOURCE_DIR}/lib/cryptlib
     ${CMAKE_CURRENT_BINARY_DIR})
 
index d7e766a..7959cc2 100644 (file)
@@ -14,6 +14,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(advapi);
 extern BOOL RegInitialize(VOID);
 extern BOOL RegCleanup(VOID);
 extern VOID UnloadNtMarta(VOID);
+extern VOID CloseKsecDdHandle(VOID);
 
 BOOL
 WINAPI
@@ -33,6 +34,7 @@ DllMain(
             CloseLogonLsaHandle();
             RegCleanup();
             UnloadNtMarta();
+            CloseKsecDdHandle();
             break;
     }
 
index 12713dd..45033f0 100644 (file)
  */
 
 #include <advapi32.h>
+#include <ksecioctl.h>
 #include <md4.h>
 #include <md5.h>
 #include <rc4.h>
 
+/* FIXME: this should be in some shared header */
+#define RTL_ENCRYPT_OPTION_SAME_PROCESS   0
+#define RTL_ENCRYPT_OPTION_CROSS_PROCESS  1
+#define RTL_ENCRYPT_OPTION_SAME_LOGON     2
+
 static const unsigned char CRYPT_LMhash_Magic[8] =
     { 'K', 'G', 'S', '!', '@', '#', '$', '%' };
 
@@ -615,6 +621,93 @@ SystemFunction036(PVOID pbBuffer, ULONG dwLen)
     return TRUE;
 }
 
+HANDLE KsecDeviceHandle;
+
+static
+NTSTATUS
+KsecOpenDevice()
+{
+    UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KsecDD");
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    HANDLE DeviceHandle;
+    NTSTATUS Status;
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &DeviceName,
+                               0x18,
+                               NULL,
+                               NULL);
+    Status = NtOpenFile(&DeviceHandle,
+                        0x100001,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                        FILE_SYNCHRONOUS_IO_NONALERT);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    if (InterlockedCompareExchangePointer(&KsecDeviceHandle, DeviceHandle, NULL) != NULL)
+    {
+        NtClose(DeviceHandle);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+VOID
+CloseKsecDdHandle(VOID)
+{
+    /* Check if we already opened a handle to ksecdd */
+    if (KsecDeviceHandle != NULL)
+    {
+        /* Close it */
+        CloseHandle(KsecDeviceHandle);
+        KsecDeviceHandle = NULL;
+    }
+}
+
+static
+NTSTATUS
+KsecDeviceIoControl(
+    ULONG IoControlCode,
+    PVOID InputBuffer,
+    SIZE_T InputBufferLength,
+    PVOID OutputBuffer,
+    SIZE_T OutputBufferLength)
+{
+    IO_STATUS_BLOCK IoStatusBlock;
+    NTSTATUS Status;
+
+    /* Check if we already have a handle */
+    if (KsecDeviceHandle == NULL)
+    {
+        /* Try to open the device */
+        Status = KsecOpenDevice();
+        if (!NT_SUCCESS(Status))
+        {
+            //ERR("Failed to open handle to KsecDd driver!\n");
+            return Status;
+        }
+    }
+
+    /* Call the driver */
+    Status = NtDeviceIoControlFile(KsecDeviceHandle,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   &IoStatusBlock,
+                                   IoControlCode,
+                                   InputBuffer,
+                                   InputBufferLength,
+                                   OutputBuffer,
+                                   OutputBufferLength);
+
+    return Status;
+}
+
 /*
    These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
    in crypt32.dll.
@@ -642,10 +735,36 @@ SystemFunction036(PVOID pbBuffer, ULONG dwLen)
  *  If flags are specified when encrypting, the same flag value must be given
  *  when decrypting the memory.
  */
-NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
+NTSTATUS
+WINAPI
+SystemFunction040(
+    _Inout_ PVOID Memory,
+    _In_ ULONG MemoryLength,
+    _In_ ULONG OptionFlags)
 {
+    ULONG IoControlCode;
+
        //FIXME("(%p, %x, %x): stub [RtlEncryptMemory]\n", memory, length, flags);
        return STATUS_SUCCESS;
+
+    if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS)
+    {
+        IoControlCode = IOCTL_KSEC_ENCRYPT_SAME_PROCESS;
+    }
+    else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
+    {
+        IoControlCode = IOCTL_KSEC_ENCRYPT_CROSS_PROCESS;
+    }
+    else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
+    {
+        IoControlCode = IOCTL_KSEC_ENCRYPT_SAME_LOGON;
+    }
+    else
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+       return KsecDeviceIoControl(IoControlCode, Memory, MemoryLength, Memory, MemoryLength);
 }
 
 /******************************************************************************
@@ -670,10 +789,36 @@ NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags)
  *  If flags are specified when encrypting, the same flag value must be given
  *  when decrypting the memory.
  */
-NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags)
+NTSTATUS
+WINAPI
+SystemFunction041(
+    _Inout_ PVOID Memory,
+    _In_ ULONG MemoryLength,
+    _In_ ULONG OptionFlags)
 {
+    ULONG IoControlCode;
+
        //FIXME("(%p, %x, %x): stub [RtlDecryptMemory]\n", memory, length, flags);
        return STATUS_SUCCESS;
+
+    if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS)
+    {
+        IoControlCode = IOCTL_KSEC_DECRYPT_SAME_PROCESS;
+    }
+    else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
+    {
+        IoControlCode = IOCTL_KSEC_DECRYPT_CROSS_PROCESS;
+    }
+    else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
+    {
+        IoControlCode = IOCTL_KSEC_DECRYPT_SAME_LOGON;
+    }
+    else
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+       return KsecDeviceIoControl(IoControlCode, Memory, MemoryLength, Memory, MemoryLength);
 }
 
 /* EOF */
index 790ca1c..389f6a3 100644 (file)
@@ -8,6 +8,7 @@ include_directories(
 list(APPEND SOURCE
      ksecdd.c
      dispatch.c
+     crypt.c
      random.c
      stubs.c
      ksecdd.rc
diff --git a/reactos/drivers/crypto/ksecdd/crypt.c b/reactos/drivers/crypto/ksecdd/crypt.c
new file mode 100644 (file)
index 0000000..6e4eda3
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * PROJECT:         ReactOS Drivers
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PURPOSE:         Kernel Security Support Provider Interface Driver
+ *
+ * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "ksecdd.h"
+
+NTSTATUS
+NTAPI
+KsecEncryptMemory (
+    _Inout_ PVOID Buffer,
+    _In_ ULONG Length,
+    _In_ ULONG OptionFlags)
+{
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+KsecDecryptMemory (
+    _Inout_ PVOID Buffer,
+    _In_ ULONG Length,
+    _In_ ULONG OptionFlags)
+{
+    return STATUS_SUCCESS;
+}
index 9209bc2..6b6e074 100644 (file)
@@ -33,7 +33,7 @@ KsecQueryFileInformation(
     }
 
     /* Validate buffer size */
-    if (*BufferLength >= sizeof(FILE_STANDARD_INFORMATION))
+    if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
     {
         *BufferLength = sizeof(FILE_STANDARD_INFORMATION);
         return STATUS_INFO_LENGTH_MISMATCH;
@@ -92,7 +92,28 @@ KsecDeviceControl(
 {
     NTSTATUS Status;
 
-    Status = STATUS_SUCCESS;
+    if ((IoControlCode == IOCTL_KSEC_RANDOM_FILL_BUFFER) ||
+        (IoControlCode == IOCTL_KSEC_ENCRYPT_SAME_PROCESS) ||
+        (IoControlCode == IOCTL_KSEC_DECRYPT_SAME_PROCESS) ||
+        (IoControlCode == IOCTL_KSEC_ENCRYPT_CROSS_PROCESS) ||
+        (IoControlCode == IOCTL_KSEC_DECRYPT_CROSS_PROCESS) ||
+        (IoControlCode == IOCTL_KSEC_ENCRYPT_SAME_LOGON) ||
+        (IoControlCode == IOCTL_KSEC_DECRYPT_SAME_LOGON))
+    {
+        /* Make sure we have a valid output buffer */
+        if ((Buffer == NULL) || (OutputLength == NULL))
+        {
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        /* Check if the input is smaller than the output */
+        if (InputLength < *OutputLength)
+        {
+            /* We might have uninitialized memory, zero it out */
+            RtlSecureZeroMemory((PUCHAR)Buffer + InputLength,
+                                *OutputLength - InputLength);
+        }
+    }
 
     /* Check ioctl code */
     switch (IoControlCode)
@@ -107,6 +128,48 @@ KsecDeviceControl(
             Status = KsecGenRandom(Buffer, *OutputLength);
             break;
 
+        case IOCTL_KSEC_ENCRYPT_SAME_PROCESS:
+
+            Status = KsecEncryptMemory(Buffer,
+                                       *OutputLength,
+                                       RTL_ENCRYPT_OPTION_SAME_PROCESS);
+            break;
+
+        case IOCTL_KSEC_DECRYPT_SAME_PROCESS:
+
+            Status = KsecDecryptMemory(Buffer,
+                                       *OutputLength,
+                                       RTL_ENCRYPT_OPTION_SAME_PROCESS);
+            break;
+
+        case IOCTL_KSEC_ENCRYPT_CROSS_PROCESS:
+
+            Status = KsecEncryptMemory(Buffer,
+                                       *OutputLength,
+                                       RTL_ENCRYPT_OPTION_CROSS_PROCESS);
+            break;
+
+        case IOCTL_KSEC_DECRYPT_CROSS_PROCESS:
+
+            Status = KsecDecryptMemory(Buffer,
+                                       *OutputLength,
+                                       RTL_ENCRYPT_OPTION_CROSS_PROCESS);
+            break;
+
+        case IOCTL_KSEC_ENCRYPT_SAME_LOGON:
+
+            Status = KsecEncryptMemory(Buffer,
+                                       *OutputLength,
+                                       RTL_ENCRYPT_OPTION_SAME_LOGON);
+            break;
+
+        case IOCTL_KSEC_DECRYPT_SAME_LOGON:
+
+            Status = KsecDecryptMemory(Buffer,
+                                       *OutputLength,
+                                       RTL_ENCRYPT_OPTION_SAME_LOGON);
+            break;
+
         default:
             DPRINT1("Unhandled control code 0x%lx\n", IoControlCode);
             __debugbreak();
@@ -188,11 +251,31 @@ KsecDdDispatch(
         case IRP_MJ_DEVICE_CONTROL:
 
             /* Extract the parameters */
-            Buffer = Irp->AssociatedIrp.SystemBuffer;
             InputLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
             OutputLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
             IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
 
+            /* Check for METHOD_OUT_DIRECT method */
+            if ((METHOD_FROM_CTL_CODE(IoControlCode) == METHOD_OUT_DIRECT) &&
+                (OutputLength != 0))
+            {
+                /* Use the provided MDL */
+                OutputLength = Irp->MdlAddress->ByteCount;
+                Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress,
+                                                      NormalPagePriority);
+                if (Buffer == NULL)
+                {
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                    Information = 0;
+                    break;
+                }
+            }
+            else
+            {
+                /* Otherwise this is METHOD_BUFFERED, use the SystemBuffer */
+                Buffer = Irp->AssociatedIrp.SystemBuffer;
+            }
+
             /* Call the internal function */
             Status = KsecDeviceControl(IoControlCode,
                                        Buffer,
@@ -205,6 +288,7 @@ KsecDdDispatch(
             DPRINT1("Unhandled major function %lu!\n",
                     IoStackLocation->MajorFunction);
             ASSERT(FALSE);
+            return STATUS_INVALID_DEVICE_REQUEST;
     }
 
     /* Return the information */
index addcd15..f15e8cc 100644 (file)
@@ -9,6 +9,26 @@
 #define _NO_KSECDD_IMPORT_
 #include <ntifs.h>
 #include <ndk/extypes.h>
+#include <ndk/rtlfuncs.h>
+#include <ndk/lpcfuncs.h>
+#include <ndk/obfuncs.h>
+#include <ntstrsafe.h>
+
+#define STATUS_KSEC_INTERNAL_ERROR ((NTSTATUS)0x80090304)
+
+/* FIXME: this should be in some shared header */
+#define RTL_ENCRYPT_OPTION_SAME_PROCESS   0
+#define RTL_ENCRYPT_OPTION_CROSS_PROCESS  1
+#define RTL_ENCRYPT_OPTION_SAME_LOGON     2
+
+typedef struct _KSEC_CONNECTION_INFO
+{
+    ULONG Unknown0;
+    NTSTATUS Status;
+    ULONG_PTR Information;
+    CHAR ConnectionString[128];
+    ULONG Flags;
+} KSEC_CONNECTION_INFO;
 
 #if defined(_M_IX86) || defined(_M_AMD64)
 typedef struct _KSEC_MACHINE_SPECIFIC_COUNTERS
@@ -41,6 +61,9 @@ typedef struct _KSEC_ENTROPY_DATA
     SYSTEM_PROCESS_INFORMATION SystemProcessInformation;
 } KSEC_ENTROPY_DATA, *PKSEC_ENTROPY_DATA;
 
+extern PEPROCESS KsecLsaProcess;;
+extern HANDLE KsecLsaProcessHandle;
+
 NTSTATUS
 NTAPI
 KsecDdDispatch(
@@ -54,3 +77,37 @@ KsecGenRandom(
     PVOID Buffer,
     SIZE_T Length);
 
+NTSTATUS
+NTAPI
+KsecEncryptMemory (
+    _Inout_ PVOID Buffer,
+    _In_ ULONG Length,
+    _In_ ULONG OptionFlags);
+
+NTSTATUS
+NTAPI
+KsecDecryptMemory (
+    _Inout_ PVOID Buffer,
+    _In_ ULONG Length,
+    _In_ ULONG OptionFlags);
+
+NTSTATUS
+NTAPI
+KsecInitLsaMemory(VOID);
+
+///
+PVOID
+NTAPI
+PsGetProcessSecurityPort(
+    PEPROCESS Process);
+
+NTSTATUS
+NTAPI
+PsSetProcessSecurityPort(
+    PEPROCESS Process,
+    PVOID SecurityPort);
+
+HANDLE
+NTAPI
+PsGetCurrentThreadProcessId(VOID);
+
index 004db5a..957e7a0 100644 (file)
     CTL_CODE(FILE_DEVICE_KSEC, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
 // 3: 0x39000E - called from SystemFunction040 aka RtlEncryptMemory with OptionFlags == 0
-#define IOCTL_KSEC_ENCRYPT_PROCESS \
+#define IOCTL_KSEC_ENCRYPT_SAME_PROCESS \
     CTL_CODE(FILE_DEVICE_KSEC, 0x03, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
 
 // 4: 0x390012 - called from SystemFunction041 aka RtlDecryptMemory with OptionFlags == 0
-#define IOCTL_KSEC_DECRYPT_PROCESS \
+#define IOCTL_KSEC_DECRYPT_SAME_PROCESS \
     CTL_CODE(FILE_DEVICE_KSEC, 0x04, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
 
 // 5: 0x390016 - called from SystemFunction040 aka RtlEncryptMemory with OptionFlags == 1