Mercurial > crates > nonstick
diff pam/src/hooks.rs @ 20:734ca62159fb
Refactor exported endpoings into pam_hooks macro
author | Anthony Nowell <anthony@algorithmia.com> |
---|---|
date | Tue, 26 Sep 2017 01:51:39 -0600 |
parents | |
children | aa7e8bd083ef |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pam/src/hooks.rs Tue Sep 26 01:51:39 2017 -0600 @@ -0,0 +1,153 @@ +use module::{PamHandle}; +use constants::{PamFlag, PamResultCode}; +use std::ffi::CStr; + +/// Provides functions that are invoked by the entrypoints generated by the `pam_hooks!` macro. +/// +/// All of hooks are ignored by PAM dispatch by default given the default return value of `PAM_IGNORE`. +/// Override any functions that you want to handle with your module. See `man pam(3)`. +pub trait PamHooks { + /// This function performs the task of establishing whether the user is permitted to gain access at + /// this time. It should be understood that the user has previously been validated by an + /// authentication module. This function checks for other things. Such things might be: the time of + /// day or the date, the terminal line, remote hostname, etc. This function may also determine + /// things like the expiration on passwords, and respond that the user change it before continuing. + fn acct_mgmt(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { + PamResultCode::PAM_IGNORE + } + + /// This function performs the task of authenticating the user. + fn sm_authenticate(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { + PamResultCode::PAM_IGNORE + } + + /// This function is used to (re-)set the authentication token of the user. + /// + /// The PAM library calls this function twice in succession. The first time with + /// PAM_PRELIM_CHECK and then, if the module does not return PAM_TRY_AGAIN, subsequently with + /// PAM_UPDATE_AUTHTOK. It is only on the second call that the authorization token is + /// (possibly) changed. + fn sm_chauthtok(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { + PamResultCode::PAM_IGNORE + } + + /// This function is called to terminate a session. + fn sm_close_session(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { + PamResultCode::PAM_IGNORE + } + + /// This function is called to commence a session. + fn sm_open_session(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { + PamResultCode::PAM_IGNORE + } + + /// This function performs the task of altering the credentials of the user with respect to the + /// corresponding authorization scheme. Generally, an authentication module may have access to more + /// information about a user than their authentication token. This function is used to make such + /// information available to the application. It should only be called after the user has been + /// authenticated but before a session has been established. + fn sm_setcred(_pamh: &PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode { + PamResultCode::PAM_IGNORE + } +} + +/// Macro to generate the `extern "C"` entrypoint bindings needed by PAM +/// +/// You can call `pam_hooks!(SomeType);` for any type that implements `PamHooks` +#[macro_export] +macro_rules! pam_hooks { + ($ident:ident) => ( + pub use pam_hooks_scope::*; + mod pam_hooks_scope { + use $crate::module::PamHandle; + use $crate::constants::{PamFlag, PamResultCode}; + use $crate::hooks::PamHooks; + use std::ffi::CStr; + use std::os::raw::{c_char, c_int}; + + fn extract_argv<'a>(argc: c_int, argv: *const *const c_char) -> Vec<&'a CStr> { + (0..argc) + .map(|o| unsafe { + CStr::from_ptr(*argv.offset(o as isize) as *const c_char) + }) + .collect() + } + + #[no_mangle] + pub extern "C" fn pam_sm_acct_mgmt( + pamh: &PamHandle, + flags: PamFlag, + argc: c_int, + argv: *const *const c_char, + ) -> PamResultCode { + let args = extract_argv(argc, argv); + super::$ident::acct_mgmt(pamh, args, flags) + } + + #[no_mangle] + pub extern "C" fn pam_sm_authenticate( + pamh: &PamHandle, + flags: PamFlag, + argc: c_int, + argv: *const *const c_char, + ) -> PamResultCode { + let args = extract_argv(argc, argv); + super::$ident::sm_authenticate(pamh, args, flags) + } + + #[no_mangle] + pub extern "C" fn pam_sm_chauthtok( + pamh: &PamHandle, + flags: PamFlag, + argc: c_int, + argv: *const *const c_char, + ) -> PamResultCode { + let args = extract_argv(argc, argv); + super::$ident::sm_chauthtok(pamh, args, flags) + } + + #[no_mangle] + pub extern "C" fn pam_sm_close_session( + pamh: &PamHandle, + flags: PamFlag, + argc: c_int, + argv: *const *const c_char, + ) -> PamResultCode { + let args = extract_argv(argc, argv); + super::$ident::sm_close_session(pamh, args, flags) + } + + #[no_mangle] + pub extern "C" fn pam_sm_open_session( + pamh: &PamHandle, + flags: PamFlag, + argc: c_int, + argv: *const *const c_char, + ) -> PamResultCode { + let args = extract_argv(argc, argv); + super::$ident::sm_open_session(pamh, args, flags) + } + + #[no_mangle] + pub extern "C" fn pam_sm_setcred( + pamh: &PamHandle, + flags: PamFlag, + argc: c_int, + argv: *const *const c_char, + ) -> PamResultCode { + let args = extract_argv(argc, argv); + super::$ident::sm_setcred(pamh, args, flags) + } + } + ) +} + +#[cfg(test)] +pub mod test { + use super::PamHooks; + + struct Foo; + impl PamHooks for Foo {} + + pam_hooks!(Foo); +} \ No newline at end of file