From f426fbf746c37da76dd5aae2ecf6593d64678f4a Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Tue, 18 Nov 2008 13:10:20 +0000
Subject: [PATCH] Ident authentication over Unix-domain sockets on Solaris,
 using getpeerucred() function.

Author: Garick Hamlin <ghamlin@isc.upenn.edu>
---
 configure                     |  6 +++--
 configure.in                  |  6 ++---
 doc/src/sgml/client-auth.sgml |  4 ++--
 src/backend/libpq/auth.c      | 42 ++++++++++++++++++++++++++++++++++-
 src/include/pg_config.h.in    |  6 +++++
 5 files changed, 56 insertions(+), 8 deletions(-)

diff --git a/configure b/configure
index 37af429c0f6..eb88c4e76e6 100755
--- a/configure
+++ b/configure
@@ -8925,7 +8925,8 @@ done
 
 
 
-for ac_header in crypt.h dld.h fp_class.h getopt.h ieeefp.h langinfo.h poll.h pwd.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/socket.h sys/shm.h sys/tas.h sys/time.h sys/un.h termios.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h
+
+for ac_header in crypt.h dld.h fp_class.h getopt.h ieeefp.h langinfo.h poll.h pwd.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/socket.h sys/shm.h sys/tas.h sys/time.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
 if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
@@ -15804,7 +15805,8 @@ fi
 
 
 
-for ac_func in cbrt dlopen fcvt fdatasync getpeereid getrlimit memmove poll pstat readlink setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs
+
+for ac_func in cbrt dlopen fcvt fdatasync getpeereid getpeerucred getrlimit memmove poll pstat readlink setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
 { echo "$as_me:$LINENO: checking for $ac_func" >&5
diff --git a/configure.in b/configure.in
index cb01da4bcb3..64b8b4eca3d 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-dnl $PostgreSQL: pgsql/configure.in,v 1.571 2008/10/30 12:28:51 petere Exp $
+dnl $PostgreSQL: pgsql/configure.in,v 1.572 2008/11/18 13:10:20 petere Exp $
 dnl
 dnl Developers, please strive to achieve this order:
 dnl
@@ -955,7 +955,7 @@ AC_SUBST(OSSP_UUID_LIBS)
 ##
 
 dnl sys/socket.h is required by AC_FUNC_ACCEPT_ARGTYPES
-AC_CHECK_HEADERS([crypt.h dld.h fp_class.h getopt.h ieeefp.h langinfo.h poll.h pwd.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/socket.h sys/shm.h sys/tas.h sys/time.h sys/un.h termios.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h])
+AC_CHECK_HEADERS([crypt.h dld.h fp_class.h getopt.h ieeefp.h langinfo.h poll.h pwd.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/socket.h sys/shm.h sys/tas.h sys/time.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h])
 
 # At least on IRIX, cpp test for netinet/tcp.h will fail unless
 # netinet/in.h is included first.
@@ -1134,7 +1134,7 @@ PGAC_VAR_INT_TIMEZONE
 AC_FUNC_ACCEPT_ARGTYPES
 PGAC_FUNC_GETTIMEOFDAY_1ARG
 
-AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getpeereid getrlimit memmove poll pstat readlink setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs])
+AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getpeereid getpeerucred getrlimit memmove poll pstat readlink setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs])
 
 AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
 AC_CHECK_DECLS(posix_fadvise, [], [], [#include <fcntl.h>])
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 93482be6eab..de473f201c0 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.110 2008/10/28 12:10:42 mha Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.111 2008/11/18 13:10:20 petere Exp $ -->
 
 <chapter id="client-authentication">
  <title>Client Authentication</title>
@@ -1005,7 +1005,7 @@ omicron       bryanh            guest1
     Unix-domain sockets (currently <systemitem
     class="osname">Linux</>, <systemitem class="osname">FreeBSD</>,
     <systemitem class="osname">NetBSD</>, <systemitem class="osname">OpenBSD</>, 
-    and <systemitem class="osname">BSD/OS</>), ident authentication can also 
+    <systemitem class="osname">BSD/OS</>, and <systemitem class="osname">Solaris</systemitem>), ident authentication can also 
     be applied to local connections. In this case, no security risk is added by
     using ident authentication; indeed it is a preferable choice for
     local connections on such systems.
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index e89b040b67e..bccb0a516f2 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.170 2008/10/28 12:10:43 mha Exp $
+ *	  $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.171 2008/11/18 13:10:20 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,9 @@
 #include <sys/uio.h>
 #include <sys/ucred.h>
 #endif
+#ifdef HAVE_UCRED_H
+# include <ucred.h>
+#endif
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <unistd.h>
@@ -1611,6 +1614,43 @@ ident_unix(int sock, char *ident_user)
 
 	strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
 
+	return true;
+#elif defined(HAVE_GETPEERUCRED)
+	/* Solaris > 10 */
+	uid_t		uid;
+	struct passwd *pass;
+	ucred_t	   *ucred;
+
+	ucred = NULL; /* must be initialized to NULL */
+	if (getpeerucred(sock, &ucred) == -1)
+	{
+		ereport(LOG,
+				(errcode_for_socket_access(),
+				 errmsg("could not get peer credentials: %m")));
+		return false;
+	}
+
+	if ((uid = ucred_geteuid(ucred)) == -1)
+	{
+		ereport(LOG,
+				(errcode_for_socket_access(),
+				 errmsg("could not get effective UID from peer credentials: %m")));
+		return false;
+	}
+
+	ucred_free(ucred);
+
+	pass = getpwuid(uid);
+	if (pass == NULL)
+	{
+		ereport(LOG,
+			(errmsg("local user with ID %d does not exist",
+					(int) uid)));
+		return false;
+	}
+
+	strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
+
 	return true;
 #elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
 	struct msghdr msg;
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 2314d819659..9f6f21bf817 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -182,6 +182,9 @@
 /* Define to 1 if you have the `getpeereid' function. */
 #undef HAVE_GETPEEREID
 
+/* Define to 1 if you have the `getpeerucred' function. */
+#undef HAVE_GETPEERUCRED
+
 /* Define to 1 if you have the `getpwuid_r' function. */
 #undef HAVE_GETPWUID_R
 
@@ -557,6 +560,9 @@
 /* Define to 1 if you have the external array `tzname'. */
 #undef HAVE_TZNAME
 
+/* Define to 1 if you have the <ucred.h> header file. */
+#undef HAVE_UCRED_H
+
 /* Define to 1 if the system has the type `uint64'. */
 #undef HAVE_UINT64
 
-- 
GitLab