rbdc_pg/message/
authentication.rs1use base64::engine::general_purpose::STANDARD;
2use base64::Engine;
3use std::str::from_utf8;
4
5use bytes::{Buf, Bytes};
6use memchr::memchr;
7use rbdc::io::Decode;
8use rbdc::{err_protocol, Error};
9
10#[derive(Debug)]
25pub enum Authentication {
26 Ok,
28
29 CleartextPassword,
32
33 Md5Password(AuthenticationMd5Password),
37
38 Sasl(AuthenticationSasl),
48
49 SaslContinue(AuthenticationSaslContinue),
53
54 SaslFinal(AuthenticationSaslFinal),
60}
61
62impl Decode<'_> for Authentication {
63 fn decode_with(mut buf: Bytes, _: ()) -> Result<Self, Error> {
64 Ok(match buf.get_u32() {
65 0 => Authentication::Ok,
66
67 3 => Authentication::CleartextPassword,
68
69 5 => {
70 let mut salt = [0; 4];
71 buf.copy_to_slice(&mut salt);
72
73 Authentication::Md5Password(AuthenticationMd5Password { salt })
74 }
75
76 10 => Authentication::Sasl(AuthenticationSasl(buf)),
77 11 => Authentication::SaslContinue(AuthenticationSaslContinue::decode(buf)?),
78 12 => Authentication::SaslFinal(AuthenticationSaslFinal::decode(buf)?),
79
80 ty => {
81 return Err(err_protocol!("unknown authentication method: {}", ty));
82 }
83 })
84 }
85}
86
87#[derive(Debug)]
89pub struct AuthenticationMd5Password {
90 pub salt: [u8; 4],
91}
92
93#[derive(Debug)]
95pub struct AuthenticationSasl(Bytes);
96
97impl AuthenticationSasl {
98 #[inline]
99 pub fn mechanisms(&self) -> SaslMechanisms<'_> {
100 SaslMechanisms(&self.0)
101 }
102}
103
104pub struct SaslMechanisms<'a>(&'a [u8]);
106
107impl<'a> Iterator for SaslMechanisms<'a> {
108 type Item = &'a str;
109
110 fn next(&mut self) -> Option<Self::Item> {
111 if !self.0.is_empty() && self.0[0] == b'\0' {
112 return None;
113 }
114
115 let mechanism = memchr(b'\0', self.0).and_then(|nul| from_utf8(&self.0[..nul]).ok())?;
116
117 self.0 = &self.0[(mechanism.len() + 1)..];
118
119 Some(mechanism)
120 }
121}
122
123#[derive(Debug)]
124pub struct AuthenticationSaslContinue {
125 pub salt: Vec<u8>,
126 pub iterations: u32,
127 pub nonce: String,
128 pub message: String,
129}
130
131impl Decode<'_> for AuthenticationSaslContinue {
132 fn decode_with(buf: Bytes, _: ()) -> Result<Self, Error> {
133 let mut iterations: u32 = 4096;
134 let mut salt = Vec::new();
135 let mut nonce = Bytes::new();
136
137 for item in buf.split(|b| *b == b',') {
141 let key = item[0];
142 let value = &item[2..];
143
144 match key {
145 b'r' => {
146 nonce = buf.slice_ref(value);
147 }
148
149 b'i' => {
150 iterations = atoi::atoi(value).unwrap_or(4096);
151 }
152
153 b's' => {
154 salt = STANDARD
155 .decode(value)
156 .map_err(|e| Error::from(e.to_string()))?;
157 }
158
159 _ => {}
160 }
161 }
162
163 Ok(Self {
164 iterations,
165 salt,
166 nonce: from_utf8(&*nonce).map_err(Error::protocol)?.to_owned(),
167 message: from_utf8(&*buf).map_err(Error::protocol)?.to_owned(),
168 })
169 }
170}
171
172#[derive(Debug)]
173pub struct AuthenticationSaslFinal {
174 pub verifier: Vec<u8>,
175}
176
177impl Decode<'_> for AuthenticationSaslFinal {
178 fn decode_with(buf: Bytes, _: ()) -> Result<Self, Error> {
179 let mut verifier = Vec::new();
180
181 for item in buf.split(|b| *b == b',') {
182 let key = item[0];
183 let value = &item[2..];
184
185 if let b'v' = key {
186 verifier = STANDARD.decode(value).map_err(Error::protocol)?;
187 }
188 }
189
190 Ok(Self { verifier })
191 }
192}