Mercurial > crates > nonstick
comparison src/constants.rs @ 60:05cc2c27334f
The Big Refactor: clean up docs and exports.
- Brings the most important symbols in the library to the root
with `pub use` statements.
- Expands and updates documentation.
- Rearranges things extensively to make the external interface nicer
and make the structure easier to understand.
- Renames a few things (e.g. `Result`).
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Wed, 21 May 2025 19:00:51 -0400 |
parents | 3f4a77aa88be |
children | a7aa5ca0d00d |
comparison
equal
deleted
inserted
replaced
59:3f4a77aa88be | 60:05cc2c27334f |
---|---|
1 //! Constants and enum values from the PAM library. | |
2 | |
1 use bitflags::bitflags; | 3 use bitflags::bitflags; |
2 use libc::{c_int, c_uint}; | 4 use libc::{c_int, c_uint}; |
3 use num_derive::FromPrimitive; | 5 use num_derive::FromPrimitive; |
4 use num_traits::FromPrimitive; | 6 use num_traits::FromPrimitive; |
5 use std::any; | 7 use std::any; |
6 use std::marker::PhantomData; | 8 use std::marker::PhantomData; |
7 // TODO: Import constants from C header file at compile time. | 9 |
8 | |
9 // The Linux-PAM flags | |
10 // see /usr/include/security/_pam_types.h | |
11 bitflags! { | 10 bitflags! { |
11 /// The available PAM flags. | |
12 /// | |
13 /// See `/usr/include/security/_pam_types.h` for more details. | |
12 #[derive(Debug, PartialEq)] | 14 #[derive(Debug, PartialEq)] |
13 #[repr(transparent)] | 15 #[repr(transparent)] |
14 pub struct Flags: c_uint { | 16 pub struct Flags: c_uint { |
17 /// Authentication service should not generate any messages. | |
15 const SILENT = 0x8000; | 18 const SILENT = 0x8000; |
19 /// The service should return [ErrorCode::AuthError] if the user | |
20 /// has a null authentication token. | |
16 const DISALLOW_NULL_AUTHTOK = 0x0001; | 21 const DISALLOW_NULL_AUTHTOK = 0x0001; |
22 /// Set user credentials for an authentication service. | |
17 const ESTABLISH_CRED = 0x0002; | 23 const ESTABLISH_CRED = 0x0002; |
24 /// Delete user credentials associated with | |
25 /// an authentication service. | |
18 const DELETE_CRED = 0x0004; | 26 const DELETE_CRED = 0x0004; |
27 /// Reinitialize user credentials. | |
19 const REINITIALIZE_CRED = 0x0008; | 28 const REINITIALIZE_CRED = 0x0008; |
29 /// Extend the lifetime of user credentials. | |
20 const REFRESH_CRED = 0x0010; | 30 const REFRESH_CRED = 0x0010; |
21 const CHANGE_EXPIRED_AUTHTOK= 0x0020; | 31 /// The password service should only update those passwords |
32 /// that have aged. If this flag is _not_ passed, | |
33 /// the password service should update all passwords. | |
34 const CHANGE_EXPIRED_AUTHTOK = 0x0020; | |
22 } | 35 } |
23 } | 36 } |
24 | 37 |
25 /// Styles of message that are shown to the user. | 38 /// Styles of message that are shown to the user. |
26 #[derive(Debug, PartialEq, FromPrimitive)] | 39 #[derive(Debug, PartialEq, FromPrimitive)] |
41 BinaryPrompt = 7, | 54 BinaryPrompt = 7, |
42 } | 55 } |
43 | 56 |
44 impl TryFrom<c_int> for MessageStyle { | 57 impl TryFrom<c_int> for MessageStyle { |
45 type Error = InvalidEnum<Self>; | 58 type Error = InvalidEnum<Self>; |
46 fn try_from(value: c_int) -> Result<Self, Self::Error> { | 59 fn try_from(value: c_int) -> std::result::Result<Self, Self::Error> { |
47 Self::from_i32(value).ok_or(value.into()) | 60 Self::from_i32(value).ok_or(value.into()) |
48 } | 61 } |
49 } | 62 } |
50 | 63 |
51 impl From<MessageStyle> for c_int { | 64 impl From<MessageStyle> for c_int { |
52 fn from(val: MessageStyle) -> Self { | 65 fn from(val: MessageStyle) -> Self { |
53 val as Self | 66 val as Self |
54 } | 67 } |
55 } | 68 } |
56 | 69 |
57 /// The Linux-PAM error return values. | 70 /// The Linux-PAM error return values. Success is an Ok [Result]. |
58 /// Success is instead represented by the `Ok` entry of a `Result`. | 71 /// |
59 /// Most abbreviations (except `AuthTok` and `Max`) are now full words. | 72 /// Most abbreviations (except `AuthTok` and `Max`) are now full words. |
60 /// For more detailed information, see | 73 /// For more detailed information, see |
61 /// `/usr/include/security/_pam_types.h`. | 74 /// `/usr/include/security/_pam_types.h`. |
62 #[allow(non_camel_case_types, dead_code)] | 75 #[allow(non_camel_case_types, dead_code)] |
63 #[derive(Copy, Clone, Debug, PartialEq, thiserror::Error, FromPrimitive)] | 76 #[derive(Copy, Clone, Debug, PartialEq, thiserror::Error, FromPrimitive)] |
125 ConversationAgain = 30, | 138 ConversationAgain = 30, |
126 #[error("call this function again to complete authentication stack")] | 139 #[error("call this function again to complete authentication stack")] |
127 Incomplete = 31, | 140 Incomplete = 31, |
128 } | 141 } |
129 | 142 |
130 pub type PamResult<T> = Result<T, ErrorCode>; | 143 /// A PAM-specific Result type with an [ErrorCode] error. |
144 pub type Result<T> = std::result::Result<T, ErrorCode>; | |
145 | |
131 impl ErrorCode { | 146 impl ErrorCode { |
132 /// Converts a PamResult into the result code that C wants. | 147 /// Converts this [Result] into a C-compatible result code. |
133 pub fn result_to_c(value: PamResult<()>) -> c_int { | 148 pub fn result_to_c<T>(value: Result<T>) -> c_int { |
134 match value { | 149 match value { |
135 Ok(_) => 0, // PAM_SUCCESS | 150 Ok(_) => 0, // PAM_SUCCESS |
136 Err(otherwise) => otherwise.into(), | 151 Err(otherwise) => otherwise.into(), |
137 } | 152 } |
138 } | 153 } |
139 | 154 |
140 /// Converts a C result code into a PamResult, with success as Ok. | 155 /// Converts a C result code into a [Result], with success as Ok. |
141 /// Invalid values are returned as a [Self::SystemError]. | 156 /// Invalid values are returned as a [Self::SystemError]. |
142 pub fn result_from(value: c_int) -> PamResult<()> { | 157 pub fn result_from(value: c_int) -> Result<()> { |
143 match value { | 158 match value { |
144 0 => Ok(()), | 159 0 => Ok(()), |
145 value => Err(value.try_into().unwrap_or(Self::SystemError)), | 160 value => Err(value.try_into().unwrap_or(Self::SystemError)), |
146 } | 161 } |
147 } | 162 } |
148 } | 163 } |
149 | 164 |
150 impl TryFrom<c_int> for ErrorCode { | 165 impl TryFrom<c_int> for ErrorCode { |
151 type Error = InvalidEnum<Self>; | 166 type Error = InvalidEnum<Self>; |
152 | 167 |
153 fn try_from(value: c_int) -> Result<Self, Self::Error> { | 168 fn try_from(value: c_int) -> std::result::Result<Self, Self::Error> { |
154 Self::from_i32(value).ok_or(value.into()) | 169 Self::from_i32(value).ok_or(value.into()) |
155 } | 170 } |
156 } | 171 } |
157 | 172 |
158 impl From<ErrorCode> for c_int { | 173 impl From<ErrorCode> for c_int { |
161 } | 176 } |
162 } | 177 } |
163 | 178 |
164 /// Error returned when attempting to coerce an invalid C integer into an enum. | 179 /// Error returned when attempting to coerce an invalid C integer into an enum. |
165 #[derive(thiserror::Error)] | 180 #[derive(thiserror::Error)] |
166 #[error("{} is not a valid {}", .0, any::type_name::<T>())] | 181 #[error("{0} is not a valid {type}", type = any::type_name::<T>())] |
167 #[derive(Debug, PartialEq)] | 182 #[derive(Debug, PartialEq)] |
168 pub struct InvalidEnum<T>(std::ffi::c_int, PhantomData<T>); | 183 pub struct InvalidEnum<T>(c_int, PhantomData<T>); |
169 | 184 |
170 impl<T> From<std::ffi::c_int> for InvalidEnum<T> { | 185 impl<T> From<InvalidEnum<T>> for c_int { |
171 fn from(value: std::ffi::c_int) -> Self { | 186 fn from(value: InvalidEnum<T>) -> Self { |
187 value.0 | |
188 } | |
189 } | |
190 | |
191 impl<T> From<c_int> for InvalidEnum<T> { | |
192 fn from(value: c_int) -> Self { | |
172 Self(value, PhantomData) | 193 Self(value, PhantomData) |
173 } | 194 } |
174 } | 195 } |
175 | 196 |
176 #[cfg(test)] | 197 #[cfg(test)] |
178 use super::*; | 199 use super::*; |
179 | 200 |
180 #[test] | 201 #[test] |
181 fn test_enums() { | 202 fn test_enums() { |
182 assert_eq!(Ok(MessageStyle::ErrorMsg), 3.try_into()); | 203 assert_eq!(Ok(MessageStyle::ErrorMsg), 3.try_into()); |
183 assert_eq!(Err(999.into()), ErrorCode::try_from(999)); | 204 assert_eq!(Err(InvalidEnum::from(999)), ErrorCode::try_from(999)); |
184 assert_eq!(Ok(()), ErrorCode::result_from(0)); | 205 assert_eq!(Ok(()), ErrorCode::result_from(0)); |
185 assert_eq!(Err(ErrorCode::Abort), ErrorCode::result_from(26)); | 206 assert_eq!(Err(ErrorCode::Abort), ErrorCode::result_from(26)); |
186 assert_eq!(Err(ErrorCode::SystemError), ErrorCode::result_from(423)); | 207 assert_eq!(Err(ErrorCode::SystemError), ErrorCode::result_from(423)); |
187 } | 208 assert!(InvalidEnum::<MessageStyle>(33, PhantomData) |
188 } | 209 .to_string() |
210 .starts_with("33 is not a valid ")); | |
211 } | |
212 } |