Mercurial > crates > nonstick
view src/conv.rs @ 69:8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
This removes the old `Conversation` type and reworks the FFI types
used for PAM conversations.
This creates safe `TestResponse` and `BinaryResponse` structures in `conv`,
providing a safe way to pass response messages to PAM Conversations.
The internals of these types are allocated on the C heap, as required by PAM.
We also remove the Conversation struct, which was specific to the real PAM
implementation so that we can introduce a better abstraction.
Also splits a new `PamApplicationHandle` trait from `PamHandle`,
for the parts of a PAM handle that are specific to the application side
of a PAM transaction.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sun, 01 Jun 2025 01:15:04 -0400 |
parents | bbe84835d6db |
children | 9f8381a1c09c |
line wrap: on
line source
//! The PAM conversation and associated Stuff. use crate::pam_ffi::{BinaryResponseInner, NulError, TextResponseInner}; use std::num::TryFromIntError; use std::ops::Deref; use std::result::Result as StdResult; /// An owned text response to a PAM conversation. /// /// It points to a value on the C heap. #[repr(C)] struct TextResponse(*mut TextResponseInner); impl TextResponse { /// Creates a text response. pub fn new(text: impl AsRef<str>) -> StdResult<Self, NulError> { TextResponseInner::alloc(text).map(Self) } } impl Deref for TextResponse { type Target = TextResponseInner; fn deref(&self) -> &Self::Target { // SAFETY: We allocated this ourselves, or it was provided by PAM. unsafe { &*self.0 } } } impl Drop for TextResponse { /// Frees an owned response. fn drop(&mut self) { // SAFETY: We allocated this ourselves, or it was provided by PAM. unsafe { TextResponseInner::free(self.0) } } } /// An owned binary response to a PAM conversation. /// /// It points to a value on the C heap. #[repr(C)] struct BinaryResponse(*mut BinaryResponseInner); impl BinaryResponse { /// Creates a binary response with the given data. pub fn new(data: impl AsRef<[u8]>, data_type: u8) -> StdResult<Self, TryFromIntError> { BinaryResponseInner::alloc(data, data_type).map(Self) } } impl Deref for BinaryResponse { type Target = BinaryResponseInner; fn deref(&self) -> &Self::Target { // SAFETY: We allocated this ourselves, or it was provided by PAM. unsafe { &*self.0 } } } impl Drop for BinaryResponse { /// Frees an owned response. fn drop(&mut self) { // SAFETY: We allocated this ourselves, or it was provided by PAM. unsafe { BinaryResponseInner::free(self.0) } } } #[cfg(test)] mod test { use super::{BinaryResponse, TextResponse}; #[test] fn test_text_response() { let resp = TextResponse::new("it's a-me!").unwrap(); assert_eq!("it's a-me!", resp.contents().to_str().unwrap()); } #[test] fn test_binary_response() { let data = [123, 210, 55]; let resp = BinaryResponse::new(&data, 99).unwrap(); assert_eq!(&data, resp.contents()); } }