mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 08:38:20 +00:00
mysql: Implement and test COM_CHANGE_USER
This reworks the parser such that COM_CHANGE_USER switches the connection back into the CONNECTION_PHASE so that we can remove the EXPECT_AUTH_SWITCH special case in the COMMAND_PHASE. Adds two pcaps produced with Python that actually do COM_CHANGE_USER as it seems not possible from the MySQL CLI.
This commit is contained in:
parent
a4c79e7304
commit
02f4665e9b
12 changed files with 275 additions and 18 deletions
|
@ -154,7 +154,6 @@ enum Expected {
|
|||
EXPECT_EOF_THEN_RESULTSET,
|
||||
EXPECT_RESULTSET,
|
||||
EXPECT_REST_OF_PACKET,
|
||||
EXPECT_AUTH_SWITCH,
|
||||
};
|
||||
|
||||
enum EOFType {
|
||||
|
@ -297,7 +296,7 @@ type MySQL_PDU(is_orig: bool) = record {
|
|||
hdr : Header;
|
||||
msg : case is_orig of {
|
||||
false -> server_msg: Server_Message(hdr.seq_id, hdr.len, state);
|
||||
true -> client_msg: Client_Message(state);
|
||||
true -> client_msg: Client_Message(hdr.len, state);
|
||||
} &requires(state);
|
||||
} &let {
|
||||
state: int = $context.connection.get_state();
|
||||
|
@ -377,7 +376,7 @@ type Server_Connection_Phase_Packets = record {
|
|||
packet: case pkt_type of {
|
||||
0x00 -> data_ok: OK_Packet;
|
||||
0x01 -> auth_more_data: AuthMoreData(false);
|
||||
0xfe -> auth_switch_request: AuthSwitchRequestPayload;
|
||||
0xfe -> auth_switch_request: AuthSwitchRequest;
|
||||
0xff -> data_err: ERR_Packet;
|
||||
};
|
||||
};
|
||||
|
@ -443,6 +442,7 @@ type Handshake_Response_Packet_v10 = record {
|
|||
} &let {
|
||||
deprecate_eof: bool = $context.connection.set_deprecate_eof(cap_flags & CLIENT_DEPRECATE_EOF);
|
||||
client_query_attrs: bool = $context.connection.set_client_query_attrs(cap_flags & CLIENT_QUERY_ATTRIBUTES);
|
||||
proc_cap_flags: bool = $context.connection.set_client_capabilities(cap_flags);
|
||||
};
|
||||
|
||||
type Handshake_Response_Packet_v9 = record {
|
||||
|
@ -459,9 +459,9 @@ type Handshake_Response_Packet_v9 = record {
|
|||
|
||||
# Connection Phase
|
||||
|
||||
type Client_Message(state: int) = case state of {
|
||||
type Client_Message(pkt_len: uint32, state: int) = case state of {
|
||||
CONNECTION_PHASE -> connection_phase: Connection_Phase_Packets;
|
||||
COMMAND_PHASE -> command_phase : Command_Request_Packet;
|
||||
COMMAND_PHASE -> command_phase : Command_Request_Packet(pkt_len);
|
||||
};
|
||||
|
||||
type Connection_Phase_Packets = case $context.connection.get_conn_expectation() of {
|
||||
|
@ -514,17 +514,49 @@ type Query_Attributes = record {
|
|||
|
||||
# Command Request
|
||||
|
||||
type Command_Request_Packet = record {
|
||||
type Command_Request_Packet(pkt_len: uint32) = record {
|
||||
command: uint8;
|
||||
attrs : case ( command == COM_QUERY && $context.connection.get_client_query_attrs() && $context.connection.get_server_query_attrs() ) of {
|
||||
true -> query_attrs: Query_Attributes;
|
||||
false -> none: empty;
|
||||
};
|
||||
|
||||
have_change_user: case is_change_user of {
|
||||
true -> change_user: Change_User_Packet(pkt_len);
|
||||
false -> none_change_user: empty;
|
||||
};
|
||||
|
||||
arg : bytestring &restofdata;
|
||||
} &let {
|
||||
is_change_user = command == COM_CHANGE_USER;
|
||||
update_expectation: bool = $context.connection.set_next_expected_from_command(command);
|
||||
};
|
||||
|
||||
# Command from the client to switch the user mid-session.
|
||||
#
|
||||
# https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_change_user.html
|
||||
type Change_User_Packet(pkt_len: uint32) = record {
|
||||
username : NUL_String;
|
||||
auth_plugin_data_len: uint8;
|
||||
auth_plugin_data: bytestring &length=auth_plugin_data_len;
|
||||
database: NUL_String;
|
||||
charset: uint16;
|
||||
|
||||
auth_plugin_name_case: case have_auth_plugin_name of {
|
||||
true -> auth_plugin_name: NUL_String;
|
||||
false -> no_more_data1: empty;
|
||||
};
|
||||
|
||||
conn_attrs_case: case have_conn_attrs of {
|
||||
true -> conn_attrs: Handshake_Connection_Attributes;
|
||||
false -> no_conn_attrs: empty;
|
||||
};
|
||||
} &let {
|
||||
have_more_data = offsetof(auth_plugin_name_case) < pkt_len;
|
||||
have_auth_plugin_name = have_more_data && ($context.connection.get_client_capabilities() & CLIENT_PLUGIN_AUTH) == CLIENT_PLUGIN_AUTH;
|
||||
have_conn_attrs = have_more_data && ($context.connection.get_client_capabilities() & CLIENT_CONNECT_ATTRS) == CLIENT_CONNECT_ATTRS;
|
||||
} &exportsourcedata;
|
||||
|
||||
# Command Response
|
||||
|
||||
type Command_Response(pkt_len: uint32) = case $context.connection.get_expectation() of {
|
||||
|
@ -534,7 +566,6 @@ type Command_Response(pkt_len: uint32) = case $context.connection.get_expectatio
|
|||
EXPECT_RESULTSET -> resultset : Resultset(pkt_len);
|
||||
EXPECT_REST_OF_PACKET -> rest : bytestring &restofdata;
|
||||
EXPECT_STATUS -> status : Command_Response_Status;
|
||||
EXPECT_AUTH_SWITCH -> auth_switch : AuthSwitchRequest;
|
||||
EXPECT_EOF_THEN_RESULTSET -> eof : EOFIfLegacyThenResultset(pkt_len);
|
||||
default -> unknown : empty;
|
||||
};
|
||||
|
@ -643,11 +674,6 @@ type AuthMoreData(is_orig: bool) = record {
|
|||
};
|
||||
|
||||
type AuthSwitchRequest = record {
|
||||
status: uint8 &enforce(status==254);
|
||||
payload: AuthSwitchRequestPayload;
|
||||
};
|
||||
|
||||
type AuthSwitchRequestPayload = record {
|
||||
name : NUL_String;
|
||||
data : bytestring &restofdata;
|
||||
} &let {
|
||||
|
@ -708,6 +734,7 @@ refine connection MySQL_Conn += {
|
|||
bool deprecate_eof_;
|
||||
bool server_query_attrs_;
|
||||
bool client_query_attrs_;
|
||||
uint32 client_capabilities_;
|
||||
std::string auth_plugin_;
|
||||
int query_attr_idx_;
|
||||
%}
|
||||
|
@ -797,6 +824,17 @@ refine connection MySQL_Conn += {
|
|||
return true;
|
||||
%}
|
||||
|
||||
function set_client_capabilities(c: uint32): bool
|
||||
%{
|
||||
client_capabilities_ = c;
|
||||
return true;
|
||||
%}
|
||||
|
||||
function get_client_capabilities(): uint32
|
||||
%{
|
||||
return client_capabilities_;
|
||||
%}
|
||||
|
||||
function get_expectation(): Expected
|
||||
%{
|
||||
return expected_;
|
||||
|
@ -874,8 +912,7 @@ refine connection MySQL_Conn += {
|
|||
expected_ = EXPECT_STATUS;
|
||||
break;
|
||||
case COM_CHANGE_USER:
|
||||
// XXX: Could we switch into CONNECTION_PHASE instead?
|
||||
expected_ = EXPECT_AUTH_SWITCH;
|
||||
update_state(CONNECTION_PHASE);
|
||||
break;
|
||||
case COM_BINLOG_DUMP:
|
||||
expected_ = NO_EXPECTATION;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue