Module: wine Branch: master Commit: 9034e694a36df25fadd654c29a13bdd1444bbd6a URL: http://source.winehq.org/git/wine.git/?a=commit;h=9034e694a36df25fadd654c29a...
Author: Bernhard Loos bernhardloos@googlemail.com Date: Thu Sep 29 11:20:50 2011 +0200
server: Correctly implement permission checking for named pipes.
---
dlls/ntdll/tests/pipe.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ server/named_pipe.c | 10 +++++++++ 2 files changed, 62 insertions(+), 0 deletions(-)
diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c index 26c38b0..e7c49b8 100644 --- a/dlls/ntdll/tests/pipe.c +++ b/dlls/ntdll/tests/pipe.c @@ -172,6 +172,55 @@ static void test_create_invalid(void) CloseHandle(handle); }
+static void test_create(void) +{ + HANDLE hserver; + NTSTATUS res; + int j, k; + FILE_PIPE_LOCAL_INFORMATION info; + IO_STATUS_BLOCK iosb; + + static const DWORD access[] = { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE}; + static const DWORD sharing[] = { FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE }; + + for (j = 0; j < sizeof(sharing) / sizeof(DWORD); j++) { + for (k = 0; k < sizeof(access) / sizeof(DWORD); k++) { + HANDLE hclient; + BOOL should_succeed = TRUE; + + res = create_pipe(&hserver, sharing[j], FILE_SYNCHRONOUS_IO_NONALERT); + if (res) { + ok(0, "NtCreateNamedPipeFile returned %x, sharing: %x\n", res, sharing[j]); + continue; + } + + res = pNtQueryInformationFile(hserver, &iosb, &info, sizeof(info), (FILE_INFORMATION_CLASS)24); + ok(!res, "NtQueryInformationFile for server returned %x, sharing: %x\n", res, sharing[j]); + + hclient = CreateFileW(testpipe, access[k], 0, 0, OPEN_EXISTING, 0, 0); + if (hclient != INVALID_HANDLE_VALUE) { + res = pNtQueryInformationFile(hclient, &iosb, &info, sizeof(info), (FILE_INFORMATION_CLASS)24); + ok(!res, "NtQueryInformationFile for client returned %x, access: %x, sharing: %x\n", + res, access[k], sharing[j]); + CloseHandle(hclient); + } + + if (access[k] & GENERIC_WRITE) + should_succeed &= !!(sharing[j] & FILE_SHARE_WRITE); + if (access[k] & GENERIC_READ) + should_succeed &= !!(sharing[j] & FILE_SHARE_READ); + + if (should_succeed) + ok(hclient != INVALID_HANDLE_VALUE, "CreateFile failed for sharing %x, access: %x, GetLastError: %d\n", + sharing[j], access[k], GetLastError()); + else + ok(hclient == INVALID_HANDLE_VALUE, "CreateFile succeded for sharing %x, access: %x\n", sharing[j], access[k]); + + CloseHandle(hserver); + } + } +} + static BOOL ioapc_called; static void CALLBACK ioapc(void *arg, PIO_STATUS_BLOCK io, ULONG reserved) { @@ -419,6 +468,9 @@ START_TEST(pipe) trace("starting invalid create tests\n"); test_create_invalid();
+ trace("starting create tests\n"); + test_create(); + trace("starting overlapped tests\n"); test_overlapped();
diff --git a/server/named_pipe.c b/server/named_pipe.c index 750f3bc..d6c1383 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -804,6 +804,7 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc struct named_pipe *pipe = (struct named_pipe *)obj; struct pipe_server *server; struct pipe_client *client; + unsigned int pipe_sharing; int fds[2];
if (!(server = find_available_server( pipe ))) @@ -812,6 +813,15 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc return NULL; }
+ pipe_sharing = server->pipe->sharing; + if (((access & GENERIC_READ) && !(pipe_sharing & FILE_SHARE_READ)) || + ((access & GENERIC_WRITE) && !(pipe_sharing & FILE_SHARE_WRITE))) + { + set_error( STATUS_ACCESS_DENIED ); + release_object( server ); + return NULL; + } + if ((client = create_pipe_client( options ))) { if (!socketpair( PF_UNIX, SOCK_STREAM, 0, fds ))