comparison src/libpam/handle.rs @ 157:0099f2f79f86

Switch logging interface to accept fmt::Arguments. This means that we don't have to format arguments eagerly when logging; an implementation could choose to discard them if it wanted to, avoiding allocations and expensive format calls.
author Paul Fisher <paul@pfish.zone>
date Wed, 09 Jul 2025 16:59:30 -0400
parents 66e662cde087
children 634cd5f2ac8b
comparison
equal deleted inserted replaced
156:66e662cde087 157:0099f2f79f86
15 use std::any::TypeId; 15 use std::any::TypeId;
16 use std::cell::Cell; 16 use std::cell::Cell;
17 use std::ffi::{c_char, c_int, c_void, CString, OsStr, OsString}; 17 use std::ffi::{c_char, c_int, c_void, CString, OsStr, OsString};
18 use std::mem::ManuallyDrop; 18 use std::mem::ManuallyDrop;
19 use std::os::unix::ffi::OsStrExt; 19 use std::os::unix::ffi::OsStrExt;
20 use std::ptr;
21 use std::ptr::NonNull; 20 use std::ptr::NonNull;
21 use std::{fmt, ptr};
22 22
23 /// An owned PAM handle. 23 /// An owned PAM handle.
24 pub struct LibPamTransaction<C: Conversation> { 24 pub struct LibPamTransaction<C: Conversation> {
25 /// The handle itself. 25 /// The handle itself.
26 handle: ManuallyDrop<LibPamHandle>, 26 handle: ManuallyDrop<LibPamHandle>,
221 delegate!(fn account_management(&mut self, flags: Flags) -> Result<()>); 221 delegate!(fn account_management(&mut self, flags: Flags) -> Result<()>);
222 delegate!(fn change_authtok(&mut self, flags: Flags) -> Result<()>); 222 delegate!(fn change_authtok(&mut self, flags: Flags) -> Result<()>);
223 } 223 }
224 224
225 impl<C: Conversation> PamShared for LibPamTransaction<C> { 225 impl<C: Conversation> PamShared for LibPamTransaction<C> {
226 delegate!(fn log(&self, level: Level, location: Location<'_>, entry: &str) -> ()); 226 delegate!(fn log(&self, level: Level, location: Location<'_>, entry: fmt::Arguments) -> ());
227 delegate!(fn environ(&self) -> impl EnvironMap); 227 delegate!(fn environ(&self) -> impl EnvironMap);
228 delegate!(fn environ_mut(&mut self) -> impl EnvironMapMut); 228 delegate!(fn environ_mut(&mut self) -> impl EnvironMapMut);
229 delegate!(fn username(&mut self, prompt: Option<&OsStr>) -> Result<OsString>); 229 delegate!(fn username(&mut self, prompt: Option<&OsStr>) -> Result<OsString>);
230 delegate!(fn items(&self) -> impl Items); 230 delegate!(fn items(&self) -> impl Items);
231 delegate!(fn items_mut(&mut self) -> impl ItemsMut); 231 delegate!(fn items_mut(&mut self) -> impl ItemsMut);
320 unsafe { libpam_sys::pam_end(self.0.as_mut(), 0) }; 320 unsafe { libpam_sys::pam_end(self.0.as_mut(), 0) };
321 } 321 }
322 } 322 }
323 323
324 impl PamShared for LibPamHandle { 324 impl PamShared for LibPamHandle {
325 fn log(&self, level: Level, loc: Location<'_>, entry: &str) { 325 fn log(&self, level: Level, loc: Location<'_>, entry: fmt::Arguments) {
326 let entry = match CString::new(entry).or_else(|_| CString::new(dbg!(entry))) { 326 let entry = match CString::new(entry.to_string()).ok() {
327 Ok(cstr) => cstr, 327 Some(e) => e,
328 _ => return, 328 None => return,
329 }; 329 };
330 #[cfg(pam_impl = "LinuxPam")] 330 #[cfg(pam_impl = "LinuxPam")]
331 { 331 {
332 let level = match level { 332 let level = match level {
333 Level::Error => libc::LOG_ERR, 333 Level::Error => libc::LOG_ERR,
334 Level::Warning => libc::LOG_WARNING, 334 Level::Warn => libc::LOG_WARNING,
335 Level::Info => libc::LOG_INFO, 335 Level::Info => libc::LOG_INFO,
336 Level::Debug => libc::LOG_DEBUG, 336 Level::Debug => libc::LOG_DEBUG,
337 }; 337 };
338 _ = loc; 338 _ = loc;
339 // SAFETY: We're calling this function with a known value. 339 // SAFETY: We're calling this function with a known value.
340 unsafe { 340 unsafe {
341 libpam_sys::pam_syslog(self.raw_ref(), level, "%s\0".as_ptr().cast(), entry.as_ptr()) 341 libpam_sys::pam_syslog(
342 self.raw_ref(),
343 level,
344 b"%s\0".as_ptr().cast(),
345 entry.as_ptr(),
346 )
342 } 347 }
343 } 348 }
344 #[cfg(pam_impl = "OpenPam")] 349 #[cfg(pam_impl = "OpenPam")]
345 { 350 {
346 let func = CString::new(loc.function).unwrap_or(CString::default()); 351 let func = CString::new(loc.function).unwrap_or(CString::default());
347 let level = match level { 352 let level = match level {
348 Level::Error => libpam_sys::PAM_LOG_ERROR, 353 Level::Error => libpam_sys::PAM_LOG_ERROR,
349 Level::Warning => libpam_sys::PAM_LOG_NOTICE, 354 Level::Warn => libpam_sys::PAM_LOG_NOTICE,
350 Level::Info => libpam_sys::PAM_LOG_VERBOSE, 355 Level::Info => libpam_sys::PAM_LOG_VERBOSE,
351 Level::Debug => libpam_sys::PAM_LOG_DEBUG, 356 Level::Debug => libpam_sys::PAM_LOG_DEBUG,
352 }; 357 };
353 // SAFETY: We're calling this function with a known value. 358 // SAFETY: We're calling this function with a known value.
354 unsafe { 359 unsafe {
355 libpam_sys::_openpam_log( 360 libpam_sys::_openpam_log(
356 level as c_int, 361 level as c_int,
357 func.as_ptr(), 362 func.as_ptr(),
358 "%s\0".as_ptr().cast(), 363 b"%s\0".as_ptr().cast(),
359 entry.as_ptr(), 364 entry.as_ptr(),
360 ) 365 )
361 } 366 }
362 } 367 }
363 } 368 }