1#![allow(unsafe_code)]
6
7use std::os::fd::AsRawFd;
8use std::os::unix::net::UnixStream;
9
10pub fn current_uid() -> u32 {
12 unsafe { libc::getuid() }
14}
15
16#[cfg(target_os = "linux")]
18pub fn peer_cred(s: &UnixStream) -> Option<libc::ucred> {
19 let mut cred = libc::ucred {
20 pid: 0,
21 uid: 0,
22 gid: 0,
23 };
24 let mut len = std::mem::size_of::<libc::ucred>() as libc::socklen_t;
25 let rc = unsafe {
28 libc::getsockopt(
29 s.as_raw_fd(),
30 libc::SOL_SOCKET,
31 libc::SO_PEERCRED,
32 (&raw mut cred).cast::<libc::c_void>(),
33 &mut len,
34 )
35 };
36 (rc == 0).then_some(cred)
37}
38
39pub fn peer_uid(s: &UnixStream) -> Option<u32> {
41 #[cfg(target_os = "linux")]
42 {
43 peer_cred(s).map(|c| c.uid)
44 }
45 #[cfg(not(target_os = "linux"))]
46 {
47 let mut uid: libc::uid_t = 0;
48 let mut gid: libc::gid_t = 0;
49 let rc = unsafe { libc::getpeereid(s.as_raw_fd(), &mut uid, &mut gid) };
52 (rc == 0).then_some(uid)
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn the_peer_of_a_pair_is_this_process() {
62 let (a, _b) = UnixStream::pair().unwrap();
63 assert_eq!(peer_uid(&a), Some(current_uid()));
64 }
65}