aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-08-01 23:25:39 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-08-01 23:25:39 +0000
commitbc042e0a775040927b194473b4abf9c48e56d0a5 (patch)
tree081de4fd0d17366b5f7f15cd49fdd175ae75ed24 /src
parent7208518720260735b7c8b1c27f34e5fe08951241 (diff)
downloadpostgresql-bc042e0a775040927b194473b4abf9c48e56d0a5.tar.gz
postgresql-bc042e0a775040927b194473b4abf9c48e56d0a5.zip
Support ident authentication on local (Unix) socket connections, if the
system supports SO_PEERCRED requests for Unix sockets. This is an amalgamation of patches submitted by Helge Bahmann and Oliver Elphick, with some editorializing by yours truly.
Diffstat (limited to 'src')
-rw-r--r--src/backend/libpq/auth.c8
-rw-r--r--src/backend/libpq/hba.c136
-rw-r--r--src/backend/libpq/pg_hba.conf.sample35
-rw-r--r--src/include/config.h.in5
-rw-r--r--src/include/libpq/hba.h5
5 files changed, 140 insertions, 49 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 6cf122119f1..77bcc4ef236 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.54 2001/07/21 00:29:56 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.55 2001/08/01 23:25:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -494,8 +494,7 @@ ClientAuthentication(Port *port)
break;
case uaIdent:
- status = authident(&port->raddr.in, &port->laddr.in,
- port->user, port->auth_arg);
+ status = authident(port);
break;
case uaPassword:
@@ -654,8 +653,7 @@ map_old_to_new(Port *port, UserAuth old, int status)
break;
case uaIdent:
- status = authident(&port->raddr.in, &port->laddr.in,
- port->user, port->auth_arg);
+ status = authident(port);
break;
case uaPassword:
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index a2f31c9244a..905cb61121f 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -5,7 +5,7 @@
* wherein you authenticate a user by seeing what IP address the system
* says he comes from and possibly using ident).
*
- * $Id: hba.c,v 1.57 2001/07/31 22:55:45 tgl Exp $
+ * $Id: hba.c,v 1.58 2001/08/01 23:25:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -286,12 +286,25 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
/*
* Disallow auth methods that need AF_INET sockets to work.
+ * Allow "ident" if we can get the identity of the connection
+ * peer on Unix domain sockets from the OS.
*/
- if (!*error_p &&
- (port->auth_method == uaIdent ||
- port->auth_method == uaKrb4 ||
- port->auth_method == uaKrb5))
+ if (port->auth_method == uaKrb4 ||
+ port->auth_method == uaKrb5)
goto hba_syntax;
+#ifndef HAVE_SO_PEERCRED
+ if (port->auth_method == uaIdent)
+ {
+ /* Give a special error message for this case... */
+ snprintf(PQerrormsg, PQERRORMSG_LENGTH,
+ "parse_hba: \"ident\" auth is not supported on local connections on this platform\n");
+ fputs(PQerrormsg, stderr);
+ pqdebug("%s", PQerrormsg);
+
+ *error_p = true;
+ return;
+ }
+#endif
/*
* If this record doesn't match the parameters of the connection
@@ -732,12 +745,12 @@ interpret_ident_response(char *ident_response,
*
* But iff we're unable to get the information from ident, return false.
*/
-static int
-ident(const struct in_addr remote_ip_addr,
- const struct in_addr local_ip_addr,
- const ushort remote_port,
- const ushort local_port,
- char *ident_user)
+static bool
+ident_inet(const struct in_addr remote_ip_addr,
+ const struct in_addr local_ip_addr,
+ const ushort remote_port,
+ const ushort local_port,
+ char *ident_user)
{
int sock_fd, /* File descriptor for socket on which we
* talk to Ident */
@@ -848,28 +861,103 @@ ident(const struct in_addr remote_ip_addr,
return ident_return;
}
+#ifdef HAVE_SO_PEERCRED
+/*
+ * Ask kernel about the credentials of the connecting process and
+ * determine the symbolic name of the corresponding user.
+ *
+ * Returns either true and the username put into "ident_user",
+ * or false if we were unable to determine the username.
+ */
+static bool
+ident_unix(int sock, char *ident_user)
+{
+ struct ucred peercred;
+ socklen_t so_len;
+ struct passwd *pass;
+
+#ifdef SO_PASSCRED
+ int passcred = -1;
+
+ so_len = sizeof(passcred);
+ if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &passcred, so_len) != 0)
+ {
+ /* We could not set the socket to pass credentials */
+ snprintf(PQerrormsg, PQERRORMSG_LENGTH,
+ "Could not set the UNIX socket to pass credentials: %s\n",
+ strerror(errno));
+ fputs(PQerrormsg, stderr);
+ pqdebug("%s", PQerrormsg);
+ return false;
+ }
+#endif /* SO_PASSCRED */
+
+ errno = 0;
+ so_len = sizeof(peercred);
+ if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred))
+ {
+ /* We didn't get a valid credentials struct. */
+ snprintf(PQerrormsg, PQERRORMSG_LENGTH,
+ "Could not get valid credentials from the UNIX socket: %s\n",
+ strerror(errno));
+ fputs(PQerrormsg, stderr);
+ pqdebug("%s", PQerrormsg);
+ return false;
+ }
+
+ /* Convert UID to user login name */
+ pass = getpwuid(peercred.uid);
+
+ if (pass == NULL)
+ {
+ /* Error - no username with the given uid */
+ snprintf(PQerrormsg, PQERRORMSG_LENGTH,
+ "There is no entry in /etc/passwd with the socket's uid\n");
+ fputs(PQerrormsg, stderr);
+ pqdebug("%s", PQerrormsg);
+ return false;
+ }
+
+ StrNCpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX);
+
+ return true;
+}
+#endif
/*
- * Talk to the ident server on the remote host and find out who owns the
- * connection described by "port". Then look in the usermap file under
- * the usermap *auth_arg and see if that user is equivalent to
- * Postgres user *user.
+ * Determine the username of the initiator of the connection described
+ * by "port". Then look in the usermap file under the usermap
+ * port->auth_arg and see if that user is equivalent to Postgres user
+ * port->user.
*
- * Return STATUS_OK if yes.
+ * Return STATUS_OK if yes, STATUS_ERROR if no match (or couldn't get info).
*/
int
-authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr,
- const char *pg_user, const char *auth_arg)
+authident(hbaPort *port)
{
- /* We were unable to get ident to give us a username */
char ident_user[IDENT_USERNAME_MAX + 1];
- /* The username returned by ident */
- if (!ident(raddr->sin_addr, laddr->sin_addr,
- raddr->sin_port, laddr->sin_port, ident_user))
- return STATUS_ERROR;
+ switch (port->raddr.sa.sa_family)
+ {
+ case AF_INET:
+ if (!ident_inet(port->raddr.in.sin_addr,
+ port->laddr.in.sin_addr,
+ port->raddr.in.sin_port,
+ port->laddr.in.sin_port, ident_user))
+ return STATUS_ERROR;
+ break;
+#ifdef HAVE_SO_PEERCRED
+ case AF_UNIX:
+ if (!ident_unix(port->sock, ident_user))
+ return STATUS_ERROR;
+ break;
+#endif
+ default:
+ return STATUS_ERROR;
+ }
- if (check_ident_usermap(auth_arg, pg_user, ident_user))
+ if (check_ident_usermap(port->auth_arg, port->user, ident_user))
return STATUS_OK;
else
return STATUS_ERROR;
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
index 9c8d8ae74d5..7dc39ee67b9 100644
--- a/src/backend/libpq/pg_hba.conf.sample
+++ b/src/backend/libpq/pg_hba.conf.sample
@@ -126,28 +126,31 @@
# usernames stored in secondary password files but not
# secondary passwords.
#
-# ident: Authentication is done by the ident server on the local
-# (127.0.0.1) or remote host. AUTH_ARGUMENT is required and
-# maps names found in the $PGDATA/pg_ident.conf file. The
-# connection is accepted if the file contains an entry for
-# this map name with the ident-supplied username and the
-# requested PostgreSQL username. The special map name
-# "sameuser" indicates an implied map (not in pg_ident.conf)
-# that maps each ident username to the identical PostgreSQL
-# username.
-#
-# krb4: Kerberos V4 authentication is used.
-#
-# krb5: Kerberos V5 authentication is used.
+# ident: For TCP/IP connections, authentication is done by contacting
+# the ident server on the client host. (CAUTION: this is only
+# as secure as the client machine!) On machines that support
+# SO_PEERCRED socket requests, this method also works for
+# local Unix-domain connections. AUTH_ARGUMENT is required:
+# it determines how to map remote user names to Postgres user
+# names. The AUTH_ARGUMENT is a map name found in the
+# $PGDATA/pg_ident.conf file. The connection is accepted if
+# that file contains an entry for this map name with the
+# ident-supplied username and the requested Postgres username.
+# The special map name "sameuser" indicates an implied map
+# (not in pg_ident.conf) that maps each ident username to the
+# identical PostgreSQL username.
+#
+# krb4: Kerberos V4 authentication is used. Allowed only for
+# TCP/IP connections, not for local UNIX-domain sockets.
+#
+# krb5: Kerberos V5 authentication is used. Allowed only for
+# TCP/IP connections, not for local UNIX-domain sockets.
#
# reject: Reject the connection. This is used to reject certain hosts
# that are part of a network specified later in the file.
# To be effective, "reject" must appear before the later
# entries.
#
-# Local UNIX-domain socket connections support only the AUTH_TYPEs of
-# "trust", "password", "crypt", and "reject".
-#
#
#
# Examples
diff --git a/src/include/config.h.in b/src/include/config.h.in
index 70e9d6aa92b..971a32a3ace 100644
--- a/src/include/config.h.in
+++ b/src/include/config.h.in
@@ -8,7 +8,7 @@
* or in config.h afterwards. Of course, if you edit config.h, then your
* changes will be overwritten the next time you run configure.
*
- * $Id: config.h.in,v 1.168 2001/07/16 05:07:00 tgl Exp $
+ * $Id: config.h.in,v 1.169 2001/08/01 23:25:39 tgl Exp $
*/
#ifndef CONFIG_H
@@ -685,6 +685,9 @@ extern int fdatasync(int fildes);
/* Define if you have on_exit() */
#undef HAVE_ON_EXIT
+/* Define if you have SO_PEERCRED */
+#undef HAVE_SO_PEERCRED
+
/*
*------------------------------------------------------------------------
* Part 4: pull in system-specific declarations.
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index c1524946e3d..0d792da3d35 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -4,7 +4,7 @@
* Interface to hba.c
*
*
- * $Id: hba.h,v 1.21 2001/07/31 22:55:45 tgl Exp $
+ * $Id: hba.h,v 1.22 2001/08/01 23:25:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -41,8 +41,7 @@ typedef enum UserAuth
typedef struct Port hbaPort;
extern int hba_getauthmethod(hbaPort *port);
-extern int authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr,
- const char *postgres_username, const char *auth_arg);
+extern int authident(hbaPort *port);
extern void load_hba_and_ident(void);
#endif