1 //! Unix peer credentials.
3 // NOTE: Code in this file is heavily based on work done in PR 13 from the tokio-uds repository on
6 // For reference, the link is here: https://github.com/tokio-rs/tokio-uds/pull/13
7 // Credit to Martin Habovštiak (GitHub username Kixunil) and contributors for this work.
9 use libc
::{gid_t, pid_t, uid_t}
;
11 /// Credentials for a UNIX process for credentials passing.
12 #[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")]
13 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
15 /// The UID part of the peer credential. This is the effective UID of the process at the domain
16 /// socket's endpoint.
18 /// The GID part of the peer credential. This is the effective GID of the process at the domain
19 /// socket's endpoint.
21 /// The PID part of the peer credential. This field is optional because the PID part of the
22 /// peer credentials is not supported on every platform. On platforms where the mechanism to
23 /// discover the PID exists, this field will be populated to the PID of the process at the
24 /// domain socket's endpoint. Otherwise, it will be set to None.
25 pub pid
: Option
<pid_t
>,
28 #[cfg(any(target_os = "android", target_os = "linux"))]
29 pub use self::impl_linux
::peer_cred
;
32 target_os
= "dragonfly",
33 target_os
= "freebsd",
34 target_os
= "openbsd",
37 pub use self::impl_bsd
::peer_cred
;
39 #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
40 pub use self::impl_mac
::peer_cred
;
42 #[cfg(any(target_os = "linux", target_os = "android"))]
45 use crate::os
::unix
::io
::AsRawFd
;
46 use crate::os
::unix
::net
::UnixStream
;
48 use libc
::{c_void, getsockopt, socklen_t, ucred, SOL_SOCKET, SO_PEERCRED}
;
50 pub fn peer_cred(socket
: &UnixStream
) -> io
::Result
<UCred
> {
51 let ucred_size
= mem
::size_of
::<ucred
>();
53 // Trivial sanity checks.
54 assert
!(mem
::size_of
::<u32>() <= mem
::size_of
::<usize>());
55 assert
!(ucred_size
<= u32::MAX
as usize);
57 let mut ucred_size
= ucred_size
as socklen_t
;
58 let mut ucred
: ucred
= ucred { pid: 1, uid: 1, gid: 1 }
;
65 &mut ucred
as *mut ucred
as *mut c_void
,
69 if ret
== 0 && ucred_size
as usize == mem
::size_of
::<ucred
>() {
70 Ok(UCred { uid: ucred.uid, gid: ucred.gid, pid: Some(ucred.pid) }
)
72 Err(io
::Error
::last_os_error())
79 target_os
= "dragonfly",
80 target_os
= "freebsd",
81 target_os
= "openbsd",
88 use crate::os
::unix
::io
::AsRawFd
;
89 use crate::os
::unix
::net
::UnixStream
;
91 pub fn peer_cred(socket
: &UnixStream
) -> io
::Result
<UCred
> {
92 let mut cred
= UCred { uid: 1, gid: 1, pid: None }
;
94 let ret
= libc
::getpeereid(socket
.as_raw_fd(), &mut cred
.uid
, &mut cred
.gid
);
96 if ret
== 0 { Ok(cred) }
else { Err(io::Error::last_os_error()) }
101 #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
104 use crate::os
::unix
::io
::AsRawFd
;
105 use crate::os
::unix
::net
::UnixStream
;
106 use crate::{io, mem}
;
107 use libc
::{c_void, getpeereid, getsockopt, pid_t, socklen_t, LOCAL_PEERPID, SOL_LOCAL}
;
109 pub fn peer_cred(socket
: &UnixStream
) -> io
::Result
<UCred
> {
110 let mut cred
= UCred { uid: 1, gid: 1, pid: None }
;
112 let ret
= getpeereid(socket
.as_raw_fd(), &mut cred
.uid
, &mut cred
.gid
);
115 return Err(io
::Error
::last_os_error());
118 let mut pid
: pid_t
= 1;
119 let mut pid_size
= mem
::size_of
::<pid_t
>() as socklen_t
;
121 let ret
= getsockopt(
125 &mut pid
as *mut pid_t
as *mut c_void
,
129 if ret
== 0 && pid_size
as usize == mem
::size_of
::<pid_t
>() {
130 cred
.pid
= Some(pid
);
133 Err(io
::Error
::last_os_error())