Mercurial > crates > nonstick
diff src/libpam/handle.rs @ 130:80c07e5ab22f
Transfer over (almost) completely to using libpam-sys.
This reimplements everything in nonstick on top of the new -sys crate.
We don't yet use libpam-sys's helpers for binary message payloads. Soon.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Tue, 01 Jul 2025 06:11:43 -0400 |
parents | 39760dfc9b3b |
children | a632a8874131 |
line wrap: on
line diff
--- a/src/libpam/handle.rs Mon Jun 30 23:49:54 2025 -0400 +++ b/src/libpam/handle.rs Tue Jul 01 06:11:43 2025 -0400 @@ -1,11 +1,10 @@ use super::conversation::LibPamConversation; use crate::constants::{ErrorCode, Result}; -use crate::conv::Message; +use crate::conv::Exchange; use crate::environ::EnvironMapMut; use crate::handle::PamShared; use crate::libpam::environ::{LibPamEnviron, LibPamEnvironMut}; -pub use crate::libpam::pam_ffi::LibPamHandle; -use crate::libpam::{memory, pam_ffi}; +use crate::libpam::memory; use crate::logging::{Level, Location}; use crate::{ guide, linklist, stdlinks, Conversation, EnvironMap, Flags, PamHandleApplication, @@ -14,29 +13,30 @@ use num_enum::{IntoPrimitive, TryFromPrimitive}; use std::cell::Cell; use std::ffi::{c_char, c_int, CString}; -use std::ops::{Deref, DerefMut}; + use std::ptr; +use std::ptr::NonNull; +use libpam_sys::cfg_pam_impl; /// Owner for a PAM handle. -struct HandleWrap(*mut LibPamHandle); +pub struct LibPamHandle(pub NonNull<libpam_sys::pam_handle>); -impl Deref for HandleWrap { - type Target = LibPamHandle; - fn deref(&self) -> &Self::Target { - unsafe { &*self.0 } +impl AsRef<libpam_sys::pam_handle> for LibPamHandle { + fn as_ref(&self) -> &libpam_sys::pam_handle { + unsafe { self.0.as_ref() } } } -impl DerefMut for HandleWrap { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { &mut *self.0 } +impl AsMut<libpam_sys::pam_handle> for LibPamHandle { + fn as_mut(&mut self) -> &mut libpam_sys::pam_handle { + unsafe { self.0.as_mut() } } } /// An owned PAM handle. pub struct OwnedLibPamHandle<'a> { /// The handle itself. - handle: HandleWrap, + handle: LibPamHandle, /// The last return value from the handle. last_return: Cell<Result<()>>, /// If set, the Conversation that this PAM handle owns. @@ -102,20 +102,23 @@ let service_cstr = CString::new(service_name).map_err(|_| ErrorCode::ConversationError)?; let username_cstr = memory::prompt_ptr(memory::option_cstr(username.as_deref())?.as_ref()); - let mut handle: *mut LibPamHandle = ptr::null_mut(); + let mut handle: *mut libpam_sys::pam_handle = ptr::null_mut(); // SAFETY: We've set everything up properly to call `pam_start`. // The returned value will be a valid pointer provided the result is OK. let result = unsafe { - pam_ffi::pam_start( + libpam_sys::pam_start( service_cstr.as_ptr(), username_cstr, - conv.as_ref(), + (conv.as_ref() as *const LibPamConversation) + .cast_mut() + .cast(), &mut handle, ) }; ErrorCode::result_from(result)?; + let handle = NonNull::new(handle).ok_or(ErrorCode::BufferError)?; Ok(Self { - handle: HandleWrap(handle), + handle: LibPamHandle(handle), last_return: Cell::new(Ok(())), conversation: Some(conv), }) @@ -124,21 +127,22 @@ impl PamHandleApplication for OwnedLibPamHandle<'_> { fn authenticate(&mut self, flags: Flags) -> Result<()> { - let ret = unsafe { pam_ffi::pam_authenticate(self.handle.0, flags.bits() as c_int) }; + let ret = + unsafe { libpam_sys::pam_authenticate(self.handle.as_mut(), flags.bits() as c_int) }; let result = ErrorCode::result_from(ret); self.last_return.set(result); result } fn account_management(&mut self, flags: Flags) -> Result<()> { - let ret = unsafe { pam_ffi::pam_acct_mgmt(self.handle.0, flags.bits() as c_int) }; + let ret = unsafe { libpam_sys::pam_acct_mgmt(self.handle.as_mut(), flags.bits() as c_int) }; let result = ErrorCode::result_from(ret); self.last_return.set(result); result } fn change_authtok(&mut self, flags: Flags) -> Result<()> { - let ret = unsafe { pam_ffi::pam_chauthtok(self.handle.0, flags.bits() as c_int) }; + let ret = unsafe { libpam_sys::pam_chauthtok(self.handle.as_mut(), flags.bits() as c_int) }; let result = ErrorCode::result_from(ret); self.last_return.set(result); result @@ -167,8 +171,8 @@ #[doc = stdlinks!(3 pam_end)] fn drop(&mut self) { unsafe { - pam_ffi::pam_end( - self.handle.0, + libpam_sys::pam_end( + self.handle.as_mut(), ErrorCode::result_to_c(self.last_return.get()), ); } @@ -190,6 +194,7 @@ } impl PamShared for LibPamHandle { + #[cfg(any())] fn log(&self, level: Level, loc: Location<'_>, entry: &str) { let entry = match CString::new(entry).or_else(|_| CString::new(dbg!(entry))) { Ok(cstr) => cstr, @@ -200,7 +205,7 @@ _ = loc; // SAFETY: We're calling this function with a known value. unsafe { - pam_ffi::pam_syslog(self, level as c_int, "%s\0".as_ptr().cast(), entry.as_ptr()) + libpam_sys::pam_syslog(self, level as c_int, "%s\0".as_ptr().cast(), entry.as_ptr()) } } #[cfg(pam_impl = "openpam")] @@ -208,7 +213,7 @@ let func = CString::new(loc.function).unwrap_or(CString::default()); // SAFETY: We're calling this function with a known value. unsafe { - pam_ffi::_openpam_log( + libpam_sys::_openpam_log( level as c_int, func.as_ptr(), "%s\0".as_ptr().cast(), @@ -218,11 +223,17 @@ } } + fn log(&self, _level: Level, _loc: Location<'_>, _entry: &str) {} + fn username(&mut self, prompt: Option<&str>) -> Result<String> { let prompt = memory::option_cstr(prompt)?; let mut output: *const c_char = ptr::null(); let ret = unsafe { - pam_ffi::pam_get_user(self, &mut output, memory::prompt_ptr(prompt.as_ref())) + libpam_sys::pam_get_user( + self.as_mut(), + &mut output, + memory::prompt_ptr(prompt.as_ref()), + ) }; ErrorCode::result_from(ret)?; unsafe { memory::copy_pam_string(output) } @@ -255,7 +266,7 @@ } impl Conversation for LibPamHandle { - fn communicate(&self, messages: &[Message]) { + fn communicate(&self, messages: &[Exchange]) { match self.conversation_item() { Ok(conv) => conv.communicate(messages), Err(e) => { @@ -268,13 +279,14 @@ } impl PamHandleModule for LibPamHandle { + #[cfg_pam_impl(any("LinuxPam", "OpenPam"))] fn authtok(&mut self, prompt: Option<&str>) -> Result<String> { let prompt = memory::option_cstr(prompt)?; let mut output: *const c_char = ptr::null_mut(); // SAFETY: We're calling this with known-good values. let res = unsafe { - pam_ffi::pam_get_authtok( - self, + libpam_sys::pam_get_authtok( + self.as_mut(), ItemType::AuthTok.into(), &mut output, memory::prompt_ptr(prompt.as_ref()), @@ -287,6 +299,11 @@ .unwrap_or(Err(ErrorCode::ConversationError)) } + #[cfg_pam_impl(not(any("LinuxPam", "OpenPam")))] + fn authtok(&mut self, prompt: Option<&str>) -> Result<String> { + Err(ErrorCode::ConversationError) + } + cstr_item!(get = authtok_item, item = ItemType::AuthTok); cstr_item!(get = old_authtok_item, item = ItemType::OldAuthTok); } @@ -309,7 +326,8 @@ /// You better be requesting an item which is a C string. unsafe fn get_cstr_item(&self, item_type: ItemType) -> Result<Option<String>> { let mut output = ptr::null(); - let ret = unsafe { pam_ffi::pam_get_item(self, item_type as c_int, &mut output) }; + let ret = + unsafe { libpam_sys::pam_get_item(self.as_ref(), item_type as c_int, &mut output) }; ErrorCode::result_from(ret)?; memory::copy_pam_string(output.cast()) } @@ -322,8 +340,8 @@ unsafe fn set_cstr_item(&mut self, item_type: ItemType, data: Option<&str>) -> Result<()> { let data_str = memory::option_cstr(data)?; let ret = unsafe { - pam_ffi::pam_set_item( - self, + libpam_sys::pam_set_item( + self.as_mut(), item_type as c_int, memory::prompt_ptr(data_str.as_ref()).cast(), ) @@ -335,8 +353,8 @@ fn conversation_item(&self) -> Result<&mut LibPamConversation<'_>> { let output: *mut LibPamConversation = ptr::null_mut(); let result = unsafe { - pam_ffi::pam_get_item( - self, + libpam_sys::pam_get_item( + self.as_ref(), ItemType::Conversation.into(), &mut output.cast_const().cast(), )