diff --git a/src/warden-server/bin/getStatus.pl b/src/warden-server/bin/getStatus.pl index bc788f470b570c3a4e8c3f26c6b8ad9f2d98fff0..403810134e4c12fb24431cbe0247eae737ebfc13 100755 --- a/src/warden-server/bin/getStatus.pl +++ b/src/warden-server/bin/getStatus.pl @@ -102,14 +102,14 @@ my @server_status = @$server_status_ref; print "Warden server variables:\n"; print "========================\n"; print "SERVER_VERSION:\t\t$server_status[0]\n"; -print "ADDRESS:\t\t$server_status[1]\n"; -print "PORT:\t\t\t$server_status[2]\n"; +#print "ADDRESS:\t\t$server_status[1]\n"; +#print "PORT:\t\t\t$server_status[2]\n"; print "LOGDIR:\t\t\t$server_status[3]\n"; -print "PIDDIR:\t\t\t$server_status[4]\n"; +#print "PIDDIR:\t\t\t$server_status[4]\n"; print "VARDIR:\t\t\t$server_status[5]\n"; -print "SSL_KEY_FILE:\t\t$server_status[6]\n"; -print "SSL_CERT_FILE:\t\t$server_status[7]\n"; -print "SSLCA_FILE:\t\t$server_status[8]\n"; +#print "SSL_KEY_FILE:\t\t$server_status[6]\n"; +#print "SSL_CERT_FILE:\t\t$server_status[7]\n"; +#print "SSLCA_FILE:\t\t$server_status[8]\n"; print "SYSLOG_FACILITY:\t$server_status[9]\n"; print "\n"; diff --git a/src/warden-server/bin/warden-server.pl b/src/warden-server/bin/warden-server.pl index 0e53be5b8517dd688aa45a534dd83bd51009fb21..1f06dbd5d96a0c4981883ff4b6fd0fcb549bd68a 100755 --- a/src/warden-server/bin/warden-server.pl +++ b/src/warden-server/bin/warden-server.pl @@ -96,7 +96,7 @@ 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"; ################################################################################ @@ -246,38 +246,38 @@ sub saveNewEvent #----------------------------------------------------------------------------- # 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); - } + # $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 { - + # 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(); + #$DBH->commit(); # log last inserted ID - $sth = $DBH->prepare("SELECT last_insert_rowid();"); + $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: $an)"); + 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);"); @@ -285,7 +285,7 @@ sub saveNewEvent } else { return 1; } - } + } } # END of saveNewEvent @@ -810,12 +810,12 @@ write2log("info", "Size of DB file ($db_file) is: $db_size_human"); # start TCP server my $server = SOAP::Transport::TCP::Server ->new( - Listen => 5, + Listen => 20, LocalAddr => $ADDRESS, LocalPort => $PORT, Proto => "tcp", ReuseAddr => 1, - SSL_verify_mode => 0x03, + SSL_verify_mode => 0x02, SSL_use_cert => 1, SSL_server => 1, SSL_key_file => $SSL_KEY_FILE, diff --git a/src/warden-server/doc/warden-apache.readme b/src/warden-server/doc/warden-apache.readme new file mode 100644 index 0000000000000000000000000000000000000000..4698aaab835e418c59453944ff9834ab47f4341e --- /dev/null +++ b/src/warden-server/doc/warden-apache.readme @@ -0,0 +1,46 @@ +apache2 +mysql-server +a2enmod ssl +libapache2-mod-perl2 +mysql -u root -p < warden.sql +libcrypt-x509-perl +libmime-base64-perl +apache2-mpm-prefork + +<IfModule mpm_prefork_module> + StartServers 2 + MinSpareServers 4 + MaxSpareServers 8 + ServerLimit 700 + MaxClients 700 + MaxRequestsPerChild 0 +</IfModule> +Timeout 10 +KeepAlive Off + + +Instalace Apache +Povoleni SSL +Instalace mod_perl +Apache - Virtual Host <*:443> - pro jine jeste povolit port +Include cesty do Apache +Nastaveni spravnych Adres - klient, server +Nastaveni db na serveru +Pouziti jineho cert server/client +Instalace 2 balicku +Instalace prefork +nastavni apache2.conf +================ +Instalace DB +restore db z adr. etc/warden.sql + +==== +Instalace serveru do jine cesty nez /opt -> nevytvari adresar, nemaze pri odinstalaci + + + + + + + + diff --git a/src/warden-server/doc/warden.mysql b/src/warden-server/doc/warden.mysql new file mode 100644 index 0000000000000000000000000000000000000000..043e76dec7b81f7dd414be2e66a7f568111e5167 --- /dev/null +++ b/src/warden-server/doc/warden.mysql @@ -0,0 +1,84 @@ +-- MySQL dump 10.11 +-- +-- Host: localhost Database: warden +-- ------------------------------------------------------ +-- Server version 5.0.51a-24+lenny3 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `warden` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `warden` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `warden`; + +-- +-- Table structure for table `clients` +-- + +DROP TABLE IF EXISTS `clients`; +SET @saved_cs_client = @@character_set_client; +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, + `requestor` varchar(256) default NULL, + `service` varchar(64) default NULL, + `client_type` varchar(1) default NULL, + `type` varchar(64) default NULL, + `receive_own_events` varchar(1) default NULL, + `description_tags` varchar(256) default NULL, + `ip_net_client` varchar(256) default NULL, + PRIMARY KEY (`client_id`) +) ENGINE=MyISAM AUTO_INCREMENT=16 DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `events` +-- + +DROP TABLE IF EXISTS `events`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; +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, + `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, + `note` text, + `priority` int(1) default NULL, + `timeout` int(2) default NULL, + `valid` varchar(1) default NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=31 DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2012-03-22 15:29:35 diff --git a/src/warden-server/etc/warden-apache.conf b/src/warden-server/etc/warden-apache.conf new file mode 100644 index 0000000000000000000000000000000000000000..77f5d19c989ebfaae1527c9694dd401b009e45dc --- /dev/null +++ b/src/warden-server/etc/warden-apache.conf @@ -0,0 +1,25 @@ + SSLEngine on + + SSLVerifyDepth 3 + SSLVerifyClient require + SSLOptions +StdEnvVars +ExportCertData + + SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL + + SSLCertificateFile server-cert.pem + SSLCertificateKeyFile server-key.pem + SSLCACertificateFile ca-cert.pem + + #Mozno umistit jeste pred samotny <VirtualHost> + #http://perl.apache.org/docs/2.0/user/config/config.html#C_Parent_ + #Create a new parent Perl interpreter for the given VirtualHost and give it its own interpreter pool + + PerlOptions +Parent + PerlSwitches -I/opt/warden-server/lib + + <Location /Warden> + SetHandler perl-script + PerlHandler Warden::ApacheDispatch + SSLOptions +StdEnvVars + </Location> + diff --git a/src/warden-server/lib/Warden.pm b/src/warden-server/lib/Warden.pm new file mode 100755 index 0000000000000000000000000000000000000000..a4474b32702d92cf0cf1e40276ce2f4ce1f567c3 --- /dev/null +++ b/src/warden-server/lib/Warden.pm @@ -0,0 +1,998 @@ +#!/usr/bin/perl -w +# +# 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 SOAP::Transport::HTTP; +#use File::Pid; +#use POSIX; +use DBI; +use DBD::mysql; +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; +#use Crypt::OpenSSL::X509; +use MIME::Base64; +use Crypt::X509; + +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; + +#DB options +our $DB_NAME = undef; +our $DB_USER = undef; +our $DB_PASS = undef; +our $DB_HOST = undef; + +# +#$ADDRESS = "147.228.52.72"; +## +###------------------------------------------------------------------------------- +### PORT - used TCP port for Warden server +###------------------------------------------------------------------------------- +#$PORT = "8889"; +## +###------------------------------------------------------------------------------- +### BASEDIR - base directory of Warden server +###------------------------------------------------------------------------------- +#our $BASEDIR = "/opt/warden-server/"; +## +###------------------------------------------------------------------------------- +### VARDIR - var directory +###------------------------------------------------------------------------------- +#$VARDIR = "$BASEDIR/var/"; +## +###------------------------------------------------------------------------------- +### LOGDIR - logging directory +###------------------------------------------------------------------------------- +#$LOGDIR = "/var/log/"; +## +###------------------------------------------------------------------------------- +### PIDDIR - process ID directory +###------------------------------------------------------------------------------- +#$PIDDIR = "/var/run/"; +## +## +## +## 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=$DB_NAME;host=$DB_HOST", $DB_USER, $DB_PASS, {RaiseError => 1, mysql_auto_reconnect => 0}) || die "Could not connect to database: $DBI::errstr"; +#our $DBH; + +################################################################################ +# 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 $CN = $ENV{'SSL_CLIENT_S_DN_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; + + + push @an_array, "'$CN'"; + my @a = split("\n", $ENV{'SSL_CLIENT_CERT'}); + pop @a; + shift @a; + my $der = decode_base64(join("", @a)); + my $decoded= Crypt::X509->new(cert => $der); + + foreach my $tmp (@{$decoded->SubjectAltName}){ + if($tmp =~ s/dNSName=//){ + push @an_array, "'$tmp'"; + } + } + + 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 @alt_names_array = $socket->peer_certificate("subjectAltNames"); + my $CN = $ENV{'SSL_CLIENT_S_DN_CN'}; + my $AN_FILTER = altNamesFilter(undef); + my $IP = $ENV{'REMOTE_ADDR'}; + my $LOCAL_IP = $ENV{'SERVER_ADDR'}; + + 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_id()"); + 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!"); + return 0; + } else { + return 1; + } + } + + #$DBH->disconnect(); +} # 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 = $ENV{'SSL_CLIENT_S_DN_CN'}; + my $AN_FILTER = altNamesFilter(undef); + my $IP = $ENV{'REMOTE_ADDR'}; + + 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') { + write2log("info", "SELECT * FROM events WHERE type != 'test' AND id > $last_id_db AND type = $requested_type_db AND valid = 't' ORDER BY id ASC;"); + $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"); + write2log("info", "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;"); + $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; + + my $CN = $ENV{'SSL_CLIENT_S_DN_CN'}; + my $IP = $ENV{'REMOTE_ADDR'}; + my $LOCAL_IP = $ENV{'SERVER_ADDR'}; + + + + 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; + my $CN = $ENV{'SSL_CLIENT_S_DN_CN'}; + my $IP = $ENV{'REMOTE_ADDR'}; + my $LOCAL_IP = $ENV{'SERVER_ADDR'}; + + + + 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; + my $CN = $ENV{'SSL_CLIENT_S_DN_CN'}; + my $IP = $ENV{'REMOTE_ADDR'}; + my $LOCAL_IP = $ENV{'SERVER_ADDR'}; + + + 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; + + my $CN = $ENV{'SSL_CLIENT_S_DN_CN'}; + my $IP = $ENV{'REMOTE_ADDR'}; + my $LOCAL_IP = $ENV{'SERVER_ADDR'}; + + + 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; + my $CN = $ENV{'SSL_CLIENT_S_DN_CN'}; + my $IP = $ENV{'REMOTE_ADDR'}; + my $LOCAL_IP = $ENV{'SERVER_ADDR'}; + + + 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); + + $sth = $DBH->prepare("SELECT data_length + index_length FROM information_schema.TABLES WHERE table_schema = ? AND TABLE_NAME = ?"); + $sth->execute("warden", "events"); + my $db_size_db = $sth->fetchrow(); + my $db_size = (defined $db_size_db ? Format::Human::Bytes::base10($db_size_db) : "none"); + + # 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 => 5, +## 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 = $ENV{'SSL_CLIENT_S_DN_CN'}; +# my @alt_names_array = $socket->peer_certificate("subjectAltNames"); +# our $AN_FILTER = altNamesFilter(undef); +# our $IP = $ENV{'REMOTE_ADDR'}; +# our $LOCAL_IP = $ENV{'SERVER_ADDR'}; +## +## # 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; +## } +##} +# +1; + diff --git a/src/warden-server/lib/Warden/ApacheDispatch.pm b/src/warden-server/lib/Warden/ApacheDispatch.pm new file mode 100644 index 0000000000000000000000000000000000000000..ebd7ad68b31497bdb4a3cb05d14a4aeb445e8d63 --- /dev/null +++ b/src/warden-server/lib/Warden/ApacheDispatch.pm @@ -0,0 +1,7 @@ +package Warden::ApacheDispatch; + use SOAP::Transport::HTTP; +my $server = SOAP::Transport::HTTP::Apache->dispatch_to('.','Warden'); + sub handler { + $server->handler(@_) + } +1; diff --git a/src/warden-server/lib/WardenReg.pm b/src/warden-server/lib/WardenReg.pm index 06c8f59fbedc2059c38fd223773e83e867e74c0a..2da50837c51c78ab887c584a14bde283c6533a47 100755 --- a/src/warden-server/lib/WardenReg.pm +++ b/src/warden-server/lib/WardenReg.pm @@ -36,7 +36,8 @@ package WardenReg; use strict; use SOAP::Lite; use IO::Socket::SSL qw(debug1); -use SOAP::Transport::TCP; +#use SOAP::Transport::TCP; +use SOAP::Transport::HTTP; our $VERSION = "0.1"; @@ -54,34 +55,81 @@ sub 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::TCP::Client->new( +# PeerAddr => $server, +# PeerPort => $port, +# Proto => 'tcp', +# 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, +# ))) {errMsg("Sorry, unable to create socket: " . &SOAP::Transport::TCP::Client::errstr)} +# +# # setting of URI and serialize SOAP envelope and data object +# my $soap = SOAP::Lite->uri($uri); +# my $envelope = $soap->serializer->envelope(method => $method, $data); +# +# # setting of TCP URI and send serialized SOAP envelope and data +# my $tcp_uri = "tcp://$server:$port/$service"; +# my $result = $client->send_receive(envelope => $envelope, endpoint => $tcp_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; +# } +#} +# 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 $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::TCP::Client->new( - PeerAddr => $server, - PeerPort => $port, - Proto => 'tcp', - 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, - ))) {errMsg("Sorry, unable to create socket: " . &SOAP::Transport::TCP::Client::errstr)} + if (!($client = SOAP::Transport::HTTP::Client->new( +# ssl_opts => { +# verify_hostname => 0, +# 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 +#} +))) {errMsg("Sorry, unable to create socket: " . &SOAP::Transport::HTTP::Client::errstr)} + $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($uri); + 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 $tcp_uri = "tcp://$server:$port/$service"; +# setting of TCP URI and send serialized SOAP envelope and data + my $tcp_uri = "https://$server:$port/$service"; my $result = $client->send_receive(envelope => $envelope, endpoint => $tcp_uri); # check server response @@ -95,6 +143,9 @@ sub c2s } } + + + #------------------------------------------------------------------------------- # registerSender - register new warden sender #------------------------------------------------------------------------------- diff --git a/src/warden-server/lib/WardenStatus.pm b/src/warden-server/lib/WardenStatus.pm index 4eed30f874a288f997deac67f0cc2936358bbef8..e11afc2db2d27f7ac40fd88ca3bed3bc728d9cbc 100755 --- a/src/warden-server/lib/WardenStatus.pm +++ b/src/warden-server/lib/WardenStatus.pm @@ -36,9 +36,11 @@ package WardenStatus; use strict; use SOAP::Lite; use IO::Socket::SSL qw(debug1); -use SOAP::Transport::TCP +#use SOAP::Transport::TCP; +use SOAP::Transport::HTTP; +#use Data::Dumper; +our $VERSION = "0.1"; -our $VERSION = "0.2"; #------------------------------------------------------------------------------- # errMsg - print error message and die @@ -53,33 +55,79 @@ sub 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 $client; +# my ($server, $port, $service) = $uri =~ /https:\/\/(.+)\:(\d+)\/(.+)/; +# if (!($client = SOAP::Transport::TCP::Client->new( +# PeerAddr => $server, +# PeerPort => $port, +# Proto => 'tcp', +# 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, +# ))) {errMsg("Sorry, unable to create socket: " . &SOAP::Transport::TCP::Client::errstr)} +# +# # setting of URI and serialize SOAP envelope and data object +# my $soap = SOAP::Lite->uri($uri); +# my $envelope = $soap->serializer->envelope(method => $method); +# +# # setting of TCP URI and send serialized SOAP envelope and data +# my $tcp_uri = "tcp://$server:$port/$service"; +# my $result = $client->send_receive(envelope => $envelope, endpoint => $tcp_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; +# } +#} sub c2s { - my $uri = shift; - my $ssl_key_file = shift; - my $ssl_cert_file = shift; - my $ssl_ca_file = shift; - my $method = shift; + 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::TCP::Client->new( - PeerAddr => $server, - PeerPort => $port, - Proto => 'tcp', - 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, - ))) {errMsg("Sorry, unable to create socket: " . &SOAP::Transport::TCP::Client::errstr)} + if (!($client = SOAP::Transport::HTTP::Client->new( +# ssl_opts => { +# verify_hostname => 0, +# 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 +#} +))) {errMsg("Sorry, unable to create socket: " . &SOAP::Transport::HTTP::Client::errstr)} + $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($uri); + my $soap = SOAP::Lite->uri($service)->proxy($uri); my $envelope = $soap->serializer->envelope(method => $method); - # setting of TCP URI and send serialized SOAP envelope and data - my $tcp_uri = "tcp://$server:$port/$service"; +# setting of TCP URI and send serialized SOAP envelope and data + my $tcp_uri = "https://$server:$port/$service"; my $result = $client->send_receive(envelope => $envelope, endpoint => $tcp_uri); # check server response @@ -109,33 +157,39 @@ sub getClients my $conf_file = $etcdir . "warden-client.conf"; my ($uri, $ssl_key_file, $ssl_cert_file, $ssl_ca_file) = WardenConf::loadConf($conf_file); - # call server method getClients my $response = c2s($uri, $ssl_key_file, $ssl_cert_file, $ssl_ca_file, "getClients"); + # match getClients functions response + $response->match('/Envelope/Body/getClientsResponse/'); + my $i = 1; my ($client_id, $hostname, $registered, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); my @clients; + my $response_data = $response->valueof("[$i]"); - # parse returned SOAP data object - my @response_list = $response->valueof('/Envelope/Body/getClientsResponse/'); - while (scalar @response_list) { - my $response_data = shift(@response_list); + # parse returned data object + while (defined $response_data) { + # inicialization of temporal client array my @client; # parse items of one client - $client_id = $response_data->{'CLIENT_ID'}; + $client_id = $response_data->{'CLIENT_ID'} ; $hostname = $response_data->{'HOSTNAME'}; $registered = $response_data->{'REGISTERED'}; $requestor = $response_data->{'REQUESTOR'}; $service = $response_data->{'SERVICE'}; $client_type = $response_data->{'CLIENT_TYPE'}; - $type = $response_data->{'TYPE'}; - $receive_own_events = $response_data->{'RECEIVE_OWN_EVENTS'}; - $description_tags = $response_data->{'DESCRIPTION_TAGS'}; + $type = defined $response_data->{'TYPE'} ? $response_data->{'TYPE'} : ""; + $receive_own_events = defined $response_data->{'RECEIVE_OWN_EVENTS'} ? $response_data->{'RECEIVE_OWN_EVENTS'} : ""; + $description_tags = defined $response_data->{'DESCRIPTION_TAGS'} ? $response_data->{'DESCRIPTION_TAGS'} : ""; $ip_net_client = $response_data->{'IP_NET_CLIENT'}; # push received clients from warden server into @clients which is returned @client = ("$client_id", "$hostname", "$registered", "$requestor", "$service", "$client_type", "$type", "$receive_own_events", "$description_tags", "$ip_net_client"); push (@clients,\@client); + + # go to the next received client + $i++; + $response_data = $response->valueof("[$i]"); } return @clients; } # End of getClients @@ -156,23 +210,25 @@ sub getStatus my $conf_file = $etcdir . "warden-client.conf"; my ($uri, $ssl_key_file, $ssl_cert_file, $ssl_ca_file) = WardenConf::loadConf($conf_file); - # call server method getStatus my $response = c2s($uri, $ssl_key_file, $ssl_cert_file, $ssl_ca_file, "getStatus"); - # parse returned SOAP data object - my @response_list = $response->valueof('/Envelope/Body/getStatusResponse/'); - my $response_data = shift(@response_list); - + # match getStatus functions response + $response->match('/Envelope/Body/getStatusResponse/'); + my @status; + my $i = 1; + + # get first value from SOAP data object + my $response_data = $response->valueof("[$i]"); # parse items of server status my $version = $response_data->{'VERSION'}; - my $address = $response_data->{'ADDRESS'}; - my $port = $response_data->{'PORT'}; + #my $address = $response_data->{'ADDRESS'}; + #my $port = $response_data->{'PORT'}; my $logdir = $response_data->{'LOGDIR'}; - my $piddir = $response_data->{'PIDDIR'}; + #my $piddir = $response_data->{'PIDDIR'}; my $vardir = $response_data->{'VARDIR'}; - my $ssl_key_file_server = $response_data->{'SSL_KEY_FILE'}; - my $ssl_cert_file_server = $response_data->{'SSL_CERT_FILE'}; - my $ssl_ca_file_server = $response_data->{'SSL_CA_FILE'}; + #my $ssl_key_file_server = $response_data->{'SSL_KEY_FILE'}; + #my $ssl_cert_file_server = $response_data->{'SSL_CERT_FILE'}; + #my $ssl_ca_file_server = $response_data->{'SSL_CA_FILE'}; my $facility = $response_data->{'FACILITY'}; my $db_size = $response_data->{'DB_SIZE'}; my $events_sum = $response_data->{'EVENTS_SUM'}; @@ -181,23 +237,24 @@ sub getStatus my $events_last_timestamp = $response_data->{'EVENTS_LAST_TIMESTAMP'}; my $clients_sum = $response_data->{'CLIENTS_SUM'}; - my @status; - my @server_status = ("$version", "$address", "$port", "$logdir", "$piddir", "$vardir", "$ssl_key_file_server", "$ssl_cert_file_server", "$ssl_ca_file_server", "$facility", "$db_size", "$events_sum", "$events_last_id", "$events_first_timestamp", "$events_last_timestamp", "$clients_sum"); + #my @server_status = ("$version", "$address", "$port", "$logdir", "$piddir", "$vardir", "$ssl_key_file_server", "$ssl_cert_file_server", "$ssl_ca_file_server", "$facility", "$db_size", "$events_sum", "$events_last_id", "$events_first_timestamp", "$events_last_timestamp", "$clients_sum"); + my @server_status = ("$version", undef, undef, "$logdir", undef, "$vardir", undef, undef, undef, "$facility", "$db_size", "$events_sum", "$events_last_id", "$events_first_timestamp", "$events_last_timestamp", "$clients_sum"); push(@status, \@server_status); - while (scalar @response_list) { - my $response_data = shift(@response_list); + $i++; + $response_data = $response->valueof("[$i]"); + while (defined $response_data) { my @client_status; - - # parse item of client status + # parse SOAP data object my $client_id = $response_data->{'CLIENT_ID'}; my $hostname = $response_data->{'HOSTNAME'}; my $service = $response_data->{'SERVICE'}; my $count = $response_data->{'COUNT'}; my $timestamp = $response_data->{'TIMESTAMP'}; - @client_status = ("$client_id", "$hostname", "$service", "$count", "$timestamp"); push(@status, \@client_status); + $i++; + $response_data = $response->valueof("[$i]"); } return @status; } # End of getStatus diff --git a/src/warden-server/sh/install.sh b/src/warden-server/sh/install.sh index 238a086b33175de8eab9d807690a567bfea87260..56102940265250f0394c90c20a3970bc95caad0f 100755 --- a/src/warden-server/sh/install.sh +++ b/src/warden-server/sh/install.sh @@ -160,18 +160,6 @@ perl_chck() fi } -sqlite_chck() -{ - echo -n "Checking SQLite database engine ... " - if which sqlite3 1> /dev/null; then - echo "OK" - else - echo "FAILED!" - echo "Error: SQLite3 database engine is not installed!" - exit 1 - fi -} - modules_chck() { for module in ${modules[@]}; @@ -189,6 +177,7 @@ 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 "OK" else @@ -296,6 +285,11 @@ make_server_conf() # FACILITY - syslog facility #------------------------------------------------------------------------------- \$FACILITY = \"local7\"; + +\$DB_NAME = \"warden\"; +\$DB_USER = \"username\"; +\$DB_PASS = \"\"; +\$DB_HOST = \"localhost\"; " > $server_conf 2> $err; ret_val=`echo $?` if [ $ret_val -eq 0 ]; then @@ -306,18 +300,46 @@ make_server_conf() } -create_db() +changeServerPath() { - 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 + echo "Update server path ..."; + for file in `ls -1 $bin | grep -v warden-alive | grep -v create_tables.sh | grep -v wardend` + 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 ..." @@ -326,8 +348,8 @@ create_symlinks() 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 +# echo "- making symlink: ${bin}/wardend -> $init" +# ln -s ${bin}/wardend $init } @@ -336,7 +358,8 @@ 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=(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 @@ -378,7 +401,9 @@ local_bin="/usr/local/bin" etc="${server_path}/etc" client_conf="${etc}/warden-client.conf" 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" err="/tmp/warden-err" init="/etc/init.d/wardend" @@ -392,8 +417,8 @@ echo "------------------------- Dependencies check-in -------------------------" # Perl interpreter test perl_chck -# SQLite database engine test -sqlite_chck +## SQLite database engine test +#sqlite_chck # Perl modules test modules_chck @@ -410,8 +435,14 @@ make_client_conf # create server configuration file make_server_conf -# create warden server database -create_db +## create warden server database +#create_db + +#update paths in utilities +changeServerPath + +#update paths in apachefile +updateCertsPath # crate symlinks from warden server bin directory to /usr/local/bin create_symlinks @@ -421,7 +452,7 @@ echo "Please check client configuration file in $client_conf!" echo "Please check server configuration file in $server_conf!" echo echo "Warden server directory: $server_path" -echo "Warden server daemon: $init [start|stop|status|restart|force-stop]" +#echo "Warden server daemon: $init [start|stop|status|restart|force-stop]" echo echo "Installation of $package_version package was SUCCESSFUL!!!"