From: Russ Combs Date: Wed, 27 May 2015 19:08:32 +0000 (-0400) Subject: Squashed commit of the following: X-Git-Tag: 3.0.0-233~969 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=55dcf17fc4e66afe3bbf7b237506a9d1b4262a6a;p=thirdparty%2Fsnort3.git Squashed commit of the following: commit 4eac8870ac2220666d8da50dd3531143bebdf0f9 Author: Russ Combs Date: Wed May 27 15:06:52 2015 -0400 -- stream_tcp reassembles payload only -- remove obsolete REG_TEST logging -- change max_dsize to const -- refactor encode_format*() -- rewrite alert_csv with default suitable for reg tests and debugging -- dump 20 hex bytes per line instead of 16 -- fix final_flush packet -- add raw mode hext DAQ and logger; fix dns inspector typo for tcp checks -- document raw hext mode -- cleanup flush flags vs dir -- add alert_csv.separator, delete alert_test -- tweak log config; rename daq/log user to hext -- cleanup logging -- stream_tcp refactoring and cleanup --- diff --git a/doc/daq.txt b/doc/daq.txt index 7e40f81cc..e0a405b01 100644 --- a/doc/daq.txt +++ b/doc/daq.txt @@ -513,11 +513,14 @@ with these Snort options: * This module is primarily for development and test. -=== User Module +=== Hext Module -The user module generates packets suitable for processing with Snort's -stream_user from simple text input. The first character of the line -determines it's purpose: +The hext module generates packets suitable for processing by Snort from +hex/plain text. Raw packets include full headers and are processed +normally. Otherwise the packets contain only payload and are accompanied +with flow information (4-tuple) suitable for processing by stream_user. + +The first character of the line determines it's purpose: '$' command '#' comment @@ -557,8 +560,8 @@ Strings may contain the following escape sequences: \\ = 0x5C = \ Format your input carefully; there is minimal error checking and little -tolerance for arbitrary whitespace. You can use Snort's -L user option to -generate user input from a pcap. +tolerance for arbitrary whitespace. You can use Snort's -L hext option to +generate hext input from a pcap. * This module only supports ip4 traffic. @@ -567,3 +570,22 @@ generate user input from a pcap. * This module is primarily for development and test. +The hext DAQ also supports a raw mode which is activated by setting the +data link type. For example, you can input full ethernet packets with +--daq-var dlt=1 (Data link types are defined in the DAQ include +sfbpf_dlt.h.) Combine that with the hext logger in raw mode for a quick +(and dirty) way to edit pcaps. With --lua "log_hext = { raw = true }", the +hext logger will dump the full packet in a way that can be read by the hext +DAQ in raw mode. Here is an example: + + # 3 [96] + + x02 09 08 07 06 05 02 01 02 03 04 05 08 00 45 00 00 52 00 03 # ..............E..R.. + x00 00 40 06 5C 90 0A 01 02 03 0A 09 08 07 BD EC 00 50 00 00 # ..@.\............P.. + x00 02 00 00 00 02 50 10 20 00 8A E1 00 00 47 45 54 20 2F 74 # ......P. .....GET /t + x72 69 67 67 65 72 2F 31 20 48 54 54 50 2F 31 2E 31 0D 0A 48 # rigger/1 HTTP/1.1..H + x6F 73 74 3A 20 6C 6F 63 61 6C 68 6F 73 74 0D 0A # ost: localhost.. + +A comment indicating packet number and size precedes each packet dump. +Note that the commands are not applicable in raw mode and have no effect. + diff --git a/extra/src/codecs/socket.cc b/extra/src/codecs/socket.cc index b12c0b459..b487a558d 100644 --- a/extra/src/codecs/socket.cc +++ b/extra/src/codecs/socket.cc @@ -85,12 +85,9 @@ static void set_flags(const DAQ_SktHdr_t* pci, CodecData& codec, DecodeData& sno snort.decode_flags |= DECODE_SOF; if ( pci->flags & DAQ_SKT_FLAG_END_FLOW ) - { snort.decode_flags |= DECODE_EOF; - codec.lyr_len = 1; // eat pseudo-octet - } - else - codec.lyr_len = 0; + + codec.lyr_len = 0; } bool SocketCodec::decode(const RawData& raw, CodecData& codec, DecodeData& snort) diff --git a/extra/src/daqs/CMakeLists.txt b/extra/src/daqs/CMakeLists.txt index 4dc9e7cc5..d1b39adbc 100644 --- a/extra/src/daqs/CMakeLists.txt +++ b/extra/src/daqs/CMakeLists.txt @@ -2,5 +2,5 @@ add_example_library(daq_socket daqs daq_socket.c daq_socket.h) add_example_library(daq_file daqs daq_file.c daq_socket.h) -add_example_library(daq_user daqs daq_user.c daq_socket.h) +add_example_library(daq_hext daqs daq_hext.c daq_socket.h) diff --git a/extra/src/daqs/Makefile.am b/extra/src/daqs/Makefile.am index 241cb3ab5..118edc709 100644 --- a/extra/src/daqs/Makefile.am +++ b/extra/src/daqs/Makefile.am @@ -12,10 +12,10 @@ daq_file_la_CFLAGS = -DBUILDING_SO daq_file_la_LDFLAGS = -module -export-dynamic -avoid-version -shared daq_file_la_SOURCES = daq_file.c daq_socket.h -daqlib_LTLIBRARIES += daq_user.la -daq_user_la_CFLAGS = -DBUILDING_SO -daq_user_la_LDFLAGS = -module -export-dynamic -avoid-version -shared -daq_user_la_SOURCES = daq_user.c daq_socket.h +daqlib_LTLIBRARIES += daq_hext.la +daq_hext_la_CFLAGS = -DBUILDING_SO +daq_hext_la_LDFLAGS = -module -export-dynamic -avoid-version -shared +daq_hext_la_SOURCES = daq_hext.c daq_socket.h AM_CFLAGS = @AM_CFLAGS@ diff --git a/extra/src/daqs/daq_user.c b/extra/src/daqs/daq_hext.c similarity index 81% rename from extra/src/daqs/daq_user.c rename to extra/src/daqs/daq_hext.c index 528c6904a..1179acf5b 100644 --- a/extra/src/daqs/daq_user.c +++ b/extra/src/daqs/daq_hext.c @@ -16,7 +16,7 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //-------------------------------------------------------------------------- */ -/* daq_user.c author Russ Combs */ +/* daq_hext.c author Russ Combs */ #include "daq_socket.h" @@ -39,7 +39,7 @@ #include #define DAQ_MOD_VERSION 0 -#define DAQ_NAME "user" +#define DAQ_NAME "hext" #define DAQ_TYPE (DAQ_TYPE_FILE_CAPABLE|DAQ_TYPE_INTF_CAPABLE|DAQ_TYPE_MULTI_INSTANCE) #define DEF_BUF_SZ 16384 @@ -52,7 +52,7 @@ typedef struct { int start; int stop; int eof; - int fsm; + int dlt; unsigned snaplen; unsigned idx; @@ -255,7 +255,7 @@ static int parse(FileImpl* impl) // file functions //------------------------------------------------------------------------- -static int user_setup(FileImpl* impl) +static int hext_setup(FileImpl* impl) { if ( !strcmp(impl->name, "tty") ) { @@ -267,7 +267,7 @@ static int user_setup(FileImpl* impl) DAQ_NAME, strerror(errno)); return -1; } - parse_host("192.168.1.1 12345", &impl->cfg.src_addr, &impl->cfg.src_port); + parse_host("192.168.1.2 12345", &impl->cfg.src_addr, &impl->cfg.src_port); parse_host("10.1.2.3 80", &impl->cfg.dst_addr, &impl->cfg.dst_port); impl->cfg.ip_proto = impl->pci.ip_proto = IPPROTO_TCP; @@ -277,7 +277,7 @@ static int user_setup(FileImpl* impl) return 0; } -static void user_cleanup(FileImpl* impl) +static void hext_cleanup(FileImpl* impl) { if ( impl->fyle != stdin ) fclose(impl->fyle); @@ -285,7 +285,7 @@ static void user_cleanup(FileImpl* impl) impl->fyle = NULL; } -static int user_read(FileImpl* impl) +static int hext_read(FileImpl* impl) { int n = 0; @@ -300,7 +300,7 @@ static int user_read(FileImpl* impl) if ( !n ) { - if ( !impl->eof ) + if ( (impl->dlt == DLT_SOCKET) && !impl->eof ) { impl->eof = 1; return 1; // <= zero won't make it :( @@ -324,6 +324,29 @@ static int user_read(FileImpl* impl) // daq utilities //------------------------------------------------------------------------- +static int get_vars ( + FileImpl* impl, const DAQ_Config_t* cfg, char* errBuf, size_t errMax +) { + const char* s = NULL; + DAQ_Dict* entry; + + for ( entry = cfg->values; entry; entry = entry->next) + { + if ( !strcmp(entry->key, "dlt") ) + s = entry->value; + + else + { + snprintf(errBuf, errMax, "unknown var (%s)", s); + return 0; + } + } + if ( s ) + impl->dlt = atoi(s); + + return 1; +} + static void set_pkt_hdr(FileImpl* impl, DAQ_PktHdr_t* phdr, ssize_t len) { struct timeval t; @@ -340,6 +363,11 @@ static void set_pkt_hdr(FileImpl* impl, DAQ_PktHdr_t* phdr, ssize_t len) phdr->address_space_id = 0; phdr->opaque = 0; + if ( impl->dlt != DLT_SOCKET ) + { + phdr->priv_ptr = NULL; + return; + } impl->pci.flags &= ~(DAQ_SKT_FLAG_START_FLOW|DAQ_SKT_FLAG_END_FLOW); if ( impl->start ) @@ -356,11 +384,11 @@ static void set_pkt_hdr(FileImpl* impl, DAQ_PktHdr_t* phdr, ssize_t len) // forward all but drops, retries and blacklists: static const int s_fwd[MAX_DAQ_VERDICT] = { 1, 0, 1, 1, 0, 1, 0 }; -static int user_daq_process( +static int hext_daq_process( FileImpl* impl, DAQ_Analysis_Func_t cb, void* user) { DAQ_PktHdr_t hdr; - int n = user_read(impl); + int n = hext_read(impl); if ( n < 1 ) return n; @@ -379,7 +407,7 @@ static int user_daq_process( // daq //------------------------------------------------------------------------- -static void user_daq_shutdown (void* handle) +static void hext_daq_shutdown (void* handle) { FileImpl* impl = (FileImpl*)handle; @@ -394,7 +422,7 @@ static void user_daq_shutdown (void* handle) //------------------------------------------------------------------------- -static int user_daq_initialize ( +static int hext_daq_initialize ( const DAQ_Config_t* cfg, void** handle, char* errBuf, size_t errMax) { FileImpl* impl = calloc(1, sizeof(*impl)); @@ -405,13 +433,14 @@ static int user_daq_initialize ( return DAQ_ERROR_NOMEM; } - impl->fyle = NULL; - impl->start = impl->stop = 0; impl->snaplen = cfg->snaplen ? cfg->snaplen : DEF_BUF_SZ; + impl->dlt = DLT_SOCKET; - impl->idx = 0; - impl->fsm = 0; - impl->line[0] = '\0'; + if ( !get_vars(impl, cfg, errBuf, errMax) ) + { + free(impl); + return DAQ_ERROR; + } if ( cfg->name ) { @@ -425,7 +454,7 @@ static int user_daq_initialize ( if ( !(impl->buf = malloc(impl->snaplen)) ) { snprintf(errBuf, errMax, "%s: failed to allocate the ipfw buffer", DAQ_NAME); - user_daq_shutdown(impl); + hext_daq_shutdown(impl); return DAQ_ERROR_NOMEM; } @@ -437,28 +466,28 @@ static int user_daq_initialize ( //------------------------------------------------------------------------- -static int user_daq_start (void* handle) +static int hext_daq_start (void* handle) { FileImpl* impl = (FileImpl*)handle; - if ( user_setup(impl) ) + if ( hext_setup(impl) ) return DAQ_ERROR; impl->state = DAQ_STATE_STARTED; return DAQ_SUCCESS; } -static int user_daq_stop (void* handle) +static int hext_daq_stop (void* handle) { FileImpl* impl = (FileImpl*)handle; - user_cleanup(impl); + hext_cleanup(impl); impl->state = DAQ_STATE_STOPPED; return DAQ_SUCCESS; } //------------------------------------------------------------------------- -static int user_daq_inject ( +static int hext_daq_inject ( void* handle, const DAQ_PktHdr_t* hdr, const uint8_t* buf, uint32_t len, int rev) { (void)handle; @@ -471,7 +500,7 @@ static int user_daq_inject ( //------------------------------------------------------------------------- -static int user_daq_acquire ( +static int hext_daq_acquire ( void* handle, int cnt, DAQ_Analysis_Func_t callback, DAQ_Meta_Func_t meta, void* user) { (void)meta; @@ -482,7 +511,7 @@ static int user_daq_acquire ( while ( hit < cnt || cnt <= 0 ) { - int status = user_daq_process(impl, callback, user); + int status = hext_daq_process(impl, callback, user); if ( status > 0 ) { @@ -500,71 +529,71 @@ static int user_daq_acquire ( //------------------------------------------------------------------------- -static int user_daq_breakloop (void* handle) +static int hext_daq_breakloop (void* handle) { FileImpl* impl = (FileImpl*)handle; impl->stop = 1; return DAQ_SUCCESS; } -static DAQ_State user_daq_check_status (void* handle) +static DAQ_State hext_daq_check_status (void* handle) { FileImpl* impl = (FileImpl*)handle; return impl->state; } -static int user_daq_get_stats (void* handle, DAQ_Stats_t* stats) +static int hext_daq_get_stats (void* handle, DAQ_Stats_t* stats) { FileImpl* impl = (FileImpl*)handle; *stats = impl->stats; return DAQ_SUCCESS; } -static void user_daq_reset_stats (void* handle) +static void hext_daq_reset_stats (void* handle) { FileImpl* impl = (FileImpl*)handle; memset(&impl->stats, 0, sizeof(impl->stats)); } -static int user_daq_get_snaplen (void* handle) +static int hext_daq_get_snaplen (void* handle) { FileImpl* impl = (FileImpl*)handle; return impl->snaplen; } -static uint32_t user_daq_get_capabilities (void* handle) +static uint32_t hext_daq_get_capabilities (void* handle) { (void)handle; return DAQ_CAPA_BLOCK | DAQ_CAPA_REPLACE | DAQ_CAPA_INJECT | DAQ_CAPA_INJECT_RAW | DAQ_CAPA_BREAKLOOP | DAQ_CAPA_UNPRIV_START; } -static int user_daq_get_datalink_type(void *handle) +static int hext_daq_get_datalink_type(void *handle) { - (void)handle; - return DLT_SOCKET; + FileImpl* impl = (FileImpl*)handle; + return impl->dlt; } -static const char* user_daq_get_errbuf (void* handle) +static const char* hext_daq_get_errbuf (void* handle) { FileImpl* impl = (FileImpl*)handle; return impl->error; } -static void user_daq_set_errbuf (void* handle, const char* s) +static void hext_daq_set_errbuf (void* handle, const char* s) { FileImpl* impl = (FileImpl*)handle; DPE(impl->error, "%s", s ? s : ""); } -static int user_daq_get_device_index(void* handle, const char* device) +static int hext_daq_get_device_index(void* handle, const char* device) { (void)handle; (void)device; return DAQ_ERROR_NOTSUP; } -static int user_daq_set_filter (void* handle, const char* filter) +static int hext_daq_set_filter (void* handle, const char* filter) { (void)handle; (void)filter; @@ -576,30 +605,30 @@ static int user_daq_set_filter (void* handle, const char* filter) #ifdef BUILDING_SO DAQ_SO_PUBLIC DAQ_Module_t DAQ_MODULE_DATA = #else -DAQ_Module_t user_daq_module_data = +DAQ_Module_t hext_daq_module_data = #endif { .api_version = DAQ_API_VERSION, .module_version = DAQ_MOD_VERSION, .name = DAQ_NAME, .type = DAQ_TYPE, - .initialize = user_daq_initialize, - .set_filter = user_daq_set_filter, - .start = user_daq_start, - .acquire = user_daq_acquire, - .inject = user_daq_inject, - .breakloop = user_daq_breakloop, - .stop = user_daq_stop, - .shutdown = user_daq_shutdown, - .check_status = user_daq_check_status, - .get_stats = user_daq_get_stats, - .reset_stats = user_daq_reset_stats, - .get_snaplen = user_daq_get_snaplen, - .get_capabilities = user_daq_get_capabilities, - .get_datalink_type = user_daq_get_datalink_type, - .get_errbuf = user_daq_get_errbuf, - .set_errbuf = user_daq_set_errbuf, - .get_device_index = user_daq_get_device_index, + .initialize = hext_daq_initialize, + .set_filter = hext_daq_set_filter, + .start = hext_daq_start, + .acquire = hext_daq_acquire, + .inject = hext_daq_inject, + .breakloop = hext_daq_breakloop, + .stop = hext_daq_stop, + .shutdown = hext_daq_shutdown, + .check_status = hext_daq_check_status, + .get_stats = hext_daq_get_stats, + .reset_stats = hext_daq_reset_stats, + .get_snaplen = hext_daq_get_snaplen, + .get_capabilities = hext_daq_get_capabilities, + .get_datalink_type = hext_daq_get_datalink_type, + .get_errbuf = hext_daq_get_errbuf, + .set_errbuf = hext_daq_set_errbuf, + .get_device_index = hext_daq_get_device_index, .modify_flow = NULL, .hup_prep = NULL, .hup_apply = NULL, diff --git a/extra/src/loggers/CMakeLists.txt b/extra/src/loggers/CMakeLists.txt index a9592c9a9..fe217875f 100644 --- a/extra/src/loggers/CMakeLists.txt +++ b/extra/src/loggers/CMakeLists.txt @@ -1,6 +1,6 @@ add_example_library(alert_ex loggers alert_ex.cc) -add_example_library(log_user loggers log_user.cc) +add_example_library(log_hext loggers log_hext.cc) install ( FILES alert.lua diff --git a/extra/src/loggers/Makefile.am b/extra/src/loggers/Makefile.am index e5680f2f7..630cb96b3 100644 --- a/extra/src/loggers/Makefile.am +++ b/extra/src/loggers/Makefile.am @@ -7,10 +7,10 @@ libalert_ex_la_CXXFLAGS = $(AM_CXXFLAGS) libalert_ex_la_LDFLAGS = -export-dynamic -shared libalert_ex_la_SOURCES = alert_ex.cc -loglib_LTLIBRARIES += liblog_user.la -liblog_user_la_CXXFLAGS = $(AM_CXXFLAGS) -liblog_user_la_LDFLAGS = -export-dynamic -shared -liblog_user_la_SOURCES = log_user.cc +loglib_LTLIBRARIES += liblog_hext.la +liblog_hext_la_CXXFLAGS = $(AM_CXXFLAGS) +liblog_hext_la_LDFLAGS = -export-dynamic -shared +liblog_hext_la_SOURCES = log_hext.cc dist_loglib_SCRIPTS = alert.lua diff --git a/extra/src/loggers/log_user.cc b/extra/src/loggers/log_hext.cc similarity index 71% rename from extra/src/loggers/log_user.cc rename to extra/src/loggers/log_hext.cc index 5c362c7d7..61d2695cb 100644 --- a/extra/src/loggers/log_user.cc +++ b/extra/src/loggers/log_hext.cc @@ -16,7 +16,7 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //-------------------------------------------------------------------------- -// log_user.cc author Russ Combs +// log_hext.cc author Russ Combs #ifdef HAVE_CONFIG_H #include "config.h" @@ -36,12 +36,13 @@ using namespace std; #include "log/text_log.h" #include "sfip/sf_ip.h" -#define S_NAME "log_user" +#define S_NAME "log_hext" #define F_NAME S_NAME ".txt" -static const char* s_help = "output payload suitable for daq user"; +static const char* s_help = "output payload suitable for daq hext"; -static THREAD_LOCAL TextLog* user_log = nullptr; +static THREAD_LOCAL TextLog* hext_log = nullptr; +static THREAD_LOCAL unsigned s_pkt_num = 0; //------------------------------------------------------------------------- // impl stuff @@ -49,6 +50,12 @@ static THREAD_LOCAL TextLog* user_log = nullptr; #define LOG_CHARS 20 +static void log_raw(const Packet* p) +{ + TextLog_Print(hext_log, "\n# %u [%u]\n", + s_pkt_num++, p->pkth->caplen); +} + static void log_header(const Packet* p) { char src[INET6_ADDRSTRLEN]; @@ -60,7 +67,7 @@ static void log_header(const Packet* p) addr = p->ptrs.ip_api.get_dst(); sfip_ntop(addr, dst, sizeof(dst)); - TextLog_Print(user_log, "\n$packet %s %d -> %s %d\n", + TextLog_Print(hext_log, "\n$packet %s %d -> %s %d\n", src, p->ptrs.sp, dst, p->ptrs.dp); } @@ -70,7 +77,7 @@ static void log_data(const uint8_t* p, unsigned n) char txt[LOG_CHARS+1]; unsigned odx = 0, idx = 0; - TextLog_NewLine(user_log); + TextLog_NewLine(hext_log); for ( idx = 0; idx < n; idx++) { @@ -81,19 +88,19 @@ static void log_data(const uint8_t* p, unsigned n) if ( odx == LOG_CHARS ) { txt[odx] = hex[3*odx] = '\0'; - TextLog_Print(user_log, "x%s # %s\n", hex, txt); + TextLog_Print(hext_log, "x%s # %s\n", hex, txt); odx = 0; } } if ( odx ) { txt[odx] = hex[3*odx] = '\0'; - TextLog_Print(user_log, "x%s", hex); + TextLog_Print(hext_log, "x%s", hex); while ( odx++ < LOG_CHARS ) - TextLog_Print(user_log, " "); + TextLog_Print(hext_log, " "); - TextLog_Print(user_log, " # %s\n", txt); + TextLog_Print(hext_log, " # %s\n", txt); } } @@ -106,6 +113,9 @@ static const Parameter s_params[] = { "file", Parameter::PT_BOOL, nullptr, "false", "output to " F_NAME " instead of stdout" }, + { "raw", Parameter::PT_BOOL, nullptr, "false", + "output all full packets if true, else just TCP payload" }, + { "limit", Parameter::PT_INT, "0:", "0", "set limit (0 is unlimited)" }, @@ -115,10 +125,10 @@ static const Parameter s_params[] = { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; -class UserModule : public Module +class HextModule : public Module { public: - UserModule() : Module(S_NAME, s_help, s_params) { } + HextModule() : Module(S_NAME, s_help, s_params) { } bool set(const char*, Value&, SnortConfig*) override; bool begin(const char*, int, SnortConfig*) override; @@ -126,15 +136,19 @@ public: public: bool file; + bool raw; unsigned long limit; unsigned units; }; -bool UserModule::set(const char*, Value& v, SnortConfig*) +bool HextModule::set(const char*, Value& v, SnortConfig*) { if ( v.is("file") ) file = v.get_bool(); + else if ( v.is("raw") ) + raw = v.get_bool(); + else if ( v.is("limit") ) limit = v.get_long(); @@ -147,15 +161,16 @@ bool UserModule::set(const char*, Value& v, SnortConfig*) return true; } -bool UserModule::begin(const char*, int, SnortConfig*) +bool HextModule::begin(const char*, int, SnortConfig*) { file = false; + raw = false; limit = 0; units = 0; return true; } -bool UserModule::end(const char*, int, SnortConfig*) +bool HextModule::end(const char*, int, SnortConfig*) { while ( units-- ) limit *= 1024; @@ -167,10 +182,10 @@ bool UserModule::end(const char*, int, SnortConfig*) // logger stuff //------------------------------------------------------------------------- -class UserLogger : public Logger +class HextLogger : public Logger { public: - UserLogger(UserModule*); + HextLogger(HextModule*); void open() override; void close() override; @@ -180,29 +195,36 @@ public: private: string file; unsigned long limit; + bool raw; }; -UserLogger::UserLogger(UserModule* m) +HextLogger::HextLogger(HextModule* m) { file = m->file ? F_NAME : "stdout"; limit = m->limit; + raw = m->raw; } -void UserLogger::open() +void HextLogger::open() { const unsigned buf_sz = 65536; - user_log = TextLog_Init(file.c_str(), buf_sz, limit); + hext_log = TextLog_Init(file.c_str(), buf_sz, limit); } -void UserLogger::close() +void HextLogger::close() { - if ( user_log ) - TextLog_Term(user_log); + if ( hext_log ) + TextLog_Term(hext_log); } -void UserLogger::log(Packet* p, const char*, Event*) +void HextLogger::log(Packet* p, const char*, Event*) { - if ( p->data and p->dsize ) + if ( raw ) + { + log_raw(p); + log_data(p->pkt, p->pkth->caplen); + } + else if ( p->is_tcp() and p->dsize ) { log_header(p); log_data(p->data, p->dsize); @@ -214,20 +236,20 @@ void UserLogger::log(Packet* p, const char*, Event*) //------------------------------------------------------------------------- static Module* mod_ctor() -{ return new UserModule; } +{ return new HextModule; } static void mod_dtor(Module* m) { delete m; } -static Logger* user_ctor(SnortConfig*, Module* mod) +static Logger* hext_ctor(SnortConfig*, Module* mod) { - return new UserLogger((UserModule*)mod); + return new HextLogger((HextModule*)mod); } -static void user_dtor(Logger* p) +static void hext_dtor(Logger* p) { delete p; } -static const LogApi user_api = +static const LogApi hext_api = { { PT_LOGGER, @@ -242,13 +264,13 @@ static const LogApi user_api = mod_dtor }, OUTPUT_TYPE_FLAG__ALERT, - user_ctor, - user_dtor + hext_ctor, + hext_dtor }; SO_PUBLIC const BaseApi* snort_plugins[] = { - &user_api.base, + &hext_api.base, nullptr }; diff --git a/src/codecs/ip/cd_ipv4.cc b/src/codecs/ip/cd_ipv4.cc index ceb90f276..24b1b1468 100644 --- a/src/codecs/ip/cd_ipv4.cc +++ b/src/codecs/ip/cd_ipv4.cc @@ -22,7 +22,9 @@ #include "config.h" #endif +#include #include + #include "utils/dnet_header.h" #include "main/snort_config.h" #include "fpdetect.h" @@ -575,11 +577,13 @@ void Ipv4Codec::log(TextLog* const text_log, const uint8_t* raw_pkt, src.addr32 = ip4h->get_src(); dst.addr32 = ip4h->get_dst(); - TextLog_Print(text_log, "%d.%d.%d.%d -> %d.%d.%d.%d", - (int)src.addr8[0], (int)src.addr8[1], - (int)src.addr8[2], (int)src.addr8[3], - (int)dst.addr8[0], (int)dst.addr8[1], - (int)dst.addr8[2], (int)dst.addr8[3]); + char src_buf[INET_ADDRSTRLEN]; + char dst_buf[INET_ADDRSTRLEN]; + + inet_ntop(AF_INET, &src, src_buf, sizeof(src_buf)); + inet_ntop(AF_INET, &dst, dst_buf, sizeof(dst_buf)); + + TextLog_Print(text_log, "%s -> %s", src_buf, dst_buf); } TextLog_NewLine(text_log); diff --git a/src/codecs/ip/cd_ipv6.cc b/src/codecs/ip/cd_ipv6.cc index c26221990..fdbd430ac 100644 --- a/src/codecs/ip/cd_ipv6.cc +++ b/src/codecs/ip/cd_ipv6.cc @@ -22,9 +22,10 @@ #include "config.h" #endif +#include #include -#include "detection/fpdetect.h" +#include "detection/fpdetect.h" #include "protocols/ipv6.h" #include "codecs/codec_module.h" #include "framework/codec.h" @@ -540,20 +541,13 @@ void Ipv6Codec::log(TextLog* const text_log, const uint8_t* raw_pkt, const ip::snort_in6_addr* const src = ip6h->get_src(); const ip::snort_in6_addr* const dst = ip6h->get_dst(); - TextLog_Print(text_log, "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:" - "%02X%02X:%02X%02X:%02X%02X -> %02X%02X:%02X%02X:" - "%02X%02X:%02X%02X:%02X%02X:%02X%02X", - (int)src->u6_addr8[0], (int)src->u6_addr8[1], (int)src->u6_addr8[2], - (int)src->u6_addr8[3], (int)src->u6_addr8[4], (int)src->u6_addr8[5], - (int)src->u6_addr8[6], (int)src->u6_addr8[7], (int)src->u6_addr8[8], - (int)src->u6_addr8[9], (int)src->u6_addr8[10], (int)src->u6_addr8[11], - (int)src->u6_addr8[12], (int)src->u6_addr8[13], (int)src->u6_addr8[14], - (int)src->u6_addr8[15], (int)dst->u6_addr8[0], (int)dst->u6_addr8[1], - (int)dst->u6_addr8[2], (int)dst->u6_addr8[3], (int)dst->u6_addr8[4], - (int)dst->u6_addr8[5], (int)dst->u6_addr8[6], (int)dst->u6_addr8[7], - (int)dst->u6_addr8[8], (int)dst->u6_addr8[9], (int)dst->u6_addr8[10], - (int)dst->u6_addr8[11], (int)dst->u6_addr8[12], (int)dst->u6_addr8[13], - (int)dst->u6_addr8[14], (int)dst->u6_addr8[15]); + char src_buf[INET6_ADDRSTRLEN]; + char dst_buf[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET6, src, src_buf, sizeof(src_buf)); + inet_ntop(AF_INET6, dst, dst_buf, sizeof(dst_buf)); + + TextLog_Print(text_log, "%s -> %s", src_buf, dst_buf); } TextLog_NewLine(text_log); diff --git a/src/detection/rules.h b/src/detection/rules.h index 2f511de2a..5ec0b8f23 100644 --- a/src/detection/rules.h +++ b/src/detection/rules.h @@ -49,8 +49,6 @@ #define EventIsInternal(gid) (gid == GENERATOR_INTERNAL) -/* D A T A S T R U C T U R E S *********************************************/ - struct OutputSet; struct ListHead diff --git a/src/flow/flow_cache.cc b/src/flow/flow_cache.cc index 39009368a..e800e64be 100644 --- a/src/flow/flow_cache.cc +++ b/src/flow/flow_cache.cc @@ -182,7 +182,12 @@ uint32_t FlowCache::prune_stale(uint32_t thetime, Flow* save_me) { // FIXIT-L this loops forever if 1 flow in cache if (flow == save_me) + { + if ( hash_table->get_count() == 1 ) + break; + hash_table->touch(); + } else if ((flow->last_data_seen + timeoutAggressive) < thetime) { diff --git a/src/flow/session.h b/src/flow/session.h index add6ba69f..041cadd0f 100644 --- a/src/flow/session.h +++ b/src/flow/session.h @@ -57,9 +57,6 @@ public: virtual void set_extra_data(Packet*, uint32_t /*flag*/) { } virtual void clear_extra_data(Packet*, uint32_t /*flag*/) { } - virtual int get_rebuilt_packets(Packet*, PacketIterator, void* /*userdata*/) { return 0; } - virtual int get_segments(Packet*, StreamSegmentIterator, void* /*userdata*/) { return -1; } - virtual bool is_sequenced(uint8_t /*dir*/) { return true; } virtual bool are_packets_missing(uint8_t /*dir*/) { return true; } diff --git a/src/framework/codec.h b/src/framework/codec.h index 283e6b5b4..a9c822750 100644 --- a/src/framework/codec.h +++ b/src/framework/codec.h @@ -235,7 +235,7 @@ class SO_PUBLIC Codec public: virtual ~Codec() { } - // PKT_MAX = ETHERNET_HEADER_LEN () + VLAN_HEADER (4) + ETHERNET_MTU () + IP_MAXPACKET() + // PKT_MAX = ETHERNET_HEADER_LEN + VLAN_HEADER + ETHERNET_MTU + IP_MAXPACKET /* PKT_MAX is sized to ensure that any reassembled packet * can accommodate a full datagram at innermost layer @@ -243,7 +243,7 @@ public: * ETHERNET_HEADER_LEN == 14 * VLAN_HEADER == 4 * ETHERNET_MTU == 1500 - * IP_MAXPACKET == 65535 + * IP_MAXPACKET == 65535 FIXIT-L use Packet::max_dsize */ static const uint32_t PKT_MAX = 14 + 4 + 1500 + 65535; diff --git a/src/framework/decode_data.h b/src/framework/decode_data.h index e7c1175dd..c0e97b237 100644 --- a/src/framework/decode_data.h +++ b/src/framework/decode_data.h @@ -121,11 +121,11 @@ struct DecodeData PktType type; ip::IpApi ip_api; - mpls::MplsHdr mplsHdr; + mpls::MplsHdr mplsHdr; // FIXIT-L need to zero this? inline void reset() { - memset((char*)&tcph, '\0', offsetof(DecodeData, ip_api)); + memset(this, 0, offsetof(DecodeData, ip_api)); ip_api.reset(); } diff --git a/src/framework/parameter.cc b/src/framework/parameter.cc index 79730ee95..6b64c45d5 100644 --- a/src/framework/parameter.cc +++ b/src/framework/parameter.cc @@ -435,3 +435,14 @@ const Parameter* Parameter::find(const Parameter* p, const char* s) return nullptr; } +int Parameter::index(const char* r, const char* s) +{ + const char* t = ::find(r, s); + + if ( !t ) + return -1; + + unsigned idx = get_index(r, t); + return (int)idx; +} + diff --git a/src/framework/parameter.h b/src/framework/parameter.h index 270557b1a..7b39ac307 100644 --- a/src/framework/parameter.h +++ b/src/framework/parameter.h @@ -71,6 +71,9 @@ struct Parameter const char* get_string() const; static const Parameter* find(const Parameter*, const char*); + + // 0-based; -1 if not found; list is | delimited + static int index(const char* list, const char* key); }; #endif diff --git a/src/ips_options/ips_cvs.cc b/src/ips_options/ips_cvs.cc index 7f84c8bf7..c19d6c9b7 100644 --- a/src/ips_options/ips_cvs.cc +++ b/src/ips_options/ips_cvs.cc @@ -160,28 +160,17 @@ bool CvsOption::operator==(const IpsOption& ips) const int CvsOption::eval(Cursor&, Packet* p) { - int ret; int rval = DETECTION_OPTION_NO_MATCH; CvsRuleOption* cvs_rule_option = &config; - if (p == NULL) - { - return rval; - } - - if ((p->ptrs.tcph == NULL) || (p->data == NULL) || (p->dsize == 0)) - { - return rval; - } - - if (cvs_rule_option == NULL) + if ( !p->has_tcp_data() ) { return rval; } DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "CVS begin detection\n"); ); - ret = CvsDecode(p->data, p->dsize, cvs_rule_option); + int ret = CvsDecode(p->data, p->dsize, cvs_rule_option); if (ret == CVS_ALERT) { diff --git a/src/log/log.cc b/src/log/log.cc index 2fe993442..6ef6ee5db 100644 --- a/src/log/log.cc +++ b/src/log/log.cc @@ -148,37 +148,22 @@ void CloseLogger() void LogIPPkt(Packet* p) { log_mutex.lock(); + TextLog_NewLine(text_log); + LogTimeStamp(text_log, p); LogIPPkt(text_log, p); TextLog_Flush(text_log); log_mutex.unlock(); } -void snort_print(Packet* p) +void LogFlow(Packet* p) { - if (p->ptrs.ip_api.is_ip()) - { - LogIPPkt(text_log, p); - } -#if 0 - // FIXIT-L ARP logging not impelemted - else if (p->proto_bits & PROTO_BIT__ARP) - { - log_mutex.lock(); - LogArpHeader(text_log, p); - TextLog_Flush(text_log); - log_mutex.unlock(); - } -#endif -#if 0 - else if (p->eplh != NULL) - { - LogEapolPkt(text_log, p); - } - else if (p->wifih && SnortConfig::output_wifi_mgmt()) - { - LogWifiPkt(text_log, p); - } -#endif + log_mutex.lock(); + TextLog_NewLine(text_log); + LogTimeStamp(text_log, p); + TextLog_Print(text_log, " %s ", p->get_type()); + LogIpAddrs(text_log, p); + TextLog_NewLine(text_log); + log_mutex.unlock(); } void LogNetData(const uint8_t* data, const int len, Packet* p) diff --git a/src/log/log.h b/src/log/log.h index ff6bd571d..8234a876c 100644 --- a/src/log/log.h +++ b/src/log/log.h @@ -37,8 +37,8 @@ int RollAlertFile(const char*); void OpenLogger(); void CloseLogger(); void LogIPPkt(Packet*); -void snort_print(Packet*); -void LogNetData(const uint8_t* data, const int len, Packet* p = NULL); +void LogFlow(Packet*); +void LogNetData(const uint8_t* data, const int len, Packet*); #endif diff --git a/src/log/log_text.cc b/src/log/log_text.cc index 0f8ff649c..a98a781b2 100644 --- a/src/log/log_text.cc +++ b/src/log/log_text.cc @@ -1,7 +1,6 @@ //-------------------------------------------------------------------------- // Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved. -// Copyright (C) 2002-2013 Sourcefire, Inc. -// Copyright (C) 1998-2002 Martin Roesch +// Copyright (C) 2007-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 @@ -572,7 +571,7 @@ void LogIpOptions(TextLog* log, const IP4Hdr* ip4h, const Packet* const p) */ void LogIpAddrs(TextLog* log, Packet* p) { - if ( p->is_fragment() || ( !p->is_tcp() && !p->is_udp())) + if ( p->is_fragment() || (!p->is_tcp() && !p->is_udp() && !p->is_data()) ) { const char* ip_fmt = "%s -> %s"; @@ -709,10 +708,6 @@ void LogIPHeader(TextLog* log, Packet* p) /* print fragment info if necessary */ if ( p->is_fragment() ) { -#ifdef REG_TEST - frag_off >>= 3; -#endif - TextLog_Print(log, "Frag Offset: 0x%04X Frag Size: 0x%04X\n", frag_off, p->ptrs.ip_api.pay_len()); } @@ -887,12 +882,6 @@ static void LogTcpOptions(TextLog* log, const tcp::TcpOptIterator& opt_iter) } } } - -#ifdef REG_TEST - TextLog_Putc(log, ' '); -#endif - - TextLog_NewLine(log); } void LogTcpOptions(TextLog* log, const tcp::TCPHdr* tcph, uint16_t valid_tcp_len) @@ -947,13 +936,10 @@ void LogTCPHeader(TextLog* log, Packet* p) } /* dump the TCP options */ -#ifdef REG_TEST - // emulate snort bug - if ( !p->is_cooked() || (p->pseudo_type == PSEUDO_PKT_IP) ) -#endif if (tcph->has_options()) { LogTcpOptions(log, p); + TextLog_NewLine(log); } } @@ -1517,7 +1503,7 @@ static void LogCharData(TextLog* log, char* data, int len) } /* - * Function: LogNetData(TextLog*, uint8_t *,int, Packet *) + * Function: LogNetData(TextLog*, uint8_t*,int, Packet*) * * Purpose: Do a side by side dump of a buffer, hex on * the left, decoded ASCII on the right. @@ -1528,10 +1514,15 @@ static void LogCharData(TextLog* log, char* data, int len) * * Returns: void function */ -#define BYTES_PER_FRAME 16 -/* middle of packet:"41 02 43 04 45 06 47 08 49 0A 4B 0C 4D 0E 4F 0F A.C.E.G.I.K.M.O." - at end of packet:"41 02 43 04 45 06 47 08 A.C.E.G."*/ -const char pad3[] = " "; +#define SEPARATOR \ + "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" + +#define BYTES_PER_FRAME 20 +/* middle:"41 02 43 04 45 06 47 08 49 0A 4B 0C 4D 0E 4F 0F 01 02 03 04 A.C.E.G.I.K.M.O....." + at end:"41 02 43 04 45 06 47 08 A.C.E.G."*/ + +static const char pad3[] = + " "; void LogNetData(TextLog* log, const uint8_t* data, const int len, Packet* p) { @@ -1547,31 +1538,10 @@ void LogNetData(TextLog* log, const uint8_t* data, const int len, Packet* p) int i; byte_pos = char_pos = 0; - ip_ob_start = ip_ob_end = -1; if ( !len ) - { - TextLog_NewLine(log); return; - } - if ( !data ) - { - TextLog_Print(log, "Got NULL ptr in LogNetData()\n"); - return; - } - - if ( len > IP_MAXPACKET ) - { - if (SnortConfig::log_verbose()) - { - TextLog_Print( - log, "Got bogus buffer length (%d) for LogNetData, " - "defaulting to %d bytes\n", len, BYTES_PER_FRAME - ); - } - end = data + BYTES_PER_FRAME; - } if (p && SnortConfig::obfuscate() ) { @@ -1600,6 +1570,15 @@ void LogNetData(TextLog* log, const uint8_t* data, const int len, Packet* p) ip_ob_end = ip_ob_start + 2 + 2*(sizeof(struct in6_addr)); } } +#if 0 + TextLog_Print(log, "%s[%d]\n", p->get_pseudo_type(), p->dsize); + LogDiv(log); +#else + char div[64]; + snprintf(div, sizeof(div), "- - - %s[%d]", p->get_pseudo_type(), p->dsize); + div[sizeof(div)-1] = '\0'; + TextLog_Print(log, "%s%s\n", div, SEPARATOR+strlen(div)); +#endif /* loop thru the whole buffer */ while ( pb < end ) @@ -1651,39 +1630,34 @@ void LogNetData(TextLog* log, const uint8_t* data, const int len, Packet* p) pb += BYTES_PER_FRAME; TextLog_NewLine(log); } -#ifndef REG_TEST - TextLog_NewLine(log); -#endif + LogDiv(log); } -#ifdef REG_TEST -#define SEPARATOR \ - "=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+" -#else -#define SEPARATOR \ - "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" -#endif +void LogDiv(TextLog* log) +{ + TextLog_Print(log, "%s\n", SEPARATOR); +} static int LogObfuscatedData(TextLog* log, Packet* p) { uint8_t* payload = NULL; uint16_t payload_len = 0; - TextLog_Print(log, "%s\n", SEPARATOR); - if (obApi->getObfuscatedPayload(p, &payload, (uint16_t*)&payload_len) != OB_RET_SUCCESS) { return -1; } + LogDiv(log); + /* dump the application layer data */ if (SnortConfig::output_app_data() && !SnortConfig::verbose_byte_dump()) { if (SnortConfig::output_char_data()) LogCharData(log, (char*)payload, payload_len); else - LogNetData(log, payload, payload_len, NULL); + LogNetData(log, payload, payload_len, p); } else if (SnortConfig::verbose_byte_dump()) { @@ -1694,54 +1668,13 @@ static int LogObfuscatedData(TextLog* log, Packet* p) SafeMemcpy(buf + dlen, payload, payload_len, buf, buf + sizeof(buf)); - LogNetData(log, buf, dlen + payload_len, NULL); + LogNetData(log, buf, dlen + payload_len, p); } free(payload); return 0; } -#ifndef REG_TEST -static void LogPacketType(TextLog* log, Packet* p) -{ - TextLog_NewLine(log); - - if ( !p->dsize || !p->is_cooked() ) - return; - - switch ( p->pseudo_type ) - { - case PSEUDO_PKT_SMB_SEG: - TextLog_Print(log, "%s", "SMB desegmented packet"); - break; - case PSEUDO_PKT_DCE_SEG: - TextLog_Print(log, "%s", "DCE/RPC desegmented packet"); - break; - case PSEUDO_PKT_DCE_FRAG: - TextLog_Print(log, "%s", "DCE/RPC defragmented packet"); - break; - case PSEUDO_PKT_SMB_TRANS: - TextLog_Print(log, "%s", "SMB Transact reassembled packet"); - break; - case PSEUDO_PKT_DCE_RPKT: - TextLog_Print(log, "%s", "DCE/RPC reassembled packet"); - break; - case PSEUDO_PKT_TCP: - TextLog_Print(log, "%s", "Stream reassembled packet"); - break; - case PSEUDO_PKT_IP: - TextLog_Print(log, "%s", "Frag reassembled packet"); - break; - default: - // FIXIT-L do we get here for portscan or sdf? - TextLog_Print(log, "%s", "Cooked packet"); - break; - } /* switch */ - TextLog_NewLine(log); -} - -#endif - /*-------------------------------------------------------------------- * Function: LogIPPkt(TextLog*, int, Packet *) * @@ -1755,20 +1688,8 @@ static void LogPacketType(TextLog* log, Packet* p) *-------------------------------------------------------------------- */ -#define DATA_LEN(p) \ - (p->ptrs.ip_api.actual_ip_len() - (p->ptrs.ip_api.hlen())) - void LogIPPkt(TextLog* log, Packet* p) { -#ifndef REG_TEST - LogPacketType(log, p); - TextLog_Print(log, "%s\n", SEPARATOR); -#endif - - /* dump the timestamp */ - LogTimeStamp(log, p); - - /* dump the ethernet header if we're doing that sort of thing */ if ( SnortConfig::output_datalink() ) { Log2ndHeader(log, p); @@ -1776,7 +1697,7 @@ void LogIPPkt(TextLog* log, Packet* p) if ( p->proto_bits & PROTO_BIT__MPLS ) LogMPLSHeader(log, p); - // FIXIT-J --> log everything in order!! + // FIXIT-L --> log everything in order!! ip::IpApi tmp_api = p->ptrs.ip_api; int8_t num_layer = 0; uint8_t tmp_next = p->get_ip_proto_next(); @@ -1785,11 +1706,6 @@ void LogIPPkt(TextLog* log, Packet* p) while (layer::set_outer_ip_api(p, p->ptrs.ip_api, p->ip_proto_next, num_layer) && tmp_api != p->ptrs.ip_api) { -#ifdef REG_TEST - // In Snort, cooked packets should not print an outer IP Header - if (p->is_cooked() && (p->pseudo_type != PSEUDO_PKT_IP)) - break; -#endif LogOuterIPHeader(log, p); if (first) @@ -1797,10 +1713,6 @@ void LogIPPkt(TextLog* log, Packet* p) LogGREHeader(log, p); // checks for valid gre layer before logging first = false; } - -#ifdef REG_TEST - break; -#endif } p->ip_proto_next = tmp_next; @@ -1818,20 +1730,18 @@ void LogIPPkt(TextLog* log, Packet* p) if ( p->ptrs.tcph != NULL ) LogTCPHeader(log, p); else - LogNetData(log, p->ptrs.ip_api.ip_data(), p->ptrs.ip_api.pay_len(), NULL); + LogNetData(log, p->ptrs.ip_api.ip_data(), p->ptrs.ip_api.pay_len(), p); break; case PktType::UDP: if ( p->ptrs.udph != NULL ) { -#ifdef REG_TEST // for consistency, nothing to log (tcp doesn't log paylen) LogUDPHeader(log, p); -#endif } else { - LogNetData(log, p->ptrs.ip_api.ip_data(), p->ptrs.ip_api.pay_len(), NULL); + LogNetData(log, p->ptrs.ip_api.ip_data(), p->ptrs.ip_api.pay_len(), p); } break; @@ -1844,7 +1754,7 @@ void LogIPPkt(TextLog* log, Packet* p) if ( p->ptrs.icmph != NULL ) LogICMPHeader(log, p); else - LogNetData(log, p->ptrs.ip_api.ip_data(), p->ptrs.ip_api.pay_len(), NULL); + LogNetData(log, p->ptrs.ip_api.ip_data(), p->ptrs.ip_api.pay_len(), p); break; default: @@ -1865,20 +1775,6 @@ void LogPayload(TextLog* log, Packet* p) /* dump the application layer data */ if (SnortConfig::output_app_data() && !SnortConfig::verbose_byte_dump()) { -#ifdef REG_TEST - const uint8_t* tmp_data = 0; - uint16_t tmp_dsize = 0; - - if ( p->proto_bits & PROTO_BIT__ICMP_EMBED ) - { - tmp_data = p->data; - tmp_dsize = p->dsize; - p->data = p->layers[p->num_layers - 1].start; - - // layer.length may be layer's length, not the actual length - p->dsize = (uint16_t)((tmp_data - p->data) + tmp_dsize); - } -#endif if (SnortConfig::output_char_data()) { LogCharData(log, (char*)p->data, p->dsize); @@ -1895,44 +1791,32 @@ void LogPayload(TextLog* log, Packet* p) } else { - LogNetData(log, p->data, p->dsize, NULL); + LogNetData(log, p->data, p->dsize, p); if (!IsJSNormData(p->flow)) { TextLog_Print(log, "%s\n", "Normalized JavaScript for this packet"); - LogNetData(log, g_file_data.data, g_file_data.len, NULL); + LogNetData(log, g_file_data.data, g_file_data.len, p); } else if (!IsGzipData(p->flow)) { TextLog_Print(log, "%s\n", "Decompressed Data for this packet"); - LogNetData(log, g_file_data.data, g_file_data.len, NULL); + LogNetData(log, g_file_data.data, g_file_data.len, p); } } - -#ifdef REG_TEST - if ( p->proto_bits & PROTO_BIT__ICMP_EMBED ) - { - p->data = tmp_data; - p->dsize = tmp_dsize; - } -#endif } else if (SnortConfig::verbose_byte_dump()) { LogNetData(log, p->pkt, p->pkth->caplen, p); } -#ifdef REG_TEST - TextLog_Print(log, "\n%s\n\n", SEPARATOR); -#endif } /*-------------------------------------------------------------------- * ARP stuff cloned from log.c + * FIXIT-L these must be converted to use TextLog (or just deleted) *-------------------------------------------------------------------- */ #if 0 -// these must be converted to use TextLog -// (or just deleted) /**************************************************************************** * * Function: PrintEapolKey(FILE *) diff --git a/src/log/log_text.h b/src/log/log_text.h index 0da2db3e5..ddf7f00eb 100644 --- a/src/log/log_text.h +++ b/src/log/log_text.h @@ -58,16 +58,20 @@ void LogIPPkt(TextLog*, Packet*); void LogPayload(TextLog*, Packet*); void LogNetData(TextLog*, const uint8_t* data, const int len, Packet*); +void LogDiv(TextLog*); void LogTimeStamp(TextLog*, Packet*); + void LogTrHeader(TextLog*, Packet*); void Log2ndHeader(TextLog*, Packet*); void LogIpAddrs(TextLog*, Packet*); -SO_PUBLIC void LogIpOptions(TextLog*, const IP4Hdr*, uint16_t valid_ip4_len); -SO_PUBLIC void LogTcpOptions(TextLog*, const tcp::TCPHdr*, uint16_t valid_tcp_len); + void LogIPHeader(TextLog*, Packet*); void LogTCPHeader(TextLog*, Packet*); void LogUDPHeader(TextLog*, Packet*); void LogICMPHeader(TextLog*, Packet*); +SO_PUBLIC void LogIpOptions(TextLog*, const IP4Hdr*, uint16_t valid_ip4_len); +SO_PUBLIC void LogTcpOptions(TextLog*, const tcp::TCPHdr*, uint16_t valid_tcp_len); + #endif diff --git a/src/log/obfuscation.cc b/src/log/obfuscation.cc index 411828b04..d60baa183 100644 --- a/src/log/obfuscation.cc +++ b/src/log/obfuscation.cc @@ -39,11 +39,10 @@ extern "C" { # ifndef OBFUSCATION_TEST # define OBFUSCATION_TEST # endif -# define TraverseReassembled stream.traverse_stream_segments static int TraverseReassembled( -Packet*, -int (*)(DAQ_PktHdr_t*, uint8_t*, uint8_t*, uint32_t, void*), -void* + Packet*, + int (*)(DAQ_PktHdr_t*, uint8_t*, uint8_t*, uint32_t, void*), + void* ); #endif @@ -110,21 +109,25 @@ static inline int NumObfuscateMaxLenEntries(void); static inline int NumObfuscateSliceEntries(void); static inline ObRet ObfuscationEntryOverflow(ob_size_t); static inline int PayloadObfuscationRequired(Packet*); + static inline void SetObfuscationEntry(ObfuscationEntry*, Packet*, -ob_size_t, ob_size_t, ob_char_t); + ob_size_t, ob_size_t, ob_char_t); + static inline void SortObfuscationEntries(void); + static inline void SetObfuscationCallbackData( -ObfuscationCallbackData*, Packet*, ObfuscationCallback, void*); + ObfuscationCallbackData*, Packet*, ObfuscationCallback, void*); + static inline void SetObfuscationStreamCallbackData( -ObfuscationStreamCallbackData*, ObfuscationCallbackData*, -Packet*, ObfuscationCallback, void*); + ObfuscationStreamCallbackData*, ObfuscationCallbackData*, + Packet*, ObfuscationCallback, void*); static ObRet AddObfuscationEntry(Packet*, ob_size_t, ob_size_t, ob_char_t); static int ObfuscationEntrySort(const void*, const void*); + static ObRet TraverseObfuscationList(ObfuscationCallbackData*, -const DAQ_PktHdr_t*, const uint8_t*, ob_size_t); -static int ObfuscateStreamSegmentsCallback(DAQ_PktHdr_t*, -uint8_t*, uint8_t*, uint32_t, void*); + const DAQ_PktHdr_t*, const uint8_t*, ob_size_t); + static ObRet GetObfuscatedPayloadCallback(const DAQ_PktHdr_t*, const uint8_t*, ob_size_t, ob_char_t, void*); static void PrintObfuscationEntry(const ObfuscationEntry*, int); @@ -214,26 +217,12 @@ static ObRet OB_API_ObfuscatePacket(Packet* p, } // obfuscatePacketStreamSegments -static ObRet OB_API_ObfuscatePacketStreamSegments(Packet* p, - ObfuscationCallback user_callback, void* user_data) +// FIXIT-L traverse_reassembled() deleted +// this should also be deleted if it is no longer needed +static ObRet OB_API_ObfuscatePacketStreamSegments(Packet*, + ObfuscationCallback, void*) { - ObfuscationStreamCallbackData stream_callback_data; - ObfuscationCallbackData callback_data; - - if (!PayloadObfuscationRequired(p)) - return OB_RET_ERROR; - - SortObfuscationEntries(); - SetObfuscationStreamCallbackData(&stream_callback_data, &callback_data, - p, user_callback, user_data); - - if (stream.traverse_stream_segments(p, ObfuscateStreamSegmentsCallback, - (void*)&stream_callback_data) == -1) - { - return OB_RET_ERROR; - } - - return OB_RET_SUCCESS; + return OB_RET_ERROR; } // getObfuscatedPayload @@ -887,73 +876,6 @@ static ObRet TraverseObfuscationList(ObfuscationCallbackData* data, return OB_RET_SUCCESS; } -/******************************************************************************* - * Function: ObfuscateStreamSegmentsCallback() - * - * Stream API callback for traverse_stream_segments. - * - * Arguments - * DAQ_PktHdr_t *pkth - * The pcap header information associated with the segment packet. - * uint8_t *pkt - * Pointer to the segment packet data starting at packet headers - * uint8_t *payload - * Pointer to the segment payload data to be obfuscated - * uint32_t - * The sequence number of this segment - * void *data - * The ObfuscationCallBack data - * - * Returns - * Per stream api traverse_reassembled: - * 0 if obfuscation was successful. - * -1 if we had to bail on the obfuscation due to the user callback - * telling us to - this should tell traverse_stream_segments to stop - * traversing and not call this anymore. - * - ******************************************************************************/ -static int ObfuscateStreamSegmentsCallback(DAQ_PktHdr_t* pkth, - uint8_t* pkt, uint8_t* payload, uint32_t seq_num, void* data) -{ - ObfuscationStreamCallbackData* callback_data = - (ObfuscationStreamCallbackData*)data; - ob_size_t payload_size = (uint16_t)(pkth->caplen - (payload - pkt)); - - if ((pkt >= payload) || ((ob_size_t)(payload - pkt) > pkth->caplen)) - return -1; - - if (callback_data->data->user_callback(pkth, pkt, (ob_size_t)(payload - pkt), - 0, callback_data->data->user_data) != OB_RET_SUCCESS) - { - return -1; - } - - /* If we get an overlap set the entry index to where the last packet - * started, else set the last entry index to the end of the one for - * the last segment */ - if (callback_data->next_seq > seq_num) - { - callback_data->data->entry_index = callback_data->last_entry_index; - callback_data->data->total_offset -= - (ob_size_t)(callback_data->next_seq - seq_num); - } - else - { - callback_data->last_entry_index = callback_data->data->entry_index; - } - - if (TraverseObfuscationList(callback_data->data, NULL, - payload, payload_size) != OB_RET_SUCCESS) - { - return -1; - } - - /* Update next expected sequence number */ - callback_data->next_seq = seq_num + payload_size; - - return 0; -} - /******************************************************************************* * Function: GetObfuscationPayloadCallback() * @@ -1445,7 +1367,6 @@ int main(int argc, char* argv[]) packet.reset(); packet.pseudo_type = 0; - packet.max_dsize = 0; packet.user_policy_id = 0; packet.iplist_id = 0; packeet.ps_proto = 0; @@ -1455,6 +1376,7 @@ int main(int argc, char* argv[]) pkthtmp->caplen = payload_bytes; pkthtmp->ts.tv_sec = 0; pkthtmp->ts.tv_usec = 0; + packet.packet_flags |= PKT_PAYLOAD_OBFUSCATE; packet.data = payload; packet.dsize = payload_bytes; diff --git a/src/log/text_log.cc b/src/log/text_log.cc index 6503b397c..1e4e4388c 100644 --- a/src/log/text_log.cc +++ b/src/log/text_log.cc @@ -1,6 +1,6 @@ //-------------------------------------------------------------------------- // Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved. -// Copyright (C) 2003-2013 Sourcefire, Inc. +// Copyright (C) 2007-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 diff --git a/src/loggers/CMakeLists.txt b/src/loggers/CMakeLists.txt index 714c2f2d2..a6a281fe6 100644 --- a/src/loggers/CMakeLists.txt +++ b/src/loggers/CMakeLists.txt @@ -11,7 +11,6 @@ set (PLUGIN_LIST alert_fast.cc alert_full.cc alert_syslog.cc - alert_test.cc alert_unixsock.cc log_null.cc log_pcap.cc @@ -44,7 +43,6 @@ else (STATIC_LOGGERS) add_shared_library(alert_fast loggers alert_fast.cc) add_shared_library(alert_full loggers alert_full.cc) add_shared_library(alert_syslog loggers alert_syslog.cc) - add_shared_library(alert_test loggers alert_test.cc) add_shared_library(alert_unixsock loggers alert_unixsock.cc) add_shared_library(log_null loggers log_null.cc) add_shared_library(log_pcap loggers log_pcap.cc) diff --git a/src/loggers/Makefile.am b/src/loggers/Makefile.am index 786b0807f..0d938f643 100644 --- a/src/loggers/Makefile.am +++ b/src/loggers/Makefile.am @@ -12,7 +12,6 @@ alert_csv.cc \ alert_fast.cc \ alert_full.cc \ alert_syslog.cc \ -alert_test.cc \ alert_unixsock.cc \ log_null.cc \ log_pcap.cc \ @@ -50,11 +49,6 @@ libalert_syslog_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO libalert_syslog_la_LDFLAGS = -export-dynamic -shared libalert_syslog_la_SOURCES = alert_syslog.cc -ehlib_LTLIBRARIES += libalert_test.la -libalert_test_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO -libalert_test_la_LDFLAGS = -export-dynamic -shared -libalert_test_la_SOURCES = alert_test.cc - ehlib_LTLIBRARIES += libalert_unixsock.la libalert_unixsock_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO libalert_unixsock_la_LDFLAGS = -export-dynamic -shared diff --git a/src/loggers/alert_csv.cc b/src/loggers/alert_csv.cc index c3617f61d..cdd3fbc91 100644 --- a/src/loggers/alert_csv.cc +++ b/src/loggers/alert_csv.cc @@ -1,8 +1,5 @@ //-------------------------------------------------------------------------- // Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved. -// Copyright (C) 2002-2013 Sourcefire, Inc. -// Copyright (C) 1998-2002 Martin Roesch -// Copyright (C) 2001 Brian Caswell // // 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 @@ -19,6 +16,14 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //-------------------------------------------------------------------------- +// alert_csv.cc author Russ Combs +// +// this a complete rewrite of the work originally done by: +// +// 1998-2002 Martin Roesch +// 2001-2001 Brian Caswell +// 2002-2013 Sourcefire, Inc. + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -29,15 +34,16 @@ #include #include +#include #include "framework/logger.h" #include "framework/module.h" #include "protocols/packet.h" -#include "parser.h" -#include "snort_debug.h" -#include "mstring.h" -#include "util.h" -#include "log.h" +#include "detection/signature.h" +#include "main/snort_debug.h" +#include "utils/util.h" +#include "utils/stats.h" +#include "log/log.h" #include "log/text_log.h" #include "log/log_text.h" #include "protocols/tcp.h" @@ -45,6 +51,7 @@ #include "protocols/icmp4.h" #include "protocols/icmp6.h" #include "protocols/eth.h" +#include "packet_io/active.h" #define LOG_BUFFER (4*K_BYTES) @@ -55,33 +62,317 @@ static THREAD_LOCAL TextLog* csv_log; using namespace std; +//------------------------------------------------------------------------- +// field formatting functions +//------------------------------------------------------------------------- + +struct Args +{ + Packet* pkt; + const char* msg; + Event* event; +}; + +static void ff_action(Args&) +{ + TextLog_Puts(csv_log, Active_GetDispositionString()); +} + +static void ff_dir(Args& a) +{ + const char* dir; + + if ( a.pkt->packet_flags & PKT_FROM_CLIENT ) + dir = "C2S"; + else if ( a.pkt->packet_flags & PKT_FROM_SERVER ) + dir = "S2C"; + else + dir = "UNK"; + + TextLog_Puts(csv_log, dir); +} + +static void ff_dgm_len(Args& a) +{ + if (a.pkt->has_ip()) + TextLog_Print(csv_log, "%d", a.pkt->ptrs.ip_api.dgram_len()); + else + TextLog_Print(csv_log, "%d", a.pkt->dsize); +} + +static void ff_dst_addr(Args& a) +{ + if ( a.pkt->has_ip() or a.pkt->is_data() ) + TextLog_Puts(csv_log, inet_ntoa(a.pkt->ptrs.ip_api.get_dst())); +} + +static void ff_dst_ap(Args& a) +{ + const char* addr = ""; + unsigned port = 0; + + if ( a.pkt->has_ip() or a.pkt->is_data() ) + addr = sfip_to_str(a.pkt->ptrs.ip_api.get_dst()); + + if ( a.pkt->proto_bits & (PROTO_BIT__TCP|PROTO_BIT__UDP) ) + port = a.pkt->ptrs.dp; + + TextLog_Print(csv_log, "%s:%d", addr, port); +} + +static void ff_dst_port(Args& a) +{ + if ( a.pkt->proto_bits & (PROTO_BIT__TCP|PROTO_BIT__UDP) ) + TextLog_Print(csv_log, "%d", a.pkt->ptrs.dp); +} + +static void ff_eth_dst(Args& a) +{ + if ( !(a.pkt->proto_bits & PROTO_BIT__ETH) ) + return; + + const eth::EtherHdr* eh = layer::get_eth_layer(a.pkt); + + TextLog_Print(csv_log, "%02X:%02X:%02X:%02X:%02X:%02X", eh->ether_dst[0], + eh->ether_dst[1], eh->ether_dst[2], eh->ether_dst[3], + eh->ether_dst[4], eh->ether_dst[5]); +} + +static void ff_eth_len(Args& a) +{ + if ( !(a.pkt->proto_bits & PROTO_BIT__ETH) ) + return; + + TextLog_Print(csv_log, "0x%X", a.pkt->pkth->pktlen); +} + +static void ff_eth_src(Args& a) +{ + if ( !(a.pkt->proto_bits & PROTO_BIT__ETH) ) + return; + + const eth::EtherHdr* eh = layer::get_eth_layer(a.pkt); + + TextLog_Print(csv_log, "%02X:%02X:%02X:%02X:%02X:%02X", eh->ether_src[0], + eh->ether_src[1], eh->ether_src[2], eh->ether_src[3], + eh->ether_src[4], eh->ether_src[5]); +} + +static void ff_eth_type(Args& a) +{ + if ( !(a.pkt->proto_bits & PROTO_BIT__ETH) ) + return; + + const eth::EtherHdr* eh = layer::get_eth_layer(a.pkt); + TextLog_Print(csv_log, "0x%X", ntohs(eh->ether_type)); +} + +static void ff_gid(Args& a) +{ + if (a.event ) + TextLog_Print(csv_log, "%u", a.event->sig_info->generator); +} + +static void ff_icmp_code(Args& a) +{ + if (a.pkt->ptrs.icmph ) + TextLog_Print(csv_log, "%d", a.pkt->ptrs.icmph->code); +} + +static void ff_icmp_id(Args& a) +{ + if (a.pkt->ptrs.icmph ) + TextLog_Print(csv_log, "%d", ntohs(a.pkt->ptrs.icmph->s_icmp_id)); +} + +static void ff_icmp_seq(Args& a) +{ + if (a.pkt->ptrs.icmph ) + TextLog_Print(csv_log, "%d", ntohs(a.pkt->ptrs.icmph->s_icmp_seq)); +} + +static void ff_icmp_type(Args& a) +{ + if (a.pkt->ptrs.icmph ) + TextLog_Print(csv_log, "%d", a.pkt->ptrs.icmph->type); +} + +static void ff_ip_id(Args& a) +{ + if (a.pkt->has_ip()) + TextLog_Print(csv_log, "%u", a.pkt->ptrs.ip_api.id()); +} + +static void ff_ip_len(Args& a) +{ + if (a.pkt->has_ip()) + TextLog_Print(csv_log, "%d", a.pkt->ptrs.ip_api.pay_len()); +} + +static void ff_msg(Args& a) +{ + TextLog_Quote(csv_log, a.msg); +} + +static void ff_pkt_gen(Args& a) +{ + TextLog_Puts(csv_log, a.pkt->get_pseudo_type()); +} + +static void ff_pkt_num(Args&) +{ + TextLog_Print(csv_log, STDu64, pc.total_from_daq); +} + +static void ff_proto(Args& a) +{ + TextLog_Puts(csv_log, a.pkt->get_type()); +} + +static void ff_rev(Args& a) +{ + if (a.event ) + TextLog_Print(csv_log, "%u", a.event->sig_info->rev); +} + +static void ff_rule(Args& a) +{ + TextLog_Print(csv_log, "%u:%u:%u", + a.event->sig_info->generator, a.event->sig_info->id, a.event->sig_info->rev); +} + +static void ff_sid(Args& a) +{ + if (a.event ) + TextLog_Print(csv_log, "%u", a.event->sig_info->id); +} + +static void ff_src_addr(Args& a) +{ + if ( a.pkt->has_ip() or a.pkt->is_data() ) + TextLog_Puts(csv_log, inet_ntoa(a.pkt->ptrs.ip_api.get_src())); +} + +static void ff_src_ap(Args& a) +{ + const char* addr = ""; + unsigned port = 0; + + if ( a.pkt->has_ip() or a.pkt->is_data() ) + addr = sfip_to_str(a.pkt->ptrs.ip_api.get_src()); + + if ( a.pkt->proto_bits & (PROTO_BIT__TCP|PROTO_BIT__UDP) ) + port = a.pkt->ptrs.sp; + + TextLog_Print(csv_log, "%s:%d", addr, port); +} + +static void ff_src_port(Args& a) +{ + if ( a.pkt->proto_bits & (PROTO_BIT__TCP|PROTO_BIT__UDP) ) + TextLog_Print(csv_log, "%d", a.pkt->ptrs.sp); +} + +static void ff_tcp_ack(Args& a) +{ + if (a.pkt->ptrs.tcph ) + TextLog_Print(csv_log, "0x%lX", (u_long)ntohl(a.pkt->ptrs.tcph->th_ack)); +} + +static void ff_tcp_flags(Args& a) +{ + if (a.pkt->ptrs.tcph ) + { + char tcpFlags[9]; + CreateTCPFlagString(a.pkt->ptrs.tcph, tcpFlags); + TextLog_Print(csv_log, "%s", tcpFlags); + } +} + +static void ff_tcp_len(Args& a) +{ + if (a.pkt->ptrs.tcph ) + TextLog_Print(csv_log, "%d", (a.pkt->ptrs.tcph->off())); +} + +static void ff_tcp_seq(Args& a) +{ + if (a.pkt->ptrs.tcph ) + TextLog_Print(csv_log, "0x%lX", (u_long)ntohl(a.pkt->ptrs.tcph->th_seq)); +} + +static void ff_tcp_win(Args& a) +{ + if (a.pkt->ptrs.tcph ) + TextLog_Print(csv_log, "0x%X", ntohs(a.pkt->ptrs.tcph->th_win)); +} + +static void ff_tos(Args& a) +{ + if (a.pkt->has_ip()) + TextLog_Print(csv_log, "%d", a.pkt->ptrs.ip_api.tos()); +} + +static void ff_ttl(Args& a) +{ + if (a.pkt->has_ip()) + TextLog_Print(csv_log, "%d",a.pkt->ptrs.ip_api.ttl()); +} + +static void ff_timestamp(Args& a) +{ + LogTimeStamp(csv_log, a.pkt); +} + +static void ff_udp_len(Args& a) +{ + if (a.pkt->ptrs.udph ) + TextLog_Print(csv_log, "%d", ntohs(a.pkt->ptrs.udph->uh_len)); +} + //------------------------------------------------------------------------- // module stuff //------------------------------------------------------------------------- +typedef void (*CsvFunc)(Args&); + +static const CsvFunc csv_func[] = +{ + ff_action, ff_dir, ff_dgm_len, ff_dst_addr, ff_dst_ap, ff_dst_port, + ff_eth_dst, ff_eth_len, ff_eth_src, ff_eth_type, ff_gid, + ff_icmp_code, ff_icmp_id, ff_icmp_seq, ff_icmp_type, + ff_ip_id, ff_ip_len, ff_msg, ff_pkt_gen, ff_pkt_num, ff_proto, + ff_rev, ff_rule, ff_sid, ff_src_addr, ff_src_ap, ff_src_port, + ff_tcp_ack, ff_tcp_flags, ff_tcp_len, ff_tcp_seq, ff_tcp_win, + ff_timestamp, ff_tos, ff_ttl, ff_udp_len +}; + #define csv_range \ - "timestamp | gid | sid | rev | msg | proto | " \ - "src_addr | dst_addr | src_port | dst_port | " \ - "eth_src | eth_dst | eth_type | eth_len | " \ - "ttl | tos | id | ip_len | dgm_len | " \ - "icmp_type | icmp_code | icmp_id | icmp_seq | " \ - "tcp_flags | tcp_seq | tcp_ack | tcp_len | tcp_win | " \ - "udp_len" + "action | dir | dgm_len | dst_addr | dst_ap | dst_port | " \ + "eth_dst | eth_len | eth_src | eth_type | gid | " \ + "icmp_code | icmp_id | icmp_seq | icmp_type | " \ + "ip_id | ip_len | msg | pkt_gen | pkt_num | proto | " \ + "rev | rule | sid | src_addr | src_ap | src_port | " \ + "tcp_ack | tcp_flags | tcp_len | tcp_seq | tcp_win | " \ + "timestamp | tos | ttl | udp_len" #define csv_deflt \ - "timestamp gid sid rev src_addr src_port dst_addr dst_port" + "timestamp pkt_num proto pkt_gen dgm_len dir src_ap dst_ap rule action" static const Parameter s_params[] = { { "file", Parameter::PT_BOOL, nullptr, "false", "output to " F_NAME " instead of stdout" }, - { "csv", Parameter::PT_MULTI, csv_range, csv_deflt, + { "fields", Parameter::PT_MULTI, csv_range, csv_deflt, "selected fields will be output in given order left to right" }, { "limit", Parameter::PT_INT, "0:", "0", "set limit (0 is unlimited)" }, + { "separator", Parameter::PT_STRING, nullptr, ", ", + "separate fields with this character sequence" }, + // FIXIT-M provide PT_UNITS that converts to multiplier automatically { "units", Parameter::PT_ENUM, "B | K | M | G", "B", "bytes | KB | MB | GB" }, @@ -103,9 +394,10 @@ public: public: bool file; - string csvargs; + string sep; unsigned long limit; unsigned units; + vector fields; }; bool CsvModule::set(const char*, Value& v, SnortConfig*) @@ -113,12 +405,22 @@ bool CsvModule::set(const char*, Value& v, SnortConfig*) if ( v.is("file") ) file = v.get_bool(); - else if ( v.is("csv") ) - csvargs = SnortStrdup(v.get_string()); + else if ( v.is("fields") ) + { + string tok; + v.set_first_token(); + fields.clear(); + + while ( v.get_next_token(tok) ) + fields.push_back(csv_func[Parameter::index(csv_range, tok.c_str())]); + } else if ( v.is("limit") ) limit = v.get_long(); + else if ( v.is("separator") ) + sep = v.get_string(); + else if ( v.is("units") ) units = v.get_long(); @@ -133,7 +435,17 @@ bool CsvModule::begin(const char*, int, SnortConfig*) file = false; limit = 0; units = 0; - csvargs = csv_deflt; + sep = ", "; + + if ( fields.empty() ) + { + Value v(csv_deflt); + string tok; + v.set_first_token(); + + while ( v.get_next_token(tok) ) + fields.push_back(csv_func[Parameter::index(csv_range, tok.c_str())]); + } return true; } @@ -153,7 +465,6 @@ class CsvLogger : public Logger { public: CsvLogger(CsvModule*); - ~CsvLogger(); void open() override; void close() override; @@ -163,20 +474,16 @@ public: public: string file; unsigned long limit; - char** args; - int numargs; + vector fields; + string sep; }; CsvLogger::CsvLogger(CsvModule* m) { file = m->file ? F_NAME : "stdout"; limit = m->limit; - args = mSplit(m->csvargs.c_str(), " \n\t", 0, &numargs, 0); -} - -CsvLogger::~CsvLogger() -{ - mSplitFree(&args, numargs); + sep = m->sep; + fields = std::move(m->fields); } void CsvLogger::open() @@ -192,209 +499,17 @@ void CsvLogger::close() void CsvLogger::alert(Packet* p, const char* msg, Event* event) { - int num; - char* type; - char tcpFlags[9]; - const eth::EtherHdr* eh = nullptr; - - assert(p); + Args a = { p, msg, event }; + bool first = true; - if (p->proto_bits & PROTO_BIT__ETH) - eh = layer::get_eth_layer(p); - - // TBD an enum would be an improvement here - for (num = 0; num < numargs; num++) + for ( CsvFunc f : fields ) { - type = args[num]; - - if (!strcasecmp("timestamp", type)) - { - LogTimeStamp(csv_log, p); - } - else if (!strcasecmp("gid", type)) - { - if (event != NULL) - TextLog_Print(csv_log, "%lu", (unsigned long)event->sig_info->generator); - } - else if (!strcasecmp("sid", type)) - { - if (event != NULL) - TextLog_Print(csv_log, "%lu", (unsigned long)event->sig_info->id); - } - else if (!strcasecmp("rev", type)) - { - if (event != NULL) - TextLog_Print(csv_log, "%lu", (unsigned long)event->sig_info->rev); - } - else if (!strcasecmp("msg", type)) - { - TextLog_Quote(csv_log, msg); /* Don't fatal */ - } - else if (!strcasecmp("proto", type)) - { - // api returns zero if invalid - switch (p->type()) - { - case PktType::UDP: - TextLog_Puts(csv_log, "UDP"); - break; - case PktType::TCP: - TextLog_Puts(csv_log, "TCP"); - break; - case PktType::ICMP: - TextLog_Puts(csv_log, "ICMP"); - break; - default: - break; - } - } - else if (!strcasecmp("eth_src", type)) - { - if (eh) - { - TextLog_Print(csv_log, "%02X:%02X:%02X:%02X:%02X:%02X", eh->ether_src[0], - eh->ether_src[1], eh->ether_src[2], eh->ether_src[3], - eh->ether_src[4], eh->ether_src[5]); - } - } - else if (!strcasecmp("eth_dst", type)) - { - if (eh) - { - TextLog_Print(csv_log, "%02X:%02X:%02X:%02X:%02X:%02X", eh->ether_dst[0], - eh->ether_dst[1], eh->ether_dst[2], eh->ether_dst[3], - eh->ether_dst[4], eh->ether_dst[5]); - } - } - else if (!strcasecmp("eth_type", type)) - { - if (eh != NULL) - TextLog_Print(csv_log, "0x%X", ntohs(eh->ether_type)); - } - else if (!strcasecmp("eth_len", type)) - { - if (eh != NULL) - TextLog_Print(csv_log, "0x%X", p->pkth->pktlen); - } - else if (!strcasecmp("udp_len", type)) - { - if (p->ptrs.udph != NULL) - TextLog_Print(csv_log, "%d", ntohs(p->ptrs.udph->uh_len)); - } - else if (!strcasecmp("src_port", type)) - { - // api return 0 if invalid - switch (p->type()) - { - case PktType::UDP: - case PktType::TCP: - TextLog_Print(csv_log, "%d", p->ptrs.sp); - break; - default: - break; - } - } - else if (!strcasecmp("dst_port", type)) - { - switch (p->type()) - { - case PktType::UDP: - case PktType::TCP: - TextLog_Print(csv_log, "%d", p->ptrs.dp); - break; - default: - break; - } - } - else if (!strcasecmp("src_addr", type)) - { - if (p->has_ip()) - TextLog_Puts(csv_log, inet_ntoa(p->ptrs.ip_api.get_src())); - } - else if (!strcasecmp("dst_addr", type)) - { - if (p->has_ip()) - TextLog_Puts(csv_log, inet_ntoa(p->ptrs.ip_api.get_dst())); - } - else if (!strcasecmp("icmp_type", type)) - { - if (p->ptrs.icmph != NULL) - TextLog_Print(csv_log, "%d", p->ptrs.icmph->type); - } - else if (!strcasecmp("icmp_code", type)) - { - if (p->ptrs.icmph != NULL) - TextLog_Print(csv_log, "%d", p->ptrs.icmph->code); - } - else if (!strcasecmp("icmp_id", type)) - { - if (p->ptrs.icmph != NULL) - TextLog_Print(csv_log, "%d", ntohs(p->ptrs.icmph->s_icmp_id)); - } - else if (!strcasecmp("icmp_seq", type)) - { - if (p->ptrs.icmph != NULL) - TextLog_Print(csv_log, "%d", ntohs(p->ptrs.icmph->s_icmp_seq)); - } - else if (!strcasecmp("ttl", type)) - { - if (p->has_ip()) - TextLog_Print(csv_log, "%d",p->ptrs.ip_api.ttl()); - } - else if (!strcasecmp("tos", type)) - { - if (p->has_ip()) - TextLog_Print(csv_log, "%d", p->ptrs.ip_api.tos()); - } - else if (!strcasecmp("id", type)) - { - if (p->has_ip()) - TextLog_Print(csv_log, "%u", p->ptrs.ip_api.id()); - } - else if (!strcasecmp("ip_len", type)) - { - if (p->has_ip()) - TextLog_Print(csv_log, "%d", p->ptrs.ip_api.pay_len()); - } - else if (!strcasecmp("dgm_len", type)) - { - if (p->has_ip()) - { - // XXX might cause a bug when IPv6 is printed? - TextLog_Print(csv_log, "%d", p->ptrs.ip_api.dgram_len()); - } - } - else if (!strcasecmp("tcp_seq", type)) - { - if (p->ptrs.tcph != NULL) - TextLog_Print(csv_log, "0x%lX", (u_long)ntohl(p->ptrs.tcph->th_seq)); - } - else if (!strcasecmp("tcp_ack", type)) - { - if (p->ptrs.tcph != NULL) - TextLog_Print(csv_log, "0x%lX", (u_long)ntohl(p->ptrs.tcph->th_ack)); - } - else if (!strcasecmp("tcp_len", type)) - { - if (p->ptrs.tcph != NULL) - TextLog_Print(csv_log, "%d", (p->ptrs.tcph->off())); - } - else if (!strcasecmp("tcp_win", type)) - { - if (p->ptrs.tcph != NULL) - TextLog_Print(csv_log, "0x%X", ntohs(p->ptrs.tcph->th_win)); - } - else if (!strcasecmp("tcp_flags",type)) - { - if (p->ptrs.tcph != NULL) - { - CreateTCPFlagString(p->ptrs.tcph, tcpFlags); - TextLog_Print(csv_log, "%s", tcpFlags); - } - } - - if (num < numargs - 1) - TextLog_Putc(csv_log, ','); + if ( first ) + first = false; + else + TextLog_Puts(csv_log, sep.c_str()); + + f(a); } TextLog_NewLine(csv_log); diff --git a/src/loggers/alert_fast.cc b/src/loggers/alert_fast.cc index 2162c2883..8dce8765e 100644 --- a/src/loggers/alert_fast.cc +++ b/src/loggers/alert_fast.cc @@ -153,7 +153,9 @@ bool FastModule::end(const char*, int, SnortConfig*) //------------------------------------------------------------------------- // logger stuff //------------------------------------------------------------------------- -static const char* s_dispos[] = { " [Allow]", " [CDrop]", " [WDrop]", " [Drop]", " [FDrop]" }; + +static const char* s_dispos[] = +{ " [Allow]", " [CDrop]", " [WDrop]", " [Drop]", " [FDrop]" }; class FastLogger : public Logger { @@ -190,71 +192,17 @@ void FastLogger::close() TextLog_Term(fast_log); } -#ifdef REG_TEST -static void LogReassembly(const Packet* p) -{ - /* Log whether or not this is reassembled data - only indicate - * if we're actually going to show any of the payload */ - if ( !SnortConfig::output_app_data() || !p->dsize || !p->is_cooked() ) - return; - - switch ( p->pseudo_type ) - { - case PSEUDO_PKT_SMB_SEG: - TextLog_Print(fast_log, "%s\n", "SMB desegmented packet"); - break; - case PSEUDO_PKT_DCE_SEG: - TextLog_Print(fast_log, "%s\n", "DCE/RPC desegmented packet"); - break; - case PSEUDO_PKT_DCE_FRAG: - TextLog_Print(fast_log, "%s\n", "DCE/RPC defragmented packet"); - break; - case PSEUDO_PKT_SMB_TRANS: - TextLog_Print(fast_log, "%s\n", "SMB Transact reassembled packet"); - break; - case PSEUDO_PKT_DCE_RPKT: - TextLog_Print(fast_log, "%s\n", "DCE/RPC reassembled packet"); - break; - case PSEUDO_PKT_TCP: - TextLog_Print(fast_log, "%s\n", "Stream reassembled packet"); - break; - case PSEUDO_PKT_IP: - TextLog_Print(fast_log, "%s\n", "Frag reassembled packet"); - break; - default: - // FIXIT do we get here for portscan or sdf? - break; - } -} - -#endif - -#ifndef REG_TEST -static const char* get_pkt_type(Packet* p) -{ - switch ( p->ptrs.get_pkt_type() ) - { - case PktType::IP: return "IP"; - case PktType::ICMP: return "ICMP"; - case PktType::TCP: return "TCP"; - case PktType::UDP: return "UDP"; - default: break; - } - return "error"; -} -#endif - void FastLogger::alert(Packet* p, const char* msg, Event* event) { - tActiveDrop dispos = Active_GetDisposition(); LogTimeStamp(fast_log, p); + tActiveDrop dispos = Active_GetDisposition(); if ( dispos > ACTIVE_ALLOW ) { if ( dispos > ACTIVE_DROP ) dispos = ACTIVE_DROP; - TextLog_Puts(fast_log, s_dispos[dispos]); + TextLog_Print(fast_log, " %s", s_dispos[dispos]); } { @@ -283,42 +231,28 @@ void FastLogger::alert(Packet* p, const char* msg, Event* event) } if (msg != NULL) - { -#ifdef REG_TEST - string tmp = msg + 1; - tmp.pop_back(); - TextLog_Puts(fast_log, tmp.c_str()); -#else TextLog_Puts(fast_log, msg); -#endif - } + TextLog_Puts(fast_log, " [**] "); } /* print the packet header to the alert file */ { LogPriorityData(fast_log, event, 0); -#ifndef REG_TEST - TextLog_Print(fast_log, "{%s} ", get_pkt_type(p)); -#else - TextLog_Print(fast_log, "{%s} ", protocol_names[p->get_ip_proto_next()]); -#endif + TextLog_Print(fast_log, "{%s} ", p->get_type()); LogIpAddrs(fast_log, p); } if ( packet || SnortConfig::output_app_data() ) { TextLog_NewLine(fast_log); -#ifdef REG_TEST - LogReassembly(p); -#endif if (p->has_ip()) LogIPPkt(fast_log, p); else - LogPayload(fast_log, p); + LogNetData(fast_log, p->data, p->dsize, p); #if 0 - // FIXIT-L -J LogArpHeader unimplemented + // FIXIT-L LogArpHeader unimplemented else if (p->proto_bits & PROTO_BIT__ARP) LogArpHeader(fast_log, p); #endif diff --git a/src/loggers/alert_full.cc b/src/loggers/alert_full.cc index bcbe9afb3..f27757c0a 100644 --- a/src/loggers/alert_full.cc +++ b/src/loggers/alert_full.cc @@ -208,6 +208,7 @@ void FullLogger::alert(Packet* p, const char* msg, Event* event) DEBUG_WRAP(DebugMessage(DEBUG_LOG, "Logging Alert data!\n"); ); LogTimeStamp(full_log, p); + TextLog_Putc(full_log, ' '); if (p && p->has_ip()) { diff --git a/src/loggers/alert_test.cc b/src/loggers/alert_test.cc deleted file mode 100644 index 25ece64cc..000000000 --- a/src/loggers/alert_test.cc +++ /dev/null @@ -1,248 +0,0 @@ -//-------------------------------------------------------------------------- -// Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved. -// Copyright (C) 2007-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. -//-------------------------------------------------------------------------- - -/* alert_test_ - * - * Output is tab delimited in the following order: - * packet count, gid, sid, rev, msg, session, rebuilt - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "snort_types.h" -#include "framework/logger.h" -#include "framework/module.h" -#include "event.h" -#include "protocols/packet.h" -#include "snort_debug.h" -#include "parser.h" -#include "util.h" -#include "log/log_text.h" -#include "log/text_log.h" -#include "utils/stats.h" - -#include -#include -#include -#include - -#include - -#define TEST_FLAG_MSG 0x01 -#define TEST_FLAG_SESSION 0x02 -#define TEST_FLAG_REBUILT 0x04 -#define TEST_FLAG_FILE 0x08 - -static THREAD_LOCAL TextLog* test_file = nullptr; - -using namespace std; - -#define S_NAME "alert_test" -#define F_NAME S_NAME ".txt" - -//------------------------------------------------------------------------- -// alert_test module -//------------------------------------------------------------------------- - -static const Parameter s_params[] = -{ - { "file", Parameter::PT_BOOL, nullptr, "false", - "output to " F_NAME " instead of stdout" }, - - { "rebuilt", Parameter::PT_BOOL, nullptr, "false", - "include type:count where type is S for stream and F for frag" }, - - { "session", Parameter::PT_BOOL, nullptr, "false", - "include src-dst each of form -addr:port" }, - - { "msg", Parameter::PT_BOOL, nullptr, "false", - "include alert msg" }, - - { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } -}; - -#define s_help \ - "output event in custom tsv format" - -class TestModule : public Module -{ -public: - TestModule() : Module(S_NAME, s_help, s_params) { } - - bool set(const char*, Value&, SnortConfig*) override; - bool begin(const char*, int, SnortConfig*) override; - -public: - unsigned flags; -}; - -bool TestModule::set(const char*, Value& v, SnortConfig*) -{ - if ( v.is("file") ) - { - if ( v.get_bool() ) - flags |= TEST_FLAG_FILE; - } - else if ( v.is("rebuilt") ) - { - if ( v.get_bool() ) - flags |= TEST_FLAG_REBUILT; - } - else if ( v.is("session") ) - { - if ( v.get_bool() ) - flags |= TEST_FLAG_SESSION; - } - else if ( v.is("msg") ) - { - if ( v.get_bool() ) - flags |= TEST_FLAG_MSG; - } - else - return false; - - return true; -} - -bool TestModule::begin(const char*, int, SnortConfig*) -{ - flags = 0; - return true; -} - -//------------------------------------------------------------------------- - -class TestLogger : public Logger -{ -public: - TestLogger(TestModule*); - - void open() override; - void close() override; - - void alert(Packet*, const char* msg, Event*) override; - -private: - unsigned flags; -}; - -TestLogger::TestLogger(TestModule* m) -{ - flags = m->flags; -} - -void TestLogger::open() -{ - const char* f = (flags & TEST_FLAG_FILE) ? F_NAME : "stdout"; - test_file = TextLog_Init(f); -} - -void TestLogger::close() -{ - TextLog_Term(test_file); -} - -void TestLogger::alert(Packet* p, const char* msg, Event* event) -{ - TextLog_Print(test_file, "" STDu64 "\t", pc.total_from_daq); - - if (event != NULL) - { - TextLog_Print(test_file, "%lu\t%lu\t%lu\t", - (unsigned long)event->sig_info->generator, - (unsigned long)event->sig_info->id, - (unsigned long)event->sig_info->rev); - } - - if (flags & TEST_FLAG_MSG) - { - if (msg != NULL) - TextLog_Print(test_file, "%s\t", msg); - } - - if (flags & TEST_FLAG_SESSION) - LogIpAddrs(test_file, p); - - if ( (flags & TEST_FLAG_REBUILT) && (p->packet_flags & PKT_PSEUDO) ) - { - const char* s; - switch ( p->pseudo_type ) - { - case PSEUDO_PKT_IP: s = "ip-defrag"; break; - case PSEUDO_PKT_TCP: s = "tcp-deseg"; break; - case PSEUDO_PKT_DCE_RPKT: s = "dce-pkt"; break; - case PSEUDO_PKT_DCE_SEG: s = "dce-deseg"; break; - case PSEUDO_PKT_DCE_FRAG: s = "dec-defrag"; break; - case PSEUDO_PKT_SMB_SEG: s = "smb-deseg"; break; - case PSEUDO_PKT_SMB_TRANS: s = "smb-trans"; break; - case PSEUDO_PKT_PS: s = "port_scan"; break; - case PSEUDO_PKT_SDF: s = "sdf"; break; - default: s = "pseudo pkt"; break; - } - TextLog_Print(test_file, "%s", s); - } - TextLog_Print(test_file, "\n"); - TextLog_Flush(test_file); -} - -//------------------------------------------------------------------------- - -static Module* mod_ctor() -{ return new TestModule; } - -static void mod_dtor(Module* m) -{ delete m; } - -static Logger* test_ctor(SnortConfig*, Module* mod) -{ return new TestLogger((TestModule*)mod); } - -static void test_dtor(Logger* p) -{ delete p; } - -static LogApi test_api -{ - { - PT_LOGGER, - sizeof(LogApi), - LOGAPI_VERSION, - 0, - API_RESERVED, - API_OPTIONS, - S_NAME, - s_help, - mod_ctor, - mod_dtor - }, - OUTPUT_TYPE_FLAG__ALERT, - test_ctor, - test_dtor -}; - -#ifdef BUILDING_SO -SO_PUBLIC const BaseApi* snort_plugins[] = -{ - &test_api.base, - nullptr -}; -#else -const BaseApi* alert_test = &test_api.base; -#endif - diff --git a/src/loggers/log_codecs.cc b/src/loggers/log_codecs.cc index b6eef99db..b30ba5860 100644 --- a/src/loggers/log_codecs.cc +++ b/src/loggers/log_codecs.cc @@ -29,12 +29,14 @@ #include #include "main/snort_types.h" +#include "main/snort_config.h" #include "framework/logger.h" #include "framework/module.h" #include "protocols/packet.h" #include "protocols/packet_manager.h" #include "detection/signature.h" #include "log/text_log.h" +#include "log/log_text.h" #include "utils/stats.h" static THREAD_LOCAL TextLog* test_file = nullptr; @@ -138,8 +140,6 @@ void CodecLogger::close() void CodecLogger::log(Packet* p, const char* msg, Event* e) { - std::string s = std::string(msg); - TextLog_Print(test_file, "pkt:" STDu64 "\t", pc.total_from_daq); if (e != NULL) @@ -159,6 +159,10 @@ void CodecLogger::log(Packet* p, const char* msg, Event* e) TextLog_NewLine(test_file); PacketManager::log_protocols(test_file, p); TextLog_NewLine(test_file); + + if ( p->dsize and SnortConfig::output_app_data() ) + LogNetData(test_file, p->data, p->dsize, p); + TextLog_NewLine(test_file); } diff --git a/src/loggers/log_pcap.cc b/src/loggers/log_pcap.cc index 23497b5c0..8da3c62f2 100644 --- a/src/loggers/log_pcap.cc +++ b/src/loggers/log_pcap.cc @@ -154,15 +154,6 @@ static inline size_t SizeOf(const DAQ_PktHdr_t* pkth) return PCAP_PKT_HDR_SZ + pkth->caplen; } -static int SizeOfCallback( - DAQ_PktHdr_t* pkth, uint8_t*, void* userdata) -{ - size_t* pSize = (size_t*)userdata; - (*pSize) += SizeOf(pkth); - - return 0; -} - static void LogTcpdumpSingle( LtdConfig* data, Packet* p, const char*, Event*) { @@ -180,35 +171,11 @@ static void LogTcpdumpSingle( } } -static int LogTcpdumpStreamCallback( - DAQ_PktHdr_t* pkth, uint8_t* packet_data, void*) -{ - pcap_dump((u_char*)context.dumpd, - (struct pcap_pkthdr*)pkth, - (u_char*)packet_data); - - return 0; -} - static void LogTcpdumpStream( - LtdConfig* data, Packet* p, const char*, Event*) + LtdConfig*, Packet*, const char*, Event*) { - size_t dumpSize = 0; - - stream.traverse_reassembled(p, SizeOfCallback, &dumpSize); - - if ( data->limit && (context.size + dumpSize > data->limit) ) - TcpdumpRollLogFile(data); - - stream.traverse_reassembled(p, LogTcpdumpStreamCallback, data); - - context.size += dumpSize; - - if (!SnortConfig::line_buffered_logging()) - { - /* we happen to know that pcap_dumper_t* is really just a FILE* */ - fflush( (FILE*)context.dumpd); - } +// FIXIT-L log reassembled stream data with original packet? +// (take original packet headers and append reassembled data) } static void TcpdumpInitLogFile(LtdConfig*, int /*nostamps?*/) diff --git a/src/loggers/loggers.cc b/src/loggers/loggers.cc index fcdf0ef89..df6ffd939 100644 --- a/src/loggers/loggers.cc +++ b/src/loggers/loggers.cc @@ -37,7 +37,6 @@ extern const BaseApi* alert_csv; extern const BaseApi* alert_fast; extern const BaseApi* alert_full; extern const BaseApi* alert_syslog; -extern const BaseApi* alert_test; extern const BaseApi* alert_unix_sock; extern const BaseApi* log_null; extern const BaseApi* log_pcap; @@ -56,7 +55,6 @@ const BaseApi* loggers[] = alert_fast, alert_full, alert_syslog, - alert_test, alert_unix_sock, // loggers log_null, diff --git a/src/loggers/unified2.cc b/src/loggers/unified2.cc index 8783bb3f8..1aa51289c 100644 --- a/src/loggers/unified2.cc +++ b/src/loggers/unified2.cc @@ -127,8 +127,6 @@ static THREAD_LOCAL char io_buffer[u2_buf_sz]; static void Unified2InitFile(Unified2Config*); static inline void Unified2RotateFile(Unified2Config*); static void _Unified2LogPacketAlert(Packet*, const char*, Unified2Config*, Event*); -static void _Unified2LogStreamAlert(Packet*, const char*, Unified2Config*, Event*); -static int Unified2LogStreamCallback(DAQ_PktHdr_t*, uint8_t*, void*); static void Unified2Write(uint8_t*, uint32_t, Unified2Config*); static void _AlertIP4_v2(Packet*, const char*, Unified2Config*, Event*); @@ -638,67 +636,6 @@ static void _Unified2LogPacketAlert( Unified2Write(write_pkt_buffer, write_len, config); } -/** - * Callback for the Stream reassembler to log packets - * - */ -static int Unified2LogStreamCallback(DAQ_PktHdr_t* pkth, - uint8_t* packet_data, void* userdata) -{ - Unified2LogCallbackData* unifiedData = (Unified2LogCallbackData*)userdata; - Serial_Unified2_Header hdr; - uint32_t write_len = sizeof(Serial_Unified2_Header) + sizeof(Serial_Unified2Packet) - 4; - - if (!userdata || !pkth || !packet_data) - return -1; - - write_len += pkth->caplen; - - if ( unifiedData->config->limit && - (u2.current + write_len) > unifiedData->config->limit ) - Unified2RotateFile(unifiedData->config); - - hdr.type = htonl(UNIFIED2_PACKET); - hdr.length = htonl(sizeof(Serial_Unified2Packet) - 4 + pkth->caplen); - - /* Event data will already be set */ - - unifiedData->logheader->packet_second = htonl((uint32_t)pkth->ts.tv_sec); - unifiedData->logheader->packet_microsecond = htonl((uint32_t)pkth->ts.tv_usec); - unifiedData->logheader->packet_length = htonl(pkth->caplen); - - if (SafeMemcpy(write_pkt_buffer, &hdr, sizeof(Serial_Unified2_Header), - write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS) - { - ErrorMessage("%s(%d) Failed to copy Serial_Unified2_Header. " - "Not writing unified2 event.\n", __FILE__, __LINE__); - return -1; - } - - if (SafeMemcpy(write_pkt_buffer + sizeof(Serial_Unified2_Header), - unifiedData->logheader, sizeof(Serial_Unified2Packet) - 4, - write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS) - { - ErrorMessage("%s(%d) Failed to copy Serial_Unified2Packet. " - "Not writing unified2 event.\n", __FILE__, __LINE__); - return -1; - } - - if (SafeMemcpy(write_pkt_buffer + sizeof(Serial_Unified2_Header) + - sizeof(Serial_Unified2Packet) - 4, - packet_data, pkth->caplen, - write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS) - { - ErrorMessage("%s(%d) Failed to copy packet data. " - "Not writing unified2 event.\n", __FILE__, __LINE__); - return -1; - } - - Unified2Write(write_pkt_buffer, write_len, unifiedData->config); - - return 0; -} - static ObRet Unified2LogObfuscationCallback(const DAQ_PktHdr_t* pkth, const uint8_t* packet_data, ob_size_t length, ob_char_t ob_char, void* userdata) @@ -788,59 +725,6 @@ static ObRet Unified2LogObfuscationCallback(const DAQ_PktHdr_t* pkth, return OB_RET_SUCCESS; } -/** - * Log a set of packets stored in the stream reassembler - * - */ -static void _Unified2LogStreamAlert( - Packet* p, const char*, Unified2Config* config, Event* event) -{ - Unified2LogCallbackData unifiedData; - Serial_Unified2Packet logheader; - - logheader.sensor_id = 0; - logheader.linktype = u2.base_proto; - - /* setup the event header */ - if (event != NULL) - { - logheader.event_id = htonl(event->event_reference); - logheader.event_second = htonl(event->ref_time.tv_sec); - } - else - { - logheader.event_id = 0; - logheader.event_second = 0; - } - - /* queue up the stream for logging */ - unifiedData.logheader = &logheader; - unifiedData.config = config; - unifiedData.event = event; - unifiedData.num_bytes = 0; - - if ((p != NULL) && (p->pkt != NULL) && (p->pkth != NULL) - && obApi->payloadObfuscationRequired(p)) - { - if (obApi->obfuscatePacketStreamSegments(p, Unified2LogObfuscationCallback, - (void*)&unifiedData) == OB_RET_SUCCESS) - { - /* Write the last record */ - if (unifiedData.num_bytes != 0) - Unified2Write(write_pkt_buffer, unifiedData.num_bytes, config); - return; - } - - /* Reset since we failed */ - unifiedData.num_bytes = 0; - } - - if (!p) - return; - - stream.traverse_reassembled(p, Unified2LogStreamCallback, &unifiedData); -} - /****************************************************************************** * Function: Unified2Write() * @@ -1214,7 +1098,9 @@ void U2Logger::log(Packet* p, const char* msg, Event* event) { DEBUG_WRAP(DebugMessage(DEBUG_LOG, "[*] Reassembled packet, dumping stream packets\n"); ); - _Unified2LogStreamAlert(p, msg, &config, event); + // FIXIT-L replace with reassembled stream data and + // optionally the first captured packet + //_Unified2LogStreamAlert(p, msg, &config, event); } else { diff --git a/src/main/modules.cc b/src/main/modules.cc index 92547e87c..22b913d41 100644 --- a/src/main/modules.cc +++ b/src/main/modules.cc @@ -658,9 +658,6 @@ static const Parameter output_params[] = { "logdir", Parameter::PT_STRING, nullptr, ".", "where to put log files (same as -l)" }, - { "nolog", Parameter::PT_BOOL, nullptr, "false", - "turn off logging (alerts still work, same as -N)" }, - { "obfuscate", Parameter::PT_BOOL, nullptr, "false", "obfuscate the logged IP addresses (same as -O)" }, @@ -710,9 +707,6 @@ bool OutputModule::set(const char*, Value& v, SnortConfig* sc) else if ( v.is("max_data") ) sc->event_trace_max = v.get_long(); - else if ( v.is("nolog") ) - v.update_mask(sc->output_flags, OUTPUT_FLAG__NO_LOG); - else if ( v.is("obfuscate") ) v.update_mask(sc->output_flags, OUTPUT_FLAG__OBFUSCATE); diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index 73097489d..706c11de9 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -521,14 +521,6 @@ bool SnortConfig::verify() return false; } - if ( (snort_conf->output_flags & OUTPUT_FLAG__NO_LOG) != - (output_flags & OUTPUT_FLAG__NO_LOG) ) - { - ErrorMessage("Snort Reload: Changing from log to no log or vice " - "versa requires a restart.\n"); - return false; - } - if ((snort_conf->run_flags & RUN_FLAG__NO_PROMISCUOUS) != (run_flags & RUN_FLAG__NO_PROMISCUOUS)) { diff --git a/src/main/snort_config.h b/src/main/snort_config.h index 46eb97677..fab514ad0 100644 --- a/src/main/snort_config.h +++ b/src/main/snort_config.h @@ -93,10 +93,7 @@ enum OutputFlag OUTPUT_FLAG__OBFUSCATE = 0x00000100, /* -B */ OUTPUT_FLAG__ALERT_IFACE = 0x00000200, /* -I */ OUTPUT_FLAG__NO_TIMESTAMP = 0x00000400, /* --nostamps */ - - OUTPUT_FLAG__NO_ALERT = 0x00001000, /* -A none */ - OUTPUT_FLAG__NO_LOG = 0x00002000, /* -K none */ - OUTPUT_FLAG__ALERTS = 0x00004000, /* -A != none */ + OUTPUT_FLAG__ALERTS = 0x00000800, /* -A */ }; enum LoggingFlag diff --git a/src/main/snort_module.cc b/src/main/snort_module.cc index 2069547a0..a6cffff8a 100644 --- a/src/main/snort_module.cc +++ b/src/main/snort_module.cc @@ -96,10 +96,6 @@ static void x2c(unsigned x) // parameters //------------------------------------------------------------------------- -#ifdef REG_TEST -#define REG_TEST_IGNORE " -N --pcap-reset " -#endif - static const Parameter s_params[] = { { "-?", Parameter::PT_STRING, "(optional)", nullptr, @@ -153,7 +149,7 @@ static const Parameter s_params[] = " checksum mode (all,noip,notcp,noudp,noicmp,none)" }, { "-L", Parameter::PT_STRING, nullptr, nullptr, - " logging mode (none, text, pcap, or log_*)" }, + " logging mode (none, dump, pcap, or log_*)" }, { "-l", Parameter::PT_STRING, nullptr, nullptr, " log to this directory instead of current directory" }, @@ -164,11 +160,6 @@ static const Parameter s_params[] = { "-m", Parameter::PT_INT, "0:", nullptr, " set umask = " }, -#ifdef REG_TEST - { "-N", Parameter::PT_IMPLIED, nullptr, nullptr, - "ignored - for REG_TEST only" }, -#endif - { "-n", Parameter::PT_INT, "0:", nullptr, " stop after count packets" }, @@ -369,11 +360,6 @@ static const Parameter s_params[] = { "--pcap-reload", Parameter::PT_IMPLIED, nullptr, nullptr, "if reading multiple pcaps, reload snort config between pcaps" }, -#ifdef REG_TEST - { "--pcap-reset", Parameter::PT_IMPLIED, nullptr, nullptr, - "ignored - for REG_TEST only" }, -#endif - { "--pcap-show", Parameter::PT_IMPLIED, nullptr, nullptr, "print a line saying what pcap is currently being read" }, @@ -840,11 +826,6 @@ bool SnortModule::set(const char*, Value& v, SnortConfig* sc) else if ( v.is("--x2c") ) x2c(v.get_long()); -#ifdef REG_TEST - else if ( !strstr(REG_TEST_IGNORE, v.get_name()) ) - return false; -#endif - return true; } diff --git a/src/packet_io/active.cc b/src/packet_io/active.cc index dd6610aca..e6f1adcc5 100644 --- a/src/packet_io/active.cc +++ b/src/packet_io/active.cc @@ -489,3 +489,17 @@ static int Active_SendIp( uint64_t Active_GetInjects(void) { return s_injects; } +const char* Active_GetDispositionString() +{ + switch ( active_drop_pkt ) + { + case ACTIVE_ALLOW: return "allow"; + case ACTIVE_CANT_DROP: return "cant_drop"; + case ACTIVE_WOULD_DROP: return "would_drop"; + case ACTIVE_DROP: return "drop"; + case ACTIVE_FORCE_DROP: return "force_drop"; + default: break; + } + return "error"; +} + diff --git a/src/packet_io/active.h b/src/packet_io/active.h index dd1b56410..a7171bd5e 100644 --- a/src/packet_io/active.h +++ b/src/packet_io/active.h @@ -234,5 +234,5 @@ SO_PUBLIC int Active_ForceDropResetAction(Packet* p); SO_PUBLIC const char* Active_GetDispositionString(); -#endif // ACTIVE_H +#endif diff --git a/src/packet_io/sfdaq.cc b/src/packet_io/sfdaq.cc index 03c31c921..d8719e875 100644 --- a/src/packet_io/sfdaq.cc +++ b/src/packet_io/sfdaq.cc @@ -51,11 +51,9 @@ extern "C" { #define DAQ_DEFAULT "pcap" #endif -#ifdef REG_TEST #ifndef DAQ_CAPA_INJECT_RAW #define DAQ_CAPA_INJECT_RAW 0x200 #endif -#endif // common for all daq threads / instances static const DAQ_Module_t* daq_mod = NULL; diff --git a/src/parser/config_file.cc b/src/parser/config_file.cc index e09e7fb28..1b6321708 100644 --- a/src/parser/config_file.cc +++ b/src/parser/config_file.cc @@ -57,8 +57,8 @@ #include "sfip/sf_ip.h" #define LOG_NONE "none" -#define LOG_TEXT "text" -#define LOG_PCAP "pcap" +#define LOG_DUMP "dump" +#define LOG_CODECS "codecs" #define ALERT_NONE "none" #define ALERT_CMG "cmg" @@ -66,13 +66,9 @@ #define ALERT_DJR "djr" #define ALERT_U2 "u2" #define ALERT_AJK "ajk" -#ifdef REG_TEST -#define ALERT_CON "console" -#endif #define OUTPUT_U2 "unified2" #define OUTPUT_FAST "alert_fast" -#define OUTPUT_PCAP "log_pcap" static std::string lua_conf; static std::string snort_conf_dir; @@ -340,11 +336,6 @@ void ConfigDirtyPig(SnortConfig* sc, const char*) sc->dirty_pig = 1; } -void ConfigNoLog(SnortConfig* sc, const char*) -{ - sc->output_flags |= OUTPUT_FLAG__NO_LOG; -} - void ConfigObfuscate(SnortConfig* sc, const char*) { sc->output_flags |= OUTPUT_FLAG__OBFUSCATE; @@ -609,10 +600,8 @@ void config_daemon(SnortConfig* sc, const char* val) void config_alert_mode(SnortConfig* sc, const char* val) { if (strcasecmp(val, ALERT_NONE) == 0) - { - sc->output_flags |= OUTPUT_FLAG__NO_ALERT; EventManager::enable_alerts(false); - } + else if ( !strcasecmp(val, ALERT_CMG) or !strcasecmp(val, ALERT_JH) or !strcasecmp(val, ALERT_DJR) ) { @@ -623,10 +612,6 @@ void config_alert_mode(SnortConfig* sc, const char* val) else if ( !strcasecmp(val, ALERT_U2) or !strcasecmp(val, ALERT_AJK) ) sc->output = OUTPUT_U2; -#ifdef REG_TEST - else if (strcasecmp(val, ALERT_CON) == 0) - sc->output = OUTPUT_FAST; -#endif else sc->output = val; @@ -638,21 +623,13 @@ void config_log_mode(SnortConfig* sc, const char* val) { if (strcasecmp(val, LOG_NONE) == 0) { - sc->output_flags |= OUTPUT_FLAG__NO_LOG; Snort::set_main_hook(snort_ignore); EventManager::enable_logs(false); } - else if (strcasecmp(val, LOG_TEXT) == 0) - { - Snort::set_main_hook(snort_print); - } - else if (strcasecmp(val, LOG_PCAP) == 0) - { - sc->output = OUTPUT_PCAP; - Snort::set_main_hook(snort_log); - } else { + if ( !strcmp(val, LOG_DUMP) ) + val = LOG_CODECS; sc->output = val; Snort::set_main_hook(snort_log); } diff --git a/src/parser/config_file.h b/src/parser/config_file.h index 30a9c75f9..6fa512e1d 100644 --- a/src/parser/config_file.h +++ b/src/parser/config_file.h @@ -43,7 +43,6 @@ void ConfigDaqMode(SnortConfig*, const char*); void ConfigDaqVar(SnortConfig*, const char*); void ConfigDaqDir(SnortConfig*, const char*); void ConfigDirtyPig(SnortConfig*, const char*); -void ConfigNoLog(SnortConfig*, const char*); void ConfigNoLoggingTimestamps(SnortConfig*, const char*); void ConfigObfuscate(SnortConfig*, const char*); void ConfigObfuscationMask(SnortConfig*, const char*); diff --git a/src/protocols/ip.cc b/src/protocols/ip.cc index 5e475ea7d..be224eec7 100644 --- a/src/protocols/ip.cc +++ b/src/protocols/ip.cc @@ -60,7 +60,7 @@ void IpApi::set(const ip::IP6Hdr* h6) std::memcpy(&(dst.ip8), &(h6->ip6_dst), 16); } -void IpApi::set(sfip_t& sip, sfip_t& dip) +void IpApi::set(const sfip_t& sip, const sfip_t& dip) { type = IAT_DATA; sfip_set_ip(&src, &sip); diff --git a/src/protocols/ip.h b/src/protocols/ip.h index 782b88614..5d0a870fa 100644 --- a/src/protocols/ip.h +++ b/src/protocols/ip.h @@ -57,7 +57,7 @@ public: void set(const IP4Hdr* h4); void set(const IP6Hdr* h6); - void set(sfip_t& src, sfip_t& dst); + void set(const sfip_t& src, const sfip_t& dst); bool set(const uint8_t* raw_ip_data); void reset(); diff --git a/src/protocols/packet.cc b/src/protocols/packet.cc index e61a884fa..9aa74349d 100644 --- a/src/protocols/packet.cc +++ b/src/protocols/packet.cc @@ -94,3 +94,72 @@ bool Packet::get_ip_proto_next(uint8_t& lyr, uint8_t& proto) const return false; } +const char* Packet::get_type() const +{ + switch ( ptrs.get_pkt_type() ) + { + case PktType::IP: + return "IP"; + + case PktType::ICMP: + return "ICMP"; + + case PktType::TCP: + return "TCP"; + + case PktType::UDP: + return "UDP"; + + case PktType::USER: + case PktType::FILE: + if ( proto_bits & PROTO_BIT__TCP ) + return "TCP"; + if ( proto_bits & PROTO_BIT__UDP ) + return "UDP"; + break; + + default: + break; + } + return "error"; +} + +const char* Packet::get_pseudo_type() const +{ + if ( !(packet_flags & PKT_PSEUDO) ) + return "raw"; + + switch ( pseudo_type ) + { + case PSEUDO_PKT_IP: + return "stream_ip"; + + case PSEUDO_PKT_TCP: + return "stream_tcp"; + + case PSEUDO_PKT_DCE_RPKT: + return "dce2_rpc_reass"; + + case PSEUDO_PKT_DCE_SEG: + return "dce2_rpc_deseg"; + + case PSEUDO_PKT_DCE_FRAG: + return "dce2_rpc_defrag"; + + case PSEUDO_PKT_SMB_SEG: + return "dce2_smb_deseg"; + + case PSEUDO_PKT_SMB_TRANS: + return "dce2_smb_transact"; + + case PSEUDO_PKT_PS: + return "port_scan"; + + case PSEUDO_PKT_SDF: + return "sdf"; + + default: break; + } + return "other"; +} + diff --git a/src/protocols/packet.h b/src/protocols/packet.h index 0a064698a..b4f2e5b95 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -33,12 +33,12 @@ #include #include #include -#else /* !WIN32 */ +#else #include #ifndef IFNAMSIZ #define IFNAMESIZ MAX_ADAPTER_NAME -#endif /* !IFNAMSIZ */ -#endif /* !WIN32 */ +#endif +#endif extern "C" { #include @@ -129,12 +129,12 @@ constexpr int16_t SFTARGET_UNKNOWN_PROTOCOL = -1; constexpr uint8_t TCP_OPTLENMAX = 40; /* (((2^4) - 1) * 4 - TCP_HEADER_LEN) */ constexpr uint8_t DEFAULT_LAYERMAX = 40; -/* D A T A S T R U C T U R E S *********************************************/ -class Flow; - +// Packet is an abstraction describing a unit of work. it may define a +// wire packet or it may define a cooked packet. the latter contains +// payload data only, no headers. struct SO_PUBLIC Packet { - Flow* flow; /* for session tracking */ + class Flow* flow; /* for session tracking */ uint32_t packet_flags; /* special flags for the packet */ uint32_t xtradata_mask; @@ -160,15 +160,18 @@ struct SO_PUBLIC Packet PseudoPacketType pseudo_type; // valid only when PKT_PSEUDO is set uint32_t iplist_id; - uint16_t max_dsize; - /**policyId provided in configuration file. Used for correlating configuration - * with event output - */ + // for correlating configuration with event output uint16_t user_policy_id; uint8_t ps_proto; // Used for portscan and unified2 logging + // IP_MAXPACKET is the minimum allowable max_dsize + // there is no requirement that all data fit into an IP datagram + // but we do require that an IP datagram fit into Packet space + // we can increase beyond this if needed + static const uint32_t max_dsize = IP_MAXPACKET; + /* Boolean functions - general information about this packet */ inline bool has_ip() const { return ptrs.ip_api.is_ip(); } @@ -200,10 +203,16 @@ struct SO_PUBLIC Packet inline bool is_fragment() const { return ptrs.decode_flags & DECODE_FRAG; } + inline bool has_tcp_data() const + { return (proto_bits & PROTO_BIT__TCP) and data and dsize; } + /* Get general, non-boolean information */ inline PktType type() const { return ptrs.get_pkt_type(); } // defined in codec.h + const char* get_type() const; + const char* get_pseudo_type() const; + /* the ip_api return the protocol_ID of the protocol directly after the * innermost IP layer. However, especially in IPv6, the next protocol * can frequently be an IP extension. Therefore, this function @@ -237,7 +246,7 @@ struct SO_PUBLIC Packet inline void reset() { - memset(&flow, '\0', offsetof(Packet, pkth)); + memset(this, 0, offsetof(Packet, pkth)); ptrs.reset(); } bool from_client() @@ -262,8 +271,6 @@ struct SO_PUBLIC Packet { return (packet_flags & (PKT_REBUILT_STREAM|PKT_REBUILT_FRAG)) != 0; } }; -#define PKT_ZERO_LEN offsetof(Packet, pkth) - /* Macros to deal with sequence numbers - p810 TCP Illustrated vol 2 */ #define SEQ_LT(a,b) ((int)((a) - (b)) < 0) #define SEQ_LEQ(a,b) ((int)((a) - (b)) <= 0) diff --git a/src/protocols/packet_manager.cc b/src/protocols/packet_manager.cc index a915dd8fc..33ac426b3 100644 --- a/src/protocols/packet_manager.cc +++ b/src/protocols/packet_manager.cc @@ -198,7 +198,7 @@ void PacketManager::decode( codec_data.codec_flags |= CODEC_STREAM_REBUILT; // initialize all Packet information - memset(p, 0, PKT_ZERO_LEN); + p->reset(); p->pkth = pkthdr; p->pkt = pkt; p->ptrs.reset(); @@ -640,6 +640,34 @@ const uint8_t* PacketManager::encode_reject(UnreachResponse type, } } +static void set_hdr( + const Packet* p, Packet* c, const DAQ_PktHdr_t* phdr, uint32_t opaque) +{ + c->reset(); + DAQ_PktHdr_t* pkth = (DAQ_PktHdr_t*)c->pkth; + +#ifdef HAVE_DAQ_ADDRESS_SPACE_ID + if ( !phdr ) + phdr = p->pkth; + + pkth->ingress_index = phdr->ingress_index; + pkth->ingress_group = phdr->ingress_group; + pkth->egress_index = phdr->egress_index; + pkth->egress_group = phdr->egress_group; + pkth->flags = phdr->flags & (~DAQ_PKT_FLAG_HW_TCP_CS_GOOD); + pkth->address_space_id = phdr->address_space_id; + pkth->opaque = opaque; + UNUSED(p); +#else +#ifdef HAVE_DAQ_ACQUIRE_WITH_META + pkth->opaque = p->pkth->opaque; +#endif + UNUSED(p); + UNUSED(phdr); + UNUSED(opaque); +#endif +} + //------------------------------------------------------------------------- // formatters: // - these packets undergo detection @@ -648,7 +676,29 @@ const uint8_t* PacketManager::encode_reject(UnreachResponse type, // - inner layer header is very similar but payload differs // - original ttl is always used //------------------------------------------------------------------------- -int PacketManager::encode_format_with_daq_info( + +int PacketManager::format_tcp( + EncodeFlags, const Packet* p, Packet* c, PseudoPacketType type, + const DAQ_PktHdr_t* phdr, uint32_t opaque) +{ + c->reset(); + DAQ_PktHdr_t* pkth = (DAQ_PktHdr_t*)c->pkth; + set_hdr(p, c, phdr, opaque); + + c->packet_flags |= PKT_PSEUDO; + c->pseudo_type = type; + c->user_policy_id = p->user_policy_id; // cooked packet gets same policy as raw + + // setup pkt capture header + pkth->caplen = 0; + pkth->pktlen = 0; + pkth->ts = p->pkth->ts; + + total_rebuilt_pkts++; // update local counter + return 0; +} + +int PacketManager::encode_format( EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type, const DAQ_PktHdr_t* phdr, uint32_t opaque) { @@ -661,23 +711,8 @@ int PacketManager::encode_format_with_daq_info( if ( num_layers <= 0 ) return -1; - memset(c, 0, PKT_ZERO_LEN); - -#ifdef HAVE_DAQ_ADDRESS_SPACE_ID - pkth->ingress_index = phdr->ingress_index; - pkth->ingress_group = phdr->ingress_group; - pkth->egress_index = phdr->egress_index; - pkth->egress_group = phdr->egress_group; - pkth->flags = phdr->flags & (~DAQ_PKT_FLAG_HW_TCP_CS_GOOD); - pkth->address_space_id = phdr->address_space_id; - pkth->opaque = opaque; -#elif defined(HAVE_DAQ_ACQUIRE_WITH_META) - pkth->opaque = opaque; - UNUSED(phdr); -#else - UNUSED(phdr); - UNUSED(opaque); -#endif /* HAVE_DAQ_ADDRESS_SPACE_ID */ + c->reset(); + set_hdr(p, c, phdr, opaque); if ( f & ENC_FLAG_NET ) { @@ -748,9 +783,8 @@ int PacketManager::encode_format_with_daq_info( len = c->data - c->pkt; // len < ETHERNET_HEADER_LEN + VLAN_HEADER + ETHERNET_MTU - assert((unsigned)len < Codec::PKT_MAX - IP_MAXPACKET); + assert((unsigned)len < Codec::PKT_MAX - c->max_dsize); - c->max_dsize = IP_MAXPACKET - len; c->proto_bits = p->proto_bits; c->ip_proto_next = p->ip_proto_next; c->packet_flags |= PKT_PSEUDO; @@ -767,26 +801,6 @@ int PacketManager::encode_format_with_daq_info( return 0; } -#ifdef HAVE_DAQ_ADDRESS_SPACE_ID -int PacketManager::encode_format(EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type) -{ - return encode_format_with_daq_info(f, p, c, type, p->pkth, p->pkth->opaque); -} - -#elif defined(HAVE_DAQ_ACQUIRE_WITH_META) -int PacketManager::encode_format(EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type) -{ - return encode_format_with_daq_info(f, p, c, type, nullptr, p->pkth->opaque); -} - -#else -int PacketManager::encode_format(EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type) -{ - return encode_format_with_daq_info(f, p, c, type, nullptr, 0); -} - -#endif - //------------------------------------------------------------------------- // updaters: these functions set length and checksum fields, only needed // when a packet is modified. some packets only have replacements so only diff --git a/src/protocols/packet_manager.h b/src/protocols/packet_manager.h index 1df951042..d3ff898c3 100644 --- a/src/protocols/packet_manager.h +++ b/src/protocols/packet_manager.h @@ -54,67 +54,81 @@ enum class UnreachResponse class SO_PUBLIC PacketManager { public: - // decode this packet and set all relevent packet fields. static void decode(Packet*, const struct _daq_pkthdr*, const uint8_t*, bool cooked = false); // allocate a Packet for later formatting (cloning) static Packet* encode_new(bool allocate_packet_data = true); + // release the allocated Packet static void encode_delete(Packet*); // when encoding, rather than copy the destination MAC address from the // inbound packet, manually set the MAC address. static void encode_set_dst_mac(uint8_t*); + // get the MAC address which has been set using encode_set_dst_mac(). // Useful for root decoders setting the MAC address static uint8_t* encode_get_dst_mac(); + // update the packet's checksums and length variables. Call this function // after Snort has changed any data in this packet static void encode_update(Packet*); - // format packet for detection. Original ttl is always used. - static int encode_format( - EncodeFlags f, const Packet* orig, Packet* clone, PseudoPacketType type); - // encode the packet with pre-set daq info. - static int encode_format_with_daq_info( - EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type, - const DAQ_PktHdr_t*, uint32_t opaque); - // orig is the wire pkt; clone was obtained with New() + + //-------------------------------------------------------------------- + // FIXIT-L encode_format() should be replaced with a function that + // does format and update in one step for packets cooked for internal + // use only like stream_tcp and port_scan. stream_ip packets should + // just be decoded from last layer on. at that point all the + // Codec::format methods can be deleted too. the new function should + // be some super set of format_tcp(). + //-------------------------------------------------------------------- + + // format packet for detection. Original ttl is always used. orig is + // the wire pkt; clone was obtained with New() + static int encode_format( EncodeFlags f, const Packet* orig, Packet* + clone, PseudoPacketType type, const DAQ_PktHdr_t* = nullptr, + uint32_t opaque = 0); + + static int format_tcp( + EncodeFlags f, const Packet* orig, Packet* clone, PseudoPacketType type, + const DAQ_PktHdr_t* = nullptr, uint32_t opaque = 0); // Send a TCP response. TcpResponse params determined the type // of response. Len will be set to the response's length. // payload && payload_len are optional. static const uint8_t* encode_response( - TcpResponse, EncodeFlags, const Packet* orig, uint32_t& len, - const uint8_t* const payload = nullptr, uint32_t payload_len = 0); + TcpResponse, EncodeFlags, const Packet* orig, uint32_t& len, + const uint8_t* const payload = nullptr, uint32_t payload_len = 0); + // Send an ICMP unreachable response! static const uint8_t* encode_reject(UnreachResponse type, EncodeFlags flags, const Packet* p, uint32_t& len); - // for backwards compatability and convenience. - static inline int encode_format_with_daq_info( - EncodeFlags f, const Packet* orig, Packet* clone, - PseudoPacketType type, uint32_t opaque) - { return encode_format_with_daq_info(f, orig, clone, type, nullptr, opaque); } - /* codec support and statistics */ // get the number of packets which have been rebuilt by this thread static PegCount get_rebuilt_packet_count(void); + // set the packet to be encoded. static void encode_set_pkt(Packet* p); + // get the max payload for the current packet static uint16_t encode_get_max_payload(const Packet*); + // reset the current 'clone' packet static inline void encode_reset(void) { encode_set_pkt(NULL); } // print codec information. MUST be called after thread_term. static void dump_stats(); + // Get the name of the given protocol static const char* get_proto_name(uint16_t protocol); + // Get the name of the given protocol static const char* get_proto_name(uint8_t protocol); + // print this packets information, layer by layer static void log_protocols(TextLog* const, const Packet* const); @@ -133,14 +147,13 @@ public: { return CodecManager::s_proto_map[proto]; } private: - // STATISTICS!! - // The only time we should accumulate is when CodecManager tells us too friend void CodecManager::thread_term(); static void accumulate(); static void pop_teredo(Packet*, RawData&); + static bool encode(const Packet* p, EncodeFlags, - uint8_t lyr_start, uint8_t next_prot, Buffer& buf); + uint8_t lyr_start, uint8_t next_prot, Buffer& buf); // constant offsets into the s_stats array. Notice the stat_offset // constant which is used when adding a protocol specific codec @@ -155,6 +168,5 @@ private: static std::array g_stats; static const std::array stat_names; }; - #endif diff --git a/src/service_inspectors/dns/dns.cc b/src/service_inspectors/dns/dns.cc index a3348577d..6f9f3301b 100644 --- a/src/service_inspectors/dns/dns.cc +++ b/src/service_inspectors/dns/dns.cc @@ -1017,7 +1017,7 @@ static void snort_dns(Packet* p) PROFILE_VARS; /* For TCP, do a few extra checks... */ - if (p->is_udp()) + if ( p->has_tcp_data() ) { /* If session picked up mid-stream, do not process further. * Would be almost impossible to tell where we are in the @@ -1101,7 +1101,7 @@ void Dns::show(SnortConfig*) void Dns::eval(Packet* p) { // precondition - what we registered for - assert((p->is_udp() || p->is_tcp()) && p->dsize && p->data); + assert((p->is_udp() and p->dsize and p->data) or p->has_tcp_data()); ++dnsstats.total_packets; snort_dns(p); diff --git a/src/service_inspectors/ftp_telnet/ftp.cc b/src/service_inspectors/ftp_telnet/ftp.cc index 766b5ea00..cf227a0a8 100644 --- a/src/service_inspectors/ftp_telnet/ftp.cc +++ b/src/service_inspectors/ftp_telnet/ftp.cc @@ -399,7 +399,7 @@ StreamSplitter* FtpServer::get_splitter(bool c2s) void FtpServer::eval(Packet* p) { // precondition - what we registered for - assert(p->is_tcp() && p->data && p->dsize); + assert(p->has_tcp_data()); ++ftstats.total_packets; snort_ftp(p); diff --git a/src/service_inspectors/ftp_telnet/ftp_data.cc b/src/service_inspectors/ftp_telnet/ftp_data.cc index 5ad97fd12..12b68a86d 100644 --- a/src/service_inspectors/ftp_telnet/ftp_data.cc +++ b/src/service_inspectors/ftp_telnet/ftp_data.cc @@ -247,7 +247,7 @@ ProfileStats* FtpDataModule::get_profile() const void FtpData::eval(Packet* p) { // precondition - what we registered for - assert(p->is_tcp()); + assert(p->has_tcp_data()); if ( file_api->get_max_file_depth() < 0 ) return; diff --git a/src/service_inspectors/ftp_telnet/telnet.cc b/src/service_inspectors/ftp_telnet/telnet.cc index ab57720ae..e8e4a933f 100644 --- a/src/service_inspectors/ftp_telnet/telnet.cc +++ b/src/service_inspectors/ftp_telnet/telnet.cc @@ -264,7 +264,7 @@ void Telnet::show(SnortConfig*) void Telnet::eval(Packet* p) { // precondition - what we registered for - assert(p->is_tcp() && p->dsize && p->data); + assert(p->has_tcp_data()); ++tnstats.total_packets; snort_telnet(config, p); diff --git a/src/service_inspectors/http_inspect/hi_server.cc b/src/service_inspectors/http_inspect/hi_server.cc index d1333d926..e61c96841 100644 --- a/src/service_inspectors/http_inspect/hi_server.cc +++ b/src/service_inspectors/http_inspect/hi_server.cc @@ -203,7 +203,7 @@ static int IsHttpServerData(HI_SESSION* session, Packet* p, HttpSessionData* sd) return HI_INVALID_ARG; } - seq_num = GET_PKT_SEQ(p); + seq_num = sd ? sd->resp_state.next_seq : 0; /* ** Let's set up the data pointers. @@ -1279,7 +1279,7 @@ static int HttpResponseInspection(HI_SESSION* session, Packet* p, const unsigned clearHttpRespBuffer(Server); - seq_num = GET_PKT_SEQ(p); + seq_num = sd ? sd->resp_state.next_seq : 0; { expected_pkt = !p->is_pdu_start(); diff --git a/src/service_inspectors/http_inspect/http_inspect.cc b/src/service_inspectors/http_inspect/http_inspect.cc index 765e8b83b..8c4e82a29 100644 --- a/src/service_inspectors/http_inspect/http_inspect.cc +++ b/src/service_inspectors/http_inspect/http_inspect.cc @@ -331,9 +331,7 @@ void HttpInspect::eval(Packet* p) PROFILE_VARS; // preconditions - what we registered for - // FIXIT remove proto check? check for tcp or user? - //assert(p->is_tcp() && p->dsize && p->data); - assert(p->dsize && p->data); + assert(p->has_tcp_data()); MODULE_PROFILE_START(hiPerfStats); hi_clear_events(); diff --git a/src/service_inspectors/imap/imap.cc b/src/service_inspectors/imap/imap.cc index dace1ad8f..7e7f63781 100644 --- a/src/service_inspectors/imap/imap.cc +++ b/src/service_inspectors/imap/imap.cc @@ -826,7 +826,7 @@ void Imap::eval(Packet* p) { PROFILE_VARS; // precondition - what we registered for - assert(p->is_tcp() && p->dsize && p->data); + assert(p->has_tcp_data()); ++imapstats.total_packets; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc index dbbbb99c2..a7c4cc1e0 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_head_shared.cc @@ -59,10 +59,10 @@ void NHttpMsgHeadShared::parse_header_block() header_line = new Field[session_data->num_head_lines[source_id]]; while (bytes_used < msg_text.length) { + assert(num_headers < session_data->num_head_lines[source_id]); header_line[num_headers].start = msg_text.start + bytes_used; header_line[num_headers].length = find_header_end(header_line[num_headers].start, msg_text.length - bytes_used, num_seps); - assert(num_headers < session_data->num_head_lines[source_id]); if (header_line[num_headers].length > MAX_HEADER_LENGTH) { infractions += INF_TOO_LONG_HEADER; diff --git a/src/service_inspectors/pop/pop.cc b/src/service_inspectors/pop/pop.cc index 6748425e3..d8b96c4cb 100644 --- a/src/service_inspectors/pop/pop.cc +++ b/src/service_inspectors/pop/pop.cc @@ -759,7 +759,7 @@ void Pop::eval(Packet* p) { PROFILE_VARS; // precondition - what we registered for - assert(p->is_tcp() && p->dsize && p->data); + assert(p->has_tcp_data()); ++popstats.total_packets; diff --git a/src/service_inspectors/rpc_decode/rpc_decode.cc b/src/service_inspectors/rpc_decode/rpc_decode.cc index 0936b70ac..d325bef27 100644 --- a/src/service_inspectors/rpc_decode/rpc_decode.cc +++ b/src/service_inspectors/rpc_decode/rpc_decode.cc @@ -942,7 +942,7 @@ static int ConvertRPC(RpcDecodeConfig* rconfig, RpcSsnData* rsdata, Packet* p) DEBUG_WRAP(DebugMessage(DEBUG_RPC, "New size: %d\n", decoded_len); DebugMessage(DEBUG_RPC, "converted data:\n"); - //LogNetData(data, decoded_len, NULL); + //LogNetData(data, decoded_len, p); ); set_alt_data(DecodeBuffer.data, decoded_len); @@ -1018,7 +1018,7 @@ void RpcDecode::eval(Packet* p) PROFILE_VARS; // preconditions - what we registered for - assert(p->is_tcp() && p->dsize); + assert(p->has_tcp_data()); /* If we're stateful that means stream has been configured. * In this case we don't look at server packets. diff --git a/src/service_inspectors/smtp/smtp.cc b/src/service_inspectors/smtp/smtp.cc index bfa45c27a..296d98166 100644 --- a/src/service_inspectors/smtp/smtp.cc +++ b/src/service_inspectors/smtp/smtp.cc @@ -1669,7 +1669,7 @@ void Smtp::eval(Packet* p) { PROFILE_VARS; // precondition - what we registered for - assert(p->is_tcp() && p->dsize && p->data); + assert(p->has_tcp_data()); ++smtpstats.total_packets; diff --git a/src/service_inspectors/ssh/ssh.cc b/src/service_inspectors/ssh/ssh.cc index 1e062513e..44dd924c4 100644 --- a/src/service_inspectors/ssh/ssh.cc +++ b/src/service_inspectors/ssh/ssh.cc @@ -819,7 +819,7 @@ void Ssh::show(SnortConfig*) void Ssh::eval(Packet* p) { // precondition - what we registered for - assert(p->is_tcp() && p->dsize && p->data); + assert(p->has_tcp_data()); ++sshstats.total_packets; snort_ssh(config, p); diff --git a/src/stream/paf.cc b/src/stream/paf.cc index b676f2558..3c08d518b 100644 --- a/src/stream/paf.cc +++ b/src/stream/paf.cc @@ -111,6 +111,8 @@ static uint32_t paf_flush ( // such as exceeding s5_pkt->max_dsize. the actual amount // flushed would ideally be applied to ps->fpt later. for // now we try to circumvent such cases so we track correctly. + // FIXIT-L max_dsize should no longer be exceeded since it excludes + // headers. case FT_MAX: at = s5_len; if ( ps->fpt > s5_len ) @@ -262,7 +264,7 @@ void paf_clear (PAF_State* ps) //-------------------------------------------------------------------- -uint32_t paf_check ( +int32_t paf_check ( StreamSplitter* ss, PAF_State* ps, Flow* ssn, const uint8_t* data, uint32_t len, uint32_t total, uint32_t seq, uint32_t* flags) diff --git a/src/stream/paf.h b/src/stream/paf.h index c07ef47dc..97466079e 100644 --- a/src/stream/paf.h +++ b/src/stream/paf.h @@ -72,7 +72,7 @@ static inline void paf_jump(PAF_State* ps, uint32_t n) } // called on each in order segment -uint32_t paf_check( +int32_t paf_check( StreamSplitter* paf_config, PAF_State*, Flow* ssn, const uint8_t* data, uint32_t len, uint32_t total, uint32_t seq, uint32_t* flags); diff --git a/src/stream/stream.h b/src/stream/stream.h index b9a7f03ef..f8024d814 100644 --- a/src/stream/stream.h +++ b/src/stream/stream.h @@ -77,7 +77,6 @@ private: unsigned use; }; -/* D A T A S T R U C T U R E S **********************************/ // FIXIT-L some of this stuff can be better encapsulated struct StreamGlobalConfig diff --git a/src/stream/stream_api.cc b/src/stream/stream_api.cc index 41313b5a6..942004088 100644 --- a/src/stream/stream_api.cc +++ b/src/stream/stream_api.cc @@ -813,22 +813,6 @@ void Stream::clear_extra_data( flow->session->clear_extra_data(p, flag); } -int Stream::traverse_reassembled( - Packet* p, PacketIterator callback, void* userdata) -{ - Flow* flow = p->flow; - assert(flow && flow->session); - return flow->session->get_rebuilt_packets(p, callback, userdata); -} - -int Stream::traverse_stream_segments( - Packet* p, StreamSegmentIterator callback, void* userdata) -{ - Flow* flow = p->flow; - assert(flow && flow->session); - return flow->session->get_segments(p, callback, userdata); -} - char Stream::get_reassembly_direction(Flow* flow) { assert(flow && flow->session); diff --git a/src/stream/stream_api.h b/src/stream/stream_api.h index c8087021e..6827c7aa8 100644 --- a/src/stream/stream_api.h +++ b/src/stream/stream_api.h @@ -136,22 +136,6 @@ public: static void flush_request(Packet*); // flush listener static void flush_response(Packet*); // flush talker - /* Calls user-provided callback function for each packet of - * a reassembled stream. If the callback function returns non-zero, - * iteration ends. - * - * Returns number of packets - */ - static int traverse_reassembled(Packet*, PacketIterator, void* userdata); // PKT - - /* Calls user-provided callback function for each segment of - * a reassembled stream. If the callback function returns non-zero, - * iteration ends. - * - * Returns number of packets - */ - static int traverse_stream_segments(Packet*, StreamSegmentIterator, void* userdata); // PKT - /* Add session alert - true if added */ static bool add_session_alert(Flow*, Packet*, uint32_t gid, uint32_t sid); diff --git a/src/stream/tcp/tcp_session.cc b/src/stream/tcp/tcp_session.cc index 8cdd41613..527242f4f 100644 --- a/src/stream/tcp/tcp_session.cc +++ b/src/stream/tcp/tcp_session.cc @@ -381,41 +381,23 @@ static inline bool DataToFlush (const TcpTracker* st) } /* P R O T O T Y P E S ********************************************/ -static void StreamPrintTcpConfig(StreamTcpConfig*); -static inline void SetupTcpDataBlock(TcpDataBlock*, Packet*); -static int ProcessTcp(Flow*, Packet*, TcpDataBlock*, - StreamTcpConfig*); +static int ProcessTcp(Flow*, Packet*, TcpDataBlock*, StreamTcpConfig*); + static inline int CheckFlushPolicyOnData( TcpSession *, TcpTracker *, TcpTracker *, Packet *); + static inline int CheckFlushPolicyOnAck( TcpSession *, TcpTracker *, TcpTracker *, Packet *); -static void StreamSeglistAddNode(TcpTracker *, TcpSegment *, - TcpSegment *); + +static void StreamSeglistAddNode(TcpTracker *, TcpSegment *, TcpSegment *); static int StreamSeglistDeleteNode(TcpTracker*, TcpSegment*); static int StreamSeglistDeleteNodeTrim(TcpTracker*, TcpSegment*, uint32_t flush_seq); -static int AddStreamNode( - TcpTracker*, Packet*, TcpDataBlock*, - int16_t len, uint32_t slide, uint32_t trunc, - uint32_t seq, TcpSegment *left, TcpSegment **retSeg); + static int DupStreamNode( - Packet*, - TcpTracker*, - TcpSegment* left, - TcpSegment** retSeg); - -static uint32_t StreamGetWscale(Packet*, uint16_t*); -static uint32_t StreamPacketHasWscale(Packet*); -static uint32_t StreamGetMss(Packet*, uint16_t*); -static uint32_t StreamGetTcpTimestamp(Packet*, uint32_t*, int strip); + Packet*, TcpTracker*, TcpSegment* left, TcpSegment** retSeg); -int s5TcpStreamSizeInit(SnortConfig* sc, char* name, char* parameters, void** dataPtr); -int s5TcpStreamSizeEval(Packet*, const uint8_t** cursor, void* dataPtr); -void s5TcpStreamSizeCleanup(void* dataPtr); -int s5TcpStreamReassembleRuleOptionInit( - SnortConfig* sc, char* name, char* parameters, void** dataPtr); -int s5TcpStreamReassembleRuleOptionEval(Packet*, const uint8_t** cursor, void* dataPtr); -void s5TcpStreamReassembleRuleOptionCleanup(void* dataPtr); +static uint32_t StreamGetTcpTimestamp(Packet*, uint32_t*, int strip); /* G L O B A L S **************************************************/ @@ -464,9 +446,79 @@ static const char* const flush_policy_names[] = #endif static THREAD_LOCAL Packet* s5_pkt = nullptr; -static THREAD_LOCAL Packet* cleanup_pkt = nullptr; -/* F U N C T I O N S **********************************************/ +//------------------------------------------------------------------------- +// TcpSegment stuff +//------------------------------------------------------------------------- + +TcpSegment* TcpSegment::init( + Packet* p, const struct timeval& tv, const uint8_t* data, unsigned dsize) +{ + TcpSegment* ss; + unsigned size = sizeof(*ss); + + if ( dsize > 0 ) + size += dsize - 1; // ss contains 1st byte + + tcp_memcap->alloc(size); + + if ( tcp_memcap->at_max() ) + { + sfBase.iStreamFaults++; + + // FIXIT eliminate the packet dependency? + if ( p ) + flow_con->prune_flows(PktType::TCP, p); + } + + ss = (TcpSegment*)malloc(size); + + if ( !ss ) + return nullptr; + + ss->tv = tv; + memcpy(ss->data, data, dsize); + ss->orig_dsize = dsize; + + ss->payload = ss->data; + ss->prev = ss->next = nullptr; + ss->ts = ss->seq = 0; + ss->size = ss->orig_dsize; + ss->urg_offset = 0; + ss->buffered = 0; + + return ss; +} + +void TcpSegment::term(TcpSegment* seg) +{ + unsigned dropped = sizeof(TcpSegment); + + if ( seg->size > 0 ) + dropped += seg->size - 1; // seg contains 1st byte + + tcp_memcap->dealloc(dropped); + free(seg); + tcpStats.segs_released++; +} + +bool TcpSegment::is_retransmit(const uint8_t* rdata, uint16_t rsize, uint32_t rseq) +{ + // retransmit must have same payload at same place + if ( !SEQ_EQ(seq, rseq) ) + return false; + + if ( ((size <= rsize) and !memcmp(data, rdata, size)) or + ((size > rsize) and !memcmp(data, rdata, rsize)) ) + return true; + + return false; +} + +//------------------------------------------------------------------------- +// flush policy stuff +//------------------------------------------------------------------------- + static inline void init_flush_policy(Flow*, TcpTracker* trk) { if ( !trk->splitter ) @@ -644,15 +696,13 @@ inline bool StreamTcpConfig::midstream_allowed(Packet* p) } //------------------------------------------------------------------------- -// FIXIT-L directionality must be fixed per 297 bug fixes -// // when client ports are configured, that means c2s and is stored on the // client side; when the session starts, the server policy is obtained from // the client side because segments are stored on the receiving side. // -// this could be improved further beyond the 297 bug fixes by storing the -// c2s policy on the server side and then obtaining server policy from the -// server on session startup. +// this could be improved further by storing the c2s policy on the server +// side and then obtaining server policy from the server on session +// startup. // // either way, this client / server distinction must be kept in mind to // make sense of the code in this file. @@ -1634,7 +1684,6 @@ static inline void UpdateSsn( void tcp_sinit() { s5_pkt = PacketManager::encode_new(); - cleanup_pkt = PacketManager::encode_new(); tcp_memcap = new Memcap(26214400); // FIXIT-M replace with session memcap //AtomSplitter::init(); // FIXIT-L PAF implement } @@ -1647,11 +1696,6 @@ void tcp_sterm() s5_pkt = nullptr; } - if (cleanup_pkt) - { - PacketManager::encode_delete(cleanup_pkt); - cleanup_pkt = nullptr; - } delete tcp_memcap; tcp_memcap = nullptr; } @@ -1678,25 +1722,6 @@ static inline void SetupTcpDataBlock(TcpDataBlock* tdb, Packet* p) #endif } -static void SegmentFree (TcpSegment *seg) -{ - unsigned dropped = sizeof(TcpSegment); - - STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - "Dumping segment at seq %X, size %d, caplen %d\n", - seg->seq, seg->size, seg->caplen); ); - - if ( seg->caplen > 0 ) - dropped += seg->caplen - 1; // seg contains 1st byte - - tcp_memcap->dealloc(dropped); - free(seg); - tcpStats.segs_released++; - - STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - "SegmentFree dropped %d bytes\n", dropped); ); -} - static void DeleteSeglist(TcpSegment *listhead) { TcpSegment *idx = listhead; @@ -1710,7 +1735,7 @@ static void DeleteSeglist(TcpSegment *listhead) i++; dump_me = idx; idx = idx->next; - SegmentFree(dump_me); + TcpSegment::term(dump_me); } STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, @@ -1718,7 +1743,7 @@ static void DeleteSeglist(TcpSegment *listhead) } static inline int purge_alerts( - TcpTracker *st, uint32_t flush_seq, Flow* flow) + TcpTracker *st, uint32_t /*flush_seq*/, Flow* flow) { int i; int new_count = 0; @@ -1727,13 +1752,14 @@ static inline int purge_alerts( { StreamAlertInfo* ai = st->alerts + i; - if (SEQ_LT(ai->seq, flush_seq) ) + //if (SEQ_LT(ai->seq, flush_seq) ) { stream.log_extra_data( flow, st->xtradata_mask, ai->event_id, ai->event_second); memset(ai, 0, sizeof(*ai)); } +#if 0 else { if (new_count != i) @@ -1742,6 +1768,7 @@ static inline int purge_alerts( } new_count++; } +#endif } st->alert_count = new_count; @@ -1883,18 +1910,16 @@ static inline int purge_flushed_ackd (TcpSession *tcpssn, TcpTracker *st) return 0; } +#define SEPARATOR \ + "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" + static void ShowRebuiltPacket(TcpSession* ssn, Packet* pkt) { if ( (ssn->client.config->flags & STREAM_CONFIG_SHOW_PACKETS) || (ssn->server.config->flags & STREAM_CONFIG_SHOW_PACKETS) ) { -#ifdef REG_TEST - printf("+++++++++++++++++++Stream Packet+++++++++++++++++++++\n"); -#endif - LogIPPkt(pkt); -#ifdef REG_TEST - printf("\n+++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); -#endif + LogFlow(pkt); + LogNetData(pkt->data, pkt->dsize, pkt); } } @@ -1961,7 +1986,7 @@ static int FlushStream( { s5_pkt->data = sb->data; s5_pkt->dsize = sb->length; - assert(sb->length < 65536); // FIXIT-M should be < s5_pkt->max_dsize); + assert(sb->length <= s5_pkt->max_dsize); // FIXIT-M flushbuf should be eliminated from this function // since we are actually using the stream splitter buffer @@ -1981,7 +2006,7 @@ static int FlushStream( ss->size = bytes_to_copy; sr->seq += bytes_to_copy; sr->size -= bytes_to_copy; - sr->payload += bytes_to_copy + (ss->payload - ss->data); + sr->payload += bytes_to_copy; } ss->buffered = SL_BUF_FLUSHED; st->flush_count++; @@ -2023,36 +2048,75 @@ static int FlushStream( return bytes_flushed; } +// FIXIT-L consolidate encode format, update, and this into new function? +static void prep_s5_pkt(Flow* flow, Packet* p, uint32_t pkt_flags) +{ + s5_pkt->ptrs.set_pkt_type(PktType::USER); + s5_pkt->proto_bits |= PROTO_BIT__TCP; + s5_pkt->packet_flags |= (pkt_flags & PKT_PDU_FULL); + s5_pkt->flow = flow; + + if ( p == s5_pkt ) + { + // final + if ( pkt_flags & PKT_FROM_SERVER ) + { + s5_pkt->packet_flags |= PKT_FROM_SERVER; + s5_pkt->ptrs.ip_api.set(flow->server_ip, flow->client_ip); + s5_pkt->ptrs.sp = flow->server_port; + s5_pkt->ptrs.dp = flow->client_port; + } + else + { + s5_pkt->packet_flags |= PKT_FROM_CLIENT; + s5_pkt->ptrs.ip_api.set(flow->client_ip, flow->server_ip); + s5_pkt->ptrs.sp = flow->client_port; + s5_pkt->ptrs.dp = flow->server_port; + } + } + else if ( !p->packet_flags || (pkt_flags & p->packet_flags) ) + { + // forward + s5_pkt->packet_flags |= (p->packet_flags & (PKT_FROM_CLIENT|PKT_FROM_SERVER)); + s5_pkt->ptrs.ip_api.set(*p->ptrs.ip_api.get_src(), *p->ptrs.ip_api.get_dst()); + s5_pkt->ptrs.sp = p->ptrs.sp; + s5_pkt->ptrs.dp = p->ptrs.dp; + } + else + { + // reverse + if ( p->packet_flags & PKT_FROM_CLIENT ) + s5_pkt->packet_flags |= PKT_FROM_SERVER; + else + s5_pkt->packet_flags |= PKT_FROM_CLIENT; + + s5_pkt->ptrs.ip_api.set(*p->ptrs.ip_api.get_dst(), *p->ptrs.ip_api.get_src()); + s5_pkt->ptrs.dp = p->ptrs.sp; + s5_pkt->ptrs.sp = p->ptrs.dp; + } +} + static inline int _flush_to_seq( - TcpSession *tcpssn, TcpTracker *st, uint32_t bytes, Packet *p, uint32_t dir) + TcpSession *tcpssn, TcpTracker *st, uint32_t bytes, Packet *p, uint32_t pkt_flags) { uint32_t stop_seq; uint32_t footprint; uint32_t bytes_processed = 0; int32_t flushed_bytes; -#ifdef HAVE_DAQ_ADDRESS_SPACE_ID - DAQ_PktHdr_t pkth; -#endif EncodeFlags enc_flags = 0; PROFILE_VARS; MODULE_PROFILE_START(s5TcpFlushPerfStats); - if ( !p->packet_flags || (dir & p->packet_flags) ) - enc_flags = ENC_FLAG_FWD; - #ifdef HAVE_DAQ_ADDRESS_SPACE_ID - GetPacketHeaderFoo(tcpssn, &pkth, dir); - PacketManager::encode_format_with_daq_info(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP, &pkth, 0); -#elif defined(HAVE_DAQ_ACQUIRE_WITH_META) - PacketManager::encode_format_with_daq_info(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP, 0); + DAQ_PktHdr_t pkth; + GetPacketHeaderFoo(tcpssn, &pkth, pkt_flags); + PacketManager::format_tcp(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP, &pkth, pkth.opaque); #else - PacketManager::encode_format(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP); + PacketManager::format_tcp(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP); #endif - // TBD in ips mode, these should be coming from current packet (tdb) - ((TCPHdr*)s5_pkt->ptrs.tcph)->th_ack = htonl(st->l_unackd); - ((TCPHdr*)s5_pkt->ptrs.tcph)->th_win = htons((uint16_t)st->l_window); + prep_s5_pkt(tcpssn->flow, p, pkt_flags); // if not specified, set bytes to flush to what was acked if ( !bytes && SEQ_GT(st->r_win_base, st->seglist_base_seq) ) @@ -2098,7 +2162,6 @@ static inline int _flush_to_seq( ((DAQ_PktHdr_t*)s5_pkt->pkth)->ts.tv_sec = st->seglist_next->tv.tv_sec; ((DAQ_PktHdr_t*)s5_pkt->pkth)->ts.tv_usec = st->seglist_next->tv.tv_usec; - ((TCPHdr*)s5_pkt->ptrs.tcph)->th_seq = htonl(st->seglist_next->seq); /* setup the pseudopacket payload */ s5_pkt->dsize = 0; @@ -2120,13 +2183,9 @@ static inline int _flush_to_seq( if ((p->packet_flags & PKT_PDU_TAIL)) s5_pkt->packet_flags |= PKT_PDU_TAIL; - PacketManager::encode_update(s5_pkt); - sfBase.iStreamFlushes++; bytes_processed += flushed_bytes; - s5_pkt->packet_flags |= dir; - s5_pkt->flow = tcpssn->flow; s5_pkt->application_protocol_ordinal = p->application_protocol_ordinal; ShowRebuiltPacket(tcpssn, s5_pkt); @@ -2167,7 +2226,7 @@ static inline int _flush_to_seq( st->flags &= ~TF_MISSING_PREV_PKT; } } - while ( DataToFlush(st) ); + while ( st->seglist_next and DataToFlush(st) ); /* tell them how many bytes we processed */ MODULE_PROFILE_END(s5TcpFlushPerfStats); @@ -2179,7 +2238,7 @@ static inline int _flush_to_seq( * and fire it thru the system. */ static inline int flush_to_seq( - TcpSession *tcpssn, TcpTracker *st, uint32_t bytes, Packet *p, uint32_t dir) + TcpSession *tcpssn, TcpTracker *st, uint32_t bytes, Packet *p, uint32_t pkt_flags) { STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "In flush_to_seq()\n"); ); @@ -2229,7 +2288,7 @@ static inline int flush_to_seq( } st->flags &= ~TF_FIRST_PKT_MISSING; - return _flush_to_seq(tcpssn, st, bytes, p, dir); + return _flush_to_seq(tcpssn, st, bytes, p, pkt_flags); } /* @@ -2289,13 +2348,6 @@ static inline uint32_t get_q_sequenced(TcpTracker *st) return ( len > 0 ) ? len : 0; } -static inline int flush_ackd( - TcpSession *tcpssn, TcpTracker *st, Packet *p, uint32_t dir) -{ - uint32_t bytes = get_q_footprint(st); - return flush_to_seq(tcpssn, st, bytes, p, dir); -} - // FIXIT-L flush_stream() calls should be replaced with calls to // CheckFlushPolicyOn*() with the exception that for the *OnAck() case, // any available ackd data must be flushed in both directions. @@ -2306,13 +2358,14 @@ static inline int flush_stream( if ( !st->flush_policy ) return 0; + uint32_t bytes; + if ( Normalize_IsEnabled(NORM_TCP_IPS) ) - { - uint32_t bytes = get_q_sequenced(st); - return flush_to_seq(tcpssn, st, bytes, p, dir); - } + bytes = get_q_sequenced(st); + else + bytes = get_q_footprint(st); - return flush_ackd(tcpssn, st, p, dir); + return flush_to_seq(tcpssn, st, bytes, p, dir); } static void TcpSessionClear (Flow* lwssn, TcpSession* tcpssn, int freeApplicationData) @@ -2377,33 +2430,27 @@ static void TcpSessionClear (Flow* lwssn, TcpSession* tcpssn, int freeApplicatio } static void final_flush( - Flow* lwssn, TcpSession* tcpssn, TcpTracker& trk, Packet* p, - PegCount& peg, uint32_t flag) + TcpSession* tcpssn, TcpTracker& trk, Packet* p, + PegCount& peg, uint32_t dir) { if ( !p ) { - DAQ_PktHdr_t* const tmp_pcap_hdr = const_cast(cleanup_pkt->pkth); + p = s5_pkt; + + DAQ_PktHdr_t* const tmp_pcap_hdr = const_cast(p->pkth); peg++; /* Do each field individually because of size differences on 64bit OS */ tmp_pcap_hdr->ts.tv_sec = trk.seglist->tv.tv_sec; tmp_pcap_hdr->ts.tv_usec = trk.seglist->tv.tv_usec; - tmp_pcap_hdr->caplen = trk.seglist->caplen; - tmp_pcap_hdr->pktlen = trk.seglist->pktlen; - - Snort::decode_rebuilt_packet(cleanup_pkt, tmp_pcap_hdr, trk.seglist->pkt, lwssn); - p = cleanup_pkt; } - if ( p->ptrs.tcph ) - { - trk.flags |= TF_FORCE_FLUSH; + trk.flags |= TF_FORCE_FLUSH; - if ( flush_stream(tcpssn, &trk, p, flag) ) - purge_flushed_ackd(tcpssn, &trk); + if ( flush_stream(tcpssn, &trk, p, dir) ) + purge_flushed_ackd(tcpssn, &trk); - trk.flags &= ~TF_FORCE_FLUSH; - } + trk.flags &= ~TF_FORCE_FLUSH; } // flush data on both sides as necessary @@ -2415,7 +2462,7 @@ static void FlushQueuedSegs(Flow* lwssn, TcpSession* tcpssn, bool clear, Packet* if ( (pending and (p or tcpssn->client.seglist) and !(lwssn->ssn_state.ignore_direction & SSN_DIR_FROM_SERVER)) ) { - final_flush(lwssn, tcpssn, tcpssn->client, p, tcpStats.s5tcp1, PKT_FROM_SERVER); + final_flush(tcpssn, tcpssn->client, p, tcpStats.s5tcp1, PKT_FROM_SERVER); } // flush the server (data from client) @@ -2424,7 +2471,7 @@ static void FlushQueuedSegs(Flow* lwssn, TcpSession* tcpssn, bool clear, Packet* if ( (pending and (p or tcpssn->server.seglist) and !(lwssn->ssn_state.ignore_direction & SSN_DIR_FROM_CLIENT)) ) { - final_flush(lwssn, tcpssn, tcpssn->server, p, tcpStats.s5tcp2, PKT_FROM_CLIENT); + final_flush(tcpssn, tcpssn->server, p, tcpStats.s5tcp2, PKT_FROM_CLIENT); } } @@ -2455,7 +2502,9 @@ static void CheckSegments (const TcpTracker* a) #endif -#ifdef REG_TEST +#ifndef REG_TEST +#define S5TraceTCP(pkt, flow, tdb, evt) +#else #define LCL(p, x) (p->x - p->isn) #define RMT(p, x, q) (p->x - (q ? q->isn : 0)) @@ -2643,10 +2692,7 @@ static inline void S5TraceTCP( } TraceTCP(p, lws, tdb, event); } - -#else -#define S5TraceTCP(pkt, flow, tdb, evt) -#endif // REG_TEST +#endif static uint32_t StreamGetTcpTimestamp(Packet* p, uint32_t* ts, int strip) { @@ -2811,51 +2857,6 @@ static void FinishServerInit(Packet* p, TcpDataBlock* tdb, TcpSession* ssn) #endif } -static void NewQueue( - TcpTracker *st, Packet *p, TcpDataBlock *tdb) -{ - TcpSegment *ss = NULL; - uint32_t overlap = 0; - PROFILE_VARS; - - STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - "In NewQueue\n"); ); - - MODULE_PROFILE_START(s5TcpInsertPerfStats); - - if (st->flush_policy != STREAM_FLPOLICY_IGNORE) - { - uint32_t seq = tdb->seq; - - if ( p->ptrs.tcph->th_flags & TH_SYN ) - seq++; - - /* new packet seq is below the last ack... */ - if ( SEQ_GT(st->r_win_base, seq) ) - { - STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - "segment overlaps ack'd data...\n"); ); - overlap = st->r_win_base - tdb->seq; - if (overlap >= p->dsize) - { - STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - "full overlap on ack'd data, dropping segment\n"); ); - MODULE_PROFILE_END(s5TcpInsertPerfStats); - return; - } - } - - AddStreamNode(st, p, tdb, p->dsize, overlap, 0, tdb->seq+overlap, NULL, &ss); - - STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - "Attached new queue to seglist, %d bytes queued, " - "base_seq 0x%X\n", - ss->size, st->seglist_base_seq); ); - } - - MODULE_PROFILE_END(s5TcpInsertPerfStats); -} - static inline int SegmentFastTrack(TcpSegment *tail, TcpDataBlock *tdb) { STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, @@ -2868,41 +2869,6 @@ static inline int SegmentFastTrack(TcpSegment *tail, TcpDataBlock *tdb) return 0; } -static inline TcpSegment* SegmentAlloc( - Packet* p, const struct timeval* tv, uint32_t caplen, uint32_t pktlen, const uint8_t* pkt) -{ - TcpSegment* ss; - unsigned size = sizeof(*ss); - - if ( caplen > 0 ) - size += caplen - 1; // ss contains 1st byte - - tcp_memcap->alloc(size); - - if ( tcp_memcap->at_max() ) - { - sfBase.iStreamFaults++; - - if ( !p ) - { - tcp_memcap->dealloc(size); - return NULL; - } - flow_con->prune_flows(PktType::TCP, p); - } - - ss = (TcpSegment*)SnortAlloc(size); - - ss->tv.tv_sec = tv->tv_sec; - ss->tv.tv_usec = tv->tv_usec; - ss->caplen = caplen; - ss->pktlen = pktlen; - - memcpy(ss->pkt, pkt, caplen); - - return ss; -} - static int AddStreamNode( TcpTracker *st, Packet *p, TcpDataBlock* tdb, @@ -2910,8 +2876,7 @@ static int AddStreamNode( uint32_t slide, uint32_t trunc, uint32_t seq, - TcpSegment *left, - TcpSegment **retSeg) + TcpSegment *left) { TcpSegment *ss = NULL; int32_t newSize = len - slide - trunc; @@ -2952,10 +2917,11 @@ static int AddStreamNode( return STREAM_INSERT_ANOMALY; } - ss = SegmentAlloc(p, &p->pkth->ts, p->pkth->caplen, p->pkth->pktlen, p->pkt); + // FIXIT-L don't allocate overlapped part + ss = TcpSegment::init(p, p->pkth->ts, p->data, p->dsize); - ss->data = ss->pkt + (p->data - p->pkt); - ss->orig_dsize = p->dsize; + if ( !ss ) + return STREAM_INSERT_FAILED; ss->payload = ss->data + slide; ss->size = (uint16_t)newSize; @@ -3004,8 +2970,6 @@ static int AddStreamNode( StreamSeglistAddNode(st, left, ss); st->seg_bytes_logical += ss->size; - st->seg_bytes_total += ss->caplen; /* Includes protocol headers and payload */ - st->total_segs_queued++; st->total_bytes_queued += ss->size; p->packet_flags |= PKT_STREAM_INSERT; @@ -3015,7 +2979,6 @@ static int AddStreamNode( "%d segments queued\n", ss->size, ss->seq, st->seg_bytes_logical, SegsToFlush(st, 0)); ); - *retSeg = ss; #ifdef SEG_TEST CheckSegments(st); #endif @@ -3025,14 +2988,12 @@ static int AddStreamNode( static int DupStreamNode( Packet *p, TcpTracker *st, TcpSegment *left, TcpSegment **retSeg) { - TcpSegment* ss = SegmentAlloc(p, &left->tv, left->caplen, left->pktlen, left->pkt); + TcpSegment* ss = TcpSegment::init(p, left->tv, left->payload, left->size); if ( !ss ) return STREAM_INSERT_FAILED; tcpStats.segs_split++; - ss->data = ss->pkt + (left->data - left->pkt); - ss->orig_dsize = left->orig_dsize; /* twiddle the values for overlaps */ ss->payload = ss->data; @@ -3040,8 +3001,6 @@ static int DupStreamNode( ss->seq = left->seq; StreamSeglistAddNode(st, left, ss); - st->seg_bytes_total += ss->caplen; - st->total_segs_queued++; //st->total_bytes_queued += ss->size; STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, @@ -3053,23 +3012,6 @@ static int DupStreamNode( return STREAM_INSERT_OK; } -static inline bool IsRetransmit( - TcpSegment *seg, const uint8_t *rdata, uint16_t rsize, uint32_t rseq) -{ - // If seg->orig_size == seg->size, then it's sequence number wasn't adjusted - // so can just do a straight compare of the sequence numbers. - // Don't want to count as a retransmit if segment's size/sequence number - // has been adjusted. - if (SEQ_EQ(seg->seq, rseq) && (seg->orig_dsize == seg->size)) - { - if (((seg->size <= rsize) && (memcmp(seg->data, rdata, seg->size) == 0)) - || ((seg->size > rsize) && (memcmp(seg->data, rdata, rsize) == 0))) - return true; - } - - return false; -} - static inline void RetransmitProcess(Packet* p, TcpSession*) { // Data has already been analyzed so don't bother looking at it again. @@ -3094,10 +3036,50 @@ static inline NormMode get_norm_ips(TcpTracker* st) return Normalize_GetMode(NORM_TCP_IPS); } +static void NewQueue( + TcpTracker *st, Packet *p, TcpDataBlock *tdb) +{ + PROFILE_VARS; + MODULE_PROFILE_START(s5TcpInsertPerfStats); + + STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "In NewQueue\n"); ); + + uint32_t overlap = 0; + uint32_t seq = tdb->seq; + + if ( p->ptrs.tcph->th_flags & TH_SYN ) + seq++; + + /* new packet seq is below the last ack... */ + if ( SEQ_GT(st->r_win_base, seq) ) + { + STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, + "segment overlaps ack'd data...\n"); ); + overlap = st->r_win_base - tdb->seq; + + if (overlap >= p->dsize) + { + STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, + "full overlap on ack'd data, dropping segment\n"); ); + MODULE_PROFILE_END(s5TcpInsertPerfStats); + return; + } + } + + // BLOCK add new block to seglist containing data + AddStreamNode(st, p, tdb, p->dsize, overlap, 0, tdb->seq+overlap, NULL); + + STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, + "Attached new queue to seglist, %d bytes queued, " + "base_seq 0x%X\n", + p->dsize-overlap, st->seglist_base_seq); ); + + MODULE_PROFILE_END(s5TcpInsertPerfStats); +} + static int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn) { - TcpSegment *ss = NULL; TcpSegment *left = NULL; TcpSegment *right = NULL; TcpSegment *dump_me = NULL; @@ -3156,9 +3138,9 @@ static int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, "Fast tracking segment! (tail_seq %X size %d)\n", st->seglist_tail->seq, st->seglist_tail->size); ); + // BLOCK add to existing block and/or allocate new block ret = AddStreamNode(st, p, tdb, len, - slide /* 0 */, trunc /* 0 */, seq, left /* tail */, - &ss); + slide /* 0 */, trunc /* 0 */, seq, left /* tail */); MODULE_PROFILE_END(s5TcpInsertPerfStats); return ret; @@ -3191,6 +3173,8 @@ static int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, if (SEQ_LEQ(dist_head, dist_tail)) { + TcpSegment* ss; + /* Start iterating at the head (left) */ for (ss = st->seglist; ss; ss = ss->next) { @@ -3219,6 +3203,8 @@ static int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, } else { + TcpSegment* ss; + /* Start iterating at the tail (right) */ for (ss = st->seglist_tail; ss; ss = ss->prev) { @@ -3374,8 +3360,7 @@ static int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, ret = DupStreamNode(p, st, left, &right); if (ret != STREAM_INSERT_OK) { - /* No warning, - * its done in StreamSeglistAddNode */ + /* No warning, its done in StreamSeglistAddNode */ MODULE_PROFILE_END(s5TcpInsertPerfStats); return ret; } @@ -3383,9 +3368,10 @@ static int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, st->seg_bytes_logical -= overlap; right->seq = seq + len; - right->size -= (int16_t)(seq + len - left->seq); - right->payload += (seq + len - left->seq); - st->seg_bytes_logical -= (seq + len - left->seq); + uint16_t delta = (int16_t)(right->seq - left->seq); + right->size -= delta; + right->payload += delta; + st->seg_bytes_logical -= delta; } else { @@ -3437,7 +3423,7 @@ static int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, if (overlap < right->size) { - if (IsRetransmit(right, rdata, rsize, rseq)) + if ( right->is_retransmit(rdata, rsize, rseq) ) { // All data was retransmitted RetransmitProcess(p, tcpssn); @@ -3508,7 +3494,7 @@ static int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, // Don't want to count retransmits as overlaps or do anything // else with them. Account for retransmits of multiple PDUs // in one segment. - if (IsRetransmit(right, rdata, rsize, rseq)) + if ( right->is_retransmit(rdata, rsize, rseq) ) { rdata += right->size; rsize -= right->size; @@ -3629,7 +3615,7 @@ static int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, /* insert this one, and see if we need to chunk it up Adjust slide so that is correct relative to orig seq */ slide = seq - tdb->seq; - ret = AddStreamNode(st, p, tdb, len, slide, trunc, seq, left, &ss); + ret = AddStreamNode(st, p, tdb, len, slide, trunc, seq, left); if (ret != STREAM_INSERT_OK) { /* no warning, already done above */ @@ -3693,7 +3679,7 @@ right_overlap_last: /* Adjust slide so that is correct relative to orig seq */ slide = seq - tdb->seq; ret = AddStreamNode( - st, p, tdb, len, slide, trunc, seq, left, &ss); + st, p, tdb, len, slide, trunc, seq, left); } else { @@ -3723,6 +3709,13 @@ static void ProcessTcpStream( SetPacketHeaderFoo(tcpssn, p); #endif + if (rcv->flush_policy == STREAM_FLPOLICY_IGNORE) + { + STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, + "Ignoring segment due to IGNORE flush_policy\n"); ); + return; + } + if ((config->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY) && !tcpssn->flow->two_way_traffic()) { @@ -3765,62 +3758,40 @@ static void ProcessTcpStream( return; } - if (rcv->seg_count != 0) - { - if (rcv->flush_policy == STREAM_FLPOLICY_IGNORE) - { - STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - "Ignoring segment due to IGNORE flush_policy\n"); ); - return; - } - else - { - STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - "queuing segment\n"); ); - - if ( SEQ_GT(rcv->r_win_base, tdb->seq) ) - { - uint32_t offset = rcv->r_win_base - tdb->seq; + STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, + "queuing segment\n"); ); - if ( offset < p->dsize ) - { - tdb->seq += offset; - p->data += offset; - p->dsize -= (uint16_t)offset; + if ( !rcv->seg_count ) + { + NewQueue(rcv, p, tdb); + return; + } + if ( SEQ_GT(rcv->r_win_base, tdb->seq) ) + { + uint32_t offset = rcv->r_win_base - tdb->seq; - StreamQueue(rcv, p, tdb, tcpssn); + if ( offset < p->dsize ) + { + tdb->seq += offset; + p->data += offset; + p->dsize -= (uint16_t)offset; - p->dsize += (uint16_t)offset; - p->data -= offset; - tdb->seq -= offset; - } - } - else - StreamQueue(rcv, p, tdb, tcpssn); + StreamQueue(rcv, p, tdb, tcpssn); - if ((rcv->config->overlap_limit) && - (rcv->overlap_count > rcv->config->overlap_limit)) - { - /* Alert on overlap limit and reset counter */ - EventExcessiveOverlap(); - rcv->overlap_count = 0; - } + p->dsize += (uint16_t)offset; + p->data -= offset; + tdb->seq -= offset; } } else + StreamQueue(rcv, p, tdb, tcpssn); + + if ((rcv->config->overlap_limit) && + (rcv->overlap_count > rcv->config->overlap_limit)) { - if (rcv->flush_policy == STREAM_FLPOLICY_IGNORE) - { - STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - "Ignoring segment due to IGNORE flush_policy\n"); ); - return; - } - else - { - STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, - "queuing segment\n"); ); - NewQueue(rcv, p, tdb); - } + /* Alert on overlap limit and reset counter */ + EventExcessiveOverlap(); + rcv->overlap_count = 0; } } @@ -5910,8 +5881,6 @@ int CheckFlushPolicyOnAck( static void StreamSeglistAddNode( TcpTracker *st, TcpSegment *prev, TcpSegment *ss) { - tcpStats.segs_queued++; - if (prev) { ss->next = prev->next; @@ -5932,6 +5901,9 @@ static void StreamSeglistAddNode( st->seglist = ss; } st->seg_count++; + st->seg_bytes_total += ss->orig_dsize; + st->total_segs_queued++; + tcpStats.segs_queued++; } static int StreamSeglistDeleteNode (TcpTracker* st, TcpSegment* seg) @@ -5954,9 +5926,9 @@ static int StreamSeglistDeleteNode (TcpTracker* st, TcpSegment* seg) st->seglist_tail = seg->prev; st->seg_bytes_logical -= seg->size; - st->seg_bytes_total -= seg->caplen; + st->seg_bytes_total -= seg->orig_dsize; - ret = seg->caplen; + ret = seg->orig_dsize; if (seg->buffered) { @@ -5967,7 +5939,7 @@ static int StreamSeglistDeleteNode (TcpTracker* st, TcpSegment* seg) if ( st->seglist_next == seg ) st->seglist_next = NULL; - SegmentFree(seg); + TcpSegment::term(seg); st->seg_count--; return ret; @@ -6180,7 +6152,7 @@ void TcpSession::flush_client(Packet* p) void TcpSession::flush_listener(Packet* p) { TcpTracker *listener = NULL; - int dir = 0; + uint32_t dir = 0; int flushed = 0; /* figure out direction of this packet -- we should've already @@ -6217,7 +6189,7 @@ void TcpSession::flush_listener(Packet* p) void TcpSession::flush_talker(Packet* p) { TcpTracker *talker = NULL; - int dir = 0; + uint32_t dir = 0; int flushed = 0; /* figure out direction of this packet -- we should've already @@ -6251,92 +6223,57 @@ void TcpSession::flush_talker(Packet* p) } } -/* Iterates through the packets that were reassembled for - * logging of tagged packets. - */ -int TcpSession::get_rebuilt_packets( - Packet* p, PacketIterator callback, void *userdata) +// FIXIT add alert and check alerted go away when we finish +// packet / PDU split because PDU rules won't run on raw packets +bool TcpSession::add_alert(Packet* p, uint32_t gid, uint32_t sid) { - int packets = 0; TcpTracker *st; - TcpSegment *ss; - uint32_t start_seq = ntohl(p->ptrs.tcph->th_seq); - uint32_t end_seq = start_seq + p->dsize; + StreamAlertInfo* ai; - /* TcpTracker is the opposite of the ip of the reassembled - * packet --> it came out the queue for the other side */ - if (sfip_equals(p->ptrs.ip_api.get_src(), &flow->client_ip)) + if (sfip_equals(p->ptrs.ip_api.get_src(),&flow->client_ip)) st = &server; else st = &client; - // skip over segments not covered by this reassembled packet - for (ss = st->seglist; ss && SEQ_LT(ss->seq, start_seq); ss = ss->next); + if (st->alert_count >= MAX_SESSION_ALERTS) + return false; + + ai = st->alerts + st->alert_count; + ai->gid = gid; + ai->sid = sid; + ai->seq = 0; - // return flushed segments only - for (; ss && ss->buffered == SL_BUF_FLUSHED; ss = ss->next) - { - if (SEQ_GEQ(ss->seq,start_seq) && SEQ_LT(ss->seq, end_seq)) - { - DAQ_PktHdr_t pkth; - pkth.ts.tv_sec = ss->tv.tv_sec; - pkth.ts.tv_usec = ss->tv.tv_usec; - pkth.caplen = ss->caplen; - pkth.pktlen = ss->pktlen; - - callback(&pkth, ss->pkt, userdata); - packets++; - } - else - break; - } + st->alert_count++; - return packets; + return true; } -/* Iterates through the packets that were reassembled for - * logging of tagged packets. - */ -int TcpSession::get_segments( - Packet* p, StreamSegmentIterator callback, void *userdata) +bool TcpSession::check_alerted(Packet* p, uint32_t gid, uint32_t sid) { - int packets = 0; + /* If this is not a rebuilt packet, no need to check further */ + if ( !(p->packet_flags & PKT_REBUILT_STREAM) ) + return false; + TcpTracker *st; - TcpSegment *ss; - uint32_t start_seq = ntohl(p->ptrs.tcph->th_seq); - uint32_t end_seq = start_seq + p->dsize; - /* TcpTracker is the opposite of the ip of the reassembled - * packet --> it came out the queue for the other side */ if (sfip_equals(p->ptrs.ip_api.get_src(), &flow->client_ip)) st = &server; else st = &client; - // skip over segments not covered by this reassembled packet - for (ss = st->seglist; ss && SEQ_LT(ss->seq, start_seq); ss = ss->next); - - // return flushed segments only - for (; ss && ss->buffered == SL_BUF_FLUSHED; ss = ss->next) + for ( int i = 0; i < st->alert_count; i++ ) { - if (SEQ_GEQ(ss->seq,start_seq) && SEQ_LT(ss->seq, end_seq)) + /* This is a rebuilt packet and if we've seen this alert before, + * return that we have previously alerted on original packet. + */ + if ( st->alerts[i].gid == gid && + st->alerts[i].sid == sid ) { - DAQ_PktHdr_t pkth; - pkth.ts.tv_sec = ss->tv.tv_sec; - pkth.ts.tv_usec = ss->tv.tv_usec; - pkth.caplen = ss->caplen; - pkth.pktlen = ss->pktlen; - - if (callback(&pkth, ss->pkt, ss->data, ss->seq, userdata) != 0) - return -1; - - packets++; + return true; } - else - break; } - return packets; + return false; } int TcpSession::update_alert( @@ -6351,10 +6288,7 @@ int TcpSession::update_alert( else st = &client; - seq_num = GET_PKT_SEQ(p); - - if ( p->ptrs.tcph->th_flags & TH_FIN ) - seq_num--; + seq_num = 0; for (i=0; ialert_count; i++) { @@ -6652,60 +6586,6 @@ midstream_pickup_allowed: return 0; } -bool TcpSession::add_alert(Packet* p, uint32_t gid, uint32_t sid) -{ - TcpTracker *st; - StreamAlertInfo* ai; - - if (sfip_equals(p->ptrs.ip_api.get_src(),&flow->client_ip)) - st = &server; - else - st = &client; - - if (st->alert_count >= MAX_SESSION_ALERTS) - return false; - - ai = st->alerts + st->alert_count; - ai->gid = gid; - ai->sid = sid; - ai->seq = GET_PKT_SEQ(p); - - if ( p->ptrs.tcph->th_flags & TH_FIN ) - ai->seq--; - - st->alert_count++; - - return true; -} - -bool TcpSession::check_alerted(Packet* p, uint32_t gid, uint32_t sid) -{ - /* If this is not a rebuilt packet, no need to check further */ - if ( !(p->packet_flags & PKT_REBUILT_STREAM) ) - return false; - - TcpTracker *st; - - if (sfip_equals(p->ptrs.ip_api.get_src(), &flow->client_ip)) - st = &server; - else - st = &client; - - for ( int i = 0; i < st->alert_count; i++ ) - { - /* This is a rebuilt packet and if we've seen this alert before, - * return that we have previously alerted on original packet. - */ - if ( st->alerts[i].gid == gid && - st->alerts[i].sid == sid ) - { - return true; - } - } - - return false; -} - void TcpSession::flush() { if ( (SegsToFlush(&server, 1) > 0) || (SegsToFlush(&client, 1) > 0) ) diff --git a/src/stream/tcp/tcp_session.h b/src/stream/tcp/tcp_session.h index 5e39ab606..82aca3410 100644 --- a/src/stream/tcp/tcp_session.h +++ b/src/stream/tcp/tcp_session.h @@ -80,15 +80,16 @@ struct StreamAlertInfo struct TcpSegment { - uint8_t* data; + static TcpSegment* init(struct Packet*, const struct timeval&, const uint8_t*, unsigned); + static void term(TcpSegment*); + bool is_retransmit(const uint8_t*, uint16_t size, uint32_t); + uint8_t* payload; TcpSegment *prev; TcpSegment *next; struct timeval tv; - uint32_t caplen; - uint32_t pktlen; uint32_t ts; uint32_t seq; @@ -99,11 +100,7 @@ struct TcpSegment uint16_t urg_offset; uint8_t buffered; - // this sequence ensures 4-byte alignment of iph in pkt - // (only significant if we call the grinder) - uint8_t pad1; - uint16_t pad2; - uint8_t pkt[1]; // variable length + uint8_t data[1]; // variable length }; enum FlushPolicy @@ -209,9 +206,6 @@ public: void set_extra_data(Packet*, uint32_t /*flag*/) override; void clear_extra_data(Packet*, uint32_t /*flag*/) override; - int get_rebuilt_packets(Packet*, PacketIterator, void* /*userdata*/) override; - int get_segments(Packet*, StreamSegmentIterator, void* /*userdata*/) override; - bool is_sequenced(uint8_t /*dir*/) override; bool are_packets_missing(uint8_t /*dir*/) override; diff --git a/src/stream/user/user_session.cc b/src/stream/user/user_session.cc index 1dc7f81f0..db3601a5d 100644 --- a/src/stream/user/user_session.cc +++ b/src/stream/user/user_session.cc @@ -53,10 +53,15 @@ UserSegment* UserSegment::init(const uint8_t* p, unsigned n) { unsigned bucket = (n > BUCKET) ? n : BUCKET; UserSegment* us = (UserSegment*)malloc(sizeof(*us)+bucket-1); + + if ( !us ) + return nullptr; + us->len = 0; us->offset = 0; us->used = 0; us->copy(p, n); + return us; } @@ -275,6 +280,10 @@ void UserTracker::add_data(Packet* p) if ( avail < p->dsize ) { UserSegment* us = UserSegment::init(p->data+avail, p->dsize-avail); + + if ( !us ) + return; + seg_list.push_back(us); } total += p->dsize; @@ -486,7 +495,7 @@ int UserSession::process(Packet* p) UserTracker& ut = p->from_client() ? server : client; - if ( p->ptrs.decode_flags & DECODE_SOF ) + if ( p->ptrs.decode_flags & DECODE_SOF or !ut.splitter ) start(p, flow); if ( p->data && p->dsize ) @@ -523,12 +532,6 @@ void UserSession::flush_listener(Packet*) { } void UserSession::set_extra_data(Packet*, uint32_t /*flag*/) { } void UserSession::clear_extra_data(Packet*, uint32_t /*flag*/) { } -int UserSession::get_rebuilt_packets(Packet*, PacketIterator, void* /*userdata*/) -{ return 0; } - -int UserSession::get_segments(Packet*, StreamSegmentIterator, void* /*userdata*/) -{ return 0; } - uint8_t UserSession::get_reassembly_direction() { return SSN_DIR_NONE; } diff --git a/src/stream/user/user_session.h b/src/stream/user/user_session.h index ccaa48a42..d72f31fe5 100644 --- a/src/stream/user/user_session.h +++ b/src/stream/user/user_session.h @@ -117,9 +117,6 @@ private: void set_extra_data(Packet*, uint32_t flag) override; void clear_extra_data(Packet*, uint32_t flag) override; - int get_rebuilt_packets(Packet*, PacketIterator, void* userdata) override; - int get_segments(Packet*, StreamSegmentIterator, void* userdata) override; - uint8_t get_reassembly_direction() override; public: diff --git a/src/utils/stats.cc b/src/utils/stats.cc index e87f87651..01309275d 100644 --- a/src/utils/stats.cc +++ b/src/utils/stats.cc @@ -175,9 +175,7 @@ struct DAQStats PegCount verdicts[MAX_SFDAQ_VERDICT]; PegCount internal_blacklist; PegCount internal_whitelist; -#ifdef REG_TEST PegCount skipped; -#endif PegCount fail_open; PegCount idle; }; @@ -204,9 +202,7 @@ const PegInfo daq_names[] = // FIXIT-L these are not exactly DAQ counts - but they are related { "internal blacklist", "packets blacklisted internally due to lack of DAQ support" }, { "internal whitelist", "packets whitelisted internally due to lack of DAQ support" }, -#ifdef REG_TEST { "skipped", "packets skipped at startup" }, -#endif { "fail open", "packets passed during initialization" }, { "idle", "attempts to acquire from DAQ without available packets" }, { nullptr, nullptr } @@ -287,9 +283,7 @@ static void get_daq_stats(DAQStats& daq_stats) daq_stats.internal_blacklist = gaux.internal_blacklist; daq_stats.internal_whitelist = gaux.internal_whitelist; -#ifdef REG_TEST daq_stats.skipped = snort_conf->pkt_skip; -#endif daq_stats.fail_open = gaux.total_fail_open; daq_stats.idle = gaux.idle; } diff --git a/src/utils/util.cc b/src/utils/util.cc index 22bf7ccf7..97769dd0f 100644 --- a/src/utils/util.cc +++ b/src/utils/util.cc @@ -192,7 +192,7 @@ void ts_print(const struct timeval* tvp, char* timebuf) int year = (lt->tm_year >= 100) ? (lt->tm_year - 100) : lt->tm_year; (void)SnortSnprintf(timebuf, TIMEBUF_SIZE, - "%02d/%02d/%02d-%02d:%02d:%02d.%06u ", + "%02d/%02d/%02d-%02d:%02d:%02d.%06u", lt->tm_mon + 1, lt->tm_mday, year, s / 3600, (s % 3600) / 60, s % 60, (u_int)tvp->tv_usec); @@ -200,7 +200,7 @@ void ts_print(const struct timeval* tvp, char* timebuf) else { (void)SnortSnprintf(timebuf, TIMEBUF_SIZE, - "%02d/%02d-%02d:%02d:%02d.%06u ", lt->tm_mon + 1, + "%02d/%02d-%02d:%02d:%02d.%06u", lt->tm_mon + 1, lt->tm_mday, s / 3600, (s % 3600) / 60, s % 60, (u_int)tvp->tv_usec); }