comparison src/constants.rs @ 170:f052e2417195

Completely avoid using libpam_sys if we're not actually linking.
author Paul Fisher <paul@pfish.zone>
date Wed, 16 Jul 2025 18:45:20 -0400
parents 2f5913131295
children e27c5c667a5a
comparison
equal deleted inserted replaced
169:77470e45e397 170:f052e2417195
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, xsso}; 3 use crate::_doc::{linklist, man7, manbsd, xsso};
4 use bitflags::bitflags; 4 use bitflags::bitflags;
5 use libpam_sys_consts::constants;
6 use num_enum::{IntoPrimitive, TryFromPrimitive}; 5 use num_enum::{IntoPrimitive, TryFromPrimitive};
7 use std::error::Error; 6 use std::error::Error;
8 use std::ffi::c_int; 7 use std::ffi::c_int;
9 use std::fmt; 8 use std::fmt;
10 use std::fmt::{Display, Formatter}; 9 use std::fmt::{Display, Formatter};
11 use std::result::Result as StdResult; 10 use std::result::Result as StdResult;
11
12 #[cfg(features = "link")]
13 use libpam_sys_consts::constants as pam_constants;
14
15
16 /// The union of constants available in all versions of PAM.
17 /// The values here are fictitious and should not be used.
18 #[cfg(not(features = "link"))]
19 mod pam_constants {
20 pub const PAM_SUCCESS: i32 = 0;
21
22 /// Generates a sequence of values.
23 macro_rules! c_enum {
24 ($first:ident = $value:expr, $($rest:ident,)*) => {
25 c_enum!(($value) $first, $($rest,)*);
26 };
27 (($value:expr) $first:ident, $($rest:ident,)*) => {
28 pub const $first: i32 = $value;
29 c_enum!(($value+1) $($rest,)*);
30 };
31 (($value:expr)) => {};
32 }
33
34 // Since all these values are fictitious, we can start them wherever.
35 // All the items.
36 c_enum!(
37 PAM_SERVICE = 64,
38 PAM_USER,
39 PAM_TTY,
40 PAM_RHOST,
41 PAM_CONV,
42 PAM_AUTHTOK,
43 PAM_OLDAUTHTOK,
44 PAM_RUSER,
45 PAM_USER_PROMPT,
46 // Linux-only items.
47 PAM_FAIL_DELAY,
48 PAM_XDISPLAY,
49 PAM_XAUTHDATA,
50 PAM_AUTHTOK_TYPE,
51 // OpenPAM-only items.
52 PAM_REPOSITORY,
53 PAM_AUTHTOK_PROMPT,
54 PAM_OLDAUTHTOK_PROMPT,
55 PAM_HOST,
56 // Sun-only items.
57 PAM_RESOURCE,
58 PAM_AUSER,
59 );
60
61 // Prompt types.
62 c_enum!(
63 PAM_PROMPT_ECHO_OFF = 96,
64 PAM_PROMPT_ECHO_ON,
65 PAM_ERROR_MSG,
66 PAM_TEXT_INFO,
67 PAM_RADIO_TYPE,
68 PAM_BINARY_PROMPT,
69 );
70
71 // Errors.
72 c_enum!(
73 PAM_OPEN_ERR = 128,
74 PAM_SYMBOL_ERR,
75 PAM_SERVICE_ERR,
76 PAM_SYSTEM_ERR,
77 PAM_BUF_ERR,
78 PAM_PERM_DENIED,
79 PAM_AUTH_ERR,
80 PAM_CRED_INSUFFICIENT,
81 PAM_AUTHINFO_UNAVAIL,
82 PAM_USER_UNKNOWN,
83 PAM_MAXTRIES,
84 PAM_NEW_AUTHTOK_REQD,
85 PAM_ACCT_EXPIRED,
86 PAM_SESSION_ERR,
87 PAM_CRED_UNAVAIL,
88 PAM_CRED_EXPIRED,
89 PAM_CRED_ERR,
90 PAM_NO_MODULE_DATA,
91 PAM_CONV_ERR,
92 PAM_AUTHTOK_ERR,
93 PAM_AUTHTOK_RECOVERY_ERR,
94 PAM_AUTHTOK_LOCK_BUSY,
95 PAM_AUTHTOK_DISABLE_AGING,
96 PAM_TRY_AGAIN,
97 PAM_IGNORE,
98 PAM_ABORT,
99 PAM_AUTHTOK_EXPIRED,
100 PAM_MODULE_UNKNOWN,
101 PAM_BAD_ITEM,
102 PAM_CONV_AGAIN,
103 PAM_INCOMPLETE,
104 // OpenPAM-only errors.
105 PAM_DOMAIN_UNKNOWN,
106 PAM_BAD_HANDLE,
107 PAM_BAD_FEATURE,
108 PAM_BAD_CONSTANT,
109 );
110
111 macro_rules! flag_enum {
112 ($first:ident = $value:expr, $($rest:ident,)*) => {
113 flag_enum!(($value) $first, $($rest,)*);
114 };
115 (($value:expr) $first:ident, $($rest:ident,)*) => {
116 pub const $first: i32 = $value;
117 flag_enum!(($value*2) $($rest,)*);
118 };
119 (($value:expr)) => {};
120 }
121
122 flag_enum!(
123 PAM_SILENT = 256,
124 PAM_DISALLOW_NULL_AUTHTOK,
125 PAM_ESTABLISH_CRED,
126 PAM_DELETE_CRED,
127 PAM_REINITIALIZE_CRED,
128 PAM_REFRESH_CRED,
129
130 PAM_CHANGE_EXPIRED_AUTHTOK,
131
132 PAM_PRELIM_CHECK,
133 PAM_UPDATE_AUTHTOK,
134 PAM_DATA_REPLACE,
135 PAM_DATA_SILENT,
136 );
137 }
12 138
13 /// Creates a bitflags! macro, with an extra SILENT element. 139 /// Creates a bitflags! macro, with an extra SILENT element.
14 macro_rules! pam_flags { 140 macro_rules! pam_flags {
15 ( 141 (
16 $(#[$m:meta])* 142 $(#[$m:meta])*
22 $(#[$m])* 148 $(#[$m])*
23 #[derive(Clone, Copy, Debug, Default, PartialEq)] 149 #[derive(Clone, Copy, Debug, Default, PartialEq)]
24 #[repr(transparent)] 150 #[repr(transparent)]
25 pub struct $name: c_int { 151 pub struct $name: c_int {
26 /// The module should not generate any messages. 152 /// The module should not generate any messages.
27 const SILENT = constants::PAM_SILENT; 153 const SILENT = pam_constants::PAM_SILENT;
28 $($inner)* 154 $($inner)*
29 } 155 }
30 } 156 }
31 } 157 }
32 } 158 }
35 /// Flags for authentication and account management. 161 /// Flags for authentication and account management.
36 AuthnFlags { 162 AuthnFlags {
37 /// The module should return [AuthError](ErrorCode::AuthError) 163 /// The module should return [AuthError](ErrorCode::AuthError)
38 /// if the user has an empty authentication token, rather than 164 /// if the user has an empty authentication token, rather than
39 /// allowing them to log in. 165 /// allowing them to log in.
40 const DISALLOW_NULL_AUTHTOK = constants::PAM_DISALLOW_NULL_AUTHTOK; 166 const DISALLOW_NULL_AUTHTOK = pam_constants::PAM_DISALLOW_NULL_AUTHTOK;
41 } 167 }
42 } 168 }
43 169
44 pam_flags! { 170 pam_flags! {
45 /// Flags for changing the authentication token. 171 /// Flags for changing the authentication token.
46 AuthtokFlags { 172 AuthtokFlags {
47 /// Indicates that the user's authentication token should 173 /// Indicates that the user's authentication token should
48 /// only be changed if it is expired. If not passed, 174 /// only be changed if it is expired. If not passed,
49 /// the authentication token should be changed unconditionally. 175 /// the authentication token should be changed unconditionally.
50 const CHANGE_EXPIRED_AUTHTOK = constants::PAM_CHANGE_EXPIRED_AUTHTOK; 176 const CHANGE_EXPIRED_AUTHTOK = pam_constants::PAM_CHANGE_EXPIRED_AUTHTOK;
51 177
52 /// Don't check if the password is any good (Sun only). 178 /// Don't check if the password is any good (Sun only).
53 #[cfg(pam_impl = "Sun")] 179 #[cfg(pam_impl = "Sun")]
54 const NO_AUTHTOK_CHECK = constants::PAM_NO_AUTHTOK_CHECK; 180 const NO_AUTHTOK_CHECK = pam_constants::PAM_NO_AUTHTOK_CHECK;
55 } 181 }
56 } 182 }
57 183
58 pam_flags! { 184 pam_flags! {
59 /// Common flag(s) shared by all PAM actions. 185 /// Common flag(s) shared by all PAM actions.
103 229
104 flag_enum! { 230 flag_enum! {
105 /// The credential management action that should take place. 231 /// The credential management action that should take place.
106 CredAction { 232 CredAction {
107 /// Set the user's credentials from this module. Default if unspecified. 233 /// Set the user's credentials from this module. Default if unspecified.
108 Establish = constants::PAM_ESTABLISH_CRED, 234 Establish = pam_constants::PAM_ESTABLISH_CRED,
109 /// Revoke the user's credentials established by this module. 235 /// Revoke the user's credentials established by this module.
110 Delete = constants::PAM_DELETE_CRED, 236 Delete = pam_constants::PAM_DELETE_CRED,
111 /// Fully reinitialize the user's credentials from this module. 237 /// Fully reinitialize the user's credentials from this module.
112 Reinitialize = constants::PAM_REINITIALIZE_CRED, 238 Reinitialize = pam_constants::PAM_REINITIALIZE_CRED,
113 /// Extend the lifetime of the user's credentials from this module. 239 /// Extend the lifetime of the user's credentials from this module.
114 Refresh = constants::PAM_REFRESH_CRED, 240 Refresh = pam_constants::PAM_REFRESH_CRED,
115 } 241 }
116 } 242 }
117 243
118 impl CredAction { 244 impl CredAction {
119 /// Separates this enum from the remaining [`BaseFlags`]. 245 /// Separates this enum from the remaining [`BaseFlags`].
131 257
132 flag_enum! { 258 flag_enum! {
133 AuthtokAction { 259 AuthtokAction {
134 /// This is a preliminary call to check if we're ready to change passwords 260 /// This is a preliminary call to check if we're ready to change passwords
135 /// and that the new password is acceptable. 261 /// and that the new password is acceptable.
136 PreliminaryCheck = constants::PAM_PRELIM_CHECK, 262 PreliminaryCheck = pam_constants::PAM_PRELIM_CHECK,
137 /// You should actually update the password. 263 /// You should actually update the password.
138 Update = constants::PAM_UPDATE_AUTHTOK, 264 Update = pam_constants::PAM_UPDATE_AUTHTOK,
139 } 265 }
140 } 266 }
141 267
142 impl AuthtokAction { 268 impl AuthtokAction {
143 /// Separates this enum from the remaining [`AuthtokFlags`]. 269 /// Separates this enum from the remaining [`AuthtokFlags`].
166 #[allow(non_camel_case_types, dead_code)] 292 #[allow(non_camel_case_types, dead_code)]
167 #[derive(Copy, Clone, Debug, PartialEq, TryFromPrimitive, IntoPrimitive)] 293 #[derive(Copy, Clone, Debug, PartialEq, TryFromPrimitive, IntoPrimitive)]
168 #[non_exhaustive] // C might give us anything! 294 #[non_exhaustive] // C might give us anything!
169 #[repr(i32)] 295 #[repr(i32)]
170 pub enum ErrorCode { 296 pub enum ErrorCode {
171 OpenError = constants::PAM_OPEN_ERR, 297 OpenError = pam_constants::PAM_OPEN_ERR,
172 SymbolError = constants::PAM_SYMBOL_ERR, 298 SymbolError = pam_constants::PAM_SYMBOL_ERR,
173 ServiceError = constants::PAM_SERVICE_ERR, 299 ServiceError = pam_constants::PAM_SERVICE_ERR,
174 SystemError = constants::PAM_SYSTEM_ERR, 300 SystemError = pam_constants::PAM_SYSTEM_ERR,
175 BufferError = constants::PAM_BUF_ERR, 301 BufferError = pam_constants::PAM_BUF_ERR,
176 PermissionDenied = constants::PAM_PERM_DENIED, 302 PermissionDenied = pam_constants::PAM_PERM_DENIED,
177 AuthenticationError = constants::PAM_AUTH_ERR, 303 AuthenticationError = pam_constants::PAM_AUTH_ERR,
178 CredentialsInsufficient = constants::PAM_CRED_INSUFFICIENT, 304 CredentialsInsufficient = pam_constants::PAM_CRED_INSUFFICIENT,
179 AuthInfoUnavailable = constants::PAM_AUTHINFO_UNAVAIL, 305 AuthInfoUnavailable = pam_constants::PAM_AUTHINFO_UNAVAIL,
180 UserUnknown = constants::PAM_USER_UNKNOWN, 306 UserUnknown = pam_constants::PAM_USER_UNKNOWN,
181 MaxTries = constants::PAM_MAXTRIES, 307 MaxTries = pam_constants::PAM_MAXTRIES,
182 NewAuthTokRequired = constants::PAM_NEW_AUTHTOK_REQD, 308 NewAuthTokRequired = pam_constants::PAM_NEW_AUTHTOK_REQD,
183 AccountExpired = constants::PAM_ACCT_EXPIRED, 309 AccountExpired = pam_constants::PAM_ACCT_EXPIRED,
184 SessionError = constants::PAM_SESSION_ERR, 310 SessionError = pam_constants::PAM_SESSION_ERR,
185 CredentialsUnavailable = constants::PAM_CRED_UNAVAIL, 311 CredentialsUnavailable = pam_constants::PAM_CRED_UNAVAIL,
186 CredentialsExpired = constants::PAM_CRED_EXPIRED, 312 CredentialsExpired = pam_constants::PAM_CRED_EXPIRED,
187 CredentialsError = constants::PAM_CRED_ERR, 313 CredentialsError = pam_constants::PAM_CRED_ERR,
188 NoModuleData = constants::PAM_NO_MODULE_DATA, 314 NoModuleData = pam_constants::PAM_NO_MODULE_DATA,
189 ConversationError = constants::PAM_CONV_ERR, 315 ConversationError = pam_constants::PAM_CONV_ERR,
190 AuthTokError = constants::PAM_AUTHTOK_ERR, 316 AuthTokError = pam_constants::PAM_AUTHTOK_ERR,
191 AuthTokRecoveryError = constants::PAM_AUTHTOK_RECOVERY_ERR, 317 AuthTokRecoveryError = pam_constants::PAM_AUTHTOK_RECOVERY_ERR,
192 AuthTokLockBusy = constants::PAM_AUTHTOK_LOCK_BUSY, 318 AuthTokLockBusy = pam_constants::PAM_AUTHTOK_LOCK_BUSY,
193 AuthTokDisableAging = constants::PAM_AUTHTOK_DISABLE_AGING, 319 AuthTokDisableAging = pam_constants::PAM_AUTHTOK_DISABLE_AGING,
194 TryAgain = constants::PAM_TRY_AGAIN, 320 TryAgain = pam_constants::PAM_TRY_AGAIN,
195 Ignore = constants::PAM_IGNORE, 321 Ignore = pam_constants::PAM_IGNORE,
196 Abort = constants::PAM_ABORT, 322 Abort = pam_constants::PAM_ABORT,
197 AuthTokExpired = constants::PAM_AUTHTOK_EXPIRED, 323 AuthTokExpired = pam_constants::PAM_AUTHTOK_EXPIRED,
198 #[cfg(feature = "basic-ext")] 324 #[cfg(feature = "basic-ext")]
199 ModuleUnknown = constants::PAM_MODULE_UNKNOWN, 325 ModuleUnknown = pam_constants::PAM_MODULE_UNKNOWN,
200 #[cfg(feature = "basic-ext")] 326 #[cfg(feature = "basic-ext")]
201 BadItem = constants::PAM_BAD_ITEM, 327 BadItem = pam_constants::PAM_BAD_ITEM,
202 #[cfg(feature = "linux-pam-ext")] 328 #[cfg(feature = "linux-pam-ext")]
203 ConversationAgain = constants::PAM_CONV_AGAIN, 329 ConversationAgain = pam_constants::PAM_CONV_AGAIN,
204 #[cfg(feature = "linux-pam-ext")] 330 #[cfg(feature = "linux-pam-ext")]
205 Incomplete = constants::PAM_INCOMPLETE, 331 Incomplete = pam_constants::PAM_INCOMPLETE,
206 #[cfg(feature = "openpam-ext")] 332 #[cfg(feature = "openpam-ext")]
207 DomainUnknown = constants::PAM_DOMAIN_UNKNOWN, 333 DomainUnknown = pam_constants::PAM_DOMAIN_UNKNOWN,
208 #[cfg(feature = "openpam-ext")] 334 #[cfg(feature = "openpam-ext")]
209 BadHandle = constants::PAM_BAD_HANDLE, 335 BadHandle = pam_constants::PAM_BAD_HANDLE,
210 #[cfg(feature = "openpam-ext")] 336 #[cfg(feature = "openpam-ext")]
211 BadFeature = constants::PAM_BAD_FEATURE, 337 BadFeature = pam_constants::PAM_BAD_FEATURE,
212 #[cfg(feature = "openpam-ext")] 338 #[cfg(feature = "openpam-ext")]
213 BadConstant = constants::PAM_BAD_CONSTANT, 339 BadConstant = pam_constants::PAM_BAD_CONSTANT,
214 } 340 }
215 341
216 /// A PAM-specific Result type with an [ErrorCode] error. 342 /// A PAM-specific Result type with an [ErrorCode] error.
217 pub type Result<T> = StdResult<T, ErrorCode>; 343 pub type Result<T> = StdResult<T, ErrorCode>;
218 344
278 404
279 #[test] 405 #[test]
280 fn test_enums() { 406 fn test_enums() {
281 assert_eq!(Ok(()), ErrorCode::result_from(0)); 407 assert_eq!(Ok(()), ErrorCode::result_from(0));
282 assert_eq!( 408 assert_eq!(
283 constants::PAM_SESSION_ERR, 409 pam_constants::PAM_SESSION_ERR,
284 ErrorCode::result_to_c::<()>(Err(ErrorCode::SessionError)) 410 ErrorCode::result_to_c::<()>(Err(ErrorCode::SessionError))
285 ); 411 );
286 assert_eq!( 412 assert_eq!(
287 Err(ErrorCode::Abort), 413 Err(ErrorCode::Abort),
288 ErrorCode::result_from(constants::PAM_ABORT) 414 ErrorCode::result_from(pam_constants::PAM_ABORT)
289 ); 415 );
290 assert_eq!(Err(ErrorCode::SystemError), ErrorCode::result_from(423)); 416 assert_eq!(Err(ErrorCode::SystemError), ErrorCode::result_from(423));
291 } 417 }
292 418
293 #[test] 419 #[test]
295 AuthtokAction::extract(-1).expect_err("too many set"); 421 AuthtokAction::extract(-1).expect_err("too many set");
296 AuthtokAction::extract(0).expect_err("too few set"); 422 AuthtokAction::extract(0).expect_err("too few set");
297 assert_eq!( 423 assert_eq!(
298 Ok(( 424 Ok((
299 AuthtokAction::Update, 425 AuthtokAction::Update,
300 AuthtokFlags::from_bits_retain(0x7fff0000) 426 AuthtokFlags::from_bits_retain(0x7f000000)
301 )), 427 )),
302 AuthtokAction::extract(0x7fff0000 | constants::PAM_UPDATE_AUTHTOK) 428 AuthtokAction::extract(0x7f000000 | pam_constants::PAM_UPDATE_AUTHTOK)
303 ); 429 );
304 CredAction::extract(0xffff).expect_err("too many set"); 430 CredAction::extract(0xffff).expect_err("too many set");
305 assert_eq!( 431 assert_eq!(
306 Ok((CredAction::Establish, BaseFlags::empty())), 432 Ok((CredAction::Establish, BaseFlags::empty())),
307 CredAction::extract(0) 433 CredAction::extract(0)
308 ); 434 );
309 assert_eq!( 435 assert_eq!(
310 Ok((CredAction::Delete, BaseFlags::from_bits_retain(0x55000000))), 436 Ok((CredAction::Delete, BaseFlags::from_bits_retain(0x55000000))),
311 CredAction::extract(0x55000000 | constants::PAM_DELETE_CRED) 437 CredAction::extract(0x55000000 | pam_constants::PAM_DELETE_CRED)
312 ); 438 );
313 } 439 }
314 } 440 }