view src/macros.rs @ 59:3f4a77aa88be

Fix string copyting and improve error situation. This change is too big and includes several things: - Fix copying strings from PAM by fixing const and mut on pam funcs. - Improve error enums by simplifying conversions and removing unnecessary and ambiguous "success" variants. - Make a bunch of casts nicer. - Assorted other cleanup.
author Paul Fisher <paul@pfish.zone>
date Wed, 21 May 2025 00:27:18 -0400
parents daa2cde64601
children
line wrap: on
line source

/// Macro to generate the `extern "C"` entrypoint bindings needed by PAM
///
/// You can call `pam_hooks!(SomeType);` for any type that implements `PamHooks`
///
/// ## Examples:
///
/// Here is full example of a PAM module that would authenticate and authorize everybody:
///
/// ```
/// #[macro_use] extern crate nonstick;
///
/// use nonstick::module::{PamHooks, PamHandle};
/// use nonstick::constants::{PamResult, Flags};
/// use std::ffi::CStr;
///
/// # fn main() {}
/// struct MyPamModule;
/// pam_hooks!(MyPamModule);
///
/// impl PamHooks for MyPamModule {
///    fn acct_mgmt(pamh: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> PamResult<()> {
///        println!("Everybody is authorized!");
///        Ok(())
///    }
///
///    fn sm_authenticate(pamh: &mut PamHandle, args: Vec<&CStr>, flags: Flags) -> PamResult<()> {
///        println!("Everybody is authenticated!");
///        Ok(())
///    }
/// }
/// ```
#[macro_export]
macro_rules! pam_hooks {
    ($ident:ident) => {
        pub use self::pam_hooks_scope::*;
        mod pam_hooks_scope {
            use std::ffi::CStr;
            use std::os::raw::{c_char, c_int};
            use $crate::constants::{ErrorCode, Flags};
            use $crate::module::{PamHandle, PamHooks};

            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: &mut PamHandle,
                flags: Flags,
                argc: c_int,
                argv: *const *const c_char,
            ) -> c_int {
                let args = extract_argv(argc, argv);
                ErrorCode::result_to_c(super::$ident::acct_mgmt(pamh, args, flags))
            }

            #[no_mangle]
            pub extern "C" fn pam_sm_authenticate(
                pamh: &mut PamHandle,
                flags: Flags,
                argc: c_int,
                argv: *const *const c_char,
            ) -> c_int {
                let args = extract_argv(argc, argv);
                ErrorCode::result_to_c(super::$ident::sm_authenticate(pamh, args, flags))
            }

            #[no_mangle]
            pub extern "C" fn pam_sm_chauthtok(
                pamh: &mut PamHandle,
                flags: Flags,
                argc: c_int,
                argv: *const *const c_char,
            ) -> c_int {
                let args = extract_argv(argc, argv);
                ErrorCode::result_to_c(super::$ident::sm_chauthtok(pamh, args, flags))
            }

            #[no_mangle]
            pub extern "C" fn pam_sm_close_session(
                pamh: &mut PamHandle,
                flags: Flags,
                argc: c_int,
                argv: *const *const c_char,
            ) -> c_int {
                let args = extract_argv(argc, argv);
                ErrorCode::result_to_c(super::$ident::sm_close_session(pamh, args, flags))
            }

            #[no_mangle]
            pub extern "C" fn pam_sm_open_session(
                pamh: &mut PamHandle,
                flags: Flags,
                argc: c_int,
                argv: *const *const c_char,
            ) -> c_int {
                let args = extract_argv(argc, argv);
                ErrorCode::result_to_c(super::$ident::sm_open_session(pamh, args, flags))
            }

            #[no_mangle]
            pub extern "C" fn pam_sm_setcred(
                pamh: &mut PamHandle,
                flags: Flags,
                argc: c_int,
                argv: *const *const c_char,
            ) -> c_int {
                let args = extract_argv(argc, argv);
                ErrorCode::result_to_c(super::$ident::sm_setcred(pamh, args, flags))
            }
        }
    };
}

#[cfg(test)]
pub mod test {
    use crate::module::PamHooks;

    struct Foo;
    impl PamHooks for Foo {}

    pam_hooks!(Foo);
}