diff --git a/CHANGELOG.md b/CHANGELOG.md index a110f6500b..f3f5df6023 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Added `mremap` (#[1306](https://github.com/nix-rust/nix/pull/1306)) +- Added `getpeereid` (#[1342](https://github.com/nix-rust/nix/pull/1342)) +### Changed ### Fixed ### Changed diff --git a/src/unistd.rs b/src/unistd.rs index a945ac265a..d566200019 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -2785,3 +2785,23 @@ pub fn ttyname(fd: RawFd) -> Result { buf.truncate(nul); Ok(OsString::from_vec(buf).into()) } + +/// Get the effective user ID and group ID associated with a Unix domain socket. +/// +/// See also [getpeereid(3)](https://www.freebsd.org/cgi/man.cgi?query=getpeereid) +#[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly", +))] +pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> { + let mut uid = 1; + let mut gid = 1; + + let ret = unsafe { libc::getpeereid(fd, &mut uid, &mut gid) }; + + Errno::result(ret).map(|_| (Uid(uid), Gid(gid))) +} diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 113bef62e5..15cd1b05f8 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -1066,3 +1066,42 @@ fn test_ttyname_invalid_fd() { fn test_ttyname_invalid_fd() { assert_eq!(ttyname(-1), Err(Error::Sys(Errno::ENOTTY))); } + +#[test] +#[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly", +))] +fn test_getpeereid() { + use std::os::unix::net::UnixStream; + let (sock_a, sock_b) = UnixStream::pair().unwrap(); + + let (uid_a, gid_a) = getpeereid(sock_a.as_raw_fd()).unwrap(); + let (uid_b, gid_b) = getpeereid(sock_b.as_raw_fd()).unwrap(); + + let uid = geteuid(); + let gid = getegid(); + + assert_eq!(uid, uid_a); + assert_eq!(gid, gid_a); + assert_eq!(uid_a, uid_b); + assert_eq!(gid_a, gid_b); +} + +#[test] +#[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly", +))] +fn test_getpeereid_invalid_fd() { + // getpeereid is not POSIX, so error codes are inconsistent between different Unices. + assert!(getpeereid(-1).is_err()); +}