mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
SMTP: Add enable_mail_data_file_analysis
Enabling this option will instantiate a new fa_file instance for every mail data (message content) transferred over an SMTP connection. A new event smtp_mail_data_file() can be used to intercept and identify the creation of such files.
This commit is contained in:
parent
9e2accf016
commit
72be23f379
5 changed files with 50 additions and 2 deletions
|
@ -628,6 +628,12 @@ export {
|
||||||
## is introduced and a weird is raised. Conventionally, MIME messages
|
## is introduced and a weird is raised. Conventionally, MIME messages
|
||||||
## have a maximum line length of 1000 octets when properly encoded.
|
## have a maximum line length of 1000 octets when properly encoded.
|
||||||
const bdat_max_line_length = 4096 &redef;
|
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.
|
||||||
|
##
|
||||||
|
## :zeek:see:`smtp_mail_data_file`.
|
||||||
|
const enable_mail_data_file_analysis = F &redef;
|
||||||
}
|
}
|
||||||
|
|
||||||
module TCP;
|
module TCP;
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "zeek/analyzer/protocol/smtp/BDAT.h"
|
#include "zeek/analyzer/protocol/smtp/BDAT.h"
|
||||||
#include "zeek/analyzer/protocol/smtp/consts.bif.h"
|
#include "zeek/analyzer/protocol/smtp/consts.bif.h"
|
||||||
#include "zeek/analyzer/protocol/smtp/events.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
|
#undef SMTP_CMD_DEF
|
||||||
#define SMTP_CMD_DEF(cmd) #cmd,
|
#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) )
|
if ( bdat->RemainingChunkSize() < static_cast<uint64_t>(bdat_len) )
|
||||||
bdat_len = static_cast<int>(bdat->RemainingChunkSize());
|
bdat_len = static_cast<int>(bdat->RemainingChunkSize());
|
||||||
|
|
||||||
if ( bdat_len > 0 )
|
if ( bdat_len > 0 ) {
|
||||||
bdat->NextStream(bdat_len, line, orig);
|
bdat->NextStream(bdat_len, line, orig);
|
||||||
|
|
||||||
|
if ( ! mail_fuid.empty() )
|
||||||
|
MailDataFileAnalysis(line, bdat_len);
|
||||||
|
}
|
||||||
|
|
||||||
// All BDAT chunks seen?
|
// All BDAT chunks seen?
|
||||||
if ( bdat->IsLastChunk() && bdat->RemainingChunkSize() == 0 )
|
if ( bdat->IsLastChunk() && bdat->RemainingChunkSize() == 0 )
|
||||||
UpdateState(detail::SMTP_CMD_END_OF_DATA, 0, orig);
|
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);
|
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 ( ! mail_fuid.empty() ) {
|
||||||
|
MailDataFileAnalysis(reinterpret_cast<const u_char*>(line), length);
|
||||||
|
MailDataFileAnalysis(reinterpret_cast<const u_char*>("\r\n"), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool SMTP_Analyzer::ProcessBdatArg(int arg_len, const char* arg, bool orig) {
|
bool SMTP_Analyzer::ProcessBdatArg(int arg_len, const char* arg, bool orig) {
|
||||||
// For the BDAT command, parse out the chunk-size from the line
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SMTP_Analyzer::MailDataFileAnalysis(const u_char* data, uint64_t len) {
|
||||||
|
return file_mgr->DataIn(data, len, GetAnalyzerTag(), Conn(), true, mail_fuid, "message/rfc822");
|
||||||
|
}
|
||||||
|
|
||||||
void SMTP_Analyzer::BeginData(bool orig, detail::SMTP_State new_state) {
|
void SMTP_Analyzer::BeginData(bool orig, detail::SMTP_State new_state) {
|
||||||
state = new_state;
|
state = new_state;
|
||||||
skip_data = false; // reset the flag at the beginning of the mail
|
skip_data = false; // reset the flag at the beginning of the mail
|
||||||
|
@ -890,6 +907,13 @@ void SMTP_Analyzer::BeginData(bool orig, detail::SMTP_State new_state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mail = new analyzer::mime::MIME_Mail(this, orig);
|
mail = new analyzer::mime::MIME_Mail(this, orig);
|
||||||
|
|
||||||
|
if ( zeek::BifConst::SMTP::enable_mail_data_file_analysis ) {
|
||||||
|
mail_fuid = MailDataFileAnalysis(reinterpret_cast<const u_char*>(""), 0);
|
||||||
|
|
||||||
|
auto* f = file_mgr->LookupFile(mail_fuid);
|
||||||
|
f->FileEvent(smtp_mail_data_file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMTP_Analyzer::EndData() {
|
void SMTP_Analyzer::EndData() {
|
||||||
|
@ -911,6 +935,11 @@ void SMTP_Analyzer::EndData() {
|
||||||
delete mail;
|
delete mail;
|
||||||
mail = nullptr;
|
mail = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ! mail_fuid.empty() ) {
|
||||||
|
file_mgr->EndOfFile(mail_fuid);
|
||||||
|
mail_fuid.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace zeek::analyzer::smtp
|
} // namespace zeek::analyzer::smtp
|
||||||
|
|
|
@ -61,6 +61,7 @@ protected:
|
||||||
void ProcessExtension(int ext_len, const char* ext);
|
void ProcessExtension(int ext_len, const char* ext);
|
||||||
void ProcessData(int length, const char* line);
|
void ProcessData(int length, const char* line);
|
||||||
bool ProcessBdatArg(int arg_len, const char* arg, bool orig);
|
bool ProcessBdatArg(int arg_len, const char* arg, bool orig);
|
||||||
|
std::string MailDataFileAnalysis(const u_char* data, uint64_t len);
|
||||||
|
|
||||||
void UpdateState(int cmd_code, int reply_code, bool orig);
|
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
|
std::unique_ptr<detail::SMTP_BDAT_Analyzer> bdat; // if set, BDAT chunk transfer active
|
||||||
|
|
||||||
analyzer::mime::MIME_Mail* mail;
|
analyzer::mime::MIME_Mail* mail;
|
||||||
|
std::string mail_fuid; // fuid for mail data file analysis
|
||||||
|
|
||||||
private:
|
private:
|
||||||
analyzer::tcp::ContentLine_Analyzer* cl_orig;
|
analyzer::tcp::ContentLine_Analyzer* cl_orig;
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
const SMTP::bdat_max_line_length: count;
|
const SMTP::bdat_max_line_length: count;
|
||||||
|
const SMTP::enable_mail_data_file_analysis: bool;
|
||||||
|
|
|
@ -106,3 +106,13 @@ event smtp_unexpected%(c: connection, is_orig: bool, msg: string, detail: string
|
||||||
## c: The connection.
|
## c: The connection.
|
||||||
##
|
##
|
||||||
event smtp_starttls%(c: connection%);
|
event smtp_starttls%(c: connection%);
|
||||||
|
|
||||||
|
## Generated when a new file is created for analyzing the full mail
|
||||||
|
## of an RFC822 message in an SMTP transaction.
|
||||||
|
##
|
||||||
|
## This event can be leveraged to extract the full mail data to disk.
|
||||||
|
##
|
||||||
|
## f: The file corresponding to the mail data.
|
||||||
|
##
|
||||||
|
## .. zeek:see:: SMTP::enable_mail_data_file_analysis
|
||||||
|
event smtp_mail_data_file%(f: fa_file%);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue