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