From 1ce2201ed8bab2569b5cd1dbed7ae7665f76a515 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 26 Feb 2018 19:25:08 +0100 Subject: [PATCH] server: Share security descriptor among all pipe instances. Based on patch by Jonathan Doron. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/ntdll/tests/pipe.c | 21 +++++++++-------- server/named_pipe.c | 52 ++++++++++++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c index 235ab12991a..5cbf6e77901 100644 --- a/dlls/ntdll/tests/pipe.c +++ b/dlls/ntdll/tests/pipe.c @@ -1209,7 +1209,7 @@ static void test_file_info(void) CloseHandle( client ); } -static PSECURITY_DESCRIPTOR get_security_descriptor(HANDLE handle) +static PSECURITY_DESCRIPTOR get_security_descriptor(HANDLE handle, BOOL todo) { SECURITY_DESCRIPTOR *sec_desc; ULONG length = 0; @@ -1217,8 +1217,10 @@ static PSECURITY_DESCRIPTOR get_security_descriptor(HANDLE handle) status = NtQuerySecurityObject(handle, GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, NULL, 0, &length); + todo_wine_if(todo && status == STATUS_PIPE_DISCONNECTED) ok(status == STATUS_BUFFER_TOO_SMALL, "Failed to query object security descriptor length: %08x\n", status); + if(status != STATUS_BUFFER_TOO_SMALL) return NULL; ok(length != 0, "length = 0\n"); sec_desc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, length); @@ -1295,7 +1297,8 @@ static void _test_group(unsigned line, HANDLE handle, SID *expected_sid, BOOL to PSID group_sid; NTSTATUS status; - sec_desc = get_security_descriptor(handle); + sec_desc = get_security_descriptor(handle, todo); + if (!sec_desc) return; status = RtlGetGroupSecurityDescriptor(sec_desc, &group_sid, &defaulted); ok_(__FILE__,line)(status == STATUS_SUCCESS, @@ -1351,13 +1354,13 @@ static void test_security_info(void) ok(status == STATUS_SUCCESS, "NtSetSecurityObject failed: %08x\n", status); test_group(server, world_sid, FALSE); - test_group(client, world_sid, TRUE); + test_group(client, world_sid, FALSE); /* new instance of pipe server has the same security descriptor */ server2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 10, 0x20000, 0x20000, 0, NULL); ok(server2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError()); - test_group(server2, world_sid, TRUE); + test_group(server2, world_sid, FALSE); /* set client group, server changes as well */ ret = SetSecurityDescriptorGroup(sec_desc, local_sid, FALSE); @@ -1366,8 +1369,8 @@ static void test_security_info(void) ok(status == STATUS_SUCCESS, "NtSetSecurityObject failed: %08x\n", status); test_group(server, local_sid, FALSE); - test_group(client, local_sid, TRUE); - test_group(server2, local_sid, TRUE); + test_group(client, local_sid, FALSE); + test_group(server2, local_sid, FALSE); CloseHandle(server); /* SD is preserved after closing server object */ @@ -1378,19 +1381,17 @@ static void test_security_info(void) client = CreateFileA(PIPENAME, GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL); ok(client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); - test_group(client, local_sid, TRUE); + test_group(client, local_sid, FALSE); ret = DisconnectNamedPipe(server); ok(ret, "DisconnectNamedPipe failed: %u\n", GetLastError()); /* disconnected server may be queried for security info, but client does not */ - test_group(server, local_sid, TRUE); + test_group(server, local_sid, FALSE); status = NtQuerySecurityObject(client, GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, NULL, 0, &length); - todo_wine ok(status == STATUS_PIPE_DISCONNECTED, "NtQuerySecurityObject returned %08x\n", status); status = NtSetSecurityObject(client, GROUP_SECURITY_INFORMATION, sec_desc); - todo_wine ok(status == STATUS_PIPE_DISCONNECTED, "NtQuerySecurityObject returned %08x\n", status); /* attempting to create another pipe instance with specified sd fails */ diff --git a/server/named_pipe.c b/server/named_pipe.c index c6b37cef06f..c77b07fc91b 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -150,6 +150,9 @@ static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue ); /* server end functions */ static void pipe_server_dump( struct object *obj, int verbose ); +static struct security_descriptor *pipe_server_get_sd( struct object *obj ); +static int pipe_server_set_sd( struct object *obj, const struct security_descriptor *sd, + unsigned int set_info ); static void pipe_server_destroy( struct object *obj); static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static void pipe_server_get_file_info( struct fd *fd, unsigned int info_class ); @@ -166,8 +169,8 @@ static const struct object_ops pipe_server_ops = no_signal, /* signal */ pipe_end_get_fd, /* get_fd */ default_fd_map_access, /* map_access */ - default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ + pipe_server_get_sd, /* get_sd */ + pipe_server_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ no_link_name, /* link_name */ NULL, /* unlink_name */ @@ -193,6 +196,9 @@ static const struct fd_ops pipe_server_fd_ops = /* client end functions */ static void pipe_client_dump( struct object *obj, int verbose ); +static struct security_descriptor *pipe_client_get_sd( struct object *obj ); +static int pipe_client_set_sd( struct object *obj, const struct security_descriptor *sd, + unsigned int set_info ); static void pipe_client_destroy( struct object *obj ); static int pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static void pipe_client_get_file_info( struct fd *fd, unsigned int info_class ); @@ -209,8 +215,8 @@ static const struct object_ops pipe_client_ops = no_signal, /* signal */ pipe_end_get_fd, /* get_fd */ default_fd_map_access, /* map_access */ - default_get_sd, /* get_sd */ - default_set_sd, /* set_sd */ + pipe_client_get_sd, /* get_sd */ + pipe_client_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ no_link_name, /* link_name */ NULL, /* unlink_name */ @@ -583,6 +589,36 @@ static void pipe_end_get_file_info( struct fd *fd, struct named_pipe *pipe, unsi } } +static struct security_descriptor *pipe_server_get_sd( struct object *obj ) +{ + struct pipe_server *server = (struct pipe_server *) obj; + return default_get_sd( &server->pipe->obj ); +} + +static struct security_descriptor *pipe_client_get_sd( struct object *obj ) +{ + struct pipe_client *client = (struct pipe_client *) obj; + if (client->server) return default_get_sd( &client->server->pipe->obj ); + set_error( STATUS_PIPE_DISCONNECTED ); + return NULL; +} + +static int pipe_server_set_sd( struct object *obj, const struct security_descriptor *sd, + unsigned int set_info ) +{ + struct pipe_server *server = (struct pipe_server *) obj; + return default_set_sd( &server->pipe->obj, sd, set_info ); +} + +static int pipe_client_set_sd( struct object *obj, const struct security_descriptor *sd, + unsigned int set_info ) +{ + struct pipe_client *client = (struct pipe_client *) obj; + if (client->server) return default_set_sd( &client->server->pipe->obj, sd, set_info ); + set_error( STATUS_PIPE_DISCONNECTED ); + return 0; +} + static void pipe_server_get_file_info( struct fd *fd, unsigned int info_class ) { struct pipe_server *server = get_fd_user( fd ); @@ -1170,6 +1206,10 @@ DECL_HANDLER(create_named_pipe) pipe->timeout = req->timeout; pipe->flags = req->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE; pipe->sharing = req->sharing; + if (sd) default_set_sd( &pipe->obj, sd, OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | + SACL_SECURITY_INFORMATION ); } else { @@ -1193,10 +1233,6 @@ DECL_HANDLER(create_named_pipe) { reply->handle = alloc_handle( current->process, server, req->access, objattr->attributes ); server->pipe->instances++; - if (sd) default_set_sd( &server->pipe_end.obj, sd, OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION | - SACL_SECURITY_INFORMATION ); release_object( server ); }