2010-08-14 14:30:41 +02:00
/*
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* Filename : spp_ai . c
*
* Description : Main file for the spp_ai Snort preprocessor module
*
* Version : 0.1
* Created : 26 / 07 / 2010 11 : 00 : 41
* 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"
# include "sfPolicyUserData.h"
2010-10-03 04:18:43 +02:00
# include "sf_preproc_info.h"
2010-08-14 14:30:41 +02:00
2010-10-04 17:48:07 +02:00
# include <errno.h>
2010-08-14 14:30:41 +02:00
# include <stdlib.h>
# include <string.h>
2010-09-04 21:33:53 +02:00
/** \defgroup spp_ai Main file for spp_ai module
* @ { */
2010-09-16 02:00:02 +02:00
AI_snort_alert * ( * get_alerts ) ( void ) ;
2010-09-21 21:47:48 +02:00
AI_config * config = NULL ;
2010-09-16 02:00:02 +02:00
2010-08-14 14:30:41 +02:00
tSfPolicyUserContextId ex_config = NULL ;
2010-09-04 21:33:53 +02:00
static void * ( * alertparser_thread ) ( void * ) = NULL ;
2010-08-14 14:30:41 +02:00
# ifdef SNORT_RELOAD
tSfPolicyUserContextId ex_swap_config = NULL ;
# endif
static void AI_init ( char * ) ;
static void AI_process ( void * , void * ) ;
static AI_config * AI_parse ( char * ) ;
# ifdef SNORT_RELOAD
static void AI_reload ( char * ) ;
static int AI_reloadSwapPolicyFree ( tSfPolicyUserContextId , tSfPolicyId , void * ) ;
static void * AI_reloadSwap ( void ) ;
static void AI_reloadSwapFree ( void * ) ;
# endif
2010-10-03 04:18:43 +02:00
/**
* \ brief Function called when the module experiences a fatal error
* \ param msg Error message
* \ param file File where the error occurred
* \ param line Line number where the error occurred
*/
void
AI_fatal_err ( const char * msg , const char * file , const int line )
{
_dpd . fatalMsg ( " %s: %s at %s:%d (%s) \n " ,
PREPROC_NAME , msg , file , line ,
( ( errno ! = 0 ) ? strerror ( errno ) : " " ) ) ;
} /* ----- end of function AI_fatal_err ----- */
2010-08-14 14:30:41 +02:00
/**
* \ brief Set up the preprocessor module
*/
void AI_setup ( void )
{
# ifndef SNORT_RELOAD
_dpd . registerPreproc ( " ai " , AI_init ) ;
# else
_dpd . registerPreproc ( " ai " , AI_init , AI_reload ,
AI_reloadSwap , AI_reloadSwapFree ) ;
# endif
DEBUG_WRAP ( _dpd . debugMsg ( DEBUG_PLUGIN , " Preprocessor: AI is setup \n " ) ; ) ;
} /* ----- end of function AI_setup ----- */
/**
* \ brief Initialize the preprocessor module
* \ param args Configuration arguments passed to the module
*/
static void AI_init ( char * args )
{
pthread_t cleanup_thread ,
2010-09-11 02:12:39 +02:00
logparse_thread ,
2010-10-07 12:19:21 +02:00
webserv_thread ,
2010-10-21 17:36:47 +02:00
neural_thread ,
2010-09-11 02:12:39 +02:00
correlation_thread ;
2010-08-14 14:30:41 +02:00
tSfPolicyId policy_id = _dpd . getParserPolicy ( ) ;
_dpd . logMsg ( " AI dynamic preprocessor configuration \n " ) ;
if ( ex_config = = NULL )
{
ex_config = sfPolicyConfigCreate ( ) ;
if ( ex_config = = NULL )
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Could not allocate configuration struct " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
config = AI_parse ( args ) ;
sfPolicyUserPolicySet ( ex_config , policy_id ) ;
sfPolicyUserDataSetCurrent ( ex_config , config ) ;
2010-10-26 21:58:34 +02:00
/* Initialize the extra correlation modules */
AI_init_corr_modules ( ) ;
2010-09-11 02:12:39 +02:00
/* If the hash_cleanup_interval or stream_expire_interval options are set to zero,
2010-08-14 14:30:41 +02:00
* no cleanup will be made on the streams */
if ( config - > hashCleanupInterval ! = 0 & & config - > streamExpireInterval ! = 0 )
{
if ( pthread_create ( & cleanup_thread , NULL , AI_hashcleanup_thread , config ) ! = 0 )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Failed to create the hash cleanup thread " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
}
2010-09-11 02:12:39 +02:00
/* If the correlation_graph_interval option is set to zero, no correlation
* algorithm will be run over the alerts */
if ( config - > correlationGraphInterval ! = 0 )
{
if ( pthread_create ( & correlation_thread , NULL , AI_alert_correlation_thread , config ) ! = 0 )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Failed to create the alert correlation thread " , __FILE__ , __LINE__ ) ;
2010-09-11 02:12:39 +02:00
}
}
2010-08-14 14:30:41 +02:00
if ( strlen ( config - > alertfile ) > 0 )
{
2010-09-04 21:33:53 +02:00
if ( pthread_create ( & logparse_thread , NULL , alertparser_thread , config ) ! = 0 )
2010-08-14 14:30:41 +02:00
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Failed to create the alert parser thread " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
}
2010-10-07 12:19:21 +02:00
/* If webserv_port is != 0, start the web server */
if ( config - > webserv_port ! = 0 )
{
if ( pthread_create ( & webserv_thread , NULL , AI_webserv_thread , NULL ) ! = 0 )
{
AI_fatal_err ( " Failed to create the web server thread " , __FILE__ , __LINE__ ) ;
}
}
2010-10-21 17:36:47 +02:00
/* If neural_network_training_interval != 0, start the thread for the neural network */
if ( config - > neuralNetworkTrainingInterval ! = 0 )
{
if ( pthread_create ( & neural_thread , NULL , AI_neural_thread , NULL ) ! = 0 )
{
AI_fatal_err ( " Failed to create the neural network thread " , __FILE__ , __LINE__ ) ;
}
}
2010-11-23 18:42:20 +01:00
2010-08-14 14:30:41 +02:00
/* Register the preprocessor function, Transport layer, ID 10000 */
_dpd . addPreproc ( AI_process , PRIORITY_TRANSPORT , 10000 , PROTO_BIT__TCP | PROTO_BIT__UDP ) ;
DEBUG_WRAP ( _dpd . debugMsg ( DEBUG_PLUGIN , " Preprocessor: AI is initialized \n " ) ; ) ;
} /* ----- end of function AI_init ----- */
/**
* \ brief Parse the arguments passed to the module saving them to a valid configuration struct
* \ param args Arguments passed to the module
* \ return Pointer to AI_config keeping the configuration for the module
*/
static AI_config * AI_parse ( char * args )
{
char * arg ;
char * match ;
2010-11-20 16:47:57 +01:00
char alertfile [ 1024 ] = { 0 } ,
alert_history_file [ 1024 ] = { 0 } ,
clusterfile [ 1024 ] = { 0 } ,
corr_alerts_dir [ 1024 ] = { 0 } ,
corr_modules_dir [ 1024 ] = { 0 } ,
corr_rules_dir [ 1024 ] = { 0 } ,
webserv_dir [ 1024 ] = { 0 } ,
webserv_banner [ 1024 ] = { 0 } ;
2010-08-14 14:30:41 +02:00
char * * matches = NULL ;
int nmatches = 0 ;
2010-09-14 19:24:03 +02:00
int i ;
int offset ;
int len ;
double corr_threshold_coefficient = DEFAULT_CORR_THRESHOLD ;
2010-08-14 14:30:41 +02:00
uint32_t netmask ;
2010-09-14 19:24:03 +02:00
int min_val ;
int max_val ;
char label [ 256 ] ;
cluster_type type ;
2010-08-14 14:30:41 +02:00
hierarchy_node * * hierarchy_nodes = NULL ;
int n_hierarchy_nodes = 0 ;
2010-10-14 02:45:31 +02:00
unsigned short webserv_port = 0 ;
2010-10-25 17:39:44 +02:00
unsigned long alertfile_len = 0 ,
alert_bufsize = 0 ,
alert_clustering_interval = 0 ,
alert_correlation_weight = 0 ,
2010-10-14 02:45:31 +02:00
alert_history_file_len = 0 ,
alert_serialization_interval = 0 ,
bayesian_correlation_cache_validity = 0 ,
2010-10-25 17:39:44 +02:00
bayesian_correlation_interval = 0 ,
cleanup_interval = 0 ,
2010-10-14 02:45:31 +02:00
clusterfile_len = 0 ,
cluster_max_alert_interval = 0 ,
corr_alerts_dir_len = 0 ,
2010-10-26 21:58:34 +02:00
corr_modules_dir_len = 0 ,
2010-10-25 17:39:44 +02:00
corr_rules_dir_len = 0 ,
2010-10-14 02:45:31 +02:00
correlation_graph_interval = 0 ,
2010-10-25 17:39:44 +02:00
database_parsing_interval = 0 ,
2010-10-21 17:36:47 +02:00
manual_correlations_parsing_interval = 0 ,
2010-11-20 16:47:57 +01:00
neural_clustering_interval = 0 ,
2010-10-21 17:36:47 +02:00
neural_network_training_interval = 0 ,
2010-10-25 17:39:44 +02:00
neural_train_steps = 0 ,
output_neurons_per_side = 0 ,
stream_expire_interval = 0 ,
webserv_banner_len = 0 ,
webserv_dir_len = 0 ;
2010-08-14 14:30:41 +02:00
2010-09-14 19:24:03 +02:00
BOOL has_cleanup_interval = false ,
has_stream_expire_interval = false ,
has_correlation_interval = false ,
has_corr_alerts_dir = false ,
2010-10-26 21:58:34 +02:00
has_corr_modules_dir = false ,
2010-09-14 19:24:03 +02:00
has_database_interval = false ,
2010-10-07 12:19:21 +02:00
has_webserv_dir = false ,
has_webserv_banner = false ,
2010-09-14 19:24:03 +02:00
has_alertfile = false ,
has_clusterfile = false ,
has_corr_rules_dir = false ,
has_clustering = false ,
2010-09-20 14:39:08 +02:00
has_database_log = false ,
2010-09-29 12:24:30 +02:00
has_database_output = false ,
2010-09-20 14:39:08 +02:00
has_alert_history_file = false ;
2010-08-14 14:30:41 +02:00
if ( ! ( config = ( AI_config * ) malloc ( sizeof ( AI_config ) ) ) )
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Could not allocate configuration struct " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
memset ( config , 0 , sizeof ( AI_config ) ) ;
/* Parsing the hashtable_cleanup_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " hashtable_cleanup_interval " ) ) )
{
has_cleanup_interval = true ;
for ( arg + = strlen ( " hashtable_cleanup_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Hashtable_cleanup_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
cleanup_interval = strtoul ( arg , NULL , 10 ) ;
config - > hashCleanupInterval = cleanup_interval ;
_dpd . logMsg ( " Hash table cleanup interval: %d \n " , config - > hashCleanupInterval ) ;
}
/* Parsing the tcp_stream_expire_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " tcp_stream_expire_interval " ) ) )
{
has_stream_expire_interval = true ;
for ( arg + = strlen ( " tcp_stream_expire_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " tcp_stream_expire_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
stream_expire_interval = strtoul ( arg , NULL , 10 ) ;
config - > streamExpireInterval = stream_expire_interval ;
_dpd . logMsg ( " TCP stream expire interval: %d \n " , config - > streamExpireInterval ) ;
}
/* Parsing the alert_clustering_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " alert_clustering_interval " ) ) )
{
for ( arg + = strlen ( " alert_clustering_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " alert_clustering_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
alert_clustering_interval = strtoul ( arg , NULL , 10 ) ;
config - > alertClusteringInterval = alert_clustering_interval ;
_dpd . logMsg ( " Alert clustering interval: %d \n " , config - > alertClusteringInterval ) ;
}
2010-09-04 21:33:53 +02:00
/* Parsing the database_parsing_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " database_parsing_interval " ) ) )
{
has_database_interval = true ;
for ( arg + = strlen ( " database_parsing_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " database_parsing_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-09-04 21:33:53 +02:00
}
database_parsing_interval = strtoul ( arg , NULL , 10 ) ;
config - > databaseParsingInterval = database_parsing_interval ;
_dpd . logMsg ( " Database parsing interval: %d \n " , config - > databaseParsingInterval ) ;
}
2010-09-11 02:12:39 +02:00
/* Parsing the correlation_graph_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " correlation_graph_interval " ) ) )
{
has_correlation_interval = true ;
for ( arg + = strlen ( " correlation_graph_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " correlation_graph_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-09-11 02:12:39 +02:00
}
correlation_graph_interval = strtoul ( arg , NULL , 10 ) ;
config - > correlationGraphInterval = correlation_graph_interval ;
_dpd . logMsg ( " Correlation graph thread interval: %d \n " , config - > correlationGraphInterval ) ;
}
2010-09-21 16:27:46 +02:00
/* Parsing the alert_serialization_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " alert_serialization_interval " ) ) )
{
for ( arg + = strlen ( " alert_serialization_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " alert_serialization_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-09-21 16:27:46 +02:00
}
alert_serialization_interval = strtoul ( arg , NULL , 10 ) ;
config - > alertSerializationInterval = alert_serialization_interval ;
_dpd . logMsg ( " Alert serialization thread interval: %d \n " , config - > correlationGraphInterval ) ;
}
/* Parsing the alert_bufsize option */
if ( ( arg = ( char * ) strcasestr ( args , " alert_bufsize " ) ) )
{
for ( arg + = strlen ( " alert_bufsize " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " alert_bufsize option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-09-21 16:27:46 +02:00
}
alert_bufsize = strtoul ( arg , NULL , 10 ) ;
config - > alert_bufsize = alert_bufsize ;
_dpd . logMsg ( " Alert buffer size: %d \n " , config - > alert_bufsize ) ;
}
2010-10-07 12:19:21 +02:00
/* Parsing the webserv_port option */
if ( ( arg = ( char * ) strcasestr ( args , " webserv_port " ) ) )
{
for ( arg + = strlen ( " webserv_port " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
AI_fatal_err ( " webserv_port option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
}
webserv_port = ( unsigned short ) strtoul ( arg , NULL , 10 ) ;
config - > webserv_port = webserv_port ;
} else {
config - > webserv_port = DEFAULT_WEBSERV_PORT ;
}
_dpd . logMsg ( " Web server port: %d \n " , config - > webserv_port ) ;
2010-09-14 19:24:03 +02:00
/* Parsing the correlation_threshold_coefficient option */
if ( ( arg = ( char * ) strcasestr ( args , " correlation_threshold_coefficient " ) ) )
{
for ( arg + = strlen ( " correlation_threshold_coefficient " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " correlation_threshold_coefficient option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-09-14 19:24:03 +02:00
}
corr_threshold_coefficient = strtod ( arg , NULL ) ;
}
config - > correlationThresholdCoefficient = corr_threshold_coefficient ;
2010-10-07 12:19:21 +02:00
_dpd . logMsg ( " Correlation threshold coefficient: %f \n " , corr_threshold_coefficient ) ;
2010-09-14 19:24:03 +02:00
2010-09-23 21:57:20 +02:00
/* Parsing the bayesian_correlation_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " bayesian_correlation_interval " ) ) )
{
for ( arg + = strlen ( " bayesian_correlation_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " bayesian_correlation_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-09-23 21:57:20 +02:00
}
bayesian_correlation_interval = strtoul ( arg , NULL , 10 ) ;
config - > bayesianCorrelationInterval = bayesian_correlation_interval ;
} else {
bayesian_correlation_interval = DEFAULT_BAYESIAN_CORRELATION_INTERVAL ;
}
config - > bayesianCorrelationInterval = bayesian_correlation_interval ;
_dpd . logMsg ( " Bayesian correlation interval: %u \n " , config - > bayesianCorrelationInterval ) ;
2010-10-14 02:45:31 +02:00
/* Parsing the manual_correlations_parsing_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " manual_correlations_parsing_interval " ) ) )
{
for ( arg + = strlen ( " manual_correlations_parsing_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
AI_fatal_err ( " manual_correlations_parsing_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
}
manual_correlations_parsing_interval = strtoul ( arg , NULL , 10 ) ;
} else {
manual_correlations_parsing_interval = DEFAULT_MANUAL_CORRELATIONS_PARSING_INTERVAL ;
}
config - > manualCorrelationsParsingInterval = manual_correlations_parsing_interval ;
_dpd . logMsg ( " Manual correlations parsing interval: %u \n " , config - > manualCorrelationsParsingInterval ) ;
2010-09-23 21:57:20 +02:00
/* Parsing the bayesian_correlation_cache_validity option */
if ( ( arg = ( char * ) strcasestr ( args , " bayesian_correlation_cache_validity " ) ) )
{
for ( arg + = strlen ( " bayesian_correlation_cache_validity " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " bayesian_correlation_cache_validity option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-09-23 21:57:20 +02:00
}
bayesian_correlation_cache_validity = strtoul ( arg , NULL , 10 ) ;
config - > bayesianCorrelationCacheValidity = bayesian_correlation_cache_validity ;
} else {
bayesian_correlation_cache_validity = DEFAULT_BAYESIAN_CORRELATION_CACHE_VALIDITY ;
}
config - > bayesianCorrelationCacheValidity = bayesian_correlation_cache_validity ;
_dpd . logMsg ( " Bayesian cache validity interval: %u \n " , config - > bayesianCorrelationCacheValidity ) ;
2010-09-29 12:24:30 +02:00
/* Parsing the cluster_max_alert_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " cluster_max_alert_interval " ) ) )
{
for ( arg + = strlen ( " cluster_max_alert_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " cluster_max_alert_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
2010-09-29 12:24:30 +02:00
}
cluster_max_alert_interval = strtoul ( arg , NULL , 10 ) ;
} else {
cluster_max_alert_interval = DEFAULT_CLUSTER_MAX_ALERT_INTERVAL ;
}
config - > clusterMaxAlertInterval = cluster_max_alert_interval ;
_dpd . logMsg ( " Cluster alert max interval: %u \n " , config - > clusterMaxAlertInterval ) ;
2010-10-21 17:36:47 +02:00
/* Parsing the neural_network_training_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " neural_network_training_interval " ) ) )
{
for ( arg + = strlen ( " neural_network_training_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
AI_fatal_err ( " neural_network_training_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
}
neural_network_training_interval = strtoul ( arg , NULL , 10 ) ;
} else {
neural_network_training_interval = DEFAULT_NEURAL_NETWORK_TRAINING_INTERVAL ;
}
config - > neuralNetworkTrainingInterval = neural_network_training_interval ;
_dpd . logMsg ( " Neural network training interval: %u \n " , config - > neuralNetworkTrainingInterval ) ;
2010-11-20 16:47:57 +01:00
/* Parsing the neural_clustering_interval option */
if ( ( arg = ( char * ) strcasestr ( args , " neural_clustering_interval " ) ) )
{
for ( arg + = strlen ( " neural_clustering_interval " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
AI_fatal_err ( " neural_clustering_interval option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
}
neural_clustering_interval = strtoul ( arg , NULL , 10 ) ;
} else {
neural_clustering_interval = DEFAULT_NEURAL_CLUSTERING_INTERVAL ;
}
config - > neuralClusteringInterval = neural_clustering_interval ;
_dpd . logMsg ( " Neural network clustering interval: %u \n " , config - > neuralClusteringInterval ) ;
2010-10-21 17:36:47 +02:00
/* Parsing the output_neurons_per_side option */
if ( ( arg = ( char * ) strcasestr ( args , " output_neurons_per_side " ) ) )
{
for ( arg + = strlen ( " output_neurons_per_side " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
AI_fatal_err ( " output_neurons_per_side option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
}
output_neurons_per_side = strtoul ( arg , NULL , 10 ) ;
} else {
output_neurons_per_side = DEFAULT_OUTPUT_NEURONS_PER_SIDE ;
}
config - > outputNeuronsPerSide = output_neurons_per_side ;
_dpd . logMsg ( " Output neurons per side: %u \n " , config - > outputNeuronsPerSide ) ;
2010-10-25 17:39:44 +02:00
/* Parsing the neural_train_steps option */
if ( ( arg = ( char * ) strcasestr ( args , " neural_train_steps " ) ) )
{
for ( arg + = strlen ( " neural_train_steps " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
AI_fatal_err ( " neural_train_steps option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
}
neural_train_steps = strtoul ( arg , NULL , 10 ) ;
} else {
neural_train_steps = DEFAULT_NEURAL_TRAIN_STEPS ;
}
config - > neural_train_steps = neural_train_steps ;
_dpd . logMsg ( " Neural train steps: %u \n " , config - > neural_train_steps ) ;
/* Parsing the alert_correlation_weight option */
if ( ( arg = ( char * ) strcasestr ( args , " alert_correlation_weight " ) ) )
{
for ( arg + = strlen ( " alert_correlation_weight " ) ;
* arg & & ( * arg < ' 0 ' | | * arg > ' 9 ' ) ;
arg + + ) ;
if ( ! ( * arg ) )
{
AI_fatal_err ( " alert_correlation_weight option used but "
" no value specified " , __FILE__ , __LINE__ ) ;
}
alert_correlation_weight = strtoul ( arg , NULL , 10 ) ;
} else {
alert_correlation_weight = DEFAULT_ALERT_CORRELATION_WEIGHT ;
}
config - > alert_correlation_weight = alert_correlation_weight ;
_dpd . logMsg ( " Alert correlation weight: %u \n " , config - > alert_correlation_weight ) ;
2010-08-14 14:30:41 +02:00
/* Parsing the alertfile option */
if ( ( arg = ( char * ) strcasestr ( args , " alertfile " ) ) )
{
for ( arg + = strlen ( " alertfile " ) ;
* arg & & * arg ! = ' " ' ;
arg + + ) ;
if ( ! ( * ( arg + + ) ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " alertfile option used but no filename specified " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
for ( alertfile [ ( + + alertfile_len ) - 1 ] = * arg ;
* arg & & * arg ! = ' " ' & & alertfile_len < 1024 ;
arg + + , alertfile [ ( + + alertfile_len ) - 1 ] = * arg ) ;
if ( alertfile [ 0 ] = = 0 | | alertfile_len < = 1 ) {
has_alertfile = false ;
} else {
if ( alertfile_len > = 1024 ) {
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " alertfile path too long ( >= 1024 ) " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
} else if ( strlen ( alertfile ) = = 0 ) {
has_alertfile = false ;
} else {
has_alertfile = true ;
2010-09-04 21:33:53 +02:00
alertparser_thread = AI_file_alertparser_thread ;
2010-08-14 14:30:41 +02:00
alertfile [ alertfile_len - 1 ] = 0 ;
strncpy ( config - > alertfile , alertfile , alertfile_len ) ;
_dpd . logMsg ( " alertfile path: %s \n " , config - > alertfile ) ;
}
}
}
2010-09-20 14:39:08 +02:00
/* Parsing the alert_history_file option */
if ( ( arg = ( char * ) strcasestr ( args , " alert_history_file " ) ) )
{
for ( arg + = strlen ( " alert_history_file " ) ;
* arg & & * arg ! = ' " ' ;
arg + + ) ;
if ( ! ( * ( arg + + ) ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " alert_history_file option used but no filename specified " , __FILE__ , __LINE__ ) ;
2010-09-20 14:39:08 +02:00
}
for ( alert_history_file [ ( + + alert_history_file_len ) - 1 ] = * arg ;
* arg & & * arg ! = ' " ' & & alert_history_file_len < 1024 ;
arg + + , alert_history_file [ ( + + alert_history_file_len ) - 1 ] = * arg ) ;
if ( alert_history_file [ 0 ] = = 0 | | alert_history_file_len < = 1 ) {
has_alert_history_file = false ;
} else {
if ( alert_history_file_len > = 1024 ) {
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " alert_history_file path too long ( >= 1024 ) " , __FILE__ , __LINE__ ) ;
2010-09-20 14:39:08 +02:00
} else if ( strlen ( alert_history_file ) = = 0 ) {
has_alert_history_file = false ;
} else {
has_alert_history_file = true ;
alert_history_file [ alert_history_file_len - 1 ] = 0 ;
strncpy ( config - > alert_history_file , alert_history_file , alert_history_file_len ) ;
_dpd . logMsg ( " alert_history_file path: %s \n " , config - > alert_history_file ) ;
}
}
}
2010-08-14 14:30:41 +02:00
/* Parsing the clusterfile option */
if ( ( arg = ( char * ) strcasestr ( args , " clusterfile " ) ) )
{
for ( arg + = strlen ( " clusterfile " ) ;
* arg & & * arg ! = ' " ' ;
arg + + ) ;
if ( ! ( * ( arg + + ) ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " clusterfile option used but no filename specified " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
for ( clusterfile [ ( + + clusterfile_len ) - 1 ] = * arg ;
* arg & & * arg ! = ' " ' & & clusterfile_len < 1024 ;
arg + + , clusterfile [ ( + + clusterfile_len ) - 1 ] = * arg ) ;
if ( clusterfile [ 0 ] = = 0 | | clusterfile_len < = 1 ) {
has_clusterfile = false ;
} else {
if ( clusterfile_len > = 1024 ) {
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " clusterfile path too long ( >= 1024 ) " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
} else if ( strlen ( clusterfile ) = = 0 ) {
has_clusterfile = false ;
} else {
has_clusterfile = true ;
clusterfile [ clusterfile_len - 1 ] = 0 ;
strncpy ( config - > clusterfile , clusterfile , clusterfile_len ) ;
_dpd . logMsg ( " clusterfile path: %s \n " , config - > clusterfile ) ;
}
}
}
2010-09-11 02:12:39 +02:00
/* Parsing the correlation_rules_dir option */
if ( ( arg = ( char * ) strcasestr ( args , " correlation_rules_dir " ) ) )
{
for ( arg + = strlen ( " correlation_rules_dir " ) ;
* arg & & * arg ! = ' " ' ;
arg + + ) ;
if ( ! ( * ( arg + + ) ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " correlation_rules_dir option used but no filename specified " , __FILE__ , __LINE__ ) ;
2010-09-11 02:12:39 +02:00
}
for ( corr_rules_dir [ ( + + corr_rules_dir_len ) - 1 ] = * arg ;
* arg & & * arg ! = ' " ' & & corr_rules_dir_len < 1024 ;
arg + + , corr_rules_dir [ ( + + corr_rules_dir_len ) - 1 ] = * arg ) ;
if ( corr_rules_dir [ 0 ] = = 0 | | corr_rules_dir_len < = 1 ) {
has_corr_rules_dir = false ;
} else {
if ( corr_rules_dir_len > = 1024 ) {
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " corr_rules_dir path too long ( >= 1024 ) " , __FILE__ , __LINE__ ) ;
2010-09-11 02:12:39 +02:00
} else if ( strlen ( corr_rules_dir ) = = 0 ) {
has_corr_rules_dir = false ;
} else {
has_corr_rules_dir = true ;
corr_rules_dir [ corr_rules_dir_len - 1 ] = 0 ;
strncpy ( config - > corr_rules_dir , corr_rules_dir , corr_rules_dir_len ) ;
_dpd . logMsg ( " corr_rules_dir path: %s \n " , config - > corr_rules_dir ) ;
}
}
}
2010-09-14 19:24:03 +02:00
/* Parsing the correlated_alerts_dir option */
if ( ( arg = ( char * ) strcasestr ( args , " correlated_alerts_dir " ) ) )
{
for ( arg + = strlen ( " correlated_alerts_dir " ) ;
* arg & & * arg ! = ' " ' ;
arg + + ) ;
if ( ! ( * ( arg + + ) ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " correlated_alerts_dir option used but no filename specified " , __FILE__ , __LINE__ ) ;
2010-09-14 19:24:03 +02:00
}
for ( corr_alerts_dir [ ( + + corr_alerts_dir_len ) - 1 ] = * arg ;
* arg & & * arg ! = ' " ' & & corr_alerts_dir_len < 1024 ;
arg + + , corr_alerts_dir [ ( + + corr_alerts_dir_len ) - 1 ] = * arg ) ;
if ( corr_alerts_dir [ 0 ] = = 0 | | corr_alerts_dir_len < = 1 ) {
has_corr_alerts_dir = false ;
} else {
if ( corr_alerts_dir_len > = 1024 ) {
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " correlated_alerts_dir path too long ( >= 1024 ) " , __FILE__ , __LINE__ ) ;
2010-09-14 19:24:03 +02:00
} else if ( strlen ( corr_alerts_dir ) = = 0 ) {
has_corr_alerts_dir = false ;
} else {
has_corr_alerts_dir = true ;
corr_alerts_dir [ corr_alerts_dir_len - 1 ] = 0 ;
strncpy ( config - > corr_alerts_dir , corr_alerts_dir , corr_alerts_dir_len ) ;
_dpd . logMsg ( " correlated_alerts_dir: %s \n " , config - > corr_alerts_dir ) ;
}
}
}
2010-10-07 12:19:21 +02:00
/* Parsing the webserv_dir option */
if ( ( arg = ( char * ) strcasestr ( args , " webserv_dir " ) ) )
{
for ( arg + = strlen ( " webserv_dir " ) ;
* arg & & * arg ! = ' " ' ;
arg + + ) ;
if ( ! ( * ( arg + + ) ) )
{
AI_fatal_err ( " webserv_dir option used but no filename specified " , __FILE__ , __LINE__ ) ;
}
for ( webserv_dir [ ( + + webserv_dir_len ) - 1 ] = * arg ;
* arg & & * arg ! = ' " ' & & webserv_dir_len < sizeof ( webserv_dir ) ;
arg + + , webserv_dir [ ( + + webserv_dir_len ) - 1 ] = * arg ) ;
if ( webserv_dir [ 0 ] = = 0 | | webserv_dir_len < = 1 ) {
has_webserv_dir = false ;
} else {
if ( webserv_dir_len > = sizeof ( webserv_dir ) ) {
AI_fatal_err ( " webserv_dir path too long ( >= 1024 ) " , __FILE__ , __LINE__ ) ;
} else if ( strlen ( webserv_dir ) = = 0 ) {
has_webserv_dir = false ;
} else {
has_webserv_dir = true ;
webserv_dir [ webserv_dir_len - 1 ] = 0 ;
strncpy ( config - > webserv_dir , webserv_dir , webserv_dir_len ) ;
}
}
}
if ( ! has_webserv_dir )
{
# ifndef HAVE_CONFIG_H
AI_fatal_err ( " Unable to read PREFIX from config.h " , __FILE__ , __LINE__ ) ;
# endif
snprintf ( config - > webserv_dir , sizeof ( config - > webserv_dir ) , " %s/share/snort_ai_preprocessor/htdocs " , PREFIX ) ;
}
/* Remove unnecessary '/' at the end of the web server directory */
for ( i = strlen ( config - > webserv_dir ) - 1 ; i > = 0 & & config - > webserv_dir [ i ] = = ' / ' ; i - - )
config - > webserv_dir [ i ] = 0 ;
_dpd . logMsg ( " webserv_dir: %s \n " , config - > webserv_dir ) ;
2010-11-20 16:47:57 +01:00
snprintf ( config - > neural_clusters_log , sizeof ( config - > neural_clusters_log ) , " %s/neural_clusters.xml " , config - > webserv_dir ) ;
_dpd . logMsg ( " neural_clusters_log: %s \n " , config - > neural_clusters_log ) ;
2010-10-26 21:58:34 +02:00
/* Parsing the corr_modules_dir option */
if ( ( arg = ( char * ) strcasestr ( args , " corr_modules_dir " ) ) )
{
for ( arg + = strlen ( " corr_modules_dir " ) ;
* arg & & * arg ! = ' " ' ;
arg + + ) ;
if ( ! ( * ( arg + + ) ) )
{
AI_fatal_err ( " corr_modules_dir option used but no filename specified " , __FILE__ , __LINE__ ) ;
}
for ( corr_modules_dir [ ( + + corr_modules_dir_len ) - 1 ] = * arg ;
* arg & & * arg ! = ' " ' & & corr_modules_dir_len < sizeof ( corr_modules_dir ) ;
arg + + , corr_modules_dir [ ( + + corr_modules_dir_len ) - 1 ] = * arg ) ;
if ( corr_modules_dir [ 0 ] = = 0 | | corr_modules_dir_len < = 1 ) {
has_corr_modules_dir = false ;
} else {
if ( corr_modules_dir_len > = sizeof ( corr_modules_dir ) ) {
AI_fatal_err ( " corr_modules_dir path too long ( >= 1024 ) " , __FILE__ , __LINE__ ) ;
} else if ( strlen ( corr_modules_dir ) = = 0 ) {
has_corr_modules_dir = false ;
} else {
has_corr_modules_dir = true ;
corr_modules_dir [ corr_modules_dir_len - 1 ] = 0 ;
strncpy ( config - > corr_modules_dir , corr_modules_dir , corr_modules_dir_len ) ;
}
}
}
if ( ! has_corr_modules_dir )
{
# ifndef HAVE_CONFIG_H
AI_fatal_err ( " Unable to read PREFIX from config.h " , __FILE__ , __LINE__ ) ;
# endif
snprintf ( config - > corr_modules_dir , sizeof ( config - > corr_modules_dir ) , " %s/share/snort_ai_preprocessor/corr_modules " , PREFIX ) ;
}
2010-10-21 17:36:47 +02:00
/* Neural network output file */
if ( config - > neuralNetworkTrainingInterval ! = 0 )
{
# ifndef HAVE_DB
AI_fatal_err ( " Neural network based correlation support set but the module was compiled with no database support "
" (recompile the module with database support or set the neural_network_training_interval option in snort.conf to 0 " ,
__FILE__ , __LINE__ ) ;
# endif
# ifndef HAVE_CONFIG_H
AI_fatal_err ( " Unable to read PREFIX from config.h " , __FILE__ , __LINE__ ) ;
# endif
snprintf ( config - > netfile , sizeof ( config - > netfile ) , " %s/share/snort_ai_preprocessor/som.dat " , PREFIX ) ;
}
2010-10-07 12:19:21 +02:00
/* Parsing the webserv_banner option */
if ( ( arg = ( char * ) strcasestr ( args , " webserv_banner " ) ) )
{
for ( arg + = strlen ( " webserv_banner " ) ;
* arg & & * arg ! = ' " ' ;
arg + + ) ;
if ( ! ( * ( arg + + ) ) )
{
AI_fatal_err ( " webserv_banner option used but no value specified " , __FILE__ , __LINE__ ) ;
}
for ( webserv_banner [ ( + + webserv_banner_len ) - 1 ] = * arg ;
* arg & & * arg ! = ' " ' & & webserv_banner_len < sizeof ( webserv_banner ) ;
arg + + , webserv_banner [ ( + + webserv_banner_len ) - 1 ] = * arg ) ;
if ( webserv_banner [ 0 ] = = 0 | | webserv_banner_len < = 1 ) {
has_webserv_banner = false ;
} else {
if ( webserv_banner_len > = sizeof ( webserv_banner ) ) {
AI_fatal_err ( " webserv_banner path too long ( >= 1024 ) " , __FILE__ , __LINE__ ) ;
} else if ( strlen ( webserv_banner ) = = 0 ) {
has_webserv_banner = false ;
} else {
has_webserv_banner = true ;
webserv_banner [ webserv_banner_len - 1 ] = 0 ;
strncpy ( config - > webserv_banner , webserv_banner , webserv_banner_len ) ;
}
}
}
if ( ! has_webserv_banner )
{
strncpy ( config - > webserv_banner , DEFAULT_WEBSERV_BANNER , webserv_banner_len ) ;
}
_dpd . logMsg ( " webserv_banner: %s \n " , config - > webserv_banner ) ;
2010-09-04 21:33:53 +02:00
/* Parsing database option */
2010-09-29 12:24:30 +02:00
if ( preg_match ( " \\ s+database \\ s* \\ ( \\ s*([^ \\ )]+) \\ ) " , args , & matches , & nmatches ) > 0 )
2010-09-04 21:33:53 +02:00
{
if ( ! has_database_log )
has_database_log = true ;
match = strdup ( matches [ 0 ] ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
if ( preg_match ( " type \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
2010-09-16 17:11:46 +02:00
if ( strcasecmp ( matches [ 0 ] , " mysql " ) & & strcasecmp ( matches [ 0 ] , " postgresql " ) )
2010-09-04 21:33:53 +02:00
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Not supported database type in configuration (supported types: mysql, postgresql) " , __FILE__ , __LINE__ ) ;
2010-09-04 21:33:53 +02:00
}
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( preg_match ( " name \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
strncpy ( config - > dbname , matches [ 0 ] , sizeof ( config - > dbname ) ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( preg_match ( " user \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
strncpy ( config - > dbuser , matches [ 0 ] , sizeof ( config - > dbuser ) ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( preg_match ( " password \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
strncpy ( config - > dbpass , matches [ 0 ] , sizeof ( config - > dbpass ) ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( preg_match ( " host \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
strncpy ( config - > dbhost , matches [ 0 ] , sizeof ( config - > dbhost ) ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
free ( match ) ;
2010-10-05 04:01:35 +02:00
if ( ! strlen ( config - > dbname ) )
2010-09-04 21:33:53 +02:00
{
2010-10-05 04:01:35 +02:00
AI_fatal_err ( " Database option used in config, but missing configuration option (at least 'type' and 'name' options must be used) " , __FILE__ , __LINE__ ) ;
2010-09-04 21:33:53 +02:00
}
2010-09-29 12:24:30 +02:00
_dpd . logMsg ( " Reading alerts from the database %s \n " , config - > dbname ) ;
}
/* Parsing output_database option */
2010-10-01 19:32:34 +02:00
config - > outdbtype = outdb_none ;
2010-09-29 12:24:30 +02:00
if ( preg_match ( " \\ s*output_database \\ s* \\ ( \\ s*([^ \\ )]+) \\ ) " , args , & matches , & nmatches ) > 0 )
{
if ( ! has_database_output )
has_database_output = true ;
match = strdup ( matches [ 0 ] ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
if ( preg_match ( " type \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
if ( ! strcasecmp ( matches [ 0 ] , " mysql " ) )
{
# ifndef HAVE_LIBMYSQLCLIENT
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " mysql output set in 'output_database' option but the module was not compiled through --with-mysql option " , __FILE__ , __LINE__ ) ;
2010-09-29 12:24:30 +02:00
# else
2010-10-01 19:32:34 +02:00
config - > outdbtype = outdb_mysql ;
2010-09-29 12:24:30 +02:00
# endif
} else if ( ! strcasecmp ( matches [ 0 ] , " postgresql " ) ) {
# ifndef HAVE_LIBPQ
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " postgresql output set in 'output_database' option but the module was not compiled through --with-postgresql option " , __FILE__ , __LINE__ ) ;
2010-09-29 12:24:30 +02:00
# else
2010-10-01 19:32:34 +02:00
config - > outdbtype = outdb_postgresql ;
2010-09-29 12:24:30 +02:00
# endif
2010-10-01 19:32:34 +02:00
} else {
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Not supported database in configuration (supported types: mysql, postgresql) " , __FILE__ , __LINE__ ) ;
2010-09-29 12:24:30 +02:00
}
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( preg_match ( " name \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
strncpy ( config - > outdbname , matches [ 0 ] , sizeof ( config - > outdbname ) ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( preg_match ( " user \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
strncpy ( config - > outdbuser , matches [ 0 ] , sizeof ( config - > outdbuser ) ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( preg_match ( " password \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
strncpy ( config - > outdbpass , matches [ 0 ] , sizeof ( config - > outdbpass ) ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( preg_match ( " host \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
strncpy ( config - > outdbhost , matches [ 0 ] , sizeof ( config - > outdbhost ) ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
free ( match ) ;
2010-10-05 04:01:35 +02:00
if ( ! strlen ( config - > outdbname ) )
2010-09-29 12:24:30 +02:00
{
2010-10-05 04:01:35 +02:00
AI_fatal_err ( " Output database option used in config, but missing configuration option (at least 'type' and 'name' options must be used) " , __FILE__ , __LINE__ ) ;
2010-09-29 12:24:30 +02:00
}
2010-10-02 17:46:15 +02:00
AI_outdb_mutex_initialize ( ) ;
2010-09-29 12:24:30 +02:00
_dpd . logMsg ( " Saving output alerts to the database %s \n " , config - > outdbname ) ;
2010-09-04 21:33:53 +02:00
}
2010-09-29 12:24:30 +02:00
2010-08-14 14:30:41 +02:00
/* Parsing cluster options */
while ( preg_match ( " \\ s*(cluster \\ s* \\ ( \\ s*)([^ \\ )]+) \\ ) " , args , & matches , & nmatches ) > 0 )
{
2010-08-16 22:09:34 +02:00
if ( ! has_clustering )
has_clustering = true ;
2010-08-14 14:30:41 +02:00
memset ( label , 0 , sizeof ( label ) ) ;
min_val = - 1 ;
max_val = - 1 ;
type = none ;
match = strdup ( matches [ 1 ] ) ;
offset = ( int ) strcasestr ( args , matches [ 0 ] ) - ( int ) args ;
len = strlen ( matches [ 0 ] ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
if ( preg_match ( " class \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
if ( ! strcasecmp ( matches [ 0 ] , " src_port " ) )
type = src_port ;
else if ( ! strcasecmp ( matches [ 0 ] , " dst_port " ) )
type = dst_port ;
else if ( ! strcasecmp ( matches [ 0 ] , " src_addr " ) )
type = src_addr ;
else if ( ! strcasecmp ( matches [ 0 ] , " dst_addr " ) )
type = dst_addr ;
else
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Unknown class type in configuration " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( preg_match ( " name \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
if ( strlen ( matches [ 0 ] ) > sizeof ( label ) )
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Label name too long in configuration " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
strncpy ( label , matches [ 0 ] , sizeof ( label ) ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( preg_match ( " range \\ s*= \\ s* \" ([^ \" ]+) \" " , match , & matches , & nmatches ) > 0 )
{
arg = strdup ( matches [ 0 ] ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
switch ( type )
{
case src_port :
case dst_port :
if ( preg_match ( " ^([0-9]+)-([0-9]+)$ " , arg , & matches , & nmatches ) > 0 )
{
min_val = strtoul ( matches [ 0 ] , NULL , 10 ) ;
max_val = strtoul ( matches [ 1 ] , NULL , 10 ) ;
2010-08-16 22:09:34 +02:00
if ( min_val > max_val )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Parse error in configuration: minval > maxval " , __FILE__ , __LINE__ ) ;
2010-08-16 22:09:34 +02:00
}
2010-08-14 14:30:41 +02:00
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
} else if ( preg_match ( " ^([0-9]+)$ " , arg , & matches , & nmatches ) > 0 ) {
min_val = strtoul ( matches [ 0 ] , NULL , 10 ) ;
max_val = min_val ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
} else {
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Unallowed format for a port range in configuration file " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
break ;
case src_addr :
case dst_addr :
if ( preg_match ( " ^([0-9]{1,3} \\ .[0-9]{1,3} \\ .[0-9]{1,3} \\ .[0-9]{1,3})/([0-9]{1,2})$ " , arg , & matches , & nmatches ) > 0 )
{
if ( ( min_val = inet_addr ( matches [ 0 ] ) ) = = INADDR_NONE )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Unallowed IPv4 format in configuration " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
netmask = strtoul ( matches [ 1 ] , NULL , 10 ) ;
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
if ( netmask > 32 )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " The netmask number of bits should be in [0,32] in configuration file " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
netmask = 1 < < ( ( 8 * sizeof ( uint32_t ) ) - netmask ) ;
min_val = ntohl ( min_val ) & ( ~ ( netmask - 1 ) ) ;
max_val = min_val | ( netmask - 1 ) ;
} else if ( preg_match ( " ^([0-9]{1,3} \\ .[0-9]{1,3} \\ .[0-9]{1,3} \\ .[0-9]{1,3})$ " , arg , & matches , & nmatches ) > 0 ) {
if ( ( min_val = inet_addr ( matches [ 0 ] ) ) = = INADDR_NONE )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Unallowed IPv4 format in configuration " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
min_val = ntohl ( min_val ) ;
max_val = min_val ;
} else {
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Invalid value for an IP address or a subnet in configuration " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
break ;
/* TODO Manage ranges and clusters for timestamps (and more?) here */
default :
break ;
}
if ( matches )
{
for ( i = 0 ; i < nmatches ; i + + )
free ( matches [ i ] ) ;
free ( matches ) ;
matches = NULL ;
}
if ( arg )
{
free ( arg ) ;
arg = NULL ;
}
}
for ( i = offset ; i < = strlen ( args ) ; i + + )
args [ i ] = args [ i + len ] ;
if ( min_val = = - 1 | | max_val = = - 1 | | type = = none | | strlen ( label ) = = 0 )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Invalid cluster in configuration \n All of the following fields are required: class, range, name " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
free ( match ) ;
match = NULL ;
}
if ( ! ( hierarchy_nodes = ( hierarchy_node * * ) realloc ( hierarchy_nodes , ( + + n_hierarchy_nodes ) * sizeof ( hierarchy_node ) ) ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Fatal dynamic memory allocation failure " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
free ( match ) ;
match = NULL ;
}
if ( ! ( hierarchy_nodes [ n_hierarchy_nodes - 1 ] = ( hierarchy_node * ) malloc ( sizeof ( hierarchy_node ) ) ) )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Fatal dynamic memory allocation failure " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
free ( match ) ;
match = NULL ;
}
hierarchy_nodes [ n_hierarchy_nodes - 1 ] - > type = type ;
hierarchy_nodes [ n_hierarchy_nodes - 1 ] - > min_val = min_val ;
hierarchy_nodes [ n_hierarchy_nodes - 1 ] - > max_val = max_val ;
hierarchy_nodes [ n_hierarchy_nodes - 1 ] - > nchildren = 0 ;
hierarchy_nodes [ n_hierarchy_nodes - 1 ] - > children = NULL ;
hierarchy_nodes [ n_hierarchy_nodes - 1 ] - > parent = NULL ;
strncpy ( hierarchy_nodes [ n_hierarchy_nodes - 1 ] - > label ,
label ,
sizeof ( hierarchy_nodes [ n_hierarchy_nodes - 1 ] - > label ) ) ;
free ( match ) ;
match = NULL ;
}
if ( ! has_cleanup_interval )
{
2010-08-16 22:09:34 +02:00
config - > hashCleanupInterval = DEFAULT_HASH_CLEANUP_INTERVAL ;
2010-08-14 14:30:41 +02:00
}
if ( ! has_stream_expire_interval )
{
2010-08-16 22:09:34 +02:00
config - > streamExpireInterval = DEFAULT_STREAM_EXPIRE_INTERVAL ;
2010-08-14 14:30:41 +02:00
}
2010-09-11 02:12:39 +02:00
if ( ! has_correlation_interval )
{
config - > correlationGraphInterval = DEFAULT_ALERT_CORRELATION_INTERVAL ;
}
2010-09-04 21:33:53 +02:00
if ( ! has_database_interval & & has_database_log )
{
config - > databaseParsingInterval = DEFAULT_DATABASE_INTERVAL ;
}
if ( ! has_alertfile & & ! has_database_log )
2010-08-14 14:30:41 +02:00
{
2010-08-16 22:09:34 +02:00
strncpy ( config - > alertfile , DEFAULT_ALERT_LOG_FILE , sizeof ( config - > alertfile ) ) ;
2010-09-04 21:33:53 +02:00
has_alertfile = true ;
alertparser_thread = AI_file_alertparser_thread ;
} else if ( has_database_log ) {
has_alertfile = false ;
2010-09-05 23:54:22 +02:00
2010-09-16 17:11:46 +02:00
# ifdef HAVE_DB
2010-09-14 19:24:03 +02:00
alertparser_thread = AI_db_alertparser_thread ;
2010-09-11 02:12:39 +02:00
# else
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Database logging enabled in config file, but the module was not compiled "
" with database support (recompile, i.e., with ./configure --with-mysql or --with-postgresql) " , __FILE__ , __LINE__ ) ;
2010-09-05 23:54:22 +02:00
# endif
2010-09-04 21:33:53 +02:00
} else if ( has_alertfile ) {
alertparser_thread = AI_file_alertparser_thread ;
2010-08-14 14:30:41 +02:00
}
2010-09-20 14:39:08 +02:00
if ( ! has_alert_history_file )
{
strncpy ( config - > alert_history_file , DEFAULT_ALERT_HISTORY_FILE , sizeof ( config - > alert_history_file ) ) ;
has_alert_history_file = true ;
}
2010-08-16 22:09:34 +02:00
if ( has_clustering )
2010-08-14 14:30:41 +02:00
{
if ( ! hierarchy_nodes )
{
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Cluster file specified in the configuration but no clusters were specified " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
2010-08-16 22:09:34 +02:00
if ( ! has_clusterfile )
{
strncpy ( config - > clusterfile , DEFAULT_CLUSTER_LOG_FILE , sizeof ( config - > clusterfile ) ) ;
}
2010-08-14 14:30:41 +02:00
if ( ! alert_clustering_interval )
{
2010-08-16 22:09:34 +02:00
config - > alertClusteringInterval = DEFAULT_ALERT_CLUSTERING_INTERVAL ;
2010-08-14 14:30:41 +02:00
}
2010-09-21 21:47:48 +02:00
AI_hierarchies_build ( hierarchy_nodes , n_hierarchy_nodes ) ;
2010-08-14 14:30:41 +02:00
}
2010-09-11 02:12:39 +02:00
if ( ! has_corr_rules_dir )
{
# ifndef HAVE_CONFIG_H
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Unable to read PREFIX from config.h " , __FILE__ , __LINE__ ) ;
2010-09-11 02:12:39 +02:00
# endif
if ( ! strcmp ( PREFIX , " /usr " ) | | ! strcmp ( PREFIX , " /usr/ " ) )
{
strncpy ( config - > corr_rules_dir , DEFAULT_CORR_RULES_DIR , sizeof ( DEFAULT_CORR_RULES_DIR ) ) ;
} else {
snprintf ( config - > corr_rules_dir , sizeof ( config - > corr_rules_dir ) , " %s/etc/corr_rules " , PREFIX ) ;
}
}
2010-09-29 12:24:30 +02:00
_dpd . logMsg ( " Using correlation rules from directory %s \n " , config - > corr_rules_dir ) ;
2010-09-11 02:12:39 +02:00
2010-09-14 19:24:03 +02:00
if ( ! has_corr_alerts_dir )
{
strncpy ( config - > corr_alerts_dir , DEFAULT_CORR_ALERTS_DIR , sizeof ( DEFAULT_CORR_ALERTS_DIR ) ) ;
}
2010-09-21 16:27:46 +02:00
if ( ! alert_serialization_interval )
{
config - > alertSerializationInterval = DEFAULT_ALERT_SERIALIZATION_INTERVAL ;
}
if ( ! alert_bufsize )
{
config - > alert_bufsize = DEFAULT_ALERT_BUFSIZE ;
}
2010-09-29 12:24:30 +02:00
_dpd . logMsg ( " Saving correlated alerts information in %s \n " , config - > corr_alerts_dir ) ;
2010-09-14 19:24:03 +02:00
2010-09-04 21:33:53 +02:00
if ( has_database_log )
{
2010-09-16 17:11:46 +02:00
# ifdef HAVE_DB
2010-09-11 02:12:39 +02:00
get_alerts = AI_db_get_alerts ;
# else
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Using database alert log, but the module was not compiled with database support " , __FILE__ , __LINE__ ) ;
2010-09-05 23:54:22 +02:00
# endif
2010-09-04 21:33:53 +02:00
} else {
get_alerts = AI_get_alerts ;
}
2010-08-14 14:30:41 +02:00
return config ;
} /* ----- end of function AI_config ----- */
/**
* \ brief Function executed every time the module receives a packet to be processed
* \ param pkt void * pointer to the packet data
* \ param context void * pointer to the context
*/
void AI_process ( void * pkt , void * context )
{
SFSnortPacket * p = ( SFSnortPacket * ) pkt ;
2010-09-21 21:47:48 +02:00
AI_config * _config ;
2010-08-14 14:30:41 +02:00
sfPolicyUserPolicySet ( ex_config , _dpd . getRuntimePolicy ( ) ) ;
2010-09-21 21:47:48 +02:00
_config = ( AI_config * ) sfPolicyUserDataGetCurrent ( ex_config ) ;
2010-08-14 14:30:41 +02:00
2010-09-21 21:47:48 +02:00
if ( _config = = NULL )
2010-08-14 14:30:41 +02:00
return ;
if ( ! p - > ip4_header | | p - > ip4_header - > proto ! = IPPROTO_TCP | | ! p - > tcp_header )
{
/* Not for me, return */
return ;
}
AI_pkt_enqueue ( pkt ) ;
} /* ----- end of function AI_process ----- */
# ifdef SNORT_RELOAD
static void AI_reload ( char * args )
{
2010-09-21 21:47:48 +02:00
/* AI_config *config; */
2010-08-14 14:30:41 +02:00
tSfPolicyId policy_id = _dpd . getParserPolicy ( ) ;
_dpd . logMsg ( " AI dynamic preprocessor configuration \n " ) ;
if ( ex_swap_config = = NULL )
{
ex_swap_config = sfPolicyConfigCreate ( ) ;
if ( ex_swap_config = = NULL )
2010-10-03 04:18:43 +02:00
AI_fatal_err ( " Could not allocate configuration struct " , __FILE__ , __LINE__ ) ;
2010-08-14 14:30:41 +02:00
}
config = AI_parse ( args ) ;
sfPolicyUserPolicySet ( ex_swap_config , policy_id ) ;
sfPolicyUserDataSetCurrent ( ex_swap_config , config ) ;
/* Register the preprocessor function, Transport layer, ID 10000 */
_dpd . addPreproc ( AI_process , PRIORITY_TRANSPORT , 10000 , PROTO_BIT__TCP | PROTO_BIT__UDP ) ;
DEBUG_WRAP ( _dpd . debugMsg ( DEBUG_PLUGIN , " Preprocessor: AI is initialized \n " ) ; ) ;
}
static int AI_reloadSwapPolicyFree ( tSfPolicyUserContextId config , tSfPolicyId policyId , void * data )
{
AI_config * policy_config = ( AI_config * ) data ;
sfPolicyUserDataClear ( config , policyId ) ;
free ( policy_config ) ;
return 0 ;
}
static void * AI_reloadSwap ( void )
{
tSfPolicyUserContextId old_config = ex_config ;
if ( ex_swap_config = = NULL )
return NULL ;
ex_config = ex_swap_config ;
ex_swap_config = NULL ;
return ( void * ) old_config ;
}
static void AI_reloadSwapFree ( void * data )
{
tSfPolicyUserContextId config = ( tSfPolicyUserContextId ) data ;
if ( data = = NULL )
return ;
sfPolicyUserDataIterate ( config , AI_reloadSwapPolicyFree ) ;
sfPolicyConfigDelete ( config ) ;
}
# endif
2010-09-04 21:33:53 +02:00
/** @} */