#include "time/packet_time.h"
#include "utils/util_cstring.h"
+#define MAX_LINE_LEN 75
+
using namespace snort;
static int already_fatal = 0;
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
[[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)));
ignore_data = ignored;
}
-bool DecodeConfig::is_ignore_data()
+bool DecodeConfig::is_ignore_data() const
{
return ignore_data;
}
b64_depth = depth;
}
-int DecodeConfig::get_b64_depth()
+int DecodeConfig::get_b64_depth() const
{
return b64_depth;
}
qp_depth = depth;
}
-int DecodeConfig::get_qp_depth()
+int DecodeConfig::get_qp_depth() const
{
return qp_depth;
}
bitenc_depth = depth;
}
-int DecodeConfig::get_bitenc_depth()
+int DecodeConfig::get_bitenc_depth() const
{
return bitenc_depth;
}
uu_depth = depth;
}
-int DecodeConfig::get_uu_depth()
+int DecodeConfig::get_uu_depth() const
{
return uu_depth;
}
decompress_pdf = enabled;
}
-bool DecodeConfig::is_decompress_pdf()
+bool DecodeConfig::is_decompress_pdf() const
{
return decompress_pdf;
}
decompress_swf = enabled;
}
-bool DecodeConfig::is_decompress_swf()
+bool DecodeConfig::is_decompress_swf() const
{
return decompress_swf;
}
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;
}
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);
}
{
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:
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;
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;
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;
}
}
-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)
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;
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;
};
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;
*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();
void Imap::show(SnortConfig*)
{
- PrintImapConf(config);
+ if ( config )
+ config->decode_conf.show();
}
void Imap::eval(Packet* p)
*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();
void Pop::show(SnortConfig*)
{
- PrintPopConf(config);
+ if ( config )
+ config->decode_conf.show();
}
void Pop::eval(Packet* p)
#include "smtp.h"
+#include <string>
+
#include "detection/detection_engine.h"
#include "detection/detection_util.h"
#include "log/messages.h"
{ 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)
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;
return smtp_ssn;
}
-static void SMTP_InitCmds(SMTP_PROTO_CONF* config)
+static void SMTP_InitCmds(SmtpProtoConf* config)
{
if (config == nullptr)
return;
config->num_cmds = CMD_LAST;
}
-static void SMTP_TermCmds(SMTP_PROTO_CONF* config)
+static void SMTP_TermCmds(SmtpProtoConf* config)
{
if (!config)
return;
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));
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;
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;
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 */
tok->name_len = strlen(name);
tok->search_id = config->num_cmds - 1;
- if (type)
+ if ( type )
tok->type = type;
/* free global memory structures */
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;
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)
* @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 */
*
* @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;
* @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;
*
* @return none
*/
-static void snort_smtp(SMTP_PROTO_CONF* config, Packet* p)
+static void snort_smtp(SmtpProtoConf* config, Packet* p)
{
int pkt_dir;
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);
class Smtp : public Inspector
{
public:
- Smtp(SMTP_PROTO_CONF*);
+ Smtp(SmtpProtoConf*);
~Smtp() override;
bool configure(SnortConfig*) override;
void ProcessSmtpCmdsList(const SmtpCmd*);
private:
- SMTP_PROTO_CONF* config;
+ SmtpProtoConf* config;
};
-Smtp::Smtp(SMTP_PROTO_CONF* pc)
+Smtp::Smtp(SmtpProtoConf* pc)
{
config = pc;
void Smtp::show(SnortConfig*)
{
- SMTP_PrintConfig(config);
+ if ( config )
+ config->show();
}
void Smtp::eval(Packet* p)
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
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 )
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;
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 <acc2@localhost>\r\n";
uint8_t* eol = ptr + 38;
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;
{
public:
using snort::MimeSession::MimeSession;
- SMTP_PROTO_CONF* config;
+ SmtpProtoConf* config;
#ifndef UNIT_TEST
private:
#endif
#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,
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;
SMTPCmdConfig* cmd_config = nullptr;
SMTPSearch* cmd_search = nullptr;
snort::SearchTool* cmd_search_mpse = nullptr;
+
+ void show() const;
};
struct SmtpStats
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);
else if ( v.is("xlink2state") )
{
- config->xlink2state = (XLINK2STATE)v.get_uint8();
+ config->xlink2state = (SMTPXlinkState)v.get_uint8();
Active::set_enabled();
}
return true;
}
-SMTP_PROTO_CONF* SmtpModule::get_data()
+SmtpProtoConf* SmtpModule::get_data()
{
- SMTP_PROTO_CONF* tmp = config;
+ SmtpProtoConf* tmp = config;
config = nullptr;
return tmp;
}
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;
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
void add_commands(snort::Value&, uint32_t flags);
private:
- SMTP_PROTO_CONF* config;
+ SmtpProtoConf* config;
std::vector<SmtpCmd*> cmds;
std::string names;
int number;
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;
}
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);
#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;
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;
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=<SOME DATA>
-
- 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
- <SOME DATA> 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;
#include "smtp.h"
-int ParseXLink2State(SMTP_PROTO_CONF*, snort::Packet*, SMTPData*, const uint8_t*);
+int ParseXLink2State(SmtpProtoConf*, snort::Packet*, SMTPData*, const uint8_t*);
#endif