aboutsummaryrefslogtreecommitdiff
path: root/src/platform
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2018-05-03 14:28:44 -0700
committerGarrett D'Amore <garrett@damore.org>2018-05-03 15:14:45 -0700
commitafd555af4fba0acbf16c174dd9dece24181a1a38 (patch)
tree9d49fec85c58ecad9a034a98e092627968494bc0 /src/platform
parentfa986e725f08e30eab68e16765b2cf71613b871c (diff)
downloadnng-afd555af4fba0acbf16c174dd9dece24181a1a38.tar.gz
nng-afd555af4fba0acbf16c174dd9dece24181a1a38.tar.bz2
nng-afd555af4fba0acbf16c174dd9dece24181a1a38.zip
fixes #383 Would like peerid for IPC
We offer uid, gid, process id, and even zone id where we have them. Docs and tests are provided.
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/posix/posix_aio.h2
-rw-r--r--src/platform/posix/posix_ipc.c64
-rw-r--r--src/platform/posix/posix_pipedesc.c68
-rw-r--r--src/platform/windows/win_ipc.c60
4 files changed, 191 insertions, 3 deletions
diff --git a/src/platform/posix/posix_aio.h b/src/platform/posix/posix_aio.h
index 3954f225..7d6a7231 100644
--- a/src/platform/posix/posix_aio.h
+++ b/src/platform/posix/posix_aio.h
@@ -33,6 +33,8 @@ extern int nni_posix_pipedesc_peername(nni_posix_pipedesc *, nni_sockaddr *);
extern int nni_posix_pipedesc_sockname(nni_posix_pipedesc *, nni_sockaddr *);
extern int nni_posix_pipedesc_set_nodelay(nni_posix_pipedesc *, bool);
extern int nni_posix_pipedesc_set_keepalive(nni_posix_pipedesc *, bool);
+extern int nni_posix_pipedesc_get_peerid(
+ nni_posix_pipedesc *, uint64_t *, uint64_t *, uint64_t *, uint64_t *);
extern int nni_posix_epdesc_init(nni_posix_epdesc **, int);
extern void nni_posix_epdesc_set_local(nni_posix_epdesc *, void *, size_t);
diff --git a/src/platform/posix/posix_ipc.c b/src/platform/posix/posix_ipc.c
index c1bb9292..5ba3c8fb 100644
--- a/src/platform/posix/posix_ipc.c
+++ b/src/platform/posix/posix_ipc.c
@@ -183,4 +183,68 @@ nni_plat_ipc_pipe_recv(nni_plat_ipc_pipe *p, nni_aio *aio)
nni_posix_pipedesc_recv((void *) p, aio);
}
+int
+nni_plat_ipc_pipe_get_peer_uid(nni_plat_ipc_pipe *p, uint64_t *uid)
+{
+ int rv;
+ uint64_t ignore;
+
+ if ((rv = nni_posix_pipedesc_get_peerid(
+ (void *) p, uid, &ignore, &ignore, &ignore)) != 0) {
+ return (rv);
+ }
+ return (0);
+}
+
+int
+nni_plat_ipc_pipe_get_peer_gid(nni_plat_ipc_pipe *p, uint64_t *gid)
+{
+ int rv;
+ uint64_t ignore;
+
+ if ((rv = nni_posix_pipedesc_get_peerid(
+ (void *) p, &ignore, gid, &ignore, &ignore)) != 0) {
+ return (rv);
+ }
+ return (0);
+}
+
+int
+nni_plat_ipc_pipe_get_peer_zoneid(nni_plat_ipc_pipe *p, uint64_t *zid)
+{
+ int rv;
+ uint64_t ignore;
+ uint64_t id;
+
+ if ((rv = nni_posix_pipedesc_get_peerid(
+ (void *) p, &ignore, &ignore, &ignore, &id)) != 0) {
+ return (rv);
+ }
+ if (id == (uint64_t) -1) {
+ // NB: -1 is not a legal zone id (illumos/Solaris)
+ return (NNG_ENOTSUP);
+ }
+ *zid = id;
+ return (0);
+}
+
+int
+nni_plat_ipc_pipe_get_peer_pid(nni_plat_ipc_pipe *p, uint64_t *pid)
+{
+ int rv;
+ uint64_t ignore;
+ uint64_t id;
+
+ if ((rv = nni_posix_pipedesc_get_peerid(
+ (void *) p, &ignore, &ignore, &id, &ignore)) != 0) {
+ return (rv);
+ }
+ if (id == (uint64_t) -1) {
+ // NB: -1 is not a legal process id
+ return (NNG_ENOTSUP);
+ }
+ *pid = id;
+ return (0);
+}
+
#endif // NNG_PLATFORM_POSIX
diff --git a/src/platform/posix/posix_pipedesc.c b/src/platform/posix/posix_pipedesc.c
index f9cbb94b..61005ca8 100644
--- a/src/platform/posix/posix_pipedesc.c
+++ b/src/platform/posix/posix_pipedesc.c
@@ -26,6 +26,12 @@
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
+#if defined(NNG_HAVE_GETPEERUCRED)
+#include <ucred.h>
+#elif defined(NNG_HAVE_LOCALPEERCRED)
+#include <sys/ucred.h>
+#include <sys/un.h>
+#endif
// nni_posix_pipedesc is a descriptor kept one per transport pipe (i.e. open
// file descriptor for TCP socket, etc.) This contains the list of pending
@@ -402,6 +408,68 @@ nni_posix_pipedesc_init(nni_posix_pipedesc **pdp, int fd)
return (0);
}
+int
+nni_posix_pipedesc_get_peerid(nni_posix_pipedesc *pd, uint64_t *euid,
+ uint64_t *egid, uint64_t *prid, uint64_t *znid)
+{
+ int fd = pd->node.fd;
+#if defined(NNG_HAVE_GETPEEREID)
+ uid_t uid;
+ gid_t gid;
+
+ if (getpeereid(fd, &uid, &gid) != 0) {
+ return (nni_plat_errno(errno));
+ }
+ *euid = uid;
+ *egid = gid;
+ *prid = (uint64_t) -1;
+ *znid = (uint64_t) -1;
+ return (0);
+#elif defined(NNG_HAVE_GETPEERUCRED)
+ ucred *ucp;
+ if (getpeerucred(fd, &ucp) != 0) {
+ return (nni_plat_errno(errno));
+ }
+ *euid = ucred_geteuid(ucp);
+ *egid = ucred_geteuid(ucp);
+ *prid = ucred_getpid(ucp);
+ *znid = ucred_getzoneid(ucp);
+ ucred_free(ucp);
+ return (0);
+#elif defined(NNG_HAVE_SOPEERCRED)
+ struct ucred uc;
+ socklen_t len = sizeof(uc);
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &uc, &len) != 0) {
+ return (nni_plat_errno(errno));
+ }
+ *euid = uc.uid;
+ *egid = uc.gid;
+ *prid = uc.pid;
+ *znid = (uint64_t) -1;
+ return (0);
+#elif defined(NNG_HAVE_LOCALPEERCRED)
+ struct xucred xu;
+ socklen_t len = sizeof(xu);
+ if (getsockopt(fd, SOL_LOCAL, LOCAL_PEERCRED, &xu, &len) != 0) {
+ return (nni_plat_errno(errno));
+ }
+ *euid = xu.cr_uid;
+ *egid = xu.cr_gid;
+ *prid = (uint64_t) -1; // XXX: macOS has undocumented LOCAL_PEERPID...
+ *znid = (uint64_t) -1;
+ return (0);
+#else
+ if (fd < 0) {
+ return (NNG_ECLOSED);
+ }
+ NNI_ARG_UNUSED(euid);
+ NNI_ARG_UNUSED(egid);
+ NNI_ARG_UNUSED(prid);
+ NNI_ARG_UNUSED(znid);
+ return (NNG_ENOTSUP);
+#endif
+}
+
void
nni_posix_pipedesc_fini(nni_posix_pipedesc *pd)
{
diff --git a/src/platform/windows/win_ipc.c b/src/platform/windows/win_ipc.c
index 7d118672..c6376cc7 100644
--- a/src/platform/windows/win_ipc.c
+++ b/src/platform/windows/win_ipc.c
@@ -16,6 +16,7 @@
struct nni_plat_ipc_pipe {
HANDLE p;
+ int mode;
nni_win_event rcv_ev;
nni_win_event snd_ev;
};
@@ -128,7 +129,7 @@ nni_win_ipc_pipe_finish(nni_win_event *evt, nni_aio *aio)
}
static int
-nni_win_ipc_pipe_init(nni_plat_ipc_pipe **pipep, HANDLE p)
+nni_win_ipc_pipe_init(nni_plat_ipc_pipe **pipep, HANDLE p, int mode)
{
nni_plat_ipc_pipe *pipe;
int rv;
@@ -136,6 +137,7 @@ nni_win_ipc_pipe_init(nni_plat_ipc_pipe **pipep, HANDLE p)
if ((pipe = NNI_ALLOC_STRUCT(pipe)) == NULL) {
return (NNG_ENOMEM);
}
+ pipe->mode = mode;
rv = nni_win_event_init(&pipe->rcv_ev, &nni_win_ipc_pipe_ops, pipe);
if (rv != 0) {
nni_plat_ipc_pipe_fini(pipe);
@@ -189,6 +191,56 @@ nni_plat_ipc_pipe_fini(nni_plat_ipc_pipe *pipe)
}
int
+nni_plat_ipc_pipe_get_peer_uid(nni_plat_ipc_pipe *pipe, uint64_t *id)
+{
+ NNI_ARG_UNUSED(pipe);
+ NNI_ARG_UNUSED(id);
+ return (NNG_ENOTSUP);
+}
+
+int
+nni_plat_ipc_pipe_get_peer_gid(nni_plat_ipc_pipe *pipe, uint64_t *id)
+{
+ NNI_ARG_UNUSED(pipe);
+ NNI_ARG_UNUSED(id);
+ return (NNG_ENOTSUP);
+}
+
+int
+nni_plat_ipc_pipe_get_peer_zoneid(nni_plat_ipc_pipe *pipe, uint64_t *id)
+{
+ NNI_ARG_UNUSED(pipe);
+ NNI_ARG_UNUSED(id);
+ return (NNG_ENOTSUP);
+}
+
+// nni_plat_ipc_pipe_get_peer_gid obtains the peer group id, if possible.
+// NB: Only POSIX systems support group IDs.
+int
+nni_plat_ipc_pipe_get_peer_pid(nni_plat_ipc_pipe *pipe, uint64_t *pid)
+{
+ ULONG id;
+ switch (pipe->mode) {
+ case NNI_EP_MODE_DIAL:
+ if (!GetNamedPipeServerProcessId(pipe->p, &id)) {
+ return (nni_win_error(GetLastError()));
+ }
+ *pid = id;
+ break;
+ case NNI_EP_MODE_LISTEN:
+ if (!GetNamedPipeClientProcessId(pipe->p, &id)) {
+ return (nni_win_error(GetLastError()));
+ }
+ *pid = id;
+ break;
+ default:
+ // Should never occur!
+ return (NNG_EINVAL);
+ }
+ return (0);
+}
+
+int
nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const nni_sockaddr *sa, int mode)
{
const char * path;
@@ -331,7 +383,8 @@ nni_win_ipc_acc_finish(nni_win_event *evt, nni_aio *aio)
oldp = ep->p;
ep->p = newp;
- if ((rv = nni_win_ipc_pipe_init(&pipe, oldp)) != 0) {
+ if ((rv = nni_win_ipc_pipe_init(&pipe, oldp, NNI_EP_MODE_LISTEN)) !=
+ 0) {
// The new pipe is already fine for us. Discard
// the old one, since failed to be able to use it.
DisconnectNamedPipe(oldp);
@@ -466,7 +519,8 @@ nni_win_ipc_conn_thr(void *arg)
}
goto fail;
}
- if (((rv = nni_win_ipc_pipe_init(&pipe, p)) != 0) ||
+ if (((rv = nni_win_ipc_pipe_init(
+ &pipe, p, NNI_EP_MODE_DIAL)) != 0) ||
((rv = nni_win_iocp_register(p)) != 0)) {
goto fail;
}