Mercurial > crates > nonstick
diff src/libpam/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/libpam/items.rs Sun Jul 06 19:10:26 2025 -0400 @@ -0,0 +1,90 @@ +use crate::constants::ErrorCode; +use crate::constants::Result; +use crate::items::{Items, ItemsMut}; +use crate::libpam::handle::ItemType; +use crate::libpam::handle::LibPamHandle; +use crate::libpam::memory; +use std::ffi::{c_int, OsStr, OsString}; +use std::ptr; + +pub struct LibPamItems<'a>(pub &'a LibPamHandle); +pub struct LibPamItemsMut<'a>(pub &'a mut LibPamHandle); + +/// Macro to implement getting/setting a CStr-based item. +macro_rules! cstr_item { + (get = $getter:ident, item = $item_type:path) => { + fn $getter(&self) -> Result<Option<OsString>> { + unsafe { get_cstr_item(&self.0, $item_type) } + } + }; + (set = $setter:ident, item = $item_type:path) => { + fn $setter(&mut self, value: Option<&OsStr>) -> Result<()> { + unsafe { set_cstr_item(&mut self.0, $item_type, value) } + } + }; +} + +impl Items<'_> for LibPamItems<'_> { + cstr_item!(get = user, item = ItemType::User); + cstr_item!(get = service, item = ItemType::Service); + cstr_item!(get = user_prompt, item = ItemType::UserPrompt); + cstr_item!(get = tty_name, item = ItemType::Tty); + cstr_item!(get = remote_user, item = ItemType::RemoteUser); + cstr_item!(get = remote_host, item = ItemType::RemoteHost); +} + +impl Items<'_> for LibPamItemsMut<'_> { + cstr_item!(get = user, item = ItemType::User); + cstr_item!(get = service, item = ItemType::Service); + cstr_item!(get = user_prompt, item = ItemType::UserPrompt); + cstr_item!(get = tty_name, item = ItemType::Tty); + cstr_item!(get = remote_user, item = ItemType::RemoteUser); + cstr_item!(get = remote_host, item = ItemType::RemoteHost); +} + +impl ItemsMut<'_> for LibPamItemsMut<'_> { + cstr_item!(set = set_user, item = ItemType::User); + cstr_item!(set = set_service, item = ItemType::Service); + cstr_item!(set = set_user_prompt, item = ItemType::UserPrompt); + cstr_item!(set = set_tty_name, item = ItemType::Tty); + cstr_item!(set = set_remote_user, item = ItemType::RemoteUser); + cstr_item!(set = set_remote_host, item = ItemType::RemoteHost); + cstr_item!(set = set_authtok, item = ItemType::AuthTok); + cstr_item!(set = set_old_authtok, item = ItemType::OldAuthTok); +} + +/// Gets a C string item. +/// +/// # Safety +/// +/// You better be requesting an item which is a C string. +pub unsafe fn get_cstr_item( + hdl: &LibPamHandle, + item_type: ItemType, +) -> crate::Result<Option<OsString>> { + let mut output = ptr::null(); + let ret = unsafe { libpam_sys::pam_get_item(hdl.raw_ref(), item_type as c_int, &mut output) }; + ErrorCode::result_from(ret)?; + Ok(memory::copy_pam_string(output.cast())) +} + +/// Sets a C string item. +/// +/// # Safety +/// +/// You better be setting an item which is a C string. +pub unsafe fn set_cstr_item( + hdl: &mut LibPamHandle, + item_type: ItemType, + data: Option<&OsStr>, +) -> crate::Result<()> { + let data_str = memory::option_cstr_os(data); + let ret = unsafe { + libpam_sys::pam_set_item( + hdl.raw_mut(), + item_type as c_int, + memory::prompt_ptr(data_str.as_deref()).cast(), + ) + }; + ErrorCode::result_from(ret) +}