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) |