comparison src/handle.rs @ 116:a12706e42c9d

Logging, macros, and building: - Changes logging API to accept the `Location` of the log statement. Fixes OpenPAM implementation. - Stops publicly exporting doc macros. - Uses dlopen to detect the PAM library rather than header jankery.
author Paul Fisher <paul@pfish.zone>
date Sun, 29 Jun 2025 18:27:51 -0400
parents dfcd96a74ac4
children
comparison
equal deleted inserted replaced
115:1e11a52b4665 116:a12706e42c9d
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 2
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; 6 use crate::logging::{Level, Location};
7 use crate::{_guide, _linklist, _man7, _manbsd, _stdlinks}; 7 use crate::{guide, linklist, man7, manbsd, stdlinks};
8 8
9 macro_rules! trait_item { 9 macro_rules! trait_item {
10 ($(#[$md:meta])* get = $getter:ident, item = $item:literal $(, see = $see:path)?) => { 10 ($(#[$md:meta])* get = $getter:ident, item = $item:literal $(, see = $see:path)?) => {
11 $(#[$md])* 11 $(#[$md])*
12 #[doc = ""] 12 #[doc = ""]
19 /// The item is assumed to be valid UTF-8 text. 19 /// The item is assumed to be valid UTF-8 text.
20 /// If it is not, `ConversationError` is returned. 20 /// If it is not, `ConversationError` is returned.
21 /// 21 ///
22 /// # References 22 /// # References
23 /// 23 ///
24 #[doc = _linklist!(pam_get_item: mwg, adg, _std)] 24 #[doc = linklist!(pam_get_item: mwg, adg, _std)]
25 /// 25 ///
26 #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_get_item")] 26 #[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")] 27 #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_item")]
28 #[doc = _stdlinks!(3 pam_get_item)] 28 #[doc = stdlinks!(3 pam_get_item)]
29 fn $getter(&self) -> Result<Option<String>>; 29 fn $getter(&self) -> Result<Option<String>>;
30 }; 30 };
31 ($(#[$md:meta])* set = $setter:ident, item = $item:literal $(, see = $see:path)?) => { 31 ($(#[$md:meta])* set = $setter:ident, item = $item:literal $(, see = $see:path)?) => {
32 $(#[$md])* 32 $(#[$md])*
33 #[doc = ""] 33 #[doc = ""]
40 /// If the string contains a null byte, this will return 40 /// If the string contains a null byte, this will return
41 /// a `ConversationError`. 41 /// a `ConversationError`.
42 /// 42 ///
43 /// # References 43 /// # References
44 /// 44 ///
45 #[doc = _linklist!(pam_set_item: mwg, adg, _std)] 45 #[doc = linklist!(pam_set_item: mwg, adg, _std)]
46 /// 46 ///
47 #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_set_item")] 47 #[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")] 48 #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_set_item")]
49 #[doc = _stdlinks!(3 pam_set_item)] 49 #[doc = stdlinks!(3 pam_set_item)]
50 fn $setter(&mut self, value: Option<&str>) -> Result<()>; 50 fn $setter(&mut self, value: Option<&str>) -> Result<()>;
51 }; 51 };
52 } 52 }
53 53
54 /// Functionality for both PAM applications and PAM modules. 54 /// Functionality for both PAM applications and PAM modules.
73 /// [OpenPAM's `openpam_log`][manbsd] for more details. 73 /// [OpenPAM's `openpam_log`][manbsd] for more details.
74 /// 74 ///
75 /// # Example 75 /// # Example
76 /// 76 ///
77 /// ```no_run 77 /// ```no_run
78 /// # use nonstick::{PamShared}; 78 /// # use nonstick::PamShared;
79 /// # use nonstick::logging::Level; 79 /// use nonstick::logging::Level;
80 /// use nonstick::location;
80 /// # fn _test(pam_hdl: impl PamShared) { 81 /// # fn _test(pam_hdl: impl PamShared) {
81 /// # let delay_ms = 100; 82 /// # let delay_ms = 100;
82 /// # let url = "https://zombo.com"; 83 /// # let url = "https://zombo.com";
83 /// // Usually, instead of calling this manually, just use the macros. 84 /// // Usually, instead of calling this manually, just use the macros.
84 /// nonstick::error!(pam_hdl, "something bad happened!"); 85 /// nonstick::error!(pam_hdl, "something bad happened!");
85 /// nonstick::warn!(pam_hdl, "loading information took {delay_ms} ms"); 86 /// nonstick::warn!(pam_hdl, "loading information took {delay_ms} ms");
86 /// nonstick::info!(pam_hdl, "using network backend"); 87 /// nonstick::info!(pam_hdl, "using network backend");
87 /// nonstick::debug!(pam_hdl, "sending GET request to {url}"); 88 /// nonstick::debug!(pam_hdl, "sending GET request to {url}");
88 /// // But if you really want to, you can call this yourself: 89 /// // But if you really want to, you can call this yourself:
89 /// pam_hdl.log(Level::Warning, "this is unnecessarily verbose"); 90 /// pam_hdl.log(Level::Warning, location!(), "this is unnecessarily verbose");
90 /// # } 91 /// # }
91 /// ``` 92 /// ```
92 #[doc = _man7!(3 pam_syslog)] 93 #[doc = man7!(3 pam_syslog)]
93 #[doc = _manbsd!(3 openpam_log)] 94 #[doc = manbsd!(3 openpam_log)]
94 fn log(&self, level: Level, entry: &str); 95 fn log(&self, level: Level, loc: Location<'_>, entry: &str);
95 96
96 /// Retrieves the name of the user who is authenticating or logging in. 97 /// Retrieves the name of the user who is authenticating or logging in.
97 /// 98 ///
98 /// If the username has previously been obtained, this uses that username; 99 /// If the username has previously been obtained, this uses that username;
99 /// otherwise it prompts the user with the first of these that is present: 100 /// otherwise it prompts the user with the first of these that is present:
101 /// 1. The prompt string passed to this function. 102 /// 1. The prompt string passed to this function.
102 /// 2. The string returned by `get_user_prompt_item`. 103 /// 2. The string returned by `get_user_prompt_item`.
103 /// 3. The default prompt, `login: `. 104 /// 3. The default prompt, `login: `.
104 /// 105 ///
105 /// # References 106 /// # References
106 #[doc = _linklist!(pam_get_user: mwg, _std)] 107 #[doc = linklist!(pam_get_user: mwg, _std)]
107 /// 108 ///
108 /// # Example 109 /// # Example
109 /// 110 ///
110 /// ```no_run 111 /// ```no_run
111 /// # use nonstick::PamShared; 112 /// # use nonstick::PamShared;
117 /// // both user and user_2 would have the same value. 118 /// // both user and user_2 would have the same value.
118 /// let user_2 = handle.username(Some("who ARE you even???"))?; 119 /// let user_2 = handle.username(Some("who ARE you even???"))?;
119 /// # Ok(()) 120 /// # Ok(())
120 /// # } 121 /// # }
121 /// ``` 122 /// ```
122 #[doc = _stdlinks!(3 pam_get_user)] 123 #[doc = stdlinks!(3 pam_get_user)]
123 #[doc = _guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_user")] 124 #[doc = guide!(mwg: "mwg-expected-by-module-item.html#mwg-pam_get_user")]
124 fn username(&mut self, prompt: Option<&str>) -> Result<String>; 125 fn username(&mut self, prompt: Option<&str>) -> Result<String>;
125 126
126 /// The contents of the environment to set, read-only. 127 /// The contents of the environment to set, read-only.
127 fn environ(&self) -> impl EnvironMap; 128 fn environ(&self) -> impl EnvironMap;
128 129
274 /// A PAM module may change the caller's [username](PamShared::username) 275 /// A PAM module may change the caller's [username](PamShared::username)
275 /// as part of the login process, so be sure to check it after making 276 /// as part of the login process, so be sure to check it after making
276 /// any PAM application call. 277 /// any PAM application call.
277 /// 278 ///
278 /// # References 279 /// # References
279 #[doc = _linklist!(pam_authenticate: adg, _std)] 280 #[doc = linklist!(pam_authenticate: adg, _std)]
280 /// 281 ///
281 #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_authenticate")] 282 #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_authenticate")]
282 #[doc = _stdlinks!(3 pam_authenticate)] 283 #[doc = stdlinks!(3 pam_authenticate)]
283 fn authenticate(&mut self, flags: Flags) -> Result<()>; 284 fn authenticate(&mut self, flags: Flags) -> Result<()>;
284 285
285 /// Verifies the validity of the user's account (and other stuff). 286 /// Verifies the validity of the user's account (and other stuff).
286 /// 287 ///
287 /// After [authentication](Self::authenticate), an application should call 288 /// After [authentication](Self::authenticate), an application should call
288 /// this to ensure that the user's account is still valid. This may check 289 /// this to ensure that the user's account is still valid. This may check
289 /// for token expiration or that the user's account is not locked. 290 /// for token expiration or that the user's account is not locked.
290 /// 291 ///
291 /// # References 292 /// # References
292 #[doc = _linklist!(pam_acct_mgmt: adg, _std)] 293 #[doc = linklist!(pam_acct_mgmt: adg, _std)]
293 /// 294 ///
294 #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_acct_mgmt")] 295 #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_acct_mgmt")]
295 #[doc = _stdlinks!(3 pam_acct_mgmt)] 296 #[doc = stdlinks!(3 pam_acct_mgmt)]
296 fn account_management(&mut self, flags: Flags) -> Result<()>; 297 fn account_management(&mut self, flags: Flags) -> Result<()>;
297 298
298 /// Changes the authentication token. 299 /// Changes the authentication token.
299 /// 300 ///
300 /// # References 301 /// # References
301 #[doc = _linklist!(pam_chauthtok: adg, _std)] 302 #[doc = linklist!(pam_chauthtok: adg, _std)]
302 /// 303 ///
303 #[doc = _guide!(adg: "adg-interface-by-app-expected.html#adg-pam_chauthtok")] 304 #[doc = guide!(adg: "adg-interface-by-app-expected.html#adg-pam_chauthtok")]
304 #[doc = _stdlinks!(3 pam_chauthtok)] 305 #[doc = stdlinks!(3 pam_chauthtok)]
305 fn change_authtok(&mut self, flags: Flags) -> Result<()>; 306 fn change_authtok(&mut self, flags: Flags) -> Result<()>;
306 } 307 }
307 308
308 /// Functionality of a PAM handle that can be expected by a PAM module. 309 /// Functionality of a PAM handle that can be expected by a PAM module.
309 /// 310 ///
319 /// PAM modules. This is an extension provided by 320 /// PAM modules. This is an extension provided by
320 /// both Linux-PAM and OpenPAM. 321 /// both Linux-PAM and OpenPAM.
321 /// 322 ///
322 /// # References 323 /// # References
323 /// 324 ///
324 #[doc = _linklist!(pam_get_authtok: man7, manbsd)] 325 #[doc = linklist!(pam_get_authtok: man7, manbsd)]
325 /// 326 ///
326 /// # Example 327 /// # Example
327 /// 328 ///
328 /// ```no_run 329 /// ```no_run
329 /// # use nonstick::handle::PamHandleModule; 330 /// # use nonstick::handle::PamHandleModule;
333 /// // Get the user's password using a custom prompt. 334 /// // Get the user's password using a custom prompt.
334 /// let pass = handle.authtok(Some("Reveal your secrets!"))?; 335 /// let pass = handle.authtok(Some("Reveal your secrets!"))?;
335 /// Ok(()) 336 /// Ok(())
336 /// # } 337 /// # }
337 /// ``` 338 /// ```
338 #[doc = _man7!(3 pam_get_authtok)] 339 #[doc = man7!(3 pam_get_authtok)]
339 #[doc = _manbsd!(3 pam_get_authtok)] 340 #[doc = manbsd!(3 pam_get_authtok)]
340 fn authtok(&mut self, prompt: Option<&str>) -> Result<String>; 341 fn authtok(&mut self, prompt: Option<&str>) -> Result<String>;
341 342
342 trait_item!( 343 trait_item!(
343 /// Gets the user's authentication token (e.g., password). 344 /// Gets the user's authentication token (e.g., password).
344 /// 345 ///