Mercurial > crates > nonstick
diff src/items.rs @ 146:1bc52025156b
Split PAM items into their own separate struct.
To trim down the number of methods on `PamShared`, this puts all the
Items into their own struct(s). This also makes the split between
authtok/authtok_item easier to understand.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sun, 06 Jul 2025 19:10:26 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/items.rs Sun Jul 06 19:10:26 2025 -0400 @@ -0,0 +1,169 @@ +use crate::_doc::{guide, linklist, stdlinks}; +use crate::constants::Result; +#[cfg(doc)] +use crate::handle::{ModuleClient, PamShared}; +use std::ffi::{OsStr, OsString}; + +macro_rules! getter { + ($(#[$md:meta])* $getter:ident($item:literal $(, see = $see:path)?)) => { + $(#[$md])* + #[doc = ""] + #[doc = concat!("Gets the `", $item, "` of the PAM handle.")] + $( + #[doc = concat!("See [`", stringify!($see), "`].")] + )? + fn $getter(&self) -> Result<Option<OsString>>; + }; +} + +pub(crate) use getter; +macro_rules! setter { + ($(#[$md:meta])* $setter:ident($item:literal $(, see = $see:path)?)) => { + $(#[$md])* + #[doc = ""] + #[doc = concat!("Sets the `", $item, "` from the PAM handle.")] + $( + #[doc = concat!("See [`", stringify!($see), "`].")] + )? + /// + /// Sets the item's value. PAM copies the string's contents. + /// + /// # Panics + /// + /// If the string contains a nul byte, this will panic. + /// + fn $setter(&mut self, value: Option<&OsStr>) -> Result<()>; + }; +} + +/// Provides access to Items, pieces of data shared by the PAM application, +/// modules, and the framework itself. +/// +/// # References +/// +#[doc = linklist!(pam_get_item: mwg, adg, _std)] +/// +#[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_get_item")] +#[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_item")] +#[doc = stdlinks!(3 pam_get_item)] +pub trait Items<'a> { + getter!( + /// The identity of the user for whom service is being requested. + /// + /// Unlike [`username`](PamShared::username), this will simply get + /// the current state of the user item, and not request the username. + /// While PAM usually sets this automatically in the `username` call, + /// it may be changed by a module during the PAM transaction. + /// Applications should check it after each step of the PAM process. + user("PAM_USER", see = PamShared::username) + ); + + getter!( + /// If set, the identity of the remote user logging in. + /// + /// This is only as trustworthy as the application calling PAM. + remote_user("PAM_RUSER", see = Self::remote_host) + ); + + getter!( + /// If set, the remote location where the user is coming from. + /// + /// This is only as trustworthy as the application calling PAM. + /// This can be combined with [`Self::remote_user`] to identify + /// the account the user is attempting to log in from, + /// with `remote_user@remote_host`. + /// + /// If unset, "it is unclear where the authentication request + /// is originating from." + remote_host("PAM_RHOST", see = Self::remote_user) + ); + + getter!( + /// The service name, which identifies the PAM stack which is used + /// to perform authentication. + service("PAM_SERVICE") + ); + + getter!( + /// The string used to prompt for a user's name. + /// By default, this is a localized version of `login: `. + user_prompt("PAM_USER_PROMPT") + ); + + getter!( + /// The device path of the TTY being used to log in. + /// + /// This is the terminal the user is logging in on, + /// specified as the full device path (e.g. `/dev/tty0`). + /// Very old applications may use this instead of `PAM_XDISPLAY`. + tty_name("PAM_TTY") + ); +} + +/// Provides write access to PAM Items, data shared by the PAM application, +/// the framework, and modules. +/// +/// # References +/// +#[doc = linklist!(pam_set_item: mwg, adg, _std)] +/// +#[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_set_item")] +#[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_set_item")] +#[doc = stdlinks!(3 pam_set_item)] +pub trait ItemsMut<'a>: Items<'a> { + setter!( + /// Sets the identity of the logging-in user. + /// + /// Usually this will be set during the course of + /// a [`username`](PamShared::username) call, but you may set it manually + /// or change it during the PAM process. + set_user("PAM_USER", see = Items::user) + ); + + setter!( + /// Sets the service name. It's probably a bad idea to change this. + set_service("PAM_SERVICE", see = Items::service) + ); + + setter!( + /// Sets the string used to prompt for a user's name. + set_user_prompt("PAM_USER_PROMPT", see = Items::user_prompt) + ); + + setter!( + /// Sets the path to the terminal where the user is logging on. + set_tty_name("PAM_TTY", see = Items::tty_name) + ); + + setter!( + /// Sets the identity of the remote user logging in. + /// + /// This may be set by the application before making calls + /// into a PAM transaction. + set_remote_user("PAM_RUSER", see = Items::remote_user) + ); + + setter!( + /// Sets the location where the user is coming from. + /// + /// This may be set by the application before making calls + /// into a PAM transaction. + set_remote_host("PAM_RHOST", see = Items::remote_host) + ); + + setter!( + /// Gets the user's authentication token (e.g., password). + /// + /// This is usually set automatically when + /// [`authtok`](ModuleClient::authtok) is called, + /// but can be manually set. + set_authtok("PAM_AUTHTOK", see = ModuleClient::authtok_item) + ); + setter!( + /// Sets the user's "old authentication token" when changing passwords. + /// + /// This is usually set automatically by PAM when + /// [`old_authtok`](ModuleClient::old_authtok) is called. + set_old_authtok("PAM_OLDAUTHTOK", see = ModuleClient::old_authtok_item) + ); +}