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