]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
update mime paf
authorhuica <huica@cisco.com>
Fri, 17 Jul 2015 20:04:20 +0000 (16:04 -0400)
committerhuica <huica@cisco.com>
Fri, 17 Jul 2015 20:04:20 +0000 (16:04 -0400)
src/file_api/file_api.h
src/file_api/file_mime_paf.cc [new file with mode: 0644]
src/file_api/file_mime_paf.h [new file with mode: 0644]

index a2840d1d7be95945a75eac6ce0c3279eb95ba966..41355fa286fc88f5bd0817c9eeaff124760f55e6 100644 (file)
@@ -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 <sys/types.h>
 
@@ -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 (file)
index 0000000..b87b631
--- /dev/null
@@ -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 <huica@cisco.com>
+**
+**  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 (file)
index 0000000..01a7c3b
--- /dev/null
@@ -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 <huica@cisco.com>
+
+#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 <pcre.h>
+#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
+