changeset 12887:352999078d83

Added net_getunixcred() to get UNIX socket peer process's UID and GID.
author Timo Sirainen <tss@iki.fi>
date Tue, 05 Apr 2011 12:24:59 +0300
parents 1ff458ba2e4b
children 03b8a8fe1959
files configure.in src/lib/network.c src/lib/network.h
diffstat 3 files changed, 58 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Mon Apr 04 16:08:50 2011 +0300
+++ b/configure.in	Tue Apr 05 12:24:59 2011 +0300
@@ -283,7 +283,7 @@
   sys/quota.h sys/fs/ufs_quota.h ufs/ufs/quota.h jfs/quota.h sys/fs/quota_common.h \
   mntent.h sys/mnttab.h sys/event.h sys/time.h sys/mkdev.h linux/dqblk_xfs.h \
   xfs/xqm.h execinfo.h ucontext.h malloc_np.h sys/utsname.h sys/vmount.h \
-  sys/utsname.h glob.h linux/falloc.h)
+  sys/utsname.h glob.h linux/falloc.h ucred.h)
 
 dnl * gcc specific options
 if test "x$ac_cv_c_compiler_gnu" = "xyes"; then
@@ -380,7 +380,7 @@
 	       strtoull strtoll strtouq strtoq \
 	       setpriority quotactl getmntent kqueue kevent backtrace_symbols \
 	       walkcontext dirfd clearenv malloc_usable_size glob fallocate \
-	       posix_fadvise)
+	       posix_fadvise getpeereid getpeerucred)
 
 AC_CHECK_LIB(rt, clock_gettime, [
   AC_DEFINE(HAVE_CLOCK_GETTIME,, Define if you have the clock_gettime function)
--- a/src/lib/network.c	Mon Apr 04 16:08:50 2011 +0300
+++ b/src/lib/network.c	Tue Apr 05 12:24:59 2011 +0300
@@ -1,5 +1,6 @@
 /* Copyright (c) 1999-2011 Dovecot authors, see the included COPYING file */
 
+#define _GNU_SOURCE /* For Linux's struct ucred */
 #include "lib.h"
 #include "close-keep-errno.h"
 #include "fd-set-nonblock.h"
@@ -12,6 +13,9 @@
 #include <ctype.h>
 #include <sys/un.h>
 #include <netinet/tcp.h>
+#ifdef HAVE_UCRED_H
+#  include <ucred.h> /* for getpeerucred() */
+#endif
 
 union sockaddr_union {
 	struct sockaddr sa;
@@ -686,6 +690,51 @@
 	return 0;
 }
 
+int net_getunixcred(int fd, struct net_unix_cred *cred_r)
+{
+#if defined(SO_PEERCRED)
+	/* Linux */
+	struct ucred ucred;
+	socklen_t len = sizeof(ucred);
+
+	if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) {
+		i_error("getsockopt(SO_PEERCRED) failed: %m");
+		return -1;
+	}
+	cred_r->uid = ucred.uid;
+	cred_r->gid = ucred.gid;
+	return 0;
+#elif defined(HAVE_GETPEEREID)
+	/* OSX 10.4+, FreeBSD 4.6+, OpenBSD 3.0+, NetBSD 5.0+ */
+	if (getpeereid(fd, &cred_r->uid, &cred_r->gid) < 0) {
+		i_error("getpeereid() failed: %m");
+		return -1;
+	}
+	return 0;
+#elif defined(HAVE_GETPEERUCRED)
+	/* Solaris */
+	ucred_t *ucred;
+
+	if (getpeerucred(fd, &ucred) < 0) {
+		i_error("getpeerucred() failed: %m");
+		return -1;
+	}
+	cred_r->uid = ucred_geteuid(ucred);
+	cred_r->gid = ucred_getrgid(ucred);
+	ucred_free(ucred);
+
+	if (cred_r->uid == (uid_t)-1 ||
+	    cred_r->gid == (gid_t)-1) {
+		errno = EINVAL;
+		return -1;
+	}
+	return 0;
+#else
+	errno = EINVAL;
+	return -1;
+#endif
+}
+
 const char *net_ip2addr(const struct ip_addr *ip)
 {
 #ifdef HAVE_IPV6
--- a/src/lib/network.h	Mon Apr 04 16:08:50 2011 +0300
+++ b/src/lib/network.h	Tue Apr 05 12:24:59 2011 +0300
@@ -31,6 +31,11 @@
 };
 ARRAY_DEFINE_TYPE(ip_addr, struct ip_addr);
 
+struct net_unix_cred {
+	uid_t uid;
+	gid_t gid;
+};
+
 /* maxmimum string length of IP address */
 #ifdef HAVE_IPV6
 #  define MAX_IP_LEN INET6_ADDRSTRLEN
@@ -109,6 +114,8 @@
 int net_getpeername(int fd, struct ip_addr *addr, unsigned int *port);
 /* Get UNIX socket name. */
 int net_getunixname(int fd, const char **name_r);
+/* Get UNIX socket peer process's credentials. */
+int net_getunixcred(int fd, struct net_unix_cred *cred_r);
 
 /* Returns ip_addr as string, or NULL if ip is invalid. */
 const char *net_ip2addr(const struct ip_addr *ip);