From f14413b684d57211068ee56ee04695efcc87a23a Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 30 Oct 2019 12:58:32 +0100 Subject: [PATCH] Sort out getpeereid() and peer auth handling on Windows The getpeereid() uses have so far been protected by HAVE_UNIX_SOCKETS, so they didn't ever care about Windows support. But in anticipation of Unix-domain socket support on Windows, that needs to be handled differently. Windows doesn't support getpeereid() at this time, so we use the existing not-supported code path. We let configure do its usual thing of picking up the replacement from libpgport, instead of the custom overrides that it was doing before. But then Windows doesn't have struct passwd, so this patch sprinkles some additional #ifdef WIN32 around to make it work. This is similar to existing code that deals with this issue. Reviewed-by: Andrew Dunstan Discussion: https://www.postgresql.org/message-id/5974caea-1267-7708-40f2-6009a9d653b0@2ndquadrant.com --- configure | 36 +++++++++++++------------------ configure.in | 11 ++++------ src/backend/libpq/auth.c | 17 +++++++-------- src/include/port.h | 2 +- src/interfaces/libpq/fe-connect.c | 10 ++++++--- src/tools/msvc/Mkvcbuild.pm | 2 +- 6 files changed, 36 insertions(+), 42 deletions(-) diff --git a/configure b/configure index 3d9bd0bdf87..de431d0d38b 100755 --- a/configure +++ b/configure @@ -15685,6 +15685,19 @@ esac fi +ac_fn_c_check_func "$LINENO" "getpeereid" "ac_cv_func_getpeereid" +if test "x$ac_cv_func_getpeereid" = xyes; then : + $as_echo "#define HAVE_GETPEEREID 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" getpeereid.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS getpeereid.$ac_objext" + ;; +esac + +fi + ac_fn_c_check_func "$LINENO" "getrusage" "ac_cv_func_getrusage" if test "x$ac_cv_func_getrusage" = xyes; then : $as_echo "#define HAVE_GETRUSAGE 1" >>confdefs.h @@ -15863,19 +15876,13 @@ $as_echo "$as_me: On $host_os we will use our strtof wrapper." >&6;} esac case $host_os in - # Windows uses a specialised env handler - # and doesn't need a replacement getpeereid because it doesn't use - # Unix sockets. mingw*) $as_echo "#define HAVE_UNSETENV 1" >>confdefs.h - -$as_echo "#define HAVE_GETPEEREID 1" >>confdefs.h - ac_cv_func_unsetenv=yes - ac_cv_func_getpeereid=yes;; + ;; *) ac_fn_c_check_func "$LINENO" "unsetenv" "ac_cv_func_unsetenv" if test "x$ac_cv_func_unsetenv" = xyes; then : @@ -15890,21 +15897,8 @@ esac fi -ac_fn_c_check_func "$LINENO" "getpeereid" "ac_cv_func_getpeereid" -if test "x$ac_cv_func_getpeereid" = xyes; then : - $as_echo "#define HAVE_GETPEEREID 1" >>confdefs.h -else - case " $LIBOBJS " in - *" getpeereid.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS getpeereid.$ac_objext" - ;; -esac - -fi - - - ;; + ;; esac # System's version of getaddrinfo(), if any, may be used only if we found diff --git a/configure.in b/configure.in index 34aea0b4ace..85829be069a 100644 --- a/configure.in +++ b/configure.in @@ -1729,6 +1729,7 @@ AC_REPLACE_FUNCS(m4_normalize([ explicit_bzero fls getopt + getpeereid getrusage inet_aton mkdtemp @@ -1757,18 +1758,14 @@ case $host_os in esac case $host_os in - # Windows uses a specialised env handler - # and doesn't need a replacement getpeereid because it doesn't use - # Unix sockets. mingw*) AC_DEFINE(HAVE_UNSETENV, 1, [Define to 1 because replacement version used.]) - AC_DEFINE(HAVE_GETPEEREID, 1, [Define to 1 because function not required.]) ac_cv_func_unsetenv=yes - ac_cv_func_getpeereid=yes;; + ;; *) - AC_REPLACE_FUNCS([unsetenv getpeereid]) - ;; + AC_REPLACE_FUNCS([unsetenv]) + ;; esac # System's version of getaddrinfo(), if any, may be used only if we found diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index c12b810c3d5..5399144c20c 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -77,9 +77,7 @@ static int ident_inet(hbaPort *port); * Peer authentication *---------------------------------------------------------------- */ -#ifdef HAVE_UNIX_SOCKETS static int auth_peer(hbaPort *port); -#endif /*---------------------------------------------------------------- @@ -559,11 +557,7 @@ ClientAuthentication(Port *port) break; case uaPeer: -#ifdef HAVE_UNIX_SOCKETS status = auth_peer(port); -#else - Assert(false); -#endif break; case uaIdent: @@ -1984,16 +1978,16 @@ ident_inet_done: * * Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR. */ -#ifdef HAVE_UNIX_SOCKETS - static int auth_peer(hbaPort *port) { uid_t uid; gid_t gid; +#ifndef WIN32 struct passwd *pw; char *peer_user; int ret; +#endif if (getpeereid(port->sock, &uid, &gid) != 0) { @@ -2009,6 +2003,7 @@ auth_peer(hbaPort *port) return STATUS_ERROR; } +#ifndef WIN32 errno = 0; /* clear errno before call */ pw = getpwuid(uid); if (!pw) @@ -2030,8 +2025,12 @@ auth_peer(hbaPort *port) pfree(peer_user); return ret; +#else + /* should have failed with ENOSYS above */ + Assert(false); + return STATUS_ERROR; +#endif } -#endif /* HAVE_UNIX_SOCKETS */ /*---------------------------------------------------------------- diff --git a/src/include/port.h b/src/include/port.h index bfd2e2759f6..9567590581b 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -354,7 +354,7 @@ extern int fls(int mask); #define ftello(a) ftell(a) #endif -#if !defined(HAVE_GETPEEREID) && !defined(WIN32) +#ifndef HAVE_GETPEEREID extern int getpeereid(int sock, uid_t *uid, gid_t *gid); #endif diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 66a91286056..3ca7e0560cd 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -2733,8 +2733,6 @@ 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. @@ -2742,10 +2740,12 @@ 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)) { +#ifndef WIN32 char pwdbuf[BUFSIZ]; struct passwd pass_buf; struct passwd *pass; int passerr; +#endif uid_t uid; gid_t gid; @@ -2766,6 +2766,7 @@ keep_going: /* We will come back to here until there is goto error_return; } +#ifndef WIN32 passerr = pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass); if (pass == NULL) { @@ -2788,8 +2789,11 @@ keep_going: /* We will come back to here until there is conn->requirepeer, pass->pw_name); goto error_return; } +#else /* WIN32 */ + /* should have failed with ENOSYS above */ + Assert(false); +#endif /* WIN32 */ } -#endif /* HAVE_UNIX_SOCKETS */ if (IS_AF_UNIX(conn->raddr.addr.ss_family)) { diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 275f3bb6991..3d6ef0de84b 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -94,7 +94,7 @@ sub mkvcbuild $solution = CreateSolution($vsVersion, $config); our @pgportfiles = qw( - chklocale.c explicit_bzero.c fls.c fseeko.c getrusage.c inet_aton.c random.c + chklocale.c explicit_bzero.c fls.c fseeko.c getpeereid.c getrusage.c inet_aton.c random.c srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c dirent.c dlopen.c getopt.c getopt_long.c