Mercurial > crates > nonstick
comparison src/constants.rs @ 90:f6186e41399b
Miscellaneous fixes and cleanup:
- Rename `get_user` to `username` and `get_authtok` to `authtok`.
- Use pam_strerror for error messages.
- Add library linkage to build.rs (it was missing???).
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Sat, 14 Jun 2025 09:30:16 -0400 |
| parents | 05291b601f0a |
| children | 5ddbcada30f2 |
comparison
equal
deleted
inserted
replaced
| 89:dd3e9c4bcde3 | 90:f6186e41399b |
|---|---|
| 7 #[cfg(feature = "link")] | 7 #[cfg(feature = "link")] |
| 8 use crate::libpam::pam_ffi; | 8 use crate::libpam::pam_ffi; |
| 9 use bitflags::bitflags; | 9 use bitflags::bitflags; |
| 10 use libc::c_int; | 10 use libc::c_int; |
| 11 use num_enum::{IntoPrimitive, TryFromPrimitive}; | 11 use num_enum::{IntoPrimitive, TryFromPrimitive}; |
| 12 use std::error::Error; | |
| 12 use std::ffi::c_uint; | 13 use std::ffi::c_uint; |
| 14 use std::fmt; | |
| 15 use std::fmt::{Display, Formatter}; | |
| 13 use std::result::Result as StdResult; | 16 use std::result::Result as StdResult; |
| 14 | 17 |
| 15 /// Arbitrary values for PAM constants when not linking against system PAM. | 18 /// Arbitrary values for PAM constants when not linking against system PAM. |
| 16 /// | 19 /// |
| 17 /// **The values of these constants are deliberately selected _not_ to match | 20 /// **The values of these constants are deliberately selected _not_ to match |
| 75 PAM_SYMBOL_ERR = 550, | 78 PAM_SYMBOL_ERR = 550, |
| 76 PAM_SYSTEM_ERR = 551, | 79 PAM_SYSTEM_ERR = 551, |
| 77 PAM_TRY_AGAIN = 552, | 80 PAM_TRY_AGAIN = 552, |
| 78 PAM_USER_UNKNOWN = 553 | 81 PAM_USER_UNKNOWN = 553 |
| 79 ); | 82 ); |
| 83 | |
| 84 fn strerror(val: c_uint) -> Option<&'static str> { | |
| 85 None | |
| 86 } | |
| 80 } | 87 } |
| 81 | 88 |
| 82 bitflags! { | 89 bitflags! { |
| 83 /// The available PAM flags. | 90 /// The available PAM flags. |
| 84 /// | 91 /// |
| 138 /// | 145 /// |
| 139 /// Most abbreviations (except `AuthTok` and `Max`) are now full words. | 146 /// Most abbreviations (except `AuthTok` and `Max`) are now full words. |
| 140 /// For more detailed information, see | 147 /// For more detailed information, see |
| 141 /// `/usr/include/security/_pam_types.h`. | 148 /// `/usr/include/security/_pam_types.h`. |
| 142 #[allow(non_camel_case_types, dead_code)] | 149 #[allow(non_camel_case_types, dead_code)] |
| 143 #[derive(Copy, Clone, Debug, PartialEq, thiserror::Error, TryFromPrimitive, IntoPrimitive)] | 150 #[derive(Copy, Clone, Debug, PartialEq, TryFromPrimitive, IntoPrimitive)] |
| 144 #[non_exhaustive] // C might give us anything! | 151 #[non_exhaustive] // C might give us anything! |
| 145 #[repr(u32)] | 152 #[repr(u32)] |
| 146 pub enum ErrorCode { | 153 pub enum ErrorCode { |
| 147 #[error("dlopen() failure when dynamically loading a service module")] | |
| 148 OpenError = pam_ffi::PAM_OPEN_ERR, | 154 OpenError = pam_ffi::PAM_OPEN_ERR, |
| 149 #[error("symbol not found")] | |
| 150 SymbolError = pam_ffi::PAM_SYMBOL_ERR, | 155 SymbolError = pam_ffi::PAM_SYMBOL_ERR, |
| 151 #[error("error in service module")] | |
| 152 ServiceError = pam_ffi::PAM_SERVICE_ERR, | 156 ServiceError = pam_ffi::PAM_SERVICE_ERR, |
| 153 #[error("system error")] | |
| 154 SystemError = pam_ffi::PAM_SYSTEM_ERR, | 157 SystemError = pam_ffi::PAM_SYSTEM_ERR, |
| 155 #[error("memory buffer error")] | |
| 156 BufferError = pam_ffi::PAM_BUF_ERR, | 158 BufferError = pam_ffi::PAM_BUF_ERR, |
| 157 #[error("permission denied")] | |
| 158 PermissionDenied = pam_ffi::PAM_PERM_DENIED, | 159 PermissionDenied = pam_ffi::PAM_PERM_DENIED, |
| 159 #[error("authentication failure")] | |
| 160 AuthenticationError = pam_ffi::PAM_AUTH_ERR, | 160 AuthenticationError = pam_ffi::PAM_AUTH_ERR, |
| 161 #[error("cannot access authentication data due to insufficient credentials")] | |
| 162 CredentialsInsufficient = pam_ffi::PAM_CRED_INSUFFICIENT, | 161 CredentialsInsufficient = pam_ffi::PAM_CRED_INSUFFICIENT, |
| 163 #[error("underlying authentication service cannot retrieve authentication information")] | |
| 164 AuthInfoUnavailable = pam_ffi::PAM_AUTHINFO_UNAVAIL, | 162 AuthInfoUnavailable = pam_ffi::PAM_AUTHINFO_UNAVAIL, |
| 165 #[error("user not known to the underlying authentication module")] | |
| 166 UserUnknown = pam_ffi::PAM_USER_UNKNOWN, | 163 UserUnknown = pam_ffi::PAM_USER_UNKNOWN, |
| 167 #[error("retry limit reached; do not attempt further")] | |
| 168 MaxTries = pam_ffi::PAM_MAXTRIES, | 164 MaxTries = pam_ffi::PAM_MAXTRIES, |
| 169 #[error("new authentication token required")] | |
| 170 NewAuthTokRequired = pam_ffi::PAM_NEW_AUTHTOK_REQD, | 165 NewAuthTokRequired = pam_ffi::PAM_NEW_AUTHTOK_REQD, |
| 171 #[error("user account has expired")] | |
| 172 AccountExpired = pam_ffi::PAM_ACCT_EXPIRED, | 166 AccountExpired = pam_ffi::PAM_ACCT_EXPIRED, |
| 173 #[error("cannot make/remove an entry for the specified session")] | |
| 174 SessionError = pam_ffi::PAM_SESSION_ERR, | 167 SessionError = pam_ffi::PAM_SESSION_ERR, |
| 175 #[error("underlying authentication service cannot retrieve user credentials")] | |
| 176 CredentialsUnavailable = pam_ffi::PAM_CRED_UNAVAIL, | 168 CredentialsUnavailable = pam_ffi::PAM_CRED_UNAVAIL, |
| 177 #[error("user credentials expired")] | |
| 178 CredentialsExpired = pam_ffi::PAM_CRED_EXPIRED, | 169 CredentialsExpired = pam_ffi::PAM_CRED_EXPIRED, |
| 179 #[error("failure setting user credentials")] | |
| 180 CredentialsError = pam_ffi::PAM_CRED_ERR, | 170 CredentialsError = pam_ffi::PAM_CRED_ERR, |
| 181 #[error("no module-specific data is present")] | |
| 182 NoModuleData = pam_ffi::PAM_NO_MODULE_DATA, | 171 NoModuleData = pam_ffi::PAM_NO_MODULE_DATA, |
| 183 #[error("conversation error")] | |
| 184 ConversationError = pam_ffi::PAM_CONV_ERR, | 172 ConversationError = pam_ffi::PAM_CONV_ERR, |
| 185 #[error("authentication token manipulation error")] | |
| 186 AuthTokError = pam_ffi::PAM_AUTHTOK_ERR, | 173 AuthTokError = pam_ffi::PAM_AUTHTOK_ERR, |
| 187 #[error("authentication information cannot be recovered")] | |
| 188 AuthTokRecoveryError = pam_ffi::PAM_AUTHTOK_RECOVERY_ERR, | 174 AuthTokRecoveryError = pam_ffi::PAM_AUTHTOK_RECOVERY_ERR, |
| 189 #[error("authentication token lock busy")] | |
| 190 AuthTokLockBusy = pam_ffi::PAM_AUTHTOK_LOCK_BUSY, | 175 AuthTokLockBusy = pam_ffi::PAM_AUTHTOK_LOCK_BUSY, |
| 191 #[error("authentication token aging disabled")] | |
| 192 AuthTokDisableAging = pam_ffi::PAM_AUTHTOK_DISABLE_AGING, | 176 AuthTokDisableAging = pam_ffi::PAM_AUTHTOK_DISABLE_AGING, |
| 193 #[error("preliminary password check failed")] | |
| 194 TryAgain = pam_ffi::PAM_TRY_AGAIN, | 177 TryAgain = pam_ffi::PAM_TRY_AGAIN, |
| 195 #[error("ignore underlying account module, regardless of control flag")] | |
| 196 Ignore = pam_ffi::PAM_IGNORE, | 178 Ignore = pam_ffi::PAM_IGNORE, |
| 197 #[error("critical error; this module should fail now")] | |
| 198 Abort = pam_ffi::PAM_ABORT, | 179 Abort = pam_ffi::PAM_ABORT, |
| 199 #[error("authentication token has expired")] | |
| 200 AuthTokExpired = pam_ffi::PAM_AUTHTOK_EXPIRED, | 180 AuthTokExpired = pam_ffi::PAM_AUTHTOK_EXPIRED, |
| 201 #[error("module is not known")] | |
| 202 ModuleUnknown = pam_ffi::PAM_MODULE_UNKNOWN, | 181 ModuleUnknown = pam_ffi::PAM_MODULE_UNKNOWN, |
| 203 #[error("bad item passed to pam_[whatever]_item")] | |
| 204 BadItem = pam_ffi::PAM_BAD_ITEM, | 182 BadItem = pam_ffi::PAM_BAD_ITEM, |
| 205 #[cfg(feature = "linux-pam-extensions")] | 183 #[cfg(feature = "linux-pam-extensions")] |
| 206 #[error("conversation function is event-driven and data is not available yet")] | |
| 207 ConversationAgain = pam_ffi::PAM_CONV_AGAIN, | 184 ConversationAgain = pam_ffi::PAM_CONV_AGAIN, |
| 208 #[cfg(feature = "linux-pam-extensions")] | 185 #[cfg(feature = "linux-pam-extensions")] |
| 209 #[error("call this function again to complete authentication stack")] | |
| 210 Incomplete = pam_ffi::PAM_INCOMPLETE, | 186 Incomplete = pam_ffi::PAM_INCOMPLETE, |
| 211 } | 187 } |
| 212 | 188 |
| 213 /// A PAM-specific Result type with an [ErrorCode] error. | 189 /// A PAM-specific Result type with an [ErrorCode] error. |
| 214 pub type Result<T> = StdResult<T, ErrorCode>; | 190 pub type Result<T> = StdResult<T, ErrorCode>; |
| 191 | |
| 192 impl Display for ErrorCode { | |
| 193 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | |
| 194 match pam_ffi::strerror((*self).into()) { | |
| 195 Some(err) => f.write_str(err), | |
| 196 None => self.fmt_internal(f), | |
| 197 } | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 impl Error for ErrorCode {} | |
| 215 | 202 |
| 216 impl ErrorCode { | 203 impl ErrorCode { |
| 217 /// Converts this [Result] into a C-compatible result code. | 204 /// Converts this [Result] into a C-compatible result code. |
| 218 pub fn result_to_c<T>(value: Result<T>) -> c_int { | 205 pub fn result_to_c<T>(value: Result<T>) -> c_int { |
| 219 match value { | 206 match value { |
| 227 pub fn result_from(value: c_int) -> Result<()> { | 214 pub fn result_from(value: c_int) -> Result<()> { |
| 228 match value { | 215 match value { |
| 229 0 => Ok(()), | 216 0 => Ok(()), |
| 230 value => Err((value as u32).try_into().unwrap_or(Self::SystemError)), | 217 value => Err((value as u32).try_into().unwrap_or(Self::SystemError)), |
| 231 } | 218 } |
| 219 } | |
| 220 | |
| 221 /// A basic Display implementation for if we don't link against PAM. | |
| 222 fn fmt_internal(self, f: &mut Formatter<'_>) -> fmt::Result { | |
| 223 write!(f, "PAM error: {self:?} ({n})", n = self as c_uint) | |
| 232 } | 224 } |
| 233 } | 225 } |
| 234 | 226 |
| 235 /// Returned when text that should not have any `\0` bytes in it does. | 227 /// Returned when text that should not have any `\0` bytes in it does. |
| 236 /// Analogous to [`std::ffi::NulError`], but the data it was created from | 228 /// Analogous to [`std::ffi::NulError`], but the data it was created from |
