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

Commit 040aee2

Browse files
committed
Add server authentication over Unix-domain sockets
This adds a libpq connection parameter requirepeer that specifies the user name that the server process is expected to run under. reviewed by KaiGai Kohei
1 parent ed92bec commit 040aee2

File tree

3 files changed

+123
-3
lines changed

3 files changed

+123
-3
lines changed

doc/src/sgml/libpq.sgml

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.314 2010/07/14 17:09:45 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.315 2010/07/18 11:37:25 petere Exp $ -->
22

33
<chapter id="libpq">
44
<title><application>libpq</application> - C Library</title>
@@ -509,6 +509,28 @@
509509
</listitem>
510510
</varlistentry>
511511

512+
<varlistentry id="libpq-connect-requirepeer" xreflabel="requirepeer">
513+
<term><literal>requirepeer</literal></term>
514+
<listitem>
515+
<para>
516+
For Unix-domain socket connections, if this parameter is
517+
set, the client checks at the beginning of the connection
518+
that the server process runs under the specified user name,
519+
otherwise the connection is aborted with an error. This
520+
parameter can be used to achieve the kind of server
521+
authentication that SSL certificates achieve on TCP/IP
522+
connections. (Note that if the Unix-domain socket is
523+
in <filename>/tmp</filename> or another publically writable
524+
location, any user could start a server there. Use this
525+
parameter to ensure that you are connected to a server run
526+
by a trusted user,
527+
e.g., <literal>requirepeer=postgres</literal>.) This
528+
option is only supported on some platforms, currently
529+
Linux, FreeBSD, NetBSD, OpenBSD, and Solaris.
530+
</para>
531+
</listitem>
532+
</varlistentry>
533+
512534
<varlistentry id="libpq-connect-krbsrvname" xreflabel="krbsrvname">
513535
<term><literal>krbsrvname</literal></term>
514536
<listitem>
@@ -6139,6 +6161,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
61396161
</para>
61406162
</listitem>
61416163

6164+
<listitem>
6165+
<para>
6166+
<indexterm>
6167+
<primary><envar>PGREQUIREPEER</envar></primary>
6168+
</indexterm>
6169+
<envar>PGREQUIREPEER</envar> behaves the same as the <xref
6170+
linkend="libpq-connect-requirepeer"> connection parameter.
6171+
</para>
6172+
</listitem>
6173+
61426174
<listitem>
61436175
<para>
61446176
<indexterm>

src/interfaces/libpq/fe-connect.c

+88-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.398 2010/07/08 16:19:50 mha Exp $
11+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.399 2010/07/18 11:37:26 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -229,6 +229,9 @@ static const PQconninfoOption PQconninfoOptions[] = {
229229
{"sslcrl", "PGSSLCRL", NULL, NULL,
230230
"SSL-Revocation-List", "", 64},
231231

232+
{"requirepeer", "PGREQUIREPEER", NULL, NULL,
233+
"Require-Peer", "", 10},
234+
232235
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
233236
/* Kerberos and GSSAPI authentication support specifying the service name */
234237
{"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
@@ -595,6 +598,8 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
595598
conn->sslmode = strdup("require");
596599
}
597600
#endif
601+
tmp = conninfo_getval(connOptions, "requirepeer");
602+
conn->requirepeer = tmp ? strdup(tmp) : NULL;
598603
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
599604
tmp = conninfo_getval(connOptions, "krbsrvname");
600605
conn->krbsrvname = tmp ? strdup(tmp) : NULL;
@@ -1746,6 +1751,86 @@ PQconnectPoll(PGconn *conn)
17461751
char *startpacket;
17471752
int packetlen;
17481753

1754+
#ifdef HAVE_UNIX_SOCKETS
1755+
if (conn->requirepeer)
1756+
{
1757+
char pwdbuf[BUFSIZ];
1758+
struct passwd pass_buf;
1759+
struct passwd *pass;
1760+
uid_t uid;
1761+
1762+
# if defined(HAVE_GETPEEREID)
1763+
gid_t gid;
1764+
1765+
errno = 0;
1766+
if (getpeereid(sock, &uid, &gid) != 0)
1767+
{
1768+
appendPQExpBuffer(&conn->errorMessage,
1769+
libpq_gettext("could not get peer credentials: %s\n"),
1770+
pqStrerror(errno, sebuf, sizeof(sebuf)));
1771+
goto error_return;
1772+
}
1773+
# elif defined(SO_PEERCRED)
1774+
struct ucred peercred;
1775+
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
1776+
1777+
errno = 0;
1778+
if (getsockopt(conn->sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
1779+
so_len != sizeof(peercred))
1780+
{
1781+
appendPQExpBuffer(&conn->errorMessage,
1782+
libpq_gettext("could not get peer credentials: %s\n"),
1783+
pqStrerror(errno, sebuf, sizeof(sebuf)));
1784+
goto error_return;
1785+
}
1786+
uid = peercred.uid;
1787+
# elif defined(HAVE_GETPEERUCRED)
1788+
ucred_t *ucred;
1789+
1790+
ucred = NULL; /* must be initialized to NULL */
1791+
if (getpeerucred(sock, &ucred) == -1)
1792+
{
1793+
appendPQExpBuffer(&conn->errorMessage,
1794+
libpq_gettext("could not get peer credentials: %s\n"),
1795+
pqStrerror(errno, sebuf, sizeof(sebuf)));
1796+
goto error_return;
1797+
}
1798+
1799+
if ((uid = ucred_geteuid(ucred)) == -1)
1800+
{
1801+
appendPQExpBuffer(&conn->errorMessage,
1802+
libpq_gettext("could not get effective UID from peer credentials: %s\n"),
1803+
pqStrerror(errno, sebuf, sizeof(sebuf)));
1804+
ucred_free(ucred);
1805+
goto error_return;
1806+
}
1807+
ucred_free(ucred);
1808+
# else
1809+
appendPQExpBuffer(&conn->errorMessage,
1810+
libpq_gettext("requirepeer parameter is not supported on this platform\n"));
1811+
goto error_return;
1812+
# endif
1813+
1814+
pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
1815+
1816+
if (pass == NULL)
1817+
{
1818+
appendPQExpBuffer(&conn->errorMessage,
1819+
libpq_gettext("local user with ID %d does not exist\n"),
1820+
(int) peercred.uid);
1821+
goto error_return;
1822+
}
1823+
1824+
if (strcmp(pass->pw_name, conn->requirepeer) != 0)
1825+
{
1826+
appendPQExpBuffer(&conn->errorMessage,
1827+
libpq_gettext("requirepeer failed (actual: %s != required: %s)\n"),
1828+
pass->pw_name, conn->requirepeer);
1829+
goto error_return;
1830+
}
1831+
}
1832+
#endif /* HAVE_UNIX_SOCKETS */
1833+
17491834
#ifdef USE_SSL
17501835

17511836
/*
@@ -2553,6 +2638,8 @@ freePGconn(PGconn *conn)
25532638
free(conn->sslrootcert);
25542639
if (conn->sslcrl)
25552640
free(conn->sslcrl);
2641+
if (conn->requirepeer)
2642+
free(conn->requirepeer);
25562643
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
25572644
if (conn->krbsrvname)
25582645
free(conn->krbsrvname);

src/interfaces/libpq/libpq-int.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
15-
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.153 2010/07/14 17:09:45 tgl Exp $
15+
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.154 2010/07/18 11:37:26 petere Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -310,6 +310,7 @@ struct pg_conn
310310
char *sslcert; /* client certificate filename */
311311
char *sslrootcert; /* root certificate filename */
312312
char *sslcrl; /* certificate revocation list filename */
313+
char *requirepeer; /* required peer credentials for local sockets */
313314

314315
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
315316
char *krbsrvname; /* Kerberos service name */

0 commit comments

Comments
 (0)