comparison src/handle.rs @ 143:ebb71a412b58

Turn everything into OsString and Just Walk Out! for strings with nul. To reduce the hazard surface of the API, this replaces most uses of &str with &OsStr (and likewise with String/OsString). Also, I've decided that instead of dealing with callers putting `\0` in their parameters, I'm going to follow the example of std::env and Just Walk Out! (i.e., panic!()). This makes things a lot less annoying for both me and (hopefully) users.
author Paul Fisher <paul@pfish.zone>
date Sat, 05 Jul 2025 22:12:46 -0400
parents a508a69c068a
children 56b559b7ecea
comparison
equal deleted inserted replaced
142:5c1e315c18ff 143:ebb71a412b58
3 use crate::constants::{Flags, Result}; 3 use crate::constants::{Flags, Result};
4 use crate::conv::Conversation; 4 use crate::conv::Conversation;
5 use crate::environ::{EnvironMap, EnvironMapMut}; 5 use crate::environ::{EnvironMap, EnvironMapMut};
6 use crate::logging::{Level, Location}; 6 use crate::logging::{Level, Location};
7 use crate::{guide, linklist, man7, manbsd, stdlinks}; 7 use crate::{guide, linklist, man7, manbsd, stdlinks};
8 use std::ffi::{OsStr, OsString};
8 9
9 macro_rules! trait_item { 10 macro_rules! trait_item {
10 ($(#[$md:meta])* get = $getter:ident, item = $item:literal $(, see = $see:path)?) => { 11 ($(#[$md:meta])* get = $getter:ident, item = $item:literal $(, see = $see:path)?) => {
11 $(#[$md])* 12 $(#[$md])*
12 #[doc = ""] 13 #[doc = ""]
24 #[doc = linklist!(pam_get_item: mwg, adg, _std)] 25 #[doc = linklist!(pam_get_item: mwg, adg, _std)]
25 /// 26 ///
26 #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_get_item")] 27 #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_get_item")]
27 #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_item")] 28 #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_item")]
28 #[doc = stdlinks!(3 pam_get_item)] 29 #[doc = stdlinks!(3 pam_get_item)]
29 fn $getter(&self) -> Result<Option<String>>; 30 fn $getter(&self) -> Result<Option<OsString>>;
30 }; 31 };
31 ($(#[$md:meta])* set = $setter:ident, item = $item:literal $(, see = $see:path)?) => { 32 ($(#[$md:meta])* set = $setter:ident, item = $item:literal $(, see = $see:path)?) => {
32 $(#[$md])* 33 $(#[$md])*
33 #[doc = ""] 34 #[doc = ""]
34 #[doc = concat!("Sets the `", $item, "` from the PAM handle.")] 35 #[doc = concat!("Sets the `", $item, "` from the PAM handle.")]
35 $( 36 $(
36 #[doc = concat!("See [`", stringify!($see), "`].")] 37 #[doc = concat!("See [`", stringify!($see), "`].")]
37 )? 38 )?
38 /// 39 ///
39 /// Sets the item's value. PAM copies the string's contents. 40 /// Sets the item's value. PAM copies the string's contents.
40 /// If the string contains a null byte, this will return 41 ///
41 /// a `ConversationError`. 42 /// # Panics
43 ///
44 /// If the string contains a nul byte, this will panic.
42 /// 45 ///
43 /// # References 46 /// # References
44 /// 47 ///
45 #[doc = linklist!(pam_set_item: mwg, adg, _std)] 48 #[doc = linklist!(pam_set_item: mwg, adg, _std)]
46 /// 49 ///
47 #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_set_item")] 50 #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_set_item")]
48 #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_set_item")] 51 #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_set_item")]
49 #[doc = stdlinks!(3 pam_set_item)] 52 #[doc = stdlinks!(3 pam_set_item)]
50 fn $setter(&mut self, value: Option<&str>) -> Result<()>; 53 fn $setter(&mut self, value: Option<&OsStr>) -> Result<()>;
51 }; 54 };
52 } 55 }
53 56
54 /// Functionality for both PAM applications and PAM modules. 57 /// Functionality for both PAM applications and PAM modules.
55 /// 58 ///
114 /// // Get the username using the default prompt. 117 /// // Get the username using the default prompt.
115 /// let user = handle.username(None)?; 118 /// let user = handle.username(None)?;
116 /// // Get the username using a custom prompt. 119 /// // Get the username using a custom prompt.
117 /// // If this were actually called right after the above, 120 /// // If this were actually called right after the above,
118 /// // both user and user_2 would have the same value. 121 /// // both user and user_2 would have the same value.
119 /// let user_2 = handle.username(Some("who ARE you even???"))?; 122 /// let user_2 = handle.username(Some("who ARE you even???".as_ref()))?;
120 /// # Ok(()) 123 /// # Ok(())
121 /// # } 124 /// # }
122 /// ``` 125 /// ```
123 #[doc = stdlinks!(3 pam_get_user)] 126 #[doc = stdlinks!(3 pam_get_user)]
124 #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_user")] 127 #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_user")]
125 fn username(&mut self, prompt: Option<&str>) -> Result<String>; 128 fn username(&mut self, prompt: Option<&OsStr>) -> Result<OsString>;
126 129
127 /// The contents of the environment to set, read-only. 130 /// The contents of the environment to set, read-only.
128 fn environ(&self) -> impl EnvironMap; 131 fn environ(&self) -> impl EnvironMap;
129 132
130 /// A writable version of the environment. 133 /// A writable version of the environment.
329 /// # use nonstick::handle::PamHandleModule; 332 /// # use nonstick::handle::PamHandleModule;
330 /// # fn _doc(handle: &mut impl PamHandleModule) -> Result<(), Box<dyn std::error::Error>> { 333 /// # fn _doc(handle: &mut impl PamHandleModule) -> Result<(), Box<dyn std::error::Error>> {
331 /// // Get the user's password using the default prompt. 334 /// // Get the user's password using the default prompt.
332 /// let pass = handle.authtok(None)?; 335 /// let pass = handle.authtok(None)?;
333 /// // Get the user's password using a custom prompt. 336 /// // Get the user's password using a custom prompt.
334 /// let pass = handle.authtok(Some("Reveal your secrets!"))?; 337 /// let pass = handle.authtok(Some("Reveal your secrets!".as_ref()))?;
335 /// Ok(()) 338 /// Ok(())
336 /// # } 339 /// # }
337 /// ``` 340 /// ```
338 #[doc = man7!(3 pam_get_authtok)] 341 #[doc = man7!(3 pam_get_authtok)]
339 #[doc = manbsd!(3 pam_get_authtok)] 342 #[doc = manbsd!(3 pam_get_authtok)]
340 fn authtok(&mut self, prompt: Option<&str>) -> Result<String>; 343 fn authtok(&mut self, prompt: Option<&OsStr>) -> Result<OsString>;
341 344
342 /// Retrieves the user's old authentication token when changing passwords. 345 /// Retrieves the user's old authentication token when changing passwords.
343 /// 346 ///
344 /// 347 ///
345 fn old_authtok(&mut self, prompt: Option<&str>) -> Result<String>; 348 fn old_authtok(&mut self, prompt: Option<&OsStr>) -> Result<OsString>;
346 349
347 trait_item!( 350 trait_item!(
348 /// Gets the user's authentication token (e.g., password). 351 /// Gets the user's authentication token (e.g., password).
349 /// 352 ///
350 /// This is normally set automatically by PAM when calling 353 /// This is normally set automatically by PAM when calling