aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2018-04-27 14:14:08 -0700
committerGarrett D'Amore <garrett@damore.org>2018-04-30 11:33:10 -0700
commit2b0d31553e542c130e2595ff9a3ac9756a2c1619 (patch)
treef9ef54cfe7c4336e4765091445aa4d86a53645b5 /tests
parent88c7a328dfaca4a9fce13ebbc4bce6b24d048c3e (diff)
downloadnng-2b0d31553e542c130e2595ff9a3ac9756a2c1619.tar.gz
nng-2b0d31553e542c130e2595ff9a3ac9756a2c1619.tar.bz2
nng-2b0d31553e542c130e2595ff9a3ac9756a2c1619.zip
fixes #6 Security attributes support
fixes #382 Permissions support for IPC on POSIX This adds support for permission management on Windows and POSIX systems. There are two different properties, and they are very different. Tests and documentation are included.
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/ipcperms.c114
-rw-r--r--tests/ipcwinsec.c200
3 files changed, 316 insertions, 0 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 6db01e82..3cfc89fa 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -136,6 +136,8 @@ add_nng_test(httpserver 30 NNG_SUPP_HTTP)
add_nng_test(idhash 5 ON)
add_nng_test(inproc 5 NNG_TRANSPORT_INPROC)
add_nng_test(ipc 5 NNG_TRANSPORT_IPC)
+add_nng_test(ipcperms 5 NNG_TRANSPORT_IPC)
+add_nng_test(ipcwinsec 5 NNG_TRANSPORT_IPC)
add_nng_test(list 5 ON)
add_nng_test(message 5 ON)
add_nng_test(multistress 60 ON)
diff --git a/tests/ipcperms.c b/tests/ipcperms.c
new file mode 100644
index 00000000..84801efd
--- /dev/null
+++ b/tests/ipcperms.c
@@ -0,0 +1,114 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#include "convey.h"
+#include "trantest.h"
+
+#include "nng.h"
+
+#include "protocol/reqrep0/rep.h"
+#include "protocol/reqrep0/req.h"
+#include "transport/ipc/ipc.h"
+
+#include "stubs.h"
+
+#ifndef _WIN32
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <unistd.h>
+#endif
+
+#define ADDR "/tmp/ipc_perms_test"
+
+// Inproc tests.
+
+#ifdef _WIN32
+TestMain("IPC Permissions", {
+
+ atexit(nng_fini);
+ Convey("Given a socket and an IPC listener", {
+ nng_socket s;
+ nng_listener l;
+
+ So(nng_rep0_open(&s) == 0);
+ Reset({ nng_close(s); });
+ So(nng_listener_create(&l, s, "ipc://" ADDR) == 0);
+ Convey("We cannot set perms on Windows", {
+ So(nng_listener_setopt_int(l, NNG_OPT_IPC_PERMISSIONS,
+ 0444) == NNG_ENOTSUP);
+ });
+ });
+})
+#else
+TestMain("IPC Permissions", {
+ atexit(nng_fini);
+
+ Convey("Given a socket and an IPC listener", {
+ nng_socket s;
+ nng_listener l;
+
+ So(nng_rep0_open(&s) == 0);
+ Reset({
+ nng_close(s);
+ unlink(ADDR);
+ });
+ So(nng_listener_create(&l, s, "ipc://" ADDR) == 0);
+ Convey("We can set perms on POSIX", {
+ struct stat st;
+ So(nng_listener_setopt_int(
+ l, NNG_OPT_IPC_PERMISSIONS, 0444) == 0);
+ So(nng_listener_start(l, 0) == 0);
+ So(stat(ADDR, &st) == 0);
+ So((st.st_mode & 0777) == 0444);
+
+ Convey("And permissions are honored", {
+ struct sockaddr_un sa;
+ int cfd;
+
+ if (geteuid() == 0) {
+ Skip("Running as root");
+ }
+ strcpy(sa.sun_path, ADDR);
+ sa.sun_family = AF_UNIX;
+ So((cfd = socket(AF_UNIX, SOCK_STREAM, 0)) >=
+ 0);
+ Reset({ close(cfd); });
+ So(connect(cfd, (void *) &sa, sizeof(sa)) < 0);
+ So(errno == EACCES);
+ });
+ });
+
+ Convey("We cannot set perms after it is started", {
+ So(nng_listener_start(l, 0) == 0);
+ So(nng_listener_setopt_int(
+ l, NNG_OPT_IPC_PERMISSIONS, 0444) == NNG_EBUSY);
+ });
+
+ Convey("We cannot set bogus permissions", {
+ So(nng_listener_setopt_int(l, NNG_OPT_IPC_PERMISSIONS,
+ S_IFREG) == NNG_EINVAL);
+ });
+ });
+
+ Convey("We cannot set perms on an IPC dialer", {
+ nng_socket s;
+ nng_dialer d;
+
+ So(nng_rep0_open(&s) == 0);
+ Reset({ nng_close(s); });
+ So(nng_dialer_create(&d, s, "ipc://" ADDR) == 0);
+ So(nng_dialer_setopt_int(d, NNG_OPT_IPC_PERMISSIONS, 0444) ==
+ NNG_ENOTSUP);
+ });
+})
+#endif \ No newline at end of file
diff --git a/tests/ipcwinsec.c b/tests/ipcwinsec.c
new file mode 100644
index 00000000..80ec163c
--- /dev/null
+++ b/tests/ipcwinsec.c
@@ -0,0 +1,200 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#include "convey.h"
+#include "trantest.h"
+
+#include "nng.h"
+
+#include "protocol/reqrep0/rep.h"
+#include "protocol/reqrep0/req.h"
+#include "transport/ipc/ipc.h"
+
+#include "stubs.h"
+
+#define ADDR "/tmp/ipc_winsec_test"
+
+// Inproc tests.
+
+#ifndef _WIN32
+TestMain("IPC Security Descriptor", {
+
+ atexit(nng_fini);
+ Convey("Given a socket and an IPC listener", {
+ nng_socket s;
+ nng_listener l;
+ int x;
+
+ So(nng_rep0_open(&s) == 0);
+ Reset({ nng_close(s); });
+ So(nng_listener_create(&l, s, "ipc://" ADDR) == 0);
+ Convey("We cannot set Windows SECURITY_DESCRIPTOR on POSIX", {
+ So(nng_listener_setopt_ptr(l,
+ NNG_OPT_IPC_SECURITY_DESCRIPTOR,
+ &x) == NNG_ENOTSUP);
+ });
+ });
+})
+#else
+
+#include <assert.h>
+
+// Microsoft prefers CamelCase header names, but relies on case insensitive
+// file systems to make that work. The rest of the world (min-gw64 included)
+// uses case sensitive names and lowercase.
+
+#include <accctrl.h>
+
+#include <sddl.h>
+
+#include <aclapi.h>
+
+SECURITY_DESCRIPTOR *
+sdescAuthUsers(PSID sid, PACL *aclp)
+{
+ SECURITY_DESCRIPTOR *sdesc;
+ EXPLICIT_ACCESS xa;
+ ACL * acl;
+
+ sdesc = calloc(SECURITY_DESCRIPTOR_MIN_LENGTH, 1);
+ assert(sdesc != NULL);
+
+ InitializeSecurityDescriptor(sdesc, SECURITY_DESCRIPTOR_REVISION);
+
+ xa.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
+ xa.grfAccessMode = SET_ACCESS;
+ xa.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
+ xa.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ xa.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+ xa.Trustee.ptstrName = (LPSTR) sid;
+
+ SetEntriesInAcl(1, &xa, NULL, &acl);
+ *aclp = acl;
+
+ SetSecurityDescriptorDacl(sdesc, TRUE, acl, FALSE);
+ return (sdesc);
+}
+
+TestMain("IPC Security Descriptor", {
+ atexit(nng_fini);
+
+ Convey("Given a socket and an IPC listener", {
+ nng_socket s;
+ nng_listener l;
+
+ So(nng_rep0_open(&s) == 0);
+ Reset({ nng_close(s); });
+
+ So(nng_listener_create(&l, s, "ipc://" ADDR) == 0);
+ Convey("We can set security descriptor on Windows", {
+
+ SECURITY_DESCRIPTOR *sdesc;
+ SID users;
+ DWORD size;
+ PACL acl = NULL;
+
+ size = sizeof(users);
+ CreateWellKnownSid(
+ WinAuthenticatedUserSid, NULL, &users, &size);
+
+ sdesc = sdescAuthUsers(&users, &acl);
+ assert(sdesc != NULL);
+ assert(acl != NULL);
+ Reset({
+ free(sdesc);
+ LocalFree(acl);
+ });
+
+ So(nng_listener_setopt_ptr(l,
+ NNG_OPT_IPC_SECURITY_DESCRIPTOR, sdesc) == 0);
+ So(nng_listener_start(l, 0) == 0);
+
+ Convey("And they are effective", {
+ PACL dacl;
+ PSECURITY_DESCRIPTOR sd;
+ PACE_HEADER ace;
+ PSID asid;
+ PACCESS_ALLOWED_ACE allowed;
+
+ HANDLE ph = CreateFileA("\\\\.\\\\pipe\\" ADDR,
+ READ_CONTROL, 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED, NULL);
+
+ So(ph != INVALID_HANDLE_VALUE);
+ Reset({ CloseHandle(ph); });
+
+ So(GetSecurityInfo(ph, SE_KERNEL_OBJECT,
+ DACL_SECURITY_INFORMATION, NULL, NULL,
+ &dacl, NULL, &sd) == ERROR_SUCCESS);
+ Reset({ LocalFree(sd); });
+
+ So(dacl->AceCount == 1);
+ So(GetAce(dacl, 0, &ace) == TRUE);
+ allowed = (PACCESS_ALLOWED_ACE) ace;
+ asid = (PSID) &allowed->SidStart;
+ So(IsValidSid(asid));
+ So(EqualSid(asid, &users) == TRUE);
+ });
+ });
+
+ Convey("We cannot set security descriptor after started", {
+
+ SECURITY_DESCRIPTOR *sdesc;
+ SID users;
+ DWORD size;
+ PACL acl = NULL;
+
+ size = sizeof(users);
+ CreateWellKnownSid(
+ WinAuthenticatedUserSid, NULL, &users, &size);
+
+ sdesc = sdescAuthUsers(&users, &acl);
+ assert(sdesc != NULL);
+ assert(acl != NULL);
+ Reset({
+ free(sdesc);
+ LocalFree(acl);
+ });
+
+ So(nng_listener_start(l, 0) == 0);
+ So(nng_listener_setopt_ptr(l,
+ NNG_OPT_IPC_SECURITY_DESCRIPTOR,
+ sdesc) == NNG_EBUSY);
+ });
+
+ Convey("We cannot set bogus security", {
+ So(nng_listener_setopt_ptr(l,
+ NNG_OPT_IPC_SECURITY_DESCRIPTOR,
+ NULL) == NNG_EINVAL);
+ });
+ });
+
+ Convey("We cannot set security descriptor on an IPC dialer", {
+ nng_socket s;
+ nng_dialer d;
+ SECURITY_DESCRIPTOR *sdesc;
+
+ sdesc = calloc(SECURITY_DESCRIPTOR_MIN_LENGTH, 1);
+ assert(sdesc != NULL);
+ InitializeSecurityDescriptor(
+ sdesc, SECURITY_DESCRIPTOR_REVISION);
+
+ So(nng_rep0_open(&s) == 0);
+ Reset({
+ nng_close(s);
+ free(sdesc);
+ });
+
+ So(nng_dialer_create(&d, s, "ipc://" ADDR) == 0);
+ So(nng_dialer_setopt_ptr(d, NNG_OPT_IPC_SECURITY_DESCRIPTOR,
+ sdesc) == NNG_ENOTSUP);
+ });
+})
+#endif \ No newline at end of file