#include <sys/types.h>
#include <ac/unistd.h>
+#include <ac/socket.h>
+#include <ac/errno.h>
+
+#ifdef HAVE_GETPEERUCRED
+#include <ucred.h>
+#endif
+
#ifdef LDAP_PF_LOCAL_SENDMSG
#include <lber.h>
#ifdef HAVE_SYS_UIO_H
#include <sys/stat.h>
#endif
-#include <ac/socket.h>
-#include <ac/errno.h>
-
-#ifdef HAVE_GETPEERUCRED
-#include <ucred.h>
-#endif
-
#ifdef HAVE_SYS_UCRED_H
#ifdef HAVE_GRP_H
#include <grp.h> /* for NGROUPS on Tru64 5.1 */
#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 )
#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 )
*egid = peercred.cr_gid;
return 0;
}
-#elif defined( LDAP_PF_LOCAL_SENDMSG )
+#elif defined( LDAP_PF_LOCAL_SENDMSG ) && defined( MSG_WAITALL )
int err, fd;
struct iovec iov;
struct msghdr msg = {0};
# 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 = 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
* called with MSG_PEEK (is this a bug?). Hence we need
* to receive the Abandon PDU.
*/
- peerbv->bv_len = recvmsg( s, &msg, MSG_WAITALL );
- if( peerbv->bv_len >= 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 &&
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 = (*(int *)CMSG_DATA( cmsg ));
# endif
err = fstat( fd, &st );
+ if ( err == 0 )
+ rlen = read(fd, &rname, rlen);
close(fd);
- if( err == 0 && S_ISFIFO(st.st_mode) &&
- ((st.st_mode & (S_IRWXG|S_IRWXO)) == 0))
+ if( err == 0 && st.st_mode == mode &&
+ llen == rlen && !memcmp(&lname, &rname, llen))
{
*euid = st.st_uid;
*egid = st.st_gid;
return 0;
}
- } else if ( peer->bv_len < 0 ) {
- peer->bv_len = 0;
}
#elif defined(SOCKCREDSIZE)
struct msghdr msg;
- socklen_t crmsgsize;
+ ber_socklen_t crmsgsize;
void *crmsg;
struct cmsghdr *cmp;
struct sockcred *sc;