sqlx_core_guts/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 = base64::decode(value).map_err(Error::protocol)?;
154 }
155
156 _ => {}
157 }
158 }
159
160 Ok(Self {
161 iterations,
162 salt,
163 nonce: from_utf8(&*nonce).map_err(Error::protocol)?.to_owned(),
164 message: from_utf8(&*buf).map_err(Error::protocol)?.to_owned(),
165 })
166 }
167}
168
169#[derive(Debug)]
170pub struct AuthenticationSaslFinal {
171 pub verifier: Vec<u8>,
172}
173
174impl Decode<'_> for AuthenticationSaslFinal {
175 fn decode_with(buf: Bytes, _: ()) -> Result<Self, Error> {
176 let mut verifier = Vec::new();
177
178 for item in buf.split(|b| *b == b',') {
179 let key = item[0];
180 let value = &item[2..];
181
182 if let b'v' = key {
183 verifier = base64::decode(value).map_err(Error::protocol)?;
184 }
185 }
186
187 Ok(Self { verifier })
188 }
189}