Mercurial > crates > nonstick
comparison src/libpam/question.rs @ 108:e97534be35e3
Make some proc macros for doing cfg-like stuff for PAM impls.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sat, 28 Jun 2025 00:34:45 -0400 |
parents | 49d9e2b5c189 |
children | 178310336596 |
comparison
equal
deleted
inserted
replaced
107:49c6633f6fd2 | 108:e97534be35e3 |
---|---|
1 //! Data and types dealing with PAM messages. | 1 //! Data and types dealing with PAM messages. |
2 | 2 |
3 #[cfg(feature = "linux-pam-extensions")] | 3 #[cfg(feature = "linux-pam-ext")] |
4 use crate::conv::{BinaryQAndA, RadioQAndA}; | 4 use crate::conv::{BinaryQAndA, RadioQAndA}; |
5 use crate::conv::{ErrorMsg, InfoMsg, MaskedQAndA, Message, QAndA}; | 5 use crate::conv::{ErrorMsg, InfoMsg, MaskedQAndA, Message, QAndA}; |
6 use crate::libpam::conversation::OwnedMessage; | 6 use crate::libpam::conversation::OwnedMessage; |
7 use crate::libpam::memory::{CBinaryData, CHeapBox, CHeapString, Immovable}; | 7 use crate::libpam::memory::{CBinaryData, CHeapBox, CHeapString, Immovable}; |
8 use crate::libpam::pam_ffi; | 8 use crate::libpam::pam_ffi; |
186 /// An error message. | 186 /// An error message. |
187 ErrorMsg = pam_ffi::PAM_ERROR_MSG, | 187 ErrorMsg = pam_ffi::PAM_ERROR_MSG, |
188 /// An informational message. | 188 /// An informational message. |
189 TextInfo = pam_ffi::PAM_TEXT_INFO, | 189 TextInfo = pam_ffi::PAM_TEXT_INFO, |
190 /// Yes/No/Maybe conditionals. A Linux-PAM extension. | 190 /// Yes/No/Maybe conditionals. A Linux-PAM extension. |
191 #[cfg(feature = "linux-pam-extensions")] | 191 #[cfg(feature = "linux-pam-ext")] |
192 RadioType = pam_ffi::PAM_RADIO_TYPE, | 192 RadioType = pam_ffi::PAM_RADIO_TYPE, |
193 /// For server–client non-human interaction. | 193 /// For server–client non-human interaction. |
194 /// | 194 /// |
195 /// NOT part of the X/Open PAM specification. | 195 /// NOT part of the X/Open PAM specification. |
196 /// A Linux-PAM extension. | 196 /// A Linux-PAM extension. |
197 #[cfg(feature = "linux-pam-extensions")] | 197 #[cfg(feature = "linux-pam-ext")] |
198 BinaryPrompt = pam_ffi::PAM_BINARY_PROMPT, | 198 BinaryPrompt = pam_ffi::PAM_BINARY_PROMPT, |
199 } | 199 } |
200 | 200 |
201 impl Question { | 201 impl Question { |
202 /// Gets this message's data pointer as a string. | 202 /// Gets this message's data pointer as a string. |
234 let (style, data): (_, CHeapBox<c_void>) = match *msg { | 234 let (style, data): (_, CHeapBox<c_void>) = match *msg { |
235 Message::MaskedPrompt(p) => alloc(Style::PromptEchoOff, p.question()), | 235 Message::MaskedPrompt(p) => alloc(Style::PromptEchoOff, p.question()), |
236 Message::Prompt(p) => alloc(Style::PromptEchoOn, p.question()), | 236 Message::Prompt(p) => alloc(Style::PromptEchoOn, p.question()), |
237 Message::Error(p) => alloc(Style::ErrorMsg, p.question()), | 237 Message::Error(p) => alloc(Style::ErrorMsg, p.question()), |
238 Message::Info(p) => alloc(Style::TextInfo, p.question()), | 238 Message::Info(p) => alloc(Style::TextInfo, p.question()), |
239 #[cfg(feature = "linux-pam-extensions")] | 239 #[cfg(feature = "linux-pam-ext")] |
240 Message::RadioPrompt(p) => alloc(Style::RadioType, p.question()), | 240 Message::RadioPrompt(p) => alloc(Style::RadioType, p.question()), |
241 #[cfg(feature = "linux-pam-extensions")] | 241 #[cfg(feature = "linux-pam-ext")] |
242 Message::BinaryPrompt(p) => Ok((Style::BinaryPrompt, unsafe { | 242 Message::BinaryPrompt(p) => Ok((Style::BinaryPrompt, unsafe { |
243 CHeapBox::cast(CBinaryData::alloc(p.question())?) | 243 CHeapBox::cast(CBinaryData::alloc(p.question())?) |
244 })), | 244 })), |
245 #[cfg(not(feature = "linux-pam-extensions"))] | 245 #[cfg(not(feature = "linux-pam-ext"))] |
246 Message::RadioPrompt(_) | Message::BinaryPrompt(_) => Err(ErrorCode::ConversationError), | 246 Message::RadioPrompt(_) | Message::BinaryPrompt(_) => Err(ErrorCode::ConversationError), |
247 }?; | 247 }?; |
248 Ok(Self { | 248 Ok(Self { |
249 style: style.into(), | 249 style: style.into(), |
250 data: Some(data), | 250 data: Some(data), |
259 unsafe { | 259 unsafe { |
260 // This is nice-to-have. We'll try to zero out the data | 260 // This is nice-to-have. We'll try to zero out the data |
261 // in the Question. If it's not a supported format, we skip it. | 261 // in the Question. If it's not a supported format, we skip it. |
262 if let Ok(style) = Style::try_from(self.style) { | 262 if let Ok(style) = Style::try_from(self.style) { |
263 let _ = match style { | 263 let _ = match style { |
264 #[cfg(feature = "linux-pam-extensions")] | 264 #[cfg(feature = "linux-pam-ext")] |
265 Style::BinaryPrompt => self | 265 Style::BinaryPrompt => self |
266 .data | 266 .data |
267 .as_ref() | 267 .as_ref() |
268 .map(|p| CBinaryData::zero_contents(CHeapBox::as_ptr(p).cast())), | 268 .map(|p| CBinaryData::zero_contents(CHeapBox::as_ptr(p).cast())), |
269 #[cfg(feature = "linux-pam-extensions")] | 269 #[cfg(feature = "linux-pam-ext")] |
270 Style::RadioType => self | 270 Style::RadioType => self |
271 .data | 271 .data |
272 .as_ref() | 272 .as_ref() |
273 .map(|p| CHeapString::zero(CHeapBox::as_ptr(p).cast())), | 273 .map(|p| CHeapString::zero(CHeapBox::as_ptr(p).cast())), |
274 Style::TextInfo | 274 Style::TextInfo |
299 Self::MaskedPrompt(MaskedQAndA::new(question.string_data()?)) | 299 Self::MaskedPrompt(MaskedQAndA::new(question.string_data()?)) |
300 } | 300 } |
301 Style::PromptEchoOn => Self::Prompt(QAndA::new(question.string_data()?)), | 301 Style::PromptEchoOn => Self::Prompt(QAndA::new(question.string_data()?)), |
302 Style::ErrorMsg => Self::Error(ErrorMsg::new(question.string_data()?)), | 302 Style::ErrorMsg => Self::Error(ErrorMsg::new(question.string_data()?)), |
303 Style::TextInfo => Self::Info(InfoMsg::new(question.string_data()?)), | 303 Style::TextInfo => Self::Info(InfoMsg::new(question.string_data()?)), |
304 #[cfg(feature = "linux-pam-extensions")] | 304 #[cfg(feature = "linux-pam-ext")] |
305 Style::RadioType => Self::RadioPrompt(RadioQAndA::new(question.string_data()?)), | 305 Style::RadioType => Self::RadioPrompt(RadioQAndA::new(question.string_data()?)), |
306 #[cfg(feature = "linux-pam-extensions")] | 306 #[cfg(feature = "linux-pam-ext")] |
307 Style::BinaryPrompt => Self::BinaryPrompt(BinaryQAndA::new(question.binary_data())), | 307 Style::BinaryPrompt => Self::BinaryPrompt(BinaryQAndA::new(question.binary_data())), |
308 } | 308 } |
309 }; | 309 }; |
310 Ok(prompt) | 310 Ok(prompt) |
311 } | 311 } |
351 assert_matches!(hey => OwnedMessage::Info, "hey"); | 351 assert_matches!(hey => OwnedMessage::Info, "hey"); |
352 assert_matches!(gasp => OwnedMessage::Error, "gasp"); | 352 assert_matches!(gasp => OwnedMessage::Error, "gasp"); |
353 } | 353 } |
354 | 354 |
355 #[test] | 355 #[test] |
356 #[cfg(not(feature = "linux-pam-extensions"))] | 356 #[cfg(not(feature = "linux-pam-ext"))] |
357 fn no_linux_extensions() { | 357 fn no_linux_extensions() { |
358 use crate::conv::{BinaryQAndA, RadioQAndA}; | 358 use crate::conv::{BinaryQAndA, RadioQAndA}; |
359 <$typ>::new(&[ | 359 <$typ>::new(&[ |
360 BinaryQAndA::new((&[5, 4, 3, 2, 1], 66)).message(), | 360 BinaryQAndA::new((&[5, 4, 3, 2, 1], 66)).message(), |
361 RadioQAndA::new("you must choose").message(), | 361 RadioQAndA::new("you must choose").message(), |
362 ]).unwrap_err(); | 362 ]).unwrap_err(); |
363 } | 363 } |
364 | 364 |
365 #[test] | 365 #[test] |
366 #[cfg(feature = "linux-pam-extensions")] | 366 #[cfg(feature = "linux-pam-ext")] |
367 fn linux_extensions() { | 367 fn linux_extensions() { |
368 let interrogation = Box::pin(<$typ>::new(&[ | 368 let interrogation = Box::pin(<$typ>::new(&[ |
369 BinaryQAndA::new((&[5, 4, 3, 2, 1], 66)).message(), | 369 BinaryQAndA::new((&[5, 4, 3, 2, 1], 66)).message(), |
370 RadioQAndA::new("you must choose").message(), | 370 RadioQAndA::new("you must choose").message(), |
371 ]).unwrap()); | 371 ]).unwrap()); |