Mercurial > crates > nonstick
annotate src/conv.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 | 58f9d2a4df38 |
rev | line source |
---|---|
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
1 //! The PAM conversation and associated Stuff. |
60
05cc2c27334f
The Big Refactor: clean up docs and exports.
Paul Fisher <paul@pfish.zone>
parents:
59
diff
changeset
|
2 |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
3 // Temporarily allowed until we get the actual conversation functions hooked up. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
4 #![allow(dead_code)] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
5 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
6 use crate::constants::{NulError, Result, TooBigError}; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
7 use crate::pam_ffi::{BinaryResponseInner, GenericResponse, TextResponseInner}; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
8 use secure_string::SecureString; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
9 use std::mem; |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
10 use std::result::Result as StdResult; |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
11 use std::str::Utf8Error; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
12 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
13 // TODO: In most cases, we should be passing around references to strings |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
14 // or binary data. Right now we don't because that turns type inference and |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
15 // trait definitions/implementations into a HUGE MESS. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
16 // |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
17 // Ideally, we would be using some kind of `TD: TextData` and `BD: BinaryData` |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
18 // associated types in the various Conversation traits to avoid copying |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
19 // when unnecessary. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
20 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
21 /// The types of message and request that can be sent to a user. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
22 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
23 /// The data within each enum value is the prompt (or other information) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
24 /// that will be presented to the user. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
25 #[derive(Debug)] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
26 pub enum Message<'a> { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
27 /// Requests information from the user; will be masked when typing. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
28 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
29 /// Response: [`Response::MaskedText`] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
30 MaskedPrompt(&'a str), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
31 /// Requests information from the user; will not be masked. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
32 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
33 /// Response: [`Response::Text`] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
34 Prompt(&'a str), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
35 /// "Yes/No/Maybe conditionals" (a Linux-PAM extension). |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
36 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
37 /// Response: [`Response::Text`] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
38 /// (Linux-PAM documentation doesn't define its contents.) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
39 RadioPrompt(&'a str), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
40 /// Raises an error message to the user. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
41 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
42 /// Response: [`Response::NoResponse`] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
43 Error(&'a str), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
44 /// Sends an informational message to the user. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
45 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
46 /// Response: [`Response::NoResponse`] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
47 Info(&'a str), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
48 /// Requests binary data from the client (a Linux-PAM extension). |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
49 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
50 /// This is used for non-human or non-keyboard prompts (security key?). |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
51 /// NOT part of the X/Open PAM specification. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
52 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
53 /// Response: [`Response::Binary`] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
54 BinaryPrompt { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
55 /// Some binary data. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
56 data: &'a [u8], |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
57 /// A "type" that you can use for signalling. Has no strict definition in PAM. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
58 data_type: u8, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
59 }, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
60 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
61 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
62 /// The responses that PAM will return from a request. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
63 #[derive(Debug, PartialEq, derive_more::From)] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
64 pub enum Response { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
65 /// Used to fill in list entries where there is no response expected. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
66 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
67 /// Used in response to: |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
68 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
69 /// - [`Error`](Message::Error) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
70 /// - [`Info`](Message::Info) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
71 NoResponse, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
72 /// A response with text data from the user. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
73 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
74 /// Used in response to: |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
75 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
76 /// - [`Prompt`](Message::Prompt) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
77 /// - [`RadioPrompt`](Message::RadioPrompt) (a Linux-PAM extension) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
78 Text(String), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
79 /// A response to a masked request with text data from the user. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
80 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
81 /// Used in response to: |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
82 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
83 /// - [`MaskedPrompt`](Message::MaskedPrompt) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
84 MaskedText(SecureString), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
85 /// A response to a binary request (a Linux-PAM extension). |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
86 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
87 /// Used in response to: |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
88 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
89 /// - [`BinaryPrompt`](Message::BinaryPrompt) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
90 Binary(BinaryData), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
91 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
92 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
93 /// A channel for PAM modules to request information from the user. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
94 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
95 /// This trait is used by both applications and PAM modules: |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
96 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
97 /// - Applications implement Conversation and provide a user interface |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
98 /// to allow the user to respond to PAM questions. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
99 /// - Modules call a Conversation implementation to request information |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
100 /// or send information to the user. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
101 pub trait Conversation { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
102 /// Sends messages to the user. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
103 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
104 /// The returned Vec of messages always contains exactly as many entries |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
105 /// as there were messages in the request; one corresponding to each. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
106 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
107 /// Messages with no response (e.g. [info](Message::Info) and |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
108 /// [error](Message::Error)) will have a `None` entry instead of a `Response`. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
109 fn send(&mut self, messages: &[Message]) -> Result<Vec<Response>>; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
110 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
111 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
112 /// Trait that an application can implement if they want to handle messages |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
113 /// one at a time. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
114 pub trait DemuxedConversation { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
115 /// Prompts the user for some text. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
116 fn prompt(&mut self, request: &str) -> Result<String>; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
117 /// Prompts the user for some text, but hides their typing. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
118 fn masked_prompt(&mut self, request: &str) -> Result<SecureString>; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
119 /// Prompts the user for a radio option (a Linux-PAM extension). |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
120 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
121 /// The Linux-PAM documentation doesn't give the format of the response. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
122 fn radio_prompt(&mut self, request: &str) -> Result<String>; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
123 /// Alerts the user to an error. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
124 fn error(&mut self, message: &str); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
125 /// Sends an informational message to the user. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
126 fn info(&mut self, message: &str); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
127 /// Requests binary data from the user (a Linux-PAM extension). |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
128 fn binary_prompt(&mut self, data: &[u8], data_type: u8) -> Result<BinaryData>; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
129 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
130 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
131 impl<D: DemuxedConversation> Conversation for D { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
132 fn send(&mut self, messages: &[Message]) -> Result<Vec<Response>> { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
133 messages |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
134 .iter() |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
135 .map(|msg| match *msg { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
136 Message::Prompt(prompt) => self.prompt(prompt).map(Response::from), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
137 Message::MaskedPrompt(prompt) => self.masked_prompt(prompt).map(Response::from), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
138 Message::RadioPrompt(prompt) => self.radio_prompt(prompt).map(Response::from), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
139 Message::Info(message) => { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
140 self.info(message); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
141 Ok(Response::NoResponse) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
142 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
143 Message::Error(message) => { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
144 self.error(message); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
145 Ok(Response::NoResponse) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
146 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
147 Message::BinaryPrompt { data_type, data } => { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
148 self.binary_prompt(data, data_type).map(Response::from) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
149 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
150 }) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
151 .collect() |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
152 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
153 } |
15
27730595f1ea
Adding pam-http module
Anthony Nowell <anthony@algorithmia.com>
parents:
diff
changeset
|
154 |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
155 /// An owned text response to a PAM conversation. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
156 /// |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
157 /// It points to a value on the C heap. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
158 #[repr(C)] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
159 struct TextResponse(*mut TextResponseInner); |
63
a7aa5ca0d00d
Move MessageStyle to conv, the only place it is used.
Paul Fisher <paul@pfish.zone>
parents:
62
diff
changeset
|
160 |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
161 impl TextResponse { |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
162 /// Allocates a new response with the given text. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
163 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
164 /// A copy of the provided text will be allocated on the C heap. |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
165 pub fn new(text: impl AsRef<str>) -> StdResult<Self, NulError> { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
166 TextResponseInner::alloc(text).map(Self) |
63
a7aa5ca0d00d
Move MessageStyle to conv, the only place it is used.
Paul Fisher <paul@pfish.zone>
parents:
62
diff
changeset
|
167 } |
a7aa5ca0d00d
Move MessageStyle to conv, the only place it is used.
Paul Fisher <paul@pfish.zone>
parents:
62
diff
changeset
|
168 |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
169 /// Converts this into a GenericResponse. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
170 fn generic(self) -> *mut GenericResponse { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
171 let ret = self.0 as *mut GenericResponse; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
172 mem::forget(self); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
173 ret |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
174 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
175 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
176 /// Gets the string data, if possible. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
177 pub fn as_str(&self) -> StdResult<&str, Utf8Error> { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
178 // SAFETY: We allocated this ourselves or got it back from PAM. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
179 unsafe { &*self.0 }.contents().to_str() |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
180 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
181 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
182 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
183 impl Drop for TextResponse { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
184 /// Frees an owned response. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
185 fn drop(&mut self) { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
186 // SAFETY: We allocated this ourselves, or it was provided by PAM. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
187 unsafe { TextResponseInner::free(self.0) } |
63
a7aa5ca0d00d
Move MessageStyle to conv, the only place it is used.
Paul Fisher <paul@pfish.zone>
parents:
62
diff
changeset
|
188 } |
a7aa5ca0d00d
Move MessageStyle to conv, the only place it is used.
Paul Fisher <paul@pfish.zone>
parents:
62
diff
changeset
|
189 } |
a7aa5ca0d00d
Move MessageStyle to conv, the only place it is used.
Paul Fisher <paul@pfish.zone>
parents:
62
diff
changeset
|
190 |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
191 /// An owned binary response to a PAM conversation. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
192 /// |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
193 /// It points to a value on the C heap. |
15
27730595f1ea
Adding pam-http module
Anthony Nowell <anthony@algorithmia.com>
parents:
diff
changeset
|
194 #[repr(C)] |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
195 pub struct BinaryResponse(pub(super) *mut BinaryResponseInner); |
15
27730595f1ea
Adding pam-http module
Anthony Nowell <anthony@algorithmia.com>
parents:
diff
changeset
|
196 |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
197 impl BinaryResponse { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
198 /// Creates a binary response with the given data. |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
199 /// |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
200 /// A copy of the data will be made and allocated on the C heap. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
201 pub fn new(data: &[u8], data_type: u8) -> StdResult<Self, TooBigError> { |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
202 BinaryResponseInner::alloc(data, data_type).map(Self) |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
203 } |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
204 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
205 /// Converts this into a GenericResponse. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
206 fn generic(self) -> *mut GenericResponse { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
207 let ret = self.0 as *mut GenericResponse; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
208 mem::forget(self); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
209 ret |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
210 } |
15
27730595f1ea
Adding pam-http module
Anthony Nowell <anthony@algorithmia.com>
parents:
diff
changeset
|
211 |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
212 /// The data type we point to. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
213 pub fn data_type(&self) -> u8 { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
214 // SAFETY: We allocated this ourselves or got it back from PAM. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
215 unsafe { &*self.0 }.data_type() |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
216 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
217 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
218 /// The data we point to. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
219 pub fn data(&self) -> &[u8] { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
220 // SAFETY: We allocated this ourselves or got it back from PAM. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
221 unsafe { &*self.0 }.contents() |
15
27730595f1ea
Adding pam-http module
Anthony Nowell <anthony@algorithmia.com>
parents:
diff
changeset
|
222 } |
27730595f1ea
Adding pam-http module
Anthony Nowell <anthony@algorithmia.com>
parents:
diff
changeset
|
223 } |
27730595f1ea
Adding pam-http module
Anthony Nowell <anthony@algorithmia.com>
parents:
diff
changeset
|
224 |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
225 impl Drop for BinaryResponse { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
226 /// Frees an owned response. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
227 fn drop(&mut self) { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
228 // SAFETY: We allocated this ourselves, or it was provided by PAM. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
229 unsafe { BinaryResponseInner::free(self.0) } |
15
27730595f1ea
Adding pam-http module
Anthony Nowell <anthony@algorithmia.com>
parents:
diff
changeset
|
230 } |
27730595f1ea
Adding pam-http module
Anthony Nowell <anthony@algorithmia.com>
parents:
diff
changeset
|
231 } |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
232 |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
233 /// Owned binary data. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
234 #[derive(Debug, PartialEq)] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
235 pub struct BinaryData { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
236 data: Vec<u8>, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
237 data_type: u8, |
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 impl BinaryData { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
241 pub fn new(data: Vec<u8>, data_type: u8) -> Self { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
242 Self { data, data_type } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
243 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
244 pub fn data(&self) -> &[u8] { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
245 &self.data |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
246 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
247 pub fn data_type(&self) -> u8 { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
248 self.data_type |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
249 } |
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 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
252 impl From<BinaryResponse> for BinaryData { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
253 /// Copies the data onto the Rust heap. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
254 fn from(value: BinaryResponse) -> Self { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
255 Self { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
256 data: value.data().to_vec(), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
257 data_type: value.data_type(), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
258 } |
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 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
261 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
262 impl From<BinaryData> for Vec<u8> { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
263 /// Extracts the inner vector from the BinaryData. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
264 fn from(value: BinaryData) -> Self { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
265 value.data |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
266 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
267 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
268 |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
269 #[cfg(test)] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
270 mod test { |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
271 use super::{ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
272 BinaryResponse, Conversation, DemuxedConversation, Message, Response, SecureString, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
273 TextResponse, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
274 }; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
275 use crate::constants::ErrorCode; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
276 use crate::pam_ffi::GenericResponse; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
277 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
278 #[test] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
279 fn test_demux() { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
280 #[derive(Default)] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
281 struct DemuxTester { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
282 error_ran: bool, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
283 info_ran: bool, |
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 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
286 impl DemuxedConversation for DemuxTester { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
287 fn prompt(&mut self, request: &str) -> crate::Result<String> { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
288 match request { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
289 "what" => Ok("whatwhat".to_owned()), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
290 "give_err" => Err(ErrorCode::PermissionDenied), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
291 _ => panic!("unexpected prompt!"), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
292 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
293 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
294 fn masked_prompt(&mut self, request: &str) -> crate::Result<SecureString> { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
295 assert_eq!("reveal", request); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
296 Ok(SecureString::from("my secrets")) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
297 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
298 fn radio_prompt(&mut self, request: &str) -> crate::Result<String> { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
299 assert_eq!("channel?", request); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
300 Ok("zero".to_owned()) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
301 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
302 fn error(&mut self, message: &str) { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
303 self.error_ran = true; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
304 assert_eq!("whoopsie", message); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
305 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
306 fn info(&mut self, message: &str) { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
307 self.info_ran = true; |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
308 assert_eq!("did you know", message); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
309 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
310 fn binary_prompt( |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
311 &mut self, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
312 data: &[u8], |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
313 data_type: u8, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
314 ) -> crate::Result<super::BinaryData> { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
315 assert_eq!(&[10, 9, 8], data); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
316 assert_eq!(66, data_type); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
317 Ok(super::BinaryData::new(vec![5, 5, 5], 5)) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
318 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
319 } |
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 let mut tester = DemuxTester::default(); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
322 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
323 assert_eq!( |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
324 vec![ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
325 Response::Text("whatwhat".to_owned()), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
326 Response::MaskedText("my secrets".into()), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
327 Response::NoResponse, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
328 Response::NoResponse, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
329 ], |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
330 tester |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
331 .send(&[ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
332 Message::Prompt("what"), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
333 Message::MaskedPrompt("reveal"), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
334 Message::Error("whoopsie"), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
335 Message::Info("did you know"), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
336 ]) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
337 .unwrap() |
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 assert!(tester.error_ran); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
340 assert!(tester.info_ran); |
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 assert_eq!( |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
343 ErrorCode::PermissionDenied, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
344 tester.send(&[Message::Prompt("give_err")]).unwrap_err(), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
345 ); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
346 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
347 // Test the Linux-PAM extensions separately. |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
348 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
349 assert_eq!( |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
350 vec![ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
351 Response::Text("zero".to_owned()), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
352 Response::Binary(super::BinaryData::new(vec![5, 5, 5], 5)), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
353 ], |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
354 tester |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
355 .send(&[ |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
356 Message::RadioPrompt("channel?"), |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
357 Message::BinaryPrompt { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
358 data: &[10, 9, 8], |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
359 data_type: 66 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
360 }, |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
361 ]) |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
362 .unwrap() |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
363 ); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
364 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
365 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
366 // The below tests are used in conjunction with ASAN to verify |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
367 // that we correctly clean up all our memory. |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
368 |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
369 #[test] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
370 fn test_text_response() { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
371 let resp = TextResponse::new("it's a-me!").unwrap(); |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
372 assert_eq!("it's a-me!", resp.as_str().unwrap()); |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
373 } |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
374 |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
375 #[test] |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
376 fn test_binary_response() { |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
377 let data = [123, 210, 55]; |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
378 let resp = BinaryResponse::new(&data, 99).unwrap(); |
70
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
379 assert_eq!(data, resp.data()); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
380 assert_eq!(99, resp.data_type()); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
381 } |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
382 |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
383 #[test] |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
384 fn test_to_generic() { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
385 let text = TextResponse::new("oh no").unwrap(); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
386 let text = text.generic(); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
387 let binary = BinaryResponse::new(&[], 33).unwrap(); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
388 let binary = binary.generic(); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
389 unsafe { |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
390 GenericResponse::free(text); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
391 GenericResponse::free(binary); |
9f8381a1c09c
Implement low-level conversation primitives.
Paul Fisher <paul@pfish.zone>
parents:
69
diff
changeset
|
392 } |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
393 } |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
394 } |