sasl/client/
mod.rs

1use alloc::vec::Vec;
2use core::fmt;
3
4use crate::common::Credentials;
5
6#[cfg(feature = "scram")]
7use crate::common::scram::DeriveError;
8#[cfg(feature = "scram")]
9use hmac::digest::InvalidLength;
10
11#[derive(Debug, PartialEq)]
12pub enum MechanismError {
13    AnonymousRequiresNoCredentials,
14
15    PlainRequiresUsername,
16    PlainRequiresPlaintextPassword,
17
18    CannotGenerateNonce,
19    ScramRequiresUsername,
20    ScramRequiresPassword,
21
22    CannotDecodeChallenge,
23    NoServerNonce,
24    NoServerSalt,
25    NoServerIterations,
26    #[cfg(feature = "scram")]
27    DeriveError(DeriveError),
28    #[cfg(feature = "scram")]
29    InvalidKeyLength(InvalidLength),
30    InvalidState,
31
32    CannotDecodeSuccessResponse,
33    InvalidSignatureInSuccessResponse,
34    NoSignatureInSuccessResponse,
35}
36
37#[cfg(feature = "scram")]
38impl From<DeriveError> for MechanismError {
39    fn from(err: DeriveError) -> MechanismError {
40        MechanismError::DeriveError(err)
41    }
42}
43
44#[cfg(feature = "scram")]
45impl From<InvalidLength> for MechanismError {
46    fn from(err: InvalidLength) -> MechanismError {
47        MechanismError::InvalidKeyLength(err)
48    }
49}
50
51impl fmt::Display for MechanismError {
52    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
53        write!(
54            fmt,
55            "{}",
56            match self {
57                MechanismError::AnonymousRequiresNoCredentials =>
58                    "ANONYMOUS mechanism requires no credentials",
59
60                MechanismError::PlainRequiresUsername => "PLAIN requires a username",
61                MechanismError::PlainRequiresPlaintextPassword =>
62                    "PLAIN requires a plaintext password",
63
64                MechanismError::CannotGenerateNonce => "can't generate nonce",
65                MechanismError::ScramRequiresUsername => "SCRAM requires a username",
66                MechanismError::ScramRequiresPassword => "SCRAM requires a password",
67
68                MechanismError::CannotDecodeChallenge => "can't decode challenge",
69                MechanismError::NoServerNonce => "no server nonce",
70                MechanismError::NoServerSalt => "no server salt",
71                MechanismError::NoServerIterations => "no server iterations",
72                #[cfg(feature = "scram")]
73                MechanismError::DeriveError(err) => return write!(fmt, "derive error: {}", err),
74                #[cfg(feature = "scram")]
75                MechanismError::InvalidKeyLength(err) =>
76                    return write!(fmt, "invalid key length: {}", err),
77                MechanismError::InvalidState => "not in the right state to receive this response",
78
79                MechanismError::CannotDecodeSuccessResponse => "can't decode success response",
80                MechanismError::InvalidSignatureInSuccessResponse =>
81                    "invalid signature in success response",
82                MechanismError::NoSignatureInSuccessResponse => "no signature in success response",
83            }
84        )
85    }
86}
87
88impl core::error::Error for MechanismError {}
89
90/// A trait which defines SASL mechanisms.
91pub trait Mechanism {
92    /// The name of the mechanism.
93    fn name(&self) -> &str;
94
95    /// Creates this mechanism from `Credentials`.
96    fn from_credentials(credentials: Credentials) -> Result<Self, MechanismError>
97    where
98        Self: Sized;
99
100    /// Provides initial payload of the SASL mechanism.
101    fn initial(&mut self) -> Vec<u8> {
102        Vec::new()
103    }
104
105    /// Creates a response to the SASL challenge.
106    fn response(&mut self, _challenge: &[u8]) -> Result<Vec<u8>, MechanismError> {
107        Ok(Vec::new())
108    }
109
110    /// Verifies the server success response, if there is one.
111    fn success(&mut self, _data: &[u8]) -> Result<(), MechanismError> {
112        Ok(())
113    }
114}
115
116pub mod mechanisms;