6 # ---------------------------------------------------------------------------
\r
7 # Author: Meir Michanie (meirm@riunx.com)
\r
8 # Co-Author: J.A.Senger (jorge@br10.com.br)
\r
10 # ---------------------------------------------------------------------------
\r
11 # http://www.riunx.com/
\r
12 # ---------------------------------------------------------------------------
\r
14 # ---------------------------------------------------------------------------
\r
16 # ---------------------------------------------------------------------------
\r
18 # "Ossec to Snorby" records the OSSEC HIDS alert logs in MySQL database.
\r
19 # It can run as a daemon (ossec2snorby.pl), recording in real-time the logs in database or
\r
20 # as a simple script (ossec2snorby.pl).
\r
22 # ---------------------------------------------------------------------------
\r
23 # Snorby support by Jean-Pierre Zurbrugg (jp.zurbrugg@live.com)
\r
24 # ---------------------------------------------------------------------------
\r
25 # The original script by the Author and Co-author was taken as a template and
\r
26 # modified to work with Snorby (http://snorby.org) which uses a Snort DB schema.
\r
27 # Credit must go to the author\Co-author for the initial template.
\r
29 ########################### WARNING ###############################
\r
30 # My modifications are by far stable and worthy of a production environment
\r
31 # WHITHOUT INICIAL TWEAKING. Please setup your labs and make sure everything
\r
32 # works properly before using this script on a production environment.
\r
33 ########################### WARNING ###############################
\r
37 # * Extra validations were added to make sure srcip\dstip do not remain with
\r
38 # a default value of "0" which causes GUI parsing errors if left unhandled.
\r
39 # * Validation against '$hostname'; if localhost then srcip="127.0.0.1"
\r
40 # * Snorby expects IP related data to be published on its "iphdr" table.
\r
41 # * Snorby expects OSSEC's logs to be converted to HEX and wordwrapped.
\r
42 # * Modified the scripts "Daemon" mode; it now uses "tail -Fn 0 <file>"
\r
44 # ---------------------------------------------------------------------------
\r
46 # ---------------------------------------------------------------------------
\r
49 # Perl DBD::mysql module
\r
52 # Snorby prerequesites:
\r
53 # import ossec2snorby_category.sql from contrib directory
\r
54 # Populate "domain" in /etc/ossec2snorby.conf
\r
56 # ---------------------------------------------------------------------------
\r
57 # Installation steps
\r
58 # ---------------------------------------------------------------------------
\r
60 # 1) Create a user to access the database initially created by Snorby;
\r
61 # 2) Copy ossec2snorby.conf to /etc/ossec2snorby.conf with 0600 permissions
\r
62 # 3) Edit /etc/ossec2snorby.conf according to your needs:
\r
67 # dbpasswd=mypassword
\r
71 # domain=mydomain.local
\r
73 # NOTE: It is recommended to keep "resolve" as "1" and populate "domain" with
\r
74 # your actual domain. Not doing so will restrict the script and force it
\r
75 # to populate IPs as "0.0.0.1" for events whose SRC or DST IP are unknown.
\r
77 # ---------------------------------------------------------------------------
\r
79 # ---------------------------------------------------------------------------
\r
81 # This program is free software; you can redistribute it and/or
\r
82 # modify it under the terms of the GNU General Public License
\r
83 # as published by the Free Software Foundation; either version 2
\r
84 # of the License, or (at your option) any later version.
\r
86 # This program is distributed in the hope that it will be useful,
\r
87 # but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
88 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
89 # GNU General Public License for more details.
\r
91 # You should have received a copy of the GNU General Public License
\r
92 # along with this program; if not, write to the Free Software
\r
93 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\r
95 # ---------------------------------------------------------------------------
\r
97 # ---------------------------------------------------------------------------
\r
99 # OSSEC HIDS is an Open Source Host-based Intrusion Detection System.
\r
100 # It performs log analysis and correlation, integrity checking,
\r
101 # rootkit detection, time-based alerting and active response.
\r
102 # http://www.ossec.net
\r
104 # ---------------------------------------------------------------------------
\r
106 # ---------------------------------------------------------------------------
\r
108 # ---------------------------------------------------------------------------
\r
110 $SIG{TERM} = sub { &gracefulend('TERM')};
\r
111 $SIG{INT} = sub { &gracefulend('INT')};
\r
113 # If no ARGV are given then present &help().
\r
114 &help() unless @ARGV;
\r
116 my ($RUNASDAEMON)=0;
\r
117 my ($DAEMONLOGFILE)='/var/log/ossec2snorby.log';
\r
118 my ($DAEMONLOGERRORFILE) = '/var/log/ossec2snorby.err';
\r
119 # Declare OSSEC's log path and filename format.
\r
120 my $LOG='/var/ossec/logs/alerts/alerts.log'; # we need to tail this file instead of the old.
\r
121 # With this we can survive file rotations while
\r
122 # running in daemon mode.
\r
124 my ($LOGGER)='ossec2snorby';
\r
125 my($OCT) = '(?:25[012345]|2[0-4]\d|1?\d\d?)';
\r
126 my($IP) = $OCT . '\.' . $OCT . '\.' . $OCT . '\.' . $OCT;
\r
128 my ($hids_id,$hids,$hids_interface,$last_cid)=(undef, 'localhost', 'ossec',0);
\r
129 my ($tempvar,$VERBOSE)=(0,0);
\r
132 $conf{dbhost}='localhost';
\r
133 $conf{database}='snort';
\r
135 $conf{dbport}='3306';
\r
136 $conf{dbpasswd}='password';
\r
137 $conf{dbuser}='user';
\r
138 $conf{daemonize}=0;
\r
139 $conf{sensor}='sensor';
\r
140 $conf{hids_interface}='ossec';
\r
144 # OSSEC's default class_ID
\r
145 # We will categorize events as "unknown" if a match could not be found...
\r
146 my $sig_class_id=2; # We will try to fetch the correct class_id later.
\r
148 my($sig_class_name,$taillog);
\r
149 # ---------------------------------------------------------------------------
\r
150 # Arguments parsing
\r
151 # ---------------------------------------------------------------------------
\r
154 if (m/^-d$|^--daemon$/){
\r
155 $conf{daemonize}=1;
\r
156 }elsif ( m/^-h$|^--help$/){
\r
158 }elsif ( m/^-n$|^--noname$/){
\r
159 $conf{'resolve'}=0;
\r
160 }elsif ( m/^-v$|^--verbose$/){
\r
162 }elsif ( m/^--interface$/){
\r
163 $conf{hids_interface}= shift @ARGV if @ARGV; # ossec-rt/ossec-feed
\r
164 }elsif ( m/^--sensor$/){
\r
165 $conf{sensor}= shift @ARGV if @ARGV; # monitor
\r
166 }elsif ( m/^--conf$/){
\r
167 $conf{conf}= shift @ARGV if @ARGV; # localhost
\r
169 }elsif ( m/^--dbhost$/){
\r
170 $conf{dbhost}= shift @ARGV if @ARGV; # localhost
\r
171 }elsif ( m/^--dbport$/){
\r
172 $conf{dbport}= shift @ARGV if @ARGV; # localhost
\r
173 }elsif ( m/^--dbname$/){
\r
174 $conf{database}= shift @ARGV if @ARGV; # snort
\r
175 }elsif ( m/^--dbuser$/){
\r
176 $conf{dbuser}= shift @ARGV if @ARGV; # root
\r
177 }elsif ( m/^--dbpass$/){
\r
178 $conf{dbpasswd}= shift @ARGV if @ARGV; # monitor
\r
182 if ($conf{dbpasswd}=~ m/^--stdin$/){
\r
183 print "dbpassword:";
\r
184 $conf{dbpasswd}=<>;
\r
185 chomp $conf{dbpasswd};
\r
187 $hids=$conf{sensor} if exists($conf{sensor});
\r
188 $hids_interface=$conf{hids_interface} if exists($conf{hids_interface});
\r
190 # START IN DAEMON MODE ?
\r
191 &daemonize() if $conf{daemonize};
\r
193 my $dbi= ossecmysql->new(%conf) || die ("Could not connect to $conf{dbhost}:$conf{dbport}:$conf{database} as $conf{dbpasswd}\n");
\r
197 my ($query,$numrows,$row_ref);
\r
201 $query= 'select sid,last_cid from sensor where hostname=? and interface=?';
\r
202 $numrows= $dbi->execute($query,$hids,$hids_interface);
\r
204 $row_ref=$dbi->{sth}->fetchrow_hashref;
\r
205 $hids_id=$row_ref->{sid};
\r
206 $last_cid=$row_ref->{last_cid};
\r
208 $query="INSERT INTO sensor ( sid , hostname , interface , filter , detail , encoding , last_cid )
\r
210 NULL , ?, ? , NULL , ? , ?, ?
\r
212 $numrows= $dbi->execute($query,$hids,$hids_interface,1,2,0);
\r
213 $hids_id=$dbi->lastid();
\r
215 $dbi->{sth}->finish;
\r
216 &forceprintlog ("SENSOR:$hids; feed:$hids_interface; id:$hids_id; last cid:$last_cid");
\r
221 my ($timestamp,$sec,$mail,$date,$alerthost,$alerthostip,$datasource,$rule,$level,$description,
\r
222 $srcip,$dstip,$user,$text,$filtered,$osseclevel)=();
\r
223 my $lasttimestamp=0;
\r
226 &taillog($last_cid,$LOG);
\r
227 ################################################################
\r
228 sub forceprintlog(){
\r
236 my ($last_cid,$LOG)=@_;
\r
239 # we reached a newline, finish up with current record.
\r
241 next unless $timestamp;
\r
242 $alerthostip=$alerthost if $alerthost=~ m/^$IP$/;
\r
246 $dstip=$alerthostip;
\r
247 $resolv{$alerthost}=$dstip;
\r
250 if (exists $resolv{$alerthost}){
\r
251 $dstip=$resolv{$alerthost};
\r
253 if ($conf{'resolve'}){
\r
254 if ($alerthost =~m/(\d+\.\d+\.\d+\.\d+)/ ){
\r
257 # the "host" command doesn't work with Flatname\NetBIOS names.
\r
258 # The server's hostname is almost always a flatname and OSSEC
\r
259 # doesn't return an IP for alerts generated from localhost.
\r
260 # Ex. 2013 Jan 24 15:51:36 ubuntu->/var/log/auth.log
\r
261 my $x = `cat /etc/hostname`; # get Host's hostname
\r
262 chomp $x; # remove extra lines, if any.
\r
263 if ($x eq $alerthost) { # Validate if $alerthost is us, localhost.
\r
264 $dstip='127.0.0.1'; # Snorby does not allow empty\"0" as IP value.
\r
266 my $fetch=&host2ip($alerthost);
\r
268 if (defined $fetch){
\r
276 $resolv{$alerthost}=$dstip;
\r
280 #Populate SRC IP (requires dstip to be populated)
\r
281 if (! defined $srcip) {
\r
282 if (defined $dstip) {
\r
283 #Feb 6 15:18:21 1.1.1.1 %ASA-3-313001: Denied ICMP type=3, code=3 from 111.111.1.1 on interface OUTSIDE
\r
284 $filtered =~ s/$dstip//; # filter out known dstip from log output.
\r
285 $srcip=$1 if $filtered=~ m/\s($IP)\s/; # Search all text for an IP address.
\r
286 # This could easily bug out with logs that contains
\r
287 # version numbering such as mysql 1.3.4.5.
\r
289 # Windows logs include "User Name" in their log output. Some companies name their employees's PCs after its users which is
\r
290 # resolvable via DNS.
\r
291 # Windows logs may state a computer name as "User Name". Lets strip out the "$" from the computer name...
\r
292 if (defined $user and ! defined $srcip) {
\r
294 $u=~ s/\$//; # remove "$" from computer names.
\r
296 my $fetch=&host2ip($u);
\r
297 $srcip=$fetch if (defined $fetch);
\r
299 if (! defined $srcip or $srcip eq '') {
\r
300 # NO recognizable IPs or User Names were found on log output,
\r
301 # this suggests the log was generated by dstip.
\r
306 $last_cid= &prepair2basedata(
\r
323 ($timestamp,$sec,$mail,$date,$alerthost,$alerthostip,$datasource,$rule,$level,$description,
\r
324 $srcip,$dstip,$user,$text)=();
\r
327 if (m/^\*\* Alert ([0-9]+).([0-9]+):(.*)$/){
\r
329 if ( $timestamp == $lasttimestamp){
\r
333 $lasttimestamp=$timestamp;
\r
337 $mail=$mail ? $mail : 'nomail';
\r
338 #2006 Aug 29 17:19:52 firewall -> /var/log/messages
\r
339 #2006 Aug 30 11:52:14 192.168.0.45->/var/log/secure
\r
340 #2006 Sep 12 11:12:16 92382-Snort1 -> 172.16.176.132
\r
341 }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s+(\S+)\s*->(.*)$/){
\r
345 if ($datasource=~ m/(\d+\.\d+\.\d+\.\d+)/){
\r
347 $datasource="remoted";
\r
349 #2006 Aug 29 17:33:31 (recepcao) 10.0.3.154 -> syscheck
\r
350 }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s+\((.*?)\)\s+(\S+)\s*->(.*)$/){
\r
355 }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s(.*?)$/){
\r
357 $alerthost='localhost';
\r
359 }elsif ( m/Rule: ([0-9]+) \(level ([0-9]+)\) -> \'(.*)\'$/ ){
\r
362 $osseclevel=$level; # Keep copy of OSSEC level as it will later be converted to snort level.
\r
364 }elsif ( m/src\s?ip:/i){
\r
368 $srcip='1'; # Snorby doesn't like srcip\dstip = 0\null.
\r
370 }elsif ( m/User: (.*)$/){
\r
372 }elsif ( m/(.*)$/){
\r
375 # Get IP from User Name + DNS query.
\r
376 if (! defined $user){
\r
377 if ( m/User\s?Name:\s?(\S+)\s/i){
\r
382 $x =~ s/(.$)/$1\r\n/; # lets multiline this string for cleaner output once $payload wordwraps it.
\r
385 # This variable will be used to populate srcip once we reach the end of the current log entry.
\r
388 } # End of while read line
\r
393 if ($ip=~ m/(\d+)\.(\d+)\.(\d+)\.(\d+)/){
\r
394 my $num= ($1 * 256 ** 3) + ($2 * 256 ** 2)+ ($3 * 256 ** 1)+ ($4);
\r
398 return "1"; # Snorby has a bug where it wont ouput "N\A" on the IP columns if srcip\dstip = 0\null
\r
403 sub prepair2basedata(){
\r
421 my ($payload,$count,$query,$row_ref,$sig_id);
\r
427 # Note: the original script stated sig_class_id as "1" by default which in BASE might be ok but for
\r
428 # snorby it maps to a category of "not-suspicious" which is not efficient when stats are ran based on
\r
429 # event categories alone...
\r
431 # Furthermore, OSSEC allows a rule to have multiple categories assigned to it which snorby was not prepared to handle GUI
\r
432 # wize. (The event details contains a small section where the category value can be shown, this section is too small
\r
433 # to show OSSEC's sometimes long category results such as :
\r
434 # syslog,sshd,invalid_login,authentication_failed,)
\r
436 # We will use the last category shown only...This isn't the correct approach but my programing skills prevent me
\r
437 # from providing a better solution.
\r
439 # ex: - syslog,sshd,invalid_login,authentication_failed,
\r
440 if ($mail=~ m/\.*\,?(\w+\_?\w+)\,?$/){ # $mail contains the rule's categories. No clue why its named $mail...
\r
441 $sig_class_name=$1;
\r
442 &printlog ("SIG_CLASS_NAME: $sig_class_name \n");
\r
443 $query = "SELECT sig_class_id FROM category WHERE cat_name=?";
\r
444 $dbi->execute($query,$sig_class_name);
\r
445 $count=$dbi->{sth}->rows;
\r
447 $row_ref=$dbi->{sth}->fetchrow_hashref;
\r
448 $sig_class_id=$row_ref->{sig_class_id};
\r
449 &printlog ("SIG_CLASS_ID: $sig_class_id");
\r
451 &printlog ("SIG_CLASS_ID NOT FOUND. USING DEFAULT SIG.");
\r
455 &printlog ("COULD NOT GET A RULE CATEGORY. USING DEFAULT SIG.");
\r
461 # Get/Set signature id
\r
463 # Convert OSSEC Severity to Snort Severity.
\r
464 # Dont modify this after having live data on Snorby as it will create duplicated
\r
466 $level=4 if ($level <= 4); # Informational only.
\r
467 $level=3 if ($level == 5); # User generated errors \ low severity.
\r
468 $level=2 if (($level >= 6) && ($level <=11)); # Low to mid severity attacks.
\r
469 $level=1 if ($level >= 12); # High importance events \ Successfull attacks \ all our bases belong to them!
\r
471 $query = "SELECT sig_id FROM signature where sig_name=? and sig_class_id=? and sig_priority=? and sig_rev=? and sig_sid=? and sig_gid is NULL";
\r
472 $dbi->execute($query,$description,$sig_class_id,$level,0,$rule);
\r
473 $count=$dbi->{sth}->rows;
\r
475 $row_ref=$dbi->{sth}->fetchrow_hashref;
\r
476 $sig_id=$row_ref->{sig_id};
\r
477 &printlog ("REUSING SIGNATURE\n");
\r
479 $query="INSERT INTO signature ( sig_id , sig_name , sig_class_id , sig_priority , sig_rev , sig_sid , sig_gid )
\r
481 NULL ,?, ? , ? , ? , ?, NULL
\r
483 $dbi->execute($query,$description,$sig_class_id,$level,0,$rule);
\r
484 $sig_id = $dbi->lastid();
\r
486 $dbi->{sth}->finish;
\r
487 &printlog ("SIGNATURE: $sig_id\n");
\r
490 ############################
\r
491 ############################
\r
493 # &printlog ("filtered: $filtered \n");
\r
494 # &printlog ("SRC IP: $srcip \n");
\r
495 # &printlog ("DST IP: $dstip \n");
\r
496 # &printlog ("mail: $mail \n");
\r
497 # &printlog ("sig_class_name: $sig_class_name");
\r
498 # &printlog ("date: $date \n");
\r
499 # &printlog ("alerthost: $alerthost \n");
\r
500 # &printlog ("rule: $rule \n");
\r
501 # &printlog ("level: $level \n");
\r
502 # &printlog ("OSSEC level: $osseclevel \n");
\r
503 # &printlog ("USER: $user \n");
\r
504 # &printlog ("text: $text \n");
\r
505 # &printlog ("sec?: $sec \n");
\r
506 # &printlog ("datasource: $datasource \n");
\r
507 # &printlog ("description: $description \n");
\r
509 ############################
\r
515 $query="INSERT INTO event ( sid , cid , signature , timestamp )
\r
520 $dbi->execute($query,$hids_id,$last_cid,$sig_id,&fixdate2base($date));
\r
522 &printlog ("EVENT: ($query,$hids_id,$last_cid,$sig_id,&fixdate2base($date)\n");
\r
523 $dbi->{sth}->finish;
\r
528 # And yet again,Snorby doesn't like empty IP fields; Validate if srcip or dstip are empty.
\r
529 $srcip = "1" if !defined $srcip; # leaving the fields srcip / dstip with a value = 0
\r
530 $dstip = "1" if !defined $dstip; # causes output to get messed up on the GUI.
\r
532 $query=" INSERT INTO iphdr ( sid , cid , ip_src , ip_dst , ip_ver , ip_hlen , ip_tos , ip_len , ip_id , ip_flags , ip_off , ip_ttl , ip_proto , ip_csum )
\r
534 ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?
\r
536 $dbi->execute($query,$hids_id,$last_cid,&ossec_aton($srcip),&ossec_aton($dstip),4,5,0,20,0,0,0,0,0,0);
\r
537 &printlog ("iphdr: ($query,$hids_id,$last_cid,&ossec_aton($srcip),&ossec_aton($dstip),4,5,0,undef,undef,undef,undef,undef,undef,undef)\n");
\r
538 $dbi->{sth}->finish;
\r
544 $payload = "$date ($alerthost) $dstip->$datasource\r\nRule: $rule (OSSEC level $osseclevel) -> $description\r\n$text";
\r
545 $payload =~ s/(.{1,109}\S|\S+)\s+/$1\r\n/mg; # Snorby does not wordwrap the payload, lets wrap the first 109 non-whitespace chars.
\r
546 $payload = unpack("H*",$payload); # Convert to HEX
\r
548 $query=" INSERT INTO data ( sid , cid , data_payload )
\r
551 $dbi->execute($query,$hids_id,$last_cid,$payload);
\r
552 &printlog ("DATA: ($query,$hids_id,$last_cid,$payload)\n");
\r
553 $dbi->{sth}->finish;
\r
556 $query="UPDATE sensor SET last_cid=? where sid=? limit 1";
\r
557 $numrows= $dbi->execute($query,$last_cid,$hids_id);
\r
559 $dbi->{sth}->finish;
\r
564 # This sub requires argument 0 to be a named host. We also need to know
\r
565 # the domain to which we belong to in order to append it to the host if
\r
566 # its a flatname host.
\r
568 my $domain=$conf{domain} if exists($conf{domain});
\r
571 # Validate if we were fed a flatnamed host or a FQDN.
\r
572 if ($host =~ m/.*\..+/){
\r
574 $CMD=`host $host 2>/dev/null | grep 'has address' `;
\r
575 if ($CMD =~m/(\d+\.\d+\.\d+\.\d+)/ ){
\r
578 return undef; # return False.
\r
583 if (! defined $domain or $domain eq ''){
\r
584 &printlog ('[WARNING]: domain value was not populated on ossec2snorby.conf." .
\r
585 " DNS resolutions cannot be completed for NetBIOS\Flatname hosts.');
\r
589 # There is an extra "." after $domain, this is to ensure linux
\r
590 # does not append "localdomain" at the end of the host.
\r
591 $CMD=`host $host.$domain. 2>/dev/null | grep 'has address' `;
\r
592 if ($CMD =~m/(\d+\.\d+\.\d+\.\d+)/ ){
\r
595 return undef; # return False.
\r
600 sub fixdate2base(){
\r
602 $date=~ s/ Jan /-01-/;
\r
603 $date=~ s/ Feb /-02-/;
\r
604 $date=~ s/ Mar /-03-/;
\r
605 $date=~ s/ Apr /-04-/;
\r
606 $date=~ s/ May /-05-/;
\r
607 $date=~ s/ Jun /-06-/;
\r
608 $date=~ s/ Jul /-07-/;
\r
609 $date=~ s/ Aug /-08-/;
\r
610 $date=~ s/ Sep /-09-/;
\r
611 $date=~ s/ Oct /-10-/;
\r
612 $date=~ s/ Nov /-11-/;
\r
613 $date=~ s/ Dec /-12-/;
\r
618 print "OSSEC report tool $VERSION\n";
\r
619 print "Licensed under GPL\n";
\r
620 print "Contributor Meir Michanie\n";
\r
625 print "This tool helps you import into base the alerts generated by ossec."
\r
626 . " More info in the doc directory .\n";
\r
628 print "$0 [-h|--help] # This text you read now\n";
\r
629 print "Options:\n";
\r
630 print "\t--dbhost <hostname>\n";
\r
631 print "\t--dbname <database>\n";
\r
632 print "\t--dbport <[0-9]+>\n";
\r
633 print "\t--dbpass <dbpasswd>\n";
\r
634 print "\t--dbuser <dbuser>\n";
\r
635 print "\t-d|--daemonize\n";
\r
636 print "\t-n|--noname\n";
\r
637 print "\t-v|--verbose\n";
\r
638 print "\t--conf <ossec2based-config>\n";
\r
639 print "\t--sensor <sensor-name>\n";
\r
640 print "\t--interface <ifname>\n";
\r
647 my $running = kill 0, `cat /var/run/ossec2base2.pid`;
\r
649 print "OSSEC2SNORBY is already running...\n";
\r
653 chdir '/' or die "Can't chdir to /: $!";
\r
655 open STDOUT, ">>$DAEMONLOGFILE"
\r
656 or die "Can't write to $DAEMONLOGFILE: $!";
\r
658 # I may be mistaken but the original script didn't seem to actually
\r
659 # tail the logs. It would run until it hit EOF and then exit script.
\r
660 $taillog= open STDIN,"-|", "/usr/bin/tail", "-Fn 0", "$LOG";
\r
662 &forceprintlog ("Daemon started TAIL PID: $taillog");
\r
663 &forceprintlog ("NOW MONITORING: $LOG");
\r
665 &forceprintlog ("Could not start daemon on $LOG: $!");
\r
669 defined(my $pid = fork) or die "Can't fork: $!";
\r
671 open (PIDFILE , ">/var/run/ossec2snorby.pid") ;
\r
672 print PIDFILE "$pid\n";
\r
676 setsid or die "Can't start a new session: $!";
\r
677 open STDERR, ">>$DAEMONLOGERRORFILE" or die "Can't write to $DAEMONLOGERRORFILE: $!";
\r
682 &forceprintlog ("Terminating upon signal $signal");
\r
683 &forceprintlog ("Daemon halted");
\r
684 # This might be paranoid or simply useless but better safe than sorry.
\r
685 close STDOUT or die "WARNING: Closing STDOUT failed.";
\r
686 close STDERR or die "WARNING: Closing STDERR failed.";
\r
687 kill 3, $taillog or die "WARNING: Closing $taillog failed.";
\r
688 close STDIN or die "WARNING: Closing STDIN failed.";
\r
693 return unless $VERBOSE;
\r
695 foreach my $line(@lines){
\r
697 my ($date)=scalar localtime;
\r
698 $date=~ s/^\S+\s+(\S+.*\s[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}).*$/$1/;
\r
699 print "$date $LOGGER: $line\n";
\r
706 my $conf=$hash_ref->{conf};
\r
707 unless (-f $conf) { &printlog ("ERROR: I can't find config file $conf"); exit 1;}
\r
708 unless (open ( CONF , "$conf")){ &printlog ("ERROR: I can't open file $conf");exit 1;}
\r
711 if ( m/^(\S+)\s?=\s?(.*?)$/) {
\r
712 $hash_ref->{$1} = $2;
\r