Mercurial > crates > nonstick
comparison src/handle.rs @ 71:58f9d2a4df38
Reorganize everything again???
- Splits ffi/memory stuff into a bunch of stuff in the pam_ffi module.
- Builds infrastructure for passing Messages and Responses.
- Adds tests for some things at least.
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Tue, 03 Jun 2025 21:54:58 -0400 |
| parents | 9f8381a1c09c |
| children | 47eb242a4f88 |
comparison
equal
deleted
inserted
replaced
| 70:9f8381a1c09c | 71:58f9d2a4df38 |
|---|---|
| 1 //! The wrapper types and traits for handles into the PAM library. | 1 //! The wrapper types and traits for handles into the PAM library. |
| 2 use crate::constants::{ErrorCode, Result}; | 2 use crate::constants::{ErrorCode, Result}; |
| 3 use crate::items::{Item, ItemType}; | 3 use crate::items::{Item, ItemType}; |
| 4 use crate::{memory, pam_ffi}; | 4 use crate::pam_ffi; |
| 5 use libc::c_char; | 5 use crate::pam_ffi::memory; |
| 6 use secure_string::SecureString; | 6 use secure_string::SecureString; |
| 7 use std::ffi::{c_int, CString}; | 7 use std::ffi::{c_char, c_int, c_void, CString}; |
| 8 use std::mem; | 8 use std::{mem, ptr}; |
| 9 | 9 |
| 10 /// Features of a PAM handle that are available to applications and modules. | 10 /// Features of a PAM handle that are available to applications and modules. |
| 11 /// | 11 /// |
| 12 /// You probably want [`LibPamHandle`]. This trait is intended to allow creating | 12 /// You probably want [`LibPamHandle`]. This trait is intended to allow creating |
| 13 /// mock PAM handle types used for testing PAM modules and applications. | 13 /// mock PAM handle types used for testing PAM modules and applications. |
| 175 /// | 175 /// |
| 176 /// This structure wraps an opaque PAM handle and gives you a nice Rusty | 176 /// This structure wraps an opaque PAM handle and gives you a nice Rusty |
| 177 /// interface to use PAM. | 177 /// interface to use PAM. |
| 178 #[repr(C)] | 178 #[repr(C)] |
| 179 pub struct LibPamHandle(pam_ffi::Handle); | 179 pub struct LibPamHandle(pam_ffi::Handle); |
| 180 | |
| 181 impl LibPamHandle { | |
| 182 /// Converts a pointer passed from PAM into a borrowed handle. | |
| 183 /// | |
| 184 /// # Safety | |
| 185 /// | |
| 186 /// It is your responsibility to provide a valid pointer. | |
| 187 pub unsafe fn from_ptr<'a>(ptr: *mut libc::c_void) -> &'a mut LibPamHandle { | |
| 188 &mut *(ptr as *mut LibPamHandle) | |
| 189 } | |
| 190 } | |
| 191 | 180 |
| 192 impl Drop for LibPamHandle { | 181 impl Drop for LibPamHandle { |
| 193 /// Ends the PAM session with a zero error code. | 182 /// Ends the PAM session with a zero error code. |
| 194 /// You probably want to call [`close`](Self::close) instead of | 183 /// You probably want to call [`close`](Self::close) instead of |
| 195 /// letting this drop by itself. | 184 /// letting this drop by itself. |
| 201 } | 190 } |
| 202 | 191 |
| 203 impl PamHandle for LibPamHandle { | 192 impl PamHandle for LibPamHandle { |
| 204 fn get_user(&mut self, prompt: Option<&str>) -> crate::Result<String> { | 193 fn get_user(&mut self, prompt: Option<&str>) -> crate::Result<String> { |
| 205 let prompt = memory::option_cstr(prompt)?; | 194 let prompt = memory::option_cstr(prompt)?; |
| 206 let mut output: *const c_char = std::ptr::null_mut(); | 195 let mut output: *const c_char = ptr::null_mut(); |
| 207 let ret = unsafe { | 196 let ret = unsafe { |
| 208 pam_ffi::pam_get_user(&self.0, &mut output, memory::prompt_ptr(prompt.as_ref())) | 197 pam_ffi::pam_get_user(&self.0, &mut output, memory::prompt_ptr(prompt.as_ref())) |
| 209 }; | 198 }; |
| 210 ErrorCode::result_from(ret)?; | 199 ErrorCode::result_from(ret)?; |
| 211 memory::copy_pam_string(output) | 200 unsafe {memory::copy_pam_string(output)} |
| 212 } | 201 } |
| 213 | 202 |
| 214 fn get_authtok(&mut self, prompt: Option<&str>) -> crate::Result<SecureString> { | 203 fn get_authtok(&mut self, prompt: Option<&str>) -> crate::Result<SecureString> { |
| 215 let prompt = memory::option_cstr(prompt)?; | 204 let prompt = memory::option_cstr(prompt)?; |
| 216 let mut output: *const c_char = std::ptr::null_mut(); | 205 let mut output: *const c_char = ptr::null_mut(); |
| 217 let res = unsafe { | 206 let res = unsafe { |
| 218 pam_ffi::pam_get_authtok( | 207 pam_ffi::pam_get_authtok( |
| 219 &self.0, | 208 &self.0, |
| 220 ItemType::AuthTok.into(), | 209 ItemType::AuthTok.into(), |
| 221 &mut output, | 210 &mut output, |
| 222 memory::prompt_ptr(prompt.as_ref()), | 211 memory::prompt_ptr(prompt.as_ref()), |
| 223 ) | 212 ) |
| 224 }; | 213 }; |
| 225 ErrorCode::result_from(res)?; | 214 ErrorCode::result_from(res)?; |
| 226 memory::copy_pam_string(output).map(SecureString::from) | 215 unsafe {memory::copy_pam_string(output)}.map(SecureString::from) |
| 227 } | 216 } |
| 228 | 217 |
| 229 fn get_item<T: Item>(&mut self) -> crate::Result<Option<T>> { | 218 fn get_item<T: Item>(&mut self) -> Result<Option<T>> { |
| 230 let mut ptr: *const libc::c_void = std::ptr::null(); | 219 let mut ptr: *const c_void = ptr::null(); |
| 231 let out = unsafe { | 220 let out = unsafe { |
| 232 let ret = pam_ffi::pam_get_item(&self.0, T::type_id().into(), &mut ptr); | 221 let ret = pam_ffi::pam_get_item(&self.0, T::type_id().into(), &mut ptr); |
| 233 ErrorCode::result_from(ret)?; | 222 ErrorCode::result_from(ret)?; |
| 234 let typed_ptr: *const T::Raw = ptr.cast(); | 223 (ptr as *const T::Raw).as_ref().map(|p| T::from_raw(p)) |
| 235 match typed_ptr.is_null() { | |
| 236 true => None, | |
| 237 false => Some(T::from_raw(typed_ptr)), | |
| 238 } | |
| 239 }; | 224 }; |
| 240 Ok(out) | 225 Ok(out) |
| 241 } | 226 } |
| 242 | 227 |
| 243 fn set_item<T: Item>(&mut self, item: T) -> crate::Result<()> { | 228 fn set_item<T: Item>(&mut self, item: T) -> Result<()> { |
| 244 let ret = unsafe { | 229 let ret = unsafe { |
| 245 pam_ffi::pam_set_item(&mut self.0, T::type_id().into(), item.into_raw().cast()) | 230 pam_ffi::pam_set_item(&mut self.0, T::type_id().into(), item.into_raw().cast()) |
| 246 }; | 231 }; |
| 247 ErrorCode::result_from(ret) | 232 ErrorCode::result_from(ret) |
| 248 } | 233 } |
| 259 } | 244 } |
| 260 | 245 |
| 261 impl PamModuleHandle for LibPamHandle { | 246 impl PamModuleHandle for LibPamHandle { |
| 262 unsafe fn get_data<T>(&mut self, key: &str) -> crate::Result<Option<&T>> { | 247 unsafe fn get_data<T>(&mut self, key: &str) -> crate::Result<Option<&T>> { |
| 263 let c_key = CString::new(key).map_err(|_| ErrorCode::ConversationError)?; | 248 let c_key = CString::new(key).map_err(|_| ErrorCode::ConversationError)?; |
| 264 let mut ptr: *const libc::c_void = std::ptr::null(); | 249 let mut ptr: *const c_void = ptr::null(); |
| 265 ErrorCode::result_from(pam_ffi::pam_get_data(&self.0, c_key.as_ptr(), &mut ptr))?; | 250 ErrorCode::result_from(pam_ffi::pam_get_data(&self.0, c_key.as_ptr(), &mut ptr))?; |
| 266 match ptr.is_null() { | 251 Ok((ptr as *const T).as_ref()) |
| 267 true => Ok(None), | |
| 268 false => { | |
| 269 let typed_ptr = ptr.cast(); | |
| 270 Ok(Some(&*typed_ptr)) | |
| 271 } | |
| 272 } | |
| 273 } | 252 } |
| 274 | 253 |
| 275 fn set_data<T>(&mut self, key: &str, data: Box<T>) -> crate::Result<()> { | 254 fn set_data<T>(&mut self, key: &str, data: Box<T>) -> crate::Result<()> { |
| 276 let c_key = CString::new(key).map_err(|_| ErrorCode::ConversationError)?; | 255 let c_key = CString::new(key).map_err(|_| ErrorCode::ConversationError)?; |
| 277 let ret = unsafe { | 256 let ret = unsafe { |
