Mercurial > crates > nonstick
annotate src/handle.rs @ 72:47eb242a4f88
Fill out the PamHandle trait.
This updates the PamHandle trait to have methods for each Item,
and implements them on the LibPamHandle.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Wed, 04 Jun 2025 03:53:36 -0400 |
parents | 58f9d2a4df38 |
children | ac6881304c78 |
rev | line source |
---|---|
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
1 //! The wrapper types and traits for handles into the PAM library. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
2 use crate::constants::{ErrorCode, Result}; |
72 | 3 use crate::conv::Conversation; |
4 use crate::items::ItemType; | |
5 use crate::module::ConversationMux; | |
71
58f9d2a4df38
Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents:
70
diff
changeset
|
6 use crate::pam_ffi; |
72 | 7 use crate::pam_ffi::{memory, LibPamConversation, LibPamHandle}; |
8 use std::ffi::{c_char, c_int}; | |
71
58f9d2a4df38
Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents:
70
diff
changeset
|
9 use std::{mem, ptr}; |
15
27730595f1ea
Adding pam-http module
Anthony Nowell <anthony@algorithmia.com>
parents:
diff
changeset
|
10 |
72 | 11 macro_rules! trait_item { |
12 (get = $getter:ident, item = $item:literal $(, see = $see:path)? $(, $($doc:literal)*)?) => { | |
13 $( | |
14 $(#[doc = $doc])* | |
15 #[doc = ""] | |
16 )? | |
17 #[doc = concat!("Gets the `", $item, "` of the PAM handle.")] | |
18 $( | |
19 #[doc = concat!("See [`", stringify!($see), "`].")] | |
20 )? | |
21 #[doc = ""] | |
22 #[doc = "Returns a reference to the item's value, owned by PAM."] | |
23 #[doc = "The item is assumed to be valid UTF-8 text."] | |
24 #[doc = "If it is not, `ConversationError` is returned."] | |
25 #[doc = ""] | |
26 #[doc = "See the [`pam_get_item`][man] manual page,"] | |
27 #[doc = "[`pam_get_item` in the Module Writers' Guide][mwg], or"] | |
28 #[doc = "[`pam_get_item` in the Application Developers' Guide][adg]."] | |
29 #[doc = ""] | |
30 #[doc = "[man]: https://www.man7.org/linux/man-pages/man3/pam_get_item.3.html"] | |
31 #[doc = "[adg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/adg-interface-by-app-expected.html#adg-pam_get_item"] | |
32 #[doc = "[mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-by-module-item.html#mwg-pam_get_item"] | |
33 fn $getter(&mut self) -> Result<Option<&str>>; | |
34 }; | |
35 (set = $setter:ident, item = $item:literal $(, see = $see:path)? $(, $($doc:literal)*)?) => { | |
36 $( | |
37 $(#[doc = $doc])* | |
38 #[doc = ""] | |
39 )? | |
40 #[doc = concat!("Sets the `", $item, "` from the PAM handle.")] | |
41 $( | |
42 #[doc = concat!("See [`", stringify!($see), "`].")] | |
43 )? | |
44 #[doc = ""] | |
45 #[doc = "Sets the item's value. PAM copies the string's contents."] | |
46 #[doc = "If the string contains a null byte, this will return "] | |
47 #[doc = "a `ConversationError`."] | |
48 #[doc = ""] | |
49 #[doc = "See the [`pam_set_item`][man] manual page,"] | |
50 #[doc = "[`pam_set_item` in the Module Writers' Guide][mwg], or"] | |
51 #[doc = "[`pam_set_item` in the Application Developers' Guide][adg]."] | |
52 #[doc = ""] | |
53 #[doc = "[man]: https://www.man7.org/linux/man-pages/man3/pam_set_item.3.html"] | |
54 #[doc = "[adg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/adg-interface-by-app-expected.html#adg-pam_set_item"] | |
55 #[doc = "[mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-by-module-item.html#mwg-pam_set_item"] | |
56 fn $setter(&mut self, value: Option<&str>) -> Result<()>; | |
57 }; | |
58 } | |
59 | |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
60 /// Features of a PAM handle that are available to applications and modules. |
56
daa2cde64601
Big big refactor. Probably should have been multiple changes.
Paul Fisher <paul@pfish.zone>
parents:
51
diff
changeset
|
61 /// |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
62 /// You probably want [`LibPamHandle`]. This trait is intended to allow creating |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
63 /// mock PAM handle types used for testing PAM modules and applications. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
64 pub trait PamHandle { |
72 | 65 type Conv: Conversation; |
19
d654aa0655e5
Making PamHandle a struct with methods
Anthony Nowell <anthony@algorithmia.com>
parents:
15
diff
changeset
|
66 /// Retrieves the name of the user who is authenticating or logging in. |
d654aa0655e5
Making PamHandle a struct with methods
Anthony Nowell <anthony@algorithmia.com>
parents:
15
diff
changeset
|
67 /// |
72 | 68 /// If the username has previously been obtained, this uses that username; |
69 /// otherwise it prompts the user with the first of these that is present: | |
70 /// | |
71 /// 1. The prompt string passed to this function. | |
72 /// 2. The string returned by `get_user_prompt_item`. | |
73 /// 3. The default prompt, `login: ` | |
74 /// | |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
75 /// See the [`pam_get_user` manual page][man] |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
76 /// or [`pam_get_user` in the Module Writer's Guide][mwg]. |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
77 /// |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
78 /// # Example |
19
d654aa0655e5
Making PamHandle a struct with methods
Anthony Nowell <anthony@algorithmia.com>
parents:
15
diff
changeset
|
79 /// |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
80 /// ```no_run |
72 | 81 /// # use nonstick::PamModuleHandle; |
82 /// # fn _doc(handle: &mut impl PamModuleHandle) -> Result<(), Box<dyn std::error::Error>> { | |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
83 /// // Get the username using the default prompt. |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
84 /// let user = handle.get_user(None)?; |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
85 /// // Get the username using a custom prompt. |
72 | 86 /// // If this were actually called right after the above, |
87 /// // both user and user_2 would have the same value. | |
88 /// let user_2 = handle.get_user(Some("who ARE you even???"))?; | |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
89 /// # Ok(()) |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
90 /// # } |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
91 /// ``` |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
92 /// |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
93 /// [man]: https://www.man7.org/linux/man-pages/man3/pam_get_user.3.html |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
94 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-by-module-item.html#mwg-pam_get_user |
72 | 95 fn get_user(&mut self, prompt: Option<&str>) -> Result<Option<&str>>; |
96 | |
97 trait_item!( | |
98 get = user_item, | |
99 item = "PAM_USER", | |
100 "The identity of the user for whom service is being requested." | |
101 "" | |
102 "While PAM usually sets this automatically during the course of " | |
103 "a [`get_user`](Self::get_user) call, it may be changed by a module " | |
104 "over the course of the PAM transaction." | |
105 "Applications should check it after each step of the PAM process." | |
106 ); | |
107 trait_item!( | |
108 set = set_user_item, | |
109 item = "PAM_USER", | |
110 see = Self::user_item, | |
111 "Sets the identity of the logging-in user." | |
112 "" | |
113 "Usually this will be set during the course of " | |
114 "a [`get_user`](Self::get_user) call, but you may set it manually " | |
115 "or change it during the PAM process." | |
116 ); | |
44
50371046c61a
Add support for pam_get_authtok and minor cleanups.
Paul Fisher <paul@pfish.zone>
parents:
34
diff
changeset
|
117 |
72 | 118 trait_item!( |
119 get = service, | |
120 item = "PAM_SERVICE", | |
121 "The service name, which identifies the PAM stack which is used " | |
122 "to perform authentication." | |
123 ); | |
124 trait_item!( | |
125 set = set_service, | |
126 item = "PAM_SERVICE", | |
127 see = Self::service, | |
128 "The service name, which identifies the PAM stack which is used " | |
129 "to perform authentication. It's probably a bad idea to change this." | |
130 ); | |
131 | |
132 trait_item!( | |
133 get = user_prompt, | |
134 item = "PAM_USER_PROMPT", | |
135 "The string used to prompt for a user's name." | |
136 "By default, this is a localized version of `login: `." | |
137 ); | |
138 trait_item!( | |
139 set = set_user_prompt, | |
140 item = "PAM_USER_PROMPT", | |
141 see = Self::user_prompt, | |
142 "Sets the string used to prompt for a user's name." | |
143 ); | |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
144 |
72 | 145 trait_item!( |
146 get = tty_name, | |
147 item = "PAM_TTY", | |
148 "\"The terminal name prefixed by /dev/ for device files.\"" | |
149 "" | |
150 "This is the terminal the user is logging in on." | |
151 "Very old applications may use this instead of `PAM_XDISPLAY`." | |
152 ); | |
153 trait_item!( | |
154 set = set_tty_name, | |
155 item = "PAM_TTY", | |
156 see = Self::tty_name, | |
157 "Sets the terminal name." | |
158 "" | |
159 "(TODO: See if libpam sets this itself or if the application does.)" | |
160 ); | |
161 | |
162 trait_item!( | |
163 get = remote_user, | |
164 item = "PAM_RUSER", | |
165 "If set, the identity of the remote user logging in." | |
166 "" | |
167 "This is only as trustworthy as the application calling PAM." | |
168 "Also see [`remote_host`](Self::remote_host)." | |
169 ); | |
170 trait_item!( | |
171 set = set_remote_user, | |
172 item = "PAM_RUSER", | |
173 "Sets the identity of the remote user logging in." | |
174 "" | |
175 "This is usually set by the application before making calls " | |
176 "into a PAM session. (TODO: check this!)" | |
177 ); | |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
178 |
72 | 179 trait_item!( |
180 get = remote_host, | |
181 item = "PAM_RHOST", | |
182 "If set, the remote location where the user is coming from." | |
183 "" | |
184 "This is only as trustworthy as the application calling PAM. " | |
185 "This can be combined with [`Self::remote_user`] to identify " | |
186 "the account the user is attempting to log in from, " | |
187 "with `remote_user@remote_host`." | |
188 "" | |
189 "If unset, \"it is unclear where the authentication request " | |
190 "is originating from.\"" | |
191 ); | |
192 trait_item!( | |
193 set = set_remote_host, | |
194 item = "PAM_RHOST", | |
195 see = Self::remote_host, | |
196 "Sets the location where the user is coming from." | |
197 "" | |
198 "This is usually set by the application before making calls " | |
199 "into a PAM session. (TODO: check this!)" | |
200 ); | |
201 | |
202 trait_item!( | |
203 set = set_authtok_item, | |
204 item = "PAM_AUTHTOK", | |
205 see = PamModuleHandle::authtok_item, | |
206 "Sets the user's authentication token (e.g., password)." | |
207 "" | |
208 "This is usually set automatically when " | |
209 "[`get_authtok`](PamModuleHandle::get_authtok) is called, " | |
210 "but can be manually set." | |
211 ); | |
212 | |
213 trait_item!( | |
214 set = set_old_authtok_item, | |
215 item = "PAM_OLDAUTHTOK", | |
216 see = PamModuleHandle::old_authtok_item, | |
217 "Sets the user's \"old authentication token\" when changing passwords." | |
218 "" | |
219 "This is usually set automatically by PAM." | |
220 ); | |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
221 } |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
222 |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
223 /// Functionality of a PAM handle that can be expected by a PAM application. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
224 /// |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
225 /// If you are not writing a PAM client application (e.g., you are writing |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
226 /// a module), you should not use the functionality exposed by this trait. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
227 /// |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
228 /// Like [`PamHandle`], this is intended to allow creating mock implementations |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
229 /// of PAM for testing PAM applications. |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
230 pub trait PamApplicationHandle: PamHandle { |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
231 /// Closes the PAM session on an owned PAM handle. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
232 /// |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
233 /// This should be called with the result of the application's last call |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
234 /// into PAM services. Since this is only applicable to *owned* PAM handles, |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
235 /// a PAM module should never call this (and it will never be handed |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
236 /// an owned `PamHandle` that it can `close`). |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
237 /// |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
238 /// See the [`pam_end` manual page][man] for more information. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
239 /// |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
240 /// ```no_run |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
241 /// # use nonstick::PamApplicationHandle; |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
242 /// # use std::error::Error; |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
243 /// # fn _doc(handle: impl PamApplicationHandle, auth_result: nonstick::Result<()>) -> Result<(), Box<dyn Error>> { |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
244 /// // Earlier: authentication was performed and the result was stored |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
245 /// // into auth_result. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
246 /// handle.close(auth_result)?; |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
247 /// # Ok(()) |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
248 /// # } |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
249 /// ``` |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
250 /// |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
251 /// [man]: https://www.man7.org/linux/man-pages/man3/pam_end.3.html |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
252 fn close(self, status: Result<()>) -> Result<()>; |
72 | 253 |
254 /// Uses a new PAM conversation. | |
255 fn set_conversation(&mut self, conversation: Self::Conv) -> Result<()>; | |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
256 } |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
257 |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
258 /// Functionality of a PAM handle that can be expected by a PAM module. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
259 /// |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
260 /// If you are not writing a PAM module (e.g., you are writing an application), |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
261 /// you should not use any of the functionality exposed by this trait. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
262 /// |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
263 /// Like [`PamHandle`], this is intended to allow creating mock implementations |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
264 /// of PAM for testing PAM modules. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
265 pub trait PamModuleHandle: PamHandle { |
72 | 266 /// Gets a channel for communication with the user. |
267 /// | |
268 /// The Conversation is the conduit which you use for all communication | |
269 /// with the user. | |
270 fn conversation(&mut self) -> Result<ConversationMux<'_, Self::Conv>>; | |
271 | |
272 /// Retrieves the authentication token from the user. | |
273 /// | |
274 /// This should only be used by *authentication* and *password-change* | |
275 /// PAM modules. | |
276 /// | |
277 /// See the [`pam_get_authtok` manual page][man] | |
278 /// or [`pam_get_item` in the Module Writer's Guide][mwg]. | |
279 /// | |
280 /// # Example | |
281 /// | |
282 /// ```no_run | |
283 /// # use nonstick::PamModuleHandle; | |
284 /// # fn _doc(handle: &mut impl PamModuleHandle) -> Result<(), Box<dyn std::error::Error>> { | |
285 /// // Get the user's password using the default prompt. | |
286 /// let pass = handle.get_authtok(None)?; | |
287 /// // Get the user's password using a custom prompt. | |
288 /// let pass = handle.get_authtok(Some("Reveal your secrets!"))?; | |
289 /// Ok(()) | |
290 /// # } | |
291 /// ``` | |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
292 /// |
72 | 293 /// [man]: https://www.man7.org/linux/man-pages/man3/pam_get_authtok.3.html |
294 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-by-module-item.html#mwg-pam_get_item | |
295 fn get_authtok(&mut self, prompt: Option<&str>) -> Result<Option<&str>>; | |
296 | |
297 trait_item!( | |
298 get = authtok_item, | |
299 item = "PAM_AUTHTOK", | |
300 see = Self::get_authtok, | |
301 "Gets the user's authentication token (e.g., password)." | |
302 "" | |
303 "This is normally set automatically by PAM when calling " | |
304 "[`get_authtok`](Self::get_authtok), but can be set explicitly." | |
305 "" | |
306 "Like `get_authtok`, this should only ever be called " | |
307 "by *authentication* and *password-change* PAM modules." | |
308 ); | |
309 | |
310 trait_item!( | |
311 get = old_authtok_item, | |
312 item = "PAM_OLDAUTHTOK", | |
313 see = PamHandle::set_old_authtok_item, | |
314 "Gets the user's old authentication token when changing passwords." | |
315 "" | |
316 "This should only ever be called by *password-change* PAM modules." | |
317 ); | |
318 | |
319 /* | |
320 TODO: Re-enable this at some point. | |
321 /// Gets some pointer, identified by `key`, that has been set previously | |
322 /// using [`set_data`](Self::set_data). | |
323 /// | |
324 /// The data, if present, is still owned by the current PAM session. | |
325 /// | |
326 /// See the [`pam_get_data` manual page][man] | |
327 /// or [`pam_get_data` in the Module Writer's Guide][mwg]. | |
328 /// | |
329 /// # Safety | |
330 /// | |
331 /// The data stored under the provided key must be of type `T`, | |
332 /// otherwise you'll get back a completely invalid `&T` | |
333 /// and further behavior is undefined. | |
334 /// | |
335 /// [man]: https://www.man7.org/linux/man-pages/man3/pam_get_data.3.html | |
336 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-by-module-item.html#mwg-pam_get_data | |
337 unsafe fn get_data<T>(&mut self, key: &str) -> Result<Option<&T>>; | |
338 | |
339 /// Stores a pointer that can be retrieved later with [`get_data`](Self::get_data). | |
340 /// | |
341 /// This data is accessible to this module and other PAM modules | |
342 /// (using the provided `key`), but is *not* accessible to the application. | |
343 /// The PAM session takes ownership of the data, and it will be dropped | |
344 /// when the session ends. | |
345 /// | |
346 /// See the [`pam_set_data` manual page][man] | |
347 /// or [`pam_set_data` in the Module Writer's Guide][mwg]. | |
348 /// | |
349 /// [man]: https://www.man7.org/linux/man-pages/man3/pam_set_data.3.html | |
350 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-by-module-item.html#mwg-pam_set_data | |
351 fn set_data<T>(&mut self, key: &str, data: Box<T>) -> Result<()>; | |
352 */ | |
353 } | |
354 | |
355 | |
356 impl LibPamHandle { | |
357 /// Gets a C string item. | |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
358 /// |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
359 /// # Safety |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
360 /// |
72 | 361 /// You better be requesting an item which is a C string. |
362 unsafe fn get_cstr_item(&mut self, item_type: ItemType) -> Result<Option<&str>> { | |
363 let mut output = ptr::null(); | |
364 let ret = unsafe { pam_ffi::pam_get_item(self, item_type as c_int, &mut output) }; | |
365 ErrorCode::result_from(ret)?; | |
366 memory::wrap_string(output.cast()) | |
367 } | |
368 | |
369 /// Sets a C string item. | |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
370 /// |
72 | 371 /// # Safety |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
372 /// |
72 | 373 /// You better be setting an item which is a C string. |
374 unsafe fn set_cstr_item(&mut self, item_type: ItemType, data: Option<&str>) -> Result<()> { | |
375 let data_str = memory::option_cstr(data)?; | |
376 let ret = unsafe { | |
377 pam_ffi::pam_set_item( | |
378 self, | |
379 item_type as c_int, | |
380 memory::prompt_ptr(data_str.as_ref()).cast(), | |
381 ) | |
382 }; | |
383 ErrorCode::result_from(ret) | |
384 } | |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
385 } |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
386 |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
387 impl Drop for LibPamHandle { |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
388 /// Ends the PAM session with a zero error code. |
69
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
389 /// You probably want to call [`close`](Self::close) instead of |
8f3ae0c7ab92
Rework conversation data types and make safe wrappers.
Paul Fisher <paul@pfish.zone>
parents:
66
diff
changeset
|
390 /// letting this drop by itself. |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
391 fn drop(&mut self) { |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
392 unsafe { |
72 | 393 pam_ffi::pam_end(self, 0); |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
394 } |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
395 } |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
396 } |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
397 |
72 | 398 macro_rules! cstr_item { |
399 (get = $getter:ident, item = $item_type:path) => { | |
400 fn $getter(&mut self) -> Result<Option<&str>> { | |
401 unsafe { self.get_cstr_item($item_type) } | |
402 } | |
403 }; | |
404 (set = $setter:ident, item = $item_type:path) => { | |
405 fn $setter(&mut self, value: Option<&str>) -> Result<()> { | |
406 unsafe { self.set_cstr_item($item_type, value) } | |
407 } | |
408 }; | |
409 } | |
410 | |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
411 impl PamHandle for LibPamHandle { |
72 | 412 type Conv = LibPamConversation; |
413 fn get_user(&mut self, prompt: Option<&str>) -> Result<Option<&str>> { | |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
414 let prompt = memory::option_cstr(prompt)?; |
72 | 415 let mut output: *const c_char = ptr::null(); |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
416 let ret = unsafe { |
72 | 417 pam_ffi::pam_get_user(self, &mut output, memory::prompt_ptr(prompt.as_ref())) |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
418 }; |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
419 ErrorCode::result_from(ret)?; |
72 | 420 unsafe { memory::wrap_string(output) } |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
421 } |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
422 |
72 | 423 cstr_item!(get = user_item, item = ItemType::User); |
424 cstr_item!(set = set_user_item, item = ItemType::User); | |
425 cstr_item!(get = service, item = ItemType::Service); | |
426 cstr_item!(set = set_service, item = ItemType::Service); | |
427 cstr_item!(get = user_prompt, item = ItemType::UserPrompt); | |
428 cstr_item!(set = set_user_prompt, item = ItemType::UserPrompt); | |
429 cstr_item!(get = tty_name, item = ItemType::Tty); | |
430 cstr_item!(set = set_tty_name, item = ItemType::Tty); | |
431 cstr_item!(get = remote_user, item = ItemType::RemoteUser); | |
432 cstr_item!(set = set_remote_user, item = ItemType::RemoteUser); | |
433 cstr_item!(get = remote_host, item = ItemType::RemoteHost); | |
434 cstr_item!(set = set_remote_host, item = ItemType::RemoteHost); | |
435 cstr_item!(set = set_authtok_item, item = ItemType::AuthTok); | |
436 cstr_item!(set = set_old_authtok_item, item = ItemType::OldAuthTok); | |
437 } | |
438 | |
439 impl PamApplicationHandle for LibPamHandle { | |
440 fn close(mut self, status: Result<()>) -> Result<()> { | |
441 let result = unsafe { pam_ffi::pam_end(&mut self, ErrorCode::result_to_c(status)) }; | |
442 // Since we've already `pam_end`ed this session, we don't want it to be | |
443 // double-freed on drop. | |
444 mem::forget(self); | |
445 ErrorCode::result_from(result) | |
446 } | |
447 | |
448 fn set_conversation(&mut self, conversation: Self::Conv) -> Result<()> { | |
449 todo!() | |
450 } | |
451 } | |
452 | |
453 impl PamModuleHandle for LibPamHandle { | |
454 fn conversation(&mut self) -> Result<ConversationMux<'_, Self::Conv>> { | |
455 todo!() | |
456 } | |
457 | |
458 fn get_authtok(&mut self, prompt: Option<&str>) -> Result<Option<&str>> { | |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
459 let prompt = memory::option_cstr(prompt)?; |
71
58f9d2a4df38
Reorganize everything again???
Paul Fisher <paul@pfish.zone>
parents:
70
diff
changeset
|
460 let mut output: *const c_char = ptr::null_mut(); |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
461 let res = unsafe { |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
462 pam_ffi::pam_get_authtok( |
72 | 463 self, |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
464 ItemType::AuthTok.into(), |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
465 &mut output, |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
466 memory::prompt_ptr(prompt.as_ref()), |
64
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
467 ) |
bbe84835d6db
More organization; add lots of docs.
Paul Fisher <paul@pfish.zone>
parents:
60
diff
changeset
|
468 }; |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
469 ErrorCode::result_from(res)?; |
72 | 470 unsafe { memory::wrap_string(output) } |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
471 } |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
472 |
72 | 473 cstr_item!(get = authtok_item, item = ItemType::AuthTok); |
474 cstr_item!(get = old_authtok_item, item = ItemType::OldAuthTok); | |
44
50371046c61a
Add support for pam_get_authtok and minor cleanups.
Paul Fisher <paul@pfish.zone>
parents:
34
diff
changeset
|
475 } |
66
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
476 |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
477 /// Function called at the end of a PAM session that is called to clean up |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
478 /// a value previously provided to PAM in a `pam_set_data` call. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
479 /// |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
480 /// You should never call this yourself. |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
481 extern "C" fn set_data_cleanup<T>(_: *const libc::c_void, c_data: *mut libc::c_void, _: c_int) { |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
482 unsafe { |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
483 let _data: Box<T> = Box::from_raw(c_data.cast()); |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
484 } |
a674799a5cd3
Make `PamHandle` and `PamModuleHandle` traits.
Paul Fisher <paul@pfish.zone>
parents:
64
diff
changeset
|
485 } |