Mercurial > crates > nonstick
diff src/constants.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 | a12706e42c9d |
children | a632a8874131 |
line wrap: on
line diff
--- a/src/constants.rs Mon Jun 30 23:49:54 2025 -0400 +++ b/src/constants.rs Tue Jul 01 06:11:43 2025 -0400 @@ -4,29 +4,25 @@ // between Linux-PAM and OpenPAM header files. #![allow(clippy::unnecessary_cast)] -#[cfg(feature = "link")] -use crate::libpam::pam_ffi; use crate::{linklist, man7, manbsd, xsso}; use bitflags::bitflags; -use libc::c_int; +use std::ffi::c_int; use num_enum::{IntoPrimitive, TryFromPrimitive}; use std::error::Error; -use std::ffi::c_uint; -use std::fmt; use std::fmt::{Display, Formatter}; use std::result::Result as StdResult; +use std::fmt; -/// Arbitrary values for PAM constants when not linking against system PAM. +/// Values for constants not provided by certain PAM implementations. /// /// **The values of these constants are deliberately selected _not_ to match /// any PAM implementations. Applications should always use the symbolic value /// and not a magic number.** -#[cfg(not(feature = "link"))] mod pam_ffi { - use std::ffi::c_uint; + pub use libpam_sys::*; macro_rules! define { - ($(#[$attr:meta])* $($name:ident = $value:expr),+) => { + ($(#[$attr:meta])* $($name:ident = $value:expr;)+) => { define!( @meta { $(#[$attr])* } $(pub const $name: i32 = $value;)+ @@ -35,60 +31,32 @@ (@meta $m:tt $($i:item)+) => { define!(@expand $($m $i)+); }; (@expand $({ $(#[$m:meta])* } $i:item)+) => {$($(#[$m])* $i)+}; } - const fn bit(n: u8) -> i32 { - 1 << n - } + + define!( - PAM_SILENT = bit(13), - PAM_DISALLOW_NULL_AUTHTOK = bit(14), - PAM_ESTABLISH_CRED = bit(15), - PAM_DELETE_CRED = bit(16), - PAM_REINITIALIZE_CRED = bit(17), - PAM_REFRESH_CRED = bit(18), - PAM_CHANGE_EXPIRED_AUTHTOK = bit(19), - PAM_PRELIM_CHECK = bit(20), - PAM_UPDATE_AUTHTOK = bit(21) + /// A fictitious constant for testing purposes. + #[cfg(not(feature = "link"))] + #[cfg_pam_impl(not("OpenPam"))] + PAM_BAD_CONSTANT = 513; + PAM_BAD_FEATURE = 514; ); define!( - PAM_ABORT = 513, - PAM_ACCT_EXPIRED = 514, - PAM_AUTHINFO_UNAVAIL = 515, - PAM_AUTHTOK_DISABLE_AGING = 516, - PAM_AUTHTOK_ERR = 517, - PAM_AUTHTOK_EXPIRED = 518, - PAM_AUTHTOK_LOCK_BUSY = 519, - PAM_AUTHTOK_RECOVERY_ERR = 520, - PAM_AUTH_ERR = 521, - PAM_BAD_ITEM = 522, - PAM_BUF_ERR = 533, - PAM_CONV_AGAIN = 534, - PAM_CONV_ERR = 535, - PAM_CRED_ERR = 536, - PAM_CRED_EXPIRED = 537, - PAM_CRED_INSUFFICIENT = 538, - PAM_CRED_UNAVAIL = 539, - PAM_IGNORE = 540, - PAM_INCOMPLETE = 541, - PAM_MAXTRIES = 542, - PAM_MODULE_UNKNOWN = 543, - PAM_NEW_AUTHTOK_REQD = 544, - PAM_NO_MODULE_DATA = 545, - PAM_OPEN_ERR = 546, - PAM_PERM_DENIED = 547, - PAM_SERVICE_ERR = 548, - PAM_SESSION_ERR = 549, - PAM_SYMBOL_ERR = 550, - PAM_SYSTEM_ERR = 551, - PAM_TRY_AGAIN = 552, - PAM_USER_UNKNOWN = 553 + /// A fictitious constant for testing purposes. + #[cfg(not(feature = "link"))] + #[cfg_pam_impl(not(any("LinuxPam", "OpenPam")))] + PAM_BAD_ITEM = 515; + PAM_MODULE_UNKNOWN = 516; ); - /// Dummy implementation of strerror so that it always returns None. - pub fn strerror(val: c_uint) -> Option<&'static str> { - _ = val; - None - } + define!( + /// A fictitious constant for testing purposes. + #[cfg(not(feature = "link"))] + #[cfg_pam_impl(not("LinuxPam"))] + PAM_CONV_AGAIN = 517; + PAM_INCOMPLETE = 518; + ); + } bitflags! { @@ -100,24 +68,24 @@ #[repr(transparent)] pub struct Flags: c_int { /// The module should not generate any messages. - const SILENT = pam_ffi::PAM_SILENT; + const SILENT = libpam_sys::PAM_SILENT; /// The module should return [ErrorCode::AuthError] /// if the user has an empty authentication token /// rather than immediately accepting them. - const DISALLOW_NULL_AUTHTOK = pam_ffi::PAM_DISALLOW_NULL_AUTHTOK; + const DISALLOW_NULL_AUTHTOK = libpam_sys::PAM_DISALLOW_NULL_AUTHTOK; // Flag used for `set_credentials`. /// Set user credentials for an authentication service. - const ESTABLISH_CREDENTIALS = pam_ffi::PAM_ESTABLISH_CRED; + const ESTABLISH_CREDENTIALS = libpam_sys::PAM_ESTABLISH_CRED; /// Delete user credentials associated with /// an authentication service. - const DELETE_CREDENTIALS = pam_ffi::PAM_DELETE_CRED; + const DELETE_CREDENTIALS = libpam_sys::PAM_DELETE_CRED; /// Reinitialize user credentials. - const REINITIALIZE_CREDENTIALS = pam_ffi::PAM_REINITIALIZE_CRED; + const REINITIALIZE_CREDENTIALS = libpam_sys::PAM_REINITIALIZE_CRED; /// Extend the lifetime of user credentials. - const REFRESH_CREDENTIALS = pam_ffi::PAM_REFRESH_CRED; + const REFRESH_CREDENTIALS = libpam_sys::PAM_REFRESH_CRED; // Flags used for password changing. @@ -126,7 +94,7 @@ /// the password service should update all passwords. /// /// This flag is only used by `change_authtok`. - const CHANGE_EXPIRED_AUTHTOK = pam_ffi::PAM_CHANGE_EXPIRED_AUTHTOK; + const CHANGE_EXPIRED_AUTHTOK = libpam_sys::PAM_CHANGE_EXPIRED_AUTHTOK; /// This is a preliminary check for password changing. /// The password should not be changed. /// @@ -134,7 +102,7 @@ /// Applications may not use this flag. /// /// This flag is only used by `change_authtok`. - const PRELIMINARY_CHECK = pam_ffi::PAM_PRELIM_CHECK; + const PRELIMINARY_CHECK = libpam_sys::PAM_PRELIM_CHECK; /// The password should actuallyPR be updated. /// This and [Self::PRELIMINARY_CHECK] are mutually exclusive. /// @@ -142,7 +110,7 @@ /// Applications may not use this flag. /// /// This flag is only used by `change_authtok`. - const UPDATE_AUTHTOK = pam_ffi::PAM_UPDATE_AUTHTOK; + const UPDATE_AUTHTOK = libpam_sys::PAM_UPDATE_AUTHTOK; } } @@ -207,7 +175,7 @@ impl Display for ErrorCode { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match pam_ffi::strerror((*self).into()) { + match strerror((*self).into()) { Some(err) => f.write_str(err), None => self.fmt_internal(f), } @@ -236,10 +204,31 @@ /// A basic Display implementation for if we don't link against PAM. fn fmt_internal(self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "PAM error: {self:?} ({n})", n = self as c_uint) + let n : c_int = self.into(); + write!(f, "PAM error: {self:?} ({n})") } } +/// Gets a string version of an error message. +#[cfg(feature = "link")] +pub fn strerror(code: c_int) -> Option<&'static str> { + use std::ptr; + use std::ffi::CStr; + // SAFETY: PAM impls don't care about the PAM handle and always return + // static strings. + let strerror = unsafe { libpam_sys::pam_strerror(ptr::null(), code as c_int) }; + // SAFETY: We just got this back from PAM and we checked if it's null. + (!strerror.is_null()) + .then(|| unsafe { CStr::from_ptr(strerror) }.to_str().ok()) + .flatten() +} + +/// Dummy implementation of strerror so that it always returns None. +#[cfg(not(feature = "link"))] +pub fn strerror(_: c_int) -> Option<&'static str> { + None +} + #[cfg(test)] mod tests { use super::*;