sqlx_postgres/message/
sasl.rs

1use crate::io::BufMutExt;
2use crate::message::{FrontendMessage, FrontendMessageFormat};
3use sqlx_core::Error;
4use std::num::Saturating;
5
6pub struct SaslInitialResponse<'a> {
7    pub response: &'a str,
8    pub plus: bool,
9}
10
11impl SaslInitialResponse<'_> {
12    #[inline(always)]
13    fn selected_mechanism(&self) -> &'static str {
14        if self.plus {
15            "SCRAM-SHA-256-PLUS"
16        } else {
17            "SCRAM-SHA-256"
18        }
19    }
20}
21
22impl FrontendMessage for SaslInitialResponse<'_> {
23    const FORMAT: FrontendMessageFormat = FrontendMessageFormat::PasswordPolymorphic;
24
25    #[inline(always)]
26    fn body_size_hint(&self) -> Saturating<usize> {
27        let mut size = Saturating(0);
28
29        size += self.selected_mechanism().len();
30        size += 1; // NUL terminator
31
32        size += 4; // response_len
33        size += self.response.len();
34
35        size
36    }
37
38    fn encode_body(&self, buf: &mut Vec<u8>) -> Result<(), Error> {
39        // name of the SASL authentication mechanism that the client selected
40        buf.put_str_nul(self.selected_mechanism());
41
42        let response_len = i32::try_from(self.response.len()).map_err(|_| {
43            err_protocol!(
44                "SASL Initial Response length too long for protcol: {}",
45                self.response.len()
46            )
47        })?;
48
49        buf.extend_from_slice(&response_len.to_be_bytes());
50        buf.extend_from_slice(self.response.as_bytes());
51
52        Ok(())
53    }
54}
55
56pub struct SaslResponse<'a>(pub &'a str);
57
58impl FrontendMessage for SaslResponse<'_> {
59    const FORMAT: FrontendMessageFormat = FrontendMessageFormat::PasswordPolymorphic;
60
61    fn body_size_hint(&self) -> Saturating<usize> {
62        Saturating(self.0.len())
63    }
64
65    fn encode_body(&self, buf: &mut Vec<u8>) -> Result<(), Error> {
66        buf.extend(self.0.as_bytes());
67        Ok(())
68    }
69}