Skip site navigation (1) Skip section navigation (2)

Add another AUTHTYPE for UNIX-domain connections

From: Anton Berezin <tobez(at)tobez(dot)org>
To: pgsql-patches(at)postgresql(dot)org
Subject: Add another AUTHTYPE for UNIX-domain connections
Date: 2001-12-03 00:58:04
Message-ID: 20011203015804.A42199@heechee.tobez.org (view raw or flat)
Thread:
Lists: pgsql-patches
Hi,

On some platforms, it is possible to reliably determine the effective
credentials of a UNIX-domain peer.  Such functionality is not to be
missed from the PostgreSQL host-based authentication.  Its use allows
one to combine the convenience of the `trust' authmethod with a strict
checking of the connectee's identity.

I have chosen to re-use the existing pg_ident.conf mechanism for mapping
system user names to Postgres user names;  this should not present any
problems since `ident' authmethod is only applicable over TCP
connections, and the new `user' authmethod only works for local
connections;  one can always use different map names if one needs both
methods to co-exist (which is in my opinion very unlikely, considering
that the getpeereid() is a reliable method and that we all know how
reliable ident is).

The patch below implements this functionality, including necessary
changes to configure.in;  the only thing missing is documentation
patches - something I do not feel qualified to do, since English is not
my native language.

The patch is against 7.1.3 tarball - though I would not be surprised if
it applies fine against the current development version.  I verified
that it works as expected on FreeBSD 5.0-current.  I gather it should
work equally well on other platforms that have getpeereid(), which I
believe are at this moment OpenBSD-current and NetBSD-current.

Cheers,
%Anton.



diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/configure ./configure
--- /tmp/postgresql-7.1.3/configure	Thu Aug 16 20:36:31 2001
+++ ./configure	Mon Dec  3 01:53:19 2001
@@ -5472,7 +5472,7 @@ EOF
 
 fi
 
-for ac_func in fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen fdatasync
+for ac_func in fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen fdatasync getpeereid
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
 echo "configure:5479: checking for $ac_func" >&5
diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/configure.in ./configure.in
--- /tmp/postgresql-7.1.3/configure.in	Sun Dec  2 21:58:22 2001
+++ ./configure.in	Mon Dec  3 01:53:20 2001
@@ -759,7 +759,7 @@ PGAC_VAR_INT_TIMEZONE
 AC_FUNC_ACCEPT_ARGTYPES
 PGAC_FUNC_GETTIMEOFDAY_1ARG
 
-AC_CHECK_FUNCS([fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen fdatasync])
+AC_CHECK_FUNCS([fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen fdatasync getpeereid])
 
 dnl Check whether <unistd.h> declares fdatasync().
 AC_EGREP_HEADER(fdatasync, unistd.h, AC_DEFINE(HAVE_FDATASYNC_DECL))
diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/src/backend/libpq/auth.c ./src/backend/libpq/auth.c
--- /tmp/postgresql-7.1.3/src/backend/libpq/auth.c	Thu Mar 22 04:59:30 2001
+++ ./src/backend/libpq/auth.c	Mon Dec  3 01:53:20 2001
@@ -439,6 +439,9 @@ auth_failed(Port *port)
 		case uaCrypt:
 			authmethod = "Password";
 			break;
+		case uaUser:
+			authmethod = "Peer eid";
+			break;
 	}
 
 	sprintf(buffer, "%s authentication failed for user '%s'",
@@ -536,6 +539,17 @@ be_recvauth(Port *port)
 
 				break;
 
+#ifdef HAVE_GETPEEREID
+			case uaUser:
+				if (authuser(port->sock, port->user, port->auth_arg) == STATUS_OK)
+				{
+					areq = AUTH_REQ_OK;
+					auth_handler = handle_done_auth;
+				}
+
+				break;
+#endif
+
 			case uaPassword:
 				areq = AUTH_REQ_PASSWORD;
 				auth_handler = handle_password_auth;
@@ -762,6 +776,7 @@ map_old_to_new(Port *port, UserAuth old,
 	{
 			case uaCrypt:
 			case uaReject:
+			case uaUser:
 			status = STATUS_ERROR;
 			break;
 
diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/src/backend/libpq/hba.c ./src/backend/libpq/hba.c
--- /tmp/postgresql-7.1.3/src/backend/libpq/hba.c	Sat Feb 10 03:31:26 2001
+++ ./src/backend/libpq/hba.c	Mon Dec  3 01:53:20 2001
@@ -125,6 +125,10 @@ read_hba_entry2(FILE *file, UserAuth *us
 		*userauth_p = uaReject;
 	else if (strcmp(buf, "crypt") == 0)
 		*userauth_p = uaCrypt;
+#ifdef HAVE_GETPEEREID
+	else if (strcmp(buf, "user") == 0)
+		*userauth_p = uaUser;
+#endif
 	else
 	{
 		*error_p = true;
@@ -280,6 +284,11 @@ process_hba_record(FILE *file, hbaPort *
 
 		read_hba_entry2(file, &port->auth_method, port->auth_arg, error_p);
 
+#ifdef HAVE_GETPEEREID
+		if (!*error_p && port->auth_method == uaUser)
+			*error_p = true;
+#endif
+
 		if (*error_p)
 			goto syntax;
 
@@ -781,8 +790,8 @@ verify_against_usermap(const char *pguse
 		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
 			   "verify_against_usermap: hba configuration file does not "
 		   "have the usermap field filled in in the entry that pertains "
-		  "to this connection.  That field is essential for Ident-based "
-				 "authentication.\n");
+		    "to this connection.  That field is essential for Ident- or "
+				 "user-based authentication.\n");
 		fputs(PQerrormsg, stderr);
 		pqdebug("%s", PQerrormsg);
 	}
@@ -867,6 +876,39 @@ authident(struct sockaddr_in * raddr, st
 	return checks_out ? STATUS_OK : STATUS_ERROR;
 }
 
+int
+authuser(int sock, const char *postgres_username,
+		 const char *auth_arg)
+{
+/*---------------------------------------------------------------------------
+  Get the effective credentials of a UNIX-domain peer.  Then lookup the
+  local UNIX user password entry.  Then look in the usermap file under
+  the usermap *auth_arg and see if that user is equivalent to
+  Postgres user *user.
+
+  Return STATUS_OK if yes.
+---------------------------------------------------------------------------*/
+#ifdef HAVE_GETPEEREID
+	bool		checks_out;
+	uid_t		euid;
+	gid_t		egid;
+	struct passwd *pw;
+
+	if (getpeereid(sock, &euid, &egid) != 0)
+		return STATUS_ERROR;
+
+	setpwent();
+	if ((pw = getpwuid(euid)) == NULL)
+		return STATUS_ERROR;
+
+	verify_against_usermap(postgres_username, pw->pw_name, auth_arg,
+						   &checks_out);
+
+	return checks_out ? STATUS_OK : STATUS_ERROR;
+#else
+	return STATUS_ERROR;
+#endif
+}
 
 #ifdef CYR_RECODE
 #define CHARSET_FILE "charset.conf"
diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/src/backend/libpq/pg_hba.conf.sample ./src/backend/libpq/pg_hba.conf.sample
--- /tmp/postgresql-7.1.3/src/backend/libpq/pg_hba.conf.sample	Tue Nov 21 21:44:32 2000
+++ ./src/backend/libpq/pg_hba.conf.sample	Mon Dec  3 01:53:20 2001
@@ -121,10 +121,17 @@
 #
 #   krb5:   	Kerberos V5 authentication is used.
 #
+#   user: 	The system user identity is verified using getpeereid()
+#		system call.  This is only supported for local (UNIX
+#		socket) connections, and only on some platforms.  The
+#		correspondence between local system users and the
+#		requested PostgreSQL username is established using the
+#		same method as for "ident" AUTHTYPE.
+#
 #   reject: 	Reject the connection.
 #
 # Local (UNIX socket) connections support only AUTHTYPEs "trust",
-# "password", "crypt", and "reject".
+# "password", "crypt", "user", and "reject".
 
 
 # Examples
@@ -146,6 +153,11 @@
 # host identifies him as (typically his Unix username):
 #
 # host       template1   192.168.93.0  255.255.255.0      ident     sameuser
+# 
+# Allow any existing local unix user to connect to database "template1"
+# using the same PostgreSQL username:
+#
+# local      template1                                    user      sameuser
 # 
 # Allow a user from host 192.168.12.10 to connect to database "template1"
 # if the user's password in pg_shadow is correctly supplied:
diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/src/include/config.h.in ./src/include/config.h.in
--- /tmp/postgresql-7.1.3/src/include/config.h.in	Sun Apr 15 00:55:02 2001
+++ ./src/include/config.h.in	Mon Dec  3 01:53:20 2001
@@ -388,6 +388,9 @@
 /* Define if you have the setproctitle function.  */
 #undef HAVE_SETPROCTITLE
 
+/* Set to 1 if you have the getpeereid function. */
+#undef HAVE_GETPEEREID
+
 /* Define if you have the pstat function. */
 #undef HAVE_PSTAT
 
diff -u -ruN --show-c-function /tmp/postgresql-7.1.3/src/include/libpq/hba.h ./src/include/libpq/hba.h
--- /tmp/postgresql-7.1.3/src/include/libpq/hba.h	Thu Mar 22 05:00:47 2001
+++ ./src/include/libpq/hba.h	Mon Dec  3 01:53:20 2001
@@ -35,7 +35,8 @@ typedef enum UserAuth
 	uaTrust,
 	uaIdent,
 	uaPassword,
-	uaCrypt
+	uaCrypt,
+	uaUser
 } UserAuth;
 
 typedef struct Port hbaPort;
@@ -43,5 +44,7 @@ typedef struct Port hbaPort;
 int			hba_getauthmethod(hbaPort *port);
 int authident(struct sockaddr_in * raddr, struct sockaddr_in * laddr,
 		  const char *postgres_username, const char *auth_arg);
+int authuser(int sock, const char *postgres_username,
+		const char *auth_arg);
 
 #endif



-- 
| Anton Berezin                |      FreeBSD: The power to serve |
| catpipe Systems ApS   _ _ |_ |           http://www.FreeBSD.org |
| tobez(at)catpipe(dot)net    (_(_||  |                tobez(at)FreeBSD(dot)org | 
| +45 7021 0050                |         Private: tobez(at)tobez(dot)org |

Responses

pgsql-patches by date

Next:From: Tom LaneDate: 2001-12-03 01:25:48
Subject: Re: Add another AUTHTYPE for UNIX-domain connections
Previous:From: Peter EisentrautDate: 2001-12-02 11:42:14
Subject: Re: Microtiming patch for psql (reprise)

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group