use crate::users::Users; use rsasl::error::{SessionError}; use rsasl::mechname::Mechname; use rsasl::property::{AuthId, Password}; use rsasl::session::{Session, SessionData}; use rsasl::validate::{validations, Validation}; use rsasl::{SASL}; use std::sync::Arc; use rsasl::registry::Mechanism; mod fabfire; struct Callback { users: Users, } impl Callback { pub fn new(users: Users) -> Self { Self { users } } } impl rsasl::callback::Callback for Callback { fn validate( &self, session: &mut SessionData, validation: Validation, _mechanism: &Mechname, ) -> Result<(), SessionError> { match validation { validations::SIMPLE => { let authnid = session .get_property::() .ok_or(SessionError::no_property::())?; let user = self .users .get_user(authnid.as_str()) .ok_or(SessionError::AuthenticationFailure)?; let passwd = session .get_property::() .ok_or(SessionError::no_property::())?; if user .check_password(passwd.as_bytes()) .map_err(|_e| SessionError::AuthenticationFailure)? { Ok(()) } else { Err(SessionError::AuthenticationFailure) } } _ => Err(SessionError::no_validate(validation)), } } } struct Inner { rsasl: SASL, } impl Inner { pub fn new(rsasl: SASL) -> Self { Self { rsasl } } } #[derive(Clone)] pub struct AuthenticationHandle { inner: Arc, } impl AuthenticationHandle { pub fn new(userdb: Users) -> Self { let span = tracing::debug_span!("authentication"); let _guard = span.enter(); let mut rsasl = SASL::new(); rsasl.install_callback(Arc::new(Callback::new(userdb))); let mechs: Vec<&'static str> = rsasl.server_mech_list().into_iter() .map(|m| m.mechanism.as_str()) .collect(); tracing::info!(available_mechs=mechs.len(), "initialized sasl backend"); tracing::debug!(?mechs, "available mechs"); Self { inner: Arc::new(Inner::new(rsasl)), } } pub fn start(&self, mechanism: &Mechname) -> anyhow::Result { Ok(self.inner.rsasl.server_start(mechanism)?) } pub fn list_available_mechs(&self) -> impl IntoIterator { self.inner .rsasl .server_mech_list() .into_iter() .map(|m| m.mechanism) } }