Mercurial > crates > nonstick
comparison src/module.rs @ 64:bbe84835d6db v0.0.5
More organization; add lots of docs.
- moves `PamHandle` to its own module, since it will be used
by both modules and clients.
- adds a ton of documentation to the `PamModule` trait
and reorders methods to most-interesting-first.
- adds more flag values from pam_modules.h.
- other misc cleanup.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Thu, 22 May 2025 01:52:32 -0400 |
parents | 05cc2c27334f |
children |
comparison
equal
deleted
inserted
replaced
63:a7aa5ca0d00d | 64:bbe84835d6db |
---|---|
1 //! Functions and types useful for implementing a PAM module. | 1 //! Functions and types useful for implementing a PAM module. |
2 | 2 |
3 use crate::constants::{ErrorCode, Flags, Result}; | 3 use crate::constants::{ErrorCode, Flags, Result}; |
4 use crate::items::{Item, ItemType}; | 4 use crate::handle::PamHandle; |
5 use crate::memory; | 5 use std::ffi::CStr; |
6 use libc::c_char; | 6 |
7 use secure_string::SecureString; | 7 /// A trait for a PAM module to implement. |
8 use std::ffi::{c_int, CStr, CString}; | 8 /// |
9 | 9 /// The default implementations of all these hooks tell PAM to ignore them |
10 use crate::pam_ffi; | 10 /// (i.e., behave as if this module does not exist) by returning [`ErrorCode::Ignore`]. |
11 | 11 /// Override any functions you wish to handle in your module. |
12 /// Function called at the end of a PAM session that is called to clean up | 12 /// After implementing this trait, use the [`pam_hooks!`](crate::pam_hooks!) macro |
13 /// a value previously provided to PAM in a `pam_set_data` call. | 13 /// to make the functions available to PAM. |
14 /// | |
15 /// You should never call this yourself. | |
16 extern "C" fn cleanup<T>(_: *const libc::c_void, c_data: *mut libc::c_void, _: c_int) { | |
17 unsafe { | |
18 let _data: Box<T> = Box::from_raw(c_data.cast()); | |
19 } | |
20 } | |
21 | |
22 /// An opaque structure pointing to a PAM handle. | |
23 #[repr(transparent)] | |
24 pub struct PamHandle(*mut libc::c_void); | |
25 | |
26 impl PamHandle { | |
27 /// Gets some value, identified by `key`, that has been set by the module | |
28 /// previously. | |
29 /// | |
30 /// See the [`pam_get_data` manual page]( | |
31 /// https://www.man7.org/linux/man-pages/man3/pam_get_data.3.html). | |
32 /// | |
33 /// # Safety | |
34 /// | |
35 /// The data stored under the provided key must be of type `T` otherwise the | |
36 /// behaviour of this function is undefined. | |
37 /// | |
38 /// The data, if present, is owned by the current PAM conversation. | |
39 pub unsafe fn get_data<T>(&self, key: &str) -> Result<Option<&T>> { | |
40 let c_key = CString::new(key).map_err(|_| ErrorCode::ConversationError)?; | |
41 let mut ptr: *const libc::c_void = std::ptr::null(); | |
42 ErrorCode::result_from(pam_ffi::pam_get_data(self.0, c_key.as_ptr(), &mut ptr))?; | |
43 match ptr.is_null() { | |
44 true => Ok(None), | |
45 false => { | |
46 let typed_ptr = ptr.cast(); | |
47 Ok(Some(&*typed_ptr)) | |
48 } | |
49 } | |
50 } | |
51 | |
52 /// Stores a value that can be retrieved later with `get_data`. | |
53 /// The conversation takes ownership of the data. | |
54 /// | |
55 /// See the [`pam_set_data` manual page]( | |
56 /// https://www.man7.org/linux/man-pages/man3/pam_set_data.3.html). | |
57 pub fn set_data<T>(&mut self, key: &str, data: Box<T>) -> Result<()> { | |
58 let c_key = CString::new(key).map_err(|_| ErrorCode::ConversationError)?; | |
59 let ret = unsafe { | |
60 pam_ffi::pam_set_data( | |
61 self.0, | |
62 c_key.as_ptr(), | |
63 Box::into_raw(data).cast(), | |
64 cleanup::<T>, | |
65 ) | |
66 }; | |
67 ErrorCode::result_from(ret) | |
68 } | |
69 | |
70 /// Retrieves a value that has been set, possibly by the pam client. | |
71 /// This is particularly useful for getting a `PamConv` reference. | |
72 /// | |
73 /// These items are *references to PAM memory* | |
74 /// which are *owned by the conversation*. | |
75 /// | |
76 /// See the [`pam_get_item` manual page]( | |
77 /// https://www.man7.org/linux/man-pages/man3/pam_get_item.3.html). | |
78 pub fn get_item<T: crate::items::Item>(&self) -> Result<Option<T>> { | |
79 let mut ptr: *const libc::c_void = std::ptr::null(); | |
80 let out = unsafe { | |
81 let ret = pam_ffi::pam_get_item(self.0, T::type_id().into(), &mut ptr); | |
82 ErrorCode::result_from(ret)?; | |
83 let typed_ptr: *const T::Raw = ptr.cast(); | |
84 match typed_ptr.is_null() { | |
85 true => None, | |
86 false => Some(T::from_raw(typed_ptr)), | |
87 } | |
88 }; | |
89 Ok(out) | |
90 } | |
91 | |
92 /// Sets an item in the pam context. It can be retrieved using `get_item`. | |
93 /// | |
94 /// See the [`pam_set_item` manual page]( | |
95 /// https://www.man7.org/linux/man-pages/man3/pam_set_item.3.html). | |
96 pub fn set_item<T: Item>(&mut self, item: T) -> Result<()> { | |
97 let ret = | |
98 unsafe { pam_ffi::pam_set_item(self.0, T::type_id().into(), item.into_raw().cast()) }; | |
99 ErrorCode::result_from(ret) | |
100 } | |
101 | |
102 /// Retrieves the name of the user who is authenticating or logging in. | |
103 /// | |
104 /// This is really a specialization of `get_item`. | |
105 /// | |
106 /// See the [`pam_get_user` manual page]( | |
107 /// https://www.man7.org/linux/man-pages/man3/pam_get_user.3.html). | |
108 pub fn get_user(&self, prompt: Option<&str>) -> Result<String> { | |
109 let prompt = memory::option_cstr(prompt)?; | |
110 let mut output: *const c_char = std::ptr::null_mut(); | |
111 let ret = unsafe { | |
112 pam_ffi::pam_get_user(self.0, &mut output, memory::prompt_ptr(prompt.as_ref())) | |
113 }; | |
114 ErrorCode::result_from(ret)?; | |
115 memory::copy_pam_string(output) | |
116 } | |
117 | |
118 /// Retrieves the authentication token from the user. | |
119 /// | |
120 /// This is really a specialization of `get_item`. | |
121 /// | |
122 /// See the [`pam_get_authtok` manual page]( | |
123 /// https://www.man7.org/linux/man-pages/man3/pam_get_authtok.3.html). | |
124 pub fn get_authtok(&self, prompt: Option<&str>) -> Result<SecureString> { | |
125 let prompt = memory::option_cstr(prompt)?; | |
126 let mut output: *const c_char = std::ptr::null_mut(); | |
127 let res = unsafe { | |
128 pam_ffi::pam_get_authtok( | |
129 self.0, | |
130 ItemType::AuthTok.into(), | |
131 &mut output, | |
132 memory::prompt_ptr(prompt.as_ref()), | |
133 ) | |
134 }; | |
135 ErrorCode::result_from(res)?; | |
136 memory::copy_pam_string(output).map(SecureString::from) | |
137 } | |
138 } | |
139 | |
140 impl From<*mut libc::c_void> for PamHandle { | |
141 /// Wraps an internal Handle pointer. | |
142 fn from(value: *mut libc::c_void) -> Self { | |
143 Self(value) | |
144 } | |
145 } | |
146 | |
147 /// Trait representing what a PAM module can do. | |
148 /// | |
149 /// By default, all the functions in this trait are ignored. | |
150 /// Implement any functions you wish to handle in your module. | |
151 /// After implementing this trait, use the [crate::pam_hooks!] macro | |
152 /// to export your functions. | |
153 /// | 14 /// |
154 /// For more information, see [`pam(3)`’s root manual page][manpage] | 15 /// For more information, see [`pam(3)`’s root manual page][manpage] |
155 /// and the [PAM Module Writer’s Guide][module-guide]. | 16 /// and the [PAM Module Writer’s Guide][mwg]. |
156 /// | 17 /// |
157 /// [manpage]: https://www.man7.org/linux/man-pages/man3/pam.3.html | 18 /// [manpage]: https://www.man7.org/linux/man-pages/man3/pam.3.html |
158 /// [module-guide]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/Linux-PAM_MWG.html | 19 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/Linux-PAM_MWG.html |
159 #[allow(unused_variables)] | 20 #[allow(unused_variables)] |
160 pub trait PamModule { | 21 pub trait PamModule { |
161 /// This function performs the task of establishing whether the user is permitted to gain access at | 22 // Functions for auth modules. |
162 /// this time. It should be understood that the user has previously been validated by an | 23 |
163 /// authentication module. This function checks for other things. Such things might be: the time of | 24 /// Authenticate the user. |
164 /// day or the date, the terminal line, remote hostname, etc. This function may also determine | 25 /// |
165 /// things like the expiration on passwords, and respond that the user change it before continuing. | 26 /// This is probably the first thing you want to implement. |
166 fn acct_mgmt(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | 27 /// In most cases, you will want to get the user and password, |
167 Err(ErrorCode::Ignore) | 28 /// using [`PamHandle::get_user`] and [`PamHandle::get_authtok`], |
168 } | 29 /// and verify them against something. |
169 | 30 /// |
170 /// This function performs the task of authenticating the user. | 31 /// See [the Module Writer's Guide entry for `pam_sm_authenticate`][mwg] |
171 fn sm_authenticate(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | 32 /// for more information. |
172 Err(ErrorCode::Ignore) | 33 /// |
173 } | 34 /// # Valid flags |
174 | 35 /// |
175 /// This function is used to (re-)set the authentication token of the user. | 36 /// This function may be called with the following flags set: |
176 /// | 37 /// |
177 /// The PAM library calls this function twice in succession. The first time with | 38 /// - [`Flags::SILENT`] |
178 /// `PAM_PRELIM_CHECK` and then, if the module does not return `PAM_TRY_AGAIN`, subsequently with | 39 /// - [`Flags::DISALLOW_NULL_AUTHTOK`] |
179 /// `PAM_UPDATE_AUTHTOK`. It is only on the second call that the authorization token is | 40 /// |
180 /// (possibly) changed. | 41 /// # Returns |
181 fn sm_chauthtok(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | 42 /// |
182 Err(ErrorCode::Ignore) | 43 /// If the password check was successful, return `Ok(())`. |
183 } | 44 /// |
184 | 45 /// Sensible error codes to return include: |
185 /// This function is called to terminate a session. | 46 /// |
186 fn sm_close_session(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | 47 /// - [`ErrorCode::AuthenticationError`]: Generic authentication error |
187 Err(ErrorCode::Ignore) | 48 /// (like an incorrect password). |
188 } | 49 /// - [`ErrorCode::CredentialsInsufficient`]: The application does not have |
189 | 50 /// sufficient credentials to authenticate the user. |
190 /// This function is called to commence a session. | 51 /// - [`ErrorCode::AuthInfoUnavailable`]: The module was not able to access |
191 fn sm_open_session(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | 52 /// the authentication information, for instance due to a network failure. |
192 Err(ErrorCode::Ignore) | 53 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service. |
193 } | 54 /// - [`ErrorCode::MaxTries`]: The user has tried authenticating too many times. |
194 | 55 /// They should not try again. |
195 /// This function performs the task of altering the credentials of the user with respect to the | 56 /// |
196 /// corresponding authorization scheme. Generally, an authentication module may have access to more | 57 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-auth.html#mwg-pam_sm_authenticate |
197 /// information about a user than their authentication token. This function is used to make such | 58 fn authenticate(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { |
198 /// information available to the application. It should only be called after the user has been | 59 Err(ErrorCode::Ignore) |
199 /// authenticated but before a session has been established. | 60 } |
200 fn sm_setcred(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | 61 |
62 /// Perform "account management". | |
63 /// | |
64 /// When PAM calls this function, the user has already been authenticated | |
65 /// by an authentication module (either this one or some other module). | |
66 /// This hook can check for other things, for instance: | |
67 /// | |
68 /// - Date/time (keep your kids off the computer at night) | |
69 /// - Remote host (only let employees log in from the office) | |
70 /// | |
71 /// You can also check things like, e.g., password expiration, | |
72 /// and alert that the user change it before continuing, | |
73 /// or really do whatever you want. | |
74 /// | |
75 /// See [the Module Writer's Guide entry for `pam_sm_acct_mgmt`][mwg] | |
76 /// for more information. | |
77 /// | |
78 /// | |
79 /// # Valid flags | |
80 /// | |
81 /// This function may be called with the following flags set: | |
82 /// | |
83 /// - [`Flags::SILENT`] | |
84 /// - [`Flags::DISALLOW_NULL_AUTHTOK`] | |
85 /// | |
86 /// # Returns | |
87 /// | |
88 /// If the user should be allowed to log in, return `Ok(())`. | |
89 /// | |
90 /// Sensible error codes to return include: | |
91 /// | |
92 /// - [`ErrorCode::AccountExpired`]: The user's account has expired. | |
93 /// - [`ErrorCode::AuthenticationError`]: Generic authentication error. | |
94 /// - [`ErrorCode::NewAuthTokRequired`]: The user's authentication token has expired. | |
95 /// PAM will ask the user to set a new authentication token, which may be handled by | |
96 /// this module in [`Self::change_authtok`]. | |
97 /// - [`ErrorCode::PermissionDenied`]: This one is pretty self-explanatory. | |
98 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service. | |
99 /// | |
100 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-acct.html#mwg-pam_sm_acct_mgmt | |
101 fn account_management(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | |
102 Err(ErrorCode::Ignore) | |
103 } | |
104 | |
105 /// Set credentials on this session. | |
106 /// | |
107 /// If an authentication module knows more about the user than just | |
108 /// their authentication token, then it uses this function to provide | |
109 /// that information to the application. It should only be called after | |
110 /// authentication but before a session is established. | |
111 /// | |
112 /// See [the Module Writer's Guide entry for `pam_sm_setcred`][mwg] | |
113 /// for more information. | |
114 /// | |
115 /// # Valid flags | |
116 /// | |
117 /// This function may be called with the following flags set: | |
118 /// | |
119 /// - [`Flags::SILENT`] | |
120 /// - [`Flags::ESTABLISH_CREDENTIALS`]: Initialize credentials for the user. | |
121 /// - [`Flags::DELETE_CREDENTIALS`]: Delete the credentials associated with this module. | |
122 /// - [`Flags::REINITIALIZE_CREDENTIALS`]: Re-initialize credentials for this user. | |
123 /// - [`Flags::REFRESH_CREDENTIALS`]: Extend the lifetime of the user's credentials. | |
124 /// | |
125 /// # Returns | |
126 /// | |
127 /// If credentials were set successfully, return `Ok(())`. | |
128 /// | |
129 /// Sensible error codes to return include: | |
130 /// | |
131 /// - [`ErrorCode::CredentialsUnavailable`]: The credentials cannot be retrieved. | |
132 /// - [`ErrorCode::CredentialsExpired`]: The credentials have expired. | |
133 /// - [`ErrorCode::CredentialsError`]: Some other error occurred when setting credentials. | |
134 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service. | |
135 /// | |
136 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-auth.html#mwg-pam_sm_setcred | |
137 fn set_credentials(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | |
138 Err(ErrorCode::Ignore) | |
139 } | |
140 | |
141 // Function for chauthtok modules. | |
142 | |
143 /// Called to set or reset the user's authentication token. | |
144 /// | |
145 /// PAM calls this function twice in succession. | |
146 /// 1. The first time, [`Flags::PRELIMINARY_CHECK`] will be set. | |
147 /// If the new token is acceptable, return success; | |
148 /// if not, return [`ErrorCode::TryAgain`] to re-prompt the user. | |
149 /// 2. After the preliminary check succeeds, [`Flags::UPDATE_AUTHTOK`] | |
150 /// will be set. On this call, actually update the stored auth token. | |
151 /// | |
152 /// See [the Module Writer's Guide entry for `pam_sm_chauthtok`][mwg] | |
153 /// for more information. | |
154 /// | |
155 /// # Valid flags | |
156 /// | |
157 /// This function may be called with the following flags set: | |
158 /// | |
159 /// - [`Flags::SILENT`] | |
160 /// - [`Flags::CHANGE_EXPIRED_AUTHTOK`]: This module should only change | |
161 /// any expired passwords, and leave non-expired passwords alone. | |
162 /// If present, it _must_ be combined with one of the following. | |
163 /// - [`Flags::PRELIMINARY_CHECK`]: Don't actually change the password, | |
164 /// just check if the new one is valid. | |
165 /// - [`Flags::UPDATE_AUTHTOK`]: Do actually change the password. | |
166 /// | |
167 /// # Returns | |
168 /// | |
169 /// If the authentication token was changed successfully | |
170 /// (or the check passed), return `Ok(())`. | |
171 /// | |
172 /// Sensible error codes to return include: | |
173 /// | |
174 /// - [`ErrorCode::AuthTokError`]: The service could not get the authentication token. | |
175 /// - [`ErrorCode::AuthTokRecoveryError`]: The service could not get the old token. | |
176 /// - [`ErrorCode::AuthTokLockBusy`]: The password cannot be changed because | |
177 /// the authentication token is currently locked. | |
178 /// - [`ErrorCode::AuthTokDisableAging`]: Aging (expiration) is disabled. | |
179 /// - [`ErrorCode::PermissionDenied`]: What it says on the tin. | |
180 /// - [`ErrorCode::TryAgain`]: When the preliminary check is unsuccessful, | |
181 /// ask the user for a new authentication token. | |
182 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service. | |
183 /// | |
184 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-chauthtok.html#mwg-pam_sm_chauthtok | |
185 fn change_authtok(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | |
186 Err(ErrorCode::Ignore) | |
187 } | |
188 | |
189 // Functions for session modules. | |
190 | |
191 /// Called when a session is opened. | |
192 /// | |
193 /// See [the Module Writer's Guide entry for `pam_sm_open_session`][mwg] | |
194 /// for more information. | |
195 /// | |
196 /// # Valid flags | |
197 /// | |
198 /// The only valid flag is [`Flags::SILENT`]. | |
199 /// | |
200 /// # Returns | |
201 /// | |
202 /// If the session was opened successfully, return `Ok(())`. | |
203 /// | |
204 /// A sensible error code to return is: | |
205 /// | |
206 /// - [`ErrorCode::SessionError`]: Cannot make an entry for this session. | |
207 /// | |
208 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-session.html#mwg-pam_sm_open_session | |
209 fn open_session(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | |
210 Err(ErrorCode::Ignore) | |
211 } | |
212 | |
213 /// Called when a session is being terminated. | |
214 /// | |
215 /// See [the Module Writer's Guide entry for `pam_sm_close_session`][mwg] | |
216 /// for more information. | |
217 /// | |
218 /// # Valid flags | |
219 /// | |
220 /// The only valid flag is [`Flags::SILENT`]. | |
221 /// | |
222 /// # Returns | |
223 /// | |
224 /// If the session was closed successfully, return `Ok(())`. | |
225 /// | |
226 /// A sensible error code to return is: | |
227 /// | |
228 /// - [`ErrorCode::SessionError`]: Cannot remove an entry for this session. | |
229 /// | |
230 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-session.html#mwg-pam_sm_close_session | |
231 fn close_session(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> Result<()> { | |
201 Err(ErrorCode::Ignore) | 232 Err(ErrorCode::Ignore) |
202 } | 233 } |
203 } | 234 } |
204 | 235 |
205 /// Generates the dynamic library entry points for a [PamModule] implementation. | 236 /// Generates the dynamic library entry points for a [PamModule] implementation. |
210 /// | 241 /// |
211 /// ## Examples: | 242 /// ## Examples: |
212 /// | 243 /// |
213 /// Here is full example of a PAM module that would authenticate and authorize everybody: | 244 /// Here is full example of a PAM module that would authenticate and authorize everybody: |
214 /// | 245 /// |
215 /// ``` | 246 /// ```no_run |
216 /// use nonstick::{Flags, PamHandle, PamModule, Result as PamResult, pam_hooks}; | 247 /// use nonstick::{Flags, PamHandle, PamModule, Result as PamResult, pam_hooks}; |
217 /// use std::ffi::CStr; | 248 /// use std::ffi::CStr; |
218 /// | |
219 /// # fn main() {} | 249 /// # fn main() {} |
250 /// | |
220 /// struct MyPamModule; | 251 /// struct MyPamModule; |
221 /// pam_hooks!(MyPamModule); | 252 /// pam_hooks!(MyPamModule); |
222 /// | 253 /// |
223 /// impl PamModule for MyPamModule { | 254 /// impl PamModule for MyPamModule { |
224 /// fn acct_mgmt(pamh: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> PamResult<()> { | 255 /// fn authenticate(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> PamResult<()> { |
256 /// let password = handle.get_authtok(Some("what's your password?"))?; | |
257 /// eprintln!("If you say your password is {:?}, who am I to disagree!", password.unsecure()); | |
258 /// Ok(()) | |
259 /// } | |
260 /// | |
261 /// fn account_management(handle: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> PamResult<()> { | |
262 /// let username = handle.get_user(None)?; | |
225 /// // You should use a Conversation to communicate with the user | 263 /// // You should use a Conversation to communicate with the user |
226 /// // instead of writing to the console, but this is just an example. | 264 /// // instead of writing to the console, but this is just an example. |
227 /// eprintln!("Everybody is authorized!"); | 265 /// eprintln!("Hello {username}! I trust you unconditionally!"); |
228 /// Ok(()) | |
229 /// } | |
230 /// | |
231 /// fn sm_authenticate(pamh: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> PamResult<()> { | |
232 /// eprintln!("Everybody is authenticated!"); | |
233 /// Ok(()) | 266 /// Ok(()) |
234 /// } | 267 /// } |
235 /// } | 268 /// } |
236 /// ``` | 269 /// ``` |
237 #[macro_export] | 270 #[macro_export] |
247 flags: Flags, | 280 flags: Flags, |
248 argc: c_int, | 281 argc: c_int, |
249 argv: *const *const c_char, | 282 argv: *const *const c_char, |
250 ) -> c_int { | 283 ) -> c_int { |
251 let args = extract_argv(argc, argv); | 284 let args = extract_argv(argc, argv); |
252 ErrorCode::result_to_c(super::$ident::acct_mgmt(&mut pamh.into(), args, flags)) | 285 ErrorCode::result_to_c(super::$ident::account_management( |
253 } | |
254 | |
255 #[no_mangle] | |
256 extern "C" fn pam_sm_authenticate( | |
257 pamh: *mut libc::c_void, | |
258 flags: Flags, | |
259 argc: c_int, | |
260 argv: *const *const c_char, | |
261 ) -> c_int { | |
262 let args = extract_argv(argc, argv); | |
263 ErrorCode::result_to_c(super::$ident::sm_authenticate( | |
264 &mut pamh.into(), | 286 &mut pamh.into(), |
265 args, | 287 args, |
266 flags, | 288 flags, |
267 )) | 289 )) |
268 } | 290 } |
269 | 291 |
270 #[no_mangle] | 292 #[no_mangle] |
293 extern "C" fn pam_sm_authenticate( | |
294 pamh: *mut libc::c_void, | |
295 flags: Flags, | |
296 argc: c_int, | |
297 argv: *const *const c_char, | |
298 ) -> c_int { | |
299 let args = extract_argv(argc, argv); | |
300 ErrorCode::result_to_c(super::$ident::authenticate(&mut pamh.into(), args, flags)) | |
301 } | |
302 | |
303 #[no_mangle] | |
271 extern "C" fn pam_sm_chauthtok( | 304 extern "C" fn pam_sm_chauthtok( |
272 pamh: *mut libc::c_void, | 305 pamh: *mut libc::c_void, |
273 flags: Flags, | 306 flags: Flags, |
274 argc: c_int, | 307 argc: c_int, |
275 argv: *const *const c_char, | 308 argv: *const *const c_char, |
276 ) -> c_int { | 309 ) -> c_int { |
277 let args = extract_argv(argc, argv); | 310 let args = extract_argv(argc, argv); |
278 ErrorCode::result_to_c(super::$ident::sm_chauthtok(&mut pamh.into(), args, flags)) | 311 ErrorCode::result_to_c(super::$ident::change_authtok(&mut pamh.into(), args, flags)) |
279 } | 312 } |
280 | 313 |
281 #[no_mangle] | 314 #[no_mangle] |
282 extern "C" fn pam_sm_close_session( | 315 extern "C" fn pam_sm_close_session( |
283 pamh: *mut libc::c_void, | 316 pamh: *mut libc::c_void, |
284 flags: Flags, | 317 flags: Flags, |
285 argc: c_int, | 318 argc: c_int, |
286 argv: *const *const c_char, | 319 argv: *const *const c_char, |
287 ) -> c_int { | 320 ) -> c_int { |
288 let args = extract_argv(argc, argv); | 321 let args = extract_argv(argc, argv); |
289 ErrorCode::result_to_c(super::$ident::sm_close_session( | 322 ErrorCode::result_to_c(super::$ident::close_session(&mut pamh.into(), args, flags)) |
323 } | |
324 | |
325 #[no_mangle] | |
326 extern "C" fn pam_sm_open_session( | |
327 pamh: *mut libc::c_void, | |
328 flags: Flags, | |
329 argc: c_int, | |
330 argv: *const *const c_char, | |
331 ) -> c_int { | |
332 let args = extract_argv(argc, argv); | |
333 ErrorCode::result_to_c(super::$ident::open_session(&mut pamh.into(), args, flags)) | |
334 } | |
335 | |
336 #[no_mangle] | |
337 extern "C" fn pam_sm_setcred( | |
338 pamh: *mut libc::c_void, | |
339 flags: Flags, | |
340 argc: c_int, | |
341 argv: *const *const c_char, | |
342 ) -> c_int { | |
343 let args = extract_argv(argc, argv); | |
344 ErrorCode::result_to_c(super::$ident::set_credentials( | |
290 &mut pamh.into(), | 345 &mut pamh.into(), |
291 args, | 346 args, |
292 flags, | 347 flags, |
293 )) | 348 )) |
294 } | |
295 | |
296 #[no_mangle] | |
297 extern "C" fn pam_sm_open_session( | |
298 pamh: *mut libc::c_void, | |
299 flags: Flags, | |
300 argc: c_int, | |
301 argv: *const *const c_char, | |
302 ) -> c_int { | |
303 let args = extract_argv(argc, argv); | |
304 ErrorCode::result_to_c(super::$ident::sm_open_session( | |
305 &mut pamh.into(), | |
306 args, | |
307 flags, | |
308 )) | |
309 } | |
310 | |
311 #[no_mangle] | |
312 extern "C" fn pam_sm_setcred( | |
313 pamh: *mut libc::c_void, | |
314 flags: Flags, | |
315 argc: c_int, | |
316 argv: *const *const c_char, | |
317 ) -> c_int { | |
318 let args = extract_argv(argc, argv); | |
319 ErrorCode::result_to_c(super::$ident::sm_setcred(&mut pamh.into(), args, flags)) | |
320 } | 349 } |
321 | 350 |
322 /// Turns `argc`/`argv` into a [Vec] of [CStr]s. | 351 /// Turns `argc`/`argv` into a [Vec] of [CStr]s. |
323 /// | 352 /// |
324 /// # Safety | 353 /// # Safety |