unftp_auth_pam/
lib.rs

1#![cfg(target_family = "unix")]
2
3//! [`Authenticator`] implementation that authenticates against [`PAM`].
4//!
5//! [`Authenticator`]: libunftp::auth::Authenticator
6//! [`PAM`]: https://en.wikipedia.org/wiki/Pluggable_authentication_module
7
8use async_trait::async_trait;
9use libunftp::auth::*;
10
11/// [`Authenticator`] implementation that authenticates against [`PAM`].
12///
13/// [`Authenticator`]: libunftp::auth::Authenticator
14/// [`PAM`]: https://en.wikipedia.org/wiki/Pluggable_authentication_module
15#[derive(Debug)]
16pub struct PamAuthenticator {
17    service: String,
18}
19
20impl PamAuthenticator {
21    /// Initialize a new [`PamAuthenticator`] for the given PAM service.
22    pub fn new<S: Into<String>>(service: S) -> Self {
23        let service = service.into();
24        PamAuthenticator { service }
25    }
26}
27
28#[async_trait]
29impl Authenticator<DefaultUser> for PamAuthenticator {
30    #[allow(clippy::type_complexity)]
31    #[tracing_attributes::instrument]
32    async fn authenticate(&self, username: &str, creds: &Credentials) -> Result<DefaultUser, AuthenticationError> {
33        let username = username.to_string();
34        let password = creds.password.as_ref().ok_or(AuthenticationError::BadPassword)?;
35        let service = self.service.clone();
36
37        let mut auth = pam_auth::Authenticator::with_password(&service).map_err(|e| AuthenticationError::with_source("pam error", e))?;
38
39        auth.get_handler().set_credentials(&username, password);
40        auth.authenticate().map_err(|e| AuthenticationError::with_source("pam error", e))?;
41        Ok(DefaultUser {})
42    }
43}