Mercurial > crates > nonstick
view libpam-sys/src/lib.rs @ 136:efbc235f01d3 default tip
Separate libpam-sys-helpers from libpam-sys.
This separates the parts of libpam-sys that don't need linking against libpam
from the parts that do need to link against libpam.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Thu, 03 Jul 2025 14:28:04 -0400 |
parents | libpam-sys/src/ffi.rs@6c1e1bdb4164 |
children |
line wrap: on
line source
//! `libpam-sys` provides low-level access to `libpam`. //! //! Everything in here is directly as exported from the `libpam` library or //! its header files, with limited exceptions: //! //! - The [`pam_impl`] submodule (and the [`pam_impl_name!`] macro) contains //! tools for detecting the current PAM library. //! - [`AppData`] is an opaque pointer newtype. //! - [`ConversationCallback`] and [`CleanupCallback`] are aliases for //! what are otherwise anonymous function types. //! #![doc = concat!("This documentation was built for the **", pam_impl_name!(), "** implementation.")] //! //! You can override this **at build time** by setting the `LIBPAMSYS_IMPL` //! environment variable to one of the values of the [`pam_impl::PamImpl`] enum. //! //! For more information about configuration, see [the README](https://crates.io/crate/libpam-sys). #![allow(non_camel_case_types)] #![allow(unused_imports)] #[doc(inline)] pub use libpam_sys_helpers::constants::*; #[doc(inline)] pub use libpam_sys_helpers::{pam_impl, pam_impl_name}; use num_enum::{IntoPrimitive, TryFromPrimitive}; use std::ffi::{c_char, c_int, c_uint, c_void}; use std::fmt; use std::marker::{PhantomData, PhantomPinned}; /// A marker struct to make whatever it's in `!Sync`, `!Send`, and `!Unpin`. #[derive(Default, PartialOrd, PartialEq, Ord, Eq)] #[repr(C)] struct ExtremelyUnsafe { _value: (), _marker: PhantomData<(PhantomPinned, *mut c_void)>, } impl fmt::Debug for ExtremelyUnsafe { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "ExtremelyUnsafe({self:p})") } } /// An opaque structure that PAM uses to communicate. /// /// This is only ever returned in pointer form and cannot be constructed. #[repr(C)] pub struct pam_handle(ExtremelyUnsafe); impl fmt::Debug for pam_handle { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "pam_handle({self:p}") } } /// An opaque structure that is passed through PAM in a conversation. #[repr(C)] pub struct AppData(ExtremelyUnsafe); impl fmt::Debug for AppData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "AppData({self:p}") } } /// Just an alias for the type of [`pam_conv::conv`]. /// /// For important details about the format of `messages`, /// see [`libpam_sys_helpers::memory::PtrPtrVec`]. /// /// ```no_run /// # use libpam_sys::{ConversationCallback, pam_conv}; /// fn convo() -> ConversationCallback { /// // ... /// # unimplemented!() /// } /// let conv = pam_conv{conv: convo(), appdata_ptr: std::ptr::null_mut()}; /// ``` pub type ConversationCallback = unsafe extern "C" fn( num_msg: c_int, msg: *const *const pam_message, resp: *mut *mut pam_response, appdata: *mut AppData, ) -> c_int; /// Alias for the callback to [`pam_set_data`]. /// /// ```no_run /// # use std::ffi::CString; /// use libpam_sys::{CleanupCallback, pam_set_data}; /// # use libpam_sys::pam_handle; /// # let handle: *mut pam_handle = std::ptr::null_mut(); /// # let mut my_data = 100; /// # let data_ptr = &mut my_data as *mut i32; /// fn cleanup() -> CleanupCallback { /// // ... /// # unimplemented!() /// } /// let name = CString::new("name").unwrap(); /// unsafe { /// pam_set_data(handle, name.as_ptr().cast_mut(), data_ptr.cast(), cleanup()); /// } /// ``` pub type CleanupCallback = unsafe extern "C" fn(pamh: *mut pam_handle, data: *mut c_void, pam_end_status: c_int); /// Used by PAM to communicate between the module and the application. #[repr(C)] pub struct pam_conv { pub conv: unsafe extern "C" fn( num_msg: c_int, msg: *const *const pam_message, resp: *mut *mut pam_response, appdata: *mut AppData, ) -> c_int, pub appdata_ptr: *mut AppData, } /// A message sent into a PAM conversation. #[repr(C)] pub struct pam_message { pub msg_style: c_int, pub msg: *const c_char, } /// A response returned from a PAM conversation. #[repr(C)] pub struct pam_response { pub resp: *mut c_char, /// Completely unused. pub resp_retcode: c_int, } /// Definition of the PAM_XAUTHDATA item. Compatible with `xcb_auth_info_t`. #[cfg(pam_impl = "LinuxPam")] #[repr(C)] pub struct pam_xauth_data { pub namelen: c_int, pub name: *mut c_char, pub datalen: c_int, pub data: *mut c_char, } #[cfg(pam_impl = "LinuxPam")] #[derive(Debug)] #[repr(C)] pub struct pam_modutil_privs { pub grplist: *mut libc::gid_t, pub number_of_groups: c_int, pub allocated: c_int, pub old_gid: libc::gid_t, pub old_uid: libc::uid_t, pub is_dropped: c_int, } #[cfg(pam_impl = "OpenPam")] pub type pam_func_t = unsafe extern "C" fn( handle: *mut pam_handle, flags: c_int, argc: c_int, argv: *const *const c_char, ) -> c_int; #[cfg(pam_impl = "OpenPam")] #[derive(Debug)] #[repr(C)] pub struct pam_module { pub path: *mut c_char, pub func: [pam_func_t; 6], pub dlh: *mut c_void, } #[cfg(pam_impl = "OpenPam")] #[derive(Debug)] #[repr(C)] pub struct pam_repository { pub typ: *mut c_char, pub scope: *mut c_void, pub scope_len: usize, } // These are the functions specified in X/SSO. Everybody exports them. #[link(name = "pam")] extern "C" { /// Account validation. pub fn pam_acct_mgmt(pamh: *mut pam_handle, flags: c_int) -> c_int; /// Authenticate a user. pub fn pam_authenticate(pamh: *mut pam_handle, flags: c_int) -> c_int; // Nobody implements pam_authenticate_secondary. /// Manage authentication tokens. pub fn pam_chauthtok(pamh: *mut pam_handle, flags: c_int) -> c_int; /// Close an opened user session. pub fn pam_close_session(pamh: *mut pam_handle, flags: c_int) -> c_int; /// Ends the PAM transaction. pub fn pam_end(pamh: *mut pam_handle, flags: c_int) -> c_int; /// Gets module-specific data. PAM still owns the data. pub fn pam_get_data( pamh: *mut pam_handle, module_data_name: *const c_char, data: *mut *const c_void, ) -> c_int; /// Gets an environment variable. You own the return value. pub fn pam_getenv(pamh: *const pam_handle, name: *const c_char) -> *mut c_char; /// Gets all the environment variables. You own everything it points to. pub fn pam_getenvlist(pamh: *const pam_handle) -> *mut *mut c_char; /// Get information about the transaction. /// /// The item is owned by PAM. pub fn pam_get_item( pamh: *const pam_handle, item_type: c_int, item: *mut *const c_void, ) -> c_int; // Nobody implements pam_get_mapped_authtok. // Nobody implements pam_get_mapped_username. /// Get the username. PAM owns it. pub fn pam_get_user( pamh: *mut pam_handle, user: *mut *const c_char, prompt: *const c_char, ) -> c_int; /// Opens a user session. pub fn pam_open_session(pamh: *mut pam_handle, flags: c_int) -> c_int; /// Sets the value of an environment variable. `namevalue` is copied. pub fn pam_putenv(pamh: *mut pam_handle, namevalue: *const c_char) -> c_int; /// Update or delete user credentials. pub fn pam_setcred(pamh: *mut pam_handle, flags: c_int) -> c_int; /// Set module-specific data. PAM will call `cleanup` when completed. pub fn pam_set_data( pamh: *mut pam_handle, module_data_name: *const c_char, data: *mut c_void, cleanup: unsafe extern "C" fn( pamh: *mut pam_handle, data: *mut c_void, pam_end_status: c_int, ), ) -> c_int; /// Set information about the transaction. The `item` is copied. pub fn pam_set_item(pamh: *mut pam_handle, item_type: c_int, item: *const c_void) -> c_int; // Nobody implements pam_set_mapped_authtok. // Nobody implements pam_set_mapped_username. // The pam_sm_whatever functions are prototypes for the functions that // a PAM module should implement, not symbols provided by PAM. // Nobody implements pam_authenticate_secondary. /// Starts a PAM transaction. The `conv` may or may not be copied. pub fn pam_start( service: *const c_char, user: *const c_char, pam_conv: *mut pam_conv, pamh: *mut *mut pam_handle, ) -> c_int; /// Gets a statically-allocated error string. /// /// All implementations of PAM known to this library (Linux-PAM, OpenPAM, /// and Sun) ignore `pamh` and will accept a null pointer. pub fn pam_strerror(pamh: *const pam_handle, error_number: c_int) -> *mut c_char; } #[cfg(any(pam_impl = "LinuxPam", pam_impl = "OpenPam"))] extern "C" { /// Gets `PAM_AUTHTOK`, or asks the user if that is unset. pub fn pam_get_authtok( pamh: *mut pam_handle, item: c_int, authtok: *mut *const c_char, prompt: *const c_char, ) -> c_int; pub fn pam_prompt( pamh: *const pam_handle, style: c_int, response: *mut *mut c_char, fmt: *const c_char, ... ) -> c_int; } #[cfg(pam_impl = "LinuxPam")] extern "C" { pub fn pam_fail_delay(pamh: *mut pam_handle, musec_delay: c_uint) -> c_int; /// Start a PAM transaction based on configuration in the given directory. pub fn pam_start_confdir( service_name: *const c_char, user: *const c_char, pam_conversation: *mut pam_conv, confdir: *const c_char, pamh: *mut *mut pam_handle, ) -> c_int; // We don't export the v-variants of the formatting functions. pub fn pam_syslog(pamh: *const pam_handle, priority: c_int, fmt: *const c_char, ...); pub fn pam_get_authtok_noverify( pamh: *const pam_handle, authtok: *mut *const c_char, prompt: *const c_char, ) -> c_int; pub fn pam_get_authtok_verify( pamh: *const pam_handle, authtok: *mut *const c_char, prompt: *const c_char, ) -> c_int; // pam_modutil also lives in libpam for Linux. pub fn pam_modutil_check_user_in_passwd( pamh: *mut pam_handle, user_name: *const c_char, file_name: *const c_char, ) -> c_int; pub fn pam_modutil_getpwnam(pamh: *mut pam_handle, user: *const c_char) -> *mut libc::passwd; pub fn pam_modutil_getpwuid(pamh: *mut pam_handle, uid: libc::uid_t) -> *mut libc::passwd; pub fn pam_modutil_getgrnam(pamh: *mut pam_handle, group: *const c_char) -> *mut libc::group; pub fn pam_modutil_getgrgid(pamh: *mut pam_handle, gid: libc::gid_t) -> *mut libc::group; pub fn pam_modutil_getspnam(pamh: *mut pam_handle, user: *const c_char) -> *mut libc::spwd; pub fn pam_modutil_user_in_group_nam_nam( pamh: *mut pam_handle, user: *const c_char, group: *const c_char, ) -> c_int; pub fn pam_modutil_user_in_group_nam_gid( pamh: *mut pam_handle, user: *const c_char, group: libc::gid_t, ) -> c_int; pub fn pam_modutil_user_in_group_uid_nam( pamh: *mut pam_handle, user: libc::uid_t, group: *const c_char, ) -> c_int; pub fn pam_modutil_user_in_group_uid_gid( pamh: *mut pam_handle, user: libc::uid_t, group: libc::gid_t, ) -> c_int; pub fn pam_modutil_getlogin(pamh: *mut pam_handle) -> *const c_char; pub fn pam_modutil_read(fd: c_int, buffer: *mut c_char, count: c_int) -> c_int; pub fn pam_modutil_write(fd: c_int, buffer: *const c_char, count: c_int) -> c_int; pub fn pam_modutil_audit_write( pamh: *mut pam_handle, typ: c_int, message: *const c_char, retval: c_int, ) -> c_int; pub fn pam_modutil_drop_priv( pamh: *mut pam_handle, p: *mut pam_modutil_privs, pw: *const libc::passwd, ) -> c_int; pub fn pam_modutil_regain_priv(pamh: *mut pam_handle, p: *mut pam_modutil_privs) -> c_int; pub fn pam_modutil_sanitize_helper_fds( pamh: *mut pam_handle, redirect_stdin: pam_modutil_redirect_fd, redirect_stdout: pam_modutil_redirect_fd, redirect_stderr: pam_modutil_redirect_fd, ) -> c_int; pub fn pam_modutil_search_key( pamh: *mut pam_handle, file_name: *const c_char, key: *const c_char, ) -> *mut c_char; } #[cfg(pam_impl = "OpenPam")] extern "C" { pub fn openpam_borrow_cred(pamh: *mut pam_handle, passwd: *const libc::passwd) -> c_int; pub fn openpam_subst( pamh: *const pam_handle, buf: *mut c_char, _bufsize: *mut usize, _template: *const c_char, ) -> c_int; pub fn openpam_free_data(pamh: *mut pam_handle, data: *mut c_void, status: c_int); pub fn openpam_free_envlist(_envlist: *mut *mut c_char); pub fn openpam_get_option(_pamh: *mut pam_handle, _option: *const c_char) -> *const c_char; pub fn openpam_restore_cred(pamh: *mut pam_handle) -> c_int; pub fn openpam_set_option( _pamh: *mut pam_handle, _option: *const c_char, _value: *const c_char, ) -> c_int; pub fn pam_error(pamh: *const pam_handle, _fmt: *const c_char, ...) -> c_int; pub fn pam_info(_pamh: *const pam_handle, _fmt: *const c_char, ...) -> c_int; pub fn openpam_readline( _f: *mut libc::FILE, _lineno: *mut c_int, _lenp: *mut usize, ) -> *mut c_char; pub fn openpam_readlinev( _f: *mut libc::FILE, _lineno: *mut c_int, _lenp: *mut c_int, ) -> *mut *mut c_char; pub fn openpam_readword( _f: *mut libc::FILE, _lineno: *mut c_int, _lenp: *mut usize, ) -> *mut c_char; pub fn openpam_straddch( _str: *mut *mut c_char, _sizep: *mut usize, _lenp: *mut usize, ch: c_int, ) -> c_int; pub fn openpam_set_feature(_feature: c_int, _onoff: c_int) -> c_int; pub fn openpam_get_feature(_feature: c_int, _onoff: *mut c_int) -> c_int; pub fn _openpam_log(_level: c_int, _func: *const c_char, _fmt: *const c_char, ...); /// A premade conversation function that talks to the TTY. /// /// ```no_run /// # use std::ffi::CString; /// # use std::ptr; /// use libpam_sys::*; /// # let service = CString::new("whatever").unwrap(); /// # let user = CString::new("whatever").unwrap(); /// let mut handle: *mut pam_handle = ptr::null_mut(); /// let mut conv = pam_conv{ /// conv: openpam_ttyconv, /// appdata_ptr: ptr::null_mut(), /// }; /// let result = unsafe { pam_start( /// service.as_ptr(), user.as_ptr(), &mut conv, &mut handle /// ) }; /// ``` pub fn openpam_ttyconv( n: c_int, _msg: *const *const pam_message, _resp: *mut *mut pam_response, _data: *mut AppData, ) -> c_int; pub static mut openpam_ttyconv_timeout: c_int; /// A null conversation function. /// /// ```no_run /// # use std::ffi::CString; /// # use std::ptr; /// use libpam_sys::*; /// # let service = CString::new("whatever").unwrap(); /// # let user = CString::new("whatever").unwrap(); /// let mut handle: *mut pam_handle = ptr::null_mut(); /// let mut conv = pam_conv{ /// conv: openpam_nullconv, /// appdata_ptr: ptr::null_mut(), /// }; /// let result = unsafe { pam_start( /// service.as_ptr(), user.as_ptr(), &mut conv, &mut handle /// ) }; /// ``` pub fn openpam_nullconv( n: c_int, _msg: *const *const pam_message, _resp: *mut *mut pam_response, _data: *mut AppData, ) -> c_int; }