Mercurial > crates > nonstick
annotate src/pam_ffi.rs @ 70:9f8381a1c09c
Implement low-level conversation primitives.
This change does two primary things:
1. Introduces new Conversation traits, to be implemented both
by the library and by PAM client applications.
2. Builds the memory-management infrastructure for passing messages
through the conversation.
...and it adds tests for both of the above, including ASAN tests.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Tue, 03 Jun 2025 01:21:59 -0400 |
parents | 8f3ae0c7ab92 |
children |
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 |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
12 use crate::constants::{InvalidEnum, NulError, TooBigError}; |
69
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::slice; |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
18 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
19 /// 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
|
20 type Immovable = PhantomData<(*mut u8, PhantomPinned)>; |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
21 |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
22 /// An opaque pointer given to us by PAM. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
23 #[repr(C)] |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
24 pub struct Handle { |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
25 _data: (), |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
26 _marker: Immovable, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
27 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
28 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
29 /// 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
|
30 #[derive(Debug, PartialEq, FromPrimitive)] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
31 #[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
|
32 pub enum MessageStyle { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
33 /// 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
|
34 PromptEchoOff = 1, |
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 not be masked. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
36 PromptEchoOn = 2, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
37 /// An error message. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
38 ErrorMsg = 3, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
39 /// An informational message. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
40 TextInfo = 4, |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
41 /// Yes/No/Maybe conditionals. A Linux-PAM extension. |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
42 RadioType = 5, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
43 /// For server–client non-human interaction. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
44 /// |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
45 /// NOT part of the X/Open PAM specification. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
46 /// A Linux-PAM extension. |
69
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. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
71 /// |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
72 /// For most requests, this will be an owned [`CStr`], but for requests |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
73 /// with [`MessageStyle::BinaryPrompt`], this will be [`BinaryData`] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
74 /// (a Linux-PAM extension). |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
75 data: *const c_void, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
76 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
77 |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
78 #[repr(C)] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
79 pub struct TextResponseInner { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
80 data: *mut c_char, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
81 _unused: c_int, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
82 } |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
83 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
84 impl TextResponseInner { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
85 /// 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
|
86 /// |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
87 /// 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
|
88 /// 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
|
89 /// 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
|
90 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
|
91 let str_data = Self::malloc_str(text)?; |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
92 let inner = GenericResponse::alloc(str_data); |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
93 Ok(inner as *mut Self) |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
94 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
95 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
96 /// 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
|
97 pub fn contents(&self) -> &CStr { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
98 // 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
|
99 // 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
|
100 // In either case, it's going to be a valid null-terminated string. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
101 unsafe { CStr::from_ptr(self.data) } |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
102 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
103 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
104 /// Releases memory owned by this response. |
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 /// # Safety |
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 /// 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
|
109 pub unsafe fn free(me: *mut Self) { |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
110 if !me.is_null() { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
111 let data = (*me).data; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
112 if !data.is_null() { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
113 libc::memset(data as *mut c_void, 0, libc::strlen(data)); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
114 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
115 libc::free(data as *mut c_void); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
116 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
117 libc::free(me as *mut c_void); |
69
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 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
120 /// 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
|
121 /// |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
122 /// 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
|
123 /// |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
124 /// - 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
|
125 /// - it doesn't take ownership of the data passed in. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
126 fn malloc_str(text: impl AsRef<str>) -> Result<*mut c_void, NulError> { |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
127 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
|
128 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
|
129 return Err(NulError(nul)); |
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 unsafe { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
132 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
|
133 libc::memcpy(data_alloc, data.as_ptr() as *const c_void, data.len()); |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
134 Ok(data_alloc) |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
135 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
136 } |
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 |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
139 /// A [`GenericResponse`] with [`BinaryData`] in it. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
140 #[repr(C)] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
141 pub struct BinaryResponseInner { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
142 data: *mut BinaryData, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
143 _unused: c_int, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
144 } |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
145 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
146 impl BinaryResponseInner { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
147 /// 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
|
148 /// |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
149 /// 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
|
150 /// It is passed through PAM unchanged. |
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 /// 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
|
153 /// 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
|
154 /// on the pointer you get back when you're done with it. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
155 pub fn alloc(data: &[u8], data_type: u8) -> Result<*mut Self, TooBigError> { |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
156 let bin_data = BinaryData::alloc(data, data_type)?; |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
157 let inner = GenericResponse::alloc(bin_data as *mut c_void); |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
158 Ok(inner as *mut Self) |
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 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
161 /// 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
|
162 pub fn contents(&self) -> &[u8] { |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
163 self.data().contents() |
69
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 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
166 /// 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
|
167 pub fn data_type(&self) -> u8 { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
168 self.data().data_type |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
169 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
170 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
171 #[inline] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
172 fn data(&self) -> &BinaryData { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
173 // 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
|
174 // 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
|
175 // BinaryResponseInner::alloc. In both cases, it points to valid data. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
176 unsafe { &*(self.data) } |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
177 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
178 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
179 /// Releases memory owned by this response. |
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 /// # Safety |
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 /// 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
|
184 pub unsafe fn free(me: *mut Self) { |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
185 if !me.is_null() { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
186 BinaryData::free((*me).data); |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
187 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
188 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
|
189 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
190 } |
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 /// 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
|
193 /// |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
194 /// 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
|
195 /// This must be allocated on the C heap. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
196 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
197 /// A Linux-PAM extension. |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
198 #[repr(C)] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
199 struct BinaryData { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
200 /// 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
|
201 total_length: [u8; 4], |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
202 /// A tag of undefined meaning. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
203 data_type: u8, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
204 /// 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
|
205 data: [u8; 0], |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
206 _marker: Immovable, |
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 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
209 impl BinaryData { |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
210 /// Copies the given data to a new BinaryData on the heap. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
211 fn alloc(source: &[u8], data_type: u8) -> Result<*mut BinaryData, TooBigError> { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
212 let buffer_size = u32::try_from(source.len() + 5).map_err(|_| TooBigError { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
213 max: (u32::MAX - 5) as usize, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
214 actual: source.len(), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
215 })?; |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
216 let data = unsafe { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
217 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
|
218 let data = &mut *dest_buffer; |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
219 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
|
220 data.data_type = data_type; |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
221 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
|
222 libc::memcpy( |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
223 dest as *mut c_void, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
224 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
|
225 source.len(), |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
226 ); |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
227 dest_buffer |
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 Ok(data) |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
230 } |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
231 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
232 fn length(&self) -> usize { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
233 u32::from_be_bytes(self.total_length).saturating_sub(5) as usize |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
234 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
235 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
236 fn contents(&self) -> &[u8] { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
237 unsafe { slice::from_raw_parts(self.data.as_ptr(), self.length()) } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
238 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
239 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
240 /// Clears this data and frees it. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
241 fn free(me: *mut Self) { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
242 if me.is_null() { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
243 return; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
244 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
245 unsafe { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
246 let me_too = &mut *me; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
247 let contents = slice::from_raw_parts_mut(me_too.data.as_mut_ptr(), me_too.length()); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
248 for v in contents { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
249 *v = 0 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
250 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
251 me_too.data_type = 0; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
252 me_too.total_length = [0; 4]; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
253 libc::free(me as *mut c_void); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
254 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
255 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
256 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
257 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
258 /// Generic version of response data. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
259 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
260 /// This has the same structure as [`BinaryResponseInner`] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
261 /// and [`TextResponseInner`]. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
262 #[repr(C)] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
263 pub struct GenericResponse { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
264 /// Pointer to the data returned in a response. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
265 /// For most responses, this will be a [`CStr`], but for responses to |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
266 /// [`MessageStyle::BinaryPrompt`]s, this will be [`BinaryData`] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
267 /// (a Linux-PAM extension). |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
268 data: *mut c_void, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
269 /// Unused. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
270 return_code: c_int, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
271 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
272 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
273 impl GenericResponse { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
274 /// Allocates a response on the C heap pointing to the given data. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
275 fn alloc(data: *mut c_void) -> *mut Self { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
276 unsafe { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
277 let alloc = libc::calloc(1, size_of::<Self>()) as *mut Self; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
278 (*alloc).data = data; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
279 alloc |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
280 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
281 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
282 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
283 /// Frees a response on the C heap. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
284 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
285 /// # Safety |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
286 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
287 /// It's on you to stop using this GenericResponse after freeing it. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
288 pub unsafe fn free(me: *mut GenericResponse) { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
289 if !me.is_null() { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
290 libc::free((*me).data); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
291 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
292 libc::free(me as *mut c_void); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
293 } |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
294 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
295 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
296 /// 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
|
297 #[repr(C)] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
298 pub struct AppData { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
299 _data: (), |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
300 _marker: Immovable, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
301 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
302 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
303 /// 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
|
304 /// |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
305 /// - `num_msg` is the number of messages in the `pam_message` array. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
306 /// - `messages` is a pointer to some [`Message`]s (see note). |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
307 /// - `responses` is a pointer to an array of [`GenericResponse`]s, |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
308 /// which PAM sets in response to a module's request. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
309 /// This is an array of structs, not an array of pointers to a struct. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
310 /// There should always be exactly as many `responses` as `num_msg`. |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
311 /// - `appdata` is the `appdata` field of the [`Conversation`] we were passed. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
312 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
313 /// NOTE: On Linux-PAM and other compatible implementations, `messages` |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
314 /// is treated as a pointer-to-pointers, like `int argc, char **argv`. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
315 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
316 /// ```text |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
317 /// ┌──────────┐ points to ┌─────────────┐ ╔═ Message ═╗ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
318 /// │ messages │ ┄┄┄┄┄┄┄┄┄┄> │ messages[0] │ ┄┄┄┄> ║ style ║ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
319 /// └──────────┘ │ messages[1] │ ┄┄╮ ║ data ║ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
320 /// │ ... │ ┆ ╚═══════════╝ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
321 /// ┆ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
322 /// ┆ ╔═ Message ═╗ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
323 /// ╰┄┄> ║ style ║ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
324 /// ║ data ║ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
325 /// ╚═══════════╝ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
326 /// ``` |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
327 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
328 /// On OpenPAM and other compatible implementations (like Solaris), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
329 /// `messages` is a pointer-to-pointer-to-array. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
330 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
331 /// ```text |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
332 /// ┌──────────┐ points to ┌───────────┐ ╔═ Message[] ═╗ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
333 /// │ messages │ ┄┄┄┄┄┄┄┄┄┄> │ *messages │ ┄┄┄┄> ║ style ║ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
334 /// └──────────┘ └───────────┘ ║ data ║ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
335 /// ╟─────────────╢ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
336 /// ║ style ║ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
337 /// ║ data ║ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
338 /// ╟─────────────╢ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
339 /// ║ ... ║ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
340 /// ``` |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
341 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
342 /// ***THIS LIBRARY CURRENTLY SUPPORTS ONLY LINUX-PAM.*** |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
343 pub type ConversationCallback = extern "C" fn( |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
344 num_msg: c_int, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
345 messages: *const *const Message, |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
346 responses: &mut *const GenericResponse, |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
347 appdata: *const AppData, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
348 ) -> c_int; |
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 /// 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
|
351 #[repr(C)] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
352 pub struct Conversation { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
353 callback: ConversationCallback, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
354 appdata: *const AppData, |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
355 } |
60
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
356 |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
357 #[link(name = "pam")] |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
358 extern "C" { |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
359 pub fn pam_get_data( |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
360 pamh: *const Handle, |
60
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
361 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
|
362 data: &mut *const c_void, |
60
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
363 ) -> c_int; |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
364 |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
365 pub fn pam_set_data( |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
366 pamh: *mut Handle, |
60
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
367 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
|
368 data: *const c_void, |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
369 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
|
370 ) -> c_int; |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
371 |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
372 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
|
373 |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
374 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
|
375 |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
376 pub fn pam_get_user( |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
377 pamh: *const Handle, |
60
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
378 user: &mut *const c_char, |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
379 prompt: *const c_char, |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
380 ) -> c_int; |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
381 |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
382 pub fn pam_get_authtok( |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
383 pamh: *const Handle, |
60
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
384 item_type: c_int, |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
385 data: &mut *const c_char, |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
386 prompt: *const c_char, |
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
387 ) -> c_int; |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
388 |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
389 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
|
390 } |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
391 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
392 #[cfg(test)] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
393 mod test { |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
394 use super::{BinaryResponseInner, GenericResponse, TextResponseInner}; |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
395 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
396 #[test] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
397 fn test_text_response() { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
398 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
|
399 let borrow_resp = unsafe { &*resp }; |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
400 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
|
401 assert_eq!("hello", data); |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
402 unsafe { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
403 TextResponseInner::free(resp); |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
404 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
405 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
|
406 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
407 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
408 #[test] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
409 fn test_binary_response() { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
410 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
|
411 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
|
412 let borrow_resp = unsafe { &*resp }; |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
413 let data = borrow_resp.contents(); |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
414 assert_eq!(&real_data, data); |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
415 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
|
416 unsafe { BinaryResponseInner::free(resp) }; |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
417 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
418 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
419 #[test] |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
420 fn test_free_safety() { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
421 unsafe { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
422 TextResponseInner::free(std::ptr::null_mut()); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
423 BinaryResponseInner::free(std::ptr::null_mut()); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
424 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
425 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
426 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
427 #[test] |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
428 #[ignore] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
429 fn test_binary_response_too_big() { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
430 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
|
431 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
|
432 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
433 } |