diff src/libpam/module.rs @ 166:2f5913131295

Separate flag/action flags into flags and action. This also individualizes the type of flag for each PAM function, so that you can only call a function with the right flags and values.
author Paul Fisher <paul@pfish.zone>
date Tue, 15 Jul 2025 00:32:24 -0400
parents 1bc52025156b
children e27c5c667a5a
line wrap: on
line diff
--- a/src/libpam/module.rs	Mon Jul 14 18:56:55 2025 -0400
+++ b/src/libpam/module.rs	Tue Jul 15 00:32:24 2025 -0400
@@ -11,7 +11,7 @@
 ///
 /// ```no_run
 /// use nonstick::{
-///     pam_hooks, ConversationAdapter, Flags, LibPamTransaction, ModuleClient, PamModule,
+///     pam_hooks, ConversationAdapter, AuthnFlags, LibPamTransaction, ModuleClient, PamModule,
 ///     Result as PamResult,
 /// };
 /// use std::ffi::CStr;
@@ -21,7 +21,7 @@
 /// pam_hooks!(MyPamModule);
 ///
 /// impl<T: ModuleClient> PamModule<T> for MyPamModule {
-///     fn authenticate(handle: &mut T, args: Vec<&CStr>, flags: Flags) -> PamResult<()> {
+///     fn authenticate(handle: &mut T, args: Vec<&CStr>, flags: AuthnFlags) -> PamResult<()> {
 ///         let password = handle.authtok(Some("what's your password?".as_ref()))?;
 ///         let response =
 ///             format!("If you say your password is {password:?}, who am I to disagree?");
@@ -29,7 +29,7 @@
 ///         Ok(())
 ///     }
 ///
-///     fn account_management(handle: &mut T, args: Vec<&CStr>, flags: Flags) -> PamResult<()> {
+///     fn account_management(handle: &mut T, args: Vec<&CStr>, flags: AuthnFlags) -> PamResult<()> {
 ///         let username = handle.username(None)?;
 ///         let response = format!("Hello {username:?}! I trust you unconditionally.");
 ///         handle.info_msg(&response);
@@ -42,96 +42,98 @@
     ($ident:ident) => {
         mod _pam_hooks_scope {
             use std::ffi::{c_char, c_int, c_void, CStr};
-            use $crate::{ErrorCode, Flags, LibPamHandle, PamModule};
+            use $crate::{
+                AuthnFlags, AuthtokAction, BaseFlags, CredAction, ErrorCode, LibPamHandle,
+                PamModule,
+            };
+
+            macro_rules! handle {
+                ($pamh:ident) => {
+                    match unsafe { $pamh.cast::<LibPamHandle>().as_mut() } {
+                        Some(handle) => handle,
+                        None => return ErrorCode::Ignore.into(),
+                    }
+                };
+            }
 
             #[no_mangle]
             extern "C" fn pam_sm_acct_mgmt(
                 pamh: *mut c_void,
-                flags: Flags,
+                flags: AuthnFlags,
                 argc: c_int,
                 argv: *const *const c_char,
             ) -> c_int {
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    let args = extract_argv(argc, argv);
-                    ErrorCode::result_to_c(super::$ident::account_management(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
+                let handle = handle!(pamh);
+                let args = extract_argv(argc, argv);
+                ErrorCode::result_to_c(super::$ident::account_management(handle, args, flags))
             }
 
             #[no_mangle]
             extern "C" fn pam_sm_authenticate(
                 pamh: *mut c_void,
-                flags: Flags,
+                flags: AuthnFlags,
                 argc: c_int,
                 argv: *const *const c_char,
             ) -> c_int {
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    let args = extract_argv(argc, argv);
-                    ErrorCode::result_to_c(super::$ident::authenticate(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
+                let handle = handle!(pamh);
+                let args = extract_argv(argc, argv);
+                ErrorCode::result_to_c(super::$ident::authenticate(handle, args, flags))
             }
 
             #[no_mangle]
             extern "C" fn pam_sm_chauthtok(
                 pamh: *mut c_void,
-                flags: Flags,
+                flags: c_int,
                 argc: c_int,
                 argv: *const *const c_char,
             ) -> c_int {
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    let args = extract_argv(argc, argv);
-                    ErrorCode::result_to_c(super::$ident::change_authtok(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
+                let handle = handle!(pamh);
+                let (action, flags) = match AuthtokAction::extract(flags) {
+                    Ok(val) => val,
+                    Err(e) => return e.into(),
+                };
+                let args = extract_argv(argc, argv);
+                ErrorCode::result_to_c(super::$ident::change_authtok(handle, args, action, flags))
             }
 
             #[no_mangle]
             extern "C" fn pam_sm_close_session(
                 pamh: *mut c_void,
-                flags: Flags,
+                flags: BaseFlags,
                 argc: c_int,
                 argv: *const *const c_char,
             ) -> c_int {
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    let args = extract_argv(argc, argv);
-                    ErrorCode::result_to_c(super::$ident::close_session(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
+                let handle = handle!(pamh);
+                let args = extract_argv(argc, argv);
+                ErrorCode::result_to_c(super::$ident::close_session(handle, args, flags))
             }
 
             #[no_mangle]
             extern "C" fn pam_sm_open_session(
                 pamh: *mut c_void,
-                flags: Flags,
+                flags: BaseFlags,
                 argc: c_int,
                 argv: *const *const c_char,
             ) -> c_int {
+                let handle = handle!(pamh);
                 let args = extract_argv(argc, argv);
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    ErrorCode::result_to_c(super::$ident::open_session(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
+                ErrorCode::result_to_c(super::$ident::open_session(handle, args, flags))
             }
 
             #[no_mangle]
             extern "C" fn pam_sm_setcred(
                 pamh: *mut c_void,
-                flags: Flags,
+                flags: c_int,
                 argc: c_int,
                 argv: *const *const c_char,
             ) -> c_int {
+                let handle = handle!(pamh);
+                let (action, flags) = match CredAction::extract(flags) {
+                    Ok(val) => val,
+                    Err(e) => return e.into(),
+                };
                 let args = extract_argv(argc, argv);
-                if let Some(handle) = unsafe { pamh.cast::<LibPamHandle>().as_mut() } {
-                    ErrorCode::result_to_c(super::$ident::set_credentials(handle, args, flags))
-                } else {
-                    ErrorCode::Ignore as c_int
-                }
+                ErrorCode::result_to_c(super::$ident::set_credentials(handle, args, action, flags))
             }
 
             /// Turns `argc`/`argv` into a [Vec] of [CStr]s.