pamsm-0.5.2/.cargo_vcs_info.json0000644000000001120000000000100121470ustar { "git": { "sha1": "f8f16f4dd3ddcca534dde0b4d394898d5b562a55" } } pamsm-0.5.2/.clippy.toml000064400000000000000000000000200072674642500132400ustar 00000000000000msrv = "1.32.0" pamsm-0.5.2/.gitignore000064400000000000000000000000220072674642500127570ustar 00000000000000target Cargo.lock pamsm-0.5.2/.travis.yml000064400000000000000000000007150072674642500131110ustar 00000000000000language: rust rust: - 1.32.0 # minimum supported toolchain - stable - beta - nightly matrix: allow_failures: - rust: nightly before_script: - bash -c 'if [[ "$TRAVIS_RUST_VERSION" == "$CLIPPY_RUST_VERSION" ]]; then rustup component add clippy-preview; fi' script: - cargo test --all-features - bash -c 'if [[ "$TRAVIS_RUST_VERSION" == "$CLIPPY_RUST_VERSION" ]]; then cargo clippy --all-features -- -D warnings; fi' pamsm-0.5.2/Cargo.toml0000644000000024010000000000100101500ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "pamsm" version = "0.5.2" authors = ["Raphael Catolino "] description = "Rust wrappers around PAM Service Modules functions" homepage = "https://github.com/rcatolino/pam_sm_rust" readme = "readme.md" keywords = ["pam", "service", "module", "wrapper", "ffi"] categories = ["os::unix-apis", "authentication", "api-bindings"] license = "GPL-3.0" [package.metadata.docs.rs] features = ["libpam"] [package.metadata.release] disable-publish = true disable-push = true pre-release-commit-message = "cargo: pamsm release {{version}}" pro-release-commit-message = "cargo: version bump to {{version}}" sign-commit = true tag-message = "pams {{version}}" upload-doc = false [dependencies.bitflags] version = "1.0" [dev-dependencies.time] version = "^0.2" [features] libpam = [] pamsm-0.5.2/Cargo.toml.orig000064400000000000000000000014410072674642500136640ustar 00000000000000[package] name = "pamsm" version = "0.5.2" readme = "readme.md" description = "Rust wrappers around PAM Service Modules functions" authors = ["Raphael Catolino "] license = "GPL-3.0" homepage = "https://github.com/rcatolino/pam_sm_rust" keywords = ["pam", "service", "module", "wrapper", "ffi"] categories = ["os::unix-apis", "authentication", "api-bindings"] [dev-dependencies] time = "^0.2" [dependencies] bitflags = "1.0" [features] libpam = [] [package.metadata.release] sign-commit = true upload-doc = false disable-publish = true disable-push = true pre-release-commit-message = "cargo: pamsm release {{version}}" pro-release-commit-message = "cargo: version bump to {{version}}" tag-message = "pams {{version}}" [package.metadata.docs.rs] features = ["libpam"] pamsm-0.5.2/License000064400000000000000000000012240072674642500123010ustar 00000000000000Copyright (c) 2017 raphael.catolino@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . pamsm-0.5.2/readme.md000064400000000000000000000011560072674642500125570ustar 00000000000000# PAM SM [![Crates.io version shield](https://img.shields.io/crates/v/pamsm.svg)](https://crates.io/crates/pamsm) [![Crates.io license shield](https://img.shields.io/crates/l/pamsm.svg)](https://crates.io/crates/pamsm) Rust FFI wrapper to implement PAM service modules for Linux. **[Documentation](https://docs.rs/pamsm/) -** **[Cargo](https://crates.io/crates/pamsm) -** **[Repository](https://github.com/rcatolino/pam_sm_rust)** ## Features This crate supports the following optional features: * `libpam`: this enables the extension trait `PamLibExt` and linking against `libpam.so` for its native implementation. pamsm-0.5.2/src/lib.rs000064400000000000000000000020430072674642500126770ustar 00000000000000// Copyright (C) 2016 Raphael Catolino //! PAM Service Module wrappers //! # Usage //! For example, here is a time based authentication module : //! //! ```rust,no_run //! #[macro_use] extern crate pamsm; //! extern crate time; //! //! use pamsm::{PamServiceModule, Pam, PamFlags, PamError}; //! //! struct PamTime; //! //! impl PamServiceModule for PamTime { //! fn authenticate(pamh: Pam, _: PamFlags, args: Vec) -> PamError { //! let hour = time::OffsetDateTime::now_utc().hour(); //! if hour != 4 { //! // Only allow authentication when it's 4 AM //! PamError::SUCCESS //! } else { //! PamError::AUTH_ERR //! } //! } //! } //! //! pam_module!(PamTime); //! ``` #[macro_use] extern crate bitflags; #[cfg(feature = "libpam")] mod libpam; mod pam; mod pam_types; pub use pam::{Pam, PamError, PamFlags, PamServiceModule}; #[cfg(feature = "libpam")] pub use libpam::{PamCleanupCb, PamData, PamLibExt, PamResult}; #[cfg(feature = "libpam")] pub use pam_types::PamMsgStyle; pamsm-0.5.2/src/libpam.rs000064400000000000000000000346750072674642500134150ustar 00000000000000#![allow(dead_code)] use pam::{Pam, PamError, PamFlags}; use pam_types::{PamConv, PamHandle, PamItemType, PamMessage, PamMsgStyle, PamResponse}; use std::ffi::{CStr, CString, NulError}; use std::ops::Deref; use std::option::Option; use std::os::raw::{c_char, c_int, c_void}; use std::ptr; pub type PamResult = Result; /// Prototype of the callback used with [`PamLibExt::send_bytes`] pub type PamCleanupCb = fn(&Vec, Pam, PamFlags, PamError); #[derive(Clone)] struct PamByteData { cb: Option, data: Vec, } /// Trait to implement for data stored with pam using [`PamLibExt::send_data`] /// in order to provide a cleanup callback. /// # Example /// ``` /// extern crate pamsm; /// use pamsm::{Pam, PamData, PamError, PamFlags}; /// use std::fs::write; /// /// struct Token([u8; 32]); /// /// impl PamData for Token { /// fn cleanup(&self, _pam: Pam, flags: PamFlags, status: PamError) { /// if !flags.contains(PamFlags::DATA_REPLACE) && status == PamError::SUCCESS { /// match write(".token.bin", self.0) { /// Ok(_) => (), /// Err(err) => { /// if !flags.contains(PamFlags::SILENT) { /// println!("Error persisting token : {:?}", err); /// } /// } /// }; /// } /// } /// } /// ``` pub trait PamData { /// The cleanup method will be called before the data is dropped by pam. /// See `pam_set_data (3)` fn cleanup(&self, _pam: Pam, _flags: PamFlags, _status: PamError) {} } impl PamData for PamByteData { fn cleanup(&self, pam: Pam, flags: PamFlags, status: PamError) { if let Some(cb) = self.cb { (cb)(&self.data, pam, flags, status); } } } /// Blanket implementation for types that implement `Deref` when `T` implements `PamData`. impl PamData for U where U: Deref, { fn cleanup(&self, pam: Pam, flags: PamFlags, status: PamError) { T::cleanup(&*self, pam, flags, status) } } impl PamError { fn to_result(self, ok: T) -> PamResult { if self == PamError::SUCCESS { Ok(ok) } else { Err(self) } } } /// This contains a private marker trait, used to seal private traits. mod private { pub trait Sealed {} impl Sealed for super::Pam {} } impl Pam { // End users should call the item specific methods fn get_cstr_item(&self, item_type: PamItemType) -> PamResult> { match item_type { PamItemType::CONV | PamItemType::FAIL_DELAY | PamItemType::XAUTHDATA => { panic!("Error, get_cstr_item can only be used with pam item returning c-strings") } _ => (), } let mut raw_item: *const c_void = ptr::null(); let r = unsafe { PamError::new(pam_get_item(self.0, item_type as c_int, &mut raw_item)) }; if raw_item.is_null() { r.to_result(None) } else { // pam should keep the underlying token allocated during the lifetime of the module r.to_result(Some(unsafe { CStr::from_ptr(raw_item as *const c_char) })) } } } /// Extension trait over `Pam`, usually provided by the `libpam` shared library. pub trait PamLibExt: private::Sealed { /// Get the username. If the PAM_USER item is not set, this function /// prompts for a username (like get_authtok). /// Returns PamError::SERVICE_ERR if the prompt contains any null byte fn get_user(&self, prompt: Option<&str>) -> PamResult>; /// Get the username, i.e. the PAM_USER item. If it's not set return None. fn get_cached_user(&self) -> PamResult>; /// Get the cached authentication token. fn get_cached_authtok(&self) -> PamResult>; /// Get the cached old authentication token. fn get_cached_oldauthtok(&self) -> PamResult>; /// Get the cached authentication token or prompt the user for one if there isn't any. /// Returns PamError::SERVICE_ERR if the prompt contains any null byte fn get_authtok(&self, prompt: Option<&str>) -> PamResult>; fn set_authtok(&self, authtok: &CString) -> PamResult<()>; /// Get the remote hostname. fn get_rhost(&self) -> PamResult>; /// Get the remote username. fn get_ruser(&self) -> PamResult>; /// Get the service name. fn get_service(&self) -> PamResult>; /// Prompt the user for custom input. /// Returns PamError::SERVICE_ERR if the prompt contains any null byte fn conv(&self, prompt: Option<&str>, style: PamMsgStyle) -> PamResult>; /// Get a variable from the pam environment list. fn getenv(&self, name: &str) -> PamResult>; /// Put a variable in the pam environment list. /// `name_value` takes for form documented in pam_putent(3) : /// /// - `NAME=value` will set variable `NAME` to value `value` /// - `NAME=` will set variable `NAME` to an empty value /// - `NAME` will unset the variable `NAME` fn putenv(&self, name_value: &str) -> PamResult<()>; /// Send data to be stored by the pam library under the name `module_name`. /// The data can then be retrieved from a different /// callback in this module, or even by a different module /// using [`retrieve_data`][Self::retrieve_data]. /// /// When this method is called a second time with the same `module_name`, the method /// [`PamData::cleanup`] is called on the data previously stored. /// The same happens when the application calls `pam_end (3)` /// /// If your data can be converted into / from [`Vec`][std::vec::Vec] /// you should consider using the [`send_bytes`][Self::send_bytes] method instead. /// /// # Safety /// This method should not be used if the [`send_bytes`][Self::send_bytes] method is also used /// with the same `module_name`. unsafe fn send_data( &self, module_name: &str, data: T, ) -> PamResult<()>; /// Retrieve data previously stored with [`send_data`][Self::send_data]. /// /// Note that the result is a _copy_ of the data and not a shared reference, /// which differs from the behavior of the underlying `pam_get_data (3)` function. /// /// If you want to share the data instead you can wrap it in [`Arc`][std::sync::Arc]. /// # Safety /// The type parameter `T` must be the same as the one used in /// [`send_data`][Self::send_data] with the name `module_name`. /// /// If the data was stored with [`send_bytes`][Self::send_bytes] you must use /// [`retrieve_bytes`][Self::retrieve_bytes] instead. unsafe fn retrieve_data(&self, module_name: &str) -> PamResult; /// Similar to [`send_data`][Self::send_data], but only works with [`Vec`][std::vec::Vec]. /// The PamData trait doesn't have to be implemented on the data, a callback can be passed /// as an argument instead. fn send_bytes( &self, module_name: &str, data: Vec, cb: Option, ) -> PamResult<()>; /// Retrieve bytes previously stored with [`send_bytes`][Self::send_bytes]. /// The result is a clone of the data. fn retrieve_bytes(&self, module_name: &str) -> PamResult>; } impl From for PamError { fn from(_: NulError) -> PamError { PamError::SERVICE_ERR } } impl PamLibExt for Pam { fn get_user(&self, prompt: Option<&str>) -> PamResult> { let cprompt = match prompt { None => None, Some(p) => Some(CString::new(p)?), }; let mut raw_user: *const c_char = ptr::null(); let r = unsafe { PamError::new(pam_get_user( self.0, &mut raw_user, cprompt.as_ref().map_or(ptr::null(), |p| p.as_ptr()), )) }; if raw_user.is_null() { r.to_result(None) } else { r.to_result(Some(unsafe { CStr::from_ptr(raw_user) })) } } fn get_cached_user(&self) -> PamResult> { self.get_cstr_item(PamItemType::USER) } fn get_cached_authtok(&self) -> PamResult> { self.get_cstr_item(PamItemType::AUTHTOK) } fn get_cached_oldauthtok(&self) -> PamResult> { self.get_cstr_item(PamItemType::OLDAUTHTOK) } fn get_authtok(&self, prompt: Option<&str>) -> PamResult> { let cprompt = match prompt { None => None, Some(p) => Some(CString::new(p)?), }; let mut raw_at: *const c_char = ptr::null(); let r = unsafe { PamError::new(pam_get_authtok( self.0, PamItemType::AUTHTOK as i32, &mut raw_at, cprompt.as_ref().map_or(ptr::null(), |p| p.as_ptr()), )) }; if raw_at.is_null() { r.to_result(None) } else { r.to_result(unsafe { Some(CStr::from_ptr(raw_at)) }) } } fn set_authtok(&self, authtok: &CString) -> PamResult<()> { unsafe { set_item( self.0, PamItemType::AUTHTOK, authtok.as_ptr() as *const c_void, ) } } fn get_rhost(&self) -> PamResult> { self.get_cstr_item(PamItemType::RHOST) } fn get_ruser(&self) -> PamResult> { self.get_cstr_item(PamItemType::RUSER) } fn get_service(&self) -> PamResult> { self.get_cstr_item(PamItemType::SERVICE) } fn conv(&self, prompt: Option<&str>, style: PamMsgStyle) -> PamResult> { let mut conv_pointer: *const c_void = ptr::null(); let r = unsafe { PamError::new(pam_get_item( self.0, PamItemType::CONV as c_int, &mut conv_pointer, )) }; if r != PamError::SUCCESS { return Err(r); } if conv_pointer.is_null() { return Ok(None); } let conv = unsafe { &*(conv_pointer as *const PamConv) }; let mut resp_ptr: *mut PamResponse = ptr::null_mut(); let msg_cstr = CString::new(prompt.unwrap_or(""))?; let msg = PamMessage { msg_style: style, msg: msg_cstr.as_ptr(), }; match conv.cb.map(|cb| { PamError::new(cb( 1, &mut (&msg as *const PamMessage), &mut resp_ptr, conv.appdata_ptr, )) }) { Some(PamError::SUCCESS) => { Ok(unsafe { (*resp_ptr).resp }.map(|r| unsafe { CStr::from_ptr(r.as_ptr()) })) } Some(ret) => Err(ret), None => Ok(None), } } fn getenv(&self, name: &str) -> PamResult> { let cname = CString::new(name)?; let cenv = unsafe { pam_getenv(self.0, cname.as_ptr()) }; if cenv.is_null() { Ok(None) } else { unsafe { Ok(Some(CStr::from_ptr(cenv))) } } } fn putenv(&self, name_value: &str) -> PamResult<()> { let cenv = CString::new(name_value)?; unsafe { PamError::new(pam_putenv(self.0, cenv.as_ptr())).to_result(()) } } unsafe fn send_data( &self, module_name: &str, data: T, ) -> PamResult<()> { // The data has to be allocated on the heap because it will outlive the call stack. let data_copy = Box::new(data); PamError::new(pam_set_data( self.0, CString::new(module_name)?.as_ptr(), Box::into_raw(data_copy) as *mut c_void, Some(pam_data_cleanup::), )) .to_result(()) } unsafe fn retrieve_data(&self, module_name: &str) -> PamResult { let mut data_ptr: *const c_void = ptr::null(); // pam_get_data should be safe as long as T is the type that what used in send_data. PamError::new(pam_get_data( self.0, CString::new(module_name)?.as_ptr(), &mut data_ptr, )) .to_result(data_ptr as *const T) .map(|ptr| (*ptr).clone()) // pam guaranties the data is valid when SUCCESS is returned. } fn send_bytes( &self, module_name: &str, data: Vec, cb: Option, ) -> PamResult<()> { let data_cb = PamByteData { cb, data }; unsafe { self.send_data(module_name, data_cb) } } fn retrieve_bytes(&self, module_name: &str) -> PamResult> { unsafe { self.retrieve_data::(module_name) }.map(|data_cb| data_cb.data) } } unsafe extern "C" fn pam_data_cleanup( handle: PamHandle, data: *mut c_void, error_status: c_int, ) { Box::from_raw(data as *mut T).cleanup( Pam(handle), PamFlags::from_bits_truncate(error_status), PamError::new(error_status & 0xff), ); } unsafe fn set_item(pamh: PamHandle, item_type: PamItemType, item: *const c_void) -> PamResult<()> { PamError::new(pam_set_item(pamh, item_type as c_int, item)).to_result(()) } // Raw functions #[link(name = "pam")] extern "C" { pub fn pam_set_item(pamh: PamHandle, item_type: c_int, item: *const c_void) -> c_int; pub fn pam_get_item(pamh: PamHandle, item_type: c_int, item: *mut *const c_void) -> c_int; pub fn pam_strerror(pamh: PamHandle, errnum: c_int) -> *const c_char; pub fn pam_putenv(pamh: PamHandle, name_value: *const c_char) -> c_int; pub fn pam_getenv(pamh: PamHandle, name: *const c_char) -> *const c_char; pub fn pam_getenvlist(pamh: PamHandle) -> *mut *mut c_char; pub fn pam_set_data( pamh: PamHandle, module_data_name: *const c_char, data: *mut c_void, cleanup: Option, ) -> c_int; pub fn pam_get_data( pamh: PamHandle, module_data_name: *const c_char, data: *mut *const c_void, ) -> c_int; pub fn pam_get_user(pamh: PamHandle, user: *mut *const c_char, prompt: *const c_char) -> c_int; pub fn pam_get_authtok( pamh: PamHandle, item: c_int, authok_ptr: *mut *const c_char, prompt: *const c_char, ) -> c_int; } pamsm-0.5.2/src/pam.rs000064400000000000000000000161140072674642500127120ustar 00000000000000// Copyright (c) 2017 raphael.catolino@gmail.com #![allow(non_camel_case_types)] #![allow(clippy::upper_case_acronyms)] use pam_types::PamHandle; use std::fmt; use std::os::raw::c_int; /// Opaque PAM handle, with additional native methods available via `PamLibExt`. #[repr(transparent)] pub struct Pam(pub(crate) PamHandle); bitflags! { pub struct PamFlags : c_int { const DATA_REPLACE = 0x2000_0000; const SILENT = 0x8000; const DISALLOW_NULL_AUTHTOK = 0x0001; const ESTABLISH_CRED = 0x0002; const DELETE_CRED = 0x0004; const REINITIALIZE_CRED = 0x0008; const REFRESH_CRED = 0x0010; const CHANGE_EXPIRED_AUTHTOK = 0x0020; } } impl fmt::Display for PamError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self) } } macro_rules! int_enum { ( $name:ident ($ukey:ident = $uvalue:expr) { $( $key:ident = $value:expr ),* }) => { #[derive(Clone, Copy, Debug, PartialEq)] pub enum $name { $( $key = $value, )* $ukey = $uvalue, } impl $name { #[cfg(feature = "libpam")] pub(crate) fn new(r: c_int) -> $name { match r { $( $value => $name::$key, )* _ => $name::$ukey, } } } } } int_enum! { PamError (UNKNOWN_RESULT = -1) { SUCCESS = 0, /* Successful function return */ OPEN_ERR = 1, /* dlopen() failure when dynamically */ SYMBOL_ERR = 2, /* Symbol not found */ SERVICE_ERR = 3, /* Error in service module */ SYSTEM_ERR = 4, /* System error */ BUF_ERR = 5, /* Memory buffer error */ PERM_DENIED = 6, /* Permission denied */ AUTH_ERR = 7, /* Authentication failure */ CRED_INSUFFICIENT = 8, /* Can not access authentication data */ AUTHINFO_UNAVAIL = 9, /* Underlying authentication service can not retrieve authentication information */ USER_UNKNOWN = 10, /* User not known to the underlying authenticaiton module */ MAXTRIES = 11, /* An authentication service has maintained a retry count which has been reached. No further retries should be attempted */ NEW_AUTHTOK_REQD = 12, /* New authentication token required. */ ACCT_EXPIRED = 13, /* User account has expired */ SESSION_ERR = 14, /* Can not make/remove an entry for the specified session */ CRED_UNAVAIL = 15, /* Underlying authentication service can not retrieve user credentials */ CRED_EXPIRED = 16, /* User credentials expired */ CRED_ERR = 17, /* Failure setting user credentials */ NO_MODULE_DATA = 18, /* No module specific data is present */ CONV_ERR = 19, /* Conversation error */ AUTHTOK_ERR = 20, /* Authentication token manipulation error */ AUTHTOK_RECOVERY_ERR = 21, /* Authentication information cannot be recovered */ AUTHTOK_LOCK_BUSY = 22, /* Authentication token lock busy */ AUTHTOK_DISABLE_AGING = 23, /* Authentication token aging disabled */ TRY_AGAIN = 24, /* Preliminary check by password service */ IGNORE = 25, /* Ignore underlying account module regardless of whether the control flag is required, optional, or sufficient */ ABORT = 26, /* Critical error (?module fail now request) */ AUTHTOK_EXPIRED = 27, /* user's authentication token has expired */ MODULE_UNKNOWN = 28, /* module is not known */ BAD_ITEM = 29, /* Bad item passed to *_item() */ CONV_AGAIN = 30, /* conversation function is event driven and data is not available yet */ INCOMPLETE = 31 /* please call this function again to complete authentication stack. Before calling again, verify that conversation is completed */ } } /// Default service module implementation. /// All default functions return SERVICE_ERR. /// You can override functions depending on what kind of module you implement. /// See the respective pam_sm_* man pages for documentation. pub trait PamServiceModule { fn open_session(_: Pam, _: PamFlags, _: Vec) -> PamError { PamError::SERVICE_ERR } fn close_session(_: Pam, _: PamFlags, _: Vec) -> PamError { PamError::SERVICE_ERR } fn authenticate(_: Pam, _: PamFlags, _: Vec) -> PamError { PamError::SERVICE_ERR } fn setcred(_: Pam, _: PamFlags, _: Vec) -> PamError { PamError::SERVICE_ERR } fn acct_mgmt(_: Pam, _: PamFlags, _: Vec) -> PamError { PamError::SERVICE_ERR } fn chauthtok(_: Pam, _: PamFlags, _: Vec) -> PamError { PamError::SERVICE_ERR } } /// Define entrypoints for the PAM module. /// /// This macro must be called exactly once in a PAM module. /// It then exports all the pam_sm_* symbols. /// /// The argument to the macro is a type implementing the /// `PamServiceModule` trait. /// /// # Example /// /// ```ignore /// // lib.rs /// #[macro_use] extern crate pamsm; /// /// pam_module!(MyPamService); /// ``` #[macro_export] macro_rules! pam_module { ($pamsm_ty:ty) => { // Check trait bound on input type. fn _check_pamsm_trait() {} fn _t() { _check_pamsm_trait::<$pamsm_ty>() } // Callback entry definition. macro_rules! pam_callback { ($pam_cb:ident, $rust_cb:ident) => { #[no_mangle] #[doc(hidden)] pub unsafe extern "C" fn $pam_cb( pamh: pamsm::Pam, flags: std::os::raw::c_int, argc: std::os::raw::c_int, argv: *const *const std::os::raw::c_char, ) -> std::os::raw::c_int { use std::os::raw::c_int; if argc < 0 { return pamsm::PamError::SERVICE_ERR as std::os::raw::c_int; } let mut args = Vec::::with_capacity(argc as usize); for count in 0..(argc as isize) { match { std::ffi::CStr::from_ptr( *argv.offset(count) as *const std::os::raw::c_char ) .to_str() } { Ok(s) => args.push(s.to_owned()), Err(_) => return pamsm::PamError::SERVICE_ERR as c_int, }; } <$pamsm_ty>::$rust_cb(pamh, PamFlags::from_bits_unchecked(flags), args) as c_int } }; } pam_callback!(pam_sm_open_session, open_session); pam_callback!(pam_sm_close_session, close_session); pam_callback!(pam_sm_authenticate, authenticate); pam_callback!(pam_sm_setcred, setcred); pam_callback!(pam_sm_acct_mgmt, acct_mgmt); pam_callback!(pam_sm_chauthtok, chauthtok); }; } pamsm-0.5.2/src/pam_types.rs000064400000000000000000000043600072674642500141360ustar 00000000000000#![allow(dead_code)] #![allow(non_camel_case_types)] #![allow(clippy::upper_case_acronyms)] use pam::PamError; use std::option::Option; use std::os::raw::{c_char, c_int, c_void}; use std::ptr::NonNull; pub type PamHandle = *const c_void; #[repr(C)] pub enum PamMsgStyle { PROMPT_ECHO_OFF = 1, /* Ask for password without echo */ PROMPT_ECHO_ON = 2, /* Ask for password with echo */ ERROR_MSG = 3, /* Display an error message */ TEXT_INFO = 4, /* Display arbitrary text */ // Linux extensions PAM_MAX_NUM_MSG = 32, PAM_RADIO_TYPE = 5, /* yes/no/maybe conditionals */ PAM_BINARY_PROMPT = 7, } #[repr(C)] pub struct PamMessage { pub msg_style: PamMsgStyle, pub msg: *const c_char, } #[repr(C)] pub struct PamResponse { pub resp: Option>, pub resp_retcode: PamError, } pub(crate) type PamConvCallback = extern "C" fn( num_msg: c_int, msg: *mut *const PamMessage, resp: *mut *mut PamResponse, appdata_ptr: *mut c_void, ) -> c_int; #[repr(C)] pub(crate) struct PamConv { pub(crate) cb: Option, pub(crate) appdata_ptr: *mut c_void, } #[repr(C)] pub enum LogLvl { EMERG = 0, /* system is unusable */ ALERT = 1, /* action must be taken immediately */ CRIT = 2, /* critical conditions */ ERR = 3, /* error conditions */ WARNING = 4, /* warning conditions */ NOTICE = 5, /* normal but significant condition */ INFO = 6, /* informational */ DEBUG = 7, /* debug-level messages */ } #[repr(C)] pub enum PamItemType { SERVICE = 1, /* The service name */ USER = 2, /* The user name */ TTY = 3, /* The tty name */ RHOST = 4, /* The remote host name */ CONV = 5, /* The pam_conv structure */ AUTHTOK = 6, /* The authentication token (password) */ OLDAUTHTOK = 7, /* The old authentication token */ RUSER = 8, /* The remote user name */ USER_PROMPT = 9, /* the prompt for getting a username */ FAIL_DELAY = 10, /* app supplied function to override failure delays */ XDISPLAY = 11, /* X display name */ XAUTHDATA = 12, /* X server authentication data */ AUTHTOK_TYPE = 13, /* The type for pam_get_authtok */ }