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
This commit is contained in:
parent
0c99d41ec8
commit
3980f7fc6e
6
configure
vendored
6
configure
vendored
@ -18852,8 +18852,7 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
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
|
|
||||||
do
|
do
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
|
{ $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
|
do
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
|
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||||
|
@ -1191,7 +1191,7 @@ PGAC_VAR_INT_TIMEZONE
|
|||||||
AC_FUNC_ACCEPT_ARGTYPES
|
AC_FUNC_ACCEPT_ARGTYPES
|
||||||
PGAC_FUNC_GETTIMEOFDAY_1ARG
|
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)
|
AC_REPLACE_FUNCS(fseeko)
|
||||||
case $host_os in
|
case $host_os in
|
||||||
@ -1310,7 +1310,7 @@ fi
|
|||||||
pgac_save_LIBS="$LIBS"
|
pgac_save_LIBS="$LIBS"
|
||||||
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
|
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
|
case $host_os in
|
||||||
|
|
||||||
|
@ -17,12 +17,6 @@
|
|||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/socket.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 <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -1756,84 +1750,24 @@ static int
|
|||||||
auth_peer(hbaPort *port)
|
auth_peer(hbaPort *port)
|
||||||
{
|
{
|
||||||
char ident_user[IDENT_USERNAME_MAX + 1];
|
char ident_user[IDENT_USERNAME_MAX + 1];
|
||||||
uid_t uid = 0;
|
uid_t uid;
|
||||||
struct passwd *pass;
|
|
||||||
|
|
||||||
#if defined(HAVE_GETPEEREID)
|
|
||||||
/* Most BSDen, including OS X: use getpeereid() */
|
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
struct passwd *pass;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (getpeereid(port->sock, &uid, &gid) != 0)
|
if (getpeereid(port->sock, &uid, &gid) != 0)
|
||||||
{
|
{
|
||||||
/* We didn't get a valid credentials struct. */
|
/* Provide special error message if getpeereid is a stub */
|
||||||
ereport(LOG,
|
if (errno == ENOSYS)
|
||||||
(errcode_for_socket_access(),
|
ereport(LOG,
|
||||||
errmsg("could not get peer credentials: %m")));
|
(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;
|
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")));
|
|
||||||
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);
|
pass = getpwuid(uid);
|
||||||
|
|
||||||
|
@ -395,6 +395,10 @@ extern void srand48(long seed);
|
|||||||
extern int getopt(int nargc, char *const * nargv, const char *ostr);
|
extern int getopt(int nargc, char *const * nargv, const char *ostr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_GETPEEREID
|
||||||
|
extern int getpeereid(int sock, uid_t *uid, gid_t *gid);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_ISINF
|
#ifndef HAVE_ISINF
|
||||||
extern int isinf(double x);
|
extern int isinf(double x);
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,12 +21,6 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.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-fe.h"
|
||||||
#include "libpq-int.h"
|
#include "libpq-int.h"
|
||||||
@ -1859,6 +1853,7 @@ keep_going: /* We will come back to here until there is
|
|||||||
char *startpacket;
|
char *startpacket;
|
||||||
int packetlen;
|
int packetlen;
|
||||||
|
|
||||||
|
#ifdef HAVE_UNIX_SOCKETS
|
||||||
/*
|
/*
|
||||||
* Implement requirepeer check, if requested and it's a
|
* Implement requirepeer check, if requested and it's a
|
||||||
* Unix-domain socket.
|
* Unix-domain socket.
|
||||||
@ -1866,82 +1861,25 @@ keep_going: /* We will come back to here until there is
|
|||||||
if (conn->requirepeer && conn->requirepeer[0] &&
|
if (conn->requirepeer && conn->requirepeer[0] &&
|
||||||
IS_AF_UNIX(conn->raddr.addr.ss_family))
|
IS_AF_UNIX(conn->raddr.addr.ss_family))
|
||||||
{
|
{
|
||||||
#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(LOCAL_PEERCRED) || defined(HAVE_GETPEERUCRED)
|
|
||||||
char pwdbuf[BUFSIZ];
|
char pwdbuf[BUFSIZ];
|
||||||
struct passwd pass_buf;
|
struct passwd pass_buf;
|
||||||
struct passwd *pass;
|
struct passwd *pass;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
|
|
||||||
#if defined(HAVE_GETPEEREID)
|
|
||||||
/* Most BSDen, including OS X: use getpeereid() */
|
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (getpeereid(conn->sock, &uid, &gid) != 0)
|
if (getpeereid(conn->sock, &uid, &gid) != 0)
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&conn->errorMessage,
|
/* Provide special error message if getpeereid is a stub */
|
||||||
libpq_gettext("could not get peer credentials: %s\n"),
|
if (errno == ENOSYS)
|
||||||
pqStrerror(errno, sebuf, sizeof(sebuf)));
|
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;
|
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);
|
|
||||||
goto error_return;
|
|
||||||
}
|
|
||||||
ucred_free(ucred);
|
|
||||||
#else
|
|
||||||
#error missing implementation method for requirepeer
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
|
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);
|
conn->requirepeer, pass->pw_name);
|
||||||
goto error_return;
|
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
|
#ifdef USE_SSL
|
||||||
|
|
||||||
|
80
src/port/getpeereid.c
Normal file
80
src/port/getpeereid.c
Normal file
@ -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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user