From 587c8499aa7e43b00623df4c58b91911c3a07d69 Mon Sep 17 00:00:00 2001 From: Pav Lucistnik Date: Thu, 26 Jan 2006 10:56:46 +0000 Subject: [PATCH] New slave port to security/barnyard - adds patches for sguil6 PR: ports/92241 Submitted by: Paul Schmehl --- security/Makefile | 1 + security/barnyard-sguil/Makefile | 18 + .../barnyard-sguil/files/patch-configure.in | 63 + .../barnyard-sguil/files/patch-op-sguil.c | 1873 +++++++++++++++++ .../barnyard-sguil/files/patch-op_plugbase.c | 20 + .../barnyard-sguil/files/patch-op_sguil.h | 26 + security/barnyard-sguil6/Makefile | 18 + .../barnyard-sguil6/files/patch-configure.in | 63 + .../barnyard-sguil6/files/patch-op-sguil.c | 1873 +++++++++++++++++ .../barnyard-sguil6/files/patch-op_plugbase.c | 20 + .../barnyard-sguil6/files/patch-op_sguil.h | 26 + 11 files changed, 4001 insertions(+) create mode 100644 security/barnyard-sguil/Makefile create mode 100644 security/barnyard-sguil/files/patch-configure.in create mode 100644 security/barnyard-sguil/files/patch-op-sguil.c create mode 100644 security/barnyard-sguil/files/patch-op_plugbase.c create mode 100644 security/barnyard-sguil/files/patch-op_sguil.h create mode 100644 security/barnyard-sguil6/Makefile create mode 100644 security/barnyard-sguil6/files/patch-configure.in create mode 100644 security/barnyard-sguil6/files/patch-op-sguil.c create mode 100644 security/barnyard-sguil6/files/patch-op_plugbase.c create mode 100644 security/barnyard-sguil6/files/patch-op_sguil.h diff --git a/security/Makefile b/security/Makefile index 6fda48cfff9c..d1164a57db01 100644 --- a/security/Makefile +++ b/security/Makefile @@ -26,6 +26,7 @@ SUBDIR += autossh SUBDIR += avcheck SUBDIR += barnyard + SUBDIR += barnyard-sguil6 SUBDIR += base SUBDIR += bcrypt SUBDIR += bcwipe diff --git a/security/barnyard-sguil/Makefile b/security/barnyard-sguil/Makefile new file mode 100644 index 000000000000..a3e01c102350 --- /dev/null +++ b/security/barnyard-sguil/Makefile @@ -0,0 +1,18 @@ +# New ports collection makefile for: barnyard-sguil6 +# Date created: 23 Jan 2006 +# Whom: pauls +# +# $FreeBSD$ +# + +PKGNAMESUFFIX= -sguil6 +COMMENT= An output system for Snort (patched for sguil6) + +LIB_DEPENDS+= tcl84.1:${PORTSDIR}/lang/tcl84 + +MASTERDIR= ${.CURDIR}/../barnyard +PATCHDIR= ${.CURDIR}/files + +CONFIGURE_ARGS+= --enable-tcl --with-tcl=${PREFIX}/lib/tcl8.4 + +.include "${MASTERDIR}/Makefile" diff --git a/security/barnyard-sguil/files/patch-configure.in b/security/barnyard-sguil/files/patch-configure.in new file mode 100644 index 000000000000..aad901a05648 --- /dev/null +++ b/security/barnyard-sguil/files/patch-configure.in @@ -0,0 +1,63 @@ +--- configure.in.orig Sat May 1 11:43:29 2004 ++++ configure.in Mon Jan 23 14:32:54 2006 +@@ -1,4 +1,4 @@ +-# $Id: configure.in,v 1.17 2004/05/01 16:43:29 andrewbaker Exp $ ++# $Id: configure.in,v 1.2 2005/03/08 20:37:40 bamm Exp $ + AC_INIT(src/barnyard.c) + AM_CONFIG_HEADER(config.h) + AM_INIT_AUTOMAKE(barnyard,0.2.0) +@@ -281,13 +281,53 @@ + + dnl check for the header + LDFLAGS="${LDFLAGS} -L${MYSQL_LIB_DIR}" +- LIBS="${LIBS} -lz -lssl -lmysqlclient" ++ LIBS="${LIBS} -lmysqlclient -lcrypto" + AC_CHECK_LIB(mysqlclient, mysql_real_connect, FOUND=yes, FOUND=no) + + if test "$FOUND" = "no"; then + FAIL_MESSAGE("mysqlclient library", "$MYSQL_LIB_DIR") + fi + ++fi ++ ++AC_ARG_ENABLE(tcl, ++ [ --enable-tcl Enable Tcl language support.],, ++ [enable_tcl="no"]) ++dnl AC_MSG_RESULT($enable_tcl) ++ ++if test "yes" = "$enable_tcl"; then ++ ++ dnl let tclsh tell us where it was ++ dnl installed (prefer new tcl versions). ++ AC_CHECK_PROGS(TCLSH, tclsh8.4 tclsh8.3 tclsh8.2 tclsh8.1 tclsh8.0 tclsh) ++ if test "$TCLSH" != ""; then ++ tclpath=`echo 'puts [[lindex $tcl_pkgPath 0]]' | $TCLSH` ++ fi ++ ++ dnl let the user overwrite the installation ++ dnl directory which was just found. ++ AC_ARG_WITH(tcl, ++ [ --with-tcl=PATH Location of tclConfig.sh], ++ tclpath="$withval") ++ ++ dnl check, if tclConfig.sh can be found in ++ dnl tclsh's installation directory. ++ if test ! -r $tclpath/tclConfig.sh; then ++ AC_MSG_RESULT( ++ [ ++ Can't find Tcl libraries. Use --with-tcl to specify ++ the directory containing tclConfig.sh on your system. ++ Continuing build without Tcl support.]) ++ else ++ dnl source tclsh's configuration file ++ dnl and tell the user about the version. ++ . $tclpath/tclConfig.sh ++ AC_MSG_CHECKING([for the tcl version number]) ++ AC_MSG_RESULT([$TCL_VERSION, patchlevel $TCL_PATCH_LEVEL]) ++ LIBS="$LIBS $TCL_LIBS $TCL_LIB_SPEC" ++ TCL_INCLUDE="$TCL_PREFIX/include/tcl$TCL_VERSION" ++ CPPFLAGS="$CPPFLAGS -I$TCL_INCLUDE -DENABLE_TCL"; ++ fi + fi + + diff --git a/security/barnyard-sguil/files/patch-op-sguil.c b/security/barnyard-sguil/files/patch-op-sguil.c new file mode 100644 index 000000000000..563af968217b --- /dev/null +++ b/security/barnyard-sguil/files/patch-op-sguil.c @@ -0,0 +1,1873 @@ +--- src/output-plugins/op_sguil.c.orig Sat Apr 3 13:57:33 2004 ++++ src/output-plugins/op_sguil.c Mon Jan 23 18:22:09 2006 +@@ -1,8 +1,9 @@ +-/* $Id: op_sguil.c,v 1.5 2004/04/03 19:57:33 andrewbaker Exp $ */ ++/* $Id: op_sguil.c,v 1.16 2005/09/01 15:17:56 bamm Exp $ */ ++ + /* +-** Copyright (C) 2001-2002 Andrew R. Baker ++** Copyright (C) 2002-2005 Robert (Bamm) Visscher + ** +-** This program is distributed under the terms of version 1.0 of the ++** This program is distributed under the terms of version 1.0 of the + ** Q Public License. See LICENSE.QPL for further details. + ** + ** This program is distributed in the hope that it will be useful, +@@ -11,21 +12,16 @@ + ** + */ + +-/* op_sguil is a modified op_acid_db plugin configured to work with +- * sguil (Snort GUI for Lamerz). Sguil and ACIDs DB schemas differ. +- * Sguil combines the event and iphdr tables along with moving the +- * src and dst port columns into event. I've also added SguilSendEvent +- * which opens a network socket and sends RT events to sguild. +- * +- * Andrew, sorry about mangling your code but it works so well :) +- * +- * Bammkkkk ++/* ++** op_sguil is the sguil output plugin for barnyard (http://barnyard.sf.net). ++** For more information about sguil see http://www.sguil.net + */ + +-/* I N C L U D E S *****************************************************/ +- +-#ifdef ENABLE_MYSQL /* Wrap the whole thing in an ENABLE_MYSQL block */ ++/********************************************************************* ++* I N C L U D E S * ++*********************************************************************/ + ++/* Std includes */ + #include + #include + #include +@@ -48,52 +44,13 @@ + #include "op_decode.h" + #include "event.h" + +-/* Needed for network socket */ + #include + #include + #include + #include + +-#ifdef ENABLE_MYSQL +-#include +-#include +-#endif /* ENABLE_MYSQL */ +- +-/* D A T A S T R U C T U R E S **************************************/ +-typedef struct _OpSguil_Data +-{ +- u_int8_t flavor; /* what flavor of db? MySQL, postgres, ... */ +- u_int16_t unused; +- char *server; +- char *database; +- char *user; +- char *password; +- int sensor_id; +- int options; +- char *sguild_host; +- int sguild_sock; +- int sguild_port; +- int nospin; +- u_int32_t event_id; +- /* db handles go here */ +-#ifdef ENABLE_MYSQL +- MYSQL *mysql; +-#endif /* ENABLE_MYSQL */ +-} OpSguil_Data; +- +- +-#define MAX_QUERY_SIZE 8192 +-#define SYSLOG_BUF 1024 +- +-/* database flavor defines */ +-#define FLAVOR_MYSQL 1 +-#define FLAVOR_POSTGRES 2 +- +-static char *sgdb_flavours[] = {NULL, "mysql", "postgres"}; +- +-/* Network socket defines */ +-#define MAX_MSG_LEN 100 +- ++/* Yeah TCL! */ ++#include + + /* Output plug-in API functions */ + static int OpSguil_Setup(OutputPlugin *, char *args); +@@ -103,56 +60,39 @@ + static int OpSguil_Log(void *, void *); + static int OpSguil_LogConfig(OutputPlugin *outputPlugin); + +-/* Internal functions */ +-int SguildConnect(OpSguil_Data *); +-int SguilSendEvent(OpSguil_Data *data, char *eventMsg); +-int read_line(); +-OpSguil_Data *OpSguil_ParseArgs(char *); +-int sgDbClose(OpSguil_Data *data); +-int sgDbConnect(OpSguil_Data *data); +-u_int32_t SguilGetNextCid(OpSguil_Data *data); +-u_int32_t SguilGetSensorId(OpSguil_Data *data); +-int SguilCheckSchemaVersion(OpSguil_Data *data); +-int InsertIPData(OpSguil_Data *data, Packet *p); +-int sgInsertICMPData(OpSguil_Data *data, Packet *p); +-int sgInsertUDPData(OpSguil_Data *data, Packet *p); +-int sgInsertTCPData(OpSguil_Data *data, Packet *p); +-int sgInsertPayloadData(OpSguil_Data *data, Packet *p); +- +-int sgSelectAsUInt(OpSguil_Data *data, char *sql, unsigned int *result); +-int sgInsert(OpSguil_Data *data, char *sql, unsigned int *row_id); +-int sgBeginTransaction(OpSguil_Data *); +-int sgEndTransaction(OpSguil_Data *); +-int sgAbortTransaction(OpSguil_Data *); +- +-#ifdef ENABLE_MYSQL +-int sgMysqlConnect(OpSguil_Data *); +-int sgMysqlClose(MYSQL *mysql); +-int sgMysqlSelectAsUInt(MYSQL *mysql, char *sql, unsigned int *result); +-int sgMysqlInsert(MYSQL *mysql, char *sql, unsigned int *row_id); +-#endif ++typedef struct _OpSguil_Data ++{ ++ char *sensor_name; ++ char *tag_path; ++ char *passwd; ++ u_int16_t sensor_id; ++ u_int32_t event_id; ++ u_int16_t agent_port; ++ int agent_sock; ++} OpSguil_Data; + +-/* Global variables */ +-static char sql_buffer[MAX_QUERY_SIZE]; ++#define MAX_MSG_LEN 2048 ++#define STD_BUFFER 128 + +-/* +- * Rather than using an incremental connection id (cid), this uses the +- * current time in milliseconds. BY is fast, but will we get dups in the +- * same millisecond? +- * Okay, lets wait on doing this. +-long GetMilliseconds() +-{ +- struct timeval tv; +- gettimeofday(&tv, NULL); ++int OpSguil_AppendIPHdrData(Tcl_DString *list, Packet *p); ++int OpSguil_AppendICMPData(Tcl_DString *list, Packet *p); ++int OpSguil_AppendTCPData(Tcl_DString *list, Packet *p); ++int OpSguil_AppendUDPData(Tcl_DString *list, Packet *p); ++int OpSguil_AppendPayloadData(Tcl_DString *list, Packet *p); ++int OpSguil_SensorAgentConnect(OpSguil_Data *); ++//int OpSguil_SensorAgentAuth(OpSguil_Data *); ++int OpSguil_SensorAgentInit(OpSguil_Data *); ++int OpSguil_RTEventMsg(OpSguil_Data *data, char *msg); ++int OpSguil_SendAgentMsg(OpSguil_Data *data, char *msg); ++int OpSguil_RecvAgentMsg(); ++OpSguil_Data *OpSguil_ParseArgs(char *); + +- return (long)(tv.tv_sec * 1000 + tv.tv_usec / 1000); +-}*/ + + /* init routine makes this processor available for dataprocessor directives */ + void OpSguil_Init() + { + OutputPlugin *outputPlugin; +- ++ + outputPlugin = RegisterOutputPlugin("sguil", "log"); + outputPlugin->setupFunc = OpSguil_Setup; + outputPlugin->exitFunc = OpSguil_Exit; +@@ -160,25 +100,9 @@ + outputPlugin->stopFunc = OpSguil_Stop; + outputPlugin->outputFunc = OpSguil_Log; + outputPlugin->logConfigFunc = OpSguil_LogConfig; +- ++ + } + +-int OpSguil_LogConfig(OutputPlugin *outputPlugin) +-{ +- OpSguil_Data *data = NULL; +- +- if(!outputPlugin || !outputPlugin->data) +- return -1; +- +- data = (OpSguil_Data *)outputPlugin->data; +- +- LogMessage("OpSguil configured\n"); +- /* XXX We need to print the configuration details here */ +- return 0; +-} +- +- +- + /* Setup the output plugin, process any arguments, link the functions to + * the output functional node + */ +@@ -186,11 +110,11 @@ + { + /* setup the run time context for this output plugin */ + outputPlugin->data = OpSguil_ParseArgs(args); +- ++ + return 0; + } +- +-/* Inverse of the setup function, free memory allocated in Setup ++ ++/* Inverse of the setup function, free memory allocated in Setup + * can't free the outputPlugin since it is also the list node itself + */ + int OpSguil_Exit(OutputPlugin *outputPlugin) +@@ -198,478 +122,353 @@ + return 0; + } + +-/* ++/* + * this function gets called at start time, you should open any output files + * or establish DB connections, etc, here + */ + int OpSguil_Start(OutputPlugin *outputPlugin, void *spool_header) + { +- char tmpMsg [256]; + OpSguil_Data *data = (OpSguil_Data *)outputPlugin->data; +- LogMessage("OpSguil_Start\n"); + + if(data == NULL) + FatalError("ERROR: Unable to find context for Sguil startup!\n"); ++ ++ if(pv.verbose) ++ OpSguil_LogConfig(outputPlugin); ++ ++ /* Figure out out sensor_name */ ++ if(data->sensor_name == NULL) ++ { ++ /* See if the user used the ProgVar config hostname: */ ++ if(pv.hostname != NULL) ++ { ++ data->sensor_name = pv.hostname; ++ } ++ else ++ { ++ FatalError("ERROR: Unable to determine hostname."); ++ } ++ } ++ ++ /* Connect to sensor_agent */ ++ OpSguil_SensorAgentConnect(data); ++ ++ /* Initialize - get sid and next cid */ ++ if(pv.verbose) ++ LogMessage("Waiting for sid and cid from sensor_agent.\n"); ++ OpSguil_SensorAgentInit(data); + +- /* Connect to sguild */ +- if(SguildConnect(data)) +- FatalError("OpSguil_: Failed to connect to sguild: %s:%i\n", +- data->sguild_host, data->sguild_port); +- +- /* Write a system-info message*/ +- sprintf(tmpMsg, "RTEvent |||system-info|%s||Barnyard started.||||||||\n", pv.hostname); +- SguilSendEvent(data, tmpMsg); +- +- /* Connect to the database */ +- if(sgDbConnect(data)) +- FatalError("OpSguil_: Failed to connect to database: %s:%s@%s/%s\n", +- data->user, data->password, data->server, data->database); +- +- /* check the db schema */ +- /*if(SguilCheckSchemaVersion(data)) +- FatalError("OpSguil_: database schema mismatch\n");*/ +- +- /* if sensor id == 0, then we attempt attempt to determine it dynamically */ +- if(data->sensor_id == 0) +- { +- data->sensor_id = SguilGetSensorId(data); +- /* XXX: Error checking */ +- } +- /* Get the next cid from the database */ +- data->event_id = SguilGetNextCid(data); + if(pv.verbose) + { +- LogMessage("OpAcidDB configuration details\n"); +- LogMessage("Database Flavour: %s\n", sgdb_flavours[data->flavor]); +- LogMessage("Database Server: %s\n", data->server); +- LogMessage("Database User: %s\n", data->user); +- LogMessage("SensorID: %i\n", data->sensor_id); +- LogMessage("Sguild Host: %s\n", data->sguild_host); +- LogMessage("Sguild Port: %i\n", data->sguild_port); +- } +- if((data->nospin) == NULL) +- { +- if(pv.verbose) +- { +- LogMessage("Barnyard will sleep(15) if unable to connect to sguild.\n"); +- } +- data->nospin = 0; +- } +- else +- { +- if(pv.verbose) +- { +- LogMessage("Spinning disabled.\n"); +- } ++ ++ LogMessage("Sensor Name: %s\n", data->sensor_name); ++ LogMessage("Agent Port: %u\n", data->agent_port); ++ + } + +- sprintf(tmpMsg, "RTEvent |||system-info|%s||Database Server: %s.||||||||\n", +- pv.hostname, data->server); +- SguilSendEvent(data, tmpMsg); +- +- sprintf(tmpMsg, "RTEvent |||system-info|%s||Database Next CID: %i.||||||||\n", +- pv.hostname, data->event_id); +- SguilSendEvent(data, tmpMsg); ++/* ++** if(SensorAgentAuth(data)) ++** FatalError("OpSguil: Authentication failed.\n"); ++** ++** if(pv.verbose) ++** LogMessage("OpSguil: Authentication successful.); ++*/ ++ + return 0; + } + + int OpSguil_Stop(OutputPlugin *outputPlugin) + { + OpSguil_Data *data = (OpSguil_Data *)outputPlugin->data; +- ++ + if(data == NULL) + FatalError("ERROR: Unable to find context for Sguil startup!\n"); ++ ++ return 0; ++} ++ ++int OpSguil_LogConfig(OutputPlugin *outputPlugin) ++{ ++ ++ OpSguil_Data *data = NULL; ++ ++ if(!outputPlugin || !outputPlugin->data) ++ return -1; ++ ++ data = (OpSguil_Data *)outputPlugin->data; ++ ++ LogMessage("OpSguil configured\n"); ++ ++ /* XXX We need to print the configuration details here */ + +- /* close database connection */ +- sgDbClose(data); +- + return 0; + } + +-/* sguil only uses log */ +-int OpSguil_Log(void *context, void *data) ++ ++int OpSguil_Log(void *context, void *ul_data) + { ++ + char timestamp[TIMEBUF_SIZE]; +- char syslogMessage[SYSLOG_BUF]; +- char eventInfo[SYSLOG_BUF]; +- //int MAX_INSERT_LEN = 1024; +- char insertColumns[MAX_QUERY_SIZE]; +- char insertValues[MAX_QUERY_SIZE]; +- char valuesTemp[MAX_QUERY_SIZE]; +- char ipInfo[38]; +- char portInfo[16]; +- char *esc_message; + Sid *sid = NULL; + ClassType *class_type; +- UnifiedLogRecord *record = (UnifiedLogRecord *)data; +- OpSguil_Data *op_data = (OpSguil_Data *)context; ++ UnifiedLogRecord *record = (UnifiedLogRecord *)ul_data; ++ OpSguil_Data *data = (OpSguil_Data *)context; + Packet p; ++ char buffer[STD_BUFFER]; ++ Tcl_DString list; + +- bzero(syslogMessage, SYSLOG_BUF); +- bzero(insertColumns, MAX_QUERY_SIZE); +- bzero(insertValues, MAX_QUERY_SIZE); +- +-#if 0 /* this is broken */ +- /* skip tagged packets, since the db does not have a mechanism to +- * deal with them properly +- */ +- if(record->log.event.event_reference) +- { +- LogMessage("Skipping tagged packet %i\n", record->log.event.event_reference); +- return 0; +- } +-#endif ++ bzero(buffer, STD_BUFFER); + ++ //LogMessage("Event id ==> %u\n", record->log.event.event_id); ++ //LogMessage("Ref time ==> %lu\n", record->log.event.ref_time.tv_sec); + +- RenderTimestamp(record->log.pkth.ts.tv_sec, timestamp, TIMEBUF_SIZE); +- //fprintf(stdout, "Timestamp: %lu\n", GetMilliseconds()); +- //fflush(stdout); ++ /* Sig info */ + sid = GetSid(record->log.event.sig_generator, record->log.event.sig_id); + if(sid == NULL) + sid = FakeSid(record->log.event.sig_generator, record->log.event.sig_id); ++ sid->rev = record->log.event.sig_rev; ++ + class_type = GetClassType(record->log.event.classification); ++ ++ /* Here we build our RT event to send to sguild. The event is built with a ++ ** proper tcl list format. ++ ** RT FORMAT: ++ ** ++ ** 0 1 2 3 4 5 6 7 ++ ** {RTEVENT} {0} {sid} {cid} {sensor name} {snort event_id} {snort event_ref} {snort ref_time} ++ ** ++ ** 8 9 10 11 12 13 14 ++ ** {sig_gen} {sig id} {rev} {message} {timestamp} {priority} {class_type} ++ ** ++ ** 15 16 17 18 19 20 21 ++ ** {sip (dec)} {sip (string)} {dip (dec)} {dip (string)} {ip proto} {ip ver} {ip hlen} ++ ** ++ ** 22 23 24 25 26 27 28 ++ ** {ip tos} {ip len} {ip id} {ip flags} {ip off} {ip ttl} {ip csum} ++ ** ++ ** 29 30 31 32 33 ++ ** {icmp type} {icmp code} {icmp csum} {icmp id} {icmp seq} ++ ** ++ ** 34 35 ++ ** {src port} {dst port} ++ ** ++ ** 36 37 38 39 40 41 42 43 ++ ** {tcp seq} {tcp ack} {tcp off} {tcp res} {tcp flags} {tcp win} {tcp csum} {tcp urp} ++ ** ++ ** 44 45 ++ ** {udp len} {udp csum} ++ ** ++ ** 46 ++ ** {data payload} ++ */ ++ ++ Tcl_DStringInit(&list); ++ ++ /* RTEVENT */ ++ Tcl_DStringAppendElement(&list, "RTEVENT"); ++ ++ /* Status - 0 */ ++ Tcl_DStringAppendElement(&list, "0"); ++ ++ /* Sensor ID (sid) */ ++ sprintf(buffer, "%u", data->sensor_id); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Event ID (cid) */ ++ sprintf(buffer, "%u", data->event_id); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Sensor Name */ ++ Tcl_DStringAppendElement(&list, data->sensor_name); ++ ++ /* Snort Event ID */ ++ sprintf(buffer, "%u", record->log.event.event_id); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Snort Event Ref */ ++ sprintf(buffer, "%u", record->log.event.event_reference); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Snort Event Ref Time */ ++ if(record->log.event.ref_time.tv_sec == 0) ++ { ++ Tcl_DStringAppendElement(&list, ""); ++ } ++ else ++ { ++ RenderTimestamp(record->log.event.ref_time.tv_sec, timestamp, TIMEBUF_SIZE); ++ Tcl_DStringAppendElement(&list, timestamp); ++ } ++ ++ /* Generator ID */ ++ sprintf(buffer, "%d", sid->gen); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Signature ID */ ++ sprintf(buffer, "%d", sid->sid); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Signature Revision */ ++ sprintf(buffer, "%d", sid->rev); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Signature Msg */ ++ Tcl_DStringAppendElement(&list, sid->msg); ++ ++ /* Packet Timestamp */ ++ RenderTimestamp(record->log.pkth.ts.tv_sec, timestamp, TIMEBUF_SIZE); ++ Tcl_DStringAppendElement(&list, timestamp); ++ ++ /* Alert Priority */ ++ sprintf(buffer, "%u", record->log.event.priority); ++ Tcl_DStringAppendElement(&list, buffer); + +- //sgBeginTransaction(op_data); /* XXX: Error checking */ +- /* Build the event insert. */ +- snprintf(insertColumns, MAX_QUERY_SIZE, +- "INSERT INTO event (status, sid, cid, signature_id, signature_rev, signature, timestamp, priority, class"); +- +- esc_message = malloc(strlen(sid->msg)*2+1); +- mysql_real_escape_string(op_data->mysql, esc_message, sid->msg, strlen(sid->msg)); +- +- if(class_type == NULL) +- { +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- "VALUES ('0', '%u', '%u', '%d', '%d', '%s', '%s', '%u', 'unknown'", +- op_data->sensor_id, op_data->event_id, sid->sid, sid->rev, esc_message, timestamp, +- record->log.event.priority); +- snprintf(eventInfo, SYSLOG_BUF, "RTEvent |0|%u|unknown|%s|%s|%u|%u|%s", +- record->log.event.priority, +- pv.hostname, timestamp, op_data->sensor_id, op_data->event_id, +- sid->msg); ++ /* Alert Classification */ ++ if (class_type == NULL) ++ { ++ Tcl_DStringAppendElement(&list, "unknown"); + } + else + { +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- "VALUES ('0', '%u', '%u', '%d', '%d', '%s', '%s', '%u', '%s'", +- op_data->sensor_id, op_data->event_id, sid->sid, sid->rev, esc_message, timestamp, +- record->log.event.priority, class_type->type); +- snprintf(eventInfo, SYSLOG_BUF, "RTEvent |0|%u|%s|%s|%s|%u|%u|%s", +- record->log.event.priority, class_type->type, +- pv.hostname, timestamp, op_data->sensor_id, op_data->event_id, +- sid->msg); +- } +- +- free(esc_message); +- +- insertValues[0] = '\0'; +- strcat(insertValues, valuesTemp); +- +- syslogMessage[0] = '\0'; +- strcat(syslogMessage, eventInfo); +- /* decode the packet */ ++ Tcl_DStringAppendElement(&list, class_type->type); ++ } ++ ++ /* Pull decoded info from the packet */ + if(DecodePacket(&p, &record->log.pkth, record->pkt + 2) == 0) + { +- + if(p.iph) + { +- /* Insert ip header information */ +- //InsertIPData(op_data, &p); +- strcat(insertColumns, +- ",src_ip, dst_ip, ip_proto, ip_ver, ip_hlen, ip_tos, ip_len, ip_id, ip_flags, ip_off, ip_ttl, ip_csum"); +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- ",'%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u'", +- ntohl(p.iph->ip_src.s_addr), ntohl(p.iph->ip_dst.s_addr), p.iph->ip_proto, IP_VER(p.iph), +- IP_HLEN(p.iph), p.iph->ip_tos, ntohs(p.iph->ip_len), ntohs(p.iph->ip_id), +-#if defined(WORDS_BIGENDIAN) +- ((p.iph->ip_off & 0xE000) >> 13), +- htons(p.iph->ip_off & 0x1FFF), +-#else +- ((p.iph->ip_off & 0x00E0) >> 5), +- htons(p.iph->ip_off & 0xFF1F), +-#endif +- p.iph->ip_ttl, +- htons(p.iph->ip_csum) < MAX_QUERY_SIZE); +- +- strcat(insertValues, valuesTemp); +- ++ int i; + +- /* SYSLOG - Changed to SguilSendEvent*/ +- snprintf(ipInfo, 38, "|%u.%u.%u.%u|%u.%u.%u.%u|%u", +-#if defined(WORDS_BIGENDIAN) +- (p.iph->ip_src.s_addr & 0xff000000) >> 24, +- (p.iph->ip_src.s_addr & 0x00ff0000) >> 16, +- (p.iph->ip_src.s_addr & 0x0000ff00) >> 8, +- (p.iph->ip_src.s_addr & 0x000000ff), +- (p.iph->ip_dst.s_addr & 0xff000000) >> 24, +- (p.iph->ip_dst.s_addr & 0x00ff0000) >> 16, +- (p.iph->ip_dst.s_addr & 0x0000ff00) >> 8, +- (p.iph->ip_dst.s_addr & 0x000000ff), +-#else +- (p.iph->ip_src.s_addr & 0x000000ff), +- (p.iph->ip_src.s_addr & 0x0000ff00) >> 8, +- (p.iph->ip_src.s_addr & 0x00ff0000) >> 16, +- (p.iph->ip_src.s_addr & 0xff000000) >> 24, +- (p.iph->ip_dst.s_addr & 0x000000ff), +- (p.iph->ip_dst.s_addr & 0x0000ff00) >> 8, +- (p.iph->ip_dst.s_addr & 0x00ff0000) >> 16, +- (p.iph->ip_dst.s_addr & 0xff000000) >> 24, +-#endif +- p.iph->ip_proto); +- strcat(syslogMessage, ipInfo); ++ /* Add IP header */ ++ OpSguil_AppendIPHdrData(&list, &p); + +- /* store layer 4 data for non fragmented packets */ ++ /* Add icmp || udp || tcp data */ + if(!(p.pkt_flags & PKT_FRAG_FLAG)) + { ++ + switch(p.iph->ip_proto) + { + case IPPROTO_ICMP: +- snprintf(portInfo, 16, "|||"); +- if(!p.icmph) +- break; +- strcat(insertColumns, +- ", icmp_type, icmp_code)"); +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- ", '%u', '%u')", p.icmph->icmp_type, +- p.icmph->icmp_code); +- strcat(insertValues, valuesTemp); +- strcat(insertColumns, insertValues); +- sgInsert(op_data, insertColumns, NULL); +- sgInsertICMPData(op_data, &p); ++ OpSguil_AppendICMPData(&list, &p); + break; ++ + case IPPROTO_TCP: +- strcat(insertColumns, +- ", src_port, dst_port)"); +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- ", '%u', '%u')", p.sp, p.dp); +- strcat(insertValues, valuesTemp); +- strcat(insertColumns, insertValues); +- sgInsert(op_data, insertColumns, NULL); +- sgInsertTCPData(op_data, &p); +- snprintf(portInfo, 16, "|%u|%u|", +- p.sp, p.dp); ++ OpSguil_AppendTCPData(&list, &p); + break; ++ + case IPPROTO_UDP: +- strcat(insertColumns, +- ", src_port, dst_port)"); +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- ", '%u', '%u')", p.sp, p.dp); +- strcat(insertValues, valuesTemp); +- strcat(insertColumns, insertValues); +- sgInsert(op_data, insertColumns, NULL); +- sgInsertUDPData(op_data, &p); +- snprintf(portInfo, 16, "|%u|%u|", +- p.sp, p.dp); ++ OpSguil_AppendUDPData(&list, &p); ++ break; ++ ++ default: ++ for(i = 0; i < 17; ++i) ++ { ++ Tcl_DStringAppendElement(&list, ""); ++ } + break; + } +- strcat(syslogMessage, portInfo); ++ + } + else + { +- strcat(syslogMessage, "|||"); ++ /* Null out TCP/UDP/ICMP fields */ ++ for(i = 0; i < 17; ++i) ++ { ++ Tcl_DStringAppendElement(&list, ""); ++ } + } +- +- +- /* Insert payload data */ +- sgInsertPayloadData(op_data, &p); + } + else + { +- strcat(syslogMessage, "||||||"); ++ ++ /* No IP Header. */ ++ int i; ++ for(i = 0; i < 31; ++i) ++ { ++ Tcl_DStringAppendElement(&list, ""); ++ } + } +- } + +- //sgEndTransaction(op_data); /* XXX: Error Checking */ +- ++op_data->event_id; +- /* Append the sig id and rev to the RT event */ +- snprintf(eventInfo, SYSLOG_BUF, "%u|%u|\n", sid->sid, sid->rev); +- strcat(syslogMessage, eventInfo); +- /* Write to the network socket */ +- SguilSendEvent(op_data, syslogMessage); +- return 0; +-} ++ /* Add payload data */ ++ OpSguil_AppendPayloadData(&list, &p); + +-int sgInsertUDPData(OpSguil_Data *op_data, Packet *p) +-{ +- if(!p->udph) +- return 0; +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "INSERT INTO udphdr(sid, cid, udp_len, udp_csum)" +- "VALUES ('%u', '%u', '%u', '%u')", +- op_data->sensor_id, op_data->event_id, +- ntohs(p->udph->uh_len), +- ntohs(p->udph->uh_chk)) < MAX_QUERY_SIZE) ++ } ++ else ++ { ++ /* ack! an event without a packet. Append 32 fillers */ ++ int i; ++ for(i = 0; i < 32; ++i) + { +- sgInsert(op_data, sql_buffer, NULL); /* XXX: Error Checking */ ++ Tcl_DStringAppendElement(&list, ""); + } +- return 0; +-} ++ } + +-int sgInsertTCPData(OpSguil_Data *op_data, Packet *p) +-{ +- if(!p->tcph) +- return 0; ++ /* Send msg to sensor_agent */ ++ if (OpSguil_RTEventMsg(data, Tcl_DStringValue(&list))) ++ FatalError("Unable to send RT Events to sensor agent.\n"); + +- /* insert data into the tcp header table */ +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "INSERT INTO tcphdr(sid, cid, tcp_seq, " +- "tcp_ack, tcp_off, tcp_res, tcp_flags, tcp_win, tcp_csum, " +- "tcp_urp) VALUES('%u', '%u', '%u', '%u', '%u', " +- "'%u', '%u', '%u', '%u', '%u')", +- op_data->sensor_id, op_data->event_id, +- ntohl(p->tcph->th_seq), ntohl(p->tcph->th_ack), +- TCP_OFFSET(p->tcph), TCP_X2(p->tcph), p->tcph->th_flags, +- ntohs(p->tcph->th_win), ntohs(p->tcph->th_sum), +- ntohs(p->tcph->th_urp)) < MAX_QUERY_SIZE) +- { +- sgInsert(op_data, sql_buffer, NULL); /* XXX: Error checking */ +- } +- /* XXX: TCP Options not handled */ +- return 0; +-} ++ /* Free! */ ++ Tcl_DStringFree(&list); ++ ++ /* bump the event id */ ++ ++data->event_id; + +-int sgInsertICMPData(OpSguil_Data *op_data, Packet *p) +-{ +- if(!p->icmph) +- return 0; +- if(p->icmph->icmp_type == 0 || p->icmph->icmp_type == 8 || +- p->icmph->icmp_type == 13 || p->icmph->icmp_type == 14 || +- p->icmph->icmp_type == 15 || p->icmph->icmp_type == 16) +- { +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "INSERT INTO icmphdr(sid, cid, " +- "icmp_csum, icmp_id, icmp_seq) " +- "VALUES('%u', '%u', '%u', '%u', '%u')", +- op_data->sensor_id, op_data->event_id, +- ntohs(p->icmph->icmp_csum), +- htons(p->icmph->icmp_hun.ih_idseq.icd_id), +- htons(p->icmph->icmp_hun.ih_idseq.icd_seq)) +- < MAX_QUERY_SIZE) +- { +- sgInsert(op_data, sql_buffer, NULL); /* XXX: Error checking */ +- } +- } +- else +- { +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "INSERT INTO icmphdr(sid, cid, " +- "icmp_csum) VALUES('%u', '%u', '%u')", +- op_data->sensor_id, op_data->event_id, +- ntohs(p->icmph->icmp_csum)) +- < MAX_QUERY_SIZE) +- { +- sgInsert(op_data, sql_buffer, NULL); /* XXX: Error Checking */ +- } +- } + return 0; + } + +-int sgInsertPayloadData(OpSguil_Data *op_data, Packet *p) ++int OpSguil_RTEventMsg(OpSguil_Data *data, char *msg) + { +- char *hex_payload; +- if(p->dsize) +- { +- hex_payload = fasthex(p->data, p->dsize); +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "INSERT INTO data(sid, cid, data_payload) " +- "VALUES('%u', '%u', '%s')", op_data->sensor_id, +- op_data->event_id, hex_payload) < MAX_QUERY_SIZE) +- { +- sgInsert(op_data, sql_buffer, NULL); /* XXX: Error Checking */ +- } +- free(hex_payload); +- } +- return 0; +-} + ++ char tmpRecvMsg[MAX_MSG_LEN]; + +-/* Attempts to retrieve the sensor id +- */ +-unsigned int SguilGetSensorId(OpSguil_Data *op_data) +-{ +- unsigned int sensor_id = 0; +- /* XXX: This should be moved to global setup */ +- if(pv.hostname == NULL) +- { +- /* query the hostname */ +- /* the DB schema allows for a hostname of up to 2^16-1 characters, i am limiting +- * this to 255 (+1 for the NULL) +- */ +- pv.hostname = (char *)malloc(256); +- if(gethostname(pv.hostname, 256)) +- { +- FatalError("Error querying hostname: %s\n", strerror(errno)); +- } +- } ++ /* Send Msg */ ++ OpSguil_SendAgentMsg(data, msg); + +- /* XXX: need to escape strings */ +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "SELECT sid FROM sensor WHERE hostname='%s'" +- , pv.hostname) < MAX_QUERY_SIZE) ++ /* Get confirmation */ ++ memset(tmpRecvMsg,0x0,MAX_MSG_LEN); ++ if(OpSguil_RecvAgentMsg(data, tmpRecvMsg) == 1 ) + { +- if(sgSelectAsUInt(op_data, sql_buffer, &sensor_id) == -1) +- { +- FatalError("Database Error\n"); +- } +- if(sensor_id == 0) +- { + +- /* insert sensor information */ ++ if(pv.verbose) ++ LogMessage("Retrying\n"); ++ ++ OpSguil_RTEventMsg(data, msg); + +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO sensor (hostname) " +- "VALUES ('%s')", pv.hostname) < MAX_QUERY_SIZE) +- { +- sgInsert(op_data, sql_buffer, &sensor_id); +- /* XXX: Error checking */ +- } +- else +- { +- FatalError("Error building SQL Query\n"); +- } +- } +- if(pv.verbose >= 2) +- LogMessage("sensor_id == %u\n", sensor_id); + } + else + { +- FatalError("Error building SQL Query\n"); +- } +- return sensor_id; +-} + +-/* Retrieves the next acid_cid to use for inserting into the database for this +- * sensor +- */ +-unsigned int SguilGetNextCid(OpSguil_Data *data) +-{ +- unsigned int cid = 0; +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "SELECT max(cid) FROM event WHERE sid='%u'", data->sensor_id) +- < MAX_QUERY_SIZE) +- { +- if(sgSelectAsUInt(data, sql_buffer, &cid) == -1) ++ char **toks; ++ int num_toks; ++ ++ if(pv.verbose) ++ LogMessage("Received: %s", tmpRecvMsg); ++ ++ /* Parse the response */ ++ toks = mSplit(tmpRecvMsg, " ", 2, &num_toks, 0); ++ if(strcasecmp("Confirm", toks[0]) != 0 || atoi(toks[1]) != data->event_id ) + { +- FatalError("Database Error\n"); ++ ++ FatalError("Expected Confirm %u and got: %s\n", data->event_id, tmpRecvMsg); ++ + } +-#ifdef DEBUG +- LogMessage("cid == %u\n", cid); fflush(stdout); +-#endif ++ ++ FreeToks(toks, num_toks); ++ + } +- else +- { +- FatalError("Database Error\n"); +- } +- return ++cid; ++ ++ return 0; ++ + } + + OpSguil_Data *OpSguil_ParseArgs(char *args) + { +- OpSguil_Data *op_data; + ++ OpSguil_Data *op_data; ++ + op_data = (OpSguil_Data *)SafeAlloc(sizeof(OpSguil_Data)); +- +- op_data->options = 0; +- ++ + if(args != NULL) + { + char **toks; +@@ -685,77 +484,38 @@ + while(isspace((int)*index)) + ++index; + stoks = mSplit(index, " ", 2, &num_stoks, 0); +- if(strcasecmp("database", stoks[0]) == 0) +- { +- if(num_stoks > 1 && op_data->database == NULL) +- op_data->database = strdup(stoks[1]); +- else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, +- file_line, index); +- } +- else if(strcasecmp("server", stoks[0]) == 0) +- { +- if(num_stoks > 1 && op_data->server == NULL) +- op_data->server = strdup(stoks[1]); +- else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, +- file_line, index); +- } +- else if(strcasecmp("user", stoks[0]) == 0) ++ if(strcasecmp("agent_port", stoks[0]) == 0) + { +- if(num_stoks > 1 && op_data->user == NULL) +- op_data->user = strdup(stoks[1]); ++ if(num_stoks > 1) ++ op_data->agent_port = atoi(stoks[1]); + else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, ++ LogMessage("Argument Error in %s(%i): %s\n", file_name, + file_line, index); + } +- else if(strcasecmp("password", stoks[0]) == 0) ++ else if(strcasecmp("tag_path", stoks[0]) == 0) + { +- if(num_stoks > 1 && op_data->password == NULL) +- op_data->password = strdup(stoks[1]); ++ if(num_stoks > 1 && op_data->tag_path == NULL) ++ op_data->tag_path = strdup(stoks[1]); + else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, ++ LogMessage("Argument Error in %s(%i): %s\n", file_name, + file_line, index); + } +- else if(strcasecmp("sensor_id", stoks[0]) == 0) ++ else if(strcasecmp("sensor_name", stoks[0]) == 0) + { +- if(num_stoks > 1 && op_data->sensor_id == 0) +- op_data->sensor_id = atoi(stoks[1]); ++ if(num_stoks > 1 && op_data->sensor_name == NULL) ++ op_data->sensor_name = strdup(stoks[1]); + else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, ++ LogMessage("Argument Error in %s(%i): %s\n", file_name, + file_line, index); + } +- else if(strcasecmp("sguild_host", stoks[0]) == 0) +- { +- if(num_stoks > 1 && op_data->sguild_host == 0) +- op_data->sguild_host = strdup(stoks[1]); +- else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, +- file_line, index); +- } +- else if(strcasecmp("nospin", stoks[0]) == 0) +- { +- op_data->nospin = 1; +- } +- else if(strcasecmp("sguild_port", stoks[0]) == 0) ++ else if(strcasecmp("passwd", stoks[0]) == 0) + { +- if(num_stoks > 1 && op_data->sguild_port == 0) +- op_data->sguild_port = atoi(stoks[1]); +- else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, +- file_line, index); +- } +- +-#ifdef ENABLE_MYSQL +- else if(strcasecmp("mysql", stoks[0]) == 0) +- { +- if(op_data->flavor == 0) +- op_data->flavor = FLAVOR_MYSQL; ++ if(num_stoks > 1 && op_data->passwd == NULL) ++ op_data->passwd = strdup(stoks[1]); + else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, ++ LogMessage("Argument Error in %s(%i): %s\n", file_name, + file_line, index); + } +-#endif /* ENABLE_MYSQL */ + else + { + fprintf(stderr, "WARNING %s (%d) => Unrecognized argument for " +@@ -765,378 +525,544 @@ + } + /* free your mSplit tokens */ + FreeToks(toks, num_toks); +- } +- if(op_data->flavor == 0) +- FatalError("You must specify a database flavor\n"); + +- if (op_data->sguild_host == NULL) +- { +- FatalError("You must specify a sguild host.\n"); + } + +- if (!op_data->sguild_port) ++ if (op_data->agent_port == 0) + { +- FatalError("You must specify a sguild port.\n"); ++ op_data->agent_port = 7735; + } ++ + return op_data; +-} + ++} + +-int sgDbConnect(OpSguil_Data *op_data) ++int OpSguil_AppendIPHdrData(Tcl_DString *list, Packet *p) + { +- switch(op_data->flavor) +- { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlConnect(op_data); ++ char buffer[STD_BUFFER]; ++ ++ bzero(buffer, STD_BUFFER); ++ ++ sprintf(buffer, "%u", ntohl(p->iph->ip_src.s_addr)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u.%u.%u.%u", ++#if defined(WORDS_BIGENDIAN) ++ (p->iph->ip_src.s_addr & 0xff000000) >> 24, ++ (p->iph->ip_src.s_addr & 0x00ff0000) >> 16, ++ (p->iph->ip_src.s_addr & 0x0000ff00) >> 8, ++ (p->iph->ip_src.s_addr & 0x000000ff)); ++#else ++ (p->iph->ip_src.s_addr & 0x000000ff), ++ (p->iph->ip_src.s_addr & 0x0000ff00) >> 8, ++ (p->iph->ip_src.s_addr & 0x00ff0000) >> 16, ++ (p->iph->ip_src.s_addr & 0xff000000) >> 24); + #endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; +- } +-// return 1; ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", ntohl(p->iph->ip_dst.s_addr)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u.%u.%u.%u", ++#if defined(WORDS_BIGENDIAN) ++ (p->iph->ip_dst.s_addr & 0xff000000) >> 24, ++ (p->iph->ip_dst.s_addr & 0x00ff0000) >> 16, ++ (p->iph->ip_dst.s_addr & 0x0000ff00) >> 8, ++ (p->iph->ip_dst.s_addr & 0x000000ff)); ++#else ++ (p->iph->ip_dst.s_addr & 0x000000ff), ++ (p->iph->ip_dst.s_addr & 0x0000ff00) >> 8, ++ (p->iph->ip_dst.s_addr & 0x00ff0000) >> 16, ++ (p->iph->ip_dst.s_addr & 0xff000000) >> 24); ++#endif ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", p->iph->ip_proto); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", IP_VER(p->iph)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", IP_HLEN(p->iph)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", p->iph->ip_tos); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", ntohs(p->iph->ip_len)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", ntohs(p->iph->ip_id)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++#if defined(WORDS_BIGENDIAN) ++ ++ sprintf(buffer, "%u", ((p->iph->ip_off & 0xE000) >> 13)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", htons(p->iph->ip_off & 0x1FFF)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++#else ++ ++ sprintf(buffer, "%u", ((p->iph->ip_off & 0x00E0) >> 5)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", htons(p->iph->ip_off & 0xFF1F)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++#endif ++ ++ sprintf(buffer, "%u", p->iph->ip_ttl); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", htons(p->iph->ip_csum)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ return 0; + } + +-int sgDbClose(OpSguil_Data *op_data) ++int OpSguil_AppendICMPData(Tcl_DString *list, Packet *p) + { +- switch(op_data->flavor) ++ ++ int i; ++ char buffer[STD_BUFFER]; ++ ++ bzero(buffer, STD_BUFFER); ++ ++ if(!p->icmph) + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlClose(op_data->mysql); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; +- } +-} + ++ /* Null out ICMP fields */ ++ for(i=0; i < 5; i++) ++ Tcl_DStringAppendElement(list, ""); + +-int sgSelectAsUInt(OpSguil_Data *op_data, char *sql, unsigned int *result) +-{ +- switch(op_data->flavor) ++ } ++ else + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlSelectAsUInt(op_data->mysql, sql, result); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; ++ ++ /* ICMP type */ ++ sprintf(buffer, "%u", p->icmph->icmp_type); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ /* ICMP code */ ++ sprintf(buffer, "%u", p->icmph->icmp_code); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ /* ICMP CSUM */ ++ sprintf(buffer, "%u", ntohs(p->icmph->icmp_csum)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ /* Append other ICMP data if we have it */ ++ if(p->icmph->icmp_type == ICMP_ECHOREPLY || ++ p->icmph->icmp_type == ICMP_ECHO || ++ p->icmph->icmp_type == ICMP_TIMESTAMP || ++ p->icmph->icmp_type == ICMP_TIMESTAMPREPLY || ++ p->icmph->icmp_type == ICMP_INFO_REQUEST || ++ p->icmph->icmp_type == ICMP_INFO_REPLY) ++ { ++ ++ /* ICMP ID */ ++ sprintf(buffer, "%u", htons(p->icmph->icmp_hun.ih_idseq.icd_id)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ /* ICMP Seq */ ++ sprintf(buffer, "%u", htons(p->icmph->icmp_hun.ih_idseq.icd_seq)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ } ++ else ++ { ++ ++ /* Add two empty elements */ ++ for(i=0; i < 2; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ } ++ + } ++ ++ /* blank out 12 elements */ ++ for(i = 0; i < 12; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ return 0; ++ + } + +-int sgInsert(OpSguil_Data *op_data, char *sql, unsigned int *row_id) ++int OpSguil_AppendTCPData(Tcl_DString *list, Packet *p) + { +- switch(op_data->flavor) ++ ++ /* ++ ** 33 34 35 36 37 38 39 40 ++ ** {tcp seq} {tcp ack} {tcp off} {tcp res} {tcp flags} {tcp win} {tcp csum} {tcp urp} ++ ** ++ */ ++ ++ int i; ++ char buffer[STD_BUFFER]; ++ ++ bzero(buffer, STD_BUFFER); ++ ++ /* empty elements for icmp data */ ++ for(i=0; i < 5; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ if(!p->tcph) + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlInsert(op_data->mysql, sql, row_id); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; +- } +-} + +-int sgBeginTransaction(OpSguil_Data *op_data) +-{ +- switch(op_data->flavor) ++ /* Null out TCP fields */ ++ for(i=0; i < 10; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ } ++ else + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlInsert(op_data->mysql, "BEGIN", NULL); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; ++ ++ sprintf(buffer, "%u", p->sp); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", p->dp); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohl(p->tcph->th_seq)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohl(p->tcph->th_ack)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", TCP_OFFSET(p->tcph)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", TCP_X2(p->tcph)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", p->tcph->th_flags); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohs(p->tcph->th_win)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohs(p->tcph->th_sum)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohs(p->tcph->th_urp)); ++ Tcl_DStringAppendElement(list, buffer); ++ + } ++ ++ /* empty elements for UDP data */ ++ for(i=0; i < 2; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ return 0; ++ + } + +-int sgEndTransaction(OpSguil_Data *op_data) ++int OpSguil_AppendUDPData(Tcl_DString *list, Packet *p) + { +- switch(op_data->flavor) ++ ++ int i; ++ char buffer[STD_BUFFER]; ++ ++ bzero(buffer, STD_BUFFER); ++ ++ /* empty elements for icmp data */ ++ for(i=0; i < 5; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ if(!p->udph) + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlInsert(op_data->mysql, "COMMIT", NULL); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; ++ ++ /* Null out port info */ ++ for(i=0; i < 2; i++) ++ Tcl_DStringAppendElement(list, ""); ++ + } +-} +- +-int sgAbortTransaction(OpSguil_Data *op_data) +-{ +- switch(op_data->flavor) ++ else + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlInsert(op_data->mysql, "ROLLBACK", NULL); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; ++ ++ /* source and dst port */ ++ sprintf(buffer, "%u", p->sp); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", p->dp); ++ Tcl_DStringAppendElement(list, buffer); ++ + } +-} + ++ /* empty elements for tcp data */ ++ for(i=0; i < 8; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ if(!p->udph) ++ { ++ ++ /* Null out UDP info */ ++ for(i=0; i < 2; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ } ++ else ++ { ++ ++ sprintf(buffer, "%u", ntohs(p->udph->uh_len)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohs(p->udph->uh_chk)); ++ Tcl_DStringAppendElement(list, buffer); + +-#ifdef ENABLE_MYSQL +-int sgMysqlConnect(OpSguil_Data *op_data) +-{ +- op_data->mysql = mysql_init(NULL); +- if(!mysql_real_connect(op_data->mysql, op_data->server, op_data->user, +- op_data->password, op_data->database, 0, NULL, 0)) +- { +- FatalError("Failed to connect to database %s:%s@%s/%s: %s\n", +- op_data->user, op_data->password, op_data->server, +- op_data->database, mysql_error(op_data->mysql)); + } ++ + return 0; ++ + } + +-int sgMysqlClose(MYSQL *mysql) ++int OpSguil_AppendPayloadData(Tcl_DString *list, Packet *p) + { +- mysql_close(mysql); ++ ++ char *hex_payload; ++ ++ if(p->dsize) ++ { ++ hex_payload = fasthex(p->data, p->dsize); ++ Tcl_DStringAppendElement(list, hex_payload); ++ free(hex_payload); ++ } else { ++ Tcl_DStringAppendElement(list, ""); ++ } ++ + return 0; ++ + } + +-int sgMysqlExecuteQuery(MYSQL *mysql, char *sql) ++ ++int OpSguil_SensorAgentConnect(OpSguil_Data *data) + { +- int mysqlErrno; +- int result; +- while((result = mysql_query(mysql, sql) != 0)) ++ ++ int sockfd; ++ struct sockaddr_in my_addr; ++ ++ while(1) + { +- mysqlErrno = mysql_errno(mysql); +- if(mysqlErrno < CR_MIN_ERROR) ++ ++ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { +- if(pv.verbose) +- LogMessage("MySQL ERROR(%i): %s. Aborting Query\n", +- mysql_errno(mysql), mysql_error(mysql)); +- return result; ++ FatalError("Cannot open a local socket.\n"); ++ return 1; + } +- if((mysqlErrno == CR_SERVER_LOST) +- || (mysqlErrno == CR_SERVER_GONE_ERROR)) ++ ++ my_addr.sin_family = AF_INET; ++ my_addr.sin_port = htons(data->agent_port); ++ my_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); ++ memset(&(my_addr.sin_zero), '\0', 8); ++ ++ ++ if (connect(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) < 0) + { +- LogMessage("Lost connection to MySQL server. Reconnecting\n"); +- while(mysql_ping(mysql) != 0) ++ LogMessage("Cannot connect to localhost on TCP port %u.\n", ++ data->agent_port); ++ close(sockfd); ++ LogMessage("Waiting 15 secs to try again.\n"); ++ if (BarnyardSleep(15)) + { +- if(BarnyardSleep(15)) +- return result; ++ LogMessage("Received Kill Signal..."); ++ CleanExit(0); + } +- LogMessage("Reconnected to MySQL server.\n"); ++ + } + else + { +- /* XXX we could spin here, but we do not */ +- LogMessage("MySQL Error(%i): %s\n", mysqlErrno, mysql_error(mysql)); ++ ++ data->agent_sock = sockfd; ++ LogMessage("Connected to localhost on %u.\n", ++ data->agent_port); ++ return 0; ++ + } ++ + } +- return result; +-} + ++} + +-int sgMysqlSelectAsUInt(MYSQL *mysql, char *sql, unsigned int *result) ++/* ++int OpSguil_SensorAgentAuth(OpSguil_Data *data) + { +- int rval = 0; +- MYSQL_RES *mysql_res; +- MYSQL_ROW tuple; +- +- if(sgMysqlExecuteQuery(mysql, sql) != 0) +- { +- /* XXX: should really just return up the chain */ +- FatalError("Error (%s) executing query: %s\n", mysql_error(mysql), sql); +- return -1; +- } + +- mysql_res = mysql_store_result(mysql); +- if((tuple = mysql_fetch_row(mysql_res))) +- { +- if(tuple[0] == NULL) +- *result = 0; +- else +- *result = atoi(tuple[0]); +- rval = 1; +- } +- mysql_free_result(mysql_res); +- return rval; ++ Tcl_DString auth_cmd; ++ ++ Tcl_DStringInit(&auth_cmd); ++ Tcl_DStringAppendElement(auth_cmd, "AUTH"); ++ Tcl_DStringAppendElement(auth_cmd, data->passwd); ++ ++ + } ++*/ + +-int sgMysqlInsert(MYSQL *mysql, char *sql, unsigned int *row_id) ++/* Request sensor ID (sid) and next cid from sensor_agent */ ++int OpSguil_SensorAgentInit(OpSguil_Data *data) + { +- if(sgMysqlExecuteQuery(mysql, sql) != 0) ++ ++ char tmpSendMsg[MAX_MSG_LEN]; ++ char tmpRecvMsg[MAX_MSG_LEN]; ++ ++ /* Send our Request */ ++ snprintf(tmpSendMsg, MAX_MSG_LEN, "SidCidRequest %s", data->sensor_name); ++ OpSguil_SendAgentMsg(data, tmpSendMsg); ++ ++ /* Get the Results */ ++ memset(tmpRecvMsg,0x0,MAX_MSG_LEN); ++ if(OpSguil_RecvAgentMsg(data, tmpRecvMsg) == 1 ) + { +- /* XXX: should really just return up the chain */ +- FatalError("Error (%s) executing query: %s\n", mysql_error(mysql), sql); +- return -1; ++ ++ OpSguil_SensorAgentInit(data); ++ + } ++ else ++ { + +- if(row_id != NULL) +- *row_id = mysql_insert_id(mysql); +- return 0; +-} +-#endif ++ char **toks; ++ int num_toks; + +-/* SguildConnect() opens a network socket to sguild for sending +- * RT event messages. Bammkkkk +-*/ +-int SguildConnect(OpSguil_Data *op_data) +-{ +- int sockfd; +- struct hostent *he; +- struct sockaddr_in server_addr; ++ if(pv.verbose) ++ LogMessage("Received: %s", tmpRecvMsg); + +- if ((he=gethostbyname(op_data->sguild_host)) == NULL) ++ /* Parse the response */ ++ toks = mSplit(tmpRecvMsg, " ", 3, &num_toks, 0); ++ if(strcasecmp("SidCidResponse", toks[0]) == 0) + { +- FatalError("Cannot resolve hostname: %s\n", op_data->sguild_host); +- return 1; ++ ++ data->sensor_id = atoi(toks[1]); ++ data->event_id = atoi(toks[2]); ++ + } +- +- if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) ++ else + { +- +- FatalError("Cannot open a local socket.\n"); +- return 1; +- ++ ++ FatalError("Expected SidCidResponse and got: %s\n", tmpRecvMsg); ++ + } + +- server_addr.sin_family = AF_INET; +- server_addr.sin_port = htons(op_data->sguild_port); +- server_addr.sin_addr = *((struct in_addr *)he->h_addr); +- memset(&(server_addr.sin_zero), '\0', 8); ++ FreeToks(toks, num_toks); + +- if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0) +- { +- +- LogMessage("Cannot connect to %s on TCP port %u.\n", +- op_data->sguild_host, op_data->sguild_port); +- close(sockfd); +- return 1; ++ if(pv.verbose) ++ LogMessage("Sensor ID: %u\nLast cid: %u\n", data->sensor_id, data->event_id); ++ ++ /* Use the next event_id */ ++ ++data->event_id; ++ ++ } ++ ++ return 0; ++ ++} ++ ++int OpSguil_SendAgentMsg(OpSguil_Data *data, char *msg) ++{ ++ ++ int schars; ++ size_t len; ++ char *tmpMsg; ++ ++ len = strlen(msg)+2; + +- } ++ tmpMsg = SafeAlloc(len); + +- op_data->sguild_sock = sockfd; +- return 0; ++ snprintf(tmpMsg, len, "%s\n", msg); ++ ++ if((schars = send(data->agent_sock, tmpMsg, sizeof(char)*strlen(tmpMsg), 0)) < 0) ++ { ++ ++ if(pv.verbose) ++ LogMessage("Lost connection to sensor_agent.\n"); ++ ++ /* Resend our msg */ ++ OpSguil_SendAgentMsg(data, msg); ++ ++ } ++ ++ if(pv.verbose) ++ LogMessage("Sent: %s", tmpMsg); ++ ++ free(tmpMsg); ++ ++ return 0; + + } ++ + /* I love google. http://pont.net/socket/prog/tcpServer.c */ +-int read_line(int newSd, char *line_to_return) { +- ++int OpSguil_RecvAgentMsg(OpSguil_Data *data, char *line_to_return) { ++ + static int rcv_ptr=0; + static char rcv_msg[MAX_MSG_LEN]; + static int n; ++ struct timeval tv; ++ fd_set read_fds; + int offset; +- ++ + offset=0; ++ /* wait 15 secs for our response */ ++ tv.tv_sec = 15; ++ tv.tv_usec = 0; ++ ++ FD_ZERO(&read_fds); ++ FD_SET(data->agent_sock, &read_fds); + + while(1) { +- if(rcv_ptr==0) { + +- memset(rcv_msg,0x0,MAX_MSG_LEN); +- n = recv(newSd, rcv_msg, MAX_MSG_LEN, 0); +- if (n<0) { +- LogMessage("ERROR: Unable to read data.\n"); +- return 1; +- } else if (n==0) { +- LogMessage("ERROR: Connecton closed by client\n"); +- close(newSd); +- return 1; +- } ++ /* Wait for response from sguild */ ++ select(data->agent_sock+1, &read_fds, NULL, NULL, &tv); ++ ++ if (!(FD_ISSET(data->agent_sock, &read_fds))) ++ { ++ /* timed out */ ++ if(pv.verbose) ++ LogMessage("Timed out waiting for response.\n"); ++ ++ return 1; + } ++ else ++ { ++ if(rcv_ptr==0) { ++ ++ memset(rcv_msg,0x0,MAX_MSG_LEN); ++ n = recv(data->agent_sock, rcv_msg, MAX_MSG_LEN, 0); ++ if (n<0) { ++ LogMessage("ERROR: Unable to read data.\n"); ++ /* Reconnect to sensor_agent */ ++ OpSguil_SensorAgentConnect(data); ++ } else if (n==0) { ++ LogMessage("ERROR: Connecton closed by client\n"); ++ close(data->agent_sock); ++ /* Reconnect to sensor_agent */ ++ OpSguil_SensorAgentConnect(data); ++ } ++ } ++ ++ /* if new data read on socket */ ++ /* OR */ ++ /* if another line is still in buffer */ ++ ++ /* copy line into 'line_to_return' */ ++ while(*(rcv_msg+rcv_ptr)!=0x0A && rcv_ptr return line */ ++ if(rcv_ptr==n-1) { ++ /* set last byte to END_LINE */ ++ *(line_to_return+offset)=0x0A; ++ rcv_ptr=0; ++ return ++offset; ++ } ++ ++ /* end of line but still some data in buffer => return line */ ++ if(rcv_ptr return line */ +- if(rcv_ptr==n-1) { +- /* set last byte to END_LINE */ +- *(line_to_return+offset)=0x0A; +- rcv_ptr=0; +- return ++offset; +- } +- +- /* end of line but still some data in buffer => return line */ +- if(rcv_ptr */ ++ /* wait for more data to arrive on socket */ ++ if(rcv_ptr == n) { ++ rcv_ptr = 0; ++ } ++ + } + +- /* end of buffer but line is not ended => */ +- /* wait for more data to arrive on socket */ +- if(rcv_ptr == n) { +- rcv_ptr = 0; +- } +- + } +-} + +-/* SguilSendEvent() sends the event via the open network socket. +- * Bammkkkk +-*/ +-int SguilSendEvent(OpSguil_Data *op_data, char *eventMsg) +-{ +- +- int schars; +- char line[100]; +- +- +- if((schars = send(op_data->sguild_sock, eventMsg, strlen(eventMsg), 0)) < 0) +- { +- LogMessage("ERROR! Couldn't send msg.\n"); +- +- /* ReConnect to sguild */ +- while(SguildConnect(op_data) == 1) +- { +- if(op_data->nospin) return 0; +- LogMessage("ERROR: Couldn't reconnect. Will try again in 15 secs.\n"); +- if (BarnyardSleep(15)) break; +- } +- LogMessage("Connected to %s.\n", op_data->sguild_host); +- SguilSendEvent(op_data, eventMsg); +- +- } else { +- +- //LogMessage("Msg sent: %s", eventMsg); +- //LogMessage("Chars sent: %i\n", schars); +- +- memset(line, 0x0, 100); +- if(read_line(op_data->sguild_sock, line) == 1) +- { +- +- if (op_data->nospin == 0) +- { +- +- +- LogMessage("ERROR! Didn't receive confirmation. Trying to reconnect.\n"); +- +- /* ReConnect to sguild */ +- while(SguildConnect(op_data) == 1) +- { +- LogMessage("ERROR: Couldn't reconnect. Will try again in 15 secs.\n"); +- if (BarnyardSleep(15)) break; +- } +- +- LogMessage("Connected to %s.\n", op_data->sguild_host); +- SguilSendEvent(op_data, eventMsg); +- +- } +- +- } +- } +- return 0; +- + } + +-#endif diff --git a/security/barnyard-sguil/files/patch-op_plugbase.c b/security/barnyard-sguil/files/patch-op_plugbase.c new file mode 100644 index 000000000000..5ea119214df1 --- /dev/null +++ b/security/barnyard-sguil/files/patch-op_plugbase.c @@ -0,0 +1,20 @@ +--- src/output-plugins/op_plugbase.c.orig Sun Mar 28 18:14:19 2004 ++++ src/output-plugins/op_plugbase.c Sun Jan 15 22:33:35 2006 +@@ -27,7 +27,7 @@ + #if defined(ENABLE_MYSQL) || defined(ENABLE_POSTGRES) + #include "op_acid_db.h" + #endif +-#ifdef ENABLE_MYSQL ++#ifdef ENABLE_TCL + #include "op_sguil.h" + #endif + #include "op_alert_csv.h" +@@ -47,7 +47,7 @@ + #if defined(ENABLE_MYSQL) || defined(ENABLE_POSTGRES) + OpAcidDb_Init(); + #endif +-#ifdef ENABLE_MYSQL ++#ifdef ENABLE_TCL + OpSguil_Init(); + #endif + OpAlertCSV_Init(); diff --git a/security/barnyard-sguil/files/patch-op_sguil.h b/security/barnyard-sguil/files/patch-op_sguil.h new file mode 100644 index 000000000000..de89409bf74d --- /dev/null +++ b/security/barnyard-sguil/files/patch-op_sguil.h @@ -0,0 +1,26 @@ +--- src/output-plugins/op_sguil.h.orig Mon Mar 15 22:18:20 2004 ++++ src/output-plugins/op_sguil.h Sun Jan 15 22:32:07 2006 +@@ -1,8 +1,9 @@ +-/* $Id: op_sguil.h,v 1.2 2004/03/16 04:18:20 andrewbaker Exp $ */ ++/* $Id: op_sguil.h,v 1.2 2005/03/03 21:07:44 bamm Exp $ */ ++ + /* +-** Copyright (C) 2001 Andrew R. Baker ++** Copyright (C) 2002-2004 Robert (Bamm) Visscher + ** +-** This program is distributed under the terms of version 1.0 of the ++** This program is distributed under the terms of version 1.0 of the + ** Q Public License. See LICENSE.QPL for further details. + ** + ** This program is distributed in the hope that it will be useful, +@@ -11,10 +12,4 @@ + ** + */ + +-#ifndef __OP_SGUIL_H__ +-#define __OP_SGUIL_H__ +- + void OpSguil_Init(); +- +-#endif /* __OP_SGUIL_H__ */ +- diff --git a/security/barnyard-sguil6/Makefile b/security/barnyard-sguil6/Makefile new file mode 100644 index 000000000000..a3e01c102350 --- /dev/null +++ b/security/barnyard-sguil6/Makefile @@ -0,0 +1,18 @@ +# New ports collection makefile for: barnyard-sguil6 +# Date created: 23 Jan 2006 +# Whom: pauls +# +# $FreeBSD$ +# + +PKGNAMESUFFIX= -sguil6 +COMMENT= An output system for Snort (patched for sguil6) + +LIB_DEPENDS+= tcl84.1:${PORTSDIR}/lang/tcl84 + +MASTERDIR= ${.CURDIR}/../barnyard +PATCHDIR= ${.CURDIR}/files + +CONFIGURE_ARGS+= --enable-tcl --with-tcl=${PREFIX}/lib/tcl8.4 + +.include "${MASTERDIR}/Makefile" diff --git a/security/barnyard-sguil6/files/patch-configure.in b/security/barnyard-sguil6/files/patch-configure.in new file mode 100644 index 000000000000..aad901a05648 --- /dev/null +++ b/security/barnyard-sguil6/files/patch-configure.in @@ -0,0 +1,63 @@ +--- configure.in.orig Sat May 1 11:43:29 2004 ++++ configure.in Mon Jan 23 14:32:54 2006 +@@ -1,4 +1,4 @@ +-# $Id: configure.in,v 1.17 2004/05/01 16:43:29 andrewbaker Exp $ ++# $Id: configure.in,v 1.2 2005/03/08 20:37:40 bamm Exp $ + AC_INIT(src/barnyard.c) + AM_CONFIG_HEADER(config.h) + AM_INIT_AUTOMAKE(barnyard,0.2.0) +@@ -281,13 +281,53 @@ + + dnl check for the header + LDFLAGS="${LDFLAGS} -L${MYSQL_LIB_DIR}" +- LIBS="${LIBS} -lz -lssl -lmysqlclient" ++ LIBS="${LIBS} -lmysqlclient -lcrypto" + AC_CHECK_LIB(mysqlclient, mysql_real_connect, FOUND=yes, FOUND=no) + + if test "$FOUND" = "no"; then + FAIL_MESSAGE("mysqlclient library", "$MYSQL_LIB_DIR") + fi + ++fi ++ ++AC_ARG_ENABLE(tcl, ++ [ --enable-tcl Enable Tcl language support.],, ++ [enable_tcl="no"]) ++dnl AC_MSG_RESULT($enable_tcl) ++ ++if test "yes" = "$enable_tcl"; then ++ ++ dnl let tclsh tell us where it was ++ dnl installed (prefer new tcl versions). ++ AC_CHECK_PROGS(TCLSH, tclsh8.4 tclsh8.3 tclsh8.2 tclsh8.1 tclsh8.0 tclsh) ++ if test "$TCLSH" != ""; then ++ tclpath=`echo 'puts [[lindex $tcl_pkgPath 0]]' | $TCLSH` ++ fi ++ ++ dnl let the user overwrite the installation ++ dnl directory which was just found. ++ AC_ARG_WITH(tcl, ++ [ --with-tcl=PATH Location of tclConfig.sh], ++ tclpath="$withval") ++ ++ dnl check, if tclConfig.sh can be found in ++ dnl tclsh's installation directory. ++ if test ! -r $tclpath/tclConfig.sh; then ++ AC_MSG_RESULT( ++ [ ++ Can't find Tcl libraries. Use --with-tcl to specify ++ the directory containing tclConfig.sh on your system. ++ Continuing build without Tcl support.]) ++ else ++ dnl source tclsh's configuration file ++ dnl and tell the user about the version. ++ . $tclpath/tclConfig.sh ++ AC_MSG_CHECKING([for the tcl version number]) ++ AC_MSG_RESULT([$TCL_VERSION, patchlevel $TCL_PATCH_LEVEL]) ++ LIBS="$LIBS $TCL_LIBS $TCL_LIB_SPEC" ++ TCL_INCLUDE="$TCL_PREFIX/include/tcl$TCL_VERSION" ++ CPPFLAGS="$CPPFLAGS -I$TCL_INCLUDE -DENABLE_TCL"; ++ fi + fi + + diff --git a/security/barnyard-sguil6/files/patch-op-sguil.c b/security/barnyard-sguil6/files/patch-op-sguil.c new file mode 100644 index 000000000000..563af968217b --- /dev/null +++ b/security/barnyard-sguil6/files/patch-op-sguil.c @@ -0,0 +1,1873 @@ +--- src/output-plugins/op_sguil.c.orig Sat Apr 3 13:57:33 2004 ++++ src/output-plugins/op_sguil.c Mon Jan 23 18:22:09 2006 +@@ -1,8 +1,9 @@ +-/* $Id: op_sguil.c,v 1.5 2004/04/03 19:57:33 andrewbaker Exp $ */ ++/* $Id: op_sguil.c,v 1.16 2005/09/01 15:17:56 bamm Exp $ */ ++ + /* +-** Copyright (C) 2001-2002 Andrew R. Baker ++** Copyright (C) 2002-2005 Robert (Bamm) Visscher + ** +-** This program is distributed under the terms of version 1.0 of the ++** This program is distributed under the terms of version 1.0 of the + ** Q Public License. See LICENSE.QPL for further details. + ** + ** This program is distributed in the hope that it will be useful, +@@ -11,21 +12,16 @@ + ** + */ + +-/* op_sguil is a modified op_acid_db plugin configured to work with +- * sguil (Snort GUI for Lamerz). Sguil and ACIDs DB schemas differ. +- * Sguil combines the event and iphdr tables along with moving the +- * src and dst port columns into event. I've also added SguilSendEvent +- * which opens a network socket and sends RT events to sguild. +- * +- * Andrew, sorry about mangling your code but it works so well :) +- * +- * Bammkkkk ++/* ++** op_sguil is the sguil output plugin for barnyard (http://barnyard.sf.net). ++** For more information about sguil see http://www.sguil.net + */ + +-/* I N C L U D E S *****************************************************/ +- +-#ifdef ENABLE_MYSQL /* Wrap the whole thing in an ENABLE_MYSQL block */ ++/********************************************************************* ++* I N C L U D E S * ++*********************************************************************/ + ++/* Std includes */ + #include + #include + #include +@@ -48,52 +44,13 @@ + #include "op_decode.h" + #include "event.h" + +-/* Needed for network socket */ + #include + #include + #include + #include + +-#ifdef ENABLE_MYSQL +-#include +-#include +-#endif /* ENABLE_MYSQL */ +- +-/* D A T A S T R U C T U R E S **************************************/ +-typedef struct _OpSguil_Data +-{ +- u_int8_t flavor; /* what flavor of db? MySQL, postgres, ... */ +- u_int16_t unused; +- char *server; +- char *database; +- char *user; +- char *password; +- int sensor_id; +- int options; +- char *sguild_host; +- int sguild_sock; +- int sguild_port; +- int nospin; +- u_int32_t event_id; +- /* db handles go here */ +-#ifdef ENABLE_MYSQL +- MYSQL *mysql; +-#endif /* ENABLE_MYSQL */ +-} OpSguil_Data; +- +- +-#define MAX_QUERY_SIZE 8192 +-#define SYSLOG_BUF 1024 +- +-/* database flavor defines */ +-#define FLAVOR_MYSQL 1 +-#define FLAVOR_POSTGRES 2 +- +-static char *sgdb_flavours[] = {NULL, "mysql", "postgres"}; +- +-/* Network socket defines */ +-#define MAX_MSG_LEN 100 +- ++/* Yeah TCL! */ ++#include + + /* Output plug-in API functions */ + static int OpSguil_Setup(OutputPlugin *, char *args); +@@ -103,56 +60,39 @@ + static int OpSguil_Log(void *, void *); + static int OpSguil_LogConfig(OutputPlugin *outputPlugin); + +-/* Internal functions */ +-int SguildConnect(OpSguil_Data *); +-int SguilSendEvent(OpSguil_Data *data, char *eventMsg); +-int read_line(); +-OpSguil_Data *OpSguil_ParseArgs(char *); +-int sgDbClose(OpSguil_Data *data); +-int sgDbConnect(OpSguil_Data *data); +-u_int32_t SguilGetNextCid(OpSguil_Data *data); +-u_int32_t SguilGetSensorId(OpSguil_Data *data); +-int SguilCheckSchemaVersion(OpSguil_Data *data); +-int InsertIPData(OpSguil_Data *data, Packet *p); +-int sgInsertICMPData(OpSguil_Data *data, Packet *p); +-int sgInsertUDPData(OpSguil_Data *data, Packet *p); +-int sgInsertTCPData(OpSguil_Data *data, Packet *p); +-int sgInsertPayloadData(OpSguil_Data *data, Packet *p); +- +-int sgSelectAsUInt(OpSguil_Data *data, char *sql, unsigned int *result); +-int sgInsert(OpSguil_Data *data, char *sql, unsigned int *row_id); +-int sgBeginTransaction(OpSguil_Data *); +-int sgEndTransaction(OpSguil_Data *); +-int sgAbortTransaction(OpSguil_Data *); +- +-#ifdef ENABLE_MYSQL +-int sgMysqlConnect(OpSguil_Data *); +-int sgMysqlClose(MYSQL *mysql); +-int sgMysqlSelectAsUInt(MYSQL *mysql, char *sql, unsigned int *result); +-int sgMysqlInsert(MYSQL *mysql, char *sql, unsigned int *row_id); +-#endif ++typedef struct _OpSguil_Data ++{ ++ char *sensor_name; ++ char *tag_path; ++ char *passwd; ++ u_int16_t sensor_id; ++ u_int32_t event_id; ++ u_int16_t agent_port; ++ int agent_sock; ++} OpSguil_Data; + +-/* Global variables */ +-static char sql_buffer[MAX_QUERY_SIZE]; ++#define MAX_MSG_LEN 2048 ++#define STD_BUFFER 128 + +-/* +- * Rather than using an incremental connection id (cid), this uses the +- * current time in milliseconds. BY is fast, but will we get dups in the +- * same millisecond? +- * Okay, lets wait on doing this. +-long GetMilliseconds() +-{ +- struct timeval tv; +- gettimeofday(&tv, NULL); ++int OpSguil_AppendIPHdrData(Tcl_DString *list, Packet *p); ++int OpSguil_AppendICMPData(Tcl_DString *list, Packet *p); ++int OpSguil_AppendTCPData(Tcl_DString *list, Packet *p); ++int OpSguil_AppendUDPData(Tcl_DString *list, Packet *p); ++int OpSguil_AppendPayloadData(Tcl_DString *list, Packet *p); ++int OpSguil_SensorAgentConnect(OpSguil_Data *); ++//int OpSguil_SensorAgentAuth(OpSguil_Data *); ++int OpSguil_SensorAgentInit(OpSguil_Data *); ++int OpSguil_RTEventMsg(OpSguil_Data *data, char *msg); ++int OpSguil_SendAgentMsg(OpSguil_Data *data, char *msg); ++int OpSguil_RecvAgentMsg(); ++OpSguil_Data *OpSguil_ParseArgs(char *); + +- return (long)(tv.tv_sec * 1000 + tv.tv_usec / 1000); +-}*/ + + /* init routine makes this processor available for dataprocessor directives */ + void OpSguil_Init() + { + OutputPlugin *outputPlugin; +- ++ + outputPlugin = RegisterOutputPlugin("sguil", "log"); + outputPlugin->setupFunc = OpSguil_Setup; + outputPlugin->exitFunc = OpSguil_Exit; +@@ -160,25 +100,9 @@ + outputPlugin->stopFunc = OpSguil_Stop; + outputPlugin->outputFunc = OpSguil_Log; + outputPlugin->logConfigFunc = OpSguil_LogConfig; +- ++ + } + +-int OpSguil_LogConfig(OutputPlugin *outputPlugin) +-{ +- OpSguil_Data *data = NULL; +- +- if(!outputPlugin || !outputPlugin->data) +- return -1; +- +- data = (OpSguil_Data *)outputPlugin->data; +- +- LogMessage("OpSguil configured\n"); +- /* XXX We need to print the configuration details here */ +- return 0; +-} +- +- +- + /* Setup the output plugin, process any arguments, link the functions to + * the output functional node + */ +@@ -186,11 +110,11 @@ + { + /* setup the run time context for this output plugin */ + outputPlugin->data = OpSguil_ParseArgs(args); +- ++ + return 0; + } +- +-/* Inverse of the setup function, free memory allocated in Setup ++ ++/* Inverse of the setup function, free memory allocated in Setup + * can't free the outputPlugin since it is also the list node itself + */ + int OpSguil_Exit(OutputPlugin *outputPlugin) +@@ -198,478 +122,353 @@ + return 0; + } + +-/* ++/* + * this function gets called at start time, you should open any output files + * or establish DB connections, etc, here + */ + int OpSguil_Start(OutputPlugin *outputPlugin, void *spool_header) + { +- char tmpMsg [256]; + OpSguil_Data *data = (OpSguil_Data *)outputPlugin->data; +- LogMessage("OpSguil_Start\n"); + + if(data == NULL) + FatalError("ERROR: Unable to find context for Sguil startup!\n"); ++ ++ if(pv.verbose) ++ OpSguil_LogConfig(outputPlugin); ++ ++ /* Figure out out sensor_name */ ++ if(data->sensor_name == NULL) ++ { ++ /* See if the user used the ProgVar config hostname: */ ++ if(pv.hostname != NULL) ++ { ++ data->sensor_name = pv.hostname; ++ } ++ else ++ { ++ FatalError("ERROR: Unable to determine hostname."); ++ } ++ } ++ ++ /* Connect to sensor_agent */ ++ OpSguil_SensorAgentConnect(data); ++ ++ /* Initialize - get sid and next cid */ ++ if(pv.verbose) ++ LogMessage("Waiting for sid and cid from sensor_agent.\n"); ++ OpSguil_SensorAgentInit(data); + +- /* Connect to sguild */ +- if(SguildConnect(data)) +- FatalError("OpSguil_: Failed to connect to sguild: %s:%i\n", +- data->sguild_host, data->sguild_port); +- +- /* Write a system-info message*/ +- sprintf(tmpMsg, "RTEvent |||system-info|%s||Barnyard started.||||||||\n", pv.hostname); +- SguilSendEvent(data, tmpMsg); +- +- /* Connect to the database */ +- if(sgDbConnect(data)) +- FatalError("OpSguil_: Failed to connect to database: %s:%s@%s/%s\n", +- data->user, data->password, data->server, data->database); +- +- /* check the db schema */ +- /*if(SguilCheckSchemaVersion(data)) +- FatalError("OpSguil_: database schema mismatch\n");*/ +- +- /* if sensor id == 0, then we attempt attempt to determine it dynamically */ +- if(data->sensor_id == 0) +- { +- data->sensor_id = SguilGetSensorId(data); +- /* XXX: Error checking */ +- } +- /* Get the next cid from the database */ +- data->event_id = SguilGetNextCid(data); + if(pv.verbose) + { +- LogMessage("OpAcidDB configuration details\n"); +- LogMessage("Database Flavour: %s\n", sgdb_flavours[data->flavor]); +- LogMessage("Database Server: %s\n", data->server); +- LogMessage("Database User: %s\n", data->user); +- LogMessage("SensorID: %i\n", data->sensor_id); +- LogMessage("Sguild Host: %s\n", data->sguild_host); +- LogMessage("Sguild Port: %i\n", data->sguild_port); +- } +- if((data->nospin) == NULL) +- { +- if(pv.verbose) +- { +- LogMessage("Barnyard will sleep(15) if unable to connect to sguild.\n"); +- } +- data->nospin = 0; +- } +- else +- { +- if(pv.verbose) +- { +- LogMessage("Spinning disabled.\n"); +- } ++ ++ LogMessage("Sensor Name: %s\n", data->sensor_name); ++ LogMessage("Agent Port: %u\n", data->agent_port); ++ + } + +- sprintf(tmpMsg, "RTEvent |||system-info|%s||Database Server: %s.||||||||\n", +- pv.hostname, data->server); +- SguilSendEvent(data, tmpMsg); +- +- sprintf(tmpMsg, "RTEvent |||system-info|%s||Database Next CID: %i.||||||||\n", +- pv.hostname, data->event_id); +- SguilSendEvent(data, tmpMsg); ++/* ++** if(SensorAgentAuth(data)) ++** FatalError("OpSguil: Authentication failed.\n"); ++** ++** if(pv.verbose) ++** LogMessage("OpSguil: Authentication successful.); ++*/ ++ + return 0; + } + + int OpSguil_Stop(OutputPlugin *outputPlugin) + { + OpSguil_Data *data = (OpSguil_Data *)outputPlugin->data; +- ++ + if(data == NULL) + FatalError("ERROR: Unable to find context for Sguil startup!\n"); ++ ++ return 0; ++} ++ ++int OpSguil_LogConfig(OutputPlugin *outputPlugin) ++{ ++ ++ OpSguil_Data *data = NULL; ++ ++ if(!outputPlugin || !outputPlugin->data) ++ return -1; ++ ++ data = (OpSguil_Data *)outputPlugin->data; ++ ++ LogMessage("OpSguil configured\n"); ++ ++ /* XXX We need to print the configuration details here */ + +- /* close database connection */ +- sgDbClose(data); +- + return 0; + } + +-/* sguil only uses log */ +-int OpSguil_Log(void *context, void *data) ++ ++int OpSguil_Log(void *context, void *ul_data) + { ++ + char timestamp[TIMEBUF_SIZE]; +- char syslogMessage[SYSLOG_BUF]; +- char eventInfo[SYSLOG_BUF]; +- //int MAX_INSERT_LEN = 1024; +- char insertColumns[MAX_QUERY_SIZE]; +- char insertValues[MAX_QUERY_SIZE]; +- char valuesTemp[MAX_QUERY_SIZE]; +- char ipInfo[38]; +- char portInfo[16]; +- char *esc_message; + Sid *sid = NULL; + ClassType *class_type; +- UnifiedLogRecord *record = (UnifiedLogRecord *)data; +- OpSguil_Data *op_data = (OpSguil_Data *)context; ++ UnifiedLogRecord *record = (UnifiedLogRecord *)ul_data; ++ OpSguil_Data *data = (OpSguil_Data *)context; + Packet p; ++ char buffer[STD_BUFFER]; ++ Tcl_DString list; + +- bzero(syslogMessage, SYSLOG_BUF); +- bzero(insertColumns, MAX_QUERY_SIZE); +- bzero(insertValues, MAX_QUERY_SIZE); +- +-#if 0 /* this is broken */ +- /* skip tagged packets, since the db does not have a mechanism to +- * deal with them properly +- */ +- if(record->log.event.event_reference) +- { +- LogMessage("Skipping tagged packet %i\n", record->log.event.event_reference); +- return 0; +- } +-#endif ++ bzero(buffer, STD_BUFFER); + ++ //LogMessage("Event id ==> %u\n", record->log.event.event_id); ++ //LogMessage("Ref time ==> %lu\n", record->log.event.ref_time.tv_sec); + +- RenderTimestamp(record->log.pkth.ts.tv_sec, timestamp, TIMEBUF_SIZE); +- //fprintf(stdout, "Timestamp: %lu\n", GetMilliseconds()); +- //fflush(stdout); ++ /* Sig info */ + sid = GetSid(record->log.event.sig_generator, record->log.event.sig_id); + if(sid == NULL) + sid = FakeSid(record->log.event.sig_generator, record->log.event.sig_id); ++ sid->rev = record->log.event.sig_rev; ++ + class_type = GetClassType(record->log.event.classification); ++ ++ /* Here we build our RT event to send to sguild. The event is built with a ++ ** proper tcl list format. ++ ** RT FORMAT: ++ ** ++ ** 0 1 2 3 4 5 6 7 ++ ** {RTEVENT} {0} {sid} {cid} {sensor name} {snort event_id} {snort event_ref} {snort ref_time} ++ ** ++ ** 8 9 10 11 12 13 14 ++ ** {sig_gen} {sig id} {rev} {message} {timestamp} {priority} {class_type} ++ ** ++ ** 15 16 17 18 19 20 21 ++ ** {sip (dec)} {sip (string)} {dip (dec)} {dip (string)} {ip proto} {ip ver} {ip hlen} ++ ** ++ ** 22 23 24 25 26 27 28 ++ ** {ip tos} {ip len} {ip id} {ip flags} {ip off} {ip ttl} {ip csum} ++ ** ++ ** 29 30 31 32 33 ++ ** {icmp type} {icmp code} {icmp csum} {icmp id} {icmp seq} ++ ** ++ ** 34 35 ++ ** {src port} {dst port} ++ ** ++ ** 36 37 38 39 40 41 42 43 ++ ** {tcp seq} {tcp ack} {tcp off} {tcp res} {tcp flags} {tcp win} {tcp csum} {tcp urp} ++ ** ++ ** 44 45 ++ ** {udp len} {udp csum} ++ ** ++ ** 46 ++ ** {data payload} ++ */ ++ ++ Tcl_DStringInit(&list); ++ ++ /* RTEVENT */ ++ Tcl_DStringAppendElement(&list, "RTEVENT"); ++ ++ /* Status - 0 */ ++ Tcl_DStringAppendElement(&list, "0"); ++ ++ /* Sensor ID (sid) */ ++ sprintf(buffer, "%u", data->sensor_id); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Event ID (cid) */ ++ sprintf(buffer, "%u", data->event_id); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Sensor Name */ ++ Tcl_DStringAppendElement(&list, data->sensor_name); ++ ++ /* Snort Event ID */ ++ sprintf(buffer, "%u", record->log.event.event_id); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Snort Event Ref */ ++ sprintf(buffer, "%u", record->log.event.event_reference); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Snort Event Ref Time */ ++ if(record->log.event.ref_time.tv_sec == 0) ++ { ++ Tcl_DStringAppendElement(&list, ""); ++ } ++ else ++ { ++ RenderTimestamp(record->log.event.ref_time.tv_sec, timestamp, TIMEBUF_SIZE); ++ Tcl_DStringAppendElement(&list, timestamp); ++ } ++ ++ /* Generator ID */ ++ sprintf(buffer, "%d", sid->gen); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Signature ID */ ++ sprintf(buffer, "%d", sid->sid); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Signature Revision */ ++ sprintf(buffer, "%d", sid->rev); ++ Tcl_DStringAppendElement(&list, buffer); ++ ++ /* Signature Msg */ ++ Tcl_DStringAppendElement(&list, sid->msg); ++ ++ /* Packet Timestamp */ ++ RenderTimestamp(record->log.pkth.ts.tv_sec, timestamp, TIMEBUF_SIZE); ++ Tcl_DStringAppendElement(&list, timestamp); ++ ++ /* Alert Priority */ ++ sprintf(buffer, "%u", record->log.event.priority); ++ Tcl_DStringAppendElement(&list, buffer); + +- //sgBeginTransaction(op_data); /* XXX: Error checking */ +- /* Build the event insert. */ +- snprintf(insertColumns, MAX_QUERY_SIZE, +- "INSERT INTO event (status, sid, cid, signature_id, signature_rev, signature, timestamp, priority, class"); +- +- esc_message = malloc(strlen(sid->msg)*2+1); +- mysql_real_escape_string(op_data->mysql, esc_message, sid->msg, strlen(sid->msg)); +- +- if(class_type == NULL) +- { +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- "VALUES ('0', '%u', '%u', '%d', '%d', '%s', '%s', '%u', 'unknown'", +- op_data->sensor_id, op_data->event_id, sid->sid, sid->rev, esc_message, timestamp, +- record->log.event.priority); +- snprintf(eventInfo, SYSLOG_BUF, "RTEvent |0|%u|unknown|%s|%s|%u|%u|%s", +- record->log.event.priority, +- pv.hostname, timestamp, op_data->sensor_id, op_data->event_id, +- sid->msg); ++ /* Alert Classification */ ++ if (class_type == NULL) ++ { ++ Tcl_DStringAppendElement(&list, "unknown"); + } + else + { +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- "VALUES ('0', '%u', '%u', '%d', '%d', '%s', '%s', '%u', '%s'", +- op_data->sensor_id, op_data->event_id, sid->sid, sid->rev, esc_message, timestamp, +- record->log.event.priority, class_type->type); +- snprintf(eventInfo, SYSLOG_BUF, "RTEvent |0|%u|%s|%s|%s|%u|%u|%s", +- record->log.event.priority, class_type->type, +- pv.hostname, timestamp, op_data->sensor_id, op_data->event_id, +- sid->msg); +- } +- +- free(esc_message); +- +- insertValues[0] = '\0'; +- strcat(insertValues, valuesTemp); +- +- syslogMessage[0] = '\0'; +- strcat(syslogMessage, eventInfo); +- /* decode the packet */ ++ Tcl_DStringAppendElement(&list, class_type->type); ++ } ++ ++ /* Pull decoded info from the packet */ + if(DecodePacket(&p, &record->log.pkth, record->pkt + 2) == 0) + { +- + if(p.iph) + { +- /* Insert ip header information */ +- //InsertIPData(op_data, &p); +- strcat(insertColumns, +- ",src_ip, dst_ip, ip_proto, ip_ver, ip_hlen, ip_tos, ip_len, ip_id, ip_flags, ip_off, ip_ttl, ip_csum"); +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- ",'%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u'", +- ntohl(p.iph->ip_src.s_addr), ntohl(p.iph->ip_dst.s_addr), p.iph->ip_proto, IP_VER(p.iph), +- IP_HLEN(p.iph), p.iph->ip_tos, ntohs(p.iph->ip_len), ntohs(p.iph->ip_id), +-#if defined(WORDS_BIGENDIAN) +- ((p.iph->ip_off & 0xE000) >> 13), +- htons(p.iph->ip_off & 0x1FFF), +-#else +- ((p.iph->ip_off & 0x00E0) >> 5), +- htons(p.iph->ip_off & 0xFF1F), +-#endif +- p.iph->ip_ttl, +- htons(p.iph->ip_csum) < MAX_QUERY_SIZE); +- +- strcat(insertValues, valuesTemp); +- ++ int i; + +- /* SYSLOG - Changed to SguilSendEvent*/ +- snprintf(ipInfo, 38, "|%u.%u.%u.%u|%u.%u.%u.%u|%u", +-#if defined(WORDS_BIGENDIAN) +- (p.iph->ip_src.s_addr & 0xff000000) >> 24, +- (p.iph->ip_src.s_addr & 0x00ff0000) >> 16, +- (p.iph->ip_src.s_addr & 0x0000ff00) >> 8, +- (p.iph->ip_src.s_addr & 0x000000ff), +- (p.iph->ip_dst.s_addr & 0xff000000) >> 24, +- (p.iph->ip_dst.s_addr & 0x00ff0000) >> 16, +- (p.iph->ip_dst.s_addr & 0x0000ff00) >> 8, +- (p.iph->ip_dst.s_addr & 0x000000ff), +-#else +- (p.iph->ip_src.s_addr & 0x000000ff), +- (p.iph->ip_src.s_addr & 0x0000ff00) >> 8, +- (p.iph->ip_src.s_addr & 0x00ff0000) >> 16, +- (p.iph->ip_src.s_addr & 0xff000000) >> 24, +- (p.iph->ip_dst.s_addr & 0x000000ff), +- (p.iph->ip_dst.s_addr & 0x0000ff00) >> 8, +- (p.iph->ip_dst.s_addr & 0x00ff0000) >> 16, +- (p.iph->ip_dst.s_addr & 0xff000000) >> 24, +-#endif +- p.iph->ip_proto); +- strcat(syslogMessage, ipInfo); ++ /* Add IP header */ ++ OpSguil_AppendIPHdrData(&list, &p); + +- /* store layer 4 data for non fragmented packets */ ++ /* Add icmp || udp || tcp data */ + if(!(p.pkt_flags & PKT_FRAG_FLAG)) + { ++ + switch(p.iph->ip_proto) + { + case IPPROTO_ICMP: +- snprintf(portInfo, 16, "|||"); +- if(!p.icmph) +- break; +- strcat(insertColumns, +- ", icmp_type, icmp_code)"); +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- ", '%u', '%u')", p.icmph->icmp_type, +- p.icmph->icmp_code); +- strcat(insertValues, valuesTemp); +- strcat(insertColumns, insertValues); +- sgInsert(op_data, insertColumns, NULL); +- sgInsertICMPData(op_data, &p); ++ OpSguil_AppendICMPData(&list, &p); + break; ++ + case IPPROTO_TCP: +- strcat(insertColumns, +- ", src_port, dst_port)"); +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- ", '%u', '%u')", p.sp, p.dp); +- strcat(insertValues, valuesTemp); +- strcat(insertColumns, insertValues); +- sgInsert(op_data, insertColumns, NULL); +- sgInsertTCPData(op_data, &p); +- snprintf(portInfo, 16, "|%u|%u|", +- p.sp, p.dp); ++ OpSguil_AppendTCPData(&list, &p); + break; ++ + case IPPROTO_UDP: +- strcat(insertColumns, +- ", src_port, dst_port)"); +- snprintf(valuesTemp, MAX_QUERY_SIZE, +- ", '%u', '%u')", p.sp, p.dp); +- strcat(insertValues, valuesTemp); +- strcat(insertColumns, insertValues); +- sgInsert(op_data, insertColumns, NULL); +- sgInsertUDPData(op_data, &p); +- snprintf(portInfo, 16, "|%u|%u|", +- p.sp, p.dp); ++ OpSguil_AppendUDPData(&list, &p); ++ break; ++ ++ default: ++ for(i = 0; i < 17; ++i) ++ { ++ Tcl_DStringAppendElement(&list, ""); ++ } + break; + } +- strcat(syslogMessage, portInfo); ++ + } + else + { +- strcat(syslogMessage, "|||"); ++ /* Null out TCP/UDP/ICMP fields */ ++ for(i = 0; i < 17; ++i) ++ { ++ Tcl_DStringAppendElement(&list, ""); ++ } + } +- +- +- /* Insert payload data */ +- sgInsertPayloadData(op_data, &p); + } + else + { +- strcat(syslogMessage, "||||||"); ++ ++ /* No IP Header. */ ++ int i; ++ for(i = 0; i < 31; ++i) ++ { ++ Tcl_DStringAppendElement(&list, ""); ++ } + } +- } + +- //sgEndTransaction(op_data); /* XXX: Error Checking */ +- ++op_data->event_id; +- /* Append the sig id and rev to the RT event */ +- snprintf(eventInfo, SYSLOG_BUF, "%u|%u|\n", sid->sid, sid->rev); +- strcat(syslogMessage, eventInfo); +- /* Write to the network socket */ +- SguilSendEvent(op_data, syslogMessage); +- return 0; +-} ++ /* Add payload data */ ++ OpSguil_AppendPayloadData(&list, &p); + +-int sgInsertUDPData(OpSguil_Data *op_data, Packet *p) +-{ +- if(!p->udph) +- return 0; +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "INSERT INTO udphdr(sid, cid, udp_len, udp_csum)" +- "VALUES ('%u', '%u', '%u', '%u')", +- op_data->sensor_id, op_data->event_id, +- ntohs(p->udph->uh_len), +- ntohs(p->udph->uh_chk)) < MAX_QUERY_SIZE) ++ } ++ else ++ { ++ /* ack! an event without a packet. Append 32 fillers */ ++ int i; ++ for(i = 0; i < 32; ++i) + { +- sgInsert(op_data, sql_buffer, NULL); /* XXX: Error Checking */ ++ Tcl_DStringAppendElement(&list, ""); + } +- return 0; +-} ++ } + +-int sgInsertTCPData(OpSguil_Data *op_data, Packet *p) +-{ +- if(!p->tcph) +- return 0; ++ /* Send msg to sensor_agent */ ++ if (OpSguil_RTEventMsg(data, Tcl_DStringValue(&list))) ++ FatalError("Unable to send RT Events to sensor agent.\n"); + +- /* insert data into the tcp header table */ +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "INSERT INTO tcphdr(sid, cid, tcp_seq, " +- "tcp_ack, tcp_off, tcp_res, tcp_flags, tcp_win, tcp_csum, " +- "tcp_urp) VALUES('%u', '%u', '%u', '%u', '%u', " +- "'%u', '%u', '%u', '%u', '%u')", +- op_data->sensor_id, op_data->event_id, +- ntohl(p->tcph->th_seq), ntohl(p->tcph->th_ack), +- TCP_OFFSET(p->tcph), TCP_X2(p->tcph), p->tcph->th_flags, +- ntohs(p->tcph->th_win), ntohs(p->tcph->th_sum), +- ntohs(p->tcph->th_urp)) < MAX_QUERY_SIZE) +- { +- sgInsert(op_data, sql_buffer, NULL); /* XXX: Error checking */ +- } +- /* XXX: TCP Options not handled */ +- return 0; +-} ++ /* Free! */ ++ Tcl_DStringFree(&list); ++ ++ /* bump the event id */ ++ ++data->event_id; + +-int sgInsertICMPData(OpSguil_Data *op_data, Packet *p) +-{ +- if(!p->icmph) +- return 0; +- if(p->icmph->icmp_type == 0 || p->icmph->icmp_type == 8 || +- p->icmph->icmp_type == 13 || p->icmph->icmp_type == 14 || +- p->icmph->icmp_type == 15 || p->icmph->icmp_type == 16) +- { +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "INSERT INTO icmphdr(sid, cid, " +- "icmp_csum, icmp_id, icmp_seq) " +- "VALUES('%u', '%u', '%u', '%u', '%u')", +- op_data->sensor_id, op_data->event_id, +- ntohs(p->icmph->icmp_csum), +- htons(p->icmph->icmp_hun.ih_idseq.icd_id), +- htons(p->icmph->icmp_hun.ih_idseq.icd_seq)) +- < MAX_QUERY_SIZE) +- { +- sgInsert(op_data, sql_buffer, NULL); /* XXX: Error checking */ +- } +- } +- else +- { +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "INSERT INTO icmphdr(sid, cid, " +- "icmp_csum) VALUES('%u', '%u', '%u')", +- op_data->sensor_id, op_data->event_id, +- ntohs(p->icmph->icmp_csum)) +- < MAX_QUERY_SIZE) +- { +- sgInsert(op_data, sql_buffer, NULL); /* XXX: Error Checking */ +- } +- } + return 0; + } + +-int sgInsertPayloadData(OpSguil_Data *op_data, Packet *p) ++int OpSguil_RTEventMsg(OpSguil_Data *data, char *msg) + { +- char *hex_payload; +- if(p->dsize) +- { +- hex_payload = fasthex(p->data, p->dsize); +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "INSERT INTO data(sid, cid, data_payload) " +- "VALUES('%u', '%u', '%s')", op_data->sensor_id, +- op_data->event_id, hex_payload) < MAX_QUERY_SIZE) +- { +- sgInsert(op_data, sql_buffer, NULL); /* XXX: Error Checking */ +- } +- free(hex_payload); +- } +- return 0; +-} + ++ char tmpRecvMsg[MAX_MSG_LEN]; + +-/* Attempts to retrieve the sensor id +- */ +-unsigned int SguilGetSensorId(OpSguil_Data *op_data) +-{ +- unsigned int sensor_id = 0; +- /* XXX: This should be moved to global setup */ +- if(pv.hostname == NULL) +- { +- /* query the hostname */ +- /* the DB schema allows for a hostname of up to 2^16-1 characters, i am limiting +- * this to 255 (+1 for the NULL) +- */ +- pv.hostname = (char *)malloc(256); +- if(gethostname(pv.hostname, 256)) +- { +- FatalError("Error querying hostname: %s\n", strerror(errno)); +- } +- } ++ /* Send Msg */ ++ OpSguil_SendAgentMsg(data, msg); + +- /* XXX: need to escape strings */ +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "SELECT sid FROM sensor WHERE hostname='%s'" +- , pv.hostname) < MAX_QUERY_SIZE) ++ /* Get confirmation */ ++ memset(tmpRecvMsg,0x0,MAX_MSG_LEN); ++ if(OpSguil_RecvAgentMsg(data, tmpRecvMsg) == 1 ) + { +- if(sgSelectAsUInt(op_data, sql_buffer, &sensor_id) == -1) +- { +- FatalError("Database Error\n"); +- } +- if(sensor_id == 0) +- { + +- /* insert sensor information */ ++ if(pv.verbose) ++ LogMessage("Retrying\n"); ++ ++ OpSguil_RTEventMsg(data, msg); + +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, "INSERT INTO sensor (hostname) " +- "VALUES ('%s')", pv.hostname) < MAX_QUERY_SIZE) +- { +- sgInsert(op_data, sql_buffer, &sensor_id); +- /* XXX: Error checking */ +- } +- else +- { +- FatalError("Error building SQL Query\n"); +- } +- } +- if(pv.verbose >= 2) +- LogMessage("sensor_id == %u\n", sensor_id); + } + else + { +- FatalError("Error building SQL Query\n"); +- } +- return sensor_id; +-} + +-/* Retrieves the next acid_cid to use for inserting into the database for this +- * sensor +- */ +-unsigned int SguilGetNextCid(OpSguil_Data *data) +-{ +- unsigned int cid = 0; +- if(snprintf(sql_buffer, MAX_QUERY_SIZE, +- "SELECT max(cid) FROM event WHERE sid='%u'", data->sensor_id) +- < MAX_QUERY_SIZE) +- { +- if(sgSelectAsUInt(data, sql_buffer, &cid) == -1) ++ char **toks; ++ int num_toks; ++ ++ if(pv.verbose) ++ LogMessage("Received: %s", tmpRecvMsg); ++ ++ /* Parse the response */ ++ toks = mSplit(tmpRecvMsg, " ", 2, &num_toks, 0); ++ if(strcasecmp("Confirm", toks[0]) != 0 || atoi(toks[1]) != data->event_id ) + { +- FatalError("Database Error\n"); ++ ++ FatalError("Expected Confirm %u and got: %s\n", data->event_id, tmpRecvMsg); ++ + } +-#ifdef DEBUG +- LogMessage("cid == %u\n", cid); fflush(stdout); +-#endif ++ ++ FreeToks(toks, num_toks); ++ + } +- else +- { +- FatalError("Database Error\n"); +- } +- return ++cid; ++ ++ return 0; ++ + } + + OpSguil_Data *OpSguil_ParseArgs(char *args) + { +- OpSguil_Data *op_data; + ++ OpSguil_Data *op_data; ++ + op_data = (OpSguil_Data *)SafeAlloc(sizeof(OpSguil_Data)); +- +- op_data->options = 0; +- ++ + if(args != NULL) + { + char **toks; +@@ -685,77 +484,38 @@ + while(isspace((int)*index)) + ++index; + stoks = mSplit(index, " ", 2, &num_stoks, 0); +- if(strcasecmp("database", stoks[0]) == 0) +- { +- if(num_stoks > 1 && op_data->database == NULL) +- op_data->database = strdup(stoks[1]); +- else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, +- file_line, index); +- } +- else if(strcasecmp("server", stoks[0]) == 0) +- { +- if(num_stoks > 1 && op_data->server == NULL) +- op_data->server = strdup(stoks[1]); +- else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, +- file_line, index); +- } +- else if(strcasecmp("user", stoks[0]) == 0) ++ if(strcasecmp("agent_port", stoks[0]) == 0) + { +- if(num_stoks > 1 && op_data->user == NULL) +- op_data->user = strdup(stoks[1]); ++ if(num_stoks > 1) ++ op_data->agent_port = atoi(stoks[1]); + else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, ++ LogMessage("Argument Error in %s(%i): %s\n", file_name, + file_line, index); + } +- else if(strcasecmp("password", stoks[0]) == 0) ++ else if(strcasecmp("tag_path", stoks[0]) == 0) + { +- if(num_stoks > 1 && op_data->password == NULL) +- op_data->password = strdup(stoks[1]); ++ if(num_stoks > 1 && op_data->tag_path == NULL) ++ op_data->tag_path = strdup(stoks[1]); + else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, ++ LogMessage("Argument Error in %s(%i): %s\n", file_name, + file_line, index); + } +- else if(strcasecmp("sensor_id", stoks[0]) == 0) ++ else if(strcasecmp("sensor_name", stoks[0]) == 0) + { +- if(num_stoks > 1 && op_data->sensor_id == 0) +- op_data->sensor_id = atoi(stoks[1]); ++ if(num_stoks > 1 && op_data->sensor_name == NULL) ++ op_data->sensor_name = strdup(stoks[1]); + else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, ++ LogMessage("Argument Error in %s(%i): %s\n", file_name, + file_line, index); + } +- else if(strcasecmp("sguild_host", stoks[0]) == 0) +- { +- if(num_stoks > 1 && op_data->sguild_host == 0) +- op_data->sguild_host = strdup(stoks[1]); +- else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, +- file_line, index); +- } +- else if(strcasecmp("nospin", stoks[0]) == 0) +- { +- op_data->nospin = 1; +- } +- else if(strcasecmp("sguild_port", stoks[0]) == 0) ++ else if(strcasecmp("passwd", stoks[0]) == 0) + { +- if(num_stoks > 1 && op_data->sguild_port == 0) +- op_data->sguild_port = atoi(stoks[1]); +- else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, +- file_line, index); +- } +- +-#ifdef ENABLE_MYSQL +- else if(strcasecmp("mysql", stoks[0]) == 0) +- { +- if(op_data->flavor == 0) +- op_data->flavor = FLAVOR_MYSQL; ++ if(num_stoks > 1 && op_data->passwd == NULL) ++ op_data->passwd = strdup(stoks[1]); + else +- LogMessage("Argument Error in %s(%i): %s\n", file_name, ++ LogMessage("Argument Error in %s(%i): %s\n", file_name, + file_line, index); + } +-#endif /* ENABLE_MYSQL */ + else + { + fprintf(stderr, "WARNING %s (%d) => Unrecognized argument for " +@@ -765,378 +525,544 @@ + } + /* free your mSplit tokens */ + FreeToks(toks, num_toks); +- } +- if(op_data->flavor == 0) +- FatalError("You must specify a database flavor\n"); + +- if (op_data->sguild_host == NULL) +- { +- FatalError("You must specify a sguild host.\n"); + } + +- if (!op_data->sguild_port) ++ if (op_data->agent_port == 0) + { +- FatalError("You must specify a sguild port.\n"); ++ op_data->agent_port = 7735; + } ++ + return op_data; +-} + ++} + +-int sgDbConnect(OpSguil_Data *op_data) ++int OpSguil_AppendIPHdrData(Tcl_DString *list, Packet *p) + { +- switch(op_data->flavor) +- { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlConnect(op_data); ++ char buffer[STD_BUFFER]; ++ ++ bzero(buffer, STD_BUFFER); ++ ++ sprintf(buffer, "%u", ntohl(p->iph->ip_src.s_addr)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u.%u.%u.%u", ++#if defined(WORDS_BIGENDIAN) ++ (p->iph->ip_src.s_addr & 0xff000000) >> 24, ++ (p->iph->ip_src.s_addr & 0x00ff0000) >> 16, ++ (p->iph->ip_src.s_addr & 0x0000ff00) >> 8, ++ (p->iph->ip_src.s_addr & 0x000000ff)); ++#else ++ (p->iph->ip_src.s_addr & 0x000000ff), ++ (p->iph->ip_src.s_addr & 0x0000ff00) >> 8, ++ (p->iph->ip_src.s_addr & 0x00ff0000) >> 16, ++ (p->iph->ip_src.s_addr & 0xff000000) >> 24); + #endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; +- } +-// return 1; ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", ntohl(p->iph->ip_dst.s_addr)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u.%u.%u.%u", ++#if defined(WORDS_BIGENDIAN) ++ (p->iph->ip_dst.s_addr & 0xff000000) >> 24, ++ (p->iph->ip_dst.s_addr & 0x00ff0000) >> 16, ++ (p->iph->ip_dst.s_addr & 0x0000ff00) >> 8, ++ (p->iph->ip_dst.s_addr & 0x000000ff)); ++#else ++ (p->iph->ip_dst.s_addr & 0x000000ff), ++ (p->iph->ip_dst.s_addr & 0x0000ff00) >> 8, ++ (p->iph->ip_dst.s_addr & 0x00ff0000) >> 16, ++ (p->iph->ip_dst.s_addr & 0xff000000) >> 24); ++#endif ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", p->iph->ip_proto); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", IP_VER(p->iph)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", IP_HLEN(p->iph)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", p->iph->ip_tos); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", ntohs(p->iph->ip_len)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", ntohs(p->iph->ip_id)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++#if defined(WORDS_BIGENDIAN) ++ ++ sprintf(buffer, "%u", ((p->iph->ip_off & 0xE000) >> 13)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", htons(p->iph->ip_off & 0x1FFF)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++#else ++ ++ sprintf(buffer, "%u", ((p->iph->ip_off & 0x00E0) >> 5)); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", htons(p->iph->ip_off & 0xFF1F)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++#endif ++ ++ sprintf(buffer, "%u", p->iph->ip_ttl); ++ Tcl_DStringAppendElement(list, buffer); ++ sprintf(buffer, "%u", htons(p->iph->ip_csum)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ return 0; + } + +-int sgDbClose(OpSguil_Data *op_data) ++int OpSguil_AppendICMPData(Tcl_DString *list, Packet *p) + { +- switch(op_data->flavor) ++ ++ int i; ++ char buffer[STD_BUFFER]; ++ ++ bzero(buffer, STD_BUFFER); ++ ++ if(!p->icmph) + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlClose(op_data->mysql); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; +- } +-} + ++ /* Null out ICMP fields */ ++ for(i=0; i < 5; i++) ++ Tcl_DStringAppendElement(list, ""); + +-int sgSelectAsUInt(OpSguil_Data *op_data, char *sql, unsigned int *result) +-{ +- switch(op_data->flavor) ++ } ++ else + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlSelectAsUInt(op_data->mysql, sql, result); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; ++ ++ /* ICMP type */ ++ sprintf(buffer, "%u", p->icmph->icmp_type); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ /* ICMP code */ ++ sprintf(buffer, "%u", p->icmph->icmp_code); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ /* ICMP CSUM */ ++ sprintf(buffer, "%u", ntohs(p->icmph->icmp_csum)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ /* Append other ICMP data if we have it */ ++ if(p->icmph->icmp_type == ICMP_ECHOREPLY || ++ p->icmph->icmp_type == ICMP_ECHO || ++ p->icmph->icmp_type == ICMP_TIMESTAMP || ++ p->icmph->icmp_type == ICMP_TIMESTAMPREPLY || ++ p->icmph->icmp_type == ICMP_INFO_REQUEST || ++ p->icmph->icmp_type == ICMP_INFO_REPLY) ++ { ++ ++ /* ICMP ID */ ++ sprintf(buffer, "%u", htons(p->icmph->icmp_hun.ih_idseq.icd_id)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ /* ICMP Seq */ ++ sprintf(buffer, "%u", htons(p->icmph->icmp_hun.ih_idseq.icd_seq)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ } ++ else ++ { ++ ++ /* Add two empty elements */ ++ for(i=0; i < 2; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ } ++ + } ++ ++ /* blank out 12 elements */ ++ for(i = 0; i < 12; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ return 0; ++ + } + +-int sgInsert(OpSguil_Data *op_data, char *sql, unsigned int *row_id) ++int OpSguil_AppendTCPData(Tcl_DString *list, Packet *p) + { +- switch(op_data->flavor) ++ ++ /* ++ ** 33 34 35 36 37 38 39 40 ++ ** {tcp seq} {tcp ack} {tcp off} {tcp res} {tcp flags} {tcp win} {tcp csum} {tcp urp} ++ ** ++ */ ++ ++ int i; ++ char buffer[STD_BUFFER]; ++ ++ bzero(buffer, STD_BUFFER); ++ ++ /* empty elements for icmp data */ ++ for(i=0; i < 5; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ if(!p->tcph) + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlInsert(op_data->mysql, sql, row_id); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; +- } +-} + +-int sgBeginTransaction(OpSguil_Data *op_data) +-{ +- switch(op_data->flavor) ++ /* Null out TCP fields */ ++ for(i=0; i < 10; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ } ++ else + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlInsert(op_data->mysql, "BEGIN", NULL); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; ++ ++ sprintf(buffer, "%u", p->sp); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", p->dp); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohl(p->tcph->th_seq)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohl(p->tcph->th_ack)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", TCP_OFFSET(p->tcph)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", TCP_X2(p->tcph)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", p->tcph->th_flags); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohs(p->tcph->th_win)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohs(p->tcph->th_sum)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohs(p->tcph->th_urp)); ++ Tcl_DStringAppendElement(list, buffer); ++ + } ++ ++ /* empty elements for UDP data */ ++ for(i=0; i < 2; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ return 0; ++ + } + +-int sgEndTransaction(OpSguil_Data *op_data) ++int OpSguil_AppendUDPData(Tcl_DString *list, Packet *p) + { +- switch(op_data->flavor) ++ ++ int i; ++ char buffer[STD_BUFFER]; ++ ++ bzero(buffer, STD_BUFFER); ++ ++ /* empty elements for icmp data */ ++ for(i=0; i < 5; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ if(!p->udph) + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlInsert(op_data->mysql, "COMMIT", NULL); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; ++ ++ /* Null out port info */ ++ for(i=0; i < 2; i++) ++ Tcl_DStringAppendElement(list, ""); ++ + } +-} +- +-int sgAbortTransaction(OpSguil_Data *op_data) +-{ +- switch(op_data->flavor) ++ else + { +-#ifdef ENABLE_MYSQL +- case FLAVOR_MYSQL: +- return sgMysqlInsert(op_data->mysql, "ROLLBACK", NULL); +-#endif +- default: +- FatalError("Database flavor not supported\n"); +- return 1; ++ ++ /* source and dst port */ ++ sprintf(buffer, "%u", p->sp); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", p->dp); ++ Tcl_DStringAppendElement(list, buffer); ++ + } +-} + ++ /* empty elements for tcp data */ ++ for(i=0; i < 8; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ if(!p->udph) ++ { ++ ++ /* Null out UDP info */ ++ for(i=0; i < 2; i++) ++ Tcl_DStringAppendElement(list, ""); ++ ++ } ++ else ++ { ++ ++ sprintf(buffer, "%u", ntohs(p->udph->uh_len)); ++ Tcl_DStringAppendElement(list, buffer); ++ ++ sprintf(buffer, "%u", ntohs(p->udph->uh_chk)); ++ Tcl_DStringAppendElement(list, buffer); + +-#ifdef ENABLE_MYSQL +-int sgMysqlConnect(OpSguil_Data *op_data) +-{ +- op_data->mysql = mysql_init(NULL); +- if(!mysql_real_connect(op_data->mysql, op_data->server, op_data->user, +- op_data->password, op_data->database, 0, NULL, 0)) +- { +- FatalError("Failed to connect to database %s:%s@%s/%s: %s\n", +- op_data->user, op_data->password, op_data->server, +- op_data->database, mysql_error(op_data->mysql)); + } ++ + return 0; ++ + } + +-int sgMysqlClose(MYSQL *mysql) ++int OpSguil_AppendPayloadData(Tcl_DString *list, Packet *p) + { +- mysql_close(mysql); ++ ++ char *hex_payload; ++ ++ if(p->dsize) ++ { ++ hex_payload = fasthex(p->data, p->dsize); ++ Tcl_DStringAppendElement(list, hex_payload); ++ free(hex_payload); ++ } else { ++ Tcl_DStringAppendElement(list, ""); ++ } ++ + return 0; ++ + } + +-int sgMysqlExecuteQuery(MYSQL *mysql, char *sql) ++ ++int OpSguil_SensorAgentConnect(OpSguil_Data *data) + { +- int mysqlErrno; +- int result; +- while((result = mysql_query(mysql, sql) != 0)) ++ ++ int sockfd; ++ struct sockaddr_in my_addr; ++ ++ while(1) + { +- mysqlErrno = mysql_errno(mysql); +- if(mysqlErrno < CR_MIN_ERROR) ++ ++ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { +- if(pv.verbose) +- LogMessage("MySQL ERROR(%i): %s. Aborting Query\n", +- mysql_errno(mysql), mysql_error(mysql)); +- return result; ++ FatalError("Cannot open a local socket.\n"); ++ return 1; + } +- if((mysqlErrno == CR_SERVER_LOST) +- || (mysqlErrno == CR_SERVER_GONE_ERROR)) ++ ++ my_addr.sin_family = AF_INET; ++ my_addr.sin_port = htons(data->agent_port); ++ my_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); ++ memset(&(my_addr.sin_zero), '\0', 8); ++ ++ ++ if (connect(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) < 0) + { +- LogMessage("Lost connection to MySQL server. Reconnecting\n"); +- while(mysql_ping(mysql) != 0) ++ LogMessage("Cannot connect to localhost on TCP port %u.\n", ++ data->agent_port); ++ close(sockfd); ++ LogMessage("Waiting 15 secs to try again.\n"); ++ if (BarnyardSleep(15)) + { +- if(BarnyardSleep(15)) +- return result; ++ LogMessage("Received Kill Signal..."); ++ CleanExit(0); + } +- LogMessage("Reconnected to MySQL server.\n"); ++ + } + else + { +- /* XXX we could spin here, but we do not */ +- LogMessage("MySQL Error(%i): %s\n", mysqlErrno, mysql_error(mysql)); ++ ++ data->agent_sock = sockfd; ++ LogMessage("Connected to localhost on %u.\n", ++ data->agent_port); ++ return 0; ++ + } ++ + } +- return result; +-} + ++} + +-int sgMysqlSelectAsUInt(MYSQL *mysql, char *sql, unsigned int *result) ++/* ++int OpSguil_SensorAgentAuth(OpSguil_Data *data) + { +- int rval = 0; +- MYSQL_RES *mysql_res; +- MYSQL_ROW tuple; +- +- if(sgMysqlExecuteQuery(mysql, sql) != 0) +- { +- /* XXX: should really just return up the chain */ +- FatalError("Error (%s) executing query: %s\n", mysql_error(mysql), sql); +- return -1; +- } + +- mysql_res = mysql_store_result(mysql); +- if((tuple = mysql_fetch_row(mysql_res))) +- { +- if(tuple[0] == NULL) +- *result = 0; +- else +- *result = atoi(tuple[0]); +- rval = 1; +- } +- mysql_free_result(mysql_res); +- return rval; ++ Tcl_DString auth_cmd; ++ ++ Tcl_DStringInit(&auth_cmd); ++ Tcl_DStringAppendElement(auth_cmd, "AUTH"); ++ Tcl_DStringAppendElement(auth_cmd, data->passwd); ++ ++ + } ++*/ + +-int sgMysqlInsert(MYSQL *mysql, char *sql, unsigned int *row_id) ++/* Request sensor ID (sid) and next cid from sensor_agent */ ++int OpSguil_SensorAgentInit(OpSguil_Data *data) + { +- if(sgMysqlExecuteQuery(mysql, sql) != 0) ++ ++ char tmpSendMsg[MAX_MSG_LEN]; ++ char tmpRecvMsg[MAX_MSG_LEN]; ++ ++ /* Send our Request */ ++ snprintf(tmpSendMsg, MAX_MSG_LEN, "SidCidRequest %s", data->sensor_name); ++ OpSguil_SendAgentMsg(data, tmpSendMsg); ++ ++ /* Get the Results */ ++ memset(tmpRecvMsg,0x0,MAX_MSG_LEN); ++ if(OpSguil_RecvAgentMsg(data, tmpRecvMsg) == 1 ) + { +- /* XXX: should really just return up the chain */ +- FatalError("Error (%s) executing query: %s\n", mysql_error(mysql), sql); +- return -1; ++ ++ OpSguil_SensorAgentInit(data); ++ + } ++ else ++ { + +- if(row_id != NULL) +- *row_id = mysql_insert_id(mysql); +- return 0; +-} +-#endif ++ char **toks; ++ int num_toks; + +-/* SguildConnect() opens a network socket to sguild for sending +- * RT event messages. Bammkkkk +-*/ +-int SguildConnect(OpSguil_Data *op_data) +-{ +- int sockfd; +- struct hostent *he; +- struct sockaddr_in server_addr; ++ if(pv.verbose) ++ LogMessage("Received: %s", tmpRecvMsg); + +- if ((he=gethostbyname(op_data->sguild_host)) == NULL) ++ /* Parse the response */ ++ toks = mSplit(tmpRecvMsg, " ", 3, &num_toks, 0); ++ if(strcasecmp("SidCidResponse", toks[0]) == 0) + { +- FatalError("Cannot resolve hostname: %s\n", op_data->sguild_host); +- return 1; ++ ++ data->sensor_id = atoi(toks[1]); ++ data->event_id = atoi(toks[2]); ++ + } +- +- if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) ++ else + { +- +- FatalError("Cannot open a local socket.\n"); +- return 1; +- ++ ++ FatalError("Expected SidCidResponse and got: %s\n", tmpRecvMsg); ++ + } + +- server_addr.sin_family = AF_INET; +- server_addr.sin_port = htons(op_data->sguild_port); +- server_addr.sin_addr = *((struct in_addr *)he->h_addr); +- memset(&(server_addr.sin_zero), '\0', 8); ++ FreeToks(toks, num_toks); + +- if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0) +- { +- +- LogMessage("Cannot connect to %s on TCP port %u.\n", +- op_data->sguild_host, op_data->sguild_port); +- close(sockfd); +- return 1; ++ if(pv.verbose) ++ LogMessage("Sensor ID: %u\nLast cid: %u\n", data->sensor_id, data->event_id); ++ ++ /* Use the next event_id */ ++ ++data->event_id; ++ ++ } ++ ++ return 0; ++ ++} ++ ++int OpSguil_SendAgentMsg(OpSguil_Data *data, char *msg) ++{ ++ ++ int schars; ++ size_t len; ++ char *tmpMsg; ++ ++ len = strlen(msg)+2; + +- } ++ tmpMsg = SafeAlloc(len); + +- op_data->sguild_sock = sockfd; +- return 0; ++ snprintf(tmpMsg, len, "%s\n", msg); ++ ++ if((schars = send(data->agent_sock, tmpMsg, sizeof(char)*strlen(tmpMsg), 0)) < 0) ++ { ++ ++ if(pv.verbose) ++ LogMessage("Lost connection to sensor_agent.\n"); ++ ++ /* Resend our msg */ ++ OpSguil_SendAgentMsg(data, msg); ++ ++ } ++ ++ if(pv.verbose) ++ LogMessage("Sent: %s", tmpMsg); ++ ++ free(tmpMsg); ++ ++ return 0; + + } ++ + /* I love google. http://pont.net/socket/prog/tcpServer.c */ +-int read_line(int newSd, char *line_to_return) { +- ++int OpSguil_RecvAgentMsg(OpSguil_Data *data, char *line_to_return) { ++ + static int rcv_ptr=0; + static char rcv_msg[MAX_MSG_LEN]; + static int n; ++ struct timeval tv; ++ fd_set read_fds; + int offset; +- ++ + offset=0; ++ /* wait 15 secs for our response */ ++ tv.tv_sec = 15; ++ tv.tv_usec = 0; ++ ++ FD_ZERO(&read_fds); ++ FD_SET(data->agent_sock, &read_fds); + + while(1) { +- if(rcv_ptr==0) { + +- memset(rcv_msg,0x0,MAX_MSG_LEN); +- n = recv(newSd, rcv_msg, MAX_MSG_LEN, 0); +- if (n<0) { +- LogMessage("ERROR: Unable to read data.\n"); +- return 1; +- } else if (n==0) { +- LogMessage("ERROR: Connecton closed by client\n"); +- close(newSd); +- return 1; +- } ++ /* Wait for response from sguild */ ++ select(data->agent_sock+1, &read_fds, NULL, NULL, &tv); ++ ++ if (!(FD_ISSET(data->agent_sock, &read_fds))) ++ { ++ /* timed out */ ++ if(pv.verbose) ++ LogMessage("Timed out waiting for response.\n"); ++ ++ return 1; + } ++ else ++ { ++ if(rcv_ptr==0) { ++ ++ memset(rcv_msg,0x0,MAX_MSG_LEN); ++ n = recv(data->agent_sock, rcv_msg, MAX_MSG_LEN, 0); ++ if (n<0) { ++ LogMessage("ERROR: Unable to read data.\n"); ++ /* Reconnect to sensor_agent */ ++ OpSguil_SensorAgentConnect(data); ++ } else if (n==0) { ++ LogMessage("ERROR: Connecton closed by client\n"); ++ close(data->agent_sock); ++ /* Reconnect to sensor_agent */ ++ OpSguil_SensorAgentConnect(data); ++ } ++ } ++ ++ /* if new data read on socket */ ++ /* OR */ ++ /* if another line is still in buffer */ ++ ++ /* copy line into 'line_to_return' */ ++ while(*(rcv_msg+rcv_ptr)!=0x0A && rcv_ptr return line */ ++ if(rcv_ptr==n-1) { ++ /* set last byte to END_LINE */ ++ *(line_to_return+offset)=0x0A; ++ rcv_ptr=0; ++ return ++offset; ++ } ++ ++ /* end of line but still some data in buffer => return line */ ++ if(rcv_ptr return line */ +- if(rcv_ptr==n-1) { +- /* set last byte to END_LINE */ +- *(line_to_return+offset)=0x0A; +- rcv_ptr=0; +- return ++offset; +- } +- +- /* end of line but still some data in buffer => return line */ +- if(rcv_ptr */ ++ /* wait for more data to arrive on socket */ ++ if(rcv_ptr == n) { ++ rcv_ptr = 0; ++ } ++ + } + +- /* end of buffer but line is not ended => */ +- /* wait for more data to arrive on socket */ +- if(rcv_ptr == n) { +- rcv_ptr = 0; +- } +- + } +-} + +-/* SguilSendEvent() sends the event via the open network socket. +- * Bammkkkk +-*/ +-int SguilSendEvent(OpSguil_Data *op_data, char *eventMsg) +-{ +- +- int schars; +- char line[100]; +- +- +- if((schars = send(op_data->sguild_sock, eventMsg, strlen(eventMsg), 0)) < 0) +- { +- LogMessage("ERROR! Couldn't send msg.\n"); +- +- /* ReConnect to sguild */ +- while(SguildConnect(op_data) == 1) +- { +- if(op_data->nospin) return 0; +- LogMessage("ERROR: Couldn't reconnect. Will try again in 15 secs.\n"); +- if (BarnyardSleep(15)) break; +- } +- LogMessage("Connected to %s.\n", op_data->sguild_host); +- SguilSendEvent(op_data, eventMsg); +- +- } else { +- +- //LogMessage("Msg sent: %s", eventMsg); +- //LogMessage("Chars sent: %i\n", schars); +- +- memset(line, 0x0, 100); +- if(read_line(op_data->sguild_sock, line) == 1) +- { +- +- if (op_data->nospin == 0) +- { +- +- +- LogMessage("ERROR! Didn't receive confirmation. Trying to reconnect.\n"); +- +- /* ReConnect to sguild */ +- while(SguildConnect(op_data) == 1) +- { +- LogMessage("ERROR: Couldn't reconnect. Will try again in 15 secs.\n"); +- if (BarnyardSleep(15)) break; +- } +- +- LogMessage("Connected to %s.\n", op_data->sguild_host); +- SguilSendEvent(op_data, eventMsg); +- +- } +- +- } +- } +- return 0; +- + } + +-#endif diff --git a/security/barnyard-sguil6/files/patch-op_plugbase.c b/security/barnyard-sguil6/files/patch-op_plugbase.c new file mode 100644 index 000000000000..5ea119214df1 --- /dev/null +++ b/security/barnyard-sguil6/files/patch-op_plugbase.c @@ -0,0 +1,20 @@ +--- src/output-plugins/op_plugbase.c.orig Sun Mar 28 18:14:19 2004 ++++ src/output-plugins/op_plugbase.c Sun Jan 15 22:33:35 2006 +@@ -27,7 +27,7 @@ + #if defined(ENABLE_MYSQL) || defined(ENABLE_POSTGRES) + #include "op_acid_db.h" + #endif +-#ifdef ENABLE_MYSQL ++#ifdef ENABLE_TCL + #include "op_sguil.h" + #endif + #include "op_alert_csv.h" +@@ -47,7 +47,7 @@ + #if defined(ENABLE_MYSQL) || defined(ENABLE_POSTGRES) + OpAcidDb_Init(); + #endif +-#ifdef ENABLE_MYSQL ++#ifdef ENABLE_TCL + OpSguil_Init(); + #endif + OpAlertCSV_Init(); diff --git a/security/barnyard-sguil6/files/patch-op_sguil.h b/security/barnyard-sguil6/files/patch-op_sguil.h new file mode 100644 index 000000000000..de89409bf74d --- /dev/null +++ b/security/barnyard-sguil6/files/patch-op_sguil.h @@ -0,0 +1,26 @@ +--- src/output-plugins/op_sguil.h.orig Mon Mar 15 22:18:20 2004 ++++ src/output-plugins/op_sguil.h Sun Jan 15 22:32:07 2006 +@@ -1,8 +1,9 @@ +-/* $Id: op_sguil.h,v 1.2 2004/03/16 04:18:20 andrewbaker Exp $ */ ++/* $Id: op_sguil.h,v 1.2 2005/03/03 21:07:44 bamm Exp $ */ ++ + /* +-** Copyright (C) 2001 Andrew R. Baker ++** Copyright (C) 2002-2004 Robert (Bamm) Visscher + ** +-** This program is distributed under the terms of version 1.0 of the ++** This program is distributed under the terms of version 1.0 of the + ** Q Public License. See LICENSE.QPL for further details. + ** + ** This program is distributed in the hope that it will be useful, +@@ -11,10 +12,4 @@ + ** + */ + +-#ifndef __OP_SGUIL_H__ +-#define __OP_SGUIL_H__ +- + void OpSguil_Init(); +- +-#endif /* __OP_SGUIL_H__ */ +-