From 50280bcfedbfc6fe538a969469183f1c03191049 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sun, 2 Mar 2003 07:46:33 +0000 Subject: [PATCH] Interoperability fix for sendmsg/recvmsg with access rights --- libraries/libldap/os-local.c | 26 ++++++++++++++++++++++++++ libraries/liblutil/getpeereid.c | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/libraries/libldap/os-local.c b/libraries/libldap/os-local.c index 833328fd90..0133550399 100644 --- a/libraries/libldap/os-local.c +++ b/libraries/libldap/os-local.c @@ -131,6 +131,10 @@ ldap_pvt_is_socket_ready(LDAP *ld, int s) } #undef TRACE +#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && defined(HAVE_SENDMSG) +#define DO_SENDMSG +#endif + static int ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_un *sa, int async) { @@ -155,6 +159,28 @@ ldap_pvt_connect(LDAP *ld, ber_socket_t s, struct sockaddr_un *sa, int async) if ( ldap_pvt_ndelay_off(ld, s) == -1 ) { return ( -1 ); } +#ifdef DO_SENDMSG + /* Send a dummy message with access rights. Remote side will + * obtain our uid/gid by fstat'ing this descriptor. + */ +sendcred: { + int fds[2], rc; + /* Abandon, noop, has no reply */ + char txt[] = {LDAP_TAG_MESSAGE, 6, LDAP_TAG_MSGID, 1, 0, LDAP_REQ_ABANDON, 1, 0}; + struct iovec iov = {txt, sizeof(txt)}; + struct msghdr msg = {0}; + if (pipe(fds) == 0) { + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_accrights = (char *)fds; + msg.msg_accrightslen = sizeof(int); + rc = sendmsg( s, &msg, 0 ); + if (rc < 0) rc = errno; + close(fds[0]); + close(fds[1]); + } + } +#endif return ( 0 ); } diff --git a/libraries/liblutil/getpeereid.c b/libraries/liblutil/getpeereid.c index 15d908f1ea..d72f7297f5 100644 --- a/libraries/liblutil/getpeereid.c +++ b/libraries/liblutil/getpeereid.c @@ -13,11 +13,17 @@ #include #include +#include #if HAVE_SYS_UCRED_H #include #endif +#if !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && defined(HAVE_SENDMSG) +#define DO_SENDMSG +#include +#endif + int getpeereid( int s, uid_t *euid, gid_t *egid ) { #ifdef LDAP_PF_LOCAL @@ -46,9 +52,34 @@ int getpeereid( int s, uid_t *euid, gid_t *egid ) *egid = peercred.cr_gid; return 0; } +#elif defined( DO_SENDMSG ) + int dummy, fd[2]; + struct iovec iov = {(char *)&dummy, 1}; + struct msghdr msg = {0}; + struct stat st; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_accrights = (char *)fd; + msg.msg_accrightslen = sizeof(fd); + if( recvmsg( s, &msg, MSG_PEEK) >= 0 && msg.msg_accrightslen == sizeof(int) ) + { + /* We must receive a valid descriptor, it must be a pipe, + * and it must only be accessible by its owner. + */ + dummy = fstat( fd[0], &st ); + close(fd[0]); + if( dummy == 0 && S_ISFIFO(st.st_mode) && + ((st.st_mode & (S_IRWXG|S_IRWXO)) == 0)) + { + *euid = st.st_uid; + *egid = st.st_gid; + return 0; + } + } #endif +#endif /* LDAP_PF_LOCAL */ return -1; } -#endif +#endif /* HAVE_GETPEEREID */ -- 2.39.5