Skip to content

Commit

Permalink
Add UnixCredentials support on FreeBSD/DragonFly (cmsgcred/SCM_CREDS)
Browse files Browse the repository at this point in the history
  • Loading branch information
valpackett committed Apr 14, 2020
1 parent 154ff58 commit 720e4fe
Showing 1 changed file with 81 additions and 11 deletions.
92 changes: 81 additions & 11 deletions src/sys/socket/mod.rs
Expand Up @@ -189,7 +189,8 @@ cfg_if! {
if #[cfg(any(target_os = "android", target_os = "linux"))] {
/// Unix credentials of the sending process.
///
/// This struct is used with the `SO_PEERCRED` ancillary message for UNIX sockets.
/// This struct is used with the `SO_PEERCRED` ancillary message
/// and the `SCM_CREDENTIALS` control message for UNIX sockets.
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct UnixCredentials(libc::ucred);
Expand Down Expand Up @@ -222,8 +223,43 @@ cfg_if! {
self.0
}
}
}
}
} else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] {
/// Unix credentials of the sending process.
///
/// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets.
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct UnixCredentials(libc::cmsgcred);

impl UnixCredentials {
/// Returns the process identifier
pub fn pid(&self) -> libc::pid_t {
self.0.cmcred_pid
}

/// Returns the user identifier
pub fn uid(&self) -> libc::uid_t {
self.0.cmcred_uid
}

/// Returns the group identifier
pub fn gid(&self) -> libc::gid_t {
self.0.cmcred_gid
}
}

impl From<libc::cmsgcred> for UnixCredentials {
fn from(cred: libc::cmsgcred) -> Self {
UnixCredentials(cred)
}
}

impl Into<libc::cmsgcred> for UnixCredentials {
fn into(self) -> libc::cmsgcred {
self.0
}
}
}}

/// Request for multicast socket operations
///
Expand Down Expand Up @@ -367,7 +403,12 @@ pub enum ControlMessageOwned {
ScmRights(Vec<RawFd>),
/// Received version of
/// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "freebsd",
target_os = "dragonfly",
))]
ScmCredentials(UnixCredentials),
/// A message of type `SCM_TIMESTAMP`, containing the time the
/// packet was received by the kernel.
Expand Down Expand Up @@ -498,6 +539,11 @@ impl ControlMessageOwned {
let cred: libc::ucred = ptr::read_unaligned(p as *const _);
ControlMessageOwned::ScmCredentials(cred.into())
}
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
(libc::SOL_SOCKET, /* libc::SCM_CREDS */ 0x03) => {
let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _);
ControlMessageOwned::ScmCredentials(cred.into())
}
(libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
let tv: libc::timeval = ptr::read_unaligned(p as *const _);
ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
Expand Down Expand Up @@ -574,17 +620,25 @@ pub enum ControlMessage<'a> {
/// Instead, you can put all fds to be passed into a single `ScmRights`
/// message.
ScmRights(&'a [RawFd]),
/// A message of type `SCM_CREDENTIALS`, containing the pid, uid and gid of
/// A message of type `SCM_CREDENTIALS`/`SCM_CREDS`, containing the pid, uid and gid of
/// a process connected to the socket.
///
/// This is similar to the socket option `SO_PEERCRED`, but requires a
/// process to explicitly send its credentials. A process running as root is
/// allowed to specify any credentials, while credentials sent by other
/// processes are verified by the kernel.
/// process to explicitly send its credentials.
///
/// On Linux, a process running as root is allowed to specify any credentials,
/// while credentials sent by other processes are verified by the kernel.
///
/// On FreeBSD/DragonFly, credentials are always overwritten by the kernel.
///
/// For further information, please refer to the
/// [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html) man page.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "freebsd",
target_os = "dragonfly",
))]
ScmCredentials(&'a UnixCredentials),

/// Set IV for `AF_ALG` crypto API.
Expand Down Expand Up @@ -655,6 +709,10 @@ impl<'a> ControlMessage<'a> {
ControlMessage::ScmCredentials(creds) => {
&creds.0 as *const libc::ucred as *const u8
}
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
ControlMessage::ScmCredentials(creds) => {
&creds.0 as *const libc::cmsgcred as *const u8
}
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::AlgSetIv(iv) => {
unsafe {
Expand Down Expand Up @@ -692,7 +750,12 @@ impl<'a> ControlMessage<'a> {
ControlMessage::ScmRights(fds) => {
mem::size_of_val(fds)
},
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "freebsd",
target_os = "dragonfly",
))]
ControlMessage::ScmCredentials(creds) => {
mem::size_of_val(creds)
}
Expand All @@ -715,7 +778,12 @@ impl<'a> ControlMessage<'a> {
fn cmsg_level(&self) -> libc::c_int {
match *self {
ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "freebsd",
target_os = "dragonfly",
))]
ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
Expand All @@ -729,6 +797,8 @@ impl<'a> ControlMessage<'a> {
ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
ControlMessage::ScmCredentials(_) => /* libc::SCM_CREDS */ 0x03, // https://github.com/rust-lang/libc/pull/1740
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::AlgSetIv(_) => {
libc::ALG_SET_IV
Expand Down

0 comments on commit 720e4fe

Please sign in to comment.