mirror of
https://github.com/BlackLight/Snort_AIPreproc.git
synced 2024-11-24 04:35:11 +01:00
Supporting alerts and packets info output to db
This commit is contained in:
parent
a454d15d29
commit
f28830d744
10 changed files with 594 additions and 81 deletions
|
@ -23,6 +23,7 @@ cluster.c \
|
|||
correlation.c \
|
||||
db.c \
|
||||
mysql.c \
|
||||
outdb.c \
|
||||
postgresql.c \
|
||||
regex.c \
|
||||
spp_ai.c \
|
||||
|
|
10
Makefile.in
10
Makefile.in
|
@ -79,9 +79,9 @@ am_libsf_ai_preproc_la_OBJECTS = libsf_ai_preproc_la-alert_history.lo \
|
|||
libsf_ai_preproc_la-alert_parser.lo \
|
||||
libsf_ai_preproc_la-bayesian.lo libsf_ai_preproc_la-cluster.lo \
|
||||
libsf_ai_preproc_la-correlation.lo libsf_ai_preproc_la-db.lo \
|
||||
libsf_ai_preproc_la-mysql.lo libsf_ai_preproc_la-postgresql.lo \
|
||||
libsf_ai_preproc_la-regex.lo libsf_ai_preproc_la-spp_ai.lo \
|
||||
libsf_ai_preproc_la-stream.lo
|
||||
libsf_ai_preproc_la-mysql.lo libsf_ai_preproc_la-outdb.lo \
|
||||
libsf_ai_preproc_la-postgresql.lo libsf_ai_preproc_la-regex.lo \
|
||||
libsf_ai_preproc_la-spp_ai.lo libsf_ai_preproc_la-stream.lo
|
||||
nodist_libsf_ai_preproc_la_OBJECTS = \
|
||||
libsf_ai_preproc_la-sf_dynamic_preproc_lib.lo \
|
||||
libsf_ai_preproc_la-sfPolicyUserData.lo
|
||||
|
@ -258,6 +258,7 @@ cluster.c \
|
|||
correlation.c \
|
||||
db.c \
|
||||
mysql.c \
|
||||
outdb.c \
|
||||
postgresql.c \
|
||||
regex.c \
|
||||
spp_ai.c \
|
||||
|
@ -395,6 +396,9 @@ libsf_ai_preproc_la-db.lo: db.c
|
|||
libsf_ai_preproc_la-mysql.lo: mysql.c
|
||||
$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsf_ai_preproc_la_CFLAGS) $(CFLAGS) -c -o libsf_ai_preproc_la-mysql.lo `test -f 'mysql.c' || echo '$(srcdir)/'`mysql.c
|
||||
|
||||
libsf_ai_preproc_la-outdb.lo: outdb.c
|
||||
$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsf_ai_preproc_la_CFLAGS) $(CFLAGS) -c -o libsf_ai_preproc_la-outdb.lo `test -f 'outdb.c' || echo '$(srcdir)/'`outdb.c
|
||||
|
||||
libsf_ai_preproc_la-postgresql.lo: postgresql.c
|
||||
$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsf_ai_preproc_la_CFLAGS) $(CFLAGS) -c -o libsf_ai_preproc_la-postgresql.lo `test -f 'postgresql.c' || echo '$(srcdir)/'`postgresql.c
|
||||
|
||||
|
|
|
@ -145,8 +145,10 @@ AI_file_alertparser_thread ( void* arg )
|
|||
AI_snort_alert *alert = NULL;
|
||||
AI_snort_alert *tmp = NULL;
|
||||
BOOL in_alert = false;
|
||||
|
||||
pthread_t alerts_pool_thread;
|
||||
pthread_t serializer_thread;
|
||||
pthread_t db_thread;
|
||||
|
||||
/* Initialize the mutex lock, so nobody can read the alerts while we write there */
|
||||
pthread_mutex_init ( &alert_mutex, NULL );
|
||||
|
@ -241,8 +243,6 @@ AI_file_alertparser_thread ( void* arg )
|
|||
fseek ( alert_fp, 0, SEEK_END );
|
||||
#endif
|
||||
|
||||
/* Set the lock flag to true until it's done with alert parsing */
|
||||
|
||||
while ( !feof ( alert_fp ))
|
||||
{
|
||||
fgets ( line, sizeof(line), alert_fp );
|
||||
|
@ -285,6 +285,12 @@ AI_file_alertparser_thread ( void* arg )
|
|||
if ( pthread_create ( &serializer_thread, NULL, AI_serializer_thread, alert ) != 0 )
|
||||
_dpd.fatalMsg ( "Failed to create the alerts' serializer thread\n" );
|
||||
|
||||
if ( config->outdbtype != outdb_none )
|
||||
{
|
||||
if ( pthread_create ( &db_thread, NULL, AI_store_alert_to_db_thread, alert ) != 0 )
|
||||
_dpd.fatalMsg ( "Failed to create the alert to db storing thread\n" );
|
||||
}
|
||||
|
||||
in_alert = false;
|
||||
alert = NULL;
|
||||
}
|
||||
|
|
37
db.h
37
db.h
|
@ -27,14 +27,23 @@
|
|||
typedef MYSQL_RES* DB_result;
|
||||
typedef MYSQL_ROW DB_row;
|
||||
|
||||
#define DB_init mysql_do_init
|
||||
#define DB_query mysql_do_query
|
||||
#define DB_num_rows mysql_num_rows
|
||||
#define DB_fetch_row mysql_fetch_row
|
||||
#define DB_free_result mysql_free_result
|
||||
#define DB_close mysql_do_close
|
||||
#define DB_init mysql_do_init
|
||||
#define DB_is_init mysql_is_init
|
||||
#define DB_query mysql_do_query
|
||||
#define DB_num_rows mysql_num_rows
|
||||
#define DB_fetch_row mysql_fetch_row
|
||||
#define DB_free_result mysql_free_result
|
||||
#define DB_escape_string mysql_do_escape_string
|
||||
#define DB_close mysql_do_close
|
||||
|
||||
#define DB_out_init mysql_do_out_init
|
||||
#define DB_is_out_init mysql_is_out_init
|
||||
#define DB_out_query mysql_do_out_query
|
||||
#define DB_out_escape_string mysql_do_out_escape_string
|
||||
#define DB_out_close mysql_do_out_close
|
||||
|
||||
DB_result* DB_query ( const char* );
|
||||
DB_result* DB_out_query ( const char* );
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBPQ
|
||||
|
@ -50,20 +59,32 @@
|
|||
typedef char** DB_row;
|
||||
|
||||
#define DB_init postgresql_do_init
|
||||
#define DB_is_init postgresql_is_init
|
||||
#define DB_query postgresql_do_query
|
||||
#define DB_num_rows postgresql_num_rows
|
||||
#define DB_fetch_row postgresql_fetch_row
|
||||
#define DB_free_result postgresql_free_result
|
||||
#define DB_close postgresql_do_close
|
||||
|
||||
#define DB_out_init postgresql_do_out_init
|
||||
#define DB_is_out_init postgresql_is_out_init
|
||||
#define DB_out_query postgresql_do_out_query
|
||||
#define DB_out_close postgresql_do_out_close
|
||||
|
||||
int DB_num_rows ( PSQL_result *res );
|
||||
DB_row DB_fetch_row ( PSQL_result *res );
|
||||
void DB_free_result ( PSQL_result *res );
|
||||
DB_result DB_query ( const char* );
|
||||
DB_result DB_out_query ( const char* );
|
||||
#endif
|
||||
|
||||
void* DB_init();
|
||||
void DB_close();
|
||||
void* DB_init();
|
||||
unsigned long DB_escape_string();
|
||||
void DB_close();
|
||||
|
||||
void* DB_out_init();
|
||||
unsigned long DB_out_escape_string();
|
||||
void DB_out_close();
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
156
mysql.c
156
mysql.c
|
@ -25,56 +25,146 @@
|
|||
/** \defgroup mysql Module for the interface with a MySQL DBMS
|
||||
* @{ */
|
||||
|
||||
PRIVATE MYSQL *db = NULL;
|
||||
/***************************/
|
||||
/* Database descriptors */
|
||||
PRIVATE MYSQL *db = NULL;
|
||||
PRIVATE MYSQL *outdb = NULL;
|
||||
/***************************/
|
||||
|
||||
/*************************************************************/
|
||||
/* Private functions (operating on the database descriptors) */
|
||||
|
||||
PRIVATE BOOL
|
||||
__mysql_is_init ( MYSQL *__DB )
|
||||
{
|
||||
return ( __DB != NULL );
|
||||
}
|
||||
|
||||
PRIVATE void*
|
||||
__mysql_do_init ( MYSQL **__DB, BOOL is_out )
|
||||
{
|
||||
if ( __mysql_is_init ( *__DB ) )
|
||||
return (void*) *__DB;
|
||||
|
||||
if ( !( *__DB = (MYSQL*) malloc ( sizeof ( MYSQL ))))
|
||||
return NULL;
|
||||
|
||||
if ( !( mysql_init ( *__DB )))
|
||||
return NULL;
|
||||
|
||||
if ( is_out )
|
||||
{
|
||||
if ( !mysql_real_connect ( *__DB, config->outdbhost, config->outdbuser, config->outdbpass, NULL, 0, NULL, 0 ))
|
||||
return NULL;
|
||||
|
||||
if ( mysql_select_db ( *__DB, config->outdbname ))
|
||||
return NULL;
|
||||
} else {
|
||||
if ( !mysql_real_connect ( *__DB, config->dbhost, config->dbuser, config->dbpass, NULL, 0, NULL, 0 ))
|
||||
return NULL;
|
||||
|
||||
if ( mysql_select_db ( *__DB, config->dbname ))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void*) *__DB;
|
||||
}
|
||||
|
||||
PRIVATE MYSQL_RES*
|
||||
__mysql_do_query ( MYSQL *__DB, const char *query )
|
||||
{
|
||||
MYSQL_RES *res = NULL;
|
||||
|
||||
if ( mysql_query ( __DB, query ))
|
||||
return NULL;
|
||||
|
||||
if ( !( res = mysql_store_result ( __DB )))
|
||||
return NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
PRIVATE void
|
||||
__mysql_do_close ( MYSQL **__DB )
|
||||
{
|
||||
if ( *__DB )
|
||||
mysql_close ( *__DB );
|
||||
|
||||
free ( *__DB );
|
||||
*__DB = NULL;
|
||||
}
|
||||
|
||||
/* End of private functions */
|
||||
/****************************/
|
||||
|
||||
/********************/
|
||||
/* Public functions */
|
||||
|
||||
BOOL
|
||||
mysql_is_init ()
|
||||
{
|
||||
return __mysql_is_init ( db );
|
||||
}
|
||||
|
||||
void*
|
||||
mysql_do_init ()
|
||||
{
|
||||
if ( !( db = (MYSQL*) malloc ( sizeof ( MYSQL ))))
|
||||
return NULL;
|
||||
|
||||
if ( !( mysql_init ( db )))
|
||||
return NULL;
|
||||
|
||||
if ( !mysql_real_connect ( db, config->dbhost, config->dbuser, config->dbpass, NULL, 0, NULL, 0 ))
|
||||
return NULL;
|
||||
|
||||
if ( mysql_select_db ( db, config->dbname ))
|
||||
return NULL;
|
||||
|
||||
return (void*) db;
|
||||
return __mysql_do_init ( &db, false );
|
||||
}
|
||||
|
||||
MYSQL_RES*
|
||||
mysql_do_query ( const char *query )
|
||||
{
|
||||
MYSQL_RES *res = NULL;
|
||||
return __mysql_do_query ( db, query );
|
||||
}
|
||||
|
||||
if ( mysql_query ( db, query ))
|
||||
{
|
||||
mysql_close ( db );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( !( res = mysql_store_result ( db )))
|
||||
{
|
||||
mysql_close ( db );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return res;
|
||||
unsigned long
|
||||
mysql_do_escape_string ( char **to, const char *from, unsigned long length )
|
||||
{
|
||||
return mysql_real_escape_string ( db, *to, from, length );
|
||||
}
|
||||
|
||||
void
|
||||
mysql_do_close ()
|
||||
{
|
||||
if ( db )
|
||||
mysql_close ( db );
|
||||
|
||||
free ( db );
|
||||
db = NULL;
|
||||
__mysql_do_close ( &db );
|
||||
}
|
||||
|
||||
/* Output database functions */
|
||||
|
||||
BOOL
|
||||
mysql_is_out_init ()
|
||||
{
|
||||
return __mysql_is_init ( outdb );
|
||||
}
|
||||
|
||||
void*
|
||||
mysql_do_out_init ()
|
||||
{
|
||||
return __mysql_do_init ( &outdb, true );
|
||||
}
|
||||
|
||||
MYSQL_RES*
|
||||
mysql_do_out_query ( const char *query )
|
||||
{
|
||||
return __mysql_do_query ( outdb, query );
|
||||
}
|
||||
|
||||
unsigned long
|
||||
mysql_do_out_escape_string ( char **to, const char *from, unsigned long length )
|
||||
{
|
||||
return mysql_real_escape_string ( outdb, *to, from, length );
|
||||
}
|
||||
|
||||
void
|
||||
mysql_do_out_close ()
|
||||
{
|
||||
__mysql_do_close ( &outdb );
|
||||
}
|
||||
|
||||
/* End of public functions */
|
||||
/***************************/
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
|
|
211
outdb.c
Normal file
211
outdb.c
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: outdb.c
|
||||
*
|
||||
* Description: Module for writing to a database the outputs (alerts, hyperalerts,
|
||||
* clustered alerts, correlated alerts, alerts' TCP streams) from the
|
||||
* preprocessor module
|
||||
*
|
||||
* Version: 0.1
|
||||
* Created: 30/09/2010 20:02:17
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: BlackLight (http://0x00.ath.cx), <blacklight@autistici.org>
|
||||
* Licence: GNU GPL v.3
|
||||
* Company: DO WHAT YOU WANT CAUSE A PIRATE IS FREE, YOU ARE A PIRATE!
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include "spp_ai.h"
|
||||
|
||||
/** \defgroup outdb Storing alerts, packets, clusters and correlations information on a database
|
||||
* @{ */
|
||||
|
||||
#ifdef HAVE_DB
|
||||
|
||||
#include "db.h"
|
||||
#include <alloca.h>
|
||||
#include <pthread.h>
|
||||
|
||||
enum { ALERTS_TABLE, IPV4_HEADERS_TABLE, TCP_HEADERS_TABLE, PACKET_STREAMS_TABLE, CLUSTERED_ALERTS_TABLE, CORRELATED_ALERTS_TABLE, N_TABLES };
|
||||
|
||||
static const char *outdb_config[] = {
|
||||
"ca_alerts", "ca_ipv4_headers", "ca_tcp_headers",
|
||||
"ca_packet_streams", "ca_clustered_alerts", "ca_correlated_alerts"
|
||||
};
|
||||
|
||||
PRIVATE pthread_mutex_t mutex;
|
||||
|
||||
/**
|
||||
* \brief Thread for storing an alert to the database
|
||||
* \param arg Alert to be stored
|
||||
*/
|
||||
|
||||
void*
|
||||
AI_store_alert_to_db_thread ( void *arg )
|
||||
{
|
||||
char srcip[INET_ADDRSTRLEN], dstip[INET_ADDRSTRLEN];
|
||||
char query[65535] = { 0 };
|
||||
unsigned char *pkt_data = NULL;
|
||||
unsigned long latest_ip_hdr_id = 0,
|
||||
latest_tcp_hdr_id = 0,
|
||||
latest_alert_id = 0,
|
||||
pkt_size = 0,
|
||||
pkt_size_offset = 0;
|
||||
|
||||
struct pkt_info *pkt = NULL;
|
||||
DB_result res;
|
||||
DB_row row;
|
||||
AI_snort_alert *alert = (AI_snort_alert*) arg;
|
||||
|
||||
pthread_mutex_init ( &mutex, NULL );
|
||||
|
||||
if ( !DB_out_init() )
|
||||
_dpd.fatalMsg ( "AIPreproc: Unable to connect to output database '%s'\n", config->outdbname );
|
||||
|
||||
pthread_mutex_lock ( &mutex );
|
||||
|
||||
inet_ntop ( AF_INET, &(alert->ip_src_addr), srcip, INET_ADDRSTRLEN );
|
||||
inet_ntop ( AF_INET, &(alert->ip_dst_addr), dstip, INET_ADDRSTRLEN );
|
||||
|
||||
/* Store the IP header information */
|
||||
memset ( query, 0, sizeof ( query ));
|
||||
snprintf ( query, sizeof ( query ), "INSERT INTO %s (ip_tos, ip_len, ip_id, ip_ttl, ip_proto, ip_src_addr, ip_dst_addr) "
|
||||
"VALUES (%u, %u, %u, %u, %u, '%s', '%s')",
|
||||
outdb_config[IPV4_HEADERS_TABLE],
|
||||
alert->ip_tos,
|
||||
ntohs (alert->ip_len ),
|
||||
ntohs (alert->ip_id ),
|
||||
alert->ip_ttl,
|
||||
alert->ip_proto,
|
||||
srcip,
|
||||
dstip );
|
||||
|
||||
DB_out_query ( query );
|
||||
|
||||
memset ( query, 0, sizeof ( query ));
|
||||
snprintf ( query, sizeof ( query ), "SELECT MAX(ip_hdr_id) FROM %s", outdb_config[IPV4_HEADERS_TABLE] );
|
||||
|
||||
if ( !( res = (DB_result) DB_out_query ( query )))
|
||||
{
|
||||
_dpd.logMsg ( "AIPreproc: Warning: error in executing query: '%s'\n", query );
|
||||
pthread_exit ((void*) 0);
|
||||
}
|
||||
|
||||
if ( !( row = (DB_row) DB_fetch_row ( res )))
|
||||
{
|
||||
pthread_exit ((void*) 0);
|
||||
}
|
||||
|
||||
latest_ip_hdr_id = strtoul ( row[0], NULL, 10 );
|
||||
DB_free_result ( res );
|
||||
|
||||
if ( alert->ip_proto == IPPROTO_TCP || alert->ip_proto == IPPROTO_UDP )
|
||||
{
|
||||
/* Store the TCP header information */
|
||||
memset ( query, 0, sizeof ( query ));
|
||||
snprintf ( query, sizeof ( query ), "INSERT INTO %s (tcp_src_port, tcp_dst_port, tcp_seq, tcp_ack, tcp_flags, tcp_window, tcp_len) "
|
||||
"VALUES (%u, %u, %u, %u, %u, %u, %u)",
|
||||
outdb_config[TCP_HEADERS_TABLE],
|
||||
ntohs (alert->tcp_src_port ),
|
||||
ntohs (alert->tcp_dst_port ),
|
||||
ntohl (alert->tcp_seq ),
|
||||
ntohl (alert->tcp_ack ),
|
||||
alert->tcp_flags,
|
||||
ntohs (alert->tcp_window ),
|
||||
ntohs (alert->tcp_len ));
|
||||
|
||||
DB_out_query ( query );
|
||||
|
||||
memset ( query, 0, sizeof ( query ));
|
||||
snprintf ( query, sizeof ( query ), "SELECT MAX(tcp_hdr_id) FROM %s", outdb_config[TCP_HEADERS_TABLE] );
|
||||
|
||||
if ( !( res = (DB_result) DB_out_query ( query )))
|
||||
{
|
||||
_dpd.logMsg ( "AIPreproc: Warning: error in executing query: '%s'\n", query );
|
||||
pthread_exit ((void*) 0);
|
||||
}
|
||||
|
||||
if ( !( row = (DB_row) DB_fetch_row ( res )))
|
||||
{
|
||||
pthread_exit ((void*) 0);
|
||||
}
|
||||
|
||||
latest_tcp_hdr_id = strtoul ( row[0], NULL, 10 );
|
||||
DB_free_result ( res );
|
||||
}
|
||||
|
||||
memset ( query, 0, sizeof ( query ));
|
||||
snprintf ( query, sizeof ( query ), "INSERT INTO %s (gid, sid, rev, priority, description, classification, timestamp, ip_hdr, tcp_hdr) "
|
||||
"VALUES (%u, %u, %u, %u, '%s', '%s', from_unixtime('%lu'), %lu, %lu)",
|
||||
outdb_config[ALERTS_TABLE],
|
||||
alert->gid,
|
||||
alert->sid,
|
||||
alert->rev,
|
||||
alert->priority,
|
||||
((alert->desc) ? alert->desc : ""),
|
||||
((alert->classification) ? alert->classification : ""),
|
||||
alert->timestamp,
|
||||
latest_ip_hdr_id,
|
||||
((alert->ip_proto == IPPROTO_TCP || alert->ip_proto == IPPROTO_UDP) ? latest_tcp_hdr_id : 0));
|
||||
|
||||
DB_out_query ( query );
|
||||
|
||||
memset ( query, 0, sizeof ( query ));
|
||||
snprintf ( query, sizeof ( query ), "SELECT MAX(alert_id) FROM %s", outdb_config[ALERTS_TABLE] );
|
||||
|
||||
if ( !( res = (DB_result) DB_out_query ( query )))
|
||||
{
|
||||
_dpd.logMsg ( "AIPreproc: Warning: error in executing query: '%s'\n", query );
|
||||
pthread_exit ((void*) 0);
|
||||
}
|
||||
|
||||
if ( !( row = (DB_row) DB_fetch_row ( res )))
|
||||
{
|
||||
pthread_exit ((void*) 0);
|
||||
}
|
||||
|
||||
latest_alert_id = strtoul ( row[0], NULL, 10 );
|
||||
alert->alert_id = latest_alert_id;
|
||||
DB_free_result ( res );
|
||||
|
||||
if ( alert->stream )
|
||||
{
|
||||
for ( pkt = alert->stream; pkt; pkt = pkt->next )
|
||||
{
|
||||
pkt_data = NULL;
|
||||
pkt_size = pkt->pkt->pcap_cap_len;
|
||||
pkt_size_offset = 0;
|
||||
|
||||
if ( !( pkt_data = (unsigned char*) alloca ( 2 * (pkt->pkt->pcap_header->len + pkt->pkt->payload_size) + 1 )))
|
||||
_dpd.fatalMsg ( "AIPreproc: Fatal dynamic allocation memory at %s:%d\n", __FILE__, __LINE__ );
|
||||
|
||||
DB_out_escape_string ( &pkt_data,
|
||||
pkt->pkt->pkt_data,
|
||||
pkt->pkt->pcap_header->len + pkt->pkt->payload_size );
|
||||
|
||||
memset ( query, 0, sizeof ( query ));
|
||||
snprintf ( query, sizeof ( query ), "INSERT INTO %s (alert_id, pkt_len, timestamp, content) "
|
||||
"VALUES (%lu, %u, from_unixtime('%lu'), '%s')",
|
||||
outdb_config[PACKET_STREAMS_TABLE],
|
||||
latest_alert_id,
|
||||
pkt->pkt->pcap_header->len + pkt->pkt->payload_size,
|
||||
pkt->timestamp,
|
||||
pkt_data );
|
||||
|
||||
DB_out_query ( query );
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock ( &mutex );
|
||||
pthread_exit ((void*) 0);
|
||||
return (void*) 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
144
postgresql.c
144
postgresql.c
|
@ -27,41 +27,78 @@
|
|||
/** \defgroup postgresql Module for the interface with a PostgreSQL DBMS
|
||||
* @{ */
|
||||
|
||||
PRIVATE PGconn *db = NULL;
|
||||
/***************************/
|
||||
/* Database descriptors */
|
||||
PRIVATE PGconn *db = NULL;
|
||||
PRIVATE PGconn *outdb = NULL;
|
||||
/***************************/
|
||||
|
||||
void*
|
||||
postgresql_do_init ()
|
||||
/*************************************************************/
|
||||
/* Private functions (operating on the database descriptors) */
|
||||
|
||||
PRIVATE BOOL
|
||||
__postgresql_is_init ( PGconn *__DB )
|
||||
{
|
||||
return ( __DB != NULL );
|
||||
}
|
||||
|
||||
PRIVATE void*
|
||||
__postgresql_do_init ( PGconn **__DB, BOOL is_out )
|
||||
{
|
||||
char *conninfo = NULL;
|
||||
int conninfo_max_length =
|
||||
((config->dbhost) ? strlen ( config->dbhost ) : 0) +
|
||||
((config->dbuser) ? strlen ( config->dbuser ) : 0) +
|
||||
((config->dbpass) ? strlen ( config->dbpass ) : 0) +
|
||||
((config->dbname) ? strlen ( config->dbname ) : 0) + 100;
|
||||
( is_out ?
|
||||
((config->outdbhost) ? strlen ( config->outdbhost ) : 0) +
|
||||
((config->outdbuser) ? strlen ( config->outdbuser ) : 0) +
|
||||
((config->outdbpass) ? strlen ( config->outdbpass ) : 0) +
|
||||
((config->outdbname) ? strlen ( config->outdbname ) : 0) :
|
||||
|
||||
((config->dbhost) ? strlen ( config->dbhost ) : 0) +
|
||||
((config->dbuser) ? strlen ( config->dbuser ) : 0) +
|
||||
((config->dbpass) ? strlen ( config->dbpass ) : 0) +
|
||||
((config->dbname) ? strlen ( config->dbname ) : 0)) + 100;
|
||||
|
||||
if ( postgresql_is_init ( *__DB ))
|
||||
return (void*) *__DB;
|
||||
|
||||
if ( !( conninfo = (char*) alloca ( conninfo_max_length )))
|
||||
_dpd.fatalMsg ( "AIPreproc: Fatal dynamic memory allocation error at %s:%d\n", __FILE__, __LINE__ );
|
||||
|
||||
memset ( conninfo, 0, conninfo_max_length );
|
||||
snprintf ( conninfo, conninfo_max_length, "dbname=%s", config->dbname );
|
||||
|
||||
if ( config->dbuser )
|
||||
sprintf ( conninfo, "%s user=%s", conninfo, config->dbuser );
|
||||
if ( is_out )
|
||||
{
|
||||
snprintf ( conninfo, conninfo_max_length, "dbname=%s", config->outdbname );
|
||||
|
||||
if ( config->dbpass )
|
||||
sprintf ( conninfo, "%s password=%s", conninfo, config->dbpass );
|
||||
if ( config->outdbuser )
|
||||
sprintf ( conninfo, "%s user=%s", conninfo, config->outdbuser );
|
||||
|
||||
if ( config->dbhost )
|
||||
sprintf ( conninfo, "%s hostaddr=%s", conninfo, config->dbhost );
|
||||
if ( config->outdbpass )
|
||||
sprintf ( conninfo, "%s password=%s", conninfo, config->outdbpass );
|
||||
|
||||
if ( PQstatus ( db = PQconnectdb ( conninfo )) != CONNECTION_OK )
|
||||
if ( config->outdbhost )
|
||||
sprintf ( conninfo, "%s hostaddr=%s", conninfo, config->outdbhost );
|
||||
} else {
|
||||
snprintf ( conninfo, conninfo_max_length, "dbname=%s", config->dbname );
|
||||
|
||||
if ( config->dbuser )
|
||||
sprintf ( conninfo, "%s user=%s", conninfo, config->dbuser );
|
||||
|
||||
if ( config->dbpass )
|
||||
sprintf ( conninfo, "%s password=%s", conninfo, config->dbpass );
|
||||
|
||||
if ( config->dbhost )
|
||||
sprintf ( conninfo, "%s hostaddr=%s", conninfo, config->dbhost );
|
||||
}
|
||||
|
||||
if ( PQstatus ( *__DB = PQconnectdb ( conninfo )) != CONNECTION_OK )
|
||||
return NULL;
|
||||
|
||||
return (void*) db;
|
||||
return (void*) *__DB;
|
||||
}
|
||||
|
||||
PSQL_result*
|
||||
postgresql_do_query ( const char *query )
|
||||
PRIVATE PSQL_result*
|
||||
__postgresql_do_query ( PGconn *__DB, const char *query )
|
||||
{
|
||||
int i, j, ntuples, nfields;
|
||||
PSQL_result *res = NULL;
|
||||
|
@ -69,9 +106,9 @@ postgresql_do_query ( const char *query )
|
|||
if ( !( res = (PSQL_result*) malloc ( sizeof ( PSQL_result ))))
|
||||
_dpd.fatalMsg ( "AIPreproc: Fatal dynamic memory allocation error at %s:%d\n", __FILE__, __LINE__ );
|
||||
|
||||
if ( PQresultStatus ( res->res = PQexec( db, query )) != PGRES_TUPLES_OK )
|
||||
if ( PQresultStatus ( res->res = PQexec( __DB, query )) != PGRES_TUPLES_OK )
|
||||
{
|
||||
PQfinish ( db );
|
||||
PQfinish ( __DB );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -131,15 +168,74 @@ postgresql_free_result ( PSQL_result *res )
|
|||
}
|
||||
}
|
||||
|
||||
PRIVATE void
|
||||
__postgresql_do_close ( PGconn **__DB )
|
||||
{
|
||||
if ( *__DB )
|
||||
PQfinish ( *__DB );
|
||||
|
||||
*__DB = NULL;
|
||||
}
|
||||
|
||||
/* End of private functions */
|
||||
/****************************/
|
||||
|
||||
/********************/
|
||||
/* Public functions */
|
||||
|
||||
BOOL
|
||||
postgresql_is_init ()
|
||||
{
|
||||
return __postgresql_is_init ( db );
|
||||
}
|
||||
|
||||
void*
|
||||
postgresql_do_init ()
|
||||
{
|
||||
return __postgresql_do_init ( &db, false );
|
||||
}
|
||||
|
||||
PSQL_result*
|
||||
postgresql_do_query ( const char *query )
|
||||
{
|
||||
return __postgresql_do_query ( db, query );
|
||||
}
|
||||
|
||||
void
|
||||
postgresql_do_close ()
|
||||
{
|
||||
if ( db )
|
||||
PQfinish ( db );
|
||||
|
||||
db = NULL;
|
||||
__postgresql_do_close ( &db );
|
||||
}
|
||||
|
||||
/* Output database functions */
|
||||
|
||||
BOOL
|
||||
postgresql_is_out_init ()
|
||||
{
|
||||
return __postgresql_is_init ( outdb );
|
||||
}
|
||||
|
||||
void*
|
||||
postgresql_do_out_init ()
|
||||
{
|
||||
return __postgresql_do_init ( &outdb, true );
|
||||
}
|
||||
|
||||
PSQL_result*
|
||||
postgresql_do_out_query ( const char *query )
|
||||
{
|
||||
return __postgresql_do_query ( outdb, query );
|
||||
}
|
||||
|
||||
void
|
||||
postgresql_do_out_close ()
|
||||
{
|
||||
__postgresql_do_close ( &outdb );
|
||||
}
|
||||
|
||||
/* End of public functions */
|
||||
/***************************/
|
||||
|
||||
/* @} */
|
||||
|
||||
#endif
|
||||
|
|
82
schemas/mysql.sql
Normal file
82
schemas/mysql.sql
Normal file
|
@ -0,0 +1,82 @@
|
|||
DROP TABLE IF EXISTS ca_ipv4_headers;
|
||||
CREATE TABLE ca_ipv4_headers (
|
||||
ip_hdr_id integer auto_increment,
|
||||
ip_tos integer,
|
||||
ip_len integer,
|
||||
ip_id integer,
|
||||
ip_ttl integer,
|
||||
ip_proto integer,
|
||||
ip_src_addr varchar(32),
|
||||
ip_dst_addr varchar(32),
|
||||
|
||||
primary key(ip_hdr_id)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS ca_tcp_headers;
|
||||
CREATE TABLE ca_tcp_headers (
|
||||
tcp_hdr_id integer auto_increment,
|
||||
tcp_src_port integer,
|
||||
tcp_dst_port integer,
|
||||
tcp_seq integer,
|
||||
tcp_ack integer,
|
||||
tcp_flags integer,
|
||||
tcp_window integer,
|
||||
tcp_len integer,
|
||||
|
||||
primary key(tcp_hdr_id)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS ca_packet_streams;
|
||||
CREATE TABLE ca_packet_streams (
|
||||
pkt_id integer auto_increment,
|
||||
alert_id integer,
|
||||
pkt_len integer,
|
||||
timestamp datetime,
|
||||
content longblob,
|
||||
|
||||
primary key(pkt_id),
|
||||
foreign key(alert_id) references ca_alerts(alert_id)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS ca_alerts;
|
||||
CREATE TABLE ca_alerts (
|
||||
alert_id integer auto_increment,
|
||||
gid integer,
|
||||
sid integer,
|
||||
rev integer,
|
||||
priority integer,
|
||||
description varchar(255),
|
||||
classification varchar(255),
|
||||
timestamp datetime,
|
||||
ip_hdr integer,
|
||||
tcp_hdr integer,
|
||||
cluster_id integer,
|
||||
|
||||
primary key(alert_id),
|
||||
foreign key(ip_hdr) references ca_ip_headers(ip_hdr_id),
|
||||
foreign key(tcp_hdr) references ca_tcp_headers(tcp_hdr_id),
|
||||
foreign key(cluster_id) references ca_clustered_alerts(cluster_id)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS ca_clustered_alerts;
|
||||
CREATE TABLE ca_clustered_alerts (
|
||||
cluster_id integer auto_increment,
|
||||
clustered_srcip varchar(255) default null,
|
||||
clustered_dstip varchar(255) default null,
|
||||
clustered_srcport varchar(255) default null,
|
||||
clustered_dstport varchar(255) default null,
|
||||
|
||||
primary key(cluster_id)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS ca_correlated_alerts;
|
||||
CREATE TABLE ca_correlated_alerts (
|
||||
cluster1 integer,
|
||||
cluster2 integer,
|
||||
correlation_coeff double,
|
||||
|
||||
primary key(cluster1, cluster2),
|
||||
foreign key(cluster1) references ca_clustered_alerts(cluster_id),
|
||||
foreign key(cluster2) references ca_clustered_alerts(cluster_id)
|
||||
);
|
||||
|
14
spp_ai.c
14
spp_ai.c
|
@ -654,8 +654,9 @@ static AI_config * AI_parse(char *args)
|
|||
_dpd.logMsg(" Reading alerts from the database %s\n", config->dbname );
|
||||
}
|
||||
|
||||
|
||||
/* Parsing output_database option */
|
||||
config->outdbtype = outdb_none;
|
||||
|
||||
if ( preg_match ( "\\s*output_database\\s*\\(\\s*([^\\)]+)\\)", args, &matches, &nmatches ) > 0 )
|
||||
{
|
||||
if ( ! has_database_output )
|
||||
|
@ -671,24 +672,21 @@ static AI_config * AI_parse(char *args)
|
|||
|
||||
if ( preg_match ( "type\\s*=\\s*\"([^\"]+)\"", match, &matches, &nmatches ) > 0 )
|
||||
{
|
||||
if ( strcasecmp ( matches[0], "mysql" ) && strcasecmp ( matches[0], "postgresql" ))
|
||||
{
|
||||
_dpd.fatalMsg ( "AIPreproc: Not supported database '%s' (supported types: mysql, postgresql)\n", matches[0] );
|
||||
}
|
||||
|
||||
if ( !strcasecmp ( matches[0], "mysql" ))
|
||||
{
|
||||
#ifndef HAVE_LIBMYSQLCLIENT
|
||||
_dpd.fatalMsg ( "AIPreproc: mysql output set in 'output_database' option but the module was not compiled through --with-mysql option\n" );
|
||||
#else
|
||||
config->outdbtype = mysql;
|
||||
config->outdbtype = outdb_mysql;
|
||||
#endif
|
||||
} else if ( !strcasecmp ( matches[0], "postgresql" )) {
|
||||
#ifndef HAVE_LIBPQ
|
||||
_dpd.fatalMsg ( "AIPreproc: postgresql output set in 'output_database' option but the module was not compiled through --with-postgresql option\n" );
|
||||
#else
|
||||
config->outdbtype = postgresql;
|
||||
config->outdbtype = outdb_postgresql;
|
||||
#endif
|
||||
} else {
|
||||
_dpd.fatalMsg ( "AIPreproc: Not supported database '%s' (supported types: mysql, postgresql)\n", matches[0] );
|
||||
}
|
||||
|
||||
for ( i=0; i < nmatches; i++ )
|
||||
|
|
10
spp_ai.h
10
spp_ai.h
|
@ -206,7 +206,7 @@ typedef struct
|
|||
|
||||
/** Output database type, if clustered alerts and
|
||||
* correlations are saved to a database as well */
|
||||
enum { mysql, postgresql } outdbtype;
|
||||
enum { outdb_none, outdb_mysql, outdb_postgresql, OUTDBTYPE_NUM } outdbtype;
|
||||
|
||||
/** Output database name, if clustered alerts and
|
||||
* correlations are saved to a database as well */
|
||||
|
@ -338,6 +338,10 @@ typedef struct _AI_snort_alert {
|
|||
|
||||
/** Number of derived alerts */
|
||||
unsigned int n_derived_alerts;
|
||||
|
||||
/** Alert ID on the database, if the alerts
|
||||
* are stored on a database as well */
|
||||
unsigned long int alert_id;
|
||||
} AI_snort_alert;
|
||||
/*****************************************************************/
|
||||
/** Key for the AI_alert_event structure, containing the Snort ID of the alert */
|
||||
|
@ -355,8 +359,6 @@ typedef struct _AI_alert_event {
|
|||
struct _AI_alert_event *next;
|
||||
UT_hash_handle hh;
|
||||
} AI_alert_event;
|
||||
/*****************************************************************/
|
||||
|
||||
|
||||
int preg_match ( const char*, char*, char***, int* );
|
||||
char* str_replace ( char*, char*, char *);
|
||||
|
@ -389,6 +391,8 @@ const AI_alert_event* AI_get_alert_events_by_key ( AI_alert_event_key );
|
|||
unsigned int AI_get_history_alert_number ();
|
||||
double AI_alert_bayesian_correlation ( AI_snort_alert *a, AI_snort_alert *b );
|
||||
|
||||
void* AI_store_alert_to_db_thread ( void* );
|
||||
|
||||
/** Function pointer to the function used for getting the alert list (from log file, db, ...) */
|
||||
extern AI_snort_alert* (*get_alerts)(void);
|
||||
|
||||
|
|
Loading…
Reference in a new issue