diff --git a/packages/TODO.zcu b/packages/TODO.zcu deleted file mode 100644 index e12f02a4d0b5f06c57b09427bd66c4a4a81f7487..0000000000000000000000000000000000000000 --- a/packages/TODO.zcu +++ /dev/null @@ -1,6 +0,0 @@ -* sjednotit warden-client.conf a warden-server.conf -* ipv6 -* zrusit vsude licence a nahradit jedinym radkem s odkazem -* generovani konfiguracnich souboru z template z balicku a ne primo ze shell skriptu -* verze klienta a serveru jsou mimo sync coz je osklive, proc mam pouzivat c1.1.1 a s0.1.1 ? to nedava smysl ... - diff --git a/packages/build-client.sh b/packages/build-client.sh index dfe9a89374faaf8273413019f283401b92c1cd16..d516d7078a6bec2ddea9bbd174c47a44f1914828 100755 --- a/packages/build-client.sh +++ b/packages/build-client.sh @@ -3,35 +3,10 @@ # build-client.sh # # Copyright (C) 2011-2012 Cesnet z.s.p.o -# Author(s): Tomas PLESNIK <plesnik@ics.muni.cz> -# Jan SOUKAL <soukal@ics.muni.cz> # -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name of the Cesnet z.s.p.o 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 any express or implied -# warranties, including, but not limited to, the implied warranties of -# merchantability and fitness for a particular purpose are disclaimed. -# In no event shall the Cesnet z.s.p.o or contributors be liable for -# any direct, indirect, incidental, special, exemplary, or consequential -# damages (including, but not limited to, procurement of substitute -# goods or services; loss of use, data, or profits; or business -# interruption) however caused and on any theory of liability, whether -# in contract, strict liability, or tort (including negligence or -# otherwise) arising in any way out of the use of this software, even -# if advised of the possibility of such damage. - -VERSION="1.1" +# Use of this source is governed by a BSD-style license, see LICENSE file. + +VERSION="1.2" #------------------------------------------------------------------------------- # FUNCTIONS @@ -52,17 +27,17 @@ err() #------------------------------------------------------------------------------- # edit when you build new package -version="2.0.0-beta" +version="2.1-beta" package_name="warden-client" -package="$package_name-$version" -doc="$package/$package_name/doc" -etc="$package/$package_name/etc" -lib="$package/$package_name/lib" -var="$package/$package_name/var" -tar="$package.tar.gz" -sig="$tar.sig" -err="/tmp/$package-err" +package="${package_name}-${version}" +doc="${package}/${package_name}/doc" +etc="${package}/${package_name}/etc" +lib="${package}/${package_name}/lib" +var="${package}/${package_name}/var" +tar="${package}.tar.gz" +sig="${tar}.sig" +err="/tmp/${package}-err" # make directory structure echo "Building $package_name package version $version ..." @@ -70,34 +45,34 @@ echo echo -n "Building 'base' directory ... " mkdir -p $package 2> $err || err -cp -R ../src/$package_name/sh/* $package 2> $err || err -cp ../src/$package_name/doc/CHANGELOG $package 2> $err || err -cp ../src/$package_name/doc/INSTALL $package 2> $err || err -cp ../src/$package_name/doc/LICENSE $package 2> $err || err -cp ../src/$package_name/doc/README $package 2> $err || err -cp ../src/$package_name/doc/README.cesnet $package 2> $err || err +cp -R ../src/${package_name}/sh/* $package 2> $err || err +cp ../src/${package_name}/doc/CHANGELOG $package 2> $err || err +cp ../src/${package_name}/doc/INSTALL $package 2> $err || err +cp ../src/${package_name}/doc/LICENSE $package 2> $err || err +cp ../src/${package_name}/doc/README $package 2> $err || err +cp ../src/${package_name}/doc/README.cesnet $package 2> $err || err echo "OK" -echo -n "Building '$doc' directory ... " +echo -n "Building '${doc}' directory ... " mkdir -p $doc 2> $err || err -cp -R ../src/$package_name/doc/* $doc 2> $err || err +cp -R ../src/${package_name}/doc/* $doc 2> $err || err echo "OK" -echo -n "Building '$etc' directory ... " +echo -n "Building '${etc}' directory ... " mkdir -p $etc 2> $err || err -cp ../src/$package_name/etc/package_version $etc 2> $err || err +cp ../src/${package_name}/etc/package_version $etc 2> $err || err echo "OK" -echo -n "Building '$lib' directory ... " +echo -n "Building '${lib}' directory ... " mkdir -p $lib 2> $err || err -cp -R ../src/$package_name/lib/* $lib 2> $err || err +cp -R ../src/${package_name}/lib/*.pm $lib 2> $err || err echo "OK" -echo -n "Building '$var' directory ... " +echo -n "Building '${var}' directory ... " mkdir -p $var 2> $err || err echo "OK" diff --git a/packages/build-server.sh b/packages/build-server.sh index 8e4fdedba61c75c13da94165fff69dbfc8e51b0c..802b9689b9018034b9fa4acb86bfccc7c438b551 100755 --- a/packages/build-server.sh +++ b/packages/build-server.sh @@ -3,35 +3,10 @@ # build-server.sh # # Copyright (C) 2011-2012 Cesnet z.s.p.o -# Author(s): Tomas PLESNIK <plesnik@ics.muni.cz> -# Jan SOUKAL <soukal@ics.muni.cz> # -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name of the Cesnet z.s.p.o 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 any express or implied -# warranties, including, but not limited to, the implied warranties of -# merchantability and fitness for a particular purpose are disclaimed. -# In no event shall the Cesnet z.s.p.o or contributors be liable for -# any direct, indirect, incidental, special, exemplary, or consequential -# damages (including, but not limited to, procurement of substitute -# goods or services; loss of use, data, or profits; or business -# interruption) however caused and on any theory of liability, whether -# in contract, strict liability, or tort (including negligence or -# otherwise) arising in any way out of the use of this software, even -# if advised of the possibility of such damage. - -VERSION="1.0" +# Use of this source is governed by a BSD-style license, see LICENSE file. + +VERSION="2.1" err() { @@ -49,18 +24,17 @@ err() #------------------------------------------------------------------------------- # edit when you build new package -version="0.1.1" +version="2.1-beta6" package_name="warden-server" -package="$package_name-$version" -bin="$package/$package_name/bin" -doc="$package/$package_name/doc" -etc="$package/$package_name/etc" -lib="$package/$package_name/lib" -var="$package/$package_name/var" -tar="$package.tar.gz" -sig="$tar.sig" -err="/tmp/$package-err" +package="${package_name}-${version}" +bin="${package}/${package_name}/bin" +doc="${package}/${package_name}/doc" +etc="${package}/${package_name}/etc" +lib="${package}/${package_name}/lib" +tar="${package}.tar.gz" +sig="${tar}.sig" +err="/tmp/${package}-err" # make directory structure echo "Building $package_name package version $version ..." @@ -68,40 +42,38 @@ echo echo -n "Building 'base' directory ... " mkdir -p $package 2> $err || err -cp ../src/$package_name/sh/install.sh $package 2> $err || err -cp ../src/$package_name/sh/uninstall.sh $package 2> $err || err -cp ../src/$package_name/doc/CHANGELOG $package 2> $err || err -cp ../src/$package_name/doc/INSTALL $package 2> $err || err -cp ../src/$package_name/doc/LICENSE $package 2> $err || err -cp ../src/$package_name/doc/README $package 2> $err || err -cp ../src/$package_name/doc/README.warden-apache $package 2> $err || err +cp ../src/${package_name}/sh/install.sh $package 2> $err || err +cp ../src/${package_name}/sh/update.sh $package 2> $err || err +cp ../src/${package_name}/sh/uninstall.sh $package 2> $err || err +cp ../src/${package_name}/doc/AUTHORS $package 2> $err || err +cp ../src/${package_name}/doc/CHANGELOG $package 2> $err || err +cp ../src/${package_name}/doc/INSTALL $package 2> $err || err +cp ../src/${package_name}/doc/LICENSE $package 2> $err || err +cp ../src/${package_name}/doc/README $package 2> $err || err +cp ../src/${package_name}/doc/UNINSTALL $package 2> $err || err +cp ../src/${package_name}/doc/UPDATE $package 2> $err || err echo "OK" -echo -n "Building '$bin' directory ... " +echo -n "Building '${bin}' directory ... " mkdir -p $bin 2> $err || err -cp -R ../src/$package_name/bin/* $bin 2> $err || err -cp -R ../src/$package_name/sh/create_tables.sh $bin 2> $err || err +cp -R ../src/${package_name}/bin/* $bin 2> $err || err echo "OK" -echo -n "Building '$doc' directory ... " +echo -n "Building '${doc}' directory ... " mkdir -p $doc 2> $err || err -cp -R ../src/$package_name/doc/* $doc 2> $err || err +cp -R ../src/${package_name}/doc/* $doc 2> $err || err echo "OK" -echo -n "Building '$etc' directory ... " +echo -n "Building '${etc}' directory ... " mkdir -p $etc 2> $err || err -cp ../src/$package_name/etc/package_version $etc 2> $err || err -cp ../src/$package_name/etc/warden-apache.conf $etc 2> $err || err +cp ../src/${package_name}/etc/package_version $etc 2> $err || err echo "OK" -echo -n "Building '$lib' directory ... " +echo -n "Building '${lib}' directory ... " mkdir -p $lib 2> $err || err -cp -R ../src/$package_name/lib/* $lib 2> $err || err -echo "OK" - -echo -n "Building '$var' directory ... " -mkdir -p $var 2> $err || err +cp -R ../src/${package_name}/lib/* $lib 2> $err || err +rm -rf ${lib}/*.t 2> $err || err echo "OK" diff --git a/packages/chck_modules_version.sh b/packages/chck_modules_version.sh index d72b8a4516f8149e9daab82829318570e0a62cc5..7ab6e6eebd84c7248b0936ea818ec7d8133bd443 100755 --- a/packages/chck_modules_version.sh +++ b/packages/chck_modules_version.sh @@ -2,9 +2,8 @@ # # Script obtain Perl package version # -modules=(SOAP::Lite IO::Socket::SSL SOAP::Transport::TCP FindBin DateTime) -#modules=(SOAP::Lite SOAP::Transport::TCP File::Pid POSIX DBI Format::Human::Bytes Sys::Syslog File::Basename FindBin Net::CIDR::Lite DateTime) -#modules=(SOAP::Lite SOAP::Transport::TCP File::Pid POSIX DBI DBD::SQLite Format::Human::Bytes Sys::Syslog File::Basename FindBin Net::CIDR::Lite DateTime Getopt::Std Switch IO::Socket::SSL) +#modules=(LWP::Protocol::https) +modules=(SOAP::Lite SOAP::Transport::HTTP DBI DBD::mysql Format::Human::Bytes Sys::Syslog File::Basename Net::CIDR::Lite DateTime Getopt::Std Switch IO::Socket::SSL MIME::Base64 Crypt::X509 Carp) for module in ${modules[@]} do diff --git a/packages/warden-client-2.0.0-beta2.tar.gz b/packages/warden-client-2.0.0-beta2.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..d14d09a187463ec97c0ad923257beb9d8f7bc209 Binary files /dev/null and b/packages/warden-client-2.0.0-beta2.tar.gz differ diff --git a/packages/warden-client-2.0.0-beta2.tar.gz.sig b/packages/warden-client-2.0.0-beta2.tar.gz.sig new file mode 100644 index 0000000000000000000000000000000000000000..76128cd4672dd15aa16989c491d1fe88ede91e10 --- /dev/null +++ b/packages/warden-client-2.0.0-beta2.tar.gz.sig @@ -0,0 +1 @@ +9bca641d8c71f24a0010576fec2808a7ed055594 warden-client-2.0.0-beta2.tar.gz diff --git a/packages/warden-client-2.0.tar.gz b/packages/warden-client-2.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b38ddbb80ad2a89ed19edacccbc88830b26d4288 Binary files /dev/null and b/packages/warden-client-2.0.tar.gz differ diff --git a/packages/warden-client-2.0.tar.gz.sig b/packages/warden-client-2.0.tar.gz.sig new file mode 100644 index 0000000000000000000000000000000000000000..da6e0df32e088773e296781fa5dda31e880e40d4 --- /dev/null +++ b/packages/warden-client-2.0.tar.gz.sig @@ -0,0 +1 @@ +72dafef0ed1a625f11cda121abf3c2d970c26ca0 warden-client-2.0.tar.gz diff --git a/packages/warden-client-2.1-beta.tar.gz b/packages/warden-client-2.1-beta.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..65ca139ec6918c766b0699837bcfebae289e4aa4 Binary files /dev/null and b/packages/warden-client-2.1-beta.tar.gz differ diff --git a/packages/warden-client-2.1-beta.tar.gz.sig b/packages/warden-client-2.1-beta.tar.gz.sig new file mode 100644 index 0000000000000000000000000000000000000000..95a71a6b2da0e5f21b3b7e32881779e74f47796c --- /dev/null +++ b/packages/warden-client-2.1-beta.tar.gz.sig @@ -0,0 +1 @@ +24cc18c69a7fdb6f59bc31bf00a046a396eae3ba warden-client-2.1-beta.tar.gz diff --git a/packages/warden-server-2.0.0-beta.tar.gz b/packages/warden-server-2.0.0-beta.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..4b4c3e5d4e236bcfa2d18d56114e508404c15322 Binary files /dev/null and b/packages/warden-server-2.0.0-beta.tar.gz differ diff --git a/packages/warden-server-2.0.0-beta.tar.gz.sig b/packages/warden-server-2.0.0-beta.tar.gz.sig new file mode 100644 index 0000000000000000000000000000000000000000..3391937c8afadfb8e67bcb4902f7e15399014266 --- /dev/null +++ b/packages/warden-server-2.0.0-beta.tar.gz.sig @@ -0,0 +1 @@ +01bfc44ba12f04f1a56386e4efca8e626f1cdbd1 warden-server-2.0.0-beta.tar.gz diff --git a/packages/warden-server-2.0.tar.gz b/packages/warden-server-2.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..4fb537780eeeed7cf5bdaf8bc84a236520a554cb Binary files /dev/null and b/packages/warden-server-2.0.tar.gz differ diff --git a/packages/warden-server-2.0.tar.gz.sig b/packages/warden-server-2.0.tar.gz.sig new file mode 100644 index 0000000000000000000000000000000000000000..4e95c8501f39252b54e6402a68a4eab10f915877 --- /dev/null +++ b/packages/warden-server-2.0.tar.gz.sig @@ -0,0 +1 @@ +9ad83d6d136358179d68c49255af0f426b564edc warden-server-2.0.tar.gz diff --git a/packages/warden-server-2.1-beta4.tar.gz b/packages/warden-server-2.1-beta4.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..9422c1e1b4ee3ff36c527d86010b366030bcbc93 Binary files /dev/null and b/packages/warden-server-2.1-beta4.tar.gz differ diff --git a/packages/warden-server-2.1-beta4.tar.gz.sig b/packages/warden-server-2.1-beta4.tar.gz.sig new file mode 100644 index 0000000000000000000000000000000000000000..fc2869d91ff5bae4ad3f276864f8200eed4adfa9 --- /dev/null +++ b/packages/warden-server-2.1-beta4.tar.gz.sig @@ -0,0 +1 @@ +3bf719d1f0887f7feb394aafc8a85b48a66e2498 warden-server-2.1-beta4.tar.gz diff --git a/packages/warden-server-2.1-beta5.tar.gz b/packages/warden-server-2.1-beta5.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..29e0b5cc2f7d2c93ecc23598307b5b730f09eed8 Binary files /dev/null and b/packages/warden-server-2.1-beta5.tar.gz differ diff --git a/packages/warden-server-2.1-beta5.tar.gz.sig b/packages/warden-server-2.1-beta5.tar.gz.sig new file mode 100644 index 0000000000000000000000000000000000000000..34e1e59eb2960358829dda6fb1c3c00cceafc918 --- /dev/null +++ b/packages/warden-server-2.1-beta5.tar.gz.sig @@ -0,0 +1 @@ +e4e6cd82c07aa02f4a73aa37f5da13e7d04ab0fe warden-server-2.1-beta5.tar.gz diff --git a/packages/warden-server-2.1-beta6.tar.gz b/packages/warden-server-2.1-beta6.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..7a175976964b8a0412679a479802163179ed6c65 Binary files /dev/null and b/packages/warden-server-2.1-beta6.tar.gz differ diff --git a/packages/warden-server-2.1-beta6.tar.gz.sig b/packages/warden-server-2.1-beta6.tar.gz.sig new file mode 100644 index 0000000000000000000000000000000000000000..662cd86cc443fce14f019f078cc523fb48ea6777 --- /dev/null +++ b/packages/warden-server-2.1-beta6.tar.gz.sig @@ -0,0 +1 @@ +47f95f7e738cf5eb2d8faf3a98e7db6decb1c936 warden-server-2.1-beta6.tar.gz diff --git a/src/meta/README b/src/contrib/meta/README similarity index 100% rename from src/meta/README rename to src/contrib/meta/README diff --git a/src/meta/other/importMetaClients.sh b/src/contrib/meta/other/importMetaClients.sh similarity index 100% rename from src/meta/other/importMetaClients.sh rename to src/contrib/meta/other/importMetaClients.sh diff --git a/src/meta/other/meta-nodes b/src/contrib/meta/other/meta-nodes similarity index 100% rename from src/meta/other/meta-nodes rename to src/contrib/meta/other/meta-nodes diff --git a/src/contrib/meta/other/meta_check.sh b/src/contrib/meta/other/meta_check.sh new file mode 100755 index 0000000000000000000000000000000000000000..dc9d4b22609ace7a543d43c4976bfc00e9ca5d4a --- /dev/null +++ b/src/contrib/meta/other/meta_check.sh @@ -0,0 +1,15 @@ +#!/bin/bash +#Logovatko poctu prenesenych zprav na Warden server a vytizeni serveru + + +USER=root +PASS= +DB=warden +INT=1 + +QUERY="SELECT NOW(), COUNT( id ), COUNT(DISTINCT(note)) FROM events WHERE received > DATE_SUB(UTC_TIMESTAMP(), INTERVAL $INT MINUTE) AND service='test';" + +M_OUT=`echo $QUERY | mysql -s -u$USER -p"$PASS" $DB` +U_OUT=`uptime | awk '{print $11}'` +RET="${M_OUT} ${U_OUT%?}" +echo $RET diff --git a/src/contrib/meta/warden-client-meta.tgz b/src/contrib/meta/warden-client-meta.tgz new file mode 100644 index 0000000000000000000000000000000000000000..a600e4237a8579284e957bcfaa52e6ff8c01019e Binary files /dev/null and b/src/contrib/meta/warden-client-meta.tgz differ diff --git a/src/meta/wardentest-lenny-meta.sh b/src/contrib/meta/wardentest-lenny-meta.sh similarity index 100% rename from src/meta/wardentest-lenny-meta.sh rename to src/contrib/meta/wardentest-lenny-meta.sh diff --git a/src/meta/wtw-lenny-meta.sh b/src/contrib/meta/wtw-lenny-meta.sh similarity index 100% rename from src/meta/wtw-lenny-meta.sh rename to src/contrib/meta/wtw-lenny-meta.sh diff --git a/src/contrib/networkReporter-client/networkReporter.pl b/src/contrib/networkReporter-client/networkReporter.pl new file mode 100755 index 0000000000000000000000000000000000000000..ed32b7d99a7e478f0d065d293a28fc2b5041c897 --- /dev/null +++ b/src/contrib/networkReporter-client/networkReporter.pl @@ -0,0 +1,175 @@ +#!/usr/bin/perl +# +# networkReporter.pl - Warden client for communication with RT ticketing system +# +# Copyright (C) 2012 Masaryk University +# Author(s): Jakub CEGAN <cegan@ics.muni.cz> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Masaryk 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +use warnings; +use strict; + +use lib '/opt/warden-client'; +use Email::Simple; +use Sys::Hostname; +use Text::Wrap; +use DateTime; + + +sub sendmailWrapper{ + my $message = shift; + + if(open(my $sendmail, '|/usr/sbin/sendmail -oi -t')){ + print $sendmail $message; + close $sendmail; + return 1; + } else { + return (0, "Sending email failed: $!"); + } +} + +sub timeToLocal{ + my $time = shift; + + my ($y,$m,$d,$h,$mm,$s); + if(!($$time =~ m/(\d{4})\-(\d{2})\-(\d{2})\ (\d{2})\:(\d{2})\:(\d{2})/)){ + return (0, "Bad time format!\n"); + } + + ($y,$m,$d,$h,$mm,$s) = $$time =~ m/(\d{4})\-(\d{2})\-(\d{2})\ (\d{2})\:(\d{2})\:(\d{2})/; + eval{ + my $dt = DateTime->new( + year => $y, + month => $m, + day => $d, + hour => $h, + minute => $mm, + second => $s, + time_zone =>'gmt'); + $dt->set_time_zone('local'); + $$time = $dt->strftime('%d. %m. %Y v %H:%M');}; + if($@){ + return (0, "Can't convert time to epoch format!\n"); + } + return 1; +} + +#------------------------------------------------------------------------------- +# reportToRT - fuction for creating tickets in the RT system +# +# param: hash with gateway address and warden event array +# +# return: ok || fail +#------------------------------------------------------------------------------- +sub reportToRT{ + + my $inputData = shift; + my $toGateway = $$inputData{'gateway'}; + my @event = @{$$inputData{'data'}}; + + my $fromHostname; + my $message; + my ($rc, $err); + + if(!($toGateway)){ + return (0, "Empty 'To' email header!\n"); + } + + eval{ + $fromHostname = hostname(); + if(!($fromHostname =~ m/\.ics\.muni\.cz/gi)){ + $fromHostname .= '.ics.muni.cz'; + } + }; + if($@){ + return (0, "Can't retrive hostname for 'From' header!\n"); + } + + ($rc, $err) = timeToLocal(\$event[3]); + if(!$rc){ + return (0, $err); + } + + my $text = "DobrĂ˝ den, + z Vašà IP adresy $event[6] jsme zaznamenali $event[3] celkem $event[9] pokus(y) o pĹ™ipojenĂ k neexistujĂcĂ sluĹľbÄ› (tzv. honeypotu). V tomto konkrĂ©tnĂm pĹ™ĂpadÄ› se jednalo o protokol $event[7] a port ÄŤĂslo $event[8]. Je pravdÄ›podobnĂ©, Ĺľe se jedná o virus, napadenĂ˝ poÄŤĂtaÄŤ ÄŤi zneuĹľitĂ˝ uĹľivatelskĂ˝ účet. DoporuÄŤujeme Vám zkontrolovat zabezpeÄŤenĂ tohoto poÄŤitaÄŤe. + + S pozdravem + + CSIRT-MU + http://www.muni.cz/csirt"; + + eval{ + $message = Email::Simple->create( + header => [ + To => $toGateway, + From => 'tools@'.$fromHostname, + Subject => 'Pristup na honeypot v siti CESNET'], + body => fill('','',$text)); + }; + if($@){ + return (0, "Can't create email message\n"); + } + + ($rc, $err) = sendmailWrapper($message->as_string); + if(!$rc){ + return (0, $err); + } + return 1; +} + + +my $warden_path = '/opt/warden-client'; + +require $warden_path . '/lib/WardenClientReceive.pm'; + +my $requested_type = "portscan"; +my $ip_reg = '147\.251\.\d+\.\d+'; +my $client = 'CESNET_IDS'; +my $gateway = 'rt@rt-devel.ics.muni.cz'; + +$Text::Wrap::columns = 90; + + +my $logger; +my @new_events; + +@new_events = WardenClientReceive::getNewEvents($warden_path, $requested_type); +#@new_events = (["5179620","au1.cesnet.cz","CESNET_IDS","2012-11-08 17:04:56","portscan","IP","147.251.216.8","XXX","666","2","","0","720"]); +foreach (@new_events) { + my @event = @$_; + + if(($event[6] =~ /^$ip_reg$/i) and ($event[2] =~ /^$client$/i)){ + my %input = (gateway => $gateway, data => \@event); + my ($rc,$err) = reportToRT(\%input); + if(!$rc){ + #print "ERR: $err\n"; + syslog("err|Warden client - networkReporter $err\n"); + } + } +} + +exit 0; diff --git a/src/meta/warden-client-meta.tgz b/src/meta/warden-client-meta.tgz deleted file mode 100644 index da544a5e0a3cede6d7741e1bb44c05d16d35439e..0000000000000000000000000000000000000000 Binary files a/src/meta/warden-client-meta.tgz and /dev/null differ diff --git a/src/warden-client/bin/receiver.pl b/src/warden-client/bin/receiver.pl index 426e27d6ffcb4c841f8d682425daa383714fcda5..b303178169694d70be6f715862709cc3b91247eb 100755 --- a/src/warden-client/bin/receiver.pl +++ b/src/warden-client/bin/receiver.pl @@ -3,34 +3,8 @@ # receiver.pl # # Copyright (C) 2011-2012 Cesnet z.s.p.o -# Author(s): Tomas PLESNIK <plesnik@ics.muni.cz> -# Jan SOUKAL <soukal@ics.muni.cz> -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name of the Cesnet z.s.p.o 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 any express or implied -# warranties, including, but not limited to, the implied warranties of -# merchantability and fitness for a particular purpose are disclaimed. -# In no event shall the Cesnet z.s.p.o or contributors be liable for -# any direct, indirect, incidental, special, exemplary, or consequential -# damages (including, but not limited to, procurement of substitute -# goods or services; loss of use, data, or profits; or business -# interruption) however caused and on any theory of liability, whether -# in contract, strict liability, or tort (including negligence or -# otherwise) arising in any way out of the use of this software, even -# if advised of the possibility of such damage. # +# Use of this source is governed by a BSD-style license, see LICENSE file. use strict; diff --git a/src/warden-client/bin/sender.pl b/src/warden-client/bin/sender.pl index caedc70e0a6281ff7e604b58c10beca56d5b52f9..18816172ece753b2bce4f36fff64450955668ad8 100755 --- a/src/warden-client/bin/sender.pl +++ b/src/warden-client/bin/sender.pl @@ -3,34 +3,8 @@ # sender.pl # # Copyright (C) 2011-2012 Cesnet z.s.p.o -# Author(s): Tomas PLESNIK <plesnik@ics.muni.cz> -# Jan SOUKAL <soukal@ics.muni.cz> -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name of the Cesnet z.s.p.o 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 any express or implied -# warranties, including, but not limited to, the implied warranties of -# merchantability and fitness for a particular purpose are disclaimed. -# In no event shall the Cesnet z.s.p.o or contributors be liable for -# any direct, indirect, incidental, special, exemplary, or consequential -# damages (including, but not limited to, procurement of substitute -# goods or services; loss of use, data, or profits; or business -# interruption) however caused and on any theory of liability, whether -# in contract, strict liability, or tort (including negligence or -# otherwise) arising in any way out of the use of this software, even -# if advised of the possibility of such damage. # +# Use of this source is governed by a BSD-style license, see LICENSE file. use Switch; use strict; @@ -61,11 +35,11 @@ switch (int(rand(9) + 0.5)) { case 8 { $type = 'webattack'; } case 9 { $type = 'other'; } } - + my $source_type = ""; switch (int(rand(2) + 0.5)) { case 0 { $source_type = 'IP'; } - case 1 { $source_type = 'url'; } + case 1 { $source_type = 'URL'; } case 2 { $source_type = 'Reply-To:'; } } @@ -84,7 +58,7 @@ switch (int(rand(5) + 0.5)) { case 2 { $target_port = '25'; } case 3 { $target_port = '443'; } case 4 { $target_port = '3389'; } - case 5 { $target_port = 'null'; } + case 5 { $target_port = undef; } } my $attack_scale = (int(rand(100000) + 0.5) + 1000); @@ -94,13 +68,13 @@ my $note = "tohle je takova normalni jednoducha poznamka"; my $priority = ""; switch (int(rand(1) + 0.5)) { case 0 { $priority = int(rand(255) + 0.5); } - case 1 { $priority = 'null'; } + case 1 { $priority = undef; } } my $timeout = ""; switch (int(rand(1) + 0.5)) { case 0 { $timeout = int(rand(255) + 0.5); } - case 1 { $timeout = 'null'; } + case 1 { $timeout = undef; } } my @event = ( diff --git a/src/warden-client/doc/CHANGELOG b/src/warden-client/doc/CHANGELOG index 1a7dbfc908ec4d300e3ac9ceda807aeb6487607e..79f017b8364c3eed9342dbacdfab1f88acc25410 100644 --- a/src/warden-client/doc/CHANGELOG +++ b/src/warden-client/doc/CHANGELOG @@ -1,3 +1,27 @@ +2012-11-05 v.2.1-beta version +------------------------------- +- Added WardenClientCommon.pm package containing error-handling and + connect-to-server functions +- Installation of Warden client does not require copying of certificates + and keys (#553) +- Enhanced error messages (#552) +- Reading of configuration file enhanced (#533) +- Added protection from unexpected results in XML data returned from + server (#532) +- Added support for error (debug) logging via STDERR and/or Syslog (#520,#522) +- Receiving of all types of messages now supported +- Unexpected errors does not crush the client application (#519) +- Maximum number of events received ($MAX_RCV_EVENTS_LIMIT) in one + batch can be set in etc/warden-client.conf. Default is 6000. (#504) +- Added support for batch processing (#504) + + +2012-07-27 v.2.0 stable version and bugfix release of warden-client-2.0.0-beta +------------------------------------------------------------------------------ +- Sender client code fixed, so that it will not terminate "parent" + application when crashed + + 2012-05-10 v.2.0.0-beta beta version of warden-client-2.0.0 ----------------------------------------------------------- - Changed communication with server: HTTP layer added (compatible with diff --git a/src/warden-client/doc/README b/src/warden-client/doc/README index 51cd655cd80581edd699f5f48f02959fb2970c25..15307238ee2d41e26108f8c1bc096bf80bd5596f 100644 --- a/src/warden-client/doc/README +++ b/src/warden-client/doc/README @@ -1,16 +1,16 @@ -+-----------------------------------+ -| README - Warden Client 2.0.0-beta | -+-----------------------------------+ ++----------------------------+ +| README - Warden Client 2.1 | ++----------------------------+ Content A. Overall Information B. Installation Dependencies - C. Registration - D. Installation - E. Update - F. Uninstallation - G. Configuration + C. Installation + D. Update + E. Uninstallation + F. Configuration + G. Registration H. Integration with Local Applications I. Functions, Arguments and Calls @@ -21,7 +21,8 @@ A. Overall Information 1. About Warden Client Warden is a client-based architecture service designed to share detected - security events (issues) among CSIRT and CERT teams in a simple and fast way. + security events (issues) among CSIRT and CERT teams in a simple and fast + way. This package offers a client capable of both reporting events to server and retreiving batch of new events from server. It consists of several Perl @@ -29,7 +30,7 @@ A. Overall Information 2. Version - 2.0.0-beta (2012-05-10) + 2.1 (2012-11-05) 3. Package structure @@ -38,101 +39,42 @@ A. Overall Information CHANGELOG example-sender.pl.txt example-receiver.pl.txt - INSTALL - LICENSE - README - README.cesnet + INSTALL + LICENSE + README + README.cesnet etc/ warden-client.conf - package_version + package_version lib/ WardenClientConf.pm WardenClientSend.pm WardenClientReceive.pm + WardenClientCommon.pm var/ -------------------------------------------------------------------------------- B. Installation Dependencies - Perl >= 5.10.1 - SOAP::Lite >= 0.712 - IO::Socket::SSL >= 1.33 - SOAP::Transport::HTTP >= 0.712 - FindBin >= 1.50 - DateTime >= 0.61 - + Perl >= 5.10.1 + SOAP::Lite >= 0.712 + IO::Socket::SSL >= 1.74 + SOAP::Transport::HTTP >= 0.712 + FindBin >= 1.50 + DateTime >= 0.61 + Carp >= 1.11 -------------------------------------------------------------------------------- -C. Registration - - Any client attempting to communicate with the Warden server must be - registered on this server. Unknown (not registered) clients are not allowed - to exchange any data with server. - - Registration of your client is provided by the Warden server administrator. - Usually via e-mail. - - Clients also need to have valid client SSL certificates to prove their - identity to the Warden server. - - Each client is defined by its hostname, service name, type of client, type - of requested events, receiving of own events, description tags and CIDR - this client is allowed to communicate from. - - Hostname hostname of client to be registered - - Service name Text string. Unique name of the service - the client is integrated in. - E.g. 'ScanDetector_1.0'. This is mandatory for - 'Sender' client. Default value null is used for - 'Receiver' client. - - Type of client Either 'Sender' or 'Receiver'. - - Type of requested events Type of events the client only accepts from - the Warden server. This is mandatory only for - 'Receiver' client. Default value null is used - for 'Sender' client. Brief information about - event types is provided in section G. Functions - arguments and calls. - - Receiving of own events Enables receiving of events sent from your - organization domain = yes/no (organizations are - separated based on the top-level and - second-level domain). This is mandatory only - for 'Receiver' client. - - Description tags Tags are case insensitive alphanumeric strings - designed to allow event receivers to filter - according to event source. For example, - receiver can decide to use only events - originating from honeypots or filter out events - generated manually by users. This is mandatory - for 'Sender' client. - - CIDR CIDR stands for IP (sub)net the client is going - to communicate from (see examples below!). Any - communications between the client and the Warden - server must be performed from IP address from - a range stated in CIDR. - Examples: '123.123.0.0/16', '123.123.123.123/32' - - - For complete information about client attributes and/or event types you will - have to contact particular Warden server administrator/provider. - - --------------------------------------------------------------------------------- -D. Installation (First installation of the Warden client package) +C. Installation (First installation of the Warden client package) 1. Check SHA1 checksum of corresponding Warden client package archive - $ sha1sum -c warden-client-2.0.0-beta.tar.gz.sig + $ sha1sum -c warden-client-2.1.tar.gz.sig 2. Untar it - $ tar xzvf warden-client-2.0.0-beta.tar.gz + $ tar xzvf warden-client-2.1.tar.gz 3. Run install.sh @@ -149,22 +91,20 @@ D. Installation (First installation of the Warden client package) However, the Warden client uses SSL certificates for security purposes which are often not accessible by standard users. - To solve this issue, the Warden client should be installed under root - privileges. It copyies local SSL key and certificate files into - warden-client/etc folder where those are accessible even with standard - privileges. + Install script does check the accessibility of SSL certificates to + provided user. If these files are restricted, the install script will raise + a warning. However this will not stop the install process. Either privileges + to read them must be changed or Warden client must be run under root. - Should users want to preserve standard location of certificate files, - they are advised to remove key and certificate files after installation - from warden-client/etc/ and manually edit paths to certificate files in - warden-client/etc/warden-client.conf. In most cases, this change will force - the Warden client to be run under root privileges though. + Of course, after installation of Warden client, SSL certificates may also be + copied to another location accessible by the user and corresponding paths + changed in warden-client/etc/warden-client.conf. 5. Configuration file After successful installation process you are advised to check configuration file warden-client/etc/warden-client.conf. For more information see section - below G. Configuration. + below F. Configuration. 6. Usage of install.sh @@ -172,7 +112,7 @@ D. Installation (First installation of the Warden client package) [-c <ssl_cert_file>] [-a <ssl_ca_file>] [-hV] -d <directory> installation directory (default: /opt) -u <user> owner of warden client package (user for - running detection scripts) + running detection scripts) -k <ssl_key_file> SSL certificate key file path -c <ssl_cert_file> SSL certificate file path -a <ssl_ca_file> CA certificate file path @@ -184,15 +124,15 @@ D. Installation (First installation of the Warden client package) -------------------------------------------------------------------------------- -E. Update (Update of previously installed the Warden client package) +D. Update (Update of previously installed the Warden client package) 1. Check SHA1 checksum of corresponding the Warden client package archive - $ sha1sum -c warden-client-2.0.0-beta.tar.gz.sig + $ sha1sum -c warden-client-2.0.tar.gz.sig 2. Untar it - $ tar xzvf warden-client-2.0.0-beta.tar.gz + $ tar xzvf warden-client-2.0.tar.gz 3. Run update.sh @@ -206,7 +146,7 @@ E. Update (Update of previously installed the Warden client package) After successful update process you are advised to check configuration file warden-client/etc/warden-client.conf. For more information see section - G. Configuration. + F. Configuration. 5. Usage of update.sh @@ -221,7 +161,7 @@ E. Update (Update of previously installed the Warden client package) -------------------------------------------------------------------------------- -F. Uninstallation +E. Uninstallation 1. Run uninstall.sh @@ -246,7 +186,7 @@ F. Uninstallation -------------------------------------------------------------------------------- -G. Configuration +F. Configuration SOAP protocol is used for handling communication between server and clients. Therefore, correct URI of the Warden server must be set. @@ -269,11 +209,107 @@ G. Configuration e.g. '/etc/ssl/certs/tcs-ca-bundle.pem' + Client receives events in batches. Maximum number of events received in one + batch can is set in MAX_RCV_EVENTS_LIMIT. Note that this option only + affects clients that receives events from the Warden server (e.g., uses + lib/WardenClientReceive.pm module). + + MAX_RCV_EVENTS_LIMIT - maximum number of events in one batch + - default set to 6000, which generates app. 250 MB + of memory consumption. + - only affects "receiving" clients + + Note: server is queried for the MAX_RCV_EVENTS_LIMIT number of events, + however server can have its own internal maximum size of batch. Contact + your Warden server administrator if you need to know Warden server batch + limits. + + Since Warden client 2.1 there is also possibility to log status and other + information either to STDERR of Syslog. + + LOG_STDERR - if set to 1 (default), all status information and + possible error will be printed to STDERR + - to disable, set LOG_STDERR to 0 + + LOG_SYSLOG - if set to 1, all status information and possible + errors will be reported to Syslog + - default is 0, which means that reporting to Syslog + is disabled + + LOG_SYSLOG_FACILITY - facility to use when logging via Syslog + - deafult is "local7" + + LOG_VERBOSE - when set to 1, also debug information (such as stack + dump) will be printed when logging. + - default is 0, which means that verbose mode is + disabled + + +-------------------------------------------------------------------------------- +G. Registration + + Any client attempting to communicate with the Warden server must be + registered on this server. Unknown (not registered) clients are not allowed + to exchange any data with server. + + Registration of your client is provided by the Warden server administrator. + Usually via e-mail. + + Clients also need to have valid client SSL certificates to prove their + identity to the Warden server. + + Each client is defined by its hostname, service name, type of client, type + of requested events, receiving of own events, description tags and CIDR + this client is allowed to communicate from. + + Hostname hostname of client to be registered + + Service name Text string. Unique name of the service the client + is integrated in. + E.g. 'ScanDetector_1.0'. This is mandatory for + 'Sender' client. Default value null is used for + 'Receiver' client. + + Type of client Either 'Sender' or 'Receiver'. + + Type of requested events Type of events the client only accepts from + the Warden server. This is mandatory only for + 'Receiver' client. Default value null is used + for 'Sender' client. Brief information about + event types is provided in section I. Functions + arguments and calls. + + Receiving of own events Enables receiving of events sent from your + organization domain = yes/no (organizations are + separated based on the top-level and + second-level domain). This is mandatory only + for 'Receiver' client. + + Description tags Tags are case insensitive alphanumeric strings + designed to allow event receivers to filter + according to event source. For example, + receiver can decide to use only events + originating from honeypots or filter out events + generated manually by users. This is mandatory + for 'Sender' client. + + CIDR CIDR stands for IP (sub)net the client is going + to communicate from (see examples below!). Any + communications between the client and the Warden + server must be performed from IP address from + a range stated in CIDR. + Examples: '123.123.0.0/16', '123.123.123.123/32' + + + For complete information about client attributes and/or event types you will + have to contact particular Warden server administrator/provider. + + -------------------------------------------------------------------------------- H. Integration with Local Applications (Note: Clients need to be registered on server to be able to communicate with - server properly. See section C. Registration for more information about + server properly. See section G. Registration for more information about client registration.) 1. Client sender (this type of client reports events to the Warden server) @@ -331,7 +367,7 @@ I. Functions, Arguments and Calls # SERVICE - VARCHAR (64) # Name of a service detecting this event. Service must be the same with this # provided in 'Sender' client registration. See more about this issue in - # section C. Registration. + # section G. Registration. $service = "ScanDetector"; # DETECTED - TIMESTAMP in UTC, ISO 8601 @@ -344,6 +380,8 @@ I. Functions, Arguments and Calls # portscan - scannig of TCP/UDP ports # bruteforce - bruteforce/dictionary attack against authentication # service(s) + # probe - other connection attempts (for example ICMP) or + # unrecognized/undecided portscan or bruteforce # spam - unsolicited e-mail that does not have phishing-like # character # phishing - e-mail attempting to gather sensitive data @@ -357,39 +395,39 @@ I. Functions, Arguments and Calls # SOURCE_TYPE - VARCHAR 64 # Type of source of reported attack/issue. Currently supported values are: - # IP, URL, Reply-To:, null + # 'IP', 'URL', 'Reply-To:' $source_type = "IP"; # SOURCE - VARCHAR 256 - # identification of an attack source/origin according to source_type + # Identification of an attack source/origin according to source_type. $source = "123.123.123.123"; # TARGET_PROTO - VARCHAR 16 # Protocol type of reported attack/issue target. Supported are all L3 and L4 - # protocols and null. + # protocols or 'undef'. $target_proto = "TCP"; # TARGET_PORT - INT 2 - # Port number of reported attack/issue target or null. + # Port number of reported attack/issue target or 'undef'. $target_port = "22"; # ATTACK_SCALE - INT 4 - # Definition of attack scale, e.g., number of affected targets. Null is also + # Definition of attack scale, e.g., number of affected targets. 'undef' is also # possible when attack scale is not known or clear enough. $attack_scale = "1234567890"; # NOTE - TEXT - # Some important(!) note or comment or null. Also, it may contain virus + # Some important(!) note, comment or 'undef'. Also, it may contain virus # sample, phishing e-mail with headers and other accordingly to event type. $note = "this threat is dangerous"; # PRIORITY - INT 1 - # Subjective definition of incident severity. Values 0-255 or null are - # possible where 0 is the lowest priority. - $priority = "null"; + # Subjective definition of incident severity. Values 0-255 are + # possible where 0 is the lowest priority or 'undef'. + $priority = "1"; # TIMEOUT - INT 2 - # Subjective time (in minutes) or null. After this time event might be + # Subjective time (in minutes) or 'undef'. After this time event might be # considered timeouted. $timeout = "20"; @@ -413,7 +451,7 @@ I. Functions, Arguments and Calls # Definition of requested event type. Type must be the same with this # provided in 'Receiver' client registration. See more about this issue in - # section C. Registration. See more about event types in section + # section G. Registration. See more about event types in section # I. 1. WardenClientSend::saveNewEvent $requested_type = "botnet_c_c"; @@ -425,6 +463,11 @@ I. Functions, Arguments and Calls explained in section I. 1. WardenClientSend::saveNewEvent. It has one additional attribute ID - unique id of this particular event (BIGINT). + Amount of events received in each batch equals to MAX_RCV_EVENTS_LIMIT + value set in warden-client/etc/warden-client.conf. For more information see + section F. Configuration. + -------------------------------------------------------------------------------- Copyright (C) 2011-2012 Cesnet z.s.p.o + diff --git a/src/warden-client/doc/README.cesnet b/src/warden-client/doc/README.cesnet index 5a6f61e581bad627f6464521fe8ac23f486c9b50..15ab12b3ae5bbc4654fa6fc9a8510614c7ebdcc8 100644 --- a/src/warden-client/doc/README.cesnet +++ b/src/warden-client/doc/README.cesnet @@ -1,8 +1,8 @@ -+-------------------------------------+ -| README.cesnet - Warden Client 1.2.0 | -| | -| CESNET Specifics | -+-------------------------------------+ ++-----------------------------------+ +| README.cesnet - Warden Client 2.1 | +| | +| CESNET Specifics | ++-----------------------------------+ Content @@ -26,7 +26,7 @@ A. Overall Information 2. Version - 1.2.0 (2012-03-30) + 2.1 (2012-10-18) -------------------------------------------------------------------------------- B. Registration @@ -45,7 +45,8 @@ B. Registration * For receiver client: - hostname of the machine, where client runs, - client type = receiver, - - type of requested events (for example 'portscan', see below) + - whether client should receive all events, or type of requested + events (for example 'portscan', see below) otherwise - receiving of sent events from my organization = yes/no (organizations are separated based on the top-level and second-level domain), - CIDR from which client will communicate with Warden server. @@ -88,7 +89,8 @@ C. Description tags 1. Detection medium - * Network - network data based (Snort, Suricata, Bro, FTAS, LaBrea, Kippo) + * Network - network data based (Snort, Suricata, Bro, FTAS, LaBrea, Kippo, + Dionaea) * Host - host based (Swatch, Logcheck) * Correlation - corellation engines (Prelude, OSSIM) * External - credible external sources (incident reporting, ticket @@ -97,7 +99,7 @@ C. Description tags 2. Data source * Content - datagram content based detectors (Snort, Bro) - * Flow - netflow based (FTAS, FlowMon) + * Flow - netflow based (FTAS, FlowMon, HoneyScan) * Connection - connection data (portscan, portsweep) * Data - application data based (SpamAssassin, antiviruses) * Log - based on system logs, where more specific source is not @@ -113,7 +115,7 @@ C. Description tags 4. Detector/analyzer product name examples - * Snort, FTAS, SpamAssassin, LaBrea, Swatch, Prelude + * Snort, FTAS, SpamAssassin, LaBrea, Swatch, Prelude, Kippo, Dionaea -------------------------------------------------------------------------------- D. Types of events @@ -126,6 +128,8 @@ D. Types of events * portscan - TCP/UDP port scanning/sweeping * bruteforce - dictionary/bruteforce attack to services authentication + * probe - other connection attempts (for example ICMP) or + unrecognized/undecided portscan or bruteforce * spam - unsolicited commercial email (except phishing) * phishing - email, trying to scam user to revealing personal information (possibly by some other channel) @@ -134,6 +138,8 @@ D. Types of events * malware - virus/malware sample * copyright - copyright infringement * webattack - web application attack + * test - clients can use these at will when debugging/testing, these + messages will be processed and stored, but ignored later * other - the rest, uncategorizable yet In case of complex scenarios with structured info more events with diff --git a/src/warden-client/doc/example-receiver.pl.txt b/src/warden-client/doc/example-receiver.pl.txt old mode 100644 new mode 100755 index 7236548d03518741f5f4f644bfc04b1b4a4c117d..090e9a9d4d9fb5289814f12d708eed811bd475ee --- a/src/warden-client/doc/example-receiver.pl.txt +++ b/src/warden-client/doc/example-receiver.pl.txt @@ -7,7 +7,7 @@ use strict; #------------------------------------------------------------------------------ -# Warden 1.2.0. Client, Receiver, Example +# Warden 2.1 Client, Receiver, Example # # Simple use of warden-client receiver functionality to download new events # from # Warden server. This code illustrates how to integrate warden-client @@ -18,17 +18,14 @@ use strict; # This code should developer add into his/her application. # Path to warden-client directory -my $warden_path = '/opt/warden-client'; +my $warden_path = '/opt/warden-client/'; # Inclusion of warden-client receiving functionality require $warden_path . '/lib/WardenClientReceive.pm'; # Definition of requested event type. This attributes is also set on server # and must not change. -my $requested_type = "botnet_c_c"; - -# Download of new evetns from Warden server -my @new_events = WardenClientReceive::getNewEvents($warden_path, $requested_type); +my $requested_type = "portscan"; #------------------------------------------------------------------------------ # Simple code that prints out new events obtained from Warden server. @@ -37,9 +34,15 @@ print "+------------------------------------------------------------------------ print "| id | hostname | service | detected | type | source_type | source | target_proto | target_port | attack_scale | note | priority | timeout |\n"; print "+------------------------------------------------------------------------------------------------------------------------------------------+\n"; -foreach (@new_events) { - print "| " . join(' | ', @$_) . " |" . "\n"; +# Download of new evetns from Warden server +while (my @new_events = WardenClientReceive::getNewEvents($warden_path, $requested_type)) { + foreach my $event_ref (@new_events) { + my @event = @$event_ref; + print "| " . join(' | ', @event) . " |" . "\n"; + } +print "+------------------------------------------------------------------------------------------------------------------------------------------+\n"; } + print "+------------------------------------------------------------------------------------------------------------------------------------------+"; print "\n"; print "Last events in: " . scalar(localtime(time)) . "\n"; diff --git a/src/warden-client/doc/example-sender.pl.txt b/src/warden-client/doc/example-sender.pl.txt old mode 100644 new mode 100755 index b0988177f135a3335c6087a59e4f4181602df4ad..40af31a0b048fb37204e076a8e64c59c7a514fd4 --- a/src/warden-client/doc/example-sender.pl.txt +++ b/src/warden-client/doc/example-sender.pl.txt @@ -8,7 +8,7 @@ use strict; use DateTime; #------------------------------------------------------------------------------- -# Warden 1.2.0. Client, Sender, Example +# Warden 2.1. Client, Sender, Example # # Sample script using warden-client sending functionality. This example is not # intended to be a standalone script. It only shows how to use warden-client @@ -32,7 +32,7 @@ my $target_proto = "TCP"; my $target_port = "22"; my $attack_scale = "1234567890"; my $note = "important note or comment"; -my $priority = "null"; +my $priority = undef; my $timeout = "20"; my @event = ($service, $detected, $type, $source_type, $source, diff --git a/src/warden-client/etc/package_version b/src/warden-client/etc/package_version index faa8f64f32791692b7686b61ce2aea3a8bf3a4cc..b0e13726b780dad53fd80e1534c75ee691e0d022 100644 --- a/src/warden-client/etc/package_version +++ b/src/warden-client/etc/package_version @@ -1 +1 @@ -warden-client-2.0.0-beta +warden-client-2.1 diff --git a/src/warden-client/etc/warden-client.conf b/src/warden-client/etc/warden-client.conf index 276b8ed18c54a9e9020cf90660538ab3fcd95fff..a58d30bd8e688630132ffd3c64ac777c95a050f2 100644 --- a/src/warden-client/etc/warden-client.conf +++ b/src/warden-client/etc/warden-client.conf @@ -22,3 +22,29 @@ $SSL_CERT_FILE = "/opt/warden-client/etc/warden-dev.cesnet.cz.pem"; #------------------------------------------------------------------------------- $SSL_CA_FILE = "/etc/ssl/certs/tcs-ca-bundle.pem"; +#------------------------------------------------------------------------------- +# MAX_RCV_EVENTS_LIMIT - maximum number of events the client is allowd to get +# from the Warden server in one batch +#------------------------------------------------------------------------------- +$MAX_RCV_EVENTS_LIMIT = 6000; #consumes app. 250 MB of memory + +#------------------------------------------------------------------------------- +# Log options +# +# LOG_STDERR, LOG_SYSLOG - hide (0) or allow (1) error reporting on STDERR +# and/or to Syslog +# LOG_STDERR_VERBOSE, LOG_SYSLOG_VERBOSE - print only error message without +# a stack (0) or print debug info +# including err. message and stack (1) +#------------------------------------------------------------------------------- +$LOG_STDERR = 1; + +$LOG_SYSLOG = 1; +$LOG_SYSLOG_FACILITY = "local7"; + +$LOG_VERBOSE = 0; + + + +1; + \ No newline at end of file diff --git a/src/warden-client/lib/WardenClientCommon.pm b/src/warden-client/lib/WardenClientCommon.pm new file mode 100755 index 0000000000000000000000000000000000000000..901588d0d2f4ad57835b05a32de8045fe1a9f011 --- /dev/null +++ b/src/warden-client/lib/WardenClientCommon.pm @@ -0,0 +1,86 @@ +#!/usr/bin/perl -w +# +# WardenClientCommon.pm +# +# Copyright (C) 2011-2012 Cesnet z.s.p.o +# +# Use of this source is governed by a BSD-style license, see LICENSE file. + +package WardenClientCommon; + +use strict; +use Carp; +use SOAP::Lite; +use IO::Socket::SSL qw(debug1); +use SOAP::Transport::HTTP; + +our $VERSION = "2.1"; + +#------------------------------------------------------------------------------- +# errMsg - print error message and die +#------------------------------------------------------------------------------- +sub errMsg +{ + my $msg = shift; + + if ($WardenClientConf::LOG_VERBOSE) { # user wants to log debug information + $msg .= "\nStack info: " . Carp::longmess(); + } + + die($msg . "\n"); +} # End of errMsg + + +#------------------------------------------------------------------------------- +# c2s - connect to server, send request and receive response +#------------------------------------------------------------------------------- +sub c2s +{ + my $uri = shift; + my $ssl_key_file = shift; + my $ssl_cert_file = shift; + my $ssl_ca_file = shift; + my $method = shift; + my $data = shift; + + my $client; + my ($server, $port, $service) = $uri =~ /https:\/\/(.+)\:(\d+)\/(.+)/; + if (!($client = SOAP::Transport::HTTP::Client->new())) { + errMsg("Unable to create socket: " . &SOAP::Transport::HTTP::Client::errstr) + } + $client->timeout(10); + $client->ssl_opts(verify_hostname => 1, + SSL_use_cert => 1, + SSL_verify_mode => 0x02, + SSL_key_file => $ssl_key_file, + SSL_cert_file => $ssl_cert_file, + SSL_ca_file => $ssl_ca_file); + + # setting of URI and serialize SOAP envelope and data object + my $soap = SOAP::Lite->uri($service)->proxy($uri); + my $envelope; + if (!defined $data) { + $envelope = $soap->serializer->envelope(method => $method); + } else { + $envelope = $soap->serializer->envelope(method => $method, $data); + } + + # setting of TCP URI and send serialized SOAP envelope and data + my $server_uri = "https://$server:$port/$service"; + my $result = $client->send_receive(envelope => $envelope, endpoint => $server_uri); + + # check server response + if (!defined $result) { + errMsg("Server returned empty response. Problem with used SSL ceritificates or Warden server at $server:$port is down."); + } else { + # deserialized response from server -> create SOAP envelope and data object + my $response; + + eval { + $response = $soap->deserializer->deserialize($result); + } or errMsg($@ . "Received data: " . $result); + # check SOAP fault status + $response->fault ? errMsg("Server sent error message:: " . $response->faultstring) : return $response; + } +} + diff --git a/src/warden-client/lib/WardenClientConf.pm b/src/warden-client/lib/WardenClientConf.pm index 637e046f324073e02e1d3557d598e9257145f71b..034ad9e00d695779e094e0c707867de9ffbbcf2f 100755 --- a/src/warden-client/lib/WardenClientConf.pm +++ b/src/warden-client/lib/WardenClientConf.pm @@ -10,33 +10,30 @@ package WardenClientConf; use strict; -our $VERSION = "2.0"; +# preset of default variables +our $URI = undef; +our $SSL_KEY_FILE = undef; +our $SSL_CERT_FILE = undef; +our $SSL_CA_FILE = undef; +our $MAX_RCV_EVENTS_LIMIT = undef; +our $LOG_STDERR = 1; +our $LOG_SYSLOG = 0; +our $LOG_SYSLOG_FACILITY = "local7"; +our $LOG_VERBOSE = 0; -#------------------------------------------------------------------------------- -# loadConf - load variables from configuration file -#------------------------------------------------------------------------------- -sub loadConf -{ - my $conf_file = shift; - # preset of default variables - our $URI = undef; - our $SSL_KEY_FILE = undef; - our $SSL_CERT_FILE = undef; - our $SSL_CA_FILE = undef; +our $VERSION = "2.1"; - # read config file - if ( ! open( TMP, $conf_file) ) { - die("Can't read config file '$conf_file': $!\n"); - } - close TMP; +sub loadConf +{ + my $conf_file = shift; - # load set variables by user - if ( !do $conf_file ) { - die("Errors in config file '$conf_file': $@"); + # load configuration variables set by user + unless (do $conf_file) { + die("Errors in config file '$conf_file': $@") if $@; + die("Can't read config file '$conf_file': $!") unless defined $_; + # if $_ defined, it's retvalue of last statement of conf, for which we don't care } +} - return ($URI, $SSL_KEY_FILE, $SSL_CERT_FILE, $SSL_CA_FILE); - -} # End of loadConf 1; diff --git a/src/warden-client/lib/WardenClientReceive.pm b/src/warden-client/lib/WardenClientReceive.pm index 0b7a3f5774862943b0a9f674a30963b06d9df45d..dc52f622693600c7b41c21f79b77ad2120e4e62f 100755 --- a/src/warden-client/lib/WardenClientReceive.pm +++ b/src/warden-client/lib/WardenClientReceive.pm @@ -13,163 +13,122 @@ use SOAP::Lite; use IO::Socket::SSL qw(debug1); use SOAP::Transport::HTTP; use FindBin; +use Sys::Syslog; -our $VERSION = "2.0"; #first iteration after 'port to Apache' - -#------------------------------------------------------------------------------- -# errMsg - print error message and die -#------------------------------------------------------------------------------- -sub errMsg -{ - my $msg = shift; - die($msg . "\n"); -} # End of errMsg - - -#------------------------------------------------------------------------------- -# c2s - connect to server, send request and receive response -#------------------------------------------------------------------------------- -sub c2s -{ - my $uri = shift; - my $ssl_key_file = shift; - my $ssl_cert_file = shift; - my $ssl_ca_file = shift; - my $method = shift; - my $data = shift; - - my $client; - my ($server, $port, $service) = $uri =~ /https:\/\/(.+)\:(\d+)\/(.+)/; - if (!($client = SOAP::Transport::HTTP::Client->new())) { - errMsg("Sorry, unable to create socket: " . &SOAP::Transport::HTTP::Client::errstr) - } - $client->timeout(60); - $client->ssl_opts(verify_hostname => 1, - SSL_use_cert => 1, - SSL_verify_mode => 0x02, - SSL_key_file => $ssl_key_file, - SSL_cert_file => $ssl_cert_file, - SSL_ca_file => $ssl_ca_file); - - # setting of URI and serialize SOAP envelope and data object - my $soap = SOAP::Lite->uri($service)->proxy($uri); - my $envelope; - if (!defined $data) { - $envelope = $soap->serializer->envelope(method => $method); - } else { - $envelope = $soap->serializer->envelope(method => $method, $data); - } - - # setting of TCP URI and send serialized SOAP envelope and data - my $server_uri = "https://$server:$port/$service"; - my $result = $client->send_receive(envelope => $envelope, endpoint => $server_uri); - - # check server response - if (!defined $result) { - errMsg("Error: server returned empty response." . "\n" . "Problem with used SSL ceritificates or Warden server at $server:$port is down."); - } else { - # deserialized response from server -> create SOAP envelope and data object - my $response = $soap->deserializer->deserialize($result); - # check SOAP fault status - $response->fault ? errMsg("Server sent error message:: " . $response->faultstring) : return $response; - } -} - - - +our $VERSION = "2.1"; #------------------------------------------------------------------------------- # getNewEvents - get new events from warden server greater than last received ID #------------------------------------------------------------------------------- sub getNewEvents { - my $warden_path = shift; - my $requested_type = shift; - - my $vardir = $warden_path . "/var/"; - my $etcdir = $warden_path . "/etc/"; - my $libdir = $warden_path . "/lib/"; - - # read the config file - require $libdir . "WardenClientConf.pm"; - my $conf_file = $etcdir . "warden-client.conf"; - my ($uri, $ssl_key_file, $ssl_cert_file, $ssl_ca_file) = WardenClientConf::loadConf($conf_file); - - # set name of ID file for each client aplication - my $caller_name = $FindBin::Script; - my $id_file = $vardir . $caller_name . ".id"; - - #----------------------------------------------------------------------------- - # get last ID from ID file (if exist) or - # get last ID from warden server DB and save it into ID file - my $last_id; - if (-e $id_file) { - open(ID, "< $id_file") || errMsg("Cannot open ID file $id_file: $!"); - foreach(<ID>) { - $last_id = $_; + my @events; + + eval { + + my $warden_path = shift; + my $requested_type = shift; + + my $vardir = $warden_path . "/var/"; + my $etcdir = $warden_path . "/etc/"; + my $libdir = $warden_path . "/lib/"; + + require $libdir . "WardenClientConf.pm"; + require $libdir . "WardenClientCommon.pm"; + + # read the config file + my $conf_file = $etcdir . "warden-client.conf"; + WardenClientConf::loadConf($conf_file); + + # set name of ID file for each client aplication + my $caller_name = $FindBin::Script; + my $id_file = $vardir . $caller_name . ".id"; + + #----------------------------------------------------------------------------- + # get last ID from ID file (if exist) or + # get last ID from warden server DB and save it into ID file + my $last_id; + if (-e $id_file) { + open(ID, "< $id_file") || WardenClientCommon::errMsg("Cannot open ID file $id_file: $!"); + foreach(<ID>) { + $last_id = $_; + } + close ID; + } else { + my $response = WardenClientCommon::c2s($WardenClientConf::URI, $WardenClientConf::SSL_KEY_FILE, $WardenClientConf::SSL_CERT_FILE, $WardenClientConf::SSL_CA_FILE, "getLastId"); + $last_id = $response->result; + open(ID, "> $id_file") || WardenClientCommon::errMsg("Cannot open ID file $id_file: $!"); + print ID $last_id; + close ID; } - close ID; - } else { - my $response = c2s($uri, $ssl_key_file, $ssl_cert_file, $ssl_ca_file, "getLastId"); - $last_id = $response->result; - open(ID, "> $id_file") || die ("Cannot open ID file $id_file: $!"); - print ID $last_id; - close ID; - } - - #----------------------------------------------------------------------------- - # get new events from warden server DB based on gathered last ID - - # create SOAP data obejct - my $request_data = SOAP::Data->name( - request => \SOAP::Data->value( - SOAP::Data->name(REQUESTED_TYPE => $requested_type), - SOAP::Data->name(LAST_ID => $last_id) - ) - ); + + #----------------------------------------------------------------------------- + # get new events from warden server DB based on gathered last ID + + # create SOAP data obejct + my $request_data = SOAP::Data->name( + request => \SOAP::Data->value( + SOAP::Data->name(REQUESTED_TYPE => $requested_type), + SOAP::Data->name(LAST_ID => $last_id), + SOAP::Data->name(MAX_RCV_EVENTS_LIMIT => $WardenClientConf::MAX_RCV_EVENTS_LIMIT) + ) + ); + + # call server method getNewEvents + my $response = WardenClientCommon::c2s($WardenClientConf::URI, $WardenClientConf::SSL_KEY_FILE, $WardenClientConf::SSL_CERT_FILE, $WardenClientConf::SSL_CA_FILE, "getNewEvents", $request_data); + + # parse returned SOAP data object + my ($id, $hostname, $service, $detected, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout); + my @response_list = $response->valueof('/Envelope/Body/getNewEventsResponse/event/'); + while (scalar @response_list) { + my $response_data = shift(@response_list); + my @event; + + # parse items of one event + $id = $response_data->{'ID'}; + $hostname = $response_data->{'HOSTNAME'}; + $service = $response_data->{'SERVICE'}; + $detected = $response_data->{'DETECTED'}; + $type = $response_data->{'TYPE'}; + $source_type = $response_data->{'SOURCE_TYPE'}; + $source = $response_data->{'SOURCE'}; + $target_proto = $response_data->{'TARGET_PROTO'}; + $target_port = $response_data->{'TARGET_PORT'}; + $attack_scale = $response_data->{'ATTACK_SCALE'}; + $note = $response_data->{'NOTE'}; + $priority = $response_data->{'PRIORITY'}; + $timeout = $response_data->{'TIMEOUT'}; + + # push new event from warden server into @events which is returned + @event = ($id, $hostname, $service, $detected, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout); + push (@events, \@event); + + # set maximum received ID from current batch + if ($id > $last_id) { + $last_id = $id; + } + } #end of while loop + + # write last return ID + if (defined $last_id) { # must be defined for first check ID + open(ID, "> $id_file") || WardenClientCommon::errMsg("Cannot open ID file $id_file: $!"); + print ID $last_id; + close ID; + } + } # End of eval block + or do { - # call server method getNewEvents - my $response = c2s($uri, $ssl_key_file, $ssl_cert_file, $ssl_ca_file, "getNewEvents", $request_data); - - # parse returned SOAP data object - my ($id, $hostname, $service, $detected, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout); - my @events; - my @response_list = $response->valueof('/Envelope/Body/getNewEventsResponse/event/'); - while (scalar @response_list) { - my $response_data = shift(@response_list); - my @event; - - # parse items of one event - $id = $response_data->{'ID'}; - $hostname = $response_data->{'HOSTNAME'}; - $service = $response_data->{'SERVICE'}; - $detected = $response_data->{'DETECTED'}; - $type = $response_data->{'TYPE'}; - $source_type = $response_data->{'SOURCE_TYPE'}; - $source = $response_data->{'SOURCE'}; - $target_proto = $response_data->{'TARGET_PROTO'}; - $target_port = $response_data->{'TARGET_PORT'}; - $attack_scale = $response_data->{'ATTACK_SCALE'}; - $note = $response_data->{'NOTE'}; - $priority = $response_data->{'PRIORITY'}; - $timeout = $response_data->{'TIMEOUT'}; - - # push new event from warden server into @events which is returned - @event = ($id, $hostname, $service, $detected, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout); - push (@events, \@event); - - # set maximum received ID from current batch - if ($id > $last_id) { - $last_id = $id; + if ($WardenClientConf::LOG_STDERR) { + print STDERR $@ . "\n"; + } + + if ($WardenClientConf::LOG_SYSLOG) { + openlog("Warden:", "pid", "WardenClientConf::LOG_SYSLOG_FACILITY"); + syslog("err|WardenClientConf::LOG_SYSLOG_FACILITY", $@ . "\n"); + closelog(); } - } #end of while loop - - # write last return ID - if (defined $last_id) { # must be defined for first check ID - open(ID, "> $id_file") || die ("Cannot open ID file $id_file: $!"); - print ID $last_id; - close ID; - } + return; + }; return @events; diff --git a/src/warden-client/lib/WardenClientSend.pm b/src/warden-client/lib/WardenClientSend.pm index 05f7850bc0b3896ba8365f3ebb92a0339e2f6a35..2e20210f1683984f123159f60d9f56e66e3642af 100755 --- a/src/warden-client/lib/WardenClientSend.pm +++ b/src/warden-client/lib/WardenClientSend.pm @@ -12,118 +12,81 @@ use strict; use SOAP::Lite; use IO::Socket::SSL qw(debug1); use SOAP::Transport::HTTP; +use Sys::Syslog; -our $VERSION = "2.0"; #first iteration after 'port to Apache' - - -#------------------------------------------------------------------------------- -# errMsg - print error message and die -#------------------------------------------------------------------------------- -sub errMsg -{ - my $msg = shift; - die($msg . "\n"); -} # End of errMsg - - -#------------------------------------------------------------------------------- -# c2s - connect to server, send request and receive response -#------------------------------------------------------------------------------- -sub c2s -{ - my $uri = shift; - my $ssl_key_file = shift; - my $ssl_cert_file = shift; - my $ssl_ca_file = shift; - my $method = shift; - my $data = shift; - - my ($server, $port, $service) = $uri =~ /https:\/\/(.+)\:(\d+)\/(.+)/; - - my $client; - if (!($client = SOAP::Transport::HTTP::Client->new())) { - errMsg("Sorry, unable to create socket: " . &SOAP::Transport::HTTP::Client::errstr) - } - $client->timeout(60); - $client->ssl_opts(verify_hostname => 1, - SSL_use_cert => 1, - SSL_verify_mode => 0x02, - SSL_key_file => $ssl_key_file, - SSL_cert_file => $ssl_cert_file, - SSL_ca_file => $ssl_ca_file); - - - # setting of URI and serialize SOAP envelope and data object - my $soap = SOAP::Lite->uri($service)->proxy($uri); - my $envelope = $soap->serializer->envelope(method => $method, $data); - - # setting of TCP URI and send serialized SOAP envelope and data - my $server_uri = "https://$server:$port/$service"; - - my $result = $client->send_receive(envelope => $envelope, endpoint => $server_uri); - - # check server response - if (!defined $result) { - errMsg("Error: server returned empty response." . "\n" . "Problem with used SSL ceritificates or Warden server at $server:$port is down."); - } else { - # deserialized response from server -> create SOAP envelope and data object - my $response = $soap->deserializer->deserialize($result); - # check SOAP fault status - $response->fault ? errMsg("Server sent error message:: " . $response->faultstring) : return 1; - } -} - +our $VERSION = "2.1"; #------------------------------------------------------------------------------- # saveNewEvent - send new event from detection scripts to warden server #------------------------------------------------------------------------------- sub saveNewEvent { - my $warden_path = shift; - my $event_ref = shift; - - my $etcdir = $warden_path . "/etc/"; - my $libdir = $warden_path . "/lib/"; - - # read the config file - require $libdir . "WardenClientConf.pm"; - my $conf_file = $etcdir . "warden-client.conf"; - my ($uri, $ssl_key_file, $ssl_cert_file, $ssl_ca_file) = WardenClientConf::loadConf($conf_file); - - # prepare variables of event - my @event = @{$event_ref}; - my $service = $event[0]; - my $detected = $event[1]; - my $type = $event[2]; - my $source_type = $event[3]; - my $source = $event[4]; - my $target_proto = $event[5]; - my $target_port = $event[6]; - my $attack_scale = $event[7]; - my $note = $event[8]; - my $priority = $event[9]; - my $timeout = $event[10]; - - # create SOAP data object - my $event = SOAP::Data->name( - event => \SOAP::Data->value( - SOAP::Data->name(SERVICE => $service), - SOAP::Data->name(DETECTED => $detected), - SOAP::Data->name(TYPE => $type), - SOAP::Data->name(SOURCE_TYPE => $source_type), - SOAP::Data->name(SOURCE => $source), - SOAP::Data->name(TARGET_PROTO => $target_proto), - SOAP::Data->name(TARGET_PORT => $target_port), - SOAP::Data->name(ATTACK_SCALE => $attack_scale), - SOAP::Data->name(NOTE => $note), - SOAP::Data->name(PRIORITY => $priority), - SOAP::Data->name(TIMEOUT => $timeout) - ) - ); - - my $result = c2s($uri, $ssl_key_file, $ssl_cert_file, $ssl_ca_file, "saveNewEvent", $event); - $result ? return 1 : return 0; - + my $result; + + eval { + my $warden_path = shift; + my $event_ref = shift; + + my $etcdir = $warden_path . "/etc/"; + my $libdir = $warden_path . "/lib/"; + + require $libdir . "WardenClientConf.pm"; + require $libdir . "WardenClientCommon.pm"; + + # read the config file + my $conf_file = $etcdir . "warden-client.conf"; + WardenClientConf::loadConf($conf_file); + + # prepare variables of event + my @event = @{$event_ref}; + my $service = $event[0]; + my $detected = $event[1]; + my $type = $event[2]; + my $source_type = $event[3]; + my $source = $event[4]; + my $target_proto = $event[5]; + my $target_port = $event[6]; + my $attack_scale = $event[7]; + my $note = $event[8]; + my $priority = $event[9]; + my $timeout = $event[10]; + + # create SOAP data object + my $event = SOAP::Data->name( + event => \SOAP::Data->value( + SOAP::Data->name(SERVICE => $service), + SOAP::Data->name(DETECTED => $detected), + SOAP::Data->name(TYPE => $type), + SOAP::Data->name(SOURCE_TYPE => $source_type), + SOAP::Data->name(SOURCE => $source), + SOAP::Data->name(TARGET_PROTO => $target_proto), + SOAP::Data->name(TARGET_PORT => $target_port), + SOAP::Data->name(ATTACK_SCALE => $attack_scale), + SOAP::Data->name(NOTE => $note), + SOAP::Data->name(PRIORITY => $priority), + SOAP::Data->name(TIMEOUT => $timeout) + ) + ); + + $result = WardenClientCommon::c2s($WardenClientConf::URI, $WardenClientConf::SSL_KEY_FILE, $WardenClientConf::SSL_CERT_FILE, $WardenClientConf::SSL_CA_FILE, "saveNewEvent", $event); + } # End of eval block + or do { + + if ($WardenClientConf::LOG_STDERR) { + print STDERR $@ . "\n"; + } + + if ($WardenClientConf::LOG_SYSLOG) { + openlog("Warden-client:", "pid", "$WardenClientConf::LOG_SYSLOG_FACILITY"); + syslog("err|$WardenClientConf::LOG_SYSLOG_FACILITY", $@ . "\n"); + closelog(); + } + + return 0; + }; + + $result ? return 1 : return 0; + } # End of saveNewEvent 1; diff --git a/src/warden-client/lib/WardenClientSend.t b/src/warden-client/lib/WardenClientSend.t new file mode 100644 index 0000000000000000000000000000000000000000..b32a36bd0e1d408ff8e89ba822115757a097bfc7 --- /dev/null +++ b/src/warden-client/lib/WardenClientSend.t @@ -0,0 +1,32 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Test::More tests => 2; + +use lib '..'; +use WardenClientSend; + +my $uri_ok = 'https://warden-dev.cesnet.cz:443/Warden'; +my $ssl_key_file_ok = '/opt/warden-client/etc/warden-dev.cesnet.cz.key'; +my $ssl_cert_file_ok = '/opt/warden-client/etc/warden-dev.cesnet.cz.pem'; +my $ssl_ca_file_ok = '/opt/warden-client/etc/tcs-ca-meta-bundle.pem'; +my $method_ok = 'saveNewEvent'; +my $data_ok = ''; + +my $warden_path_ok = '/opt/warden-client'; +my $warden_path_fail = '/path/to/fail'; +my @event_ok = ("honeyscan", "1234567890", "portscan","IP", "123.123.123.123", "TCP", "22", "1234567890", "important note or comment", "null", "20"); +my @vent_ok = ('HoneyScan', '2012-09-01T23:02:48', 'webattackReply-To:', '170.96.48.164', 'UDP', '44392354', 'tohle je takova normalni jednoducha poznamka', '180187'); + +my $ret; + +#my ($ret) = WardenClientSend::c2s($uri_ok, $ssl_key_file_ok, $ssl_cert_file_ok, $ssl_ca_file_ok, $method_ok, $data_ok); +#ok ($ret == 1, 'Everything is fine!'); + +$ret = WardenClientSend::saveNewEvent($warden_path_fail,\@event_ok); +ok ($ret == 0, 'Bad Warden path!'); + +$ret = WardenClientSend::saveNewEvent($warden_path_ok,\@event_ok); +ok ($ret == 1, 'Everything is fine.'); diff --git a/src/warden-client/sh/install.sh b/src/warden-client/sh/install.sh index f121a99a219a690f47828541572584658ee9412d..8e70ec0946441ca0b970e95398fff49b81453ab0 100755 --- a/src/warden-client/sh/install.sh +++ b/src/warden-client/sh/install.sh @@ -7,7 +7,7 @@ # Use of this source is governed by a BSD-style license, see LICENSE file. -VERSION="2.0" +VERSION="2.1" #------------------------------------------------------------------------------- # FUNCTIONS @@ -139,40 +139,47 @@ modules_chck() make_warden_dir() { echo -n "Creating warden client directory ... " - test -d $prefix || mkdir -p $prefix - if cp -R ${dirname}/warden-client $prefix 2> $err; then + test -d $prefix || mkdir -p prefix + + if cp -R ${dirname}/warden-client $prefix 2> $err; then echo "OK" else - err_clean + err_clean fi + echo -n "Copying files ... " + files=(CHANGELOG INSTALL LICENSE README README.cesnet) for file in ${files[@]}; do - cp ${dirname}/$file ${client_path}/doc + cp ${dirname}/warden-client/doc/$file ${client_path}/doc done - cp ${dirname}/uninstall.sh $client_path + + test -d ${client_path}/ || mkdir -p ${client_path}/ + cp ${dirname}/uninstall.sh ${client_path}/ + + echo "OK" } -copy_key() +check_key() { - echo -n "Copying certificate key file ... " - if cp $key $etc 2> $err; then + echo -n "Checking certificate key file ... " + if su ${user} -c "test -r ${key}" 2> $err; then echo "OK" else - err_clean + echo "Warning: certificate key file is not readable by user ${user}!" fi } -copy_cert() +check_cert() { - echo -n "Copying certificate file ... " - if cp $cert $etc 2> $err; then + echo -n "Checking certificate file ... " + if su ${user} -c "test -r ${key}" 2> $err; then echo "OK" else - err_clean + echo "Warning: certificate file is not readable by user ${user}!" fi } @@ -192,17 +199,44 @@ make_conf_file() #------------------------------------------------------------------------------- # SSL_KEY_FILE - path to client SSL certificate key file #------------------------------------------------------------------------------- -\$SSL_KEY_FILE = \"${etc}/${key_file}\"; +\$SSL_KEY_FILE = \"${key}\"; #------------------------------------------------------------------------------- # SSL_CERT_FILE - path to client SSL certificate file #------------------------------------------------------------------------------- -\$SSL_CERT_FILE = \"${etc}/${cert_file}\"; +\$SSL_CERT_FILE = \"${cert}\"; #------------------------------------------------------------------------------- # SSL_CA_FILE - path to CA certificate file #------------------------------------------------------------------------------- \$SSL_CA_FILE = \"${ca_file}\"; + +#------------------------------------------------------------------------------- +# MAX_RCV_EVENTS_LIMIT - maximum number of events the client is allowd to get +# from the Warden server in one batch +#------------------------------------------------------------------------------- +\$MAX_RCV_EVENTS_LIMIT = 6000; #consumes app. 250 MB of memory + +#------------------------------------------------------------------------------- +# Log options +# +# LOG_STDERR, LOG_SYSLOG - hide (0) or allow (1) error reporting on STDERR +# and/or to Syslog +# LOG_STDERR_VERBOSE, LOG_SYSLOG_VERBOSE - print only error message without +# a stack (0) or print debug info +# including err. message and stack (1) +#------------------------------------------------------------------------------- +\$LOG_STDERR = 1; + +\$LOG_SYSLOG = 0; +\$LOG_SYSLOG_FACILITY = \"local7\"; + +\$LOG_VERBOSE = 0; + + + +1; + " > $conf_file 2> $err; ret_val=`echo $?` if [ $ret_val -eq 0 ]; then @@ -217,7 +251,6 @@ change_permissions() { echo -n "Changing permissions to installed package ... " chown -R $user: $client_path 2> $err || err_clean - chmod 400 ${etc}/$key_file ${etc}/$cert_file || err_clean chmod 644 ${etc}/package_version || err_clean if chmod 600 $conf_file; then echo "OK" @@ -233,8 +266,7 @@ change_permissions() #------------------------------------------------------------------------------- # list of used Perl modules -modules=(SOAP::Lite IO::Socket::SSL SOAP::Transport::TCP FindBin DateTime) - +modules=(SOAP::Lite IO::Socket::SSL SOAP::Transport::HTTP FindBin DateTime Carp) # read input while getopts "d:u:k:c:a:Vh" options; do case $options in @@ -286,10 +318,10 @@ echo "------------------------- Installation process --------------------------" make_warden_dir # copy cert key file -copy_key +check_key # copy cert file -copy_cert +check_cert # create conf file make_conf_file diff --git a/src/warden-client/sh/uninstall.sh b/src/warden-client/sh/uninstall.sh index c2b52d0c2acd5a1d6fa0f7c152935347f202270f..96e63413bec166489f1dc3d9e88714c1bd4ed8d9 100755 --- a/src/warden-client/sh/uninstall.sh +++ b/src/warden-client/sh/uninstall.sh @@ -6,7 +6,7 @@ # # Use of this source is governed by a BSD-style license, see LICENSE file. -VERSION="2.0" +VERSION="2.1" #------------------------------------------------------------------------------- # FUNCTIONS @@ -126,12 +126,6 @@ uninstall_warden_client() # MAIN #------------------------------------------------------------------------------- -# OS test -os_chck - -# Shell test -shell_chck - # read input while getopts "d:Vh" options; do case $options in @@ -156,6 +150,9 @@ obtain_package_version echo echo "------------------------- Uninstallation process --------------------------------" +# root check +root_chck + # check if $prefix/warden-client directory exist warden_dir_chck diff --git a/src/warden-client/sh/update.sh b/src/warden-client/sh/update.sh index 5590252bdbbde0598ff2b54743c8dc81e91d6923..a08085c6bceafd9bc7ee50a0fa4c7365db7a4f16 100755 --- a/src/warden-client/sh/update.sh +++ b/src/warden-client/sh/update.sh @@ -7,7 +7,7 @@ # Use of this source is governed by a BSD-style license, see LICENSE file. -VERSION="2.0" +VERSION="2.1" #------------------------------------------------------------------------------- # FUNCTIONS @@ -184,6 +184,28 @@ make_conf_file() ssl_key_file=`cat $conf_file | grep '$SSL_KEY_FILE'` ssl_cert_file=`cat $conf_file | grep '$SSL_CERT_FILE'` ssl_ca_file=`cat $conf_file | grep '$SSL_CA_FILE'` + max_rcv_events_limit=`cat $conf_file | grep '$MAX_RCV_EVENTS_LIMIT'` + + log_stderr=`cat $conf_file | grep '$LOG_STDERR'` + if [ -z $log_stderr ]; then + log_stderr="\$LOG_STDERR = 1;" + fi + + log_syslog=`cat $conf_file | grep '$LOG_SYSLOG'` + if [ -z $log_syslog ]; then + log_syslog="\$LOG_SYSLOG = 0;" + fi + + log_syslog_facility=`cat $conf_file | grep '$LOG_SYSLOG_FACILITY'` + if [ -z $log_syslog_facility ]; then + log_syslog_facility="\$LOG_SYSLOG_FACILITY = \"local7\";" + fi + + log_verbose=`cat $conf_file | grep '$LOG_VERBOSE'` + if [ -z $log_verbose ]; then + log_verbose="\$LOG_VERBOSE = 0;" + fi + echo "# # warden-client.conf - configuration file for the warden sender/receiver client # @@ -207,6 +229,30 @@ $ssl_cert_file # SSL_CA_FILE - path to CA certificate file #------------------------------------------------------------------------------- $ssl_ca_file + +#------------------------------------------------------------------------------- +# MAX_RCV_EVENTS_LIMIT - maximum number of events the client is allowd to get +# from the Warden server in one batch +#------------------------------------------------------------------------------- +$max_rcv_events_limit + +#------------------------------------------------------------------------------- +# Log options +# +# LOG_STDERR, LOG_SYSLOG - hide (0) or allow (1) error reporting on STDERR +# and/or to Syslog +# LOG_STDERR_VERBOSE, LOG_SYSLOG_VERBOSE - print only error message without +# a stack (0) or print debug info +# including err. message and stack (1) +#------------------------------------------------------------------------------- +$log_stderr + +$log_syslog +$log_syslog_facility + +$log_verbose + +1; " > $conf_file 2> $err; ret_val=`echo $?` if [ $ret_val -eq 0 ]; then @@ -221,9 +267,6 @@ change_permissions() { echo -n "Changing permissions to updated package ... " chown -R $user: $client_path 2>$err || err_clean - key_file=`echo $ssl_key_file | cut -d "\"" -f 2` - cert_file=`echo $ssl_cert_file | cut -d "\"" -f 2` - chmod 400 $key_file $cert_file || err_clean chmod 644 $old_package_version_file || err_clean if chmod 600 $conf_file; then echo "OK" @@ -239,7 +282,7 @@ change_permissions() #------------------------------------------------------------------------------- # list of used Perl modules -modules=(SOAP::Lite IO::Socket::SSL SOAP::Transport::TCP FindBin DateTime) +modules=(SOAP::Lite IO::Socket::SSL SOAP::Transport::HTTP FindBin DateTime Carp) # read input while getopts "d:Vh" options; do diff --git a/src/warden-server/bin/getClients.pl b/src/warden-server/bin/getClients.pl index 987d19238c679ada8c18003887b7b53d9575b003..63fff51198bc46bd81b969878c6d26a8afcda9c0 100755 --- a/src/warden-server/bin/getClients.pl +++ b/src/warden-server/bin/getClients.pl @@ -10,7 +10,7 @@ use strict; use Getopt::Std; use File::Basename; -our $VERSION = "2.0"; +our $VERSION = "2.1"; my $warden_path = '/opt/warden-server'; require $warden_path . '/lib/WardenStatus.pm'; @@ -71,22 +71,22 @@ if ($UID != 0) { my @clients = WardenStatus::getClients($warden_path); -print "+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n"; -print "| Client ID | Hostname | Registered | Requestor | Service | CT | Type | ROE | Description tags | IP Net Client |\n"; -print "+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n"; +print "+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n"; +print "| Client ID | Hostname | Registered | Requestor | Service | CT | Type | ROE | Description tags | IP Net Client |\n"; +print "+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n"; foreach (@clients) { - printf("| %-10s ", @$_[0]); - printf("| %-30s ", @$_[1]); - printf("| %19s ", @$_[2]); - printf("| %-10s ", @$_[3]); - printf("| %-20s ", @$_[4]); - printf("| %-2s ", @$_[5]); - printf("| %-15s ", @$_[6]); - printf("| %-4s ", @$_[7]); - printf("| %-30s ", @$_[8]); - printf("| %-18s |\n", @$_[9]); + printf("| %-10s ", @$_[0] || "unknown"); + printf("| %-30s ", @$_[1] || "unknown"); + printf("| %19s ", @$_[2] || "unknown"); + printf("| %-23s ", @$_[3] || "unknown"); + printf("| %-25s ", @$_[4] || "unknown"); + printf("| %-2s ", @$_[5] || "unknown"); + printf("| %-15s ", @$_[6] || "unknown"); + printf("| %-4s ", @$_[7] || "unknown"); + printf("| %-50s ", @$_[8] || "unknown"); + printf("| %-18s |\n", @$_[9] || "unknown"); } -print "+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n"; +print "+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+\n"; print "\n"; print "Current registered clients in: " . scalar localtime(time) . "\n"; diff --git a/src/warden-server/bin/getStatus.pl b/src/warden-server/bin/getStatus.pl index bc49afbad74bed2cc8728e8e8a9849c467e82c69..bcd6adf6d09286fab51f5ea3a15ff14465437402 100755 --- a/src/warden-server/bin/getStatus.pl +++ b/src/warden-server/bin/getStatus.pl @@ -10,7 +10,7 @@ use strict; use Getopt::Std; use File::Basename; -our $VERSION = "2.0"; +our $VERSION = "2.1"; my $warden_path = '/opt/warden-server'; require $warden_path . '/lib/WardenStatus.pm'; @@ -74,6 +74,21 @@ my @status = WardenStatus::getStatus($warden_path); my $server_status_ref = shift(@status); my @server_status = @$server_status_ref; +my $syslog; +my $syslog_verbose; + +if ($server_status[7] == 1) { + $syslog = "enabled"; +} else { + $syslog = "disabled"; +} + +if ($server_status[8] == 1) { + $syslog_verbose = "enabled"; +} else { + $syslog_verbose = "disabled"; +} + print "Warden server variables:\n"; print "========================\n"; print "SERVER_VERSION:\t\t$server_status[0]\n"; @@ -83,34 +98,37 @@ print "PORT:\t\t\t$server_status[3]\n"; print "DB_NAME:\t\t$server_status[4]\n"; print "DB_USER:\t\t$server_status[5]\n"; print "DB_HOST:\t\t$server_status[6]\n"; -print "SYSLOG_FACILITY:\t$server_status[7]\n"; +print "SYSLOG:\t\t\t$syslog\n"; +print "SYSLOG_VERBOSE:\t\t$syslog_verbose\n"; +print "SYSLOG_FACILITY:\t$server_status[9]\n"; print "\n"; print "Warden server status:\n"; print "=====================\n"; -print "Database size:\t\t\t$server_status[8]\n"; -print "Count of saved events:\t\t$server_status[9]\n"; -print "Last ID in events table:\t$server_status[10]\n"; -print "Time of first inserted event:\t$server_status[11] (UTC)\n"; -print "Time of latest inserted event:\t$server_status[12] (UTC)\n"; -print "Count of registered clients:\t$server_status[13]\n"; +print "Database size:\t\t\t$server_status[10]\n"; +print "Count of saved events:\t\t$server_status[11]\n"; +print "Last ID in events table:\t$server_status[12]\n"; +print "Time of first inserted event:\t$server_status[13] (UTC)\n"; +print "Time of latest inserted event:\t$server_status[14] (UTC)\n"; +print "Count of registered clients:\t$server_status[15]\n"; print "\n"; # check if sum of registered client isn't 0 -if ($server_status[13] != 0) { - print "Statistics of registered senders:\n"; - print "+-----------------------------------------------------------------------------------------------------------+\n"; - print "| Client ID | Hostname | Service | Stored events | Last insertion (UTC) |\n"; - print "+-----------------------------------------------------------------------------------------------------------+\n"; +if ($server_status[15] != 0) { + print "Statistics of active registered senders:\n"; + print "========================================\n"; + print "+----------------------------------------------------------------------------------------------------------------+\n"; + print "| Client ID | Hostname | Service | Stored events | Last insertion (UTC) |\n"; + print "+----------------------------------------------------------------------------------------------------------------+\n"; foreach my $client_status_ref (@status){ my @client_status = @$client_status_ref; - printf("| %-10s ", $client_status[0]); - printf("| %-30s ", $client_status[1]); - printf("| %-20s ", $client_status[2]); - printf("| %-13s ", $client_status[3]); - printf("| %-20s |\n", $client_status[4]); + printf("| %-10s ", $client_status[0] || "unknown"); + printf("| %-30s ", $client_status[1] || "unknown"); + printf("| %-25s ", $client_status[2] || "unknown"); + printf("| %-13s ", $client_status[3] || "unknown"); + printf("| %-20s |\n", $client_status[4] || "unknown"); } - print "+-----------------------------------------------------------------------------------------------------------+\n"; + print "+----------------------------------------------------------------------------------------------------------------+\n"; print "\n"; } diff --git a/src/warden-server/bin/getWebStatus.sh b/src/warden-server/bin/getWebStatus.sh deleted file mode 100755 index 726e0ac93d3cc32d4cba9ab4e099dc92f8e68f7e..0000000000000000000000000000000000000000 --- a/src/warden-server/bin/getWebStatus.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -DB_NAME=`cat /opt/warden-server/etc/warden-server.conf | grep '$DB_NAME' | sed 's/[";]//g' |awk '{print $3}'` -DB_USER=`cat /opt/warden-server/etc/warden-server.conf | grep '$DB_USER' | sed 's/[";]//g' |awk '{print $3}'` -DB_PASS=`cat /opt/warden-server/etc/warden-server.conf | grep '$DB_PASS' | sed 's/[";]//g' |awk '{print $3}'` -DB_HOST=`cat /opt/warden-server/etc/warden-server.conf | grep '$DB_HOST' | sed 's/[";]//g' |awk '{print $3}'` - -echo "DB_NAME: $DB_NAME" -echo "DB_USER: $DB_USER" -#echo "DB_PASS: $DB_PASS" -echo "DB_HOST: $DB_HOST" -echo - -echo "DB status:" -echo "----------" -echo "SELECT FROM_UNIXTIME( UNIX_TIMESTAMP( received ) - ( UNIX_TIMESTAMP( received ) % ( 60 ) ) ) AS t, COUNT( id ) FROM events GROUP BY t" | mysql -h $DB_HOST --user=$DB_USER $DB_NAME --password=$DB_PASS -echo -echo "apache2ctl status:" -echo "------------------" -apache2ctl status -echo -echo "uptime:" -echo "-------" -uptime -echo -echo -n klientu: ; netstat -nlpa | grep :443 | grep ESTA | wc -l; -echo -n FIN:; netstat | grep WAIT2 | wc -l - diff --git a/src/warden-server/bin/registerReceiver.pl b/src/warden-server/bin/registerReceiver.pl index b9df7a45ca833cf8eaf45a53956347921703255f..cada6e2055937d5432d881bd5d21c57b2dbe5a69 100755 --- a/src/warden-server/bin/registerReceiver.pl +++ b/src/warden-server/bin/registerReceiver.pl @@ -31,7 +31,7 @@ sub help { print "-h print this text and exit\n"; print "-n hostname of receiver\n"; print "-r client registration requestor\n"; - print "-t type of received events\n"; + print "-t type of received events or '_any_' for receiving of all types of events\n"; print "-o enable receiving of own events\n"; print "-i CIDR of receiver\n"; exit 0; diff --git a/src/warden-server/bin/warden-alive b/src/warden-server/bin/warden-alive deleted file mode 100755 index 214acc9a48a663e8b80251c04be569a7b0cb8a02..0000000000000000000000000000000000000000 --- a/src/warden-server/bin/warden-alive +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/perl - -# Pri pouziti Apache + mod_perl se tento soubor nepouziva - -# -# warden-alive -# -# Copyright (C) 2011-2012 Cesnet z.s.p.o -# Author(s): Jan Mach <jan.mach@cesnet.cz> -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name of the Cesnet z.s.p.o 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 any express or implied -# warranties, including, but not limited to, the implied warranties of -# merchantability and fitness for a particular purpose are disclaimed. -# In no event shall the Cesnet z.s.p.o or contributors be liable for -# any direct, indirect, incidental, special, exemplary, or consequential -# damages (including, but not limited to, procurement of substitute -# goods or services; loss of use, data, or profits; or business -# interruption) however caused and on any theory of liability, whether -# in contract, strict liability, or tort (including negligence or -# otherwise) arising in any way out of the use of this software, even -# if advised of the possibility of such damage. - -our $VERSION = "0.1"; - -my $rv = `ps aux | grep "/usr/bin/perl -w /opt/warden-server/bin/warden-server.pl" | grep -v grep | grep -v process-alive | wc -l`; -if ($rv) { - print "WARDEN OK: Warden server is running\n"; -} -else { - print "WARDEN CRITICAL: Warden server is not running\n"; -}; diff --git a/src/warden-server/bin/warden-server.pl b/src/warden-server/bin/warden-server.pl deleted file mode 100755 index 3b1ccd94d4daefaf82f55313df9326d2931c178d..0000000000000000000000000000000000000000 --- a/src/warden-server/bin/warden-server.pl +++ /dev/null @@ -1,891 +0,0 @@ -#!/usr/bin/perl -w - -# Pri pouziti Apache + mod_perl se tento soubor nepouziva - - -# -# warden-server.pl -# -# Copyright (C) 2011-2012 Cesnet z.s.p.o -# Author(s): Tomas PLESNIK <plesnik@ics.muni.cz> -# Jan SOUKAL <soukal@ics.muni.cz> -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name of the Cesnet z.s.p.o 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 any express or implied -# warranties, including, but not limited to, the implied warranties of -# merchantability and fitness for a particular purpose are disclaimed. -# In no event shall the Cesnet z.s.p.o or contributors be liable for -# any direct, indirect, incidental, special, exemplary, or consequential -# damages (including, but not limited to, procurement of substitute -# goods or services; loss of use, data, or profits; or business -# interruption) however caused and on any theory of liability, whether -# in contract, strict liability, or tort (including negligence or -# otherwise) arising in any way out of the use of this software, even -# if advised of the possibility of such damage. - -package Warden; - -use strict; -use SOAP::Lite; -use SOAP::Transport::TCP; -use File::Pid; -use POSIX; -use DBI; -use Format::Human::Bytes; -use Sys::Syslog qw(:DEFAULT setlogsock); -Sys::Syslog::setlogsock('unix'); -use File::Basename; -use FindBin; -use Data::Dumper; -use Net::CIDR::Lite; -use DateTime; - -our $VERSION = "0.1"; - -################################################################################ -# CONFIG FILE VARIABLES -################################################################################ - -my $script_name = $FindBin::Script; -my $conf_file = "/opt/warden-server/etc/warden-server.conf"; - -# first declaration of globa variables from config file -our $ADDRESS = undef; -our $PORT = undef; -our $LOGDIR = undef; -our $PIDDIR = undef; -our $VARDIR = undef; -our $SSL_KEY_FILE = undef; -our $SSL_CERT_FILE = undef; -our $SSL_CA_FILE = undef; -our $FACILITY = undef; - -# read config file -if ( ! open( TMP, $conf_file) ) { - die errMsg("Can't read config file '$conf_file': $!\n"); -} -close TMP; - -# load set variables by user -if ( !do $conf_file ) { - die errMsg("Errors in config file '$conf_file': $@"); -} - - - -################################################################################ -# VARIABLES -################################################################################ -my $die_now = 0; - -# PID path -my $pid_file = $PIDDIR . $script_name . ".pid"; - -# DB file -my $db_file = "warden.db"; -my $db = $VARDIR . $db_file; - -# connect to DB - DBH is GLOBAL variable -my $dbargs = {AutoCommit => 0, PrintError => 1}; -our $DBH = DBI->connect("dbi:SQLite:dbname=$db","","",$dbargs) or die errMsg("Can't connect to DB: $!"); -#our $DBH = DBI->connect("DBI:mysql:database=warden;host=localhost", "root", "", {RaiseError => 1, mysql_auto_reconnect => 1}) || die "Could not connect to database: $DBI::errstr"; - - -################################################################################ -# LOCAL FUNCTIONS -################################################################################ - -#------------------------------------------------------------------------------- -# errMsg - print error message and die -#------------------------------------------------------------------------------- -sub errMsg -{ - my $msg = shift; - $msg = trim($msg); - print $msg . "\n"; - exit 1; -} # End of errMsg - - -#------------------------------------------------------------------------------- -# trim - remove whitespace from the start and end of the string -#------------------------------------------------------------------------------- -sub trim -{ - my $string = shift; - $string =~ s/^\s+//; - $string =~ s/\s+$//; - return $string; -} # End of trim - - -#------------------------------------------------------------------------------- -# write2log - writing message to syslog -#------------------------------------------------------------------------------- -sub write2log -{ - my $priority = shift; - my $msg = shift; - my $filename = File::Basename::basename($0); - - Sys::Syslog::openlog($filename, "cons,pid", $FACILITY); - Sys::Syslog::syslog("$priority", "$msg"); - Sys::Syslog::closelog(); -} # End of write2log - - -#------------------------------------------------------------------------------- -# signalHandler - catch signals and end the program if one is caught. -#------------------------------------------------------------------------------- -sub signalHandler -{ - $die_now = 1; # this will cause the "infinite loop" to exit -} # End of signalHandler - - -#------------------------------------------------------------------------------- -# sslErrorHandler - handle errors in SSL negitiation -#------------------------------------------------------------------------------- -sub sslErrorHandler -{ - my $socket = shift; - my $msg = shift; - - my $ip = $socket->peerhost; - print $socket $msg; - $socket->close; - write2log ("err", "Caught SSL handshake error from $ip: $msg"); - return 1; -} # End of sslErrorHandler - - -#------------------------------------------------------------------------------- -# altNamesFilter - parse hostnames from subjectAltNames array for SQL -# IN operator in database query -#------------------------------------------------------------------------------- -sub altNamesFilter -{ - my $alt_names_array_ref = shift; - my @alt_names_array = @$alt_names_array_ref; - - our $CN; - my @an_array; - - push @an_array, $DBH->quote($CN); - my $i = 1; - while ($i <= scalar @alt_names_array) { - push @an_array, $DBH->quote($alt_names_array[$i]); - $i+=2; - } - my $an_filter = join(',', @an_array); - return $an_filter; -} - - - -################################################################################ -# SOAP Functions -################################################################################ - -#----------------------------------------------------------------------------- -# saveNewEvent - save new received event into database -#----------------------------------------------------------------------------- -sub saveNewEvent -{ - my ($class, $data) = @_; - my ($sth, $cidr_list); - - # variables defined by server - our $IP; # IP address of sender - our $CN; # common name of sender - our $AN_FILTER; # alternate names of sender - - my $cn_db = $DBH->quote($CN); - - # variables defined by server - my $client_type = "s"; # incoming client MUST be sender - my $client_type_db = $DBH->quote($client_type); - my $valid = "t"; # registered sender has valid events - my $valid_db = $DBH->quote($valid); - my $received = DateTime->now; # time of event delivery (UTC) - my $received_db = $DBH->quote($received); - - # parse object (event) parameters - my $service = $data->{'SERVICE'}; - my $service_db = $DBH->quote($service); - my $detected = $data->{'DETECTED'}; - my $detected_db = $DBH->quote($detected); - my $type = $data->{'TYPE'}; - my $type_db = $DBH->quote($type); - my $source_type = $data->{'SOURCE_TYPE'}; - my $source_type_db = $DBH->quote($source_type); - my $source = $data->{'SOURCE'}; - my $source_db = $DBH->quote($source); - my $target_proto = $data->{'TARGET_PROTO'}; - my $target_proto_db = $DBH->quote($target_proto); - my $target_port = $data->{'TARGET_PORT'}; - my $target_port_db = $DBH->quote($target_port); - my $attack_scale = $data->{'ATTACK_SCALE'}; - my $attack_scale_db = $DBH->quote($attack_scale); - my $note = $data->{'NOTE'}; - my $note_db = $DBH->quote($note); - my $priority = $data->{'PRIORITY'}; - my $priority_db = $DBH->quote($priority); - my $timeout = $data->{'TIMEOUT'}; - my $timeout_db = $DBH->quote($timeout); - - # Authorization of incomming client - #----------------------------------------------------------------------------- - - # obtain cidr based on rigth common name and alternate names, service and client_type - # $sth = $DBH->prepare("SELECT hostname, ip_net_client FROM clients WHERE hostname IN ($AN_FILTER) AND service = $service_db AND client_type = $client_type_db limit 1;"); - # if ( !defined $sth ) {die("Cannot prepare authorization statement in saveNewEvent: $DBI::errstr\n")} - # $sth->execute; - # my ($an, $cidr) = $sth->fetchrow(); - - # # check if client is registered - # if (!defined $cidr) { - # write2log ("err", "Unauthorized access to saveNewEvent from: $IP (CN: $CN; AN: $an) - client is not registered"); - # die("Access denied - client is not registered at warden server!"); - # } else { - # $cidr_list = Net::CIDR::Lite - # -> new - # -> add($cidr); - # } - - # check if client has IP from registered CIDR - # if (!$cidr_list->bin_find($IP)) { - # write2log ("err", "Unauthorized access to saveNewEvent from: $IP (CN: $CN; AN: $an) - access from bad subnet: $cidr"); - # die("Access denied - access from bad subnet!"); - # } else { -{ - # insert new event - $DBH->do("INSERT INTO events VALUES (null,$cn_db,$service_db,$detected_db,$received_db,$type_db,$source_type_db,$source_db,$target_proto_db,$target_port_db,$attack_scale_db,$note_db,$priority_db,$timeout_db,$valid_db);"); - if ($DBH->err()) {die("Cannot do insert statement in saveNewEvent: $DBI::errstr\n")} - #$DBH->commit(); - - # log last inserted ID - $sth = $DBH->prepare("SELECT last_insert_rowid()"); - if ( !defined $sth ) {die("Cannot prepare last ID statement in saveNewEvent: $DBI::errstr\n")} - $sth->execute; - my $id= $sth->fetchrow(); - write2log ("info", "Stored new event (#$id) from $IP (CN: $CN; AN: )"); - - if (! defined $id) { - write2log ("err", "Event from $IP ($CN) was not save: INSERT INTO events VALUES (null,$cn_db,$service_db,$detected_db,$received_db,$type_db,$source_type_db,$source_db,$target_proto_db,$target_port_db,$attack_scale_db,$note_db,$priority_db,$timeout_db,$valid_db);"); - die("Event was not save at warden server - database return empty ID!"); - } else { - return 1; - } - } -} # END of saveNewEvent - - -#----------------------------------------------------------------------------- -# getNewEvents - get new events from the DB greater than received ID -#----------------------------------------------------------------------------- -sub getNewEvents -{ - my ($class, $data) = @_; - my ($sth, @events, $event, @ids); - my ($id, $hostname, $service, $detected, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout); - - # variables defined by server - our $IP; # IP address of receiver - our $CN; # common name of receiver - our $AN_FILTER; # alternate name of receiver - - my $cn_db = $DBH->quote($CN); - my $client_type = "r"; # incoming client MUST be sender - my $client_type_db = $DBH->quote($client_type); - my $cidr_list; - - # parse SOAP data object - my $requested_type = $data->{'REQUESTED_TYPE'}; - my $requested_type_db = $DBH->quote($requested_type); - my $last_id = $data->{'LAST_ID'}; - my $last_id_db = $DBH->quote($last_id); - - # Authorization of incomming client - #----------------------------------------------------------------------------- - - # obtain cidr based on rigth common name, service and client_type - $sth = $DBH->prepare("SELECT hostname, receive_own_events, ip_net_client FROM clients WHERE hostname IN ($AN_FILTER) AND type = $requested_type_db AND client_type = $client_type_db limit 1;"); - if ( !defined $sth ) {die("Cannot prepare authorization statement in getNewEvents: $DBI::errstr\n")} - $sth->execute; - my ($an, $receive_own_events, $cidr) = $sth->fetchrow(); - - # check if client is registered - if (!defined $cidr) { - write2log ("err", "Unauthorized access to getNewEvents from: $IP (CN: $CN; AN: $an) - client is not registered"); - die("Access denied - client is not registered at warden server!"); - } else { - $cidr_list = Net::CIDR::Lite - -> new - -> add($cidr); - } - - # check if client has IP from registered CIDR - if (!$cidr_list->bin_find($IP)) { - write2log ("err", "Unauthorized access to getNewEvents from: $IP (CN: $CN; AN: $an) - access from bad subnet: $cidr"); - die("Access denied - access from bad subnet!"); - } else { - - # check if client want your own events or not - if ($receive_own_events eq 't') { - $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > $last_id_db AND type = $requested_type_db AND valid = 't' ORDER BY id ASC;"); - } else { - my ($domain) = $CN =~ /([^\.]+\.[^\.]+)$/; - my $domain_db = $DBH->quote("%$domain"); - $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > $last_id_db AND type = $requested_type_db AND valid = 't' AND hostname NOT LIKE $domain_db ORDER BY id ASC;"); - } - if ( !defined $sth ) { die("Cannot prepare statement in getNewEvents: $DBI::errstr\n") } - $sth->execute; - - # parse items of events stored in DB - while (my @result = $sth->fetchrow()) { - $id = $result[0]; - $hostname = $result[1]; - $service = $result[2]; - $detected = $result[3]; - $type = $result[5]; - $source_type = $result[6]; - $source = $result[7]; - $target_proto = $result[8]; - $target_port = $result[9]; - $attack_scale = $result[10]; - $note = $result[11]; - $priority = $result[12]; - $timeout = $result[13]; - - # create SOAP data object - $event = SOAP::Data->name(event => \SOAP::Data->value( - SOAP::Data->name(ID => $id), - SOAP::Data->name(HOSTNAME => $hostname), - SOAP::Data->name(SERVICE => $service), - SOAP::Data->name(DETECTED => $detected), - SOAP::Data->name(TYPE => $type), - SOAP::Data->name(SOURCE_TYPE => $source_type), - SOAP::Data->name(SOURCE => $source), - SOAP::Data->name(TARGET_PROTO => $target_proto), - SOAP::Data->name(TARGET_PORT => $target_port), - SOAP::Data->name(ATTACK_SCALE => $attack_scale), - SOAP::Data->name(NOTE => $note), - SOAP::Data->name(PRIORITY => $priority), - SOAP::Data->name(TIMEOUT => $timeout) - )); - push(@events, $event); - push(@ids, $id); - } - - # log sent ID of events - if (scalar(@events)!=0) { - write2log("info", "Sent events with ID: [@ids] to $IP (CN: $CN; AN: $an)"); - } - return @events; - } -} # END of getNewEvents - - -#----------------------------------------------------------------------------- -# getLastId - get lastest saved event ID -#----------------------------------------------------------------------------- -sub getLastId -{ - my ($class, $arg) = @_; - - my $sth = $DBH->prepare("SELECT max(id) FROM events;"); - if ( !defined $sth ) { die("Cannot prepare statement in getLastId: $DBI::errstr\n") } - $sth->execute; - my $result = $sth->fetchrow(); - return $result; -} # END of getLastID - - -#----------------------------------------------------------------------------- -# registerSender - register new sender -#----------------------------------------------------------------------------- -sub registerSender -{ - my ($class, $data) = @_; - - my $sth; - our $IP; - our $LOCAL_IP; - our $CN; - - if ($LOCAL_IP ne $IP) { - write2log ("err", "Unauthorized access to registerSender from: $IP ($CN) - access allowed only from localhost"); - die("Access denied - access allowed only from localhost!"); - } else { - # defined variables by server - my $client_type = "s"; - my $client_type_db = $DBH->quote($client_type); - my $registered = DateTime->now; - my $registered_db = $DBH->quote($registered); - my $type = "null"; - my $type_db = $DBH->quote($type); - my $receive_own_events = "null"; - my $receive_own_events_db = $DBH->quote($receive_own_events); - - # parse SOAP data oject - my $hostname = $data->{'HOSTNAME'}; - my $hostname_db = $DBH->quote($hostname); - my $requestor = $data->{'REQUESTOR'}; - my $requestor_db = $DBH->quote($requestor); - my $service = $data->{'SERVICE'}; - my $service_db = $DBH->quote($service); - my $description_tags = $data->{'DESCRIPTION_TAGS'}; - my $description_tags_db = $DBH->quote($description_tags); - my $ip_net_client = $data->{'IP_NET_CLIENT'}; - my $ip_net_client_db = $DBH->quote($ip_net_client); - - # check if sender has been already registered - $sth = $DBH->prepare("SELECT registered FROM clients WHERE hostname = $hostname_db AND requestor = $requestor_db AND service = $service_db AND client_type = $client_type_db AND type = $type_db AND receive_own_events = $receive_own_events_db AND description_tags = $description_tags_db AND ip_net_client = $ip_net_client_db;"); - if ( !defined $sth ) {die("Cannot prepare check statement in registerSender: $DBI::errstr\n")} - $sth->execute; - my $result = $sth->fetchrow(); - - # register new sender - if (defined $result) { - write2log ("err", "Attempt to re-register the sender"); - die("Error - sender has already been registered at $result"); - } else { - $DBH->do("INSERT INTO clients VALUES (null,$hostname_db,$registered_db,$requestor_db,$service_db,$client_type_db,$type_db,$receive_own_events_db,$description_tags_db,$ip_net_client_db);"); - if ($DBH->err()) {die("Cannot do statement in registerSender: $DBI::errstr\n")} - $DBH->commit(); - write2log("info", "New sender $hostname (service: $service, cidr: $ip_net_client) was registered"); - return 1; - } - } -} # END of registerSender - - -#----------------------------------------------------------------------------- -# registerReceiver - register new receiver -#----------------------------------------------------------------------------- -sub registerReceiver -{ - my ($class, $data) = @_; - - my $sth; - our $IP; - our $LOCAL_IP; - our $CN; - - if ($LOCAL_IP ne $IP) { - write2log ("err", "Unauthorized access to registerReceiver from: $IP ($CN) - access allowed only from localhost"); - die("Access denied - access allowed only from localhost!"); - } else { - # variables defined by server - my $client_type = "r"; - my $client_type_db = $DBH->quote($client_type); - my $registered = DateTime->now; - my $registered_db = $DBH->quote($registered); - my $service = "null"; - my $service_db = $DBH->quote($service); - my $description_tags = "null"; - my $description_tags_db = $DBH->quote($description_tags); - - # parse SOAP data oject - my $hostname = $data->{'HOSTNAME'}; - my $hostname_db = $DBH->quote($hostname); - my $requestor = $data->{'REQUESTOR'}; - my $requestor_db = $DBH->quote($requestor); - my $type = $data->{'TYPE'}; - my $type_db = $DBH->quote($type); - my $receive_own_events = $data->{'RECEIVE_OWN_EVENTS'}; - my $receive_own_events_db = $DBH->quote($receive_own_events); - my $ip_net_client = $data->{'IP_NET_CLIENT'}; - my $ip_net_client_db = $DBH->quote($ip_net_client); - - # check if receiver has been already registered - $sth = $DBH->prepare("SELECT registered FROM clients WHERE hostname = $hostname_db AND requestor = $requestor_db AND service = $service_db AND client_type = $client_type_db AND type = $type_db AND receive_own_events = $receive_own_events_db AND description_tags = $description_tags_db AND ip_net_client = $ip_net_client_db;"); - if ( !defined $sth ) {die("Cannot prepare check statement in registerReceiver: $DBI::errstr\n")} - $sth->execute; - my $result = $sth->fetchrow(); - - # register new receiver - if (defined $result) { - write2log ("err", "Attempt to re-register the receiver"); - die("Error - receiver has already been registered at $result"); - } else { - $DBH->do("INSERT INTO clients VALUES (null,$hostname_db,$registered_db,$requestor_db,$service_db,$client_type_db,$type_db,$receive_own_events_db,$description_tags_db,$ip_net_client_db);"); - if ($DBH->err()) {die("Cannot do statement in registerReceiver: $DBI::errstr\n")} - $DBH->commit(); - write2log("info", "New receiver $hostname (type: $type, cidr: $ip_net_client: receive_own_events: $receive_own_events) was registered"); - return 1; - } - } -} # END of registerReceiver - - -#----------------------------------------------------------------------------- -# unregisterClient - unregister client -#----------------------------------------------------------------------------- -sub unregisterClient -{ - my ($class, $data) = @_; - - my $sth; - our $IP; - our $LOCAL_IP; - our $CN; - - if ($LOCAL_IP ne $IP) { - write2log ("err", "Unauthorized access to unregisterClients from: $IP ($CN) - access allowed only from localhost"); - die("Access denied - access allowed only from localhost!"); - } else { - # parse SOAP data oject - my $client_id = $data->{'CLIENT_ID'}; - my $client_id_db = $DBH->quote($client_id); - - # check if receiver has been already registered - $sth = $DBH->prepare("SELECT client_id, hostname, service, client_type FROM clients WHERE client_id = $client_id_db;"); - if ( !defined $sth ) {die("Cannot prepare check statement in unregisterClient: $DBI::errstr\n")} - $sth->execute; - my ($id, $hostname, $service, $client_type) = $sth->fetchrow(); - my $hostname_db = $DBH->quote($hostname); - my $service_db = $DBH->quote($service); - - # delete registered client - if (!defined $id) { - write2log ("err", "Attempt to delete unregister client"); - die("Error - client (#$client_id) is not registered"); - } else { - if ($client_type eq 's') { - $DBH->do("DELETE FROM clients WHERE client_id = $client_id_db;"); - if ($DBH->err()) {die("Cannot do delete statement of sender in unregisterClient: $DBI::errstr\n")} - $DBH->commit(); - - $DBH->do("UPDATE events SET valid = 'f' where hostname = $hostname_db AND service = $service_db;"); - if ($DBH->err()) {die("Cannot do unvalidation statement in unregisterClient: $DBI::errstr\n")} - $DBH->commit(); - - write2log("info", "Sender $hostname (client_id: $client_id, service: $service) was deleted and its data were invalidated" ); - return 1; - } else { - $DBH->do("DELETE FROM clients WHERE client_id = $client_id_db;"); - if ($DBH->err()) {die("Cannot do delete statement of receiver in unregisterClient: $DBI::errstr\n")} - $DBH->commit(); - write2log("info", "Receiver $hostname (client_id: $client_id) was deleted" ); - return 1; - } - } - } -} # END of unregisterClient - - -#----------------------------------------------------------------------------- -# getClients - get list of clients which were registered at warden server -#----------------------------------------------------------------------------- -sub getClients -{ - my ($class, $arg) = @_; - - our $IP; - our $LOCAL_IP; - our $CN; - - if ($LOCAL_IP ne $IP) { - write2log ("err", "Unauthorized access to getClients from: $IP ($CN) - access allowed only from localhost"); - die("Access denied - access allowed only from localhost!"); - } else { - my (@clients, $client); - my ($client_id, $hostname, $registered, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); - my $sth = $DBH->prepare("SELECT * FROM clients;"); - if (!defined $sth) { die("Cannot prepare statement in getClients: $DBI::errstr\n") } - $sth->execute; - - while ( my @result = $sth->fetchrow() ) { - $client_id = $result[0]; - $hostname = $result[1]; - $registered = $result[2]; - $requestor = $result[3]; - $service = $result[4]; - $client_type = $result[5]; - $type = $result[6]; - $receive_own_events = $result[7]; - $description_tags = $result[8]; - $ip_net_client = $result[9]; - - $client = SOAP::Data->name(client => \SOAP::Data->value( - SOAP::Data->name(CLIENT_ID => $client_id), - SOAP::Data->name(HOSTNAME => $hostname), - SOAP::Data->name(REGISTERED => $registered), - SOAP::Data->name(REQUESTOR => $requestor), - SOAP::Data->name(SERVICE => $service), - SOAP::Data->name(CLIENT_TYPE => $client_type), - SOAP::Data->name(TYPE => $type), - SOAP::Data->name(RECEIVE_OWN_EVENTS => $receive_own_events), - SOAP::Data->name(DESCRIPTION_TAGS => $description_tags), - SOAP::Data->name(IP_NET_CLIENT => $ip_net_client), - )); - push(@clients, $client); - } - my $sum = scalar @clients; - write2log("info", "Sending information about $sum registered clients"); - return @clients; - } -} # END of getClients - - -#----------------------------------------------------------------------------- -# getStatus - get list of status items of warden server -#----------------------------------------------------------------------------- -sub getStatus -{ - my ($class, $arg) = @_; - - our $IP; - our $LOCAL_IP; - our $CN; - - if ($LOCAL_IP ne $IP) { - write2log ("err", "Unauthorized access to getStatus from: $IP ($CN) - access allowed only from localhost"); - die("Access denied - access allowed only from localhost!"); - } else { - my ($sth, @status); - - # size of database events - my $db_size = Format::Human::Bytes::base10(-s $db); - - # sum of records in table events - $sth = $DBH->prepare("SELECT count(*) FROM events WHERE valid = 't';"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } - $sth->execute; - my $events_sum = $sth->fetchrow(); - if (!defined $events_sum) { $events_sum = "none" } - - # id of last record in table events - $sth = $DBH->prepare("SELECT max(id) FROM events;"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } - $sth->execute; - my $events_last_id = $sth->fetchrow(); - if (!defined $events_last_id) { $events_last_id = "none" } - - # timestamp of first record in table events - $sth = $DBH->prepare("SELECT received FROM events WHERE id = (SELECT min(id) FROM events);"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } - $sth->execute; - my $events_first_timestamp = $sth->fetchrow(); - if (!defined $events_first_timestamp) { $events_first_timestamp = "none" } - - # timestamp of last record in table events - $sth = $DBH->prepare("SELECT received FROM events WHERE id = (SELECT max(id) FROM events);"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } - $sth->execute; - my $events_last_timestamp = $sth->fetchrow(); - if (!defined $events_last_timestamp) { $events_last_timestamp = "none" } - - # sum of records in table clients - $sth = $DBH->prepare("SELECT count(*) FROM clients;"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } - $sth->execute; - my $clients_sum = $sth->fetchrow(); - if (!defined $clients_sum) { $clients_sum = "none" } - - my $server_status = SOAP::Data->name(server_status => \SOAP::Data->value( - SOAP::Data->name(VERSION => $VERSION), - SOAP::Data->name(ADDRESS => $ADDRESS), - SOAP::Data->name(PORT => $PORT), - SOAP::Data->name(LOGDIR => $LOGDIR), - SOAP::Data->name(PIDDIR => $PIDDIR), - SOAP::Data->name(VARDIR => $VARDIR), - SOAP::Data->name(SSL_KEY_FILE => $SSL_KEY_FILE), - SOAP::Data->name(SSL_CERT_FILE => $SSL_CERT_FILE), - SOAP::Data->name(SSL_CA_FILE => $SSL_CA_FILE), - SOAP::Data->name(FACILITY => $FACILITY), - SOAP::Data->name(DB_SIZE => $db_size), - SOAP::Data->name(EVENTS_SUM => $events_sum), - SOAP::Data->name(EVENTS_LAST_ID => $events_last_id), - SOAP::Data->name(EVENTS_FIRST_TIMESTAMP => $events_first_timestamp), - SOAP::Data->name(EVENTS_LAST_TIMESTAMP => $events_last_timestamp), - SOAP::Data->name(CLIENTS_SUM => $clients_sum) - )); - push(@status, $server_status); - - # statistics of senders - if ($clients_sum != 0) { - $sth = $DBH->prepare("SELECT client_id, hostname, service FROM clients WHERE client_type = 's';"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } - $sth->execute; - my ($client_id, $hostname, $service); - my $client_status; - while(($client_id, $hostname, $service) = $sth->fetchrow()) { - my $hostname_db = $DBH->quote($hostname); - my $service_db = $DBH->quote($service); - my $sth2; - # sum of stored events - $sth2 = $DBH->prepare("SELECT count(*) FROM events WHERE hostname = $hostname_db AND service = $service_db;"); - if ( !defined $sth2 ) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } - $sth2->execute; - my $count = $sth2->fetchrow(); - if (!defined $count) {$count = "none"} - # timestamp of last stored event - $sth2 = $DBH->prepare("SELECT max(received) FROM events WHERE hostname = $hostname_db AND service = $service_db;"); - if ( !defined $sth2 ) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } - $sth2->execute; - my $timestamp = $sth2->fetchrow(); - if (!defined $timestamp) { $timestamp = "none" } - # create SOAP data object - $client_status = SOAP::Data->name(client_status => \SOAP::Data->value( - SOAP::Data->name(CLIENT_ID => $client_id), - SOAP::Data->name(HOSTNAME => $hostname), - SOAP::Data->name(SERVICE => $service), - SOAP::Data->name(COUNT => $count), - SOAP::Data->name(TIMESTAMP => $timestamp), - )); - push(@status, $client_status); - } - } - write2log("info", "Sent of warden server status info"); - return @status; - } -} # END of getStatus - - - -################################################################################ -# MAIN warden-server -################################################################################ - -#------------------------------------------------------------------------------- -# Superuser controle -#------------------------------------------------------------------------------- -my $UID = $<; -if ($UID != 0) { - die errMsg("You must be root for running this script!") -} - -#------------------------------------------------------------------------------- -# Daemonize section -#------------------------------------------------------------------------------- -use POSIX qw(setsid); -chdir '/'; -umask 0; -# all STDERR messages are printed on terminal -open STDIN, '/dev/null' or die errMsg("Can't read /dev/null: $!"); -open STDOUT, '/dev/null' or die errMsg("Can't write to /dev/null: $!"); -defined( my $pid = fork ) or die errMsg("Can't fork: $!"); -exit if $pid; - -#------------------------------------------------------------------------------- -# Dissociate this process from the controlling terminal -# that started it and stop being part of whatever -# process group this process was a part of. -#------------------------------------------------------------------------------ -POSIX::setsid() or die errMsg("Can't start a new session."); - -#------------------------------------------------------------------------------- -# Callback signal handler for signals. -#------------------------------------------------------------------------------- -$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signalHandler; -$SIG{PIPE} = 'ignore'; - -#------------------------------------------------------------------------------- -# Create pid file in /var/run/ -#------------------------------------------------------------------------------- -my $pfh = File::Pid->new( { file => $pid_file, } ); -$pfh->write or die errMsg("Can't write PID file $pid_file: $!"); -my $pid_number = $pfh->pid; - -#------------------------------------------------------------------------------- -# Starting of Warden server -#------------------------------------------------------------------------------- -write2log("info", "Starting WARDEN server daemon with pid $pid_number"); - -# log of warden database size -my $db_size_human = Format::Human::Bytes::base10(-s $db); -write2log("info", "Size of DB file ($db_file) is: $db_size_human"); - -# start TCP server -my $server = SOAP::Transport::TCP::Server - ->new( - Listen => 20, - LocalAddr => $ADDRESS, - LocalPort => $PORT, - Proto => "tcp", - ReuseAddr => 1, - SSL_verify_mode => 0x02, - SSL_use_cert => 1, - SSL_server => 1, - SSL_key_file => $SSL_KEY_FILE, - SSL_cert_file => $SSL_CERT_FILE, - SSL_ca_file => $SSL_CA_FILE, - SSL_error_trap =>\&sslErrorHandler, - ); - -# check if socket exist -$server or die errMsg("Socket error: $!"); - -# start SOAP server -my $soap = SOAP::Server - ->new() - ->dispatch_to('Warden'); - - -#------------------------------------------------------------------------------- -# Process of incoming client's requests and send response -#------------------------------------------------------------------------------- -write2log("info", "Starting TCP and SOAP server at $ADDRESS:$PORT"); -while ($die_now != 1) -{ - my $socket = $server->accept(); - next if (!$socket); - - our $CN = $socket->peer_certificate("cn"); - my @alt_names_array = $socket->peer_certificate("subjectAltNames"); - our $AN_FILTER = altNamesFilter(\@alt_names_array); - our $IP = $socket->peerhost; - our $LOCAL_IP = $socket->sockhost; - - # read input serialized SOAP envelope and data - my ($request, $buf); - while (defined($buf = <$socket>)) - { - $request .= $buf; - } - - # handle of called server function from client and send response to client - my $response = $soap->handle($request); - print $socket $response; - - $socket->close; - undef($socket); - undef($CN); - undef($AN_FILTER); - undef($IP); - undef($LOCAL_IP); -} - - - -################################################################################ -# Cleanup section -################################################################################ -END { - if ($die_now == 1) - { - my $pid = trim(`cat $pid_file`); - write2log("info", "Stopping WARDEN server daemon with pid $pid"); - - # close connection to DB - $DBH->disconnect(); - - # remove pid file - $pfh->remove if defined $pfh; - } -} diff --git a/src/warden-server/bin/wardenWatchdog.pl b/src/warden-server/bin/wardenWatchdog.pl new file mode 100755 index 0000000000000000000000000000000000000000..001a16957509ec689862e8e757fddb1a9f6410fa --- /dev/null +++ b/src/warden-server/bin/wardenWatchdog.pl @@ -0,0 +1,271 @@ +#!/usr/bin/perl +# +# WardenWatchdog.pl +# +# Copyright (C) 2011-2012 Cesnet z.s.p.o +# +# Use of this source is governed by a BSD-style license, see LICENSE file. + + +#use WardenConf; +use strict; +use warnings; +use DBI; +use DBD::mysql; +use DateTime; +use Email::Simple; +use Sys::Hostname; +use Data::Dumper; + +sub sendmail_wrapper{ + my $message = shift; + if(open(my $sendmail, '|/usr/sbin/sendmail -oi -t')){ + print $sendmail $message; + close $sendmail; + return 1; + } else { + return (0, "Sending email failed: $!"); + } +} + +# Array of hashes +#{query => ; text => ; contact => } + +sub send_report{ + + my $input_data = shift; + my $contact = $$input_data{'contact'}; + my $domain = $$input_data{'domain'}; + my $text = $$input_data{'text'}; + + my $from_hostname; + my $message; + + if(!($contact)){ + return (0, "Empty 'To' email header!\n"); + } + + $domain =~ s/\./\./; + eval{ + $from_hostname = hostname(); + if(!($from_hostname =~ m/^$domain$/gi)){ + $from_hostname = $domain; + } + 1; + } or do { + return (0, "Can't retrive hostname for 'From' header!\n"); + }; + + eval{ + $message = Email::Simple->create( + header => [ + To => $contact, + From => 'warden_watchdog@'.$from_hostname, + Subject => "Kotrola stavu udalosti warden serveru na stroji $domain"], + body => $text); + } or do { + return (0, "Can't create email message\n"); + }; + + my ($rc, $err) = sendmail_wrapper($message->as_string); + if(!$rc){ + return (0, $err); + } + return 1; +} + +sub connect_to_DB { + + my $dbPlatform = 'mysql'; + my $dbName = 'warden'; + my $dbHostname = 'localhost'; + my $dbUser = 'root'; + my $dbPasswd = 'w4rd3n&r00t'; + + my $dbhRef = shift; + my $dbh; + + if($dbh = DBI->connect( "dbi:$dbPlatform:database=$dbName;host=$dbHostname", $dbUser, $dbPasswd, {RaiseError => 1, mysql_auto_reconnect => 1})){ + $$dbhRef = $dbh; + return 1; + } + else{ + return (0,"Cannot connect to database! ".DBI->errstr); + } +} + + +sub update_procedures{ + + my $procRef = shift; + + my @procedures = @{$procRef}; + my $dbh; + + # connect to DB + my ($rc,$err) = connect_to_DB(\$dbh); + if (!$rc){ + return (0,'update_procedures can\'t connect do DB: '.$err); + } + + foreach my $proc (@procedures) { + $dbh->do($proc); + } + + # disconnect to DB + $dbh->disconnect; + + return 1; +} + + +sub send_query{ + + my $configRef = shift; + my $eventsRef = shift; + + my @config = @{$configRef}; + my %bad_events; + my ($rc,$err); + my $dbh; + + my $i = 0; + # connect to DB + ($rc,$err) = connect_to_DB(\$dbh); + if (!$rc){ + return (0,'send_query can\'t connect do DB: '.$err); + } + + while ($i < scalar(@config)) { + # run DB query -> requestor, client name + my $sth; + if (defined($config[$i]{query})){ + $sth = $dbh->prepare($config[$i]{query}); + } + else{ + return (0, "No query availble\n"); + } + + if (!($sth->execute)){ + return (0, "Couldn't get data from my database: $sth->errstr\n"); + }; + + my @result; + my $contact; + my $msg_text = 1; + while(@result = $sth->fetchrow()){ + if (defined($config[$i]{contact})){ + $contact = $config[$i]{contact}; + if($msg_text){ + $bad_events{$contact} .= $config[$i]{text} . "\n\n"; + $msg_text = 0; + } + $bad_events{$contact} .= join(", ",@result) . "\n"; + } + else{ + $contact = "from_db\@$result[0]"; + $bad_events{$contact} .= $config[$i]{text} . "\n\n"; + $bad_events{$contact} .= join(", ",@result) . "\n"; + } + } + foreach my $key (keys %bad_events){ + $bad_events{$key} .= "\n\n"; + } + + $sth->finish; + $i++; + } + # disconnect to DB + $dbh->disconnect; + + %$eventsRef = %bad_events; + + return 1; +} + + +sub run{ + + my $domain = shift; + my $period = shift; + + my $date; + + eval{ + my $dt = DateTime->now(); + $dt = DateTime->now()->subtract(days => $period); + $date = $dt->date(); + } or do { + #print "Warden watchdog - can't work with date\n"; + syslog("err|Warden watchdog - can't work with date\n"); + }; + + # stored procedures + # iptest - is ip from private network + + my @procedures = ('DROP FUNCTION IF EXISTS iptest;', 'CREATE FUNCTION iptest(ip VARCHAR(15)) RETURNS TINYINT(1) DETERMINISTIC +BEGIN + SET @nip = INET_ATON(ip); + IF( + ISNULL( @nip) OR + @nip BETWEEN 0 AND 16777216 OR + @nip BETWEEN 167772160 AND 171966464 OR + @nip BETWEEN 2130706432 AND 2130706433 OR + @nip BETWEEN 2851995648 AND 2851995649 OR + @nip BETWEEN 2886729728 AND 2886729729 OR + @nip BETWEEN 3221225472 AND 3221225473 OR + @nip BETWEEN 3221225984 AND 3221225985 OR + @nip BETWEEN 3227017984 AND 3227017985 OR + @nip BETWEEN 3232235520 AND 3232235521 OR + @nip BETWEEN 3323068416 AND 3323068417 OR + @nip BETWEEN 3325256704 AND 3325256705 OR + @nip BETWEEN 3405803776 AND 3405803777 OR + @nip BETWEEN 3758096384 AND 3758096385 OR + @nip BETWEEN 4026531840 AND 4026531841 OR + @nip > 4294967295) THEN + RETURN TRUE; + ELSE + RETURN FALSE; + END IF; +END;'); + + # {query => ; text => ; contact => } + # Time of last event of each client. + # Is it unsupported type of event? + # Is event from the future? + # Martane - Is IP from the private network? + my @configuration = ( + {query => "SELECT hostname, service, MAX(received) FROM events WHERE valid = 't' GROUP BY hostname, service ORDER BY MAX(received) ASC;", text => "Uvedeny klient, nebo klienti jiz delsi dobu nereportovali zadne udalosti do Wardenu. Je mozne, ze nefunguji spravne.", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'}, + {query => "SELECT requestor FROM clients WHERE service IN (SELECT service FROM events WHERE detected > '$date' AND type NOT IN ('portscan', 'bruteforce', 'probe', 'spam', 'phishing', 'botnet_c_c', 'dos', 'malware', 'copyright', 'webattack', 'test', 'other') AND valid = 't' GROUP BY service) GROUP BY requestor;", text => "Uvedeny klient, nebo klienti zasilaji nepodporovany nebo zastaraly typ udalosti na server Warden", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'}, + {query => "SELECT hostname, service, type, COUNT(*) FROM events WHERE detected - received > 0 AND received > '$date' GROUP BY hostname, service, type;", text => "Uvedeny klient, nebo klienti odesilaji odesilaji udalosti s casem z budoucnosti. Cas prirazeny serverem pri prichodu udalosti (received) musi byt vzdy roven nebo vetsi casu detekce (detected).", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'}, + {query => "SELECT hostname, service, received, source, count(source) AS c, min(received), max(received) FROM events WHERE valid = 't' AND source_type = 'IP' AND iptest(source) GROUP BY hostname, service, source ORDER BY c DESC;", text => "Uvedeni klient, nebo klienti odesilaji udalosti se zdrojovou adresou, ktera by se nemela objevit v internetu (privatni rozsah), nebo je neplatna (prazdny oktet, oktet je vetsi nez 255, apod.). kvuli omezeni verzi MySQL serveru funguje zatim pouze pro IPv6.", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'}); + + my ($rc,$err) = update_procedures(\@procedures); + if (!$rc){ + #print "Warden watchdog - $err\n"; + syslog("err|Warden watchdog - $err\n"); + } + + my %bad_events; + my $i = 0; + while ($i < scalar(@configuration)) { + my ($rc,$err) = send_query(\@configuration,\%bad_events); + if (!$rc){ + #print "Warden watchdog - $err\n"; + syslog("err|Warden watchdog - $err\n"); + } + $i++; + } + + while (my ($contact, $text) = each(%bad_events)){ + my %input = (contact => $contact, domain => $domain, text => $text); + my ($rc,$err) = send_report(\%input); + if (!$rc){ + #print $err; + syslog("err|Warden client - networkReporter $err\n"); + } + } +} + +run('warden-dev.cesnet.cz',7); +1; diff --git a/src/warden-server/bin/wardend b/src/warden-server/bin/wardend deleted file mode 100755 index ffd4a3b61c3d157bfba6ceced71d2198dad06d9b..0000000000000000000000000000000000000000 --- a/src/warden-server/bin/wardend +++ /dev/null @@ -1,159 +0,0 @@ -#!/bin/bash - -# Pri pouziti Apache + mod_perl se tento soubor nepouziva - -# -# wardend -# -# Copyright (C) 2011-2012 Cesnet z.s.p.o -# Author(s): Tomas PLESNIK <plesnik@ics.muni.cz> -# Jan SOUKAL <soukal@ics.muni.cz> -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name of the Cesnet z.s.p.o 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 any express or implied -# warranties, including, but not limited to, the implied warranties of -# merchantability and fitness for a particular purpose are disclaimed. -# In no event shall the Cesnet z.s.p.o or contributors be liable for -# any direct, indirect, incidental, special, exemplary, or consequential -# damages (including, but not limited to, procurement of substitute -# goods or services; loss of use, data, or profits; or business -# interruption) however caused and on any theory of liability, whether -# in contract, strict liability, or tort (including negligence or -# otherwise) arising in any way out of the use of this software, even -# if advised of the possibility of such damage. - -### BEGIN INIT INFO -# Provides: wardend -# Required-Start: $local_fs $network $syslog $time -# Required-Stop: $local_fs $syslog $time -# Default-Start: 2 3 4 5 -# Default-Stop: -# Short-Description: Start the Warden server -# Description: Starts or stops server for exchange of events -# among CSIRT teams -### END INIT INFO - -VERSION="0.2" - -DAEMON="/usr/local/bin/warden-server.pl" -PID_FILE="/var/run/warden-server.pl.pid" -LOCK_FILE="/var/lock/warden-server" -SCRIPTNAME=`basename "$0"` - -# check if daemon is present and executable -test -x $DAEMON || exit 0 - -if [ $UID -ne 0 ]; then - echo "You must be root for runnnig this script!" - exit 1 -fi - -usage() { - echo "Usage: $0 [start|stop|status|restart|force-stop]" - exit 1 -} - -check_status() { - if /bin/ps axo pid,comm | grep -q "warden-serv*"; then - STATUS=1 # true - warden is running - else - STATUS=0 # false - warden is not running - fi -} - -get_pid() { - PID=`ps axo pid,comm | grep "warden-serv*" | sed 's/^ \{1,4\}//g' | cut -f 1 -d " "` - return $PID -} - -warden_start() { - check_status - if [ $STATUS -eq 1 ]; then - get_pid PID - echo "Warden server daemon is running (pid $PID)." - else - logger -s "Starting Warden server daemon ..." - $DAEMON - PID=`cat $PID_FILE` - logger -s "Warden server daemon is running (pid $PID)." - touch $LOCK_FILE - fi -} - -warden_stop() { - check_status - if [ $STATUS -eq 1 ]; then - logger -s "Stopping Warden server daemon ..." - if [ -e $PID_FILE ]; then - PID=`cat $PID_FILE` - kill -1 $PID - rm -f $LOCK_FILE - logger -s "Warden server daemon (pid $PID) is stopped." - else - echo "Unable to stop Warden server daemon. Try to use: $SCRIPTNAME force-stop" - fi - else - echo "Warden daemon is NOT running." - fi -} - -warden_status() { - check_status - if [ $STATUS -eq 1 ]; then - get_pid PID - echo "Warden daemon is running (pid $PID)." - exit 0 - else - echo "Warden daemon is NOT running." - exit 1 - fi -} - -warden_force_stop() { - logger -s "Force stopping Warden server daemon ..." - get_pid PID - kill -9 $PID 1>/dev/null 2>&1 - if [ -e $PID_FILE ]; then - rm -f $PID_FILE - fi - if [ -e $LOCK_FILE ]; then - rm -f $LOCK_FILE - fi -} - -case $1 in - status) - warden_status - ;; - start) - warden_start - ;; - stop) - warden_stop - ;; - force-stop) - warden_force_stop - ;; - restart) - $0 stop - sleep 1 - $0 start - ;; - *) - usage - ;; -esac - -exit 0 diff --git a/src/warden-server/doc/AUTHORS b/src/warden-server/doc/AUTHORS index dc439cbfa32b7859975d91970a955506f0441c3c..836f0d9a222692f572df8525bc3abed999f9cd0d 100644 --- a/src/warden-server/doc/AUTHORS +++ b/src/warden-server/doc/AUTHORS @@ -1,23 +1,25 @@ AUTHORS AND MAINTAINERS : -MAIN DEVELOPERS: -Tomas Plesnik <plesnik@ics.muni.cz> -Jan Soukal <soukal@ics.muni.cz> -Michal Kostenec <kostenec@civ.zcu.cz> +PROJECT ARCHITECTS: +Pavel Kacha <ph@cesnet.cz> +Andrea Kropacova <andrea@cesnet.cz> +Jan Vykopal <vykopal@cesnet.cz> -CONTRIBUTORS: -Vit Slama <slama@cis.vutbr.cz> -Martin Drasar <drasar@ics.muni.cz> +MAIN DEVELOPERS: +Michal Kostenec <kostenec@cesnet.cz> +Tomas Plesnik <plesnik@cesnet.cz> +Jan Soukal <soukal@cesnet.cz> TESTING: -Jakub Cegan <cegan@ics.muni.cz> +Jakub Cegan <jakubcegan@cesnet.cz> -DEVELOPMENT MANAGER: -Jan Vykopal <vykopal@ics.muni.cz> - -PROJECT MANAGERS: -Pavel Kacha <ph@cesnet.cz> -Andrea Kropacova <andrea@cesnet.cz> +CONTRIBUTORS: +Radoslav Bodo <bodik@civ.zcu.cz> +Martin Drasar <drasar@ics.muni.cz> +Vit Slama <slama@cis.vutbr.cz> COMMUNITY: -Radomir Orkac <orkac@cesnet.cz> +Radomir Orkac <orkac@cesnet.cz> +Daniel Studeny <Daniel.Studeny@cesnet.cz> +Pavel Vachek <Pavel.Vachek@cesnet.cz> +Martin Zadnik <izadnik@fit.vutbr.cz> diff --git a/src/warden-server/doc/CHANGELOG b/src/warden-server/doc/CHANGELOG index 0b5b6725f4eb66785d24242b5dcbd1647b027fe9..d44a5d70b617e9c6d01b911f06abb1fb6aacab02 100644 --- a/src/warden-server/doc/CHANGELOG +++ b/src/warden-server/doc/CHANGELOG @@ -1,3 +1,33 @@ +2012-11-16 v2.1 stable version +------------------------------ +- fixed bug in default value of database timestamp type (#576, #577) +- fixed bug in getStatus function (#566) +- fixed bug in re-registration check of client (#541) +- added Syslog logging support (#578) +- added update process (#573) +- added server limit of maximum number of events that can be (#526) + delivered to one client in one batch +- added validation of received events parameters (#524) +- server can provide clients with events disregarding event (#523) + type +- added verbose logging option (stack info) (#521) +- enhanced call of database error function (#549) +- enhanced response time of getStatus function (#546) +- enhanced server logging/warning function (#534) +- enhanced reading of configuration files (#533) +- other minor bugs and issues fixed + + +2012-07-27 v2.0 stable version +------------------------------ +- MySQL database engine used +- Apache used to support faster multithread processing (communication switched to HTTPs protocol) +- enhanced support of Alternate Names in SSL certificates (#505) +- added automatic reconnect to DB (#494) +- enhanced authentization and authorization (#495) +- other minor bugs and issues fixed + + 2012-03-02 v0.1.0 beta version ------------------------------ - initial release of the Warden server diff --git a/src/warden-server/doc/INSTALL b/src/warden-server/doc/INSTALL index 33a79427a858ea9718ffbced6bc560a875fc4beb..dcd5cf607eb0f56d77f2dec542a4365dc44d31f0 100644 --- a/src/warden-server/doc/INSTALL +++ b/src/warden-server/doc/INSTALL @@ -1,5 +1,17 @@ Installation process --------------------- +==================== + +Content + + A. Overview + B. Pre-installation step + C. Installation step + D. Post-installation steps + +-------------------------------------------------------------------------------- + +A. Overview +----------- For installation of warden-server package on local machine use install.sh. @@ -10,13 +22,80 @@ For more information about install.sh options run install.sh -h. You must be root for running this script. -Uninstallation process ----------------------- +B. Pre-installation step +------------------------ -For uninstallation of warden-server package from local machine use uninstall.sh. - -Default uninstallation directory is /opt/warden-server/. - -For more information about uninstall.sh options run uninstall.sh -h. +1) Install necessary packages + + # aptitude install apache2 mysql-server libapache2-mod-perl2 apache2-mpm-prefork -You must be root for running this script. + +C. Installation step +-------------------- + +1) Install Warden server package + + # ./warden-server-2.1/install.sh -d /opt -k /etc/ssl/private/server.key -c /etc/ssl/certs/server.pem -a /etc/ssl/certs/bundle.pem + + +D. Post-installation steps +-------------------------- + +1) Enable of mod_ssl module + + # a2enmod ssl + + +2) Apache server configuration + + a) VirtualHost section configuration + + - include parameters from the Warden server configuration file (<warden-server_path>/etc/warden-apache.conf) + + # vim /etc/apache2/sites-enables/default(-ssl) + + <VirtualHost *:443> + ... + + Include /opt/warden-server/etc/warden-apache.conf + </VirtualHost> + + + b) Apache server performance configuration + + # vim /etc/apache2/apache2.conf + + - prefork module settings + + <IfModule mpm_prefork_module> + StartServers 2 + MinSpareServers 4 + MaxSpareServers 8 + ServerLimit 700 + MaxClients 700 + MaxRequestsPerChild 0 + </IfModule> + + - connection settings + + Timeout 10 + KeepAlive Off + + +3) MySQL database configuration + + a) Create new user acount (optional) + + b) Create new database structure + + $ mysql -u <user> -h localhost -p < {warden-server_path}/doc/warden.mysql + + +4) Warden server configuration + + - configure warden-server.conf, warden-client.conf and warden-apache.conf placed in <warden-server_path>/etc directory + + +5) Restart of Apache server + + # /etc/init.d/apache2 restart diff --git a/src/warden-server/doc/README b/src/warden-server/doc/README index 4f395dccebfcfc7d67da289b37d598825c08091c..c50005d6ed9b7a355dffe0a42746a89971ea6734 100644 --- a/src/warden-server/doc/README +++ b/src/warden-server/doc/README @@ -1,15 +1,17 @@ -+------------------------------+ -| README - Warden Server 0.1.0 | -+------------------------------+ ++----------------------------+ +| README - Warden Server 2.1 | ++----------------------------+ Content A. Overall Information B. Installation Dependencies C. Installation - D. Miscellaneous - E. Registration of Clients - F. Status Info + D. Update + E. Uninstallation + F. Miscellaneous + G. Registration of Clients + H. Status Info -------------------------------------------------------------------------------- A. Overall Information @@ -23,87 +25,109 @@ A. Overall Information 2. Version - 0.1.0 (2012-03-02) + 2.1 (2012-11-16) 3. Package structure warden-server/ bin/ - create_tables.sh getClients.pl getStatus.pl + getWebStatus.sh registerReceiver.pl registerSender.pl unregisterClients.pl - warden-alive - wardend - warden-server.pl doc/ + AUTHORS CHANGELOG INSTALL LICENSE README + UNINSTALL + UPDATE + warden.mysql + warden20to21.patch etc/ + package_version + warden-apache.conf warden-client.conf warden-server.conf - package_version lib/ WardenConf.pm + Warden.pm WardenReg.pm WardenStatus.pm - var/ - warden.db + Warden/ + ApacheDispatch.pm uninstall.sh + -------------------------------------------------------------------------------- B. Installation Dependencies 1. Applications: Perl >= 5.10.1 - SQLite >= 3.7.3 + MySQL >= 5.1.63 + Apache >= 2.2.14 2. Perl modules: SOAP::Lite >= 0.712 - SOAP::Transport::TCP >= 0.712 - File::Pid >= 1.01 - POSIX >= 1.17 + SOAP::Transport::HTTP >= 0.712 DBI >= 1.612 - DBD::SQLite >= 1.29 + DBD::mysql >= 4.016 Format::Human::Bytes >= 0.05 Sys::Syslog >= 0.27 File::Basename >= 2.77 - FindBin >= 1.50 Net::CIDR::Lite >= 0.21 DateTime >= 0.61 Getopt::Std >= 1.06 Switch >= 2.14 - IO::Socket::SSL >= 1.33 + IO::Socket::SSL >= 1.66 + MIME::Base64 >= 3.08 + Crypt::X509 >= 0.40 + Carp >= 1.11 + -------------------------------------------------------------------------------- C. Installation 1. Check SHA1 checksum of the Warden server package archive. - $ sha1sum -c warden-server-0.1.0.tar.gz.sig + $ sha1sum -c warden-server-2.1.tar.gz.sig 2. Untar it. - $ tar xzvf warden-server-0.1.0.tar.gz + $ tar xzvf warden-server-2.1.tar.gz 3. Run install.sh. - Default destination directory is /opt/warden-server/ + Default installation directory is /opt/warden-server/ For more information about install.sh options run install.sh -h + Usage: $ ./install.sh [-d <directory>] [-k <ssl_key_file>] + [-c <ssl_cert_file>] [-a <ssl_ca_file>] [-hV]" + -d <directory> installation directory (default: /opt) + -k <ssl_key_file> SSL certificate key file path + -c <ssl_cert_file> SSL certificate file path + -a <ssl_ca_file> CA certificate file path + -h print this help + -V print script version number and exit + + Example: # ./install.sh -d /opt -k /etc/ssl/private/server.key + -c /etc/ssl/certs/server.pem + -a /etc/ssl/certs/bundle.pem + You must be root for running this script. 4. Configuration files - You are advised to check configuration file warden-server.conf and - warden-client.conf in warden-server/etc/ directory after installation. + You are advised to check configuration file warden-apache.conf, + warden-server.conf and warden-client.conf in warden-server/etc/ + directory after installation. For more information about post-installation + steps see INSTALL file in 'doc' directory. Although this is the Warden server package it also contains several functions (for administration and maintenance) that are strictly @@ -133,108 +157,141 @@ C. Installation SSL_CA_FILE - path to a CA file e.g. '/etc/ssl/certs/tcs-ca-bundle.pem' - b) warden-server.conf + + b) warden-server.conf: The Warden server configuration file contains: - ADDRESS - IP address/domain name of the Warden server - e.g. warden.server.com + BASEDIR - base directory of the Warden server + e.g. /opt/warden-server/ - PORT - used TCP port for the Warden server - e.g. 443 + SYSLOG - enable/disable syslog logging + e.g. 1 - BASEDIR - base directory of the Warden server - e.g. /opt/warden-server/ + SYSLOG_VERBOSE - enable/disable logging in verbose mode (stack info added) + e.g. 1 - VARDIR - var directory - e.g. $BASEDIR/var/ + SYSLOG_FACILITY - syslog facility + e.g. local7 - LOGDIR - logging directory - e.g. /var/log/ - - PIDDIR - Process ID directory - e.g. /var/run/ + DB_NAME - MySQL database name of Warden server + e.g. warden - SSL_KEY_FILE - path to the server SSL certificate key file - e.g. /etc/ssl/private/warden.server.com.key + DB_USER - MySQL database user of Warden server + e.g. warden - SSL_CERT_FILE - path to the server SSL certificate file - e.g. /etc/ssl/certs/warden.server.com.pem - - SSL_CA_FILE - path to a CA certificate file - e.g. /etc/ssl/certs/tcs-ca-bundle.pem + DB_PASS - MySQL database password of Warden server - FACILITY - syslog facility - e.g. local7 + DB_HOST - MySQL database host + e.g. localhost - 5. Usage of install.sh + MAX_EVENTS_LIMIT - server limit of maximum number of events that can be + delivered to one client in one batch + e.g. 1000000 - Usage: $ ./install.sh [-d <directory>] [-k <ssl_key_file>] - [-c <ssl_cert_file>] [-a <ssl_ca_file>] [-hV]" - -d <directory> installation directory (default: /opt) - -k <ssl_key_file> SSL certificate key file path - -c <ssl_cert_file> SSL certificate file path - -a <ssl_ca_file> CA certificate file path - -h print this help - -V print script version number and exit - - Example: $ ./install.sh -d /opt -k /etc/ssl/private/server.key - -c /etc/ssl/certs/server.pem - -a /etc/ssl/certs/bundle.pem + VALID_STRINGS - validation hash containing allowed event attributes + e.g. - 6. Usage of uninstall.sh + %VALID_STRINGS = ( + 'type' => ['portscan', 'bruteforce', 'probe', 'spam', 'phishing', 'botnet_c_c', 'dos', 'malware', 'copyright', 'webattack', 'test', 'other'], + 'source_type' => ['IP', 'URL', 'Reply-To:'] + ); - Usage: $ ./uninstall.sh [-d <directory>] [-hV] - -d <directory> uninstallation directory (default: /opt) + + c) warden-apache.conf + + The Apache2 configuration file for Warden server: + + SSLEngine on + + SSLVerifyDepth 3 + SSLVerifyClient require + SSLOptions +StdEnvVars +ExportCertData + + SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL + + SSLCertificateFile <path_to_server_certificate> + SSLCertificateKeyFile <path_to_server_certificate_key> + SSLCACertificateFile <path_to_CA_certificate> + + PerlOptions +Parent + PerlSwitches -I <path_to_warden_server_libs> + + <Location /Warden> + SetHandler perl-script + PerlHandler Warden::ApacheDispatch + SSLOptions +StdEnvVars + </Location> + + +-------------------------------------------------------------------------------- +D. Update + +For update of the Warden server package from local machine use update.sh. + + Default destination directory is /opt/warden-server/. + + For more information about update.sh options run update.sh -h + + Usage: $ ./update.sh [-d <directory>] [-hV] + -d <directory> destination directory (default: /opt) -h print this help -V print script version number and exit - Example: # ./uninstall.sh -d /opt - + Example: # ./update.sh -d /opt + + You must be root for running this script. + + For more information about post-update steps see UPDATE file in 'doc' + directory. + + -------------------------------------------------------------------------------- -D. Miscellaneous +E. Uninstallation - 1. Error Messages + For uninstallation of the Warden server package from local machine use uninstall.sh. + + Default uninstallation directory is /opt/warden-server/. - Error messages of the server functions are sent via Syslog to log file, - default is /var/log/messages. + For more information about uninstall.sh options run uninstall.sh -h - During installation, until Syslog reporting is initiated, error - messages may be reported to the standard error output instead. - - 2. Init Script + Usage: $ ./uninstall.sh [-d <directory>] [-hV] + -d <directory> uninstallation directory (default: /opt) + -h print this help + -V print script version number and exit - Usage: /etc/init.d/wardend [start|stop|status|restart|force-stop] + Example: # ./uninstall.sh -d /opt - The PID of the Warden server process is stored in - /var/run/warden-server.pl.pid. + You must be root for running this script. - The lock file is placed in /var/lock/warden-server. + For more information about post-uninstallation steps see UNINSTALL file in 'doc' + directory. - To start the Warden server after rebooting, set init script - /etc/init.d/wardend to runlevels configuration system. - 3. Nagios Integration +-------------------------------------------------------------------------------- +F. Miscellaneous - Nagios check is available via Nagios plugin located in - /opt/warden-server/bin/warden-alive. + 1. Error Messages + + Error messages of the server functions are sent via Syslog. + Default is local7 facility. - 4. Firewall Settings + 2. Firewall Settings - Make sure that the TCP port listed in warden-server.conf ($PORT variable) + Make sure that the TCP port listed in /etc/apache2/sites-enables/default(-ssl) is allowed on your firewall. - 5. Privileges + 3. Privileges The Warden server runs only under root privileges. - 6. Known Issues + 4. Known Issues + + No issues are known. - Benchmarking of the Warden system showed that the system is capable of - sending/receiving about 4 events per second. -------------------------------------------------------------------------------- -E. Registration of Clients +G. Registration of Clients The Warden server administrator is responsible for registering new clients or removing those already registered. Both registration or unregistration scripts @@ -273,8 +330,8 @@ E. Registration of Clients hostname - hostname of the client, requestor - organization or authorized person who demands new client registration, - type - the type of events the client wish to receive (only - this and nothing else), + type - the type of events the client wish to receive or '_any_' + for receiving of all types of events, receive_own_events - boolean value describing if events originating from the same CIDR will be sent to the client, ip_net_client - CIDR the client is only allowed to communicate from. @@ -298,7 +355,7 @@ E. Registration of Clients deleted, they are merely set 'invalid' in DB table events. -------------------------------------------------------------------------------- -F. Status Info +H. Status Info Functions in this section show status of the Warden server and active (registered) clients to the Warden system administrator. @@ -310,7 +367,8 @@ F. Status Info 1. Get Status Function getStatus is accessible via getStatus.pl. Function has no input - parameters and returns info about the Warden server and its DB status. + parameters and returns info about the Warden server, its DB status and + event's statistics of active registered senders. 2. Get Clients diff --git a/src/warden-server/doc/README.warden-apache b/src/warden-server/doc/README.warden-apache deleted file mode 100644 index 9f3647a2d266bbf560912def591a3d7584501eb5..0000000000000000000000000000000000000000 --- a/src/warden-server/doc/README.warden-apache +++ /dev/null @@ -1,91 +0,0 @@ -Strucny technicky navod pro preklopeni Warden serveru pod Apache a mod_perl -=========================================================================== - -INSTALACE -========= - -1) Instalace Apache a MySQL DB - - aptitude install apache2 mysql-server - -2) Povoleni mod_ssl - - an2enmod ssl - -3) Instalace knihovny mod_perl - - libapache2-mod-perl2 - -4) Instalace podpory metody prefork pro Apache - - apache2-mpm-prefork - -5) Instalace nove pridanych modulu - - aptitude install libcrypt-x509-perl libmime-base64-perl - - -KONFIGURACE -=========== - -1) Nastaveni APACHE - - a) /etc/apache2/sites-enables/default - - konfigurace sekce <VirtualHost *:443> - - includovani potrebnych parametru ze souboru {warden-server}/etc/warden-apache.conf - Include /opt/warden-server/etc/warden-apache.conf - - b) Nastaveni vykonovych parametru Apache (/etc/apache2/apache2.conf) - - modul prefork (nastavujte dle vykonu vaseho serveru) - = pro 12C, 16GB RAM funguje dobre - - <IfModule mpm_prefork_module> - StartServers 2 - MinSpareServers 4 - MaxSpareServers 8 - ServerLimit 700 - MaxClients 700 - MaxRequestsPerChild 0 - </IfModule> - - - - parametry spojeni - - Timeout 10 - KeepAlive Off - - - c) restartovani Apache po kazde zmene Warden.pm (serverova cast) - - -2) Nastaveni DB - - a) (volitelne) Vytvoreni noveho uzivatele - b) Vytvoreni databazove struktury - - mysql -u uzivatel -p heslo < {warden-server}/doc/warden.mysql - -3) Nastaveni warden-server.conf, warden-client.conf, {warden-server}/etc/warden-apache.conf - - a) Zkontrolovat spravnost IP adres, portu a hlavne cest k certifikatum + nove udaje pro pripojeni do DB - b) Pro klienta a server na jednom stroji jsou zrejme treba 2 ruzne certifikaty (me to jinak nejde, zkuste;)) - - Tato chyba se vypisuje pri problemu s certifikaty (chybna adresa serveru, chybne cesty pro certifikat, stejny certifikat pro klienta a server) - - DEBUG: .../IO/Socket/SSL.pm:420: fatal SSL error: SSL connect attempt failed with unknown errorerror:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed not well-formed (invalid token) at line 1, column 3, byte 3 at /usr/lib/perl5/XML/Parser.pm line 187 - - -SLEDOVATKO -========== - - Pro sledovani stavu Apache, poctu prijatych udalosti, poctu klientu lze pouzit sledovatko - {warden-server}/bin/getWebStatus.sh - - - - - - - - - diff --git a/src/warden-server/doc/UNINSTALL b/src/warden-server/doc/UNINSTALL new file mode 100644 index 0000000000000000000000000000000000000000..d9a61e4e012ef7f0040d10026421141c62173c65 --- /dev/null +++ b/src/warden-server/doc/UNINSTALL @@ -0,0 +1,95 @@ +Uninstallation process +====================== + +Content + + A. Overview + B. Uninstallation step + C. Post-uninstallation steps + +-------------------------------------------------------------------------------- + +A. Overview +----------- + +For uninstallation of warden-server package from local machine use uninstall.sh. + +Default uninstallation directory is /opt/warden-server/. + +For more information about uninstall.sh options run uninstall.sh -h. + +You must be root for running this script. + + +B. Uninstallation step +---------------------- + +1) Uninstall Warden server package (example for default installation path) + + # /opt/warden-server/uninstall.sh -d /opt + + +C. Post-uninstallation steps +---------------------------- + +1) Stop Apache server + + # /etc/init.d/apache2 stop + + +2) Disable of mod_ssl module + + # a2dismod ssl + + +3) Remove Apache server configuration + + a) VirtualHost section configuration + + - remove include parameters from the Warden server configuration file (<warden-server_path>/etc/warden-apache.conf) + + # vim /etc/apache2/sites-enables/default(-ssl) + + <VirtualHost *:443> + ... + + Include /opt/warden-server/etc/warden-apache.conf + </VirtualHost> + + + b) remove Apache server performance configuration + + # vim /etc/apache2/apache2.conf + + - prefork module settings + + <IfModule mpm_prefork_module> + StartServers 2 + MinSpareServers 4 + MaxSpareServers 8 + ServerLimit 700 + MaxClients 700 + MaxRequestsPerChild 0 + </IfModule> + + - connection settings + + Timeout 10 + KeepAlive Off + + +4) Drop MySQL database + + $ mysql -u <user> -h localhost -p <password> + mysql> DROP DATABASE warden; + mysql> exit + + +5) Uninstall unnecessary packages (optional) + + # aptitude remove apache2 mysql-server libapache2-mod-perl2 apache2-mpm-prefork + + +6) Start Apache server + + # /etc/init.d/apache2 start diff --git a/src/warden-server/doc/UPDATE b/src/warden-server/doc/UPDATE new file mode 100644 index 0000000000000000000000000000000000000000..c9ce426ac2998573d0a82265d28b5426a277b9fd --- /dev/null +++ b/src/warden-server/doc/UPDATE @@ -0,0 +1,42 @@ +Update process +============== + +Content + + A. Overview + B. Update steps + C. Post-update steps + +-------------------------------------------------------------------------------- + +A. Overview +----------- + +For update of warden-server package from local machine use update.sh. + +Default destination directory is /opt/warden-server/. + +For more information about update.sh options run update.sh -h. + +You must be root for running this script. + + +B. Update steps +--------------- + +1) Update Warden server package (default destination path) + + # ./warden-server-2.1/update.sh -d /opt + + +C. Post-update steps +-------------------- + +1) Update Warden server database + + $ mysql -u <user> -h localhost -p <password> < {warden-server_path}/doc/warden20to21.patch + + +2) Restart Apache server + + # /etc/init.d/apache2 restart diff --git a/src/warden-server/doc/warden.mysql b/src/warden-server/doc/warden.mysql index 8015a38bc13d0423fad8a77f18d94c49a4728f7a..48a298232103f71148c97a8b8ecd3f43bc7b4af3 100644 --- a/src/warden-server/doc/warden.mysql +++ b/src/warden-server/doc/warden.mysql @@ -33,7 +33,7 @@ SET character_set_client = utf8; CREATE TABLE `clients` ( `client_id` int(11) NOT NULL auto_increment, `hostname` varchar(256) default NULL, - `registered` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `registered` timestamp NOT NULL default '0000-00-00 00:00:00', `requestor` varchar(256) default NULL, `service` varchar(64) default NULL, `client_type` varchar(1) default NULL, @@ -56,17 +56,17 @@ CREATE TABLE `events` ( `id` int(11) NOT NULL auto_increment, `hostname` varchar(256) default NULL, `service` varchar(64) default NULL, - `detected` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `detected` timestamp NOT NULL default '0000-00-00 00:00:00', `received` timestamp NOT NULL default '0000-00-00 00:00:00', `type` varchar(64) default NULL, `source_type` varchar(64) default NULL, `source` varchar(256) default NULL, `target_proto` varchar(16) default NULL, - `target_port` int(2) default NULL, - `attack_scale` int(4) default NULL, + `target_port` int(2) unsigned default NULL, + `attack_scale` int(4) unsigned default NULL, `note` text, - `priority` int(1) default NULL, - `timeout` int(2) default NULL, + `priority` int(1) unsigned default NULL, + `timeout` int(2) unsigned default NULL, `valid` varchar(1) default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; diff --git a/src/warden-server/doc/warden20to21.patch b/src/warden-server/doc/warden20to21.patch new file mode 100644 index 0000000000000000000000000000000000000000..bf9c15fd92573c5b31eb2e16285634a53d40431a --- /dev/null +++ b/src/warden-server/doc/warden20to21.patch @@ -0,0 +1,8 @@ +ALTER TABLE `clients` CHANGE `registered` `registered` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00'; + +ALTER TABLE `events` +CHANGE `detected` `detected` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', +CHANGE `target_port` `target_port` INT( 2 ) UNSIGNED DEFAULT NULL , +CHANGE `attack_scale` `attack_scale` INT( 4 ) UNSIGNED DEFAULT NULL , +CHANGE `priority` `priority` INT( 1 ) UNSIGNED DEFAULT NULL , +CHANGE `timeout` `timeout` INT( 2 ) UNSIGNED DEFAULT NULL; diff --git a/src/warden-server/etc/package_version b/src/warden-server/etc/package_version index dab9935085995a0173d2a4ecbef8c889dca05383..a27c1875f7ec4c43357ea2e43e62891f93fb0b3d 100644 --- a/src/warden-server/etc/package_version +++ b/src/warden-server/etc/package_version @@ -1 +1 @@ -warden-server-2.0.0 +warden-server-2.1 diff --git a/src/warden-server/etc/warden-apache.conf b/src/warden-server/etc/warden-apache.conf index 118d4622ff6913884209fa686c72b5d2a59cc84e..0035c33a11bbfcc8c3fdc1986275fee267c2fe98 100644 --- a/src/warden-server/etc/warden-apache.conf +++ b/src/warden-server/etc/warden-apache.conf @@ -11,11 +11,11 @@ SSLOptions +StdEnvVars +ExportCertData SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL SSLCertificateFile /etc/ssl/certs/warden-dev.cesnet.cz.pem -SSLCertificateKeyFile /opt/warden-client/etc/warden-dev.cesnet.cz.key +SSLCertificateKeyFile /etc/ssl/private/warden-dev.cesnet.cz.key SSLCACertificateFile /etc/ssl/certs/tcs-ca-bundle.pem PerlOptions +Parent -PerlSwitches -I/opt/warden-server/lib +PerlSwitches -I /opt/warden-server/lib <Location /Warden> SetHandler perl-script diff --git a/src/warden-server/etc/warden-client.conf b/src/warden-server/etc/warden-client.conf index 1816343471fc35451346c684ece0379f89f59046..945209a4bd204fff987d53237d8686c6d9048cac 100644 --- a/src/warden-server/etc/warden-client.conf +++ b/src/warden-server/etc/warden-client.conf @@ -13,7 +13,7 @@ $URI = "https://warden-dev.cesnet.cz:443/Warden"; $SSL_KEY_FILE = "/etc/ssl/private/warden-dev.cesnet.cz.key"; #------------------------------------------------------------------------------- -# SSL_CERT_FILE - path toserver SSL certificate file +# SSL_CERT_FILE - path to server SSL certificate file #------------------------------------------------------------------------------- $SSL_CERT_FILE = "/etc/ssl/certs/warden-dev.cesnet.cz.pem"; diff --git a/src/warden-server/etc/warden-server.conf b/src/warden-server/etc/warden-server.conf index 4d9ff78c9ad5823b7db7abf08e27e2259e6677e7..1ac4fcecee6ee116ccc6beb983da2dbec97cad9f 100644 --- a/src/warden-server/etc/warden-server.conf +++ b/src/warden-server/etc/warden-server.conf @@ -5,30 +5,53 @@ #------------------------------------------------------------------------------- # BASEDIR - base directory of Warden server #------------------------------------------------------------------------------- -$BASEDIR = "/opt/warden-server"; +$BASEDIR = '/opt/warden-server'; #------------------------------------------------------------------------------- -# FACILITY - syslog facility +# SYSLOG - enable/disable syslog logging #------------------------------------------------------------------------------- -$FACILITY = "local7"; +$SYSLOG = 1; #------------------------------------------------------------------------------- -# DB_NAME - database name of Warden server +# SYSLOG_VERBOSE - enable/disable logging in verbose mode (stack info added) #------------------------------------------------------------------------------- -$DB_NAME = "warden"; +$SYSLOG_VERBOSE = 1; #------------------------------------------------------------------------------- -# DB_USER - user of Warden server database +# SYSLOG_FACILITY - syslog facility #------------------------------------------------------------------------------- -$DB_USER = "root"; +$SYSLOG_FACILITY = 'local7'; #------------------------------------------------------------------------------- -# DB_PASS - password of Warden server database +# DB_NAME - MySQL database name of Warden server #------------------------------------------------------------------------------- -$DB_PASS = ""; +$DB_NAME = 'warden'; #------------------------------------------------------------------------------- -# DB_HOST - what IP address to listen on of Warden server +# DB_USER - MySQL database user of Warden server #------------------------------------------------------------------------------- -$DB_HOST = "localhost"; +$DB_USER = 'root'; +#------------------------------------------------------------------------------- +# DB_PASS - MySQL database password of Warden server +#------------------------------------------------------------------------------- +$DB_PASS = ''; + +#------------------------------------------------------------------------------- +# DB_HOST - MySQL database host +#------------------------------------------------------------------------------- +$DB_HOST = 'localhost'; + +#------------------------------------------------------------------------------- +# MAX_EVENTS_LIMIT - server limit of maximum number of events that can be +# delivered to one client in one batch +#------------------------------------------------------------------------------- +$MAX_EVENTS_LIMIT = '1000000'; + +#------------------------------------------------------------------------------- +# VALID_STRINGS - validation hash containing allowed event attributes +#------------------------------------------------------------------------------- +%VALID_STRINGS = ( + 'type' => ['portscan', 'bruteforce', 'probe', 'spam', 'phishing', 'botnet_c_c', 'dos', 'malware', 'copyright', 'webattack', 'test', 'other'], + 'source_type' => ['IP', 'URL', 'Reply-To:'] +); diff --git a/src/warden-server/lib/Warden.pm b/src/warden-server/lib/Warden.pm index 3fd286005175bf26502fbc40c4619fc37c9b5bb8..3eeccebdfdb93fc947899fb112bd961704f5c239 100755 --- a/src/warden-server/lib/Warden.pm +++ b/src/warden-server/lib/Warden.pm @@ -19,30 +19,32 @@ use Net::CIDR::Lite; use DateTime; use MIME::Base64; use Crypt::X509; +use SOAP::Lite; +use Carp; -our $VERSION = "2.0"; +our $VERSION = "2.1"; ################################################################################ # READING OF CONFIGURATION VARIABLES ################################################################################ -my $conf_file = "/opt/warden-server/etc/warden-server.conf"; -our $FACILITY = undef; -our $DB_NAME = undef; -our $DB_USER = undef; -our $DB_PASS = undef; -our $DB_HOST = undef; - -# read config file -if (!open( TMP, $conf_file)) { - die errMsg("Can't read config file '$conf_file': $!\n"); -} -close TMP; +my $conf_file = "/opt/warden-server/etc/warden-server.conf"; # path is updated by install.sh +our $SYSLOG = undef; +our $SYSLOG_VERBOSE = undef; +our $SYSLOG_FACILITY = undef; +our $DB_NAME = undef; +our $DB_USER = undef; +our $DB_PASS = undef; +our $DB_HOST = undef; +our $MAX_EVENTS_LIMIT = 1000000; # default value +our %VALID_STRINGS = (); # inicialization of empty hash # load set variables by user -if (!do $conf_file) { - die errMsg("Errors in config file '$conf_file': $@"); +unless (do $conf_file) { + die("Errors in config file '$conf_file': $@") if $@; + die("Can't read config file '$conf_file': $!") unless defined $_; + # if $_ defined, it's retvalue of last statement of conf, for which we don't care } @@ -50,7 +52,7 @@ if (!do $conf_file) { # VARIABLES ################################################################################ -our $DBH = DBI->connect("DBI:mysql:database=$DB_NAME;host=$DB_HOST", $DB_USER, $DB_PASS, {RaiseError => 1, mysql_auto_reconnect => 1}) || die "Could not connect to database: $DBI::errstr"; +our $DBH = DBI->connect("DBI:mysql:database=$DB_NAME;host=$DB_HOST", $DB_USER, $DB_PASS, {RaiseError => 1, mysql_auto_reconnect => 1}) || die "Could not connect to database: $DBH->errstr"; ################################################################################ @@ -58,42 +60,31 @@ our $DBH = DBI->connect("DBI:mysql:database=$DB_NAME;host=$DB_HOST", $DB_USER, $ ################################################################################ #------------------------------------------------------------------------------- -# errMsg - print error message and die -#------------------------------------------------------------------------------- -sub errMsg -{ - my $msg = shift; - $msg = trim($msg); - print $msg . "\n"; - exit 1; -} # End of errMsg - - -#------------------------------------------------------------------------------- -# trim - remove whitespace from the start and end of the string +# sendMsg - sent message to syslog (SYS::Syslog) and to client (SOAP::Fault) +# +# Args: (SYSLOG severity, SYSLOG msg, SOAP msg) #------------------------------------------------------------------------------- -sub trim +sub sendMsg { - my $string = shift; - $string =~ s/^\s+//; - $string =~ s/\s+$//; - return $string; -} # End of trim + my $severity = shift; + my $syslog_msg = shift; + my $soap_msg = shift; + my $filename = File::Basename::basename($0); + if ($SYSLOG_VERBOSE == 1 && ($severity eq "err" || $severity eq "debug")) { + $syslog_msg .= "\nStack info: " . Carp::longmess(); + } -#------------------------------------------------------------------------------- -# write2log - writing message to syslog -#------------------------------------------------------------------------------- -sub write2log -{ - my $priority = shift; - my $msg = shift; - my $filename = File::Basename::basename($0); + if ($SYSLOG == 1 && defined $severity && defined $syslog_msg) { + Sys::Syslog::openlog($filename, "cons,pid", $SYSLOG_FACILITY); + Sys::Syslog::syslog("$severity", "$syslog_msg"); + Sys::Syslog::closelog(); + } - Sys::Syslog::openlog($filename, "cons,pid", $FACILITY); - Sys::Syslog::syslog("$priority", "$msg"); - Sys::Syslog::closelog(); -} # End of write2log + if (defined $soap_msg) { + die SOAP::Fault->faultstring($soap_msg); + } +} # End of sendMsg #------------------------------------------------------------------------------- @@ -127,57 +118,56 @@ sub getAltNames sub authorizeClient { - my ($alt_names, $ip, $service_type, $client_type, $function_name) = @_; - - my $sth; - # obtain cidr based on rigth common name and alternate names, service and client_type - if($function_name eq 'saveNewEvent') { - $sth = $DBH->prepare( "SELECT hostname, ip_net_client, receive_own_events - FROM clients WHERE hostname IN ($alt_names) AND service = ? AND client_type = ? - ORDER BY SUBSTRING_INDEX(ip_net_client,'/', -1) DESC;"); - } - elsif($function_name eq 'getNewEvents') { - $sth = $DBH->prepare( "SELECT hostname, ip_net_client, receive_own_events - FROM clients WHERE hostname IN ($alt_names) AND type = ? AND client_type = ? - ORDER BY SUBSTRING_INDEX(ip_net_client,'/', -1) DESC;"); - } + my ($alt_names, $ip, $service_type, $client_type, $function_name) = @_; + my $sth; - if (!defined $sth) { die("Cannot prepare authorization statement in $function_name: $DBI::errstr\n")} - $sth->execute($service_type, $client_type); - - my ($an, $cidr, $receive_own, $cidr_list); - my $correct_ip_source = 0; - my %ret; - - while(($an, $cidr, $receive_own) = $sth->fetchrow()) { - my $cidr_list = Net::CIDR::Lite-> new -> add($cidr); - - $ret{'dns'} = $an; - $ret{'cidr'} = $cidr; - $ret{'receive_own'} = $receive_own; - - if ($cidr_list->bin_find($ip)) { - $correct_ip_source = 1; - last; - } - }; + # obtain cidr based on rigth common name and alternate names, service and client_type + if($function_name eq 'saveNewEvent') { + $sth = $DBH->prepare("SELECT hostname, ip_net_client, receive_own_events FROM clients WHERE hostname IN ($alt_names) AND service = ? AND client_type = ? ORDER BY SUBSTRING_INDEX(ip_net_client,'/', -1) DESC;"); + } elsif($function_name eq 'getNewEvents') { + $sth = $DBH->prepare("SELECT hostname, ip_net_client, receive_own_events FROM clients WHERE hostname IN ($alt_names) AND (type = ? OR type = '_any_') AND client_type = ? ORDER BY SUBSTRING_INDEX(ip_net_client,'/', -1) DESC;"); + } + if (!defined $sth) { + sendMsg("err", + "Cannot prepare authorization statement in '$function_name': $DBH->errstr", + "Internal 'prepare' server error") + } + $sth->execute($service_type, $client_type); - # check if client is registered - if ($sth->rows == 0) { - write2log ("err", "Unauthorized access to $function_name from: $ip (CN(AN): $alt_names), used service '$service_type' - client is not registered"); - die("Access denied - client is not registered at warden server!"); - return undef; - } + my ($an, $cidr, $receive_own, $cidr_list); + my $correct_ip_source = 0; + my %ret; + while(($an, $cidr, $receive_own) = $sth->fetchrow()) { + my $cidr_list = Net::CIDR::Lite-> new -> add($cidr); - # check if client has IP from registered CIDR - if (!$correct_ip_source) { - write2log ("err", "Unauthorized access to $function_name from: $ip (CN(AN): $alt_names), used service '$service_type' - access from bad subnet: Registered subnet '" . $ret{'cidr'} . "'"); - die("Access denied - access from unauthorized subnet!"); - return undef; + $ret{'dns'} = $an; + $ret{'cidr'} = $cidr; + $ret{'receive_own'} = $receive_own; + + if ($cidr_list->bin_find($ip)) { + $correct_ip_source = 1; + last; } + } - return %ret; -} + # check if client is registered + if ($sth->rows == 0) { + sendMsg("err", + "Unauthorized access to function '$function_name' from [IP: '$ip'; CN(AN): $alt_names; Client_type: '$client_type'; Service/Type: '$service_type'] - client is not registered", + "Access denied - client is not registered at Warden server '$ENV{'SERVER_NAME'}'"); + return undef; + } + + # check if client has IP from registered CIDR + if (!$correct_ip_source) { + sendMsg ("err", + "Unauthorized access to function '$function_name' from [IP: '$ip'; CN(AN): $alt_names; Client_type: '$client_type'; Service/Type: '$service_type'] - access from another subnet than '$ret{'cidr'}'", + "Access denied - access to Warden server '$ENV{'SERVER_NAME'}' from unauthorized subnet"); + return undef; + } + + return %ret; +} # END of authorizeClient ################################################################################ @@ -198,33 +188,91 @@ sub saveNewEvent my $ip = $ENV{'REMOTE_ADDR'}; # variables defined by server - my $client_type = "s"; # incoming client MUST be sender - my $valid = "t"; # registered sender has valid events + my $function_name = 'saveNewEvent'; + my $client_type = 's'; # incoming client MUST be sender + my $valid = 't'; # registered sender has valid events my $received = DateTime->now; # time of event delivery (UTC) # parse object (event) parameters my $service = $data->{'SERVICE'}; my $detected = $data->{'DETECTED'}; - my $type = $data->{'TYPE'}; + my $type = $data->{'TYPE'}; my $source_type = $data->{'SOURCE_TYPE'}; my $source = $data->{'SOURCE'}; my $target_proto = $data->{'TARGET_PROTO'}; my $target_port = $data->{'TARGET_PORT'}; my $attack_scale = $data->{'ATTACK_SCALE'}; - my $note = $data->{'NOTE'}; + my $note = $data->{'NOTE'}; my $priority = $data->{'PRIORITY'}; my $timeout = $data->{'TIMEOUT'}; + my %client = authorizeClient($alt_names, $ip, $service, $client_type, $function_name); + if (defined %client) { + sendMsg("info", + "Incoming event: [service: '$service', detected: '$detected', type: '$type', source_type: '$source_type', source: '$source', target_proto: '$target_proto', target_port: '$target_port', attack_scale: '$attack_scale', note: '$note', priority: '$priority', timeout: '$timeout']", + undef); + if (%VALID_STRINGS) { # check if hash is not empty - use VALIDATION HASH + if (!(exists $VALID_STRINGS{'type'} && grep $type eq $_, @{$VALID_STRINGS{'type'}})) { + sendMsg("err", + "Unknown event type from [IP: '$ip'; CN(AN): $alt_names; Service: '$service'; Type: '$type']", + "Unknown event type: '$type'"); + } elsif (!(exists $VALID_STRINGS{'source_type'} && grep $source_type eq $_, @{$VALID_STRINGS{'source_type'}})) { + sendMsg("err", + "Unknown source type from [IP '$ip'; CN(AN): $alt_names; Service: '$service'; Source_type: '$source_type']", + "Unknown source type: '$source_type'"); + } + } - my %client = authorizeClient($alt_names, $ip, $service, $client_type, 'saveNewEvent'); - if(defined %client) { - # insert new events into DB - $sth=$DBH->prepare("INSERT INTO events VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"); - if (!defined $sth) { die("Cannot do insert statement in saveNewEvent: $DBI::errstr\n") } + # http://my.safaribooksonline.com/book/programming/regular-expressions/9780596802837/4dot-validation-and-formatting/id2983571 + if ($detected !~ /^((?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?/) { + sendMsg("err", + "Unknown detected time format from [IP: '$ip'; CN(AN): $alt_names; Service: '$service'; Detected: '$detected']", + "Unknown detected time format: '$detected'"); + } - $sth->execute(undef, $client{'dns'}, $service, $detected, $received, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout, $valid); + my $change_string = ""; + if (defined $target_port && $target_port !~ /^\d+\z/) { + $change_string = $change_string . "target_port: '$target_port'"; + $target_port = undef; + } + if (defined $attack_scale && $attack_scale !~ /^\d+\z/) { + if ($change_string eq "") { + $change_string = $change_string . "attack_scale: '$attack_scale'"; + } else { + $change_string = $change_string . ", attack_scale: '$attack_scale'"; + } + $attack_scale = undef; + } + if (defined $priority && $priority !~ /^\d+\z/) { + if ($change_string eq "") { + $change_string = $change_string . "priority: '$priority'"; + } else { + $change_string = $change_string . ", priority: '$priority'"; + } + $priority = undef; + } + if (defined $timeout && $timeout !~ /^\d+\z/) { + if ($change_string eq "") { + $change_string = $change_string . "timeout: '$timeout'"; + } else { + $change_string = $change_string . ", timeout: '$timeout'"; + } + $timeout = undef; + } + if ($change_string ne ""){ + sendMsg("info", + "Unknown event items detected {originaly - $change_string} received in $received from [IP '$ip'; CN(AN): $alt_names; Service: '$service'; Type: '$type'; Detected: '$detected']", + undef); + } - return 1; + $sth=$DBH->prepare("INSERT INTO events VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"); + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } + $sth->execute(undef, $client{'dns'}, $service, $detected, $received, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout, $valid); + return 1; } } # END of saveNewEvent @@ -239,30 +287,68 @@ sub getNewEvents my ($id, $hostname, $service, $detected, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout); # client network information - my $cn = $ENV{'SSL_CLIENT_S_DN_CN'}; - my $alt_names = getAltNames(undef); - my $ip = $ENV{'REMOTE_ADDR'}; + my $cn = $ENV{'SSL_CLIENT_S_DN_CN'}; + my $alt_names = getAltNames(undef); + my $ip = $ENV{'REMOTE_ADDR'}; - my $client_type = "r"; # incoming client MUST be sender + my $client_type = 'r'; # incoming client MUST be sender + my $function_name = 'getNewEvents'; # parse SOAP data object - my $requested_type = $data->{'REQUESTED_TYPE'}; - my $last_id = $data->{'LAST_ID'}; - + my $requested_type = $data->{'REQUESTED_TYPE'} || '_any_'; + my $last_id = $data->{'LAST_ID'}; + my $max_rcv_events_limit = $data->{'MAX_RCV_EVENTS_LIMIT'}; # client events limit + + # comparison of client and server limit - which can be used + my $used_limit; + if (defined $max_rcv_events_limit && $max_rcv_events_limit < $MAX_EVENTS_LIMIT) { + $used_limit = $max_rcv_events_limit; + } else { + $used_limit = $MAX_EVENTS_LIMIT; + } - my %client = authorizeClient($alt_names, $ip, $requested_type, $client_type, 'getNewEvents'); + my %client = authorizeClient($alt_names, $ip, $requested_type, $client_type, $function_name); if(defined %client) { - # check if client want your own events or not if ($client{'receive_own'} eq 't') { - $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND type = ? AND valid = 't' ORDER BY id ASC;"); - if (!defined $sth) {die("Cannot prepare ROE statement in getNewEvents: $DBI::errstr\n")} - $sth->execute($last_id, $requested_type); + if ($requested_type eq '_any_') { + $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND valid = 't' ORDER BY id ASC LIMIT ?;"); + if (!defined $sth) { + sendMsg("err", + "Cannot prepare ROE-ANY statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } + $sth->execute($last_id, $used_limit); + } else { + $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND type = ? AND valid = 't' ORDER BY id ASC LIMIT ?;"); + if (!defined $sth) { + sendMsg("err", + "Cannot prepare ROE statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } + $sth->execute($last_id, $requested_type, $used_limit); + } } else { - $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND type = ? AND valid = 't' AND hostname NOT LIKE ? ORDER BY id ASC;"); - if (!defined $sth) {die("Cannot prepare statement in getNewEvents: $DBI::errstr\n")} - my ($domain) = $cn =~ /([^\.]+\.[^\.]+)$/; - $domain = '\%' . $domain; - $sth->execute($last_id, $requested_type, $domain); + if ($requested_type eq '_any_') { + $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND valid = 't' AND hostname NOT LIKE ? ORDER BY id ASC LIMIT ?;"); + if (!defined $sth) { + sendMsg("err", + "Cannot prepare ANY statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } + my ($domain) = $cn =~ /([^\.]+\.[^\.]+)$/; + $domain = '\%' . $domain; + $sth->execute($last_id, $domain, $used_limit); + } else { + $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND type = ? AND valid = 't' AND hostname NOT LIKE ? ORDER BY id ASC LIMIT ?;"); + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr\n", + "Internal 'prepare' server error"); + } + my ($domain) = $cn =~ /([^\.]+\.[^\.]+)$/; + $domain = '\%' . $domain; + $sth->execute($last_id, $requested_type, $domain, $used_limit); + } } # parse items of events stored in DB @@ -276,19 +362,19 @@ sub getNewEvents $source = $result[7]; $target_proto = $result[8]; $target_port = $result[9]; - $attack_scale = $result[10]; + $attack_scale = $result[10]; $note = $result[11]; $priority = $result[12]; $timeout = $result[13]; # create SOAP data object $event = SOAP::Data->name(event => \SOAP::Data->value( - SOAP::Data->name(ID => $id), + SOAP::Data->name(ID => $id), SOAP::Data->name(HOSTNAME => $hostname), SOAP::Data->name(SERVICE => $service), SOAP::Data->name(DETECTED => $detected), SOAP::Data->name(TYPE => $type), - SOAP::Data->name(SOURCE_TYPE=> $source_type), + SOAP::Data->name(SOURCE_TYPE => $source_type), SOAP::Data->name(SOURCE => $source), SOAP::Data->name(TARGET_PROTO => $target_proto), SOAP::Data->name(TARGET_PORT => $target_port), @@ -304,9 +390,13 @@ sub getNewEvents # log sent ID of events if (scalar @events != 0) { if (scalar @ids == 1) { - write2log("info", "Sent 1 events [#$ids[0]] to $ip (CN(AN): $alt_names)"); + sendMsg("info", + "Sent 1 event [#$ids[0]] to [IP: '$ip'; CN(AN): $alt_names; Client_limit: '$max_rcv_events_limit', Requested_type: '$requested_type']", + undef); } else { - write2log("info", "Sent " . scalar @ids . " events [#$ids[0] - #$ids[-1]] to $ip (CN(AN): $alt_names)"); + sendMsg("info", + "Sent " . scalar @ids . " events [#$ids[0] - #$ids[-1]] to [IP: '$ip'; CN(AN): $alt_names, Client_limit: '$max_rcv_events_limit', Requested_type: '$requested_type']", + undef); } } return @events; @@ -320,9 +410,14 @@ sub getNewEvents sub getLastId { my ($class, $arg) = @_; + my $function_name = 'getLastId'; my $sth = $DBH->prepare("SELECT max(id) FROM events;"); - if ( !defined $sth ) { die("Cannot prepare statement in getLastId: $DBI::errstr\n") } + if ( !defined $sth ) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute; my $result = $sth->fetchrow(); @@ -343,9 +438,12 @@ sub registerSender my $ip = $ENV{'REMOTE_ADDR'}; my $local_ip = $ENV{'SERVER_ADDR'}; + my $function_name = 'registerSender'; + if ($local_ip ne $ip) { - write2log ("err", "Unauthorized access to registerSender from: $ip ($cn) - access allowed only from localhost"); - die("Access denied - access allowed only from localhost!"); + sendMsg("err", + "Unauthorized access to function '$function_name' from [IP: '$ip'; CN(AN): '$cn'] - access allowed only from 'localhost'", + "Access denied - access allowed only from 'localhost'"); } else { # defined variables by method my $client_type = "s"; @@ -361,29 +459,40 @@ sub registerSender my $ip_net_client = $data->{'IP_NET_CLIENT'}; # check if sender has been already registered - $sth = $DBH->prepare("SELECT registered FROM clients WHERE hostname = ? AND requestor = ? AND service = ? AND client_type = ? AND type = ? AND receive_own_events = ? AND description_tags = ? AND ip_net_client = ? LIMIT 1;"); - if (!defined $sth) {die("Cannot prepare check statement in registerSender: $DBI::errstr\n")} - $sth->execute($hostname, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); + $sth = $DBH->prepare("SELECT registered FROM clients WHERE hostname = ? AND service = ? AND client_type = ? AND ip_net_client = ? LIMIT 1;"); + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } + $sth->execute($hostname, $service, $client_type, $ip_net_client); my $result = $sth->fetchrow(); # register new sender if (defined $result) { - write2log ("err", "Attempt to re-register the sender"); - die("Error - sender has already been registered at $result"); + sendMsg("err", + "Attempt to re-register sender [Hostname: '$hostname', Service: '$service', CIDR: '$ip_net_client'] from '$ip'", + "Sender has been already registered at Warden server '$ENV{'SERVER_NAME'}' in '$result'"); } else { $sth = $DBH->prepare("INSERT INTO clients VALUES (?,?,?,?,?,?,?,?,?,?);"); - if (!defined $sth) {die("Cannot do statement in registerSender: $DBI::errstr\n")} + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute(undef, $hostname, $registered, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); - write2log("info", "New sender $hostname (service: $service, cidr: $ip_net_client) was registered"); + sendMsg("info", + "New sender [Hostname: '$hostname', Requestor: '$requestor', Service: '$service', Description_tags: '$description_tags', CIDR: '$ip_net_client'] has been registered at Warden server '$ENV{'SERVER_NAME'}'", + undef); return 1; } } } # END of registerSender -##----------------------------------------------------------------------------- -## registerReceiver - register new receiver -##----------------------------------------------------------------------------- +#----------------------------------------------------------------------------- +# registerReceiver - register new receiver +#----------------------------------------------------------------------------- sub registerReceiver { my ($class, $data) = @_; @@ -394,9 +503,12 @@ sub registerReceiver my $ip = $ENV{'REMOTE_ADDR'}; my $local_ip = $ENV{'SERVER_ADDR'}; + my $function_name = 'registerReceiver'; + if ($local_ip ne $ip) { - write2log ("err", "Unauthorized access to registerReceiver from: $ip ($cn) - access allowed only from localhost"); - die("Access denied - access allowed only from localhost!"); + sendMsg("err", + "Unauthorized access to function '$function_name' from [IP: '$ip'; CN(AN): '$cn'] - access allowed only from 'localhost'", + "Access denied - access allowed only from 'localhost'"); } else { # variables defined by method my $client_type = "r"; @@ -412,20 +524,31 @@ sub registerReceiver my $ip_net_client = $data->{'IP_NET_CLIENT'}; # check if receiver has been already registered - $sth = $DBH->prepare("SELECT registered FROM clients WHERE hostname = ? AND requestor = ? AND service = ? AND client_type = ? AND type = ? AND receive_own_events = ? AND description_tags = ? AND ip_net_client = ? LIMIT 1;"); - if (!defined $sth) {die("Cannot prepare check statement in registerReceiver: $DBI::errstr\n")} - $sth->execute($hostname, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); + $sth = $DBH->prepare("SELECT registered FROM clients WHERE hostname = ? AND client_type = ? AND type = ? AND ip_net_client = ? LIMIT 1;"); + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } + $sth->execute($hostname, $client_type, $type, $ip_net_client); my $result = $sth->fetchrow(); # register new receiver if (defined $result) { - write2log ("err", "Attempt to re-register the receiver"); - die("Error - receiver has already been registered at $result"); + sendMsg("err", + "Attempt to re-register receiver [Hostname: '$hostname', Type: '$type', CIDR: '$ip_net_client'] from '$ip'", + "Receiver has already been registered at Warden server '$ENV{'SERVER_NAME'}' in '$result'"); } else { $sth = $DBH->prepare("INSERT INTO clients VALUES (?,?,?,?,?,?,?,?,?,?);"); - if (!defined($sth)) {die("Cannot do statement in registerReceiver: $DBI::errstr\n")} + if (!defined($sth)) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute(undef, $hostname, $registered, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); - write2log("info", "New receiver $hostname (type: $type, cidr: $ip_net_client: receive_own_events: $receive_own_events) was registered"); + sendMsg("info", + "New receiver [Hostname: '$hostname', Requestor: '$requestor' Type: '$type', ROE: '$receive_own_events', CIDR: '$ip_net_client'] has been registered at Warden server '$ENV{'SERVER_NAME'}'", + undef); return 1; } } @@ -445,41 +568,63 @@ sub unregisterClient my $ip = $ENV{'REMOTE_ADDR'}; my $local_ip = $ENV{'SERVER_ADDR'}; + my $function_name = 'unregisterClient'; + if ($local_ip ne $ip) { - write2log ("err", "Unauthorized access to unregisterClients from: $ip ($cn) - access allowed only from localhost"); - die("Access denied - access allowed only from localhost!"); + sendMsg("err", + "Unauthorized access to function '$function_name' from [IP: '$ip', CN(AN): '$cn'] - access allowed only from 'localhost'", + "Access denied - access allowed only from 'localhost'"); } else { # parse SOAP data oject my $client_id = $data->{'CLIENT_ID'}; # check if receiver has been already registered - $sth = $DBH->prepare("SELECT client_id, hostname, service, client_type FROM clients WHERE client_id = ? LIMIT 1;"); - if (!defined $sth) {die("Cannot prepare check statement in unregisterClient: $DBI::errstr\n")} + $sth = $DBH->prepare("SELECT client_id, hostname, service, type, client_type FROM clients WHERE client_id = ? LIMIT 1;"); + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute($client_id); - my ($id, $hostname, $service, $client_type) = $sth->fetchrow(); + my ($id, $hostname, $service, $type, $client_type) = $sth->fetchrow(); # delete registered client if (!defined $id) { - write2log ("err", "Attempt to delete unregister client"); - die("Error - client (#$client_id) is not registered"); + sendMsg("err", + "Attempt to delete unregister client [Client_id: $id, Hostname: '$hostname', Service: '$service', Type: '$type', Client_type: '$client_type']", + "Client (#$client_id) is not registered at Warden server '$ENV{'SERVER_NAME'}'"); } else { if ($client_type eq 's') { $sth = $DBH->prepare("DELETE FROM clients WHERE client_id = ?;"); - if (!defined $sth) {die("Cannot do delete statement of sender in unregisterClient: $DBI::errstr\n")} + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute($client_id); $sth = $DBH->prepare("UPDATE events SET valid = 'f' where hostname = ? AND service = ?;"); - if (!defined $sth) {die("Cannot do unvalidation statement in unregisterClient: $DBI::errstr\n")} + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute($hostname, $service); - - write2log("info", "Sender $hostname (client_id: $client_id, service: $service) was deleted and its data were invalidated" ); + sendMsg("info", + "Sender [Client_id: '$client_id', Hostname: '$hostname', Service: '$service'] has been deleted from Warden server '$ENV{'SERVER_NAME'}' and its data were invalidated", + undef); return 1; } else { $sth = $DBH->prepare("DELETE FROM clients WHERE client_id = ?;"); - if (!defined $sth) {die("Cannot do delete statement of receiver in unregisterClient: $DBI::errstr\n")} + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute($client_id); - - write2log("info", "Receiver $hostname (client_id: $client_id) was deleted" ); + sendMsg("info", + "Receiver [Client_id: '$client_id', Hostname: '$hostname', Type: '$type'] has been deleted from Warden server '$ENV{'SERVER_NAME'}'", + undef); return 1; } } @@ -499,14 +644,21 @@ sub getClients my $ip = $ENV{'REMOTE_ADDR'}; my $local_ip = $ENV{'SERVER_ADDR'}; + my $function_name = 'getClients'; + if ($local_ip ne $ip) { - write2log ("err", "Unauthorized access to getClients from: $ip ($cn) - access allowed only from localhost"); - die("Access denied - access allowed only from localhost!"); + sendMsg("err", + "Unauthorized access to function '$function_name' from [IP: '$ip', CN(AN): '$cn'] - access allowed only from 'localhost'", + "Access denied - access allowed only from 'localhost'"); } else { my (@clients, $client); my ($client_id, $hostname, $registered, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); my $sth = $DBH->prepare("SELECT * FROM clients ORDER BY client_id ASC;"); - if (!defined $sth) { die("Cannot prepare statement in getClients: $DBI::errstr\n") } + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute; while ( my @result = $sth->fetchrow() ) { @@ -536,7 +688,9 @@ sub getClients push(@clients, $client); } my $sum = scalar @clients; - write2log("info", "Sending information about $sum registered clients"); + sendMsg("info", + "Sent information about $sum registered clients from Warden server '$ENV{'SERVER_NAME'}'", + undef); return @clients; } } # END of getClients @@ -554,9 +708,15 @@ sub getStatus my $ip = $ENV{'REMOTE_ADDR'}; my $local_ip = $ENV{'SERVER_ADDR'}; + my $function_name = 'getStatus'; + + #----------------------------------------------------------------------------- + # Warden server stats + if ($local_ip ne $ip) { - write2log ("err", "Unauthorized access to getStatus from: $ip ($cn) - access allowed only from localhost"); - die("Access denied - access allowed only from localhost!"); + sendMsg("err", + "Unauthorized access to function '$function_name' from [IP: '$ip', CN(AN): '$cn'] - access allowed only from 'localhost'", + "Access denied - access allowed only from 'localhost'"); } else { my ($sth, @status); @@ -577,35 +737,55 @@ sub getStatus # sum of records in table events $sth = $DBH->prepare("SELECT count(*) FROM events WHERE valid = 't';"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute; my $events_sum = $sth->fetchrow(); if (!defined $events_sum) { $events_sum = "none" } # id of last record in table events $sth = $DBH->prepare("SELECT max(id) FROM events;"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute; my $events_last_id = $sth->fetchrow(); if (!defined $events_last_id) { $events_last_id = "none" } # timestamp of first record in table events $sth = $DBH->prepare("SELECT received FROM events WHERE id = (SELECT min(id) FROM events);"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute; my $events_first_timestamp = $sth->fetchrow(); if (!defined $events_first_timestamp) { $events_first_timestamp = "none" } # timestamp of last record in table events $sth = $DBH->prepare("SELECT received FROM events WHERE id = (SELECT max(id) FROM events);"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute; my $events_last_timestamp = $sth->fetchrow(); if (!defined $events_last_timestamp) { $events_last_timestamp = "none" } # sum of records in table clients $sth = $DBH->prepare("SELECT count(*) FROM clients;"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute; my $clients_sum = $sth->fetchrow(); if (!defined $clients_sum) { $clients_sum = "none" } @@ -615,7 +795,9 @@ sub getStatus SOAP::Data->name(HOSTNAME => $hostname), SOAP::Data->name(IP_ADDRESS => $ip_address), SOAP::Data->name(PORT => $port), - SOAP::Data->name(FACILITY => $FACILITY), + SOAP::Data->name(SYSLOG => $SYSLOG), + SOAP::Data->name(SYSLOG_VERBOSE => $SYSLOG_VERBOSE), + SOAP::Data->name(SYSLOG_FACILITY => $SYSLOG_FACILITY), SOAP::Data->name(DB_NAME => $DB_NAME), SOAP::Data->name(DB_USER => $DB_USER), SOAP::Data->name(DB_HOST => $DB_HOST), @@ -628,39 +810,33 @@ sub getStatus )); push(@status, $server_status); - # statistics of senders + #--------------------------------------------------------------------------- + # Statistics table of senders + if ($clients_sum != 0) { - $sth = $DBH->prepare("SELECT client_id, hostname, service FROM clients WHERE client_type = 's' ORDER BY client_id ASC;"); - if (!defined $sth) {die("Cannot prepare statement in getStatus: $DBI::errstr\n")} + $sth = $DBH->prepare("SELECT clients.client_id, clients.hostname, clients.service, count(*), max(received) FROM events LEFT JOIN clients ON (events.hostname=clients.hostname AND events.service=clients.service) GROUP BY hostname, service;"); + if (!defined $sth) { + sendMsg("err", + "Cannot prepare statement in function '$function_name': $DBH->errstr", + "Internal 'prepare' server error"); + } $sth->execute; - my ($client_id, $hostname, $service); - my $client_status; - while(($client_id, $hostname, $service) = $sth->fetchrow()) { - my $sth2; - # sum of stored events - $sth2 = $DBH->prepare("SELECT count(*) FROM events WHERE hostname = ? AND service = ?;"); - if (!defined $sth2) {die("Cannot prepare statement in getStatus: $DBI::errstr\n")} - $sth2->execute($hostname, $service); - my $count = $sth2->fetchrow(); - if (!defined $count) {$count = "none"} - # timestamp of last stored event - $sth2 = $DBH->prepare("SELECT max(received) FROM events WHERE hostname = ? AND service = ?;"); - if (!defined $sth2) {die("Cannot prepare statement in getStatus: $DBI::errstr\n")} - $sth2->execute($hostname, $service); - my $timestamp = $sth2->fetchrow(); - if (!defined $timestamp) {$timestamp = "none"} - # create SOAP data object + my ($hash_ref, $client_id, $hostname, $service, $count, $timestamp, $client_status); + $hash_ref = $sth->fetchall_hashref("client_id"); + foreach my $key (sort {$a<=>$b} keys %$hash_ref) { $client_status = SOAP::Data->name(client_status => \SOAP::Data->value( - SOAP::Data->name(CLIENT_ID => $client_id), - SOAP::Data->name(HOSTNAME => $hostname), - SOAP::Data->name(SERVICE => $service), - SOAP::Data->name(COUNT => $count), - SOAP::Data->name(TIMESTAMP => $timestamp), + SOAP::Data->name(CLIENT_ID => $hash_ref->{$key}->{client_id}), + SOAP::Data->name(HOSTNAME => $hash_ref->{$key}->{hostname}), + SOAP::Data->name(SERVICE => $hash_ref->{$key}->{service}), + SOAP::Data->name(COUNT => $hash_ref->{$key}->{"count(*)"}), + SOAP::Data->name(TIMESTAMP => $hash_ref->{$key}->{"max(received)"}), )); - push(@status, $client_status); + push(@status, $client_status); } } - write2log("info", "Sent of warden server status info"); + sendMsg("info", + "Server status info sent from Warden server '$ENV{'SERVER_NAME'}'", + undef); return @status; } } # END of getStatus diff --git a/src/warden-server/lib/Warden.t b/src/warden-server/lib/Warden.t new file mode 100644 index 0000000000000000000000000000000000000000..7f0ecc3ec03f5943b0be6148454b9ee2fcab3692 --- /dev/null +++ b/src/warden-server/lib/Warden.t @@ -0,0 +1,144 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use DBI; +use DBD::mysql; +use Data::Dumper; + +use Test::More tests => 18; +use Test::MockModule; +use Test::Exception; + +use lib '..'; +use Warden; + +# Fake $ENV values +BEGIN { + $ENV{'SSL_CLIENT_S_DN_CN'} = 'warden-dev.cesnet.cz'; + $ENV{'SSL_CLIENT_CERT'} = '-----BEGIN CERTIFICATE----- +MIIEZzCCA0+gAwIBAgIRAKV1flST9dLTKDnQZsgWFmQwDQYJKoZIhvcNAQEFBQAw +NjELMAkGA1UEBhMCTkwxDzANBgNVBAoTBlRFUkVOQTEWMBQGA1UEAxMNVEVSRU5B +IFNTTCBDQTAeFw0xMTA4MTgwMDAwMDBaFw0xMzA4MTcyMzU5NTlaMD0xCzAJBgNV +BAYTAkNaMQ8wDQYDVQQKEwZDRVNORVQxHTAbBgNVBAMTFHdhcmRlbi1kZXYuY2Vz +bmV0LmN6MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxIzyexCL/CB6 +COj691JLEWYEVkBLhROqbENk0ka/LbTtS5oNS3WDJVOK7aoHO3yluAdg1VocfFeY +hTgZGAzC82IuNLc+873XTfO2bzotbJL31CBUwpz2QhEAjGgjdvSx++VZAlbDKIa7 +RnRcp9AsxPgqlUokVZbmR55sRO7QPaFqBUO061rj56uKzZocXy9RB+vVBQFUR5CF +GKOJhsiRU3GtHpEshKpOGX6jiC5OkUkcVr61Fb4BgKPFFptiiuwTuHUM40PLAdC/ +B2lWdt4qPZqeiDFOVAQJH2tpi0Bhn2dmS1ttU76qpfP4RCPXZFxdxqxWgMjGq7Fp +ON3G3ySb3QIDAQABo4IBZzCCAWMwHwYDVR0jBBgwFoAUDL2TaAzz3qujSWsrN1dH +6pDjue0wHQYDVR0OBBYEFMfGqZzdRFP42/ewN/5kPQoI83hxMA4GA1UdDwEB/wQE +AwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD +AjAYBgNVHSAEETAPMA0GCysGAQQBsjEBAgIdMDoGA1UdHwQzMDEwL6AtoCuGKWh0 +dHA6Ly9jcmwudGNzLnRlcmVuYS5vcmcvVEVSRU5BU1NMQ0EuY3JsMG0GCCsGAQUF +BwEBBGEwXzA1BggrBgEFBQcwAoYpaHR0cDovL2NydC50Y3MudGVyZW5hLm9yZy9U +RVJFTkFTU0xDQS5jcnQwJgYIKwYBBQUHMAGGGmh0dHA6Ly9vY3NwLnRjcy50ZXJl +bmEub3JnMB8GA1UdEQQYMBaCFHdhcmRlbi1kZXYuY2VzbmV0LmN6MA0GCSqGSIb3 +DQEBBQUAA4IBAQC/mZ2bKGj4ysHVB4q/skhYXMiTYBmVD7G7X434YIg70VDBM5IJ +efNNfx8HNdCprboX5PSPCpxl9n3TPARnEO2cm7XvVvt+wkdjNOys8z7a2DIPaeJ+ +An3sIPzWUtm85UxujghIJ9nPh1ovZ75cQ2HF5C79qCyKzHtfP77Kq61Nm2Ay4aTq +gWyjFAPRjnB9fczhjdzntVRdjUFVq8z4ifq3Lv+hbN6aOjhfKRt8Ksr3IFlfKJdy +0sE0lEZdjG+O8rsuHCT/c+90IvGsG5JLT5SPJIxwQ1+fPJDfB37VWmUC9meSe7rt +iP0EQsnY1ytKuyUylJl0FiF/wG3rB8N7qlua +-----END CERTIFICATE-----'; + $ENV{'REMOTE_ADDR'} = '195.113.161.39'; + $ENV{'SERVER_NAME'} = 'warden-dev.cesnet.cz'; + $ENV{'SERVER_ADDR'} = '195.113.161.39'; + $ENV{'SERVER_PORT'} = '443'; + + $Warden::MAX_EVENTS_LIMIT = "1000001"; + %Warden::VALID_STRINGS = ( + 'type' => ['portscan', 'bruteforce', 'probe', 'spam', 'phishing', 'botnet_c_c', 'dos', 'malware', 'copyright', 'webattack', 'test', 'other'], + 'source_type' => ['IP', 'URL', 'Reply-To:']); + + my $correctDBH = DBI->connect("DBI:mysql:database=warden;host=localhost", "root", "w4rd3n&r00t", {RaiseError => 1, mysql_auto_reconnect => 1}) || die "Could not connect to database: $DBI::errstr"; + + my $failDBH; + + $Warden::DBH = $correctDBH; +} + + +my $ret; + +# Alternate names test +print "GetAltNames test\n"; + +# 1 +#$alt_names, $ip, $service_type, $client_type, $function_name +lives_and( sub{ is Warden::getAltNames("warden-dev.cesnet.cz","195.113.161.39","honeyscan","s","someEvent"), "'warden-dev.cesnet.cz','warden-dev.cesnet.cz'"}, 'everything is OK.'); +#print "$@\n"; + +# Client authorizaton test +print "AuthorizeClient tests\n"; + +# 2 +dies_ok( sub{ Warden::authorizeClient("'warden-dev.cesnet.cz','warden-dev.cesnet.cz'","195.113.161.39","honeyscan","s","badAndUglyEvent") }, 'badAndUglyEvent: die (doesn\'t exist)' ); +#print "$@\n"; + +# 3 +dies_ok( sub{ Warden::authorizeClient("'warden-dev.cesnet.cz','warden-dev.cesnet.cz'","195.113.161.222","badType","s","saveNewEvent")}, 'saveNewEvent: client is not registered'); +#print "$@\n"; + +# 4 +dies_ok( sub{ Warden::authorizeClient("'warden-dev.cesnet.cz','warden-dev.cesnet.cz'","195.113.161.222","badType","s","getNewEvents")}, 'getNewEvents: client is not registered'); +#print "$@\n"; + +# 5 +lives_and( sub{ is Warden::authorizeClient("'warden-dev.cesnet.cz','warden-dev.cesnet.cz'","195.113.161.39","honeyscan","s","saveNewEvent"), '3/8'}, 'saveNewEvent: OK.'); +#print "$@\n"; + +# 6 +lives_and( sub{ is Warden::authorizeClient("'warden-dev.cesnet.cz','warden-dev.cesnet.cz'","195.113.161.39","any","r","getNewEvents"), '3/8'}, 'getNewEvents: OK.'); +#print "$@\n"; + +# Save event test +print "SaveNewEvent tests\n"; +# TODO: run database and SELECT error checks +my %event = ('TYPE' => 'badType', 'DETECTED' => '2012-09-18T06:06:06+01:00', 'SERVICE' => 'test', 'SOURCE_TYPE' => 'IP', 'SOURCE' => '123.123.123.123', 'TARGET_PROTO' => 'TCP', 'TARGET_PORT' => '22', 'ATTACK_SCALE' => '1234567890', 'NOTE' => 'Unit testing event', 'PRIORITY' => '1', 'TIMEOUT' => '20'); +dies_ok( sub{ $ret = Warden::saveNewEvent("test", \%event)}, 'bad type'); + +%event = ('TYPE' => 'test', 'DETECTED' => '2012-09-18T06:06:06+01:00', 'SERVICE' => 'test', 'SOURCE_TYPE' => 'BADTYPE', 'SOURCE' => '123.123.123.123', 'TARGET_PROTO' => 'TCP', 'TARGET_PORT' => '22', 'ATTACK_SCALE' => '1234567890', 'NOTE' => 'Unit testing event', 'PRIORITY' => '1', 'TIMEOUT' => '20'); +dies_ok( sub{ $ret = Warden::saveNewEvent("test", \%event)}, 'bad source type.'); + +%event = ('TYPE' => 'test', 'DETECTED' => 'XXXX-09-18T06:06:06+01:00', 'SERVICE' => 'test', 'SOURCE_TYPE' => 'IP', 'SOURCE' => '123.123.123.123', 'TARGET_PROTO' => 'TCP', 'TARGET_PORT' => '22', 'ATTACK_SCALE' => '1234567890', 'NOTE' => 'Unit testing event', 'PRIORITY' => '1', 'TIMEOUT' => '20'); +dies_ok( sub{ $ret = Warden::saveNewEvent("test", \%event)}, 'bad date format.'); + +%event = ('TYPE' => 'test', 'DETECTED' => '2012-09-18T06:06:06+01:00', 'SERVICE' => 'test', 'SOURCE_TYPE' => 'IP', 'SOURCE' => '123.123.123.123', 'TARGET_PROTO' => 'TCP', 'TARGET_PORT' => 'XXX', 'ATTACK_SCALE' => '1234567890', 'NOTE' => 'Unit testing event', 'PRIORITY' => '1', 'TIMEOUT' => '20'); +dies_ok( sub{ $ret = Warden::saveNewEvent("test", \%event)}, 'port is not a number.'); + +%event = ('TYPE' => 'test', 'DETECTED' => '2012-09-18T06:06:06+01:00', 'SERVICE' => 'test', 'SOURCE_TYPE' => 'IP', 'SOURCE' => '123.123.123.123', 'TARGET_PROTO' => 'TCP', 'TARGET_PORT' => '22', 'ATTACK_SCALE' => 'XXX', 'NOTE' => 'Unit testing event', 'PRIORITY' => '1', 'TIMEOUT' => '20'); +dies_ok( sub{ $ret = Warden::saveNewEvent("test", \%event)}, 'attack scale is not a number.'); + +%event = ('TYPE' => 'test', 'DETECTED' => '2012-09-18T06:06:06+01:00', 'SERVICE' => 'test', 'SOURCE_TYPE' => 'IP', 'SOURCE' => '123.123.123.123', 'TARGET_PROTO' => 'TCP', 'TARGET_PORT' => '22', 'ATTACK_SCALE' => '1234567890', 'NOTE' => 'Unit testing event', 'PRIORITY' => 'XXX', 'TIMEOUT' => '20'); +dies_ok( sub{ $ret = Warden::saveNewEvent("test", \%event)}, 'priority is not a number.'); + +%event = ('TYPE' => 'test', 'DETECTED' => '2012-09-18T06:06:06+01:00', 'SERVICE' => 'test', 'SOURCE_TYPE' => 'IP', 'SOURCE' => '123.123.123.123', 'TARGET_PROTO' => 'TCP', 'TARGET_PORT' => '22', 'ATTACK_SCALE' => '1234567890', 'NOTE' => 'Unit testing event', 'PRIORITY' => '1', 'TIMEOUT' => 'XXX'); +dies_ok( sub{ $ret = Warden::saveNewEvent("test", \%event)}, 'timeout is not a number.'); + +%event = ('TYPE' => 'test', 'DETECTED' => '2012-09-18T06:06:06+01:00', 'SERVICE' => 'test', 'SOURCE_TYPE' => 'IP', 'SOURCE' => '123.123.123.123', 'TARGET_PROTO' => 'TCP', 'TARGET_PORT' => '22', 'ATTACK_SCALE' => '1234567890', 'NOTE' => 'Unit testing event', 'PRIORITY' => '1', 'TIMEOUT' => '20'); +lives_ok( sub{ $ret = Warden::saveNewEvent("test", \%event)}, 'everything is fine.'); + +# Get new event +print "GetNewEvents tests\n"; +# TODO: run database and SELECT error checks +# dies_ok {Warden::getNewEvents()} 'Cannot work with the database.'; +my %getEventHash = ('REQUESTED_TYPE' => 'any', 'LAST_ID' => '1', 'MAX_RCV_EVENTS_LIMIT' => '10'); +lives_ok( sub{ Warden::getNewEvents("test",\%getEventHash)}, 'everything is fine.'); + +# Get last ID test +print "GetLastId test\n"; +# TODO: run database and SELECT error checks +lives_ok( sub{Warden::getLastId() =~ /^\d+$/}, 'getLastID is OK.'); + +# Get clients test +print "GetClients\n"; +# TODO: run database and SELECT error checks +lives_ok( sub{ Warden::getClients()}, 'everything is fine.'); + +print "GetStatus\n"; +# run database and SELECT error checks +lives_ok( sub{ Warden::getStatus()}, 'everything is fine.'); + diff --git a/src/warden-server/lib/WardenConf.pm b/src/warden-server/lib/WardenConf.pm index 68103e459944098b7415a443724d5827a724f0e8..db32d5a3f176a9d124ff91b12f2da29bb566a044 100755 --- a/src/warden-server/lib/WardenConf.pm +++ b/src/warden-server/lib/WardenConf.pm @@ -20,20 +20,16 @@ sub loadConf my $conf_file = shift; # preset of default variables - our $URI = undef; - our $SSL_KEY_FILE = undef; - our $SSL_CERT_FILE = undef; - our $SSL_CA_FILE = undef; - - # read config file - if ( ! open( TMP, $conf_file) ) { - die "Can't read config file '$conf_file': $!\n"; - } - close TMP; + our $URI = undef; + our $SSL_KEY_FILE = undef; + our $SSL_CERT_FILE = undef; + our $SSL_CA_FILE = undef; # load set variables by user - if ( !do $conf_file ) { - die("Errors in config file '$conf_file': $@"); + unless (do $conf_file) { + die("Errors in config file '$conf_file': $@") if $@; + die("Can't read config file '$conf_file': $!") unless defined $_; + # if $_ defined, it's retvalue of last statement of conf, for which we don't care } return ($URI, $SSL_KEY_FILE, $SSL_CERT_FILE, $SSL_CA_FILE); diff --git a/src/warden-server/lib/WardenReg.pm b/src/warden-server/lib/WardenReg.pm index 12361f0b75f985af79d816cd720e80ab8096ff07..39aa7430adeb8d67cf64d2cfbaae6e709beee6ef 100755 --- a/src/warden-server/lib/WardenReg.pm +++ b/src/warden-server/lib/WardenReg.pm @@ -43,7 +43,7 @@ sub c2s if (!($client = SOAP::Transport::HTTP::Client->new())) { errMsg("Sorry, unable to create socket: " . &SOAP::Transport::HTTP::Client::errstr) } - $client->timeout(60); + $client->timeout(10); $client->ssl_opts( verify_hostname => 1, SSL_use_cert => 1, SSL_verify_mode => 0x02, diff --git a/src/warden-server/lib/WardenStatus.pm b/src/warden-server/lib/WardenStatus.pm index 1075ec4d67532548881796e267a7452803c92fdf..1907ecbfb897efb57c79137f3dd795bc55cb070a 100755 --- a/src/warden-server/lib/WardenStatus.pm +++ b/src/warden-server/lib/WardenStatus.pm @@ -43,7 +43,7 @@ sub c2s if (!($client = SOAP::Transport::HTTP::Client->new())) { errMsg("Sorry, unable to create socket: " . &SOAP::Transport::HTTP::Client::errstr) } - $client->timeout(60); + $client->timeout(10); $client->ssl_opts(verify_hostname => 1, SSL_use_cert => 1, SSL_verify_mode => 0x02, @@ -146,7 +146,9 @@ sub getStatus my $db_name = $response_data->{'DB_NAME'}; my $db_user = $response_data->{'DB_USER'}; my $db_host = $response_data->{'DB_HOST'}; - my $facility = $response_data->{'FACILITY'}; + my $syslog = $response_data->{'SYSLOG'}; + my $syslog_verbose = $response_data->{'SYSLOG_VERBOSE'}; + my $syslog_facility = $response_data->{'SYSLOG_FACILITY'}; my $db_size = $response_data->{'DB_SIZE'}; my $events_sum = $response_data->{'EVENTS_SUM'}; my $events_last_id = $response_data->{'EVENTS_LAST_ID'}; @@ -154,7 +156,7 @@ sub getStatus my $events_last_timestamp = $response_data->{'EVENTS_LAST_TIMESTAMP'}; my $clients_sum = $response_data->{'CLIENTS_SUM'}; - my @server_status = ($version, $server_hostname, $ip_address, $port, $db_name, $db_user, $db_host, $facility, $db_size, $events_sum, $events_last_id, $events_first_timestamp, $events_last_timestamp, $clients_sum); + my @server_status = ($version, $server_hostname, $ip_address, $port, $db_name, $db_user, $db_host, $syslog, $syslog_verbose, $syslog_facility, $db_size, $events_sum, $events_last_id, $events_first_timestamp, $events_last_timestamp, $clients_sum); my @status; push(@status, \@server_status); diff --git a/src/warden-server/sh/create_tables.sh b/src/warden-server/sh/create_tables.sh deleted file mode 100755 index 9fa8ecc2962ef788fbc6e8737a7255bcb96d553d..0000000000000000000000000000000000000000 --- a/src/warden-server/sh/create_tables.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -# Pri pouziti Apache + mod_perl se tento soubor nepouziva - -# -# create_table.sh -# -# Copyright (C) 2011-2012 Cesnet z.s.p.o -# Author(s): Tomas PLESNIK <plesnik@ics.muni.cz> -# Jan SOUKAL <soukal@ics.muni.cz> -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name of the Cesnet z.s.p.o 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 any express or implied -# warranties, including, but not limited to, the implied warranties of -# merchantability and fitness for a particular purpose are disclaimed. -# In no event shall the Cesnet z.s.p.o or contributors be liable for -# any direct, indirect, incidental, special, exemplary, or consequential -# damages (including, but not limited to, procurement of substitute -# goods or services; loss of use, data, or profits; or business -# interruption) however caused and on any theory of liability, whether -# in contract, strict liability, or tort (including negligence or -# otherwise) arising in any way out of the use of this software, even -# if advised of the possibility of such damage. - -VERSION="0.1" - -sqlite=`which sqlite3` -db_file=$1 - -# create table events -$sqlite $db_file "CREATE TABLE events (id INTEGER PRIMARY KEY, hostname VARCHAR(256), service VARCHAR(64), detected TIMESTAMP, received TIMESTAMP, type VARCHAR(64), source_type VARCHAR(64), source VARCHAR(256), target_proto VARCHAR(16), target_port INT(2), attack_scale INT(4), note TEXT, priority INT(1), timeout INT(2), valid VARCHAR(1));" - -# create table clients -$sqlite $db_file "CREATE TABLE clients (client_id INTEGER PRIMARY KEY, hostname VARCHAR(256), registered TIMESTAMP, requestor VARCHAR(256), service VARCHAR(64), client_type VARCHAR(1), type VARCHAR(64), receive_own_events VARCHAR(1), description_tags VARCHAR(256), ip_net_client VARCHAR(256));" - -exit 0 diff --git a/src/warden-server/sh/install.sh b/src/warden-server/sh/install.sh index 763699bfe4b2468778b5dd06d827fde0846261f6..70a7feb99e4a22d19f208eee644b760cd807093c 100755 --- a/src/warden-server/sh/install.sh +++ b/src/warden-server/sh/install.sh @@ -3,35 +3,11 @@ # install.sh # # Copyright (C) 2011-2012 Cesnet z.s.p.o -# Author(s): Tomas PLESNIK <plesnik@ics.muni.cz> -# Jan SOUKAL <soukal@ics.muni.cz> # -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name of the Cesnet z.s.p.o 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 any express or implied -# warranties, including, but not limited to, the implied warranties of -# merchantability and fitness for a particular purpose are disclaimed. -# In no event shall the Cesnet z.s.p.o or contributors be liable for -# any direct, indirect, incidental, special, exemplary, or consequential -# damages (including, but not limited to, procurement of substitute -# goods or services; loss of use, data, or profits; or business -# interruption) however caused and on any theory of liability, whether -# in contract, strict liability, or tort (including negligence or -# otherwise) arising in any way out of the use of this software, even -# if advised of the possibility of such damage. +# Use of this source is governed by a BSD-style license, see LICENSE file. + -VERSION="0.2" +VERSION="2.1" #------------------------------------------------------------------------------- # FUNCTIONS @@ -86,26 +62,6 @@ err_clean() } -os_chck() -{ - OS=`uname` - if [ "$OS" != "Linux" ]; then - echo "Sorry, unsupported operating system detected - \"${OS}\"!" - exit 1 - fi -} - - -shell_chck() -{ - SHELL=`echo $SHELL` - if [ "$SHELL" != "/bin/bash" ]; then - echo "Sorry, this script is usable in Bourne Again Shell (bash) only!" - exit 1 - fi -} - - root_chck() { if [ $UID -ne 0 ]; then @@ -176,19 +132,13 @@ modules_chck() make_warden_dir() { - echo -n "Creating warden server directory ... " - test -d ${prefix} || mkdir -p ${prefix} - if cp -R $dirname/warden-server $prefix 2> $err; then + echo -n "Creating Warden server directory ... " + test -d $prefix || mkdir -p $prefix + if cp -R ${dirname}/warden-server $prefix 2> $err; then echo "OK" else err_clean fi - - files=(CHANGELOG INSTALL LICENSE README) - for file in ${files[@]}; - do - cp ${dirname}/$file $server_path/doc - done cp ${dirname}/uninstall.sh $server_path } @@ -218,8 +168,7 @@ make_client_conf() #------------------------------------------------------------------------------- # SSL_CA_FILE - path to CA certificate file #------------------------------------------------------------------------------- -\$SSL_CA_FILE = \"${ca_file}\"; -" > $client_conf 2> $err; ret_val=`echo $?` +\$SSL_CA_FILE = \"${ca_file}\";" > $client_conf 2> $err; ret_val=`echo $?` if [ $ret_val -eq 0 ]; then echo "OK" @@ -242,15 +191,89 @@ make_server_conf() \$BASEDIR = \"${server_path}\"; #------------------------------------------------------------------------------- -# FACILITY - syslog facility +# SYSLOG - enable/disable syslog logging #------------------------------------------------------------------------------- -\$FACILITY = \"local7\"; +\$SYSLOG = 1; -\$DB_NAME = \"warden\"; -\$DB_USER = \"username\"; -\$DB_PASS = \"\"; -\$DB_HOST = \"localhost\"; -" > $server_conf 2> $err; ret_val=`echo $?` +#------------------------------------------------------------------------------- +# SYSLOG_VERBOSE - enable/disable logging in verbose mode (stack info added) +#------------------------------------------------------------------------------- +\$SYSLOG_VERBOSE = 1; + +#------------------------------------------------------------------------------- +# SYSLOG_FACILITY - syslog facility +#------------------------------------------------------------------------------- +\$SYSLOG_FACILITY = \"local7\"; + +#------------------------------------------------------------------------------- +# DB_NAME - MySQL database name of Warden server +#------------------------------------------------------------------------------- +\$DB_NAME = \"warden\"; + +#------------------------------------------------------------------------------- +# DB_USER - MySQL database user of Warden server +#------------------------------------------------------------------------------- +\$DB_USER = \"warden\"; + +#------------------------------------------------------------------------------- +# DB_PASS - MySQL database password of Warden server +#------------------------------------------------------------------------------- +\$DB_PASS = \"\"; + +#------------------------------------------------------------------------------- +# DB_HOST - MySQL database host +#------------------------------------------------------------------------------- +\$DB_HOST = \"localhost\"; + +#------------------------------------------------------------------------------- +# MAX_EVENTS_LIMIT - server limit of maximum number of events that can be +# delivered to one client in one batch +#------------------------------------------------------------------------------- +\$MAX_EVENTS_LIMIT = 1000000; + +#------------------------------------------------------------------------------- +# VALID_STRINGS - validation hash containing allowed event attributes +#------------------------------------------------------------------------------- +%VALID_STRINGS = ( + \"type\" => [\"portscan\", \"bruteforce\", \"probe\", \"spam\", \"phishing\", \"botnet_c_c\", \"dos\", \"malware\", \"copyright\", \"webattack\", \"test\", \"other\", \"_any_\"], + \"source_type\" => [\"IP\", \"URL\", \"Reply-To:\"] +);" > $server_conf 2> $err; ret_val=`echo $?` + + if [ $ret_val -eq 0 ]; then + echo "OK" + else + err_clean + fi +} + +make_apache_conf() +{ + echo -n "Creating Apache configuration file ... " + echo "# +# +# warden-apache.conf - configuration file for the Apache server +# + +SSLEngine on + +SSLVerifyDepth 3 +SSLVerifyClient require +SSLOptions +StdEnvVars +ExportCertData + +SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL + +SSLCertificateFile $cert +SSLCertificateKeyFile $key +SSLCACertificateFile $ca_file + +PerlOptions +Parent +PerlSwitches -I $lib + +<Location /Warden> + SetHandler perl-script + PerlHandler Warden::ApacheDispatch + SSLOptions +StdEnvVars +</Location>" > $apache_conf 2> $err; ret_val=`echo $?` if [ $ret_val -eq 0 ]; then echo "OK" @@ -263,53 +286,26 @@ make_server_conf() changeServerPath() { echo "Update server path ..."; - for file in `ls -1 $bin | grep -v warden-alive | grep -v create_tables.sh | grep -v wardend` + for file in `ls -1 $bin` do echo "- update server path: ${bin}/$file" perl -pi -e "s#/opt#${prefix}#" ${bin}/$file done - echo "- update server path: ${apache_conf}" - perl -pi -e "s#/opt#${prefix}#" ${apache_conf} - echo "- update server path: ${lib}/Warden.pm" perl -pi -e "s#/opt#${prefix}#" ${lib}/Warden.pm } -updateCertsPath() -{ - - echo "- update certs path: ${apache_conf}" - perl -pi -e "s#server-cert.pem#${cert}#" ${apache_conf} - perl -pi -e "s#server-key.pem#${key}#" ${apache_conf} - perl -pi -e "s#ca-cert.pem#${ca_file}#" ${apache_conf} -} - -#create_db() -#{ -# echo -n "Creating warden server database ... " -# $create_tables $db_file 2> $err || err_clean -# if chmod 600 $db_file 2> $err; then -# echo "OK" -# else -# err_clean -# fi -#} - - - create_symlinks() { echo "Creating symbolic links ..." - for file in `ls -1 $bin | grep -v warden-alive | grep -v create_tables.sh | grep -v wardend` + for file in `ls -1 $bin` do echo "- making symlink: ${local_bin}/$file -> ${bin}/$file" ln -s ${bin}/$file ${local_bin}/$file done -# echo "- making symlink: ${bin}/wardend -> $init" -# ln -s ${bin}/wardend $init } @@ -318,14 +314,7 @@ create_symlinks() #------------------------------------------------------------------------------- # list of used Perl modules -#modules=(SOAP::Lite SOAP::Transport::TCP File::Pid POSIX DBI DBD::SQLite Format::Human::Bytes Sys::Syslog File::Basename FindBin Net::CIDR::Lite DateTime Getopt::Std Switch IO::Socket::SSL) -modules=(DBI DBD::mysql Format::Human::Bytes Sys::Syslog File::Basename FindBin Net::CIDR::Lite DateTime Getopt::Std Switch IO::Socket::SSL MIME::Base64 Crypt::X509) - -# OS test -os_chck - -# Shell test -shell_chck +modules=(SOAP::Lite SOAP::Transport::HTTP DBI DBD::mysql Format::Human::Bytes Sys::Syslog File::Basename Net::CIDR::Lite DateTime Getopt::Std Switch IO::Socket::SSL MIME::Base64 Crypt::X509 Carp) # read input while getopts "d:k:c:a:Vh" options; do @@ -348,11 +337,10 @@ params_chck # create variables dirname=`dirname $0` -hostname=`hostname` +hostname=`hostname -f` key_file=`basename $key` cert_file=`basename $cert` package_version=`cat ${dirname}/warden-server/etc/package_version` -create_tables="${dirname}/warden-server/bin/create_tables.sh" [[ $prefix == */ ]] && prefix="${prefix%?}" # remove last char (slash) from prefix server_path="${prefix}/warden-server" @@ -364,9 +352,8 @@ server_conf="${etc}/warden-server.conf" apache_conf="${etc}/warden-apache.conf" var="${server_path}/var" lib="${server_path}/lib" -db_file="${var}/warden.db" +doc="${server_path}/doc" err="/tmp/warden-err" -init="/etc/init.d/wardend" # check if warden-server is installed old_package_chck @@ -377,9 +364,6 @@ echo "------------------------- Dependencies check-in -------------------------" # Perl interpreter test perl_chck -## SQLite database engine test -#sqlite_chck - # Perl modules test modules_chck @@ -395,27 +379,27 @@ make_client_conf # create server configuration file make_server_conf -## create warden server database -#create_db +# create Apache configuration file +make_apache_conf #update paths in utilities changeServerPath -#update paths in apachefile -updateCertsPath - # crate symlinks from warden server bin directory to /usr/local/bin create_symlinks echo -echo "Please check client configuration file in ${client_conf}!" -echo "Please check server configuration file in ${server_conf}!" +echo "Please check configuration files:" +echo " - ${client_conf}" +echo " - ${server_conf}" +echo " - ${apache_conf}" echo echo "Warden server directory: $server_path" -#echo "Warden server daemon: $init [start|stop|status|restart|force-stop]" +echo +echo "Please follow post-installation steps in ${doc}/INSTALL!" echo echo "Installation of $package_version package was SUCCESSFUL!!!" - +echo # cleanup section rm -rf $err diff --git a/src/warden-server/sh/uninstall.sh b/src/warden-server/sh/uninstall.sh index 060bda6002043f0caf8cee4d83b0ee8a1681dc5c..d9bdcbf84fdb8437bcb174dcb98d585acecb80f9 100755 --- a/src/warden-server/sh/uninstall.sh +++ b/src/warden-server/sh/uninstall.sh @@ -3,35 +3,9 @@ # uninstall.sh # # Copyright (C) 2011-2012 Cesnet z.s.p.o -# Author(s): Tomas PLESNIK <plesnik@ics.muni.cz> -# Jan SOUKAL <soukal@ics.muni.cz> # -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name of the Cesnet z.s.p.o 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 any express or implied -# warranties, including, but not limited to, the implied warranties of -# merchantability and fitness for a particular purpose are disclaimed. -# In no event shall the Cesnet z.s.p.o or contributors be liable for -# any direct, indirect, incidental, special, exemplary, or consequential -# damages (including, but not limited to, procurement of substitute -# goods or services; loss of use, data, or profits; or business -# interruption) however caused and on any theory of liability, whether -# in contract, strict liability, or tort (including negligence or -# otherwise) arising in any way out of the use of this software, even -# if advised of the possibility of such damage. - -VERSION="0.2" + +VERSION="2.1" #------------------------------------------------------------------------------- # FUNCTIONS @@ -76,13 +50,10 @@ err_clean() echo " -> Reverting changes of warden server package ... OK" rm -rf ${server_path}/* > /dev/null 2>&1 # delete new version cp -R ${backup_dir}/* $server_path # copy old backuped server - chmod 600 $db_file # change permission to DB file - for file in `ls -1 $bin | grep -v warden-alive | grep -v create_tables.sh | grep -v wardend` + for file in `ls -1 $bin` do ln -s ${bin}/$file ${local_bin}/$file # create symlinks to /usr/local/bin done - ln -s ${bin}/wardend $init # create symlink to /etc/init.d/ - $init start # start server cat $err rm -rf $err $backup_dir echo @@ -91,26 +62,6 @@ err_clean() } -os_chck() -{ - OS=`uname` - if [ "$OS" != "Linux" ]; then - echo "Sorry, unsupported operating system detected - \"${OS}\"!" - exit 1 - fi -} - - -shell_chck() -{ - SHELL=`echo $SHELL` - if [ "$SHELL" != "/bin/bash" ]; then - echo "Sorry, this script is usable in Bourne Again Shell (bash) only!" - exit 1 - fi -} - - root_chck() { if [ $UID -ne 0 ]; then @@ -141,7 +92,7 @@ obtain_package_version() warden_dir_chck() { - echo -n "Checking warden server directory ... " + echo -n "Checking Warden server directory ... " if [ ! -d $server_path ]; then echo "FAILED!" ls $server_path @@ -152,16 +103,9 @@ warden_dir_chck() } -stop_warden_server() -{ - echo "Stopping warden server ... " - ${init} force-stop 1>/dev/null 2>&1 -} - - backup() { - echo -n "Backing-up warden server directory ... " + echo -n "Backing-up Warden server directory ... " mkdir $backup_dir if cp -R ${server_path}/* $backup_dir 2> $err; then echo "OK" @@ -174,20 +118,18 @@ backup() delete_symlinks() { echo -n "Deleting symlinks from /usr/local/bin ..." - for file in `ls -1 $bin | grep -v warden-alive | grep -v wardend | grep -v create_tables.sh` + for file in `ls -1 $bin` do rm -rf ${local_bin}/$file 2> /dev/null done echo "OK" - echo -n "Deleting symlink from ${init} ..." - rm -rf $init 2> /dev/null - echo "OK" } uninstall_warden_server() { echo -n "Uninstalling $package_version package ... " + cp ${doc}/UNINSTALL $uninstall_file if rm -rf $server_path 2> $err; then echo "OK" else @@ -201,12 +143,6 @@ uninstall_warden_server() # MAIN #------------------------------------------------------------------------------- -# OS test -os_chck - -# Shell test -shell_chck - # read input while getopts "d:Vh" options; do case $options in @@ -225,16 +161,16 @@ params_chck # create variables [[ $prefix == */ ]] && prefix="${prefix%?}" # remove last char (slash) from prefix +dirname=`dirname $0` server_path="${prefix}/warden-server" bin="${server_path}/bin" local_bin="/usr/local/bin" etc="${server_path}/etc" -var="${server_path}/etc" -db_file="${var}/warden.db" +doc="${server_path}/doc" +uninstall_file="/tmp/UNINSTALL.warden" old_package_version_file="${etc}/package_version" err="/tmp/warden-err" backup_dir="/tmp/warden-backup" -init="/etc/init.d/wardend" # obtain version of installed warden-server package obtain_package_version @@ -245,9 +181,6 @@ echo "------------------------- Uninstallation process ------------------------- # check if $prefix/warden-server directory exist warden_dir_chck -# stop running warden server -stop_warden_server - # make backup of currently installed warden-server package backup @@ -258,8 +191,10 @@ delete_symlinks uninstall_warden_server echo -echo "Uninstallation of $package_version package was SUCCESSFUL!!!" - +echo "Please follow post-uninstallation steps in $uninstall_file!" +echo +echo "Uninstallation of $package_version package was SUCCESSFUL!" +echo # cleanup section rm -rf $err $backup_dir diff --git a/src/warden-server/sh/update.sh b/src/warden-server/sh/update.sh new file mode 100755 index 0000000000000000000000000000000000000000..bc0810eef19120bd6575d104dca47ed11507c523 --- /dev/null +++ b/src/warden-server/sh/update.sh @@ -0,0 +1,435 @@ +#!/bin/bash +# +# update.sh +# +# Copyright (C) 2011-2012 Cesnet z.s.p.o +# +# Use of this source is governed by a BSD-style license, see LICENSE file. + + +VERSION="2.1" + +#------------------------------------------------------------------------------- +# FUNCTIONS +#------------------------------------------------------------------------------- +usage() +{ + echo "Usage: `basename $0` [-d <directory>] [-hV]" + echo "-d <directory> destination directory (default: /opt)" + echo "-h print this help" + echo "-V print script version number and exit" + echo + echo "Example: # ./`basename $0` -d /opt" + echo + echo "Note: You must be root for running this script." + echo " For more information about update process, see README file (section Update)." + echo + exit 0 +} + + +version() +{ + echo "`basename ${0}` - current version is $VERSION" + exit 0 +} + + +err() +{ + echo "FAILED!" + cat $err + rm -rf $err + rm -rf $backup_dir + echo + echo "Update from $old_package_version to $package_version package FAILED!!!" + exit 1 +} + + +err_clean() +{ + echo "FAILED!" + echo " -> Reverting changes of Warden server package ... OK" + rm -rf ${server_path}/* > /dev/null 2>&1 + cp -R ${backup_dir}/* $server_path + cat $err + rm -rf $err $backup_dir + echo + echo "Update from $old_package_version to $package_version package FAILED!!!" + exit 1 +} + + +root_chck() +{ + if [ $UID -ne 0 ]; then + echo "You must be root for running this script!" + exit 1 + fi +} + + +params_chck() +{ + if [ -z $prefix ]; then + prefix=/opt + echo "Warning: parameter -d <directory> is not set - default update directory is ${prefix}!" + fi +} + + +obtain_package_version() +{ + if [ -f $old_package_version_file ]; then + old_package_version=`cat $old_package_version_file` + if [ "$old_package_version" == "$package_version" ]; then + echo "Sorry, but $package_version package is already installed!" + exit 1 + fi + else + echo "Sorry, but Warden server package is not installed!" + echo "For installation of Warden server package please use install.sh script." + exit 1 + fi +} + + +perl_chck() +{ + echo -n "Checking Perl interpreter ... " + if which perl 1> /dev/null; then + echo "OK" + else + echo "FAILED!" + echo "Error: Perl interpreter is not installed!" + exit 1 + fi +} + + +modules_chck() +{ + for module in ${modules[@]}; + do + echo -n "Checking $module module ... " + if perl -e "use $module" 2> $err; then + echo "OK" + else + err + fi + done +} + + +warden_dir_chck() +{ + echo -n "Checking Warden server directory ... " + if [ ! -d $server_path ]; then + echo "FAILED!" + ls $server_path + exit 1 + else + echo "OK" + fi +} + + +backup() +{ + echo -n "Backing-up Warden server directory ... " + mkdir $backup_dir + if cp -R ${server_path}/* $backup_dir 2> $err; then + echo "OK" + else + err + fi +} + + +obtain_warden_user() +{ + echo -n "Obtaining Warden server directory owner ... " + if user=`stat -c %U $server_conf_file` 2> $err; then + echo "OK" + else + err + fi +} + + +update_warden_dir() +{ + echo -n "Updating Warden server directory ... " + if rsync -q --recursive --archive --delete --exclude='etc' --exclude='sh' ${dirname}/warden-server $prefix 2> $err; then + echo "OK" + else + err_clean + fi + cp ${dirname}/warden-server/etc/package_version $etc + cp ${dirname}/uninstall.sh $server_path +} + + +update_conf_files() +{ + echo -n "Updating $apache_conf_file ... " + + ssl_certificate_file=`cat $apache_conf_file | grep 'SSLCertificateFile'` + ssl_certificate_key_file=`cat $apache_conf_file | grep 'SSLCertificateKeyFile'` + ssl_ca_certificate_file=`cat $apache_conf_file | grep 'SSLCACertificateFile'` + perl_switches=`cat $apache_conf_file | grep 'PerlSwitches'` + + echo "# +# warden-apache.conf - configuration file for the Apache server +# + +SSLEngine on + +SSLVerifyDepth 3 +SSLVerifyClient require +SSLOptions +StdEnvVars +ExportCertData + +SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL + +$ssl_certificate_file +$ssl_certificate_key_file +$ssl_ca_certificate_file + +PerlOptions +Parent +$perl_switches + +<Location /Warden> + SetHandler perl-script + PerlHandler Warden::ApacheDispatch + SSLOptions +StdEnvVars +</Location>" > $apache_conf_file 2> $err; ret_val=`echo $?` + + if [ $ret_val -eq 0 ]; then + echo "OK" + else + err_clean + fi + +#------------------------------------------------------------------------------- + + echo -n "Updating $client_conf_file ... " + + uri=`cat $client_conf_file | grep '$URI'` + ssl_key_file=`cat $client_conf_file | grep '$SSL_KEY_FILE'` + ssl_cert_file=`cat $client_conf_file | grep '$SSL_CERT_FILE'` + ssl_ca_file=`cat $client_conf_file | grep '$SSL_CA_FILE'` + + echo "# +# warden-client.conf - configuration file for registration and status clients +# + +#------------------------------------------------------------------------------- +# URI - URI address of Warden server +#------------------------------------------------------------------------------- +$uri + +#------------------------------------------------------------------------------- +# SSL_KEY_FILE - path to server SSL certificate key file +#------------------------------------------------------------------------------- +$ssl_key_file + +#------------------------------------------------------------------------------- +# SSL_CERT_FILE - path to server SSL certificate file +#------------------------------------------------------------------------------- +$ssl_cert_file + +#------------------------------------------------------------------------------- +# SSL_CA_FILE - path to CA certificate file +#------------------------------------------------------------------------------- +$ssl_ca_file" > $client_conf_file 2> $err; ret_val=`echo $?` + + if [ $ret_val -eq 0 ]; then + echo "OK" + else + err_clean + fi + +#------------------------------------------------------------------------------- + + echo -n "Updating $server_conf_file ... " + + basedir=`cat $server_conf_file | grep '$BASEDIR'` + syslog=`cat $server_conf_file | grep '$SYSLOG' | head -n1` + if [ -z "$syslog" ]; then + syslog='$SYSLOG = 1;' + fi + syslog_verbose=`cat $server_conf_file | grep '$SYSLOG_VERBOSE'` + if [ -z "$syslog_verbose" ]; then + syslog_verbose='$SYSLOG_VERBOSE = 1;' + fi + syslog_facility=`cat $server_conf_file | grep '$SYSLOG_FACILITY'` + if [ -z "$syslog_facility" ]; then + syslog_facility=`cat $server_conf_file | grep '$FACILITY'` + else + syslog_facility='$SYSLOG_FACILITY = "local7";' + fi + db_name=`cat $server_conf_file | grep '$DB_NAME'` + db_user=`cat $server_conf_file | grep '$DB_USER'` + db_pass=`cat $server_conf_file | grep '$DB_PASS'` + db_host=`cat $server_conf_file | grep '$DB_HOST'` + max_events_limit=`cat $server_conf_file | grep '$MAX_EVENTS_LIMIT'` + if [ -z "$max_events_limit" ]; then + max_events_limit='$MAX_EVENTS_LIMIT = 1000000;' + fi + valid_strings=`cat $server_conf_file | grep -A 3 '%VALID_STRINGS'` + if [ -z "$valid_strings" ]; then + valid_strings="%VALID_STRINGS = ( + \"type\" => [\"portscan\", \"bruteforce\", \"probe\", \"spam\", \"phishing\", \"botnet_c_c\", \"dos\", \"malware\", \"copyright\", \"webattack\", \"test\", \"other\"], + \"source_type\" => [\"IP\", \"URL\", \"Reply-To:\"] +);" + fi + + echo "# +# warden-server.conf - configuration file for Warden server +# + +#------------------------------------------------------------------------------- +# BASEDIR - base directory of Warden server +#------------------------------------------------------------------------------- +$basedir + +#------------------------------------------------------------------------------- +# SYSLOG - enable/disable syslog logging +#------------------------------------------------------------------------------- +$syslog + +#------------------------------------------------------------------------------- +# SYSLOG_VERBOSE - enable/disable logging in verbose mode (stack info added) +#------------------------------------------------------------------------------- +$syslog_verbose + +#------------------------------------------------------------------------------- +# SYSLOG_FACILITY - syslog facility +#------------------------------------------------------------------------------- +$syslog_facility + +#------------------------------------------------------------------------------- +# DB_NAME - MySQL database name of Warden server +#------------------------------------------------------------------------------- +$db_name + +#------------------------------------------------------------------------------- +# DB_USER - MySQL database user of Warden server +#------------------------------------------------------------------------------- +$db_user + +#------------------------------------------------------------------------------- +# DB_PASS - MySQL database password of Warden server +#------------------------------------------------------------------------------- +$db_pass + +#------------------------------------------------------------------------------- +# DB_HOST - MySQL database host +#------------------------------------------------------------------------------- +$db_host + +#------------------------------------------------------------------------------- +# MAX_EVENTS_LIMIT - server limit of maximum number of events that can be +# delivered to one client in one batch +#------------------------------------------------------------------------------- +$max_events_limit + +#------------------------------------------------------------------------------- +# VALID_STRINGS - validation hash containing allowed event attributes +#------------------------------------------------------------------------------- +$valid_strings" > $server_conf_file 2> $err; ret_val=`echo $?` + + if [ $ret_val -eq 0 ]; then + echo "OK" + else + err_clean + fi +} + + + +#------------------------------------------------------------------------------- +# MAIN +#------------------------------------------------------------------------------- + +# list of used Perl modules +modules=(SOAP::Lite SOAP::Transport::HTTP DBI DBD::mysql Format::Human::Bytes Sys::Syslog File::Basename Net::CIDR::Lite DateTime Getopt::Std Switch IO::Socket::SSL MIME::Base64 Crypt::X509 Carp) + +# read input +while getopts "d:Vh" options; do + case $options in + d ) prefix=$OPTARG;; + h ) usage;; + V ) version;; + * ) usage;; + esac +done + +# root test +root_chck + +# params test +params_chck + +# create variables +dirname=`dirname $0` +package_version=`cat ${dirname}/warden-server/etc/package_version` +[[ $prefix == */ ]] && prefix="${prefix%?}" # remove last char (slash) from prefix +server_path="${prefix}/warden-server" +etc="${server_path}/etc" +doc="${server_path}/doc" +old_package_version_file="${etc}/package_version" +apache_conf_file="${etc}/warden-apache.conf" +client_conf_file="${etc}/warden-client.conf" +server_conf_file="${etc}/warden-server.conf" +err="/tmp/warden-err" +backup_dir="/tmp/warden-server-backup" + +# obtain version of old warden server +obtain_package_version + +echo +echo "------------------------- Dependencies check-in -------------------------" + +# Perl interpreter test +perl_chck + +# Perl modules test +modules_chck + +echo +echo "------------------------- Update process --------------------------------" + +# check warden server directory +warden_dir_chck + +# backup old warden server installation +backup + +# obtain current warden server user +obtain_warden_user + +# make warden server directory +update_warden_dir + +# create conf files +update_conf_files + +echo +echo "Please check updated configuration files:" +echo " - $apache_conf_file" +echo " - $server_conf_file" +echo " - $client_conf_file" +echo +echo "Warden server directory: $server_path" +echo +echo "Update from $old_package_version to $package_version package was SUCCESSFUL!!!" +echo +echo "Please follow post-update steps in ${doc}/UPDATE!" +echo + +# cleanup section +rm -rf $err $backup_dir + +exit 0