SMTP: Add enable_rfc822_msg_file_analysis

Enabling this option will instantiate a new fa_file instance for every
top-level RFC 822 message in an SMTP transaction.
This commit is contained in:
Arne Welzel 2025-07-12 17:10:59 +02:00
parent fba319857b
commit 6f05fbf2ce
4 changed files with 38 additions and 2 deletions

View file

@ -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<uint64_t>(bdat_len) )
bdat_len = static_cast<int>(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<const u_char*>(line));
Rfc822MsgDataIn(2, reinterpret_cast<const u_char*>("\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<const u_char*>(""));
}
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

View file

@ -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<detail::SMTP_BDAT_Analyzer> 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;

View file

@ -1 +1,2 @@
const SMTP::bdat_max_line_length: count;
const SMTP::enable_rfc822_msg_file_analysis: bool;