Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit bc042e0

Browse files
committed
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.
1 parent 7208518 commit bc042e0

File tree

8 files changed

+360
-198
lines changed

8 files changed

+360
-198
lines changed

configure

Lines changed: 163 additions & 135 deletions
Large diffs are not rendered by default.

configure.in

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,19 @@ AC_CHECK_FUNCS([fcvt getopt_long memmove pstat setproctitle setsid sigprocmask s
801801
dnl Check whether <unistd.h> declares fdatasync().
802802
AC_EGREP_HEADER(fdatasync, unistd.h, AC_DEFINE(HAVE_FDATASYNC_DECL))
803803

804+
AC_MSG_CHECKING([for SO_PEERCRED])
805+
AC_EGREP_CPP(HAVE_SO_PEERCRED,
806+
#include <sys/socket.h>
807+
#ifdef SO_PEERCRED
808+
HAVE_SO_PEERCRED
809+
#endif
810+
],
811+
[
812+
AC_MSG_RESULT(yes)
813+
AC_DEFINE(HAVE_SO_PEERCRED)
814+
],
815+
[AC_MSG_RESULT(no)])
816+
804817
AC_CACHE_CHECK([for PS_STRINGS], [pgac_cv_var_PS_STRINGS],
805818
[AC_TRY_LINK(
806819
[#include <machine/vmparam.h>

doc/src/sgml/client-auth.sgml

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.14 2001/08/01 00:48:52 momjian Exp $ -->
1+
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.15 2001/08/01 23:25:39 tgl Exp $ -->
22

33
<chapter id="client-authentication">
44
<title>Client Authentication</title>
@@ -237,14 +237,28 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
237237
<varlistentry>
238238
<term>ident</term>
239239
<listitem>
240+
<para>
241+
The identity of the user as determined on login to the
242+
operating system is used by <productname>Postgres</productname>
243+
to determine whether the user
244+
is allowed to connect as the requested database user.
245+
For TCP/IP connections the user's identity is determined by
246+
contacting the <firstterm>ident</firstterm> server on the client
247+
host. (Note that this is only as reliable as the remote ident
248+
server; ident authentication should never be used for remote hosts
249+
whose administrators are not trustworthy.)
250+
On operating systems
251+
supporting SO_PEERCRED requests for Unix domain sockets,
252+
ident authentication is possible for local connections;
253+
the system is then asked for the connecting user's identity.
254+
</para>
240255
<para>
241-
The ident server on the client host is asked for the identity
242-
of the connecting user. <productname>Postgres</productname>
243-
then verifies whether the so identified operating system user
244-
is allowed to connect as the database user that is requested.
245-
This is only available for TCP/IP connections. It can be used
246-
on the local machine by specifying the localhost address 127.0.0.1.
247-
</para>
256+
On systems without SO_PEERCRED requests, ident authentication
257+
is only available for TCP/IP connections. As a workaround,
258+
it is possible to
259+
specify the localhost address 127.0.0.1 and make connections
260+
to this address.
261+
</para>
248262
<para>
249263
The <replaceable>authentication option</replaceable> following
250264
the <literal>ident</> keyword specifies the name of an
@@ -283,7 +297,8 @@ hostssl <replaceable>database</replaceable> <replaceable>IP-address</replaceable
283297
The <filename>pg_hba.conf</filename> file is loaded only on startup
284298
and when the <application>postmaster</> receives a SIGHUP signal. If
285299
you edit the file on an active system, you will need to issue a
286-
SIGHUP to the <application>postmaster</> using <application>kill</>.
300+
SIGHUP to the <application>postmaster</> using <application>kill</>
301+
to make it re-read the file.
287302
</para>
288303

289304
<para>
@@ -563,11 +578,19 @@ host all 192.168.0.0 255.255.0.0 ident omicron
563578
You must trust the machine running the ident server.
564579
</para>
565580

581+
<para>
582+
On systems supporting SO_PEERCRED requests for Unix-domain sockets,
583+
ident authentication can also be applied to local connections. In this
584+
case, no security risk is added by using ident authentication; indeed
585+
it is a preferable choice for such a system.
586+
</para>
587+
566588
<para>
567589
When using ident-based authentication, after having determined the
568-
operating system user that initiated the connection,
569-
<productname>Postgres</productname> determines as what database
570-
system user he may connect. This is controlled by the ident map
590+
name of the operating system user that initiated the connection,
591+
<productname>Postgres</productname> checks whether that user is allowed
592+
to connect as the database user he is requesting to connect as.
593+
This is controlled by the ident map
571594
argument that follows the <literal>ident</> keyword in the
572595
<filename>pg_hba.conf</filename> file. The simplest ident map is
573596
<literal>sameuser</literal>, which allows any operating system
@@ -588,8 +611,9 @@ host all 192.168.0.0 255.255.0.0 ident omicron
588611
The other two fields specify which operating system user is
589612
allowed to connect as which database user. The same
590613
<replaceable>map-name</> can be used repeatedly to specify more
591-
user-mappings. There is also no restriction regarding how many
592-
database users a given operating system may correspond to and vice
614+
user-mappings within a single map. There is no restriction regarding
615+
how many
616+
database users a given operating system user may correspond to and vice
593617
versa.
594618
</para>
595619

@@ -669,6 +693,12 @@ FATAL 1: Database "testdb" does not exist in the system catalog.
669693
if you don't specify a database name, it defaults to the database
670694
user name, which may or may not be the right thing.
671695
</para>
696+
697+
<para>
698+
Note that the postmaster's stderr log may contain more information
699+
about an authentication failure than is reported to the client.
700+
If you are confused about the reason for a failure, check the log.
701+
</para>
672702
</sect1>
673703

674704
</chapter>

src/backend/libpq/auth.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.54 2001/07/21 00:29:56 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.55 2001/08/01 23:25:39 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -494,8 +494,7 @@ ClientAuthentication(Port *port)
494494
break;
495495

496496
case uaIdent:
497-
status = authident(&port->raddr.in, &port->laddr.in,
498-
port->user, port->auth_arg);
497+
status = authident(port);
499498
break;
500499

501500
case uaPassword:
@@ -654,8 +653,7 @@ map_old_to_new(Port *port, UserAuth old, int status)
654653
break;
655654

656655
case uaIdent:
657-
status = authident(&port->raddr.in, &port->laddr.in,
658-
port->user, port->auth_arg);
656+
status = authident(port);
659657
break;
660658

661659
case uaPassword:

src/backend/libpq/hba.c

Lines changed: 112 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* wherein you authenticate a user by seeing what IP address the system
66
* says he comes from and possibly using ident).
77
*
8-
* $Id: hba.c,v 1.57 2001/07/31 22:55:45 tgl Exp $
8+
* $Id: hba.c,v 1.58 2001/08/01 23:25:39 tgl Exp $
99
*
1010
*-------------------------------------------------------------------------
1111
*/
@@ -286,12 +286,25 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
286286

287287
/*
288288
* Disallow auth methods that need AF_INET sockets to work.
289+
* Allow "ident" if we can get the identity of the connection
290+
* peer on Unix domain sockets from the OS.
289291
*/
290-
if (!*error_p &&
291-
(port->auth_method == uaIdent ||
292-
port->auth_method == uaKrb4 ||
293-
port->auth_method == uaKrb5))
292+
if (port->auth_method == uaKrb4 ||
293+
port->auth_method == uaKrb5)
294294
goto hba_syntax;
295+
#ifndef HAVE_SO_PEERCRED
296+
if (port->auth_method == uaIdent)
297+
{
298+
/* Give a special error message for this case... */
299+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
300+
"parse_hba: \"ident\" auth is not supported on local connections on this platform\n");
301+
fputs(PQerrormsg, stderr);
302+
pqdebug("%s", PQerrormsg);
303+
304+
*error_p = true;
305+
return;
306+
}
307+
#endif
295308

296309
/*
297310
* If this record doesn't match the parameters of the connection
@@ -732,12 +745,12 @@ interpret_ident_response(char *ident_response,
732745
*
733746
* But iff we're unable to get the information from ident, return false.
734747
*/
735-
static int
736-
ident(const struct in_addr remote_ip_addr,
737-
const struct in_addr local_ip_addr,
738-
const ushort remote_port,
739-
const ushort local_port,
740-
char *ident_user)
748+
static bool
749+
ident_inet(const struct in_addr remote_ip_addr,
750+
const struct in_addr local_ip_addr,
751+
const ushort remote_port,
752+
const ushort local_port,
753+
char *ident_user)
741754
{
742755
int sock_fd, /* File descriptor for socket on which we
743756
* talk to Ident */
@@ -848,28 +861,103 @@ ident(const struct in_addr remote_ip_addr,
848861
return ident_return;
849862
}
850863

864+
#ifdef HAVE_SO_PEERCRED
865+
/*
866+
* Ask kernel about the credentials of the connecting process and
867+
* determine the symbolic name of the corresponding user.
868+
*
869+
* Returns either true and the username put into "ident_user",
870+
* or false if we were unable to determine the username.
871+
*/
872+
static bool
873+
ident_unix(int sock, char *ident_user)
874+
{
875+
struct ucred peercred;
876+
socklen_t so_len;
877+
struct passwd *pass;
878+
879+
#ifdef SO_PASSCRED
880+
int passcred = -1;
881+
882+
so_len = sizeof(passcred);
883+
if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &passcred, so_len) != 0)
884+
{
885+
/* We could not set the socket to pass credentials */
886+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
887+
"Could not set the UNIX socket to pass credentials: %s\n",
888+
strerror(errno));
889+
fputs(PQerrormsg, stderr);
890+
pqdebug("%s", PQerrormsg);
891+
return false;
892+
}
893+
#endif /* SO_PASSCRED */
894+
895+
errno = 0;
896+
so_len = sizeof(peercred);
897+
if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
898+
so_len != sizeof(peercred))
899+
{
900+
/* We didn't get a valid credentials struct. */
901+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
902+
"Could not get valid credentials from the UNIX socket: %s\n",
903+
strerror(errno));
904+
fputs(PQerrormsg, stderr);
905+
pqdebug("%s", PQerrormsg);
906+
return false;
907+
}
908+
909+
/* Convert UID to user login name */
910+
pass = getpwuid(peercred.uid);
911+
912+
if (pass == NULL)
913+
{
914+
/* Error - no username with the given uid */
915+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
916+
"There is no entry in /etc/passwd with the socket's uid\n");
917+
fputs(PQerrormsg, stderr);
918+
pqdebug("%s", PQerrormsg);
919+
return false;
920+
}
921+
922+
StrNCpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX);
923+
924+
return true;
925+
}
926+
#endif
851927

852928
/*
853-
* Talk to the ident server on the remote host and find out who owns the
854-
* connection described by "port". Then look in the usermap file under
855-
* the usermap *auth_arg and see if that user is equivalent to
856-
* Postgres user *user.
929+
* Determine the username of the initiator of the connection described
930+
* by "port". Then look in the usermap file under the usermap
931+
* port->auth_arg and see if that user is equivalent to Postgres user
932+
* port->user.
857933
*
858-
* Return STATUS_OK if yes.
934+
* Return STATUS_OK if yes, STATUS_ERROR if no match (or couldn't get info).
859935
*/
860936
int
861-
authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr,
862-
const char *pg_user, const char *auth_arg)
937+
authident(hbaPort *port)
863938
{
864-
/* We were unable to get ident to give us a username */
865939
char ident_user[IDENT_USERNAME_MAX + 1];
866940

867-
/* The username returned by ident */
868-
if (!ident(raddr->sin_addr, laddr->sin_addr,
869-
raddr->sin_port, laddr->sin_port, ident_user))
870-
return STATUS_ERROR;
941+
switch (port->raddr.sa.sa_family)
942+
{
943+
case AF_INET:
944+
if (!ident_inet(port->raddr.in.sin_addr,
945+
port->laddr.in.sin_addr,
946+
port->raddr.in.sin_port,
947+
port->laddr.in.sin_port, ident_user))
948+
return STATUS_ERROR;
949+
break;
950+
#ifdef HAVE_SO_PEERCRED
951+
case AF_UNIX:
952+
if (!ident_unix(port->sock, ident_user))
953+
return STATUS_ERROR;
954+
break;
955+
#endif
956+
default:
957+
return STATUS_ERROR;
958+
}
871959

872-
if (check_ident_usermap(auth_arg, pg_user, ident_user))
960+
if (check_ident_usermap(port->auth_arg, port->user, ident_user))
873961
return STATUS_OK;
874962
else
875963
return STATUS_ERROR;

src/backend/libpq/pg_hba.conf.sample

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -126,28 +126,31 @@
126126
# usernames stored in secondary password files but not
127127
# secondary passwords.
128128
#
129-
# ident: Authentication is done by the ident server on the local
130-
# (127.0.0.1) or remote host. AUTH_ARGUMENT is required and
131-
# maps names found in the $PGDATA/pg_ident.conf file. The
132-
# connection is accepted if the file contains an entry for
133-
# this map name with the ident-supplied username and the
134-
# requested PostgreSQL username. The special map name
135-
# "sameuser" indicates an implied map (not in pg_ident.conf)
136-
# that maps each ident username to the identical PostgreSQL
137-
# username.
138-
#
139-
# krb4: Kerberos V4 authentication is used.
140-
#
141-
# krb5: Kerberos V5 authentication is used.
129+
# ident: For TCP/IP connections, authentication is done by contacting
130+
# the ident server on the client host. (CAUTION: this is only
131+
# as secure as the client machine!) On machines that support
132+
# SO_PEERCRED socket requests, this method also works for
133+
# local Unix-domain connections. AUTH_ARGUMENT is required:
134+
# it determines how to map remote user names to Postgres user
135+
# names. The AUTH_ARGUMENT is a map name found in the
136+
# $PGDATA/pg_ident.conf file. The connection is accepted if
137+
# that file contains an entry for this map name with the
138+
# ident-supplied username and the requested Postgres username.
139+
# The special map name "sameuser" indicates an implied map
140+
# (not in pg_ident.conf) that maps each ident username to the
141+
# identical PostgreSQL username.
142+
#
143+
# krb4: Kerberos V4 authentication is used. Allowed only for
144+
# TCP/IP connections, not for local UNIX-domain sockets.
145+
#
146+
# krb5: Kerberos V5 authentication is used. Allowed only for
147+
# TCP/IP connections, not for local UNIX-domain sockets.
142148
#
143149
# reject: Reject the connection. This is used to reject certain hosts
144150
# that are part of a network specified later in the file.
145151
# To be effective, "reject" must appear before the later
146152
# entries.
147153
#
148-
# Local UNIX-domain socket connections support only the AUTH_TYPEs of
149-
# "trust", "password", "crypt", and "reject".
150-
#
151154
#
152155
#
153156
# Examples

src/include/config.h.in

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* or in config.h afterwards. Of course, if you edit config.h, then your
99
* changes will be overwritten the next time you run configure.
1010
*
11-
* $Id: config.h.in,v 1.168 2001/07/16 05:07:00 tgl Exp $
11+
* $Id: config.h.in,v 1.169 2001/08/01 23:25:39 tgl Exp $
1212
*/
1313

1414
#ifndef CONFIG_H
@@ -685,6 +685,9 @@ extern int fdatasync(int fildes);
685685
/* Define if you have on_exit() */
686686
#undef HAVE_ON_EXIT
687687

688+
/* Define if you have SO_PEERCRED */
689+
#undef HAVE_SO_PEERCRED
690+
688691
/*
689692
*------------------------------------------------------------------------
690693
* Part 4: pull in system-specific declarations.

0 commit comments

Comments
 (0)