From f7f806afa5083617f4aba02fc3b285b06a7d73d4 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 7 Mar 2017 14:01:17 +0900 Subject: [PATCH] agent: Fix get_client_pid for portability. * configure.ac: Simply check getpeerucred and ucred.h, and structure members. * agent/command-ssh.c: Include ucred.h. (get_client_pid) [HAVE_STRUCT_SOCKPEERCRED_PID]: Use sockpeercred structure for OpenBSD. [LOCAL_PEERPID]: Use LOCAL_PEERPID for macOS. [LOCAL_PEEREID]: Use LOCAL_PEEREID for NetBSD. [HAVE_GETPEERUCRED]: Use getpeerucred for OpenSolaris. -- This change also addresses following bug. GnuPG-bug-id: 2981. Signed-off-by: NIIBE Yutaka --- agent/command-ssh.c | 47 +++++++++++++++++++++++++++++++------------ configure.ac | 49 +++++++-------------------------------------- 2 files changed, 41 insertions(+), 55 deletions(-) diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 3ab41cfdb..c7afe3bc9 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -40,6 +40,9 @@ #include #include #include +#ifdef HAVE_UCRED_H +#include +#endif #include "agent.h" @@ -3556,19 +3559,45 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) } -/* Return the peer's pid. Stripped down code from libassuan. */ +/* Return the peer's pid. */ static unsigned long get_client_pid (int fd) { pid_t client_pid = (pid_t)(-1); -#ifdef HAVE_SO_PEERCRED +#ifdef SO_PEERCRED { +#ifdef HAVE_STRUCT_SOCKPEERCRED_PID + struct sockpeercred cr; +#else struct ucred cr; +#endif socklen_t cl = sizeof cr; if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl)) - client_pid = cr.pid; + { +#if defined (HAVE_STRUCT_SOCKPEERCRED_PID) || defined (HAVE_STRUCT_UCRED_PID) + client_pid = cr.pid; +#elif defined (HAVE_STRUCT_UCRED_CR_PID) + client_pid = cr.cr_pid; +#else +#error "Unknown SO_PEERCRED struct" +#endif + } + } +#elif defined (LOCAL_PEERPID) + { + socklen_t len = sizeof (pid_t); + + getsockopt(fd, SOL_LOCAL, LOCAL_PEERPID, &client_pid, &len); + } +#elif defined (LOCAL_PEEREID) + { + struct unpcbid unp; + socklen_t unpl = sizeof unp; + + if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1) + client_pid = unp.unp_pid; } #elif defined (HAVE_GETPEERUCRED) { @@ -3576,18 +3605,10 @@ get_client_pid (int fd) if (getpeerucred (fd, &ucred) != -1) { - client_pid= ucred_getpid (ucred); - ucred_free (ucred); + client_pid= ucred_getpid (ucred); + ucred_free (ucred); } } -#elif defined (HAVE_LOCAL_PEEREID) - { - struct unpcbid unp; - socklen_t unpl = sizeof unp; - - if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1) - client_pid = unp.unp_pid; - } #endif return client_pid == (pid_t)(-1)? 0 : (unsigned long)client_pid; diff --git a/configure.ac b/configure.ac index 5fc2b8518..6d35450b0 100644 --- a/configure.ac +++ b/configure.ac @@ -1274,7 +1274,8 @@ AC_MSG_NOTICE([checking for header files]) AC_HEADER_STDC AC_CHECK_HEADERS([string.h unistd.h langinfo.h termio.h locale.h getopt.h \ pty.h utmp.h pwd.h inttypes.h signal.h sys/select.h \ - stdint.h signal.h util.h libutil.h termios.h]) + stdint.h signal.h util.h libutil.h termios.h \ + ucred.h]) AC_HEADER_TIME @@ -1394,49 +1395,13 @@ fi # -# Check for the getsockopt SO_PEERCRED -# (This has been copied from libassuan) +# Check for the getsockopt SO_PEERCRED, etc. # -AC_MSG_CHECKING(for SO_PEERCRED) -AC_CACHE_VAL(gnupg_cv_sys_so_peercred, - [AC_TRY_COMPILE([#include ], - [struct ucred cr; - int cl = sizeof cr; - getsockopt (1, SOL_SOCKET, SO_PEERCRED, &cr, &cl);], - gnupg_cv_sys_so_peercred=yes, - gnupg_cv_sys_so_peercred=no) - ]) -AC_MSG_RESULT($gnupg_cv_sys_so_peercred) +AC_CHECK_MEMBERS([struct ucred.pid, struct ucred.cr_pid, struct sockpeercred.pid], [], [], [#include +#include ]) -if test $gnupg_cv_sys_so_peercred = yes; then - AC_DEFINE(HAVE_SO_PEERCRED, 1, - [Defined if SO_PEERCRED is supported (Linux specific)]) -else - # Check for the getsockopt LOCAL_PEEREID (NetBSD) - AC_MSG_CHECKING(for LOCAL_PEEREID) - AC_CACHE_VAL(gnupg_cv_sys_so_local_peereid, - [AC_TRY_COMPILE([#include - #include ], - [struct unpcbid unp; - int unpl = sizeof unp; - getsockopt (1, SOL_SOCKET, LOCAL_PEEREID, &unp, &unpl);], - gnupg_cv_sys_so_local_peereid=yes, - gnupg_cv_sys_so_local_peereid=no) - ]) - AC_MSG_RESULT($gnupg_cv_sys_so_local_peereid) - - if test $gnupg_cv_sys_so_local_peereid = yes; then - AC_DEFINE(HAVE_LOCAL_PEEREID, 1, - [Defined if LOCAL_PEEREID is supported (NetBSD specific)]) - else - # (Open)Solaris - AC_CHECK_FUNCS([getpeerucred], AC_CHECK_HEADERS([ucred.h])) - if test $ac_cv_func_getpeerucred != yes; then - # FreeBSD - AC_CHECK_FUNCS([getpeereid]) - fi - fi -fi +# (Open)Solaris +AC_CHECK_FUNCS([getpeerucred]) #