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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy