use crate::constants::{ErrorCode, RawFlags, Result};
use crate::libpam::handle::LibPamHandle;
use crate::module::PamModule;
use crate::{AuthnFlags, AuthtokAction, BaseFlags, CredAction};
use std::ffi::{c_char, c_int, c_void, CStr};
#[macro_export]
macro_rules! pam_export {
($ident:ident) => {
mod __pam_export_scope {
use std::ffi::{c_char, c_int, c_void};
use $crate::constants::{RawFlags, ReturnCode};
use $crate::libpam::module;
macro_rules! export {
($func:ident) => {
#[no_mangle]
unsafe extern "C" fn $func(
pamh: *mut c_void,
flags: RawFlags,
argc: c_int,
argv: *const *const c_char,
) -> c_int {
let ret: ReturnCode =
module::$func::<super::$ident>(pamh, flags, argc, argv).into();
ret.into()
}
};
}
export!(pam_sm_acct_mgmt);
export!(pam_sm_authenticate);
export!(pam_sm_chauthtok);
export!(pam_sm_close_session);
export!(pam_sm_open_session);
export!(pam_sm_setcred);
}
};
}
#[doc(hidden)]
pub unsafe fn pam_sm_acct_mgmt<M: PamModule<LibPamHandle>>(
pamh: *mut c_void,
flags: RawFlags,
argc: c_int,
argv: *const *const c_char,
) -> Result<()> {
let handle = wrap(pamh)?;
let args = extract_argv(argc, argv);
M::account_management(handle, args, AuthnFlags::from(flags))
}
#[doc(hidden)]
pub unsafe fn pam_sm_authenticate<M: PamModule<LibPamHandle>>(
pamh: *mut c_void,
flags: RawFlags,
argc: c_int,
argv: *const *const c_char,
) -> Result<()> {
let handle = wrap(pamh)?;
let args = extract_argv(argc, argv);
M::authenticate(handle, args, AuthnFlags::from(flags))
}
#[doc(hidden)]
pub unsafe fn pam_sm_chauthtok<M: PamModule<LibPamHandle>>(
pamh: *mut c_void,
flags: RawFlags,
argc: c_int,
argv: *const *const c_char,
) -> Result<()> {
let handle = wrap(pamh)?;
let (action, flags) = AuthtokAction::extract(flags)?;
let args = extract_argv(argc, argv);
M::change_authtok(handle, args, action, flags)
}
#[doc(hidden)]
pub unsafe fn pam_sm_close_session<M: PamModule<LibPamHandle>>(
pamh: *mut c_void,
flags: RawFlags,
argc: c_int,
argv: *const *const c_char,
) -> Result<()> {
let handle = wrap(pamh)?;
let args = extract_argv(argc, argv);
M::close_session(handle, args, BaseFlags::from(flags))
}
#[doc(hidden)]
pub unsafe fn pam_sm_open_session<M: PamModule<LibPamHandle>>(
pamh: *mut c_void,
flags: RawFlags,
argc: c_int,
argv: *const *const c_char,
) -> Result<()> {
let handle = wrap(pamh)?;
let args = extract_argv(argc, argv);
M::open_session(handle, args, BaseFlags::from(flags))
}
#[doc(hidden)]
pub unsafe fn pam_sm_setcred<M: PamModule<LibPamHandle>>(
pamh: *mut c_void,
flags: RawFlags,
argc: c_int,
argv: *const *const c_char,
) -> Result<()> {
let handle = wrap(pamh)?;
let (action, flags) = CredAction::extract(flags)?;
let args = extract_argv(argc, argv);
M::set_credentials(handle, args, action, flags)
}
unsafe 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()
}
unsafe fn wrap<'a>(handle: *mut c_void) -> Result<&'a mut LibPamHandle> {
handle
.cast::<LibPamHandle>()
.as_mut()
.ok_or(ErrorCode::SystemError)
}
#[cfg(test)]
mod tests {
use crate::{ModuleClient, PamModule};
struct Foo;
impl<T: ModuleClient> PamModule<T> for Foo {}
pam_export!(Foo);
}