@@ -3,13 +3,13 @@ use crate::myc::constants::{CapabilityFlags, Command as CommandByte};
33#[ derive( Debug ) ]
44#[ allow( dead_code) ] // The fields here are read, but only in tests. This keeps clippy quiet.
55pub struct ClientHandshake < ' a > {
6- capabilities : CapabilityFlags ,
6+ pub capabilities : CapabilityFlags ,
77 maxps : u32 ,
88 collation : u16 ,
9- username : & ' a [ u8 ] ,
9+ username : Option < & ' a [ u8 ] > ,
1010}
1111
12- pub fn client_handshake ( i : & [ u8 ] ) -> nom:: IResult < & [ u8 ] , ClientHandshake < ' _ > > {
12+ pub fn client_handshake ( i : & [ u8 ] , after_tls : bool ) -> nom:: IResult < & [ u8 ] , ClientHandshake < ' _ > > {
1313 // mysql handshake protocol documentation
1414 // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_handshake_response.html
1515
@@ -21,16 +21,24 @@ pub fn client_handshake(i: &[u8]) -> nom::IResult<&[u8], ClientHandshake<'_>> {
2121 let ( i, cap2) = nom:: number:: complete:: le_u16 ( i) ?;
2222 let cap = ( cap2 as u32 ) << 16 | cap as u32 ;
2323
24+ let capabilities = CapabilityFlags :: from_bits_truncate ( cap) ;
25+
2426 let ( i, maxps) = nom:: number:: complete:: le_u32 ( i) ?;
2527 let ( i, collation) = nom:: bytes:: complete:: take ( 1u8 ) ( i) ?;
2628 let ( i, _) = nom:: bytes:: complete:: take ( 23u8 ) ( i) ?;
27- let ( i, username) = nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?;
28- let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
29+
30+ let ( i, username) = if after_tls || !capabilities. contains ( CapabilityFlags :: CLIENT_SSL ) {
31+ let ( i, user) = nom:: bytes:: complete:: take_until ( & b"\0 " [ ..] ) ( i) ?;
32+ let ( i, _) = nom:: bytes:: complete:: tag ( b"\0 " ) ( i) ?;
33+ ( i, Some ( user) )
34+ } else {
35+ ( i, None )
36+ } ;
2937
3038 Ok ( (
3139 i,
3240 ClientHandshake {
33- capabilities : CapabilityFlags :: from_bits_truncate ( cap ) ,
41+ capabilities,
3442 maxps,
3543 collation : u16:: from ( collation[ 0 ] ) ,
3644 username,
@@ -49,7 +57,7 @@ pub fn client_handshake(i: &[u8]) -> nom::IResult<&[u8], ClientHandshake<'_>> {
4957 capabilities : CapabilityFlags :: from_bits_truncate ( cap as u32 ) ,
5058 maxps,
5159 collation : 0 ,
52- username,
60+ username : Some ( username ) ,
5361 } ,
5462 ) )
5563 }
@@ -137,20 +145,82 @@ pub fn parse(i: &[u8]) -> nom::IResult<&[u8], Command<'_>> {
137145mod tests {
138146 use super :: * ;
139147 use crate :: myc:: constants:: { CapabilityFlags , UTF8_GENERAL_CI } ;
140- use crate :: packet:: PacketReader ;
148+ use crate :: packet:: PacketConn ;
141149 use std:: io:: Cursor ;
142150
143151 #[ test]
144152 fn it_parses_handshake ( ) {
145- let data = & [
153+ let data = [
146154 0x25 , 0x00 , 0x00 , 0x01 , 0x85 , 0xa6 , 0x3f , 0x20 , 0x00 , 0x00 , 0x00 , 0x01 , 0x21 , 0x00 ,
147155 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
148156 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x6a , 0x6f , 0x6e , 0x00 , 0x00 ,
149- ] ;
150- let r = Cursor :: new ( & data[ ..] ) ;
151- let mut pr = PacketReader :: new ( r) ;
157+ ]
158+ . to_vec ( ) ;
159+ let r = Cursor :: new ( data) ;
160+ let mut pr = PacketConn :: new ( r) ;
161+ let ( _, p) = pr. next ( ) . unwrap ( ) . unwrap ( ) ;
162+ let ( _, handshake) = client_handshake ( & p, false ) . unwrap ( ) ;
163+ println ! ( "{:?}" , handshake) ;
164+ assert ! ( handshake
165+ . capabilities
166+ . contains( CapabilityFlags :: CLIENT_LONG_PASSWORD ) ) ;
167+ assert ! ( handshake
168+ . capabilities
169+ . contains( CapabilityFlags :: CLIENT_MULTI_RESULTS ) ) ;
170+ assert ! ( !handshake
171+ . capabilities
172+ . contains( CapabilityFlags :: CLIENT_CONNECT_WITH_DB ) ) ;
173+ assert ! ( !handshake
174+ . capabilities
175+ . contains( CapabilityFlags :: CLIENT_DEPRECATE_EOF ) ) ;
176+ assert_eq ! ( handshake. collation, UTF8_GENERAL_CI ) ;
177+ assert_eq ! ( handshake. username. unwrap( ) , & b"jon" [ ..] ) ;
178+ assert_eq ! ( handshake. maxps, 16777216 ) ;
179+ }
180+
181+ #[ test]
182+ fn it_parses_handshake_with_ssl_enabled ( ) {
183+ let data = [
184+ 0x25 , 0x00 , 0x00 , 0x01 , 0x85 , 0xae , 0x3f , 0x20 , 0x00 , 0x00 , 0x00 , 0x01 , 0x21 , 0x00 ,
185+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
186+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x6a , 0x6f , 0x6e , 0x00 , 0x00 , 0x05 ,
187+ ]
188+ . to_vec ( ) ;
189+ let r = Cursor :: new ( data) ;
190+ let mut pr = PacketConn :: new ( r) ;
191+ let ( _, p) = pr. next ( ) . unwrap ( ) . unwrap ( ) ;
192+ let ( _, handshake) = client_handshake ( & p, false ) . unwrap ( ) ;
193+ println ! ( "{:?}" , handshake) ;
194+ assert ! ( handshake
195+ . capabilities
196+ . contains( CapabilityFlags :: CLIENT_LONG_PASSWORD ) ) ;
197+ assert ! ( handshake
198+ . capabilities
199+ . contains( CapabilityFlags :: CLIENT_MULTI_RESULTS ) ) ;
200+ assert ! ( !handshake
201+ . capabilities
202+ . contains( CapabilityFlags :: CLIENT_CONNECT_WITH_DB ) ) ;
203+ assert ! ( !handshake
204+ . capabilities
205+ . contains( CapabilityFlags :: CLIENT_DEPRECATE_EOF ) ) ;
206+ assert ! ( handshake. capabilities. contains( CapabilityFlags :: CLIENT_SSL ) ) ;
207+ assert_eq ! ( handshake. collation, UTF8_GENERAL_CI ) ;
208+ assert_eq ! ( handshake. username, None ) ;
209+ assert_eq ! ( handshake. maxps, 16777216 ) ;
210+ }
211+
212+ #[ test]
213+ fn it_parses_handshake_after_ssl ( ) {
214+ let data = [
215+ 0x25 , 0x00 , 0x00 , 0x01 , 0x85 , 0xae , 0x3f , 0x20 , 0x00 , 0x00 , 0x00 , 0x01 , 0x21 , 0x00 ,
216+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
217+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x6a , 0x6f , 0x6e , 0x00 , 0x00 , 0x05 ,
218+ ]
219+ . to_vec ( ) ;
220+ let r = Cursor :: new ( data) ;
221+ let mut pr = PacketConn :: new ( r) ;
152222 let ( _, p) = pr. next ( ) . unwrap ( ) . unwrap ( ) ;
153- let ( _, handshake) = client_handshake ( & p) . unwrap ( ) ;
223+ let ( _, handshake) = client_handshake ( & p, true ) . unwrap ( ) ;
154224 println ! ( "{:?}" , handshake) ;
155225 assert ! ( handshake
156226 . capabilities
@@ -164,20 +234,22 @@ mod tests {
164234 assert ! ( !handshake
165235 . capabilities
166236 . contains( CapabilityFlags :: CLIENT_DEPRECATE_EOF ) ) ;
237+ assert ! ( handshake. capabilities. contains( CapabilityFlags :: CLIENT_SSL ) ) ;
167238 assert_eq ! ( handshake. collation, UTF8_GENERAL_CI ) ;
168- assert_eq ! ( handshake. username, & b"jon" [ ..] ) ;
239+ assert_eq ! ( handshake. username. unwrap ( ) , & b"jon" [ ..] ) ;
169240 assert_eq ! ( handshake. maxps, 16777216 ) ;
170241 }
171242
172243 #[ test]
173244 fn it_parses_request ( ) {
174- let data = & [
245+ let data = [
175246 0x21 , 0x00 , 0x00 , 0x00 , 0x03 , 0x73 , 0x65 , 0x6c , 0x65 , 0x63 , 0x74 , 0x20 , 0x40 , 0x40 ,
176247 0x76 , 0x65 , 0x72 , 0x73 , 0x69 , 0x6f , 0x6e , 0x5f , 0x63 , 0x6f , 0x6d , 0x6d , 0x65 , 0x6e ,
177248 0x74 , 0x20 , 0x6c , 0x69 , 0x6d , 0x69 , 0x74 , 0x20 , 0x31 ,
178- ] ;
179- let r = Cursor :: new ( & data[ ..] ) ;
180- let mut pr = PacketReader :: new ( r) ;
249+ ]
250+ . to_vec ( ) ;
251+ let r = Cursor :: new ( data) ;
252+ let mut pr = PacketConn :: new ( r) ;
181253 let ( _, p) = pr. next ( ) . unwrap ( ) . unwrap ( ) ;
182254 let ( _, cmd) = parse ( & p) . unwrap ( ) ;
183255 assert_eq ! (
@@ -191,13 +263,14 @@ mod tests {
191263 // mysql_list_fields (CommandByte::COM_FIELD_LIST / 0x04) has been deprecated in mysql 5.7 and will be removed
192264 // in a future version. The mysql command line tool issues one of these commands after
193265 // switching databases with USE <DB>.
194- let data = & [
266+ let data = [
195267 0x21 , 0x00 , 0x00 , 0x00 , 0x04 , 0x73 , 0x65 , 0x6c , 0x65 , 0x63 , 0x74 , 0x20 , 0x40 , 0x40 ,
196268 0x76 , 0x65 , 0x72 , 0x73 , 0x69 , 0x6f , 0x6e , 0x5f , 0x63 , 0x6f , 0x6d , 0x6d , 0x65 , 0x6e ,
197269 0x74 , 0x20 , 0x6c , 0x69 , 0x6d , 0x69 , 0x74 , 0x20 , 0x31 ,
198- ] ;
199- let r = Cursor :: new ( & data[ ..] ) ;
200- let mut pr = PacketReader :: new ( r) ;
270+ ]
271+ . to_vec ( ) ;
272+ let r = Cursor :: new ( data) ;
273+ let mut pr = PacketConn :: new ( r) ;
201274 let ( _, p) = pr. next ( ) . unwrap ( ) . unwrap ( ) ;
202275 let ( _, cmd) = parse ( & p) . unwrap ( ) ;
203276 assert_eq ! (
0 commit comments