//! Functions related to the in-kernel key management and retention facility //! //! For more details on this facility, see the `keyrings(7)` man page. usecrate::{build_internal_error, expect, from_str, ProcResult}; use bitflags::bitflags; #[cfg(feature = "serde1")] use serde::{Deserialize, Serialize}; use std::{collections::HashMap, io::BufRead, time::Duration};
bitflags! { /// Various key flags #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] pubstruct KeyFlags: u32 { /// The key has been instantiated const INSTANTIATED = 0x01; /// THe key has been revoked const REVOKED = 0x02; /// The key is dead /// /// I.e. the key type has been unregistered. A key may be briefly in this state during garbage collection. const DEAD = 0x04; /// The key contributes to the user's quota const QUOTA = 0x08; /// The key is under construction via a callback to user space const UNDER_CONSTRUCTION = 0x10; /// The key is negatively instantiated const NEGATIVE = 0x20; /// The key has been invalidated const INVALID = 0x40;
}
}
bitflags! { /// Bitflags that represent the permissions for a key #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] pubstruct PermissionFlags: u32 { /// The attributes of the key may be read /// /// This includes the type, description, and access rights (excluding the security label) const VIEW = 0x01; /// 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. const READ = 0x02; /// The payload of the key may be updated and the key may be revoked. /// /// For a keyring, links may be added to or removed from the keyring, and the keyring /// may be cleared completely (all links are removed). const WRITE = 0x04; /// The key may be found by a search. /// /// For keyrings: keys and keyrings that are linked to by the keyring may be searched. const SEARCH = 0x08; /// Links may be created from keyrings to the key. /// /// The initial link to a key that is established when the key is created doesn't require this permission. const LINK = 0x10; /// The ownership details and security label of the key may be changed, the key's expiration /// time may be set, and the key may be revoked. const SETATTR = 0x20; const ALL = Self::VIEW.bits() | Self::READ.bits() | Self::WRITE.bits() | Self::SEARCH.bits() | Self::LINK.bits() | Self::SETATTR.bits();
}
}
letmut chars = s.chars(); match chars.next() {
Some(c) if c == 'I' => me.insert(KeyFlags::INSTANTIATED),
_ => {}
} match chars.next() {
Some(c) if c == 'R' => me.insert(KeyFlags::REVOKED),
_ => {}
} match chars.next() {
Some(c) if c == 'D' => me.insert(KeyFlags::DEAD),
_ => {}
} match chars.next() {
Some(c) if c == 'Q' => me.insert(KeyFlags::QUOTA),
_ => {}
} match chars.next() {
Some(c) if c == 'U' => me.insert(KeyFlags::UNDER_CONSTRUCTION),
_ => {}
} match chars.next() {
Some(c) if c == 'N' => me.insert(KeyFlags::NEGATIVE),
_ => {}
} match chars.next() {
Some(c) if c == 'i' => me.insert(KeyFlags::INVALID),
_ => {}
}
let user = PermissionFlags::from_bits(from_str!(u32, &s[2..4], 16))
.ok_or_else(|| build_internal_error!(format!("Unable to parse {:?} as PermissionFlags", s)))?;
let group = PermissionFlags::from_bits(from_str!(u32, &s[4..6], 16))
.ok_or_else(|| build_internal_error!(format!("Unable to parse {:?} as PermissionFlags", s)))?;
let other = PermissionFlags::from_bits(from_str!(u32, &s[6..8], 16))
.ok_or_else(|| build_internal_error!(format!("Unable to parse {:?} as PermissionFlags", s)))?;
impl KeyTimeout { fn from_str(s: &str) -> ProcResult<KeyTimeout> { if s == "perm" {
Ok(KeyTimeout::Permanent)
} elseif s == "expd" {
Ok(KeyTimeout::Expired)
} else { let (val, unit) = s.split_at(s.len() - 1); let val = from_str!(u64, val); match unit { "s" => Ok(KeyTimeout::Timeout(Duration::from_secs(val))), "m" => Ok(KeyTimeout::Timeout(Duration::from_secs(val * 60))), "h" => Ok(KeyTimeout::Timeout(Duration::from_secs(val * 60 * 60))), "d" => Ok(KeyTimeout::Timeout(Duration::from_secs(val * 60 * 60 * 24))), "w" => Ok(KeyTimeout::Timeout(Duration::from_secs(val * 60 * 60 * 24 * 7))),
_ => Err(build_internal_error!(format!("Unable to parse keytimeout of {:?}", s))),
}
}
}
}
#[derive(Debug, Clone)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubenum KeyType { /// This is a general-purpose key type. /// /// The key is kept entirely within kernel memory. The payload may be read and updated by /// user-space applications. The payload for keys of this type is a blob of arbitrary /// data of up to 32,767 bytes.
/// The description may be any valid string, though it is preferred that it start /// with a colon-delimited prefix representing the service to which the key is of /// interest (for instance "afs:mykey").
User,
/// Keyrings are special keys which store a set of links to other keys (including /// other keyrings), analogous to a directory holding links to files. The main /// purpose of a keyring is to prevent other keys from being garbage collected /// because nothing refers to them. /// /// Keyrings with descriptions (names) that begin with a period ('.') are re‐ /// served to the implementation.
Keyring,
/// This key type is essentially the same as "user", but it does not provide /// reading (i.e., the keyctl(2) KEYCTL_READ operation), meaning that the key /// payload is never visible from user space. This is suitable for storing user‐ /// name-password pairs that should not be readable from user space. /// /// The description of a "logon" key must start with a non-empty colon-delimited /// prefix whose purpose is to identify the service to which the key belongs. /// (Note that this differs from keys of the "user" type, where the inclusion of /// a prefix is recommended but is not enforced.)
Logon,
/// This key type is similar to the "user" key type, but it may hold a payload of /// up to 1 MiB in size. This key type is useful for purposes such as holding /// Kerberos ticket caches. /// /// The payload data may be stored in a tmpfs filesystem, rather than in kernel /// memory, if the data size exceeds the overhead of storing the data in the /// filesystem. (Storing the data in a filesystem requires filesystem structures /// to be allocated in the kernel. The size of these structures determines the /// size threshold above which the tmpfs storage method is used.) Since Linux /// 4.8, the payload data is encrypted when stored in tmpfs, thereby preventing /// it from being written unencrypted into swap space.
BigKey,
/// Other specialized, but rare keys types
Other(String),
}
impl KeyType { fn from_str(s: &str) -> KeyType { match s { "keyring" => KeyType::Keyring, "user" => KeyType::User, "logon" => KeyType::Logon, "big_key" => KeyType::BigKey,
other => KeyType::Other(other.to_string()),
}
}
}
/// A key #[derive(Debug, Clone)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct Key { /// The ID (serial number) of the key pub id: u64,
/// A set of flags describing the state of the key pub flags: KeyFlags,
/// Count of the number of kernel credential structures that are /// pinning the key (approximately: the number of threads and open file /// references that refer to this key). pub usage: u32,
/// Key timeout pub timeout: KeyTimeout,
/// Key permissions pub permissions: Permissions,
/// The user ID of the key owner pub uid: u32,
/// The group ID of the key. /// /// The value of `None` here means that the key has no group ID; this can occur in certain circumstances for /// keys created by the kernel. pub gid: Option<u32>,
/// The type of key pub key_type: KeyType,
/// The key description pub description: String,
}
let id = from_str!(u64, expect!(s.next()), 16); let s_flags = expect!(s.next()); let usage = from_str!(u32, expect!(s.next())); let s_timeout = expect!(s.next()); let s_perms = expect!(s.next()); let uid = from_str!(u32, expect!(s.next())); let s_gid = expect!(s.next()); let s_type = expect!(s.next()); let desc: Vec<_> = s.collect();
/// A set of keys. #[derive(Debug, Clone)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct Keys(pub Vec<Key>);
implcrate::FromBufRead for Keys { fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> { letmut v = Vec::new();
for line in r.lines() { let line = line?;
v.push(Key::from_line(&line)?);
}
Ok(Keys(v))
}
}
/// Information about a user with at least one key #[derive(Debug, Clone)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct KeyUser { /// The user that owns the key pub uid: u32, /// The kernel-internal usage count for the kernel structure used to record key users pub usage: u32, /// The total number of keys owned by the user pub nkeys: u32, /// THe number of keys that have been instantiated pub nikeys: u32, /// The number of keys owned by the user pub qnkeys: u32, /// The maximum number of keys that the user may own pub maxkeys: u32, /// The number of bytes consumed in playloads of the keys owned by this user pub qnbytes: u32, /// The upper limit on the number of bytes in key payloads for this user pub maxbytes: u32,
}
impl KeyUser { fn from_str(s: &str) -> ProcResult<KeyUser> { letmut s = s.split_whitespace(); let uid = expect!(s.next()); let usage = from_str!(u32, expect!(s.next())); let keys = expect!(s.next()); let qkeys = expect!(s.next()); let qbytes = expect!(s.next());
let (nkeys, nikeys) = { letmut s = keys.split('/');
(from_str!(u32, expect!(s.next())), from_str!(u32, expect!(s.next())))
}; let (qnkeys, maxkeys) = { letmut s = qkeys.split('/');
(from_str!(u32, expect!(s.next())), from_str!(u32, expect!(s.next())))
}; let (qnbytes, maxbytes) = { letmut s = qbytes.split('/');
(from_str!(u32, expect!(s.next())), from_str!(u32, expect!(s.next())))
};
/// Information about a set of users with at least one key. #[derive(Debug, Clone)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] pubstruct KeyUsers(pub HashMap<u32, KeyUser>);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.