sqlx_etorreborre_postgres/message/
authentication.rs1use std::str::from_utf8;
2
3use memchr::memchr;
4use sqlx_core::bytes::{Buf, Bytes};
5
6use crate::error::Error;
7use crate::io::Decode;
8
9use base64::prelude::{Engine as _, BASE64_STANDARD};
10
11#[derive(Debug)]
26pub enum Authentication {
27 Ok,
29
30 CleartextPassword,
33
34 Md5Password(AuthenticationMd5Password),
38
39 Sasl(AuthenticationSasl),
49
50 SaslContinue(AuthenticationSaslContinue),
54
55 SaslFinal(AuthenticationSaslFinal),
61}
62
63impl Decode<'_> for Authentication {
64 fn decode_with(mut buf: Bytes, _: ()) -> Result<Self, Error> {
65 Ok(match buf.get_u32() {
66 0 => Authentication::Ok,
67
68 3 => Authentication::CleartextPassword,
69
70 5 => {
71 let mut salt = [0; 4];
72 buf.copy_to_slice(&mut salt);
73
74 Authentication::Md5Password(AuthenticationMd5Password { salt })
75 }
76
77 10 => Authentication::Sasl(AuthenticationSasl(buf)),
78 11 => Authentication::SaslContinue(AuthenticationSaslContinue::decode(buf)?),
79 12 => Authentication::SaslFinal(AuthenticationSaslFinal::decode(buf)?),
80
81 ty => {
82 return Err(err_protocol!("unknown authentication method: {}", ty));
83 }
84 })
85 }
86}
87
88#[derive(Debug)]
90pub struct AuthenticationMd5Password {
91 pub salt: [u8; 4],
92}
93
94#[derive(Debug)]
96pub struct AuthenticationSasl(Bytes);
97
98impl AuthenticationSasl {
99 #[inline]
100 pub fn mechanisms(&self) -> SaslMechanisms<'_> {
101 SaslMechanisms(&self.0)
102 }
103}
104
105pub struct SaslMechanisms<'a>(&'a [u8]);
107
108impl<'a> Iterator for SaslMechanisms<'a> {
109 type Item = &'a str;
110
111 fn next(&mut self) -> Option<Self::Item> {
112 if !self.0.is_empty() && self.0[0] == b'\0' {
113 return None;
114 }
115
116 let mechanism = memchr(b'\0', self.0).and_then(|nul| from_utf8(&self.0[..nul]).ok())?;
117
118 self.0 = &self.0[(mechanism.len() + 1)..];
119
120 Some(mechanism)
121 }
122}
123
124#[derive(Debug)]
125pub struct AuthenticationSaslContinue {
126 pub salt: Vec<u8>,
127 pub iterations: u32,
128 pub nonce: String,
129 pub message: String,
130}
131
132impl Decode<'_> for AuthenticationSaslContinue {
133 fn decode_with(buf: Bytes, _: ()) -> Result<Self, Error> {
134 let mut iterations: u32 = 4096;
135 let mut salt = Vec::new();
136 let mut nonce = Bytes::new();
137
138 for item in buf.split(|b| *b == b',') {
142 let key = item[0];
143 let value = &item[2..];
144
145 match key {
146 b'r' => {
147 nonce = buf.slice_ref(value);
148 }
149
150 b'i' => {
151 iterations = atoi::atoi(value).unwrap_or(4096);
152 }
153
154 b's' => {
155 salt = BASE64_STANDARD.decode(value).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 = BASE64_STANDARD.decode(value).map_err(Error::protocol)?;
186 }
187 }
188
189 Ok(Self { verifier })
190 }
191}