Mercurial > crates > nonstick
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); |