@@ -252,7 +252,7 @@ impl DomainSocketListenerBuilder {
252
252
impl GetMetadata for UnixStream {
253
253
#[ cfg( feature = "unix-peer-credentials-authenticator" ) ]
254
254
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| {
256
256
format_error ! (
257
257
"Failed to grab peer credentials metadata from UnixStream" ,
258
258
err
@@ -272,3 +272,124 @@ impl GetMetadata for UnixStream {
272
272
None
273
273
}
274
274
}
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