mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00

We were parsing MySQL using bigendian even though the protocol is specified as with "least significant byte first" [1]. This is most problematic when parsing length encoded strings with 2 byte length fields... Further, I think, the EOF_Packet parsing was borked, either due to testing the CLIENT_DEPRECATE_EOF with the wrong endianness, or due to the workaround in Resultset processing raising mysql_ok(). Introduce a new mysql_eof() that triggers for EOF_Packet's and remove the fake mysql_ok() Resultset invocation to fix. Adapt the mysql script and tests to account for the new event. This is a quite backwards incompatible change on the event level, but due to being quite buggy in general, doubt this matters to many. I think there is more buried, but this fixes the violation of the simple "SHOW ENGINE INNODB STATUS" and the existing tests continue to succeed... [1] https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_dt_integers.html
136 lines
4.6 KiB
JavaScript
136 lines
4.6 KiB
JavaScript
# See the file "COPYING" in the main distribution directory for copyright.
|
|
|
|
refine flow MySQL_Flow += {
|
|
function proc_mysql_initial_handshake_packet(msg: Initial_Handshake_Packet): bool
|
|
%{
|
|
if ( mysql_server_version )
|
|
{
|
|
if ( ${msg.version} == 10 )
|
|
zeek::BifEvent::enqueue_mysql_server_version(connection()->zeek_analyzer(),
|
|
connection()->zeek_analyzer()->Conn(),
|
|
zeek::make_intrusive<zeek::StringVal>(c_str(${msg.handshake10.server_version})));
|
|
if ( ${msg.version} == 9 )
|
|
zeek::BifEvent::enqueue_mysql_server_version(connection()->zeek_analyzer(),
|
|
connection()->zeek_analyzer()->Conn(),
|
|
zeek::make_intrusive<zeek::StringVal>(c_str(${msg.handshake9.server_version})));
|
|
}
|
|
return true;
|
|
%}
|
|
|
|
function proc_mysql_handshake_response_packet(msg: Handshake_Response_Packet): bool
|
|
%{
|
|
if ( ${msg.version} == 9 || ${msg.version == 10} )
|
|
connection()->zeek_analyzer()->AnalyzerConfirmation();
|
|
|
|
if ( mysql_handshake )
|
|
{
|
|
if ( ${msg.version} == 10 )
|
|
zeek::BifEvent::enqueue_mysql_handshake(connection()->zeek_analyzer(),
|
|
connection()->zeek_analyzer()->Conn(),
|
|
zeek::make_intrusive<zeek::StringVal>(c_str(${msg.v10_response.username})));
|
|
if ( ${msg.version} == 9 )
|
|
zeek::BifEvent::enqueue_mysql_handshake(connection()->zeek_analyzer(),
|
|
connection()->zeek_analyzer()->Conn(),
|
|
zeek::make_intrusive<zeek::StringVal>(c_str(${msg.v9_response.username})));
|
|
}
|
|
return true;
|
|
%}
|
|
|
|
function proc_mysql_command_request_packet(msg: Command_Request_Packet): bool
|
|
%{
|
|
if ( mysql_command_request )
|
|
zeek::BifEvent::enqueue_mysql_command_request(connection()->zeek_analyzer(),
|
|
connection()->zeek_analyzer()->Conn(),
|
|
${msg.command},
|
|
to_stringval(${msg.arg}));
|
|
return true;
|
|
%}
|
|
|
|
function proc_err_packet(msg: ERR_Packet): bool
|
|
%{
|
|
if ( mysql_error )
|
|
zeek::BifEvent::enqueue_mysql_error(connection()->zeek_analyzer(),
|
|
connection()->zeek_analyzer()->Conn(),
|
|
${msg.code},
|
|
to_stringval(${msg.msg}));
|
|
return true;
|
|
%}
|
|
|
|
function proc_ok_packet(msg: OK_Packet): bool
|
|
%{
|
|
if ( mysql_ok )
|
|
zeek::BifEvent::enqueue_mysql_ok(connection()->zeek_analyzer(),
|
|
connection()->zeek_analyzer()->Conn(),
|
|
${msg.rows});
|
|
return true;
|
|
%}
|
|
|
|
function proc_eof_packet(msg: EOF_Packet): bool
|
|
%{
|
|
if ( mysql_eof )
|
|
zeek::BifEvent::enqueue_mysql_eof(connection()->zeek_analyzer(),
|
|
connection()->zeek_analyzer()->Conn(),
|
|
${msg.typ} == EOF_INTERMEDIATE);
|
|
return true;
|
|
%}
|
|
|
|
function proc_resultset(msg: Resultset): bool
|
|
%{
|
|
if ( ${msg.is_eof} )
|
|
return true; // Raised through proc_eof_packet()
|
|
|
|
if ( ! mysql_result_row )
|
|
return true;
|
|
|
|
auto vt = zeek::id::string_vec;
|
|
auto vv = zeek::make_intrusive<zeek::VectorVal>(std::move(vt));
|
|
|
|
auto& bstring = ${msg.row.first_field.val};
|
|
auto ptr = reinterpret_cast<const char*>(bstring.data());
|
|
vv->Assign(vv->Size(), zeek::make_intrusive<zeek::StringVal>(bstring.length(), ptr));
|
|
|
|
auto& fields = *${msg.row.fields};
|
|
|
|
for ( auto& f : fields )
|
|
{
|
|
auto& bstring = f->val();
|
|
auto ptr = reinterpret_cast<const char*>(bstring.data());
|
|
vv->Assign(vv->Size(), zeek::make_intrusive<zeek::StringVal>(bstring.length(), ptr));
|
|
}
|
|
|
|
zeek::BifEvent::enqueue_mysql_result_row(connection()->zeek_analyzer(),
|
|
connection()->zeek_analyzer()->Conn(),
|
|
std::move(vv));
|
|
|
|
return true;
|
|
%}
|
|
|
|
};
|
|
|
|
refine typeattr Initial_Handshake_Packet += &let {
|
|
proc = $context.flow.proc_mysql_initial_handshake_packet(this);
|
|
};
|
|
|
|
refine typeattr Handshake_Response_Packet += &let {
|
|
proc = $context.flow.proc_mysql_handshake_response_packet(this);
|
|
};
|
|
|
|
refine typeattr Command_Request_Packet += &let {
|
|
proc = $context.flow.proc_mysql_command_request_packet(this);
|
|
};
|
|
|
|
refine typeattr ERR_Packet += &let {
|
|
proc = $context.flow.proc_err_packet(this);
|
|
};
|
|
|
|
refine typeattr OK_Packet += &let {
|
|
proc = $context.flow.proc_ok_packet(this);
|
|
};
|
|
|
|
refine typeattr EOF_Packet += &let {
|
|
proc = $context.flow.proc_eof_packet(this);
|
|
};
|
|
|
|
refine typeattr Resultset += &let {
|
|
proc = $context.flow.proc_resultset(this);
|
|
};
|