procfs_core/
keyring.rs

1//! Functions related to the in-kernel key management and retention facility
2//!
3//! For more details on this facility, see the `keyrings(7)` man page.
4use 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    /// Various key flags
12    #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
13    #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
14    pub struct KeyFlags: u32 {
15            /// The key has been instantiated
16            const INSTANTIATED = 0x01;
17            /// THe key has been revoked
18            const REVOKED = 0x02;
19            /// The key is dead
20            ///
21            /// I.e. the key type has been unregistered.  A key may be briefly in this state during garbage collection.
22            const DEAD = 0x04;
23            /// The key contributes to the user's quota
24            const QUOTA = 0x08;
25            /// The key is under construction via a callback to user space
26            const UNDER_CONSTRUCTION = 0x10;
27            /// The key is negatively instantiated
28            const NEGATIVE = 0x20;
29            /// The key has been invalidated
30            const INVALID = 0x40;
31    }
32}
33
34bitflags! {
35    /// Bitflags that represent the permissions for a key
36    #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
37    #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
38    pub struct PermissionFlags: u32 {
39        /// The attributes of the key may be read
40        ///
41        /// This includes the type, description, and access rights (excluding the security label)
42        const VIEW = 0x01;
43        /// For a key: the payload of the key may be read.  For a keyring: the list of serial numbers (keys) to which the keyring has links may be read.
44        const READ = 0x02;
45        /// The payload of the key may be updated and the key may be revoked.
46        ///
47        /// For a keyring, links may be added to or removed from the keyring, and the keyring
48        /// may be cleared completely (all links are removed).
49        const WRITE = 0x04;
50        /// The key may be found by a search.
51        ///
52        /// For keyrings: keys and keyrings that are linked to by the keyring may be searched.
53        const SEARCH = 0x08;
54        /// Links may be created from keyrings to the key.
55        ///
56        /// The initial link to a key that is established when the key is created doesn't require this permission.
57        const LINK = 0x10;
58        /// The ownership details and security label of the key may be changed, the key's expiration
59        /// time may be set, and the key may be revoked.
60        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    /// This is a general-purpose key type.
167    ///
168    /// The key is kept entirely within kernel memory.  The payload may be read and updated by
169    ///  user-space applications. The payload for keys of this type is a blob of arbitrary
170    /// data of up to 32,767 bytes.
171
172    /// The description may be any valid string, though it is preferred that it start
173    /// with a colon-delimited prefix representing the service to which the key is of
174    /// interest (for instance "afs:mykey").
175    User,
176
177    /// Keyrings are special keys which store a set of links to other keys (including
178    /// other keyrings), analogous to a directory holding links to files.   The  main
179    /// purpose  of  a  keyring is to prevent other keys from being garbage collected
180    /// because nothing refers to them.
181    ///
182    /// Keyrings with descriptions (names) that begin with a  period  ('.')  are  re‐
183    /// served to the implementation.
184    Keyring,
185
186    /// This  key  type  is  essentially  the same as "user", but it does not provide
187    /// reading (i.e., the keyctl(2) KEYCTL_READ operation),  meaning  that  the  key
188    /// payload is never visible from user space.  This is suitable for storing user‐
189    /// name-password pairs that should not be readable from user space.
190    ///
191    /// The description of a "logon" key must start with a  non-empty colon-delimited
192    /// prefix  whose  purpose  is  to identify the service to which the key belongs.
193    /// (Note that this differs from keys of the "user" type, where the inclusion  of
194    /// a prefix is recommended but is not enforced.)
195    Logon,
196
197    /// This key type is similar to the "user" key type, but it may hold a payload of
198    /// up to 1 MiB in size.  This key type is useful for purposes  such  as  holding
199    /// Kerberos ticket caches.
200    ///
201    /// The  payload  data may be stored in a tmpfs filesystem, rather than in kernel
202    /// memory, if the data size exceeds the overhead of  storing  the  data  in  the
203    /// filesystem.  (Storing the data in a filesystem requires filesystem structures
204    /// to be allocated in the kernel.  The size of these structures  determines  the
205    /// size  threshold  above  which the tmpfs storage method is used.)  Since Linux
206    /// 4.8, the payload data is encrypted when stored in tmpfs,  thereby  preventing
207    /// it from being written unencrypted into swap space.
208    BigKey,
209
210    /// Other specialized, but rare keys types
211    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/// A key
227#[derive(Debug, Clone)]
228#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
229pub struct Key {
230    /// The ID (serial number) of the key
231    pub id: u64,
232
233    /// A set of flags describing the state of the key
234    pub flags: KeyFlags,
235
236    /// Count of the number of kernel credential structures that are
237    /// pinning  the  key  (approximately: the number of threads and open file
238    /// references that refer to this key).
239    pub usage: u32,
240
241    /// Key timeout
242    pub timeout: KeyTimeout,
243
244    /// Key permissions
245    pub permissions: Permissions,
246
247    /// The user ID of the key owner
248    pub uid: u32,
249
250    /// The group ID of the key.
251    ///
252    /// The value of `None` here means that the key has no group ID; this can occur in certain circumstances for
253    /// keys created by the kernel.
254    pub gid: Option<u32>,
255
256    /// The type of key
257    pub key_type: KeyType,
258
259    /// The key description
260    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/// A set of keys.
296#[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/// Information about a user with at least one key
313#[derive(Debug, Clone)]
314#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
315pub struct KeyUser {
316    /// The user that owns the key
317    pub uid: u32,
318    /// The kernel-internal usage count for the kernel structure used to record key users
319    pub usage: u32,
320    /// The total number of keys owned by the user
321    pub nkeys: u32,
322    /// THe number of keys that have been instantiated
323    pub nikeys: u32,
324    /// The number of keys owned by the user
325    pub qnkeys: u32,
326    /// The maximum number of keys that the user may own
327    pub maxkeys: u32,
328    /// The number of bytes consumed in playloads of the keys owned by this user
329    pub qnbytes: u32,
330    /// The upper limit on the number of bytes in key payloads for this user
331    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/// Information about a set of users with at least one key.
370#[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}