Mercurial > crates > nonstick
diff src/libpam/handle.rs @ 92:5ddbcada30f2
Add the ability to log against a PAM handle.
PAM impls provide a way to log to syslog. This exposes it via nonstick.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sun, 22 Jun 2025 19:29:32 -0400 |
parents | f6186e41399b |
children | 51c9d7e8261a |
line wrap: on
line diff
--- a/src/libpam/handle.rs Wed Jun 18 16:30:41 2025 -0400 +++ b/src/libpam/handle.rs Sun Jun 22 19:29:32 2025 -0400 @@ -4,14 +4,16 @@ use crate::handle::PamShared; pub use crate::libpam::pam_ffi::LibPamHandle; use crate::libpam::{memory, pam_ffi}; +use crate::logging::Level; use crate::{Conversation, PamHandleModule}; use num_enum::{IntoPrimitive, TryFromPrimitive}; use std::cell::Cell; -use std::ffi::{c_char, c_int}; +use std::ffi::{c_char, c_int, CString}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::ptr; +/// Owner for a PAM handle. struct HandleWrap(*mut LibPamHandle); impl Deref for HandleWrap { @@ -60,6 +62,7 @@ } } +/// 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<&str>> { @@ -74,6 +77,27 @@ } impl PamShared for LibPamHandle { + fn log(&self, level: Level, entry: &str) { + let entry = match CString::new(entry).or_else(|_| CString::new(dbg!(entry))) { + Ok(cstr) => cstr, + _ => return, + }; + #[cfg(pam_impl = "linux-pam")] + { + // SAFETY: We're calling this function with a known value. + unsafe { + pam_ffi::pam_syslog(self, level as c_int, c"%s".as_ptr().cast(), entry.as_ptr()) + } + } + #[cfg(pam_impl = "openpam")] + { + // SAFETY: We're calling this function with a known value. + unsafe { + pam_ffi::openpam_log(self, level as c_int, c"%s".as_ptr().cast(), entry.as_ptr()) + } + } + } + fn username(&mut self, prompt: Option<&str>) -> Result<&str> { let prompt = memory::option_cstr(prompt)?; let mut output: *const c_char = ptr::null(); @@ -224,6 +248,9 @@ } impl PamShared for OwnedLibPamHandle<'_> { + fn log(&self, level: Level, entry: &str) { + self.handle.log(level, entry) + } delegate!(fn username(&mut self, prompt: Option<&str>) -> Result<&str>); delegate!(get = user_item, set = set_user_item); delegate!(get = service, set = set_service);