mod.rs

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