mirror of https://github.com/OISF/suricata
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			243 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
			
		
		
	
	
			243 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
/* Copyright (C) 2012 BAE Systems
 | 
						|
 * Copyright (C) 2021 Open Information Security Foundation
 | 
						|
 *
 | 
						|
 * You can copy, redistribute or modify this Program under the terms of
 | 
						|
 * the GNU General Public License version 2 as published by the Free
 | 
						|
 * Software Foundation.
 | 
						|
 *
 | 
						|
 * 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
 | 
						|
 * version 2 along with this program; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
 * 02110-1301, USA.
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * \file
 | 
						|
 *
 | 
						|
 * \author David Abarbanel <david.abarbanel@baesystems.com>
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef MIME_DECODE_H_
 | 
						|
#define MIME_DECODE_H_
 | 
						|
 | 
						|
#include "conf.h"
 | 
						|
#include "util-base64.h"
 | 
						|
#include "util-file.h"
 | 
						|
 | 
						|
/* Content Flags */
 | 
						|
#define CTNT_IS_MSG           1
 | 
						|
#define CTNT_IS_ENV           2
 | 
						|
#define CTNT_IS_ENCAP         4
 | 
						|
#define CTNT_IS_BODYPART      8
 | 
						|
#define CTNT_IS_MULTIPART    16
 | 
						|
#define CTNT_IS_ATTACHMENT   32
 | 
						|
#define CTNT_IS_BASE64       64
 | 
						|
#define CTNT_IS_QP          128
 | 
						|
#define CTNT_IS_TEXT        256
 | 
						|
#define CTNT_IS_HTML        512
 | 
						|
 | 
						|
/* URL Flags */
 | 
						|
#define URL_IS_IP4          1
 | 
						|
#define URL_IS_IP6          2
 | 
						|
#define URL_IS_EXE          4
 | 
						|
 | 
						|
/* Anomaly Flags */
 | 
						|
#define ANOM_INVALID_BASE64      1  /* invalid base64 chars */
 | 
						|
#define ANOM_INVALID_QP          2  /* invalid quoted-printable chars */
 | 
						|
#define ANOM_LONG_HEADER_NAME    4  /* header is abnormally long */
 | 
						|
#define ANOM_LONG_HEADER_VALUE   8  /* header value is abnormally long
 | 
						|
                                     * (includes multi-line) */
 | 
						|
#define ANOM_LONG_LINE          16  /* Lines that exceed 998 octets */
 | 
						|
#define ANOM_LONG_ENC_LINE      32  /* Lines that exceed 76 octets */
 | 
						|
#define ANOM_MALFORMED_MSG      64  /* Misc msg format errors found */
 | 
						|
#define ANOM_LONG_BOUNDARY     128  /* Boundary too long */
 | 
						|
#define ANOM_LONG_FILENAME     256  /* filename truncated */
 | 
						|
 | 
						|
/* Publicly exposed size constants */
 | 
						|
#define DATA_CHUNK_SIZE  3072  /* Should be divisible by 3 */
 | 
						|
 | 
						|
/* Mime Parser Constants */
 | 
						|
#define HEADER_READY    0x01
 | 
						|
#define HEADER_STARTED  0x02
 | 
						|
#define HEADER_DONE     0x03
 | 
						|
#define BODY_STARTED    0x04
 | 
						|
#define BODY_DONE       0x05
 | 
						|
#define BODY_END_BOUND  0x06
 | 
						|
#define PARSE_DONE      0x07
 | 
						|
#define PARSE_ERROR     0x08
 | 
						|
 | 
						|
/**
 | 
						|
 * \brief Mime Decoder Error Codes
 | 
						|
 */
 | 
						|
typedef enum MimeDecRetCode {
 | 
						|
    MIME_DEC_OK = 0,
 | 
						|
    MIME_DEC_MORE = 1,
 | 
						|
    MIME_DEC_ERR_DATA = -1,
 | 
						|
    MIME_DEC_ERR_MEM = -2,
 | 
						|
    MIME_DEC_ERR_PARSE = -3,
 | 
						|
    MIME_DEC_ERR_STATE = -4, /**< parser in error state */
 | 
						|
    MIME_DEC_ERR_OVERFLOW = -5,
 | 
						|
} MimeDecRetCode;
 | 
						|
 | 
						|
/**
 | 
						|
 * \brief Structure for containing configuration options
 | 
						|
 *
 | 
						|
 */
 | 
						|
typedef struct MimeDecConfig {
 | 
						|
    bool decode_base64;             /**< Decode base64 bodies */
 | 
						|
    bool decode_quoted_printable;   /**< Decode quoted-printable bodies */
 | 
						|
    bool extract_urls;              /**< Extract and store URLs in data structure */
 | 
						|
    ConfNode *extract_urls_schemes; /**< List of schemes of which to
 | 
						|
                                         extract urls  */
 | 
						|
    bool log_url_scheme;            /**< Log the scheme of extracted URLs */
 | 
						|
    bool body_md5;                  /**< Compute md5 sum of body */
 | 
						|
    uint32_t header_value_depth;  /**< Depth of which to store header values
 | 
						|
                                       (Default is 2000) */
 | 
						|
} MimeDecConfig;
 | 
						|
 | 
						|
/**
 | 
						|
 * \brief This represents a header field name and associated value
 | 
						|
 */
 | 
						|
typedef struct MimeDecField {
 | 
						|
    uint8_t *name;  /**< Name of the header field */
 | 
						|
    uint32_t name_len;  /**< Length of the name */
 | 
						|
    uint32_t value_len;  /**< Length of the value */
 | 
						|
    uint8_t *value;  /**< Value of the header field */
 | 
						|
    struct MimeDecField *next;  /**< Pointer to next field */
 | 
						|
} MimeDecField;
 | 
						|
 | 
						|
/**
 | 
						|
 * \brief This represents a URL value node in a linked list
 | 
						|
 *
 | 
						|
 * Since HTML can sometimes contain a high number of URLs, this
 | 
						|
 * structure only features the URL host name/IP or those that are
 | 
						|
 * pointing to an executable file (see url_flags to determine which).
 | 
						|
 */
 | 
						|
typedef struct MimeDecUrl {
 | 
						|
    uint8_t *url;  /**< String representation of full or partial URL (lowercase) */
 | 
						|
    uint32_t url_len;  /**< Length of the URL string */
 | 
						|
    uint32_t url_flags;  /**< Flags indicating type of URL */
 | 
						|
    struct MimeDecUrl *next;  /**< Pointer to next URL */
 | 
						|
} MimeDecUrl;
 | 
						|
 | 
						|
/**
 | 
						|
 * \brief This represents the MIME Entity (or also top level message) in a
 | 
						|
 * child-sibling tree
 | 
						|
 */
 | 
						|
typedef struct MimeDecEntity {
 | 
						|
    MimeDecField *field_list;  /**< Pointer to list of header fields */
 | 
						|
    MimeDecUrl *url_list;  /**< Pointer to list of URLs */
 | 
						|
    uint32_t header_flags; /**< Flags indicating header characteristics */
 | 
						|
    uint32_t ctnt_flags;  /**< Flags indicating type of content */
 | 
						|
    uint32_t anomaly_flags;  /**< Flags indicating an anomaly in the message */
 | 
						|
    uint32_t filename_len;  /**< Length of file attachment name */
 | 
						|
    uint8_t *filename;  /**< Name of file attachment */
 | 
						|
    uint8_t *ctnt_type;  /**< Quick access pointer to short-hand content type field */
 | 
						|
    uint32_t ctnt_type_len;  /**< Length of content type field value */
 | 
						|
    uint32_t msg_id_len;  /**< Quick access pointer to message Id */
 | 
						|
    uint8_t *msg_id;  /**< Quick access pointer to message Id */
 | 
						|
    struct MimeDecEntity *next;  /**< Pointer to list of sibling entities */
 | 
						|
    struct MimeDecEntity *child;  /**< Pointer to list of child entities */
 | 
						|
} MimeDecEntity;
 | 
						|
 | 
						|
/**
 | 
						|
 * \brief Structure contains boundary and entity for the current node (entity)
 | 
						|
 * in the stack
 | 
						|
 *
 | 
						|
 */
 | 
						|
typedef struct MimeDecStackNode {
 | 
						|
    MimeDecEntity *data;  /**< Pointer to the entity data structure */
 | 
						|
    uint8_t *bdef;  /**< Copy of boundary definition for child entity */
 | 
						|
    uint16_t bdef_len;  /**< Boundary length for child entity */
 | 
						|
    bool is_encap;      /**< Flag indicating entity is encapsulated in message */
 | 
						|
    struct MimeDecStackNode *next;  /**< Pointer to next item on the stack */
 | 
						|
} MimeDecStackNode;
 | 
						|
 | 
						|
/**
 | 
						|
 * \brief Structure holds the top of the stack along with some free reusable nodes
 | 
						|
 *
 | 
						|
 */
 | 
						|
typedef struct MimeDecStack {
 | 
						|
    MimeDecStackNode *top;  /**< Pointer to the top of the stack */
 | 
						|
    MimeDecStackNode *free_nodes;  /**< Pointer to the list of free nodes */
 | 
						|
    uint32_t free_nodes_cnt;  /**< Count of free nodes in the list */
 | 
						|
} MimeDecStack;
 | 
						|
 | 
						|
/**
 | 
						|
 * \brief Structure contains a list of value and lengths for robust data processing
 | 
						|
 *
 | 
						|
 */
 | 
						|
typedef struct DataValue {
 | 
						|
    uint8_t *value;  /**< Copy of data value */
 | 
						|
    uint32_t value_len;  /**< Length of data value */
 | 
						|
    struct DataValue *next;  /**< Pointer to next value in the list */
 | 
						|
} DataValue;
 | 
						|
 | 
						|
/**
 | 
						|
 * \brief Structure contains the current state of the MIME parser
 | 
						|
 *
 | 
						|
 */
 | 
						|
typedef struct MimeDecParseState {
 | 
						|
    MimeDecEntity *msg;  /**< Pointer to the top-level message entity */
 | 
						|
    MimeDecStack *stack;  /**< Pointer to the top of the entity stack */
 | 
						|
    uint8_t *hname;  /**< Copy of the last known header name */
 | 
						|
    uint32_t hlen;  /**< Length of the last known header name */
 | 
						|
    uint32_t hvlen; /**< Total length of value list */
 | 
						|
    DataValue *hvalue;  /**< Pointer to the incomplete header value list */
 | 
						|
    uint8_t bvremain[B64_BLOCK];  /**< Remainder from base64-decoded line */
 | 
						|
    uint8_t bvr_len;  /**< Length of remainder from base64-decoded line */
 | 
						|
    uint8_t data_chunk[DATA_CHUNK_SIZE];  /**< Buffer holding data chunk */
 | 
						|
    SCMd5 *md5_ctx;
 | 
						|
    uint8_t md5[SC_MD5_LEN];
 | 
						|
    bool has_md5;
 | 
						|
    uint8_t state_flag;  /**<  Flag representing current state of parser */
 | 
						|
    uint32_t data_chunk_len;  /**< Length of data chunk */
 | 
						|
    int found_child;  /**< Flag indicating a child entity was found */
 | 
						|
    int body_begin;  /**< Currently at beginning of body */
 | 
						|
    int body_end;  /**< Currently at end of body */
 | 
						|
    uint8_t current_line_delimiter_len; /**< Length of line delimiter */
 | 
						|
    void *data;  /**< Pointer to data specific to the caller */
 | 
						|
    int (*DataChunkProcessorFunc) (const uint8_t *chunk, uint32_t len,
 | 
						|
            struct MimeDecParseState *state);  /**< Data chunk processing function callback */
 | 
						|
} MimeDecParseState;
 | 
						|
 | 
						|
/* Config functions */
 | 
						|
void MimeDecSetConfig(MimeDecConfig *config);
 | 
						|
MimeDecConfig * MimeDecGetConfig(void);
 | 
						|
 | 
						|
/* Memory functions */
 | 
						|
void MimeDecFreeEntity(MimeDecEntity *entity);
 | 
						|
void MimeDecFreeField(MimeDecField *field);
 | 
						|
void MimeDecFreeUrl(MimeDecUrl *url);
 | 
						|
 | 
						|
/* List functions */
 | 
						|
MimeDecField * MimeDecAddField(MimeDecEntity *entity);
 | 
						|
MimeDecField * MimeDecFindField(const MimeDecEntity *entity, const char *name);
 | 
						|
int MimeDecFindFieldsForEach(const MimeDecEntity *entity, const char *name, int (*DataCallback)(const uint8_t *val, const size_t, void *data), void *data);
 | 
						|
MimeDecEntity * MimeDecAddEntity(MimeDecEntity *parent);
 | 
						|
 | 
						|
/* Helper functions */
 | 
						|
//MimeDecField * MimeDecFillField(MimeDecEntity *entity, const char *name,
 | 
						|
//        uint32_t nlen, const char *value, uint32_t vlen, int copy_name_value);
 | 
						|
 | 
						|
/* Parser functions */
 | 
						|
MimeDecParseState * MimeDecInitParser(void *data, int (*dcpfunc)(const uint8_t *chunk,
 | 
						|
        uint32_t len, MimeDecParseState *state));
 | 
						|
void MimeDecDeInitParser(MimeDecParseState *state);
 | 
						|
int MimeDecParseComplete(MimeDecParseState *state);
 | 
						|
int MimeDecParseLine(const uint8_t *line, const uint32_t len, const uint8_t delim_len, MimeDecParseState *state);
 | 
						|
MimeDecEntity * MimeDecParseFullMsg(const uint8_t *buf, uint32_t blen, void *data,
 | 
						|
        int (*DataChunkProcessorFunc)(const uint8_t *chunk, uint32_t len, MimeDecParseState *state));
 | 
						|
const char *MimeDecParseStateGetStatus(MimeDecParseState *state);
 | 
						|
 | 
						|
/* Test functions */
 | 
						|
void MimeDecRegisterTests(void);
 | 
						|
 | 
						|
#endif
 |