All pastes #910144 Raw Edit

Unnamed

public text v1 · immutable
·published 2008-02-19 19:47 UTC
rendered paste body
#!/usr/bin/perl
use Digest::MD5::File qw(file_md5_hex);
use strict;
use warnings;
use DB_File;
use Getopt::Std;
use Net::XMPP;

#Config:
my $j_host = "s-teals.info"; 
my $j_login = "bot";
my $j_pass = "pass";
my $j_adm = 'timofei1394@s-teals.info';
my $command = 'who,ps';
my $logfile = 'mdval.log';
my %opts;
#r - рекурсия (bool), n- флаг создания новой базы (bool), i - инпут, хуле (имя новой базы или имя той которую чекаем),
#v - подробный вывод при создании базы (bool), o - отпут, имя новой базы стало быть, с - флаг чека базы. a- проверка
#на новые файлы (bool) 
getopts("vncari:o:",\%opts);

if($opts{n}){
	if($opts{i} and $opts{o}){
		gen_db($opts{i},$opts{o},$opts{r},$opts{v});
	}
}

if($opts{c}){
	check($opts{i});
}

help();

#$exist_f - отсутствующие в директории файлы
#$mdfailed_f - файлы с которыми не совпала контрольная сумма
#$command_result - вывод комманд заданых в конфиге в переменной $command
#$new_f - новые файлы в подконтрольной дире

sub check{ 
	logw("Cheking start");
	my(%db,$exist_f,$md5failed_f,$new_f,$command_result);
	dbmopen(%db,"$_[0]", 0777) or logw("Check error: $!\n");
  
	while(my($path,$md5_db) = each %db){
		unless(-e $path){
			$exist_f .= "$path\n" if("$path" ne 'dir' and "$path" ne 'recursive'); #Исключаем dir и recursive из путей.
		} else {
			my $md5_new = get_md($path);
			unless($md5_new eq $md5_db){
				$md5failed_f .= "\n$path\nMD5 Old:$md5_db\nMD5 New:$md5_new\n";
			}
		}
	}
  
	if($opts{a}){
		my @ch_file_list = scan_dir($db{dir},$db{recursive});
		for(my $i=0;@ch_file_list>$i;$i++){
			$ch_file_list[$i] =~ s/\/\//\//g;
			unless($db{$ch_file_list[$i]}){
				$new_f .= $ch_file_list[$i];
			}
		}
	}
  
	dbmclose(%db);
	
	if($command){
		my @command = split(',',$command);
		$command_result .= "$command:\n";
		for(my $i=0;@command>$i;$i++){
			$command_result .= `$command[$i]`."\n";
		}
	}

		if($md5failed_f or $new_f or $exist_f){
			jabber_send($j_adm,"\nFailedMD5:\n$md5failed_f\nNewFile:\n$new_f\nExistFile:\n$exist_f\nCommand_Result:\n$command_result");
		}
	logw("Check finish");
	exit(0);
}

#Осторожно! Рекурсия =)
sub scan_dir{
	my @list;
	my $recursive = $_[1];
	my $dir = $_[0];
	for my $file (glob($dir.'/*')){
		unless(-d $file){
			push @list, $file;
		} else {
			if($recursive){
				$file =~ s/ /\\ /g;
				my @sub = scan_dir($file,$recursive);
				push @list, @sub;
			}
		}
	}
	return @list;
}

sub get_md{
	my $digest;
	$digest = file_md5_hex("$_[0]");
	return($digest);
}

sub gen_db{
	logw("Generation DB starting");
	my (@file_list,%result);
	@file_list = scan_dir($_[0],$_[2]);
	if(-e $_[1]){
		print "$_[1] already exist. Overwrite it? \[y\\n\]\n";
		while(<STDIN>){
			chop $_;
			if($_ eq ''){print "Bye-bye\n";exit(0);}
			if($_ eq 'y' or $_ eq 'Y'){unlink("$_[1]") or die "Error: $!";last;}
			if($_ eq 'n' or $_ eq 'N'){print "Bye-bye\n";exit(0);}
		}
	}
	dbmopen(%result,"$_[1]", 0777);
	($result{recursive},$result{dir}) = ($_[2],$_[0]);
	for(my $i=0;@file_list>$i;$i++){
		my $md5= get_md($file_list[$i]);
		$file_list[$i] =~ s/\/\//\//g;
		$file_list[$i] =~ s/\n|\r//g;
		$md5 =~ s/\n|\r//;
		if($_[3]){
			print "File: $file_list[$i]\n MD5:$md5\n";
		}
		$result{$file_list[$i]} = $md5;
	}
	dbmclose(%result);
	logw("Generation DB finish");
	exit(0);
}

sub jabber_send {
	logw("Sending message to jabber");
	my $cnx = new Net::XMPP::Client(debuglevel=>0);
	$cnx->Connect(hostname => "$j_host", tls => 0);
	$cnx->AuthSend('hostname' => "$j_host",
		'username' => "$j_login",
		'password' => "$j_pass",
		'resource' => "Oo");
	$cnx->MessageSend('to'      => "$_[0]",
		'type'=>"chat",
		'body'    => "$_[1]");
	$cnx->Disconnect();
}

sub logw {
	my $log_msg = shift;
	my $now_time = localtime time;
	open(LOG,">> $logfile");
	print LOG "\[$now_time\]: $log_msg\n";
	close(LOG);
}

sub help {
print <<HELP;
System of control integrity files by s-teals.org

Use:
perl $0 <keys>

Keys:
-n - Create new database with checksum files
Keys that can be used with -n:
-r - Recursive walk directory
-i <path> - path to directory with checksum files
-o <path> - path to saving database with checksums files
-v - Advanced output at create database (warning many letters)

-c - verifying checksum files by database
Keys that can be used with -c:
-i <path> - path to database with checksum
-a - verifying new files in control directory

Example:
perl $0 -nr -i /etc -o etc.db - create database with checksum files directiry  /etc with recursive walk directory

perl $0 -c -i etc.db - verifying checksum files by database etc.db without verifying new files in control directory
HELP
exit(0);
}