Mercurial > crates > nonstick
view src/macros.rs @ 56:daa2cde64601
Big big refactor. Probably should have been multiple changes.
- Makes FFI safer by explicitly specifying c_int in calls.
- Uses ToPrimitive/FromPrimitive to make this easier.
- Pulls PamFlag variables into a bitflags! struct.
- Pulls PamMessageStyle variables into an enum.
- Renames ResultCode to ErrorCode.
- Switches from PAM_SUCCESS to using a Result<(), ErrorCode>.
- Uses thiserror to make ErrorCode into an Error.
- Gets rid of pam_try! because now we have Results.
- Expands some names (e.g. Conv to Conversation).
- Adds more doc comments.
- Returns passwords as a SecureString, to avoid unnecessarily
keeping it around in memory.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sun, 04 May 2025 02:56:55 -0400 |
parents | a921b72743e4 |
children | 3f4a77aa88be |
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::{Flags, ErrorCode}; 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); }