Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
59 changes: 43 additions & 16 deletions src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::myc::constants::{CapabilityFlags, Command as CommandByte};
use nom;

#[derive(Debug)]
pub struct ClientHandshake<'a> {
Expand All @@ -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)]
Expand Down
28 changes: 20 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{CapabilityFlags, ColumnFlags, ColumnType, StatusFlags};

mod commands;
mod errorcodes;
Expand Down Expand Up @@ -238,15 +238,22 @@ impl<B: MysqlShim<W>, R: Read, W: Write> MysqlIntermediary<B, R, W> {
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);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the handshake change the only difference with the 4.1 protocol?

capabilities.insert(CapabilityFlags::CLIENT_RESERVED);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does setting this do? Aren't generally reserved flags supposed to be 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It came from default capabilities flags. Here you set it.

self.writer.write_all(&[0x00, 0x42])?; // just 4.1 proto

It should be 0x02 if you only meant CLIENT_PROTOCOL_41.

capabilities.insert(CapabilityFlags::CLIENT_SECURE_CONNECTION);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually support secure connections? I did not think so?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't. But those two are the minimal sets of flags that fixed the connection phase issue with the latest Connector/J. But I have to fix the client authentication problem.

capabilities.insert(CapabilityFlags::CLIENT_PLUGIN_AUTH);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What makes it so that we support plugin auths?

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
Expand All @@ -266,17 +273,22 @@ impl<B: MysqlShim<W>, R: Read, W: Write> MysqlIntermediary<B, R, W> {
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
),
)
}
}
Expand Down
1 change: 0 additions & 1 deletion src/packet.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use byteorder::{ByteOrder, LittleEndian};
use nom;
use std::io;
use std::io::prelude::*;

Expand Down