Mercurial > crates > nonstick
diff libpam-sys/src/structs.rs @ 118:39760dfc9b3b
Detect PAM library based only on system lib; rename minimal lib to XSso.
Also formats and assorted other cleanup.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sun, 29 Jun 2025 20:13:03 -0400 |
parents | 20f7712a6857 |
children | 476a22db8639 |
line wrap: on
line diff
--- a/libpam-sys/src/structs.rs Sun Jun 29 18:48:14 2025 -0400 +++ b/libpam-sys/src/structs.rs Sun Jun 29 20:13:03 2025 -0400 @@ -1,76 +1,71 @@ -use core::marker::{PhantomData, PhantomPinned}; -use core::slice; +use std::ffi::{c_int, 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(transparent)] +struct ExtremelyUnsafe(PhantomData<(PhantomPinned, *mut c_void)>); + +impl fmt::Debug for ExtremelyUnsafe { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("ExtremelyUnsafe") + } +} -/// The structure of the "binary message" payload for the `PAM_BINARY_PROMPT` -/// extension from Linux-PAM. -pub struct BinaryPayload { - /// The total byte size of the message, including this header, - /// as a u32 in network byte order (big endian). - pub total_bytes_u32be: [u8; 4], - /// A tag used to provide some kind of hint as to what the data is. - /// Its meaning is undefined. - pub data_type: u8, - /// Where the data itself would start, used as a marker to make this - /// not [`Unpin`] (since it is effectively an intrusive data structure - /// pointing to immediately after itself). - pub _marker: PhantomData<PhantomPinned>, +/// An opaque structure that PAM uses to communicate. +/// +/// This is only ever returned in pointer form and cannot be constructed. +#[repr(C)] +pub struct PamHandle { + _marker: ExtremelyUnsafe, +} + +impl fmt::Debug for PamHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "PamHandle({self:p}") + } +} + +/// An opaque structure that is passed through PAM in a conversation. +pub struct AppData { + _marker: ExtremelyUnsafe, } -impl BinaryPayload { - /// The most data it's possible to put into a [`BinaryPayload`]. - pub const MAX_SIZE: usize = (u32::MAX - 5) as usize; - - /// Fills in the provided buffer with the given data. - /// - /// This uses [`copy_from_slice`](slice::copy_from_slice) internally, - /// so `buf` must be exactly 5 bytes longer than `data`, or this function - /// will panic. - pub fn fill(buf: &mut [u8], data_type: u8, data: &[u8]) { - let ptr: *mut Self = buf.as_mut_ptr().cast(); - // SAFETY: We're given a slice, which always has a nonzero pointer. - let me = unsafe { ptr.as_mut().unwrap_unchecked() }; - me.total_bytes_u32be = u32::to_be_bytes(buf.len() as u32); - me.data_type = data_type; - buf[5..].copy_from_slice(data) - } - - /// The total storage needed for the message, including header. - pub fn total_bytes(&self) -> usize { - u32::from_be_bytes(self.total_bytes_u32be) as usize - } - - /// Gets the total byte buffer of the BinaryMessage stored at the pointer. - /// - /// The returned data slice is borrowed from where the pointer points to. - /// - /// # Safety - /// - /// - The pointer must point to a valid `BinaryPayload`. - /// - The borrowed data must not outlive the pointer's validity. - pub unsafe fn buffer_of<'a>(ptr: *const Self) -> &'a [u8] { - let header: &Self = ptr.as_ref().unwrap_unchecked(); - slice::from_raw_parts(ptr.cast(), header.total_bytes().max(5)) - } - - /// Gets the contents of the BinaryMessage stored at the given pointer. - /// - /// The returned data slice is borrowed from where the pointer points to. - /// This is a cheap operation and doesn't do *any* copying. - /// - /// We don't take a `&self` reference here because accessing beyond - /// the range of the `Self` data (i.e., beyond the 5 bytes of `self`) - /// is undefined behavior. Instead, you have to pass a raw pointer - /// directly to the data. - /// - /// # Safety - /// - /// - The pointer must point to a valid `BinaryPayload`. - /// - The borrowed data must not outlive the pointer's validity. - pub unsafe fn contents<'a>(ptr: *const Self) -> (u8, &'a [u8]) { - let header: &Self = ptr.as_ref().unwrap_unchecked(); - ( - header.data_type, - &Self::buffer_of(ptr)[5..] - ) +impl fmt::Debug for AppData { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "AppData({self:p}") } } + +/// The callback that PAM uses to get information in a conversation. +/// +/// For important details about the format of `messages`, +/// see the [`helpers`](crate::helpers) module. +pub type ConversationCallback = unsafe extern "C" fn( + num_msg: c_int, + messages: *const *const Message, + responses: &mut *mut Response, + appdata: *const AppData, +) -> c_int; + +/// Used by PAM to communicate between the module and the application. +#[repr(C)] +pub struct Conversation { + pub callback: ConversationCallback, + pub appdata: *const AppData, +} + +/// A message sent into a PAM conversation. +#[repr(C)] +pub struct Message { + pub style: c_int, + pub data: *const c_void, +} + +/// A response returned from a PAM conversation. +#[repr(C)] +pub struct Response { + pub data: *mut c_void, + pub _unused: c_int, +}