1use crate::{build_internal_error, expect, from_str, ProcResult};
5use bitflags::bitflags;
6#[cfg(feature = "serde1")]
7use serde::{Deserialize, Serialize};
8use std::{collections::HashMap, io::BufRead, time::Duration};
9
10bitflags! {
11 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
13 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
14 pub struct KeyFlags: u32 {
15 const INSTANTIATED = 0x01;
17 const REVOKED = 0x02;
19 const DEAD = 0x04;
23 const QUOTA = 0x08;
25 const UNDER_CONSTRUCTION = 0x10;
27 const NEGATIVE = 0x20;
29 const INVALID = 0x40;
31 }
32}
33
34bitflags! {
35 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
37 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
38 pub struct PermissionFlags: u32 {
39 const VIEW = 0x01;
43 const READ = 0x02;
45 const WRITE = 0x04;
50 const SEARCH = 0x08;
54 const LINK = 0x10;
58 const SETATTR = 0x20;
61 const ALL = Self::VIEW.bits() | Self::READ.bits() | Self::WRITE.bits() | Self::SEARCH.bits() | Self::LINK.bits() | Self::SETATTR.bits();
62 }
63}
64
65impl KeyFlags {
66 fn from_str(s: &str) -> KeyFlags {
67 let mut me = KeyFlags::empty();
68
69 let mut chars = s.chars();
70 match chars.next() {
71 Some(c) if c == 'I' => me.insert(KeyFlags::INSTANTIATED),
72 _ => {}
73 }
74 match chars.next() {
75 Some(c) if c == 'R' => me.insert(KeyFlags::REVOKED),
76 _ => {}
77 }
78 match chars.next() {
79 Some(c) if c == 'D' => me.insert(KeyFlags::DEAD),
80 _ => {}
81 }
82 match chars.next() {
83 Some(c) if c == 'Q' => me.insert(KeyFlags::QUOTA),
84 _ => {}
85 }
86 match chars.next() {
87 Some(c) if c == 'U' => me.insert(KeyFlags::UNDER_CONSTRUCTION),
88 _ => {}
89 }
90 match chars.next() {
91 Some(c) if c == 'N' => me.insert(KeyFlags::NEGATIVE),
92 _ => {}
93 }
94 match chars.next() {
95 Some(c) if c == 'i' => me.insert(KeyFlags::INVALID),
96 _ => {}
97 }
98
99 me
100 }
101}
102
103#[derive(Debug, Clone)]
104#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
105pub struct Permissions {
106 pub possessor: PermissionFlags,
107 pub user: PermissionFlags,
108 pub group: PermissionFlags,
109 pub other: PermissionFlags,
110}
111impl Permissions {
112 fn from_str(s: &str) -> ProcResult<Permissions> {
113 let possessor = PermissionFlags::from_bits(from_str!(u32, &s[0..2], 16))
114 .ok_or_else(|| build_internal_error!(format!("Unable to parse {:?} as PermissionFlags", s)))?;
115
116 let user = PermissionFlags::from_bits(from_str!(u32, &s[2..4], 16))
117 .ok_or_else(|| build_internal_error!(format!("Unable to parse {:?} as PermissionFlags", s)))?;
118
119 let group = PermissionFlags::from_bits(from_str!(u32, &s[4..6], 16))
120 .ok_or_else(|| build_internal_error!(format!("Unable to parse {:?} as PermissionFlags", s)))?;
121
122 let other = PermissionFlags::from_bits(from_str!(u32, &s[6..8], 16))
123 .ok_or_else(|| build_internal_error!(format!("Unable to parse {:?} as PermissionFlags", s)))?;
124
125 Ok(Permissions {
126 possessor,
127 user,
128 group,
129 other,
130 })
131 }
132}
133
134#[derive(Debug, Clone, Eq, PartialEq)]
135#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
136pub enum KeyTimeout {
137 Permanent,
138 Expired,
139 Timeout(Duration),
140}
141
142impl KeyTimeout {
143 fn from_str(s: &str) -> ProcResult<KeyTimeout> {
144 if s == "perm" {
145 Ok(KeyTimeout::Permanent)
146 } else if s == "expd" {
147 Ok(KeyTimeout::Expired)
148 } else {
149 let (val, unit) = s.split_at(s.len() - 1);
150 let val = from_str!(u64, val);
151 match unit {
152 "s" => Ok(KeyTimeout::Timeout(Duration::from_secs(val))),
153 "m" => Ok(KeyTimeout::Timeout(Duration::from_secs(val * 60))),
154 "h" => Ok(KeyTimeout::Timeout(Duration::from_secs(val * 60 * 60))),
155 "d" => Ok(KeyTimeout::Timeout(Duration::from_secs(val * 60 * 60 * 24))),
156 "w" => Ok(KeyTimeout::Timeout(Duration::from_secs(val * 60 * 60 * 24 * 7))),
157 _ => Err(build_internal_error!(format!("Unable to parse keytimeout of {:?}", s))),
158 }
159 }
160 }
161}
162
163#[derive(Debug, Clone)]
164#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
165pub enum KeyType {
166 User,
176
177 Keyring,
185
186 Logon,
196
197 BigKey,
209
210 Other(String),
212}
213
214impl KeyType {
215 fn from_str(s: &str) -> KeyType {
216 match s {
217 "keyring" => KeyType::Keyring,
218 "user" => KeyType::User,
219 "logon" => KeyType::Logon,
220 "big_key" => KeyType::BigKey,
221 other => KeyType::Other(other.to_string()),
222 }
223 }
224}
225
226#[derive(Debug, Clone)]
228#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
229pub struct Key {
230 pub id: u64,
232
233 pub flags: KeyFlags,
235
236 pub usage: u32,
240
241 pub timeout: KeyTimeout,
243
244 pub permissions: Permissions,
246
247 pub uid: u32,
249
250 pub gid: Option<u32>,
255
256 pub key_type: KeyType,
258
259 pub description: String,
261}
262
263impl Key {
264 fn from_line(s: &str) -> ProcResult<Key> {
265 let mut s = s.split_whitespace();
266
267 let id = from_str!(u64, expect!(s.next()), 16);
268 let s_flags = expect!(s.next());
269 let usage = from_str!(u32, expect!(s.next()));
270 let s_timeout = expect!(s.next());
271 let s_perms = expect!(s.next());
272 let uid = from_str!(u32, expect!(s.next()));
273 let s_gid = expect!(s.next());
274 let s_type = expect!(s.next());
275 let desc: Vec<_> = s.collect();
276
277 Ok(Key {
278 id,
279 flags: KeyFlags::from_str(s_flags),
280 usage,
281 timeout: KeyTimeout::from_str(s_timeout)?,
282 permissions: Permissions::from_str(s_perms)?,
283 uid,
284 gid: if s_gid == "-1" {
285 None
286 } else {
287 Some(from_str!(u32, s_gid))
288 },
289 key_type: KeyType::from_str(s_type),
290 description: desc.join(" "),
291 })
292 }
293}
294
295#[derive(Debug, Clone)]
297#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
298pub struct Keys(pub Vec<Key>);
299
300impl crate::FromBufRead for Keys {
301 fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
302 let mut v = Vec::new();
303
304 for line in r.lines() {
305 let line = line?;
306 v.push(Key::from_line(&line)?);
307 }
308 Ok(Keys(v))
309 }
310}
311
312#[derive(Debug, Clone)]
314#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
315pub struct KeyUser {
316 pub uid: u32,
318 pub usage: u32,
320 pub nkeys: u32,
322 pub nikeys: u32,
324 pub qnkeys: u32,
326 pub maxkeys: u32,
328 pub qnbytes: u32,
330 pub maxbytes: u32,
332}
333
334impl KeyUser {
335 fn from_str(s: &str) -> ProcResult<KeyUser> {
336 let mut s = s.split_whitespace();
337 let uid = expect!(s.next());
338 let usage = from_str!(u32, expect!(s.next()));
339 let keys = expect!(s.next());
340 let qkeys = expect!(s.next());
341 let qbytes = expect!(s.next());
342
343 let (nkeys, nikeys) = {
344 let mut s = keys.split('/');
345 (from_str!(u32, expect!(s.next())), from_str!(u32, expect!(s.next())))
346 };
347 let (qnkeys, maxkeys) = {
348 let mut s = qkeys.split('/');
349 (from_str!(u32, expect!(s.next())), from_str!(u32, expect!(s.next())))
350 };
351 let (qnbytes, maxbytes) = {
352 let mut s = qbytes.split('/');
353 (from_str!(u32, expect!(s.next())), from_str!(u32, expect!(s.next())))
354 };
355
356 Ok(KeyUser {
357 uid: from_str!(u32, &uid[0..uid.len() - 1]),
358 usage,
359 nkeys,
360 nikeys,
361 qnkeys,
362 maxkeys,
363 qnbytes,
364 maxbytes,
365 })
366 }
367}
368
369#[derive(Debug, Clone)]
371#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
372pub struct KeyUsers(pub HashMap<u32, KeyUser>);
373
374impl crate::FromBufRead for KeyUsers {
375 fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
376 let mut map = HashMap::new();
377
378 for line in r.lines() {
379 let line = line?;
380 let user = KeyUser::from_str(&line)?;
381 map.insert(user.uid, user);
382 }
383 Ok(KeyUsers(map))
384 }
385}
386
387#[cfg(test)]
388mod tests {
389 use super::*;
390
391 #[test]
392 fn key_flags() {
393 assert_eq!(KeyFlags::from_str("I------"), KeyFlags::INSTANTIATED);
394 assert_eq!(KeyFlags::from_str("IR"), KeyFlags::INSTANTIATED | KeyFlags::REVOKED);
395 assert_eq!(KeyFlags::from_str("IRDQUNi"), KeyFlags::all());
396 }
397
398 #[test]
399 fn timeout() {
400 assert_eq!(KeyTimeout::from_str("perm").unwrap(), KeyTimeout::Permanent);
401 assert_eq!(KeyTimeout::from_str("expd").unwrap(), KeyTimeout::Expired);
402 assert_eq!(
403 KeyTimeout::from_str("2w").unwrap(),
404 KeyTimeout::Timeout(Duration::from_secs(1209600))
405 );
406 assert_eq!(
407 KeyTimeout::from_str("14d").unwrap(),
408 KeyTimeout::Timeout(Duration::from_secs(1209600))
409 );
410 assert_eq!(
411 KeyTimeout::from_str("336h").unwrap(),
412 KeyTimeout::Timeout(Duration::from_secs(1209600))
413 );
414 assert_eq!(
415 KeyTimeout::from_str("20160m").unwrap(),
416 KeyTimeout::Timeout(Duration::from_secs(1209600))
417 );
418 assert_eq!(
419 KeyTimeout::from_str("1209600s").unwrap(),
420 KeyTimeout::Timeout(Duration::from_secs(1209600))
421 );
422 }
423}