Mercurial > crates > nonstick
comparison 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 |
comparison
equal
deleted
inserted
replaced
129:5b2de52dd8b2 | 130:80c07e5ab22f |
---|---|
2 | 2 |
3 // We have a lot of dumb casts that we just gotta do because of differences | 3 // We have a lot of dumb casts that we just gotta do because of differences |
4 // between Linux-PAM and OpenPAM header files. | 4 // between Linux-PAM and OpenPAM header files. |
5 #![allow(clippy::unnecessary_cast)] | 5 #![allow(clippy::unnecessary_cast)] |
6 | 6 |
7 #[cfg(feature = "link")] | |
8 use crate::libpam::pam_ffi; | |
9 use crate::{linklist, man7, manbsd, xsso}; | 7 use crate::{linklist, man7, manbsd, xsso}; |
10 use bitflags::bitflags; | 8 use bitflags::bitflags; |
11 use libc::c_int; | 9 use std::ffi::c_int; |
12 use num_enum::{IntoPrimitive, TryFromPrimitive}; | 10 use num_enum::{IntoPrimitive, TryFromPrimitive}; |
13 use std::error::Error; | 11 use std::error::Error; |
14 use std::ffi::c_uint; | |
15 use std::fmt; | |
16 use std::fmt::{Display, Formatter}; | 12 use std::fmt::{Display, Formatter}; |
17 use std::result::Result as StdResult; | 13 use std::result::Result as StdResult; |
18 | 14 use std::fmt; |
19 /// Arbitrary values for PAM constants when not linking against system PAM. | 15 |
16 /// Values for constants not provided by certain PAM implementations. | |
20 /// | 17 /// |
21 /// **The values of these constants are deliberately selected _not_ to match | 18 /// **The values of these constants are deliberately selected _not_ to match |
22 /// any PAM implementations. Applications should always use the symbolic value | 19 /// any PAM implementations. Applications should always use the symbolic value |
23 /// and not a magic number.** | 20 /// and not a magic number.** |
24 #[cfg(not(feature = "link"))] | |
25 mod pam_ffi { | 21 mod pam_ffi { |
26 use std::ffi::c_uint; | 22 pub use libpam_sys::*; |
27 | 23 |
28 macro_rules! define { | 24 macro_rules! define { |
29 ($(#[$attr:meta])* $($name:ident = $value:expr),+) => { | 25 ($(#[$attr:meta])* $($name:ident = $value:expr;)+) => { |
30 define!( | 26 define!( |
31 @meta { $(#[$attr])* } | 27 @meta { $(#[$attr])* } |
32 $(pub const $name: i32 = $value;)+ | 28 $(pub const $name: i32 = $value;)+ |
33 ); | 29 ); |
34 }; | 30 }; |
35 (@meta $m:tt $($i:item)+) => { define!(@expand $($m $i)+); }; | 31 (@meta $m:tt $($i:item)+) => { define!(@expand $($m $i)+); }; |
36 (@expand $({ $(#[$m:meta])* } $i:item)+) => {$($(#[$m])* $i)+}; | 32 (@expand $({ $(#[$m:meta])* } $i:item)+) => {$($(#[$m])* $i)+}; |
37 } | 33 } |
38 const fn bit(n: u8) -> i32 { | 34 |
39 1 << n | 35 |
40 } | |
41 define!( | 36 define!( |
42 PAM_SILENT = bit(13), | 37 /// A fictitious constant for testing purposes. |
43 PAM_DISALLOW_NULL_AUTHTOK = bit(14), | 38 #[cfg(not(feature = "link"))] |
44 PAM_ESTABLISH_CRED = bit(15), | 39 #[cfg_pam_impl(not("OpenPam"))] |
45 PAM_DELETE_CRED = bit(16), | 40 PAM_BAD_CONSTANT = 513; |
46 PAM_REINITIALIZE_CRED = bit(17), | 41 PAM_BAD_FEATURE = 514; |
47 PAM_REFRESH_CRED = bit(18), | |
48 PAM_CHANGE_EXPIRED_AUTHTOK = bit(19), | |
49 PAM_PRELIM_CHECK = bit(20), | |
50 PAM_UPDATE_AUTHTOK = bit(21) | |
51 ); | 42 ); |
52 | 43 |
53 define!( | 44 define!( |
54 PAM_ABORT = 513, | 45 /// A fictitious constant for testing purposes. |
55 PAM_ACCT_EXPIRED = 514, | 46 #[cfg(not(feature = "link"))] |
56 PAM_AUTHINFO_UNAVAIL = 515, | 47 #[cfg_pam_impl(not(any("LinuxPam", "OpenPam")))] |
57 PAM_AUTHTOK_DISABLE_AGING = 516, | 48 PAM_BAD_ITEM = 515; |
58 PAM_AUTHTOK_ERR = 517, | 49 PAM_MODULE_UNKNOWN = 516; |
59 PAM_AUTHTOK_EXPIRED = 518, | |
60 PAM_AUTHTOK_LOCK_BUSY = 519, | |
61 PAM_AUTHTOK_RECOVERY_ERR = 520, | |
62 PAM_AUTH_ERR = 521, | |
63 PAM_BAD_ITEM = 522, | |
64 PAM_BUF_ERR = 533, | |
65 PAM_CONV_AGAIN = 534, | |
66 PAM_CONV_ERR = 535, | |
67 PAM_CRED_ERR = 536, | |
68 PAM_CRED_EXPIRED = 537, | |
69 PAM_CRED_INSUFFICIENT = 538, | |
70 PAM_CRED_UNAVAIL = 539, | |
71 PAM_IGNORE = 540, | |
72 PAM_INCOMPLETE = 541, | |
73 PAM_MAXTRIES = 542, | |
74 PAM_MODULE_UNKNOWN = 543, | |
75 PAM_NEW_AUTHTOK_REQD = 544, | |
76 PAM_NO_MODULE_DATA = 545, | |
77 PAM_OPEN_ERR = 546, | |
78 PAM_PERM_DENIED = 547, | |
79 PAM_SERVICE_ERR = 548, | |
80 PAM_SESSION_ERR = 549, | |
81 PAM_SYMBOL_ERR = 550, | |
82 PAM_SYSTEM_ERR = 551, | |
83 PAM_TRY_AGAIN = 552, | |
84 PAM_USER_UNKNOWN = 553 | |
85 ); | 50 ); |
86 | 51 |
87 /// Dummy implementation of strerror so that it always returns None. | 52 define!( |
88 pub fn strerror(val: c_uint) -> Option<&'static str> { | 53 /// A fictitious constant for testing purposes. |
89 _ = val; | 54 #[cfg(not(feature = "link"))] |
90 None | 55 #[cfg_pam_impl(not("LinuxPam"))] |
91 } | 56 PAM_CONV_AGAIN = 517; |
57 PAM_INCOMPLETE = 518; | |
58 ); | |
59 | |
92 } | 60 } |
93 | 61 |
94 bitflags! { | 62 bitflags! { |
95 /// The available PAM flags. | 63 /// The available PAM flags. |
96 /// | 64 /// |
98 /// See `/usr/include/security/pam_modules.h` for more details. | 66 /// See `/usr/include/security/pam_modules.h` for more details. |
99 #[derive(Debug, Default, PartialEq)] | 67 #[derive(Debug, Default, PartialEq)] |
100 #[repr(transparent)] | 68 #[repr(transparent)] |
101 pub struct Flags: c_int { | 69 pub struct Flags: c_int { |
102 /// The module should not generate any messages. | 70 /// The module should not generate any messages. |
103 const SILENT = pam_ffi::PAM_SILENT; | 71 const SILENT = libpam_sys::PAM_SILENT; |
104 | 72 |
105 /// The module should return [ErrorCode::AuthError] | 73 /// The module should return [ErrorCode::AuthError] |
106 /// if the user has an empty authentication token | 74 /// if the user has an empty authentication token |
107 /// rather than immediately accepting them. | 75 /// rather than immediately accepting them. |
108 const DISALLOW_NULL_AUTHTOK = pam_ffi::PAM_DISALLOW_NULL_AUTHTOK; | 76 const DISALLOW_NULL_AUTHTOK = libpam_sys::PAM_DISALLOW_NULL_AUTHTOK; |
109 | 77 |
110 // Flag used for `set_credentials`. | 78 // Flag used for `set_credentials`. |
111 | 79 |
112 /// Set user credentials for an authentication service. | 80 /// Set user credentials for an authentication service. |
113 const ESTABLISH_CREDENTIALS = pam_ffi::PAM_ESTABLISH_CRED; | 81 const ESTABLISH_CREDENTIALS = libpam_sys::PAM_ESTABLISH_CRED; |
114 /// Delete user credentials associated with | 82 /// Delete user credentials associated with |
115 /// an authentication service. | 83 /// an authentication service. |
116 const DELETE_CREDENTIALS = pam_ffi::PAM_DELETE_CRED; | 84 const DELETE_CREDENTIALS = libpam_sys::PAM_DELETE_CRED; |
117 /// Reinitialize user credentials. | 85 /// Reinitialize user credentials. |
118 const REINITIALIZE_CREDENTIALS = pam_ffi::PAM_REINITIALIZE_CRED; | 86 const REINITIALIZE_CREDENTIALS = libpam_sys::PAM_REINITIALIZE_CRED; |
119 /// Extend the lifetime of user credentials. | 87 /// Extend the lifetime of user credentials. |
120 const REFRESH_CREDENTIALS = pam_ffi::PAM_REFRESH_CRED; | 88 const REFRESH_CREDENTIALS = libpam_sys::PAM_REFRESH_CRED; |
121 | 89 |
122 // Flags used for password changing. | 90 // Flags used for password changing. |
123 | 91 |
124 /// The password service should only update those passwords | 92 /// The password service should only update those passwords |
125 /// that have aged. If this flag is _not_ passed, | 93 /// that have aged. If this flag is _not_ passed, |
126 /// the password service should update all passwords. | 94 /// the password service should update all passwords. |
127 /// | 95 /// |
128 /// This flag is only used by `change_authtok`. | 96 /// This flag is only used by `change_authtok`. |
129 const CHANGE_EXPIRED_AUTHTOK = pam_ffi::PAM_CHANGE_EXPIRED_AUTHTOK; | 97 const CHANGE_EXPIRED_AUTHTOK = libpam_sys::PAM_CHANGE_EXPIRED_AUTHTOK; |
130 /// This is a preliminary check for password changing. | 98 /// This is a preliminary check for password changing. |
131 /// The password should not be changed. | 99 /// The password should not be changed. |
132 /// | 100 /// |
133 /// This is only used between PAM and a module. | 101 /// This is only used between PAM and a module. |
134 /// Applications may not use this flag. | 102 /// Applications may not use this flag. |
135 /// | 103 /// |
136 /// This flag is only used by `change_authtok`. | 104 /// This flag is only used by `change_authtok`. |
137 const PRELIMINARY_CHECK = pam_ffi::PAM_PRELIM_CHECK; | 105 const PRELIMINARY_CHECK = libpam_sys::PAM_PRELIM_CHECK; |
138 /// The password should actuallyPR be updated. | 106 /// The password should actuallyPR be updated. |
139 /// This and [Self::PRELIMINARY_CHECK] are mutually exclusive. | 107 /// This and [Self::PRELIMINARY_CHECK] are mutually exclusive. |
140 /// | 108 /// |
141 /// This is only used between PAM and a module. | 109 /// This is only used between PAM and a module. |
142 /// Applications may not use this flag. | 110 /// Applications may not use this flag. |
143 /// | 111 /// |
144 /// This flag is only used by `change_authtok`. | 112 /// This flag is only used by `change_authtok`. |
145 const UPDATE_AUTHTOK = pam_ffi::PAM_UPDATE_AUTHTOK; | 113 const UPDATE_AUTHTOK = libpam_sys::PAM_UPDATE_AUTHTOK; |
146 } | 114 } |
147 } | 115 } |
148 | 116 |
149 /// The PAM error return codes. | 117 /// The PAM error return codes. |
150 /// | 118 /// |
205 /// A PAM-specific Result type with an [ErrorCode] error. | 173 /// A PAM-specific Result type with an [ErrorCode] error. |
206 pub type Result<T> = StdResult<T, ErrorCode>; | 174 pub type Result<T> = StdResult<T, ErrorCode>; |
207 | 175 |
208 impl Display for ErrorCode { | 176 impl Display for ErrorCode { |
209 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | 177 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
210 match pam_ffi::strerror((*self).into()) { | 178 match strerror((*self).into()) { |
211 Some(err) => f.write_str(err), | 179 Some(err) => f.write_str(err), |
212 None => self.fmt_internal(f), | 180 None => self.fmt_internal(f), |
213 } | 181 } |
214 } | 182 } |
215 } | 183 } |
234 } | 202 } |
235 } | 203 } |
236 | 204 |
237 /// A basic Display implementation for if we don't link against PAM. | 205 /// A basic Display implementation for if we don't link against PAM. |
238 fn fmt_internal(self, f: &mut Formatter<'_>) -> fmt::Result { | 206 fn fmt_internal(self, f: &mut Formatter<'_>) -> fmt::Result { |
239 write!(f, "PAM error: {self:?} ({n})", n = self as c_uint) | 207 let n : c_int = self.into(); |
240 } | 208 write!(f, "PAM error: {self:?} ({n})") |
209 } | |
210 } | |
211 | |
212 /// Gets a string version of an error message. | |
213 #[cfg(feature = "link")] | |
214 pub fn strerror(code: c_int) -> Option<&'static str> { | |
215 use std::ptr; | |
216 use std::ffi::CStr; | |
217 // SAFETY: PAM impls don't care about the PAM handle and always return | |
218 // static strings. | |
219 let strerror = unsafe { libpam_sys::pam_strerror(ptr::null(), code as c_int) }; | |
220 // SAFETY: We just got this back from PAM and we checked if it's null. | |
221 (!strerror.is_null()) | |
222 .then(|| unsafe { CStr::from_ptr(strerror) }.to_str().ok()) | |
223 .flatten() | |
224 } | |
225 | |
226 /// Dummy implementation of strerror so that it always returns None. | |
227 #[cfg(not(feature = "link"))] | |
228 pub fn strerror(_: c_int) -> Option<&'static str> { | |
229 None | |
241 } | 230 } |
242 | 231 |
243 #[cfg(test)] | 232 #[cfg(test)] |
244 mod tests { | 233 mod tests { |
245 use super::*; | 234 use super::*; |