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
15-
1618 let ( i, cap) = nom:: number:: complete:: le_u16 ( i) ?;
1719
18- if CapabilityFlags :: from_bits_truncate ( cap as u32 ) . contains ( CapabilityFlags :: CLIENT_PROTOCOL_41 )
19- {
20+ let mut capabilities = CapabilityFlags :: from_bits_truncate ( cap as u32 ) ;
21+ if capabilities . contains ( CapabilityFlags :: CLIENT_PROTOCOL_41 ) {
2022 // HandshakeResponse41
2123 let ( i, cap2) = nom:: number:: complete:: le_u16 ( i) ?;
2224 let cap = ( cap2 as u32 ) << 16 | cap as u32 ;
2325
26+ capabilities = CapabilityFlags :: from_bits_truncate ( cap as u32 ) ;
27+
2428 let ( i, maxps) = nom:: number:: complete:: le_u32 ( i) ?;
2529 let ( i, collation) = nom:: bytes:: complete:: take ( 1u8 ) ( i) ?;
30+
2631 let ( i, _) = nom:: bytes:: complete:: take ( 23u8 ) ( i) ?;
32+
2733 let ( i, username) = nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?;
2834 let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
2935
36+ let ( i, auth_response) =
37+ if capabilities. contains ( CapabilityFlags :: CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA ) {
38+ let ( i, size) = read_length_encoded_number ( i) ?;
39+ nom:: bytes:: complete:: take ( size) ( i) ?
40+ } else if capabilities. contains ( CapabilityFlags :: CLIENT_SECURE_CONNECTION ) {
41+ let ( i, size) = nom:: number:: complete:: le_u8 ( i) ?;
42+ nom:: bytes:: complete:: take ( size) ( i) ?
43+ } else {
44+ nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?
45+ } ;
46+
47+ let ( i, db) =
48+ if capabilities. contains ( CapabilityFlags :: CLIENT_CONNECT_WITH_DB ) && !i. is_empty ( ) {
49+ let ( i, db) = nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?;
50+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
51+ ( i, Some ( db) )
52+ } else {
53+ ( i, None )
54+ } ;
55+
56+ let ( i, auth_plugin) =
57+ if capabilities. contains ( CapabilityFlags :: CLIENT_PLUGIN_AUTH ) && !i. is_empty ( ) {
58+ let ( i, auth_plugin) = nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?;
59+
60+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
61+ ( i, auth_plugin)
62+ } else {
63+ ( i, & b"" [ ..] )
64+ } ;
65+
3066 Ok ( (
3167 i,
3268 ClientHandshake {
3369 capabilities : CapabilityFlags :: from_bits_truncate ( cap) ,
3470 maxps,
3571 collation : u16:: from ( collation[ 0 ] ) ,
36- username,
72+ username : username. to_vec ( ) ,
73+ db : db. map ( |c| c. to_vec ( ) ) ,
74+ auth_response : auth_response. to_vec ( ) ,
75+ auth_plugin : auth_plugin. to_vec ( ) ,
3776 } ,
3877 ) )
3978 } else {
@@ -42,19 +81,51 @@ pub fn client_handshake(i: &[u8]) -> nom::IResult<&[u8], ClientHandshake<'_>> {
4281 let ( i, maxps2) = nom:: number:: complete:: le_u8 ( i) ?;
4382 let maxps = ( maxps2 as u32 ) << 16 | maxps1 as u32 ;
4483 let ( i, username) = nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?;
84+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
85+
86+ let ( i, auth_response, db) =
87+ if capabilities. contains ( CapabilityFlags :: CLIENT_CONNECT_WITH_DB ) {
88+ let ( i, auth_response) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
89+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
90+
91+ let ( i, db) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
92+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
93+
94+ ( i, auth_response, Some ( db) )
95+ } else {
96+ ( & b"" [ ..] , i, None )
97+ } ;
4598
4699 Ok ( (
47100 i,
48101 ClientHandshake {
49102 capabilities : CapabilityFlags :: from_bits_truncate ( cap as u32 ) ,
50103 maxps,
51104 collation : 0 ,
52- username,
105+ username : username. to_vec ( ) ,
106+ db : db. map ( |c| c. to_vec ( ) ) ,
107+ auth_response : auth_response. to_vec ( ) ,
108+ auth_plugin : vec ! [ ] ,
53109 } ,
54110 ) )
55111 }
56112}
57113
114+ fn read_length_encoded_number ( i : & [ u8 ] ) -> nom:: IResult < & [ u8 ] , u64 > {
115+ let ( i, b) = nom:: number:: complete:: le_u8 ( i) ?;
116+ let size: usize = match b {
117+ 0xfb => return Ok ( ( i, 0 ) ) ,
118+ 0xfc => 2 ,
119+ 0xfd => 3 ,
120+ 0xfe => 8 ,
121+ _ => return Ok ( ( i, b as u64 ) ) ,
122+ } ;
123+ let mut bytes = [ 0u8 ; 8 ] ;
124+ let ( i, b) = nom:: bytes:: complete:: take ( size) ( i) ?;
125+ bytes[ ..size] . copy_from_slice ( b) ;
126+ Ok ( ( i, u64:: from_le_bytes ( bytes) ) )
127+ }
128+
58129#[ derive( Debug , PartialEq , Eq ) ]
59130pub enum Command < ' a > {
60131 Query ( & ' a [ u8 ] ) ,
@@ -143,10 +214,15 @@ mod tests {
143214 #[ test]
144215 fn it_parses_handshake ( ) {
145216 let data = & [
146- 0x25 , 0x00 , 0x00 , 0x01 , 0x85 , 0xa6 , 0x3f , 0x20 , 0x00 , 0x00 , 0x00 , 0x01 , 0x21 , 0x00 ,
217+ 0x5b , 0x00 , 0x00 , 0x01 , 0x8d , 0xa6 , 0xff , 0x09 , 0x00 , 0x00 , 0x00 , 0x01 , 0x21 , 0x00 ,
147218 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 ,
219+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x64 , 0x65 , 0x66 , 0x61 , 0x75 , 0x6c ,
220+ 0x74 , 0x00 , 0x14 , 0xf7 , 0xd1 , 0x6c , 0xe9 , 0x0d , 0x2f , 0x34 , 0xb0 , 0x2f , 0xd8 , 0x1d ,
221+ 0x18 , 0xc7 , 0xa4 , 0xe8 , 0x98 , 0x97 , 0x67 , 0xeb , 0xad , 0x64 , 0x65 , 0x66 , 0x61 , 0x75 ,
222+ 0x6c , 0x74 , 0x00 , 0x6d , 0x79 , 0x73 , 0x71 , 0x6c , 0x5f , 0x6e , 0x61 , 0x74 , 0x69 , 0x76 ,
223+ 0x65 , 0x5f , 0x70 , 0x61 , 0x73 , 0x73 , 0x77 , 0x6f , 0x72 , 0x64 , 0x00 ,
149224 ] ;
225+
150226 let r = Cursor :: new ( & data[ ..] ) ;
151227 let mut pr = PacketReader :: new ( r) ;
152228 let ( _, p) = pr. next ( ) . unwrap ( ) . unwrap ( ) ;
@@ -158,14 +234,14 @@ mod tests {
158234 assert ! ( handshake
159235 . capabilities
160236 . contains( CapabilityFlags :: CLIENT_MULTI_RESULTS ) ) ;
161- assert ! ( ! handshake
237+ assert ! ( handshake
162238 . capabilities
163239 . contains( CapabilityFlags :: CLIENT_CONNECT_WITH_DB ) ) ;
164- assert ! ( ! handshake
240+ assert ! ( handshake
165241 . capabilities
166242 . contains( CapabilityFlags :: CLIENT_DEPRECATE_EOF ) ) ;
167243 assert_eq ! ( handshake. collation, UTF8_GENERAL_CI ) ;
168- assert_eq ! ( handshake. username, & b"jon " [ ..] ) ;
244+ assert_eq ! ( handshake. username, & b"default " [ ..] ) ;
169245 assert_eq ! ( handshake. maxps, 16777216 ) ;
170246 }
171247
0 commit comments