diff src/pam_ffi/mod.rs @ 71:58f9d2a4df38

Reorganize everything again??? - Splits ffi/memory stuff into a bunch of stuff in the pam_ffi module. - Builds infrastructure for passing Messages and Responses. - Adds tests for some things at least.
author Paul Fisher <paul@pfish.zone>
date Tue, 03 Jun 2025 21:54:58 -0400
parents src/pam_ffi.rs@9f8381a1c09c
children 47eb242a4f88
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pam_ffi/mod.rs	Tue Jun 03 21:54:58 2025 -0400
@@ -0,0 +1,94 @@
+//! The PAM library FFI and helpers for managing it.
+//!
+//! This includes the functions provided by PAM and the data structures
+//! used by PAM, as well as a few low-level abstractions for dealing with
+//! those data structures.
+//!
+//! Everything in here is hazmat.
+//! 
+
+#![allow(dead_code)]
+
+pub mod memory;
+mod message;
+mod response;
+
+use crate::pam_ffi::memory::Immovable;
+use crate::pam_ffi::message::OwnedMessages;
+pub use message::Message;
+pub use response::RawResponse;
+use std::ffi::{c_char, c_int, c_void};
+
+/// An opaque structure that a PAM handle points to.
+#[repr(C)]
+pub struct Handle {
+    _data: (),
+    _marker: Immovable,
+}
+
+/// An opaque structure that is passed through PAM in a conversation.
+#[repr(C)]
+pub struct AppData {
+    _data: (),
+    _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.
+/// - `messages` is a pointer to the messages being sent to the user.
+///   For details about its structure, see the documentation of
+///   [`OwnedMessages`](super::OwnedMessages).
+/// - `responses` is a pointer to an array of [`RawResponse`]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 `responses` as `num_msg`.
+/// - `appdata` is the `appdata` field of the [`Conversation`] we were passed.
+pub type ConversationCallback = extern "C" fn(
+    num_msg: c_int,
+    messages: &OwnedMessages,
+    responses: &mut *mut RawResponse,
+    appdata: *const AppData,
+) -> c_int;
+
+/// A callback and the associated [`AppData`] pointer that needs to be passed back to it.
+#[repr(C)]
+pub struct Conversation {
+    callback: ConversationCallback,
+    appdata: *const AppData,
+}
+
+#[link(name = "pam")]
+extern "C" {
+    pub fn pam_get_data(
+        pamh: *const Handle,
+        module_data_name: *const c_char,
+        data: &mut *const c_void,
+    ) -> c_int;
+
+    pub fn pam_set_data(
+        pamh: *mut Handle,
+        module_data_name: *const c_char,
+        data: *const c_void,
+        cleanup: extern "C" fn(pamh: *const c_void, data: *mut c_void, error_status: c_int),
+    ) -> c_int;
+
+    pub fn pam_get_item(pamh: *const Handle, item_type: c_int, item: &mut *const c_void) -> c_int;
+
+    pub fn pam_set_item(pamh: *mut Handle, item_type: c_int, item: *const c_void) -> c_int;
+
+    pub fn pam_get_user(
+        pamh: *const Handle,
+        user: &mut *const c_char,
+        prompt: *const c_char,
+    ) -> c_int;
+
+    pub fn pam_get_authtok(
+        pamh: *const Handle,
+        item_type: c_int,
+        data: &mut *const c_char,
+        prompt: *const c_char,
+    ) -> c_int;
+
+    pub fn pam_end(pamh: *mut Handle, status: c_int) -> c_int;
+}