V 1.0.5
[logcheck] / logcheck.pl
1 #!/usr/bin/perl
2
3 #    Logchecker - perl script to check unix logfiles and notify by email
4 #    if entries appear not covered by the whitelist
5 #    Copyright (C) long time ago by Peter, peters-webcorner.de
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU General Public License as published by
9 #    the Free Software Foundation, either version 3 of the License, or
10 #    (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU General Public License for more details.
16 #
17 #    You should have received a copy of the GNU General Public License
18 #    along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
20 require 'logcheck.conf';
21 $mode="run";
22
23 use File::Basename;
24 use File::Spec;
25 $dirname = File::Spec->rel2abs(dirname(__FILE__));
26
27 $file_pidfile = $dirname."/logcheck.pid";
28
29 $file_whitelist = $dirname."/".$file_whitelist;
30 $file_logfilelist = $dirname."/".$file_logfilelist;
31
32 sub head() {
33         print "\n";
34         print "-----------------------------\n";
35         print "This is logcheck.pl V1.0.5\n";
36         print "https://peters-webcorner.de\n";
37         print "project hosted on github\n";
38         print "https://github.com/pstimpel/logcheck\n\n";
39         print "Logchecker - Copyright (C) long time ago by Peter\n";
40     print "This program comes with ABSOLUTELY NO WARRANTY; for details run `-l'.\n";
41     print "This is free software, and you are welcome to redistribute it\n";
42     print "under certain conditions. Check license for details.\n";
43         print "-----------------------------\n\n";
44 }
45
46 if (($ARGV[0] ne "") && ($ARGV[0] ne "debug") && ($ARGV[0] ne "-l") && ($ARGV[0] ne "-r") && ($ARGV[0] ne "-d")) {
47         head();
48         print "Parameters:\n";
49         print "logcheck.pl         normal run, parse logfiles and fire email if needed\n";
50         print "logcheck.pl debug   prevents script from sending mail\n";
51         print "logcheck.pl -d      prevents script from sending mail\n";
52         print "logcheck.pl -l      prints license to console\n";
53         print "logcheck.pl -p      removes existing pid-file with no further checks\n";
54         print "logcheck.pl -h      this screen\n";
55         print "PID: ".$$." \n";
56         print "DIR: ".$dirname."\n";
57         getpidfilecontent();
58         if($pidstring ne "unknown") {
59                 print "!!! PID-file existing, created by process ".$pidstring." !!!\n";
60         }
61         exit 0;
62
63 }
64
65 if ($ARGV[0] eq "-l") {
66         head();
67         print "Content of license\n\n\n";
68         system('cat LICENSE | more');
69         exit 0;
70 }
71
72 if ($ARGV[0] eq "-r") {
73         head();
74         unlink($file_pidfile);
75         print "done...\n";
76         exit 0;
77 }
78
79 if ($ARGV[0] eq "debug" || $ARGV[0] eq "-d") {
80         head();
81         print "debug mode on...\n";
82         $mode="debug";
83
84 }
85
86 if (-e $file_whitelist) {
87         if($mode eq "debug") {
88                 print "whitelist found...\n";
89         }
90
91 else 
92 {
93         open(ADR, ">$file_whitelist");
94         print ADR "";
95         close(ADR);
96         print "Please edit ".$file_whitelist." first...\n";
97         exit 1;
98               
99 }
100 if (-e $file_logfilelist) {
101         if($mode eq "debug") {
102                 print "list of logfiles found...\n";
103         }
104 } else {
105         open(ADR, ">$file_logfilelist");
106         print ADR "";
107         close(ADR);
108         print "Please edit ".$file_logfilelist." first...\n";
109         exit 1;
110               
111 }
112
113
114 $read=0;
115 open(ADR, "<$file_whitelist");
116 while(<ADR>)
117 {
118         chop($_);
119         if(length($_) > 1) {
120                 if (substr($_,0,1) ne "#") 
121                 {
122                 $read++;
123                 push @whitelisted, $_;
124                 }
125         }
126 }
127 close(ADR);
128 if ($read > 0) {
129         if($mode eq "debug") {
130                 print $read." entries in whitelist found\n";
131         }
132 }
133 else
134 {
135         if($mode eq "debug") {
136                 print "no entries in whitelist found, may be not normal...\n";
137         }
138 }
139
140
141
142 $read=0;
143 open(ADR, "<$file_logfilelist");
144 while(<ADR>)
145 {
146         chop($_);
147         if(length($_) > 1) {
148                 if (substr($_,0,1) ne "#") 
149                 {
150                 $read++;
151                 push @logfiles, $_;
152                 }       
153         }
154 }
155 close(ADR);
156 if ($read > 0) {
157         if($mode eq "debug") {
158                 print $read." entries in logfile list found\n";
159         }
160 }
161 else
162 {
163         print "there must be at least one entry in "..$file_logfilelist."\n";
164         print "ABORTING NOW!!!\n";
165         exit 1;
166 }
167
168 if (-e $file_pidfile) {
169         if($mode eq "debug") {
170                 print "There is a pid-file already, ".$file_pidfile.", abort execution\n";
171                 exit 1;
172         } else {
173                 getpidfilecontent();
174                 $psstring = `ps fax`;
175                 $Jetztwert = time();
176                 $Jetztzeit = localtime($Jetztwert);
177                 $mailer = '/usr/sbin/sendmail';
178                 $Sender = $senderaddress;
179                 open(MAIL, "|$mailer -t") || die "Can't open $mailer!\n";
180                 print MAIL "To: ".$emailaddress."\n";
181                 print MAIL "Subject: Logs NOT CHECKED report $Jetztzeit\n\n\n";
182                 print MAIL "There is a pid-file already at ".$file_pidfile.", and the execution of logcheck was aborted!\n\nRemove the pid-file, but make sure logcheck is not running anymore. See output of ps fax below\n\n";
183                 print MAIL "Pid of this (the aborted process) is: ".$$."\n";
184                 print MAIL "Pid of blocking process is: ".$pidstring."\n\n";
185                 
186                 print MAIL $psstring."\n\n";
187                 close(MAIL);
188                 exit 1;
189         }
190 }
191
192 open(ADR, ">$file_pidfile");
193 print ADR $$;
194 close(ADR);
195
196
197 foreach $thisfile (@logfiles) {
198         $outtext="";
199         $noffset="";
200         $offset;
201         $jumpover;
202         if($mode eq "debug") {
203                 print "processing ".$thisfile."\n";
204         }
205         if(-e $thisfile) 
206         {
207                 $useoffset=0;
208                 $thisoffset="";
209                 if(-e $thisfile.".offset") {
210                         if($mode eq "debug") {
211                                 print "using ".$thisfile.".offset\n";
212                         }
213                         $useoffset=1;
214                         open(OFF,"<$thisfile.offset");
215                         while(<OFF>)
216                         {
217                                 $offset=$_;
218                                 if($mode eq "debug") {
219                                         print "offset is $_\n"; 
220                                 }
221                         }
222                         close(OFF);
223                 }       
224                 $jumpover=1;    
225                 check();
226                 if($jumpover==1) {
227                         unlink($thisfile.".offset");
228                         if($mode eq "debug") {
229                                 print "offset not found, reparsing without offset\n";   
230                         }
231                         $jumpover=0;
232                         $offset="";
233                         check();
234                 }
235                 if ($outtext ne "") {
236                         if($mode eq "debug") {
237                                 print "mail not sent, cause debug is enabled\n";        
238                                 print "content of mail to $emailaddress would be:\n---------------------------------\n";
239                                 print $outtext;
240                                 print "\n---------------------------------\nend of mail\n";
241                         } else {
242                                 $Jetztwert = time();
243                                 $Jetztzeit = localtime($Jetztwert);
244                                 $mailer = '/usr/sbin/sendmail';
245                                 $Sender = $senderaddress;
246                                 open(MAIL, "|$mailer -t") || die "Can't open $mailer!\n";
247                                 print MAIL "To: ".$emailaddress."\n";
248                                 print MAIL "Subject: ($thisfile) violation report $Jetztzeit\n\n\n";
249                                 print MAIL $outtext;
250                                 close(MAIL);
251                                 $command="\/usr\/bin\/logger -p warn logcheckprint";
252                 system($command);
253                         }
254                 } else {
255                         if($mode eq "debug") {
256                                 print "nothing to send, $thisfile seems to be ok\n";    
257                         }
258                 }
259                 if ($noffset ne "") {
260                         if($mode eq "debug") {
261                                 print "new offset written in ".$thisfile.".offset\n";   
262                         }
263                         open(ADR, ">$thisfile.offset");
264                                print ADR $noffset;
265                         close(ADR);
266                 }
267         }
268         else
269         {
270                 print STDERR "logfile $thisfile not found...ignoring\n";
271         }       
272 }
273
274 unlink($file_pidfile);
275
276 exit 0;
277
278
279 sub check() {
280         # checks the logfile itself
281         open(LOG,"<$thisfile");
282         while(<LOG>) 
283         {
284                 if ($jumpover == 0) {
285                         $wl=0;
286                         foreach $wltext (@whitelisted) 
287                         {
288                                 if($_ =~/$wltext/) 
289                                 {
290                                         $wl=1;
291                                 }
292                         }
293                         if($wl==0) 
294                         {
295                                 $outtext=$outtext.$_;
296                         }
297                 }       
298                 $noffset = substr($_,0,15,);
299                 if(substr($_,0,15) eq $offset) {
300                         $jumpover=0;
301                         if($mode eq "debug") {
302                                 print "offset found\n"; 
303                         }
304                 }
305         }
306         close(LOG);
307 }
308
309 sub getpidfilecontent() {
310         $pidstring="unknown";
311         open(ADR, "<$file_pidfile");
312         while(<ADR>)
313         {
314                 chop($_);
315                 if(length($_) > 1) {
316                         if (substr($_,0,1) ne "#") 
317                         {
318                                 $pidstring = $_;
319                         }       
320                 }
321         }
322         close(ADR);
323 }