aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-06-02 13:05:01 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-06-02 13:05:01 -0400
commit3980f7fc6ecb75952ebe76c3d30ec6731728098d (patch)
tree6578e3dea9723f39ef28019d299e84103b49f4a9
parent0c99d41ec887051fb0cc6e35e358ecc936a13584 (diff)
downloadpostgresql-3980f7fc6ecb75952ebe76c3d30ec6731728098d.tar.gz
postgresql-3980f7fc6ecb75952ebe76c3d30ec6731728098d.zip
Implement getpeereid() as a src/port compatibility function.
This unifies a bunch of ugly #ifdef's in one place. Per discussion, we only need this where HAVE_UNIX_SOCKETS, so no need to cover Windows. Marko Kreen, some adjustment by Tom Lane
-rwxr-xr-xconfigure6
-rw-r--r--configure.in4
-rw-r--r--src/backend/libpq/auth.c88
-rw-r--r--src/include/port.h4
-rw-r--r--src/interfaces/libpq/fe-connect.c86
-rw-r--r--src/port/getpeereid.c80
6 files changed, 110 insertions, 158 deletions
diff --git a/configure b/configure
index 5c6022903de..a8c59231183 100755
--- a/configure
+++ b/configure
@@ -18852,8 +18852,7 @@ fi
-
-for ac_func in cbrt dlopen fcvt fdatasync getifaddrs getpeereid getpeerucred getrlimit memmove poll pstat readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l
+for ac_func in cbrt dlopen fcvt fdatasync getifaddrs getpeerucred getrlimit memmove poll pstat readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l
do
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -20424,7 +20423,8 @@ LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
-for ac_func in crypt erand48 getopt getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul
+
+for ac_func in crypt erand48 getopt getpeereid getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul
do
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
diff --git a/configure.in b/configure.in
index ed2d17d2198..6a7278aefe7 100644
--- a/configure.in
+++ b/configure.in
@@ -1191,7 +1191,7 @@ PGAC_VAR_INT_TIMEZONE
AC_FUNC_ACCEPT_ARGTYPES
PGAC_FUNC_GETTIMEOFDAY_1ARG
-AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getifaddrs getpeereid getpeerucred getrlimit memmove poll pstat readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l])
+AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getifaddrs getpeerucred getrlimit memmove poll pstat readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l])
AC_REPLACE_FUNCS(fseeko)
case $host_os in
@@ -1310,7 +1310,7 @@ fi
pgac_save_LIBS="$LIBS"
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
-AC_REPLACE_FUNCS([crypt erand48 getopt getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul])
+AC_REPLACE_FUNCS([crypt erand48 getopt getpeereid getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul])
case $host_os in
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index dc7ad2cadf4..f4099ac2345 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -17,12 +17,6 @@
#include <sys/param.h>
#include <sys/socket.h>
-#ifdef HAVE_UCRED_H
-#include <ucred.h>
-#endif
-#ifdef HAVE_SYS_UCRED_H
-#include <sys/ucred.h>
-#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
@@ -1756,85 +1750,25 @@ static int
auth_peer(hbaPort *port)
{
char ident_user[IDENT_USERNAME_MAX + 1];
- uid_t uid = 0;
- struct passwd *pass;
-
-#if defined(HAVE_GETPEEREID)
- /* Most BSDen, including OS X: use getpeereid() */
+ uid_t uid;
gid_t gid;
+ struct passwd *pass;
errno = 0;
if (getpeereid(port->sock, &uid, &gid) != 0)
{
- /* We didn't get a valid credentials struct. */
- ereport(LOG,
- (errcode_for_socket_access(),
- errmsg("could not get peer credentials: %m")));
- return STATUS_ERROR;
- }
-#elif defined(SO_PEERCRED)
- /* Linux: use getsockopt(SO_PEERCRED) */
- struct ucred peercred;
- ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
-
- errno = 0;
- if (getsockopt(port->sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
- so_len != sizeof(peercred))
- {
- /* We didn't get a valid credentials struct. */
- ereport(LOG,
- (errcode_for_socket_access(),
- errmsg("could not get peer credentials: %m")));
- return STATUS_ERROR;
- }
- uid = peercred.uid;
-#elif defined(LOCAL_PEERCRED)
- /* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
- struct xucred peercred;
- ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
-
- errno = 0;
- if (getsockopt(port->sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
- so_len != sizeof(peercred) ||
- peercred.cr_version != XUCRED_VERSION)
- {
- /* We didn't get a valid credentials struct. */
- ereport(LOG,
- (errcode_for_socket_access(),
- errmsg("could not get peer credentials: %m")));
- return STATUS_ERROR;
- }
- uid = peercred.cr_uid;
-#elif defined(HAVE_GETPEERUCRED)
- /* Solaris: use getpeerucred() */
- ucred_t *ucred;
-
- ucred = NULL; /* must be initialized to NULL */
- if (getpeerucred(port->sock, &ucred) == -1)
- {
- ereport(LOG,
- (errcode_for_socket_access(),
- errmsg("could not get peer credentials: %m")));
- return STATUS_ERROR;
- }
-
- if ((uid = ucred_geteuid(ucred)) == -1)
- {
- ereport(LOG,
- (errcode_for_socket_access(),
- errmsg("could not get effective UID from peer credentials: %m")));
+ /* Provide special error message if getpeereid is a stub */
+ if (errno == ENOSYS)
+ ereport(LOG,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("peer authentication is not supported on this platform")));
+ else
+ ereport(LOG,
+ (errcode_for_socket_access(),
+ errmsg("could not get peer credentials: %m")));
return STATUS_ERROR;
}
- ucred_free(ucred);
-#else
- ereport(LOG,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("Peer authentication is not supported on local connections on this platform")));
-
- return STATUS_ERROR;
-#endif
-
pass = getpwuid(uid);
if (pass == NULL)
diff --git a/src/include/port.h b/src/include/port.h
index 6ea681f16ac..d7295e31327 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -395,6 +395,10 @@ extern void srand48(long seed);
extern int getopt(int nargc, char *const * nargv, const char *ostr);
#endif
+#ifndef HAVE_GETPEEREID
+extern int getpeereid(int sock, uid_t *uid, gid_t *gid);
+#endif
+
#ifndef HAVE_ISINF
extern int isinf(double x);
#endif
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 5a6502fff4d..9aa6ca01eb2 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -21,12 +21,6 @@
#include <ctype.h>
#include <time.h>
#include <unistd.h>
-#ifdef HAVE_UCRED_H
-#include <ucred.h>
-#endif
-#ifdef HAVE_SYS_UCRED_H
-#include <sys/ucred.h>
-#endif
#include "libpq-fe.h"
#include "libpq-int.h"
@@ -1859,6 +1853,7 @@ keep_going: /* We will come back to here until there is
char *startpacket;
int packetlen;
+#ifdef HAVE_UNIX_SOCKETS
/*
* Implement requirepeer check, if requested and it's a
* Unix-domain socket.
@@ -1866,82 +1861,25 @@ keep_going: /* We will come back to here until there is
if (conn->requirepeer && conn->requirepeer[0] &&
IS_AF_UNIX(conn->raddr.addr.ss_family))
{
-#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(LOCAL_PEERCRED) || defined(HAVE_GETPEERUCRED)
char pwdbuf[BUFSIZ];
struct passwd pass_buf;
struct passwd *pass;
uid_t uid;
-
-#if defined(HAVE_GETPEEREID)
- /* Most BSDen, including OS X: use getpeereid() */
gid_t gid;
errno = 0;
if (getpeereid(conn->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)
- /* Linux: use getsockopt(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(LOCAL_PEERCRED)
- /* Debian with FreeBSD kernel: use LOCAL_PEERCRED */
- struct xucred peercred;
- ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
-
- errno = 0;
- if (getsockopt(conn->sock, 0, LOCAL_PEERCRED,
- &peercred, &so_len) != 0 ||
- so_len != sizeof(peercred) ||
- peercred.cr_version != XUCRED_VERSION)
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not get peer credentials: %s\n"),
- pqStrerror(errno, sebuf, sizeof(sebuf)));
- goto error_return;
- }
- uid = peercred.cr_uid;
-#elif defined(HAVE_GETPEERUCRED)
- /* Solaris: use getpeerucred() */
- ucred_t *ucred;
-
- ucred = NULL; /* must be initialized to NULL */
- if (getpeerucred(conn->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);
+ /* Provide special error message if getpeereid is a stub */
+ if (errno == ENOSYS)
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("requirepeer parameter is not supported on this platform\n"));
+ else
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not get peer credentials: %s\n"),
+ pqStrerror(errno, sebuf, sizeof(sebuf)));
goto error_return;
}
- ucred_free(ucred);
-#else
-#error missing implementation method for requirepeer
-#endif
pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
@@ -1960,12 +1898,8 @@ keep_going: /* We will come back to here until there is
conn->requirepeer, pass->pw_name);
goto error_return;
}
-#else /* can't support requirepeer */
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("requirepeer parameter is not supported on this platform\n"));
- goto error_return;
-#endif
}
+#endif /* HAVE_UNIX_SOCKETS */
#ifdef USE_SSL
diff --git a/src/port/getpeereid.c b/src/port/getpeereid.c
new file mode 100644
index 00000000000..3b826f01e87
--- /dev/null
+++ b/src/port/getpeereid.c
@@ -0,0 +1,80 @@
+/*-------------------------------------------------------------------------
+ *
+ * getpeereid.c
+ * get peer userid for UNIX-domain socket connection
+ *
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/port/getpeereid.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
+#endif
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+
+
+/*
+ * BSD-style getpeereid() for platforms that lack it.
+ */
+int
+getpeereid(int sock, uid_t *uid, gid_t *gid)
+{
+#if defined(SO_PEERCRED)
+ /* Linux: use getsockopt(SO_PEERCRED) */
+ struct ucred peercred;
+ ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+
+ if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred))
+ return -1;
+ *uid = peercred.uid;
+ *gid = peercred.gid;
+ return 0;
+#elif defined(LOCAL_PEERCRED)
+ /* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
+ struct xucred peercred;
+ ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+
+ if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred) ||
+ peercred.cr_version != XUCRED_VERSION)
+ return -1;
+ *uid = peercred.cr_uid;
+ *gid = peercred.cr_gid;
+ return 0;
+#elif defined(HAVE_GETPEERUCRED)
+ /* Solaris: use getpeerucred() */
+ ucred_t *ucred;
+
+ ucred = NULL; /* must be initialized to NULL */
+ if (getpeerucred(sock, &ucred) == -1)
+ return -1;
+
+ *uid = ucred_geteuid(ucred);
+ *gid = ucred_getegid(ucred);
+ ucred_free(ucred);
+
+ if (*uid == (pid_t)(-1) || *gid == (gid_t)(-1))
+ return -1;
+ return 0;
+#else
+ /* No implementation available on this platform */
+ errno = ENOSYS;
+ return -1;
+#endif
+}