📄 snort_smtp.c
字号:
/* * snort_smtp.c * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Copyright (C) 2005 Sourcefire Inc. * * Author: Andy Mullican * * Description: * * This file handles SMTP protocol checking and normalization. * * Entry point functions: * * SnortSMTP() * SMTP_Init() * SMTP_Free() * * */#include <sys/types.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "sf_snort_packet.h"#include "stream_api.h"#include "debug.h"#include "snort_smtp.h"#include "smtp_util.h"#include "smtp_log.h"#include "smtp_xlink2state.h"#include "smtp_normalize.h"#include "profiler.h"#ifdef PERF_PROFILINGextern PreprocStats smtpDetectPerfStats;extern int smtpDetectCalled;#endif/* Function callbacks */int SMTP_CmdStrFound(void * id, int index, void *data);int SMTP_RespStrFound(void * id, int index, void *data);int SMTP_DataStrFound(void * id, int index, void *data);/* Private functions */static void SMTP_Setup(SFSnortPacket *p);static void SMTP_ResetState(SMTP *x);static void SMTP_SessionFree(void *);static int IsServer(unsigned short port);static void GetPacketDirection(SFSnortPacket *p);static void SMTP_ProcessClientPacket(SFSnortPacket *p);static int SMTP_ProcessServerPacket(SFSnortPacket *p);static void SMTP_DataInit(SMTP *smtp);static void SMTP_DisableDetect(SFSnortPacket *p);#define CMD_SEARCH 0#define RESP_SEARCH 1#define DATA_SEARCH 2#define NUM_SEARCHES 3/* * Instantiate global preprocessor structure */SMTP *_smtp = NULL;SMTP smtp_default;t_bm bm;/* List of commands to alert on */extern SMTP_CONFIG _smtp_config;extern char _smtp_event[SMTP_EVENT_MAX][256];SMTP_token _smtp_resp[] ={ {"354", 0, RESP_354, 0, 0, 0,}, /* Data response */ {"250", 0, RESP_250, 0, 0, 0,}, /* OK */ {"421:", 0, RESP_421, 0, 0, 0,}, /* Service not available */ {NULL, 0, 0, 0, 0, 0}};static SMTP_token _smtp_data[] ={ {"BOUNDARY", 0, DATA_BOUNDARY, 0, 0, 0,}, {".\n", 0, DATA_BODY_END, 0, 0, 0,}, {".\r\n", 0, DATA_BODY_END, 0, 0, 0,}, {"\n\n", 0, DATA_HEADER_END, 0, 0, 0,}, {"\r\n\r\n", 0, DATA_HEADER_END, 0, 0, 0,}, {NULL, 0, 0, 0, 0, 0}};/* * Initialize SMTP preprocessor * * @param none * * @return none */void SMTP_Init(void){ int i = 0; /* Set up commands we will watch for */ _dpd.searchAPI->search_init(NUM_SEARCHES); for ( i = 0; _smtp_config.cmd[i].name != NULL; i++ ) { /* Save length of this command for future use */ _smtp_config.cmd[i].name_len = strlen(_smtp_config.cmd[i].name); _dpd.searchAPI->search_add(CMD_SEARCH, _smtp_config.cmd[i].name, _smtp_config.cmd[i].name_len, i); } _dpd.searchAPI->search_prep(CMD_SEARCH); for ( i = 0; _smtp_resp[i].name != NULL; i++ ) { /* Save length of this response for future use */ _smtp_resp[i].name_len = strlen(_smtp_resp[i].name); _dpd.searchAPI->search_add(RESP_SEARCH, _smtp_resp[i].name, _smtp_resp[i].name_len, i); } _dpd.searchAPI->search_prep(RESP_SEARCH); make_boyer_moore(&bm, "boundary=", 9);}/* Set up data body searches, per session */static void SMTP_DataInit(SMTP *smtp){ int i; if ( !smtp ) { return; } if ( smtp->data_search ) { _dpd.searchAPI->search_instance_free(smtp->data_search); } smtp->data_search = _dpd.searchAPI->search_instance_new(); if ( !smtp->data_search ) { return; } /* Add search for end of data body */ for ( i = 0; _smtp_data[i].name != NULL; i++ ) { /* Save length of the data for future use */ if ( _smtp_data[i].id == DATA_BOUNDARY ) { /* If we have a boundary, add it; otherwise, ignore. */ if ( smtp && smtp->boundary_len > 0 ) { _smtp_data[i].name = smtp->boundary; _smtp_data[i].name_len = smtp->boundary_len; _dpd.searchAPI->search_instance_add(_smtp->data_search, _smtp_data[i].name, _smtp_data[i].name_len, i); } } else { _smtp_data[i].name_len = strlen(_smtp_data[i].name); _dpd.searchAPI->search_instance_add(smtp->data_search, _smtp_data[i].name, _smtp_data[i].name_len, i); } } _dpd.searchAPI->search_instance_prep(smtp->data_search);}/* * Reset SMTP session state * * @param none * * @return none */static void SMTP_ResetState(SMTP *smtp){ smtp->state = COMMAND; smtp->message_number = 0; smtp->pkt_direction = SMTP_PKT_FROM_UNKNOWN; smtp->got_data_cmd = 0; smtp->got_data_resp = 0; smtp->got_starttls = 0; smtp->got_server_tls = 0; smtp->last_byte = 0; smtp->cur_client_line_len = 0; smtp->cur_server_line_len = 0; smtp->last_byte_is_lf = 0; smtp->normalizing = 0 ; smtp->token_id = 0; smtp->token_iid = 0; smtp->token_index = 0; smtp->token_length = 0; smtp->xlink2state_gotfirstchunk = 0; smtp->xlink2state_alerted = 0; smtp->boundary_len = 0; SMTP_DataInit(smtp);}/* * Given a server configuration and a port number, we decide if the port is * in the SMTP server port list. * * @param port the port number to compare with the configuration * * @return integer * @retval 0 means that the port is not a server port * @retval !0 means that the port is a server port */static int IsServer(unsigned short port){ if( (_smtp_config.ports[port/8] & (1 << port%8)) ) { return 1; } return 0;}/* * Do first-packet setup * * @param p standard Packet structure * * @return none */static void SMTP_Setup(SFSnortPacket *p){ /* Get session pointer */ SMTP *smtp = NULL; if ( !p->stream_session_ptr ) { _smtp = &smtp_default; memset(_smtp, 0, sizeof(SMTP)); return; } smtp = _dpd.streamAPI->get_application_data(p->stream_session_ptr, PP_SMTP); if ( smtp == NULL ) { smtp = (SMTP *) malloc(sizeof(SMTP)); if ( smtp == NULL ) { _dpd.fatalMsg("%s(%d) => Failed to allocate for SMTP session data\n"); return; } else { _dpd.streamAPI->set_application_data(p->stream_session_ptr, PP_SMTP, smtp, &SMTP_SessionFree); } /* Initialize state for first packet */ memset(smtp, 0, sizeof(SMTP)); /* Set up searches for data portion of mail messages */ SMTP_DataInit(smtp); } _smtp = smtp;}/* * Determine packet direction * * @param p standard Packet structure * * @return none */static void GetPacketDirection(SFSnortPacket *p){ /* * We now set the packet direction */ if (_dpd.streamAPI->get_session_flags(p->stream_session_ptr) & SSNFLAG_MIDSTREAM) { /* We can't be sure what state we are in, in this case. */ SMTP_ResetState(_smtp); if ( IsServer(p->src_port) ) { if ( !IsServer(p->dst_port) ) { _smtp->pkt_direction = SMTP_PKT_FROM_SERVER; } else { _smtp->pkt_direction = SMTP_PKT_FROM_UNKNOWN; } } else if ( IsServer(p->dst_port) ) { _smtp->pkt_direction = SMTP_PKT_FROM_CLIENT; } } else if (p->flags & FLAG_FROM_SERVER) { _smtp->pkt_direction = SMTP_PKT_FROM_SERVER; } else if (p->flags & FLAG_FROM_CLIENT) { _smtp->pkt_direction = SMTP_PKT_FROM_CLIENT; } else { _smtp->pkt_direction = SMTP_PKT_FROM_UNKNOWN; }}/* * Free SMTP-specific related to this session * * @param v pointer to SMTP session structure * * @return none */static void SMTP_SessionFree(void * v){ SMTP *smtp = (SMTP *) v; if ( smtp ) { if ( smtp->data_search ) { _dpd.searchAPI->search_instance_free(smtp->data_search); } free(smtp); } return;}/* * Free anything that needs it before shutting down preprocessor * * @param none * * @return none */void SMTP_Free(void){ _dpd.searchAPI->search_free();}/* * Callback function for string search * * @param id id in array of search strings from _smtp_config.cmds * @param index index in array of search strings from _smtp_config.cmds * @param data buffer passed in to search function * * @return response * @retval 1 commands caller to stop searching */int SMTP_CmdStrFound(void *id, int index, void *data){ int iid = (int) id;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -