comparison src/module.rs @ 193:5074d8e00560

Doc improvements.
author Paul Fisher <paul@pfish.zone>
date Sat, 02 Aug 2025 19:49:21 -0400
parents 46e8ce5cd5d1
children
comparison
equal deleted inserted replaced
192:4c39eaa4a5ae 193:5074d8e00560
1 //! Functions and types useful for implementing a PAM module. 1 //! Functions and types useful for implementing a PAM module.
2 2
3 // Temporarily allowed until we get the actual conversation functions hooked up. 3 // Temporarily allowed until we get the actual conversation functions hooked up.
4 #![allow(dead_code)] 4 #![allow(dead_code)]
5 5
6 use crate::_doc::{guide, linklist, stdlinks};
6 use crate::constants::{ 7 use crate::constants::{
7 AuthnFlags, AuthtokAction, AuthtokFlags, BaseFlags, CredAction, ErrorCode, Result, 8 AuthnFlags, AuthtokAction, AuthtokFlags, BaseFlags, CredAction, ErrorCode, Result,
8 }; 9 };
9 use crate::handle::ModuleClient; 10 use crate::handle::ModuleClient;
10 use std::ffi::CStr; 11 use std::ffi::CStr;
12
13 macro_rules! sm_refs {
14 ($sym:ident: $guide:literal) => {
15 concat!(
16 linklist!($sym: mwg, _std),
17 "\n\n",
18 guide!(mwg: $guide),
19 "\n",
20 stdlinks!(3 $sym),
21 )
22 }
23 }
11 24
12 /// A trait for a PAM module to implement. 25 /// A trait for a PAM module to implement.
13 /// 26 ///
14 /// The default implementations of all these hooks tell PAM to ignore them 27 /// The default implementations of all these hooks tell PAM to ignore them
15 /// (i.e., behave as if this module does not exist) by returning [`ErrorCode::Ignore`]. 28 /// (i.e., behave as if this module does not exist) by returning [`ErrorCode::Ignore`].
16 /// Override any functions you wish to handle in your module. 29 /// Override any functions you wish to handle in your module.
17 /// After implementing this trait, use the [`pam_export!`](crate::pam_export!) macro 30 /// After implementing this trait, use the [`pam_export!`](crate::pam_export!) macro
18 /// to make the functions available to PAM. 31 /// to make the functions available to PAM.
19 /// 32 ///
20 /// For more information, see [`pam(3)`’s root manual page][manpage] 33 /// For more information about how to write a module, see "[What is expected
21 /// and the [PAM Module Writer’s Guide][mwg]. 34 /// of a module?][what]" in the Module Writers' Guide.
22 /// 35 #[doc = ""]
23 /// [manpage]: https://www.man7.org/linux/man-pages/man3/pam.3.html 36 #[doc = guide!(what: "mwg-expected-of-module-overview.html")]
24 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/Linux-PAM_MWG.html
25 #[allow(unused_variables)] 37 #[allow(unused_variables)]
26 pub trait PamModule<T: ModuleClient> { 38 pub trait PamModule<T: ModuleClient> {
27 // Functions for auth modules. 39 // Functions for auth modules.
28 40
29 /// Authenticate the user. 41 /// Authenticate the user.
31 /// This is probably the first thing you want to implement. 43 /// This is probably the first thing you want to implement.
32 /// In most cases, you will want to get the user and password, 44 /// In most cases, you will want to get the user and password,
33 /// using [`PamShared::username`](crate::PamShared::username) 45 /// using [`PamShared::username`](crate::PamShared::username)
34 /// and [`ModuleClient::authtok`], 46 /// and [`ModuleClient::authtok`],
35 /// and verify them against something. 47 /// and verify them against something.
36 ///
37 /// See [the Module Writer's Guide entry for `pam_sm_authenticate`][mwg]
38 /// for more information.
39 /// 48 ///
40 /// # Returns 49 /// # Returns
41 /// 50 ///
42 /// If the password check was successful, return `Ok(())`. 51 /// If the password check was successful, return `Ok(())`.
43 /// 52 ///
51 /// the authentication information, for instance due to a network failure. 60 /// the authentication information, for instance due to a network failure.
52 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service. 61 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service.
53 /// - [`ErrorCode::MaxTries`]: The user has tried authenticating too many times. 62 /// - [`ErrorCode::MaxTries`]: The user has tried authenticating too many times.
54 /// They should not try again. 63 /// They should not try again.
55 /// 64 ///
56 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-auth.html#mwg-pam_sm_authenticate 65 /// # References
66 #[doc = sm_refs!(pam_sm_authenticate: "mwg-expected-of-module-auth.html#mwg-pam_sm_authenticate")]
57 fn authenticate(handle: &mut T, args: Vec<&CStr>, flags: AuthnFlags) -> Result<()> { 67 fn authenticate(handle: &mut T, args: Vec<&CStr>, flags: AuthnFlags) -> Result<()> {
58 Err(ErrorCode::Ignore) 68 Err(ErrorCode::Ignore)
59 } 69 }
60 70
61 /// Perform "account management". 71 /// Perform "account management".
68 /// - Remote host (only let employees log in from the office) 78 /// - Remote host (only let employees log in from the office)
69 /// 79 ///
70 /// You can also check things like, e.g., password expiration, 80 /// You can also check things like, e.g., password expiration,
71 /// and alert that the user change it before continuing, 81 /// and alert that the user change it before continuing,
72 /// or really do whatever you want. 82 /// or really do whatever you want.
73 ///
74 /// See [the Module Writer's Guide entry for `pam_sm_acct_mgmt`][mwg]
75 /// for more information.
76 /// 83 ///
77 /// # Returns 84 /// # Returns
78 /// 85 ///
79 /// If the user should be allowed to log in, return `Ok(())`. 86 /// If the user should be allowed to log in, return `Ok(())`.
80 /// 87 ///
86 /// PAM will ask the user to set a new authentication token, which may be handled by 93 /// PAM will ask the user to set a new authentication token, which may be handled by
87 /// this module in [`Self::change_authtok`]. 94 /// this module in [`Self::change_authtok`].
88 /// - [`ErrorCode::PermissionDenied`]: This one is pretty self-explanatory. 95 /// - [`ErrorCode::PermissionDenied`]: This one is pretty self-explanatory.
89 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service. 96 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service.
90 /// 97 ///
91 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-acct.html#mwg-pam_sm_acct_mgmt 98 /// # References
99 #[doc = sm_refs!(pam_sm_acct_mgmt: "mwg-expected-of-module-acct.html#mwg-pam_sm_acct_mgmt")]
92 fn account_management(handle: &mut T, args: Vec<&CStr>, flags: AuthnFlags) -> Result<()> { 100 fn account_management(handle: &mut T, args: Vec<&CStr>, flags: AuthnFlags) -> Result<()> {
93 Err(ErrorCode::Ignore) 101 Err(ErrorCode::Ignore)
94 } 102 }
95 103
96 /// Set credentials on this session. 104 /// Set credentials on this session.
100 /// that information to the application. It should only be called after 108 /// that information to the application. It should only be called after
101 /// authentication but before a session is established. 109 /// authentication but before a session is established.
102 /// 110 ///
103 /// The module should perform the specified `action`. 111 /// The module should perform the specified `action`.
104 /// 112 ///
105 /// See [the Module Writer's Guide entry for `pam_sm_setcred`][mwg]
106 /// for more information.
107 ///
108 /// # Returns 113 /// # Returns
109 /// 114 ///
110 /// If credentials were set successfully, return `Ok(())`. 115 /// If credentials were set successfully, return `Ok(())`.
111 /// 116 ///
112 /// Sensible error codes to return include: 117 /// Sensible error codes to return include:
114 /// - [`ErrorCode::CredentialsUnavailable`]: The credentials cannot be retrieved. 119 /// - [`ErrorCode::CredentialsUnavailable`]: The credentials cannot be retrieved.
115 /// - [`ErrorCode::CredentialsExpired`]: The credentials have expired. 120 /// - [`ErrorCode::CredentialsExpired`]: The credentials have expired.
116 /// - [`ErrorCode::CredentialsError`]: Some other error occurred when setting credentials. 121 /// - [`ErrorCode::CredentialsError`]: Some other error occurred when setting credentials.
117 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service. 122 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service.
118 /// 123 ///
119 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-auth.html#mwg-pam_sm_setcred 124 /// # References
125 #[doc = sm_refs!(pam_sm_setcred: "mwg-expected-of-module-auth.html#mwg-pam_sm_setcred")]
120 fn set_credentials( 126 fn set_credentials(
121 handle: &mut T, 127 handle: &mut T,
122 args: Vec<&CStr>, 128 args: Vec<&CStr>,
123 action: CredAction, 129 action: CredAction,
124 flags: BaseFlags, 130 flags: BaseFlags,
142 /// The new authentication token will be available in 148 /// The new authentication token will be available in
143 /// [`authtok`](ModuleClient::authtok), 149 /// [`authtok`](ModuleClient::authtok),
144 /// and the previous authentication token will be available in 150 /// and the previous authentication token will be available in
145 /// [`old_authtok`](ModuleClient::old_authtok). 151 /// [`old_authtok`](ModuleClient::old_authtok).
146 /// 152 ///
147 /// See [the Module Writer's Guide entry for `pam_sm_chauthtok`][mwg]
148 /// for more information.
149 ///
150 /// # Returns 153 /// # Returns
151 /// 154 ///
152 /// If the authentication token was changed successfully 155 /// If the authentication token was changed successfully
153 /// (or the check passed), return `Ok(())`. 156 /// (or the check passed), return `Ok(())`.
154 /// 157 ///
162 /// - [`ErrorCode::PermissionDenied`]: What it says on the tin. 165 /// - [`ErrorCode::PermissionDenied`]: What it says on the tin.
163 /// - [`ErrorCode::TryAgain`]: When the preliminary check is unsuccessful, 166 /// - [`ErrorCode::TryAgain`]: When the preliminary check is unsuccessful,
164 /// ask the user for a new authentication token. 167 /// ask the user for a new authentication token.
165 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service. 168 /// - [`ErrorCode::UserUnknown`]: The supplied username is not known by this service.
166 /// 169 ///
167 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-chauthtok.html#mwg-pam_sm_chauthtok 170 /// # References
171 #[doc = sm_refs!(pam_sm_chauthtok: "mwg-expected-of-module-acct.html#mwg-pam_sm_chauthtok")]
168 fn change_authtok( 172 fn change_authtok(
169 handle: &mut T, 173 handle: &mut T,
170 args: Vec<&CStr>, 174 args: Vec<&CStr>,
171 action: AuthtokAction, 175 action: AuthtokAction,
172 flags: AuthtokFlags, 176 flags: AuthtokFlags,
176 180
177 // Functions for session modules. 181 // Functions for session modules.
178 182
179 /// Called when a session is opened. 183 /// Called when a session is opened.
180 /// 184 ///
181 /// See [the Module Writer's Guide entry for `pam_sm_open_session`][mwg]
182 /// for more information.
183 ///
184 /// # Returns 185 /// # Returns
185 /// 186 ///
186 /// If the session was opened successfully, return `Ok(())`. 187 /// If the session was opened successfully, return `Ok(())`.
187 /// 188 ///
188 /// A sensible error code to return is: 189 /// A sensible error code to return is:
189 /// 190 ///
190 /// - [`ErrorCode::SessionError`]: Cannot make an entry for this session. 191 /// - [`ErrorCode::SessionError`]: Cannot make an entry for this session.
191 /// 192 ///
192 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-session.html#mwg-pam_sm_open_session 193 /// # References
194 #[doc = sm_refs!(pam_sm_open_session: "mwg-expected-of-module-session.html#mwg-pam_sm_open_session")]
193 fn open_session(handle: &mut T, args: Vec<&CStr>, flags: BaseFlags) -> Result<()> { 195 fn open_session(handle: &mut T, args: Vec<&CStr>, flags: BaseFlags) -> Result<()> {
194 Err(ErrorCode::Ignore) 196 Err(ErrorCode::Ignore)
195 } 197 }
196 198
197 /// Called when a session is being terminated. 199 /// Called when a session is being terminated.
198 /// 200 ///
199 /// See [the Module Writer's Guide entry for `pam_sm_close_session`][mwg]
200 /// for more information.
201 ///
202 /// # Returns 201 /// # Returns
203 /// 202 ///
204 /// If the session was closed successfully, return `Ok(())`. 203 /// If the session was closed successfully, return `Ok(())`.
205 /// 204 ///
206 /// A sensible error code to return is: 205 /// A sensible error code to return is:
207 /// 206 ///
208 /// - [`ErrorCode::SessionError`]: Cannot remove an entry for this session. 207 /// - [`ErrorCode::SessionError`]: Cannot remove an entry for this session.
209 /// 208 ///
210 /// [mwg]: https://www.chiark.greenend.org.uk/doc/libpam-doc/html/mwg-expected-of-module-session.html#mwg-pam_sm_close_session 209 /// # References
210 #[doc = sm_refs!(pam_sm_close_session: "mwg-expected-of-module-session.html#mwg-pam_sm_close_session")]
211 fn close_session(handle: &mut T, args: Vec<&CStr>, flags: BaseFlags) -> Result<()> { 211 fn close_session(handle: &mut T, args: Vec<&CStr>, flags: BaseFlags) -> Result<()> {
212 Err(ErrorCode::Ignore) 212 Err(ErrorCode::Ignore)
213 } 213 }
214 } 214 }