annotate src/pam_ffi.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 a674799a5cd3
children 9f8381a1c09c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
69
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
1 //! The PAM library FFI and helpers for managing it.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
2 //!
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
3 //! This includes the functions provided by PAM and the data structures
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
4 //! used by PAM, as well as a few low-level abstractions for dealing with
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
5 //! those data structures.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
6 //!
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
7 //! Everything in here is hazmat.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
8
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
9 // Temporarily allow dead code.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
10 #![allow(dead_code)]
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
11
69
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
12 use crate::constants::InvalidEnum;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
13 use num_derive::FromPrimitive;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
14 use num_traits::FromPrimitive;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
15 use std::ffi::{c_char, c_int, c_void, CStr};
66
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
16 use std::marker::{PhantomData, PhantomPinned};
69
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
17 use std::num::TryFromIntError;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
18 use std::slice;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
19 use thiserror::Error;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
20
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
21 /// Makes whatever it's in not [`Send`], [`Sync`], or [`Unpin`].
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
22 type Immovable = PhantomData<(*mut u8, PhantomPinned)>;
66
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
23
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
24 /// An opaque pointer given to us by PAM.
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
25 #[repr(C)]
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
26 pub struct Handle {
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
27 _data: (),
69
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
28 _marker: Immovable,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
29 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
30
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
31 /// Styles of message that are shown to the user.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
32 #[derive(Debug, PartialEq, FromPrimitive)]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
33 #[non_exhaustive] // non-exhaustive because C might give us back anything!
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
34 pub enum MessageStyle {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
35 /// Requests information from the user; will be masked when typing.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
36 PromptEchoOff = 1,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
37 /// Requests information from the user; will not be masked.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
38 PromptEchoOn = 2,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
39 /// An error message.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
40 ErrorMsg = 3,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
41 /// An informational message.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
42 TextInfo = 4,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
43 /// Yes/No/Maybe conditionals. Linux-PAM specific.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
44 RadioType = 5,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
45 /// For server–client non-human interaction.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
46 /// NOT part of the X/Open PAM specification.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
47 BinaryPrompt = 7,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
48 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
49
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
50 impl TryFrom<c_int> for MessageStyle {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
51 type Error = InvalidEnum<Self>;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
52 fn try_from(value: c_int) -> std::result::Result<Self, Self::Error> {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
53 Self::from_i32(value).ok_or(value.into())
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
54 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
55 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
56
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
57 impl From<MessageStyle> for c_int {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
58 fn from(val: MessageStyle) -> Self {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
59 val as Self
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
60 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
61 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
62
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
63 /// A message sent by PAM or a module to an application.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
64 /// This message, and its internal data, is owned by the creator
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
65 /// (either the module or PAM itself).
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
66 #[repr(C)]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
67 pub struct Message {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
68 /// The style of message to request.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
69 style: c_int,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
70 /// A description of the data requested.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
71 /// For most requests, this will be an owned [`CStr`], but for requests
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
72 /// with [`MessageStyle::BinaryPrompt`], this will be [`BinaryData`].
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
73 data: *const c_void,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
74 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
75
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
76 /// Returned when text that should not have any `\0` bytes in it does.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
77 /// Analogous to [`std::ffi::NulError`], but the data it was created from
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
78 /// is borrowed.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
79 #[derive(Debug, Error)]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
80 #[error("null byte within input at byte {0}")]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
81 pub struct NulError(usize);
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
82
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
83 #[repr(transparent)]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
84 pub struct TextResponseInner(ResponseInner);
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
85
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
86 impl TextResponseInner {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
87 /// Allocates a new text response on the C heap.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
88 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
89 /// Both `self` and its internal pointer are located on the C heap.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
90 /// You are responsible for calling [`free`](Self::free)
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
91 /// on the pointer you get back when you're done with it.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
92 pub fn alloc(text: impl AsRef<str>) -> Result<*mut Self, NulError> {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
93 let str_data = Self::malloc_str(text)?;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
94 let inner = ResponseInner::alloc(str_data);
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
95 Ok(inner as *mut Self)
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
96 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
97
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
98 /// Gets the string stored in this response.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
99 pub fn contents(&self) -> &CStr {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
100 // SAFETY: This data is either passed from PAM (so we are forced to
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
101 // trust it) or was created by us in TextResponseInner::alloc.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
102 // In either case, it's going to be a valid null-terminated string.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
103 unsafe { CStr::from_ptr(self.0.data as *const c_char) }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
104 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
105
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
106 /// Releases memory owned by this response.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
107 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
108 /// # Safety
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
109 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
110 /// You are responsible for no longer using this after calling free.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
111 pub unsafe fn free(me: *mut Self) {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
112 ResponseInner::free(me as *mut ResponseInner)
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
113 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
114
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
115 /// Allocates a string with the given contents on the C heap.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
116 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
117 /// This is like [`CString::new`](std::ffi::CString::new), but:
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
118 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
119 /// - it allocates data on the C heap with [`libc::malloc`].
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
120 /// - it doesn't take ownership of the data passed in.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
121 fn malloc_str(text: impl AsRef<str>) -> Result<*const c_void, NulError> {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
122 let data = text.as_ref().as_bytes();
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
123 if let Some(nul) = data.iter().position(|x| *x == 0) {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
124 return Err(NulError(nul));
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
125 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
126 unsafe {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
127 let data_alloc = libc::calloc(data.len() + 1, 1);
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
128 libc::memcpy(data_alloc, data.as_ptr() as *const c_void, data.len());
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
129 Ok(data_alloc as *const c_void)
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
130 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
131 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
132 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
133
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
134 /// A [`ResponseInner`] with [`BinaryData`] in it.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
135 #[repr(transparent)]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
136 pub struct BinaryResponseInner(ResponseInner);
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
137
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
138 impl BinaryResponseInner {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
139 /// Allocates a new binary response on the C heap.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
140 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
141 /// The `data_type` is a tag you can use for whatever.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
142 /// It is passed through PAM unchanged.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
143 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
144 /// The referenced data is copied to the C heap. We do not take ownership.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
145 /// You are responsible for calling [`free`](Self::free)
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
146 /// on the pointer you get back when you're done with it.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
147 pub fn alloc(data: impl AsRef<[u8]>, data_type: u8) -> Result<*mut Self, TryFromIntError> {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
148 let bin_data = BinaryData::alloc(data, data_type)?;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
149 let inner = ResponseInner::alloc(bin_data as *const c_void);
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
150 Ok(inner as *mut Self)
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
151 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
152
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
153 /// Gets the binary data in this response.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
154 pub fn contents(&self) -> &[u8] {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
155 let data = self.data();
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
156 let length = (u32::from_be_bytes(data.total_length) - 5) as usize;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
157 unsafe { slice::from_raw_parts(data.data.as_ptr(), length) }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
158 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
159
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
160 /// Gets the `data_type` tag that was embedded with the message.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
161 pub fn data_type(&self) -> u8 {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
162 self.data().data_type
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
163 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
164
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
165 #[inline]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
166 fn data(&self) -> &BinaryData {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
167 // SAFETY: This was either something we got from PAM (in which case
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
168 // we trust it), or something that was created with
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
169 // BinaryResponseInner::alloc. In both cases, it points to valid data.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
170 unsafe { &*(self.0.data as *const BinaryData) }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
171 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
172
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
173 /// Releases memory owned by this response.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
174 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
175 /// # Safety
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
176 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
177 /// You are responsible for not using this after calling free.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
178 pub unsafe fn free(me: *mut Self) {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
179 ResponseInner::free(me as *mut ResponseInner)
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
180 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
181 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
182
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
183 #[repr(C)]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
184 pub struct ResponseInner {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
185 /// Pointer to the data returned in a response.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
186 /// For most responses, this will be a [`CStr`], but for responses to
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
187 /// [`MessageStyle::BinaryPrompt`]s, this will be [`BinaryData`]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
188 data: *const c_void,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
189 /// Unused.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
190 return_code: c_int,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
191 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
192
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
193 impl ResponseInner {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
194 /// Allocates a response on the C heap pointing to the given data.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
195 fn alloc(data: *const c_void) -> *mut Self {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
196 unsafe {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
197 let alloc = libc::calloc(1, size_of::<ResponseInner>()) as *mut ResponseInner;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
198 (*alloc).data = data;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
199 alloc
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
200 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
201 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
202
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
203 /// Frees one of these that was created with [`Self::alloc`]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
204 /// (or provided by PAM).
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
205 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
206 /// # Safety
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
207 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
208 /// It's up to you to stop using `me` after calling this.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
209 unsafe fn free(me: *mut Self) {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
210 libc::free((*me).data as *mut c_void);
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
211 libc::free(me as *mut c_void)
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
212 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
213 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
214
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
215 /// Binary data used in requests and responses.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
216 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
217 /// This is an unsized data type whose memory goes beyond its data.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
218 /// This must be allocated on the C heap.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
219 #[repr(C)]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
220 struct BinaryData {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
221 /// The total length of the structure; a u32 in network byte order (BE).
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
222 total_length: [u8; 4],
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
223 /// A tag of undefined meaning.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
224 data_type: u8,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
225 /// Pointer to an array of length [`length`](Self::length) − 5
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
226 data: [u8; 0],
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
227 _marker: Immovable,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
228 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
229
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
230 impl BinaryData {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
231 fn alloc(
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
232 source: impl AsRef<[u8]>,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
233 data_type: u8,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
234 ) -> Result<*const BinaryData, TryFromIntError> {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
235 let source = source.as_ref();
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
236 let buffer_size = u32::try_from(source.len() + 5)?;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
237 let data = unsafe {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
238 let dest_buffer = libc::malloc(buffer_size as usize) as *mut BinaryData;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
239 let data = &mut *dest_buffer;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
240 data.total_length = buffer_size.to_be_bytes();
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
241 data.data_type = data_type;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
242 let dest = data.data.as_mut_ptr();
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
243 libc::memcpy(
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
244 dest as *mut c_void,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
245 source.as_ptr() as *const c_void,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
246 source.len(),
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
247 );
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
248 dest_buffer
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
249 };
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
250 Ok(data)
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
251 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
252 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
253
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
254 /// An opaque pointer we provide to PAM for callbacks.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
255 #[repr(C)]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
256 pub struct AppData {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
257 _data: (),
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
258 _marker: Immovable,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
259 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
260
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
261 /// The callback that PAM uses to get information in a conversation.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
262 ///
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
263 /// - `num_msg` is the number of messages in the `pam_message` array.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
264 /// - `messages` is a pointer to an array of pointers to [`Message`]s.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
265 /// - `responses` is a pointer to an array of [`ResponseInner`]s,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
266 /// which PAM sets in response to a module's request.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
267 /// - `appdata` is the `appdata` field of the [`Conversation`] we were passed.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
268 pub type ConversationCallback = extern "C" fn(
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
269 num_msg: c_int,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
270 messages: *const *const Message,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
271 responses: &mut *const ResponseInner,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
272 appdata: *const AppData,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
273 ) -> c_int;
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
274
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
275 /// A callback and the associated [`AppData`] pointer that needs to be passed back to it.
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
276 #[repr(C)]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
277 pub struct Conversation {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
278 callback: ConversationCallback,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
279 appdata: *const AppData,
66
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
280 }
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
281
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
282 #[link(name = "pam")]
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
283 extern "C" {
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
284 pub fn pam_get_data(
66
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
285 pamh: *const Handle,
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
286 module_data_name: *const c_char,
69
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
287 data: &mut *const c_void,
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
288 ) -> c_int;
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
289
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
290 pub fn pam_set_data(
66
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
291 pamh: *mut Handle,
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
292 module_data_name: *const c_char,
69
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
293 data: *const c_void,
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
294 cleanup: extern "C" fn(pamh: *const c_void, data: *mut c_void, error_status: c_int),
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
295 ) -> c_int;
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
296
69
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
297 pub fn pam_get_item(pamh: *const Handle, item_type: c_int, item: &mut *const c_void) -> c_int;
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
298
69
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
299 pub fn pam_set_item(pamh: *mut Handle, item_type: c_int, item: *const c_void) -> c_int;
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
300
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
301 pub fn pam_get_user(
66
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
302 pamh: *const Handle,
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
303 user: &mut *const c_char,
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
304 prompt: *const c_char,
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
305 ) -> c_int;
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
306
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
307 pub fn pam_get_authtok(
66
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
308 pamh: *const Handle,
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
309 item_type: c_int,
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
310 data: &mut *const c_char,
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
311 prompt: *const c_char,
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
312 ) -> c_int;
66
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
313
a674799a5cd3 Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents: 64
diff changeset
314 pub fn pam_end(pamh: *mut Handle, status: c_int) -> c_int;
60
05cc2c27334f The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
315 }
69
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
316
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
317 #[cfg(test)]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
318 mod test {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
319 use super::{BinaryResponseInner, TextResponseInner};
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
320
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
321 #[test]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
322 fn test_text_response() {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
323 let resp = TextResponseInner::alloc("hello").expect("alloc should succeed");
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
324 let borrow_resp = unsafe { &*resp };
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
325 let data = borrow_resp.contents().to_str().expect("valid");
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
326 assert_eq!("hello", data);
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
327 unsafe {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
328 TextResponseInner::free(resp);
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
329 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
330 TextResponseInner::alloc("hell\0o").expect_err("should error; contains nul");
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
331 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
332
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
333 #[test]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
334 fn test_binary_response() {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
335 let real_data = [1, 2, 3, 4, 5, 6, 7, 8];
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
336 let resp = BinaryResponseInner::alloc(&real_data, 7).expect("alloc should succeed");
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
337 let borrow_resp = unsafe { &*resp };
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
338 let data = borrow_resp.contents();
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
339 assert_eq!(&real_data, data);
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
340 assert_eq!(7, borrow_resp.data_type());
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
341 unsafe { BinaryResponseInner::free(resp) };
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
342 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
343
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
344 #[test]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
345 #[ignore]
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
346 fn test_binary_response_too_big() {
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
347 let big_data: Vec<u8> = vec![0xFFu8; 10_000_000_000];
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
348 BinaryResponseInner::alloc(&big_data, 0).expect_err("this is too big!");
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
349 }
8f3ae0c7ab92 Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents: 66
diff changeset
350 }