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);