[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