#!/usr/bin/perl -w # Versione use IPC::Open3; use Getopt::Long; use Time::Local; use MIME::Base64; use IO::Socket; use Sys::Hostname; use strict; our $SMTP_SERVER = "smtp.lnf.infn.it"; our $SRVNAME = hostname(); my $mailto = ""; ( my $script = $0 ) =~ s/^.+\///g; my $mailfrom = "$script\@lnf.infn.it"; my $mailsubject = "\[$script\]"; my $mailbody = "-- OUTPUT DELL'ULTIMA ESECUZIONE: caricati report nuovi o aggiornati --\n\n"; my $mailstatus = 0; my $mailerr=""; my $GVMpath = "~/.local/bin"; my $GVMCLI = "$GVMpath/gvm-cli --timeout 300 socket --socketpath /GVM/GVMD/gvmd.sock --pretty --xml "; my $VERSION = '1.0'; my $netfile = "nets.dat"; my $reportdir = "./reports/"; my $outformat = "XML"; my $mail = 'no-mail@localhost.localdomain'; my $scp = ""; my $version = 0; my $debug = 0; my ( $record, $vlan, $net, $DATE ); my ( $output, $error, $command ); my ( $TargetName, $TargetNet, $TaskName, $tstamp, $tname ); our %RepFormatId; my ( $key, $OUT, $ERR, $stout, $rec ); my ( $repofile, $repotype ); my $repoflag = 0; my $ReportList = ""; my $status = GetOptions ("netfile=s" => \$netfile, "reportdir=s" => \$reportdir, "format=s" => \$outformat, "mail=s" => \$mail, "scp=s" => \$scp, "debug" => \$debug, "version" => \$version ); open( $ERR, ">&STDERR" ); if ( !$status || $outformat !~ /^\s*(XML|AXML|TXT|PDF|CSV|ITG)\s*$/ || $mail !~ /^\S+\@(\S+\.)+\S+$/ ) { print $ERR "Errore negli argomenti della linea di comando!\n"; print $ERR "Gli argomenti consentiti sono:\n"; print $ERR " --netfile= ( default = nets.dat )\n"; print $ERR " --reportdir= ( default = ./reports/ )\n"; print $ERR " --format= ( XML | AXML | TXT | PDF | CSV | ITG, default = XML)\n"; print $ERR " --mail=
\n"; print $ERR " --scp=\n"; print $ERR " --debug\n"; print $ERR " --version\n"; exit; } if ( $version == 1) { print "gce-report.pl version is $VERSION\n"; exit; } $repotype = lc( $outformat ); $outformat = "CSV Results" if ( $outformat eq "CSV"); $outformat = "Anonymous XML" if ( $outformat eq "AXML"); $reportdir .= "/" if ( $reportdir !~ /\/$/ ); #print "$reportdir\n"; if ( $mail eq 'no-mail@localhost.localdomain' ) { $stout = ">&STDOUT"; } else { $stout = ">gce-report.out"; $mailto = $mail; } my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); $mon++; $year += 1900; my $DateTime = sprintf("%02d/%02d/%04d %02d:%02d:%02d", $mday, $mon, $year, $hour, $min, $sec ); $mailbody .= "-- Data e ora di inizio procedura: $DateTime --\n\n"; open( $OUT, $stout ); $ERR = $OUT if ( $mail ne 'no-mail@localhost.localdomain' ); # Ricerca dell'Id dei vari report format $command = "$GVMCLI \\ \"\""; #print "CMD: $command\n\n\n"; ( $output, $error ) = &ExecCommand( $command ); #print "O: $output\n"; #print "E: $error\n"; if ( $error ne "" ) { print $ERR "Errore durante la ricerca dei report format\n\n$error\n\n"; if ( $mailto ne "" ) { $mailbody .= "Errore durante la ricerca dei report format\n\n$error\n\n"; $mailstatus = &Send_a_mail( $mailfrom, $mailto, "$mailsubject error", $mailbody ); print $ERR "Errore $mailstatus durante l'invio del mail\n\n" if ( $mailstatus > 0 ); } exit; } my $RepFormat = &ReportFormatId ( $output ); if ( $RepFormat eq "Error" ) { print $ERR "Errore: non ottenuto l'id dei report format\n\n$output\n\n"; if ( $mailto ne "" ) { $mailbody .= "Errore: non ottenuto l'id dei report format\n\n$output\n\n"; $mailstatus = &Send_a_mail( $mailfrom, $mailto, "$mailsubject error", $mailbody ); print $ERR "Errore $mailstatus durante l'invio del mail\n\n" if ( $mailstatus > 0 ); } exit; } if ( $debug ) { $ReportList = "Lista dei Report Format Id:\n\n"; foreach $key ( keys %RepFormatId ) { $ReportList .= " $key:$RepFormatId{$key}\n"; } $ReportList .= "\n"; } $ReportList .= "Formato selezionato: $outformat"; $ReportList .= " --> Report Format Id: $RepFormatId{$outformat}" if ( $debug ); $ReportList .= "\n\n"; $mailbody .= $ReportList; print $OUT "-- Data e ora di inizio procedura: $DateTime --\n\n"; print $OUT $ReportList; open ( NETS, "<$netfile" ) or die( "Errore: file $netfile non trovato\n" ); while ( $net = ) { chomp( $net ); next if ( $net =~ /^\s*$/ ); next if ( $net =~ /^\s*#/ ); $TargetName = ""; $TargetNet = ""; $net =~ /^(.*),(.*)$/; $TargetName = $1; #$TargetNet = $2; $TargetName =~ s/(^\s+|\s+$)//g; #$TargetNet =~ s/(^\s+|\s+$)//g; #next if ( $TargetName eq "" || $TargetNet eq "" ); next if ( $TargetName eq "" ); $TaskName = "$TargetName scan"; #print "$TargetName\n"; #print "$TargetNet\n\n"; #print "$TaskName\n\n"; # Ricerca dell'Id del Task $command = "$GVMCLI \\ \"\""; #print "CMD: $command\n\n\n"; ( $output, $error ) = &ExecCommand( $command ); #print "O: $output\n"; #print "E: $error\n"; if ( $error ne "" ) { print $ERR "Errore durante la ricerca del task \"$TaskName\"\n\n$error\n\n"; if ( $mailto ne "" ) { $mailbody .= "Errore durante la ricerca del task \"$TaskName\"\n\n$error\n\n"; $mailstatus = &Send_a_mail( $mailfrom, $mailto, "$mailsubject error", $mailbody ); print $ERR "Errore $mailstatus durante l'invio del mail\n\n" if ( $mailstatus > 0 ); } exit; } #print "Task $TaskName:\n"; my ( $LastReportId, $LastReportTime ) = &LastReport ( $output ); print $OUT "Task: $TaskName --> Timestamp dell'ultimo report: $LastReportTime"; print $OUT ", Id: $LastReportId" if ( $debug ); if ( $LastReportId eq "Error" ) { print $OUT "\nWarning: non ottenuto l'id dell'ultimo report relativo al task \"$TaskName\"\n\n"; #print "$output\n\n"; next; } ( $tstamp = $LastReportTime ) =~ s/:/-/g; ( $tname = $TaskName ) =~ s/\s+/_/g; $repofile = "${reportdir}${tname}-${tstamp}.${repotype}"; if ( -e $repofile ) { print $OUT "\n"; } else { $command = "$GVMCLI \\ \"\""; #print "CMD: $command\n\n\n"; ( $output, $error ) = &ExecCommand( $command ); #print "O: $output\n"; #print "E: $error\n"; print $ERR "\nErrore durante la ricerca dell'ultimo report relativo al task \"$TaskName\"\n\n$error\n\n" if ( $error ne "" ); my $Report = &GetReport( $outformat, $output ); $repoflag = 1; $status = open ( REPO, ">$repofile" ); if ( ! $status ) { $mailbody .= "\nErrore nell'apertura del file $repofile\n"; print $ERR "\nErrore nell'apertura del file $repofile\n"; $mailerr = "\/error"; last; } print REPO $Report; close( REPO ); print $OUT " ----> $repofile caricato\n"; $mailbody .= "Task: $TaskName --> Timestamp dell'ultimo report: $LastReportTime"; $mailbody .= ", Id: $LastReportId" if ( $debug ); $mailbody .= " ----> $repofile caricato\n"; if ( $scp ne "" ) { $command = "scp \"$repofile\" \"$scp\""; ( $output, $error ) = &ExecCommand( $command ); #print "O:$output\n"; #print "E: $error\n"; if ( $error ne "" ) { unlink $repofile; $mailbody .= "\nErrore durante la copia del file $repofile\" --> $scp\n\n$error\nFile $repofile rimosso\n\n"; print $ERR "\nErrore durante la copia del file $repofile\" --> $scp\n\n$error\nFile $repofile rimosso\n\n"; $mailerr = "\/error"; last; } } } } ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); $mon++; $year += 1900; $DateTime = sprintf("--Data e ora di fine procedura: %02d/%02d/%04d %02d:%02d:%02d --", $mday, $mon, $year, $hour, $min, $sec ); $mailbody .= "\n$DateTime\n\n"; print $OUT "\n$DateTime\n\n"; if ( $repoflag && $mailto ne "" ) { $mailstatus = &Send_a_mail( $mailfrom, $mailto, "$mailsubject output$mailerr", $mailbody ); #print "S:$mailstatus, $mailfrom, $mailto, $mailsubject, $mailbody\n"; print $ERR "Errore $mailstatus durante l'invio del mail\n\n" if ( $mailstatus > 0 ); } close( $ERR ); close( $OUT ); exit; ######################################################################## sub ExecCommand { my ( $cmd ) = @_; my ( $rec, $out, $err ); # print "CMD: $cmd\n"; my $pid = open3( \*ECIN, \*ECOUT, \*ECERR, $cmd ); close( ECIN ); $out = ""; while ( $rec = ) { $out .= $rec; } $err = ""; while ( $rec = ) { $err .= $rec; } close( ECOUT ); close( ECERR ); return ( $out, $err ); #print "$out\n-\n"; #print "$err\n+\n"; } ######################################################################## sub LastReport { my ( $output ) = @_; my $rec=""; my $id=""; my $timestamp=""; my $repflag = 0; #print "$output\n\n"; foreach $rec ( split(/\n/, $output) ) { #print "$rec\n"; if ( $rec =~ /^\s*\s*$/ ) { $repflag = 1; } elsif ( $rec =~ /^\s*<\/last_report>\s*$/ ) { $repflag = 0; } next if ( $repflag == 0 ); if ( $rec =~ /(.+)<\/timestamp>/ ) { $timestamp = $1; $timestamp =~ s/\+.+$//g; return ( $id, $timestamp ); } } return ( "Error", "N/A" ); } ######################################################################## sub ReportFormatId { my ( $output ) = @_; my $rec=""; my $id=""; my $name = ""; my $repfflag = "Error"; #print "$output\n\n"; foreach $rec ( split(/\n/, $output) ) { #print "$rec\n"; if ( $rec =~ // ) { $id = $1; #print "$id:$1\n\n"; $repfflag = ""; } elsif ( $rec =~ /(.+)<\/name>/ ) { $name = $1; $RepFormatId{$name} = $id; } } return $repfflag; } ######################################################################## sub GetReport { my ( $outformat, $output ) = @_; my $rec=""; my $id=""; my $repflag = 0; my $Report = ""; my $eol = ""; my $decoded; $eol = "\n" if ( $outformat eq "XML" || $outformat eq "Anonymous XML" ); #print "$output\n\n"; foreach $rec ( split( /\n/, $output) ) { #print "$rec\n"; if ( $rec =~ /<\/report_format>(.*)$/ ) { $rec = $1; $repflag = 1; } next if ( $repflag == 0 ); $Report .= "$rec$eol"; last if ( $rec =~ /<\/report>$/ ); } if ( $outformat ne "XML" && $outformat ne "AXML" ) { $Report =~ s/<\/report>.*$//; $Report = decode_base64( $Report ); } return $Report; } ######################################################################## sub Send_a_mail { my ( $mailfrom, $mailto, $mailsubject, $mailbody ) = @_; my $handle; my $read; my $Mailto; #print "SaM: $mailfrom, $mailto, $mailsubject, $mailbody\n"; return 1 if ( ! defined( $mailto ) || $mailto =~ /^\s*$/ ); $handle = IO::Socket::INET->new( PeerAddr => "$SMTP_SERVER", PeerPort => "smtp(25)") || return; $handle->autoflush(1); $read = <$handle>; if ( $read !~ /^220/ ) { close ($handle); return 2; } # print "$read\n"; return 3 if ( &Write_handle( $handle, "HELO $SRVNAME\n", "^250.*Hello" ) ); return 4 if ( &Write_handle( $handle, "MAIL FROM: $mailfrom\n", "^250.*Sender ok" ) ); foreach ( split(',', $mailto) ) { return 5 if ( &Write_handle( $handle, "RCPT TO: $_\n", "^250.*Recipient ok" ) ); } return 6 if ( &Write_handle( $handle, "DATA\n", "^354.*Enter mail" ) ); return 7 if ( &Write_handle( $handle, "To: $mailto\n", "" ) ); $Mailto = ucfirst( $mailto ); return 8 if ( &Write_handle( $handle, "Reply-To: $Mailto\n", "" ) ); return 9 if ( &Write_handle( $handle, "Subject: $mailsubject\n", "" ) ); return 10 if ( &Write_handle( $handle, "$mailbody\n.\n", "^250.*Message accepted for delivery" ) ); return 11 if ( &Write_handle( $handle, "QUIT\n", "^221.*closing connection" ) ); close $handle; return 0; } ######################################################################## sub Write_handle { my( $handle, $Write_String, $Test_Answer) = @_; my $answer; #print "WSTR:$Write_String\n"; print $handle "$Write_String"; if ( $Test_Answer ne "" ) { $answer = <$handle>; #print "ANSW:$answer\n"; if ( $answer !~ /$Test_Answer/ ) { close ($handle); return 1; } } return 0; } ########################################################################