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