Mercurial > crates > nonstick
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 /// |