From 354b3c6786f78cba376c2a79ede95bb7df1dc65a Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 26 Nov 2020 13:09:21 -0500 Subject: [PATCH] unistd: Add getpeereid(3) Closes #1339. --- CHANGELOG.md | 2 ++ src/unistd.rs | 22 +++++++++++++++++++++- test/test_unistd.rs | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56abe869c8..8e982b695b 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 ### Removed diff --git a/src/unistd.rs b/src/unistd.rs index 04031e3729..f366026dfe 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -1065,7 +1065,7 @@ pub fn pipe() -> Result<(RawFd, RawFd)> { /// The following flags are supported, and will be set atomically as the pipe is /// created: /// -/// `O_CLOEXEC`: Set the close-on-exec flag for the new file descriptors. +/// `O_CLOEXEC`: Set the close-on-exec flag for the new file descriptors. #[cfg_attr(target_os = "linux", doc = "`O_DIRECT`: Create a pipe that performs I/O in \"packet\" mode. ")] #[cfg_attr(target_os = "netbsd", doc = "`O_NOSIGPIPE`: Return `EPIPE` instead of raising `SIGPIPE`. ")] /// `O_NONBLOCK`: Set the non-blocking flag for the ends of the pipe. @@ -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 a4b8a91668..f0100b6943 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -1044,3 +1044,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()); +}