diff src/handle.rs @ 69:8f3ae0c7ab92

Rework conversation data types and make safe wrappers. This removes the old `Conversation` type and reworks the FFI types used for PAM conversations. This creates safe `TestResponse` and `BinaryResponse` structures in `conv`, providing a safe way to pass response messages to PAM Conversations. The internals of these types are allocated on the C heap, as required by PAM. We also remove the Conversation struct, which was specific to the real PAM implementation so that we can introduce a better abstraction. Also splits a new `PamApplicationHandle` trait from `PamHandle`, for the parts of a PAM handle that are specific to the application side of a PAM transaction.
author Paul Fisher <paul@pfish.zone>
date Sun, 01 Jun 2025 01:15:04 -0400
parents a674799a5cd3
children 9f8381a1c09c
line wrap: on
line diff
--- a/src/handle.rs	Tue May 27 16:40:49 2025 -0400
+++ b/src/handle.rs	Sun Jun 01 01:15:04 2025 -0400
@@ -96,7 +96,16 @@
     /// [man]: https://www.man7.org/linux/man-pages/man3/pam_set_item.3.html
     /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-by-module-item.html#mwg-pam_set_item
     fn set_item<T: Item>(&mut self, item: T) -> Result<()>;
+}
 
+/// Functionality of a PAM handle that can be expected by a PAM application.
+///
+/// If you are not writing a PAM client application (e.g., you are writing
+/// a module), you should not use the functionality exposed by this trait.
+///
+/// Like [`PamHandle`], this is intended to allow creating mock implementations
+/// of PAM for testing PAM applications.
+pub trait PamApplicationHandle: PamHandle {
     /// Closes the PAM session on an owned PAM handle.
     ///
     /// This should be called with the result of the application's last call
@@ -107,9 +116,9 @@
     /// See the [`pam_end` manual page][man] for more information.
     ///
     /// ```no_run
-    /// # use nonstick::PamHandle;
+    /// # use nonstick::PamApplicationHandle;
     /// # use std::error::Error;
-    /// # fn _doc(handle: impl PamHandle, auth_result: nonstick::Result<()>) -> Result<(), Box<dyn Error>> {
+    /// # fn _doc(handle: impl PamApplicationHandle, auth_result: nonstick::Result<()>) -> Result<(), Box<dyn Error>> {
     /// // Earlier: authentication was performed and the result was stored
     /// // into auth_result.
     /// handle.close(auth_result)?;
@@ -182,6 +191,8 @@
 
 impl Drop for LibPamHandle {
     /// Ends the PAM session with a zero error code.
+    /// You probably want to call [`close`](Self::close) instead of
+    /// letting this drop by itself.
     fn drop(&mut self) {
         unsafe {
             pam_ffi::pam_end(&mut self.0, 0);
@@ -235,7 +246,9 @@
         };
         ErrorCode::result_from(ret)
     }
+}
 
+impl PamApplicationHandle for LibPamHandle {
     fn close(mut self, status: Result<()>) -> Result<()> {
         let result = unsafe { pam_ffi::pam_end(&mut self.0, ErrorCode::result_to_c(status)) };
         // Since we've already `pam_end`ed this session, we don't want it to be