2007-08-02 19:53:07 +02:00
package PandoraFMS::Tools ;
##########################################################################
# Pandora Tools Package
##########################################################################
# Copyright (c) 2004-2007 Sancho Lerena, slerena@gmail.com
# Copyright (c) 2005-2007 Artica Soluciones Tecnologicas S.L
#
#This program is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public License
#as published by the Free Software Foundation; version 2
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
##########################################################################
use warnings ;
use Time::Local ;
use Date::Manip ; # Needed to manipulate DateTime formats of input, output and compare
use POSIX qw( setsid ) ;
2008-06-13 18:42:35 +02:00
use Mail::Sendmail ; # New in 2.0. Used to sendmail internally, without external scripts
2007-08-02 19:53:07 +02:00
require Exporter ;
our @ ISA = ( "Exporter" ) ;
our % EXPORT_TAGS = ( 'all' = > [ qw( ) ] ) ;
our @ EXPORT_OK = ( @ { $ EXPORT_TAGS { 'all' } } ) ;
2008-03-13 19:33:44 +01:00
our @ EXPORT = qw(
pandora_daemonize
logger
limpia_cadena
md5check
float_equal
sqlWrap
is_numeric
clean_blank
2008-06-13 18:42:35 +02:00
pandora_sendmail
2008-06-17 Sancho Lerena <slerena@artica.es>
* config.pm: Added options for xprobe2, and autocreate.
* tools.pm: Added functions pandora_create_agent(), pandora_get_os(),
and pandora_event() (this has been moved from DB.pm).
* pandora_server.conf: Added options for xprobe2, autocreate and
autocreate_group.
* pandora_network: Added support for TCP scanning (not implemented in
console yet), parent detection using traceroute, OS fingerprinting with
xprobe2, event creation using central functions, and some optimizations.
* pandora_server: Added support for agent autocreation, OS detection from
the XML header, and event notification "new_agent" type.
* pandora_recon: First code to implement traceroute functionality
using Pureperl module. Added code for remote OS fingerprinting.
git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@874 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
2008-06-17 19:26:03 +02:00
pandora_create_agent
pandora_get_os
pandora_event
2008-03-13 19:33:44 +01:00
) ;
2007-08-02 19:53:07 +02:00
2008-06-17 Sancho Lerena <slerena@artica.es>
* config.pm: Added options for xprobe2, and autocreate.
* tools.pm: Added functions pandora_create_agent(), pandora_get_os(),
and pandora_event() (this has been moved from DB.pm).
* pandora_server.conf: Added options for xprobe2, autocreate and
autocreate_group.
* pandora_network: Added support for TCP scanning (not implemented in
console yet), parent detection using traceroute, OS fingerprinting with
xprobe2, event creation using central functions, and some optimizations.
* pandora_server: Added support for agent autocreation, OS detection from
the XML header, and event notification "new_agent" type.
* pandora_recon: First code to implement traceroute functionality
using Pureperl module. Added code for remote OS fingerprinting.
git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@874 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
2008-06-17 19:26:03 +02:00
##########################################################################
## SUB pandora_event
## Write in internal audit system an entry.
## Params: config_hash, event_title, group, agent_id, severity, id_alertam
## id_agentmodule, event_type (from a set, as string), db_handle
##########################################################################
sub pandora_event (%$$$$$$$$) {
my $ pa_config = $ _ [ 0 ] ;
my $ evento = $ _ [ 1 ] ;
my $ id_grupo = $ _ [ 2 ] ;
my $ id_agente = $ _ [ 3 ] ;
my $ severity = $ _ [ 4 ] ; # new in 2.0
my $ id_alert_am = $ _ [ 5 ] ; # new in 2.0
my $ id_agentmodule = $ _ [ 6 ] ; # new in 2.0
my $ event_type = $ _ [ 7 ] ; # new in 2.0
my $ dbh = $ _ [ 8 ] ;
my $ timestamp = & UnixDate ( "today" , "%Y-%m-%d %H:%M:%S" ) ;
my $ utimestamp ; # integer version of timestamp
$ utimestamp = & UnixDate ( $ timestamp , "%s" ) ; # convert from human to integer
$ evento = $ dbh - > quote ( $ evento ) ;
$ event_type = $ dbh - > quote ( $ event_type ) ;
$ timestamp = $ dbh - > quote ( $ timestamp ) ;
my $ query = "INSERT INTO tevento (id_agente, id_grupo, evento, timestamp, estado, utimestamp, event_type, id_agentmodule, id_alert_am, criticity) VALUES ($id_agente, $id_grupo, $evento, $timestamp, 0, $utimestamp, $event_type, $id_agentmodule, $id_alert_am, $severity)" ;
$ dbh - > do ( $ query ) ;
}
##########################################################################
# SUB pandora_get_os (string)
# Detect OS using a string, and return id_os
##########################################################################
sub pandora_get_os ($) {
$ command = $ _ [ 0 ] ;
if ( $ command =~ m/Windows/i ) {
return 9 ;
}
elsif ( $ command =~ m/Linux/i ) {
return 1 ;
}
elsif ( $ command =~ m/BSD/i ) {
return 4 ;
}
elsif ( $ command =~ m/Cisco/i ) {
return 7 ;
}
elsif ( $ command =~ m/SunOS/i ) {
return 2 ;
}
elsif ( $ command =~ m/Solaris/i ) {
return 2 ;
}
elsif ( $ command =~ m/AIX/i ) {
return 3 ;
}
elsif ( $ command =~ m/HP-UX/i ) {
return 5 ;
}
else {
return 10 ; # Unknown / Other
}
}
2007-08-02 19:53:07 +02:00
##########################################################################
# Sub daemonize ()
# Put program in background (for daemon mode)
##########################################################################
2008-03-13 19:33:44 +01:00
sub pandora_daemonize {
my $ pa_config = $ _ [ 0 ] ;
open STDIN , '/dev/null' or die "Can't read /dev/null: $!" ;
open STDOUT , '>>/dev/null' or die "Can't write to /dev/null: $!" ;
open STDERR , '>>/dev/null' or die "Can't write to /dev/null: $!" ;
chdir '/tmp' or die "Can't chdir to /tmp: $!" ;
defined ( my $ pid = fork ) or die "Can't fork: $!" ;
2007-08-02 19:53:07 +02:00
exit if $ pid ;
2008-03-13 19:33:44 +01:00
setsid or die "Can't start a new session: $!" ;
2007-08-02 19:53:07 +02:00
umask 0 ;
2008-03-13 19:33:44 +01:00
# Store PID of this process in file presented by config token
if ( $ pa_config - > { 'PID' } ne "" ) {
open ( FILE , "> " . $ pa_config - > { 'PID' } ) or die "[FATAL] Cannot open PIDfile at " . $ pa_config - > { 'PID' } ;
print FILE "$$" ;
close ( FILE ) ;
}
2007-08-02 19:53:07 +02:00
}
# -------------------------------------------+
# Pandora other General functions |
# -------------------------------------------+
2008-06-17 Sancho Lerena <slerena@artica.es>
* config.pm: Added options for xprobe2, and autocreate.
* tools.pm: Added functions pandora_create_agent(), pandora_get_os(),
and pandora_event() (this has been moved from DB.pm).
* pandora_server.conf: Added options for xprobe2, autocreate and
autocreate_group.
* pandora_network: Added support for TCP scanning (not implemented in
console yet), parent detection using traceroute, OS fingerprinting with
xprobe2, event creation using central functions, and some optimizations.
* pandora_server: Added support for agent autocreation, OS detection from
the XML header, and event notification "new_agent" type.
* pandora_recon: First code to implement traceroute functionality
using Pureperl module. Added code for remote OS fingerprinting.
git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@874 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
2008-06-17 19:26:03 +02:00
##########################################################################
# SUB pandora_create_agent (pa_config, dbh, target_ip, target_ip_id,
# id_group, network_server_assigned, name, id_os)
# Create agent, and associate address to agent in taddress_agent table.
# it returns created id_agent.
##########################################################################
sub pandora_create_agent {
my $ pa_config = $ _ [ 0 ] ;
my $ dbh = $ _ [ 1 ] ;
my $ target_ip = $ _ [ 2 ] ;
my $ target_ip_id = $ _ [ 3 ] ;
my $ id_group = $ _ [ 4 ] ;
my $ id_server = $ _ [ 5 ] ;
my $ name = $ _ [ 6 ] ;
my $ id_parent = $ _ [ 7 ] ;
my $ id_os = $ _ [ 8 ] ;
my $ server = $ pa_config - > { 'servername' } . $ pa_config - > { "servermode" } ;
logger ( $ pa_config , "$server: Creating agent $name $target_ip " , 1 ) ;
my $ query_sql2 = "INSERT INTO tagente (nombre, direccion, comentarios, id_grupo, id_os, id_network_server, intervalo, id_parent) VALUES ('$name', '$target_ip', 'Created by $server', $id_group, $id_os, $id_server, 300, $id_parent)" ;
$ dbh - > do ( $ query_sql2 ) ;
my $ lastid = $ dbh - > { 'mysql_insertid' } ;
pandora_event ( $ pa_config , "Agent '$name' created by " . $ pa_config - > { 'servername' } . $ pa_config - > { "servermode" } , $ pa_config - > { 'autocreate_group' } , $ lastid , 2 , 0 , 0 , 'new_agent' , $ dbh ) ;
if ( $ target_ip_id > 0 ) {
my $ query_sql3 = "INSERT INTO taddress_agent (id_a, id_agent) values ($target_ip_id, $lastid)" ;
$ dbh - > do ( $ query_sql3 ) ;
}
return $ lastid ;
}
2008-06-13 18:42:35 +02:00
##########################################################################
# SUB pandora_sendmail
# Send a mail, connecting directly to MTA
# param1 - config hash
# param2 - Destination email addres
# param3 - Email subject
# param4 - Email Message body
##########################################################################
sub pandora_sendmail { # added in 2.0 version
my $ pa_config = $ _ [ 0 ] ;
my $ to_address = $ _ [ 1 ] ;
my $ subject = $ _ [ 2 ] ;
my $ message = $ _ [ 3 ] ;
my % mail = ( To = > $ to_address ,
Message = > $ message ,
Subject = > $ subject ,
Smtp = > $ pa_config - > { "mta_address" } ,
Port = > $ pa_config - > { "mta_port" } ,
From = > $ pa_config - > { "mta_from" } ,
) ;
if ( $ pa_config - > { "mta_user" } ne "" ) {
$ mail { auth } = { user = > $ config - > { "mta_user" } , password = > $ config - > { "mta_pass" } , method = > $ config - > { "mta_auth" } , required = > 0 }
}
eval {
sendmail ( % mail ) ;
} ;
if ( $@ ) {
logger ( $ pa_config , "[ERROR] Sending email to $to_address with subject $subject" , 1 ) ;
logger ( $ pa_config , "ERROR Code: $@" , 4 ) ;
}
}
2007-08-02 19:53:07 +02:00
##########################################################################
# SUB is_numeric
# Return TRUE if given argument is numeric
##########################################################################
sub is_numeric {
$ x = $ _ [ 0 ] ;
if ( ! defined ( $ x ) ) {
return 0 ;
}
if ( $ x eq "" ) {
return 0 ;
}
# Integer ?
if ( $ x =~ /^-?\d/ ) {
return 1 ;
}
# Float ?
if ( $ x =~ /^-?\d*\./ ) {
return 1 ;
}
# If not, this thing is not a number
return 0 ;
}
##########################################################################
# SUB md5check (param_1, param_2)
# Verify MD5 file .checksum
##########################################################################
# param_1 : Name of data file
# param_2 : Name of md5 file
sub md5check {
my $ buf ;
my $ buf2 ;
my $ file = $ _ [ 0 ] ;
my $ md5file = $ _ [ 1 ] ;
open ( FILE , $ file ) or return 0 ;
binmode ( FILE ) ;
my $ md5 = Digest::MD5 - > new ;
while ( <FILE> ) {
$ md5 - > add ( $ _ ) ;
}
close ( FILE ) ;
$ buf2 = $ md5 - > hexdigest ;
open ( FILE , $ md5file ) or return 0 ;
while ( <FILE> ) {
$ buf = $ _ ;
}
close ( FILE ) ;
$ buf = uc ( $ buf ) ;
$ buf2 = uc ( $ buf2 ) ;
if ( $ buf =~ /$buf2/ ) {
#print "MD5 Correct";
return 1 ;
} else {
#print "MD5 Incorrect";
return 0 ;
}
}
##########################################################################
# SUB logger (pa_config, param_1, param_2)
# Log to file
##########################################################################
# param_1 : Data file
# param_2 : Data
sub logger {
my $ pa_config = $ _ [ 0 ] ;
my $ fichero = $ pa_config - > { "logfile" } ;
my $ datos = $ _ [ 1 ] ;
my $ verbose_level = 2 ; # if parameter not passed, verbosity is 5 (DEBUG)
my $ param2 = $ _ [ 2 ] ;
if ( defined $ param2 ) {
if ( is_numeric ( $ param2 ) ) {
$ verbose_level = $ param2 ;
}
}
if ( $ verbose_level <= $ pa_config - > { "verbosity" } ) {
if ( $ verbose_level > 0 ) {
$ datos = "[V" . $ verbose_level . "] " . $ datos ;
}
my $ time_now = & UnixDate ( "today" , "%Y/%m/%d %H:%M:%S" ) ;
open ( FILE , ">> $fichero" ) or die "[FATAL] Cannot open logfile at $fichero" ;
my $ server_name = $ pa_config - > { 'servername' } . $ pa_config - > { "servermode" } ;
print FILE "$time_now $server_name $datos \n" ;
close ( FILE ) ;
}
}
##########################################################################
# limpia_cadena (string) - Purge a string for any forbidden characters (esc, etc)
##########################################################################
sub limpia_cadena {
my $ micadena ;
$ micadena = $ _ [ 0 ] ;
$ micadena =~ s/[^\-\:\;\.\,\_\s\a\*\=\(\)a-zA-Z0-9]/ /g ;
$ micadena =~ s/[\n\l\f]/ /g ;
return $ micadena ;
}
2008-02-25 19:00:09 +01:00
##########################################################################
# clean_blank (string) - Purge a string for any blank spaces in it
##########################################################################
sub clean_blank {
my $ input = $ _ [ 0 ] ;
$ input =~ s/\s//g ;
return $ input ;
}
2007-08-02 19:53:07 +02:00
########################################################################################
# sub sqlWrap(texto)
# Elimina comillas y caracteres problematicos y los sustituye por equivalentes
########################################################################################
sub sqlWrap {
my $ toBeWrapped = shift ( @ _ ) ;
if ( defined $ toBeWrapped ) {
$ toBeWrapped =~ s/\'/\\\'/g ;
$ toBeWrapped =~ s/\"/\\\'/g ;
return "'" . $ toBeWrapped . "'" ;
}
}
##########################################################################
# sub float_equal (num1, num2, decimals)
# This function make possible to compare two float numbers, using only x decimals
# in comparation.
# Taken from Perl Cookbook, O'Reilly. Thanks, guys.
##########################################################################
sub float_equal {
my ( $ A , $ B , $ dp ) = @ _ ;
return sprintf ( "%.${dp}g" , $ A ) eq sprintf ( "%.${dp}g" , $ B ) ;
}
# End of function declaration
# End of defined Code
1 ;
__END__