[v3 2/2] kernel32/tests: pipe: Added test for pipe security attributes
Jonathan Doron
jond at wizery.com
Tue Sep 19 06:40:31 CDT 2017
Signed-off-by: Jonathan Doron <jond at wizery.com>
---
dlls/kernel32/tests/pipe.c | 303 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 303 insertions(+)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 0a6edd6..0086535 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,305 @@ 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_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 +3356,9 @@ START_TEST(pipe)
test_readfileex_pending();
test_overlapped_transport(TRUE, FALSE);
test_overlapped_transport(TRUE, TRUE);
+ 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