rs_sasl/
anonymous.rs

1use crate::sasl;
2
3use anyhow::{anyhow, bail, Result};
4
5/// The ANONYMOUS mechanism name.
6pub const ANONYMOUS: &str = "ANONYMOUS";
7
8/// A client implementation of the ANONYMOUS authentication mechanism, as
9/// described in RFC 4505.
10pub struct AnonymousClient {
11    trace: String,
12}
13
14impl AnonymousClient {
15    pub fn new(trace: String) -> Self {
16        Self {
17            trace,
18        }
19    }
20}
21
22impl sasl::Client for AnonymousClient {
23    fn start(&mut self) -> Result<(String, Vec<u8>)> {
24        Ok((
25            ANONYMOUS.to_string(),
26            self.trace.clone().into_bytes(),
27        ))
28    }
29
30    fn next(&mut self, _challenge: &[u8]) -> Result<Vec<u8>> {
31        Err(anyhow!(sasl::ERR_UNEXPECTED_SERVER_CHALLENGE))
32    }
33}
34
35/// Get trace information from clients logging in anonymously.
36pub type AnonymousAuthenticator = Box<dyn Fn(&str) -> Result<()> + Send>;
37
38/// A server implementation of the ANONYMOUS authentication mechanism, as
39/// described in RFC 4505.
40pub struct AnonymousServer {
41    done: bool,
42    authenticator: AnonymousAuthenticator,
43}
44
45impl AnonymousServer {
46    pub fn new(authenticator: AnonymousAuthenticator) -> Self {
47        Self {
48            done: false,
49            authenticator,
50        }
51    }
52}
53
54impl sasl::Server for AnonymousServer {
55    fn next(&mut self, response: Option<&[u8]>) -> Result<(Vec<u8>, bool)> {
56        if self.done {
57            bail!(sasl::ERR_UNEXPECTED_CLIENT_RESPONSE);
58        }
59
60        // No initial response, send an empty challenge
61        if response.is_none() {
62            return Ok((Vec::new(), false));
63        }
64        let response = response.unwrap();
65
66        self.done = true;
67
68        (self.authenticator)(std::str::from_utf8(response)?)?;
69        Ok((Vec::new(), true))
70    }
71}