aboutsummaryrefslogtreecommitdiff
path: root/src/platform/posix
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/posix')
-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
3 files changed, 134 insertions, 0 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)
{