comparison src/libpam/conversation.rs @ 141:a508a69c068a

Remove a lot of Results from functions. Many functions are documented to only return failing Results when given improper inputs or when there is a memory allocation failure (which can be verified by looking at the source). In cases where we know our input is correct, we don't need to check for memory allocation errors for the same reason that Rust doesn't do so when you, e.g., create a new Vec.
author Paul Fisher <paul@pfish.zone>
date Sat, 05 Jul 2025 17:16:56 -0400
parents 33b9622ed6d2
children 4b3a5095f68c
comparison
equal deleted inserted replaced
140:add7228adb2f 141:a508a69c068a
3 use crate::libpam::answer::BinaryAnswer; 3 use crate::libpam::answer::BinaryAnswer;
4 use crate::libpam::answer::{Answer, Answers, TextAnswer}; 4 use crate::libpam::answer::{Answer, Answers, TextAnswer};
5 use crate::libpam::question::Question; 5 use crate::libpam::question::Question;
6 use crate::ErrorCode; 6 use crate::ErrorCode;
7 use crate::Result; 7 use crate::Result;
8 use libpam_sys::AppData; 8 use libpam_sys::{AppData, ConversationCallback};
9 use libpam_sys_helpers::memory::PtrPtrVec; 9 use libpam_sys_helpers::memory::PtrPtrVec;
10 use std::ffi::c_int; 10 use std::ffi::c_int;
11 use std::iter; 11 use std::iter;
12 use std::marker::PhantomData;
13 use std::ptr::NonNull; 12 use std::ptr::NonNull;
14 use std::result::Result as StdResult; 13 use std::result::Result as StdResult;
15 14
16 /// The type used by PAM to call back into a conversation. 15 /// The type used by PAM to call back into a conversation.
16 ///
17 /// This has the same structure as a [`libpam_sys::pam_conv`].
18 #[derive(Debug)]
17 #[repr(C)] 19 #[repr(C)]
18 pub struct LibPamConversation<'a> { 20 pub struct OwnedConversation<C: Conversation> {
19 pam_conv: libpam_sys::pam_conv, 21 callback: ConversationCallback,
20 /// Marker to associate the lifetime of this with the conversation 22 conv: Box<C>,
21 /// that was passed in.
22 pub life: PhantomData<&'a mut ()>,
23 } 23 }
24 24
25 impl LibPamConversation<'_> { 25 impl<C: Conversation> OwnedConversation<C> {
26 pub fn wrap<C: Conversation>(conv: &C) -> Self { 26 pub fn new(conv: C) -> Self {
27 Self { 27 Self {
28 pam_conv: libpam_sys::pam_conv { 28 callback: Self::wrapper_callback,
29 conv: Self::wrapper_callback::<C>, 29 conv: Box::new(conv),
30 appdata_ptr: (conv as *const C).cast_mut().cast(),
31 },
32 life: PhantomData,
33 } 30 }
34 } 31 }
35 32
36 /// Passed as the conversation function into PAM for an owned handle. 33 /// Passed as the conversation function into PAM for an owned handle.
37 /// 34 ///
38 /// PAM calls this, we compute answers, then send them back. 35 /// PAM calls this, we compute answers, then send them back.
39 unsafe extern "C" fn wrapper_callback<C: Conversation>( 36 unsafe extern "C" fn wrapper_callback(
40 count: c_int, 37 count: c_int,
41 questions: *const *const libpam_sys::pam_message, 38 questions: *const *const libpam_sys::pam_message,
42 answers: *mut *mut libpam_sys::pam_response, 39 answers: *mut *mut libpam_sys::pam_response,
43 me: *mut AppData, 40 me: *mut AppData,
44 ) -> c_int { 41 ) -> c_int {
69 }; 66 };
70 ErrorCode::result_to_c(internal()) 67 ErrorCode::result_to_c(internal())
71 } 68 }
72 } 69 }
73 70
74 impl Conversation for LibPamConversation<'_> { 71 /// A conversation owned by a PAM handle and lent to us.
72 pub struct PamConv(libpam_sys::pam_conv);
73
74 impl Conversation for PamConv {
75 fn communicate(&self, messages: &[Exchange]) { 75 fn communicate(&self, messages: &[Exchange]) {
76 let internal = || { 76 let internal = || {
77 let questions: Result<_> = messages.iter().map(Question::try_from).collect(); 77 let questions: Result<_> = messages.iter().map(Question::try_from).collect();
78 let questions = PtrPtrVec::new(questions?); 78 let questions = PtrPtrVec::new(questions?);
79 let mut response_pointer = std::ptr::null_mut(); 79 let mut response_pointer = std::ptr::null_mut();
80 // SAFETY: We're calling into PAM with valid everything. 80 // SAFETY: We're calling into PAM with valid everything.
81 let result = unsafe { 81 let result = unsafe {
82 (self.pam_conv.conv)( 82 (self.0.conv)(
83 messages.len() as c_int, 83 messages.len() as c_int,
84 questions.as_ptr(), 84 questions.as_ptr(),
85 &mut response_pointer, 85 &mut response_pointer,
86 self.pam_conv.appdata_ptr, 86 self.0.appdata_ptr,
87 ) 87 )
88 }; 88 };
89 ErrorCode::result_from(result)?; 89 ErrorCode::result_from(result)?;
90 // SAFETY: This is a pointer we just got back from PAM. 90 // SAFETY: This is a pointer we just got back from PAM.
91 // We have to trust that the responses from PAM match up 91 // We have to trust that the responses from PAM match up