diff src/libpam/handle.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 56b559b7ecea
children 4d7333337569
line wrap: on
line diff
--- a/src/libpam/handle.rs	Sun Jul 06 19:04:57 2025 -0400
+++ b/src/libpam/handle.rs	Sun Jul 06 19:10:26 2025 -0400
@@ -1,14 +1,15 @@
 use super::conversation::{OwnedConversation, PamConv};
+use crate::_doc::{guide, linklist, stdlinks};
 use crate::constants::{ErrorCode, Result};
 use crate::conv::Exchange;
 use crate::environ::EnvironMapMut;
 use crate::handle::PamShared;
+use crate::items::{Items, ItemsMut};
 use crate::libpam::environ::{LibPamEnviron, LibPamEnvironMut};
-use crate::libpam::memory;
+use crate::libpam::items::{LibPamItems, LibPamItemsMut};
+use crate::libpam::{items, memory};
 use crate::logging::{Level, Location};
-use crate::{
-    guide, linklist, stdlinks, Conversation, EnvironMap, Flags, PamHandleModule, Transaction,
-};
+use crate::{Conversation, EnvironMap, Flags, ModuleClient, Transaction};
 use libpam_sys_helpers::constants;
 use num_enum::{IntoPrimitive, TryFromPrimitive};
 use std::cell::Cell;
@@ -209,28 +210,8 @@
     delegate!(fn environ(&self) -> impl EnvironMap);
     delegate!(fn environ_mut(&mut self) -> impl EnvironMapMut);
     delegate!(fn username(&mut self, prompt: Option<&OsStr>) -> Result<OsString>);
-    delegate!(get = user_item, set = set_user_item);
-    delegate!(get = service, set = set_service);
-    delegate!(get = user_prompt, set = set_user_prompt);
-    delegate!(get = tty_name, set = set_tty_name);
-    delegate!(get = remote_user, set = set_remote_user);
-    delegate!(get = remote_host, set = set_remote_host);
-    delegate!(set = set_authtok_item);
-    delegate!(set = set_old_authtok_item);
-}
-
-/// 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 { self.get_cstr_item($item_type) }
-        }
-    };
-    (set = $setter:ident, item = $item_type:path) => {
-        fn $setter(&mut self, value: Option<&OsStr>) -> Result<()> {
-            unsafe { self.set_cstr_item($item_type, value) }
-        }
-    };
+    delegate!(fn items(&self) -> impl Items);
+    delegate!(fn items_mut(&mut self) -> impl ItemsMut);
 }
 
 /// An owned variation of a basic PAM handle.
@@ -377,20 +358,13 @@
         LibPamEnvironMut::new(self)
     }
 
-    cstr_item!(get = user_item, item = ItemType::User);
-    cstr_item!(set = set_user_item, item = ItemType::User);
-    cstr_item!(get = service, item = ItemType::Service);
-    cstr_item!(set = set_service, item = ItemType::Service);
-    cstr_item!(get = user_prompt, item = ItemType::UserPrompt);
-    cstr_item!(set = set_user_prompt, item = ItemType::UserPrompt);
-    cstr_item!(get = tty_name, item = ItemType::Tty);
-    cstr_item!(set = set_tty_name, item = ItemType::Tty);
-    cstr_item!(get = remote_user, item = ItemType::RemoteUser);
-    cstr_item!(set = set_remote_user, item = ItemType::RemoteUser);
-    cstr_item!(get = remote_host, item = ItemType::RemoteHost);
-    cstr_item!(set = set_remote_host, item = ItemType::RemoteHost);
-    cstr_item!(set = set_authtok_item, item = ItemType::AuthTok);
-    cstr_item!(set = set_old_authtok_item, item = ItemType::OldAuthTok);
+    fn items(&self) -> impl Items {
+        LibPamItems(self)
+    }
+
+    fn items_mut(&mut self) -> impl ItemsMut {
+        LibPamItemsMut(self)
+    }
 }
 
 impl Conversation for LibPamHandle {
@@ -406,7 +380,7 @@
     }
 }
 
-impl PamHandleModule for LibPamHandle {
+impl ModuleClient for LibPamHandle {
     fn authtok(&mut self, prompt: Option<&OsStr>) -> Result<OsString> {
         self.get_authtok(prompt, ItemType::AuthTok)
     }
@@ -415,8 +389,12 @@
         self.get_authtok(prompt, ItemType::OldAuthTok)
     }
 
-    cstr_item!(get = authtok_item, item = ItemType::AuthTok);
-    cstr_item!(get = old_authtok_item, item = ItemType::OldAuthTok);
+    fn authtok_item(&self) -> Result<Option<OsString>> {
+        unsafe { items::get_cstr_item(self, ItemType::AuthTok) }
+    }
+    fn old_authtok_item(&self) -> Result<Option<OsString>> {
+        unsafe { items::get_cstr_item(self, ItemType::OldAuthTok) }
+    }
 }
 
 /// Function called at the end of a PAM session that is called to clean up
@@ -454,36 +432,6 @@
         Err(ErrorCode::ConversationError)
     }
 
-    /// Gets a C string item.
-    ///
-    /// # Safety
-    ///
-    /// You better be requesting an item which is a C string.
-    unsafe fn get_cstr_item(&self, item_type: ItemType) -> Result<Option<OsString>> {
-        let mut output = ptr::null();
-        let ret =
-            unsafe { libpam_sys::pam_get_item(self.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.
-    unsafe fn set_cstr_item(&mut self, item_type: ItemType, data: Option<&OsStr>) -> Result<()> {
-        let data_str = memory::option_cstr_os(data);
-        let ret = unsafe {
-            libpam_sys::pam_set_item(
-                self.raw_mut(),
-                item_type as c_int,
-                memory::prompt_ptr(data_str.as_deref()).cast(),
-            )
-        };
-        ErrorCode::result_from(ret)
-    }
-
     /// Gets the `PAM_CONV` item from the handle.
     fn conversation_item(&self) -> Result<&PamConv> {
         let output: *const PamConv = ptr::null_mut();