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 } |
