Mercurial > crates > nonstick
diff src/libpam/conversation.rs @ 87:05291b601f0a
Well and truly separate the Linux extensions.
This separates the Linux extensions on the libpam side,
and disables the two enums on the interface side.
Users can still call the Linux extensions from non-Linux PAM impls,
but they'll get a conversation error back.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Tue, 10 Jun 2025 04:40:01 -0400 |
parents | 5aa1a010f1e8 |
children |
line wrap: on
line diff
--- a/src/libpam/conversation.rs Tue Jun 10 02:43:31 2025 -0400 +++ b/src/libpam/conversation.rs Tue Jun 10 04:40:01 2025 -0400 @@ -1,7 +1,7 @@ -use crate::conv::{ - BinaryQAndA, Conversation, ErrorMsg, InfoMsg, MaskedQAndA, Message, QAndA, RadioQAndA, -}; -use crate::libpam::answer::{Answer, Answers, BinaryAnswer, TextAnswer}; +use crate::conv::{BinaryQAndA, RadioQAndA}; +use crate::conv::{Conversation, ErrorMsg, InfoMsg, MaskedQAndA, Message, QAndA}; +use crate::libpam::answer::BinaryAnswer; +use crate::libpam::answer::{Answer, Answers, TextAnswer}; use crate::libpam::memory::Immovable; use crate::libpam::pam_ffi::AppData; pub use crate::libpam::pam_ffi::LibPamConversation; @@ -11,6 +11,7 @@ use std::ffi::c_int; use std::iter; use std::marker::PhantomData; +use std::result::Result as StdResult; impl LibPamConversation<'_> { fn wrap<C: Conversation>(conv: &mut C) -> Self { @@ -22,6 +23,9 @@ } } + /// Passed as the conversation function into PAM for an owned handle. + /// + /// PAM calls this, we compute answers, then send them back. unsafe extern "C" fn wrapper_callback<C: Conversation>( count: c_int, questions: *const *const Question, @@ -43,11 +47,13 @@ .map(TryInto::try_into) .collect::<Result<_>>() .map_err(|_| ErrorCode::ConversationError)?; - // Borrow all those Q&As and ask them - let borrowed: Vec<Message> = messages.iter().map(Into::into).collect(); - conv.communicate(&borrowed); + // Borrow all those Q&As and ask them. + // If we got an invalid message type, bail before sending. + let borrowed: Result<Vec<_>> = messages.iter().map(Message::try_from).collect(); + // TODO: Do we want to log something here? + conv.communicate(&borrowed?); - // Send our answers back + // Send our answers back. let owned = Answers::build(messages).map_err(|_| ErrorCode::ConversationError)?; *answers_ptr = owned.into_ptr(); Ok(()) @@ -93,21 +99,22 @@ pub enum OwnedMessage<'a> { MaskedPrompt(MaskedQAndA<'a>), Prompt(QAndA<'a>), + Info(InfoMsg<'a>), + Error(ErrorMsg<'a>), RadioPrompt(RadioQAndA<'a>), BinaryPrompt(BinaryQAndA<'a>), - Info(InfoMsg<'a>), - Error(ErrorMsg<'a>), } -impl<'a> From<&'a OwnedMessage<'a>> for Message<'a> { - fn from(src: &'a OwnedMessage) -> Self { +impl<'a> TryFrom<&'a OwnedMessage<'a>> for Message<'a> { + type Error = ErrorCode; + fn try_from(src: &'a OwnedMessage) -> StdResult<Self, ErrorCode> { match src { - OwnedMessage::MaskedPrompt(m) => Message::MaskedPrompt(m), - OwnedMessage::Prompt(m) => Message::Prompt(m), - OwnedMessage::RadioPrompt(m) => Message::RadioPrompt(m), - OwnedMessage::BinaryPrompt(m) => Message::BinaryPrompt(m), - OwnedMessage::Info(m) => Message::Info(m), - OwnedMessage::Error(m) => Message::Error(m), + OwnedMessage::MaskedPrompt(m) => Ok(Message::MaskedPrompt(m)), + OwnedMessage::Prompt(m) => Ok(Message::Prompt(m)), + OwnedMessage::Info(m) => Ok(Message::Info(m)), + OwnedMessage::Error(m) => Ok(Message::Error(m)), + OwnedMessage::RadioPrompt(m) => Ok(Message::RadioPrompt(m)), + OwnedMessage::BinaryPrompt(m) => Ok(Message::BinaryPrompt(m)), } } } @@ -127,9 +134,9 @@ match *msg { Message::MaskedPrompt(qa) => fill_text!(qa, resp), Message::Prompt(qa) => fill_text!(qa, resp), - Message::RadioPrompt(qa) => fill_text!(qa, resp), Message::Error(m) => m.set_answer(Ok(())), Message::Info(m) => m.set_answer(Ok(())), + Message::RadioPrompt(qa) => fill_text!(qa, resp), Message::BinaryPrompt(qa) => { let bin_resp = unsafe { BinaryAnswer::upcast(resp) }; qa.set_answer(Ok(bin_resp.data().into()));