Mercurial > crates > nonstick
comparison src/module.rs @ 59:3f4a77aa88be
Fix string copyting and improve error situation.
This change is too big and includes several things:
- Fix copying strings from PAM by fixing const and mut on pam funcs.
- Improve error enums by simplifying conversions and removing
unnecessary and ambiguous "success" variants.
- Make a bunch of casts nicer.
- Assorted other cleanup.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Wed, 21 May 2025 00:27:18 -0400 |
parents | daa2cde64601 |
children | 05cc2c27334f |
comparison
equal
deleted
inserted
replaced
58:868a278a362c | 59:3f4a77aa88be |
---|---|
1 //! Functions for use in pam modules. | 1 //! Functions for use in pam modules. |
2 | 2 |
3 use crate::constants::{Flags, PamResult, ErrorCode}; | 3 use crate::constants::{ErrorCode, Flags, PamResult}; |
4 use crate::items::{Item, ItemType}; | 4 use crate::items::{Item, ItemType}; |
5 use libc::c_char; | 5 use libc::c_char; |
6 use secure_string::SecureString; | |
6 use std::ffi::{c_int, CStr, CString}; | 7 use std::ffi::{c_int, CStr, CString}; |
7 use secure_string::SecureString; | |
8 | 8 |
9 /// Opaque type, used as a pointer when making pam API calls. | 9 /// Opaque type, used as a pointer when making pam API calls. |
10 /// | 10 /// |
11 /// A module is invoked via an external function such as `pam_sm_authenticate`. | 11 /// A module is invoked via an external function such as `pam_sm_authenticate`. |
12 /// Such a call provides a pam handle pointer. The same pointer should be given | 12 /// Such a call provides a pam handle pointer. The same pointer should be given |
25 ) -> c_int; | 25 ) -> c_int; |
26 | 26 |
27 fn pam_set_data( | 27 fn pam_set_data( |
28 pamh: *const PamHandle, | 28 pamh: *const PamHandle, |
29 module_data_name: *const c_char, | 29 module_data_name: *const c_char, |
30 data: *mut libc::c_void, | 30 data: *const libc::c_void, |
31 cleanup: extern "C" fn( | 31 cleanup: extern "C" fn( |
32 pamh: *const PamHandle, | 32 pamh: *const PamHandle, |
33 data: *mut libc::c_void, | 33 data: *mut libc::c_void, |
34 error_status: c_int, | 34 error_status: c_int, |
35 ), | 35 ), |
41 item: &mut *const libc::c_void, | 41 item: &mut *const libc::c_void, |
42 ) -> c_int; | 42 ) -> c_int; |
43 | 43 |
44 fn pam_set_item(pamh: *mut PamHandle, item_type: c_int, item: *const libc::c_void) -> c_int; | 44 fn pam_set_item(pamh: *mut PamHandle, item_type: c_int, item: *const libc::c_void) -> c_int; |
45 | 45 |
46 fn pam_get_user(pamh: *const PamHandle, user: &*mut c_char, prompt: *const c_char) -> c_int; | 46 fn pam_get_user( |
47 pamh: *const PamHandle, | |
48 user: &mut *const c_char, | |
49 prompt: *const c_char, | |
50 ) -> c_int; | |
47 | 51 |
48 fn pam_get_authtok( | 52 fn pam_get_authtok( |
49 pamh: *const PamHandle, | 53 pamh: *const PamHandle, |
50 item_type: c_int, | 54 item_type: c_int, |
51 data: &*mut c_char, | 55 data: &mut *const c_char, |
52 prompt: *const c_char, | 56 prompt: *const c_char, |
53 ) -> c_int; | 57 ) -> c_int; |
54 | 58 |
55 } | 59 } |
56 | 60 |
58 /// a value previously provided to PAM in a `pam_set_data` call. | 62 /// a value previously provided to PAM in a `pam_set_data` call. |
59 /// | 63 /// |
60 /// You should never call this yourself. | 64 /// You should never call this yourself. |
61 extern "C" fn cleanup<T>(_: *const PamHandle, c_data: *mut libc::c_void, _: c_int) { | 65 extern "C" fn cleanup<T>(_: *const PamHandle, c_data: *mut libc::c_void, _: c_int) { |
62 unsafe { | 66 unsafe { |
63 let _data: Box<T> = Box::from_raw(c_data.cast::<T>()); | 67 let _data: Box<T> = Box::from_raw(c_data.cast()); |
64 } | 68 } |
65 } | 69 } |
66 | 70 |
67 impl PamHandle { | 71 impl PamHandle { |
68 /// Gets some value, identified by `key`, that has been set by the module | 72 /// Gets some value, identified by `key`, that has been set by the module |
86 let mut ptr: *const libc::c_void = std::ptr::null(); | 90 let mut ptr: *const libc::c_void = std::ptr::null(); |
87 ErrorCode::result_from(pam_get_data(self, c_key.as_ptr(), &mut ptr))?; | 91 ErrorCode::result_from(pam_get_data(self, c_key.as_ptr(), &mut ptr))?; |
88 match ptr.is_null() { | 92 match ptr.is_null() { |
89 true => Ok(None), | 93 true => Ok(None), |
90 false => { | 94 false => { |
91 let typed_ptr = ptr.cast::<T>(); | 95 let typed_ptr = ptr.cast(); |
92 Ok(Some(&*typed_ptr)) | 96 Ok(Some(&*typed_ptr)) |
93 } | 97 } |
94 } | 98 } |
95 } | 99 } |
96 | 100 |
107 let c_key = CString::new(key).map_err(|_| ErrorCode::ConversationError)?; | 111 let c_key = CString::new(key).map_err(|_| ErrorCode::ConversationError)?; |
108 let ret = unsafe { | 112 let ret = unsafe { |
109 pam_set_data( | 113 pam_set_data( |
110 self, | 114 self, |
111 c_key.as_ptr(), | 115 c_key.as_ptr(), |
112 Box::into_raw(data).cast::<libc::c_void>(), | 116 Box::into_raw(data).cast(), |
113 cleanup::<T>, | 117 cleanup::<T>, |
114 ) | 118 ) |
115 }; | 119 }; |
116 ErrorCode::result_from(ret) | 120 ErrorCode::result_from(ret) |
117 } | 121 } |
131 pub fn get_item<T: crate::items::Item>(&self) -> PamResult<Option<T>> { | 135 pub fn get_item<T: crate::items::Item>(&self) -> PamResult<Option<T>> { |
132 let mut ptr: *const libc::c_void = std::ptr::null(); | 136 let mut ptr: *const libc::c_void = std::ptr::null(); |
133 let out = unsafe { | 137 let out = unsafe { |
134 let ret = pam_get_item(self, T::type_id().into(), &mut ptr); | 138 let ret = pam_get_item(self, T::type_id().into(), &mut ptr); |
135 ErrorCode::result_from(ret)?; | 139 ErrorCode::result_from(ret)?; |
136 let typed_ptr = ptr.cast::<T::Raw>(); | 140 let typed_ptr: *const T::Raw = ptr.cast(); |
137 match typed_ptr.is_null() { | 141 match typed_ptr.is_null() { |
138 true => None, | 142 true => None, |
139 false => Some(T::from_raw(typed_ptr)), | 143 false => Some(T::from_raw(typed_ptr)), |
140 } | 144 } |
141 }; | 145 }; |
149 /// | 153 /// |
150 /// # Errors | 154 /// # Errors |
151 /// | 155 /// |
152 /// Returns an error if the underlying PAM function call fails. | 156 /// Returns an error if the underlying PAM function call fails. |
153 pub fn set_item<T: Item>(&mut self, item: T) -> PamResult<()> { | 157 pub fn set_item<T: Item>(&mut self, item: T) -> PamResult<()> { |
154 let ret = | 158 let ret = unsafe { pam_set_item(self, T::type_id().into(), item.into_raw().cast()) }; |
155 unsafe { pam_set_item(self, T::type_id().into(), item.into_raw().cast::<libc::c_void>()) }; | |
156 ErrorCode::result_from(ret) | 159 ErrorCode::result_from(ret) |
157 } | 160 } |
158 | 161 |
159 /// Retrieves the name of the user who is authenticating or logging in. | 162 /// Retrieves the name of the user who is authenticating or logging in. |
160 /// | 163 /// |
166 /// # Errors | 169 /// # Errors |
167 /// | 170 /// |
168 /// Returns an error if the underlying PAM function call fails. | 171 /// Returns an error if the underlying PAM function call fails. |
169 pub fn get_user(&self, prompt: Option<&str>) -> PamResult<String> { | 172 pub fn get_user(&self, prompt: Option<&str>) -> PamResult<String> { |
170 let prompt = option_cstr(prompt)?; | 173 let prompt = option_cstr(prompt)?; |
171 let output: *mut c_char = std::ptr::null_mut(); | 174 let mut output: *const c_char = std::ptr::null_mut(); |
172 let ret = unsafe { pam_get_user(self, &output, prompt_ptr(prompt.as_ref())) }; | 175 let ret = unsafe { pam_get_user(self, &mut output, prompt_ptr(prompt.as_ref())) }; |
173 ErrorCode::result_from(ret)?; | 176 ErrorCode::result_from(ret)?; |
174 copy_pam_string(output) | 177 copy_pam_string(output) |
175 } | 178 } |
176 | 179 |
177 /// Retrieves the authentication token from the user. | 180 /// Retrieves the authentication token from the user. |
184 /// # Errors | 187 /// # Errors |
185 /// | 188 /// |
186 /// Returns an error if the underlying PAM function call fails. | 189 /// Returns an error if the underlying PAM function call fails. |
187 pub fn get_authtok(&self, prompt: Option<&str>) -> PamResult<SecureString> { | 190 pub fn get_authtok(&self, prompt: Option<&str>) -> PamResult<SecureString> { |
188 let prompt = option_cstr(prompt)?; | 191 let prompt = option_cstr(prompt)?; |
189 let output: *mut c_char = std::ptr::null_mut(); | 192 let mut output: *const c_char = std::ptr::null_mut(); |
190 let res = unsafe { | 193 let res = unsafe { |
191 pam_get_authtok( | 194 pam_get_authtok( |
192 self, | 195 self, |
193 ItemType::AuthTok.into(), | 196 ItemType::AuthTok.into(), |
194 &output, | 197 &mut output, |
195 prompt_ptr(prompt.as_ref()), | 198 prompt_ptr(prompt.as_ref()), |
196 ) | 199 ) |
197 }; | 200 }; |
198 ErrorCode::result_from(res)?; | 201 ErrorCode::result_from(res)?; |
199 copy_pam_string(output).map(SecureString::from) | 202 copy_pam_string(output).map(SecureString::from) |