From: huica Date: Fri, 17 Jul 2015 20:04:20 +0000 (-0400) Subject: update mime paf X-Git-Tag: 3.0.0-233~828^2~56 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2c47b91852eb686fea0cb889dc05175dbd493bf9;p=thirdparty%2Fsnort3.git update mime paf --- diff --git a/src/file_api/file_api.h b/src/file_api/file_api.h index a2840d1d7..41355fa28 100644 --- a/src/file_api/file_api.h +++ b/src/file_api/file_api.h @@ -25,7 +25,6 @@ // File API provides all the convenient functions that are used by inspectors. // Currently, it provides three sets of APIs: file processing, MIME processing, // and configurations. -// FIXIT-L file api will be replaced by file class and mime class soon #include @@ -113,7 +112,6 @@ struct FileCaptureInfo; struct MailLogState; struct MailLogConfig; struct MimeState; -struct MimeDataPafInfo; #define FILE_API_VERSION 4 @@ -255,7 +253,7 @@ typedef struct _file_api * 1: upload * 0: download */ - Get_file_direction_func get_file_direction; + Get_file_direction_func get_file_direction;FileCaptureInfo /* Get file signature sha256 * diff --git a/src/file_api/file_mime_paf.cc b/src/file_api/file_mime_paf.cc new file mode 100644 index 000000000..b87b63167 --- /dev/null +++ b/src/file_api/file_mime_paf.cc @@ -0,0 +1,249 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved. +// Copyright (C) 2012-2013 Sourcefire, Inc. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- +/* +** Author(s): Hui Cao +** +** NOTES +** 9.25.2012 - Initial Source Code. Hui Cao +*/ + +#include "file_mime_paf.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "snort_types.h" +#include "file_api.h" +#include "file_mime_config.h" + +static const char* boundary_str = "boundary="; + +/* + * 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; +} + diff --git a/src/file_api/file_mime_paf.h b/src/file_api/file_mime_paf.h new file mode 100644 index 000000000..01a7c3bf2 --- /dev/null +++ b/src/file_api/file_mime_paf.h @@ -0,0 +1,95 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved. +// Copyright (C) 2012-2013 Sourcefire, Inc. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- + +// file_mime_process.h author Hui Cao + +#ifndef FILE_MIME_PAF_H +#define FILE_MIME_PAF_H + +// Provides list of MIME processing functions. Encoded file data will be decoded +// and file name will be extracted from MIME header + +#include +#include "file_api/file_api.h" +#include "file_api/file_mime_config.h" +#include "utils/sf_email_attach_decode.h" + + +/* 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; +}; + + +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; +} + + +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 +