@@ -252,7 +252,7 @@ impl DomainSocketListenerBuilder {
252252impl GetMetadata for UnixStream {
253253 #[ cfg( feature = "unix-peer-credentials-authenticator" ) ]
254254 fn metadata ( & self ) -> Option < ConnectionMetadata > {
255- let ucred = self . peer_cred ( ) . map_err ( |err| {
255+ let ucred = peer_credentials :: peer_cred ( self ) . map_err ( |err| {
256256 format_error ! (
257257 "Failed to grab peer credentials metadata from UnixStream" ,
258258 err
@@ -272,3 +272,124 @@ impl GetMetadata for UnixStream {
272272 None
273273 }
274274}
275+
276+ // == IMPORTANT NOTE ==
277+ //
278+ // The code below has been cherry-picked from the following PR:
279+ //
280+ // https://github.com/rust-lang/rust/pull/75148
281+ //
282+ // At the time of writing (16/09/20), this patch is in the nightly Rust channel. To avoid needing
283+ // to use the nightly compiler to build Parsec, we have instead opted to cherry-pick the change
284+ // from the patch to allow us to use this feature 'early'.
285+ //
286+ // Once the feature hits stable, it should be safe to revert the commit that introduced the changes
287+ // below with `git revert`.
288+
289+ #[ cfg( feature = "unix-peer-credentials-authenticator" ) ]
290+ mod peer_credentials {
291+ use libc:: { gid_t, pid_t, uid_t} ;
292+
293+ /// Credentials for a UNIX process for credentials passing.
294+ #[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq ) ]
295+ pub struct UCred {
296+ /// The UID part of the peer credential. This is the effective UID of the process at the domain
297+ /// socket's endpoint.
298+ pub uid : uid_t ,
299+ /// The GID part of the peer credential. This is the effective GID of the process at the domain
300+ /// socket's endpoint.
301+ pub gid : gid_t ,
302+ /// The PID part of the peer credential. This field is optional because the PID part of the
303+ /// peer credentials is not supported on every platform. On platforms where the mechanism to
304+ /// discover the PID exists, this field will be populated to the PID of the process at the
305+ /// domain socket's endpoint. Otherwise, it will be set to None.
306+ pub pid : Option < pid_t > ,
307+ }
308+
309+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
310+ pub use self :: impl_linux:: peer_cred;
311+
312+ #[ cfg( any(
313+ target_os = "dragonfly" ,
314+ target_os = "freebsd" ,
315+ target_os = "ios" ,
316+ target_os = "macos" ,
317+ target_os = "openbsd"
318+ ) ) ]
319+ pub use self :: impl_bsd:: peer_cred;
320+
321+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
322+ pub mod impl_linux {
323+ use super :: UCred ;
324+ use libc:: { c_void, getsockopt, socklen_t, ucred, SOL_SOCKET , SO_PEERCRED } ;
325+ use std:: os:: unix:: io:: AsRawFd ;
326+ use std:: os:: unix:: net:: UnixStream ;
327+ use std:: { io, mem} ;
328+
329+ pub fn peer_cred ( socket : & UnixStream ) -> io:: Result < UCred > {
330+ let ucred_size = mem:: size_of :: < ucred > ( ) ;
331+
332+ // Trivial sanity checks.
333+ assert ! ( mem:: size_of:: <u32 >( ) <= mem:: size_of:: <usize >( ) ) ;
334+ assert ! ( ucred_size <= u32 :: MAX as usize ) ;
335+
336+ let mut ucred_size = ucred_size as socklen_t ;
337+ let mut ucred: ucred = ucred {
338+ pid : 1 ,
339+ uid : 1 ,
340+ gid : 1 ,
341+ } ;
342+
343+ unsafe {
344+ let ret = getsockopt (
345+ socket. as_raw_fd ( ) ,
346+ SOL_SOCKET ,
347+ SO_PEERCRED ,
348+ & mut ucred as * mut ucred as * mut c_void ,
349+ & mut ucred_size,
350+ ) ;
351+
352+ if ret == 0 && ucred_size as usize == mem:: size_of :: < ucred > ( ) {
353+ Ok ( UCred {
354+ uid : ucred. uid ,
355+ gid : ucred. gid ,
356+ pid : Some ( ucred. pid ) ,
357+ } )
358+ } else {
359+ Err ( io:: Error :: last_os_error ( ) )
360+ }
361+ }
362+ }
363+ }
364+
365+ #[ cfg( any(
366+ target_os = "dragonfly" ,
367+ target_os = "macos" ,
368+ target_os = "ios" ,
369+ target_os = "freebsd" ,
370+ target_os = "openbsd"
371+ ) ) ]
372+ pub mod impl_bsd {
373+ use super :: UCred ;
374+ use std:: io;
375+ use std:: os:: unix:: io:: AsRawFd ;
376+ use std:: os:: unix:: net:: UnixStream ;
377+
378+ pub fn peer_cred ( socket : & UnixStream ) -> io:: Result < UCred > {
379+ let mut cred = UCred {
380+ uid : 1 ,
381+ gid : 1 ,
382+ pid : None ,
383+ } ;
384+ unsafe {
385+ let ret = libc:: getpeereid ( socket. as_raw_fd ( ) , & mut cred. uid , & mut cred. gid ) ;
386+
387+ if ret == 0 {
388+ Ok ( cred)
389+ } else {
390+ Err ( io:: Error :: last_os_error ( ) )
391+ }
392+ }
393+ }
394+ }
395+ }
0 commit comments