[v5 4/4] kernel32/tests: pipe: Added test for pipe security attributes

Jonathan Doron jond at wizery.com
Thu Sep 21 05:04:43 CDT 2017


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

diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 0a6edd6..4817347 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,306 @@ 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;
+    NTSTATUS Status;
+
+    RequiredLength = 0;
+    Status = NtQuerySecurityObject(Object,
+                                   GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
+                                   NULL, 0, &RequiredLength);    /* Expected c0000023 */
+    ok(Status == STATUS_BUFFER_TOO_SMALL, "Failed to query object security descriptor length [1] (ntstatus = %08x)\n", Status);
+    ok(RequiredLength != 0, "Failed to query object security descriptor length [2] (ntstatus = %08x)\n", Status);
+    if (!RequiredLength)
+        goto cleanup;
+
+    SecDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, RequiredLength);
+    ok(SecDesc != NULL, "Not enough memory for object security descriptor\n");
+    if (!SecDesc)
+        goto cleanup;
+
+    Status = NtQuerySecurityObject(Object,
+                                   GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
+                                   SecDesc, RequiredLength, &RequiredLength);
+    ok(Status == STATUS_SUCCESS, "Failed to query object security descriptor (ntstatus = %08x)\n", Status);
+    if (Status != STATUS_SUCCESS) {
+        HeapFree(GetProcessHeap(), 0, SecDesc);
+        SecDesc = NULL;
+        goto cleanup;
+    }
+
+cleanup:
+    return SecDesc;
+}
+
+static PSID GetOwner(HANDLE Object, PSECURITY_DESCRIPTOR *SecDesc)
+{
+    PSID OwnerSid;
+    UCHAR OwnerDefaulted;
+    NTSTATUS Status;
+
+    *SecDesc = NULL;
+
+    *SecDesc = GetObjectSecDesc(Object);
+    if (!*SecDesc)
+        return NULL;
+
+    Status = RtlGetOwnerSecurityDescriptor(*SecDesc, &OwnerSid, &OwnerDefaulted);
+    ok(Status == STATUS_SUCCESS, "Failed to query owner from security descriptor (ntstatus = %08x)\n", Status);
+    if (Status != STATUS_SUCCESS) {
+        HeapFree(GetProcessHeap(), 0, *SecDesc);
+        *SecDesc = NULL;
+        return NULL;
+    }
+
+    return OwnerSid;
+}
+
+static PSID GetGroup(HANDLE Object, PSECURITY_DESCRIPTOR *SecDesc)
+{
+    PSID GroupSid;
+    UCHAR GroupDefaulted;
+    NTSTATUS Status;
+
+    *SecDesc = NULL;
+
+    *SecDesc = GetObjectSecDesc(Object);
+    if (!*SecDesc)
+        return NULL;
+
+    Status = RtlGetGroupSecurityDescriptor(*SecDesc, &GroupSid, &GroupDefaulted);
+    ok(Status == STATUS_SUCCESS, "Failed to query group from security descriptor (ntstatus = %08x)\n", Status);
+    if (Status != STATUS_SUCCESS) {
+        HeapFree(GetProcessHeap(), 0, *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);
+
+    HeapFree(GetProcessHeap(), 0, 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);
+
+    HeapFree(GetProcessHeap(), 0, SecDesc);
+    return GroupSidStr;
+}
+
+static PTOKEN_OWNER GetCurrentOwner(void)
+{
+    ULONG RequiredLength;
+    HANDLE TokenHandle = NULL;
+    PTOKEN_OWNER Owner = NULL;
+    BOOL ret;
+
+    ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &TokenHandle);
+    ok(ret, "Failed to get process token (GLE:%d)\n", GetLastError());
+    if (!ret)
+        goto cleanup;
+
+    RequiredLength = 0;
+    GetTokenInformation(TokenHandle, TokenOwner, NULL, 0, &RequiredLength);
+    ok(RequiredLength != 0, "Failed to get token owner information length (GLE:%d)\n", GetLastError());
+    if (!RequiredLength)
+        goto cleanup;
+
+    Owner = (PTOKEN_OWNER)HeapAlloc(GetProcessHeap(), 0, RequiredLength);
+    ok(Owner != NULL, "Not enough memory for token owner\n");
+    if (!Owner)
+        goto cleanup;
+
+    ret = GetTokenInformation(TokenHandle, TokenOwner, Owner, RequiredLength, &RequiredLength);
+    ok(ret, "Failed to get token owner information (GLE:%d)\n", GetLastError());
+
+cleanup:
+    if (TokenHandle)
+        CloseHandle(TokenHandle);
+
+    return Owner;
+}
+
+static PTOKEN_PRIMARY_GROUP GetCurrentGroup(void)
+{
+    ULONG RequiredLength;
+    HANDLE TokenHandle = NULL;
+    PTOKEN_PRIMARY_GROUP Group = NULL;
+    BOOL ret;
+
+    ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &TokenHandle);
+    ok(ret, "Failed to get process token (GLE:%d)\n", GetLastError());
+    if (!ret)
+        goto cleanup;
+
+    RequiredLength = 0;
+    GetTokenInformation(TokenHandle, TokenPrimaryGroup, NULL, 0, &RequiredLength);
+    ok(RequiredLength != 0, "Failed to get primary group token information length (GLE:%d)\n", GetLastError());
+    if (!RequiredLength)
+        goto cleanup;
+
+    Group = (PTOKEN_PRIMARY_GROUP)HeapAlloc(GetProcessHeap(), 0, RequiredLength);
+    ok(Group != NULL, "Not enough memory for primary group token\n");
+    if (!Group)
+        goto cleanup;
+
+    ret = GetTokenInformation(TokenHandle, TokenPrimaryGroup, Group, RequiredLength, &RequiredLength);
+    ok(ret, "Failed to get primary group token information (GLE:%d)\n", GetLastError());
+
+cleanup:
+    if (TokenHandle)
+        CloseHandle(TokenHandle);
+
+    return Group;
+}
+
+enum securityTestType
+{
+    TEST_PIPE_SECURITY_DEFAULT,
+    TEST_PIPE_SECURITY_CREATE,
+    TEST_PIPE_SECURITY_SERVER,
+    TEST_PIPE_SECURITY_CLIENT,
+};
+static void test_security(enum securityTestType TestType)
+{
+    HANDLE ServerPipeHandle = INVALID_HANDLE_VALUE, ClientPipeHandle = INVALID_HANDLE_VALUE;
+    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 ClientConnected;
+    BOOL ret;
+    NTSTATUS Status;
+
+    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 = HeapAlloc(GetProcessHeap(), 0, 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");
+
+    if (TestType == TEST_PIPE_SECURITY_CREATE) {
+        SecAttr.nLength = sizeof(SecAttr);
+        SecAttr.lpSecurityDescriptor = SecDesc;
+        SecAttr.bInheritHandle = FALSE;
+        ServerPipeHandle = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 1, 0x20000, 0x20000, 0, &SecAttr);
+    } else {
+        ServerPipeHandle = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | WRITE_OWNER, PIPE_TYPE_BYTE, 1, 0x20000, 0x20000, 0, NULL);
+    }
+    ok(ServerPipeHandle != INVALID_HANDLE_VALUE, "CreateNamedPipe 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());
+
+    /* Accept the client connection */
+    ClientConnected = ConnectNamedPipe(ServerPipeHandle, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+    ok(ClientConnected, "Server failed to accept client connection (GLE:%d)\n", GetLastError());
+
+    if (TestType == TEST_PIPE_SECURITY_SERVER) {
+        Status = NtSetSecurityObject(ServerPipeHandle, GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, SecDesc);
+        ok(Status == STATUS_SUCCESS, "Failed to set the server security descriptor (ntstatus = %08x)\n", Status);
+    } else if (TestType == TEST_PIPE_SECURITY_CLIENT) {
+        Status = NtSetSecurityObject(ClientPipeHandle, GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, SecDesc);
+        ok(Status == STATUS_SUCCESS, "Failed to set the client security descriptor (ntstatus = %08x)\n", Status);
+    }
+
+    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");
+    }
+
+    if (ClientPipeHandle != INVALID_HANDLE_VALUE)
+        CloseHandle(ClientPipeHandle);
+
+    if (ProcessOwner)
+        HeapFree(GetProcessHeap(), 0, ProcessOwner);
+
+    if (ProcessGroup)
+        HeapFree(GetProcessHeap(), 0, ProcessGroup);
+
+    if (SecDesc)
+        HeapFree(GetProcessHeap(), 0, SecDesc);
+
+    if (ProcessPipeOwnerSid)
+        HeapFree(GetProcessHeap(), 0, ProcessPipeOwnerSid);
+
+    if (ProcessPipeGroupSid)
+        HeapFree(GetProcessHeap(), 0, ProcessPipeGroupSid);
+
+    if (ServerPipeOwnerSid)
+        HeapFree(GetProcessHeap(), 0, ServerPipeOwnerSid);
+
+    if (ServerPipeGroupSid)
+        HeapFree(GetProcessHeap(), 0, ServerPipeGroupSid);
+
+    if (ClientPipeOwnerSid)
+        HeapFree(GetProcessHeap(), 0, ClientPipeOwnerSid);
+
+    if (ClientPipeGroupSid)
+        HeapFree(GetProcessHeap(), 0, ClientPipeGroupSid);
+
+    if (ServerPipeHandle != INVALID_HANDLE_VALUE)
+        CloseHandle(ServerPipeHandle);
+}
+
 START_TEST(pipe)
 {
     char **argv;
@@ -3056,6 +3357,10 @@ START_TEST(pipe)
     test_readfileex_pending();
     test_overlapped_transport(TRUE, FALSE);
     test_overlapped_transport(TRUE, TRUE);
+    test_security(TEST_PIPE_SECURITY_DEFAULT);
+    test_security(TEST_PIPE_SECURITY_CREATE);
+    test_security(TEST_PIPE_SECURITY_SERVER);
+    test_security(TEST_PIPE_SECURITY_CLIENT);
     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