X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?a=blobdiff_plain;f=contrib%2Fossec2snorby%2Fossec2snorby.pl;fp=contrib%2Fossec2snorby%2Fossec2snorby.pl;h=ea3936fbeebd03086a72a504b18874a9cbb3ad3c;hb=789cbc8e52da68eba3517b920ef22e000cf3c9fd;hp=0000000000000000000000000000000000000000;hpb=ef70704f0b31b59bb719b884d6a99cb9e3e2044a;p=ossec-hids.git diff --git a/contrib/ossec2snorby/ossec2snorby.pl b/contrib/ossec2snorby/ossec2snorby.pl new file mode 100644 index 0000000..ea3936f --- /dev/null +++ b/contrib/ossec2snorby/ossec2snorby.pl @@ -0,0 +1,716 @@ +#!/usr/bin/perl -w +use Socket; +use POSIX 'setsid'; +use strict; +use ossecmysql; +# --------------------------------------------------------------------------- +# Author: Meir Michanie (meirm@riunx.com) +# Co-Author: J.A.Senger (jorge@br10.com.br) +# $Id$ +# --------------------------------------------------------------------------- +# http://www.riunx.com/ +# --------------------------------------------------------------------------- +# +# --------------------------------------------------------------------------- +# About this script +# --------------------------------------------------------------------------- +# +# "Ossec to Snorby" records the OSSEC HIDS alert logs in MySQL database. +# It can run as a daemon (ossec2snorby.pl), recording in real-time the logs in database or +# as a simple script (ossec2snorby.pl). +# +# --------------------------------------------------------------------------- +# Snorby support by Jean-Pierre Zurbrugg (jp.zurbrugg@live.com) +# --------------------------------------------------------------------------- +# The original script by the Author and Co-author was taken as a template and +# modified to work with Snorby (http://snorby.org) which uses a Snort DB schema. +# Credit must go to the author\Co-author for the initial template. +# +########################### WARNING ############################### +# My modifications are by far stable and worthy of a production environment +# WHITHOUT INICIAL TWEAKING. Please setup your labs and make sure everything +# works properly before using this script on a production environment. +########################### WARNING ############################### +# +# +# Changelog: +# * Extra validations were added to make sure srcip\dstip do not remain with +# a default value of "0" which causes GUI parsing errors if left unhandled. +# * Validation against '$hostname'; if localhost then srcip="127.0.0.1" +# * Snorby expects IP related data to be published on its "iphdr" table. +# * Snorby expects OSSEC's logs to be converted to HEX and wordwrapped. +# * Modified the scripts "Daemon" mode; it now uses "tail -Fn 0 " +# +# --------------------------------------------------------------------------- +# Prerequisites +# --------------------------------------------------------------------------- +# +# MySQL Server +# Perl DBD::mysql module +# Perl DBI module +# +# Snorby prerequesites: +# import ossec2snorby_category.sql from contrib directory +# Populate "domain" in /etc/ossec2snorby.conf +# +# --------------------------------------------------------------------------- +# Installation steps +# --------------------------------------------------------------------------- +# +# 1) Create a user to access the database initially created by Snorby; +# 2) Copy ossec2snorby.conf to /etc/ossec2snorby.conf with 0600 permissions +# 3) Edit /etc/ossec2snorby.conf according to your needs: +# dbhost=localhost +# database=snorby +# debug=5 +# dbport=3306 +# dbpasswd=mypassword +# dbuser=ossecuser +# daemonize=0 +# resolve=1 +# domain=mydomain.local +# +# NOTE: It is recommended to keep "resolve" as "1" and populate "domain" with +# your actual domain. Not doing so will restrict the script and force it +# to populate IPs as "0.0.0.1" for events whose SRC or DST IP are unknown. +# +# --------------------------------------------------------------------------- +# License +# --------------------------------------------------------------------------- +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# --------------------------------------------------------------------------- +# About OSSEC HIDS +# --------------------------------------------------------------------------- +# +# OSSEC HIDS is an Open Source Host-based Intrusion Detection System. +# It performs log analysis and correlation, integrity checking, +# rootkit detection, time-based alerting and active response. +# http://www.ossec.net +# +# --------------------------------------------------------------------------- + +# --------------------------------------------------------------------------- +# Parameters +# --------------------------------------------------------------------------- +my $VERSION="0.4"; +$SIG{TERM} = sub { &gracefulend('TERM')}; +$SIG{INT} = sub { &gracefulend('INT')}; + +# If no ARGV are given then present &help(). +&help() unless @ARGV; + +my ($RUNASDAEMON)=0; +my ($DAEMONLOGFILE)='/var/log/ossec2snorby.log'; +my ($DAEMONLOGERRORFILE) = '/var/log/ossec2snorby.err'; +# Declare OSSEC's log path and filename format. +my $LOG='/var/ossec/logs/alerts/alerts.log'; # we need to tail this file instead of the old. + # With this we can survive file rotations while + # running in daemon mode. + +my ($LOGGER)='ossec2snorby'; +my($OCT) = '(?:25[012345]|2[0-4]\d|1?\d\d?)'; +my($IP) = $OCT . '\.' . $OCT . '\.' . $OCT . '\.' . $OCT; +my $dump=0; +my ($hids_id,$hids,$hids_interface,$last_cid)=(undef, 'localhost', 'ossec',0); +my ($tempvar,$VERBOSE)=(0,0); + +my %conf; +$conf{dbhost}='localhost'; +$conf{database}='snort'; +$conf{debug}=5; +$conf{dbport}='3306'; +$conf{dbpasswd}='password'; +$conf{dbuser}='user'; +$conf{daemonize}=0; +$conf{sensor}='sensor'; +$conf{hids_interface}='ossec'; +$conf{resolve}=1; +$conf{domain}=''; + +# OSSEC's default class_ID +# We will categorize events as "unknown" if a match could not be found... +my $sig_class_id=2; # We will try to fetch the correct class_id later. + +my($sig_class_name,$taillog); +# --------------------------------------------------------------------------- +# Arguments parsing +# --------------------------------------------------------------------------- +while (@ARGV){ + $_= shift @ARGV; + if (m/^-d$|^--daemon$/){ + $conf{daemonize}=1; + }elsif ( m/^-h$|^--help$/){ + &help(); + }elsif ( m/^-n$|^--noname$/){ + $conf{'resolve'}=0; + }elsif ( m/^-v$|^--verbose$/){ + $VERBOSE=1; + }elsif ( m/^--interface$/){ + $conf{hids_interface}= shift @ARGV if @ARGV; # ossec-rt/ossec-feed + }elsif ( m/^--sensor$/){ + $conf{sensor}= shift @ARGV if @ARGV; # monitor + }elsif ( m/^--conf$/){ + $conf{conf}= shift @ARGV if @ARGV; # localhost + &loadconf(\%conf); + }elsif ( m/^--dbhost$/){ + $conf{dbhost}= shift @ARGV if @ARGV; # localhost + }elsif ( m/^--dbport$/){ + $conf{dbport}= shift @ARGV if @ARGV; # localhost + }elsif ( m/^--dbname$/){ + $conf{database}= shift @ARGV if @ARGV; # snort + }elsif ( m/^--dbuser$/){ + $conf{dbuser}= shift @ARGV if @ARGV; # root + }elsif ( m/^--dbpass$/){ + $conf{dbpasswd}= shift @ARGV if @ARGV; # monitor + } + +} +if ($conf{dbpasswd}=~ m/^--stdin$/){ + print "dbpassword:"; + $conf{dbpasswd}=<>; + chomp $conf{dbpasswd}; +} +$hids=$conf{sensor} if exists($conf{sensor}); +$hids_interface=$conf{hids_interface} if exists($conf{hids_interface}); + +# START IN DAEMON MODE ? +&daemonize() if $conf{daemonize}; + +my $dbi= ossecmysql->new(%conf) || die ("Could not connect to $conf{dbhost}:$conf{dbport}:$conf{database} as $conf{dbpasswd}\n"); + +#### +# SQL vars; +my ($query,$numrows,$row_ref); + +#### +#get sensor id +$query= 'select sid,last_cid from sensor where hostname=? and interface=?'; +$numrows= $dbi->execute($query,$hids,$hids_interface); +if (1==$numrows){ + $row_ref=$dbi->{sth}->fetchrow_hashref; + $hids_id=$row_ref->{sid}; + $last_cid=$row_ref->{last_cid}; +}else{ + $query="INSERT INTO sensor ( sid , hostname , interface , filter , detail , encoding , last_cid ) +VALUES ( +NULL , ?, ? , NULL , ? , ?, ? +)"; + $numrows= $dbi->execute($query,$hids,$hids_interface,1,2,0); + $hids_id=$dbi->lastid(); +} +$dbi->{sth}->finish; +&forceprintlog ("SENSOR:$hids; feed:$hids_interface; id:$hids_id; last cid:$last_cid"); + +my $newrecord=0; +my %stats; +my %resolv; +my ($timestamp,$sec,$mail,$date,$alerthost,$alerthostip,$datasource,$rule,$level,$description, + $srcip,$dstip,$user,$text,$filtered,$osseclevel)=(); +my $lasttimestamp=0; +my $delta=0; + +&taillog($last_cid,$LOG); +################################################################ +sub forceprintlog(){ + $tempvar=$VERBOSE; + $VERBOSE=1; + &printlog (@_); + $VERBOSE=$tempvar; +} + +sub taillog { + my ($last_cid,$LOG)=@_; + while (<>) { + if (m/^$/){ + # we reached a newline, finish up with current record. + $newrecord=1; + next unless $timestamp; + $alerthostip=$alerthost if $alerthost=~ m/^$IP$/; + + # Populate DST IP + if ($alerthostip){ + $dstip=$alerthostip; + $resolv{$alerthost}=$dstip; + + }else{ + if (exists $resolv{$alerthost}){ + $dstip=$resolv{$alerthost}; + }else{ + if ($conf{'resolve'}){ + if ($alerthost =~m/(\d+\.\d+\.\d+\.\d+)/ ){ + $dstip=$1; + }else{ + # the "host" command doesn't work with Flatname\NetBIOS names. + # The server's hostname is almost always a flatname and OSSEC + # doesn't return an IP for alerts generated from localhost. + # Ex. 2013 Jan 24 15:51:36 ubuntu->/var/log/auth.log + my $x = `cat /etc/hostname`; # get Host's hostname + chomp $x; # remove extra lines, if any. + if ($x eq $alerthost) { # Validate if $alerthost is us, localhost. + $dstip='127.0.0.1'; # Snorby does not allow empty\"0" as IP value. + }else{ + my $fetch=&host2ip($alerthost); + + if (defined $fetch){ + $dstip=$fetch; + }else{ + $dstip=$srcip; + } + } + } + } + $resolv{$alerthost}=$dstip; + } + } + + #Populate SRC IP (requires dstip to be populated) + if (! defined $srcip) { + if (defined $dstip) { + #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 + $filtered =~ s/$dstip//; # filter out known dstip from log output. + $srcip=$1 if $filtered=~ m/\s($IP)\s/; # Search all text for an IP address. + # This could easily bug out with logs that contains + # version numbering such as mysql 1.3.4.5. + } + # Windows logs include "User Name" in their log output. Some companies name their employees's PCs after its users which is + # resolvable via DNS. + # Windows logs may state a computer name as "User Name". Lets strip out the "$" from the computer name... + if (defined $user and ! defined $srcip) { + my $u=$user; + $u=~ s/\$//; # remove "$" from computer names. + + my $fetch=&host2ip($u); + $srcip=$fetch if (defined $fetch); + } + if (! defined $srcip or $srcip eq '') { + # NO recognizable IPs or User Names were found on log output, + # this suggests the log was generated by dstip. + $srcip=$dstip; + } + } + # + $last_cid= &prepair2basedata( + $hids_id, + $last_cid, + $timestamp, + $sec, + $mail, + $date, + $alerthost, + $datasource, + $rule, + $level, + $description, + $srcip, + $dstip, + $user, + $text + ); + ($timestamp,$sec,$mail,$date,$alerthost,$alerthostip,$datasource,$rule,$level,$description, + $srcip,$dstip,$user,$text)=(); + next ; + } + if (m/^\*\* Alert ([0-9]+).([0-9]+):(.*)$/){ + $timestamp=$1; + if ( $timestamp == $lasttimestamp){ + $delta++; + }else{ + $delta=0; + $lasttimestamp=$timestamp; + } + $sec=$2; + $mail=$3; + $mail=$mail ? $mail : 'nomail'; +#2006 Aug 29 17:19:52 firewall -> /var/log/messages +#2006 Aug 30 11:52:14 192.168.0.45->/var/log/secure +#2006 Sep 12 11:12:16 92382-Snort1 -> 172.16.176.132 + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s+(\S+)\s*->(.*)$/){ + $date=$1; + $alerthost=$2; + $datasource=$3; + if ($datasource=~ m/(\d+\.\d+\.\d+\.\d+)/){ + $alerthost=$1; + $datasource="remoted"; + } +#2006 Aug 29 17:33:31 (recepcao) 10.0.3.154 -> syscheck + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s+\((.*?)\)\s+(\S+)\s*->(.*)$/){ + $date=$1; + $alerthost=$2; + $alerthostip=$3; + $datasource=$4; + }elsif ( m/^([0-9]+\s\w+\s[0-9]+\s[0-9]+:[0-9]+:[0-9]+)\s(.*?)$/){ + $date=$1; + $alerthost='localhost'; + $datasource=$2; + }elsif ( m/Rule: ([0-9]+) \(level ([0-9]+)\) -> \'(.*)\'$/ ){ + $rule=$1; + $level=$2; + $osseclevel=$level; # Keep copy of OSSEC level as it will later be converted to snort level. + $description= $3; + }elsif ( m/src\s?ip:/i){ + if ( m/($IP)/){ + $srcip=$1; + }else{ + $srcip='1'; # Snorby doesn't like srcip\dstip = 0\null. + } + }elsif ( m/User: (.*)$/){ + $user=$1; + }elsif ( m/(.*)$/){ + my $x=$1; + + # Get IP from User Name + DNS query. + if (! defined $user){ + if ( m/User\s?Name:\s?(\S+)\s/i){ + my $u=$1; + $user="$u"; + } + } + $x =~ s/(.$)/$1\r\n/; # lets multiline this string for cleaner output once $payload wordwraps it. + $text .=$x; + + # This variable will be used to populate srcip once we reach the end of the current log entry. + $filtered=$text; + } + } # End of while read line +} + +sub ossec_aton(){ + my ($ip)=@_; + if ($ip=~ m/(\d+)\.(\d+)\.(\d+)\.(\d+)/){ + my $num= ($1 * 256 ** 3) + ($2 * 256 ** 2)+ ($3 * 256 ** 1)+ ($4); + + return "$num"; + }else{ + return "1"; # Snorby has a bug where it wont ouput "N\A" on the IP columns if srcip\dstip = 0\null + } + +} + +sub prepair2basedata(){ + my ( + $hids_id, + $last_cid, + $timestamp, + $sec, + $mail, + $date, + $alerthost, + $datasource, + $rule, + $level, + $description, + $srcip, + $dstip, + $user, + $text + )=@_; + my ($payload,$count,$query,$row_ref,$sig_id); + + +### +# Get sig_class_id +# +# Note: the original script stated sig_class_id as "1" by default which in BASE might be ok but for +# snorby it maps to a category of "not-suspicious" which is not efficient when stats are ran based on +# event categories alone... +# +# Furthermore, OSSEC allows a rule to have multiple categories assigned to it which snorby was not prepared to handle GUI +# wize. (The event details contains a small section where the category value can be shown, this section is too small +# to show OSSEC's sometimes long category results such as : +# syslog,sshd,invalid_login,authentication_failed,) +# +# We will use the last category shown only...This isn't the correct approach but my programing skills prevent me +# from providing a better solution. + + # ex: - syslog,sshd,invalid_login,authentication_failed, + if ($mail=~ m/\.*\,?(\w+\_?\w+)\,?$/){ # $mail contains the rule's categories. No clue why its named $mail... + $sig_class_name=$1; + &printlog ("SIG_CLASS_NAME: $sig_class_name \n"); + $query = "SELECT sig_class_id FROM category WHERE cat_name=?"; + $dbi->execute($query,$sig_class_name); + $count=$dbi->{sth}->rows; + if ($count){ + $row_ref=$dbi->{sth}->fetchrow_hashref; + $sig_class_id=$row_ref->{sig_class_id}; + &printlog ("SIG_CLASS_ID: $sig_class_id"); + }else{ + &printlog ("SIG_CLASS_ID NOT FOUND. USING DEFAULT SIG."); + $sig_class_id=2; + } + }else{ + &printlog ("COULD NOT GET A RULE CATEGORY. USING DEFAULT SIG."); + $sig_class_id=2; + } + +### +# +# Get/Set signature id + + # Convert OSSEC Severity to Snort Severity. + # Dont modify this after having live data on Snorby as it will create duplicated + # sig_names. + $level=4 if ($level <= 4); # Informational only. + $level=3 if ($level == 5); # User generated errors \ low severity. + $level=2 if (($level >= 6) && ($level <=11)); # Low to mid severity attacks. + $level=1 if ($level >= 12); # High importance events \ Successfull attacks \ all our bases belong to them! + + $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"; + $dbi->execute($query,$description,$sig_class_id,$level,0,$rule); + $count=$dbi->{sth}->rows; + if ($count){ + $row_ref=$dbi->{sth}->fetchrow_hashref; + $sig_id=$row_ref->{sig_id}; + &printlog ("REUSING SIGNATURE\n"); + }else{ + $query="INSERT INTO signature ( sig_id , sig_name , sig_class_id , sig_priority , sig_rev , sig_sid , sig_gid ) +VALUES ( +NULL ,?, ? , ? , ? , ?, NULL +)"; + $dbi->execute($query,$description,$sig_class_id,$level,0,$rule); + $sig_id = $dbi->lastid(); + } + $dbi->{sth}->finish; + &printlog ("SIGNATURE: $sig_id\n"); + + + ############################ + ############################ + #DEBUG + # &printlog ("filtered: $filtered \n"); + # &printlog ("SRC IP: $srcip \n"); + # &printlog ("DST IP: $dstip \n"); + # &printlog ("mail: $mail \n"); + # &printlog ("sig_class_name: $sig_class_name"); + # &printlog ("date: $date \n"); + # &printlog ("alerthost: $alerthost \n"); + # &printlog ("rule: $rule \n"); + # &printlog ("level: $level \n"); + # &printlog ("OSSEC level: $osseclevel \n"); + # &printlog ("USER: $user \n"); + # &printlog ("text: $text \n"); + # &printlog ("sec?: $sec \n"); + # &printlog ("datasource: $datasource \n"); + # &printlog ("description: $description \n"); + # exit 1; + ############################ + + +####### +# +# Set event + $query="INSERT INTO event ( sid , cid , signature , timestamp ) +VALUES ( +? , ? , ? ,? +)"; + $last_cid++; + $dbi->execute($query,$hids_id,$last_cid,$sig_id,&fixdate2base($date)); + + &printlog ("EVENT: ($query,$hids_id,$last_cid,$sig_id,&fixdate2base($date)\n"); + $dbi->{sth}->finish; +######### +# +# Set iphdr + + # And yet again,Snorby doesn't like empty IP fields; Validate if srcip or dstip are empty. + $srcip = "1" if !defined $srcip; # leaving the fields srcip / dstip with a value = 0 + $dstip = "1" if !defined $dstip; # causes output to get messed up on the GUI. + + $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 ) +VALUES ( +? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? +) "; + $dbi->execute($query,$hids_id,$last_cid,&ossec_aton($srcip),&ossec_aton($dstip),4,5,0,20,0,0,0,0,0,0); + &printlog ("iphdr: ($query,$hids_id,$last_cid,&ossec_aton($srcip),&ossec_aton($dstip),4,5,0,undef,undef,undef,undef,undef,undef,undef)\n"); + $dbi->{sth}->finish; + +######### +# +# +# Set data + $payload = "$date ($alerthost) $dstip->$datasource\r\nRule: $rule (OSSEC level $osseclevel) -> $description\r\n$text"; + $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. + $payload = unpack("H*",$payload); # Convert to HEX + + $query=" INSERT INTO data ( sid , cid , data_payload ) +VALUES ( +?,?,?)"; + $dbi->execute($query,$hids_id,$last_cid,$payload); + &printlog ("DATA: ($query,$hids_id,$last_cid,$payload)\n"); + $dbi->{sth}->finish; +########## +# + $query="UPDATE sensor SET last_cid=? where sid=? limit 1"; + $numrows= $dbi->execute($query,$last_cid,$hids_id); + + $dbi->{sth}->finish; + return $last_cid; +} # end sub + +sub host2ip { + # This sub requires argument 0 to be a named host. We also need to know + # the domain to which we belong to in order to append it to the host if + # its a flatname host. + my $host=$_[0]; + my $domain=$conf{domain} if exists($conf{domain}); + my $CMD; + + # Validate if we were fed a flatnamed host or a FQDN. + if ($host =~ m/.*\..+/){ + # FQDN + $CMD=`host $host 2>/dev/null | grep 'has address' `; + if ($CMD =~m/(\d+\.\d+\.\d+\.\d+)/ ){ + return($1); + }else{ + return undef; # return False. + } + + }else{ + # FLATNAME + if (! defined $domain or $domain eq ''){ + &printlog ('[WARNING]: domain value was not populated on ossec2snorby.conf." . + " DNS resolutions cannot be completed for NetBIOS\Flatname hosts.'); + return undef; + } + + # There is an extra "." after $domain, this is to ensure linux + # does not append "localdomain" at the end of the host. + $CMD=`host $host.$domain. 2>/dev/null | grep 'has address' `; + if ($CMD =~m/(\d+\.\d+\.\d+\.\d+)/ ){ + return($1); + }else{ + return undef; # return False. + } + } +} + +sub fixdate2base(){ + my ($date)=@_; + $date=~ s/ Jan /-01-/; + $date=~ s/ Feb /-02-/; + $date=~ s/ Mar /-03-/; + $date=~ s/ Apr /-04-/; + $date=~ s/ May /-05-/; + $date=~ s/ Jun /-06-/; + $date=~ s/ Jul /-07-/; + $date=~ s/ Aug /-08-/; + $date=~ s/ Sep /-09-/; + $date=~ s/ Oct /-10-/; + $date=~ s/ Nov /-11-/; + $date=~ s/ Dec /-12-/; + $date=~ s/\s$//g; + return $date; +} +sub version(){ + print "OSSEC report tool $VERSION\n"; + print "Licensed under GPL\n"; + print "Contributor Meir Michanie\n"; +} + +sub help(){ + &version(); + print "This tool helps you import into base the alerts generated by ossec." + . " More info in the doc directory .\n"; + print "Usage:\n"; + print "$0 [-h|--help] # This text you read now\n"; + print "Options:\n"; + print "\t--dbhost \n"; + print "\t--dbname \n"; + print "\t--dbport <[0-9]+>\n"; + print "\t--dbpass \n"; + print "\t--dbuser \n"; + print "\t-d|--daemonize\n"; + print "\t-n|--noname\n"; + print "\t-v|--verbose\n"; + print "\t--conf \n"; + print "\t--sensor \n"; + print "\t--interface \n"; + + exit 0; +} + + +sub daemonize { + my $running = kill 0, `cat /var/run/ossec2base2.pid`; + if ($running){ + print "OSSEC2SNORBY is already running...\n"; + exit 1; + } + + chdir '/' or die "Can't chdir to /: $!"; + + open STDOUT, ">>$DAEMONLOGFILE" + or die "Can't write to $DAEMONLOGFILE: $!"; + + # I may be mistaken but the original script didn't seem to actually + # tail the logs. It would run until it hit EOF and then exit script. + $taillog= open STDIN,"-|", "/usr/bin/tail", "-Fn 0", "$LOG"; + if ($taillog){ + &forceprintlog ("Daemon started TAIL PID: $taillog"); + &forceprintlog ("NOW MONITORING: $LOG"); + }else{ + &forceprintlog ("Could not start daemon on $LOG: $!"); + exit 1; + } + + defined(my $pid = fork) or die "Can't fork: $!"; + if ($pid){ + open (PIDFILE , ">/var/run/ossec2snorby.pid") ; + print PIDFILE "$pid\n"; + close (PIDFILE); + exit 0; + } + setsid or die "Can't start a new session: $!"; + open STDERR, ">>$DAEMONLOGERRORFILE" or die "Can't write to $DAEMONLOGERRORFILE: $!"; +} + +sub gracefulend(){ + my ($signal)=@_; + &forceprintlog ("Terminating upon signal $signal"); + &forceprintlog ("Daemon halted"); + # This might be paranoid or simply useless but better safe than sorry. + close STDOUT or die "WARNING: Closing STDOUT failed."; + close STDERR or die "WARNING: Closing STDERR failed."; + kill 3, $taillog or die "WARNING: Closing $taillog failed."; + close STDIN or die "WARNING: Closing STDIN failed."; + exit 0; +} + +sub printlog(){ + return unless $VERBOSE; + my (@lines)=@_; + foreach my $line(@lines){ + chomp $line; + my ($date)=scalar localtime; + $date=~ s/^\S+\s+(\S+.*\s[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}).*$/$1/; + print "$date $LOGGER: $line\n"; + } + } + + +sub loadconf(){ + my ($hash_ref)=@_; + my $conf=$hash_ref->{conf}; + unless (-f $conf) { &printlog ("ERROR: I can't find config file $conf"); exit 1;} + unless (open ( CONF , "$conf")){ &printlog ("ERROR: I can't open file $conf");exit 1;} + while (){ + next if m/^$|^#/; + if ( m/^(\S+)\s?=\s?(.*?)$/) { + $hash_ref->{$1} = $2; + } + } + close CONF; +}