Mercurial > crates > nonstick
diff src/libpam/pam_ffi.rs @ 80:5aa1a010f1e8
Start using PAM headers; improve owned/borrowed distinction.
- Uses bindgen to generate bindings (only if needed).
- Gets the story together on owned vs. borrowed handles.
- Reduces number of mutable borrows in handle operation
(since `PamHandle` is neither `Send` nor `Sync`,
we never have to worry about thread safety.
- Improves a bunch of macros so we don't have our own
special syntax for docs.
- Implement question indirection for standard XSSO PAM implementations.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Tue, 10 Jun 2025 01:09:30 -0400 |
parents | |
children | a8f4718fed5d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libpam/pam_ffi.rs Tue Jun 10 01:09:30 2025 -0400 @@ -0,0 +1,115 @@ +//! The types that are directly represented in PAM function signatures. + +#![allow(non_camel_case_types)] + +use crate::libpam::memory::Immovable; +use std::ffi::{c_int, c_void}; +use std::marker::PhantomData; +use num_enum::{IntoPrimitive, TryFromPrimitive}; + +/// An opaque structure that a PAM handle points to. +#[repr(C)] +pub struct LibPamHandle { + _data: (), + _marker: Immovable, +} + +/// An opaque structure that is passed through PAM in a conversation. +#[repr(C)] +pub struct AppData { + _data: (), + _marker: Immovable, +} + +/// Generic version of answer data. +/// +/// This has the same structure as [`BinaryAnswer`](crate::libpam::answer::BinaryAnswer) +/// and [`TextAnswer`](crate::libpam::answer::TextAnswer). +#[repr(C)] +#[derive(Debug)] +pub struct Answer { + /// Pointer to the data returned in an answer. + /// For most answers, this will be a [`CStr`](std::ffi::CStr), + /// but for [`BinaryQAndA`](crate::conv::BinaryQAndA)s (a Linux-PAM extension), + /// this will be [`CBinaryData`](crate::libpam::memory::CBinaryData) + pub data: *mut c_void, + /// Unused. + return_code: c_int, + _marker: Immovable, +} + +/// The C enum values for messages shown to the user. +#[derive(Debug, PartialEq, TryFromPrimitive, IntoPrimitive)] +#[repr(i32)] +pub enum Style { + /// Requests information from the user; will be masked when typing. + PromptEchoOff = 1, + /// Requests information from the user; will not be masked. + PromptEchoOn = 2, + /// An error message. + ErrorMsg = 3, + /// An informational message. + TextInfo = 4, + /// Yes/No/Maybe conditionals. A Linux-PAM extension. + RadioType = 5, + /// For server–client non-human interaction. + /// + /// NOT part of the X/Open PAM specification. + /// A Linux-PAM extension. + BinaryPrompt = 7, +} + +/// A question sent by PAM or a module to an application. +/// +/// PAM refers to this as a "message", but we call it a question +/// to avoid confusion with [`Message`](crate::Message). +/// +/// This question, and its internal data, is owned by its creator +/// (either the module or PAM itself). +#[repr(C)] +pub struct Question { + /// The style of message to request. + pub style: c_int, + /// A description of the data requested. + /// + /// For most requests, this will be an owned [`CStr`](std::ffi::CStr), but for requests + /// with [`Style::BinaryPrompt`], this will be [`CBinaryData`] + /// (a Linux-PAM extension). + pub data: *mut c_void, + pub _marker: Immovable, +} + +/// The callback that PAM uses to get information in a conversation. +/// +/// - `num_msg` is the number of messages in the `pam_message` array. +/// - `questions` is a pointer to the [`Question`]s being sent to the user. +/// For information about its structure, +/// see [`GenericQuestions`](super::question::GenericQuestions). +/// - `answers` is a pointer to an array of [`Answer`]s, +/// which PAM sets in response to a module's request. +/// This is an array of structs, not an array of pointers to a struct. +/// There should always be exactly as many `answers` as `num_msg`. +/// - `appdata` is the `appdata` field of the [`LibPamConversation`] we were passed. +pub type ConversationCallback = unsafe extern "C" fn( + num_msg: c_int, + questions: *const *const Question, + answers: *mut *mut Answer, + appdata: *mut AppData, +) -> c_int; + +/// The type used by PAM to call back into a conversation. +#[repr(C)] +pub struct LibPamConversation<'a> { + /// The function that is called to get information from the user. + pub callback: ConversationCallback, + /// The pointer that will be passed as the last parameter + /// to the conversation callback. + pub appdata: *mut AppData, + pub life: PhantomData<&'a mut ()>, + pub _marker: Immovable, +} + +type pam_handle = LibPamHandle; +type pam_conv = LibPamConversation<'static>; + +include!(concat!(env!("OUT_DIR"), "/bindings.rs"));