use crate::common::Identity; use crate::secret::Secret; use alloc::vec::Vec; use core::error::Error; use core::fmt; #[cfg(feature = "scram")] use crate::common::scram::DeriveError; #[macro_export] macro_rules! impl_validator_using_provider { ( $validator:ty, $secret:ty ) => { impl $crate::server::Validator<$secret> for $validator { fn validate( &self, identity: &$crate::common::Identity, value: &$secret, ) -> Result<(), $crate::server::ValidatorError> { if $crate::server::Provider::<$secret>::provide(self, identity).is_ok() { Ok(()) } else { Err($crate::server::ValidatorError::AuthenticationFailed) } } } }; } pub trait Provider: Validator { fn provide(&self, identity: &Identity) -> Result; } pub trait Validator { fn validate(&self, identity: &Identity, value: &S) -> Result<(), ValidatorError>; } #[derive(Debug, PartialEq)] pub enum ProviderError { AuthenticationFailed, #[cfg(feature = "scram")] DeriveError(DeriveError), } #[derive(Debug, PartialEq)] pub enum ValidatorError { AuthenticationFailed, ProviderError(ProviderError), } #[derive(Debug, PartialEq)] pub enum MechanismError { NoUsernameSpecified, ErrorDecodingUsername, NoPasswordSpecified, ErrorDecodingPassword, ValidatorError(ValidatorError), FailedToDecodeMessage, ChannelBindingNotSupported, ChannelBindingIsSupported, ChannelBindingMechanismIncorrect, CannotDecodeInitialMessage, NoUsername, NoNonce, FailedToGenerateNonce, ProviderError(ProviderError), CannotDecodeResponse, #[cfg(feature = "scram")] InvalidKeyLength(hmac::digest::InvalidLength), #[cfg(any(feature = "scram", feature = "anonymous"))] RandomFailure(getrandom::Error), NoProof, CannotDecodeProof, AuthenticationFailed, SaslSessionAlreadyOver, } #[cfg(feature = "scram")] impl From for ProviderError { fn from(err: DeriveError) -> ProviderError { ProviderError::DeriveError(err) } } impl From for ValidatorError { fn from(err: ProviderError) -> ValidatorError { ValidatorError::ProviderError(err) } } impl From for MechanismError { fn from(err: ProviderError) -> MechanismError { MechanismError::ProviderError(err) } } impl From for MechanismError { fn from(err: ValidatorError) -> MechanismError { MechanismError::ValidatorError(err) } } #[cfg(feature = "scram")] impl From for MechanismError { fn from(err: hmac::digest::InvalidLength) -> MechanismError { MechanismError::InvalidKeyLength(err) } } #[cfg(any(feature = "scram", feature = "anonymous"))] impl From for MechanismError { fn from(err: getrandom::Error) -> MechanismError { MechanismError::RandomFailure(err) } } impl fmt::Display for ProviderError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "provider error") } } impl fmt::Display for ValidatorError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "validator error") } } impl fmt::Display for MechanismError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self { MechanismError::NoUsernameSpecified => write!(fmt, "no username specified"), MechanismError::ErrorDecodingUsername => write!(fmt, "error decoding username"), MechanismError::NoPasswordSpecified => write!(fmt, "no password specified"), MechanismError::ErrorDecodingPassword => write!(fmt, "error decoding password"), MechanismError::ValidatorError(err) => write!(fmt, "validator error: {}", err), MechanismError::FailedToDecodeMessage => write!(fmt, "failed to decode message"), MechanismError::ChannelBindingNotSupported => { write!(fmt, "channel binding not supported") } MechanismError::ChannelBindingIsSupported => { write!(fmt, "channel binding is supported") } MechanismError::ChannelBindingMechanismIncorrect => { write!(fmt, "channel binding mechanism is incorrect") } MechanismError::CannotDecodeInitialMessage => { write!(fmt, "can’t decode initial message") } MechanismError::NoUsername => write!(fmt, "no username"), MechanismError::NoNonce => write!(fmt, "no nonce"), MechanismError::FailedToGenerateNonce => write!(fmt, "failed to generate nonce"), MechanismError::ProviderError(err) => write!(fmt, "provider error: {}", err), MechanismError::CannotDecodeResponse => write!(fmt, "can’t decode response"), #[cfg(feature = "scram")] MechanismError::InvalidKeyLength(err) => write!(fmt, "invalid key length: {}", err), #[cfg(any(feature = "scram", feature = "anonymous"))] MechanismError::RandomFailure(err) => { write!(fmt, "failure to get random data: {}", err) } MechanismError::NoProof => write!(fmt, "no proof"), MechanismError::CannotDecodeProof => write!(fmt, "can’t decode proof"), MechanismError::AuthenticationFailed => write!(fmt, "authentication failed"), MechanismError::SaslSessionAlreadyOver => write!(fmt, "SASL session already over"), } } } impl Error for ProviderError {} impl Error for ValidatorError {} impl Error for MechanismError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { MechanismError::ValidatorError(err) => Some(err), MechanismError::ProviderError(err) => Some(err), // TODO: figure out how to enable the std feature on this crate. //MechanismError::InvalidKeyLength(err) => Some(err), _ => None, } } } pub trait Mechanism { fn name(&self) -> &str; fn respond(&mut self, payload: &[u8]) -> Result; } #[derive(Debug, Clone, PartialEq, Eq)] pub enum Response { Success(Identity, Vec), Proceed(Vec), } pub mod mechanisms;