11use crate :: myc:: constants:: { CapabilityFlags , Command as CommandByte } ;
22
33#[ derive( Debug ) ]
4- pub struct ClientHandshake < ' a > {
4+ pub struct ClientHandshake {
55 capabilities : CapabilityFlags ,
66 maxps : u32 ,
77 collation : u16 ,
8- username : & ' a [ u8 ] ,
8+ pub ( crate ) db : Option < Vec < u8 > > ,
9+ pub ( crate ) username : Vec < u8 > ,
10+ pub ( crate ) auth_response : Vec < u8 > ,
11+ pub ( crate ) auth_plugin : Vec < u8 > ,
912}
1013
1114#[ allow( clippy:: branches_sharing_code) ]
12- pub fn client_handshake ( i : & [ u8 ] ) -> nom:: IResult < & [ u8 ] , ClientHandshake < ' _ > > {
15+ pub fn client_handshake ( i : & [ u8 ] ) -> nom:: IResult < & [ u8 ] , ClientHandshake > {
1316 // mysql handshake protocol documentation
1417 // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_handshake_response.html
1518
1619 let ( i, cap) = nom:: number:: complete:: le_u16 ( i) ?;
1720
18- if CapabilityFlags :: from_bits_truncate ( cap as u32 ) . contains ( CapabilityFlags :: CLIENT_PROTOCOL_41 )
19- {
21+ let mut capabilities = CapabilityFlags :: from_bits_truncate ( cap as u32 ) ;
22+ if capabilities . contains ( CapabilityFlags :: CLIENT_PROTOCOL_41 ) {
2023 // HandshakeResponse41
2124 let ( i, cap2) = nom:: number:: complete:: le_u16 ( i) ?;
2225 let cap = ( cap2 as u32 ) << 16 | cap as u32 ;
2326
27+ capabilities = CapabilityFlags :: from_bits_truncate ( cap as u32 ) ;
28+
2429 let ( i, maxps) = nom:: number:: complete:: le_u32 ( i) ?;
2530 let ( i, collation) = nom:: bytes:: complete:: take ( 1u8 ) ( i) ?;
31+
2632 let ( i, _) = nom:: bytes:: complete:: take ( 23u8 ) ( i) ?;
33+
2734 let ( i, username) = nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?;
2835 let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
2936
37+ println ! ( "iii {:?}" , i) ;
38+ let ( i, auth_response) =
39+ if capabilities. contains ( CapabilityFlags :: CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA ) {
40+ println ! ( "iii0 {:?}" , i) ;
41+
42+ let ( i, size) = read_length_encoded_number ( i) ?;
43+ nom:: bytes:: complete:: take ( size) ( i) ?
44+ } else if capabilities. contains ( CapabilityFlags :: CLIENT_SECURE_CONNECTION ) {
45+ println ! ( "iii1 {:?}" , i) ;
46+
47+ let ( i, size) = nom:: number:: complete:: le_u8 ( i) ?;
48+ nom:: bytes:: complete:: take ( size) ( i) ?
49+ } else {
50+ println ! ( "iii2 {:?}" , i) ;
51+
52+ nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?
53+ } ;
54+
55+ println ! ( "iii3 {:?}" , i) ;
56+
57+ let ( i, db) =
58+ if capabilities. contains ( CapabilityFlags :: CLIENT_CONNECT_WITH_DB ) && !i. is_empty ( ) {
59+ let ( i, db) = nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?;
60+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
61+ ( i, Some ( db) )
62+ } else {
63+ ( i, None )
64+ } ;
65+
66+ let ( i, auth_plugin) =
67+ if capabilities. contains ( CapabilityFlags :: CLIENT_PLUGIN_AUTH ) && !i. is_empty ( ) {
68+ println ! ( "iii55 {:?}" , i) ;
69+
70+ let ( i, auth_plugin) = nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?;
71+
72+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
73+ ( i, auth_plugin)
74+ } else {
75+ ( i, & b"" [ ..] )
76+ } ;
77+
3078 Ok ( (
3179 i,
3280 ClientHandshake {
3381 capabilities : CapabilityFlags :: from_bits_truncate ( cap) ,
3482 maxps,
3583 collation : u16:: from ( collation[ 0 ] ) ,
36- username,
84+ username : username. to_vec ( ) ,
85+ db : db. map ( |c| c. to_vec ( ) ) ,
86+ auth_response : auth_response. to_vec ( ) ,
87+ auth_plugin : auth_plugin. to_vec ( ) ,
3788 } ,
3889 ) )
3990 } else {
@@ -42,19 +93,51 @@ pub fn client_handshake(i: &[u8]) -> nom::IResult<&[u8], ClientHandshake<'_>> {
4293 let ( i, maxps2) = nom:: number:: complete:: le_u8 ( i) ?;
4394 let maxps = ( maxps2 as u32 ) << 16 | maxps1 as u32 ;
4495 let ( i, username) = nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?;
96+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
97+
98+ let ( i, auth_response, db) =
99+ if capabilities. contains ( CapabilityFlags :: CLIENT_CONNECT_WITH_DB ) {
100+ let ( i, auth_response) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
101+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
102+
103+ let ( i, db) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
104+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
105+
106+ ( i, auth_response, Some ( db) )
107+ } else {
108+ ( & b"" [ ..] , i, None )
109+ } ;
45110
46111 Ok ( (
47112 i,
48113 ClientHandshake {
49114 capabilities : CapabilityFlags :: from_bits_truncate ( cap as u32 ) ,
50115 maxps,
51116 collation : 0 ,
52- username,
117+ username : username. to_vec ( ) ,
118+ db : db. map ( |c| c. to_vec ( ) ) ,
119+ auth_response : auth_response. to_vec ( ) ,
120+ auth_plugin : vec ! [ ] ,
53121 } ,
54122 ) )
55123 }
56124}
57125
126+ fn read_length_encoded_number ( i : & [ u8 ] ) -> nom:: IResult < & [ u8 ] , u64 > {
127+ let ( i, b) = nom:: number:: complete:: le_u8 ( i) ?;
128+ let size: usize = match b {
129+ 0xfb => return Ok ( ( i, 0 ) ) ,
130+ 0xfc => 2 ,
131+ 0xfd => 3 ,
132+ 0xfe => 8 ,
133+ _ => return Ok ( ( i, b as u64 ) ) ,
134+ } ;
135+ let mut bytes = [ 0u8 ; 8 ] ;
136+ let ( i, b) = nom:: bytes:: complete:: take ( size) ( i) ?;
137+ bytes[ ..size] . copy_from_slice ( b) ;
138+ Ok ( ( i, u64:: from_le_bytes ( bytes) ) )
139+ }
140+
58141#[ derive( Debug , PartialEq , Eq ) ]
59142pub enum Command < ' a > {
60143 Query ( & ' a [ u8 ] ) ,
@@ -143,10 +226,14 @@ mod tests {
143226 #[ test]
144227 fn it_parses_handshake ( ) {
145228 let data = & [
146- 0x25 , 0x00 , 0x00 , 0x01 , 0x85 , 0xa6 , 0x3f , 0x20 , 0x00 , 0x00 , 0x00 , 0x01 , 0x21 , 0x00 ,
229+ 0x4f , 0x00 , 0x00 , 0x01 , 0x85 , 0xa6 , 0xff , 0x09 , 0x00 , 0x00 , 0x00 , 0x01 , 0x21 , 0x00 ,
147230 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
148- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x6a , 0x6f , 0x6e , 0x00 , 0x00 ,
231+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x6a , 0x6f , 0x6e , 0x00 , 0x14 , 0xf7 ,
232+ 0xd1 , 0x6c , 0xe9 , 0x0d , 0x2f , 0x34 , 0xb0 , 0x2f , 0xd8 , 0x1d , 0x18 , 0xc7 , 0xa4 , 0xe8 ,
233+ 0x98 , 0x97 , 0x67 , 0xeb , 0xad , 0x6d , 0x79 , 0x73 , 0x71 , 0x6c , 0x5f , 0x6e , 0x61 , 0x74 ,
234+ 0x69 , 0x76 , 0x65 , 0x5f , 0x70 , 0x61 , 0x73 , 0x73 , 0x77 , 0x6f , 0x72 , 0x64 , 0x00 ,
149235 ] ;
236+
150237 let r = Cursor :: new ( & data[ ..] ) ;
151238 let mut pr = PacketReader :: new ( r) ;
152239 let ( _, p) = pr. next ( ) . unwrap ( ) . unwrap ( ) ;
@@ -161,7 +248,7 @@ mod tests {
161248 assert ! ( !handshake
162249 . capabilities
163250 . contains( CapabilityFlags :: CLIENT_CONNECT_WITH_DB ) ) ;
164- assert ! ( ! handshake
251+ assert ! ( handshake
165252 . capabilities
166253 . contains( CapabilityFlags :: CLIENT_DEPRECATE_EOF ) ) ;
167254 assert_eq ! ( handshake. collation, UTF8_GENERAL_CI ) ;
0 commit comments