mongodb/client/auth/
plain.rs1use crate::{
2 client::{
3 auth::{
4 sasl::{SaslResponse, SaslStart},
5 AuthMechanism,
6 Credential,
7 },
8 options::ServerApi,
9 },
10 cmap::Connection,
11 error::{Error, Result},
12};
13
14pub(crate) async fn authenticate_stream(
15 conn: &mut Connection,
16 credential: &Credential,
17 server_api: Option<&ServerApi>,
18) -> Result<()> {
19 let source = credential.source.as_deref().unwrap_or("$external");
20 let username = credential
21 .username
22 .as_ref()
23 .ok_or_else(|| Error::authentication_error("PLAIN", "no username supplied"))?;
24
25 let password = credential
26 .password
27 .as_ref()
28 .ok_or_else(|| Error::authentication_error("PLAIN", "no password supplied"))?;
29
30 let sasl_start = SaslStart::new(
31 source.into(),
32 AuthMechanism::Plain,
33 payload_bytes(username, password),
34 server_api.cloned(),
35 )
36 .into_command();
37
38 let response = conn.send_message(sasl_start).await?;
39 let sasl_response = SaslResponse::parse("PLAIN", response.auth_response_body("PLAIN")?)?;
40
41 if !sasl_response.done {
42 return Err(Error::invalid_authentication_response("PLAIN"));
43 }
44
45 Ok(())
46}
47
48fn payload_bytes(username: &str, password: &str) -> Vec<u8> {
49 let mut bytes = vec![0];
50 bytes.extend(username.as_bytes());
51
52 bytes.push(0);
53 bytes.extend(password.as_bytes());
54
55 bytes
56}