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}