aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2010-07-18 11:37:26 +0000
committerPeter Eisentraut <peter_e@gmx.net>2010-07-18 11:37:26 +0000
commit040aee295ef66ce772050c99902e424d99c2124b (patch)
treeac1853909ff3f7a881318739f6df1041b14c5a5d /src
parented92bec07983931f856214a70982cc0382c464a1 (diff)
downloadpostgresql-040aee295ef66ce772050c99902e424d99c2124b.tar.gz
postgresql-040aee295ef66ce772050c99902e424d99c2124b.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/interfaces/libpq/fe-connect.c89
-rw-r--r--src/interfaces/libpq/libpq-int.h3
2 files changed, 90 insertions, 2 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 4c59ca6834f..2b99f03cc41 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.398 2010/07/08 16:19:50 mha Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.399 2010/07/18 11:37:26 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -229,6 +229,9 @@ static const PQconninfoOption PQconninfoOptions[] = {
{"sslcrl", "PGSSLCRL", NULL, NULL,
"SSL-Revocation-List", "", 64},
+ {"requirepeer", "PGREQUIREPEER", NULL, NULL,
+ "Require-Peer", "", 10},
+
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
/* Kerberos and GSSAPI authentication support specifying the service name */
{"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
@@ -595,6 +598,8 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
conn->sslmode = strdup("require");
}
#endif
+ tmp = conninfo_getval(connOptions, "requirepeer");
+ conn->requirepeer = tmp ? strdup(tmp) : NULL;
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
tmp = conninfo_getval(connOptions, "krbsrvname");
conn->krbsrvname = tmp ? strdup(tmp) : NULL;
@@ -1746,6 +1751,86 @@ keep_going: /* We will come back to here until there is
char *startpacket;
int packetlen;
+#ifdef HAVE_UNIX_SOCKETS
+ if (conn->requirepeer)
+ {
+ char pwdbuf[BUFSIZ];
+ struct passwd pass_buf;
+ struct passwd *pass;
+ uid_t uid;
+
+# if defined(HAVE_GETPEEREID)
+ gid_t gid;
+
+ errno = 0;
+ if (getpeereid(sock, &uid, &gid) != 0)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not get peer credentials: %s\n"),
+ pqStrerror(errno, sebuf, sizeof(sebuf)));
+ goto error_return;
+ }
+# elif defined(SO_PEERCRED)
+ struct ucred peercred;
+ ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+
+ errno = 0;
+ if (getsockopt(conn->sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred))
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not get peer credentials: %s\n"),
+ pqStrerror(errno, sebuf, sizeof(sebuf)));
+ goto error_return;
+ }
+ uid = peercred.uid;
+# elif defined(HAVE_GETPEERUCRED)
+ ucred_t *ucred;
+
+ ucred = NULL; /* must be initialized to NULL */
+ if (getpeerucred(sock, &ucred) == -1)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not get peer credentials: %s\n"),
+ pqStrerror(errno, sebuf, sizeof(sebuf)));
+ goto error_return;
+ }
+
+ if ((uid = ucred_geteuid(ucred)) == -1)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not get effective UID from peer credentials: %s\n"),
+ pqStrerror(errno, sebuf, sizeof(sebuf)));
+ ucred_free(ucred);
+ goto error_return;
+ }
+ ucred_free(ucred);
+# else
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("requirepeer parameter is not supported on this platform\n"));
+ goto error_return;
+# endif
+
+ pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
+
+ if (pass == NULL)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("local user with ID %d does not exist\n"),
+ (int) peercred.uid);
+ goto error_return;
+ }
+
+ if (strcmp(pass->pw_name, conn->requirepeer) != 0)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("requirepeer failed (actual: %s != required: %s)\n"),
+ pass->pw_name, conn->requirepeer);
+ goto error_return;
+ }
+ }
+#endif /* HAVE_UNIX_SOCKETS */
+
#ifdef USE_SSL
/*
@@ -2553,6 +2638,8 @@ freePGconn(PGconn *conn)
free(conn->sslrootcert);
if (conn->sslcrl)
free(conn->sslcrl);
+ if (conn->requirepeer)
+ free(conn->requirepeer);
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
if (conn->krbsrvname)
free(conn->krbsrvname);
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 571c3fbbf42..f64917995ab 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.153 2010/07/14 17:09:45 tgl Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.154 2010/07/18 11:37:26 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -310,6 +310,7 @@ struct pg_conn
char *sslcert; /* client certificate filename */
char *sslrootcert; /* root certificate filename */
char *sslcrl; /* certificate revocation list filename */
+ char *requirepeer; /* required peer credentials for local sockets */
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
char *krbsrvname; /* Kerberos service name */