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