file_mempool.h
file_mime_config.cc
file_mime_config.h
+ file_mime_paf.h
+ file_mime_paf.cc
file_mime_process.h
file_mime_process.cc
file_resume_block.cc
file_api.h \
file_service.cc file_service.h \
file_service_config.cc file_service_config.h \
+file_mime_paf.h file_mime_paf.cc \
file_mime_process.h file_mime_process.cc \
file_resume_block.cc file_resume_block.h \
file_mime_config.cc file_mime_config.h \
struct FileContext;
struct FileCaptureInfo;
-struct MAIL_LogState;
+struct MailLogState;
struct MailLogConfig;
struct MimeState;
struct MimeDataPafInfo;
typedef void (*Enable_file_capture_func)();
typedef void (*Set_file_action_log_func)();
-typedef int (*Set_log_buffers_func)(MAIL_LogState** log_state, MailLogConfig* conf);
+typedef int (*Set_log_buffers_func)(MailLogState** log_state, MailLogConfig* conf);
typedef int (*File_resume_block_add_file_func)(Packet* pkt, uint32_t file_sig,
uint32_t timeout, File_Verdict verdict, uint32_t file_type_id, uint8_t* signature);
typedef File_Verdict (*File_resume_block_check_func)(Packet* pkt, uint32_t file_sig);
typedef void (*Render_block_verdict_func)(void* ctx, Packet* p);
typedef bool (*Is_file_service_enabled)();
-typedef bool (*Check_paf_abort_func)(Flow* ssn);
typedef FilePosition (*GetFilePosition)(Packet* pkt);
-typedef void (*Reset_mime_paf_state_func)(MimeDataPafInfo* data_info);
-/* Process data boundary and flush each file based on boundary*/
-typedef bool (*Process_mime_paf_data_func)(MimeDataPafInfo* data_info, uint8_t data);
-typedef bool (*Check_data_end_func)(void* end_state, uint8_t data);
typedef uint32_t (*Get_file_type_id)(Flow*);
typedef uint32_t (*Get_new_file_instance)(Flow*);
Set_log_buffers_func set_log_buffers;
Process_mime_data_func process_mime_data;
Free_mime_session_func free_mime_session;
- Finalize_mime_position_func finalize_mime_position;
- Reset_mime_paf_state_func reset_mime_paf_state;
- Process_mime_paf_data_func process_mime_paf_data;
- Check_data_end_func check_data_end;
- Check_paf_abort_func check_paf_abort;
/*--------------Other helper functions-------------*/
File_resume_block_add_file_func file_resume_block_add_file;
#include "file_mime_config.h"
-#include <sys/types.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdio.h>
-
#include "snort_types.h"
#include "file_api.h"
#include "file_mime_process.h"
-#include "sf_email_attach_decode.h"
-#include "util.h"
-#include "parser.h"
void DecodeConfig::update_max_depth(int64_t depth)
{
void DecodeConfig::set_file_depth(int64_t file_depth)
{
- if ((!file_depth) || (file_depth > MAX_BUF))
+ if ((!file_depth) || (file_depth > MAX_DEPTH))
{
- max_depth = MAX_BUF;
+ max_depth = MAX_DEPTH;
}
else if (file_depth > max_depth)
{
int64_t get_file_depth();
bool is_decoding_enabled();
void sync_all_depths();
+
private:
bool ignore_data = false;
int max_mime_mem = DEFAULT_MAX_MIME_MEM;
}
/* accumulate MIME attachment filenames. The filenames are appended by commas */
-int log_file_name(const uint8_t* start, int length, FILE_LogState* log_state, bool* disp_cont)
+int log_file_name(const uint8_t* start, int length, FileLogState* log_state, bool* disp_cont)
{
uint8_t* alt_buf;
int alt_size;
}
-static void set_file_name_from_log(FILE_LogState* log_state, void* pv)
+static void set_file_name_from_log(FileLogState* log_state, void* pv)
{
Flow* ssn = (Flow*)pv; // FIXIT-M eliminate need for cast
* -1: fail
*
*/
-int set_log_buffers(MAIL_LogState** log_state, MailLogConfig* conf)
+int set_log_buffers(MailLogState** log_state, MailLogConfig* conf)
{
if ((*log_state == NULL)
&& (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;
- *log_state = (MAIL_LogState*)SnortAlloc(sizeof(MAIL_LogState) + bufsz);
+ *log_state = (MailLogState*)SnortAlloc(sizeof(MailLogState) + bufsz);
if ((*log_state) != NULL)
{
- uint8_t* buf = ((uint8_t*)(*log_state)) + sizeof(MAIL_LogState);
+ uint8_t* buf = ((uint8_t*)(*log_state)) + sizeof(MailLogState);
(*log_state)->log_depth = conf->email_hdrs_log_depth;
(*log_state)->recipients = buf;
(*log_state)->rcpts_logged = 0;
free_mime_session(*mime_ssn);
free(mime_ssn);
}
-
-/*
- * When the file ends (a MIME boundary detected), position are updated
- */
-void finalize_mime_position(Flow* flow, void* decode_state, FilePosition* position)
-{
- /* check to see if there are file data in the session or
- * new decoding data waiting for processing */
- if ( file_api->get_file_processed_size(flow) ||
- (decode_state && ((Email_DecodeState*)decode_state)->decoded_bytes) )
- finalFilePosition(position);
-}
-
-/* Save the bounday string into paf state*/
-static inline bool store_boundary(MimeDataPafInfo* data_info, uint8_t val)
-{
- if (!data_info->boundary_search)
- {
- if ((val == '.') || isspace (val))
- data_info->boundary_search = (char*)&boundary_str[0];
- return 0;
- }
-
- if (*(data_info->boundary_search) == '=')
- {
- /*Skip spaces for the end of boundary*/
- if (val == '=')
- data_info->boundary_search++;
- else if (!isspace(val))
- data_info->boundary_search = NULL;
- }
- else if (*(data_info->boundary_search) == '\0')
- {
- /*get boundary string*/
- if (isspace(val) || (val == '"'))
- {
- if (!data_info->boundary_len)
- return 0;
- else
- {
- /*Found boundary string*/
- data_info->boundary[data_info->boundary_len] = '\0';
- return 1;
- }
- }
-
- if (data_info->boundary_len < (int)sizeof(data_info->boundary))
- {
- data_info->boundary[data_info->boundary_len++] = val;
- }
- else
- {
- /*Found boundary string*/
- data_info->boundary[data_info->boundary_len -1] = '\0';
- return 1;
- }
- }
- else if ((val == *(data_info->boundary_search))
- || (val == *(data_info->boundary_search) - 'a' + 'A'))
- {
- data_info->boundary_search++;
- }
- else
- {
- if ((val == '.') || isspace (val))
- data_info->boundary_search = (char*)&boundary_str[0];
- else
- data_info->boundary_search = NULL;
- }
-
- return 0;
-}
-
-/* check the bounday string in the mail body*/
-static inline bool check_boundary(MimeDataPafInfo* data_info, uint8_t data)
-{
- /* Search for boundary signature "--"*/
- switch (data_info->boundary_state)
- {
- case MIME_PAF_BOUNDARY_UNKNOWN:
- if (data == '\n')
- data_info->boundary_state = MIME_PAF_BOUNDARY_LF;
- break;
-
- case MIME_PAF_BOUNDARY_LF:
- if (data == '-')
- data_info->boundary_state = MIME_PAF_BOUNDARY_HYPEN_FIRST;
- else if (data != '\n')
- data_info->boundary_state = MIME_PAF_BOUNDARY_UNKNOWN;
- break;
-
- case MIME_PAF_BOUNDARY_HYPEN_FIRST:
- if (data == '-')
- {
- data_info->boundary_state = MIME_PAF_BOUNDARY_HYPEN_SECOND;
- data_info->boundary_search = data_info->boundary;
- }
- else if (data == '\n')
- data_info->boundary_state = MIME_PAF_BOUNDARY_LF;
- else
- data_info->boundary_state = MIME_PAF_BOUNDARY_UNKNOWN;
- break;
-
- case MIME_PAF_BOUNDARY_HYPEN_SECOND:
- /* Compare with boundary string stored */
- if (*(data_info->boundary_search) == '\0')
- {
- if (data == '\n')
- {
- /*reset boundary search etc.*/
- data_info->boundary_state = MIME_PAF_BOUNDARY_UNKNOWN;
- return 1;
- }
- else if ((data != '\r') && ((data != '-')))
- data_info->boundary_state = MIME_PAF_BOUNDARY_UNKNOWN;
- }
- else if (*(data_info->boundary_search) == data)
- data_info->boundary_search++;
- else
- data_info->boundary_state = MIME_PAF_BOUNDARY_UNKNOWN;
-
- break;
- }
-
- return 0;
-}
-
-void reset_mime_paf_state(MimeDataPafInfo* data_info)
-{
- data_info->boundary_search = NULL;
- data_info->boundary_len = 0;
- data_info->boundary[0] = '\0';
- data_info->boundary_state = MIME_PAF_BOUNDARY_UNKNOWN;
- data_info->data_state = MIME_PAF_FINDING_BOUNDARY_STATE;
-}
-
-/* Process data boundary and flush each file based on boundary*/
-bool process_mime_paf_data(MimeDataPafInfo* data_info, uint8_t data)
-{
- switch (data_info->data_state)
- {
- case MIME_PAF_FINDING_BOUNDARY_STATE:
- /* Search for boundary
- Store bounday string in PAF state*/
- if (store_boundary(data_info, data))
- {
- /* End of boundary, move to MIME_PAF_FOUND_BOUNDARY_STATE*/
- DEBUG_WRAP(DebugMessage(DEBUG_FILE, "Create boudary string: %s\n",
- data_info->boundary); );
- data_info->data_state = MIME_PAF_FOUND_BOUNDARY_STATE;
- }
-
- break;
- case MIME_PAF_FOUND_BOUNDARY_STATE:
- if (check_boundary(data_info, data))
- {
- /* End of boundary, move to MIME_PAF_FOUND_BOUNDARY_STATE*/
- DEBUG_WRAP(DebugMessage(DEBUG_FILE, "Found Boudary string: %s\n",
- data_info->boundary); );
- return 1;
- }
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-bool check_data_end(void* data_end_state, uint8_t val)
-{
- DataEndState state = *((DataEndState*)data_end_state);
-
- switch (state)
- {
- case PAF_DATA_END_UNKNOWN:
- if (val == '\n')
- {
- state = PAF_DATA_END_FIRST_LF;
- }
- break;
-
- case PAF_DATA_END_FIRST_LF:
- if (val == '.')
- {
- state = PAF_DATA_END_DOT;
- }
- else if ((val != '\r') && (val != '\n'))
- {
- state = PAF_DATA_END_UNKNOWN;
- }
- break;
- case PAF_DATA_END_DOT:
- if (val == '\n')
- {
- *((DataEndState*)data_end_state) = PAF_DATA_END_UNKNOWN;
- return 1;
- }
- else if (val != '\r')
- {
- state = PAF_DATA_END_UNKNOWN;
- }
- break;
-
- default:
- state = PAF_DATA_END_UNKNOWN;
- break;
- }
-
- *((DataEndState*)data_end_state) = state;
- return 0;
-}
-
// Provides list of MIME processing functions. Encoded file data will be decoded
// and file name will be extracted from MIME header
-// FIXIT-L This will be refactored soon
#include <pcre.h>
#include "file_api/file_api.h"
#include "file_api/file_mime_config.h"
+#include "file_api/file_mime_paf.h"
#include "utils/sf_email_attach_decode.h"
#define MAX_FILE 1024
/* Maximum length of header chars before colon, based on Exim 4.32 exploit */
#define MAX_HEADER_NAME_LEN 64
-struct FILE_LogState
+struct FileLogState
{
uint8_t* filenames;
uint16_t file_logged;
uint16_t file_current;
};
-struct MAIL_LogState
+struct MailLogState
{
unsigned char* emailHdrs;
uint32_t log_depth;
uint16_t rcpts_logged;
uint8_t* senders;
uint16_t snds_logged;
- FILE_LogState file_log;
+ FileLogState file_log;
};
struct MailLogConfig
{
- uint32_t memcap = DEFAULT_MIME_MEMCAP;;
+ uint32_t memcap = DEFAULT_MIME_MEMCAP;
char log_mailfrom = 0;
char log_rcptto = 0;
char log_filename = 0;
uint32_t email_hdrs_log_depth = 0;
};
-/* State tracker for data */
-enum MimeDataState
-{
- MIME_PAF_FINDING_BOUNDARY_STATE,
- MIME_PAF_FOUND_BOUNDARY_STATE
-};
-
-/* State tracker for Boundary Signature */
-enum MimeBoundaryState
-{
- MIME_PAF_BOUNDARY_UNKNOWN = 0, /* UNKNOWN */
- MIME_PAF_BOUNDARY_LF, /* '\n' */
- MIME_PAF_BOUNDARY_HYPEN_FIRST, /* First '-' */
- MIME_PAF_BOUNDARY_HYPEN_SECOND /* Second '-' */
-};
-
-/* State tracker for end of pop/smtp command */
-enum DataEndState
-{
- PAF_DATA_END_UNKNOWN, /* Start or UNKNOWN */
- PAF_DATA_END_FIRST_CR, /* First '\r' */
- PAF_DATA_END_FIRST_LF, /* First '\n' */
- PAF_DATA_END_DOT, /* '.' */
- PAF_DATA_END_SECOND_CR, /* Second '\r' */
- PAF_DATA_END_SECOND_LF /* Second '\n' */
-};
-
-#define MAX_MIME_BOUNDARY_LEN 70 /* Max length of boundary string, defined in RFC 2046 */
-
-struct MimeDataPafInfo
-{
- MimeDataState data_state;
- char boundary[ MAX_MIME_BOUNDARY_LEN + 1]; /* MIME boundary string + '\0' */
- int boundary_len;
- char* boundary_search;
- MimeBoundaryState boundary_state;
-};
-
typedef struct _MimePcre
{
pcre* re;
Is_end_of_data_func is_end_of_data;
};
-
struct MimeState
{
int data_state;
MimeDataPafInfo mime_boundary;
DecodeConfig* decode_conf;
MailLogConfig* log_config;
- MAIL_LogState* log_state;
+ MailLogState* log_state;
void* config;
MimeMethods* methods;
};
-static inline bool scanning_boundary(MimeDataPafInfo* mime_info, uint32_t boundary_start,
- uint32_t* fp)
-{
- if (boundary_start &&
- mime_info->data_state == MIME_PAF_FOUND_BOUNDARY_STATE &&
- mime_info->boundary_state != MIME_PAF_BOUNDARY_UNKNOWN)
- {
- *fp = boundary_start;
- return true;
- }
-
- return false;
-}
-
-
-int log_file_name(const uint8_t* start, int length, FILE_LogState* log_state, bool* disp_cont);
-int set_log_buffers(MAIL_LogState** log_state, MailLogConfig* conf);
+int log_file_name(const uint8_t* start, int length, FileLogState* log_state, bool* disp_cont);
+int set_log_buffers(MailLogState** log_state, MailLogConfig* conf);
void init_mime(void);
void free_mime(void);
const uint8_t* process_mime_data(Flow *flow, const uint8_t *start, const uint8_t *end,
MimeState *mime_ssn, bool upload, FilePosition position);
void free_mime_session(MimeState*);
void free_mime_session(MimeState&);
-void finalize_mime_position(Flow* flow, void* decode_state, FilePosition* position);
-void reset_mime_paf_state(MimeDataPafInfo *data_info);
-/* Process data boundary and flush each file based on boundary*/
-bool process_mime_paf_data(MimeDataPafInfo *data_info, uint8_t val);
-bool check_data_end(void *end_state, uint8_t val);
-
#endif
fileAPI.file_resume_block_check = &file_resume_block_check;
fileAPI.process_mime_data = &process_mime_data;
fileAPI.free_mime_session = &free_mime_session;
- fileAPI.finalize_mime_position = &finalize_mime_position;
fileAPI.get_file_type_id = &get_file_type_id;
fileAPI.get_new_file_instance = &get_new_file_instance;
fileAPI.get_current_file_context = &get_current_file_context;
fileAPI.get_main_file_context = &get_main_file_context;
fileAPI.get_file_position = &get_file_position;
- fileAPI.reset_mime_paf_state = &reset_mime_paf_state;
- fileAPI.process_mime_paf_data = &process_mime_paf_data;
- fileAPI.check_data_end = check_data_end;
+
file_api = &fileAPI;
init_mime();
static inline void reset_data_states(ImapPafData* pfdata)
{
// reset MIME info
- file_api->reset_mime_paf_state(&(pfdata->mime_info));
+ reset_mime_paf_state(&(pfdata->mime_info));
// reset server info
pfdata->imap_state = IMAP_PAF_CMD_IDENTIFIER;
}
// check for mime flush point
- if (file_api->process_mime_paf_data(&(pfdata->mime_info), ch))
+ if (process_mime_paf_data(&(pfdata->mime_info), ch))
{
DEBUG_WRAP(DebugMessage(DEBUG_IMAP, "IMAP PAF: Mime Boundary found."
" Flushing data!\n"); );
#include "main/snort_types.h"
#include "stream/stream_api.h"
#include "stream/stream_splitter.h"
-#include "file_api/file_mime_process.h"
+#include "file_api/file_mime_paf.h"
struct ImapDataInfo
{
static inline void reset_data_states(PopPafData* pfdata)
{
// reset MIME info
- file_api->reset_mime_paf_state(&(pfdata->data_info));
+ reset_mime_paf_state(&(pfdata->data_info));
// reset general pop fields
pfdata->cmd_continued = false;
{
// FIXIT: This will currently flush on MIME boundary, and one line later at end of PDU
- if (file_api->check_data_end(&(pfdata->end_state), ch))
+ if (check_data_end(&(pfdata->end_state), ch))
{
DEBUG_WRAP(DebugMessage(DEBUG_POP, "End of Multi-line response found\n"); );
pfdata->end_of_data = true;
// if this is a data command, search for MIME ending
if (mime_data)
{
- if (file_api->process_mime_paf_data(&(pfdata->data_info), ch))
+ if (process_mime_paf_data(&(pfdata->data_info), ch))
{
DEBUG_WRAP(DebugMessage(DEBUG_POP, "Mime Boundary found. Flushing data!\n"); );
pfdata->cmd_continued = true;
#include "main/snort_types.h"
#include "stream/stream_api.h"
#include "stream/stream_splitter.h"
-#include "file_api/file_mime_process.h"
+#include "file_api/file_mime_paf.h"
// Structure used to record expected server termination sequence
enum PopExpectedResp
static inline void reset_data_states(SmtpPafData* pfdata)
{
// reset MIME info
- file_api->reset_mime_paf_state(&(pfdata->data_info));
+ reset_mime_paf_state(&(pfdata->data_info));
pfdata->length = 0;
}
* * Process data boundary and flush each file based on boundary*/
static inline bool process_data(SmtpPafData* pfdata, uint8_t data)
{
- if (flush_based_length(pfdata)|| file_api->check_data_end(&(pfdata->data_end_state), data))
+ if (flush_based_length(pfdata)|| check_data_end(&(pfdata->data_end_state), data))
{
DEBUG_WRAP(DebugMessage(DEBUG_SMTP, "End of data\n"); );
/*Clean up states*/
return true;
}
- return file_api->process_mime_paf_data(&(pfdata->data_info), data);
+ return process_mime_paf_data(&(pfdata->data_info), data);
}
/* Process commands/data from client
#include "main/snort_types.h"
#include "stream/stream_api.h"
#include "stream/stream_splitter.h"
-#include "file_api/file_mime_process.h"
+#include "file_api/file_mime_paf.h"
// State tracker for SMTP PAF
enum SmtpPafState
}
/* Accumulate EOL seperated headers, one or more at a time */
-int SMTP_CopyEmailHdrs(const uint8_t* start, int length, MAIL_LogState* log_state)
+int SMTP_CopyEmailHdrs(const uint8_t* start, int length, MailLogState* log_state)
{
int log_avail = 0;
uint8_t* log_buf;
/* Accumulate email addresses from RCPT TO and/or MAIL FROM commands. Email addresses are separated
by comma */
-int SMTP_CopyEmailID(const uint8_t* start, int length, int command_type, MAIL_LogState* log_state)
+int SMTP_CopyEmailID(const uint8_t* start, int length, int command_type, MailLogState* log_state)
{
uint8_t* alt_buf;
int alt_size;
#include "protocols/packet.h"
void SMTP_GetEOL(const uint8_t*, const uint8_t*, const uint8_t**, const uint8_t**);
-int SMTP_CopyEmailHdrs(const uint8_t*, int, MAIL_LogState* log_state);
-int SMTP_CopyEmailID(const uint8_t*, int, int, MAIL_LogState* log_state);
+int SMTP_CopyEmailHdrs(const uint8_t*, int, MailLogState* log_state);
+int SMTP_CopyEmailID(const uint8_t*, int, int, MailLogState* log_state);
void SMTP_LogFuncs(SMTP_PROTO_CONF* config, Packet* p, MimeState* mime_ssn);
void SMTP_ResetAltBuffer(void);