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(); |
