Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

427 lines (368 sloc) 13.513 kb
/*
** Copyright (C) 2002-2009 Sourcefire, Inc.
** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
** Copyright (C) 2000,2001 Andrew R. Baker <andrewb@uab.edu>
**
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id$ */
/* spo_alert_fast
*
* Purpose: output plugin for fast alerting
*
* Arguments: alert file
*
* Effect:
*
* Alerts are written to a file in the snort fast alert format
*
* Comments: Allows use of fast alerts with other output plugin types
*
*/
/* output plugin header file */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include <sys/types.h>
#ifndef WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif /* !WIN32 */
#include "barnyard2.h"
#include "decode.h"
#include "debug.h"
#include "plugbase.h"
#include "parser.h"
#include "util.h"
#include "log.h"
#include "mstring.h"
#include "unified2.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sfutil/sf_textlog.h"
#include "log_text.h"
#include "ipv6_port.h"
/* full buf was chosen to allow printing max size packets
* in hex/ascii mode:
* each byte => 2 nibbles + space + ascii + overhead
*/
#define FULL_BUF (4*IP_MAXPACKET)
#define FAST_BUF (4*K_BYTES)
/*
* not defined for backwards compatibility
* (default is produced by OpenAlertFile()
#define DEFAULT_FILE "alert.fast"
*/
#define DEFAULT_LIMIT (128*M_BYTES)
typedef struct _SpoAlertFastData
{
TextLog* log;
uint8_t packet_flag;
} SpoAlertFastData;
static void AlertFastInit(char *);
static SpoAlertFastData *ParseAlertFastArgs(char *);
static void AlertFastCleanExitFunc(int, void *);
static void AlertFastRestartFunc(int, void *);
static void AlertFast(Packet *, void *, uint32_t, void *);
/*
* Function: SetupAlertFast()
*
* Purpose: Registers the output plugin keyword and initialization
* function into the output plugin list. This is the function that
* gets called from InitOutputPlugins() in plugbase.c.
*
* Arguments: None.
*
* Returns: void function
*
*/
void AlertFastSetup(void)
{
/* link the preprocessor keyword to the init function in
the preproc list */
RegisterOutputPlugin("alert_fast", OUTPUT_TYPE_FLAG__ALERT, AlertFastInit);
DEBUG_WRAP(DebugMessage(DEBUG_INIT,"Output plugin: AlertFast is setup...\n"););
}
/*
* Function: AlertFastInit(char *)
*
* Purpose: Calls the argument parsing function, performs final setup on data
* structs, links the preproc function into the function list.
*
* Arguments: args => ptr to argument string
*
* Returns: void function
*
*/
static void AlertFastInit(char *args)
{
SpoAlertFastData *data;
DEBUG_WRAP(DebugMessage(DEBUG_INIT,"Output: AlertFast Initialized\n"););
/* parse the argument list from the rules file */
data = ParseAlertFastArgs(args);
DEBUG_WRAP(DebugMessage(DEBUG_INIT,"Linking AlertFast functions to call lists...\n"););
/* Set the preprocessor function into the function list */
AddFuncToOutputList(AlertFast, OUTPUT_TYPE__ALERT, data);
AddFuncToCleanExitList(AlertFastCleanExitFunc, data);
AddFuncToRestartList(AlertFastRestartFunc, data);
}
static void AlertFast(Packet *p, void *event, uint32_t event_type, void *arg)
{
SpoAlertFastData *data;
SigNode *sn;
if( p == NULL || event == NULL || arg == NULL )
{
return;
}
data = (SpoAlertFastData *)arg;
sn = GetSigByGidSid(ntohl(((Unified2EventCommon *)event)->generator_id),
ntohl(((Unified2EventCommon *)event)->signature_id),
ntohl(((Unified2EventCommon *)event)->signature_revision));
LogTimeStamp(data->log, p);
if( p != NULL && p->packet_flags & PKT_INLINE_DROP )
TextLog_Puts(data->log, " [Drop]");
if(sn != NULL)
{
#ifdef MARK_TAGGED
char c=' ';
if ((p != NULL) && (p->packet_flags & PKT_REBUILT_STREAM))
c = 'R';
else if ((p != NULL) && (p->packet_flags & PKT_REBUILT_FRAG))
c = 'F';
TextLog_Print(data->log, " [**] %c ", c);
#else
TextLog_Puts(data->log, " [**] ");
#endif
TextLog_Print(data->log, "[%lu:%lu:%lu] ",
(unsigned long) ntohl(((Unified2EventCommon *)event)->generator_id),
(unsigned long) ntohl(((Unified2EventCommon *)event)->signature_id),
(unsigned long) ntohl(((Unified2EventCommon *)event)->signature_revision));
if(BcAlertInterface())
{
TextLog_Print(data->log, "<%s> ", PRINT_INTERFACE(barnyard2_conf->interface));
}
TextLog_Puts(data->log, sn->msg);
TextLog_Puts(data->log, " [**] ");
}
/* print the packet header to the alert file */
if(p && IPH_IS_VALID(p))
{
LogPriorityData(data->log,
ntohl(((Unified2EventCommon *)event)->classification_id),
ntohl(((Unified2EventCommon *)event)->priority_id),
0);
TextLog_Print(data->log, "{%s} ", protocol_names[GET_IPH_PROTO(p)]);
if(p->frag_flag)
{
/* just print the straight IP header */
if(!BcObfuscate())
{
TextLog_Puts(data->log, inet_ntoa(GET_SRC_ADDR(p)));
TextLog_Puts(data->log, " -> ");
TextLog_Puts(data->log, inet_ntoa(GET_DST_ADDR(p)));
}
else
{
/* print the header complete with port information */
if(IS_IP4(p))
TextLog_Print(data->log, "xxx.xxx.xxx.xxx:%d -> xxx.xxx.xxx.xxx:%d", p->sp, p->dp);
else if(IS_IP6(p))
TextLog_Print(data->log, "x:x:x:x::x:x:x:x:%d -> x:x:x:x:x:x:x:x:%d", p->sp, p->dp);
}
}
else
{
switch(GET_IPH_PROTO(p))
{
case IPPROTO_UDP:
case IPPROTO_TCP:
/* print the header complete with port information */
if(!BcObfuscate())
{
TextLog_Puts(data->log, inet_ntoa(GET_SRC_ADDR(p)));
TextLog_Print(data->log, ":%d -> ", p->sp);
TextLog_Puts(data->log, inet_ntoa(GET_DST_ADDR(p)));
TextLog_Print(data->log, ":%d", p->dp);
}
else
{
/* print the header complete with port information */
if(IS_IP4(p))
TextLog_Print(data->log, "xxx.xxx.xxx.xxx:%d -> xxx.xxx.xxx.xxx:%d", p->sp, p->dp);
else if(IS_IP6(p))
TextLog_Print(data->log, "x:x:x:x::x:x:x:x:%d -> x:x:x:x:x:x:x:x:%d", p->sp, p->dp);
}
break;
case IPPROTO_ICMP:
default:
/* just print the straight IP header */
if(!BcObfuscate())
{
TextLog_Puts(data->log, inet_ntoa(GET_SRC_ADDR(p)));
TextLog_Puts(data->log, " -> ");
TextLog_Puts(data->log, inet_ntoa(GET_DST_ADDR(p)));
}
else
{
/* print the header complete with port information */
if(IS_IP4(p))
TextLog_Print(data->log, "xxx.xxx.xxx.xxx:%d -> xxx.xxx.xxx.xxx:%d", p->sp, p->dp);
else if(IS_IP6(p))
TextLog_Print(data->log, "x:x:x:x::x:x:x:x:%d -> x:x:x:x:x:x:x:x:%d", p->sp, p->dp);
}
}
}
} /* end of if (p) */
if(p && data->packet_flag)
{
/* Log whether or not this is reassembled data - only indicate
* if we're actually going to show any of the payload */
if (BcOutputAppData() && (p->dsize > 0))
{
if (p->packet_flags &
(PKT_DCE_RPKT | PKT_REBUILT_STREAM | PKT_REBUILT_FRAG |
PKT_SMB_SEG | PKT_DCE_SEG | PKT_DCE_FRAG | PKT_SMB_TRANS))
{
TextLog_NewLine(data->log);
}
if (p->packet_flags & PKT_SMB_SEG)
TextLog_Print(data->log, "%s", "SMB desegmented packet");
else if (p->packet_flags & PKT_DCE_SEG)
TextLog_Print(data->log, "%s", "DCE/RPC desegmented packet");
else if (p->packet_flags & PKT_DCE_FRAG)
TextLog_Print(data->log, "%s", "DCE/RPC defragmented packet");
else if (p->packet_flags & PKT_SMB_TRANS)
TextLog_Print(data->log, "%s", "SMB Transact reassembled packet");
else if (p->packet_flags & PKT_DCE_RPKT)
TextLog_Print(data->log, "%s", "DCE/RPC reassembled packet");
else if (p->packet_flags & PKT_REBUILT_STREAM)
TextLog_Print(data->log, "%s", "Stream reassembled packet");
else if (p->packet_flags & PKT_REBUILT_FRAG)
TextLog_Print(data->log, "%s", "Frag reassembled packet");
}
TextLog_NewLine(data->log);
if(IPH_IS_VALID(p))
LogIPPkt(data->log, GET_IPH_PROTO(p), p);
#ifndef NO_NON_ETHER_DECODER
else if(p->ah)
LogArpHeader(data->log, p);
#endif
}
TextLog_NewLine(data->log);
TextLog_Flush(data->log);
}
/*
* Function: ParseAlertFastArgs(char *)
*
* Purpose: Process positional args, if any. Syntax is:
* output alert_fast: [<logpath> ["packet"] [<limit>]]
* limit ::= <number>('G'|'M'|K')
*
* Arguments: args => argument list
*
* Returns: void function
*
*/
static SpoAlertFastData *ParseAlertFastArgs(char *args)
{
char **toks;
int num_toks;
SpoAlertFastData *data;
char* filename = NULL;
unsigned long limit = DEFAULT_LIMIT;
unsigned int bufSize = FAST_BUF;
int i;
DEBUG_WRAP(DebugMessage(DEBUG_LOG, "ParseAlertFastArgs: %s\n", args););
data = (SpoAlertFastData *)SnortAlloc(sizeof(SpoAlertFastData));
if ( !data )
{
FatalError("alert_fast: unable to allocate memory!\n");
}
if ( !args ) args = "";
toks = mSplit((char *)args, " \t", 0, &num_toks, '\\');
for (i = 0; i < num_toks; i++)
{
const char* tok = toks[i];
char *end;
switch (i)
{
case 0:
if ( !strcasecmp(tok, "stdout") )
filename = SnortStrdup(tok);
else
filename = ProcessFileOption(barnyard2_conf_for_parsing, tok);
break;
case 1:
if ( !strcasecmp("packet", tok) )
{
data->packet_flag = 1;
bufSize = FULL_BUF;
break;
}
/* in this case, only 2 options allowed */
else i++;
/* fall thru so "packet" is optional ... */
case 2:
limit = strtol(tok, &end, 10);
if ( tok == end )
FatalError("alert_fast error in %s(%i): %s\n",
file_name, file_line, tok);
if ( end && toupper(*end) == 'G' )
limit <<= 30; /* GB */
else if ( end && toupper(*end) == 'M' )
limit <<= 20; /* MB */
else if ( end && toupper(*end) == 'K' )
limit <<= 10; /* KB */
break;
case 3:
FatalError("alert_fast: error in %s(%i): %s\n",
file_name, file_line, tok);
break;
}
}
mSplitFree(&toks, num_toks);
#ifdef DEFAULT_FILE
if ( !filename ) filename = ProcessFileOption(barnyard2_conf_for_parsing, DEFAULT_FILE);
#endif
DEBUG_WRAP(DebugMessage(
DEBUG_INIT, "alert_fast: '%s' %d %ld\n",
filename?filename:"alert", data->packet_flag, limit
););
data->log = TextLog_Init(filename, bufSize, limit);
if ( filename ) free(filename);
return data;
}
static void AlertFastCleanup(int signal, void *arg, const char* msg)
{
SpoAlertFastData *data = (SpoAlertFastData *)arg;
DEBUG_WRAP(DebugMessage(DEBUG_LOG, "%s\n", msg););
/*free memory from SpoAlertFastData */
if ( data->log ) TextLog_Term(data->log);
free(data);
}
static void AlertFastCleanExitFunc(int signal, void *arg)
{
AlertFastCleanup(signal, arg, "AlertFastCleanExitFunc");
}
static void AlertFastRestartFunc(int signal, void *arg)
{
AlertFastCleanup(signal, arg, "AlertFastRestartFunc");
}
Jump to Line
Something went wrong with that request. Please try again.