summaryrefslogtreecommitdiff
path: root/sysutils
diff options
context:
space:
mode:
authorjlam <jlam>2005-08-30 23:24:33 +0000
committerjlam <jlam>2005-08-30 23:24:33 +0000
commit43bb97da2095bb36aa56a37fb5147ffb8a320c61 (patch)
tree1d69b233748c461c16d6fe7c95b776eb81fd9b53 /sysutils
parent1be75be83c6bce02ffbaa1ecfd61628bc1e65e44 (diff)
downloadpkgsrc-43bb97da2095bb36aa56a37fb5147ffb8a320c61.tar.gz
Port gamin to NetBSD by rewriting the routines that rely on socket
credentials to understand NetBSD's sockcred. Bump the PKGREVISION to 1.
Diffstat (limited to 'sysutils')
-rw-r--r--sysutils/gamin/Makefile4
-rw-r--r--sysutils/gamin/distinfo12
-rw-r--r--sysutils/gamin/patches/patch-aa4
-rw-r--r--sysutils/gamin/patches/patch-ab36
-rw-r--r--sysutils/gamin/patches/patch-ac4
-rw-r--r--sysutils/gamin/patches/patch-ad4
-rw-r--r--sysutils/gamin/patches/patch-ae264
-rw-r--r--sysutils/gamin/patches/patch-af272
8 files changed, 584 insertions, 16 deletions
diff --git a/sysutils/gamin/Makefile b/sysutils/gamin/Makefile
index be4256ad6aa..99f57216dc2 100644
--- a/sysutils/gamin/Makefile
+++ b/sysutils/gamin/Makefile
@@ -1,6 +1,7 @@
-# $NetBSD: Makefile,v 1.2 2005/08/10 22:57:24 jlam Exp $
+# $NetBSD: Makefile,v 1.3 2005/08/30 23:24:33 jlam Exp $
DISTNAME= gamin-0.1.5
+PKGREVISION= 1
CATEGORIES= sysutils
MASTER_SITES= http://www.gnome.org/~veillard/gamin/sources/
@@ -13,6 +14,7 @@ HOMEPAGE= http://www.gnome.org/~veillard/gamin/
USE_LIBTOOL= yes
USE_TOOLS+= pkg-config
GNU_CONFIGURE= yes
+CONFIGURE_ARGS+= --enable-debug
CONFIGURE_ARGS+= --disable-gtk-doc
CONFIGURE_ARGS+= --without-threads
CONFIGURE_ARGS+= --with-html-dir=${DOCDIR}
diff --git a/sysutils/gamin/distinfo b/sysutils/gamin/distinfo
index ba995a0caa3..38d5e95e6ad 100644
--- a/sysutils/gamin/distinfo
+++ b/sysutils/gamin/distinfo
@@ -1,9 +1,11 @@
-$NetBSD: distinfo,v 1.1.1.1 2005/08/10 21:01:51 jlam Exp $
+$NetBSD: distinfo,v 1.2 2005/08/30 23:24:33 jlam Exp $
SHA1 (gamin-0.1.5.tar.gz) = f9f8e4c45c7abb6bb8382bf5d969583f057d1ec3
RMD160 (gamin-0.1.5.tar.gz) = 757bf10362965f58dd919874a3a35b14627f0c0a
Size (gamin-0.1.5.tar.gz) = 531603 bytes
-SHA1 (patch-aa) = 8438e9dde835be2662d86b5d58c0b13b6e52df21
-SHA1 (patch-ab) = e504cab3278446837e13484210ab480e2610ebae
-SHA1 (patch-ac) = f1d7c9a3bda033b3f737663995a89490d01332b3
-SHA1 (patch-ad) = d82cd54452dab8e912a69b241b1ea3afc38b690c
+SHA1 (patch-aa) = b4d33eefbed42f889463a58d6f25c2df24970c69
+SHA1 (patch-ab) = 4a282a3b374c3287c2634578b9c701355f0d3455
+SHA1 (patch-ac) = 06f76b4a3354b0621e466484264ac43e92d05c86
+SHA1 (patch-ad) = 37cf3a565c3b028eb58328c6e9d7f57209a1b033
+SHA1 (patch-ae) = 4e81484b9110c70b8776bbfb49d64971eca38cdf
+SHA1 (patch-af) = ed7ba9cfd393f3109c9028cf68e3a5909c95d414
diff --git a/sysutils/gamin/patches/patch-aa b/sysutils/gamin/patches/patch-aa
index b607fc40186..6092b346866 100644
--- a/sysutils/gamin/patches/patch-aa
+++ b/sysutils/gamin/patches/patch-aa
@@ -1,6 +1,6 @@
-$NetBSD: patch-aa,v 1.1.1.1 2005/08/10 21:01:51 jlam Exp $
+$NetBSD: patch-aa,v 1.2 2005/08/30 23:24:33 jlam Exp $
---- libgamin/gam_data.c.orig 2005-05-18 14:45:04.000000000 +0000
+--- libgamin/gam_data.c.orig 2005-05-18 10:45:04.000000000 -0400
+++ libgamin/gam_data.c
@@ -471,7 +471,7 @@ gamin_data_new(void)
}
diff --git a/sysutils/gamin/patches/patch-ab b/sysutils/gamin/patches/patch-ab
index 5f578365c3d..1b28ec25b34 100644
--- a/sysutils/gamin/patches/patch-ab
+++ b/sysutils/gamin/patches/patch-ab
@@ -1,6 +1,6 @@
-$NetBSD: patch-ab,v 1.1.1.1 2005/08/10 21:01:52 jlam Exp $
+$NetBSD: patch-ab,v 1.2 2005/08/30 23:24:33 jlam Exp $
---- server/gam_kqueue.c.orig 2005-08-04 08:17:37.000000000 +0000
+--- server/gam_kqueue.c.orig 2005-08-04 04:17:37.000000000 -0400
+++ server/gam_kqueue.c
@@ -52,6 +52,7 @@
#include <string.h>
@@ -10,9 +10,12 @@ $NetBSD: patch-ab,v 1.1.1.1 2005/08/10 21:01:52 jlam Exp $
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/stat.h>
-@@ -327,7 +328,7 @@ gam_kqueue_get_uint_sysctl (const char *
+@@ -325,9 +326,9 @@ gam_kqueue_isdir (const char *pathname,
+ static gboolean
+ gam_kqueue_get_uint_sysctl (const char *name, unsigned int *value)
{
- unsigned int value_len = sizeof(*value);
+- unsigned int value_len = sizeof(*value);
++ size_t value_len = sizeof(*value);
- if (sysctlbyname(name, value, &value_len, NULL, 0) < 0)
+ if (sysctlbyname(name, value, &value_len, (void *)NULL, 0) < 0)
@@ -28,3 +31,28 @@ $NetBSD: patch-ab,v 1.1.1.1 2005/08/10 21:01:52 jlam Exp $
return TRUE; /* keep source */
}
+@@ -1134,8 +1135,10 @@ gam_kqueue_init (void)
+
+ if (! gam_kqueue_get_uint_sysctl("kern.maxfiles", &maxfiles))
+ return FALSE;
++#if defined(KERN_MAXFILESPERPROC)
+ if (! gam_kqueue_get_uint_sysctl("kern.maxfilesperproc", &maxfilesperproc))
+ return FALSE;
++#endif
+
+ /*
+ * We make sure to:
+@@ -1144,9 +1147,13 @@ gam_kqueue_init (void)
+ */
+
+ maxfiles *= CFG_GLOBAL_FILE_RESERVE_RATIO;
++#if defined(KERN_MAXFILESPERPROC)
+ maxfilesperproc = maxfilesperproc > CFG_SELF_FILE_RESERVE
+ ? maxfilesperproc - CFG_SELF_FILE_RESERVE
+ : 0;
++#else
++ maxfilesperproc = maxfiles;
++#endif
+
+ max_open_files = MIN(maxfiles, maxfilesperproc);
+
diff --git a/sysutils/gamin/patches/patch-ac b/sysutils/gamin/patches/patch-ac
index 533fd3a6646..d60ca275163 100644
--- a/sysutils/gamin/patches/patch-ac
+++ b/sysutils/gamin/patches/patch-ac
@@ -1,6 +1,6 @@
-$NetBSD: patch-ac,v 1.1.1.1 2005/08/10 21:01:52 jlam Exp $
+$NetBSD: patch-ac,v 1.2 2005/08/30 23:24:33 jlam Exp $
---- server/gam_pidname.c.orig 2005-08-01 15:27:19.000000000 +0000
+--- server/gam_pidname.c.orig 2005-08-01 11:27:19.000000000 -0400
+++ server/gam_pidname.c
@@ -7,9 +7,9 @@
diff --git a/sysutils/gamin/patches/patch-ad b/sysutils/gamin/patches/patch-ad
index 24e311bfd6e..6bb6f90e9b5 100644
--- a/sysutils/gamin/patches/patch-ad
+++ b/sysutils/gamin/patches/patch-ad
@@ -1,6 +1,6 @@
-$NetBSD: patch-ad,v 1.1.1.1 2005/08/10 21:01:52 jlam Exp $
+$NetBSD: patch-ad,v 1.2 2005/08/30 23:24:33 jlam Exp $
---- server/gam_server.c.orig 2005-08-09 18:30:12.000000000 +0000
+--- server/gam_server.c.orig 2005-08-09 14:30:12.000000000 -0400
+++ server/gam_server.c
@@ -56,6 +56,21 @@ gboolean (*gam_backend_add_subscription)
gboolean (*gam_backend_remove_subscription) (GamSubscription *sub);
diff --git a/sysutils/gamin/patches/patch-ae b/sysutils/gamin/patches/patch-ae
new file mode 100644
index 00000000000..17eb6b4dc2b
--- /dev/null
+++ b/sysutils/gamin/patches/patch-ae
@@ -0,0 +1,264 @@
+$NetBSD: patch-ae,v 1.1 2005/08/30 23:24:33 jlam Exp $
+
+--- libgamin/gam_api.c.orig 2005-08-05 18:31:46.000000000 -0400
++++ libgamin/gam_api.c
+@@ -7,6 +7,7 @@
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <unistd.h>
++#include <sys/param.h>
+ #include <sys/types.h>
+ #include <fcntl.h>
+ #include <errno.h>
+@@ -51,6 +52,20 @@ const char *FamErrlist[] = {
+ NULL
+ };
+
++#if defined(SOCKCREDSIZE)
++#define BSDCRED struct sockcred
++#define CRED_DATASIZE (SOCKCREDSIZE(NGROUPS))
++#define credpid(c,p) (p)
++#define creduid(c) (c->sc_euid)
++#define credgid(c) (c->sc_egid)
++#elif defined(HAVE_CMSGCRED)
++#define BSDCRED struct cmsgcred
++#define CRED_DATASIZE (sizeof(struct cmsgcred))
++#define credpid(c,p) (c->cmcred_pid)
++#define creduid(c) (c->cmcred_euid)
++#define credgid(c) (c->cmcred_groups[0])
++#endif
++
+ #ifdef GAMIN_DEBUG_API
+ int FAMDebug(FAMConnection *fc, const char *filename, FAMRequest * fr,
+ void *userData);
+@@ -307,12 +322,6 @@ gamin_check_secure_path(const char *path
+ goto cleanup;
+ }
+ #endif
+- if (st.st_mode & (S_IRWXG|S_IRWXO)) {
+- gam_error(DEBUG_INFO,
+- "Socket %s has wrong permissions\n",
+- path);
+- goto cleanup;
+- }
+ /*
+ * Looks good though binding may fail due to an existing server
+ */
+@@ -372,6 +381,18 @@ gamin_connect_unix_socket(const char *pa
+ }
+ strncpy(&addr.sun_path[0], path, (sizeof(addr) - 4) - 1);
+ #endif
++#if defined(BSDCRED) && defined(LOCAL_CREDS)
++ /* Set the socket to receive credentials. */
++ {
++ int on = 1;
++
++ if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof(on)) < 0) {
++ gam_error(DEBUG_INFO,
++ "Unable to setsockopt() LOCAL_CREDS on %d\n", fd);
++ return(-1);
++ }
++ }
++#endif
+
+ if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ if (retries == 0) {
+@@ -419,37 +440,35 @@ gamin_connect_unix_socket(const char *pa
+ static int
+ gamin_write_credential_byte(int fd)
+ {
+- char data[2] = { 0, 0 };
+- int written;
+-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
+- struct {
+- struct cmsghdr hdr;
+- struct cmsgcred cred;
+- } cmsg;
+- struct iovec iov;
+ struct msghdr msg;
++ struct iovec iov;
++ pid_t pid = getpid();
++ int written;
+
+- iov.iov_base = &data[0];
+- iov.iov_len = 1;
++#if defined(BSDCRED) && !defined(LOCAL_CREDS)
++ struct cmsghdr *cmsg;
++ char cmsgbuf[CMSG_SPACE(CRED_DATASIZE)];
++#endif
+
+- memset (&msg, 0, sizeof (msg));
++ iov.iov_base = &pid;
++ iov.iov_len = sizeof(pid_t);
++
++ memset (&msg, 0, sizeof(msg));
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+- msg.msg_control = &cmsg;
+- msg.msg_controllen = sizeof (cmsg);
+- memset (&cmsg, 0, sizeof (cmsg));
+- cmsg.hdr.cmsg_len = sizeof (cmsg);
+- cmsg.hdr.cmsg_level = SOL_SOCKET;
+- cmsg.hdr.cmsg_type = SCM_CREDS;
++#if defined(BSDCRED) && !defined(LOCAL_CREDS)
++ memset(cmsgbuf, 0, sizeof(cmsgbuf));
++ msg.msg_control = (void *)cmsgbuf;
++ msg.msg_controllen = sizeof(cmsgbuf);
++ cmsg = CMSG_FIRSTHDR(&msg);
++ cmsg->cmsg_len = CMSG_LEN(CRED_DATASIZE);
++ cmsg->cmsg_level = SOL_SOCKET;
++ cmsg->cmsg_type = SCM_CREDS;
+ #endif
+
+ retry:
+-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
+ written = sendmsg(fd, &msg, 0);
+-#else
+- written = write(fd, &data[0], 1);
+-#endif
+ if (written < 0) {
+ if (errno == EINTR)
+ goto retry;
+@@ -457,7 +476,7 @@ retry:
+ "Failed to write credential bytes to socket %d\n", fd);
+ return (-1);
+ }
+- if (written != 1) {
++ if (written != iov.iov_len) {
+ gam_error(DEBUG_INFO, "Wrote %d credential bytes to socket %d\n",
+ written, fd);
+ return (-1);
+@@ -641,43 +660,26 @@ gamin_check_cred(GAMDataPtr conn, int fd
+ {
+ struct msghdr msg;
+ struct iovec iov;
+- char buf;
+- pid_t c_pid;
++ pid_t c_pid, pid;
+ uid_t c_uid, s_uid;
+ gid_t c_gid;
+
+-#ifdef HAVE_CMSGCRED
+- struct {
+- struct cmsghdr hdr;
+- struct cmsgcred cred;
+- } cmsg;
+-#endif
+-
+- s_uid = getuid();
+-
+-#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
+- /* Set the socket to receive credentials on the next message */
+- {
+- int on = 1;
+-
+- if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof(on)) < 0) {
+- gam_error(DEBUG_INFO, "Unable to set LOCAL_CREDS socket option\n");
+- return(-1);
+- }
+- }
++#if defined(BSDCRED)
++ struct cmsghdr *cmsg;
++ char cmsgbuf[CMSG_SPACE(CRED_DATASIZE)];
+ #endif
+
+- iov.iov_base = &buf;
+- iov.iov_len = 1;
++ iov.iov_base = &pid;
++ iov.iov_len = sizeof(pid_t);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+-#ifdef HAVE_CMSGCRED
+- memset(&cmsg, 0, sizeof(cmsg));
+- msg.msg_control = &cmsg;
+- msg.msg_controllen = sizeof(cmsg);
++#if defined(BSDCRED)
++ memset(cmsgbuf, 0, sizeof(cmsgbuf));
++ msg.msg_control = (void *)cmsgbuf;
++ msg.msg_controllen = sizeof(cmsgbuf);
+ #endif
+
+ retry:
+@@ -685,26 +687,33 @@ retry:
+ if (errno == EINTR)
+ goto retry;
+
+- GAM_DEBUG(DEBUG_INFO, "Failed to read credentials byte on %d\n", fd);
++ GAM_DEBUG(DEBUG_INFO, "Failed to read credential bytes on %d\n", fd);
+ goto failed;
+ }
+-
+- if (buf != '\0') {
+- GAM_DEBUG(DEBUG_INFO, "Credentials byte was not nul on %d\n", fd);
++ GAM_DEBUG(DEBUG_INFO, "Read pid %d on %d\n", pid, fd);
++#if defined(BSDCRED)
++ if (msg.msg_controllen == 0) {
++ GAM_DEBUG(DEBUG_INFO,
++ "No control message received over recvmsg()\n");
++ goto failed;
++ }
++ if ((msg.msg_flags & MSG_CTRUNC) != 0) {
++ GAM_DEBUG(DEBUG_INFO,
++ "Lost control message data over recvmsg()\n");
+ goto failed;
+ }
+-#ifdef HAVE_CMSGCRED
+- if (cmsg.hdr.cmsg_len < sizeof(cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) {
++ cmsg = CMSG_FIRSTHDR(&msg);
++ if (cmsg->cmsg_type != SCM_CREDS) {
+ GAM_DEBUG(DEBUG_INFO,
+ "Message from recvmsg() was not SCM_CREDS\n");
+ goto failed;
+ }
+ #endif
+
+- GAM_DEBUG(DEBUG_INFO, "read credentials byte\n");
++ GAM_DEBUG(DEBUG_INFO, "read credential bytes\n");
+
+ {
+-#ifdef SO_PEERCRED
++#if defined(SO_PEERCRED)
+ struct ucred cr;
+ socklen_t cr_len = sizeof(cr);
+
+@@ -719,23 +728,31 @@ retry:
+ fd, cr_len, (int) sizeof(cr));
+ goto failed;
+ }
+-#elif defined(HAVE_CMSGCRED)
+- c_pid = cmsg.cred.cmcred_pid;
+- c_uid = cmsg.cred.cmcred_euid;
+- c_gid = cmsg.cred.cmcred_groups[0];
+-#else /* !SO_PEERCRED && !HAVE_CMSGCRED */
++#elif defined(BSDCRED)
++ BSDCRED *cr = (BSDCRED *)CMSG_DATA(cmsg);
++ c_pid = credpid(cr, pid);
++ c_uid = creduid(cr);
++ c_gid = credgid(cr);
++#else
+ GAM_DEBUG(DEBUG_INFO,
+ "Socket credentials not supported on this OS\n");
+ goto failed;
+ #endif
+ }
+
++ s_uid = getuid();
+ if (s_uid != c_uid) {
+ GAM_DEBUG(DEBUG_INFO,
+ "Credentials check failed: s_uid %d, c_uid %d\n",
+ (int) s_uid, (int) c_uid);
+ goto failed;
+ }
++ if (pid != c_pid) {
++ GAM_DEBUG(DEBUG_INFO,
++ "read credentials do not match: pid %d, c_pid %d\n",
++ (int) pid, (int) c_pid);
++ goto failed;
++ }
+ GAM_DEBUG(DEBUG_INFO,
+ "Credentials: s_uid %d, c_uid %d, c_gid %d, c_pid %d\n",
+ (int) s_uid, (int) c_uid, (int) c_gid, (int) c_pid);
diff --git a/sysutils/gamin/patches/patch-af b/sysutils/gamin/patches/patch-af
new file mode 100644
index 00000000000..6864e1e7071
--- /dev/null
+++ b/sysutils/gamin/patches/patch-af
@@ -0,0 +1,272 @@
+$NetBSD: patch-af,v 1.1 2005/08/30 23:24:33 jlam Exp $
+
+--- server/gam_channel.c.orig 2005-08-09 12:17:39.000000000 -0400
++++ server/gam_channel.c
+@@ -3,6 +3,7 @@
+ #include <unistd.h>
+ #include <errno.h>
+ #include <glib.h>
++#include <sys/param.h>
+ #include <sys/socket.h>
+ #include <sys/stat.h>
+ #include <sys/un.h>
+@@ -12,6 +13,20 @@
+ #include "gam_channel.h"
+ #include "gam_protocol.h"
+
++#if defined(SOCKCREDSIZE)
++#define BSDCRED struct sockcred
++#define CRED_DATASIZE (SOCKCREDSIZE(NGROUPS))
++#define credpid(c,p) (p)
++#define creduid(c) (c->sc_euid)
++#define credgid(c) (c->sc_egid)
++#elif defined(HAVE_CMSGCRED)
++#define BSDCRED struct cmsgcred
++#define CRED_DATASIZE (sizeof(struct cmsgcred))
++#define credpid(c,p) (c->cmcred_pid)
++#define creduid(c) (c->cmcred_euid)
++#define credgid(c) (c->cmcred_groups[0])
++#endif
++
+ /* #define CHANNEL_VERBOSE_DEBUGGING */
+ /************************************************************************
+ * *
+@@ -28,37 +43,35 @@
+ static gboolean
+ gam_client_conn_send_cred(int fd)
+ {
+- char data[2] = { 0, 0 };
+- int written;
+-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
+- struct {
+- struct cmsghdr hdr;
+- struct cmsgcred cred;
+- } cmsg;
+- struct iovec iov;
+ struct msghdr msg;
++ struct iovec iov;
++ pid_t pid = getpid();
++ int written;
++
++#if defined(BSDCRED) && !defined(LOCAL_CREDS)
++ struct cmsghdr *cmsg;
++ char cmsgbuf[CMSG_SPACE(CRED_DATASIZE)];
++#endif
+
+- iov.iov_base = &data[0];
+- iov.iov_len = 1;
++ iov.iov_base = &pid;
++ iov.iov_len = sizeof(pid_t);
+
+ memset (&msg, 0, sizeof (msg));
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+- msg.msg_control = &cmsg;
+- msg.msg_controllen = sizeof (cmsg);
+- memset (&cmsg, 0, sizeof (cmsg));
+- cmsg.hdr.cmsg_len = sizeof (cmsg);
+- cmsg.hdr.cmsg_level = SOL_SOCKET;
+- cmsg.hdr.cmsg_type = SCM_CREDS;
++#if defined(BSDCRED) && !defined(LOCAL_CREDS)
++ memset(cmsgbuf, 0, CMSG_SPACE(CRED_DATASIZE));
++ msg.msg_control = (void *)cmsgbuf;
++ msg.msg_controllen = CMSG_LEN(CRED_DATASIZE);
++ cmsg = CMSG_FIRSTHDR(&msg);
++ cmsg->cmsg_len = CMSG_LEN(CRED_DATASIZE);
++ cmsg->cmsg_level = SOL_SOCKET;
++ cmsg->cmsg_type = SCM_CREDS;
+ #endif
+
+ retry:
+-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
+ written = sendmsg(fd, &msg, 0);
+-#else
+- written = write(fd, &data[0], 1);
+-#endif
+ if (written < 0) {
+ if (errno == EINTR)
+ goto retry;
+@@ -66,7 +79,7 @@ retry:
+ "Failed to write credential bytes to socket %d\n", fd);
+ return (-1);
+ }
+- if (written != 1) {
++ if (written != iov.iov_len) {
+ gam_error(DEBUG_INFO, "Wrote %d credential bytes to socket %d\n",
+ written, fd);
+ return (-1);
+@@ -89,43 +102,26 @@ gam_client_conn_check_cred(GIOChannel *
+ {
+ struct msghdr msg;
+ struct iovec iov;
+- char buf;
+- pid_t c_pid;
++ pid_t c_pid, pid;
+ uid_t c_uid, s_uid;
+ gid_t c_gid;
+
+-#ifdef HAVE_CMSGCRED
+- struct {
+- struct cmsghdr hdr;
+- struct cmsgcred cred;
+- } cmsg;
++#if defined(BSDCRED)
++ struct cmsghdr *cmsg;
++ char cmsgbuf[CMSG_SPACE(CRED_DATASIZE)];
+ #endif
+
+- s_uid = getuid();
+-
+-#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
+- /* Set the socket to receive credentials on the next message */
+- {
+- int on = 1;
+-
+- if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof(on)) < 0) {
+- gam_error(DEBUG_INFO, "Unable to set LOCAL_CREDS socket option\n");
+- return FALSE;
+- }
+- }
+-#endif
+-
+- iov.iov_base = &buf;
+- iov.iov_len = 1;
++ iov.iov_base = &pid;
++ iov.iov_len = sizeof(pid_t);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+-#ifdef HAVE_CMSGCRED
+- memset(&cmsg, 0, sizeof(cmsg));
+- msg.msg_control = &cmsg;
+- msg.msg_controllen = sizeof(cmsg);
++#if defined(BSDCRED)
++ memset(cmsgbuf, 0, sizeof(cmsgbuf));
++ msg.msg_control = (void *)cmsgbuf;
++ msg.msg_controllen = sizeof(cmsgbuf);
+ #endif
+
+ retry:
+@@ -133,26 +129,33 @@ gam_client_conn_check_cred(GIOChannel *
+ if (errno == EINTR)
+ goto retry;
+
+- GAM_DEBUG(DEBUG_INFO, "Failed to read credentials byte on %d\n", fd);
++ GAM_DEBUG(DEBUG_INFO, "Failed to read credential bytes on %d\n", fd);
+ goto failed;
+ }
+-
+- if (buf != '\0') {
+- GAM_DEBUG(DEBUG_INFO, "Credentials byte was not nul on %d\n", fd);
++ GAM_DEBUG(DEBUG_INFO, "Read pid %d on %d\n", pid, fd);
++#if defined(BSDCRED)
++ if (msg.msg_controllen == 0) {
++ GAM_DEBUG(DEBUG_INFO,
++ "No control message received over recvmsg()\n");
++ goto failed;
++ }
++ if ((msg.msg_flags & MSG_CTRUNC) != 0) {
++ GAM_DEBUG(DEBUG_INFO,
++ "Lost control message data over recvmsg()\n");
+ goto failed;
+ }
+-#ifdef HAVE_CMSGCRED
+- if (cmsg.hdr.cmsg_len < sizeof(cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) {
++ cmsg = CMSG_FIRSTHDR(&msg);
++ if (cmsg->cmsg_type != SCM_CREDS) {
+ GAM_DEBUG(DEBUG_INFO,
+ "Message from recvmsg() was not SCM_CREDS\n");
+ goto failed;
+ }
+ #endif
+
+- GAM_DEBUG(DEBUG_INFO, "read credentials byte\n");
++ GAM_DEBUG(DEBUG_INFO, "read credential bytes\n");
+
+ {
+-#ifdef SO_PEERCRED
++#if defined(SO_PEERCRED)
+ struct ucred cr;
+ socklen_t cr_len = sizeof(cr);
+
+@@ -167,23 +170,31 @@ gam_client_conn_check_cred(GIOChannel *
+ fd, cr_len, (int) sizeof(cr));
+ goto failed;
+ }
+-#elif defined(HAVE_CMSGCRED)
+- c_pid = cmsg.cred.cmcred_pid;
+- c_uid = cmsg.cred.cmcred_euid;
+- c_gid = cmsg.cred.cmcred_groups[0];
+-#else /* !SO_PEERCRED && !HAVE_CMSGCRED */
++#elif defined(BSDCRED)
++ BSDCRED *cr = (BSDCRED *)CMSG_DATA(cmsg);
++ c_pid = credpid(cr, pid);
++ c_uid = creduid(cr);
++ c_gid = credgid(cr);
++#else
+ GAM_DEBUG(DEBUG_INFO,
+ "Socket credentials not supported on this OS\n");
+ goto failed;
+ #endif
+ }
+
++ s_uid = getuid();
+ if (s_uid != c_uid) {
+ GAM_DEBUG(DEBUG_INFO,
+ "Credentials check failed: s_uid %d, c_uid %d\n",
+ (int) s_uid, (int) c_uid);
+ goto failed;
+ }
++ if (pid != c_pid) {
++ GAM_DEBUG(DEBUG_INFO,
++ "read credentials do not match: pid %d, c_pid %d\n",
++ (int) pid, (int) c_pid);
++ goto failed;
++ }
+ GAM_DEBUG(DEBUG_INFO,
+ "Credentials: s_uid %d, c_uid %d, c_gid %d, c_pid %d\n",
+ (int) s_uid, (int) c_uid, (int) c_gid, (int) c_pid);
+@@ -194,7 +205,7 @@ gam_client_conn_check_cred(GIOChannel *
+ }
+
+ if (!gam_client_conn_send_cred(fd)) {
+- GAM_DEBUG(DEBUG_INFO, "Failed to send credential byte to client\n");
++ GAM_DEBUG(DEBUG_INFO, "Failed to send credential bytes to client\n");
+ goto failed;
+ }
+
+@@ -551,12 +562,6 @@ gam_check_secure_path(const char *path)
+ goto cleanup;
+ }
+ #endif
+- if (st.st_mode & (S_IRWXG|S_IRWXO)) {
+- gam_error(DEBUG_INFO,
+- "Socket %s has wrong permissions\n",
+- path);
+- goto cleanup;
+- }
+ /*
+ * Looks good though binding may fail due to an existing server
+ */
+@@ -646,6 +651,18 @@ gam_listen_unix_socket(const char *path)
+ strncpy(&addr.sun_path[0], path, (sizeof(addr) - 4) - 1);
+ umask(0077);
+ #endif
++#if defined(BSDCRED) && defined(LOCAL_CREDS)
++ /* Set the socket to receive credentials. */
++ {
++ int on = 1;
++
++ if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof(on)) < 0) {
++ gam_error(DEBUG_INFO,
++ "Unable to setsockopt() LOCAL_CREDS on %d\n", fd);
++ return(-1);
++ }
++ }
++#endif
+
+ if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ GAM_DEBUG(DEBUG_INFO, "Failed to bind to socket %s\n", path);