Skip to main content

signstar_config/
utils.rs

1//! Utilities for signstar-config.
2use nix::unistd::{User, geteuid};
3
4use crate::config::SystemUserId;
5
6/// An error that may occur when using signstar-config utils.
7#[derive(Debug, thiserror::Error)]
8pub enum Error {
9    /// There is no data about a system user.
10    #[error("Data for system user {user} is missing")]
11    SystemUserData {
12        /// The user identifier for which data is missing.
13        user: NameOrUid,
14    },
15
16    /// Unable to lookup system user data (by name or from process EUID).
17    #[error(
18        "Unable to lookup data for system user {}:\n{source}",
19        match user {
20            NameOrUid::Name(name) => format!("user {name}"),
21            NameOrUid::Uid(uid) => format!("uid {uid}"),
22        }
23    )]
24    SystemUserLookup {
25        /// The user identifier for which data could not be looked up.
26        user: NameOrUid,
27        /// The source error.
28        source: nix::errno::Errno,
29    },
30
31    /// The calling user does not match the targeted system user.
32    #[error(
33        "The targeted system user {target_user} is not the currently calling system user {current_user}."
34    )]
35    SystemUserMismatch {
36        /// The system user that is the target of the operation.
37        target_user: String,
38        /// The currently calling system user.
39        current_user: String,
40    },
41
42    /// The current user is an unprivileged user, but should be root.
43    #[error("The command requires running as root, but running as \"{user}\"")]
44    SystemUserNotRoot {
45        /// The system user that is used instead of `root`.
46        user: String,
47    },
48}
49
50/// A name or uid of a system user on a host
51#[derive(Debug, strum::Display)]
52pub enum NameOrUid {
53    /// The name of the system user.
54    Name(SystemUserId),
55    /// The ID of the system user.
56    Uid(nix::unistd::Uid),
57}
58
59/// Fails if not running as root.
60///
61/// Evaluates the effective user ID.
62///
63/// # Errors
64///
65/// Returns an error if the effective user ID is not that of root.
66pub(crate) fn fail_if_not_root(user: &User) -> Result<(), Error> {
67    if !user.uid.is_root() {
68        return Err(Error::SystemUserNotRoot {
69            user: user.name.clone(),
70        });
71    }
72    Ok(())
73}
74
75/// Returns the [`User`] associated with the current process.
76///
77/// Retrieves user data of the system based on the effective user ID of the current process.
78///
79/// # Errors
80///
81/// Returns an error if
82/// - no user data can be derived from the current process
83/// - no user data can be found on the system, associated with the ID of the user of the current
84///   process.
85pub(crate) fn get_current_system_user() -> Result<User, Error> {
86    let euid = geteuid();
87    let Some(user) = User::from_uid(euid).map_err(|source| Error::SystemUserLookup {
88        user: NameOrUid::Uid(euid),
89        source,
90    })?
91    else {
92        return Err(Error::SystemUserData {
93            user: NameOrUid::Uid(euid),
94        });
95    };
96    Ok(user)
97}