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;