@@ -189,12 +189,22 @@ cfg_if! {
189
189
if #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ] {
190
190
/// Unix credentials of the sending process.
191
191
///
192
- /// This struct is used with the `SO_PEERCRED` ancillary message for UNIX sockets.
192
+ /// This struct is used with the `SO_PEERCRED` ancillary message
193
+ /// and the `SCM_CREDENTIALS` control message for UNIX sockets.
193
194
#[ repr( transparent) ]
194
195
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
195
196
pub struct UnixCredentials ( libc:: ucred) ;
196
197
197
198
impl UnixCredentials {
199
+ /// Creates a new instance with the credentials of the current process
200
+ pub fn new( ) -> Self {
201
+ UnixCredentials ( libc:: ucred {
202
+ pid: crate :: unistd:: getpid( ) . as_raw( ) ,
203
+ uid: crate :: unistd:: getuid( ) . as_raw( ) ,
204
+ gid: crate :: unistd:: getgid( ) . as_raw( ) ,
205
+ } )
206
+ }
207
+
198
208
/// Returns the process identifier
199
209
pub fn pid( & self ) -> libc:: pid_t {
200
210
self . 0 . pid
@@ -222,6 +232,46 @@ cfg_if! {
222
232
self . 0
223
233
}
224
234
}
235
+ } else if #[ cfg( any( target_os = "freebsd" , target_os = "dragonfly" ) ) ] {
236
+ /// Unix credentials of the sending process.
237
+ ///
238
+ /// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets.
239
+ #[ repr( transparent) ]
240
+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
241
+ pub struct UnixCredentials ( libc:: cmsgcred) ;
242
+
243
+ impl UnixCredentials {
244
+ /// Returns the process identifier
245
+ pub fn pid( & self ) -> libc:: pid_t {
246
+ self . 0 . cmcred_pid
247
+ }
248
+
249
+ /// Returns the real user identifier
250
+ pub fn uid( & self ) -> libc:: uid_t {
251
+ self . 0 . cmcred_uid
252
+ }
253
+
254
+ /// Returns the effective user identifier
255
+ pub fn euid( & self ) -> libc:: uid_t {
256
+ self . 0 . cmcred_euid
257
+ }
258
+
259
+ /// Returns the real group identifier
260
+ pub fn gid( & self ) -> libc:: gid_t {
261
+ self . 0 . cmcred_gid
262
+ }
263
+
264
+ /// Returns a list group identifiers (the first one being the effective GID)
265
+ pub fn groups( & self ) -> & [ libc:: gid_t] {
266
+ unsafe { slice:: from_raw_parts( self . 0 . cmcred_groups. as_ptr( ) as * const libc:: gid_t, self . 0 . cmcred_ngroups as _) }
267
+ }
268
+ }
269
+
270
+ impl From <libc:: cmsgcred> for UnixCredentials {
271
+ fn from( cred: libc:: cmsgcred) -> Self {
272
+ UnixCredentials ( cred)
273
+ }
274
+ }
225
275
}
226
276
}
227
277
@@ -369,6 +419,10 @@ pub enum ControlMessageOwned {
369
419
/// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
370
420
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
371
421
ScmCredentials ( UnixCredentials ) ,
422
+ /// Received version of
423
+ /// [`ControlMessage::ScmCreds`][#enum.ControlMessage.html#variant.ScmCreds]
424
+ #[ cfg( any( target_os = "freebsd" , target_os = "dragonfly" ) ) ]
425
+ ScmCreds ( UnixCredentials ) ,
372
426
/// A message of type `SCM_TIMESTAMP`, containing the time the
373
427
/// packet was received by the kernel.
374
428
///
@@ -510,6 +564,11 @@ impl ControlMessageOwned {
510
564
let cred: libc:: ucred = ptr:: read_unaligned ( p as * const _ ) ;
511
565
ControlMessageOwned :: ScmCredentials ( cred. into ( ) )
512
566
}
567
+ #[ cfg( any( target_os = "freebsd" , target_os = "dragonfly" ) ) ]
568
+ ( libc:: SOL_SOCKET , libc:: SCM_CREDS ) => {
569
+ let cred: libc:: cmsgcred = ptr:: read_unaligned ( p as * const _ ) ;
570
+ ControlMessageOwned :: ScmCreds ( cred. into ( ) )
571
+ }
513
572
( libc:: SOL_SOCKET , libc:: SCM_TIMESTAMP ) => {
514
573
let tv: libc:: timeval = ptr:: read_unaligned ( p as * const _ ) ;
515
574
ControlMessageOwned :: ScmTimestamp ( TimeVal :: from ( tv) )
@@ -603,6 +662,20 @@ pub enum ControlMessage<'a> {
603
662
/// [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html) man page.
604
663
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
605
664
ScmCredentials ( & ' a UnixCredentials ) ,
665
+ /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
666
+ /// a process connected to the socket.
667
+ ///
668
+ /// This is similar to the socket options `LOCAL_CREDS` and `LOCAL_PEERCRED`, but
669
+ /// requires a process to explicitly send its credentials.
670
+ ///
671
+ /// Credentials are always overwritten by the kernel, so this variant does have
672
+ /// any data, unlike the receive-side
673
+ /// [`ControlMessageOwned::ScmCreds`][#enum.ControlMessageOwned.html#variant.ScmCreds].
674
+ ///
675
+ /// For further information, please refer to the
676
+ /// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
677
+ #[ cfg( any( target_os = "freebsd" , target_os = "dragonfly" ) ) ]
678
+ ScmCreds ,
606
679
607
680
/// Set IV for `AF_ALG` crypto API.
608
681
///
@@ -682,6 +755,13 @@ impl<'a> ControlMessage<'a> {
682
755
ControlMessage :: ScmCredentials ( creds) => {
683
756
& creds. 0 as * const libc:: ucred as * const u8
684
757
}
758
+ #[ cfg( any( target_os = "freebsd" , target_os = "dragonfly" ) ) ]
759
+ ControlMessage :: ScmCreds => {
760
+ // The kernel overwrites the data, we just zero it
761
+ // to make sure it's not uninitialized memory
762
+ unsafe { ptr:: write_bytes ( cmsg_data, 0 , self . len ( ) ) } ;
763
+ return
764
+ }
685
765
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
686
766
ControlMessage :: AlgSetIv ( iv) => {
687
767
let af_alg_iv = libc:: af_alg_iv {
@@ -738,6 +818,10 @@ impl<'a> ControlMessage<'a> {
738
818
ControlMessage :: ScmCredentials ( creds) => {
739
819
mem:: size_of_val ( creds)
740
820
}
821
+ #[ cfg( any( target_os = "freebsd" , target_os = "dragonfly" ) ) ]
822
+ ControlMessage :: ScmCreds => {
823
+ mem:: size_of :: < libc:: cmsgcred > ( )
824
+ }
741
825
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
742
826
ControlMessage :: AlgSetIv ( iv) => {
743
827
mem:: size_of :: < libc:: af_alg_iv > ( ) + iv. len ( )
@@ -763,6 +847,8 @@ impl<'a> ControlMessage<'a> {
763
847
ControlMessage :: ScmRights ( _) => libc:: SOL_SOCKET ,
764
848
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
765
849
ControlMessage :: ScmCredentials ( _) => libc:: SOL_SOCKET ,
850
+ #[ cfg( any( target_os = "freebsd" , target_os = "dragonfly" ) ) ]
851
+ ControlMessage :: ScmCreds => libc:: SOL_SOCKET ,
766
852
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
767
853
ControlMessage :: AlgSetIv ( _) | ControlMessage :: AlgSetOp ( _) |
768
854
ControlMessage :: AlgSetAeadAssoclen ( _) => libc:: SOL_ALG ,
@@ -777,6 +863,8 @@ impl<'a> ControlMessage<'a> {
777
863
ControlMessage :: ScmRights ( _) => libc:: SCM_RIGHTS ,
778
864
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
779
865
ControlMessage :: ScmCredentials ( _) => libc:: SCM_CREDENTIALS ,
866
+ #[ cfg( any( target_os = "freebsd" , target_os = "dragonfly" ) ) ]
867
+ ControlMessage :: ScmCreds => libc:: SCM_CREDS ,
780
868
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
781
869
ControlMessage :: AlgSetIv ( _) => {
782
870
libc:: ALG_SET_IV
0 commit comments