# WardenClient.pm # # Copyright (C) 2011-2015 Cesnet z.s.p.o # # Use of this source is governed by a BSD-style license, see LICENSE file. package WardenClient; use strict; use warnings; use SOAP::Lite; use File::Basename; my $lib = File::Basename::dirname(__FILE__); use lib $lib; use WardenClientCommon; ################################################################################ # VARIABLES ################################################################################ our $VERSION = "2.2"; our $VAR = "$lib/../var"; ################################################################################ # READING OF CONFIGURATION FILE ################################################################################ # load server configuration my $etc = "$lib/../etc"; my $conf_file = "$etc/warden-client.conf"; WardenClientCommon::loadConf($conf_file); ################################################################################ # FUNCTIONS ################################################################################ #------------------------------------------------------------------------------- # saveNewEvent - send new event from detection scripts to warden server #------------------------------------------------------------------------------- sub saveNewEvent { my $event_ref = shift; # 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]; # Issue #596 - Should be removed in Warden client 3.0. # check if obsolete event attribute 'Priority' is used if ((defined $priority) && ($priority >= 0)) { WardenClientCommon::errMsg("Event attribute 'Priority' is now obsolete and will be removed in Warden client v.3.0", "warn"); } # check if obsolete event attribute 'Timeout' is used if ((defined $timeout) && ($timeout >= 0)) { WardenClientCommon::errMsg("Event attribute 'Timeout' is now obsolete and will be removed in Warden client v.3.0", "warn"); } # end of Issue #596 # create SOAP data object my $event; eval { $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) ) ); } or WardenClientCommon::errMsg("Error when creating SOAP data object: " . $@); my $result = WardenClientCommon::c2s("saveNewEvent", $event); defined $result ? return 1 : return 0; } # End of saveNewEvent #------------------------------------------------------------------------------- # getNewEvents - get new events from warden server greater than last received ID #------------------------------------------------------------------------------- sub getNewEvents { my $requested_type = shift; # set name of ID file based on caller name (each client application) my ($caller_name) = ($FindBin::Script =~ /^(.*)$/); # untaint my $id_file = $VAR . $caller_name . "-". ($requested_type || "any") . ".id"; # get last event ID my $last_id; if (-e $id_file) { # get ID from ID file open(FILE, "< $id_file") or return WardenClientCommon::errMsg("Cannot open ID file $id_file: $!"); foreach(<FILE>) { $last_id = $_; } close FILE; } else { # get ID from Warden server database and print it into the ID file my $response = WardenClientCommon::c2s("getLastId"); defined $response or return; $last_id = $response->result; open(FILE, "> $id_file") or return WardenClientCommon::errMsg("Cannot open ID file $id_file: $!"); print FILE $last_id; close FILE; } # prepare SOAP data object for Warden server my $request_data; eval { $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 => $WardenClientCommon::MAX_RCV_EVENTS_LIMIT) ) ) } or return WardenClientCommon::errMsg('Unknown error when creating SOAP data object, ' . $@); # call server method getNewEvents my $response = WardenClientCommon::c2s("getNewEvents", $request_data); defined $response or return; # parse server response (SOAP data object) my @events; 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; $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'}; @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; } } # print last returned event ID into ID file if (defined $last_id) { open(FILE, "> $id_file") or return WardenClientCommon::errMsg("Cannot open ID file $id_file: $!"); print FILE $last_id; close FILE; } return @events; } # End of getNewEvents #------------------------------------------------------------------------------- # getClientInfo - retrieve information about other clients from Warden server #------------------------------------------------------------------------------- sub getClientInfo { # obtain information about clients on Warden server my $response = c2s("getClientInfo"); defined $response or return; # receive data or return undef # parse server response (SOAP data object) my @clients; my @response_list = $response->valueof('/Envelope/Body/getClientInfoResponse/client/'); while (scalar @response_list) { my $response_data = shift(@response_list); my %client; $client{'client_id'} = $response_data->{'CLIENT_ID'} ; $client{'hostname'} = $response_data->{'HOSTNAME'}; $client{'registered'} = $response_data->{'REGISTERED'}; $client{'requestor'} = $response_data->{'REQUESTOR'}; $client{'service'} = $response_data->{'SERVICE'}; $client{'client_type'} = $response_data->{'CLIENT_TYPE'}; $client{'type'} = $response_data->{'TYPE'}; $client{'receive_own_events'} = $response_data->{'RECEIVE_OWN_EVENTS'}; $client{'description_tags'} = $response_data->{'DESCRIPTION_TAGS'}; $client{'ip_net_client'} = $response_data->{'IP_NET_CLIENT'}; push (@clients,\%client); } return @clients; } # End of getClientInfo 1;