From: Steve Chew (stechew) Date: Wed, 25 Mar 2020 15:37:32 +0000 (+0000) Subject: Merge pull request #2081 in SNORT/snort3 from ~OKHOMIAK/snort3:standardize_inspectors... X-Git-Tag: 3.0.1-1~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f2810dfe82e92375bb7bee6e2f8c81caa465d6a5;p=thirdparty%2Fsnort3.git Merge pull request #2081 in SNORT/snort3 from ~OKHOMIAK/snort3:standardize_inspectors_config_output to master Squashed commit of the following: commit 136f35e3127f142c92e37717b9b864b36a2074f2 Author: Oleksii Khomiakovskyi Date: Fri Mar 13 02:15:11 2020 +0200 service_inspectors: standardize verbose config startup output for SMTP, POP and IMAP inspectors --- diff --git a/src/log/messages.cc b/src/log/messages.cc index c4c0ad476..75bf2fefe 100644 --- a/src/log/messages.cc +++ b/src/log/messages.cc @@ -33,6 +33,8 @@ #include "time/packet_time.h" #include "utils/util_cstring.h" +#define MAX_LINE_LEN 75 + using namespace snort; static int already_fatal = 0; @@ -352,5 +354,58 @@ NORETURN_ASSERT void log_safec_error(const char* msg, void*, int e) assert(false); } + +bool LogFlag(const char* caption, bool flag) +{ + LogMessage("%25.25s: %s\n", caption, flag ? "enabled" : "disabled"); + return flag; +} + +void LogLimit(const char* caption, int val, int unlim, int disable) +{ + if ( val == disable ) + LogMessage("%25.25s: %d %s\n", caption, disable, "(disabled)"); + else if ( val == unlim ) + LogMessage("%25.25s: %d %s\n", caption, val, "(unlimited)"); + else + LogMessage("%25.25s: %d\n", caption, val); +} + +void LogLimit(const char* caption, int val, int unlim) +{ + if ( val == unlim ) + LogMessage("%25.25s: %d %s\n", caption, val, "(unlimited)"); + else + LogMessage("%25.25s: %d\n", caption, val); +} + +void LogValue(const char* caption, uint32_t n) +{ + LogMessage("%25.25s: %" PRIu32 "\n", caption, n); +} + +void LogList(const char* caption, const char* list) +{ + std::string res; + std::stringstream ss; + const std::string offset(26,' '); + + size_t len = 0; + std::string val; + + ss << list; + while (ss >> val) + { + if ( len + val.length() > MAX_LINE_LEN ) + { + res += '\n' + offset; + len = 0; + } + res += ' ' + val; + len += val.length() + 1; + } + + LogMessage("%25.25s:%s\n", caption, res.c_str()); +} } //namespace snort diff --git a/src/log/messages.h b/src/log/messages.h index 316895d6d..8813b0ed9 100644 --- a/src/log/messages.h +++ b/src/log/messages.h @@ -62,10 +62,16 @@ SO_PUBLIC void ReloadError(const char*, ...) __attribute__((format (printf, 1, 2 [[noreturn]] SO_PUBLIC void ParseAbort(const char*, ...) __attribute__((format (printf, 1, 2))); SO_PUBLIC void LogMessage(const char*, ...) __attribute__((format (printf, 1, 2))); -SO_PUBLIC void LogMessage(FILE* fh, const char*, ...) __attribute__((format (printf, 2, 3))); +SO_PUBLIC void LogMessage(FILE*, const char*, ...) __attribute__((format (printf, 2, 3))); SO_PUBLIC void WarningMessage(const char*, ...) __attribute__((format (printf, 1, 2))); SO_PUBLIC void ErrorMessage(const char*, ...) __attribute__((format (printf, 1, 2))); +SO_PUBLIC bool LogFlag(const char* caption, bool flag); +SO_PUBLIC void LogLimit(const char* caption, int val, int unlim); +SO_PUBLIC void LogLimit(const char* caption, int val, int unlim, int disable); +SO_PUBLIC void LogList(const char* caption, const char* list); +SO_PUBLIC void LogValue(const char* caption, uint32_t n); + // FIXIT-RC do not call FatalError() during runtime [[noreturn]] SO_PUBLIC void FatalError(const char*, ...) __attribute__((format (printf, 1, 2))); diff --git a/src/mime/file_mime_config.cc b/src/mime/file_mime_config.cc index 42eeea616..0ab391dd1 100644 --- a/src/mime/file_mime_config.cc +++ b/src/mime/file_mime_config.cc @@ -36,7 +36,7 @@ void DecodeConfig::set_ignore_data(bool ignored) ignore_data = ignored; } -bool DecodeConfig::is_ignore_data() +bool DecodeConfig::is_ignore_data() const { return ignore_data; } @@ -46,7 +46,7 @@ void DecodeConfig::set_b64_depth(int depth) b64_depth = depth; } -int DecodeConfig::get_b64_depth() +int DecodeConfig::get_b64_depth() const { return b64_depth; } @@ -56,7 +56,7 @@ void DecodeConfig::set_qp_depth(int depth) qp_depth = depth; } -int DecodeConfig::get_qp_depth() +int DecodeConfig::get_qp_depth() const { return qp_depth; } @@ -66,7 +66,7 @@ void DecodeConfig::set_bitenc_depth(int depth) bitenc_depth = depth; } -int DecodeConfig::get_bitenc_depth() +int DecodeConfig::get_bitenc_depth() const { return bitenc_depth; } @@ -76,7 +76,7 @@ void DecodeConfig::set_uu_depth(int depth) uu_depth = depth; } -int DecodeConfig::get_uu_depth() +int DecodeConfig::get_uu_depth() const { return uu_depth; } @@ -86,7 +86,7 @@ void DecodeConfig::set_decompress_pdf(bool enabled) decompress_pdf = enabled; } -bool DecodeConfig::is_decompress_pdf() +bool DecodeConfig::is_decompress_pdf() const { return decompress_pdf; } @@ -96,7 +96,7 @@ void DecodeConfig::set_decompress_swf(bool enabled) decompress_swf = enabled; } -bool DecodeConfig::is_decompress_swf() +bool DecodeConfig::is_decompress_swf() const { return decompress_swf; } @@ -106,17 +106,17 @@ void DecodeConfig::set_decompress_zip(bool enabled) decompress_zip = enabled; } -bool DecodeConfig::is_decompress_zip() +bool DecodeConfig::is_decompress_zip() const { return decompress_zip; } -int64_t DecodeConfig::get_file_depth() +int64_t DecodeConfig::get_file_depth() const { return file_depth; } -bool DecodeConfig::is_decoding_enabled() +bool DecodeConfig::is_decoding_enabled() const { return decode_enabled; } @@ -125,90 +125,43 @@ bool DecodeConfig::is_decoding_enabled() void DecodeConfig::sync_all_depths() { file_depth = FileService::get_max_file_depth(); - if ((file_depth >= 0)or (b64_depth >= 0) or (qp_depth >= 0) - or (bitenc_depth >= 0) or (uu_depth >= 0)) - decode_enabled = true; - else - decode_enabled = false; + decode_enabled = (file_depth >= 0) or (b64_depth >= 0) or (qp_depth >= 0) or + (bitenc_depth >= 0) or (uu_depth >= 0); } int DecodeConfig::get_max_depth(int decode_depth) { sync_all_depths(); - if (!file_depth or !decode_depth) - return 0; - else if (file_depth > decode_depth) - return file_depth; - else - return decode_depth; + if ( file_depth and decode_depth ) + return (file_depth > decode_depth) ? file_depth : decode_depth; + + return 0; } -void DecodeConfig::print_decode_conf() +//FIXIT-L update this after mime decode depths are revisited +void DecodeConfig::show(bool full) const { - if (b64_depth > -1) + if ( !decode_enabled ) { - LogMessage(" Base64 Decoding: %s\n", "Enabled"); - switch (b64_depth) - { - case 0: - LogMessage(" Base64 Decoding Depth: %s\n", "Unlimited"); - break; - default: - LogMessage(" Base64 Decoding Depth: %d\n", b64_depth); - break; - } + LogFlag("decode_enabled", decode_enabled); + return; } - else - LogMessage(" Base64 Decoding: %s\n", "Disabled"); - if (qp_depth > -1) - { - LogMessage(" Quoted-Printable Decoding: %s\n","Enabled"); - switch (qp_depth) - { - case 0: - LogMessage(" Quoted-Printable Decoding Depth: %s\n", "Unlimited"); - break; - default: - LogMessage(" Quoted-Printable Decoding Depth: %d\n", qp_depth); - break; - } - } - else - LogMessage(" Quoted-Printable Decoding: %s\n", "Disabled"); - - if (uu_depth > -1) - { - LogMessage(" Unix-to-Unix Decoding: %s\n","Enabled"); - switch (uu_depth) - { - case 0: - LogMessage(" Unix-to-Unix Decoding Depth: %s\n", "Unlimited"); - break; - default: - LogMessage(" Unix-to-Unix Decoding Depth: %d\n", uu_depth); - break; - } - } - else - LogMessage(" Unix-to-Unix Decoding: %s\n", "Disabled"); - - if (bitenc_depth > -1) - { - LogMessage(" Non-Encoded MIME attachment Extraction: %s\n","Enabled"); - switch (bitenc_depth) - { - case 0: - LogMessage(" Non-Encoded MIME attachment Extraction Depth: %s\n", "Unlimited"); - break; - default: - LogMessage(" Non-Encoded MIME attachment Extraction Depth: %d\n", - bitenc_depth); - break; - } - } - else - LogMessage(" Non-Encoded MIME attachment Extraction/text: %s\n", "Disabled"); + auto b64 = (b64_depth == 0) ? -1 : ((b64_depth == -1) ? 0 : b64_depth); + auto qp = (qp_depth == 0) ? -1 : ((qp_depth == -1) ? 0 : qp_depth); + auto uu = (uu_depth == 0) ? -1 : ((uu_depth == -1) ? 0 : uu_depth); + auto bitenc = (bitenc_depth == 0) ? -1 : ((bitenc_depth == -1) ? 0 : bitenc_depth); + LogLimit("b64_decode_depth", b64, -1, 0); + LogLimit("qp_decode_depth", qp, -1, 0); + LogLimit("uu_decode_depth", uu, -1, 0); + LogLimit("bitenc_decode_depth", bitenc, -1, 0); + + if ( full ) + LogFlag("ignore_data", ignore_data); + + LogFlag("decompress_pdf", decompress_pdf); + LogFlag("decompress_swf", decompress_swf); + LogFlag("decompress_zip", decompress_zip); } diff --git a/src/mime/file_mime_config.h b/src/mime/file_mime_config.h index dd51d3446..1d15d0c38 100644 --- a/src/mime/file_mime_config.h +++ b/src/mime/file_mime_config.h @@ -39,33 +39,33 @@ class SO_PUBLIC DecodeConfig { public: void set_ignore_data(bool); - bool is_ignore_data(); + bool is_ignore_data() const; void set_b64_depth(int); - int get_b64_depth(); + int get_b64_depth() const; void set_qp_depth(int); - int get_qp_depth(); + int get_qp_depth() const; void set_bitenc_depth(int); - int get_bitenc_depth(); + int get_bitenc_depth() const; void set_uu_depth(int); - int get_uu_depth(); + int get_uu_depth() const; void set_decompress_pdf(bool); - bool is_decompress_pdf(); + bool is_decompress_pdf() const; void set_decompress_swf(bool); - bool is_decompress_swf(); + bool is_decompress_swf() const; void set_decompress_zip(bool); - bool is_decompress_zip(); + bool is_decompress_zip() const; - int64_t get_file_depth(); - bool is_decoding_enabled(); + int64_t get_file_depth() const; + bool is_decoding_enabled() const; void sync_all_depths(); - void print_decode_conf(); + void show(bool = false) const; int get_max_depth(int); private: diff --git a/src/mime/file_mime_log.cc b/src/mime/file_mime_log.cc index a63f97958..fd4df4041 100644 --- a/src/mime/file_mime_log.cc +++ b/src/mime/file_mime_log.cc @@ -63,7 +63,7 @@ int MailLogState::log_file_name(const uint8_t* start, int length) if (!alt_buf || (log_avail <= 0)) return -1; - if ( *alt_len > 0 && ((*alt_len + 1) < alt_size)) + if (*alt_len > 0 && ((*alt_len + 1) < alt_size)) { alt_buf[*alt_len] = ','; *alt_len = *alt_len + 1; @@ -137,10 +137,10 @@ int MailLogState::log_email_id(const uint8_t* start, int length, EmailUserType t if (tmp_eol == nullptr) return -1; - if ((tmp_eol+1) < (start+length)) + if ((tmp_eol + 1) < (start + length)) { - length = length - ( (tmp_eol+1) - start ); - start = tmp_eol+1; + length = length - ((tmp_eol + 1) - start); + start = tmp_eol + 1; } else return -1; @@ -170,7 +170,7 @@ int MailLogState::log_email_id(const uint8_t* start, int length, EmailUserType t else if (log_avail < length) length = log_avail; - if ( *alt_len > 0 && ((*alt_len + 1) < alt_size)) + if (*alt_len > 0 && ((*alt_len + 1) < alt_size)) { alt_buf[*alt_len] = ','; *alt_len = *alt_len + 1; @@ -221,32 +221,24 @@ void MailLogState::get_email_id(uint8_t** buf, uint32_t* len, EmailUserType type } } -bool MailLogState::is_file_name_present() +bool MailLogState::is_file_name_present() const { - if (log_flags & MIME_FLAG_FILENAME_PRESENT) - return true; - return false; + return log_flags & MIME_FLAG_FILENAME_PRESENT; } -bool MailLogState::is_email_hdrs_present() +bool MailLogState::is_email_hdrs_present() const { - if (log_flags & MIME_FLAG_EMAIL_HDRS_PRESENT) - return true; - return false; + return log_flags & MIME_FLAG_EMAIL_HDRS_PRESENT; } -bool MailLogState::is_email_from_present() +bool MailLogState::is_email_from_present() const { - if (log_flags & MIME_FLAG_MAIL_FROM_PRESENT) - return true; - return false; + return log_flags & MIME_FLAG_MAIL_FROM_PRESENT; } -bool MailLogState::is_email_to_present() +bool MailLogState::is_email_to_present() const { - if (log_flags & MIME_FLAG_RCPT_TO_PRESENT) - return true; - return false; + return log_flags & MIME_FLAG_RCPT_TO_PRESENT; } MailLogState::MailLogState(MailLogConfig* conf) @@ -254,14 +246,14 @@ MailLogState::MailLogState(MailLogConfig* conf) if (conf && (conf->log_email_hdrs || conf->log_filename || conf->log_mailfrom || conf->log_rcptto)) { - uint32_t bufsz = (2* MAX_EMAIL) + MAX_FILE + conf->email_hdrs_log_depth; + uint32_t bufsz = (2 * MAX_EMAIL) + MAX_FILE + conf->email_hdrs_log_depth; buf = (uint8_t*)snort_calloc(bufsz); log_depth = conf->email_hdrs_log_depth; recipients = buf; senders = buf + MAX_EMAIL; - filenames = buf + (2*MAX_EMAIL); - emailHdrs = buf + (2*MAX_EMAIL) + MAX_FILE; + filenames = buf + (2 * MAX_EMAIL); + emailHdrs = buf + (2 * MAX_EMAIL) + MAX_FILE; } rcpts_logged = 0; diff --git a/src/mime/file_mime_log.h b/src/mime/file_mime_log.h index 08cbd04b3..255a74321 100644 --- a/src/mime/file_mime_log.h +++ b/src/mime/file_mime_log.h @@ -37,10 +37,10 @@ enum EmailUserType struct MailLogConfig { - char log_mailfrom = 0; - char log_rcptto = 0; - char log_filename = 0; - char log_email_hdrs = 0; + bool log_mailfrom = false; + bool log_rcptto = false; + bool log_filename = false; + bool log_email_hdrs = false; uint32_t email_hdrs_log_depth = 0; }; @@ -56,16 +56,16 @@ public: int log_file_name(const uint8_t* start, int length); int log_email_hdrs(const uint8_t* start, int length); - int log_email_id (const uint8_t* start, int length, EmailUserType); + int log_email_id(const uint8_t* start, int length, EmailUserType); void get_file_name(uint8_t** buf, uint32_t* len); void get_email_hdrs(uint8_t** buf, uint32_t* len); void get_email_id(uint8_t** buf, uint32_t* len, EmailUserType); - bool is_file_name_present(); - bool is_email_hdrs_present(); - bool is_email_from_present(); - bool is_email_to_present(); + bool is_file_name_present() const; + bool is_email_hdrs_present() const; + bool is_email_from_present() const; + bool is_email_to_present() const; private: int log_flags = 0; diff --git a/src/service_inspectors/imap/imap.cc b/src/service_inspectors/imap/imap.cc index b35805381..87b596b97 100644 --- a/src/service_inspectors/imap/imap.cc +++ b/src/service_inspectors/imap/imap.cc @@ -261,17 +261,6 @@ static void IMAP_GetEOL(const uint8_t* ptr, const uint8_t* end, *eolm = tmp_eolm; } -static void PrintImapConf(IMAP_PROTO_CONF* config) -{ - if (config == nullptr) - return; - - config->decode_conf.print_decode_conf(); - - LogMessage("\n"); - -} - static inline int InspectPacket(Packet* p) { return p->has_paf_payload(); @@ -739,7 +728,8 @@ bool Imap::configure(SnortConfig*) void Imap::show(SnortConfig*) { - PrintImapConf(config); + if ( config ) + config->decode_conf.show(); } void Imap::eval(Packet* p) diff --git a/src/service_inspectors/pop/pop.cc b/src/service_inspectors/pop/pop.cc index 99d4b70a5..9eac981c7 100644 --- a/src/service_inspectors/pop/pop.cc +++ b/src/service_inspectors/pop/pop.cc @@ -221,17 +221,6 @@ static void POP_GetEOL(const uint8_t* ptr, const uint8_t* end, *eolm = tmp_eolm; } -static void PrintPopConf(POP_PROTO_CONF* config) -{ - if (config == nullptr) - return; - - config->decode_conf.print_decode_conf(); - - LogMessage("\n"); - -} - static inline int InspectPacket(Packet* p) { return p->has_paf_payload(); @@ -680,7 +669,8 @@ bool Pop::configure(SnortConfig* ) void Pop::show(SnortConfig*) { - PrintPopConf(config); + if ( config ) + config->decode_conf.show(); } void Pop::eval(Packet* p) diff --git a/src/service_inspectors/smtp/smtp.cc b/src/service_inspectors/smtp/smtp.cc index 8c719f1e3..9e0933d85 100644 --- a/src/service_inspectors/smtp/smtp.cc +++ b/src/service_inspectors/smtp/smtp.cc @@ -22,6 +22,8 @@ #include "smtp.h" +#include + #include "detection/detection_engine.h" #include "detection/detection_util.h" #include "log/messages.h" @@ -178,7 +180,18 @@ const PegInfo smtp_peg_names[] = { CountType::END, nullptr, nullptr } }; -static void snort_smtp(SMTP_PROTO_CONF* GlobalConf, Packet* p); +enum SMTPCmdGroup +{ + ALERT_CMDS = 0, + AUTH_CMDS, + BDATA_CMDS, + DATA_CMDS, + NORM_CMDS, + VALID_CMDS, + ALT_LEN_CMDS +}; + +static void snort_smtp(SmtpProtoConf* GlobalConf, Packet* p); static void SMTP_ResetState(Flow*); SmtpFlowData::SmtpFlowData() : FlowData(inspector_id) @@ -208,7 +221,7 @@ static SMTPData* get_session_data(Flow* flow) return fd ? &fd->session : nullptr; } -static SMTPData* SetNewSMTPData(SMTP_PROTO_CONF* config, Packet* p) +static SMTPData* SetNewSMTPData(SmtpProtoConf* config, Packet* p) { SMTPData* smtp_ssn; SmtpFlowData* fd = new SmtpFlowData; @@ -228,7 +241,7 @@ static SMTPData* SetNewSMTPData(SMTP_PROTO_CONF* config, Packet* p) return smtp_ssn; } -static void SMTP_InitCmds(SMTP_PROTO_CONF* config) +static void SMTP_InitCmds(SmtpProtoConf* config) { if (config == nullptr) return; @@ -248,7 +261,7 @@ static void SMTP_InitCmds(SMTP_PROTO_CONF* config) config->num_cmds = CMD_LAST; } -static void SMTP_TermCmds(SMTP_PROTO_CONF* config) +static void SMTP_TermCmds(SmtpProtoConf* config) { if (!config) return; @@ -262,7 +275,7 @@ static void SMTP_TermCmds(SMTP_PROTO_CONF* config) snort_free(config->cmd_config); } -static void SMTP_CommandSearchInit(SMTP_PROTO_CONF* config) +static void SMTP_CommandSearchInit(SmtpProtoConf* config) { config->cmd_search_mpse = new SearchTool; config->cmd_search = (SMTPSearch*)snort_calloc(config->num_cmds, sizeof(*config->cmd_search)); @@ -277,7 +290,7 @@ static void SMTP_CommandSearchInit(SMTP_PROTO_CONF* config) config->cmd_search_mpse->prep(); } -static void SMTP_CommandSearchTerm(SMTP_PROTO_CONF* config) +static void SMTP_CommandSearchTerm(SmtpProtoConf* config) { if (config->cmd_search == nullptr) return; @@ -309,7 +322,7 @@ static void SMTP_SearchFree() delete smtp_resp_search_mpse; } -static int AddCmd(SMTP_PROTO_CONF* config, const char* name, SMTPCmdTypeEnum type) +static int AddCmd(SmtpProtoConf* config, const char* name, SMTPCmdTypeEnum type) { SMTPToken* cmds; SMTPCmdConfig* cmd_config; @@ -322,11 +335,11 @@ static int AddCmd(SMTP_PROTO_CONF* config, const char* name, SMTPCmdTypeEnum typ cmd_config = (SMTPCmdConfig*)snort_calloc((config->num_cmds + 1) * sizeof(*cmd_config)); /* copy existing commands into newly allocated memory */ - memcpy_s(cmds, (config->num_cmds) * sizeof(*cmds), - config->cmds, (config->num_cmds) * sizeof(*cmds) - 1); + memcpy_s(cmds, config->num_cmds * sizeof(*cmds), + config->cmds, (config->num_cmds - 1) * sizeof(*cmds)); memcpy_s(cmd_config, config->num_cmds * sizeof(*cmd_config), - config->cmd_config, config->num_cmds - 1); + config->cmd_config, (config->num_cmds - 1) * sizeof(*cmd_config)); /* add new command to cmds cmd_config doesn't need anything added - this * will probably be done by a calling function */ @@ -336,7 +349,7 @@ static int AddCmd(SMTP_PROTO_CONF* config, const char* name, SMTPCmdTypeEnum typ tok->name_len = strlen(name); tok->search_id = config->num_cmds - 1; - if (type) + if ( type ) tok->type = type; /* free global memory structures */ @@ -350,11 +363,11 @@ static int AddCmd(SMTP_PROTO_CONF* config, const char* name, SMTPCmdTypeEnum typ config->cmds = cmds; config->cmd_config = cmd_config; - return (config->num_cmds - 1); + return config->num_cmds - 1; } /* Return id associated with a given command string */ -static int GetCmdId(SMTP_PROTO_CONF* config, const char* name, SMTPCmdTypeEnum type) +static int GetCmdId(SmtpProtoConf* config, const char* name, SMTPCmdTypeEnum type) { SMTPToken* cmd; @@ -372,142 +385,135 @@ static int GetCmdId(SMTP_PROTO_CONF* config, const char* name, SMTPCmdTypeEnum t return AddCmd(config, name, type); } -static void SMTP_PrintConfig(SMTP_PROTO_CONF* config) +static std::string GetCmdGroup(const SMTPToken* cmd_tokens, const SMTPCmdConfig* cmd_config, + SMTPCmdGroup group) { - assert(config); - - char buf[8192]; - int alert_count = 0; - - snprintf(buf, sizeof(buf) - 1, " Normalize: "); - - if (config->normalize == NORMALIZE_ALL) - sfsnprintfappend(buf, sizeof(buf) - 1, "all"); + std::string cmds; - else if (config->normalize == NORMALIZE_NONE) - sfsnprintfappend(buf, sizeof(buf) - 1, "none"); - - else if (config->normalize == NORMALIZE_CMDS) + for (auto cmd = cmd_tokens; cmd->name; cmd++) { - for (SMTPToken* cmd = config->cmds; cmd->name != nullptr; cmd++) + bool cond; + + if ( group == ALERT_CMDS ) + cond = cmd_config[cmd->search_id].alert; + else if ( group == VALID_CMDS ) + cond = !cmd_config[cmd->search_id].alert; + else if ( group == NORM_CMDS ) + cond = cmd_config[cmd->search_id].normalize; + else if ( group == ALT_LEN_CMDS ) + cond = cmd_config[cmd->search_id].max_line_len; + else if ( group == AUTH_CMDS ) + cond = (cmd->type == SMTP_CMD_TYPE_AUTH); + else if ( group == BDATA_CMDS ) + cond = (cmd->type == SMTP_CMD_TYPE_BDATA); + else if ( group == DATA_CMDS ) + cond = (cmd->type == SMTP_CMD_TYPE_DATA); + else + return cmds; + + if ( cond ) { - if (config->cmd_config[cmd->search_id].normalize) + if ( group == ALT_LEN_CMDS ) { - sfsnprintfappend(buf, sizeof(buf) - 1, "%s ", cmd->name); + std::string cmd_name = cmd->name; + int len = cmd_config[cmd->search_id].max_line_len; + cmds.append("{" + cmd_name + ", " + std::to_string(len) + "}"); + cmds.append(", "); + } + else + { + cmds.append(cmd->name); + cmds.append(" "); } } } - LogMessage("%s\n", buf); - - LogMessage(" Ignore Data: %s\n", - config->decode_conf.is_ignore_data() ? "Yes" : "No"); - LogMessage(" Ignore TLS Data: %s\n", - config->ignore_tls_data ? "Yes" : "No"); - snprintf(buf, sizeof(buf) - 1, " Max Command Line Length: "); - - if (config->max_command_line_len == 0) - sfsnprintfappend(buf, sizeof(buf) - 1, "Unlimited"); - else - sfsnprintfappend(buf, sizeof(buf) - 1, "%d", config->max_command_line_len); - - LogMessage("%s\n", buf); - + if ( !cmds.empty() ) { - snprintf(buf, sizeof(buf) - 1, " Max Specific Command Line Length: "); - int max_line_len_count = 0; - - for (SMTPToken* cmd = config->cmds; cmd->name != nullptr; cmd++) + if ( group == ALT_LEN_CMDS ) { - int max_line_len = config->cmd_config[cmd->search_id].max_line_len; - - if (max_line_len != 0) - { - if (max_line_len_count % 5 == 0) - { - LogMessage("%s\n", buf); - snprintf(buf, sizeof(buf) - 1, " %s:%d ", cmd->name, max_line_len); - } - else - { - sfsnprintfappend(buf, sizeof(buf) - 1, "%s:%d ", cmd->name, max_line_len); - } - - max_line_len_count++; - } + cmds.erase(cmds.end() - 2); + cmds = "{ " + cmds + " }"; } - - if (max_line_len_count == 0) - LogMessage("%sNone\n", buf); else - LogMessage("%s\n", buf); + cmds.pop_back(); } - snprintf(buf, sizeof(buf) - 1, " Max Header Line Length: "); - - if (config->max_header_line_len == 0) - LogMessage("%sUnlimited\n", buf); else - LogMessage("%s%d\n", buf, config->max_header_line_len); - - snprintf(buf, sizeof(buf) - 1, " Max Auth Command Line Length: "); - LogMessage("%s%d\n", buf, config->max_auth_command_line_len); - - snprintf(buf, sizeof(buf) - 1, " Max Response Line Length: "); + cmds.append("none"); - if (config->max_response_line_len == 0) - LogMessage("%sUnlimited\n", buf); - else - LogMessage("%s%d\n", buf, config->max_response_line_len); + return cmds; +} - LogMessage(" X-Link2State Enabled: %s\n", - (config->xlink2state == ALERT_XLINK2STATE) ? "Yes" : "No"); - if (config->xlink2state == DROP_XLINK2STATE) - { - LogMessage(" Drop on X-Link2State Alert: %s\n", "Yes"); - } - else +static const char* to_string(const SMTPNormType& normalize) +{ + switch (normalize) { - LogMessage(" Drop on X-Link2State Alert: %s\n", "No"); + case NORMALIZE_ALL: + return "all"; + case NORMALIZE_NONE: + return "none"; + case NORMALIZE_CMDS: + return "cmds"; } - snprintf(buf, sizeof(buf) - 1, " Alert on commands: "); - - for (SMTPToken* cmd = config->cmds; cmd->name != nullptr; cmd++) - { - if (config->cmd_config[cmd->search_id].alert) - { - sfsnprintfappend(buf, sizeof(buf) - 1, "%s ", cmd->name); - alert_count++; - } - } + return ""; +} - if (alert_count == 0) - { - LogMessage("%sNone\n", buf); - } - else +static const char* to_string(const SMTPXlinkState& mode) +{ + switch (mode) { - LogMessage("%s\n", buf); + case DISABLE_XLINK2STATE: + return "disable"; + case ALERT_XLINK2STATE: + return "alert"; + case DROP_XLINK2STATE: + return "drop"; } - config->decode_conf.print_decode_conf(); - - LogMessage(" Log Attachment filename: %s\n", - config->log_config.log_filename ? "Enabled" : "Not Enabled"); + return ""; +} - LogMessage(" Log MAIL FROM Address: %s\n", - config->log_config.log_mailfrom ? "Enabled" : "Not Enabled"); +static void log_mail_show(const snort::MailLogConfig& conf) +{ + LogFlag("log_mailfrom", conf.log_mailfrom); + LogFlag("log_rcptto", conf.log_rcptto); + LogFlag("log_filename", conf.log_filename); - LogMessage(" Log RCPT TO Addresses: %s\n", - config->log_config.log_rcptto ? "Enabled" : "Not Enabled"); + if ( LogFlag("log_email_hdrs", conf.log_email_hdrs) ) + LogValue("email_hdrs_log_depth", conf.email_hdrs_log_depth); +} - LogMessage(" Log Email Headers: %s\n", - config->log_config.log_email_hdrs ? "Enabled" : "Not Enabled"); - if (config->log_config.log_email_hdrs) - { - LogMessage(" Email Hdrs Log Depth: %u\n", - config->log_config.email_hdrs_log_depth); - } +void SmtpProtoConf::show() const +{ + auto alt_len_cmds = GetCmdGroup(cmds, cmd_config, ALT_LEN_CMDS); + auto alert_cmds = GetCmdGroup(cmds, cmd_config, ALERT_CMDS); + auto auth_cmds = GetCmdGroup(cmds, cmd_config, AUTH_CMDS); + auto bdata_cmds = GetCmdGroup(cmds, cmd_config, BDATA_CMDS); + auto data_cmds = GetCmdGroup(cmds, cmd_config, DATA_CMDS); + auto norm_cmds = GetCmdGroup(cmds, cmd_config, NORM_CMDS); + auto valid_cmds = GetCmdGroup(cmds, cmd_config, VALID_CMDS); + + LogValue("normalize", to_string(normalize)); + LogList("normalize_cmds", norm_cmds.c_str()); + + LogFlag("ignore_tls_data", ignore_tls_data); + LogLimit("max_command_line_len", max_command_line_len, 0); + LogList("alt_max_command_line_len", alt_len_cmds.c_str()); + LogLimit("max_header_line_len", max_header_line_len, 0); + LogLimit("max_auth_command_line_len", max_auth_command_line_len, 0); + LogLimit("max_response_line_length", max_response_line_len, 0); + + LogValue("xlink2state", to_string(xlink2state)); + LogList("invalid_cmds", alert_cmds.c_str()); + + LogList("auth_cmds", auth_cmds.c_str()); + LogList("binary_data_cmds", bdata_cmds.c_str()); + LogList("data_cmds", data_cmds.c_str()); + LogList("valid_cmds", valid_cmds.c_str()); + + decode_conf.show(true); + log_mail_show(log_config); } static void SMTP_ResetState(Flow* ssn) @@ -655,7 +661,7 @@ static bool SMTP_IsAuthChanged(SMTPData* smtp_ssn, const uint8_t* start_ptr, con * @return pointer into p->data where we stopped looking at data * will be end of line or end of packet */ -static const uint8_t* SMTP_HandleCommand(SMTP_PROTO_CONF* config, Packet* p, SMTPData* smtp_ssn, +static const uint8_t* SMTP_HandleCommand(SmtpProtoConf* config, Packet* p, SMTPData* smtp_ssn, const uint8_t* ptr, const uint8_t* end) { const uint8_t* eol; /* end of line */ @@ -982,7 +988,7 @@ static const uint8_t* SMTP_HandleCommand(SMTP_PROTO_CONF* config, Packet* p, SMT * * @return none */ -static void SMTP_ProcessClientPacket(SMTP_PROTO_CONF* config, Packet* p, SMTPData* smtp_ssn) +static void SMTP_ProcessClientPacket(SmtpProtoConf* config, Packet* p, SMTPData* smtp_ssn) { const uint8_t* ptr = p->data; const uint8_t* end = p->data + p->dsize; @@ -1036,7 +1042,7 @@ static void SMTP_ProcessClientPacket(SMTP_PROTO_CONF* config, Packet* p, SMTPDat * @return None */ static void SMTP_ProcessServerPacket( - SMTP_PROTO_CONF* config, Packet* p, SMTPData* smtp_ssn, int* next_state) + SmtpProtoConf* config, Packet* p, SMTPData* smtp_ssn, int* next_state) { *next_state = 0; @@ -1136,7 +1142,7 @@ static void SMTP_ProcessServerPacket( * * @return none */ -static void snort_smtp(SMTP_PROTO_CONF* config, Packet* p) +static void snort_smtp(SmtpProtoConf* config, Packet* p) { int pkt_dir; @@ -1288,7 +1294,7 @@ static int SMTP_GetEmailHdrs(Flow* flow, uint8_t** buf, uint32_t* len, uint32_t* return 1; } -static void SMTP_RegXtraDataFuncs(SMTP_PROTO_CONF* config) +static void SMTP_RegXtraDataFuncs(SmtpProtoConf* config) { config->xtra_filename_id = Stream::reg_xtra_data_cb(SMTP_GetFilename); config->xtra_mfrom_id = Stream::reg_xtra_data_cb(SMTP_GetMailFrom); @@ -1392,7 +1398,7 @@ bool SmtpMime::is_end_of_data(Flow* session) class Smtp : public Inspector { public: - Smtp(SMTP_PROTO_CONF*); + Smtp(SmtpProtoConf*); ~Smtp() override; bool configure(SnortConfig*) override; @@ -1407,10 +1413,10 @@ public: void ProcessSmtpCmdsList(const SmtpCmd*); private: - SMTP_PROTO_CONF* config; + SmtpProtoConf* config; }; -Smtp::Smtp(SMTP_PROTO_CONF* pc) +Smtp::Smtp(SmtpProtoConf* pc) { config = pc; @@ -1441,7 +1447,8 @@ bool Smtp::configure(SnortConfig*) void Smtp::show(SnortConfig*) { - SMTP_PrintConfig(config); + if ( config ) + config->show(); } void Smtp::eval(Packet* p) @@ -1482,10 +1489,10 @@ void Smtp::ProcessSmtpCmdsList(const SmtpCmd* sc) if ( sc->flags & PCMD_AUTH ) type = SMTP_CMD_TYPE_AUTH; - else if ( sc->flags & PCMD_BDATA ) + else if ( sc->flags & PCMD_BDATA ) type = SMTP_CMD_TYPE_BDATA; - else if ( sc->flags & PCMD_DATA ) + else if ( sc->flags & PCMD_DATA ) type = SMTP_CMD_TYPE_DATA; else @@ -1493,7 +1500,7 @@ void Smtp::ProcessSmtpCmdsList(const SmtpCmd* sc) id = GetCmdId(config, cmd, type); - if ( sc->flags & PCMD_INVALID ) + if ( sc->flags & PCMD_INVALID ) config->cmd_config[id].alert = true; else if ( sc->flags & PCMD_NORM ) @@ -1529,7 +1536,7 @@ static void smtp_term() static Inspector* smtp_ctor(Module* m) { SmtpModule* mod = (SmtpModule*)m; - SMTP_PROTO_CONF* conf = mod->get_data(); + SmtpProtoConf* conf = mod->get_data(); Smtp* smtp = new Smtp(conf); unsigned i = 0; @@ -1593,7 +1600,7 @@ TEST_CASE("handle_header_line", "[smtp]") log_config.log_email_hdrs = 0; SmtpMime mime_ssn(&decode_conf, &log_config); smtp_normalizing = true; - SMTP_PROTO_CONF config; + SmtpProtoConf config; mime_ssn.config = &config; uint8_t ptr[68] = "Date: Tue, 1 Mar 2016 22:37:56 -0500\r\nFrom: acc2 \r\n"; uint8_t* eol = ptr + 38; @@ -1618,7 +1625,7 @@ TEST_CASE("normalize_data", "[smtp]") DecodeConfig decode_conf; SmtpMime mime_ssn(&decode_conf, &log_config); smtp_normalizing = true; - SMTP_PROTO_CONF config; + SmtpProtoConf config; mime_ssn.config = &config; uint8_t ptr[23] = "\r\n--wac7ysb48OaltWcw\r\n"; uint8_t* data_end = ptr + 22; diff --git a/src/service_inspectors/smtp/smtp.h b/src/service_inspectors/smtp/smtp.h index d4032f5fc..e9a9a3439 100644 --- a/src/service_inspectors/smtp/smtp.h +++ b/src/service_inspectors/smtp/smtp.h @@ -142,7 +142,7 @@ class SmtpMime : public snort::MimeSession { public: using snort::MimeSession::MimeSession; - SMTP_PROTO_CONF* config; + SmtpProtoConf* config; #ifndef UNIT_TEST private: #endif diff --git a/src/service_inspectors/smtp/smtp_config.h b/src/service_inspectors/smtp/smtp_config.h index 201e00474..bee0df255 100644 --- a/src/service_inspectors/smtp/smtp_config.h +++ b/src/service_inspectors/smtp/smtp_config.h @@ -24,14 +24,14 @@ #include "mime/file_mime_process.h" #include "search_engines/search_tool.h" -enum NORM_TYPES +enum SMTPNormType { NORMALIZE_NONE = 0, NORMALIZE_CMDS, NORMALIZE_ALL }; -enum XLINK2STATE +enum SMTPXlinkState { DISABLE_XLINK2STATE = 0, ALERT_XLINK2STATE, @@ -120,15 +120,15 @@ struct SMTPToken SMTPCmdTypeEnum type; }; -struct SMTP_PROTO_CONF +struct SmtpProtoConf { - NORM_TYPES normalize; + SMTPNormType normalize; bool ignore_tls_data; int max_auth_command_line_len = 1000; int max_command_line_len = 0; int max_header_line_len = 0; int max_response_line_len = 0; - int xlink2state; + SMTPXlinkState xlink2state; snort::MailLogConfig log_config; snort::DecodeConfig decode_conf; @@ -142,6 +142,8 @@ struct SMTP_PROTO_CONF SMTPCmdConfig* cmd_config = nullptr; SMTPSearch* cmd_search = nullptr; snort::SearchTool* cmd_search_mpse = nullptr; + + void show() const; }; struct SmtpStats diff --git a/src/service_inspectors/smtp/smtp_module.cc b/src/service_inspectors/smtp/smtp_module.cc index b9a5adce4..0aaeada21 100644 --- a/src/service_inspectors/smtp/smtp_module.cc +++ b/src/service_inspectors/smtp/smtp_module.cc @@ -307,7 +307,7 @@ bool SmtpModule::set(const char*, Value& v, SnortConfig*) config->max_response_line_len = v.get_uint16(); else if ( v.is("normalize") ) - config->normalize = (NORM_TYPES)v.get_uint8(); + config->normalize = (SMTPNormType)v.get_uint8(); else if ( v.is("normalize_cmds")) add_commands(v, PCMD_NORM); @@ -331,7 +331,7 @@ bool SmtpModule::set(const char*, Value& v, SnortConfig*) else if ( v.is("xlink2state") ) { - config->xlink2state = (XLINK2STATE)v.get_uint8(); + config->xlink2state = (SMTPXlinkState)v.get_uint8(); Active::set_enabled(); } @@ -341,9 +341,9 @@ bool SmtpModule::set(const char*, Value& v, SnortConfig*) return true; } -SMTP_PROTO_CONF* SmtpModule::get_data() +SmtpProtoConf* SmtpModule::get_data() { - SMTP_PROTO_CONF* tmp = config; + SmtpProtoConf* tmp = config; config = nullptr; return tmp; } @@ -355,7 +355,7 @@ bool SmtpModule::begin(const char*, int, SnortConfig*) if(!config) { - config = new SMTP_PROTO_CONF; + config = new SmtpProtoConf; config->xlink2state = ALERT_XLINK2STATE; config->decode_conf.set_ignore_data(config->ignore_tls_data = false); config->normalize = NORMALIZE_NONE; diff --git a/src/service_inspectors/smtp/smtp_module.h b/src/service_inspectors/smtp/smtp_module.h index 58b8b2c47..ada745c15 100644 --- a/src/service_inspectors/smtp/smtp_module.h +++ b/src/service_inspectors/smtp/smtp_module.h @@ -93,7 +93,7 @@ public: PegCount* get_counts() const override; snort::ProfileStats* get_profile() const override; - SMTP_PROTO_CONF* get_data(); + SmtpProtoConf* get_data(); const SmtpCmd* get_cmd(unsigned idx); Usage get_usage() const override @@ -103,7 +103,7 @@ private: void add_commands(snort::Value&, uint32_t flags); private: - SMTP_PROTO_CONF* config; + SmtpProtoConf* config; std::vector cmds; std::string names; int number; diff --git a/src/service_inspectors/smtp/smtp_util.cc b/src/service_inspectors/smtp/smtp_util.cc index a618a1178..bf0b5384c 100644 --- a/src/service_inspectors/smtp/smtp_util.cc +++ b/src/service_inspectors/smtp/smtp_util.cc @@ -107,7 +107,7 @@ int SMTP_CopyToAltBuffer(Packet* p, const uint8_t* start, int length) return 0; } -void SMTP_LogFuncs(SMTP_PROTO_CONF* config, Packet* p, MimeSession* mime_ssn) +void SMTP_LogFuncs(SmtpProtoConf* config, Packet* p, MimeSession* mime_ssn) { if (!mime_ssn) return; diff --git a/src/service_inspectors/smtp/smtp_util.h b/src/service_inspectors/smtp/smtp_util.h index c01e01e29..eecc26a59 100644 --- a/src/service_inspectors/smtp/smtp_util.h +++ b/src/service_inspectors/smtp/smtp_util.h @@ -32,7 +32,7 @@ struct Packet; } void SMTP_GetEOL(const uint8_t*, const uint8_t*, const uint8_t**, const uint8_t**); -void SMTP_LogFuncs(SMTP_PROTO_CONF*, snort::Packet*, snort::MimeSession*); +void SMTP_LogFuncs(SmtpProtoConf*, snort::Packet*, snort::MimeSession*); int SMTP_CopyToAltBuffer(snort::Packet*, const uint8_t*, int); const uint8_t* SMTP_GetAltBuffer(snort::Packet*, unsigned& len); diff --git a/src/service_inspectors/smtp/smtp_xlink2state.cc b/src/service_inspectors/smtp/smtp_xlink2state.cc index 8e5711097..5b63bbdc5 100644 --- a/src/service_inspectors/smtp/smtp_xlink2state.cc +++ b/src/service_inspectors/smtp/smtp_xlink2state.cc @@ -38,25 +38,13 @@ using namespace snort; #define XLINK_FIRST 2 #define XLINK_CHUNK 3 -#define XLINK_LEN 12 /* strlen("X-LINK2STATE") */ +#define XLINK_LEN 12 -/* X-Link2State overlong length */ #define XLINK2STATE_MAX_LEN 520 -/* Prototypes */ static uint32_t get_xlink_hex_value(const uint8_t*, const uint8_t*); static char get_xlink_keyword(const uint8_t*, const uint8_t*); -/* - * Extract a number from a string - * - * @param buf pointer to beginning of buffer to parse - * @param end end pointer of buffer to parse - * - * @return unsigned long value of number extracted - * - * @note this could be more efficient, but the search buffer should be pretty short - */ static uint32_t get_xlink_hex_value(const uint8_t* buf, const uint8_t* end) { uint32_t value = 0; @@ -92,15 +80,6 @@ static uint32_t get_xlink_hex_value(const uint8_t* buf, const uint8_t* end) return value; } -/* - * Check for X-LINK2STATE keywords FIRST or CHUNK - * - * - * @param x pointer to "X-LINK2STATE" in buffer - * @param x_len length of buffer after x - * - * @retval int identifies which keyword found, if any - */ static char get_xlink_keyword(const uint8_t* ptr, const uint8_t* end) { int len; @@ -132,52 +111,7 @@ static char get_xlink_keyword(const uint8_t* ptr, const uint8_t* end) return XLINK_OTHER; } -/* - * Handle X-Link2State vulnerability - * - * From Lurene Grenier: - - The X-LINK2STATE command always takes the following form: - - X-LINK2STATE [FIRST|NEXT|LAST] CHUNK= - - The overwrite occurs when three criteria are met: - - No chunk identifier exists - ie neither FIRST, NEXT, or LAST are specified - No previous FIRST chunk was sent - has a length greater than 520 bytes - - Normally you send a FIRST chunk, then some intermediary chunks marked with - either NEXT or not marked, then finally a LAST chunk. If no first chunk is - sent, and a chunk with no specifier is sent, it assumes it must append to - something, but it has nothing to append to, so an overwrite occurs. Sending out - of order chunks WITH specifiers results in an exception. - - So simply: - - if (gotFirstChunk) - next; # chunks came with proper first chunk specified - if (/X-LINK2STATE [FIRST|NEXT|LAST] CHUNK/) - { - if (/X-LINK2STATE FIRST CHUNK/) gotFirstChunk = TRUE; - next; # some specifier is marked - } - if (chunkLen > 520) - attempt = TRUE; # Gotcha! - - Usually it takes more than one unspecified packet in a row, but I think this is - just a symptom of the fact that we're triggering a heap overwrite, and not a - condition of the bug. However, if we're still getting FPs this might be an - avenue to try. - - * - * @param p standard Packet structure - * @param x pointer to "X-LINK2STATE" in buffer - * - * @retval 1 if alert raised - * @retval 0 if no alert raised - */ -int ParseXLink2State(SMTP_PROTO_CONF* config, Packet* p, SMTPData* smtp_ssn, const uint8_t* ptr) +int ParseXLink2State(SmtpProtoConf* config, Packet* p, SMTPData* smtp_ssn, const uint8_t* ptr) { const uint8_t* lf = nullptr; uint32_t len = 0; diff --git a/src/service_inspectors/smtp/smtp_xlink2state.h b/src/service_inspectors/smtp/smtp_xlink2state.h index c093a438d..44be7a1ef 100644 --- a/src/service_inspectors/smtp/smtp_xlink2state.h +++ b/src/service_inspectors/smtp/smtp_xlink2state.h @@ -26,6 +26,6 @@ #include "smtp.h" -int ParseXLink2State(SMTP_PROTO_CONF*, snort::Packet*, SMTPData*, const uint8_t*); +int ParseXLink2State(SmtpProtoConf*, snort::Packet*, SMTPData*, const uint8_t*); #endif