From 1668f5bf2af6e8a2ce41b0d48102c650fd439d02 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Wed, 1 Jul 2020 23:50:25 +0200 Subject: [PATCH 1/5] Support for HandshakeResponse320 --- src/commands.rs | 59 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 1a17897..1f4085b 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,5 +1,4 @@ use crate::myc::constants::{CapabilityFlags, Command as CommandByte}; -use nom; #[derive(Debug)] pub struct ClientHandshake<'a> { @@ -10,21 +9,49 @@ pub struct ClientHandshake<'a> { } pub fn client_handshake(i: &[u8]) -> nom::IResult<&[u8], ClientHandshake<'_>> { - let (i, cap) = nom::number::complete::le_u32(i)?; - let (i, maxps) = nom::number::complete::le_u32(i)?; - let (i, collation) = nom::bytes::complete::take(1u8)(i)?; - let (i, _) = nom::bytes::complete::take(23u8)(i)?; - let (i, username) = nom::bytes::complete::take_until(&b"\0"[..])(i)?; - let (i, _) = nom::bytes::complete::tag(b"\0")(i)?; - Ok(( - i, - ClientHandshake { - capabilities: CapabilityFlags::from_bits_truncate(cap), - maxps, - collation: u16::from(collation[0]), - username, - }, - )) + // mysql handshake protocol documentation + // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_handshake_response.html + + let (i, cap) = nom::number::complete::le_u16(i)?; + + if CapabilityFlags::from_bits_truncate(cap as u32).contains(CapabilityFlags::CLIENT_PROTOCOL_41) + { + // HandshakeResponse41 + let (i, cap2) = nom::number::complete::le_u16(i)?; + let cap = (cap2 as u32) << 16 | cap as u32; + + let (i, maxps) = nom::number::complete::le_u32(i)?; + let (i, collation) = nom::bytes::complete::take(1u8)(i)?; + let (i, _) = nom::bytes::complete::take(23u8)(i)?; + let (i, username) = nom::bytes::complete::take_until(&b"\0"[..])(i)?; + let (i, _) = nom::bytes::complete::tag(b"\0")(i)?; + + Ok(( + i, + ClientHandshake { + capabilities: CapabilityFlags::from_bits_truncate(cap), + maxps, + collation: u16::from(collation[0]), + username, + }, + )) + } else { + // HandshakeResponse320 + let (i, maxps1) = nom::number::complete::le_u16(i)?; + let (i, maxps2) = nom::number::complete::le_u8(i)?; + let maxps = (maxps2 as u32) << 16 | maxps1 as u32; + let (i, username) = nom::bytes::complete::take_until(&b"\0"[..])(i)?; + + Ok(( + i, + ClientHandshake { + capabilities: CapabilityFlags::from_bits_truncate(cap as u32), + maxps, + collation: 0, + username, + }, + )) + } } #[derive(Debug, PartialEq, Eq)] From b9ea2227f363cb2e340c25c3530b6888803a7f36 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Thu, 2 Jul 2020 00:02:50 +0200 Subject: [PATCH 2/5] Fix cargo clippy warnings --- src/packet.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/packet.rs b/src/packet.rs index 85a05e7..7f0c024 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,5 +1,4 @@ use byteorder::{ByteOrder, LittleEndian}; -use nom; use std::io; use std::io::prelude::*; @@ -164,12 +163,10 @@ impl<'a> Packet<'a> { self.1.extend(bytes); } } else { - use std::mem; - assert!(self.1.is_empty()); let mut v = self.0.to_vec(); v.extend(bytes); - mem::replace(&mut self.1, v); + self.1 = v; self.0 = &[]; } } From f0b5cc063c2cb96f38b61228adc65948b1dc1dde Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Mon, 7 Dec 2020 16:09:27 +0100 Subject: [PATCH 3/5] Support latest Connector/J --- src/lib.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7a086db..6aad2ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,7 +101,7 @@ use std::io::prelude::*; use std::iter; use std::net; -pub use crate::myc::constants::{ColumnFlags, ColumnType, StatusFlags}; +pub use crate::myc::constants::{ColumnFlags, CapabilityFlags, ColumnType, StatusFlags}; mod commands; mod errorcodes; @@ -238,15 +238,22 @@ impl, R: Read, W: Write> MysqlIntermediary { fn init(&mut self) -> Result<(), B::Error> { self.writer.write_all(&[10])?; // protocol 10 + let mut capabilities = CapabilityFlags::empty(); + capabilities.insert(CapabilityFlags::CLIENT_PROTOCOL_41); + capabilities.insert(CapabilityFlags::CLIENT_RESERVED); + capabilities.insert(CapabilityFlags::CLIENT_SECURE_CONNECTION); + capabilities.insert(CapabilityFlags::CLIENT_PLUGIN_AUTH); + let capabilities_bytes = capabilities.bits().to_le_bytes(); + // 5.1.10 because that's what Ruby's ActiveRecord requires self.writer.write_all(&b"5.1.10-alpha-msql-proxy\0"[..])?; self.writer.write_all(&[0x08, 0x00, 0x00, 0x00])?; // TODO: connection ID self.writer.write_all(&b";X,po_k}\0"[..])?; // auth seed - self.writer.write_all(&[0x00, 0x42])?; // just 4.1 proto + self.writer.write_all(&capabilities_bytes[..2])?; // just 4.1 proto self.writer.write_all(&[0x21])?; // UTF8_GENERAL_CI self.writer.write_all(&[0x00, 0x00])?; // status flags - self.writer.write_all(&[0x00, 0x00])?; // extended capabilities + self.writer.write_all(&capabilities_bytes[2..])?; // extended capabilities self.writer.write_all(&[0x00])?; // no plugins self.writer.write_all(&[0x00; 6][..])?; // filler self.writer.write_all(&[0x00; 4][..])?; // filler From a195d32e8c3837fcc79591efe3c969aa699de497 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Mon, 7 Dec 2020 18:11:33 +0100 Subject: [PATCH 4/5] cargo upgrade --- Cargo.toml | 12 ++++++------ src/lib.rs | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8bcc89c..961920f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,15 +23,15 @@ codecov = { repository = "jonhoo/msql-srv", branch = "master", service = "github maintenance = { status = "experimental" } [dependencies] -nom = "5" -mysql_common = "0.22" -byteorder = "1" -chrono = "0.4" -time = "=0.2.7" +nom = "6.0.1" +mysql_common = "0.25.0" +byteorder = "1.3.4" +chrono = "0.4.19" +time = "0.2.23" [dev-dependencies] postgres = "0.15" -mysql = "18" +mysql = "20.1.0" mysql_async = "0.20.0" slab = "0.4.2" tokio = "0.1.19" diff --git a/src/lib.rs b/src/lib.rs index 6aad2ab..16f690d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -273,17 +273,17 @@ impl, R: Read, W: Write> MysqlIntermediary { io::ErrorKind::UnexpectedEof, "client sent incomplete handshake", ), - nom::Err::Failure((input, nom_e_kind)) - | nom::Err::Error((input, nom_e_kind)) => { - if let nom::error::ErrorKind::Eof = nom_e_kind { + nom::Err::Failure(nom_error) + | nom::Err::Error(nom_error) => { + if let nom::error::ErrorKind::Eof = nom_error.code { io::Error::new( io::ErrorKind::UnexpectedEof, - format!("client did not complete handshake; got {:?}", input), + format!("client did not complete handshake; got {:?}", nom_error.input), ) } else { io::Error::new( io::ErrorKind::InvalidData, - format!("bad client handshake; got {:?} ({:?})", input, nom_e_kind), + format!("bad client handshake; got {:?} ({:?})", nom_error.input, nom_error.code), ) } } From 4f018e4932f25c847e29a620c5e890099fc20cc7 Mon Sep 17 00:00:00 2001 From: Ranadeep Biswas Date: Mon, 7 Dec 2020 18:11:55 +0100 Subject: [PATCH 5/5] cargo fmt --- src/lib.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 16f690d..56e212c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,7 +101,7 @@ use std::io::prelude::*; use std::iter; use std::net; -pub use crate::myc::constants::{ColumnFlags, CapabilityFlags, ColumnType, StatusFlags}; +pub use crate::myc::constants::{CapabilityFlags, ColumnFlags, ColumnType, StatusFlags}; mod commands; mod errorcodes; @@ -273,17 +273,22 @@ impl, R: Read, W: Write> MysqlIntermediary { io::ErrorKind::UnexpectedEof, "client sent incomplete handshake", ), - nom::Err::Failure(nom_error) - | nom::Err::Error(nom_error) => { + nom::Err::Failure(nom_error) | nom::Err::Error(nom_error) => { if let nom::error::ErrorKind::Eof = nom_error.code { io::Error::new( io::ErrorKind::UnexpectedEof, - format!("client did not complete handshake; got {:?}", nom_error.input), + format!( + "client did not complete handshake; got {:?}", + nom_error.input + ), ) } else { io::Error::new( io::ErrorKind::InvalidData, - format!("bad client handshake; got {:?} ({:?})", nom_error.input, nom_error.code), + format!( + "bad client handshake; got {:?} ({:?})", + nom_error.input, nom_error.code + ), ) } }