comparison src/libpam/handle.rs @ 95:51c9d7e8261a

Return owned strings rather than borrowed strings. It's going to be irritating to have to work with strings borrowed from the PAM handle rather than just using your own. They're cheap enough to copy.
author Paul Fisher <paul@pfish.zone>
date Mon, 23 Jun 2025 14:03:44 -0400
parents 5ddbcada30f2
children f3e260f9ddcb
comparison
equal deleted inserted replaced
94:db167f96ba46 95:51c9d7e8261a
63 } 63 }
64 64
65 /// Macro to implement getting/setting a CStr-based item. 65 /// Macro to implement getting/setting a CStr-based item.
66 macro_rules! cstr_item { 66 macro_rules! cstr_item {
67 (get = $getter:ident, item = $item_type:path) => { 67 (get = $getter:ident, item = $item_type:path) => {
68 fn $getter(&self) -> Result<Option<&str>> { 68 fn $getter(&self) -> Result<Option<String>> {
69 unsafe { self.get_cstr_item($item_type) } 69 unsafe { self.get_cstr_item($item_type) }
70 } 70 }
71 }; 71 };
72 (set = $setter:ident, item = $item_type:path) => { 72 (set = $setter:ident, item = $item_type:path) => {
73 fn $setter(&mut self, value: Option<&str>) -> Result<()> { 73 fn $setter(&mut self, value: Option<&str>) -> Result<()> {
96 pam_ffi::openpam_log(self, level as c_int, c"%s".as_ptr().cast(), entry.as_ptr()) 96 pam_ffi::openpam_log(self, level as c_int, c"%s".as_ptr().cast(), entry.as_ptr())
97 } 97 }
98 } 98 }
99 } 99 }
100 100
101 fn username(&mut self, prompt: Option<&str>) -> Result<&str> { 101 fn username(&mut self, prompt: Option<&str>) -> Result<String> {
102 let prompt = memory::option_cstr(prompt)?; 102 let prompt = memory::option_cstr(prompt)?;
103 let mut output: *const c_char = ptr::null(); 103 let mut output: *const c_char = ptr::null();
104 let ret = unsafe { 104 let ret = unsafe {
105 pam_ffi::pam_get_user(self, &mut output, memory::prompt_ptr(prompt.as_ref())) 105 pam_ffi::pam_get_user(self, &mut output, memory::prompt_ptr(prompt.as_ref()))
106 }; 106 };
107 ErrorCode::result_from(ret)?; 107 ErrorCode::result_from(ret)?;
108 unsafe { memory::wrap_string(output) } 108 unsafe { memory::copy_pam_string(output) }
109 .transpose() 109 .transpose()
110 .unwrap_or(Err(ErrorCode::ConversationError)) 110 .unwrap_or(Err(ErrorCode::ConversationError))
111 } 111 }
112 112
113 cstr_item!(get = user_item, item = ItemType::User); 113 cstr_item!(get = user_item, item = ItemType::User);
138 } 138 }
139 } 139 }
140 } 140 }
141 141
142 impl PamHandleModule for LibPamHandle { 142 impl PamHandleModule for LibPamHandle {
143 fn authtok(&mut self, prompt: Option<&str>) -> Result<&str> { 143 fn authtok(&mut self, prompt: Option<&str>) -> Result<String> {
144 let prompt = memory::option_cstr(prompt)?; 144 let prompt = memory::option_cstr(prompt)?;
145 let mut output: *const c_char = ptr::null_mut(); 145 let mut output: *const c_char = ptr::null_mut();
146 // SAFETY: We're calling this with known-good values. 146 // SAFETY: We're calling this with known-good values.
147 let res = unsafe { 147 let res = unsafe {
148 pam_ffi::pam_get_authtok( 148 pam_ffi::pam_get_authtok(
152 memory::prompt_ptr(prompt.as_ref()), 152 memory::prompt_ptr(prompt.as_ref()),
153 ) 153 )
154 }; 154 };
155 ErrorCode::result_from(res)?; 155 ErrorCode::result_from(res)?;
156 // SAFETY: We got this string from PAM. 156 // SAFETY: We got this string from PAM.
157 unsafe { memory::wrap_string(output) } 157 unsafe { memory::copy_pam_string(output) }
158 .transpose() 158 .transpose()
159 .unwrap_or(Err(ErrorCode::ConversationError)) 159 .unwrap_or(Err(ErrorCode::ConversationError))
160 } 160 }
161 161
162 cstr_item!(get = authtok_item, item = ItemType::AuthTok); 162 cstr_item!(get = authtok_item, item = ItemType::AuthTok);
177 /// Gets a C string item. 177 /// Gets a C string item.
178 /// 178 ///
179 /// # Safety 179 /// # Safety
180 /// 180 ///
181 /// You better be requesting an item which is a C string. 181 /// You better be requesting an item which is a C string.
182 unsafe fn get_cstr_item(&self, item_type: ItemType) -> Result<Option<&str>> { 182 unsafe fn get_cstr_item(&self, item_type: ItemType) -> Result<Option<String>> {
183 let mut output = ptr::null(); 183 let mut output = ptr::null();
184 let ret = unsafe { pam_ffi::pam_get_item(self, item_type as c_int, &mut output) }; 184 let ret = unsafe { pam_ffi::pam_get_item(self, item_type as c_int, &mut output) };
185 ErrorCode::result_from(ret)?; 185 ErrorCode::result_from(ret)?;
186 memory::wrap_string(output.cast()) 186 memory::copy_pam_string(output.cast())
187 } 187 }
188 188
189 /// Sets a C string item. 189 /// Sets a C string item.
190 /// 190 ///
191 /// # Safety 191 /// # Safety
233 self.last_return.set(split(&result)); 233 self.last_return.set(split(&result));
234 result 234 result
235 } 235 }
236 }; 236 };
237 (get = $get:ident$(, set = $set:ident)?) => { 237 (get = $get:ident$(, set = $set:ident)?) => {
238 delegate!(fn $get(&self) -> Result<Option<&str>>); 238 delegate!(fn $get(&self) -> Result<Option<String>>);
239 $(delegate!(set = $set);)? 239 $(delegate!(set = $set);)?
240 }; 240 };
241 (set = $set:ident) => { 241 (set = $set:ident) => {
242 delegate!(fn $set(&mut self, value: Option<&str>) -> Result<()>); 242 delegate!(fn $set(&mut self, value: Option<&str>) -> Result<()>);
243 }; 243 };
249 249
250 impl PamShared for OwnedLibPamHandle<'_> { 250 impl PamShared for OwnedLibPamHandle<'_> {
251 fn log(&self, level: Level, entry: &str) { 251 fn log(&self, level: Level, entry: &str) {
252 self.handle.log(level, entry) 252 self.handle.log(level, entry)
253 } 253 }
254 delegate!(fn username(&mut self, prompt: Option<&str>) -> Result<&str>); 254 delegate!(fn username(&mut self, prompt: Option<&str>) -> Result<String>);
255 delegate!(get = user_item, set = set_user_item); 255 delegate!(get = user_item, set = set_user_item);
256 delegate!(get = service, set = set_service); 256 delegate!(get = service, set = set_service);
257 delegate!(get = user_prompt, set = set_user_prompt); 257 delegate!(get = user_prompt, set = set_user_prompt);
258 delegate!(get = tty_name, set = set_tty_name); 258 delegate!(get = tty_name, set = set_tty_name);
259 delegate!(get = remote_user, set = set_remote_user); 259 delegate!(get = remote_user, set = set_remote_user);