mac-process 0.1.0

User-mode library for querying and verifying integrity of MacOS processes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
//! Types for macOS-specific information about a process' network usage
use crate::libproc::file_info::{PIDFDInfo, PIDFDInfoFlavor};
use libc::SOCK_MAXADDRLEN;
use libc::{
    IF_NAMESIZE, c_char, c_int, c_short, c_uchar, c_ushort, gid_t, in_addr, in6_addr, off_t,
    sockaddr_un, uid_t,
};
#[cfg(target_os = "linux")]
pub const SOCK_MAXADDRLEN: c_int = 255;

/// Socket File Descriptor Info
#[repr(C)]
#[derive(Default)]
pub struct SocketFDInfo {
    /// Proc File Info
    pub pfi: ProcFileInfo,
    /// Socket Info
    pub psi: SocketInfo,
}

/// Proc File Info
#[repr(C)]
#[derive(Default)]
pub struct ProcFileInfo {
    /// Open flags
    pub fi_openflags: u32,
    /// Status
    pub fi_status: u32,
    /// Offset
    pub fi_offset: off_t,
    /// Type
    pub fi_type: i32,
    /// Reserved for future use
    pub rfu_1: i32,
}

impl PIDFDInfo for SocketFDInfo {
    fn flavor() -> PIDFDInfoFlavor {
        PIDFDInfoFlavor::SocketInfo
    }
}

/// Socket Info Kind
#[derive(Copy, Clone, Debug)]
pub enum SocketInfoKind {
    /// Generic
    Generic = 0,
    /// IPv4 and IPv6 Sockets
    In = 1,
    /// TCP Sockets
    Tcp = 2,
    /// Unix Domain Sockets
    Un = 3,
    /// Net Drive Sockets
    Ndrv = 4,
    /// Kernel Event Sockets
    KernEvent = 5,
    /// Kernel Control Sockets
    KernCtl = 6,
    /// Unknown
    Unknown,
}

impl From<c_int> for SocketInfoKind {
    fn from(value: c_int) -> SocketInfoKind {
        match value {
            0 => SocketInfoKind::Generic,
            1 => SocketInfoKind::In,
            2 => SocketInfoKind::Tcp,
            3 => SocketInfoKind::Un,
            4 => SocketInfoKind::Ndrv,
            5 => SocketInfoKind::KernEvent,
            6 => SocketInfoKind::KernCtl,
            _ => SocketInfoKind::Unknown,
        }
    }
}

/// Socket Info
#[repr(C)]
#[derive(Default)]
pub struct SocketInfo {
    /// Stat
    pub soi_stat: VInfoStat,
    /// SO
    pub soi_so: u64,
    /// PCB
    pub soi_pcb: u64,
    /// Type
    pub soi_type: c_int,
    /// Protocol
    pub soi_protocol: c_int,
    /// Family
    pub soi_family: c_int,
    /// Options
    pub soi_options: c_short,
    /// Linger
    pub soi_linger: c_short,
    /// State
    pub soi_state: c_short,
    /// Queue Length
    pub soi_qlen: c_short,
    /// Incremental Queue Length
    pub soi_incqlen: c_short,
    /// Queue Limit
    pub soi_qlimit: c_short,
    /// Time O
    pub soi_timeo: c_short,
    /// Error
    pub soi_error: c_ushort,
    /// OOB Mark
    pub soi_oobmark: u32,
    /// Receive
    pub soi_rcv: SockBufInfo,
    /// Send
    pub soi_snd: SockBufInfo,
    /// Kind
    pub soi_kind: c_int,
    /// Reserved for future use
    pub rfu_1: u32,
    /// Proto
    pub soi_proto: SocketInfoProto,
}

/// Struct for V Info Stat
#[repr(C)]
#[derive(Default)]
pub struct VInfoStat {
    /// ID of device containing file
    pub vst_dev: u32,
    /// Mode of file (see below)
    pub vst_mode: u16,
    /// Number of hard links
    pub vst_nlink: u16,
    /// File serial number
    pub vst_ino: u64,
    /// User ID of the file
    pub vst_uid: uid_t,
    /// Group ID of the file
    pub vst_gid: gid_t,
    /// Time of last access
    pub vst_atime: i64,
    /// Time of last access in nano seconds
    pub vst_atimensec: i64,
    /// Last data modification time
    pub vst_mtime: i64,
    /// Last data modification time in nano seconds
    pub vst_mtimensec: i64,
    /// Time of last status change
    pub vst_ctime: i64,
    /// Time of last status change in nano seconds
    pub vst_ctimensec: i64,
    /// File creation time(birth)
    pub vst_birthtime: i64,
    /// File creation time(birth) in nano seconds
    pub vst_birthtimensec: i64,
    /// file size, in bytes
    pub vst_size: off_t,
    /// blocks allocated for file
    pub vst_blocks: i64,
    /// optimal blocksize for I/O
    pub vst_blksize: i32,
    /// user defined flags for file
    pub vst_flags: u32,
    /// file generation number
    pub vst_gen: u32,
    /// Device ID
    pub vst_rdev: u32,
    /// RESERVED: DO NOT USE!
    pub vst_qspare: [i64; 2],
}

/// Socket Buffer Info
#[repr(C)]
#[derive(Default)]
pub struct SockBufInfo {
    /// CC
    pub sbi_cc: u32,
    /// Hiwat
    pub sbi_hiwat: u32,
    /// MB Count
    pub sbi_mbcnt: u32,
    /// MB Max
    pub sbi_mbmax: u32,
    /// Lowat
    pub sbi_lowat: u32,
    /// Flags
    pub sbi_flags: c_short,
    /// Timeo
    pub sbi_timeo: c_short,
}

/// Socket Info Proto
#[repr(C)]
pub union SocketInfoProto {
    /// In socket info
    pub pri_in: InSockInfo,
    /// TCP Socket Info
    pub pri_tcp: TcpSockInfo,
    /// Un socket info
    pub pri_un: UnSockInfo,
    /// N Drive Info
    pub pri_ndrv: NdrvInfo,
    /// Kern Event Info
    pub pri_kern_event: KernEventInfo,
    /// Kernel Control Info
    pub pri_kern_ctl: KernCtlInfo,
}

impl Default for SocketInfoProto {
    fn default() -> SocketInfoProto {
        SocketInfoProto {
            pri_in: InSockInfo::default(),
        }
    }
}

/// struct for holding IP4 or IP6 addresses
#[repr(C)]
#[derive(Copy, Clone)]
pub struct In4In6Addr {
    /// Padding
    pub i46a_pad32: [u32; 3],
    /// Address
    pub i46a_addr4: in_addr,
}

impl Default for In4In6Addr {
    fn default() -> In4In6Addr {
        In4In6Addr {
            i46a_pad32: [0; 3],
            i46a_addr4: in_addr { s_addr: 0 },
        }
    }
}

/// `InSocketInfo` struct
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct InSockInfo {
    /// Foreign Port
    pub insi_fport: c_int,
    /// Local Port
    pub insi_lport: c_int,
    /// generation count of this instance
    pub insi_gencnt: u64,
    /// generic IP/datagram flags
    pub insi_flags: u32,
    /// Flow
    pub insi_flow: u32,
    /// In Socket Info IPV4 or IPV6
    pub insi_vflag: u8,
    /// time to live proto
    pub insi_ip_ttl: u8,
    /// Reserved for future use
    pub rfu_1: u32,
    /// foreign host table entry
    pub insi_faddr: InSIAddr,
    /// local host table entry
    pub insi_laddr: InSIAddr,
    /// V4 info
    pub insi_v4: InSIV4,
    /// V6 info
    pub insi_v6: InSIV6,
}

/// In Socket Info `InSIV4` struct
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct InSIV4 {
    /// Input socket V4 type of service
    pub in4_top: c_uchar, // NOTE: Should be in4_tos!
}

/// In Socket Info `InSIV6` struct
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct InSIV6 {
    /// `Hlim`
    pub in6_hlim: u8,
    /// Checksum
    pub in6_cksum: c_int,
    /// Interface Index
    pub in6_ifindex: c_ushort,
    /// Hops
    pub in6_hops: c_short,
}

/// In Socket Info `InSIAddr` union for v4 and v6 addresses
#[repr(C)]
#[derive(Copy, Clone)]
pub union InSIAddr {
    /// v4 address
    pub ina_46: In4In6Addr,
    /// v6 address
    pub ina_6: in6_addr,
}

impl Default for InSIAddr {
    fn default() -> InSIAddr {
        InSIAddr {
            ina_46: In4In6Addr::default(),
        }
    }
}

/// TCP SI State struct
#[derive(Copy, Clone, Debug)]
pub enum TcpSIState {
    /// Closed
    Closed = 0,
    /// Listening for connection
    Listen = 1,
    /// Active, have sent syn
    SynSent = 2,
    /// Have send and received syn
    SynReceived = 3,
    /// Established
    Established = 4,
    /// Rcvd fin, waiting for close
    CloseWait = 5,
    /// Have closed, sent fin
    FinWait1 = 6,
    /// Closed xchd FIN; await FIN ACK
    Closing = 7,
    /// Had fin and close; await FIN ACK
    LastAck = 8,
    /// Have closed, fin is acked
    FinWait2 = 9,
    /// In 2*msl quiet wait after close
    TimeWait = 10,
    /// Pseudo state: reserved
    Reserved = 11,
    /// Unknown
    Unknown,
}

impl From<c_int> for TcpSIState {
    fn from(value: c_int) -> TcpSIState {
        match value {
            0 => TcpSIState::Closed,
            1 => TcpSIState::Listen,
            2 => TcpSIState::SynSent,
            3 => TcpSIState::SynReceived,
            4 => TcpSIState::Established,
            5 => TcpSIState::CloseWait,
            6 => TcpSIState::FinWait1,
            7 => TcpSIState::Closing,
            8 => TcpSIState::LastAck,
            9 => TcpSIState::FinWait2,
            10 => TcpSIState::TimeWait,
            11 => TcpSIState::Reserved,
            _ => TcpSIState::Unknown,
        }
    }
}

const TSI_T_NTIMERS: usize = 4;

/// TCP Socket Info struct
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct TcpSockInfo {
    /// In Socket Info
    pub tcpsi_ini: InSockInfo,
    /// State
    pub tcpsi_state: c_int,
    /// Timer
    pub tcpsi_timer: [c_int; TSI_T_NTIMERS],
    /// MSS
    pub tcpsi_mss: c_int,
    /// Flags
    pub tcpsi_flags: u32,
    /// Reserved for future use
    pub rfu_1: u32,
    /// TP
    pub tcpsi_tp: u64,
}

/// Unix Domain Socket Info `UnSockInfo` struct
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct UnSockInfo {
    /// opaque handle of connected socket
    pub unsi_conn_so: u64,
    /// opaque handle of connected protocol control block
    pub unsi_conn_pcb: u64,
    /// bound address
    pub unsi_addr: UnSIAddr,
    /// address of socket connected to
    pub unsi_caddr: UnSIAddr,
}

/// Unix Socket Info Address `UnSIAddr` union
#[repr(C)]
#[derive(Copy, Clone)]
pub union UnSIAddr {
    /// Socket address
    pub ua_sun: sockaddr_un,
    /// Dummy for padding
    pub ua_dummy: [c_char; SOCK_MAXADDRLEN as usize],
}

impl Default for UnSIAddr {
    fn default() -> UnSIAddr {
        UnSIAddr {
            ua_dummy: [0; SOCK_MAXADDRLEN as usize],
        }
    }
}

/// `NDrvInfo` struct for `PF_NDRV Sockets`
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct NdrvInfo {
    /// Interface Family
    pub ndrvsi_if_family: u32,
    /// Interface Unit
    pub ndrvsi_if_unit: u32,
    /// Interface name
    pub ndrvsi_if_name: [c_char; IF_NAMESIZE],
}

/// Kernel Event Info struct
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct KernEventInfo {
    /// Vendor code filter
    pub kesi_vendor_code_filter: u32,
    /// Class filter
    pub kesi_class_filter: u32,
    /// Subclass filter
    pub kesi_subclass_filter: u32,
}

const MAX_KCTL_NAME: usize = 96;

/// Kernel Control Info struct
#[repr(C)]
#[derive(Copy, Clone)]
pub struct KernCtlInfo {
    /// ID
    pub kcsi_id: u32,
    /// Reg Unit
    pub kcsi_reg_unit: u32,
    /// Flags
    pub kcsi_flags: u32,
    /// Receive Buffer Size
    pub kcsi_recvbufsize: u32,
    /// Send Buffer Size
    pub kcsi_sendbufsize: u32,
    /// Unit
    pub kcsi_unit: u32,
    /// Name
    pub kcsi_name: [c_char; MAX_KCTL_NAME],
}

impl Default for KernCtlInfo {
    fn default() -> KernCtlInfo {
        KernCtlInfo {
            kcsi_id: 0,
            kcsi_reg_unit: 0,
            kcsi_flags: 0,
            kcsi_recvbufsize: 0,
            kcsi_sendbufsize: 0,
            kcsi_unit: 0,
            kcsi_name: [0; MAX_KCTL_NAME],
        }
    }
}