[v1 3/3] kernel32/tests: pipe: Added test for pipe security attributes

Jonathan Doron jond at wizery.com
Tue Sep 12 03:01:10 CDT 2017


Signed-off-by: Jonathan Doron <jond at wizery.com>
---
 dlls/kernel32/tests/pipe.c | 241 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 241 insertions(+)

diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 0a6edd6..9b90ce9 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -28,6 +28,7 @@
 #include "winternl.h"
 #include "winioctl.h"
 #include "wine/test.h"
+#include "sddl.h"
 
 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
 
@@ -3018,6 +3019,245 @@ static void test_overlapped_transport(BOOL msg_mode, BOOL msg_read_mode)
     CloseHandle(client);
 }
 
+static PSECURITY_DESCRIPTOR GetObjectSecDesc(HANDLE Object)
+{
+    ULONG RequiredLength;
+    PSECURITY_DESCRIPTOR SecDesc = NULL;
+
+    RequiredLength = 0;
+    NtQuerySecurityObject(Object,
+                          GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
+                          NULL, 0, &RequiredLength);    // Expected c0000023
+    if (!RequiredLength)
+        goto cleanup;
+
+    SecDesc = LocalAlloc(LMEM_FIXED, RequiredLength);
+    if (!SecDesc)
+        goto cleanup;
+    memset(SecDesc, 0, RequiredLength);
+
+    if (NtQuerySecurityObject(Object,
+                              GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
+                              SecDesc, RequiredLength, &RequiredLength)) {
+        LocalFree(SecDesc);
+        SecDesc = NULL;
+        goto cleanup;
+    }
+
+cleanup:
+    return SecDesc;
+}
+
+static PSID GetOwner(HANDLE Object, PSECURITY_DESCRIPTOR *SecDesc)
+{
+    PSID OwnerSid;
+    UCHAR OwnerDefaulted;
+
+    *SecDesc = NULL;
+
+    *SecDesc = GetObjectSecDesc(Object);
+    if (!*SecDesc)
+        return NULL;
+
+    if (RtlGetOwnerSecurityDescriptor(*SecDesc, &OwnerSid, &OwnerDefaulted)) {
+        LocalFree(*SecDesc);
+        *SecDesc = NULL;
+        return NULL;
+    }
+
+    return OwnerSid;
+}
+
+static PSID GetGroup(HANDLE Object, PSECURITY_DESCRIPTOR *SecDesc)
+{
+    PSID GroupSid;
+    UCHAR GroupDefaulted;
+
+    *SecDesc = NULL;
+
+    *SecDesc = GetObjectSecDesc(Object);
+    if (!*SecDesc)
+        return NULL;
+
+    if (RtlGetGroupSecurityDescriptor(*SecDesc, &GroupSid, &GroupDefaulted)) {
+        LocalFree(*SecDesc);
+        *SecDesc = NULL;
+        return NULL;
+    }
+
+    return GroupSid;
+}
+
+static PCHAR GetOwnerString(HANDLE Object)
+{
+    PSID OwnerSid;
+    PCHAR OwnerSidStr = NULL;
+    PSECURITY_DESCRIPTOR SecDesc = NULL;
+
+    OwnerSid = GetOwner(Object, &SecDesc);
+    if (OwnerSid)
+        ConvertSidToStringSidA(OwnerSid, &OwnerSidStr);
+
+    LocalFree(SecDesc);
+    return OwnerSidStr;
+}
+
+static PCHAR GetGroupString(HANDLE Object)
+{
+    PSID GroupSid;
+    PCHAR GroupSidStr = NULL;
+    PSECURITY_DESCRIPTOR SecDesc = NULL;
+
+    GroupSid = GetGroup(Object, &SecDesc);
+    if (GroupSid)
+        ConvertSidToStringSidA(GroupSid, &GroupSidStr);
+
+    LocalFree(SecDesc);
+    return GroupSidStr;
+}
+
+static PTOKEN_OWNER GetCurrentOwner(void)
+{
+    ULONG RequiredLength;
+    HANDLE TokenHandle = NULL;
+    PTOKEN_OWNER Owner = NULL;
+
+    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &TokenHandle))
+        goto cleanup;
+
+    RequiredLength = 0;
+    GetTokenInformation(TokenHandle, TokenOwner, NULL, 0, &RequiredLength);
+    if (!RequiredLength)
+        goto cleanup;
+
+    Owner = (PTOKEN_OWNER)LocalAlloc(LMEM_FIXED, RequiredLength);
+    if (!Owner)
+        goto cleanup;
+
+    if (!GetTokenInformation(TokenHandle, TokenOwner, Owner, RequiredLength, &RequiredLength))
+        goto cleanup;
+
+cleanup:
+    if (TokenHandle)
+        CloseHandle(TokenHandle);
+
+    return Owner;
+}
+
+static PTOKEN_PRIMARY_GROUP GetCurrentGroup(void)
+{
+    ULONG RequiredLength;
+    HANDLE TokenHandle = NULL;
+    PTOKEN_PRIMARY_GROUP Group = NULL;
+
+    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &TokenHandle))
+        goto cleanup;
+
+    RequiredLength = 0;
+    GetTokenInformation(TokenHandle, TokenPrimaryGroup, NULL, 0, &RequiredLength);
+    if (!RequiredLength)
+        goto cleanup;
+
+    Group = (PTOKEN_PRIMARY_GROUP)LocalAlloc(LMEM_FIXED, RequiredLength);
+    if (!Group)
+        goto cleanup;
+
+    if (!GetTokenInformation(TokenHandle, TokenPrimaryGroup, Group, RequiredLength, &RequiredLength))
+        goto cleanup;
+
+cleanup:
+    if (TokenHandle)
+        CloseHandle(TokenHandle);
+
+    return Group;
+}
+
+static ULONG WINAPI ServerPipeThread(PVOID Param)
+{
+    ULONG RetVal;
+
+    RetVal = ConnectNamedPipe((HANDLE)Param, NULL) ? ERROR_SUCCESS : GetLastError();
+    if ((RetVal == ERROR_PIPE_CONNECTED) || (RetVal == ERROR_SUCCESS))
+        RetVal = ERROR_SUCCESS;
+
+    ExitThread(RetVal);
+}
+
+static void test_security(void)
+{
+    HANDLE ServerThread = NULL, ServerPipeHandle = NULL,
+           ClientPipeHandle = NULL;
+    PCHAR ProcessPipeOwnerSid = NULL, ProcessPipeGroupSid = NULL,
+          ServerPipeOwnerSid = NULL, ServerPipeGroupSid = NULL,
+          ClientPipeOwnerSid = NULL, ClientPipeGroupSid = NULL;
+    SECURITY_ATTRIBUTES SecAttr;
+    PSECURITY_DESCRIPTOR SecDesc = NULL;
+    PTOKEN_PRIMARY_GROUP ProcessGroup = NULL;
+    PTOKEN_OWNER ProcessOwner = NULL;
+    BOOL ret;
+
+    ProcessOwner = GetCurrentOwner();
+    ok(ProcessOwner != NULL, "Get current process owner failed\n");
+
+    ret = ConvertSidToStringSidA(ProcessOwner->Owner, &ProcessPipeOwnerSid);
+    ok(ret, "ConvertSidToStringSidA for process owner failed\n");
+
+    ProcessGroup = GetCurrentGroup();
+    ok(ProcessGroup != NULL, "Get current process primary group failed\n");
+
+    ret = ConvertSidToStringSidA(ProcessGroup->PrimaryGroup, &ProcessPipeGroupSid);
+    ok(ret, "ConvertSidToStringSidA for process primary group failed\n");
+
+    SecDesc = LocalAlloc(LMEM_FIXED, SECURITY_DESCRIPTOR_MIN_LENGTH);
+    ok(SecDesc != NULL, "Not enough memory for security descriptor\n");
+
+    ret = InitializeSecurityDescriptor(SecDesc, SECURITY_DESCRIPTOR_REVISION);
+    ok(ret, "InitializeSecurityDescriptor failed\n");
+
+    ret = SetSecurityDescriptorOwner(SecDesc, ProcessOwner->Owner, FALSE);
+    ok(ret, "SetSecurityDescriptorOwner failed\n");
+
+    ret = SetSecurityDescriptorGroup(SecDesc, ProcessGroup->PrimaryGroup, FALSE);
+    ok(ret, "SetSecurityDescriptorGroup failed\n");
+
+    SecAttr.nLength = sizeof(SecAttr);
+    SecAttr.lpSecurityDescriptor = SecDesc;
+    SecAttr.bInheritHandle = FALSE;
+    ServerPipeHandle = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 1, 0x20000, 0x20000, 0, &SecAttr);
+    ok(ServerPipeHandle != INVALID_HANDLE_VALUE, "CreateNamedPipe failed (GLE:%d)\n", GetLastError());
+
+    ServerThread = CreateThread(NULL, 0, ServerPipeThread, ServerPipeHandle, 0, NULL);
+    ok(ServerThread != NULL, "CreateThread for ServerPipeThread failed (GLE:%d)\n", GetLastError());
+
+    // Connect as a client to the named pipe
+    ClientPipeHandle = CreateFileA(PIPENAME, GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL);
+    ok(ClientPipeHandle != INVALID_HANDLE_VALUE, "CreateFile failed (GLE:%d)\n", GetLastError());
+
+    // Wait for the server thread to exit
+    WaitForSingleObject(ServerThread, INFINITE);
+
+    ServerPipeOwnerSid = GetOwnerString(ServerPipeHandle);
+    ok(ServerPipeOwnerSid != NULL, "Failed to get owner string from pipe server handle\n");
+
+    ClientPipeOwnerSid = GetOwnerString(ClientPipeHandle);
+    ok(ClientPipeOwnerSid != NULL, "Failed to get owner string from pipe client handle\n");
+
+    ServerPipeGroupSid = GetGroupString(ServerPipeHandle);
+    ok(ServerPipeGroupSid != NULL, "Failed to get group string from pipe server handle\n");
+
+    ClientPipeGroupSid = GetGroupString(ClientPipeHandle);
+    ok(ClientPipeGroupSid != NULL, "Failed to get group string from pipe client handle\n");
+
+    if (ServerPipeOwnerSid && ServerPipeGroupSid &&
+        ClientPipeOwnerSid && ClientPipeGroupSid) {
+        ok(strcmp(ProcessPipeOwnerSid, ServerPipeOwnerSid) == 0, "Process Owner does not match Server Pipe Owner\n");
+        ok(strcmp(ProcessPipeOwnerSid, ClientPipeOwnerSid) == 0, "Process Owner does not match Client Pipe Owner\n");
+
+        ok(strcmp(ProcessPipeGroupSid, ServerPipeGroupSid) == 0, "Process Group does not match Server Group Owner\n");
+        ok(strcmp(ProcessPipeGroupSid, ClientPipeGroupSid) == 0, "Process Group does not match Client Group Owner\n");
+    }
+}
+
 START_TEST(pipe)
 {
     char **argv;
@@ -3056,6 +3296,7 @@ START_TEST(pipe)
     test_readfileex_pending();
     test_overlapped_transport(TRUE, FALSE);
     test_overlapped_transport(TRUE, TRUE);
+    test_security();
     if (broken(1)) /* FIXME: Remove once Wine is ready. */
         test_overlapped_transport(FALSE, FALSE);
 }
-- 
2.9.4




More information about the wine-patches mailing list