diff options
| -rw-r--r-- | docs/man/nng_ipc_options.5.adoc | 2 | ||||
| -rw-r--r-- | docs/ref/migrate/nng1.md | 11 | ||||
| -rw-r--r-- | docs/ref/tran/ipc.md | 25 | ||||
| -rw-r--r-- | docs/ref/xref.md | 1 | ||||
| -rw-r--r-- | include/nng/nng.h | 11 | ||||
| -rw-r--r-- | src/core/listener.c | 9 | ||||
| -rw-r--r-- | src/core/listener.h | 1 | ||||
| -rw-r--r-- | src/core/stream.c | 10 | ||||
| -rw-r--r-- | src/core/stream.h | 7 | ||||
| -rw-r--r-- | src/nng.c | 13 | ||||
| -rw-r--r-- | src/platform/posix/posix_ipcwinsec_test.c | 7 | ||||
| -rw-r--r-- | src/platform/windows/win_ipc_sec_test.c | 40 | ||||
| -rw-r--r-- | src/platform/windows/win_ipclisten.c | 11 | ||||
| -rw-r--r-- | src/sp/transport.h | 3 | ||||
| -rw-r--r-- | src/sp/transport/ipc/ipc.c | 25 | ||||
| -rw-r--r-- | src/sp/transport/ipc/ipc_test.c | 21 |
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 @@ -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 }, }; |
