diff --git a/pandora_server/ChangeLog b/pandora_server/ChangeLog index 56a5f5fd9b..4ce797eeed 100644 --- a/pandora_server/ChangeLog +++ b/pandora_server/ChangeLog @@ -4,6 +4,17 @@ 2009-08-19 Sancho lerena + * pandora_server.spec: Added nmap to required packages, removed xprobe2. + + * lib/PandoraFMS/Config.pm, conf/pandora_server.conf: New token for nmap. + + * lib/PandoraFMS/ReconServer.pm: New parent detection, TCP scanning imple- + mented using NMAP. Implemented TCP profile scanning. + + * lib/PandoraFMS/Tools.pm: Some reordering in pandora_get_os() gives + more accurate OS guessing. enterprise_hook() now don't yell when enterprise + is not found :-) + * pandora_server.spec: Updated some dependencies. Also included the install of pandora_db maintance script in cron.daily. diff --git a/pandora_server/conf/pandora_server.conf b/pandora_server/conf/pandora_server.conf index d029273176..3aa834bfd2 100755 --- a/pandora_server/conf/pandora_server.conf +++ b/pandora_server/conf/pandora_server.conf @@ -172,11 +172,18 @@ mta_address localhost # mta_from: Email address that sends the mail, by default is pandora@localhost # probably you need to change it to avoid problems with your antispam -# xprobe: If provided, is used to detect with recon server, OS fingerprint -# of detected hosts. Xprobe2 is a GNU tool to detect OS types. +# xprobe2: Optional package to detect OS types using advanced TCP/IP +# fingerprinting tecniques, much more accurates than stadard nmap. +# If not provided, nmap is used insted xprobe2 xprobe2 /usr/bin/xprobe2 +# nmap: If provided, is used to detect OS type with recon server using +# advanded OS fingerprint technique. Xprobe2 gives more accurate results +# Nmap is also used to do TCP port scanning in detected host. + +nmap /usr/bin/nmap + # snmpget: Needed to do SNMP checks. By default is on /usr/bin/snmpget snmpget /usr/bin/snmpget diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 65bf696dc3..9e19d9f16a 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -37,7 +37,7 @@ our @EXPORT = qw( # version: Defines actual version of Pandora Server for this module only my $pandora_version = "3.0-dev"; -my $pandora_build = "PS090810"; +my $pandora_build = "PS090819"; our $VERSION = $pandora_version." ".$pandora_build; # Setup hash @@ -195,8 +195,12 @@ sub pandora_load_config { $pa_config->{"mta_auth"} = 'none'; # Introduced on 2.0 (Support LOGIN PLAIN CRAM-MD5 DIGEST-MD) $pa_config->{"mta_from"} = 'pandora@localhost'; # Introduced on 2.0 - # Xprobe2 for recon OS fingerprinting (optional feature to detect OS) - $pa_config->{"xprobe2"} = "/usr/bin/xprobe2"; + # nmap for recon OS fingerprinting and tcpscan (optional) + $pa_config->{"nmap"} = "/usr/bin/nmap"; + + # Xprobe2 for recon OS fingerprinting and tcpscan (optional) + $pa_config->{"xprobe2"} = "/usr/bin/xprobe"; + # Snmpget for snmpget system command (optional) $pa_config->{"snmpget"} = "/usr/bin/snmpget"; @@ -421,6 +425,9 @@ sub pandora_load_config { $pa_config->{"keepalive"} = clean_blank($1); $pa_config->{"keepalive_orig"} = clean_blank($1); } + elsif ($parametro =~ m/^nmap\s(.*)/i) { + $pa_config->{'nmap'}= clean_blank($1); + } elsif ($parametro =~ m/^xprobe2\s(.*)/i) { $pa_config->{'xprobe2'}= clean_blank($1); } diff --git a/pandora_server/lib/PandoraFMS/ReconServer.pm b/pandora_server/lib/PandoraFMS/ReconServer.pm index ae44ff2924..9452a7f613 100644 --- a/pandora_server/lib/PandoraFMS/ReconServer.pm +++ b/pandora_server/lib/PandoraFMS/ReconServer.pm @@ -25,7 +25,6 @@ use threads::shared; use Thread::Semaphore; use IO::Socket::INET; -use Net::Ping; use NetAddr::IP; use POSIX qw(strftime ceil); @@ -128,35 +127,22 @@ sub data_consumer ($$) { # Does the host already exist? next if (get_agent_from_addr ($dbh, $addr) > 0); - # Is the host alive? (thanks to Evi for the TCP scans) my $alive = 0; if (pandora_ping ($pa_config, $addr) == 1) { $alive = 1; - #Check for Remote Desktop & VNC (Desktop & Server machines) - #} elsif (tcp_scan ($addr, $pa_config->{'networktimeout'}, 3389) == 1 || - # tcp_scan ($addr, $pa_config->{'networktimeout'}, 5900) == 1) { - # $alive = 1; - #Check for management ports 10000 = Webmin, 161 = SNMP (Most embedded devices) - #} elsif (tcp_scan ($addr, $pa_config->{'networktimeout'}, 10000) == 1 || - # tcp_scan ($addr, $pa_config->{'networktimeout'}, 161) == 1) { - # $alive = 1; - #Check for SSH & Mail (Servers and Unix machines) - #} elsif (tcp_scan ($addr, $pa_config->{'networktimeout'}, 22) == 1 || - # tcp_scan ($addr, $pa_config->{'networktimeout'}, 25) == 1) { - # $alive = 1; - #Check for WWW & MySQL (Webservers and systems in a DMZ) - #} elsif (tcp_scan ($addr, $pa_config->{'networktimeout'}, 80) == 1 || - # tcp_scan ($addr, $pa_config->{'networktimeout'}, 3306) == 1) { - # $alive = 1; + # TCP Port profiling + if ((defined ($task->{'recon_ports'})) && ($task->{'recon_ports'} ne "")) { + $alive = tcp_scan ($pa_config, $addr, $task->{'recon_ports'}); + } } - next unless ($alive == 1); + next unless ($alive > 0); # Guess the OS and filter my $id_os = guess_os ($pa_config, $addr); next if ($task->{'id_os'} > 0 && $task->{'id_os'} != $id_os); - $hosts_found++; + $hosts_found ++; $addr_found .= $addr . " "; # Resolve the address @@ -205,22 +191,15 @@ sub data_consumer ($$) { # TCP scan the given host/port. Returns 1 if successful, 0 otherwise. ############################################################################## sub tcp_scan ($$$) { - my ($host, $timeout, $port) = @_; - my $rc = 0; - - eval { - local $SIG{'ALRM'} = sub { return 0; }; - alarm ($timeout); - my $handle=IO::Socket::INET->new( - Proto => 'tcp', - PeerAddr => $host, - PeerPort => $port); - $rc = 1 if ($handle); - alarm (0); + my ($pa_config, $host, $portlist) = @_; + my $runcommand; + + my $nmap = $pa_config->{'nmap'}; + eval { + $runcommand = `$nmap -p$portlist $host | grep open | wc -l`; }; - - return 0 if ($@); - return $rc; + return 0 if ($@); + return $runcommand; } ########################################################################## @@ -228,21 +207,26 @@ sub tcp_scan ($$$) { ########################################################################## sub guess_os { my ($pa_config, $host) = @_; + my $nmap = $pa_config->{'nmap'}; + my $xprobe = $pa_config->{'xprobe2'}; - my $xprobe2 = $pa_config->{'xprobe2'}; - - # Other OS - return 10 if (! -e $xprobe2); - - # Execute xprobe2 - my $output = ''; + # if xprobe2 not available, use nmap, if not, not able to detect OS + if (! -e $xprobe){ + return 10 if (! -e $nmap); + } + + # Execute Nmap (4.x) or Xprobe2 + my $output = ''; eval { - $output = `$xprobe2 $host 2> /dev/null | grep "Running OS" 2> /dev/null | head -1 2> /dev/null`; + if (-e $xprobe){ + $output = `$xprobe $host 2> /dev/null | grep 'Running OS' | head -1`; + } else { + $output = `$nmap -F -O $host 2> /dev/null | grep 'Aggressive OS guesses'`; + } }; # Check for errors return 10 if ($@); - return pandora_get_os ($output); } @@ -328,13 +312,14 @@ sub get_host_parent ($$){ # Traceroute not available return 0 unless ($TracerouteAvailable != 0); + my $traceroutetimeout = $pa_config->{'networktimeout'} * 2; my $tr = Net::Traceroute::PurePerl->new ( backend => 'PurePerl', host => $host, debug => 0, max_ttl => 15, - query_timeout => $pa_config->{'networktimeout'}, - packetlen => 40, + query_timeout => $traceroutetimeout, + packetlen => 80, protocol => 'udp', # udp or icmp ); @@ -343,7 +328,7 @@ sub get_host_parent ($$){ # Call traceroute eval { local $SIG{'ALRM'} = sub { return 0; }; - alarm($pa_config->{'networktimeout'}); + alarm($traceroutetimeout); $success = $tr->traceroute(); alarm(0); }; @@ -354,8 +339,21 @@ sub get_host_parent ($$){ # Traceroute was not successful return 0 if ($tr->hops < 2 || $success == 0); - my $parent_addr = $tr->hop_query_host($tr->hops - 1, 0); - return get_agent_from_addr ($dbh, $parent_addr); + my $hopstotal = $tr->hops; + $hopstotal--; + + # Run all list of parents until find a known parent + my $parent_addr; + my $parent_addr_check; + + for (my $ax=$hopstotal; $ax >= 0; $ax--){ + $parent_addr = $tr->hop_query_host($ax, 0); + $parent_addr_check = get_addr_id ($dbh, $parent_addr); + if ($parent_addr_check != -1){ + return get_agent_from_addr ($dbh, $parent_addr); + } + } + return 0; } 1; diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm index faacd8fbdb..8dcf80a845 100644 --- a/pandora_server/lib/PandoraFMS/Tools.pm +++ b/pandora_server/lib/PandoraFMS/Tools.pm @@ -73,12 +73,6 @@ sub pandora_get_os ($) { 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; } @@ -97,9 +91,21 @@ sub pandora_get_os ($) { elsif ($command =~ m/Apple/i){ return 8; } + elsif ($command =~ m/Linux/i){ + return 1; + } + elsif ($command =~ m/Enterasys/i){ + return 11; + } + elsif ($command =~ m/3com/i){ + return 11; + } elsif ($command =~ m/Octopus/i){ return 13; } + elsif ($command =~ m/BSD/i){ + return 4; + } else { return 10; # Unknown / Other } @@ -346,12 +352,15 @@ sub enterprise_hook ($$) { # Prepend the package name $func = 'PandoraFMS::Enterprise::' . $func; - # Try to call the function - my $output = eval { &$func (@args); }; - - # Check for errors - return undef if ($@); - + # Check if exist before try to call it + my $output = `perl -e "use $func"`; + + if ($output){ + # Try to call the function + $output = eval { &$func (@args); }; + } else { + return $undef; + } return $output; } diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec index 88e5d28250..79eb6a8396 100644 --- a/pandora_server/pandora_server.spec +++ b/pandora_server/pandora_server.spec @@ -21,8 +21,9 @@ BuildArchitectures: noarch Requires(pre): /usr/sbin/useradd AutoReq: 0 Provides: %{name}-%{version} -Requires: perl-mail-sendmail perl-DBI perl-DBD-mysql perl-time-format perl-mail-sendmail perl-netaddr-ip wmic perl-SNMP net-snmp -#Requires: xprobe2 +Requires: perl-mail-sendmail perl-DBI perl-DBD-mysql perl-time-format +Requires: perl-mail-sendmail perl-netaddr-ip perl-SNMP net-snmp +Requires: nmap wmic %description Pandora FMS is a monitoring system for big IT environments. It uses remote tests, or local agents to grab information. Pandora supports all standard OS (Linux, AIX, HP-UX, Solaris and Windows XP,2000/2003), and support multiple setups in HA enviroments.