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

Commit 3980f7f

Browse files
committed
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
1 parent 0c99d41 commit 3980f7f

File tree

6 files changed

+110
-158
lines changed

6 files changed

+110
-158
lines changed

configure

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18852,8 +18852,7 @@ fi
1885218852

1885318853

1885418854

18855-
18856-
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
18855+
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
1885718856
do
1885818857
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
1885918858
{ $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'`
2042420423

2042520424

2042620425

20427-
for ac_func in crypt erand48 getopt getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul
20426+
20427+
for ac_func in crypt erand48 getopt getpeereid getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul
2042820428
do
2042920429
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
2043020430
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5

configure.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,7 @@ PGAC_VAR_INT_TIMEZONE
11911191
AC_FUNC_ACCEPT_ARGTYPES
11921192
PGAC_FUNC_GETTIMEOFDAY_1ARG
11931193

1194-
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])
1194+
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])
11951195

11961196
AC_REPLACE_FUNCS(fseeko)
11971197
case $host_os in
@@ -1310,7 +1310,7 @@ fi
13101310
pgac_save_LIBS="$LIBS"
13111311
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
13121312

1313-
AC_REPLACE_FUNCS([crypt erand48 getopt getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul])
1313+
AC_REPLACE_FUNCS([crypt erand48 getopt getpeereid getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul])
13141314

13151315
case $host_os in
13161316

src/backend/libpq/auth.c

Lines changed: 11 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,6 @@
1717

1818
#include <sys/param.h>
1919
#include <sys/socket.h>
20-
#ifdef HAVE_UCRED_H
21-
#include <ucred.h>
22-
#endif
23-
#ifdef HAVE_SYS_UCRED_H
24-
#include <sys/ucred.h>
25-
#endif
2620
#include <netinet/in.h>
2721
#include <arpa/inet.h>
2822
#include <unistd.h>
@@ -1756,85 +1750,25 @@ static int
17561750
auth_peer(hbaPort *port)
17571751
{
17581752
char ident_user[IDENT_USERNAME_MAX + 1];
1759-
uid_t uid = 0;
1760-
struct passwd *pass;
1761-
1762-
#if defined(HAVE_GETPEEREID)
1763-
/* Most BSDen, including OS X: use getpeereid() */
1753+
uid_t uid;
17641754
gid_t gid;
1755+
struct passwd *pass;
17651756

17661757
errno = 0;
17671758
if (getpeereid(port->sock, &uid, &gid) != 0)
17681759
{
1769-
/* We didn't get a valid credentials struct. */
1770-
ereport(LOG,
1771-
(errcode_for_socket_access(),
1772-
errmsg("could not get peer credentials: %m")));
1773-
return STATUS_ERROR;
1774-
}
1775-
#elif defined(SO_PEERCRED)
1776-
/* Linux: use getsockopt(SO_PEERCRED) */
1777-
struct ucred peercred;
1778-
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
1779-
1780-
errno = 0;
1781-
if (getsockopt(port->sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
1782-
so_len != sizeof(peercred))
1783-
{
1784-
/* We didn't get a valid credentials struct. */
1785-
ereport(LOG,
1786-
(errcode_for_socket_access(),
1787-
errmsg("could not get peer credentials: %m")));
1788-
return STATUS_ERROR;
1789-
}
1790-
uid = peercred.uid;
1791-
#elif defined(LOCAL_PEERCRED)
1792-
/* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
1793-
struct xucred peercred;
1794-
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
1795-
1796-
errno = 0;
1797-
if (getsockopt(port->sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
1798-
so_len != sizeof(peercred) ||
1799-
peercred.cr_version != XUCRED_VERSION)
1800-
{
1801-
/* We didn't get a valid credentials struct. */
1802-
ereport(LOG,
1803-
(errcode_for_socket_access(),
1804-
errmsg("could not get peer credentials: %m")));
1805-
return STATUS_ERROR;
1806-
}
1807-
uid = peercred.cr_uid;
1808-
#elif defined(HAVE_GETPEERUCRED)
1809-
/* Solaris: use getpeerucred() */
1810-
ucred_t *ucred;
1811-
1812-
ucred = NULL; /* must be initialized to NULL */
1813-
if (getpeerucred(port->sock, &ucred) == -1)
1814-
{
1815-
ereport(LOG,
1816-
(errcode_for_socket_access(),
1817-
errmsg("could not get peer credentials: %m")));
1818-
return STATUS_ERROR;
1819-
}
1820-
1821-
if ((uid = ucred_geteuid(ucred)) == -1)
1822-
{
1823-
ereport(LOG,
1824-
(errcode_for_socket_access(),
1825-
errmsg("could not get effective UID from peer credentials: %m")));
1760+
/* Provide special error message if getpeereid is a stub */
1761+
if (errno == ENOSYS)
1762+
ereport(LOG,
1763+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1764+
errmsg("peer authentication is not supported on this platform")));
1765+
else
1766+
ereport(LOG,
1767+
(errcode_for_socket_access(),
1768+
errmsg("could not get peer credentials: %m")));
18261769
return STATUS_ERROR;
18271770
}
18281771

1829-
ucred_free(ucred);
1830-
#else
1831-
ereport(LOG,
1832-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1833-
errmsg("Peer authentication is not supported on local connections on this platform")));
1834-
1835-
return STATUS_ERROR;
1836-
#endif
1837-
18381772
pass = getpwuid(uid);
18391773

18401774
if (pass == NULL)

src/include/port.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,10 @@ extern void srand48(long seed);
395395
extern int getopt(int nargc, char *const * nargv, const char *ostr);
396396
#endif
397397

398+
#ifndef HAVE_GETPEEREID
399+
extern int getpeereid(int sock, uid_t *uid, gid_t *gid);
400+
#endif
401+
398402
#ifndef HAVE_ISINF
399403
extern int isinf(double x);
400404
#endif

src/interfaces/libpq/fe-connect.c

Lines changed: 10 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,6 @@
2121
#include <ctype.h>
2222
#include <time.h>
2323
#include <unistd.h>
24-
#ifdef HAVE_UCRED_H
25-
#include <ucred.h>
26-
#endif
27-
#ifdef HAVE_SYS_UCRED_H
28-
#include <sys/ucred.h>
29-
#endif
3024

3125
#include "libpq-fe.h"
3226
#include "libpq-int.h"
@@ -1859,89 +1853,33 @@ PQconnectPoll(PGconn *conn)
18591853
char *startpacket;
18601854
int packetlen;
18611855

1856+
#ifdef HAVE_UNIX_SOCKETS
18621857
/*
18631858
* Implement requirepeer check, if requested and it's a
18641859
* Unix-domain socket.
18651860
*/
18661861
if (conn->requirepeer && conn->requirepeer[0] &&
18671862
IS_AF_UNIX(conn->raddr.addr.ss_family))
18681863
{
1869-
#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(LOCAL_PEERCRED) || defined(HAVE_GETPEERUCRED)
18701864
char pwdbuf[BUFSIZ];
18711865
struct passwd pass_buf;
18721866
struct passwd *pass;
18731867
uid_t uid;
1874-
1875-
#if defined(HAVE_GETPEEREID)
1876-
/* Most BSDen, including OS X: use getpeereid() */
18771868
gid_t gid;
18781869

18791870
errno = 0;
18801871
if (getpeereid(conn->sock, &uid, &gid) != 0)
18811872
{
1882-
appendPQExpBuffer(&conn->errorMessage,
1883-
libpq_gettext("could not get peer credentials: %s\n"),
1884-
pqStrerror(errno, sebuf, sizeof(sebuf)));
1885-
goto error_return;
1886-
}
1887-
#elif defined(SO_PEERCRED)
1888-
/* Linux: use getsockopt(SO_PEERCRED) */
1889-
struct ucred peercred;
1890-
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
1891-
1892-
errno = 0;
1893-
if (getsockopt(conn->sock, SOL_SOCKET, SO_PEERCRED,
1894-
&peercred, &so_len) != 0 ||
1895-
so_len != sizeof(peercred))
1896-
{
1897-
appendPQExpBuffer(&conn->errorMessage,
1898-
libpq_gettext("could not get peer credentials: %s\n"),
1899-
pqStrerror(errno, sebuf, sizeof(sebuf)));
1900-
goto error_return;
1901-
}
1902-
uid = peercred.uid;
1903-
#elif defined(LOCAL_PEERCRED)
1904-
/* Debian with FreeBSD kernel: use LOCAL_PEERCRED */
1905-
struct xucred peercred;
1906-
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
1907-
1908-
errno = 0;
1909-
if (getsockopt(conn->sock, 0, LOCAL_PEERCRED,
1910-
&peercred, &so_len) != 0 ||
1911-
so_len != sizeof(peercred) ||
1912-
peercred.cr_version != XUCRED_VERSION)
1913-
{
1914-
appendPQExpBuffer(&conn->errorMessage,
1915-
libpq_gettext("could not get peer credentials: %s\n"),
1916-
pqStrerror(errno, sebuf, sizeof(sebuf)));
1917-
goto error_return;
1918-
}
1919-
uid = peercred.cr_uid;
1920-
#elif defined(HAVE_GETPEERUCRED)
1921-
/* Solaris: use getpeerucred() */
1922-
ucred_t *ucred;
1923-
1924-
ucred = NULL; /* must be initialized to NULL */
1925-
if (getpeerucred(conn->sock, &ucred) == -1)
1926-
{
1927-
appendPQExpBuffer(&conn->errorMessage,
1928-
libpq_gettext("could not get peer credentials: %s\n"),
1929-
pqStrerror(errno, sebuf, sizeof(sebuf)));
1930-
goto error_return;
1931-
}
1932-
1933-
if ((uid = ucred_geteuid(ucred)) == -1)
1934-
{
1935-
appendPQExpBuffer(&conn->errorMessage,
1936-
libpq_gettext("could not get effective UID from peer credentials: %s\n"),
1937-
pqStrerror(errno, sebuf, sizeof(sebuf)));
1938-
ucred_free(ucred);
1873+
/* Provide special error message if getpeereid is a stub */
1874+
if (errno == ENOSYS)
1875+
appendPQExpBuffer(&conn->errorMessage,
1876+
libpq_gettext("requirepeer parameter is not supported on this platform\n"));
1877+
else
1878+
appendPQExpBuffer(&conn->errorMessage,
1879+
libpq_gettext("could not get peer credentials: %s\n"),
1880+
pqStrerror(errno, sebuf, sizeof(sebuf)));
19391881
goto error_return;
19401882
}
1941-
ucred_free(ucred);
1942-
#else
1943-
#error missing implementation method for requirepeer
1944-
#endif
19451883

19461884
pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
19471885

@@ -1960,12 +1898,8 @@ PQconnectPoll(PGconn *conn)
19601898
conn->requirepeer, pass->pw_name);
19611899
goto error_return;
19621900
}
1963-
#else /* can't support requirepeer */
1964-
appendPQExpBuffer(&conn->errorMessage,
1965-
libpq_gettext("requirepeer parameter is not supported on this platform\n"));
1966-
goto error_return;
1967-
#endif
19681901
}
1902+
#endif /* HAVE_UNIX_SOCKETS */
19691903

19701904
#ifdef USE_SSL
19711905

src/port/getpeereid.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* getpeereid.c
4+
* get peer userid for UNIX-domain socket connection
5+
*
6+
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7+
*
8+
*
9+
* IDENTIFICATION
10+
* src/port/getpeereid.c
11+
*
12+
*-------------------------------------------------------------------------
13+
*/
14+
15+
#include "c.h"
16+
17+
#include <sys/param.h>
18+
#include <sys/socket.h>
19+
#include <unistd.h>
20+
#ifdef HAVE_SYS_UN_H
21+
#include <sys/un.h>
22+
#endif
23+
#ifdef HAVE_UCRED_H
24+
#include <ucred.h>
25+
#endif
26+
#ifdef HAVE_SYS_UCRED_H
27+
#include <sys/ucred.h>
28+
#endif
29+
30+
31+
/*
32+
* BSD-style getpeereid() for platforms that lack it.
33+
*/
34+
int
35+
getpeereid(int sock, uid_t *uid, gid_t *gid)
36+
{
37+
#if defined(SO_PEERCRED)
38+
/* Linux: use getsockopt(SO_PEERCRED) */
39+
struct ucred peercred;
40+
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
41+
42+
if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
43+
so_len != sizeof(peercred))
44+
return -1;
45+
*uid = peercred.uid;
46+
*gid = peercred.gid;
47+
return 0;
48+
#elif defined(LOCAL_PEERCRED)
49+
/* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
50+
struct xucred peercred;
51+
ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
52+
53+
if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
54+
so_len != sizeof(peercred) ||
55+
peercred.cr_version != XUCRED_VERSION)
56+
return -1;
57+
*uid = peercred.cr_uid;
58+
*gid = peercred.cr_gid;
59+
return 0;
60+
#elif defined(HAVE_GETPEERUCRED)
61+
/* Solaris: use getpeerucred() */
62+
ucred_t *ucred;
63+
64+
ucred = NULL; /* must be initialized to NULL */
65+
if (getpeerucred(sock, &ucred) == -1)
66+
return -1;
67+
68+
*uid = ucred_geteuid(ucred);
69+
*gid = ucred_getegid(ucred);
70+
ucred_free(ucred);
71+
72+
if (*uid == (pid_t)(-1) || *gid == (gid_t)(-1))
73+
return -1;
74+
return 0;
75+
#else
76+
/* No implementation available on this platform */
77+
errno = ENOSYS;
78+
return -1;
79+
#endif
80+
}

0 commit comments

Comments
 (0)