]> git.sur5r.net Git - openldap/blobdiff - libraries/liblutil/getpeereid.c
ITS#5615 return success on Solaris 10
[openldap] / libraries / liblutil / getpeereid.c
index 97d87982abf19755b707a6eaedb30de47a9cf90a..e68d0dda316bb75913d50a7b97512dfd42d66d36 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2007 The OpenLDAP Foundation.
+ * Copyright 2000-2008 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include <ucred.h>
 #endif
 
+#ifdef LDAP_PF_LOCAL_SENDMSG
+#include <lber.h>
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#include <sys/stat.h>
+#endif
+
 #ifdef HAVE_SYS_UCRED_H
 #ifdef HAVE_GRP_H
 #include <grp.h>       /* for NGROUPS on Tru64 5.1 */
 #include <sys/ucred.h>
 #endif
 
-#if !defined(HAVE_GETPEERUCRED) && \
-       !defined(SO_PEERCRED) && !defined(LOCAL_PEERCRED) && \
-       defined(HAVE_SENDMSG) && (defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTSLEN) || \
-               defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL))
-#define DO_SENDMSG
-#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-#include <sys/stat.h>
-#endif
-
 #include <stdlib.h>
 
-
-int getpeereid( int s, uid_t *euid, gid_t *egid )
+int lutil_getpeereid( int s, uid_t *euid, gid_t *egid
+#ifdef LDAP_PF_LOCAL_SENDMSG
+       , struct berval *peerbv
+#endif
+       )
 {
 #ifdef LDAP_PF_LOCAL
 #if defined( HAVE_GETPEERUCRED )
@@ -58,11 +58,12 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
                *euid = ucred_geteuid( uc );
                *egid = ucred_getegid( uc );
                ucred_free( uc );
+               return 0;
        }
 
 #elif defined( SO_PEERCRED )
        struct ucred peercred;
-       socklen_t peercredlen = sizeof peercred;
+       ber_socklen_t peercredlen = sizeof peercred;
 
        if(( getsockopt( s, SOL_SOCKET, SO_PEERCRED,
                (void *)&peercred, &peercredlen ) == 0 )
@@ -75,7 +76,7 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
 
 #elif defined( LOCAL_PEERCRED )
        struct xucred peercred;
-       socklen_t peercredlen = sizeof peercred;
+       ber_socklen_t peercredlen = sizeof peercred;
 
        if(( getsockopt( s, LOCAL_PEERCRED, 1,
                (void *)&peercred, &peercredlen ) == 0 )
@@ -85,9 +86,8 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
                *egid = peercred.cr_gid;
                return 0;
        }
-#elif defined( DO_SENDMSG )
-       char dummy[8];
-       int err, fd[2];
+#elif defined( LDAP_PF_LOCAL_SENDMSG ) && defined( MSG_WAITALL )
+       int err, fd;
        struct iovec iov;
        struct msghdr msg = {0};
 # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
@@ -97,52 +97,68 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
 # ifndef CMSG_LEN
 # define CMSG_LEN(len)         (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
 # endif
-       union {
+       struct {
                struct cmsghdr cm;
-               unsigned char control[CMSG_SPACE(sizeof(int))];
-       } control_un;
+               int fd;
+       } control_st;
        struct cmsghdr *cmsg;
 # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
        struct stat st;
+       struct sockaddr_un lname, rname;
+       ber_socklen_t llen, rlen;
 
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
+       rlen = sizeof(rname);
+       llen = sizeof(lname);
+       memset( &lname, 0, sizeof( lname ));
+       getsockname(s, (struct sockaddr *)&lname, &llen);
 
-       iov.iov_base = dummy;
-       iov.iov_len = sizeof dummy;
+       iov.iov_base = peerbv->bv_val;
+       iov.iov_len = peerbv->bv_len;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
+       peerbv->bv_len = 0;
+
 # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
-       msg.msg_control = control_un.control;
-       msg.msg_controllen = sizeof( control_un.control );
+       msg.msg_control = &control_st;
+       msg.msg_controllen = sizeof( struct cmsghdr ) + sizeof( int );  /* no padding! */
 
        cmsg = CMSG_FIRSTHDR( &msg );
+# else
+       msg.msg_accrights = (char *)&fd;
+       msg.msg_accrightslen = sizeof(fd);
+# endif
 
        /*
         * AIX returns a bogus file descriptor if recvmsg() is
         * called with MSG_PEEK (is this a bug?). Hence we need
         * to receive the Abandon PDU.
         */
-       if( recvmsg( s, &msg, MSG_WAITALL ) >= 0 &&
+       err = recvmsg( s, &msg, MSG_WAITALL );
+       if( err >= 0 &&
+# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
            cmsg->cmsg_len == CMSG_LEN( sizeof(int) ) &&
            cmsg->cmsg_level == SOL_SOCKET &&
-           cmsg->cmsg_type == SCM_RIGHTS )
+           cmsg->cmsg_type == SCM_RIGHTS
 # else
-       msg.msg_accrights = (char *)fd;
-       msg.msg_accrightslen = sizeof(fd);
-       if( recvmsg( s, &msg, MSG_PEEK) >= 0 && msg.msg_accrightslen == sizeof(int) )
+               msg.msg_accrightslen == sizeof(int)
 # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL*/
-       {
+       ) {
+               int mode = S_IFIFO|S_ISUID|S_IRWXU;
+
                /* We must receive a valid descriptor, it must be a pipe,
-                * and it must only be accessible by its owner.
+                * it must only be accessible by its owner, and it must
+                * have the name of our socket written on it.
                 */
+               peerbv->bv_len = err;
 # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
-               fd[0] = (*(int *)CMSG_DATA( cmsg ));
+               fd = (*(int *)CMSG_DATA( cmsg ));
 # endif
-               err = fstat( fd[0], &st );
-               close(fd[0]);
-               if( err == 0 && S_ISFIFO(st.st_mode) &&
-                       ((st.st_mode & (S_IRWXG|S_IRWXO)) == 0))
+               err = fstat( fd, &st );
+               if ( err == 0 )
+                       rlen = read(fd, &rname, rlen);
+               close(fd);
+               if( err == 0 && st.st_mode == mode &&
+                       llen == rlen && !memcmp(&lname, &rname, llen))
                {
                        *euid = st.st_uid;
                        *egid = st.st_gid;
@@ -151,7 +167,7 @@ int getpeereid( int s, uid_t *euid, gid_t *egid )
        }
 #elif defined(SOCKCREDSIZE)
        struct msghdr msg;
-       socklen_t crmsgsize;
+       ber_socklen_t crmsgsize;
        void *crmsg;
        struct cmsghdr *cmp;
        struct sockcred *sc;