mirror of
https://github.com/BlackLight/Snort_AIPreproc.git
synced 2024-11-27 22:25:12 +01:00
Web interface done, web server fixed, pcap support
This commit is contained in:
parent
6c3e00bc8d
commit
7a73cdbc85
20 changed files with 4633 additions and 142 deletions
|
@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS=foreign no-dependencies
|
||||||
|
|
||||||
libdir = ${exec_prefix}/lib/snort_dynamicpreprocessor
|
libdir = ${exec_prefix}/lib/snort_dynamicpreprocessor
|
||||||
lib_LTLIBRARIES = libsf_ai_preproc.la
|
lib_LTLIBRARIES = libsf_ai_preproc.la
|
||||||
libsf_ai_preproc_la_CFLAGS = -I./uthash -I./include ${LIBXML2_INCLUDES} ${LIBGRAPH_INCLUDES} -DDYNAMIC_PLUGIN -D_XOPEN_SOURCE -D_GNU_SOURCE -fvisibility=hidden -fno-strict-aliasing -Wall -pedantic -pedantic-errors -std=c99 -fstack-protector
|
libsf_ai_preproc_la_CFLAGS = -I./uthash -I./base64 -I./include ${LIBXML2_INCLUDES} ${LIBGRAPH_INCLUDES} -DDYNAMIC_PLUGIN -D_XOPEN_SOURCE -D_GNU_SOURCE -fvisibility=hidden -fno-strict-aliasing -Wall -pedantic -pedantic-errors -std=c99 -fstack-protector
|
||||||
libsf_ai_preproc_la_LDFLAGS = -module -export-dynamic
|
libsf_ai_preproc_la_LDFLAGS = -module -export-dynamic
|
||||||
|
|
||||||
BUILT_SOURCES = \
|
BUILT_SOURCES = \
|
||||||
|
@ -18,6 +18,9 @@ include/sfPolicyUserData.c
|
||||||
libsf_ai_preproc_la_SOURCES = \
|
libsf_ai_preproc_la_SOURCES = \
|
||||||
alert_history.c \
|
alert_history.c \
|
||||||
alert_parser.c \
|
alert_parser.c \
|
||||||
|
base64/base64.c \
|
||||||
|
base64/cdecode.c \
|
||||||
|
base64/cencode.c \
|
||||||
bayesian.c \
|
bayesian.c \
|
||||||
cluster.c \
|
cluster.c \
|
||||||
correlation.c \
|
correlation.c \
|
||||||
|
@ -54,10 +57,10 @@ install-data-hook:
|
||||||
mkdir -p "${SHARE_PREFIX}/htdocs"
|
mkdir -p "${SHARE_PREFIX}/htdocs"
|
||||||
mkdir -p "${SHARE_PREFIX}/htdocs/js"
|
mkdir -p "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/index.html" "${SHARE_PREFIX}/htdocs"
|
install -m 0644 "${PWD}/htdocs/index.html" "${SHARE_PREFIX}/htdocs"
|
||||||
install -m 0755 "${PWD}/htdocs/test.cgi" "${SHARE_PREFIX}/htdocs"
|
install -m 0755 "${PWD}/htdocs/pcap.cgi" "${SHARE_PREFIX}/htdocs"
|
||||||
install -m 0644 "${PWD}/htdocs/js/Curry-1.0.1.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/Curry-1.0.1.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/dracula_algorithms.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/dracula_algorithms.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/dracula_graffle.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/dracula_graffle.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/dracula_graph.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/dracula_graph.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/raphael-min.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/raphael.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/seedrandom.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/seedrandom.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
|
|
22
Makefile.in
22
Makefile.in
|
@ -80,7 +80,9 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||||
libsf_ai_preproc_la_LIBADD =
|
libsf_ai_preproc_la_LIBADD =
|
||||||
am_libsf_ai_preproc_la_OBJECTS = libsf_ai_preproc_la-alert_history.lo \
|
am_libsf_ai_preproc_la_OBJECTS = libsf_ai_preproc_la-alert_history.lo \
|
||||||
libsf_ai_preproc_la-alert_parser.lo \
|
libsf_ai_preproc_la-alert_parser.lo \
|
||||||
libsf_ai_preproc_la-bayesian.lo libsf_ai_preproc_la-cluster.lo \
|
libsf_ai_preproc_la-base64.lo libsf_ai_preproc_la-cdecode.lo \
|
||||||
|
libsf_ai_preproc_la-cencode.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-correlation.lo libsf_ai_preproc_la-db.lo \
|
||||||
libsf_ai_preproc_la-mysql.lo libsf_ai_preproc_la-outdb.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-postgresql.lo libsf_ai_preproc_la-regex.lo \
|
||||||
|
@ -244,7 +246,7 @@ top_builddir = @top_builddir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||||
lib_LTLIBRARIES = libsf_ai_preproc.la
|
lib_LTLIBRARIES = libsf_ai_preproc.la
|
||||||
libsf_ai_preproc_la_CFLAGS = -I./uthash -I./include ${LIBXML2_INCLUDES} ${LIBGRAPH_INCLUDES} -DDYNAMIC_PLUGIN -D_XOPEN_SOURCE -D_GNU_SOURCE -fvisibility=hidden -fno-strict-aliasing -Wall -pedantic -pedantic-errors -std=c99 -fstack-protector
|
libsf_ai_preproc_la_CFLAGS = -I./uthash -I./base64 -I./include ${LIBXML2_INCLUDES} ${LIBGRAPH_INCLUDES} -DDYNAMIC_PLUGIN -D_XOPEN_SOURCE -D_GNU_SOURCE -fvisibility=hidden -fno-strict-aliasing -Wall -pedantic -pedantic-errors -std=c99 -fstack-protector
|
||||||
libsf_ai_preproc_la_LDFLAGS = -module -export-dynamic
|
libsf_ai_preproc_la_LDFLAGS = -module -export-dynamic
|
||||||
BUILT_SOURCES = \
|
BUILT_SOURCES = \
|
||||||
include/sf_dynamic_preproc_lib.c \
|
include/sf_dynamic_preproc_lib.c \
|
||||||
|
@ -257,6 +259,9 @@ include/sfPolicyUserData.c
|
||||||
libsf_ai_preproc_la_SOURCES = \
|
libsf_ai_preproc_la_SOURCES = \
|
||||||
alert_history.c \
|
alert_history.c \
|
||||||
alert_parser.c \
|
alert_parser.c \
|
||||||
|
base64/base64.c \
|
||||||
|
base64/cdecode.c \
|
||||||
|
base64/cencode.c \
|
||||||
bayesian.c \
|
bayesian.c \
|
||||||
cluster.c \
|
cluster.c \
|
||||||
correlation.c \
|
correlation.c \
|
||||||
|
@ -386,6 +391,15 @@ libsf_ai_preproc_la-alert_history.lo: alert_history.c
|
||||||
libsf_ai_preproc_la-alert_parser.lo: alert_parser.c
|
libsf_ai_preproc_la-alert_parser.lo: alert_parser.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-alert_parser.lo `test -f 'alert_parser.c' || echo '$(srcdir)/'`alert_parser.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-alert_parser.lo `test -f 'alert_parser.c' || echo '$(srcdir)/'`alert_parser.c
|
||||||
|
|
||||||
|
libsf_ai_preproc_la-base64.lo: base64/base64.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-base64.lo `test -f 'base64/base64.c' || echo '$(srcdir)/'`base64/base64.c
|
||||||
|
|
||||||
|
libsf_ai_preproc_la-cdecode.lo: base64/cdecode.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-cdecode.lo `test -f 'base64/cdecode.c' || echo '$(srcdir)/'`base64/cdecode.c
|
||||||
|
|
||||||
|
libsf_ai_preproc_la-cencode.lo: base64/cencode.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-cencode.lo `test -f 'base64/cencode.c' || echo '$(srcdir)/'`base64/cencode.c
|
||||||
|
|
||||||
libsf_ai_preproc_la-bayesian.lo: bayesian.c
|
libsf_ai_preproc_la-bayesian.lo: bayesian.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-bayesian.lo `test -f 'bayesian.c' || echo '$(srcdir)/'`bayesian.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-bayesian.lo `test -f 'bayesian.c' || echo '$(srcdir)/'`bayesian.c
|
||||||
|
|
||||||
|
@ -819,12 +833,12 @@ install-data-hook:
|
||||||
mkdir -p "${SHARE_PREFIX}/htdocs"
|
mkdir -p "${SHARE_PREFIX}/htdocs"
|
||||||
mkdir -p "${SHARE_PREFIX}/htdocs/js"
|
mkdir -p "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/index.html" "${SHARE_PREFIX}/htdocs"
|
install -m 0644 "${PWD}/htdocs/index.html" "${SHARE_PREFIX}/htdocs"
|
||||||
install -m 0755 "${PWD}/htdocs/test.cgi" "${SHARE_PREFIX}/htdocs"
|
install -m 0755 "${PWD}/htdocs/pcap.cgi" "${SHARE_PREFIX}/htdocs"
|
||||||
install -m 0644 "${PWD}/htdocs/js/Curry-1.0.1.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/Curry-1.0.1.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/dracula_algorithms.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/dracula_algorithms.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/dracula_graffle.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/dracula_graffle.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/dracula_graph.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/dracula_graph.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/raphael-min.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/raphael.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
install -m 0644 "${PWD}/htdocs/js/seedrandom.js" "${SHARE_PREFIX}/htdocs/js"
|
install -m 0644 "${PWD}/htdocs/js/seedrandom.js" "${SHARE_PREFIX}/htdocs/js"
|
||||||
|
|
||||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
|
4
TODO
4
TODO
|
@ -2,8 +2,6 @@
|
||||||
AVERAGE/HIGH PRIORITY:
|
AVERAGE/HIGH PRIORITY:
|
||||||
======================
|
======================
|
||||||
|
|
||||||
- Web interface
|
|
||||||
- Function names (private functions with _ or __ ?)
|
|
||||||
- Bayesian network
|
- Bayesian network
|
||||||
- Modules for correlation coefficients
|
- Modules for correlation coefficients
|
||||||
- Code profiling
|
- Code profiling
|
||||||
|
@ -36,4 +34,6 @@ DONE:
|
||||||
+ Save clusters and correlations to db
|
+ Save clusters and correlations to db
|
||||||
+ Uniformed error messages format
|
+ Uniformed error messages format
|
||||||
+ Full PostgreSQL support for output db
|
+ Full PostgreSQL support for output db
|
||||||
|
+ Web interface
|
||||||
|
+ Function names (private functions with _ or __ ?)
|
||||||
|
|
||||||
|
|
|
@ -463,7 +463,7 @@ AI_file_alertparser_thread ( void* arg )
|
||||||
* \return A copy of the alert log linked list
|
* \return A copy of the alert log linked list
|
||||||
*/
|
*/
|
||||||
PRIVATE AI_snort_alert*
|
PRIVATE AI_snort_alert*
|
||||||
_AI_copy_alerts ( AI_snort_alert *node )
|
__AI_copy_alerts ( AI_snort_alert *node )
|
||||||
{
|
{
|
||||||
AI_snort_alert *current = NULL, *next = NULL;
|
AI_snort_alert *current = NULL, *next = NULL;
|
||||||
|
|
||||||
|
@ -474,7 +474,7 @@ _AI_copy_alerts ( AI_snort_alert *node )
|
||||||
|
|
||||||
if ( node->next )
|
if ( node->next )
|
||||||
{
|
{
|
||||||
next = _AI_copy_alerts ( node->next );
|
next = __AI_copy_alerts ( node->next );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !( current = ( AI_snort_alert* ) malloc ( sizeof ( AI_snort_alert )) ))
|
if ( !( current = ( AI_snort_alert* ) malloc ( sizeof ( AI_snort_alert )) ))
|
||||||
|
@ -485,7 +485,7 @@ _AI_copy_alerts ( AI_snort_alert *node )
|
||||||
memcpy ( current, node, sizeof ( AI_snort_alert ));
|
memcpy ( current, node, sizeof ( AI_snort_alert ));
|
||||||
current->next = next;
|
current->next = next;
|
||||||
return current;
|
return current;
|
||||||
} /* ----- end of function _AI_copy_alerts ----- */
|
} /* ----- end of function __AI_copy_alerts ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -498,7 +498,7 @@ AI_get_alerts ()
|
||||||
AI_snort_alert *alerts_copy;
|
AI_snort_alert *alerts_copy;
|
||||||
|
|
||||||
pthread_mutex_lock ( &alert_mutex );
|
pthread_mutex_lock ( &alert_mutex );
|
||||||
alerts_copy = _AI_copy_alerts ( alerts );
|
alerts_copy = __AI_copy_alerts ( alerts );
|
||||||
pthread_mutex_unlock ( &alert_mutex );
|
pthread_mutex_unlock ( &alert_mutex );
|
||||||
|
|
||||||
return alerts_copy;
|
return alerts_copy;
|
||||||
|
|
|
@ -61,13 +61,13 @@ PRIVATE double k_exp_value = 0.0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE double
|
PRIVATE double
|
||||||
_AI_bayesian_correlation_function ( time_t ta, time_t tb )
|
__AI_bayesian_correlation_function ( time_t ta, time_t tb )
|
||||||
{
|
{
|
||||||
if ( k_exp_value == 0.0 )
|
if ( k_exp_value == 0.0 )
|
||||||
k_exp_value = - (double) (config->bayesianCorrelationInterval * config->bayesianCorrelationInterval) / log ( CUTOFF_Y_VALUE );
|
k_exp_value = - (double) (config->bayesianCorrelationInterval * config->bayesianCorrelationInterval) / log ( CUTOFF_Y_VALUE );
|
||||||
|
|
||||||
return exp ( -((ta - tb) * (ta - tb)) / k_exp_value );
|
return exp ( -((ta - tb) * (ta - tb)) / k_exp_value );
|
||||||
} /* ----- end of function _AI_bayesian_correlation_function ----- */
|
} /* ----- end of function __AI_bayesian_correlation_function ----- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Compute the correlation between two alerts, A -> B: p[A|B] = p[Corr(A,B)] / P[B]
|
* \brief Compute the correlation between two alerts, A -> B: p[A|B] = p[Corr(A,B)] / P[B]
|
||||||
|
@ -134,7 +134,7 @@ AI_alert_bayesian_correlation ( AI_snort_alert *a, AI_snort_alert *b )
|
||||||
{
|
{
|
||||||
is_a_correlated = true;
|
is_a_correlated = true;
|
||||||
corr_count++;
|
corr_count++;
|
||||||
corr += _AI_bayesian_correlation_function ( events_iterator_a->timestamp, events_iterator_b->timestamp );
|
corr += __AI_bayesian_correlation_function ( events_iterator_a->timestamp, events_iterator_b->timestamp );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
78
cluster.c
78
cluster.c
|
@ -61,7 +61,7 @@ PRIVATE pthread_mutex_t mutex;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE int
|
PRIVATE int
|
||||||
_heuristic_func ( cluster_type type )
|
__AI_heuristic_func ( cluster_type type )
|
||||||
{
|
{
|
||||||
AI_snort_alert *alert_iterator;
|
AI_snort_alert *alert_iterator;
|
||||||
attribute_key key;
|
attribute_key key;
|
||||||
|
@ -119,7 +119,7 @@ _heuristic_func ( cluster_type type )
|
||||||
}
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
} /* ----- end of function _heuristic_func ----- */
|
} /* ----- end of function __AI_heuristic_func ----- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Create a new clustering hierarchy node
|
* \brief Create a new clustering hierarchy node
|
||||||
|
@ -130,7 +130,7 @@ _heuristic_func ( cluster_type type )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE hierarchy_node*
|
PRIVATE hierarchy_node*
|
||||||
_hierarchy_node_new ( char *label, int min_val, int max_val )
|
__AI_hierarchy_node_new ( char *label, int min_val, int max_val )
|
||||||
{
|
{
|
||||||
hierarchy_node *n = NULL;
|
hierarchy_node *n = NULL;
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ _hierarchy_node_new ( char *label, int min_val, int max_val )
|
||||||
strncpy ( n->label, label, sizeof ( n->label ));
|
strncpy ( n->label, label, sizeof ( n->label ));
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
} /* ----- end of function _hierarchy_node_new ----- */
|
} /* ----- end of function __AI_hierarchy_node_new ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,7 +157,7 @@ _hierarchy_node_new ( char *label, int min_val, int max_val )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE void
|
PRIVATE void
|
||||||
_hierarchy_node_append ( hierarchy_node *parent, hierarchy_node *child )
|
__AI_hierarchy_node_append ( hierarchy_node *parent, hierarchy_node *child )
|
||||||
{
|
{
|
||||||
if ( !( parent->children = ( hierarchy_node** ) realloc ( parent->children, (++(parent->nchildren)) * sizeof ( hierarchy_node* )) ))
|
if ( !( parent->children = ( hierarchy_node** ) realloc ( parent->children, (++(parent->nchildren)) * sizeof ( hierarchy_node* )) ))
|
||||||
{
|
{
|
||||||
|
@ -166,7 +166,7 @@ _hierarchy_node_append ( hierarchy_node *parent, hierarchy_node *child )
|
||||||
|
|
||||||
parent->children[ parent->nchildren - 1 ] = child;
|
parent->children[ parent->nchildren - 1 ] = child;
|
||||||
child->parent = parent;
|
child->parent = parent;
|
||||||
} /* ----- end of function _hierarchy_node_append ----- */
|
} /* ----- end of function __AI_hierarchy_node_append ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -176,7 +176,7 @@ _hierarchy_node_append ( hierarchy_node *parent, hierarchy_node *child )
|
||||||
* \return The minimum node that matches the value if any, NULL otherwise
|
* \return The minimum node that matches the value if any, NULL otherwise
|
||||||
*/
|
*/
|
||||||
PRIVATE hierarchy_node*
|
PRIVATE hierarchy_node*
|
||||||
_AI_get_min_hierarchy_node ( int val, hierarchy_node *root )
|
__AI_get_min_hierarchy_node ( int val, hierarchy_node *root )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
hierarchy_node *next = NULL;
|
hierarchy_node *next = NULL;
|
||||||
|
@ -202,8 +202,8 @@ _AI_get_min_hierarchy_node ( int val, hierarchy_node *root )
|
||||||
if ( !next )
|
if ( !next )
|
||||||
return root;
|
return root;
|
||||||
|
|
||||||
return _AI_get_min_hierarchy_node ( val, next );
|
return __AI_get_min_hierarchy_node ( val, next );
|
||||||
} /* ----- end of function _AI_get_min_hierarchy_node ----- */
|
} /* ----- end of function __AI_get_min_hierarchy_node ----- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Check if two alerts are semantically equal
|
* \brief Check if two alerts are semantically equal
|
||||||
|
@ -213,7 +213,7 @@ _AI_get_min_hierarchy_node ( int val, hierarchy_node *root )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE BOOL
|
PRIVATE BOOL
|
||||||
_AI_equal_alerts ( AI_snort_alert *a1, AI_snort_alert *a2 )
|
__AI_equal_alerts ( AI_snort_alert *a1, AI_snort_alert *a2 )
|
||||||
{
|
{
|
||||||
if ( a1->gid != a2->gid || a1->sid != a2->sid || a1->rev != a2->rev )
|
if ( a1->gid != a2->gid || a1->sid != a2->sid || a1->rev != a2->rev )
|
||||||
{
|
{
|
||||||
|
@ -249,7 +249,7 @@ _AI_equal_alerts ( AI_snort_alert *a1, AI_snort_alert *a2 )
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} /* ----- end of function _AI_equal_alerts ----- */
|
} /* ----- end of function __AI_equal_alerts ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -259,7 +259,7 @@ _AI_equal_alerts ( AI_snort_alert *a1, AI_snort_alert *a2 )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE int
|
PRIVATE int
|
||||||
_AI_merge_alerts ( AI_snort_alert **log )
|
__AI_merge_alerts ( AI_snort_alert **log )
|
||||||
{
|
{
|
||||||
AI_snort_alert *tmp, *tmp2, *tmp3;
|
AI_snort_alert *tmp, *tmp2, *tmp3;
|
||||||
AI_alerts_couple *alerts_couple;
|
AI_alerts_couple *alerts_couple;
|
||||||
|
@ -279,7 +279,7 @@ _AI_merge_alerts ( AI_snort_alert **log )
|
||||||
if ( tmp != tmp2->next )
|
if ( tmp != tmp2->next )
|
||||||
{
|
{
|
||||||
/* If the two alerts are equal... */
|
/* If the two alerts are equal... */
|
||||||
if ( _AI_equal_alerts ( tmp, tmp2->next ))
|
if ( __AI_equal_alerts ( tmp, tmp2->next ))
|
||||||
{
|
{
|
||||||
/* If we are storing the outputs of the module to a database, save the cluster containing the two alerts */
|
/* If we are storing the outputs of the module to a database, save the cluster containing the two alerts */
|
||||||
if ( config->outdbtype != outdb_none )
|
if ( config->outdbtype != outdb_none )
|
||||||
|
@ -321,7 +321,7 @@ _AI_merge_alerts ( AI_snort_alert **log )
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
} /* ----- end of function _AI_merge_alerts ----- */
|
} /* ----- end of function __AI_merge_alerts ----- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get the average heterogeneity coefficient of the set of alerts
|
* \brief Get the average heterogeneity coefficient of the set of alerts
|
||||||
|
@ -329,7 +329,7 @@ _AI_merge_alerts ( AI_snort_alert **log )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
double
|
double
|
||||||
_AI_get_alerts_heterogeneity ( int *alert_count )
|
__AI_get_alerts_heterogeneity ( int *alert_count )
|
||||||
{
|
{
|
||||||
double heterogeneity = 0.0;
|
double heterogeneity = 0.0;
|
||||||
int distinct_count = 0;
|
int distinct_count = 0;
|
||||||
|
@ -379,7 +379,7 @@ _AI_get_alerts_heterogeneity ( int *alert_count )
|
||||||
}
|
}
|
||||||
|
|
||||||
return heterogeneity;
|
return heterogeneity;
|
||||||
} /* ----- end of function _AI_get_alerts_heterogeneity ----- */
|
} /* ----- end of function __AI_get_alerts_heterogeneity ----- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Print the clustered alerts to a log file
|
* \brief Print the clustered alerts to a log file
|
||||||
|
@ -388,7 +388,7 @@ _AI_get_alerts_heterogeneity ( int *alert_count )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE void
|
PRIVATE void
|
||||||
_AI_print_clustered_alerts ( AI_snort_alert *log, FILE *fp )
|
__AI_print_clustered_alerts ( AI_snort_alert *log, FILE *fp )
|
||||||
{
|
{
|
||||||
AI_snort_alert *tmp;
|
AI_snort_alert *tmp;
|
||||||
char ip[INET_ADDRSTRLEN];
|
char ip[INET_ADDRSTRLEN];
|
||||||
|
@ -440,14 +440,14 @@ _AI_print_clustered_alerts ( AI_snort_alert *log, FILE *fp )
|
||||||
|
|
||||||
fprintf ( fp, "\n" );
|
fprintf ( fp, "\n" );
|
||||||
}
|
}
|
||||||
} /* ----- end of function _AI_print_clustered_alerts ----- */
|
} /* ----- end of function __AI_print_clustered_alerts ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Thread for periodically clustering the log information
|
* \brief Thread for periodically clustering the log information
|
||||||
*/
|
*/
|
||||||
PRIVATE void*
|
PRIVATE void*
|
||||||
_AI_cluster_thread ( void* arg )
|
__AI_cluster_thread ( void* arg )
|
||||||
{
|
{
|
||||||
AI_snort_alert *tmp;
|
AI_snort_alert *tmp;
|
||||||
hierarchy_node *node, *child;
|
hierarchy_node *node, *child;
|
||||||
|
@ -523,14 +523,14 @@ _AI_cluster_thread ( void* arg )
|
||||||
return (void*) 0;
|
return (void*) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = _AI_get_min_hierarchy_node ( hostval, h_root[type] );
|
node = __AI_get_min_hierarchy_node ( hostval, h_root[type] );
|
||||||
|
|
||||||
if ( node )
|
if ( node )
|
||||||
{
|
{
|
||||||
if ( node->min_val < node->max_val )
|
if ( node->min_val < node->max_val )
|
||||||
{
|
{
|
||||||
child = _hierarchy_node_new ( label, hostval, hostval);
|
child = __AI_hierarchy_node_new ( label, hostval, hostval);
|
||||||
_hierarchy_node_append ( node, child );
|
__AI_hierarchy_node_append ( node, child );
|
||||||
node = child;
|
node = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,8 +540,8 @@ _AI_cluster_thread ( void* arg )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
alert_count -= _AI_merge_alerts ( &alert_log );
|
alert_count -= __AI_merge_alerts ( &alert_log );
|
||||||
heterogeneity = _AI_get_alerts_heterogeneity( &single_alerts_count );
|
heterogeneity = __AI_get_alerts_heterogeneity ( &single_alerts_count );
|
||||||
|
|
||||||
/* Get the minimum size for the clusters in function of the heterogeneity of alerts' set */
|
/* Get the minimum size for the clusters in function of the heterogeneity of alerts' set */
|
||||||
if ( heterogeneity > 0 )
|
if ( heterogeneity > 0 )
|
||||||
|
@ -560,7 +560,7 @@ _AI_cluster_thread ( void* arg )
|
||||||
{
|
{
|
||||||
if ( type != none && h_root[type] )
|
if ( type != none && h_root[type] )
|
||||||
{
|
{
|
||||||
if (( heuristic_val = _heuristic_func ( type )) > 0 && heuristic_val < minval )
|
if (( heuristic_val = __AI_heuristic_func ( type )) > 0 && heuristic_val < minval )
|
||||||
{
|
{
|
||||||
minval = heuristic_val;
|
minval = heuristic_val;
|
||||||
best_type = type;
|
best_type = type;
|
||||||
|
@ -580,7 +580,7 @@ _AI_cluster_thread ( void* arg )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
alert_count -= _AI_merge_alerts ( &alert_log );
|
alert_count -= __AI_merge_alerts ( &alert_log );
|
||||||
} while ( old_alert_count != alert_count );
|
} while ( old_alert_count != alert_count );
|
||||||
|
|
||||||
pthread_mutex_unlock ( &mutex );
|
pthread_mutex_unlock ( &mutex );
|
||||||
|
@ -591,7 +591,7 @@ _AI_cluster_thread ( void* arg )
|
||||||
return (void*) 0;
|
return (void*) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_AI_print_clustered_alerts ( alert_log, cluster_fp );
|
__AI_print_clustered_alerts ( alert_log, cluster_fp );
|
||||||
fclose ( cluster_fp );
|
fclose ( cluster_fp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,7 +608,7 @@ _AI_cluster_thread ( void* arg )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE BOOL
|
PRIVATE BOOL
|
||||||
_AI_check_duplicate ( hierarchy_node *node, hierarchy_node *root )
|
__AI_check_duplicate ( hierarchy_node *node, hierarchy_node *root )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -620,7 +620,7 @@ _AI_check_duplicate ( hierarchy_node *node, hierarchy_node *root )
|
||||||
|
|
||||||
for ( i=0; i < root->nchildren; i++ )
|
for ( i=0; i < root->nchildren; i++ )
|
||||||
{
|
{
|
||||||
if ( _AI_check_duplicate ( node, root->children[i] ))
|
if ( __AI_check_duplicate ( node, root->children[i] ))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,7 +650,7 @@ AI_hierarchies_build ( hierarchy_node **nodes, int n_nodes )
|
||||||
case src_port:
|
case src_port:
|
||||||
case dst_port:
|
case dst_port:
|
||||||
if ( !h_root[ nodes[i]->type ] )
|
if ( !h_root[ nodes[i]->type ] )
|
||||||
h_root[ nodes[i]->type ] = _hierarchy_node_new ( "1-65535", 1, 65535 );
|
h_root[ nodes[i]->type ] = __AI_hierarchy_node_new ( "1-65535", 1, 65535 );
|
||||||
|
|
||||||
min_range = 65534;
|
min_range = 65534;
|
||||||
break;
|
break;
|
||||||
|
@ -658,7 +658,7 @@ AI_hierarchies_build ( hierarchy_node **nodes, int n_nodes )
|
||||||
case src_addr:
|
case src_addr:
|
||||||
case dst_addr:
|
case dst_addr:
|
||||||
if ( !h_root[ nodes[i]->type ] )
|
if ( !h_root[ nodes[i]->type ] )
|
||||||
h_root[ nodes[i]->type ] = _hierarchy_node_new ( "0.0.0.0/0", 0x0, 0xffffffff );
|
h_root[ nodes[i]->type ] = __AI_hierarchy_node_new ( "0.0.0.0/0", 0x0, 0xffffffff );
|
||||||
|
|
||||||
min_range = 0xffffffff;
|
min_range = 0xffffffff;
|
||||||
break;
|
break;
|
||||||
|
@ -671,7 +671,7 @@ AI_hierarchies_build ( hierarchy_node **nodes, int n_nodes )
|
||||||
root = h_root[ nodes[i]->type ];
|
root = h_root[ nodes[i]->type ];
|
||||||
cover = NULL;
|
cover = NULL;
|
||||||
|
|
||||||
if ( _AI_check_duplicate ( nodes[i], root ))
|
if ( __AI_check_duplicate ( nodes[i], root ))
|
||||||
{
|
{
|
||||||
AI_fatal_err ( "Parse error: duplicate cluster range in module configuration", __FILE__, __LINE__ );
|
AI_fatal_err ( "Parse error: duplicate cluster range in module configuration", __FILE__, __LINE__ );
|
||||||
}
|
}
|
||||||
|
@ -696,17 +696,17 @@ AI_hierarchies_build ( hierarchy_node **nodes, int n_nodes )
|
||||||
|
|
||||||
if ( cover )
|
if ( cover )
|
||||||
{
|
{
|
||||||
_hierarchy_node_append ( cover, nodes[i] );
|
__AI_hierarchy_node_append ( cover, nodes[i] );
|
||||||
} else {
|
} else {
|
||||||
if ( (unsigned) nodes[i]->min_val >= (unsigned) root->min_val && (unsigned) nodes[i]->max_val <= (unsigned) root->max_val &&
|
if ( (unsigned) nodes[i]->min_val >= (unsigned) root->min_val && (unsigned) nodes[i]->max_val <= (unsigned) root->max_val &&
|
||||||
( (unsigned) nodes[i]->min_val != (unsigned) root->min_val || (unsigned) nodes[i]->max_val != (unsigned) root->max_val ))
|
( (unsigned) nodes[i]->min_val != (unsigned) root->min_val || (unsigned) nodes[i]->max_val != (unsigned) root->max_val ))
|
||||||
{
|
{
|
||||||
_hierarchy_node_append ( root, nodes[i] );
|
__AI_hierarchy_node_append ( root, nodes[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pthread_create ( &cluster_thread, NULL, _AI_cluster_thread, NULL ) != 0 )
|
if ( pthread_create ( &cluster_thread, NULL, __AI_cluster_thread, NULL ) != 0 )
|
||||||
{
|
{
|
||||||
AI_fatal_err ( "Failed to create the hash cleanup thread", __FILE__, __LINE__ );
|
AI_fatal_err ( "Failed to create the hash cleanup thread", __FILE__, __LINE__ );
|
||||||
}
|
}
|
||||||
|
@ -719,7 +719,7 @@ AI_hierarchies_build ( hierarchy_node **nodes, int n_nodes )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE AI_snort_alert*
|
PRIVATE AI_snort_alert*
|
||||||
_AI_copy_clustered_alerts ( AI_snort_alert *node )
|
__AI_copy_clustered_alerts ( AI_snort_alert *node )
|
||||||
{
|
{
|
||||||
AI_snort_alert *current = NULL, *next = NULL;
|
AI_snort_alert *current = NULL, *next = NULL;
|
||||||
|
|
||||||
|
@ -730,7 +730,7 @@ _AI_copy_clustered_alerts ( AI_snort_alert *node )
|
||||||
|
|
||||||
if ( node->next )
|
if ( node->next )
|
||||||
{
|
{
|
||||||
next = _AI_copy_clustered_alerts ( node->next );
|
next = __AI_copy_clustered_alerts ( node->next );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !( current = ( AI_snort_alert* ) malloc ( sizeof ( AI_snort_alert )) ))
|
if ( !( current = ( AI_snort_alert* ) malloc ( sizeof ( AI_snort_alert )) ))
|
||||||
|
@ -741,7 +741,7 @@ _AI_copy_clustered_alerts ( AI_snort_alert *node )
|
||||||
memcpy ( current, node, sizeof ( AI_snort_alert ));
|
memcpy ( current, node, sizeof ( AI_snort_alert ));
|
||||||
current->next = next;
|
current->next = next;
|
||||||
return current;
|
return current;
|
||||||
} /* ----- end of function _AI_copy_clustered_alerts ----- */
|
} /* ----- end of function __AI_copy_clustered_alerts ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -755,7 +755,7 @@ AI_get_clustered_alerts ()
|
||||||
AI_snort_alert *alerts_copy;
|
AI_snort_alert *alerts_copy;
|
||||||
|
|
||||||
pthread_mutex_lock ( &mutex );
|
pthread_mutex_lock ( &mutex );
|
||||||
alerts_copy = _AI_copy_clustered_alerts ( alert_log );
|
alerts_copy = __AI_copy_clustered_alerts ( alert_log );
|
||||||
pthread_mutex_unlock ( &mutex );
|
pthread_mutex_unlock ( &mutex );
|
||||||
|
|
||||||
return alerts_copy;
|
return alerts_copy;
|
||||||
|
|
198
correlation.c
198
correlation.c
|
@ -54,7 +54,7 @@ PRIVATE pthread_mutex_t mutex;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE void
|
PRIVATE void
|
||||||
_AI_correlation_table_cleanup ()
|
__AI_correlation_table_cleanup ()
|
||||||
{
|
{
|
||||||
AI_alert_correlation *current;
|
AI_alert_correlation *current;
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ _AI_correlation_table_cleanup ()
|
||||||
HASH_DEL ( correlation_table, current );
|
HASH_DEL ( correlation_table, current );
|
||||||
free ( current );
|
free ( current );
|
||||||
}
|
}
|
||||||
} /* ----- end of function _AI_correlation_table_cleanup ----- */
|
} /* ----- end of function __AI_correlation_table_cleanup ----- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Recursively write a flow of correlated alerts to a .dot file, ready for being rendered as graph
|
* \brief Recursively write a flow of correlated alerts to a .dot file, ready for being rendered as graph
|
||||||
|
@ -73,7 +73,7 @@ _AI_correlation_table_cleanup ()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE void
|
PRIVATE void
|
||||||
_AI_correlated_alerts_to_dot ( AI_alert_correlation *corr, FILE *fp )
|
__AI_correlated_alerts_to_dot ( AI_alert_correlation *corr, FILE *fp )
|
||||||
{
|
{
|
||||||
char src_addr1[INET_ADDRSTRLEN],
|
char src_addr1[INET_ADDRSTRLEN],
|
||||||
dst_addr1[INET_ADDRSTRLEN],
|
dst_addr1[INET_ADDRSTRLEN],
|
||||||
|
@ -130,19 +130,29 @@ _AI_correlated_alerts_to_dot ( AI_alert_correlation *corr, FILE *fp )
|
||||||
timestamp2,
|
timestamp2,
|
||||||
corr->key.b->grouped_alerts_count
|
corr->key.b->grouped_alerts_count
|
||||||
);
|
);
|
||||||
} /* ----- end of function _AI_correlated_alerts_to_dot ----- */
|
} /* ----- end of function __AI_correlated_alerts_to_dot ----- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Recursively write the flow of correlated alerts to a .json file, ready for being rendered in the web interface
|
* \brief Recursively write the flow of correlated alerts to a .json file, ready for being rendered in the web interface
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE void
|
PRIVATE void
|
||||||
_AI_correlated_alerts_to_json ()
|
__AI_correlated_alerts_to_json ()
|
||||||
{
|
{
|
||||||
unsigned int i = 0;
|
AI_snort_alert *alert_iterator = NULL;
|
||||||
char json_file[1040] = { 0 };
|
struct pkt_info *pkt_iterator = NULL;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
AI_snort_alert *alert_iterator = NULL;
|
|
||||||
|
unsigned int i = 0,
|
||||||
|
pkt_len = 0;
|
||||||
|
|
||||||
|
char *strtime = NULL,
|
||||||
|
*encoded_pkt = NULL,
|
||||||
|
json_file[1040] = { 0 },
|
||||||
|
srcip[INET_ADDRSTRLEN] = { 0 },
|
||||||
|
dstip[INET_ADDRSTRLEN] = { 0 },
|
||||||
|
srcport[10] = { 0 },
|
||||||
|
dstport[10] = { 0 };
|
||||||
|
|
||||||
/* If there is no directory configured for the web interface, just exit */
|
/* If there is no directory configured for the web interface, just exit */
|
||||||
if ( strlen ( config->webserv_dir ) == 0 )
|
if ( strlen ( config->webserv_dir ) == 0 )
|
||||||
|
@ -159,10 +169,136 @@ _AI_correlated_alerts_to_json ()
|
||||||
|
|
||||||
for ( alert_iterator = alerts; alert_iterator; alert_iterator = alert_iterator->next )
|
for ( alert_iterator = alerts; alert_iterator; alert_iterator = alert_iterator->next )
|
||||||
{
|
{
|
||||||
|
strtime = ctime ( &(alert_iterator->timestamp ));
|
||||||
|
strtime[ strlen(strtime) - 1 ] = 0;
|
||||||
|
inet_ntop ( AF_INET, &(alert_iterator->ip_src_addr), srcip, INET_ADDRSTRLEN );
|
||||||
|
inet_ntop ( AF_INET, &(alert_iterator->ip_dst_addr), dstip, INET_ADDRSTRLEN );
|
||||||
|
snprintf ( srcport, sizeof ( srcport ), "%d", htons ( alert_iterator->tcp_src_port ));
|
||||||
|
snprintf ( dstport, sizeof ( dstport ), "%d", htons ( alert_iterator->tcp_dst_port ));
|
||||||
|
|
||||||
fprintf ( fp, "{\n"
|
fprintf ( fp, "{\n"
|
||||||
"\t\"id\": %lu,\n"
|
"\t\"id\": %lu,\n"
|
||||||
"\t\"label\": \"%s\"",
|
"\t\"label\": \"%s\",\n"
|
||||||
alert_iterator->alert_id, alert_iterator->desc );
|
"\t\"date\": \"%s\",\n"
|
||||||
|
"\t\"clusteredAlertsCount\": %u,\n"
|
||||||
|
"\t\"from\": \"%s:%s\",\n"
|
||||||
|
"\t\"to\": \"%s:%s\"",
|
||||||
|
alert_iterator->alert_id,
|
||||||
|
alert_iterator->desc,
|
||||||
|
strtime,
|
||||||
|
alert_iterator->grouped_alerts_count,
|
||||||
|
srcip, srcport, dstip, dstport
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( alert_iterator->stream )
|
||||||
|
{
|
||||||
|
fprintf ( fp, ",\n"
|
||||||
|
"\t\"packets\": [\n" );
|
||||||
|
|
||||||
|
for ( pkt_iterator = alert_iterator->stream; pkt_iterator; pkt_iterator = pkt_iterator->next )
|
||||||
|
{
|
||||||
|
pkt_len = pkt_iterator->pkt->pcap_header->len + pkt_iterator->pkt->payload_size;
|
||||||
|
|
||||||
|
if ( !( encoded_pkt = (char*) malloc ( 4*pkt_len + 1 )))
|
||||||
|
{
|
||||||
|
AI_fatal_err ( "Fatal dynamic memory allocation", __FILE__, __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
memset ( encoded_pkt, 0, 4*pkt_len + 1 );
|
||||||
|
|
||||||
|
base64_encode (
|
||||||
|
(const char*) pkt_iterator->pkt->pkt_data,
|
||||||
|
pkt_len,
|
||||||
|
&encoded_pkt
|
||||||
|
);
|
||||||
|
|
||||||
|
fprintf ( fp, "\t\t\"%s\"%s\n",
|
||||||
|
encoded_pkt, ((pkt_iterator->next) ? "," : ""));
|
||||||
|
|
||||||
|
free ( encoded_pkt );
|
||||||
|
encoded_pkt = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf ( fp, "\t]" );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i=1; i < alert_iterator->grouped_alerts_count; i++ )
|
||||||
|
{
|
||||||
|
if ( i == 1 )
|
||||||
|
{
|
||||||
|
fprintf ( fp, ",\n\t\"clusteredAlerts\": [\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( alert_iterator->grouped_alerts )
|
||||||
|
{
|
||||||
|
if ( alert_iterator->grouped_alerts[i] )
|
||||||
|
{
|
||||||
|
strtime = ctime ( &(alert_iterator->grouped_alerts[i]->timestamp ));
|
||||||
|
strtime[ strlen ( strtime ) - 1 ] = 0;
|
||||||
|
inet_ntop ( AF_INET, &(alert_iterator->grouped_alerts[i]->ip_src_addr), srcip, INET_ADDRSTRLEN );
|
||||||
|
inet_ntop ( AF_INET, &(alert_iterator->grouped_alerts[i]->ip_dst_addr), dstip, INET_ADDRSTRLEN );
|
||||||
|
snprintf ( srcport, sizeof ( srcport ), "%d", htons ( alert_iterator->grouped_alerts[i]->tcp_src_port ));
|
||||||
|
snprintf ( dstport, sizeof ( dstport ), "%d", htons ( alert_iterator->grouped_alerts[i]->tcp_dst_port ));
|
||||||
|
|
||||||
|
fprintf ( fp, "\t\t{\n"
|
||||||
|
"\t\t\t\"id\": %lu,\n"
|
||||||
|
"\t\t\t\"label\": \"%s\",\n"
|
||||||
|
"\t\t\t\"date\": \"%s\",\n"
|
||||||
|
"\t\t\t\"from\": \"%s:%s\",\n"
|
||||||
|
"\t\t\t\"to\": \"%s:%s\"%s",
|
||||||
|
alert_iterator->grouped_alerts[i]->alert_id,
|
||||||
|
alert_iterator->grouped_alerts[i]->desc,
|
||||||
|
strtime,
|
||||||
|
srcip, srcport, dstip, dstport,
|
||||||
|
(( alert_iterator->grouped_alerts[i]->stream ) ? ",\n" : "\n" )
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( alert_iterator->grouped_alerts[i]->stream )
|
||||||
|
{
|
||||||
|
fprintf ( fp, "\t\t\t\"packets\": [\n" );
|
||||||
|
|
||||||
|
for ( pkt_iterator = alert_iterator->grouped_alerts[i]->stream; pkt_iterator; pkt_iterator = pkt_iterator->next )
|
||||||
|
{
|
||||||
|
if ( !pkt_iterator->pkt->ip4_header )
|
||||||
|
{
|
||||||
|
pkt_len = pkt_iterator->pkt->pcap_header->len +
|
||||||
|
pkt_iterator->pkt->tcp_options_length +
|
||||||
|
pkt_iterator->pkt->payload_size;
|
||||||
|
} else {
|
||||||
|
pkt_len = pkt_iterator->pkt->ip4_header->data_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !( encoded_pkt = (char*) malloc ( 4*pkt_len + 1 )))
|
||||||
|
{
|
||||||
|
AI_fatal_err ( "Fatal dynamic memory allocation", __FILE__, __LINE__ );
|
||||||
|
}
|
||||||
|
|
||||||
|
memset ( encoded_pkt, 0, 4*pkt_len + 1 );
|
||||||
|
|
||||||
|
base64_encode (
|
||||||
|
(const char*) pkt_iterator->pkt->pkt_data,
|
||||||
|
pkt_len,
|
||||||
|
&encoded_pkt
|
||||||
|
);
|
||||||
|
|
||||||
|
fprintf ( fp, "\t\t\t\t\"%s\"%s\n",
|
||||||
|
encoded_pkt, ((pkt_iterator->next) ? "," : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf ( fp, "\t\t\t]\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf ( fp,
|
||||||
|
"\t\t}%s\n",
|
||||||
|
(( i < alert_iterator->grouped_alerts_count - 1 ) ? "," : "" ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( i == alert_iterator->grouped_alerts_count - 1 )
|
||||||
|
{
|
||||||
|
fprintf ( fp, "\t]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( i=0; i < alert_iterator->n_derived_alerts; i++ )
|
for ( i=0; i < alert_iterator->n_derived_alerts; i++ )
|
||||||
{
|
{
|
||||||
|
@ -188,7 +324,7 @@ _AI_correlated_alerts_to_json ()
|
||||||
fprintf ( fp, "]\n" );
|
fprintf ( fp, "]\n" );
|
||||||
fclose ( fp );
|
fclose ( fp );
|
||||||
chmod ( json_file, 0644 );
|
chmod ( json_file, 0644 );
|
||||||
} /* ----- end of function _AI_correlated_alerts_to_json ----- */
|
} /* ----- end of function __AI_correlated_alerts_to_json ----- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get the name of the function called by a pre-condition or post-condition predicate
|
* \brief Get the name of the function called by a pre-condition or post-condition predicate
|
||||||
|
@ -197,7 +333,7 @@ _AI_correlated_alerts_to_json ()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE char*
|
PRIVATE char*
|
||||||
_AI_get_function_name ( const char *orig_stmt )
|
__AI_get_function_name ( const char *orig_stmt )
|
||||||
{
|
{
|
||||||
int parenthesis_pos, function_name_len;
|
int parenthesis_pos, function_name_len;
|
||||||
char function_name[4096];
|
char function_name[4096];
|
||||||
|
@ -217,7 +353,7 @@ _AI_get_function_name ( const char *orig_stmt )
|
||||||
strncpy ( function_name, stmt, function_name_len );
|
strncpy ( function_name, stmt, function_name_len );
|
||||||
|
|
||||||
return strdup(function_name);
|
return strdup(function_name);
|
||||||
} /* ----- end of function _AI_get_function_name ----- */
|
} /* ----- end of function __AI_get_function_name ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -228,7 +364,7 @@ _AI_get_function_name ( const char *orig_stmt )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE char**
|
PRIVATE char**
|
||||||
_AI_get_function_arguments ( char *orig_stmt, int *n_args )
|
__AI_get_function_arguments ( char *orig_stmt, int *n_args )
|
||||||
{
|
{
|
||||||
char **args = NULL;
|
char **args = NULL;
|
||||||
char *tok = NULL;
|
char *tok = NULL;
|
||||||
|
@ -263,7 +399,7 @@ _AI_get_function_arguments ( char *orig_stmt, int *n_args )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
} /* ----- end of function _AI_get_function_arguments ----- */
|
} /* ----- end of function __AI_get_function_arguments ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -274,7 +410,7 @@ _AI_get_function_arguments ( char *orig_stmt, int *n_args )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE double
|
PRIVATE double
|
||||||
_AI_kb_correlation_coefficient ( AI_snort_alert *a, AI_snort_alert *b )
|
__AI_kb_correlation_coefficient ( AI_snort_alert *a, AI_snort_alert *b )
|
||||||
{
|
{
|
||||||
unsigned int i, j, k, l,
|
unsigned int i, j, k, l,
|
||||||
n_intersection = 0,
|
n_intersection = 0,
|
||||||
|
@ -314,13 +450,13 @@ _AI_kb_correlation_coefficient ( AI_snort_alert *a, AI_snort_alert *b )
|
||||||
} else {
|
} else {
|
||||||
/* Check if the predicates are the same, have the same number of arguments, and
|
/* Check if the predicates are the same, have the same number of arguments, and
|
||||||
* substitute possible occurrencies of +ANY_ADDR+ and +ANY_PORT+ or IP netmasks */
|
* substitute possible occurrencies of +ANY_ADDR+ and +ANY_PORT+ or IP netmasks */
|
||||||
function_name1 = _AI_get_function_name ( a->hyperalert->postconds[i] );
|
function_name1 = __AI_get_function_name ( a->hyperalert->postconds[i] );
|
||||||
function_name2 = _AI_get_function_name ( b->hyperalert->preconds[j] );
|
function_name2 = __AI_get_function_name ( b->hyperalert->preconds[j] );
|
||||||
|
|
||||||
if ( !strcasecmp ( function_name1, function_name2 ))
|
if ( !strcasecmp ( function_name1, function_name2 ))
|
||||||
{
|
{
|
||||||
args1 = _AI_get_function_arguments ( a->hyperalert->postconds[i], &n_args1 );
|
args1 = __AI_get_function_arguments ( a->hyperalert->postconds[i], &n_args1 );
|
||||||
args2 = _AI_get_function_arguments ( b->hyperalert->preconds[j] , &n_args2 );
|
args2 = __AI_get_function_arguments ( b->hyperalert->preconds[j] , &n_args2 );
|
||||||
|
|
||||||
if ( args1 && args2 )
|
if ( args1 && args2 )
|
||||||
{
|
{
|
||||||
|
@ -478,7 +614,7 @@ _AI_kb_correlation_coefficient ( AI_snort_alert *a, AI_snort_alert *b )
|
||||||
}
|
}
|
||||||
|
|
||||||
return (double) ((double) n_intersection / (double) n_union );
|
return (double) ((double) n_intersection / (double) n_union );
|
||||||
} /* ----- end of function _AI_kb_correlation_coefficient ----- */
|
} /* ----- end of function __AI_kb_correlation_coefficient ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -487,7 +623,7 @@ _AI_kb_correlation_coefficient ( AI_snort_alert *a, AI_snort_alert *b )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE void
|
PRIVATE void
|
||||||
_AI_macro_subst ( AI_snort_alert **alert )
|
__AI_macro_subst ( AI_snort_alert **alert )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Recognized macros:
|
* Recognized macros:
|
||||||
|
@ -570,7 +706,7 @@ _AI_macro_subst ( AI_snort_alert **alert )
|
||||||
free ( tmp );
|
free ( tmp );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} /* ----- end of function _AI_macro_subst ----- */
|
} /* ----- end of function __AI_macro_subst ----- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Parse info about a hyperalert from a correlation XML file, if it exists
|
* \brief Parse info about a hyperalert from a correlation XML file, if it exists
|
||||||
|
@ -579,7 +715,7 @@ _AI_macro_subst ( AI_snort_alert **alert )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE AI_hyperalert_info*
|
PRIVATE AI_hyperalert_info*
|
||||||
_AI_hyperalert_from_XML ( AI_hyperalert_key key )
|
__AI_hyperalert_from_XML ( AI_hyperalert_key key )
|
||||||
{
|
{
|
||||||
char hyperalert_file[1024] = {0};
|
char hyperalert_file[1024] = {0};
|
||||||
char snort_id[1024] = {0};
|
char snort_id[1024] = {0};
|
||||||
|
@ -706,7 +842,7 @@ _AI_hyperalert_from_XML ( AI_hyperalert_key key )
|
||||||
xmlFreeTextReader ( xml );
|
xmlFreeTextReader ( xml );
|
||||||
xmlCleanupParser();
|
xmlCleanupParser();
|
||||||
return hyp;
|
return hyp;
|
||||||
} /* ----- end of function _AI_hyperalert_from_XML ----- */
|
} /* ----- end of function __AI_hyperalert_from_XML ----- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Thread for correlating clustered alerts
|
* \brief Thread for correlating clustered alerts
|
||||||
|
@ -786,7 +922,7 @@ AI_alert_correlation_thread ( void *arg )
|
||||||
if ( !hyp )
|
if ( !hyp )
|
||||||
{
|
{
|
||||||
/* If there is no hyperalert knowledge on XML for this alert, ignore it and get the next one */
|
/* If there is no hyperalert knowledge on XML for this alert, ignore it and get the next one */
|
||||||
if ( !( hyp = _AI_hyperalert_from_XML ( key )))
|
if ( !( hyp = __AI_hyperalert_from_XML ( key )))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* If the XML file exists and it's valid, add the hypertalert to the hash table */
|
/* If the XML file exists and it's valid, add the hypertalert to the hash table */
|
||||||
|
@ -813,10 +949,10 @@ AI_alert_correlation_thread ( void *arg )
|
||||||
for ( i=0; i < alert_iterator->hyperalert->n_postconds; i++ )
|
for ( i=0; i < alert_iterator->hyperalert->n_postconds; i++ )
|
||||||
alert_iterator->hyperalert->postconds[i] = strdup ( hyp->postconds[i] );
|
alert_iterator->hyperalert->postconds[i] = strdup ( hyp->postconds[i] );
|
||||||
|
|
||||||
_AI_macro_subst ( &alert_iterator );
|
__AI_macro_subst ( &alert_iterator );
|
||||||
}
|
}
|
||||||
|
|
||||||
_AI_correlation_table_cleanup();
|
__AI_correlation_table_cleanup();
|
||||||
correlation_table = NULL;
|
correlation_table = NULL;
|
||||||
|
|
||||||
for ( alert_iterator = alerts; alert_iterator; alert_iterator = alert_iterator->next )
|
for ( alert_iterator = alerts; alert_iterator; alert_iterator = alert_iterator->next )
|
||||||
|
@ -835,7 +971,7 @@ AI_alert_correlation_thread ( void *arg )
|
||||||
corr_key.b = alert_iterator2;
|
corr_key.b = alert_iterator2;
|
||||||
|
|
||||||
corr->key = corr_key;
|
corr->key = corr_key;
|
||||||
kb_correlation = _AI_kb_correlation_coefficient ( corr_key.a, corr_key.b );
|
kb_correlation = __AI_kb_correlation_coefficient ( corr_key.a, corr_key.b );
|
||||||
bayesian_correlation = AI_alert_bayesian_correlation ( corr_key.a, corr_key.b );
|
bayesian_correlation = AI_alert_bayesian_correlation ( corr_key.a, corr_key.b );
|
||||||
|
|
||||||
if ( bayesian_correlation == 0.0 || config->bayesianCorrelationInterval == 0 )
|
if ( bayesian_correlation == 0.0 || config->bayesianCorrelationInterval == 0 )
|
||||||
|
@ -905,7 +1041,7 @@ AI_alert_correlation_thread ( void *arg )
|
||||||
|
|
||||||
corr->key.a->derived_alerts[ corr->key.a->n_derived_alerts - 1 ] = corr->key.b;
|
corr->key.a->derived_alerts[ corr->key.a->n_derived_alerts - 1 ] = corr->key.b;
|
||||||
corr->key.b->parent_alerts [ corr->key.b->n_parent_alerts - 1 ] = corr->key.a;
|
corr->key.b->parent_alerts [ corr->key.b->n_parent_alerts - 1 ] = corr->key.a;
|
||||||
_AI_correlated_alerts_to_dot ( corr, fp );
|
__AI_correlated_alerts_to_dot ( corr, fp );
|
||||||
|
|
||||||
if ( config->outdbtype != outdb_none )
|
if ( config->outdbtype != outdb_none )
|
||||||
{
|
{
|
||||||
|
@ -953,7 +1089,7 @@ AI_alert_correlation_thread ( void *arg )
|
||||||
{
|
{
|
||||||
if ( strlen ( config->webserv_dir ) != 0 )
|
if ( strlen ( config->webserv_dir ) != 0 )
|
||||||
{
|
{
|
||||||
_AI_correlated_alerts_to_json ();
|
__AI_correlated_alerts_to_json ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
db.c
8
db.c
|
@ -236,7 +236,7 @@ AI_db_alertparser_thread ( void *arg )
|
||||||
* \return A copy of the alert log linked list
|
* \return A copy of the alert log linked list
|
||||||
*/
|
*/
|
||||||
PRIVATE AI_snort_alert*
|
PRIVATE AI_snort_alert*
|
||||||
_AI_db_copy_alerts ( AI_snort_alert *node )
|
__AI_db_copy_alerts ( AI_snort_alert *node )
|
||||||
{
|
{
|
||||||
AI_snort_alert *current = NULL, *next = NULL;
|
AI_snort_alert *current = NULL, *next = NULL;
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ _AI_db_copy_alerts ( AI_snort_alert *node )
|
||||||
|
|
||||||
if ( node->next )
|
if ( node->next )
|
||||||
{
|
{
|
||||||
next = _AI_db_copy_alerts ( node->next );
|
next = __AI_db_copy_alerts ( node->next );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !( current = ( AI_snort_alert* ) malloc ( sizeof ( AI_snort_alert )) ))
|
if ( !( current = ( AI_snort_alert* ) malloc ( sizeof ( AI_snort_alert )) ))
|
||||||
|
@ -258,7 +258,7 @@ _AI_db_copy_alerts ( AI_snort_alert *node )
|
||||||
memcpy ( current, node, sizeof ( AI_snort_alert ));
|
memcpy ( current, node, sizeof ( AI_snort_alert ));
|
||||||
current->next = next;
|
current->next = next;
|
||||||
return current;
|
return current;
|
||||||
} /* ----- end of function _AI_db_copy_alerts ----- */
|
} /* ----- end of function __AI_db_copy_alerts ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -271,7 +271,7 @@ AI_db_get_alerts ()
|
||||||
AI_snort_alert *alerts_copy;
|
AI_snort_alert *alerts_copy;
|
||||||
|
|
||||||
pthread_mutex_lock ( &mutex );
|
pthread_mutex_lock ( &mutex );
|
||||||
alerts_copy = _AI_db_copy_alerts ( alerts );
|
alerts_copy = __AI_db_copy_alerts ( alerts );
|
||||||
pthread_mutex_unlock ( &mutex );
|
pthread_mutex_unlock ( &mutex );
|
||||||
|
|
||||||
return alerts_copy;
|
return alerts_copy;
|
||||||
|
|
|
@ -1,32 +1,62 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<script type="text/javascript" src="js/raphael-min.js"></script>
|
<style rel="stylesheet" type="text/css">
|
||||||
<script type="text/javascript" src="js/dracula_graffle.js"></script>
|
#popupAlert {
|
||||||
<script type="text/javascript" src="js/dracula_graph.js"></script>
|
z-index : 100;
|
||||||
<script type="text/javascript">
|
display : none;
|
||||||
|
position : absolute;
|
||||||
|
border : 1px solid #000;
|
||||||
|
background-color : #89ffa7;
|
||||||
|
color : #000;
|
||||||
|
opacity : 0.6;
|
||||||
|
padding : 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#alertInfo {
|
||||||
|
display : none;
|
||||||
|
border : 1px solid #888;
|
||||||
|
padding : 3px;
|
||||||
|
height : 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#alertInfoTable {
|
||||||
|
font : Fixed;
|
||||||
|
font-size : 12px;
|
||||||
|
width : 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color : #22dd22;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="js/raphael.js"></script>
|
||||||
|
<script type="text/javascript" src="js/dracula_graffle.js"></script>
|
||||||
|
<script type="text/javascript" src="js/dracula_graph.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
var redraw;
|
redraw = null;
|
||||||
var width;
|
width = 0;
|
||||||
var height;
|
height = 0;
|
||||||
var layouter = null;
|
layouter = null;
|
||||||
var renderer = null;
|
renderer = null;
|
||||||
var json = [];
|
json = [];
|
||||||
|
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
var req = new XMLHttpRequest();
|
var req = new XMLHttpRequest();
|
||||||
|
|
||||||
if ( navigator.appName.indexOf('Microsoft') != -1 )
|
if ( navigator.appName.indexOf('Microsoft') != -1 )
|
||||||
{
|
{
|
||||||
width = (document.body.offsetWidth > 50) ?
|
width = (document.body.offsetWidth > 20) ?
|
||||||
document.body.offsetWidth - 50 : 50;
|
document.body.offsetWidth - 20 : 20;
|
||||||
height = (document.body.offsetHeight > 50 ) ?
|
height = (document.body.offsetHeight > 200 ) ?
|
||||||
document.body.offsetHeight - 50 : 50;
|
document.body.offsetHeight - 200 : 200;
|
||||||
} else {
|
} else {
|
||||||
width = (window.innerWidth > 50) ?
|
width = (window.innerWidth > 20) ?
|
||||||
window.innerWidth - 50 : 50;
|
window.innerWidth - 20 : 20;
|
||||||
height = (window.innerHeight > 50) ?
|
height = (window.innerHeight > 200) ?
|
||||||
window.innerHeight- 50 : 50;
|
window.innerHeight - 200 : 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
req.open ( 'GET', 'http://' + window.location.host + '/correlation_graph.json', true );
|
req.open ( 'GET', 'http://' + window.location.host + '/correlation_graph.json', true );
|
||||||
|
@ -58,6 +88,10 @@ window.onload = function() {
|
||||||
g.addEdge ( connections[i].from, connections[i].to, { directed: true });
|
g.addEdge ( connections[i].from, connections[i].to, { directed: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var canvas = document.getElementById ( 'canvas' );
|
||||||
|
canvas.style.width = width;
|
||||||
|
canvas.style.height = height;
|
||||||
|
|
||||||
var layouter = new Graph.Layout.Spring ( g );
|
var layouter = new Graph.Layout.Spring ( g );
|
||||||
layouter.layout();
|
layouter.layout();
|
||||||
|
|
||||||
|
@ -68,6 +102,154 @@ window.onload = function() {
|
||||||
layouter.layout();
|
layouter.layout();
|
||||||
renderer.draw();
|
renderer.draw();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for ( var i=0; i < json.length; i++ )
|
||||||
|
{
|
||||||
|
var node = document.getElementById ( 'alert' + json[i].id );
|
||||||
|
|
||||||
|
if ( node )
|
||||||
|
{
|
||||||
|
node.onclick = function() {
|
||||||
|
var div = document.getElementById ( 'alertInfo' );
|
||||||
|
|
||||||
|
if ( div )
|
||||||
|
{
|
||||||
|
var id = this.id.replace ( /^alert/, "" );
|
||||||
|
var json_element = null;
|
||||||
|
|
||||||
|
for ( var i=0; i < json.length; i++ )
|
||||||
|
{
|
||||||
|
if ( json[i].id == id )
|
||||||
|
{
|
||||||
|
json_element = json[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.style.display = 'block';
|
||||||
|
var content =
|
||||||
|
'<table id="alertInfoTable" cellspacing="5"><tr style="background-color:#99ff99">' +
|
||||||
|
'<td><b>Type</b></td><td><b>From</b></td>' +
|
||||||
|
'<td><b>To</b></td><td><b>Date</b></td></tr>' +
|
||||||
|
'<tr><td>' + json_element.label;
|
||||||
|
|
||||||
|
if ( json_element.packets )
|
||||||
|
{
|
||||||
|
content += ' (<a href="http://' + window.location.host + '/pcap.cgi?packets=' +
|
||||||
|
json_element.packets.length;
|
||||||
|
|
||||||
|
for ( var j=0; j < json_element.packets.length; j++ )
|
||||||
|
{
|
||||||
|
json_element.packets[j].match ( /^.*(=*)$/ );
|
||||||
|
var pad = RegExp.$1;
|
||||||
|
var len = parseInt ( json_element.packets[j].length * 3 / 4 ) - pad.length;
|
||||||
|
json_element.date.match ( /[a-zA-Z]+\s+([a-zA-Z]+)\s+([0-9]+)\s+([0-9]+):([0-9]+):([0-9]+)\s+([0-9]+)/ );
|
||||||
|
var month = RegExp.$1;
|
||||||
|
var day = RegExp.$2;
|
||||||
|
var hour = RegExp.$3;
|
||||||
|
var min = RegExp.$4;
|
||||||
|
var sec = RegExp.$5;
|
||||||
|
var year = RegExp.$6;
|
||||||
|
|
||||||
|
switch ( month )
|
||||||
|
{
|
||||||
|
case 'Jan': month = 1; break;
|
||||||
|
case 'Feb': month = 2; break;
|
||||||
|
case 'Mar': month = 3; break;
|
||||||
|
case 'Apr': month = 4; break;
|
||||||
|
case 'May': month = 5; break;
|
||||||
|
case 'Jun': month = 6; break;
|
||||||
|
case 'Jul': month = 7; break;
|
||||||
|
case 'Ago': month = 8; break;
|
||||||
|
case 'Sep': month = 9; break;
|
||||||
|
case 'Oct': month = 10; break;
|
||||||
|
case 'Nov': month = 11; break;
|
||||||
|
case 'Dec': month = 12; break;
|
||||||
|
default : month = 1; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var timestamp = new Date ( year, month, day, hour, min, sec).getTime().toString();
|
||||||
|
timestamp = timestamp.replace ( /0{3}$/, "" );
|
||||||
|
|
||||||
|
content += '&packet_len' + j + '=' + len +
|
||||||
|
'&time' + j + '=' + timestamp +
|
||||||
|
'&packet' + j + '=' + escape ( json_element.packets[j] );
|
||||||
|
}
|
||||||
|
|
||||||
|
content += '">save as pcap file</a>)';
|
||||||
|
}
|
||||||
|
|
||||||
|
content += '</td><td>' +
|
||||||
|
json_element.from + '</td><td>' + json_element.to + '</td>' +
|
||||||
|
'<td>' + json_element.date + '</td></tr>';
|
||||||
|
|
||||||
|
if ( json_element.clusteredAlerts )
|
||||||
|
{
|
||||||
|
for ( var j=0; j < json_element.clusteredAlerts.length; j++ )
|
||||||
|
{
|
||||||
|
content +=
|
||||||
|
'<tr><td>' + json_element.clusteredAlerts[j].label;
|
||||||
|
|
||||||
|
if ( json_element.clusteredAlerts[j].packets )
|
||||||
|
{
|
||||||
|
content += ' (<a href="http://' + window.location.host + '/pcap.cgi?packets=' +
|
||||||
|
json_element.clusteredAlerts[j].packets.length;
|
||||||
|
|
||||||
|
for ( var k=0; k < json_element.clusteredAlerts[j].packets.length; k++ )
|
||||||
|
{
|
||||||
|
var unescaped = unescape ( json_element.clusteredAlerts[j].packets[k] );
|
||||||
|
unescaped.match ( /(=+)/ );
|
||||||
|
var pad = RegExp.$1;
|
||||||
|
var len = parseInt ( json_element.clusteredAlerts[j].packets[k].length * 3 / 4 ) - pad.length;
|
||||||
|
json_element.clusteredAlerts[j].date.match ( /[a-zA-Z]+\s+([a-zA-Z]+)\s+([0-9]+)\s+([0-9]+):([0-9]+):([0-9]+)\s+([0-9]+)/ );
|
||||||
|
var month = RegExp.$1;
|
||||||
|
var day = RegExp.$2;
|
||||||
|
var hour = RegExp.$3;
|
||||||
|
var min = RegExp.$4;
|
||||||
|
var sec = RegExp.$5;
|
||||||
|
var year = RegExp.$6;
|
||||||
|
|
||||||
|
switch ( month )
|
||||||
|
{
|
||||||
|
case 'Jan': month = 1; break;
|
||||||
|
case 'Feb': month = 2; break;
|
||||||
|
case 'Mar': month = 3; break;
|
||||||
|
case 'Apr': month = 4; break;
|
||||||
|
case 'May': month = 5; break;
|
||||||
|
case 'Jun': month = 6; break;
|
||||||
|
case 'Jul': month = 7; break;
|
||||||
|
case 'Ago': month = 8; break;
|
||||||
|
case 'Sep': month = 9; break;
|
||||||
|
case 'Oct': month = 10; break;
|
||||||
|
case 'Nov': month = 11; break;
|
||||||
|
case 'Dec': month = 12; break;
|
||||||
|
default : month = 1; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var timestamp = new Date ( year, month, day, hour, min, sec).getTime().toString();
|
||||||
|
timestamp = timestamp.replace ( /0{3}$/, "" );
|
||||||
|
|
||||||
|
content += '&packet_len' + k + '=' + len +
|
||||||
|
'&time' + k + '=' + timestamp +
|
||||||
|
'&packet' + k + '=' + escape ( json_element.clusteredAlerts[j].packets[k] );
|
||||||
|
}
|
||||||
|
|
||||||
|
content += '">save as pcap file</a>)';
|
||||||
|
}
|
||||||
|
|
||||||
|
content += '</td>' +
|
||||||
|
'<td>' + json_element.clusteredAlerts[j].from + '</td>' +
|
||||||
|
'<td>' + json_element.clusteredAlerts[j].to + '</td>' +
|
||||||
|
'<td>' + json_element.clusteredAlerts[j].date + '</td></tr>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content += '</table>';
|
||||||
|
div.innerHTML = content;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,8 +260,11 @@ window.onload = function() {
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="canvas" style="border: 1px"></div>
|
<div id="canvas" style="border: 1px solid #000"></div>
|
||||||
<button id="redraw" onclick="redraw();">redraw</button>
|
<button id="redraw" onclick="redraw();">Redraw</button>
|
||||||
|
<div id="popupAlert"></div>
|
||||||
|
<div id="alertInfo"></div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
143
htdocs/js/base64.js
Normal file
143
htdocs/js/base64.js
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Base64 encode / decode
|
||||||
|
* http://www.webtoolkit.info/
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
var Base64 = {
|
||||||
|
|
||||||
|
// private property
|
||||||
|
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
||||||
|
|
||||||
|
// public method for encoding
|
||||||
|
encode : function (input) {
|
||||||
|
var output = "";
|
||||||
|
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
input = Base64._utf8_encode(input);
|
||||||
|
|
||||||
|
while (i < input.length) {
|
||||||
|
|
||||||
|
chr1 = input.charCodeAt(i++);
|
||||||
|
chr2 = input.charCodeAt(i++);
|
||||||
|
chr3 = input.charCodeAt(i++);
|
||||||
|
|
||||||
|
enc1 = chr1 >> 2;
|
||||||
|
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||||
|
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||||
|
enc4 = chr3 & 63;
|
||||||
|
|
||||||
|
if (isNaN(chr2)) {
|
||||||
|
enc3 = enc4 = 64;
|
||||||
|
} else if (isNaN(chr3)) {
|
||||||
|
enc4 = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = output +
|
||||||
|
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
|
||||||
|
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
|
||||||
|
// public method for decoding
|
||||||
|
decode : function (input) {
|
||||||
|
var output = "";
|
||||||
|
var chr1, chr2, chr3;
|
||||||
|
var enc1, enc2, enc3, enc4;
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||||
|
|
||||||
|
while (i < input.length) {
|
||||||
|
|
||||||
|
enc1 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc2 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc3 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc4 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
|
|
||||||
|
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||||
|
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||||
|
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||||
|
|
||||||
|
output = output + String.fromCharCode(chr1);
|
||||||
|
|
||||||
|
if (enc3 != 64) {
|
||||||
|
output = output + String.fromCharCode(chr2);
|
||||||
|
}
|
||||||
|
if (enc4 != 64) {
|
||||||
|
output = output + String.fromCharCode(chr3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
output = Base64._utf8_decode(output);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
// private method for UTF-8 encoding
|
||||||
|
_utf8_encode : function (string) {
|
||||||
|
string = string.replace(/\r\n/g,"\n");
|
||||||
|
var utftext = "";
|
||||||
|
|
||||||
|
for (var n = 0; n < string.length; n++) {
|
||||||
|
|
||||||
|
var c = string.charCodeAt(n);
|
||||||
|
|
||||||
|
if (c < 128) {
|
||||||
|
utftext += String.fromCharCode(c);
|
||||||
|
}
|
||||||
|
else if((c > 127) && (c < 2048)) {
|
||||||
|
utftext += String.fromCharCode((c >> 6) | 192);
|
||||||
|
utftext += String.fromCharCode((c & 63) | 128);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
utftext += String.fromCharCode((c >> 12) | 224);
|
||||||
|
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
||||||
|
utftext += String.fromCharCode((c & 63) | 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return utftext;
|
||||||
|
},
|
||||||
|
|
||||||
|
// private method for UTF-8 decoding
|
||||||
|
_utf8_decode : function (utftext) {
|
||||||
|
var string = "";
|
||||||
|
var i = 0;
|
||||||
|
var c = c1 = c2 = 0;
|
||||||
|
|
||||||
|
while ( i < utftext.length ) {
|
||||||
|
|
||||||
|
c = utftext.charCodeAt(i);
|
||||||
|
|
||||||
|
if (c < 128) {
|
||||||
|
string += String.fromCharCode(c);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if((c > 191) && (c < 224)) {
|
||||||
|
c2 = utftext.charCodeAt(i+1);
|
||||||
|
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c2 = utftext.charCodeAt(i+1);
|
||||||
|
c3 = utftext.charCodeAt(i+2);
|
||||||
|
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -208,7 +208,9 @@ Graph.Renderer.Raphael.prototype = {
|
||||||
} else {
|
} else {
|
||||||
var color = Raphael.getColor();
|
var color = Raphael.getColor();
|
||||||
shape = this.r.set().
|
shape = this.r.set().
|
||||||
push(this.r.ellipse(point[0], point[1], 30, 20).attr({fill: color, stroke: color, "stroke-width": 2})).
|
push(this.r.ellipse(point[0], point[1], 30, 20).attr({fill: color, stroke: color, "stroke-width": 2,
|
||||||
|
/* Added by BlackLight */
|
||||||
|
"id": "alert" + node.id})).
|
||||||
push(this.r.text(point[0], point[1] + 30, node.label || node.id));
|
push(this.r.text(point[0], point[1] + 30, node.label || node.id));
|
||||||
}
|
}
|
||||||
shape.attr({"fill-opacity": .6});
|
shape.attr({"fill-opacity": .6});
|
||||||
|
|
129
htdocs/js/popup.js
Normal file
129
htdocs/js/popup.js
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
var dom = (document.getElementById) ? true : false;
|
||||||
|
var ns5 = ((navigator.userAgent.indexOf("Gecko")>-1) && dom) ? true: false;
|
||||||
|
var ie5 = ((navigator.userAgent.indexOf("MSIE")>-1) && dom) ? true : false;
|
||||||
|
var ns4 = (document.layers && !dom) ? true : false;
|
||||||
|
var ie4 = (document.all && !dom) ? true : false;
|
||||||
|
var nodyn = (!ns5 && !ns4 && !ie4 && !ie5) ? true : false;
|
||||||
|
|
||||||
|
var origWidth, origHeight;
|
||||||
|
if (ns4) {
|
||||||
|
origWidth = window.innerWidth; origHeight = window.innerHeight;
|
||||||
|
window.onresize = function() { if (window.innerWidth != origWidth || window.innerHeight != origHeight) history.go(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodyn) { event = "nope" }
|
||||||
|
var tipFollowMouse = true;
|
||||||
|
var tipWidth = 160;
|
||||||
|
var offX = 12; // how far from mouse to show tip
|
||||||
|
var offY = 12;
|
||||||
|
var tipFontFamily = "Verdana, arial, helvetica, sans-serif";
|
||||||
|
var tipFontSize = "8pt";
|
||||||
|
var tipFontColor = "#000000";
|
||||||
|
var tipBgColor = "#DDECFF";
|
||||||
|
var origBgColor = tipBgColor; // in case no bgColor set in array
|
||||||
|
var tipBorderColor = "#000080";
|
||||||
|
var tipBorderWidth = 2;
|
||||||
|
var tipBorderStyle = "ridge";
|
||||||
|
var tipPadding = 4;
|
||||||
|
|
||||||
|
var messages = new Array();
|
||||||
|
messages[0] = new Array('http://planmagic.com/images/plmbiz.jpg','Professional business planning software.',"#FFFFFF");
|
||||||
|
messages[1] = new Array('http://planmagic.com/images/plmmar.jpg','Professional marketing planning software.',"#DDECFF");
|
||||||
|
messages[2] = new Array('http://planmagic.com/images/plmfinance.jpg','Financial calculations and projections made easy.',"#E9E9E9");
|
||||||
|
|
||||||
|
if (document.images) {
|
||||||
|
var theImgs = new Array();
|
||||||
|
for (var i=0; i<messages.length; i++) {
|
||||||
|
theImgs[i] = new Image();
|
||||||
|
theImgs[i].src = messages[i][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var startStr = '<table width="' + tipWidth + '"><tr><td align="center" width="100%"><img src="';
|
||||||
|
var midStr = '" border="0"></td></tr><tr><td valign="top">';
|
||||||
|
var endStr = '</td></tr></table>';
|
||||||
|
|
||||||
|
var tooltip, tipcss;
|
||||||
|
function initTip() {
|
||||||
|
if (nodyn) return;
|
||||||
|
tooltip = (ns4)? document.tipDiv.document: (ie4)? document.all['tipDiv']: (ie5||ns5)? document.getElementById('tipDiv'): null;
|
||||||
|
tipcss = (ns4)? document.tipDiv: tooltip.style;
|
||||||
|
if (ie4||ie5||ns5) { // ns4 would lose all this on rewrites
|
||||||
|
tipcss.width = tipWidth+"px";
|
||||||
|
tipcss.fontFamily = tipFontFamily;
|
||||||
|
tipcss.fontSize = tipFontSize;
|
||||||
|
tipcss.color = tipFontColor;
|
||||||
|
tipcss.backgroundColor = tipBgColor;
|
||||||
|
tipcss.borderColor = tipBorderColor;
|
||||||
|
tipcss.borderWidth = tipBorderWidth+"px";
|
||||||
|
tipcss.padding = tipPadding+"px";
|
||||||
|
tipcss.borderStyle = tipBorderStyle;
|
||||||
|
}
|
||||||
|
if (tooltip&&tipFollowMouse) {
|
||||||
|
if (ns4) document.captureEvents(Event.MOUSEMOVE);
|
||||||
|
document.onmousemove = trackMouse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = initTip;
|
||||||
|
|
||||||
|
var t1,t2; // for setTimeouts
|
||||||
|
var tipOn = false; // check if over tooltip link
|
||||||
|
function doTooltip(evt,num) {
|
||||||
|
|
||||||
|
if (!tooltip) return;
|
||||||
|
if (t1) clearTimeout(t1); if (t2) clearTimeout(t2);
|
||||||
|
tipOn = true;
|
||||||
|
// set colors if included in messages array
|
||||||
|
if (messages[num][2]) var curBgColor = messages[num][2];
|
||||||
|
else curBgColor = tipBgColor;
|
||||||
|
if (messages[num][3]) var curFontColor = messages[num][3];
|
||||||
|
else curFontColor = tipFontColor;
|
||||||
|
if (ns4) {
|
||||||
|
var tip = '<table bgcolor="' + tipBorderColor + '" width="' + tipWidth + '" cellspacing="0" cellpadding="' + tipBorderWidth + '" border="0"><tr><td><table bgcolor="' + curBgColor + '" width="100%" cellspacing="0" cellpadding="' + tipPadding + '" border="0"><tr><td>'+ startStr + messages[num][0] + midStr + '<span style="font-family:' + tipFontFamily + '; font-size:' + tipFontSize + '; color:' + curFontColor + ';">' + messages[num][1] + '</span>' + endStr + '</td></tr></table></td></tr></table>';
|
||||||
|
tooltip.write(tip);
|
||||||
|
tooltip.close();
|
||||||
|
} else if (ie4||ie5||ns5) {
|
||||||
|
var tip = startStr + messages[num][0] + midStr + '<span style="font-family:' + tipFontFamily + '; font-size:' + tipFontSize + '; color:' + curFontColor + ';">' + messages[num][1] + '</span>' + endStr;
|
||||||
|
tipcss.backgroundColor = curBgColor;
|
||||||
|
tooltip.innerHTML = tip;
|
||||||
|
}
|
||||||
|
if (!tipFollowMouse) positionTip(evt);
|
||||||
|
else t1=setTimeout("tipcss.visibility='visible'",100);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mouseX, mouseY;
|
||||||
|
function trackMouse(evt) {
|
||||||
|
mouseX = (ns4||ns5)? evt.pageX: window.event.clientX + document.body.scrollLeft;
|
||||||
|
mouseY = (ns4||ns5)? evt.pageY: window.event.clientY + document.body.scrollTop;
|
||||||
|
if (tipOn) positionTip(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
function positionTip(evt) {
|
||||||
|
if (!tipFollowMouse) {
|
||||||
|
mouseX = (ns4||ns5)? evt.pageX: window.event.clientX + document.body.scrollLeft;
|
||||||
|
mouseY = (ns4||ns5)? evt.pageY: window.event.clientY + document.body.scrollTop;
|
||||||
|
}
|
||||||
|
// tooltip width and height
|
||||||
|
var tpWd = (ns4)? tooltip.width: (ie4||ie5)? tooltip.clientWidth: tooltip.offsetWidth;
|
||||||
|
var tpHt = (ns4)? tooltip.height: (ie4||ie5)? tooltip.clientHeight: tooltip.offsetHeight;
|
||||||
|
// document area in view (subtract scrollbar width for ns)
|
||||||
|
var winWd = (ns4||ns5)? window.innerWidth-20+window.pageXOffset: document.body.clientWidth+document.body.scrollLeft;
|
||||||
|
var winHt = (ns4||ns5)? window.innerHeight-20+window.pageYOffset: document.body.clientHeight+document.body.scrollTop;
|
||||||
|
// check mouse position against tip and window dimensions
|
||||||
|
// and position the tooltip
|
||||||
|
if ((mouseX+offX+tpWd)>winWd)
|
||||||
|
tipcss.left = (ns4)? mouseX-(tpWd+offX): mouseX-(tpWd+offX)+"px";
|
||||||
|
else tipcss.left = (ns4)? mouseX+offX: mouseX+offX+"px";
|
||||||
|
if ((mouseY+offY+tpHt)>winHt)
|
||||||
|
tipcss.top = (ns4)? winHt-(tpHt+offY): winHt-(tpHt+offY)+"px";
|
||||||
|
else tipcss.top = (ns4)? mouseY+offY: mouseY+offY+"px";
|
||||||
|
if (!tipFollowMouse) t1=setTimeout("tipcss.visibility='visible'",100);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideTip() {
|
||||||
|
if (!tooltip) return;
|
||||||
|
t2=setTimeout("tipcss.visibility='hidden'",100);
|
||||||
|
tipOn = false;
|
||||||
|
}
|
||||||
|
|
7
htdocs/js/raphael-min.js
vendored
7
htdocs/js/raphael-min.js
vendored
File diff suppressed because one or more lines are too long
3737
htdocs/js/raphael.js
Normal file
3737
htdocs/js/raphael.js
Normal file
File diff suppressed because it is too large
Load diff
132
htdocs/pcap.cgi
Executable file
132
htdocs/pcap.cgi
Executable file
|
@ -0,0 +1,132 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use MIME::Base64;
|
||||||
|
use Env qw(QUERY_STRING DOCUMENT_ROOT);
|
||||||
|
|
||||||
|
sub url_decode {
|
||||||
|
my $str = shift;
|
||||||
|
$str =~ s/%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;;
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub print_pcap_header {
|
||||||
|
my $out = shift;
|
||||||
|
|
||||||
|
# pcap magic_number
|
||||||
|
print $out pack ( 'L', 0xa1b2c3d4 );
|
||||||
|
|
||||||
|
# pcap version_major
|
||||||
|
print $out pack ( 'S', 0x2 );
|
||||||
|
|
||||||
|
# pcap version_minor
|
||||||
|
print $out pack ( 'S', 0x4 );
|
||||||
|
|
||||||
|
# pcap thiszone
|
||||||
|
print $out pack ( 'l', 0x0 );
|
||||||
|
|
||||||
|
# pcap sigfigs
|
||||||
|
print $out pack ( 'L', 0x0 );
|
||||||
|
|
||||||
|
# pcap snaplen
|
||||||
|
print $out pack ( 'L', 0xffff );
|
||||||
|
|
||||||
|
# pcap network
|
||||||
|
print $out pack ( 'L', 0x1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub print_packet {
|
||||||
|
my ( $out, $packet ) = @_;
|
||||||
|
|
||||||
|
# ts_sec
|
||||||
|
print $out pack ( 'L', $packet->{'time'} );
|
||||||
|
|
||||||
|
# ts_usec
|
||||||
|
print $out pack ( 'L', 0x0 );
|
||||||
|
|
||||||
|
my $pkt_data = decode_base64 ( url_decode ( $packet->{'content'} ));
|
||||||
|
my $hex = unpack ( 'H*', $pkt_data );
|
||||||
|
my @pairs = $hex =~ /([a-fA-F0-9]{2})/g;
|
||||||
|
|
||||||
|
# If this is not an IP packet, trust what the client has told you as packet length
|
||||||
|
if (( $pairs[0] ne '45' && $pairs[1] ne '00' ) || ( @pairs < 5 ))
|
||||||
|
{
|
||||||
|
# incl_len
|
||||||
|
print $out pack ( 'L', $packet->{'length'} + 12 );
|
||||||
|
|
||||||
|
# orig_len
|
||||||
|
print $out pack ( 'L', $packet->{'length'} + 12 );
|
||||||
|
} else {
|
||||||
|
# Otherwise, the length of the packet is the one specified in the IP header
|
||||||
|
my $length = hex ( $pairs[2].$pairs[3] );
|
||||||
|
|
||||||
|
# If the lengths differ (IP length and actual length of the stream received), pad
|
||||||
|
# the end of the packet with some 0's so that its length matches the one
|
||||||
|
# specified in the IP header
|
||||||
|
if ( $length > ( length ( $hex ) / 2 ))
|
||||||
|
{
|
||||||
|
my $pad_size = $length - ( length ( $hex ) / 2 );
|
||||||
|
$hex .= '00' for ( 0..$pad_size-1 );
|
||||||
|
$pkt_data = pack ( 'H*', $hex );
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add the length of a pseudo-ethernet header
|
||||||
|
$length += 14;
|
||||||
|
|
||||||
|
# incl_len
|
||||||
|
print $out pack ( 'L', $length );
|
||||||
|
|
||||||
|
# orig_len
|
||||||
|
print $out pack ( 'L', $length );
|
||||||
|
}
|
||||||
|
|
||||||
|
# pseudo ethernet header
|
||||||
|
print $out pack ( 'H*', 0 x24 );
|
||||||
|
|
||||||
|
# ethernet type (IP)
|
||||||
|
print $out pack ( 'S', 0x8 );
|
||||||
|
|
||||||
|
# packet content
|
||||||
|
print $out $pkt_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
$QUERY_STRING =~ /packets=([0-9]+)/;
|
||||||
|
my $packets_num = $1;
|
||||||
|
my %packets = ();
|
||||||
|
|
||||||
|
for ( my $i=0; $i < $packets_num; $i++ )
|
||||||
|
{
|
||||||
|
$QUERY_STRING =~ /packet_len$i=([0-9]+)/;
|
||||||
|
my $length = $1;
|
||||||
|
|
||||||
|
$QUERY_STRING =~ /time$i=([0-9]+)/;
|
||||||
|
my $time = $1;
|
||||||
|
|
||||||
|
$QUERY_STRING =~ /packet$i=(.+?)(&|$)/;
|
||||||
|
my $content = $1;
|
||||||
|
|
||||||
|
$packets{$i} = {
|
||||||
|
'length' => $length,
|
||||||
|
'time' => $time,
|
||||||
|
'content' => $content
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
print "Content-Type: application/pcap\n\n";
|
||||||
|
|
||||||
|
# open my $out, "> $DOCUMENT_ROOT/out.pcap";
|
||||||
|
open my $out, ">&STDOUT";
|
||||||
|
binmode $out;
|
||||||
|
print_pcap_header $out;
|
||||||
|
|
||||||
|
for ( my $i=0; $i < $packets_num; $i++ )
|
||||||
|
{
|
||||||
|
print_packet $out, $packets{$i};
|
||||||
|
}
|
||||||
|
|
||||||
|
close $out;
|
||||||
|
|
||||||
|
# print "Content-Type: text/html\\n\\n";
|
||||||
|
# print "<meta http-equiv=\\"refresh\\" content=\\"0;url=/out.pcap\\">\\n";
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
echo "Content-Type: text/html"
|
|
||||||
echo
|
|
||||||
echo "<h1>LOL</h1>"
|
|
||||||
echo "Query string: <b>$QUERY_STRING</b><br>"
|
|
||||||
echo "Accept: <b>$HTTP_ACCEPT</b><br>"
|
|
||||||
echo "User-Agent: <b>$HTTP_USER_AGENT</b><br>"
|
|
||||||
echo "Client addr : <b>$REMOTE_ADDR</b><br>"
|
|
||||||
|
|
15
outdb.c
15
outdb.c
|
@ -239,16 +239,25 @@ AI_store_alert_to_db_thread ( void *arg )
|
||||||
for ( pkt = alert->stream; pkt; pkt = pkt->next )
|
for ( pkt = alert->stream; pkt; pkt = pkt->next )
|
||||||
{
|
{
|
||||||
pkt_data = NULL;
|
pkt_data = NULL;
|
||||||
pkt_size = pkt->pkt->pcap_cap_len;
|
|
||||||
|
if ( !pkt->pkt->ip4_header )
|
||||||
|
{
|
||||||
|
pkt_size = pkt->pkt->pcap_header->len +
|
||||||
|
pkt->pkt->tcp_options_length +
|
||||||
|
pkt->pkt->payload_size;
|
||||||
|
} else {
|
||||||
|
pkt_size = pkt->pkt->ip4_header->data_length;
|
||||||
|
}
|
||||||
|
|
||||||
pkt_size_offset = 0;
|
pkt_size_offset = 0;
|
||||||
|
|
||||||
if ( !( pkt_data = (unsigned char*) alloca ( 2 * (pkt->pkt->pcap_header->len + pkt->pkt->payload_size) + 1 )))
|
if ( !( pkt_data = (unsigned char*) alloca ( 2 * ( pkt_size ) + 1 )))
|
||||||
AI_fatal_err ( "Fatal dynamic memory allocation error", __FILE__, __LINE__ );
|
AI_fatal_err ( "Fatal dynamic memory allocation error", __FILE__, __LINE__ );
|
||||||
|
|
||||||
DB_out_escape_string (
|
DB_out_escape_string (
|
||||||
(char**) &pkt_data,
|
(char**) &pkt_data,
|
||||||
(const char*) pkt->pkt->pkt_data,
|
(const char*) pkt->pkt->pkt_data,
|
||||||
pkt->pkt->pcap_header->len + pkt->pkt->payload_size );
|
pkt_size );
|
||||||
|
|
||||||
memset ( query, 0, sizeof ( query ));
|
memset ( query, 0, sizeof ( query ));
|
||||||
|
|
||||||
|
|
2
spp_ai.h
2
spp_ai.h
|
@ -408,6 +408,8 @@ typedef struct {
|
||||||
int preg_match ( const char*, char*, char***, int* );
|
int preg_match ( const char*, char*, char***, int* );
|
||||||
char* str_replace ( char*, char*, char *);
|
char* str_replace ( char*, char*, char *);
|
||||||
char* str_replace_all ( char*, char*, char* );
|
char* str_replace_all ( char*, char*, char* );
|
||||||
|
void base64_encode ( const char*, size_t, char** );
|
||||||
|
void base64_decode ( const char*, char** );
|
||||||
|
|
||||||
void AI_fatal_err ( const char *msg, const char *file, const int line );
|
void AI_fatal_err ( const char *msg, const char *file, const int line );
|
||||||
void* AI_hashcleanup_thread ( void* );
|
void* AI_hashcleanup_thread ( void* );
|
||||||
|
|
10
stream.c
10
stream.c
|
@ -40,7 +40,7 @@ PRIVATE pthread_mutex_t hash_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PRIVATE void
|
PRIVATE void
|
||||||
_AI_stream_free ( struct pkt_info* stream )
|
__AI_stream_free ( struct pkt_info* stream )
|
||||||
{
|
{
|
||||||
struct pkt_info *tmp = NULL;
|
struct pkt_info *tmp = NULL;
|
||||||
char ip [ INET_ADDRSTRLEN ];
|
char ip [ INET_ADDRSTRLEN ];
|
||||||
|
@ -85,7 +85,7 @@ _AI_stream_free ( struct pkt_info* stream )
|
||||||
}
|
}
|
||||||
|
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
} /* ----- end of function _AI_stream_free ----- */
|
} /* ----- end of function __AI_stream_free ----- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -131,7 +131,7 @@ AI_hashcleanup_thread ( void* arg )
|
||||||
* I won't find an answer to these enigmatic questions, I will leave
|
* I won't find an answer to these enigmatic questions, I will leave
|
||||||
* this code commented, so if a certain stream goes timeout it won't
|
* this code commented, so if a certain stream goes timeout it won't
|
||||||
* be removed. I'm sorry but it's not my fault. Ask the karma about this */
|
* be removed. I'm sorry but it's not my fault. Ask the karma about this */
|
||||||
/* _AI_stream_free ( stream ); */
|
/* __AI_stream_free ( stream ); */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ AI_pkt_enqueue ( SFSnortPacket* pkt )
|
||||||
|
|
||||||
if ( found ) {
|
if ( found ) {
|
||||||
if ( !found->observed ) {
|
if ( !found->observed ) {
|
||||||
_AI_stream_free ( found );
|
__AI_stream_free ( found );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -233,7 +233,7 @@ AI_pkt_enqueue ( SFSnortPacket* pkt )
|
||||||
|
|
||||||
if ( found ) {
|
if ( found ) {
|
||||||
if ( !found->observed ) {
|
if ( !found->observed ) {
|
||||||
_AI_stream_free ( found );
|
__AI_stream_free ( found );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
webserv.c
26
webserv.c
|
@ -196,6 +196,7 @@ __AI_webservlet_thread ( void *arg )
|
||||||
nmatches = 0,
|
nmatches = 0,
|
||||||
max_content_length = 0,
|
max_content_length = 0,
|
||||||
max_headers_length = 0,
|
max_headers_length = 0,
|
||||||
|
read_bytes = 0,
|
||||||
req_file_absolute_path_size = 0;
|
req_file_absolute_path_size = 0;
|
||||||
|
|
||||||
char ch,
|
char ch,
|
||||||
|
@ -419,9 +420,14 @@ __AI_webservlet_thread ( void *arg )
|
||||||
}
|
}
|
||||||
|
|
||||||
http_response [ http_response_len - 2 ] = ch;
|
http_response [ http_response_len - 2 ] = ch;
|
||||||
|
read_bytes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( http_response )
|
||||||
|
{
|
||||||
|
http_response [ http_response_len - 1 ] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
http_response [ http_response_len - 1 ] = 0;
|
|
||||||
pclose ( pipe );
|
pclose ( pipe );
|
||||||
|
|
||||||
if ( !http_response )
|
if ( !http_response )
|
||||||
|
@ -440,8 +446,10 @@ __AI_webservlet_thread ( void *arg )
|
||||||
!strcasecmp ( extension, "ppm" )) {
|
!strcasecmp ( extension, "ppm" )) {
|
||||||
snprintf ( content_type, sizeof ( content_type ),
|
snprintf ( content_type, sizeof ( content_type ),
|
||||||
"image/%s", extension );
|
"image/%s", extension );
|
||||||
} else {
|
} else if ( strlen ( extension ) == 0 || !strcasecmp ( extension, "txt" )) {
|
||||||
strncpy ( content_type, "text/plain", sizeof ( content_type ));
|
strncpy ( content_type, "text/plain", sizeof ( content_type ));
|
||||||
|
} else {
|
||||||
|
snprintf ( content_type, sizeof ( content_type ), "application/%s", extension );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !is_cgi )
|
if ( !is_cgi )
|
||||||
|
@ -464,11 +472,17 @@ __AI_webservlet_thread ( void *arg )
|
||||||
if ( is_cgi )
|
if ( is_cgi )
|
||||||
{
|
{
|
||||||
snprintf ( http_headers, max_headers_length, HTTP_CGI_RESPONSE_HEADERS_FORMAT,
|
snprintf ( http_headers, max_headers_length, HTTP_CGI_RESPONSE_HEADERS_FORMAT,
|
||||||
http_ver, 200, "Found", strtime, config->webserv_banner, strlen ( http_response ));
|
http_ver, 200, "Found", strtime, config->webserv_banner,
|
||||||
|
/* strlen ( http_response )); */
|
||||||
|
read_bytes );
|
||||||
} else {
|
} else {
|
||||||
|
read_bytes = (unsigned int) st.st_size;
|
||||||
|
|
||||||
snprintf ( http_headers, max_headers_length, HTTP_RESPONSE_HEADERS_FORMAT,
|
snprintf ( http_headers, max_headers_length, HTTP_RESPONSE_HEADERS_FORMAT,
|
||||||
http_ver, 200, "Found", strtime, config->webserv_banner,
|
http_ver, 200, "Found", strtime, config->webserv_banner,
|
||||||
content_type, strlen ( http_response ));
|
content_type,
|
||||||
|
/* strlen ( http_response )); */
|
||||||
|
read_bytes );
|
||||||
}
|
}
|
||||||
|
|
||||||
free ( strtime );
|
free ( strtime );
|
||||||
|
@ -588,7 +602,9 @@ __AI_webservlet_thread ( void *arg )
|
||||||
line = NULL;
|
line = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf ( sock, "%s%s", http_headers, http_response );
|
/* fprintf ( sock, "%s%s", http_headers, http_response ); */
|
||||||
|
fprintf ( sock, "%s", http_headers );
|
||||||
|
fwrite ( http_response, read_bytes, 1, sock );
|
||||||
fclose ( sock );
|
fclose ( sock );
|
||||||
close ( sd );
|
close ( sd );
|
||||||
free ( arg );
|
free ( arg );
|
||||||
|
|
Loading…
Reference in a new issue