aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/man/nng_ipc_options.5.adoc2
-rw-r--r--docs/ref/migrate/nng1.md11
-rw-r--r--docs/ref/tran/ipc.md25
-rw-r--r--docs/ref/xref.md1
-rw-r--r--include/nng/nng.h11
-rw-r--r--src/core/listener.c9
-rw-r--r--src/core/listener.h1
-rw-r--r--src/core/stream.c10
-rw-r--r--src/core/stream.h7
-rw-r--r--src/nng.c13
-rw-r--r--src/platform/posix/posix_ipcwinsec_test.c7
-rw-r--r--src/platform/windows/win_ipc_sec_test.c40
-rw-r--r--src/platform/windows/win_ipclisten.c11
-rw-r--r--src/sp/transport.h3
-rw-r--r--src/sp/transport/ipc/ipc.c25
-rw-r--r--src/sp/transport/ipc/ipc_test.c21
16 files changed, 122 insertions, 75 deletions
diff --git a/docs/man/nng_ipc_options.5.adoc b/docs/man/nng_ipc_options.5.adoc
index 516fbe80..79a302e8 100644
--- a/docs/man/nng_ipc_options.5.adoc
+++ b/docs/man/nng_ipc_options.5.adoc
@@ -25,7 +25,6 @@ nng_ipc_options - IPC-specific options
#define NNG_OPT_IPC_PEER_UID "ipc:peer-uid"
#define NNG_OPT_IPC_PEER_ZONEID "ipc:peer-zoneid"
#define NNG_OPT_IPC_PERMISSIONS "ipc:permissions"
-#define NNG_OPT_IPC_SECURITY_DESCRIPTOR "ipc:security-descriptor"
----
== DESCRIPTION
@@ -75,6 +74,7 @@ permission.
[[NNG_OPT_IPC_SECURITY_DESCRIPTOR]]((`NNG_OPT_IPC_SECURITY_DESCRIPTOR`))::
(`PSECURITY_DESCRIPTOR`)
+TODO: REWRITE THIS TO REFLECT new nng_listener_get_security_security_descriptor.
This write-only option may be used on listeners on Windows platforms to
configure the `SECURITY_DESCRIPTOR` that is used when creating the underlying
named pipe.
diff --git a/docs/ref/migrate/nng1.md b/docs/ref/migrate/nng1.md
index eac60379..152c464b 100644
--- a/docs/ref/migrate/nng1.md
+++ b/docs/ref/migrate/nng1.md
@@ -209,4 +209,15 @@ accessors functions are provided:
- `u_host` is removed - use [`nng_url_hostname`] and [`nng_url_port`] to construct if needed
- `u_rawurl` is removed - a "cooked" URL can be obtained from the new [`nng_url_sprintf`] function.
+## Security Descriptors (Windows Only)
+
+The `NNG_OPT_IPC_SECURITY_DESCRIPTOR` option is removed, and replaced
+with the functions [`nng_listener_get_security_descriptor`] and
+[`nng_stream_listener_get_security_descriptor`].
+
+Security descriptor support is only relevant to Windows,
+and is presently only supported for IPC when Named Pipes are used.
+Planned future changes to switch to UNIX domain sockets may eliminate
+support for security descriptors altogether in NNG.
+
{{#include ../xref.md}}
diff --git a/docs/ref/tran/ipc.md b/docs/ref/tran/ipc.md
index c186cadd..ec0a2700 100644
--- a/docs/ref/tran/ipc.md
+++ b/docs/ref/tran/ipc.md
@@ -67,9 +67,9 @@ prevent unauthorized access, or that checks against the peer credentials are mad
### Socket Address
-When using an [`nng_sockaddr`][sockaddr] structure,
-the actual structure is of type [`nng_sockaddr_ipc`][sockaddr_ipc],
-except for abstract sockets, which use [`nng_sockaddr_abstract`][sockaddr_abstract].
+When using an [`nng_sockaddr`] structure,
+the actual structure is of type [`nng_sockaddr_ipc`],
+except for abstract sockets, which use [`nng_sockaddr_abstract`].
### Transport Options
@@ -77,7 +77,6 @@ The following transport options are supported by this transport,
where supported by the underlying platform.
- [`NNG_OPT_IPC_PERMISSIONS`][NNG_OPT_IPC_PERMISSIONS]
-- [`NNG_OPT_IPC_SECURITY_DESCRIPTOR`][NNG_OPT_IPC_SECURITY_DESCRIPTOR]
- [`NNG_OPT_LOCADDR`][NNG_OPT_LOCADDR]
- [`NNG_OPT_REMADDR`][NNG_OPT_REMADDR]
- [`NNG_OPT_PEER_GID`][NNG_OPT_PEER_GID]
@@ -85,14 +84,10 @@ where supported by the underlying platform.
- [`NNG_OPT_PEER_UID`][NNG_OPT_PEER_UID]
- [`NNG_OPT_PEER_ZONEID`][NNG_OPT_PEER_ZONEID]
-[NNG_OPT_IPC_PERMISSIONS]: TODO.md
-[NNG_OPT_IPC_SECURITY_DESCRIPTOR]: TODO.md
-[NNG_OPT_LOCADDR]: TODO.md
-[NNG_OPT_REMADDR]: TODO.md
-[NNG_OPT_PEER_GID]: TODO.md
-[NNG_OPT_PEER_PID]: TODO.md
-[NNG_OPT_PEER_UID]: TODO.md
-[NNG_OPT_PEER_ZONEID]: TODO.md
-[sockaddr]: TODO.md
-[sockaddr_ipc]: TODO.md
-[sockaddr_abstract]: TODO.md
+### Other Configuration Parameters
+
+On Windows systems, the security descriptor for the listener,
+which can be used to control access, can be set using the function
+[`nng_listener_set_security_descriptor`].
+
+{{#include ../xref.md}}
diff --git a/docs/ref/xref.md b/docs/ref/xref.md
index 5e030bed..d5b7c9f0 100644
--- a/docs/ref/xref.md
+++ b/docs/ref/xref.md
@@ -100,6 +100,7 @@
[`nng_dialer_get_url`]: /TODO.md
[`nng_tls_config`]: /TODO.md
[`nng_tls_config_own_cert`]: /TODO.md
+[`nng_listener_set_security_descriptor`]: /TODO.md
<!-- Macros -->
diff --git a/include/nng/nng.h b/include/nng/nng.h
index ecb45c80..3d762ee6 100644
--- a/include/nng/nng.h
+++ b/include/nng/nng.h
@@ -378,6 +378,7 @@ NNG_DECL int nng_listener_set_ms(nng_listener, const char *, nng_duration);
NNG_DECL int nng_listener_set_addr(
nng_listener, const char *, const nng_sockaddr *);
NNG_DECL int nng_listener_set_tls(nng_listener, nng_tls_config *);
+NNG_DECL int nng_listener_set_security_descriptor(nng_listener, void *);
NNG_DECL int nng_listener_get_url(nng_listener id, const nng_url **urlp);
NNG_DECL int nng_listener_get_bool(nng_listener, const char *, bool *);
@@ -795,11 +796,6 @@ NNG_DECL nng_listener nng_pipe_listener(nng_pipe);
// IPC options. These will largely vary depending on the platform,
// as POSIX systems have very different options than Windows.
-// Security Descriptor. This option may only be set on listeners
-// on the Windows platform, where the object is a pointer to a
-// a Windows SECURITY_DESCRIPTOR.
-#define NNG_OPT_IPC_SECURITY_DESCRIPTOR "ipc:security-descriptor"
-
// Permissions bits. This option is only valid for listeners on
// POSIX platforms and others that honor UNIX style permission bits.
// Note that some platforms may not honor the permissions here, although
@@ -1239,6 +1235,11 @@ NNG_DECL int nng_stream_listener_get_tls(
NNG_DECL int nng_stream_listener_set_tls(
nng_stream_listener *, nng_tls_config *);
+// Security Descriptor only valid for IPC streams on Windows
+// Parameter is a PSECURITY_DESCRIPTOR.
+NNG_DECL int nng_stream_listener_set_security_descriptor(
+ nng_stream_listener *, void *);
+
// UDP operations. These are provided for convenience,
// and should be considered somewhat experimental.
diff --git a/src/core/listener.c b/src/core/listener.c
index 76d9848e..9107e3a4 100644
--- a/src/core/listener.c
+++ b/src/core/listener.c
@@ -532,6 +532,15 @@ nni_listener_set_tls(nni_listener *l, nng_tls_config *cfg)
return (l->l_ops.l_set_tls(l->l_data, cfg));
}
+int
+nni_listener_set_security_descriptor(nni_listener *l, void *desc)
+{
+ if (l->l_ops.l_set_security_descriptor == NULL) {
+ return (NNG_ENOTSUP);
+ }
+ return (l->l_ops.l_set_security_descriptor(l->l_data, desc));
+}
+
nng_url *
nni_listener_url(nni_listener *l)
{
diff --git a/src/core/listener.h b/src/core/listener.h
index eec98f2e..5902d4bc 100644
--- a/src/core/listener.h
+++ b/src/core/listener.h
@@ -29,6 +29,7 @@ extern int nni_listener_getopt(
nni_listener *, const char *, void *, size_t *, nni_type);
extern int nni_listener_get_tls(nni_listener *, nng_tls_config **);
extern int nni_listener_set_tls(nni_listener *, nng_tls_config *);
+extern int nni_listener_set_security_descriptor(nni_listener *, void *);
extern nng_url *nni_listener_url(nni_listener *);
extern void nni_listener_add_stat(nni_listener *, nni_stat_item *);
extern void nni_listener_bump_error(nni_listener *, int);
diff --git a/src/core/stream.c b/src/core/stream.c
index d900329a..e46eb59a 100644
--- a/src/core/stream.c
+++ b/src/core/stream.c
@@ -280,6 +280,16 @@ nni_stream_listener_set_tls(nng_stream_listener *l, nng_tls_config *cfg)
}
int
+nng_stream_listener_set_security_descriptor(
+ nng_stream_listener *l, void *pdesc)
+{
+ if (l->sl_set_security_descriptor == NULL) {
+ return (NNG_ENOTSUP);
+ }
+ return (l->sl_set_security_descriptor(l, pdesc));
+}
+
+int
nng_stream_listener_alloc_url(nng_stream_listener **lp, const nng_url *url)
{
for (int i = 0; stream_drivers[i].scheme != NULL; i++) {
diff --git a/src/core/stream.h b/src/core/stream.h
index 0fa79a47..9ea65834 100644
--- a/src/core/stream.h
+++ b/src/core/stream.h
@@ -32,8 +32,10 @@ extern int nni_stream_listener_get(
nng_stream_listener *, const char *, void *, size_t *, nni_type);
extern int nni_stream_listener_set(
nng_stream_listener *, const char *, const void *, size_t, nni_type);
-extern int nni_stream_listener_set_tls(nng_stream_listener *, nng_tls_config *);
-extern int nni_stream_listener_get_tls(nng_stream_listener *, nng_tls_config **);
+extern int nni_stream_listener_set_tls(
+ nng_stream_listener *, nng_tls_config *);
+extern int nni_stream_listener_get_tls(
+ nng_stream_listener *, nng_tls_config **);
// This is the common implementation of a connected byte stream. It should be
// the first element of any implementation. Applications are not permitted to
@@ -69,6 +71,7 @@ struct nng_stream_listener {
int (*sl_set)(void *, const char *, const void *, size_t, nni_type);
int (*sl_get_tls)(void *, nng_tls_config **);
int (*sl_set_tls)(void *, nng_tls_config *);
+ int (*sl_set_security_descriptor)(void *, void *);
};
#endif // CORE_STREAM_H
diff --git a/src/nng.c b/src/nng.c
index 70fbbe19..872f15b9 100644
--- a/src/nng.c
+++ b/src/nng.c
@@ -1024,6 +1024,19 @@ nng_listener_set_tls(nng_listener id, nng_tls_config *cfg)
}
int
+nng_listener_set_security_descriptor(nng_listener id, void *cfg)
+{
+ int rv;
+ nni_listener *l;
+ if ((rv = nni_listener_find(&l, id.id)) != 0) {
+ return (rv);
+ }
+ rv = nni_listener_set_security_descriptor(l, cfg);
+ nni_listener_rele(l);
+ return (rv);
+}
+
+int
nng_dialer_get_url(nng_dialer id, const nng_url **urlp)
{
int rv;
diff --git a/src/platform/posix/posix_ipcwinsec_test.c b/src/platform/posix/posix_ipcwinsec_test.c
index 934eeea9..b79e887c 100644
--- a/src/platform/posix/posix_ipcwinsec_test.c
+++ b/src/platform/posix/posix_ipcwinsec_test.c
@@ -1,5 +1,5 @@
//
-// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2024 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
@@ -19,9 +19,8 @@ test_ipc_win_sec(void)
nuts_scratch_addr("ipc", sizeof(address), address);
NUTS_PASS(nng_stream_listener_alloc(&l, address));
- NUTS_FAIL(nng_stream_listener_set_ptr(
- l, NNG_OPT_IPC_SECURITY_DESCRIPTOR, &x),
- NNG_ENOTSUP);
+ NUTS_FAIL(
+ nng_stream_listener_set_security_descriptor(l, &x), NNG_ENOTSUP);
nng_stream_listener_free(l);
}
diff --git a/src/platform/windows/win_ipc_sec_test.c b/src/platform/windows/win_ipc_sec_test.c
index ab65533b..8b76770e 100644
--- a/src/platform/windows/win_ipc_sec_test.c
+++ b/src/platform/windows/win_ipc_sec_test.c
@@ -1,5 +1,5 @@
//
-// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2024 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
@@ -72,12 +72,12 @@ test_ipc_security_descriptor(void)
NUTS_ASSERT(acl != NULL);
NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL));
- NUTS_PASS(nng_stream_listener_set_ptr(
- l, NNG_OPT_IPC_SECURITY_DESCRIPTOR, sd));
+ NUTS_PASS(nng_stream_listener_set_security_descriptor(l, sd));
NUTS_PASS(nng_stream_listener_listen(l));
nng_stream_listener_accept(l, aio);
- (void) snprintf(pipe, sizeof(pipe), "\\\\.\\pipe\\%s", address+strlen("ipc://"));
+ (void) snprintf(
+ pipe, sizeof(pipe), "\\\\.\\pipe\\%s", address + strlen("ipc://"));
HANDLE ph = CreateFileA(pipe, READ_CONTROL, 0, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
@@ -132,9 +132,8 @@ test_ipc_security_descriptor_busy(void)
NUTS_PASS(nng_stream_listener_listen(l));
- NUTS_FAIL(nng_stream_listener_set_ptr(
- l, NNG_OPT_IPC_SECURITY_DESCRIPTOR, sd),
- NNG_EBUSY);
+ NUTS_FAIL(
+ nng_stream_listener_set_security_descriptor(l, sd), NNG_EBUSY);
free(sd);
nng_stream_listener_close(l);
@@ -151,40 +150,17 @@ test_ipc_security_descriptor_bogus(void)
NUTS_PASS(nng_stream_listener_alloc(&l, address));
- NUTS_FAIL(nng_stream_listener_set_ptr(
- l, NNG_OPT_IPC_SECURITY_DESCRIPTOR, NULL),
- NNG_EINVAL);
+ NUTS_FAIL(
+ nng_stream_listener_set_security_descriptor(l, NULL), NNG_EINVAL);
nng_stream_listener_close(l);
nng_stream_listener_free(l);
}
-void
-test_ipc_security_descriptor_dialer(void)
-{
- nng_stream_dialer *d;
- char address[64];
- SECURITY_DESCRIPTOR *sdesc;
-
- nuts_scratch_addr("ipc", sizeof(address), address);
- NUTS_PASS(nng_stream_dialer_alloc(&d, address));
-
- sdesc = calloc(SECURITY_DESCRIPTOR_MIN_LENGTH, 1);
- NUTS_ASSERT(sdesc != NULL);
- InitializeSecurityDescriptor(sdesc, SECURITY_DESCRIPTOR_REVISION);
- NUTS_FAIL(nng_stream_dialer_set_ptr(
- d, NNG_OPT_IPC_SECURITY_DESCRIPTOR, sdesc),
- NNG_ENOTSUP);
- free(sdesc);
- nng_stream_dialer_free(d);
-}
-
NUTS_TESTS = {
{ "ipc security descriptor", test_ipc_security_descriptor },
{ "ipc security descriptor busy", test_ipc_security_descriptor_busy },
{ "ipc security descriptor bogus",
test_ipc_security_descriptor_bogus },
- { "ipc security descriptor dialer",
- test_ipc_security_descriptor_dialer },
{ NULL, NULL },
};
diff --git a/src/platform/windows/win_ipclisten.c b/src/platform/windows/win_ipclisten.c
index e81f4b46..3d39ed71 100644
--- a/src/platform/windows/win_ipclisten.c
+++ b/src/platform/windows/win_ipclisten.c
@@ -132,15 +132,11 @@ ipc_accept_cb(nni_win_io *io, int rv, size_t cnt)
}
static int
-ipc_listener_set_sec_desc(void *arg, const void *buf, size_t sz, nni_type t)
+ipc_listener_set_sec_desc(void *arg, void *desc)
{
ipc_listener *l = arg;
- void *desc;
int rv;
- if ((rv = nni_copyin_ptr(&desc, buf, sz, t)) != 0) {
- return (rv);
- }
if (!IsValidSecurityDescriptor((SECURITY_DESCRIPTOR *) desc)) {
return (NNG_EINVAL);
}
@@ -163,10 +159,6 @@ ipc_listener_get_addr(void *arg, void *buf, size_t *szp, nni_type t)
static const nni_option ipc_listener_options[] = {
{
- .o_name = NNG_OPT_IPC_SECURITY_DESCRIPTOR,
- .o_set = ipc_listener_set_sec_desc,
- },
- {
.o_name = NNG_OPT_LOCADDR,
.o_get = ipc_listener_get_addr,
},
@@ -339,6 +331,7 @@ nni_ipc_listener_alloc(nng_stream_listener **lp, const nng_url *url)
l->sl.sl_accept = ipc_listener_accept;
l->sl.sl_get = ipc_listener_get;
l->sl.sl_set = ipc_listener_set;
+ l->sl.sl_set_security_descriptor = ipc_listener_set_sec_desc;
snprintf(l->sa.s_ipc.sa_path, NNG_MAXADDRLEN, "%s", url->u_path);
nni_aio_list_init(&l->aios);
nni_mtx_init(&l->mtx);
diff --git a/src/sp/transport.h b/src/sp/transport.h
index b65486ed..b7134595 100644
--- a/src/sp/transport.h
+++ b/src/sp/transport.h
@@ -103,6 +103,9 @@ struct nni_sp_listener_ops {
// This may be NULL if this listener does not support TLS.
int (*l_set_tls)(void *, nng_tls_config *);
+ // l_set_security_descriptor is used exclusively on Windows.
+ int (*l_set_security_descriptor)(void *, void *);
+
// l_options is an array of listener options. The final
// element must have a NULL name. If this member is NULL, then
// no dialer specific options are available.
diff --git a/src/sp/transport/ipc/ipc.c b/src/sp/transport/ipc/ipc.c
index 69efa741..803c4b4b 100644
--- a/src/sp/transport/ipc/ipc.c
+++ b/src/sp/transport/ipc/ipc.c
@@ -13,6 +13,7 @@
#include "core/defs.h"
#include "core/nng_impl.h"
+#include "nng/nng.h"
// IPC transport. Platform specific IPC operations must be
// supplied as well. Normally the IPC is UNIX domain sockets or
@@ -1106,6 +1107,15 @@ ipc_listener_set(
return (rv);
}
+static int
+ipc_listener_set_sec_desc(void *arg, void *pdesc)
+{
+ ipc_ep *ep = arg;
+
+ return (
+ nng_stream_listener_set_security_descriptor(ep->listener, pdesc));
+}
+
static nni_sp_dialer_ops ipc_dialer_ops = {
.d_init = ipc_ep_init_dialer,
.d_fini = ipc_ep_fini,
@@ -1116,13 +1126,14 @@ static nni_sp_dialer_ops ipc_dialer_ops = {
};
static nni_sp_listener_ops ipc_listener_ops = {
- .l_init = ipc_ep_init_listener,
- .l_fini = ipc_ep_fini,
- .l_bind = ipc_ep_bind,
- .l_accept = ipc_ep_accept,
- .l_close = ipc_ep_close,
- .l_getopt = ipc_listener_get,
- .l_setopt = ipc_listener_set,
+ .l_init = ipc_ep_init_listener,
+ .l_fini = ipc_ep_fini,
+ .l_bind = ipc_ep_bind,
+ .l_accept = ipc_ep_accept,
+ .l_close = ipc_ep_close,
+ .l_getopt = ipc_listener_get,
+ .l_setopt = ipc_listener_set,
+ .l_set_security_descriptor = ipc_listener_set_sec_desc,
};
static nni_sp_tran ipc_tran = {
diff --git a/src/sp/transport/ipc/ipc_test.c b/src/sp/transport/ipc/ipc_test.c
index 6a4021a0..51eb975d 100644
--- a/src/sp/transport/ipc/ipc_test.c
+++ b/src/sp/transport/ipc/ipc_test.c
@@ -674,6 +674,26 @@ test_ipc_pipe_peer(void)
#endif // NNG_PLATFORM_POSIX
}
+void
+test_ipc_security_descriptor(void)
+{
+ nng_socket s;
+ nng_listener l;
+ char *addr;
+
+ NUTS_ADDR(addr, "ipc");
+ NUTS_OPEN(s);
+ NUTS_PASS(nng_listener_create(&l, s, addr));
+#ifdef NNG_PLATFORM_WINDOWS
+ // not a security descriptor
+ NUTS_FAIL(nng_listener_set_security_descriptor(l, addr), NNG_EINVAL);
+#else
+ // not appropriate
+ NUTS_FAIL(nng_listener_set_security_descriptor(l, addr), NNG_ENOTSUP);
+#endif
+ NUTS_CLOSE(s);
+}
+
TEST_LIST = {
{ "ipc path too long", test_path_too_long },
{ "ipc dialer perms", test_ipc_dialer_perms },
@@ -696,5 +716,6 @@ TEST_LIST = {
{ "ipc abstract embedded null", test_abstract_null },
{ "ipc unix alias", test_unix_alias },
{ "ipc peer id", test_ipc_pipe_peer },
+ { "ipc security descriptor", test_ipc_security_descriptor },
{ NULL, NULL },
};