This repository was archived by the owner on May 15, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 26
WIP Implementation of peer credentials. #13
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
7270717
Linux implementation of peer credentials.
Kixunil e0da3a9
Use struct ucred from libc crate instead of our own.
Kixunil 49c09e8
Dropped support for getting PID, since there's no way to do this on m…
Kixunil 23941f9
Untested implementation of peer_cred for macOS.
Kixunil c25564d
Fix for macOS pid -> gid.
Kixunil 1efd6b3
Implemented requested changes. Fixed cfg for non-Linux unices.
Kixunil db78129
Added test for peer credentials.
Kixunil File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
use libc::{uid_t, gid_t}; | ||
|
||
/// Credentials of a process | ||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] | ||
pub struct UCred { | ||
/// UID (user ID) of the process | ||
pub uid: uid_t, | ||
/// GID (group ID) of the process | ||
pub gid: gid_t, | ||
} | ||
|
||
#[cfg(target_os = "linux")] | ||
pub use self::impl_linux::get_peer_cred; | ||
|
||
#[cfg(target_os = "macos")] | ||
pub use self::impl_macos::get_peer_cred; | ||
|
||
#[cfg(target_os = "linux")] | ||
pub mod impl_linux { | ||
use libc::{getsockopt, SOL_SOCKET, SO_PEERCRED, c_void}; | ||
use std::{io, mem}; | ||
use UnixStream; | ||
use std::os::unix::io::AsRawFd; | ||
|
||
use libc::ucred; | ||
|
||
pub fn get_peer_cred(sock: &UnixStream) -> io::Result<super::UCred> { | ||
unsafe { | ||
let raw_fd = sock.as_raw_fd(); | ||
|
||
let mut ucred = ucred { pid: 0, uid: 0, gid: 0 }; | ||
|
||
let ucred_size = mem::size_of::<ucred>(); | ||
|
||
// These paranoid checks should be optimized-out | ||
assert!(mem::size_of::<u32>() <= mem::size_of::<usize>()); | ||
assert!(ucred_size <= u32::max_value() as usize); | ||
|
||
let mut ucred_size = ucred_size as u32; | ||
|
||
let ret = getsockopt(raw_fd, SOL_SOCKET, SO_PEERCRED, &mut ucred as *mut ucred as *mut c_void, &mut ucred_size); | ||
if ret == 0 && ucred_size as usize == mem::size_of::<ucred>() { | ||
Ok(super::UCred { | ||
uid: ucred.uid, | ||
gid: ucred.gid, | ||
}) | ||
} else { | ||
Err(io::Error::last_os_error()) | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))] | ||
pub mod impl_macos { | ||
use libc::getpeereid; | ||
use std::{io, mem}; | ||
use UnixStream; | ||
use std::os::unix::io::AsRawFd; | ||
|
||
pub fn get_peer_cred(sock: &UnixStream) -> io::Result<super::UCred> { | ||
unsafe { | ||
let raw_fd = sock.as_raw_fd(); | ||
|
||
let mut cred: super::UCred = mem::uninitialized(); | ||
|
||
let ret = getpeereid(raw_fd, &mut cred.uid, &mut cred.gid); | ||
|
||
if ret == 0 { | ||
Ok(cred) | ||
} else { | ||
Err(io::Error::last_os_error()) | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use tokio_core::reactor::Core; | ||
use UnixStream; | ||
use libc::geteuid; | ||
use libc::getegid; | ||
|
||
#[test] | ||
fn test_socket_pair() { | ||
let core = Core::new().unwrap(); | ||
let handle = core.handle(); | ||
|
||
let (a, b) = UnixStream::pair(&handle).unwrap(); | ||
let cred_a = a.peer_cred().unwrap(); | ||
let cred_b = b.peer_cred().unwrap(); | ||
assert_eq!(cred_a, cred_b); | ||
|
||
let uid = unsafe { geteuid() }; | ||
let gid = unsafe { getegid() }; | ||
|
||
assert_eq!(cred_a.uid, uid); | ||
assert_eq!(cred_a.gid, gid); | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this use
zeroed
? Seems like there's no reason to use the unsafer version here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be. But I see no point. My reasoning is that the code is already
unsafe
so I see no point in zeroing it. However, If you have good reason to do it, I'd probably go with explicit safe version (pid: 0, uid: 0, gid: 0
).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use
zeroed
here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? Is that some kind of standard?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I see no reason to use
uninitialized
, please change it tozeroed
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant
zeroed
instead ofucred { pid: 0, uid: 0, gid: 0 }
.I guess that syscall only overwrites it, so the reason would be performance. I agree it's negligible, so I accept zeroig. I'm just interested to know whether there is some difference between using
zeroed
and zeroing "manually".There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah those are the same. With libc I tend to use
zeroed
because there's often random hidden fields or fields used for padding, but either way is fine in this case.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, OK. I prefer "safe" version in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be udpated to using
UCred { ... }
?