Mercurial > crates > nonstick
comparison src/libpam/handle.rs @ 146:1bc52025156b
Split PAM items into their own separate struct.
To trim down the number of methods on `PamShared`, this puts all the
Items into their own struct(s). This also makes the split between
authtok/authtok_item easier to understand.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sun, 06 Jul 2025 19:10:26 -0400 |
parents | 56b559b7ecea |
children | 4d7333337569 |
comparison
equal
deleted
inserted
replaced
145:8f964b701652 | 146:1bc52025156b |
---|---|
1 use super::conversation::{OwnedConversation, PamConv}; | 1 use super::conversation::{OwnedConversation, PamConv}; |
2 use crate::_doc::{guide, linklist, stdlinks}; | |
2 use crate::constants::{ErrorCode, Result}; | 3 use crate::constants::{ErrorCode, Result}; |
3 use crate::conv::Exchange; | 4 use crate::conv::Exchange; |
4 use crate::environ::EnvironMapMut; | 5 use crate::environ::EnvironMapMut; |
5 use crate::handle::PamShared; | 6 use crate::handle::PamShared; |
7 use crate::items::{Items, ItemsMut}; | |
6 use crate::libpam::environ::{LibPamEnviron, LibPamEnvironMut}; | 8 use crate::libpam::environ::{LibPamEnviron, LibPamEnvironMut}; |
7 use crate::libpam::memory; | 9 use crate::libpam::items::{LibPamItems, LibPamItemsMut}; |
10 use crate::libpam::{items, memory}; | |
8 use crate::logging::{Level, Location}; | 11 use crate::logging::{Level, Location}; |
9 use crate::{ | 12 use crate::{Conversation, EnvironMap, Flags, ModuleClient, Transaction}; |
10 guide, linklist, stdlinks, Conversation, EnvironMap, Flags, PamHandleModule, Transaction, | |
11 }; | |
12 use libpam_sys_helpers::constants; | 13 use libpam_sys_helpers::constants; |
13 use num_enum::{IntoPrimitive, TryFromPrimitive}; | 14 use num_enum::{IntoPrimitive, TryFromPrimitive}; |
14 use std::cell::Cell; | 15 use std::cell::Cell; |
15 use std::ffi::{c_char, c_int, CString, OsStr, OsString}; | 16 use std::ffi::{c_char, c_int, CString, OsStr, OsString}; |
16 use std::mem::ManuallyDrop; | 17 use std::mem::ManuallyDrop; |
207 impl<C: Conversation> PamShared for LibPamTransaction<C> { | 208 impl<C: Conversation> PamShared for LibPamTransaction<C> { |
208 delegate!(fn log(&self, level: Level, location: Location<'_>, entry: &str) -> ()); | 209 delegate!(fn log(&self, level: Level, location: Location<'_>, entry: &str) -> ()); |
209 delegate!(fn environ(&self) -> impl EnvironMap); | 210 delegate!(fn environ(&self) -> impl EnvironMap); |
210 delegate!(fn environ_mut(&mut self) -> impl EnvironMapMut); | 211 delegate!(fn environ_mut(&mut self) -> impl EnvironMapMut); |
211 delegate!(fn username(&mut self, prompt: Option<&OsStr>) -> Result<OsString>); | 212 delegate!(fn username(&mut self, prompt: Option<&OsStr>) -> Result<OsString>); |
212 delegate!(get = user_item, set = set_user_item); | 213 delegate!(fn items(&self) -> impl Items); |
213 delegate!(get = service, set = set_service); | 214 delegate!(fn items_mut(&mut self) -> impl ItemsMut); |
214 delegate!(get = user_prompt, set = set_user_prompt); | |
215 delegate!(get = tty_name, set = set_tty_name); | |
216 delegate!(get = remote_user, set = set_remote_user); | |
217 delegate!(get = remote_host, set = set_remote_host); | |
218 delegate!(set = set_authtok_item); | |
219 delegate!(set = set_old_authtok_item); | |
220 } | |
221 | |
222 /// Macro to implement getting/setting a CStr-based item. | |
223 macro_rules! cstr_item { | |
224 (get = $getter:ident, item = $item_type:path) => { | |
225 fn $getter(&self) -> Result<Option<OsString>> { | |
226 unsafe { self.get_cstr_item($item_type) } | |
227 } | |
228 }; | |
229 (set = $setter:ident, item = $item_type:path) => { | |
230 fn $setter(&mut self, value: Option<&OsStr>) -> Result<()> { | |
231 unsafe { self.set_cstr_item($item_type, value) } | |
232 } | |
233 }; | |
234 } | 215 } |
235 | 216 |
236 /// An owned variation of a basic PAM handle. | 217 /// An owned variation of a basic PAM handle. |
237 /// | 218 /// |
238 /// This is the most basic version of a wrapped PAM handle. It's mostly used | 219 /// This is the most basic version of a wrapped PAM handle. It's mostly used |
375 | 356 |
376 fn environ_mut(&mut self) -> impl EnvironMapMut { | 357 fn environ_mut(&mut self) -> impl EnvironMapMut { |
377 LibPamEnvironMut::new(self) | 358 LibPamEnvironMut::new(self) |
378 } | 359 } |
379 | 360 |
380 cstr_item!(get = user_item, item = ItemType::User); | 361 fn items(&self) -> impl Items { |
381 cstr_item!(set = set_user_item, item = ItemType::User); | 362 LibPamItems(self) |
382 cstr_item!(get = service, item = ItemType::Service); | 363 } |
383 cstr_item!(set = set_service, item = ItemType::Service); | 364 |
384 cstr_item!(get = user_prompt, item = ItemType::UserPrompt); | 365 fn items_mut(&mut self) -> impl ItemsMut { |
385 cstr_item!(set = set_user_prompt, item = ItemType::UserPrompt); | 366 LibPamItemsMut(self) |
386 cstr_item!(get = tty_name, item = ItemType::Tty); | 367 } |
387 cstr_item!(set = set_tty_name, item = ItemType::Tty); | |
388 cstr_item!(get = remote_user, item = ItemType::RemoteUser); | |
389 cstr_item!(set = set_remote_user, item = ItemType::RemoteUser); | |
390 cstr_item!(get = remote_host, item = ItemType::RemoteHost); | |
391 cstr_item!(set = set_remote_host, item = ItemType::RemoteHost); | |
392 cstr_item!(set = set_authtok_item, item = ItemType::AuthTok); | |
393 cstr_item!(set = set_old_authtok_item, item = ItemType::OldAuthTok); | |
394 } | 368 } |
395 | 369 |
396 impl Conversation for LibPamHandle { | 370 impl Conversation for LibPamHandle { |
397 fn communicate(&self, messages: &[Exchange]) { | 371 fn communicate(&self, messages: &[Exchange]) { |
398 match self.conversation_item() { | 372 match self.conversation_item() { |
404 } | 378 } |
405 } | 379 } |
406 } | 380 } |
407 } | 381 } |
408 | 382 |
409 impl PamHandleModule for LibPamHandle { | 383 impl ModuleClient for LibPamHandle { |
410 fn authtok(&mut self, prompt: Option<&OsStr>) -> Result<OsString> { | 384 fn authtok(&mut self, prompt: Option<&OsStr>) -> Result<OsString> { |
411 self.get_authtok(prompt, ItemType::AuthTok) | 385 self.get_authtok(prompt, ItemType::AuthTok) |
412 } | 386 } |
413 | 387 |
414 fn old_authtok(&mut self, prompt: Option<&OsStr>) -> Result<OsString> { | 388 fn old_authtok(&mut self, prompt: Option<&OsStr>) -> Result<OsString> { |
415 self.get_authtok(prompt, ItemType::OldAuthTok) | 389 self.get_authtok(prompt, ItemType::OldAuthTok) |
416 } | 390 } |
417 | 391 |
418 cstr_item!(get = authtok_item, item = ItemType::AuthTok); | 392 fn authtok_item(&self) -> Result<Option<OsString>> { |
419 cstr_item!(get = old_authtok_item, item = ItemType::OldAuthTok); | 393 unsafe { items::get_cstr_item(self, ItemType::AuthTok) } |
394 } | |
395 fn old_authtok_item(&self) -> Result<Option<OsString>> { | |
396 unsafe { items::get_cstr_item(self, ItemType::OldAuthTok) } | |
397 } | |
420 } | 398 } |
421 | 399 |
422 /// Function called at the end of a PAM session that is called to clean up | 400 /// Function called at the end of a PAM session that is called to clean up |
423 /// a value previously provided to PAM in a `pam_set_data` call. | 401 /// a value previously provided to PAM in a `pam_set_data` call. |
424 /// | 402 /// |
450 } | 428 } |
451 | 429 |
452 #[cfg(not(any(pam_impl = "LinuxPam", pam_impl = "OpenPam")))] | 430 #[cfg(not(any(pam_impl = "LinuxPam", pam_impl = "OpenPam")))] |
453 fn get_authtok(&mut self, prompt: Option<&str>, item_type: ItemType) -> Result<String> { | 431 fn get_authtok(&mut self, prompt: Option<&str>, item_type: ItemType) -> Result<String> { |
454 Err(ErrorCode::ConversationError) | 432 Err(ErrorCode::ConversationError) |
455 } | |
456 | |
457 /// Gets a C string item. | |
458 /// | |
459 /// # Safety | |
460 /// | |
461 /// You better be requesting an item which is a C string. | |
462 unsafe fn get_cstr_item(&self, item_type: ItemType) -> Result<Option<OsString>> { | |
463 let mut output = ptr::null(); | |
464 let ret = | |
465 unsafe { libpam_sys::pam_get_item(self.raw_ref(), item_type as c_int, &mut output) }; | |
466 ErrorCode::result_from(ret)?; | |
467 Ok(memory::copy_pam_string(output.cast())) | |
468 } | |
469 | |
470 /// Sets a C string item. | |
471 /// | |
472 /// # Safety | |
473 /// | |
474 /// You better be setting an item which is a C string. | |
475 unsafe fn set_cstr_item(&mut self, item_type: ItemType, data: Option<&OsStr>) -> Result<()> { | |
476 let data_str = memory::option_cstr_os(data); | |
477 let ret = unsafe { | |
478 libpam_sys::pam_set_item( | |
479 self.raw_mut(), | |
480 item_type as c_int, | |
481 memory::prompt_ptr(data_str.as_deref()).cast(), | |
482 ) | |
483 }; | |
484 ErrorCode::result_from(ret) | |
485 } | 433 } |
486 | 434 |
487 /// Gets the `PAM_CONV` item from the handle. | 435 /// Gets the `PAM_CONV` item from the handle. |
488 fn conversation_item(&self) -> Result<&PamConv> { | 436 fn conversation_item(&self) -> Result<&PamConv> { |
489 let output: *const PamConv = ptr::null_mut(); | 437 let output: *const PamConv = ptr::null_mut(); |