diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index 961b2bcf4f..d874dc0f00 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -667,6 +667,14 @@ export { ## is introduced and a weird is raised. Conventionally, MIME messages ## have a maximum line length of 1000 octets when properly encoded. const bdat_max_line_length = 4096 &redef; + + ## Whether to send data of individual top-level RFC822 messages + ## in SMTP transactions to the file analysis framework. + ## + ## If this option is enabled, the first :zeek:see:`file_over_new_connection` + ## event for a new SMTP transaction will be for the top-level RFC822 + ## message. The file's :zeek:field:`mime_type` will be ``message/rfc822``. + const enable_rfc822_msg_file_analysis = F &redef; } module TCP; diff --git a/src/analyzer/protocol/smtp/SMTP.cc b/src/analyzer/protocol/smtp/SMTP.cc index 06a4d10b4f..8b7a925df4 100644 --- a/src/analyzer/protocol/smtp/SMTP.cc +++ b/src/analyzer/protocol/smtp/SMTP.cc @@ -10,6 +10,8 @@ #include "zeek/analyzer/protocol/smtp/BDAT.h" #include "zeek/analyzer/protocol/smtp/consts.bif.h" #include "zeek/analyzer/protocol/smtp/events.bif.h" +#include "zeek/file_analysis/File.h" +#include "zeek/file_analysis/Manager.h" #undef SMTP_CMD_DEF #define SMTP_CMD_DEF(cmd) #cmd, @@ -126,9 +128,13 @@ void SMTP_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { if ( bdat->RemainingChunkSize() < static_cast(bdat_len) ) bdat_len = static_cast(bdat->RemainingChunkSize()); - if ( bdat_len > 0 ) + if ( bdat_len > 0 ) { bdat->NextStream(bdat_len, line, orig); + if ( ! rfc822_msg_fuid.empty() ) + Rfc822MsgDataIn(bdat_len, line); + } + // All BDAT chunks seen? if ( bdat->IsLastChunk() && bdat->RemainingChunkSize() == 0 ) UpdateState(detail::SMTP_CMD_END_OF_DATA, 0, orig); @@ -844,7 +850,14 @@ void SMTP_Analyzer::UnexpectedReply(int cmd_code, int reply_code) { Unexpected(true, "unexpected reply", len, buf); } -void SMTP_Analyzer::ProcessData(int length, const char* line) { mail->Deliver(length, line, true /* trailing_CRLF */); } +void SMTP_Analyzer::ProcessData(int length, const char* line) { + mail->Deliver(length, line, true /* trailing_CRLF */); + + if ( ! rfc822_msg_fuid.empty() ) { + Rfc822MsgDataIn(length, reinterpret_cast(line)); + Rfc822MsgDataIn(2, reinterpret_cast("\r\n")); + } +} bool SMTP_Analyzer::ProcessBdatArg(int arg_len, const char* arg, bool orig) { // For the BDAT command, parse out the chunk-size from the line @@ -880,6 +893,10 @@ bool SMTP_Analyzer::ProcessBdatArg(int arg_len, const char* arg, bool orig) { return true; } +std::string SMTP_Analyzer::Rfc822MsgDataIn(int len, const u_char* data) { + return file_mgr->DataIn(data, len, GetAnalyzerTag(), Conn(), true, rfc822_msg_fuid, "message/rfc822"); +} + void SMTP_Analyzer::BeginData(bool orig, detail::SMTP_State new_state) { state = new_state; skip_data = false; // reset the flag at the beginning of the mail @@ -890,6 +907,9 @@ void SMTP_Analyzer::BeginData(bool orig, detail::SMTP_State new_state) { } mail = new analyzer::mime::MIME_Mail(this, orig); + + if ( zeek::BifConst::SMTP::enable_rfc822_msg_file_analysis ) + rfc822_msg_fuid = Rfc822MsgDataIn(0, reinterpret_cast("")); } void SMTP_Analyzer::EndData() { @@ -911,6 +931,11 @@ void SMTP_Analyzer::EndData() { delete mail; mail = nullptr; } + + if ( ! rfc822_msg_fuid.empty() ) { + file_mgr->EndOfFile(rfc822_msg_fuid); + rfc822_msg_fuid.clear(); + } } } // namespace zeek::analyzer::smtp diff --git a/src/analyzer/protocol/smtp/SMTP.h b/src/analyzer/protocol/smtp/SMTP.h index 6dd57ee455..ec559ff920 100644 --- a/src/analyzer/protocol/smtp/SMTP.h +++ b/src/analyzer/protocol/smtp/SMTP.h @@ -61,6 +61,7 @@ protected: void ProcessExtension(int ext_len, const char* ext); void ProcessData(int length, const char* line); bool ProcessBdatArg(int arg_len, const char* arg, bool orig); + std::string Rfc822MsgDataIn(int len, const u_char* data); void UpdateState(int cmd_code, int reply_code, bool orig); @@ -90,6 +91,7 @@ protected: std::unique_ptr bdat; // if set, BDAT chunk transfer active analyzer::mime::MIME_Mail* mail; + std::string rfc822_msg_fuid; // fuid for mail data file analysis private: analyzer::tcp::ContentLine_Analyzer* cl_orig; diff --git a/src/analyzer/protocol/smtp/consts.bif b/src/analyzer/protocol/smtp/consts.bif index 379887d5d5..d6100d113c 100644 --- a/src/analyzer/protocol/smtp/consts.bif +++ b/src/analyzer/protocol/smtp/consts.bif @@ -1 +1,2 @@ const SMTP::bdat_max_line_length: count; +const SMTP::enable_rfc822_msg_file_analysis: bool;