comparison 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
comparison
equal deleted inserted replaced
68:e4e7d68234d0 69:8f3ae0c7ab92
94 /// or [`pam_set_item` in the Module Writer's Guide][mwg]. 94 /// or [`pam_set_item` in the Module Writer's Guide][mwg].
95 /// 95 ///
96 /// [man]: https://www.man7.org/linux/man-pages/man3/pam_set_item.3.html 96 /// [man]: https://www.man7.org/linux/man-pages/man3/pam_set_item.3.html
97 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-by-module-item.html#mwg-pam_set_item 97 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-by-module-item.html#mwg-pam_set_item
98 fn set_item<T: Item>(&mut self, item: T) -> Result<()>; 98 fn set_item<T: Item>(&mut self, item: T) -> Result<()>;
99 99 }
100
101 /// Functionality of a PAM handle that can be expected by a PAM application.
102 ///
103 /// If you are not writing a PAM client application (e.g., you are writing
104 /// a module), you should not use the functionality exposed by this trait.
105 ///
106 /// Like [`PamHandle`], this is intended to allow creating mock implementations
107 /// of PAM for testing PAM applications.
108 pub trait PamApplicationHandle: PamHandle {
100 /// Closes the PAM session on an owned PAM handle. 109 /// Closes the PAM session on an owned PAM handle.
101 /// 110 ///
102 /// This should be called with the result of the application's last call 111 /// This should be called with the result of the application's last call
103 /// into PAM services. Since this is only applicable to *owned* PAM handles, 112 /// into PAM services. Since this is only applicable to *owned* PAM handles,
104 /// a PAM module should never call this (and it will never be handed 113 /// a PAM module should never call this (and it will never be handed
105 /// an owned `PamHandle` that it can `close`). 114 /// an owned `PamHandle` that it can `close`).
106 /// 115 ///
107 /// See the [`pam_end` manual page][man] for more information. 116 /// See the [`pam_end` manual page][man] for more information.
108 /// 117 ///
109 /// ```no_run 118 /// ```no_run
110 /// # use nonstick::PamHandle; 119 /// # use nonstick::PamApplicationHandle;
111 /// # use std::error::Error; 120 /// # use std::error::Error;
112 /// # fn _doc(handle: impl PamHandle, auth_result: nonstick::Result<()>) -> Result<(), Box<dyn Error>> { 121 /// # fn _doc(handle: impl PamApplicationHandle, auth_result: nonstick::Result<()>) -> Result<(), Box<dyn Error>> {
113 /// // Earlier: authentication was performed and the result was stored 122 /// // Earlier: authentication was performed and the result was stored
114 /// // into auth_result. 123 /// // into auth_result.
115 /// handle.close(auth_result)?; 124 /// handle.close(auth_result)?;
116 /// # Ok(()) 125 /// # Ok(())
117 /// # } 126 /// # }
180 } 189 }
181 } 190 }
182 191
183 impl Drop for LibPamHandle { 192 impl Drop for LibPamHandle {
184 /// Ends the PAM session with a zero error code. 193 /// Ends the PAM session with a zero error code.
194 /// You probably want to call [`close`](Self::close) instead of
195 /// letting this drop by itself.
185 fn drop(&mut self) { 196 fn drop(&mut self) {
186 unsafe { 197 unsafe {
187 pam_ffi::pam_end(&mut self.0, 0); 198 pam_ffi::pam_end(&mut self.0, 0);
188 } 199 }
189 } 200 }
233 let ret = unsafe { 244 let ret = unsafe {
234 pam_ffi::pam_set_item(&mut self.0, T::type_id().into(), item.into_raw().cast()) 245 pam_ffi::pam_set_item(&mut self.0, T::type_id().into(), item.into_raw().cast())
235 }; 246 };
236 ErrorCode::result_from(ret) 247 ErrorCode::result_from(ret)
237 } 248 }
238 249 }
250
251 impl PamApplicationHandle for LibPamHandle {
239 fn close(mut self, status: Result<()>) -> Result<()> { 252 fn close(mut self, status: Result<()>) -> Result<()> {
240 let result = unsafe { pam_ffi::pam_end(&mut self.0, ErrorCode::result_to_c(status)) }; 253 let result = unsafe { pam_ffi::pam_end(&mut self.0, ErrorCode::result_to_c(status)) };
241 // Since we've already `pam_end`ed this session, we don't want it to be 254 // Since we've already `pam_end`ed this session, we don't want it to be
242 // double-freed on drop. 255 // double-freed on drop.
243 mem::forget(self); 256 mem::forget(self);