Commit 1ce2201e authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

server: Share security descriptor among all pipe instances.

Based on patch by Jonathan Doron. Signed-off-by: 's avatarJacek Caban <jacek@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 1356afed
...@@ -1209,7 +1209,7 @@ static void test_file_info(void) ...@@ -1209,7 +1209,7 @@ static void test_file_info(void)
CloseHandle( client ); CloseHandle( client );
} }
static PSECURITY_DESCRIPTOR get_security_descriptor(HANDLE handle) static PSECURITY_DESCRIPTOR get_security_descriptor(HANDLE handle, BOOL todo)
{ {
SECURITY_DESCRIPTOR *sec_desc; SECURITY_DESCRIPTOR *sec_desc;
ULONG length = 0; ULONG length = 0;
...@@ -1217,8 +1217,10 @@ static PSECURITY_DESCRIPTOR get_security_descriptor(HANDLE handle) ...@@ -1217,8 +1217,10 @@ static PSECURITY_DESCRIPTOR get_security_descriptor(HANDLE handle)
status = NtQuerySecurityObject(handle, GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, status = NtQuerySecurityObject(handle, GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
NULL, 0, &length); NULL, 0, &length);
todo_wine_if(todo && status == STATUS_PIPE_DISCONNECTED)
ok(status == STATUS_BUFFER_TOO_SMALL, ok(status == STATUS_BUFFER_TOO_SMALL,
"Failed to query object security descriptor length: %08x\n", status); "Failed to query object security descriptor length: %08x\n", status);
if(status != STATUS_BUFFER_TOO_SMALL) return NULL;
ok(length != 0, "length = 0\n"); ok(length != 0, "length = 0\n");
sec_desc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, length); 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 ...@@ -1295,7 +1297,8 @@ static void _test_group(unsigned line, HANDLE handle, SID *expected_sid, BOOL to
PSID group_sid; PSID group_sid;
NTSTATUS status; 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); status = RtlGetGroupSecurityDescriptor(sec_desc, &group_sid, &defaulted);
ok_(__FILE__,line)(status == STATUS_SUCCESS, ok_(__FILE__,line)(status == STATUS_SUCCESS,
...@@ -1351,13 +1354,13 @@ static void test_security_info(void) ...@@ -1351,13 +1354,13 @@ static void test_security_info(void)
ok(status == STATUS_SUCCESS, "NtSetSecurityObject failed: %08x\n", status); ok(status == STATUS_SUCCESS, "NtSetSecurityObject failed: %08x\n", status);
test_group(server, world_sid, FALSE); 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 */ /* new instance of pipe server has the same security descriptor */
server2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 10, server2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 10,
0x20000, 0x20000, 0, NULL); 0x20000, 0x20000, 0, NULL);
ok(server2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError()); 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 */ /* set client group, server changes as well */
ret = SetSecurityDescriptorGroup(sec_desc, local_sid, FALSE); ret = SetSecurityDescriptorGroup(sec_desc, local_sid, FALSE);
...@@ -1366,8 +1369,8 @@ static void test_security_info(void) ...@@ -1366,8 +1369,8 @@ static void test_security_info(void)
ok(status == STATUS_SUCCESS, "NtSetSecurityObject failed: %08x\n", status); ok(status == STATUS_SUCCESS, "NtSetSecurityObject failed: %08x\n", status);
test_group(server, local_sid, FALSE); test_group(server, local_sid, FALSE);
test_group(client, local_sid, TRUE); test_group(client, local_sid, FALSE);
test_group(server2, local_sid, TRUE); test_group(server2, local_sid, FALSE);
CloseHandle(server); CloseHandle(server);
/* SD is preserved after closing server object */ /* SD is preserved after closing server object */
...@@ -1378,19 +1381,17 @@ static void test_security_info(void) ...@@ -1378,19 +1381,17 @@ static void test_security_info(void)
client = CreateFileA(PIPENAME, GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL); client = CreateFileA(PIPENAME, GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL);
ok(client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); 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); ret = DisconnectNamedPipe(server);
ok(ret, "DisconnectNamedPipe failed: %u\n", GetLastError()); ok(ret, "DisconnectNamedPipe failed: %u\n", GetLastError());
/* disconnected server may be queried for security info, but client does not */ /* 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, status = NtQuerySecurityObject(client, GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
NULL, 0, &length); NULL, 0, &length);
todo_wine
ok(status == STATUS_PIPE_DISCONNECTED, "NtQuerySecurityObject returned %08x\n", status); ok(status == STATUS_PIPE_DISCONNECTED, "NtQuerySecurityObject returned %08x\n", status);
status = NtSetSecurityObject(client, GROUP_SECURITY_INFORMATION, sec_desc); status = NtSetSecurityObject(client, GROUP_SECURITY_INFORMATION, sec_desc);
todo_wine
ok(status == STATUS_PIPE_DISCONNECTED, "NtQuerySecurityObject returned %08x\n", status); ok(status == STATUS_PIPE_DISCONNECTED, "NtQuerySecurityObject returned %08x\n", status);
/* attempting to create another pipe instance with specified sd fails */ /* attempting to create another pipe instance with specified sd fails */
......
...@@ -150,6 +150,9 @@ static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue ); ...@@ -150,6 +150,9 @@ static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue );
/* server end functions */ /* server end functions */
static void pipe_server_dump( struct object *obj, int verbose ); 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 void pipe_server_destroy( struct object *obj);
static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); 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 ); 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 = ...@@ -166,8 +169,8 @@ static const struct object_ops pipe_server_ops =
no_signal, /* signal */ no_signal, /* signal */
pipe_end_get_fd, /* get_fd */ pipe_end_get_fd, /* get_fd */
default_fd_map_access, /* map_access */ default_fd_map_access, /* map_access */
default_get_sd, /* get_sd */ pipe_server_get_sd, /* get_sd */
default_set_sd, /* set_sd */ pipe_server_set_sd, /* set_sd */
no_lookup_name, /* lookup_name */ no_lookup_name, /* lookup_name */
no_link_name, /* link_name */ no_link_name, /* link_name */
NULL, /* unlink_name */ NULL, /* unlink_name */
...@@ -193,6 +196,9 @@ static const struct fd_ops pipe_server_fd_ops = ...@@ -193,6 +196,9 @@ static const struct fd_ops pipe_server_fd_ops =
/* client end functions */ /* client end functions */
static void pipe_client_dump( struct object *obj, int verbose ); 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 void pipe_client_destroy( struct object *obj );
static int pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); 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 ); 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 = ...@@ -209,8 +215,8 @@ static const struct object_ops pipe_client_ops =
no_signal, /* signal */ no_signal, /* signal */
pipe_end_get_fd, /* get_fd */ pipe_end_get_fd, /* get_fd */
default_fd_map_access, /* map_access */ default_fd_map_access, /* map_access */
default_get_sd, /* get_sd */ pipe_client_get_sd, /* get_sd */
default_set_sd, /* set_sd */ pipe_client_set_sd, /* set_sd */
no_lookup_name, /* lookup_name */ no_lookup_name, /* lookup_name */
no_link_name, /* link_name */ no_link_name, /* link_name */
NULL, /* unlink_name */ NULL, /* unlink_name */
...@@ -583,6 +589,36 @@ static void pipe_end_get_file_info( struct fd *fd, struct named_pipe *pipe, unsi ...@@ -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 ) static void pipe_server_get_file_info( struct fd *fd, unsigned int info_class )
{ {
struct pipe_server *server = get_fd_user( fd ); struct pipe_server *server = get_fd_user( fd );
...@@ -1170,6 +1206,10 @@ DECL_HANDLER(create_named_pipe) ...@@ -1170,6 +1206,10 @@ DECL_HANDLER(create_named_pipe)
pipe->timeout = req->timeout; pipe->timeout = req->timeout;
pipe->flags = req->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE; pipe->flags = req->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE;
pipe->sharing = req->sharing; 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 else
{ {
...@@ -1193,10 +1233,6 @@ DECL_HANDLER(create_named_pipe) ...@@ -1193,10 +1233,6 @@ DECL_HANDLER(create_named_pipe)
{ {
reply->handle = alloc_handle( current->process, server, req->access, objattr->attributes ); reply->handle = alloc_handle( current->process, server, req->access, objattr->attributes );
server->pipe->instances++; 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 ); release_object( server );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment