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