linux_keyutils/
metadata.rs

1use crate::ffi::{self, KeyCtlOperation, KeySerialId};
2use crate::utils::{CStr, String};
3use crate::{KeyError, KeyPermissions, KeyType};
4use alloc::string::ToString;
5use core::str::{self, FromStr};
6
7/// Information about the given node/entry.
8/// Returned by [Key::metadata](crate::Key::metadata)
9/// or [KeyRing::metadata](crate::KeyRing::metadata)
10#[derive(Debug, Clone)]
11pub struct Metadata {
12    ktype: KeyType,
13    uid: u32,
14    gid: u32,
15    perm: KeyPermissions,
16    description: String,
17}
18
19impl FromStr for Metadata {
20    type Err = KeyError;
21
22    /// The returned string contains the following information about
23    /// the key:
24    ///
25    /// `type;uid;gid;perm;description`
26    ///
27    /// And is then parsed into a valid [Metadata] struct.
28    ///
29    /// In the above, type and description are strings, uid and gid are
30    /// decimal strings, and perm is a hexadecimal permissions mask.
31    fn from_str(s: &str) -> Result<Self, Self::Err> {
32        // Begin parsing
33        let mut iter = s.split(';');
34
35        // Parse type into KeyType
36        let ktype: KeyType = iter
37            .next()
38            .and_then(|v| v.try_into().ok())
39            .ok_or(KeyError::InvalidDescription)?;
40
41        // Parse the UID
42        let uid = iter
43            .next()
44            .and_then(|v| v.parse().ok())
45            .ok_or(KeyError::InvalidDescription)?;
46
47        // Parse the GID
48        let gid = iter
49            .next()
50            .and_then(|v| v.parse().ok())
51            .ok_or(KeyError::InvalidDescription)?;
52
53        // Parse the permissions
54        let perms: u32 = iter
55            .next()
56            .and_then(|v| u32::from_str_radix(v, 16).ok())
57            .ok_or(KeyError::InvalidDescription)?;
58
59        // Copy the actual description
60        let description = iter.next().ok_or(KeyError::InvalidDescription)?.to_string();
61
62        // Create the description
63        Ok(Self {
64            ktype,
65            uid,
66            gid,
67            perm: KeyPermissions::from_u32(perms),
68            description,
69        })
70    }
71}
72
73impl Metadata {
74    /// Internal method to derive information from an
75    /// arbitrary node based on ID alone.
76    pub(crate) fn from_id(id: KeySerialId) -> Result<Self, KeyError> {
77        let mut result = alloc::vec![0u8; 512];
78
79        // Obtain the description from the kernel
80        let len = ffi::keyctl!(
81            KeyCtlOperation::Describe,
82            id.as_raw_id() as libc::c_ulong,
83            result.as_mut_ptr() as _,
84            result.len() as _
85        )? as usize;
86
87        // Construct the CStr first to remove the null terminator
88        let cs = CStr::from_bytes_with_nul(&result[..len]).or(Err(KeyError::InvalidDescription))?;
89
90        // Construct the string from the resulting data ensuring utf8 compat
91        let s = cs.to_str().or(Err(KeyError::InvalidDescription))?;
92        Self::from_str(s)
93    }
94
95    /// The type of this entry
96    pub fn get_type(&self) -> KeyType {
97        self.ktype
98    }
99
100    /// The owning UID of this entry
101    pub fn get_uid(&self) -> u32 {
102        self.uid
103    }
104
105    /// The owning GID of this entry
106    pub fn get_gid(&self) -> u32 {
107        self.gid
108    }
109
110    /// The current permissions of this entry
111    pub fn get_perms(&self) -> KeyPermissions {
112        self.perm
113    }
114
115    /// The description for this entry
116    pub fn get_description(&self) -> &str {
117        &self.description
118    }
119}