--- acinclude.m4 1970-01-01 01:00:00.000000000 +0100 +++ acinclude.m4 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,135 @@ +dnl @synopsis AC_PATH_GENERIC(LIBRARY [, MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl +dnl Runs a LIBRARY-config script and defines LIBRARY_CFLAGS and LIBRARY_LIBS +dnl +dnl The script must support `--cflags' and `--libs' args. +dnl If MINIMUM-VERSION is specified, the script must also support the +dnl `--version' arg. +dnl If the `--with-library-[exec-]prefix' arguments to ./configure are given, +dnl it must also support `--prefix' and `--exec-prefix'. +dnl (In other words, it must be like gtk-config.) +dnl +dnl For example: +dnl +dnl AC_PATH_GENERIC(Foo, 1.0.0) +dnl +dnl would run `foo-config --version' and check that it is at least 1.0.0 +dnl +dnl If so, the following would then be defined: +dnl +dnl FOO_CFLAGS to `foo-config --cflags` +dnl FOO_LIBS to `foo-config --libs` +dnl +dnl (shamelessly stolen from gtk.m4 and then hacked around a fair amount) +dnl +dnl @author Angus Lees +dnl @version $Id: acinclude.m4,v 1.2 2002/02/20 10:11:42 yoann Exp $ + +AC_DEFUN(AC_PATH_GENERIC, +[dnl +dnl we're going to need uppercase, lowercase and user-friendly versions of the +dnl string `LIBRARY' +pushdef([UP], translit([$1], [a-z], [A-Z]))dnl +pushdef([DOWN], translit([$1], [A-Z], [a-z]))dnl + +dnl +dnl Get the cflags and libraries from the LIBRARY-config script +dnl +AC_ARG_WITH(DOWN-prefix,[ --with-]DOWN[-prefix=PFX Prefix where $1 is installed (optional)], + DOWN[]_config_prefix="$withval", DOWN[]_config_prefix="") +AC_ARG_WITH(DOWN-exec-prefix,[ --with-]DOWN[-exec-prefix=PFX Exec prefix where $1 is installed (optional)], + DOWN[]_config_exec_prefix="$withval", DOWN[]_config_exec_prefix="") + + if test x$DOWN[]_config_exec_prefix != x ; then + DOWN[]_config_args="$DOWN[]_config_args --exec-prefix=$DOWN[]_config_exec_prefix" + if test x${UP[]_CONFIG+set} != xset ; then + UP[]_CONFIG=$DOWN[]_config_exec_prefix/bin/DOWN-config + fi + fi + if test x$DOWN[]_config_prefix != x ; then + DOWN[]_config_args="$DOWN[]_config_args --prefix=$DOWN[]_config_prefix" + if test x${UP[]_CONFIG+set} != xset ; then + UP[]_CONFIG=$DOWN[]_config_prefix/bin/DOWN-config + fi + fi + + AC_PATH_PROG(UP[]_CONFIG, DOWN-config, no) + ifelse([$2], , + AC_MSG_CHECKING(for $1), + AC_MSG_CHECKING(for $1 - version >= $2) + ) + no_[]DOWN="" + if test "$UP[]_CONFIG" = "no" ; then + no_[]DOWN=yes + else + UP[]_CFLAGS="`$UP[]_CONFIG $DOWN[]_config_args --cflags`" + UP[]_LIBS="`$UP[]_CONFIG $DOWN[]_config_args --libs`" + ifelse([$2], , ,[ + DOWN[]_config_major_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + DOWN[]_config_minor_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + DOWN[]_config_micro_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + DOWN[]_wanted_major_version="regexp($2, [\<\([0-9]*\)], [\1])" + DOWN[]_wanted_minor_version="regexp($2, [\<\([0-9]*\)\.\([0-9]*\)], [\2])" + DOWN[]_wanted_micro_version="regexp($2, [\<\([0-9]*\).\([0-9]*\).\([0-9]*\)], [\3])" + + # Compare wanted version to what config script returned. + # If I knew what library was being run, i'd probably also compile + # a test program at this point (which also extracted and tested + # the version in some library-specific way) + if test "$DOWN[]_config_major_version" -lt \ + "$DOWN[]_wanted_major_version" \ + -o \( "$DOWN[]_config_major_version" -eq \ + "$DOWN[]_wanted_major_version" \ + -a "$DOWN[]_config_minor_version" -lt \ + "$DOWN[]_wanted_minor_version" \) \ + -o \( "$DOWN[]_config_major_version" -eq \ + "$DOWN[]_wanted_major_version" \ + -a "$DOWN[]_config_minor_version" -eq \ + "$DOWN[]_wanted_minor_version" \ + -a "$DOWN[]_config_micro_version" -lt \ + "$DOWN[]_wanted_micro_version" \) ; then + # older version found + no_[]DOWN=yes + echo -n "*** An old version of $1 " + echo -n "($DOWN[]_config_major_version" + echo -n ".$DOWN[]_config_minor_version" + echo ".$DOWN[]_config_micro_version) was found." + echo -n "*** You need a version of $1 newer than " + echo -n "$DOWN[]_wanted_major_version" + echo -n ".$DOWN[]_wanted_minor_version" + echo ".$DOWN[]_wanted_micro_version." + echo "***" + echo "*** If you have already installed a sufficiently new version, this error" + echo "*** probably means that the wrong copy of the DOWN-config shell script is" + echo "*** being found. The easiest way to fix this is to remove the old version" + echo "*** of $1, but you can also set the UP[]_CONFIG environment to point to the" + echo "*** correct copy of DOWN-config. (In this case, you will have to" + echo "*** modify your LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf" + echo "*** so that the correct libraries are found at run-time)" + fi + ]) + fi + if test "x$no_[]DOWN" = x ; then + AC_MSG_RESULT(yes) + ifelse([$3], , :, [$3]) + else + AC_MSG_RESULT(no) + if test "$UP[]_CONFIG" = "no" ; then + echo "*** The DOWN-config script installed by $1 could not be found" + echo "*** If $1 was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the UP[]_CONFIG environment variable to the" + echo "*** full path to DOWN-config." + fi + UP[]_CFLAGS="" + UP[]_LIBS="" + ifelse([$4], , :, [$4]) + fi + AC_SUBST(UP[]_CFLAGS) + AC_SUBST(UP[]_LIBS) + + popdef([UP]) + popdef([DOWN]) +]) --- configure.in 2004-08-11 19:42:18.000000000 +0200 +++ configure.in 2004-09-15 22:28:55.000000000 +0200 @@ -361,6 +361,28 @@ LDFLAGS="${LDFLAGS} -L${with_libnet_libraries}" fi + +# +# Support for prelude +# +AC_ARG_WITH(prelude, + [ --with-prelude support for Prelude IDS], + [ with_prelude="$withval" ], + [ with_prelude=yes]) + +if test "$with_prelude" = "yes"; then + AC_MSG_CHECKING(for Prelude) + + AC_PATH_GENERIC(libprelude, 0.8.0, use_prelude=yes, use_prelude=no) + if test "$use_prelude" = "yes"; then + PRELUDE_LIBS=`libprelude-config --libs` + PRELUDE_CFLAGS=`libprelude-config --cflags` + LDFLAGS="${LDFLAGS} ${PRELUDE_LIBS}" + CPPFLAGS="${CPPFLAGS} ${PRELUDE_CFLAGS} -DWITH_PRELUDE" + fi +fi + + AC_ARG_WITH(mysql, [ --with-mysql=DIR support for mysql], [ with_mysql="$withval" ], @@ -749,6 +771,7 @@ src/sfutil/Makefile \ src/detection-plugins/Makefile \ src/output-plugins/Makefile \ +src/output-plugins/spo_alert_prelude/Makefile \ src/preprocessors/Makefile \ src/preprocessors/HttpInspect/Makefile \ src/preprocessors/HttpInspect/include/Makefile \ --- doc/README.Prelude 1970-01-01 01:00:00.000000000 +0100 +++ doc/README.Prelude 2004-09-15 23:40:00.000000000 +0200 @@ -0,0 +1,367 @@ +Prelude IDS 0.8.x support for Snort +=================================== + +Snort Prelude Output Plugin (spo_alert_prelude) allows Snort to +communicate with Manager of the Prelude Hybrid IDS Suite version +0.8.x. The code is still considered experimental. All bug reports +are welcome and encouraged. + +Prelude is available from http://www.prelude-ids.org/ under the terms +of GNU Public License version 2. + +No warranty of any kind is provided, you use this code at +your own risk. + +Installation +------------ + +You must have libprelude (version 0.8.x) installed on your system before +building Snort. + +If you are installing via patch, you must run autogen.sh script +to generate the new configure file. Note that you will need autoconf 2.53 +or higher. + +A new option --with-prelude has been added to configure. This option is +on by default, so configure ran with no parameters will try to detect +libprelude. If you wish to disable Prelude support use run configure +with --with-prelude=no option. When Prelude support is enabled and +libprelude is found, Snort will be compiled with necessary build time +flags, most importantly -DWITH_PRELUDE will be set, what directly enables +Prelude-related code. + +After configure is done, proceed with snort build normaly, i.e. doing +make && make install + +If Snort is build with -DPRELUDE_DEBUG option set, you will be able +to see plugin's debug messages printed to stdout. Compiling Snort with +-DDEBUG implies -DPRELUDE_DEBUG. + +Configuration +------------- + +Edit your snort.conf file and make sure that plugin is enabled, i.e. there +is the line like: + +output alert_prelude: async, classification_file=prelude-classification.config + +The plugin currently takes following parameters: + +async + Optional parameter. + + This option enables asynchronous reporting mode in which + the alert transmission to Prelude Manager is performed by + a separate thread (different from the main Snort thread). + + If you are experiencing problems with asynchronous + reporting (i.e. lockups on exit) remove this option. + +classification_file=/path/to/file + Optional parameter. + + This parameter specifies the location of the + classification.config file from Prelude NIDS + 0.8.x distribution. This file differs significantly + from classification.config used Snort. + + The file is included in this distribution as + prelude-classification.config. + + The Prelude file is used attempt to provide some + consistency in IDMEF classification of the alerts sent + by both Snort and Prelude NIDS. + + Default: prelude-classification.config + +sensor_name=name + Optional parameter. + + This parameter specifies the name of the sensor. + + Default: snort + +config_file=/path/to/file + Optional parameter. + + This parameter specifies the name of the sensor configuration + file used by libprelude. The values in this file override these + from $PREFIX/etc/prelude-sensors/sensors-default.conf. + The format of the file is the same. + + Default: none + +impact_severity={low,medium,high} + Optional parameter. + + When we cannot determine impact severity (i.e. alert has been + emmited from a preprocessor and not the rules engine) + use this value for alert.assessment.impact.severity field + instead of using NULL value (or not creating the assessment + object at all if it's to be filled with NULLs). + + Default: not specified. + +impact_type={other,admin,dos,file,recon,user} + Optional parameter. + + When we cannot determine impact type (i.e. alert has been + emmited from a preprocessor and not the rules engine) + use this value for alert.assessment.impact.type field + instead of using NULL value (or not creating the assessment + object at all if it's to be filled with NULLs). + + Default: not specified. + + +Running +------- + +As with any other Prelude sensor you must first perform sensor +registration with the Manager you wish to use. This is accomplished in +the following steps: + +* Run sensor-adduser on machine running Snort, passing to it the address +of the host Manager is running on. If you wish to run Snort and Prelude +Manager on the same host, enter 127.0.0.1 as in the example below: + +# sensor-adduser --sensorname snort --uid 0 --manager-addr 127.0.0.1 + + +Now please start "manager-adduser" on the Manager host where you wish +to add the new user. + +Please remember that you should call "sensor-adduser" for each configured +Manager entry. + +Press enter when done. + +* As requested, run manager-adduser on the Manager host: + +# manager-adduser + + +Generated one-shot password is "T&8Ae_p[". + +This password will be requested by "sensor-adduser" in order to connect. +Please remove the first and last quote from this password before using it. + +waiting for install request from Prelude sensors... + +* Pass the password given by manager-adduser (in the case for this +example, T&8Ae_p[) to sensor-adduser program. + +Please use the one-shot password provided by the "manager-adduser" +program. + +Enter registration one shot password : Please confirm one shot password : +connecting to Manager host (127.0.0.1:5553)... Succeeded. + +Username to use to authenticate : + +* You are now prompted for the username used by the Snort sensor for +authenticating to Prelude Manager. You can pick any name of your choice, +in this example "snort1". + +Username to use to authenticate : snort1 +Please enter a password for this user : + +* Pick up the password for the sensor. This is _NOT_ the same password, +as you've used above. You will not have to remeber this password, it +will be snored in sensor's confiuration file. + +Please enter a password for this user : +Please re-enter the password (comfirm) : +Register user "snort1" ? [y/n] : y +Plaintext account creation succeed with Prelude Manager. +Using already allocated ident for snort1@your.machine.org: 1063061594273486129. + +* The sensor has been registered. Now make sure that prelude-manager +is running on the Manager host and simply start snort. You should see +messages like: + +# snort -i eth0 + +[...] + +- Connecting to Unix prelude Manager server. +- Plaintext authentication succeed with Prelude Manager. + +[...] + +* Success! This means that Snort has established communication with +Prelude Manager. From now on alerts generated by Snort will be logged +along with alerts generated by other Prelude sensors. + + +Known problems +-------------- + +* If you see the following message at startup: + +./snort: error while loading shared libraries: libprelude.so.0: cannot +open shared object file: No such file or directory + +one of the solutions is to add path to libprelude.so.0 to LD_LIBRARY_PATH +environment variable, i.e.: + +# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib + +and re-start Snort. See ldconfig(8) for more details. + +To do +----- + +- add support for more alert fields and types of alerts + +- possibly improve performance + + +Modified files +-------------- + +The following files are modified or added compared to the official Snort +2.x.x distribution: + +acinclude.m4 +autogen.sh +configure.in +doc/README.Prelude +etc/Makefile.am +etc/prelude-classification.config +etc/snort.conf +src/Makefile.am +src/output-plugins/Makefile.am +src/output-plugins/spo_alert_prelude/* +src/plugbase.c + +Assuming that unmodified Snort distribution resides in ../snort-2.x.x +the patch can be generated using the following command executed in +the main directory of the modified Snort tree: + +for i in `ls \ + acinclude.m4 \ + autogen.sh \ + configure.in \ + doc/README.Prelude \ + etc/Makefile.am \ + etc/prelude-classification.config \ + etc/snort.conf \ + src/Makefile.am \ + src/output-plugins/Makefile.am \ + src/output-plugins/spo_alert_prelude/Makefile.am \ + src/output-plugins/spo_alert_prelude/*.[ch] \ + src/plugbase.c \ + | grep -v Makefile.in | grep -v Makefile$` ; do \ + diff --new-file --unified ../snort-2.x.x/$i $i ; \ +done + +Revision history +---------------- + +2004-09-15 Version 0.3.6, for Snort 2.2.0 + + Fixed a bug in argument parsing, which prevented specifying + more than 3 arguments to the output plugin. Thanks to everyone + who reported this. + + Fixed a typing error in impact.c. + +2004-05-12 Version 0.3.5, for Snort 2.1.2 + + Included a (modified) patch from David Maciejak + to fill + {source,target}.service.protocol in lower case. + + Added impact_type and impact_severity options to set default + values for assessment.impact.{type,severity} if we cannot + get them from the rules engine instead of using a NULL value. + (Theoretically we _should_ use NULL, and this is the default, + but some people prefer to have a default value). + This was inspired by a patch from david.bizeul@netcourrier.com. + +2004-04-15 Version 0.3.4, for Snort 2.1.2 + + Documented "sensor_name" parameter. + Added "config_file" parameter; now we use + prelude_analyzer_fill_infos() to fill alert.analyzer. + The feature has been requested by Mardel Shumake + . + + Treat apo_alert_prelude initialization errors as critical + and exit immediately. + + Use log(LOG_ERR, ...) to report errors the Prelude way. + +2004-03-08 Version 0.3.3, for Snort 2.1.1 + + Port to Snort 2.1.1. Added a missing call to fill + alert.detect_time. Thanks to David Maciejak + for the patch. + + Fixed 'unused variable' warnings. + +2004-02-13 Version 0.3.2, for Snort 2.1.0 + + Fixed a bug in plugin argument parsing code. + Thanks to Kosaku Nagasaka for the + patch. + +2004-02-12 Version 0.3.1, for Snort 2.1.0 + + Added code to fill alert.{source,target}.service.protocol field. + Thanks to Kosaku Nagasaka for the + patch. + +2004-02-09 Version 0.3.0, for Snort 2.1.0 + + Code cleanup and modularization. + + Rewrite of packet dumping code (large parts imported from + Prelude). The format should be now the same as used by + Prelude NIDS. Supported protocols: Ethernet, IP, TCP, UDP. + More may be added in the future as needed. + + Reworked memory management, eliminated use of strlen(). + Code should now work faster. + + Reworked and sped up classification handling. Snort's own + classification is now also added (thanks to David Maciejak + for the reference code). + + Added a feature to change the name of the sensor from the + config file (thanks to David Maciejak + for the reference code). + +2004-02-09 Version 0.2.6, for Snort 2.0.2,2.0.6 + Fixed a crash when triggered rule had no "classtype" parameter + (possible DoS). + Fixed output of TCP parameters (seq, ack wsize) on + little-endian machines. + +2003-10-05 Version 0.2.5, for Snort 2.0.0 - 2.0.2 + Thanks to Serhii Hlodin + for Snort 2.0.2 support. + +2003-05-09 Version 0.2.4, for Snort 2.0 and 2.0.1 + Fixed handling of alert.impact.* + +2003-05-27 Version 0.2.3, for Snort 2.0 + Added support for Detection Time object. + +2003-04-20 Version 0.2.2, for Snort 2.0 + Fixed memory leaks. + Added support for packet dumps, IP and TCP options. + Modified #ifdefs, so Snort compiles cleanly + with Prelude support disabled. + +2003-04-16 Version 0.2.1, for Snort 2.0 + Fixed a bug in assigning values of 'completion' + parameter. + +2003-03-22 Second release, version 0.2, for Snort 1.9.1 + +2002-08-09 First release, version 0.1, for Snort 1.8.6 and 1.8.7 + + +- Krzysztof Zaraska --- etc/Makefile.am 2003-12-18 17:48:49.000000000 +0100 +++ etc/Makefile.am 2004-09-15 22:28:55.000000000 +0200 @@ -2,4 +2,4 @@ AUTOMAKE_OPTIONS=foreign no-dependencies EXTRA_DIST = sid sid-msg.map snort.conf classification.config gen-msg.map \ -reference.config generators unicode.map threshold.conf +reference.config generators prelude-classification.config --- etc/prelude-classification.config 1970-01-01 01:00:00.000000000 +0100 +++ etc/prelude-classification.config 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,74 @@ +# $Id: classification.config,v 1.4 2002/04/13 10:59:25 yoann Exp $ +# The following includes information for prioritizing rules +# +# Each classification includes a shortname, a description, and a default +# priority for that classification. +# +# This allows alerts to be cassified and prioritized. You can specify +# what priority each classification has. Any rule can override the default +# priority for that rule. +# +# Here are a few example rules: +# +# alert TCP any any -> any 80 (msg: "EXPLOIT ntpdx overflow"; +# dsize: > 128; classtype:attempted-admin; priority:10; +# +# alert TCP any any -> any 25 (msg:"SMTP expn root"; flags:A+; \ +# content:"expn root"; nocase; classtype:attempted-recon;) +# +# The first rule will set its type to "attempted-admin" and override +# the default priority for that type to 10. +# +# The second rule set its type to "attempted-recon" and set its +# priority to the default for that type. +# + +# +# config classification:shortname,short description,priority +# + +# Prelude Change: In order to be IDMEF compliant, priority should be +# defined using the high, medium and low keyword. +# +# Completion using failed or succeeded keyword. +# +# Type using the other, admin, dos, file, recon, or user keyword. +# +# config classification:shortname, short desc, priority, type, completion + +config classification: not-suspicious,Not Suspicious Traffic, low, other, , +config classification: unknown,Unknown Traffic, low, other, , +config classification: bad-unknown,Potentially Bad Traffic, medium, other, , +config classification: attempted-recon,Attempted Information Leak, medium, recon, , +config classification: successful-recon-limited,Information Leak, medium, recon, succeeded +config classification: successful-recon-largescale,Large Scale Information Leak, medium, recon, succeeded +config classification: attempted-dos,Attempted Denial of Service, medium, dos, , +config classification: successful-dos,Denial of Service, medium, dos, succeeded +config classification: attempted-user,Attempted User Privilege Gain, high, user, , +config classification: unsuccessful-user,Unsuccessful User Privilege Gain, high, user, failed +config classification: successful-user,Successful User Privilege Gain, high, user, succeeded +config classification: attempted-admin,Attempted Administrator Privilege Gain, high, admin, , +config classification: successful-admin,Successful Administrator Privilege Gain, high, admin, succeeded + + +# NEW CLASSIFICATIONS +config classification: rpc-portmap-decode,Decode of an RPC Query, medium, other, , +config classification: shellcode-detect,Executable code was detected, high, other, , +config classification: string-detect,A suspicious string was detected, low, other, , +config classification: suspicious-filename-detect,A suspicious filename was detected, medium, file, , +config classification: suspicious-login,An attempted login using a suspicious username was detected, medium, other, , +config classification: system-call-detect,A system call was detected, medium, other, , +config classification: tcp-connection,A TCP connection was detected, low, other, , +config classification: trojan-activity,A Network Trojan was detected, high, other, , +config classification: unusual-client-port-connection,A client was using an unusual port, medium, other, , +config classification: network-scan,Detection of a Network Scan, low, recon, , +config classification: denial-of-service,Detection of a Denial of Service Attack, medium, dos, , +config classification: non-standard-protocol,Detection of a non-standard protocol or event, medium, other, , +config classification: protocol-command-decode,Generic Protocol Command Decode, low, other, , +config classification: web-application-activity,access to a potentually vulnerable web application, medium, other, , +config classification: web-application-attack,Web Application Attack, high, other, , +config classification: misc-activity,Misc activity, low, other, , +config classification: misc-attack,Misc Attack, medium, other, , +config classification: icmp-event,Generic ICMP event, low, other, , +config classification: kickass-porn,SCORE! Get the lotion!, high, other, , +config classification: policy-violation,Potential Corporate Privacy Violation, high, other, , --- etc/snort.conf 2004-08-05 20:55:37.000000000 +0200 +++ etc/snort.conf 2004-09-15 22:28:55.000000000 +0200 @@ -446,6 +446,28 @@ # # output log_tcpdump: tcpdump.log +# alert_prelude: Reporting to Prelude Manager +# +# parameters (all optional, see README.Prelude for details): +# async - enables asynchronous (multithreaded) reporting mode +# sensor_name - name of the sensor (default snort) +# classification_file - specifies location of classification.config +# file from Prelude distribution +# (default prelude-classification.config) +# config_file - specifies of the sensor configuration file for libprelude +# (default none) +# impact_type - default value for IDMEF impact type if cannot be determined +# (default none) +# impact_severity - default value for IDMEF impact severity if cannot be +# determined (default none) +# +# output alert_prelude: async, sensor_name=snort1 +# output alert_prelude: async, config_file=sensor.conf +# output alert_prelude: async, impact_severity=medium +# output alert_prelude: async, impact_severity=medium, impact_type=recon +# output alert_prelude: async, impact_type=recon +output alert_prelude: async + # database: log to a variety of databases # --------------------------------------- # See the README.database file for more information about configuring --- src/Makefile.am 2004-06-16 20:49:24.000000000 +0200 +++ src/Makefile.am 2004-09-15 22:28:55.000000000 +0200 @@ -47,6 +47,7 @@ event_queue.c event_queue.h snort_LDADD = output-plugins/libspo.a \ +output-plugins/spo_alert_prelude/libspo_alert_prelude.a \ detection-plugins/libspd.a \ preprocessors/libspp.a \ preprocessors/flow/portscan/libportscan.a \ --- src/output-plugins/Makefile.am 2003-10-20 17:03:33.000000000 +0200 +++ src/output-plugins/Makefile.am 2004-09-15 22:28:55.000000000 +0200 @@ -1,6 +1,8 @@ ## $Id AUTOMAKE_OPTIONS=foreign no-dependencies +SUBDIRS=spo_alert_prelude + noinst_LIBRARIES = libspo.a libspo_a_SOURCES = spo_alert_fast.c spo_alert_fast.h \ @@ -11,4 +13,6 @@ spo_log_tcpdump.h spo_unified.c spo_unified.h spo_log_ascii.c spo_log_ascii.h \ spo_alert_sf_socket.h spo_alert_sf_socket.c +libspo_a_LIBADD = spo_alert_prelude/libspo_alert_prelude.a + INCLUDES = @INCLUDES@ --- src/output-plugins/spo_alert_prelude/Makefile.am 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/Makefile.am 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,9 @@ +## $Id +AUTOMAKE_OPTIONS=foreign no-dependencies + +noinst_LIBRARIES = libspo_alert_prelude.a + +libspo_alert_prelude_a_SOURCES = spo_alert_prelude.c prelude-hash.c \ + dump.c fill.c impact.c analyzer.c + +INCLUDES = @INCLUDES@ --- src/output-plugins/spo_alert_prelude/allstuff.h 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/allstuff.h 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,76 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* All rights reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +#ifndef _ALLSTUFF_H +#define _ALLSTUFF_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "decode.h" +#include "event.h" +#include "rules.h" +#include "plugbase.h" +#include "debug.h" +#include "parser.h" +#include "mstring.h" +#include "util.h" + +#include "snort.h" + +/* One macro in snort.h can ruin your day when applied to idmef-tree.h */ +#ifdef interface +#undef interface +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG +#define PRELUDE_DEBUG +#endif + +#include "patchver.h" +#include "analyzer.h" +#include "impact.h" +#include "fill.h" +#include "dump.h" + +#endif /* _ALLSTUFF_H */ + --- src/output-plugins/spo_alert_prelude/analyzer.c 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/analyzer.c 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,75 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* All rights reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef WITH_PRELUDE + +#include "allstuff.h" + +#define HOSTNAME_LEN 256 + +struct utsname *analyzer_uname = NULL; +char *analyzer_hostname; + +int analyzer_init(void) { + int ret; + + analyzer_uname = calloc(1, sizeof(struct utsname)); + if ( ! analyzer_uname ) { + printf("out of memory\n"); + return -1; + } + + analyzer_hostname = calloc(1, HOSTNAME_LEN); + if ( ! analyzer_hostname ) { + printf("out of memory\n"); + return -1; + } + + ret = uname(analyzer_uname); + if (ret < 0) { + log(LOG_ERR, "uname() failed\n"); + free(analyzer_uname); + analyzer_uname = NULL; + return -1; + } + +#ifdef PRELUDE_DEBUG + if ( analyzer_uname ) + printf("%s %s rel. %s ver. %s on %s\n", analyzer_uname->nodename, + analyzer_uname->sysname, analyzer_uname->release, + analyzer_uname->version, analyzer_uname->machine); +#endif + + ret = gethostname(analyzer_hostname, HOSTNAME_LEN); + if ( ret < 0 ) { + log(LOG_ERR, "gethostname() failed\n"); + return -1; + } + + return 0; +} + +#endif /* _ANALYZER_H */ + --- src/output-plugins/spo_alert_prelude/analyzer.h 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/analyzer.h 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,30 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* All rights reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +#ifndef _ANALYZER_H +#define _ANALYZER_H + +extern struct utsname *analyzer_uname; +extern char *analyzer_hostname; + +int analyzer_init(void); + +#endif /* _ANALYZER_H */ --- src/output-plugins/spo_alert_prelude/dump.c 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/dump.c 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,702 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* Portions copyright (C) 2002 Yoann Vandoorselaere +* All rights reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef WITH_PRELUDE + +#include "allstuff.h" + +/* from prelude-manager/plugins/decodes/nethdr.h -- adapted */ +#ifndef TH_ECNECHO +#define TH_ECNECHO 0x40 +#endif + +#ifndef TH_CWR +#define TH_CWR 0x80 +#endif + +#define ETHERTYPE_IP 0x0800 +#define ETHERTYPE_ARP 0x0806 /* Address resolution */ +#define ETHERTYPE_REVARP 0x8035 /* Reverse ARP */ + +#include "ethertype.h" + +#define OPTBUF_LEN 256 + +/* + * Yoann Vandoorselaere's code stolen from prelude-manager/plugin-utils.c + * and modifed a little. + */ + +/* + * prelude_string_to_hex: + * @input: Pointer on the input buffer. + * @len: Length of the data contained in the input buffer. + * + * This function will return a formatted hexadecimal dump. + * + * Returns: Pointer on an allocated buffer containing the hexadecimal dump, + * or NULL if an error occured. + */ +static char *prelude_string_to_hex(const unsigned char *input, uint32_t len, uint32_t *outlen) +{ + int i, totlen; + unsigned char c; + unsigned int round; + char *line, *ret, *text; + const int text_offset = 51; + const char hextbl[] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + round = (len / 16) + 1; + totlen = (round * (text_offset + 16 + 1)) + 1; + + ret = line = malloc(totlen); + if ( ! line ) + return NULL; + + text = line + text_offset; + + for ( i = 0; i < len; i++ ) { + + c = *input++; + *line++ = hextbl[c >> 4]; + *line++ = hextbl[c & 0xf]; + *line++ = ' '; + *text++ = isprint(c) ? c : '.'; + + if ( (i + 1) % 16 == 0 ) { + *text++ = '\n'; + line = text; + + if ( i + 1 < len ) + text = text + text_offset; + } + + else if ( (i + 1) % 4 == 0 ) + *line++ = ' '; + } + + if ( i % 16 != 0 ) { + /* + * fill remaining unwritten data with white space. + */ + while ( i++ % 16 != 0 ) { + + *text++ = ' '; + *line++ = ' '; + *line++ = ' '; + *line++ = ' '; + + if ( ! (i % 16 == 0) && i % 4 == 0 ) + *line++ = ' '; + } + + *text++ = '\n'; + } + + *text++ = '\0'; + + *outlen = (uint32_t) (text - ret); + + return ret; +} + +/* + * printopt(), ip_optval(), tcp_optval(), switch_ETHERNET_TYPE(): + * ripped from Yoann Vandoorselaere's code in + * prelude-manager/plugins/decodes/optparse.c and + * prelude-manager/plugins/decodes/packet-decode.c + * and adapted + */ + +static int printopt(char *buf, int bsize, const char *comment, ...) +{ + int ret; + va_list va; + + va_start(va, comment); + ret = vsnprintf(buf, bsize, comment, va); + va_end(va); + + if ( ret >= bsize || ret < 0 ) + return -1; + + return ret; +} + + +static int ip_optval(char *buf, int bsize, Options *o) +{ + int optlen = o->len + 2; + + switch (o->code) { + + case IPOPT_TS: + return printopt(buf, bsize, "ts"); + + case IPOPT_SECURITY: + return printopt(buf, bsize, "security{%d}", optlen); + + case IPOPT_RR: + return printopt(buf, bsize, "rr"); + + case IPOPT_SSRR: + return printopt(buf, bsize, "ssrr"); + + case IPOPT_LSRR: + return printopt(buf, bsize, "lsrr"); + + case IPOPT_RTRALT: + if (o->len != 2) + return printopt(buf, bsize, "ra{%d}", optlen); + else if ((o->data) && (o->data[0] || o->data[1])) + return printopt(buf, bsize, "ra{%d.%d}", o->data[0], o->data[1]); + default: + return printopt(buf, bsize, "ipopt-%d{%d}", o->code, optlen); + } + + return 0; /* not reached */ +} + +/* + * Dump tcp options and their value. + */ +static int tcp_optval(char *buf, int bsize, Options *o) +{ + switch (o->code) { + + case TCPOPT_MAXSEG: + return printopt(buf, bsize, "mss %u", extract_uint16(o->data)); + + case TCPOPT_WSCALE: + return printopt(buf, bsize, "wscale %u", o->data[0]); + + case TCPOPT_SACKOK: + return printopt(buf, bsize, "sackOK"); + + case TCPOPT_SACK: + if ( o->len % 8 != 0 ) + return printopt(buf, bsize, "malformed sack"); + else { +/* + uint32_t s, e; + int i; + + printopt("sack %d", datalen / 8 ); + for ( i = 0; i < datalen; i += 8 ) { + s = extract_uint32(optbuf + i); + e = extract_uint32(optbuf + i + 4); + } +*/ + } + + case TCPOPT_ECHO: + return printopt(buf, bsize, "echo %u", extract_uint32(o->data)); + + case TCPOPT_ECHOREPLY: + return printopt(buf, bsize, "echoreply %u", extract_uint32(o->data)); + + case TCPOPT_TIMESTAMP: + return printopt(buf, bsize, "timestamp %u %u", + extract_uint32(o->data), extract_uint32(o->data + 4)); + + case TCPOPT_CC: + return printopt(buf, bsize, "cc %u", extract_uint32(o->data)); + + case TCPOPT_CCNEW: + return printopt(buf, bsize, "ccnew %u", extract_uint32(o->data)); + + case TCPOPT_CCECHO: + return printopt(buf, bsize, "ccecho %u", extract_uint32(o->data)); + + case TCPOPT_NOP: + return printopt(buf, bsize, "nop"); + + case TCPOPT_EOL: + return printopt(buf, bsize, "eol"); + + default: + return printopt(buf, bsize, "opt-%d:", o->code); + + } + + return 0; /* not reached */ +} + + + +static const char *switch_ethertype(uint16_t type) +{ + switch (type) { + + case ETHERTYPE_IP: + return "ip"; + + case ETHERTYPE_NS: + return "ns"; + + case ETHERTYPE_SPRITE: + return "sprite"; + + case ETHERTYPE_TRAIL: + return "trail"; + + case ETHERTYPE_MOPDL: + return "mopdl"; + + case ETHERTYPE_MOPRC: + return "moprc"; + + case ETHERTYPE_DN: + return "dn"; + + case ETHERTYPE_LAT: + return "lat"; + + case ETHERTYPE_SCA: + return "sca"; + + case ETHERTYPE_ARP: + return "arp"; + + case ETHERTYPE_REVARP: + return "revarp"; + + case ETHERTYPE_LANBRIDGE: + return "lanbridge"; + + case ETHERTYPE_DECDNS: + return "decdns"; + + case ETHERTYPE_DECDTS: + return "decdts"; + + case ETHERTYPE_VEXP: + return "vexp"; + + case ETHERTYPE_VPROD: + return "vprod"; + + case ETHERTYPE_ATALK: + return "atalk"; + + case ETHERTYPE_AARP: + return "aarp"; + + case ETHERTYPE_8021Q: + return "8021q"; + + case ETHERTYPE_IPX: + return "ipx"; + + case ETHERTYPE_IPV6: + return "ipv6"; + + case ETHERTYPE_PPPOED: + return "pppoed"; + + case ETHERTYPE_PPPOES: + return "pppoes"; + + case ETHERTYPE_LOOPBACK: + return "loopback"; + + default: + return "unknown"; + } + + return NULL; +} + + + +static int dump_eth_header(idmef_alert_t *alert, Packet *p) +{ + idmef_additional_data_t *ad; + char *databuf; + int ret; + int pos; + + ad = idmef_alert_additional_data_new(alert); + idmef_string_set_constant(&ad->meaning, "Ethernet header"); + + databuf = malloc(OPTBUF_LEN); + if ( ! databuf ) + return -1; + + pos = 0; + ret = snprintf(databuf, OPTBUF_LEN, "%x:%x:%x:%x:%x:%x", + p->eh->ether_src[0], p->eh->ether_src[1], p->eh->ether_src[2], + p->eh->ether_src[3], p->eh->ether_src[4], p->eh->ether_src[5]); + if ( ret < 0 || ret > OPTBUF_LEN-1 ) + goto error; + pos += ret; + + ret = snprintf(databuf+pos, OPTBUF_LEN-pos, " -> %x:%x:%x:%x:%x:%x", + p->eh->ether_dst[0], p->eh->ether_dst[1], p->eh->ether_dst[2], + p->eh->ether_dst[3], p->eh->ether_dst[4], p->eh->ether_dst[5]); + if ( ret < 0 || ret > OPTBUF_LEN-pos-1 ) + goto error; + pos += ret; + + ret = snprintf(databuf+pos, OPTBUF_LEN-pos, " [ether_type=%s (%d)]", + switch_ethertype(ntohs(p->eh->ether_type)), ntohs(p->eh->ether_type)); + if ( ret < 0 || ret > OPTBUF_LEN-pos-1 ) + goto error; + pos += ret; + + pos++; /* Include the terminating \0 */ + + idmef_additional_data_set_data(ad, string, databuf, pos); + + return 0; + +error: + free(databuf); + return -1; +} + +static int dump_ip_header(idmef_alert_t *alert, Packet *p) +{ + idmef_additional_data_t *ad; + char *databuf; + int ret; + char *ip; + int pos; + + ad = idmef_alert_additional_data_new(alert); + idmef_string_set_constant(&ad->meaning, "Ip options"); + + databuf = malloc(OPTBUF_LEN); + if ( ! databuf ) + return -1; + + pos = 0; + ip = inet_ntoa(p->iph->ip_src); + ret = snprintf(databuf, OPTBUF_LEN, "%s", ip); + if ( ret < 0 || ret > OPTBUF_LEN-1 ) + goto error; + pos += ret; + + ip = inet_ntoa(p->iph->ip_dst); + ret = snprintf(databuf+pos, OPTBUF_LEN-pos, " -> %s ", ip); + if ( ret < 0 || ret > OPTBUF_LEN-pos-1 ) + goto error; + pos += ret; + + ret = snprintf(databuf+pos, OPTBUF_LEN-pos, + "[hl=%d,version=%d,tos=%d,len=%d,id=%d,ttl=%d,prot=%d]", + IP_HLEN(p->iph) << 2, + IP_VER(p->iph), + p->iph->ip_tos, + ntohs(p->iph->ip_len), + ntohs(p->iph->ip_id), + p->iph->ip_ttl, + p->iph->ip_proto); + if ( ret < 0 || ret > OPTBUF_LEN-pos-1 ) + goto error; + pos += ret; + + pos++; /* Include the terminating \0 */ + + idmef_additional_data_set_data(ad, string, databuf, pos); + + return 0; + +error: + free(databuf); + return -1; +} + +static int dump_ip_options(idmef_alert_t *alert, Packet *p) +{ + int data_len; + char *databuf = NULL; + int opt, opt_cnt; + idmef_additional_data_t *ad; + int ret; + + if ( p->ip_option_count == 0 ) + return 0; /* nothing to do */ + + opt_cnt = p->ip_lastopt_bad ? p->ip_option_count-1 : p->ip_option_count; + if ( opt_cnt == 0 ) + return 0; /* nothing to do */ + + ad = idmef_alert_additional_data_new(alert); + idmef_string_set_constant(&ad->meaning, "Ip options"); + + databuf = malloc(OPTBUF_LEN); + if ( ! databuf ) + goto error; + + data_len = 0; + for ( opt = 0; opt < opt_cnt; opt++ ) { + if ( data_len > OPTBUF_LEN-2 ) + goto error; + + if ( opt > 0 ) { + databuf[data_len++] = ','; + databuf[data_len] = '\0'; + } + ret = ip_optval(databuf+data_len, OPTBUF_LEN - data_len, &p->ip_options[opt]); + if ( ret < 0 ) + goto error; + + data_len += ret; + + } + + data_len++; /* Include terminating \0 */ + + idmef_additional_data_set_data(ad, string, databuf, data_len); + + return 0; /* success */ + +error: + if ( databuf ) + free(databuf); + + return -1; +} + +static int dump_udp_header(idmef_alert_t *alert, Packet *p) +{ + idmef_additional_data_t *ad; + char *databuf; + int len; + + ad = idmef_alert_additional_data_new(alert); + idmef_string_set_constant(&ad->meaning, "Udp header"); + + databuf = malloc(OPTBUF_LEN); + if ( ! databuf ) + return -1; + + len = snprintf(databuf, OPTBUF_LEN, "%d -> %d [len=%d]", + ntohs(p->udph->uh_sport), + ntohs(p->udph->uh_dport), + ntohs(p->udph->uh_len)); + if ( len < 0 || len > OPTBUF_LEN-1 ) + goto error; + + len++; /* Include the terminating \0 */ + + idmef_additional_data_set_data(ad, string, databuf, len); + + return 0; + +error: + free(databuf); + return -1; +} + +static int dump_tcp_header(idmef_alert_t *alert, Packet *p) +{ + char *databuf; + idmef_additional_data_t *ad; + int data_len; + int ret; + + databuf = malloc(OPTBUF_LEN); + if ( ! databuf ) + return -1; + + ad = idmef_alert_additional_data_new(alert); + idmef_string_set_constant(&ad->meaning, "Tcp header"); + + data_len = snprintf(databuf, OPTBUF_LEN-1, + "%d -> %d [%s%s%s%s%s%s%s%s%s%sseq=%u", + p->sp, p->dp, + p->tcph->th_flags ? "flags=" : "", + p->tcph->th_flags & TH_FIN ? "FIN " : "", + p->tcph->th_flags & TH_SYN ? "SYN " : "", + p->tcph->th_flags & TH_RST ? "RST " : "", + p->tcph->th_flags & TH_PUSH ? "PUSH " : "", + p->tcph->th_flags & TH_ACK ? "ACK " : "", + p->tcph->th_flags & TH_URG ? "URG " : "", + p->tcph->th_flags & TH_ECNECHO ? "ECNECHO " : "", + p->tcph->th_flags & TH_CWR ? "CWR " : "", + p->tcph->th_flags ? "," : "", + ntohl(p->tcph->th_seq)); + if ( data_len < 0 || data_len > OPTBUF_LEN-1 ) + goto error; + + if ( p->tcph->th_flags & TH_ACK ) { + ret = snprintf(databuf+data_len, OPTBUF_LEN-data_len-1, ",ack=%u", + ntohl(p->tcph->th_ack)); + if ( ret < 0 || ret > OPTBUF_LEN-data_len-1 ) + goto error; + + data_len += ret; + } + + if ( p->tcph->th_flags & TH_URG ) { + ret = snprintf(databuf+data_len, OPTBUF_LEN-data_len-1, ",urg=%u", + ntohs(p->tcph->th_urp)); + if ( ret < 0 || ret > OPTBUF_LEN-data_len-1 ) + goto error; + + data_len += ret; + } + + ret = snprintf(databuf+data_len, OPTBUF_LEN-data_len-1, ",win=%u]", + ntohs(p->tcph->th_win)); + if ( ret < 0 || ret > OPTBUF_LEN-data_len-1 ) + goto error; + + data_len += ret; + + data_len++; /* Include the trailing \0 */ + + idmef_additional_data_set_data(ad, string, databuf, data_len); + + return 0; + +error: + free(databuf); + return -1; +} + + +static int dump_tcp_options(idmef_alert_t *alert, Packet *p) +{ + int data_len; + char *data_out = NULL; + int opt, opt_cnt; + idmef_additional_data_t *ad; + int ret; + + if ( p->tcp_option_count == 0 ) + return 0; /* nothing to do */ + + opt_cnt = p->tcp_lastopt_bad ? p->tcp_option_count-1 : p->tcp_option_count; + if ( opt_cnt == 0 ) + return 0; /* nothing to do */ + + ad = idmef_alert_additional_data_new(alert); + idmef_string_set_constant(&ad->meaning, "Tcp options"); + + data_out = malloc(OPTBUF_LEN); + if ( ! data_out ) + goto error; + + data_len = 0; + for ( opt = 0; opt < opt_cnt; opt++ ) { + if ( data_len > OPTBUF_LEN-2 ) + goto error; + + if ( opt > 0 ) { + data_out[data_len++] = ','; + data_out[data_len] = '\0'; + } + ret = tcp_optval(data_out+data_len, OPTBUF_LEN - data_len, &p->tcp_options[opt]); + if ( ret < 0 ) + goto error; + + data_len += ret; + + } + + data_len++; /* Include terminating \0 */ + + idmef_additional_data_set_data(ad, string, data_out, data_len); + + return 0; /* success */ + +error: + free(data_out); + return -1; +} + + + +static int dump_payload(idmef_alert_t *alert, Packet *p) { + idmef_additional_data_t *ad; + char *payload_dump; + int payload_len; + + if ( p->dsize == 0 ) + return 0; + + payload_dump = prelude_string_to_hex(p->data, p->dsize, &payload_len); + if ( ! payload_dump ) + return -1; + + ad = idmef_alert_additional_data_new(alert); + idmef_additional_data_set_data(ad, string, payload_dump, payload_len); + idmef_string_set_constant(&ad->meaning, "Payload Hexadecimal Dump"); + + return 0; +} + + +int dump_packet(idmef_alert_t *alert, Packet *p) { + if ( ! p ) + return 0; + + /* Ethernet header */ + if ( p->eh ) { + if ( dump_eth_header(alert, p) < 0 ) + return -1; + } + + /* IP header */ + if ( p->iph ) { + if ( dump_ip_header(alert, p) < 0 ) + return -1; + + /* IP options */ + if ( dump_ip_options(alert, p) < 0 ) + return -1; + } + + /* UDP header */ + if ( p->udph ) { + if ( dump_udp_header(alert, p) < 0 ) + return -1; + } + + /* TCP header */ + if ( p->tcph ) { + if ( dump_tcp_header(alert, p) < 0 ) + return -1; + + /* TCP options */ + if ( dump_tcp_options(alert, p) < 0 ) + return -1; + } + + /* Payload */ + if ( dump_payload(alert, p) < 0 ) + return -1; + + return 0; /* success */ +} + +#endif /* WITH_PRELUDE */ + --- src/output-plugins/spo_alert_prelude/dump.h 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/dump.h 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,28 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* All rights reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +#ifndef _DUMP_H +#define _DUMP_H + +int dump_packet(idmef_alert_t *alert, Packet *p); + +#endif /* _DUMP_H */ + --- src/output-plugins/spo_alert_prelude/ethertype.h 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/ethertype.h 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1993, 1994, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvsroot/prelude/prelude-manager/plugins/decodes/prelude-nids/ethertype.h,v 1.1 2002/01/28 18:18:01 yoann Exp $ (LBL) + */ + +/* Types missing from some systems */ + +#ifndef ETHERTYPE_NS +#define ETHERTYPE_NS 0x0600 +#endif +#ifndef ETHERTYPE_SPRITE +#define ETHERTYPE_SPRITE 0x0500 +#endif +#ifndef ETHERTYPE_TRAIL +#define ETHERTYPE_TRAIL 0x1000 +#endif +#ifndef ETHERTYPE_MOPDL +#define ETHERTYPE_MOPDL 0x6001 +#endif +#ifndef ETHERTYPE_MOPRC +#define ETHERTYPE_MOPRC 0x6002 +#endif +#ifndef ETHERTYPE_DN +#define ETHERTYPE_DN 0x6003 +#endif +#ifndef ETHERTYPE_LAT +#define ETHERTYPE_LAT 0x6004 +#endif +#ifndef ETHERTYPE_SCA +#define ETHERTYPE_SCA 0x6007 +#endif +#ifndef ETHERTYPE_REVARP +#define ETHERTYPE_REVARP 0x8035 +#endif +#ifndef ETHERTYPE_LANBRIDGE +#define ETHERTYPE_LANBRIDGE 0x8038 +#endif +#ifndef ETHERTYPE_DECDNS +#define ETHERTYPE_DECDNS 0x803c +#endif +#ifndef ETHERTYPE_DECDTS +#define ETHERTYPE_DECDTS 0x803e +#endif +#ifndef ETHERTYPE_VEXP +#define ETHERTYPE_VEXP 0x805b +#endif +#ifndef ETHERTYPE_VPROD +#define ETHERTYPE_VPROD 0x805c +#endif +#ifndef ETHERTYPE_ATALK +#define ETHERTYPE_ATALK 0x809b +#endif +#ifndef ETHERTYPE_AARP +#define ETHERTYPE_AARP 0x80f3 +#endif +#ifndef ETHERTYPE_8021Q +#define ETHERTYPE_8021Q 0x8100 +#endif +#ifndef ETHERTYPE_IPX +#define ETHERTYPE_IPX 0x8137 +#endif +#ifndef ETHERTYPE_IPV6 +#define ETHERTYPE_IPV6 0x86dd +#endif +#ifndef ETHERTYPE_PPPOED +#define ETHERTYPE_PPPOED 0x8863 +#endif +#ifndef ETHERTYPE_PPPOES +#define ETHERTYPE_PPPOES 0x8864 +#endif +#ifndef ETHERTYPE_LOOPBACK +#define ETHERTYPE_LOOPBACK 0x9000 +#endif --- src/output-plugins/spo_alert_prelude/fill.c 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/fill.c 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,342 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* All rights reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef WITH_PRELUDE + +#include "allstuff.h" + +#define CLASS_BUF_LEN 256 +#define MAX_CLASSIFICATIONS 16 + +extern PV pv; + +int fill_analyzer(idmef_analyzer_t *anal) { + int ret; + + /* analyzer information */ + idmef_string_set_constant(&anal->model, "Snort"); + idmef_string_set_constant(&anal->class, "Network Intrusion Detection System"); + idmef_string_set_constant(&anal->version, PATCHED_VERSION); + + ret = prelude_analyzer_fill_infos(anal); + if ( ret < 0 ) + return ret; + + /* analyzer address */ + if ( ! anal->node ) + idmef_analyzer_node_new(anal); + + if ( ! idmef_string(&anal->node->name) ) + idmef_string_set(&anal->node->name, analyzer_hostname); + + return 0; +} + +static inline char fast_tolower(char c) +{ + if ( c >= 'A' && c <= 'Z' ) + return c - 'A' + 'a'; + else + return c; +} + +static inline void strtolower (char *word) +{ + char *p = word; + + while (*p) { + *p = fast_tolower(*p); + p++; + } +} + + +int fill_source(idmef_alert_t *alert, Packet *p) { + idmef_source_t *source; + idmef_address_t *saddr; + char *src_ip; + idmef_service_t *sservice; + char *iface; + char *ip_proto; + + if ( ! p ) + return 0; + + /* source information */ + source = idmef_alert_source_new(alert); + if ( ! source) + return -1; + + if ( pv.interface ) { + iface = strdup(pv.interface); + if ( ! iface ) + return -1; + + idmef_string_set(&source->interface, iface); + } + + idmef_source_node_new(source); + saddr = idmef_node_address_new(source->node); + if ( ! saddr) + return -1; + + saddr->category = ipv4_addr; + src_ip = strdup(inet_ntoa(p->iph->ip_src)); + if ( ! src_ip ) + return -1; + + idmef_string_set(&saddr->address, src_ip); + + /* port information */ + if ((p->iph->ip_proto == IPPROTO_TCP) || + (p->iph->ip_proto == IPPROTO_UDP)) { + ip_proto = strdup(protocol_names[p->iph->ip_proto]); + if ( ! ip_proto ) { + free(src_ip); + return -1; + } + strtolower(ip_proto); + + sservice = idmef_source_service_new(source); + if ( ! sservice) { + free(src_ip); + free(ip_proto); + return -1; + } + sservice->port = p->sp; + idmef_string_set(&sservice->protocol, ip_proto); + } + + return 0; +} + +int fill_target(idmef_alert_t *alert, Packet *p) { + idmef_target_t *target; + idmef_address_t *taddr; + char *dst_ip; + idmef_service_t *tservice; + char *iface; + char *ip_proto; + + if ( ! p ) + return 0; + + /* target information */ + target = idmef_alert_target_new(alert); + if ( ! target) + return -1; + + if ( pv.interface ) { + iface = strdup(pv.interface); + if ( ! iface ) + return -1; + + idmef_string_set(&target->interface, iface); + } + + idmef_target_node_new(target); + taddr = idmef_node_address_new(target->node); + if ( ! taddr) + return -1; + + taddr->category = ipv4_addr; + dst_ip = strdup(inet_ntoa(p->iph->ip_dst)); + if ( ! dst_ip ) + return -1; /* out of memory?! */ + + idmef_string_set(&taddr->address, dst_ip); + + /* port information */ + if ((p->iph->ip_proto == IPPROTO_TCP) || + (p->iph->ip_proto == IPPROTO_UDP)) { + ip_proto = strdup(protocol_names[p->iph->ip_proto]); + if ( ! ip_proto ) { + free(dst_ip); + return -1; + } + strtolower(ip_proto); + + tservice = idmef_target_service_new(target); + if ( ! tservice) { + free(dst_ip); + free(ip_proto); + return -1; + } + tservice->port = p->dp; + idmef_string_set(&tservice->protocol, ip_proto); + } + + return 0; +} + +int fill_classification(idmef_alert_t *alert, char *msg, OptTreeNode *otn_tmp) +{ + char *class_name; + idmef_classification_t *classification; + ReferenceNode *rn; + char *class_buf; + char *class_url[MAX_CLASSIFICATIONS]; + int class_no = 0; + + int i, ret; + + /* + * since otn_tmp is not always available, write value of msg there + */ + if ( ! otn_tmp ) { + class_name = strdup(msg); + if ( ! class_name ) + return -1; + + classification = idmef_alert_classification_new(alert); + idmef_string_set(&classification->name, class_name); + + return 0; /* early success */ + } + + for ( i = 0; i < MAX_CLASSIFICATIONS; i++ ) + class_url[i] = NULL; + + /* snort's own classification */ + classification = idmef_alert_classification_new(alert); + if ( ! classification ) + goto error; + + classification->origin = vendor_specific; + + class_name = strdup(msg); + if ( ! class_name ) + goto error; + + idmef_string_set(&classification->name, class_name); + + class_buf = malloc(CLASS_BUF_LEN); + if ( ! class_buf ) + goto error; + + ret = snprintf(class_buf, CLASS_BUF_LEN-1, + "http://www.snort.org/snort-db/sid.html?sid=%d", otn_tmp->sigInfo.id);; + if ( ret < 0 || ret > CLASS_BUF_LEN-1 ) + goto error; + + class_url[class_no++] = class_buf; + + idmef_string_set(&classification->url, class_buf); + + /* classification */ + rn = otn_tmp->sigInfo.refs; + while ( rn ) { + classification = idmef_alert_classification_new(alert); + if ( ! classification ) + goto error; + + if (strncasecmp(rn->system->name, "bugtraq", 7) == 0) + classification->origin = bugtraqid; + else if (strncasecmp(rn->system->name, "cve", 3) == 0) + classification->origin = cve; + else + classification->origin = vendor_specific; + + idmef_string_set(&classification->name, otn_tmp->sigInfo.message); + + if ( ( rn->system->url ) && ( class_no < MAX_CLASSIFICATIONS ) ) { + class_buf = malloc(CLASS_BUF_LEN); + if ( ! class_buf ) + goto error; + + ret = snprintf(class_buf, CLASS_BUF_LEN-1, + "%s%s", rn->system->url, rn->id); + if ( ret < 0 || ret > CLASS_BUF_LEN-1 ) + goto error; + + class_url[class_no++] = class_buf; + + idmef_string_set(&classification->url, class_buf); + } + + rn = rn->next; + } + + return 0; + +error: + + for ( i = 0; i < MAX_CLASSIFICATIONS; i++ ) + if ( class_url[i] ) + free(class_url[i]); + + return -1; + +} + +int fill_assessment(idmef_alert_t *alert, OptTreeNode *otn_tmp) { + impact_t *impact; + + if ( ! otn_tmp || ! otn_tmp->sigInfo.classType ) { + if ( impact_default_severity || impact_default_type ) { + idmef_alert_assessment_new(alert); + idmef_assessment_impact_new(alert->assessment); + if ( impact_default_severity ) + alert->assessment->impact->severity = *impact_default_severity; + + if ( impact_default_type ) + alert->assessment->impact->type = *impact_default_type; + } + + return 0; + } + + impact = impact_get(otn_tmp->sigInfo.classType->type); + if ( impact ) { + idmef_alert_assessment_new(alert); + idmef_assessment_impact_new(alert->assessment); + + alert->assessment->impact->severity = impact->severity; + alert->assessment->impact->completion = impact->completion; + alert->assessment->impact->type = impact->type; + idmef_string_set(&alert->assessment->impact->description, impact->description); + + } else { + log(LOG_ERR, "no classification mapping for type %s\n", + otn_tmp->sigInfo.classType->type); + } + + return 0; +} + +int fill_detect_time(idmef_alert_t *alert, Packet *p) { + if ( p && (p->pkth) ) { + idmef_alert_detect_time_new(alert); + alert->detect_time->sec = p->pkth->ts.tv_sec; + alert->detect_time->usec = p->pkth->ts.tv_usec; + } + + return 0; +} + +#endif /* WITH_PRELUDE */ + + --- src/output-plugins/spo_alert_prelude/fill.h 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/fill.h 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,34 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* All rights reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + + +#ifndef _FILL_H +#define _FILL_H + +int fill_analyzer(idmef_analyzer_t *anal); +int fill_source(idmef_alert_t *alert, Packet *p); +int fill_target(idmef_alert_t *alert, Packet *p); +int fill_classification(idmef_alert_t *alert, char *msg, OptTreeNode *otn_tmp); +int fill_assessment(idmef_alert_t *alert, OptTreeNode *otn_tmp); +int fill_detect_time(idmef_alert_t *alert, Packet *p); + +#endif /* _FILL_H */ + --- src/output-plugins/spo_alert_prelude/impact.c 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/impact.c 2004-09-15 23:37:56.000000000 +0200 @@ -0,0 +1,273 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* All rights reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef WITH_PRELUDE + +#include "allstuff.h" + +#include "prelude-hash.h" + +/* Public defaults */ + +idmef_impact_severity_t *impact_default_severity = NULL; +idmef_impact_type_t *impact_default_type = NULL; + +idmef_impact_severity_t default_severity = -1; +idmef_impact_type_t default_type = -1; + +/* Internals */ + +static prelude_hash_t *impact_hash; + +/* +From idmef-tree.h: + +typedef enum { + impact_low = 1, + impact_medium = 2, + impact_high = 3 +} idmef_impact_severity_t; +*/ + +static idmef_impact_severity_t find_severity(const char *name) +{ + if ( strcasecmp(name, "low") == 0 ) + return 1; + + if ( strcasecmp(name, "medium") == 0 ) + return 2; + + if ( strcasecmp(name, "high") == 0 ) + return 3; + + return -1; +} + +void impact_set_default_severity(const char *name) +{ + if ( name ) + default_severity = find_severity(name); + + if ( default_severity != -1 ) + impact_default_severity = &default_severity; +} + +/* +From idmef-tree.h: + +typedef enum { + other = 0, + admin = 1, + dos = 2, + file = 3, + recon = 4, + user = 5 +} idmef_impact_type_t; +*/ + +static idmef_impact_type_t find_type(const char *name) +{ + if ( strcasecmp(name, "other") == 0 ) + return 0; + + if ( strcasecmp(name, "admin") == 0 ) + return 1; + + if ( strcasecmp(name, "dos") == 0 ) + return 2; + + if ( strcasecmp(name, "file") == 0 ) + return 3; + + if ( strcasecmp(name, "recon") == 0 ) + return 4; + + if ( strcasecmp(name, "user") == 0 ) + return 5; + + return -1; /* not found */ +} + +void impact_set_default_type(const char *name) +{ + if ( name ) + default_type = find_type(name); + + if ( default_type != -1 ) + impact_default_type = &default_type; +} + +static void remove_spaces(char *s) +{ + int pos, start, end, len; + + if (s == NULL) return ; + + pos = 0; + start = 0; + end = 0; + len = strlen(s); + while (s[pos++] == ' ') start++; + + pos = len-1; + while ((pos>=0) && (s[pos--] == ' ')) end++; + strncpy(s, s+start, len-end); + s[len-end]='\0'; +} + +static void key_destroy(void *key) { + free(key); +} + +static void impact_destroy(void *val) { + impact_t *p = val; + + if (p->description) + free(p->description); + + free(p); +} + +static int parser_fail(const char *file, int line, const char *msg, const char *value) { + log(LOG_ERR, "%s:%d: %s%s%s\n", file, line, msg, + value ? ": " : "", value ? value : "(not set)"); + + return -1; +} + +int impact_load_classification(const char *filename) +{ + FILE *f; + char buf[1024]; + int line; + + char shortname[128], desc[128], severity[128], type[128], completion[128]; + char *key; + + impact_t *p; + + int ret; + + f = fopen(filename, "r"); + if (!f) { + log(LOG_ERR, "could not open %s\n", filename); + return -1; + } + + impact_hash = prelude_hash_new(NULL, NULL, + key_destroy, impact_destroy); + + line = 0; + do { + line++; + if (!fgets(buf, 1024, f)) + return feof(f) ? 0 : parser_fail(filename, line, "read error", NULL); + + buf[1023] = '\0'; + + if ((buf[0] == '#') || + (buf[0] == '\n') || + ((buf[0] == '\r') && (buf[1] == '\n'))) + continue; + + ret = sscanf(buf, "%*[^:]: %128[^,],%128[^,],%128[^,],%128[^,],%128[^,]", + shortname, desc, severity, type, completion); + if (ret != 5) + return parser_fail(filename, line, "data format error", NULL); + + remove_spaces(shortname); + remove_spaces(desc); + remove_spaces(severity); + remove_spaces(type); + remove_spaces(completion); + + p = calloc(1, sizeof(impact_t)); + if ( ! p ) { + return -1; + } + + p->description = strdup(desc); + if ( ! p->description ) + return -1; + + /* determine impact */ + if (strncasecmp(severity, "high", 4) == 0) + p->severity = impact_high; + else if (strncasecmp(severity, "medium", 5) == 0) + p->severity = impact_medium; + else if (strncasecmp(severity, "low", 3) == 0) + p->severity = impact_low; + else + return parser_fail(filename, line, "unknown severity", severity); + + /* determine type */ + if (strncasecmp(type, "other", 5) == 0) + p->type = other; + else if (strncasecmp(type, "admin", 5) == 0) + p->type = admin; + else if (strncasecmp(type, "dos", 3) == 0) + p->type = dos; + else if (strncasecmp(type, "file", 4) == 0) + p->type = file; + else if (strncasecmp(type, "recon", 5) == 0) + p->type = recon; + else if (strncasecmp(type, "user", 4) == 0) + p->type = user; + else + return parser_fail(filename, line, "unknown type", type); + + /* determine completion */ + if (strncasecmp(completion, "succeeded", 9) == 0) + p->completion = succeeded; + else if (strncasecmp(completion, "failed", 5) == 0) + p->completion = failed; + else if ( ! *completion ) { + /* not set */ + } else + return parser_fail(filename, line, "unknown completion", completion); + + key = strdup(shortname); + if ( ! key ) + return -1; + + prelude_hash_set(impact_hash, key, p); + + } while(1); + + fclose(f); + + return 0; +} + +impact_t *impact_get(const char *key) { + return prelude_hash_get(impact_hash, key); +} + +void impact_cleanup(void) { + prelude_hash_destroy(impact_hash); +} + +#endif /* WITH_PRELUDE */ + --- src/output-plugins/spo_alert_prelude/impact.h 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/impact.h 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,43 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* All rights reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + + +#ifndef _IMPACT_H +#define _IMPACT_H + +typedef struct _impact_t { + idmef_impact_severity_t severity; + idmef_impact_completion_t completion; + idmef_impact_type_t type; + char *description; +} impact_t; + +extern idmef_impact_severity_t *impact_default_severity; +extern idmef_impact_type_t *impact_default_type; + +void impact_set_default_severity(const char *name); +void impact_set_default_type(const char *name); + +int impact_load_classification(const char *filename); +impact_t *impact_get(const char *key); +void impact_cleanup(void); + +#endif /* _IMPACT_H */ --- src/output-plugins/spo_alert_prelude/patchver.h 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/patchver.h 2004-09-15 22:58:07.000000000 +0200 @@ -0,0 +1,30 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* All rights reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +#ifndef _PATCHVER_H +#define _PATCHVER_H + +/* Patch version */ +#define PATCHVER "0.3.6" + +#define PATCHED_VERSION VERSION "-prelude-" PATCHVER + +#endif /* _PATCHVER_H */ --- src/output-plugins/spo_alert_prelude/prelude-hash.c 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/prelude-hash.c 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,253 @@ +/***** +* +* Copyright (C) 2003 Nicolas Delon +* All Rights Reserved +* +* This file is part of the Prelude program. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +/* + * KZ: this file is taken from libprelude/src/prelude-hash.c from + * libprelude to be 0.9. Adapted for snort. Also declared internal + * functions as inlined. + */ + +#ifdef WITH_PRELUDE + +#include +#include + +#include +#include + +#include "prelude-hash.h" + +#define HASH_DEFAULT_SIZE 16 + +typedef struct hash_elem { + struct list_head list; + void *key; + void *value; +} hash_elem_t; + +struct prelude_hash { + int lists_size; + int elems_num; + struct list_head *lists; + unsigned int (*hash_func)(const void *); + int (*key_cmp_func)(const void *, const void *); + void (*key_destroy_func)(void *); + void (*value_destroy_func)(void *); +}; + + + +/* + * This function's code was taken from glib + */ +static inline unsigned int default_hash_func(const void *key) +{ + const char *ptr = key; + unsigned int hv = *ptr; + + if ( hv ) + for ( ptr += 1; *ptr; ptr++ ) + hv = (hv << 5) - hv + *ptr; + + return hv; + +} + + + +static inline int default_key_cmp_func(const void *key1, const void *key2) +{ + return strcmp((const char *) key1, (const char *) key2); +} + + + +static inline unsigned int hash_value_calc(prelude_hash_t *hash, const void *key) +{ + return (hash->hash_func(key) % hash->lists_size); +} + + + +static inline hash_elem_t *hash_elem_get(prelude_hash_t *hash, const void *key) +{ + struct list_head *list; + struct list_head *ptr; + hash_elem_t *hash_elem; + + list = hash->lists + hash_value_calc(hash, key); + + list_for_each(ptr, list) { + hash_elem = list_entry(ptr, hash_elem_t, list); + if ( hash->key_cmp_func(key, hash_elem->key) == 0 ) + return hash_elem; + } + + return NULL; +} + + + +static inline void hash_elem_key_destroy(prelude_hash_t *hash, hash_elem_t *hash_elem) +{ + if ( hash->key_destroy_func ) + hash->key_destroy_func(hash_elem->key); +} + + + +static inline void hash_elem_value_destroy(prelude_hash_t *hash, hash_elem_t *hash_elem) +{ + if ( hash->value_destroy_func ) + hash->value_destroy_func(hash_elem->value); +} + + + +prelude_hash_t *prelude_hash_new(unsigned int (*hash_func)(const void *), + int (*key_cmp_func)(const void *, const void *), + void (*key_destroy_func)(void *), + void (*value_destroy_func)(void *)) +{ + prelude_hash_t *hash; + int cnt; + + hash = calloc(1, sizeof (*hash)); + if ( ! hash ) { + log(LOG_ERR, "out of memory\n"); + return NULL; + } + + hash->lists_size = HASH_DEFAULT_SIZE; + + hash->elems_num = 0; + + hash->lists = calloc(hash->lists_size, sizeof (*hash->lists)); + if ( ! hash->lists ) { + log(LOG_ERR, "out of memory\n"); + free(hash); + return NULL; + } + + hash->hash_func = hash_func ? hash_func : default_hash_func; + hash->key_cmp_func = key_cmp_func ? key_cmp_func : default_key_cmp_func; + hash->key_destroy_func = key_destroy_func; + hash->value_destroy_func = value_destroy_func; + + for ( cnt = 0; cnt < hash->lists_size; cnt++ ) { + INIT_LIST_HEAD(hash->lists + cnt); + } + + return hash; +} + + + +void prelude_hash_destroy(prelude_hash_t *hash) +{ + struct list_head *list; + struct list_head *ptr; + struct list_head *tmp; + hash_elem_t *hash_elem; + int cnt; + + for ( cnt = 0; cnt < hash->lists_size; cnt++ ) { + list = hash->lists + cnt; + + list_for_each_safe(ptr, tmp, list) { + hash_elem = list_entry(ptr, hash_elem_t, list); + hash_elem_key_destroy(hash, hash_elem); + hash_elem_value_destroy(hash, hash_elem); + list_del(&hash_elem->list); + free(hash_elem); + } + } + + free(hash->lists); + free(hash); +} + + + +int prelude_hash_set(prelude_hash_t *hash, void *key, void *value) +{ + hash_elem_t *hash_elem; + struct list_head *list; + + hash_elem = hash_elem_get(hash, key); + + if ( hash_elem ) { + hash_elem_key_destroy(hash, hash_elem); + hash_elem_value_destroy(hash, hash_elem); + hash_elem->key = key; + hash_elem->value = value; + return 0; + } + + hash_elem = calloc(1, sizeof (*hash_elem)); + if ( ! hash_elem ) { + log(LOG_ERR, "out of memory"); + return -1; + } + + hash_elem->key = key; + hash_elem->value = value; + + list = hash->lists + hash_value_calc(hash, key); + list_add(&hash_elem->list, list); + + hash->elems_num++; + + return 1; +} + + + +void *prelude_hash_get(prelude_hash_t *hash, const void *key) +{ + hash_elem_t *hash_elem; + + return (hash_elem = hash_elem_get(hash, key)) ? hash_elem->value : NULL; +} + + + +int prelude_hash_elem_destroy(prelude_hash_t *hash, const void *key) +{ + hash_elem_t *hash_elem; + + hash_elem = hash_elem_get(hash, key); + + if ( ! hash_elem ) + return -1; + + hash_elem_key_destroy(hash, hash_elem); + hash_elem_value_destroy(hash, hash_elem); + list_del(&hash_elem->list); + free(hash_elem); + + return 0; +} + +#endif /* WITH_PRELUDE */ + --- src/output-plugins/spo_alert_prelude/prelude-hash.h 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/prelude-hash.h 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,42 @@ +/***** +* +* Copyright (C) 2003 Nicolas Delon +* All Rights Reserved +* +* This file is part of the Prelude program. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +#ifndef _LIBPRELUDE_HASH_H +#define _LIBPRELUDE_HASH_H + +typedef struct prelude_hash prelude_hash_t; + +prelude_hash_t *prelude_hash_new(unsigned int (*hash_func)(const void *), + int (*key_cmp_func)(const void *, const void *), + void (*key_destroy_func)(void *), + void (*value_destroy_func)(void *)); + +void prelude_hash_destroy(prelude_hash_t *hash); + +int prelude_hash_set(prelude_hash_t *hash, void *key, void *value); + +void *prelude_hash_get(prelude_hash_t *hash, const void *key); + +int prelude_hash_elem_destroy(prelude_hash_t *hash, const void *key); + +#endif /* _LIBPRELUDE_HASH_H */ --- src/output-plugins/spo_alert_prelude/spo_alert_prelude.c 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/spo_alert_prelude.c 2004-09-15 22:35:27.000000000 +0200 @@ -0,0 +1,330 @@ +/***** +* +* Copyright (C) 2002-2004 Krzysztof Zaraska +* Portions copyright (C) 2002 Yoann Vandoorselaere +* All rights reserved +* +* This code has been partially inspired by other Snort 1.8.x output plugins. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + + +/* + * The purpose of this module is to enable snort reporting to Prelude IDS Manager. + * + * Version: 0.3.6 + * + * Status: EXPERIMENTAL + * + * Configuration parameters: + * - async enables asynchronous (multithreaded) reporting + * - classification_file must point to classification.config from Prelude + * distribution (_not_ original snort classification.config) + * + * Preprocessor directives: + * - defining WITH_PRELUDE enables the code + * - defining PRELUDE_DEBUG enables debug messages + * - defining DEBUG automatically defines PRELUDE_DEBUG + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef WITH_PRELUDE + +#include "allstuff.h" + +typedef struct _PreludeData { + int async_mode; + char *classification_file; + char *sensor_name; + char *config_file; +} PreludeData; + +void AlertPreludeInit(u_char *); +PreludeData *parse_args(char *); +void AlertPrelude(Packet *, char *, void *, Event *); + +void AlertPreludeCleanExitFunc(int, void *); +void AlertPreludeRestartFunc(int, void *); + +/* private functions */ +void send_heartbeat(void *data); + +extern OptTreeNode *otn_tmp; + +idmef_heartbeat_t heartbeat; +prelude_msgbuf_t *msgbuf, *hb_msgbuf; + +#define MAX_CLASSIFICATIONS 16 +#define OPTBUF_LEN 1024 + +/* config defaults */ +#define DEFAULT_ASYNC_MODE 0 +#define DEFAULT_SENSOR_NAME "snort" +#define DEFAULT_CONFIG_FILE NULL +#define DEFAULT_CLASSIFICATION_FILE "prelude-classification.config" + + +void AlertPreludeSetup() { +#ifdef PRELUDE_DEBUG + printf("SetupAlertPrelude()\n"); +#endif + + RegisterOutputPlugin("alert_prelude", NT_OUTPUT_ALERT, AlertPreludeInit); +} + +void AlertPreludeInit(u_char *args) { + PreludeData *data; + int ret; + char *argv[2]; + + argv[0] = progname; + argv[1] = NULL; + + data = parse_args(args); + if ( ! data ) + return ; + +#ifdef PRELUDE_DEBUG + printf("Setting up libprelude\n"); +#endif + + /* we pass only argv[0] to avoid libprelude parsing the command line */ + ret = prelude_sensor_init(data->sensor_name, data->config_file, 1, argv); + if (ret < 0) { + log(LOG_ERR, "couldn't initialize the Prelude library\n"); + exit(1); + } + + if ( data->async_mode ) { + ret = prelude_async_init(); + + if (ret < 0) { + log(LOG_ERR, "couldn't initialize Prelude async subsystem\n"); + exit(1); + } + } + + if ( analyzer_init() < 0 ) + exit(1); + + /* Prepare analyzer information for use */ + fill_analyzer(&heartbeat.analyzer); + + INIT_LIST_HEAD(&heartbeat.additional_data_list); + + +#ifdef PRELUDE_DEBUG + printf("loading classification file\n"); +#endif + ret = impact_load_classification(data->classification_file); + if (ret < 0) { + log(LOG_ERR, "error loading file %s\n", data->classification_file); + exit(1); + } + + if ( data->async_mode ) { + msgbuf = prelude_msgbuf_new(1); /* 0 = sync mode, 1 = async mode */ + hb_msgbuf = prelude_msgbuf_new(1); + } else { + msgbuf = prelude_msgbuf_new(0); /* 0 = sync mode, 1 = async mode */ + hb_msgbuf = prelude_msgbuf_new(0); + } + + if ( ! msgbuf ) { + log(LOG_ERR, "can't allocate message buffer\n"); + exit(1); + } + + if ( ! hb_msgbuf ) { + log(LOG_ERR, "can't allocate heartbeat message buffer\n"); + exit(1); + } + +#ifdef PRELUDE_DEBUG + printf("Registering callbacks\n"); +#endif + prelude_heartbeat_register_cb(&send_heartbeat, NULL); + + AddFuncToOutputList(AlertPrelude, NT_OUTPUT_ALERT, data); + AddFuncToCleanExitList(AlertPreludeCleanExitFunc, data); + AddFuncToRestartList(AlertPreludeRestartFunc, data); +} + +char *argument_value(char *arg, char *argname) +{ + char *val; + + if (strncmp(arg, argname, strlen(argname)) == 0) { + val = strchr(arg, '='); + if (val) + return val+1; + else + return arg+strlen(arg); /* Return pointer to trailing \0 */ + } else + return NULL; +} + +PreludeData *parse_args(char *args) { + PreludeData *data; + char **args_table; + char *val; + int i,tokens; + + data = calloc(1, sizeof(PreludeData)); + if (!data) { + log(LOG_ERR, "out of memory\n"); + return NULL; + } + + args_table = mSplit(args, ", ", 6, &tokens, '\\'); + + /* defaults */ + data->async_mode = DEFAULT_ASYNC_MODE; + data->sensor_name = DEFAULT_SENSOR_NAME; + data->config_file = DEFAULT_CONFIG_FILE; + data->classification_file = DEFAULT_CLASSIFICATION_FILE; + + for (i=0;iasync_mode = 1; + + /* sensor name */ + val = argument_value(args_table[i], "sensor_name"); + if ((val) && (*val != '\0')) + data->sensor_name = val; + + /* config file */ + val = argument_value(args_table[i], "config_file"); + if ((val) && (*val != '\0')) + data->config_file = val; + + /* classification file */ + val = argument_value(args_table[i], "classification_file"); + if ((val) && (*val != '\0')) + data->classification_file = val; + + val = argument_value(args_table[i], "impact_severity"); + if ((val) && (*val != '\0')) + impact_set_default_severity(val); + + val = argument_value(args_table[i], "impact_type"); + if ((val) && (*val != '\0')) + impact_set_default_type(val); + + } + +#ifdef PRELUDE_DEBUG + if (data->async_mode) + printf("asynchronous reporting enabled\n"); + + printf("classification file: %s\n", data->classification_file); + + printf("sensor name:%s\n", data->sensor_name); + + printf("config file:%s\n", data->config_file ? data_config_file : "(none)"); +#endif + + return data; +} + +void send_heartbeat(void *data) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + heartbeat.create_time.sec = tv.tv_sec; + heartbeat.create_time.usec = tv.tv_usec; + + /* + * we could use additional data to send stats. + */ + prelude_msgbuf_set_header(hb_msgbuf, PRELUDE_MSG_IDMEF, 0); + idmef_send_heartbeat(hb_msgbuf, &heartbeat); + prelude_msgbuf_mark_end(hb_msgbuf); +} + +void AlertPrelude(Packet *p, char *msg, void *arg, Event *event) { + /* configuration */ + /* PreludeData *data = (PreludeData *) arg; */ + + /* alert structure and buffer */ + idmef_message_t *idmef; + idmef_alert_t *alert; + + /* create IDMEF alert message */ + idmef = idmef_message_new(); + if ( !idmef ) + goto error ; + + idmef_alert_new(idmef); + alert = idmef->message.alert; + + fill_analyzer(&alert->analyzer); + + if ( fill_assessment(alert, otn_tmp) < 0 ) + goto error; + + if ( fill_classification(alert, msg, otn_tmp) < 0 ) + goto error; + + if (p) { + /* detection time*/ + if ( fill_detect_time(alert, p) < 0 ) + goto error; + /* source */ + if ( fill_source(alert, p) < 0 ) + goto error; + + /* target */ + if ( fill_target(alert, p) < 0 ) + goto error; + + /* Additional data */ + if ( dump_packet(alert, p) < 0 ) + goto error; + } + + /* send the message */ + idmef_msg_send(msgbuf, idmef, PRELUDE_MSG_PRIORITY_HIGH); + + +error: + idmef_message_free(idmef); + + return ; + +} + +void AlertPreludeCleanExitFunc(int signal, void *arg) { + impact_cleanup(); + + prelude_msgbuf_close(msgbuf); + prelude_msgbuf_close(hb_msgbuf); +} + +void AlertPreludeRestartFunc(int signal, void *arg) { + /* do nothing */ +} + +#endif /* WITH_PRELUDE */ --- src/output-plugins/spo_alert_prelude/spo_alert_prelude.h 1970-01-01 01:00:00.000000000 +0100 +++ src/output-plugins/spo_alert_prelude/spo_alert_prelude.h 2004-09-15 22:28:55.000000000 +0200 @@ -0,0 +1,29 @@ +/***** +* +* Copyright (C) 2002,2003 Krzysztof Zaraska +* All Rights Reserved +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. If not, write to +* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****/ + +#include "snort.h" + +#ifndef __SPO_ALERT_PRELUDE_H__ +#define __SPO_ALERT_PRELUDE_H__ + +void AlertPreludeSetup(); + +#endif /* __SPO_ALERT_PRELUDE_H__ */ --- src/plugbase.c 2004-06-16 20:49:24.000000000 +0200 +++ src/plugbase.c 2004-09-15 22:28:55.000000000 +0200 @@ -109,6 +109,9 @@ #ifdef LINUX #include "output-plugins/spo_alert_sf_socket.h" #endif +#ifdef WITH_PRELUDE +#include "output-plugins/spo_alert_prelude/spo_alert_prelude.h" +#endif PluginSignalFuncNode *PluginCleanExitList; PluginSignalFuncNode *PluginRestartList; @@ -571,6 +574,9 @@ /* This uses linux only capabilities */ AlertSFSocket_Setup(); #endif +#ifdef WITH_PRELUDE + AlertPreludeSetup(); +#endif } int ActivateOutputPlugin(char *plugin_name, char *plugin_options)