diff src/libpam/conversation.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 002adfb98c5c
children 05291b601f0a
line wrap: on
line diff
--- a/src/libpam/conversation.rs	Sun Jun 08 04:21:58 2025 -0400
+++ b/src/libpam/conversation.rs	Tue Jun 10 01:09:30 2025 -0400
@@ -3,50 +3,15 @@
 };
 use crate::libpam::answer::{Answer, Answers, BinaryAnswer, TextAnswer};
 use crate::libpam::memory::Immovable;
-use crate::libpam::question::{Indirect, Questions};
+use crate::libpam::pam_ffi::AppData;
+pub use crate::libpam::pam_ffi::LibPamConversation;
+use crate::libpam::question::{Indirect, IndirectTrait, Question, Questions};
 use crate::ErrorCode;
 use crate::Result;
 use std::ffi::c_int;
 use std::iter;
 use std::marker::PhantomData;
 
-/// 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 [`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 `responses` 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,
-    messages: *const Indirect,
-    responses: *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.
-    callback: ConversationCallback,
-    /// The pointer that will be passed as the last parameter
-    /// to the conversation callback.
-    appdata: *mut AppData,
-    life: PhantomData<&'a mut ()>,
-    _marker: Immovable,
-}
-
 impl LibPamConversation<'_> {
     fn wrap<C: Conversation>(conv: &mut C) -> Self {
         Self {
@@ -59,7 +24,7 @@
 
     unsafe extern "C" fn wrapper_callback<C: Conversation>(
         count: c_int,
-        questions: *const Indirect,
+        questions: *const *const Question,
         answers: *mut *mut Answer,
         me: *mut AppData,
     ) -> c_int {
@@ -69,7 +34,7 @@
                 .cast::<C>()
                 .as_mut()
                 .ok_or(ErrorCode::ConversationError)?;
-            let indirect = questions.as_ref().ok_or(ErrorCode::ConversationError)?;
+            let indirect = Indirect::borrow_ptr(questions).ok_or(ErrorCode::ConversationError)?;
             let answers_ptr = answers.as_mut().ok_or(ErrorCode::ConversationError)?;
 
             // Build our owned list of Q&As from the questions we've been asked