From 1164ea7196994f98bc2423dd4ce73939d61ca69e Mon Sep 17 00:00:00 2001 From: Magnus Hoff Date: Tue, 15 Dec 2015 10:03:55 +0100 Subject: Implement support for getsockopt of peer credentials using the Linux specific SO_PEERCRED --- src/sys/socket/mod.rs | 10 +++++++++- src/sys/socket/sockopt.rs | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 4f6add4c..7eb1901a 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -6,7 +6,7 @@ use errno::Errno; use features; use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK}; use fcntl::FcntlArg::{F_SETFD, F_SETFL}; -use libc::{c_void, c_int, socklen_t, size_t}; +use libc::{c_void, c_int, socklen_t, size_t, pid_t, uid_t, gid_t}; use std::{mem, ptr, slice}; use std::os::unix::io::RawFd; use sys::uio::IoVec; @@ -581,6 +581,14 @@ pub struct linger { pub l_linger: c_int } +#[repr(C)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct ucred { + pid: pid_t, + uid: uid_t, + gid: gid_t, +} + /* * * ===== Socket Options ===== diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 2f01b91d..6ba43666 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -137,6 +137,8 @@ sockopt_impl!(Both, Broadcast, consts::SOL_SOCKET, consts::SO_BROADCAST, bool); sockopt_impl!(Both, OobInline, consts::SOL_SOCKET, consts::SO_OOBINLINE, bool); sockopt_impl!(GetOnly, SocketError, consts::SOL_SOCKET, consts::SO_ERROR, i32); sockopt_impl!(Both, KeepAlive, consts::SOL_SOCKET, consts::SO_KEEPALIVE, bool); +#[cfg(target_os = "linux")] +sockopt_impl!(GetOnly, PeerCredentials, consts::SOL_SOCKET, consts::SO_PEERCRED, super::ucred); #[cfg(any(target_os = "macos", target_os = "ios"))] sockopt_impl!(Both, TcpKeepAlive, consts::IPPROTO_TCP, consts::TCP_KEEPALIVE, u32); @@ -300,3 +302,19 @@ impl<'a> Set<'a, u8> for SetU8 { mem::size_of::() as socklen_t } } + + +#[cfg(test)] +mod test { + #[cfg(target_os = "linux")] + #[test] + fn can_get_peercred_on_unix_socket() { + use super::super::*; + + let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, 0, SockFlag::empty()).unwrap(); + let a_cred = getsockopt(a, super::PeerCredentials).unwrap(); + let b_cred = getsockopt(b, super::PeerCredentials).unwrap(); + assert_eq!(a_cred, b_cred); + assert!(a_cred.pid != 0); + } +} -- cgit v1.2.3