aboutsummaryrefslogtreecommitdiffhomepage
path: root/fallback.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fallback.cpp')
-rw-r--r--fallback.cpp80
1 files changed, 79 insertions, 1 deletions
diff --git a/fallback.cpp b/fallback.cpp
index 405c499f..e81b8702 100644
--- a/fallback.cpp
+++ b/fallback.cpp
@@ -15,8 +15,9 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
+#include <sys/socket.h>
#include <sys/stat.h>
-#include <unistd.h>
+#include <sys/param.h>
#include <errno.h>
#include <fcntl.h>
#include <wchar.h>
@@ -1520,3 +1521,80 @@ static int mk_wcswidth(const wchar_t *pwcs, size_t n)
}
#endif // HAVE_BROKEN_WCWIDTH
+
+#ifndef HAVE_GETPEEREID
+
+/*-------------------------------------------------------------------------
+ *
+ * getpeereid.c
+ * get peer userid for UNIX-domain socket connection
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/port/getpeereid.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
+#endif
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+
+/*
+ * BSD-style getpeereid() for platforms that lack it.
+ */
+int getpeereid(int sock, uid_t *uid, gid_t *gid)
+{
+#if defined(SO_PEERCRED)
+ /* Linux: use getsockopt(SO_PEERCRED) */
+ struct ucred peercred;
+ socklen_t so_len = sizeof(peercred);
+
+ if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred))
+ return -1;
+ *uid = peercred.uid;
+ *gid = peercred.gid;
+ return 0;
+#elif defined(LOCAL_PEERCRED)
+ /* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
+ struct xucred peercred;
+ socklen_t * so_len = sizeof(peercred);
+
+ if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred) ||
+ peercred.cr_version != XUCRED_VERSION)
+ return -1;
+ *uid = peercred.cr_uid;
+ *gid = peercred.cr_gid;
+ return 0;
+#elif defined(HAVE_GETPEERUCRED)
+ /* Solaris: use getpeerucred() */
+ ucred_t *ucred;
+
+ ucred = NULL; /* must be initialized to NULL */
+ if (getpeerucred(sock, &ucred) == -1)
+ return -1;
+
+ *uid = ucred_geteuid(ucred);
+ *gid = ucred_getegid(ucred);
+ ucred_free(ucred);
+
+ if (*uid == (uid_t) (-1) || *gid == (gid_t) (-1))
+ return -1;
+ return 0;
+#else
+ /* No implementation available on this platform */
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+#endif // HAVE_GETPEEREID