Mercurial > crates > nonstick
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 79:2128123b9406 | 80:5aa1a010f1e8 |
|---|---|
| 1 use crate::conv::{ | 1 use crate::conv::{ |
| 2 BinaryQAndA, Conversation, ErrorMsg, InfoMsg, MaskedQAndA, Message, QAndA, RadioQAndA, | 2 BinaryQAndA, Conversation, ErrorMsg, InfoMsg, MaskedQAndA, Message, QAndA, RadioQAndA, |
| 3 }; | 3 }; |
| 4 use crate::libpam::answer::{Answer, Answers, BinaryAnswer, TextAnswer}; | 4 use crate::libpam::answer::{Answer, Answers, BinaryAnswer, TextAnswer}; |
| 5 use crate::libpam::memory::Immovable; | 5 use crate::libpam::memory::Immovable; |
| 6 use crate::libpam::question::{Indirect, Questions}; | 6 use crate::libpam::pam_ffi::AppData; |
| 7 pub use crate::libpam::pam_ffi::LibPamConversation; | |
| 8 use crate::libpam::question::{Indirect, IndirectTrait, Question, Questions}; | |
| 7 use crate::ErrorCode; | 9 use crate::ErrorCode; |
| 8 use crate::Result; | 10 use crate::Result; |
| 9 use std::ffi::c_int; | 11 use std::ffi::c_int; |
| 10 use std::iter; | 12 use std::iter; |
| 11 use std::marker::PhantomData; | 13 use std::marker::PhantomData; |
| 12 | |
| 13 /// An opaque structure that is passed through PAM in a conversation. | |
| 14 #[repr(C)] | |
| 15 pub struct AppData { | |
| 16 _data: (), | |
| 17 _marker: Immovable, | |
| 18 } | |
| 19 | |
| 20 /// The callback that PAM uses to get information in a conversation. | |
| 21 /// | |
| 22 /// - `num_msg` is the number of messages in the `pam_message` array. | |
| 23 /// - `messages` is a pointer to the messages being sent to the user. | |
| 24 /// For details about its structure, see the documentation of | |
| 25 /// [`OwnedMessages`](super::OwnedMessages). | |
| 26 /// - `responses` is a pointer to an array of [`Answer`]s, | |
| 27 /// which PAM sets in response to a module's request. | |
| 28 /// This is an array of structs, not an array of pointers to a struct. | |
| 29 /// There should always be exactly as many `responses` as `num_msg`. | |
| 30 /// - `appdata` is the `appdata` field of the [`LibPamConversation`] we were passed. | |
| 31 pub type ConversationCallback = unsafe extern "C" fn( | |
| 32 num_msg: c_int, | |
| 33 messages: *const Indirect, | |
| 34 responses: *mut *mut Answer, | |
| 35 appdata: *mut AppData, | |
| 36 ) -> c_int; | |
| 37 | |
| 38 /// The type used by PAM to call back into a conversation. | |
| 39 #[repr(C)] | |
| 40 pub struct LibPamConversation<'a> { | |
| 41 /// The function that is called to get information from the user. | |
| 42 callback: ConversationCallback, | |
| 43 /// The pointer that will be passed as the last parameter | |
| 44 /// to the conversation callback. | |
| 45 appdata: *mut AppData, | |
| 46 life: PhantomData<&'a mut ()>, | |
| 47 _marker: Immovable, | |
| 48 } | |
| 49 | 14 |
| 50 impl LibPamConversation<'_> { | 15 impl LibPamConversation<'_> { |
| 51 fn wrap<C: Conversation>(conv: &mut C) -> Self { | 16 fn wrap<C: Conversation>(conv: &mut C) -> Self { |
| 52 Self { | 17 Self { |
| 53 callback: Self::wrapper_callback::<C>, | 18 callback: Self::wrapper_callback::<C>, |
| 57 } | 22 } |
| 58 } | 23 } |
| 59 | 24 |
| 60 unsafe extern "C" fn wrapper_callback<C: Conversation>( | 25 unsafe extern "C" fn wrapper_callback<C: Conversation>( |
| 61 count: c_int, | 26 count: c_int, |
| 62 questions: *const Indirect, | 27 questions: *const *const Question, |
| 63 answers: *mut *mut Answer, | 28 answers: *mut *mut Answer, |
| 64 me: *mut AppData, | 29 me: *mut AppData, |
| 65 ) -> c_int { | 30 ) -> c_int { |
| 66 let internal = || { | 31 let internal = || { |
| 67 // Collect all our pointers | 32 // Collect all our pointers |
| 68 let conv = me | 33 let conv = me |
| 69 .cast::<C>() | 34 .cast::<C>() |
| 70 .as_mut() | 35 .as_mut() |
| 71 .ok_or(ErrorCode::ConversationError)?; | 36 .ok_or(ErrorCode::ConversationError)?; |
| 72 let indirect = questions.as_ref().ok_or(ErrorCode::ConversationError)?; | 37 let indirect = Indirect::borrow_ptr(questions).ok_or(ErrorCode::ConversationError)?; |
| 73 let answers_ptr = answers.as_mut().ok_or(ErrorCode::ConversationError)?; | 38 let answers_ptr = answers.as_mut().ok_or(ErrorCode::ConversationError)?; |
| 74 | 39 |
| 75 // Build our owned list of Q&As from the questions we've been asked | 40 // Build our owned list of Q&As from the questions we've been asked |
| 76 let messages: Vec<OwnedMessage> = indirect | 41 let messages: Vec<OwnedMessage> = indirect |
| 77 .iter(count as usize) | 42 .iter(count as usize) |
