diff --git a/db.h b/db.h index da2c7c0..38ac2c8 100644 --- a/db.h +++ b/db.h @@ -58,18 +58,20 @@ typedef PSQL_result* DB_result; 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_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_escape_string postgresql_do_escape_string + #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 + #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_escape_string postgresql_do_out_escape_string + #define DB_out_close postgresql_do_out_close int DB_num_rows ( PSQL_result *res ); DB_row DB_fetch_row ( PSQL_result *res ); diff --git a/outdb.c b/outdb.c index 4ff8480..97260d9 100644 --- a/outdb.c +++ b/outdb.c @@ -71,8 +71,10 @@ AI_outdb_mutex_initialize () void* AI_store_alert_to_db_thread ( void *arg ) { - char query[65535] = { 0 }; - char srcip[INET_ADDRSTRLEN], + char query[65535] = { 0 }, + iphdr_id_str[20] = { 0 }, + tcphdr_id_str[20] = { 0 }, + srcip[INET_ADDRSTRLEN], dstip[INET_ADDRSTRLEN]; unsigned char *pkt_data = NULL; @@ -166,10 +168,24 @@ AI_store_alert_to_db_thread ( void *arg ) DB_free_result ( res ); } + if ( latest_ip_hdr_id ) + { + snprintf ( iphdr_id_str, sizeof ( iphdr_id_str ), ", %lu", latest_ip_hdr_id ); + } + + if ( latest_tcp_hdr_id && alert->ip_proto == IPPROTO_TCP ) + { + snprintf ( tcphdr_id_str, sizeof ( tcphdr_id_str ), ", %lu", latest_tcp_hdr_id ); + } + 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)", + + #ifdef HAVE_LIBMYSQLCLIENT + snprintf ( query, sizeof ( query ), "INSERT INTO %s (gid, sid, rev, priority, description, classification, timestamp%s%s) " + "VALUES (%u, %u, %u, %u, '%s', '%s', from_unixtime('%lu')%s%s)", outdb_config[ALERTS_TABLE], + ((latest_ip_hdr_id != 0) ? ", ip_hdr" : ""), + ((latest_tcp_hdr_id != 0) ? ", tcp_hdr" : ""), alert->gid, alert->sid, alert->rev, @@ -177,8 +193,24 @@ AI_store_alert_to_db_thread ( void *arg ) ((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)); + iphdr_id_str, + tcphdr_id_str ); + #elif HAVE_LIBPQ + snprintf ( query, sizeof ( query ), "INSERT INTO %s (gid, sid, rev, priority, description, classification, timestamp%s%s) " + "VALUES (%u, %u, %u, %u, '%s', '%s', timestamp with time zone 'epoch' + %lu * interval '1 second'%s%s)", + outdb_config[ALERTS_TABLE], + ((latest_ip_hdr_id != 0) ? ", ip_hdr" : ""), + ((latest_tcp_hdr_id != 0) ? ", tcp_hdr" : ""), + alert->gid, + alert->sid, + alert->rev, + alert->priority, + ((alert->desc) ? alert->desc : ""), + ((alert->classification) ? alert->classification : ""), + alert->timestamp, + iphdr_id_str, + tcphdr_id_str ); + #endif DB_free_result ((DB_result) DB_out_query ( query )); @@ -219,6 +251,8 @@ AI_store_alert_to_db_thread ( void *arg ) pkt->pkt->pcap_header->len + pkt->pkt->payload_size ); memset ( query, 0, sizeof ( query )); + + #ifdef HAVE_LIBMYSQLCLIENT 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], @@ -226,6 +260,15 @@ AI_store_alert_to_db_thread ( void *arg ) pkt->pkt->pcap_header->len + pkt->pkt->payload_size, pkt->timestamp, pkt_data ); + #elif HAVE_LIBPQ + snprintf ( query, sizeof ( query ), "INSERT INTO %s (alert_id, pkt_len, timestamp, content) " + "VALUES (%lu, %u, timestamp with time zone 'epoch' + %lu * interval '1 second', '%s')", + outdb_config[PACKET_STREAMS_TABLE], + latest_alert_id, + pkt->pkt->pcap_header->len + pkt->pkt->payload_size, + pkt->timestamp, + pkt_data ); + #endif DB_free_result ((DB_result) DB_out_query ( query )); } diff --git a/postgresql.c b/postgresql.c index 8a01402..322cee5 100644 --- a/postgresql.c +++ b/postgresql.c @@ -72,24 +72,54 @@ __postgresql_do_init ( PGconn **__DB, BOOL is_out ) snprintf ( conninfo, conninfo_max_length, "dbname=%s", config->outdbname ); if ( config->outdbuser ) - sprintf ( conninfo, "%s user=%s", conninfo, config->outdbuser ); + { + if ( strlen ( config->outdbuser ) != 0 ) + { + sprintf ( conninfo, "%s user=%s", conninfo, config->outdbuser ); + } + } if ( config->outdbpass ) - sprintf ( conninfo, "%s password=%s", conninfo, config->outdbpass ); + { + if ( strlen ( config->outdbpass ) != 0 ) + { + sprintf ( conninfo, "%s password=%s", conninfo, config->outdbpass ); + } + } if ( config->outdbhost ) - sprintf ( conninfo, "%s hostaddr=%s", conninfo, config->outdbhost ); + { + if ( strlen ( config->outdbhost ) != 0 ) + { + 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 ( strlen ( config->dbuser ) != 0 ) + { + sprintf ( conninfo, "%s user=%s", conninfo, config->dbuser ); + } + } if ( config->dbpass ) - sprintf ( conninfo, "%s password=%s", conninfo, config->dbpass ); + { + if ( strlen ( config->dbpass ) != 0 ) + { + sprintf ( conninfo, "%s password=%s", conninfo, config->dbpass ); + } + } if ( config->dbhost ) - sprintf ( conninfo, "%s hostaddr=%s", conninfo, config->dbhost ); + { + if ( strlen ( config->dbhost ) != 0 ) + { + sprintf ( conninfo, "%s hostaddr=%s", conninfo, config->dbhost ); + } + } } if ( PQstatus ( *__DB = PQconnectdb ( conninfo )) != CONNECTION_OK ) @@ -108,10 +138,7 @@ __postgresql_do_query ( PGconn *__DB, const char *query ) AI_fatal_err ( "Fatal dynamic memory allocation error", __FILE__, __LINE__ ); if ( PQresultStatus ( res->res = PQexec( __DB, query )) != PGRES_TUPLES_OK ) - { - PQfinish ( __DB ); return NULL; - } ntuples = PQntuples ( res->res ); res->index = 0; diff --git a/schemas/mysql.sql b/schemas/mysql.sql index 8adaf32..ad62b06 100644 --- a/schemas/mysql.sql +++ b/schemas/mysql.sql @@ -26,16 +26,15 @@ CREATE TABLE ca_tcp_headers ( 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, +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(pkt_id), - foreign key(alert_id) references ca_alerts(alert_id) + primary key(cluster_id) ); DROP TABLE IF EXISTS ca_alerts; @@ -48,8 +47,8 @@ CREATE TABLE ca_alerts ( description varchar(255), classification varchar(255), timestamp datetime, - ip_hdr integer, - tcp_hdr integer, + ip_hdr integer default 0, + tcp_hdr integer default 0, cluster_id integer default 0, primary key(alert_id), @@ -58,15 +57,16 @@ CREATE TABLE ca_alerts ( 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, +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(cluster_id) + primary key(pkt_id), + foreign key(alert_id) references ca_alerts(alert_id) ); DROP TABLE IF EXISTS ca_correlated_alerts; diff --git a/schemas/postgresql.sql b/schemas/postgresql.sql index bae2377..f34fb32 100644 --- a/schemas/postgresql.sql +++ b/schemas/postgresql.sql @@ -9,18 +9,20 @@ CREATE TABLE ca_ipv4_headers ( ip_src_addr varchar(32), ip_dst_addr varchar(32) ); +INSERT INTO ca_ipv4_headers ( ip_hdr_id ) VALUES ( 0 ); DROP TABLE IF EXISTS ca_tcp_headers CASCADE; CREATE TABLE ca_tcp_headers ( tcp_hdr_id serial primary key, tcp_src_port integer, tcp_dst_port integer, - tcp_seq integer, - tcp_ack integer, + tcp_seq bigint, + tcp_ack bigint, tcp_flags integer, tcp_window integer, tcp_len integer ); +INSERT INTO ca_tcp_headers ( tcp_hdr_id ) VALUES ( 0 ); DROP TABLE IF EXISTS ca_clustered_alerts CASCADE; CREATE TABLE ca_clustered_alerts ( @@ -30,6 +32,7 @@ CREATE TABLE ca_clustered_alerts ( clustered_srcport varchar(255) default null, clustered_dstport varchar(255) default null ); +INSERT INTO ca_clustered_alerts ( cluster_id ) VALUES ( 0 ); DROP TABLE IF EXISTS ca_alerts CASCADE; CREATE TABLE ca_alerts ( @@ -41,8 +44,8 @@ CREATE TABLE ca_alerts ( description varchar(255), classification varchar(255), timestamp timestamp, - ip_hdr integer references ca_ipv4_headers(ip_hdr_id), - tcp_hdr integer references ca_tcp_headers(tcp_hdr_id), + ip_hdr integer default 0 references ca_ipv4_headers(ip_hdr_id), + tcp_hdr integer default 0 references ca_tcp_headers(tcp_hdr_id), cluster_id integer default 0 references ca_clustered_alerts(cluster_id) ); @@ -52,7 +55,7 @@ CREATE TABLE ca_packet_streams ( alert_id integer references ca_alerts(alert_id), pkt_len integer, timestamp timestamp, - content oid + content bytea ); DROP TABLE IF EXISTS ca_correlated_alerts CASCADE; diff --git a/spp_ai.c b/spp_ai.c index 367bd62..0dc9009 100644 --- a/spp_ai.c +++ b/spp_ai.c @@ -663,9 +663,9 @@ static AI_config * AI_parse(char *args) free ( match ); - if ( !strlen ( config->dbhost ) || !strlen ( config->dbname ) || !strlen ( config->dbpass ) || !strlen ( config->dbuser )) + if ( !strlen ( config->dbname )) { - AI_fatal_err ( "Database option used in config, but missing configuration option (all 'host', 'type', 'name', 'user', and 'password' option must be used)", __FILE__, __LINE__ ); + AI_fatal_err ( "Database option used in config, but missing configuration option (at least 'type' and 'name' options must be used)", __FILE__, __LINE__ ); } _dpd.logMsg(" Reading alerts from the database %s\n", config->dbname ); @@ -759,9 +759,9 @@ static AI_config * AI_parse(char *args) free ( match ); - if ( !strlen ( config->outdbhost ) || !strlen ( config->outdbname ) || !strlen ( config->outdbpass ) || !strlen ( config->outdbuser )) + if ( !strlen ( config->outdbname )) { - AI_fatal_err ( "Output database option used in config, but missing configuration option (all 'host', 'type', 'name', 'user', and 'password' options must be used)", __FILE__, __LINE__ ); + AI_fatal_err ( "Output database option used in config, but missing configuration option (at least 'type' and 'name' options must be used)", __FILE__, __LINE__ ); } AI_outdb_mutex_initialize();