-#line 7915 "configure"
+#line 7943 "configure"
#include "confdefs.h"
#include
struct { char filler; double field; } mystruct;
exit(0);
}
EOF
-if { (eval echo configure:7927: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:7955: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
pgac_cv_alignof_double=`cat conftestval`
else
echo $ac_n "checking for POSIX signal interface""... $ac_c" 1>&6
-echo "configure:7965: checking for POSIX signal interface" >&5
+echo "configure:7993: checking for POSIX signal interface" >&5
if eval "test \"`echo '$''{'pgac_cv_func_posix_signals'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <
-#line 7970 "configure"
+#line 7998 "configure"
#include "confdefs.h"
#include
sigaction(0, &act, &oact);
; return 0; }
EOF
-if { (eval echo configure:7981: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8009: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
pgac_cv_func_posix_signals=yes
else
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8011: checking for $ac_word" >&5
+echo "configure:8039: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_TCLSH'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
done
echo $ac_n "checking for tclConfig.sh""... $ac_c" 1>&6
-echo "configure:8047: checking for tclConfig.sh" >&5
+echo "configure:8075: checking for tclConfig.sh" >&5
# Let user override test
if test -z "$TCL_CONFIG_SH"; then
pgac_test_dirs="$with_tclconfig"
# Check for Tk configuration script tkConfig.sh
if test "$with_tk" = yes; then
echo $ac_n "checking for tkConfig.sh""... $ac_c" 1>&6
-echo "configure:8080: checking for tkConfig.sh" >&5
+echo "configure:8108: checking for tkConfig.sh" >&5
# Let user override test
if test -z "$TK_CONFIG_SH"; then
pgac_test_dirs="$with_tkconfig $with_tclconfig"
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8119: checking for $ac_word" >&5
+echo "configure:8147: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_NSGMLS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8155: checking for $ac_word" >&5
+echo "configure:8183: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_JADE'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo $ac_n "checking for DocBook V3.1""... $ac_c" 1>&6
-echo "configure:8186: checking for DocBook V3.1" >&5
+echo "configure:8214: checking for DocBook V3.1" >&5
if eval "test \"`echo '$''{'pgac_cv_check_docbook'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo $ac_n "checking for DocBook stylesheets""... $ac_c" 1>&6
-echo "configure:8219: checking for DocBook stylesheets" >&5
+echo "configure:8247: checking for DocBook stylesheets" >&5
if eval "test \"`echo '$''{'pgac_cv_path_stylesheets'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8258: checking for $ac_word" >&5
+echo "configure:8286: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_SGMLSPL'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
dnl Check whether declares fdatasync().
AC_EGREP_HEADER(fdatasync, unistd.h, AC_DEFINE(HAVE_FDATASYNC_DECL))
+AC_MSG_CHECKING([for SO_PEERCRED])
+AC_EGREP_CPP(HAVE_SO_PEERCRED,
+#include
+#ifdef SO_PEERCRED
+HAVE_SO_PEERCRED
+#endif
+],
+[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SO_PEERCRED)
+],
+[AC_MSG_RESULT(no)])
+
AC_CACHE_CHECK([for PS_STRINGS], [pgac_cv_var_PS_STRINGS],
[AC_TRY_LINK(
[#include
-
+
Client Authentication
ident
+ The identity of the user as determined on login to the
+ operating system is used by
Postgres
+ to determine whether the user
+ is allowed to connect as the requested database user.
+ For TCP/IP connections the user's identity is determined by
+ contacting the ident server on the client
+ host. (Note that this is only as reliable as the remote ident
+ server; ident authentication should never be used for remote hosts
+ whose administrators are not trustworthy.)
+ On operating systems
+ supporting SO_PEERCRED requests for Unix domain sockets,
+ ident authentication is possible for local connections;
+ the system is then asked for the connecting user's identity.
+
- The ident server on the client host is asked for the identity
- of the connecting user.
Postgres
- then verifies whether the so identified operating system user
- is allowed to connect as the database user that is requested.
- This is only available for TCP/IP connections. It can be used
- on the local machine by specifying the localhost address 127.0.0.1.
-
+ On systems without SO_PEERCRED requests, ident authentication
+ is only available for TCP/IP connections. As a workaround,
+ it is possible to
+ specify the localhost address 127.0.0.1 and make connections
+ to this address.
+
The authentication option following
the ident> keyword specifies the name of an
The pg_hba.conf file is loaded only on startup
and when the
postmaster> receives a SIGHUP signal. If
you edit the file on an active system, you will need to issue a
- SIGHUP to the
postmaster> using kill>.
+ SIGHUP to the
postmaster> using kill>
+ to make it re-read the file.
You must trust the machine running the ident server.
+ On systems supporting SO_PEERCRED requests for Unix-domain sockets,
+ 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 such a system.
+
+
When using ident-based authentication, after having determined the
- operating system user that initiated the connection,
-
Postgres determines as what database
- system user he may connect. This is controlled by the ident map
+ name of the operating system user that initiated the connection,
+
Postgres checks whether that user is allowed
+ to connect as the database user he is requesting to connect as.
+ This is controlled by the ident map
argument that follows the ident> keyword in the
pg_hba.conf file. The simplest ident map is
sameuser, which allows any operating system
The other two fields specify which operating system user is
allowed to connect as which database user. The same
map-name> can be used repeatedly to specify more
- user-mappings. There is also no restriction regarding how many
- database users a given operating system may correspond to and vice
+ user-mappings within a single map. There is no restriction regarding
+ how many
+ database users a given operating system user may correspond to and vice
versa.
if you don't specify a database name, it defaults to the database
user name, which may or may not be the right thing.
+
+ Note that the postmaster's stderr log may contain more information
+ about an authentication failure than is reported to the client.
+ If you are confused about the reason for a failure, check the log.
+
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
break;
case uaIdent:
- status = authident(&port->raddr.in, &port->laddr.in,
- port->user, port->auth_arg);
+ status = authident(port);
break;
case uaPassword:
break;
case uaIdent:
- status = authident(&port->raddr.in, &port->laddr.in,
- port->user, port->auth_arg);
+ status = authident(port);
break;
case uaPassword:
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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
*
* 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 */
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;
# 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
* 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
/* 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.
* 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 $
*
*-------------------------------------------------------------------------
*/
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