Mercurial > crates > nonstick
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!( |