forked from launchbadge/sqlx
-
Notifications
You must be signed in to change notification settings - Fork 2
/
auth_switch.rs
81 lines (65 loc) 路 2.59 KB
/
auth_switch.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use bytes::{Buf, Bytes};
use crate::error::Error;
use crate::io::Encode;
use crate::io::{BufExt, Decode};
use crate::protocol::auth::AuthPlugin;
use crate::protocol::Capabilities;
// https://dev.mysql.com/doc/dev/mysql-server/8.0.12/page_protocol_connection_phase_packets_protocol_auth_switch_request.html
#[derive(Debug)]
pub struct AuthSwitchRequest {
pub plugin: AuthPlugin,
pub data: Bytes,
}
impl Decode<'_> for AuthSwitchRequest {
fn decode_with(mut buf: Bytes, _: ()) -> Result<Self, Error> {
let header = buf.get_u8();
if header != 0xfe {
return Err(err_protocol!(
"expected 0xfe (AUTH_SWITCH) but found 0x{:x}",
header
));
}
let plugin = buf.get_str_nul()?.parse()?;
if matches!(plugin, AuthPlugin::MySqlClearPassword) && buf.is_empty() {
// Contrary to the MySQL protocol, AWS Aurora with IAM sends
// no data. That is fine because the mysql_clear_password says to
// ignore any data sent.
// See: https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_authentication_methods_clear_text_password.html
return Ok(Self {
plugin,
data: Bytes::new(),
});
}
// See: https://github.com/mysql/mysql-server/blob/ea7d2e2d16ac03afdd9cb72a972a95981107bf51/sql/auth/sha2_password.cc#L942
if buf.len() != 21 {
return Err(err_protocol!(
"expected 21 bytes but found {} bytes",
buf.len()
));
}
let data = buf.get_bytes(20);
buf.advance(1); // NUL-terminator
Ok(Self { plugin, data })
}
}
#[derive(Debug)]
pub struct AuthSwitchResponse(pub Vec<u8>);
impl Encode<'_, Capabilities> for AuthSwitchResponse {
fn encode_with(&self, buf: &mut Vec<u8>, _: Capabilities) {
buf.extend_from_slice(&self.0);
}
}
#[test]
fn test_decode_auth_switch_packet_data() {
const AUTH_SWITCH_NO_DATA: &[u8] = b"\xfecaching_sha2_password\x00abcdefghijabcdefghij\x00";
let p = AuthSwitchRequest::decode_with(AUTH_SWITCH_NO_DATA.into(), ()).unwrap();
assert!(matches!(p.plugin, AuthPlugin::CachingSha2Password));
assert_eq!(p.data, &b"abcdefghijabcdefghij"[..]);
}
#[test]
fn test_decode_auth_switch_packet_no_data() {
const AUTH_SWITCH_NO_DATA: &[u8] = b"\xfemysql_clear_password\x00";
let p = AuthSwitchRequest::decode_with(AUTH_SWITCH_NO_DATA.into(), ()).unwrap();
assert!(matches!(p.plugin, AuthPlugin::MySqlClearPassword));
assert_eq!(p.data, Bytes::new());
}