comparison src/constants.rs @ 175:e30775c80b49

Separate #[cfg(feature = "link")] from other features.
author Paul Fisher <paul@pfish.zone>
date Wed, 30 Jul 2025 14:57:12 -0400
parents 6727cbe56f4a
children 0730f5f2ee2a
comparison
equal deleted inserted replaced
174:9e4ce1631bd3 175:e30775c80b49
1 //! Constants and enum values from the PAM library. 1 //! Constants and enum values from the PAM library.
2 2
3 use crate::_doc::{linklist, man7, manbsd, mansun, xsso}; 3 use crate::_doc::{linklist, man7, manbsd, mansun, xsso};
4 use bitflags::bitflags; 4 use bitflags::bitflags;
5 use std::error::Error; 5 use std::error::Error;
6 use std::ffi::c_int;
7 use std::fmt; 6 use std::fmt;
8 use std::fmt::{Display, Formatter};
9 use std::result::Result as StdResult; 7 use std::result::Result as StdResult;
10 8
11 macro_rules! wrapper { 9 macro_rules! wrapper {
12 ( 10 (
13 $(#[$m:meta])* 11 $(#[$m:meta])*
31 } 29 }
32 } 30 }
33 31
34 wrapper! { 32 wrapper! {
35 /// Type of the flags that PAM passes to us (or that we pass to PAM). 33 /// Type of the flags that PAM passes to us (or that we pass to PAM).
36 pub RawFlags(c_int); 34 pub RawFlags(i32);
37 } 35 }
38 wrapper! { 36 wrapper! {
39 /// The error code that we return to PAM. 37 /// The error code that we return to PAM.
40 pub ReturnCode(c_int); 38 pub ReturnCode(i32);
41 } 39 }
42 40
43 impl ReturnCode { 41 impl ReturnCode {
44 /// A successful return. 42 /// A successful return.
45 pub const SUCCESS: Self = Self(0); 43 pub const SUCCESS: Self = Self(0);
68 66
69 #[cfg(feature = "link")] 67 #[cfg(feature = "link")]
70 impl From<RawFlags> for $name { 68 impl From<RawFlags> for $name {
71 #[allow(unused_doc_comments)] 69 #[allow(unused_doc_comments)]
72 fn from(value: RawFlags) -> Self { 70 fn from(value: RawFlags) -> Self {
73 let value: c_int = value.into(); 71 let value: i32 = value.into();
74 let result = Self::empty(); 72 let result = Self::empty();
75 $( 73 $(
76 $(#[$m_ident $($m_arg)*])* 74 $(#[$m_ident $($m_arg)*])*
77 let result = result | if value & $value_value == 0 { 75 let result = result | if value & $value_value == 0 {
78 Self::empty() 76 Self::empty()
126 /// only be changed if it is expired. If not passed, 124 /// only be changed if it is expired. If not passed,
127 /// the authentication token should be changed unconditionally. 125 /// the authentication token should be changed unconditionally.
128 const CHANGE_EXPIRED_AUTHTOK = (link = libpam_sys::PAM_CHANGE_EXPIRED_AUTHTOK, else = 0b10); 126 const CHANGE_EXPIRED_AUTHTOK = (link = libpam_sys::PAM_CHANGE_EXPIRED_AUTHTOK, else = 0b10);
129 127
130 /// Don't check if the password is any good (Sun only). 128 /// Don't check if the password is any good (Sun only).
131 #[cfg(pam_impl = "Sun")] 129 #[cfg(feature = "sun-ext")]
132 const NO_AUTHTOK_CHECK = (link = libpam_sys::PAM_NO_AUTHTOK_CHECK, else = 0b100); 130 const NO_AUTHTOK_CHECK = (link = libpam_sys::PAM_NO_AUTHTOK_CHECK, else = 0b100);
133 } 131 }
134 } 132 }
135 133
136 pam_flags! { 134 pam_flags! {
138 BaseFlags { 136 BaseFlags {
139 /// The PAM module should not generate any messages. 137 /// The PAM module should not generate any messages.
140 const SILENT = (link = libpam_sys::PAM_SILENT, else = 0x8000); 138 const SILENT = (link = libpam_sys::PAM_SILENT, else = 0x8000);
141 } 139 }
142 } 140 }
143
144 #[cfg(feature = "openpam-ext")]
145 const BAD_CONST: ErrorCode = ErrorCode::BadConstant;
146 #[cfg(not(feature = "openpam-ext"))]
147 const BAD_CONST: ErrorCode = ErrorCode::SystemError;
148 141
149 macro_rules! flag_enum { 142 macro_rules! flag_enum {
150 ( 143 (
151 $(#[$m:meta])* 144 $(#[$m:meta])*
152 $name:ident { 145 $name:ident {
171 fn try_from(value: RawFlags) -> Result<$name> { 164 fn try_from(value: RawFlags) -> Result<$name> {
172 match value.0 { 165 match value.0 {
173 $( 166 $(
174 $item_value => Ok(Self::$item_name), 167 $item_value => Ok(Self::$item_name),
175 )* 168 )*
176 _ => Err(BAD_CONST), 169 _ => Err(ErrorCode::BAD_CONST),
177 } 170 }
178 } 171 }
179 } 172 }
180 173
181 #[cfg(feature = "link")] 174 #[cfg(feature = "link")]
196 fn split(value: RawFlags) -> Result<(Option<Self>, RawFlags)> { 189 fn split(value: RawFlags) -> Result<(Option<Self>, RawFlags)> {
197 let me = value.0 & Self::ALL_VALUES; 190 let me = value.0 & Self::ALL_VALUES;
198 let them = (value.0 & !Self::ALL_VALUES).into(); 191 let them = (value.0 & !Self::ALL_VALUES).into();
199 let me = match RawFlags(me) { 192 let me = match RawFlags(me) {
200 RawFlags(0) => None, 193 RawFlags(0) => None,
201 other => Some(Self::try_from(other).map_err(|_| BAD_CONST)?), 194 other => Some(Self::try_from(other).map_err(|_| ErrorCode::BAD_CONST)?),
202 }; 195 };
203 Ok((me, them)) 196 Ok((me, them))
204 } 197 }
205 } 198 }
206 } 199 }
252 impl AuthtokAction { 245 impl AuthtokAction {
253 /// Separates this enum from the remaining [`AuthtokFlags`]. 246 /// Separates this enum from the remaining [`AuthtokFlags`].
254 pub(crate) fn extract(value: RawFlags) -> Result<(Self, AuthtokFlags)> { 247 pub(crate) fn extract(value: RawFlags) -> Result<(Self, AuthtokFlags)> {
255 match Self::split(value)? { 248 match Self::split(value)? {
256 (Some(act), rest) => Ok((act, AuthtokFlags::from(rest))), 249 (Some(act), rest) => Ok((act, AuthtokFlags::from(rest))),
257 (None, _) => Err(BAD_CONST), 250 (None, _) => Err(ErrorCode::BAD_CONST),
258 } 251 }
259 } 252 }
260 } 253 }
261 254
262 /// Constructs an enum which has the values if it's linked 255 /// Constructs an enum which has the values if it's linked
286 match value.into() { 279 match value.into() {
287 $( 280 $(
288 $(#[$im])* 281 $(#[$im])*
289 $value => Ok(Self::$key), 282 $value => Ok(Self::$key),
290 )* 283 )*
291 _ => Err(BAD_CONST), 284 _ => Err(ErrorCode::BAD_CONST),
292 } 285 }
293 } 286 }
294 } 287 }
295 288
296 #[cfg(feature = "link")] 289 #[cfg(feature = "link")]
378 } 371 }
379 372
380 /// A PAM-specific Result type with an [ErrorCode] error. 373 /// A PAM-specific Result type with an [ErrorCode] error.
381 pub type Result<T> = StdResult<T, ErrorCode>; 374 pub type Result<T> = StdResult<T, ErrorCode>;
382 375
383 impl Display for ErrorCode { 376 #[cfg(feature = "link")]
384 #[cfg(all( 377 impl fmt::Display for ErrorCode {
385 feature = "link", 378 #[cfg(any(pam_impl = "LinuxPam", pam_impl = "OpenPam", pam_impl = "Sun"))]
386 any(pam_impl = "LinuxPam", pam_impl = "OpenPam", pam_impl = "Sun") 379 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387 ))]
388 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
389 use std::ffi::CStr; 380 use std::ffi::CStr;
390 use std::ptr; 381 use std::ptr;
391 // SAFETY: PAM impls don't care about the PAM handle and always return 382 // SAFETY: PAM impls don't care about the PAM handle and always return
392 // static strings. 383 // static strings.
393 let got = unsafe { libpam_sys::pam_strerror(ptr::null(), *self as c_int) }; 384 let got = unsafe { libpam_sys::pam_strerror(ptr::null(), *self as i32) };
394 if got.is_null() { 385 if got.is_null() {
395 // This shouldn't happen. 386 // This shouldn't happen.
396 write!(f, "PAM error: {self:?} ({:?})", *self as c_int) 387 write!(f, "PAM error: {self:?} ({:?})", *self as i32)
397 } else { 388 } else {
398 // SAFETY: We just got this back from PAM and we checked if it's null. 389 // SAFETY: We just got this back from PAM and we checked if it's null.
399 f.write_str(&unsafe { CStr::from_ptr(got) }.to_string_lossy()) 390 f.write_str(&unsafe { CStr::from_ptr(got) }.to_string_lossy())
400 } 391 }
401 } 392 }
402 #[cfg(not(all( 393 #[cfg(not(any(pam_impl = "LinuxPam", pam_impl = "OpenPam", pam_impl = "Sun")))]
403 feature = "link", 394 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
404 any(pam_impl = "LinuxPam", pam_impl = "OpenPam", pam_impl = "Sun") 395 fmt::Debug::fmt(self, f)
405 )))] 396 }
406 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 397 }
398
399 #[cfg(not(feature = "link"))]
400 impl fmt::Display for ErrorCode {
401 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
407 fmt::Debug::fmt(self, f) 402 fmt::Debug::fmt(self, f)
408 } 403 }
409 } 404 }
410 405
411 impl Error for ErrorCode {} 406 impl Error for ErrorCode {}
412 407
413 #[cfg(feature = "link")] 408 #[cfg(feature = "link")]
414 impl ErrorCode { 409 impl ErrorCode {
415 pub(crate) fn result_from(ret: c_int) -> Result<()> { 410 #[cfg(feature = "openpam-ext")]
411 const BAD_CONST: ErrorCode = ErrorCode::BadConstant;
412 #[cfg(not(feature = "openpam-ext"))]
413 const BAD_CONST: ErrorCode = ErrorCode::SystemError;
414
415
416 pub(crate) fn result_from(ret: i32) -> Result<()> {
416 match ret { 417 match ret {
417 0 => Ok(()), 418 0 => Ok(()),
418 value => Err(ReturnCode(value).try_into().unwrap_or(BAD_CONST)), 419 value => Err(ReturnCode(value).try_into().unwrap_or(Self::BAD_CONST)),
419 } 420 }
420 } 421 }
421 } 422 }
422 423
424 #[cfg(feature = "link")]
423 impl<T> From<Result<T>> for ReturnCode { 425 impl<T> From<Result<T>> for ReturnCode {
424 fn from(value: Result<T>) -> Self { 426 fn from(value: Result<T>) -> Self {
425 match value { 427 match value {
426 Ok(_) => ReturnCode::SUCCESS, 428 Ok(_) => ReturnCode::SUCCESS,
427 Err(otherwise) => otherwise.into(), 429 Err(otherwise) => otherwise.into(),
442 ); 444 );
443 assert_eq!( 445 assert_eq!(
444 Result::<()>::Err(ErrorCode::Abort), 446 Result::<()>::Err(ErrorCode::Abort),
445 ErrorCode::result_from(libpam_sys::PAM_ABORT) 447 ErrorCode::result_from(libpam_sys::PAM_ABORT)
446 ); 448 );
447 assert_eq!(Err(BAD_CONST), ErrorCode::result_from(423)); 449 assert_eq!(Err(ErrorCode::BAD_CONST), ErrorCode::result_from(423));
448 } 450 }
449 451
450 #[test] 452 #[test]
451 fn test_flags() { 453 fn test_flags() {
452 assert_eq!( 454 assert_eq!(