Skip to content

Instantly share code, notes, and snippets.

@sethhall
Created September 15, 2010 20:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sethhall/581458 to your computer and use it in GitHub Desktop.
Save sethhall/581458 to your computer and use it in GitHub Desktop.
diff --git a/configure.in b/configure.in
index c820a9a..d754ed9 100644
--- a/configure.in
+++ b/configure.in
@@ -928,6 +928,43 @@ if test "x$enable_aruba" = "xyes"; then
CPPFLAGS="$CPPFLAGS -DARUBA"
fi
+AC_ARG_ENABLE(bro,
+[ --enable-bro Enable Bro output plugin],
+ enable_bro="$enableval", enable_bro="no")
+AC_ARG_WITH(broccoli,
+[ --with-broccoli=DIR Prefix where libbroccoli is installed
+ for Bro output plugin support (optional)],
+ [ with_broccoli="$withval" ],
+ [ with_broccoli="no" ])
+if test "x$enable_bro" = "xyes"; then
+ if test -d $withval; then
+ broccoli_directory="$withval $default_directory";
+ else
+ broccoli_directory="$default_directory /usr/local/bro";
+ fi
+
+ AC_MSG_CHECKING(for broccoli)
+
+ for i in $broccoli_directory; do
+ if test -x "$i/bin/broccoli-config"; then
+ BROCCOLI_DIR="$i"
+ fi
+ done
+
+ if test -z "$BROCCOLI_DIR"; then
+ tmp=""
+ for i in $broccoli_directory; do
+ tmp="$tmp $i/include"
+ done
+ FAIL_MESSAGE("Broccoli header file (broccoli.h)", $tmp)
+ fi
+
+ AC_MSG_RESULT(yes)
+ LDFLAGS="${LDFLAGS} `${BROCCOLI_DIR}/bin/broccoli-config --libs`"
+ CPPFLAGS="${CPPFLAGS} `${BROCCOLI_DIR}/bin/broccoli-config --cflags`"
+ LIBS="${LIBS} -lbroccoli"
+fi
+
# let's make some fixes..
CFLAGS=`echo $CFLAGS | sed -e 's/-I\/usr\/include //g'`
diff --git a/etc/barnyard2.conf b/etc/barnyard2.conf
index 8499235..3009dc5 100644
--- a/etc/barnyard2.conf
+++ b/etc/barnyard2.conf
@@ -189,6 +189,15 @@ input unified2
# output alert_cef: LOG_AUTH LOG_INFO
#
+# alert_bro
+#-----------------------------
+#
+# Purpose: Send alerts to a Bro-IDS instance.
+#
+# Arguments: hostname:port
+#
+# Examples:
+# output alert_bro: 127.0.0.1:47757
# alert_fast
#-----------------------------
diff --git a/src/output-plugins/Makefile.am b/src/output-plugins/Makefile.am
index 9e8cc06..6636edd 100644
--- a/src/output-plugins/Makefile.am
+++ b/src/output-plugins/Makefile.am
@@ -5,6 +5,7 @@ noinst_LIBRARIES = libspo.a
libspo_a_SOURCES = \
spo_alert_arubaaction.c spo_alert_arubaaction.h \
+spo_alert_bro.c spo_alert_bro.h \
spo_alert_cef.c spo_alert_cef.h \
spo_alert_fast.c spo_alert_fast.h \
spo_alert_full.c spo_alert_full.h \
diff --git a/src/output-plugins/spo_alert_bro.c b/src/output-plugins/spo_alert_bro.c
new file mode 100644
index 0000000..2a9f727
--- /dev/null
+++ b/src/output-plugins/spo_alert_bro.c
@@ -0,0 +1,274 @@
+/*
+** Copyright (C) 2010 Seth Hall <seth@icir.org>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+/* $Id$ */
+
+/* spo_alert_Bro
+ *
+ * This module sends alerts to the Bro-IDS as Bro events using the Bro
+ * communications protocol.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef BROCCOLI
+
+#include <sys/types.h>
+#include <stdlib.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#include "broccoli.h"
+
+#include "barnyard2.h"
+#include "decode.h"
+#include "debug.h"
+#include "map.h"
+#include "mstring.h"
+#include "parser.h"
+#include "strlcatu.h"
+#include "strlcpyu.h"
+#include "plugbase.h"
+#include "unified2.h"
+#include "util.h"
+
+extern OptTreeNode *otn_tmp;
+
+void AlertBroSetup(void);
+void AlertBroInit(char *);
+void AlertBro(Packet *, void *, u_int32_t, void *);
+void AlertBroCleanExit(int, void *);
+void AlertBroRestart(int, void *);
+
+static BroConn *bro_conn;
+
+/*
+ * Function: AlertBroSetup()
+ *
+ * Purpose: Registers the output plugin keyword and initialization
+ * function into the output plugin list. This is the function that
+ * gets called from InitOutputPlugins() in plugbase.c.
+ *
+ * Arguments: None.
+ *
+ * Returns: void function
+ *
+ */
+void AlertBroSetup(void)
+{
+ /* link the preprocessor keyword to the init function in
+ the preproc list */
+ RegisterOutputPlugin("alert_bro", OUTPUT_TYPE_FLAG__ALERT, AlertBroInit);
+ DEBUG_WRAP(DebugMessage(DEBUG_INIT,"Output plugin: Alert-Bro is setup...\n"););
+}
+
+
+/*
+ * Function: AlertBroInit(char *)
+ *
+ * Purpose: Makes the connection to Bro, links the preproc function
+ * into the function list.
+ *
+ * Arguments: args => ptr to argument string
+ *
+ * Returns: void function
+ *
+ */
+void AlertBroInit(char *args)
+{
+ char *host_string = args;
+
+ bro_init(NULL);
+ DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Output: Alert-Bro Initialized\n"););
+
+ if ( !(bro_conn = bro_conn_new_str(host_string,
+ BRO_CFLAG_RECONNECT | BRO_CFLAG_ALWAYS_QUEUE )) )
+ {
+ FatalError("Could not get Bro connection handle.\n", host_string);
+ }
+ bro_conn_set_class(bro_conn, "barnyard");
+ LogMessage("alert_bro Connecting to Bro (%s)...", host_string);
+ if ( !bro_conn_connect(bro_conn) )
+ {
+ FatalError("failed!\nCould not connect to Bro!\n");
+ }
+ LogMessage("done.\n");
+
+ DEBUG_WRAP(DebugMessage(DEBUG_INIT,"Linking Bro alert function to call list...\n"););
+ /* Set the preprocessor function into the function list */
+ AddFuncToOutputList(AlertBro, OUTPUT_TYPE__ALERT, 0);
+ AddFuncToCleanExitList(AlertBroCleanExit, 0);
+ AddFuncToRestartList(AlertBroRestart, 0);
+}
+
+
+/*
+ * Function: AlertBro(Packet *)
+ *
+ * Arguments: p => pointer to the current packet data struct
+ *
+ * Returns: void function
+ *
+ */
+void AlertBro(Packet *p, void *event, u_int32_t event_type, void *arg)
+{
+ BroEvent *ev;
+ SigNode *sn;
+ ClassType *cn;
+ ReferenceNode *rn;
+
+ Unified2EventCommon *uevent = (Unified2EventCommon *) event;
+ BroPort src_p;
+ BroPort dst_p;
+
+ if ( p == NULL || event == NULL )
+ {
+ return;
+ }
+
+ sn = GetSigByGidSid(ntohl(uevent->generator_id),
+ ntohl(uevent->signature_id));
+
+ if(p && IPH_IS_VALID(p))
+ {
+ ev = bro_event_new("barnyard_alert");
+
+ // First value
+ BroRecord *packet_id = bro_record_new();
+ src_p.port_num = dst_p.port_num = 0;
+ // Broccoli's protocol handling is sort of broken at the moment
+ // it segfaults when doing bro_record_add_val if not tcp, udp, or icmp
+ // waiting on ticket: http://tracker.icir.org/bro/ticket/278
+ src_p.port_proto = dst_p.port_proto = IPPROTO_TCP;
+ if(GET_IPH_PROTO(p) != 255)
+ {
+ src_p.port_proto = dst_p.port_proto = GET_IPH_PROTO(p);
+ if((GET_IPH_PROTO(p) == IPPROTO_ICMP) && p->icmph)
+ {
+ src_p.port_num = htons(p->icmph->type);
+ dst_p.port_num = htons(p->icmph->code);
+ } else {
+ src_p.port_num = p->sp;
+ dst_p.port_num = p->dp;
+ }
+ }
+
+ bro_record_add_val(packet_id, "src_ip", BRO_TYPE_IPADDR, NULL, &GET_SRC_ADDR(p));
+ bro_record_add_val(packet_id, "src_p", BRO_TYPE_PORT, NULL, &src_p);
+ bro_record_add_val(packet_id, "dst_ip", BRO_TYPE_IPADDR, NULL, &GET_DST_ADDR(p));
+ bro_record_add_val(packet_id, "dst_p", BRO_TYPE_PORT, NULL, &dst_p);
+ bro_event_add_val(ev, BRO_TYPE_RECORD, "packet_id", packet_id);
+ bro_record_free(packet_id);
+
+ // Second value
+ BroRecord *sad = bro_record_new();
+ uint32_t sensor_id_hl = ntohl(uevent->sensor_id);
+ bro_record_add_val(sad, "sensor_id", BRO_TYPE_COUNT, NULL, &sensor_id_hl);
+ double ts = (double) ntohl(uevent->event_second) + (((double) ntohl(uevent->event_microsecond))/1000000);
+ bro_record_add_val(sad, "ts", BRO_TYPE_TIME, NULL, &ts);
+ uint32_t signature_id_hl = ntohl(uevent->signature_id);
+ bro_record_add_val(sad, "signature_id", BRO_TYPE_COUNT, NULL, &signature_id_hl);
+ uint32_t generator_id_hl = ntohl(uevent->generator_id);
+ bro_record_add_val(sad, "generator_id", BRO_TYPE_COUNT, NULL, &generator_id_hl);
+ uint32_t signature_revision_hl = ntohl(uevent->signature_revision);
+ bro_record_add_val(sad, "signature_revision", BRO_TYPE_COUNT, NULL, &signature_revision_hl);
+ uint32_t classification_id_hl = ntohl(uevent->classification_id);
+ bro_record_add_val(sad, "classification_id", BRO_TYPE_COUNT, NULL, &classification_id_hl);
+ BroString class_bs;
+ cn = ClassTypeLookupById(barnyard2_conf, ntohl(uevent->classification_id));
+ bro_string_init(&class_bs);
+ bro_string_set(&class_bs, cn->name);
+ bro_record_add_val(sad, "classification", BRO_TYPE_STRING, NULL, &class_bs);
+ bro_string_cleanup(&class_bs);
+ uint32_t priority_id_hl = ntohl(uevent->priority_id);
+ bro_record_add_val(sad, "priority_id", BRO_TYPE_COUNT, NULL, &priority_id_hl);
+ uint32_t event_id_hl = ntohl(uevent->event_id);
+ bro_record_add_val(sad, "event_id", BRO_TYPE_COUNT, NULL, &event_id_hl);
+ //BroSet *ref_set = bro_set_new();
+ //BroString ref_name_bs;
+ //rn = sn->refs;
+ //while(rn)
+ //{
+ // bro_string_init(&ref_name_bs);
+ // bro_string_set(&ref_name_bs, rn->system->name);
+ // bro_set_insert(ref_set, BRO_TYPE_STRING, &ref_name_bs);
+ // bro_string_cleanup(&ref_name_bs);
+ // rn = rn->next;
+ //}
+ //bro_record_add_val(sad, "references", BRO_TYPE_SET, NULL, ref_set);
+ //bro_set_free(ref_set);
+
+ bro_event_add_val(ev, BRO_TYPE_RECORD, "barnyard_alert_data", sad);
+ bro_record_free(sad);
+
+ // Third value
+ BroString msg_bs;
+ bro_string_init(&msg_bs);
+ bro_string_set(&msg_bs, sn->msg);
+ bro_event_add_val(ev, BRO_TYPE_STRING, NULL, &msg_bs);
+ bro_string_cleanup(&msg_bs);
+
+ // Fourth value
+ BroString contents_bs;
+ bro_string_init(&contents_bs);
+ bro_string_set_data(&contents_bs, (uchar *) p->data, p->dsize);
+ bro_event_add_val(ev, BRO_TYPE_STRING, NULL, &contents_bs);
+ bro_string_cleanup(&contents_bs);
+
+ // send and free the event
+ bro_event_send(bro_conn, ev);
+ bro_event_free(ev);
+ }
+ else
+ {
+ // Not bothering with alerts using faked or undecodeable packets.
+ LogMessage("WARNING (Bro) faked or undecodeable packet: %s\n", sn->msg);
+ }
+
+}
+
+void AlertBroCleanExit(int signal, void *arg)
+{
+ DEBUG_WRAP(DebugMessage(DEBUG_LOG, "AlertBroCleanExit\n"););
+ int remaining=0;
+ while (bro_event_queue_length(bro_conn) > 0)
+ {
+ remaining = bro_event_queue_flush(bro_conn);
+ LogMessage("(Bro) %d events left to flush.\n", remaining);
+ }
+ bro_conn_delete(bro_conn);
+}
+
+void AlertBroRestart(int signal, void *arg)
+{
+ DEBUG_WRAP(DebugMessage(DEBUG_LOG, "AlertBroRestartFunc\n"););
+ int remaining=0;
+ while (bro_event_queue_length(bro_conn) > 0)
+ {
+ remaining = bro_event_queue_flush(bro_conn);
+ LogMessage("(Bro) %d events left to flush.\n", remaining);
+ }
+ if(!bro_conn_reconnect(bro_conn))
+ FatalError("Could not connect to Bro!\n");
+}
+
+#endif /* BROCCOLI */
\ No newline at end of file
diff --git a/src/output-plugins/spo_alert_bro.h b/src/output-plugins/spo_alert_bro.h
new file mode 100644
index 0000000..1b4c567
--- /dev/null
+++ b/src/output-plugins/spo_alert_bro.h
@@ -0,0 +1,27 @@
+/*
+** Copyright (C) 2010 Seth Hall <seth@icir.org>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License Version 2 as
+** published by the Free Software Foundation. You may not use, modify or
+** distribute this program under any other version of the GNU General
+** Public License.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* $Id$ */
+
+#ifndef __SPO_BROCCOLI_H__
+#define __SPO_BROCCOLI_H__
+
+void AlertBroSetup(void);
+
+#endif /* __SPO_BROCOLLI_H__ */
diff --git a/src/plugbase.c b/src/plugbase.c
index 20a79a1..af99a27 100644
--- a/src/plugbase.c
+++ b/src/plugbase.c
@@ -56,6 +56,7 @@
/* built-in output plugins */
#include "output-plugins/spo_alert_arubaaction.h"
+#include "output-plugins/spo_alert_bro.h"
#include "output-plugins/spo_alert_cef.h"
#include "output-plugins/spo_alert_fast.h"
#include "output-plugins/spo_alert_full.h"
@@ -340,6 +341,10 @@ void RegisterOutputPlugins(void)
AlertPreludeSetup();
#endif
+#ifdef BROCCOLI
+ AlertBroSetup();
+#endif
+
AlertTestSetup();
PlatypusSetup();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment