Skip to content
Snippets Groups Projects
WardenClientReceive.pm 7.49 KiB
Newer Older
Tomáš Plesník's avatar
Tomáš Plesník committed
#!/usr/bin/perl -w
#
# WardenClientReceive.pm
#
Tomáš Plesník's avatar
Tomáš Plesník committed
# Copyright (C) 2011-2012 Cesnet z.s.p.o
Tomáš Plesník's avatar
Tomáš Plesník committed
# Author(s): 	Tomas PLESNIK 	<plesnik@ics.muni.cz>
Tomáš Plesník's avatar
Tomáš Plesník committed
#
# 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
Tomáš Plesník's avatar
Tomáš Plesník committed
# 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 WardenClientReceive;

use strict;
use SOAP::Lite;
use IO::Socket::SSL qw(debug1);
use SOAP::Transport::HTTP;
Tomáš Plesník's avatar
Tomáš Plesník committed
use FindBin;

our $VERSION = "1.3"; #first iteration after 'port to Apache'
Tomáš Plesník's avatar
Tomáš Plesník committed

#-------------------------------------------------------------------------------
# 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 
{
Tomáš Plesník's avatar
Tomáš Plesník committed
  my $ssl_key_file	= shift;
  my $ssl_cert_file	= shift;
  my $ssl_ca_file	  = shift;
  my $method		    = shift;
  my $data		      = shift;
Tomáš Plesník's avatar
Tomáš Plesník committed

  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->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);
Tomáš Plesník's avatar
Tomáš Plesník committed

  # setting of URI and serialize SOAP envelope and data object
  my $soap     = SOAP::Lite->uri($service)->proxy($uri);
Tomáš Plesník's avatar
Tomáš Plesník committed
  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);
Tomáš Plesník's avatar
Tomáš Plesník committed

  # 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.");
Tomáš Plesník's avatar
Tomáš Plesník committed
  } 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;
  }
}


Tomáš Plesník's avatar
Tomáš Plesník committed
#-------------------------------------------------------------------------------
# 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 = $_;
    }
    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)
    )
  );
  
  # call server method getNewEvents 
  my $response = c2s($uri, $ssl_key_file, $ssl_cert_file, $ssl_ca_file, "getNewEvents", $request_data);
Tomáš Plesník's avatar
Tomáš Plesník committed

Tomáš Plesník's avatar
Tomáš Plesník committed
  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);
Tomáš Plesník's avatar
Tomáš Plesník committed
    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'};
Tomáš Plesník's avatar
Tomáš Plesník committed

    # 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);
Tomáš Plesník's avatar
Tomáš Plesník committed
    push (@events, \@event);

    # set maximum received ID from current batch
    if ($id > $last_id) {
	    $last_id = $id;
Tomáš Plesník's avatar
Tomáš Plesník committed
    }
Tomáš Plesník's avatar
Tomáš Plesník committed

  # write last return ID
  if (defined $last_id) { # must be defined for first check ID
Tomáš Plesník's avatar
Tomáš Plesník committed
    open(ID, "> $id_file") || die ("Cannot open ID file $id_file: $!");
    print ID $last_id;
    close ID;
  }

  return @events;
Tomáš Plesník's avatar
Tomáš Plesník committed
} # End of getNewEvents

1;