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