mod.rs

  1use crate::common::Identity;
  2use crate::secret::Secret;
  3use alloc::vec::Vec;
  4use core::error::Error;
  5use core::fmt;
  6
  7#[cfg(feature = "scram")]
  8use crate::common::scram::DeriveError;
  9
 10#[macro_export]
 11macro_rules! impl_validator_using_provider {
 12    ( $validator:ty, $secret:ty ) => {
 13        impl $crate::server::Validator<$secret> for $validator {
 14            fn validate(
 15                &self,
 16                identity: &$crate::common::Identity,
 17                value: &$secret,
 18            ) -> Result<(), $crate::server::ValidatorError> {
 19                if $crate::server::Provider::<$secret>::provide(self, identity).is_ok() {
 20                    Ok(())
 21                } else {
 22                    Err($crate::server::ValidatorError::AuthenticationFailed)
 23                }
 24            }
 25        }
 26    };
 27}
 28
 29pub trait Provider<S: Secret>: Validator<S> {
 30    fn provide(&self, identity: &Identity) -> Result<S, ProviderError>;
 31}
 32
 33pub trait Validator<S: Secret> {
 34    fn validate(&self, identity: &Identity, value: &S) -> Result<(), ValidatorError>;
 35}
 36
 37#[derive(Debug, PartialEq)]
 38pub enum ProviderError {
 39    AuthenticationFailed,
 40    #[cfg(feature = "scram")]
 41    DeriveError(DeriveError),
 42}
 43
 44#[derive(Debug, PartialEq)]
 45pub enum ValidatorError {
 46    AuthenticationFailed,
 47    ProviderError(ProviderError),
 48}
 49
 50#[derive(Debug, PartialEq)]
 51pub enum MechanismError {
 52    NoUsernameSpecified,
 53    ErrorDecodingUsername,
 54    NoPasswordSpecified,
 55    ErrorDecodingPassword,
 56    ValidatorError(ValidatorError),
 57
 58    FailedToDecodeMessage,
 59    ChannelBindingNotSupported,
 60    ChannelBindingIsSupported,
 61    ChannelBindingMechanismIncorrect,
 62    CannotDecodeInitialMessage,
 63    NoUsername,
 64    NoNonce,
 65    FailedToGenerateNonce,
 66    ProviderError(ProviderError),
 67
 68    CannotDecodeResponse,
 69    #[cfg(feature = "scram")]
 70    InvalidKeyLength(hmac::digest::InvalidLength),
 71    #[cfg(any(feature = "scram", feature = "anonymous"))]
 72    RandomFailure(getrandom::Error),
 73    NoProof,
 74    CannotDecodeProof,
 75    AuthenticationFailed,
 76    SaslSessionAlreadyOver,
 77}
 78
 79#[cfg(feature = "scram")]
 80impl From<DeriveError> for ProviderError {
 81    fn from(err: DeriveError) -> ProviderError {
 82        ProviderError::DeriveError(err)
 83    }
 84}
 85
 86impl From<ProviderError> for ValidatorError {
 87    fn from(err: ProviderError) -> ValidatorError {
 88        ValidatorError::ProviderError(err)
 89    }
 90}
 91
 92impl From<ProviderError> for MechanismError {
 93    fn from(err: ProviderError) -> MechanismError {
 94        MechanismError::ProviderError(err)
 95    }
 96}
 97
 98impl From<ValidatorError> for MechanismError {
 99    fn from(err: ValidatorError) -> MechanismError {
100        MechanismError::ValidatorError(err)
101    }
102}
103
104#[cfg(feature = "scram")]
105impl From<hmac::digest::InvalidLength> for MechanismError {
106    fn from(err: hmac::digest::InvalidLength) -> MechanismError {
107        MechanismError::InvalidKeyLength(err)
108    }
109}
110
111#[cfg(any(feature = "scram", feature = "anonymous"))]
112impl From<getrandom::Error> for MechanismError {
113    fn from(err: getrandom::Error) -> MechanismError {
114        MechanismError::RandomFailure(err)
115    }
116}
117
118impl fmt::Display for ProviderError {
119    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
120        write!(fmt, "provider error")
121    }
122}
123
124impl fmt::Display for ValidatorError {
125    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
126        write!(fmt, "validator error")
127    }
128}
129
130impl fmt::Display for MechanismError {
131    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
132        match self {
133            MechanismError::NoUsernameSpecified => write!(fmt, "no username specified"),
134            MechanismError::ErrorDecodingUsername => write!(fmt, "error decoding username"),
135            MechanismError::NoPasswordSpecified => write!(fmt, "no password specified"),
136            MechanismError::ErrorDecodingPassword => write!(fmt, "error decoding password"),
137            MechanismError::ValidatorError(err) => write!(fmt, "validator error: {}", err),
138
139            MechanismError::FailedToDecodeMessage => write!(fmt, "failed to decode message"),
140            MechanismError::ChannelBindingNotSupported => {
141                write!(fmt, "channel binding not supported")
142            }
143            MechanismError::ChannelBindingIsSupported => {
144                write!(fmt, "channel binding is supported")
145            }
146            MechanismError::ChannelBindingMechanismIncorrect => {
147                write!(fmt, "channel binding mechanism is incorrect")
148            }
149            MechanismError::CannotDecodeInitialMessage => {
150                write!(fmt, "can’t decode initial message")
151            }
152            MechanismError::NoUsername => write!(fmt, "no username"),
153            MechanismError::NoNonce => write!(fmt, "no nonce"),
154            MechanismError::FailedToGenerateNonce => write!(fmt, "failed to generate nonce"),
155            MechanismError::ProviderError(err) => write!(fmt, "provider error: {}", err),
156
157            MechanismError::CannotDecodeResponse => write!(fmt, "can’t decode response"),
158            #[cfg(feature = "scram")]
159            MechanismError::InvalidKeyLength(err) => write!(fmt, "invalid key length: {}", err),
160            #[cfg(any(feature = "scram", feature = "anonymous"))]
161            MechanismError::RandomFailure(err) => {
162                write!(fmt, "failure to get random data: {}", err)
163            }
164            MechanismError::NoProof => write!(fmt, "no proof"),
165            MechanismError::CannotDecodeProof => write!(fmt, "can’t decode proof"),
166            MechanismError::AuthenticationFailed => write!(fmt, "authentication failed"),
167            MechanismError::SaslSessionAlreadyOver => write!(fmt, "SASL session already over"),
168        }
169    }
170}
171
172impl Error for ProviderError {}
173
174impl Error for ValidatorError {}
175
176impl Error for MechanismError {
177    fn source(&self) -> Option<&(dyn Error + 'static)> {
178        match self {
179            MechanismError::ValidatorError(err) => Some(err),
180            MechanismError::ProviderError(err) => Some(err),
181            // TODO: figure out how to enable the std feature on this crate.
182            //MechanismError::InvalidKeyLength(err) => Some(err),
183            _ => None,
184        }
185    }
186}
187
188pub trait Mechanism {
189    fn name(&self) -> &str;
190    fn respond(&mut self, payload: &[u8]) -> Result<Response, MechanismError>;
191}
192
193#[derive(Debug, Clone, PartialEq, Eq)]
194pub enum Response {
195    Success(Identity, Vec<u8>),
196    Proceed(Vec<u8>),
197}
198
199pub mod mechanisms;