diff -P -r -u3 snort-2.2.0/src/detection-plugins/Makefile.am snort-2.2.0_tagstream_1.3/src/detection-plugins/Makefile.am --- snort-2.2.0/src/detection-plugins/Makefile.am 2004-06-16 11:49:24.000000000 -0700 +++ snort-2.2.0_tagstream_1.3/src/detection-plugins/Makefile.am 2004-11-16 10:14:46.000000000 -0800 @@ -10,6 +10,7 @@ sp_ip_same_check.c sp_ip_same_check.h sp_ip_tos_check.c sp_ip_tos_check.h \ sp_ipoption_check.c sp_ipoption_check.h sp_pattern_match.c sp_pattern_match.h \ sp_react.c sp_react.h \ +sp_tag_stream.c sp_tag_stream.h \ sp_respond.c sp_respond.h sp_rpc_check.c sp_rpc_check.h \ sp_session.c sp_session.h sp_tcp_ack_check.c sp_tcp_ack_check.h \ sp_tcp_flag_check.h sp_tcp_flag_check.c sp_tcp_seq_check.c sp_tcp_seq_check.h \ diff -P -r -u3 snort-2.2.0/src/detection-plugins/Makefile.in snort-2.2.0_tagstream_1.3/src/detection-plugins/Makefile.in --- snort-2.2.0/src/detection-plugins/Makefile.in 2004-08-11 12:51:03.000000000 -0700 +++ snort-2.2.0_tagstream_1.3/src/detection-plugins/Makefile.in 2004-11-16 10:32:50.000000000 -0800 @@ -91,6 +91,7 @@ sp_ip_same_check.c sp_ip_same_check.h sp_ip_tos_check.c sp_ip_tos_check.h \ sp_ipoption_check.c sp_ipoption_check.h sp_pattern_match.c sp_pattern_match.h \ sp_react.c sp_react.h \ +sp_tag_stream.c sp_tag_stream.h \ sp_respond.c sp_respond.h sp_rpc_check.c sp_rpc_check.h \ sp_session.c sp_session.h sp_tcp_ack_check.c sp_tcp_ack_check.h \ sp_tcp_flag_check.h sp_tcp_flag_check.c sp_tcp_seq_check.c sp_tcp_seq_check.h \ @@ -120,6 +121,7 @@ sp_tcp_win_check.$(OBJEXT) sp_ttl_check.$(OBJEXT) \ sp_clientserver.$(OBJEXT) sp_byte_check.$(OBJEXT) \ sp_byte_jump.$(OBJEXT) sp_pcre.$(OBJEXT) sp_isdataat.$(OBJEXT) \ + sp_tag_stream.$(OBJEXT) \ sp_flowbits.$(OBJEXT) sp_asn1.$(OBJEXT) libspd_a_OBJECTS = $(am_libspd_a_OBJECTS) diff -P -r -u3 snort-2.2.0/src/detection-plugins/sp_tag_stream.c snort-2.2.0_tagstream_1.3/src/detection-plugins/sp_tag_stream.c --- snort-2.2.0/src/detection-plugins/sp_tag_stream.c 1969-12-31 16:00:00.000000000 -0800 +++ snort-2.2.0_tagstream_1.3/src/detection-plugins/sp_tag_stream.c 2004-11-16 11:14:50.000000000 -0800 @@ -0,0 +1,340 @@ +/* +** Copyright (C) 1998-2002 Martin Roesch +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_tag_stream.c,v 1.3 2004/11/16 13:18:00 By John Curry [john.curry@metre.net] Exp $ */ +/* + + This detection plugin will tag a stream or check for a tag in a stream + And return true or false as defined in the tagstream options + +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef WIN32 +#include +#include +#include +#endif /* !WIN32 */ + + +#include "rules.h" +#include "decode.h" +#include "plugbase.h" +#include "parser.h" +#include "util.h" +#include "debug.h" +#include "plugin_enum.h" +#include "spp_stream4.h" + +void TagStreamInit(char *, OptTreeNode *, int); +int TagStream(Packet *, struct _OptTreeNode *, OptFpList *); +void ParseTagStream(char *, OptTreeNode *); +static int ExtractTag6Bit(char *data,const char *type); +static int ExtractTag32Bit(char *data,const char *type); +Session *GetSession(Packet *); + +FILE *tag_stream_output=NULL; + +struct _TagStreamData{ + u_int32_t pkt; + u_int32_t pl:2, chk:7,set:7,unset:7,cl:2,inv:1; +} typedef TagStreamData; + +// Values for pl (pktlogic) 0 !=, 1 ==, 2 <, 3 > +// use these to determine logic to apply to pkt var +#define NOT_EQUAL 0 +#define EQUAL 1 +#define LESS_THAN 2 +#define GREATER_THAN 3 + +void log_event(Session *ssn, TagStreamData *tdata, struct _OptTreeNode *otn, u_int64_t, int); + +/**************************************************************************** + * + * Function: SetupTagStream() + * + * Purpose: create output file if required + * + * Arguments: None. + * + * Returns: void function + * + ****************************************************************************/ +void SetupTagStream() +{ + extern FILE *tag_stream_output; + struct stat buf; + if(stat("tagstream.debug.log",&buf)==0 && (buf.st_mode&S_IWUSR)==S_IWUSR){ + /* Using output debug file for logging all tagstream events */ + LogMessage("Tag Stream: Logging to tagstream.debug.log\n"); + tag_stream_output=fopen("tagstream.debug.log","a"); + }else{ + tag_stream_output=0; + } + + LogMessage("Tag Stream: Initializing\n"); + /* map the keyword to an initialization/processing function */ + RegisterPlugin("tagstream", TagStreamInit); + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: TagStream Initialized\n");); +} + + +/**************************************************************************** + * ParseTagStream(char *, OptTreeNode *) + * + * Purpose: Attach the option rule's argument to the data struct. + * + * Arguments: data => argument data + * otn => pointer to the current rule's OTN + * + * Returns: void function + * + ****************************************************************************/ +void ParseTagStream(char *data, OptTreeNode *otn) +{ + extern FILE *tag_stream_output; + TagStreamData *tsd; /* data struct pointer */ + size_t len=0; + /* set the ds pointer to make it easier to reference the option's + particular data struct */ + tsd = otn->ds_list[PLUGIN_TAG_STREAM]; + len=strlen(data); + while(*data) + { + while( isspace((int) *data) ) + data++; + if((char)*data=='c'){ + data++; + // Ok, we'll be nice and check for a + // '!' either before of after the = sign + if((char)*data=='!'){ tsd->cl=NOT_EQUAL; } else + if((char)*data=='='){ tsd->cl=EQUAL; } else + if((char)*data=='>'){ tsd->cl=GREATER_THAN; } else + if((char)*data=='<'){ tsd->cl=LESS_THAN; } + data++; + tsd->chk=ExtractTag6Bit( data, "check"); + }else if((char)*data=='p'){ + data++; + if((char)*data=='!'){ tsd->pl=NOT_EQUAL; } else + if((char)*data=='='){ tsd->pl=EQUAL; } else + if((char)*data=='>'){ tsd->pl=GREATER_THAN; } else + if((char)*data=='<'){ tsd->pl=LESS_THAN; } + data++; + tsd->pkt=ExtractTag32Bit( data, "packet"); + }else if((char)*data=='s'){ + data+=2; + tsd->set=ExtractTag6Bit( data, "set"); + }else if((char)*data=='u'){ + data+=2; + tsd->unset=ExtractTag6Bit( data, "unset"); + }else if((char)*data=='i'){ + data+=2; + if((char)*data=='1'){ + tsd->inv=1; + } + }else{ + data++; + } + } + if(tag_stream_output) + fprintf(tag_stream_output,"setup s=%d r=%d g=%d : p%d%d c%d%d s=%d u=%d i=%d \n" ,otn->event_data.sig_id,otn->event_data.sig_rev,otn->event_data.sig_generator,tsd->pl,tsd->pkt,tsd->cl,tsd->chk,tsd->set,tsd->unset,tsd->inv); +} + +static int ExtractTag32Bit(char *data,const char *type) +{ + int tnum =0; + errno=0; + tnum = strtol(data, NULL, 0); + if(errno == ERANGE) + { FatalError("ERROR %s Line %d => Range problem on TAG option %s value\n", file_name, file_line,type); } + return tnum; +} + +static int ExtractTag6Bit(char *data,const char *type) +{ + int tnum = ExtractTag32Bit(data,type); + errno=0; + if(tnum > 63 || tnum < 0) + { FatalError("ERROR %s Line %d => TAG option %s not a value between 0 and 63 (inclusively)\n", file_name, file_line,type); } + return tnum; +} + +/**************************************************************************** + * + * Function: TagStreamInit(char *, OptTreeNode *) + * + * Purpose: Attach the option data to the rule data struct and link in the + * detection function to the function pointer list. + * + * Arguments: data => rule arguments/data + * otn => pointer to the current rule option list node + * + * Returns: void function + * + ****************************************************************************/ +void TagStreamInit(char *data, OptTreeNode *otn, int protocol) +{ + + if(otn->ds_list[PLUGIN_TAG_STREAM]) + { + FatalError("%s(%d): Multiple tag stream options in rule\n", file_name, + file_line); + } + + /* identify this rule is in place */ + otn->ds_list[PLUGIN_TAG_STREAM] = (TagStreamData *) calloc(sizeof(TagStreamData), sizeof(char)); + /* See what options are set for this rule */ + ParseTagStream(data,otn); + /* finally, attach the option's detection function to the rule's + detect function pointer list */ + AddOptFuncToList(TagStream, otn); +} + + + +/**************************************************************************** + * + * Function: TagStream(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) + * + * Purpose: Manage session_tag_flags for this stream4 packet based on tag options + * + * Arguments: p => argument data + * otn => pointer to the current rule's OTN + * fp_list => function pointer list + * + * Returns: an integer + * + ****************************************************************************/ +int TagStream(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list) +{ + Session *ssn = NULL; + TagStreamData *tagData=NULL; + ssn = GetSession(p); + u_int64_t test4flags=0; + if(ssn) + { + tagData=otn->ds_list[PLUGIN_TAG_STREAM]; + if(tagData->pkt){ + if((tagData->pl==EQUAL && ssn->client.pkts_sent != tagData->pkt)|| + (tagData->pl==NOT_EQUAL && ssn->client.pkts_sent == tagData->pkt)|| + (tagData->pl==GREATER_THAN && ssn->client.pkts_sent <= tagData->pkt)|| + (tagData->pl==LESS_THAN && ssn->client.pkts_sent >= tagData->pkt)) + { + // The tests failed + if(tagData->inv){ + // If invert mode is enabled + // we will tell snort that we have a 'match' + // Alert - the ! test failed + log_event(ssn,tagData,otn,test4flags,1); + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + }else{ + // otherwise, allow snort to continue processing, + // Don't alert - the ! test failed + log_event(ssn,tagData,otn,test4flags,-1); + return 0; + } + } + } + if(tagData->chk){ + test4flags=0x0000000000000001 << tagData->chk; + if(( tagData->cl==EQUAL && (( ssn->session_tag_flags & test4flags) != test4flags) )|| + ( tagData->cl==GREATER_THAN && ( ssn->session_tag_flags <= test4flags) )|| + ( tagData->cl==LESS_THAN && ( ssn->session_tag_flags >= test4flags) )|| + ( tagData->cl==NOT_EQUAL && (( ssn->session_tag_flags & test4flags) != test4flags) )) + { + // The test failed + if(tagData->inv){ + // If invert mode is enabled + // we will tell snort that we have a 'match' + // Alert - the ! test failed + log_event(ssn,tagData,otn,test4flags,6); + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + }else{ + // otherwise, allow snort to continue processing, + // Don't alert - the ! test failed + log_event(ssn,tagData,otn,test4flags,-6); + return 0; + } + + } + + } + // Our test passed, lets see what else we should do + if(tagData->set){ + // We will set a tag (bit) for this stream + test4flags = 0x0000000000000001 << tagData->set; + ssn->session_tag_flags |= test4flags; + } + if(tagData->unset){ + // We will unset a tag (bit) for this stream + test4flags = 0x0000000000000001 << tagData->unset; + ssn->session_tag_flags ^= test4flags; + } + if(tagData->inv){ + // Don't alert - we are in invert mode, we don't alert + log_event(ssn,tagData,otn,test4flags,0); + return 0; + }else{ + // Alert - we matched on everything + log_event(ssn,tagData,otn,test4flags,1); + return fp_list->next->OptTestFunc(p, otn, fp_list->next); + } + } + log_event(ssn,tagData,otn,test4flags,1); +#ifdef DEBUG + DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "No session data for Tag Stream\n");); +#endif + /* if their isn't any stream4 session data associated with this packet, this rule plugin does not apply */ + return fp_list->next->OptTestFunc(p, otn, fp_list->next); +} + +void log_event(Session *ssn, TagStreamData *tdata, struct _OptTreeNode *otn, u_int64_t testV, int alert) +{ + extern FILE *tag_stream_output; + if(tag_stream_output ){ + char testcl='\0'; + FILE *LOG_MSG=tag_stream_output; + if(ssn) fprintf(LOG_MSG,"%d ",ssn->last_session_time); + if(otn) fprintf(LOG_MSG,"s=%d r=%d g=%d ",otn->event_data.sig_id,otn->event_data.sig_rev,otn->event_data.sig_generator); + if(ssn) fprintf(LOG_MSG,"%s ",inet_ntoa(*(struct in_addr*) &ssn->client.ip) ); + if(ssn) fprintf(LOG_MSG,"%s ",inet_ntoa(*(struct in_addr*) &ssn->server.ip) ); + if(ssn) fprintf(LOG_MSG,"%d %d (%d) ",ssn->client.port,ssn->server.port,ssn->client.pkts_sent); + if(ssn) fprintf(LOG_MSG,"sf=%u :",ssn->session_flags); + if(tdata) fprintf(LOG_MSG," p%d%d c%d%d ",tdata->pl,tdata->pkt,tdata->cl,tdata->chk); + if(tdata) fprintf(LOG_MSG," s=%d u=%d i=%d ",tdata->set,tdata->unset,tdata->inv); + if(ssn) fprintf(LOG_MSG,"stf=%llu ",ssn->session_tag_flags>>1); + if(tdata){ + if(tdata->cl==GREATER_THAN) testcl='>'; + if(tdata->cl==LESS_THAN) testcl='<'; + if(tdata->cl==EQUAL) testcl='='; + if(tdata->cl==NOT_EQUAL) testcl='!'; + fprintf(LOG_MSG,"t%c%lluc\n",testcl,testV>>1,alert); + } + if(tdata) fprintf(LOG_MSG,"a=%d\n",alert); + } + +} diff -P -r -u3 snort-2.2.0/src/detection-plugins/sp_tag_stream.h snort-2.2.0_tagstream_1.3/src/detection-plugins/sp_tag_stream.h --- snort-2.2.0/src/detection-plugins/sp_tag_stream.h 1969-12-31 16:00:00.000000000 -0800 +++ snort-2.2.0_tagstream_1.3/src/detection-plugins/sp_tag_stream.h 2004-11-16 10:14:46.000000000 -0800 @@ -0,0 +1,26 @@ +/* +** Copyright (C) 1998-2002 Martin Roesch +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* $Id: sp_tag_stream.c,v 1.0 2003/07/12 21:32:16 johncurry Exp $ */ +#ifndef __SP_TAG_STREAM_H__ +#define __SP_TAG_STREAM_H__ + +void SetupTagStream(); + +#endif /* __SP_TAG_STREAM_H__ */ + diff -P -r -u3 snort-2.2.0/src/plugbase.c snort-2.2.0_tagstream_1.3/src/plugbase.c --- snort-2.2.0/src/plugbase.c 2004-06-16 11:49:24.000000000 -0700 +++ snort-2.2.0_tagstream_1.3/src/plugbase.c 2004-11-16 10:14:46.000000000 -0800 @@ -92,6 +92,7 @@ #ifdef ENABLE_RESPONSE #include "detection-plugins/sp_react.h" #include "detection-plugins/sp_respond.h" +#include "detection-plugins/sp_tag_stream.h" #endif @@ -149,6 +150,7 @@ SetupIpProto(); SetupIpSameCheck(); SetupClientServer(); + SetupTagStream(); SetupByteTest(); SetupByteJump(); SetupIsDataAt(); diff -P -r -u3 snort-2.2.0/src/plugin_enum.h snort-2.2.0_tagstream_1.3/src/plugin_enum.h --- snort-2.2.0/src/plugin_enum.h 2003-10-20 08:03:22.000000000 -0700 +++ snort-2.2.0_tagstream_1.3/src/plugin_enum.h 2004-11-16 10:14:46.000000000 -0800 @@ -32,6 +32,7 @@ PLUGIN_TCP_SEQ_CHECK, PLUGIN_TCP_WIN_CHECK, PLUGIN_TTL_CHECK, + PLUGIN_TAG_STREAM, PLUGIN_BYTE_TEST, PLUGIN_PCRE, }; diff -P -r -u3 snort-2.2.0/src/preprocessors/stream.h snort-2.2.0_tagstream_1.3/src/preprocessors/stream.h --- snort-2.2.0/src/preprocessors/stream.h 2004-03-11 14:25:53.000000000 -0800 +++ snort-2.2.0_tagstream_1.3/src/preprocessors/stream.h 2004-11-16 10:14:46.000000000 -0800 @@ -51,6 +51,7 @@ u_int32_t last_session_time; /* last time this session got a packet */ u_int32_t session_flags; /* special little flags we keep */ + u_int64_t session_tag_flags; /* flags for tracking up to 64 session tags */ u_int32_t http_alert_flags; u_int8_t flush_point; diff -P -r -u3 snort-2.2.0/src/util.c snort-2.2.0_tagstream_1.3/src/util.c --- snort-2.2.0/src/util.c 2004-08-04 07:28:25.000000000 -0700 +++ snort-2.2.0_tagstream_1.3/src/util.c 2004-11-16 10:24:14.000000000 -0800 @@ -268,6 +268,9 @@ "1.7-WIN32 Port By Michael Davis (mike@datanerds.net, www.datanerds.net/~mike)\n" "1.8 - 2.x WIN32 Port By Chris Reid (chris.reid@codecraftconsultants.com)\n" #endif +#ifdef __SP_TAG_STREAM_H__ + "TAGSTREAM v1.3 By John Curry (john.curry@metre.net, www.metre.net)\n" +#endif , VERSION, BUILD); return 0; }