Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Jun 2001 14:24:14 -0400 (EDT)
From:      Dru <genisis@istar.ca>
To:        Mike Meyer <mwm@mired.org>
Cc:        <questions@FreeBSD.ORG>
Subject:   Re: script not found in /usr/local/etc/rc.d
Message-ID:  <20010617141853.S48172-100000@x1-6-00-50-ba-de-36-33.kico1.on.home.com>
In-Reply-To: <15148.61274.704322.668319@guru.mired.org>

next in thread | previous in thread | raw e-mail | index | archive | help

Hi Mike,

Forgive the long post, as this time I'll include both scripts instead of
sending them as attachments. (feel free to snip the appropriate portions)
Thanks for the help guys :)

Dru

more /usr/local/etc/rc.d/mnwclient.sh
#!/bin/sh
#
# mnwclient     This shell script takes care of starting and stopping
#               myNetWatchman Agent for FreeBSD
#
# description: mnwclient
# untested needs default paths of /bin and /usr/bin

# Check that networking is up.
#[ ${NETWORKING} = "no" ] && exit 0

# check if the mnwclient.rc file is present
[ -f /etc/mnwclient.rc ] || exit 0

# check to see if mnwclient exists
[ -f /usr/sbin/mnwclient ] || exit 0

if [ $# -eq 0 -o x$1 = xstart ]; then
    /usr/sbin/mnwclient -c /etc/mnwclient.rc &
fi

if [ x$1 = xstop ]; then
   /bin/kill `ps | grep 'perl.*mnwclient' | cut -f 1 -d " "`
fi

*************************************************************************

more /usr/sbin/mnwclient
#!/usr/bin/perl -w
##
## mnwclient - a Perl client for myNetWatchman
## Copyright (C) 2001  Chad Wagner
##
## 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##


## mnwclient -- a Perl client for myNetWatchman
## $Id: mnwclient,v 1.9 2001/05/01 03:46:12 wagnerch Exp $

use Getopt::Std;
use IO::Socket;
use POSIX;


## DEFAULTS ##

## configuration file, where configuration parameters are stored
$mnwclientrc = "/etc/mnwclient.rc";

## this is where Packet log kernel messages are logged, typically
## /var/log/messages, but may vary based on distribution.
$logfile = "/var/log/messages";

## user interface to upload packets for
$interface = "ppp0";

## default chain to inspect, typically 'input'
@chaintbl = ("input");

## location to write error messages, success, etc
$errorlog = "/var/log/mnwclient.log";

## gmt correction offset, in seconds.
$gmt = 0;

## default delay interval between rescanning log
$interval = 60;

## default dequeue interval in seconds.
$dqinterval = 1;

## default backoff factor
$backoff = 3;

## maximum backoff factor
$maxbackoff = 600;

## default debug level
$debug = 0;

## DO NOT MODIFY BELOW THIS LINE ##

## version number
$mnwvers = "1.9";

## this is the server and port
$server = "www.mynetwatchman.com";
$port = 80;
$script = "/insertwebreport.asp";

## unbuffer i/o
$| = 1;

## process switches and arguments
getopts("i:c:l:e:zh", \%args);

## set overrides
$mnwclientrc = $args{c} if defined $args{c};  ## override rc file
$errorlog    = $args{e} if defined $args{e};  ## override errors log

## check for invalid conditions, or help request
if (defined $args{h}) {
  printf "%s [-c resource_file] [-l kernel_log_file] [-e errors_log_file]\n\t[-i interface]\n\n",$0;
  printf "   -c resource_file      data file that holds configuration parameters\n";
  printf "   -l kernel_log_file    where the kernel logs dropped or filtered packets\n";
  printf "   -e errors_log_file    where this client logs error messages\n";
  printf "   -i interface          upload data for interface\n";
  exit 1;
}

## open pointer resource file
if (open(FD,$mnwclientrc)) {
  $braces=0;
  @filtbl=();
  while (<FD>) {
    $_ =~ s/\n$//g;
    $_ =~ s/^\s*//g;
    $_ =~ s/\s*$//g;
    if (m/^#/ || m/^$/) {
      ## comment
    } elsif ((m/^interface\s+(.*)$/) && (!$braces)) {
      ## interface directive
      $interface=$1;
    } elsif ((m/^chain\s+(.*)$/) && (!$braces)) {
      ## chain directive
      @chaintbl=split(/,/,$1);
    } elsif ((m/^errors\s+(.*)$/) && (!$braces)) {
      ## errors log directive
      $errorlog=$1;
    } elsif ((m/^log\s+(.*)$/) && (!$braces)) {
      ## log directive
      $logfile=$1;
    } elsif ((m/^login\s+(.*)$/) && (!$braces)) {
      ## login directive
      $agtname=$1;
    } elsif ((m/^password\s+(.*)$/) && (!$braces)) {
      ## password directive
      $agtpass=$1;
    } elsif ((m/^server\s+(.*)$/) && (!$braces)) {
      ## server directive
      $server=$1;
    } elsif ((m/^port\s+(.*)$/) && (!$braces)) {
      ## port directive
      $port=$1;
    } elsif ((m/^proxy\s+(.*)$/) && (!$braces)) {
      ## proxy directive
      ($proxyserver,$proxyport) = split(/:/,$1,2);
    } elsif ((m/^debug(?:\s+(.*))?$/) && (!$braces)) {
      ## debug directive
      if ($1 ne "") {
        $debug = $1;
      } else {
        $debug=1;
      }
    } elsif ((m/^quiet$/) && (!$braces)) {
      ## quiet directive
      $quiet=1;
    } elsif ((m/^test$/) && (!$braces)) {
      ## test directive
      $test=1;
    } elsif ((m/^gmt\s+(.*)$/) && (!$braces)) {
      ## gmt directive
      $gmt=$1 * 3600;
    } elsif ((m/^retry\s+(.*)$/) && (!$braces)) {
      ## retry directive, ignored
    } elsif ((m/^interval\s+(.*)$/) && (!$braces)) {
      ## interval directive
      $interval=$1;
    } elsif ((m/^dqinterval\s+(.*)$/) && (!$braces)) {
      ## dqinterval directive
      $dqinterval=$1;
    } elsif ((m/^backoff\s+(.*)$/) && (!$braces)) {
      ## backoff directive
      $backoff=$1;
    } elsif ((m/^maxbackoff\s+(.*)$/) && (!$braces)) {
      ## maxbackoff directive
      $maxbackoff=$1;
    } elsif ((m/^filter\s+\{$/) && (!$braces)) {
      ## filter directive, open braces mode
      $braces=1;
    } elsif ((m/^\}$/) && ($braces)) {
      ## close braces mode
      $braces=0;
    } elsif ($braces) {
      ## braces mode
      if (m/^source\s+([0-9,\.]+)\s+netmask\s+([0-9,\.]+)$/) {
        ## filter-source/netmask directive
        push(@filtbl,[0,$1,$2]);
      } elsif ((m/^port\s+(\d+)(?:\s+proto\s+(\w+))?$/) ||
               (m/^target\s+port\s+(\d+)(?:\s+proto\s+(\w+))?$/)) {
        ## filter-target/port/proto directive
        push(@filtbl,[1,$1,$2]);
      } elsif (m/^proto\s+(\w+)$/) {
        ## filter-proto directive
        push(@filtbl,[2,$1]);
      } elsif (m/^target\s+([0-9,\.]+)\s+netmask\s+([0-9,\.]+)$/) {
        ## filter-target/netmask directive
        push(@filtbl,[3,$1,$2]);
      } elsif (m/^source\s+port\s+(\d+)(?:\s+proto\s+(\w+))?$/) {
        ## filter-source/port/proto directive
        push(@filtbl,[4,$1,$2]);
      } elsif (m/^target\s+([0-9,\.]+)\s+netmask\s+([0-9,\.]+)\s+xchg\s+([0-9,\.]+)$/) {
        ## filter-target/netmask/xchg directive
        push(@filtbl,[5,$1,$2,$3]);
      } else {
        ## unknown filter directive
        printf STDERR "unknown filter directive encountered in configuration file, \"%s\"\n",$_;
      }
    } else {
      ## unknown directive
      printf STDERR "unknown directive encountered in configuration file, \"%s\"\n",$_;
    }
  }
  close(FD);
} else {
  printf STDERR "failed to open \"%s\" for reading: %s\n",$mnwclientrc,$!;
  exit 1;
}

## warn about resource file being world/group readable/writable
$mode = (stat($mnwclientrc))[2];
&warning("configuration file is set world/group readable/writeable.\n") if ($mode & 077);


## override logfile, if set on command line
$logfile = $args{l} if defined $args{l};

## override interface, if set on command line
$interface = $args{i} if defined $args{i};

## check for agent name and password
if (!defined $agtname || !defined $agtpass) {
  &fatal("agent name or password must be defined.\n");
}

## check for valid proxy port, if defined
if (defined $proxyserver) {
  if (!$proxyport) {
    &fatal("proxy directive has invalid port, or undefined port.\n");
  }
}

## stat log file and get current size
$size = (stat($logfile))[7];
$offset=$size;
$offset=0 if defined $args{z};

## initialize msgq list
@msgq=();

## report version, and state that we are running
&printk("mnwclient version %s, monitoring \"%s\" starting at offset %lu\n",$mnwvers,$logfile,$offset);

## initialize several scalars here
my($proto)=0;
my(%protonum) = (      ## protocol table
  'TCP'  => 6,         ## tcp
  'tcp'  => 6,         ## tcp
  'UDP'  => 17,        ## udp
  'udp'  => 17,        ## udp
  'ICMP' => 1,         ## icmp
  'icmp' => 1          ## icmp
);

my($count);            ## attack count
my($match);            ## match regex, used for checking for 'repeated' msgs
my($success);          ## match regex, used to submit report

## setup currdqinterval equal to dqinterval, and var for lastdq stamp
my($currdqinterval) = $dqinterval;
my($lastdq) = time;

while (1) {
  ## stat log file and get current size
  $size = (stat($logfile))[7];

  ## if offset is larger then size then logfile has been reset
  $offset=0 if ($offset > $size);

  ## read in log file, and store in data array
  open(FD,$logfile) || &fatal("unable to open kernel log for reading \"%s\": %s\n",$logfile,$!);
  seek(FD,$offset,SEEK_SET);

  while (<FD>) {
    ## initialize scalars on each looping
    $count = 1;
    $success = 0;

    ## dump debug info
    &printk("debug: logread [%s]\n",$_) if ($debug >= 9);

    ## this is our regexp that we are looking to extract meaningful data from
    if (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+kernel:\s+Packet\s+log:\s+(\w+)\s+(REJECT|DENY)\s+(\w+)\s+PROTO=(\d+)\s+([0-9,\.]+):(\d+)\s+([0-9,\.]+):(\d+)/) {
      ## deal with ipchains log formatting
      if (&ischain($2) && $4 eq $interface) {
        @last = ($1,$5,$6,$7,$8,$9);
        $match = 1;
        $success = 1;
      } else {
        $match = 0;
      }
    } elsif (m/id=firewall/) {
      ## deal with sonicwall log formatting
      my($fwtime,$fwc,$fwm,$fwsrcaddr,$fwsrcport,$fwdstaddr,$fwdstport);
      if (m/time=\"(\d+-\d+-\d+\s+\d+:\d+:\d+(?:\s+UTC)?)\"/) {
        $fwtime=$1;
      }
      if (m/c=(\d+)/) {
        $fwc=$1;
      }
      if (m/m=(\d+)/) {
        $fwm=$1;
      }
      if (m/src=([\w,\.]+)(?::(\d+))?:WAN/) {
        $fwsrcaddr=$1;
        $fwsrcport=$2;
      }
      if (m/dst=([\w,\.]+)(?::(\d+):\w+)?/) {
        $fwdstaddr=$1;
        $fwdstport=$2;
      }
      $proto = 0;
      if ($fwc == 32) {
        my(%protocvt) = (     ## port/proto -- attack
          22  => 1,           ## icmp       -- ping of death
          23  => 0,           ## ip         -- ip spoof (unsupported)
          27  => 6,           ## tcp        -- land
          67  => 0,           ## ???        -- ipsec auth failed (unsupported)
          70  => 0,           ## ???        -- ipsec dropped (unsupported)
          72  => 6,           ## tcp        -- netbus
          73  => 6,           ## 31337/tcp  -- back orifice
          74  => 6,           ## 1024/tcp   -- net spy
          75  => 6,           ## 27374/tcp  -- subseven
          76  => 6,           ## 2023/tcp   -- ripper
          77  => 6,           ## 2565/tcp   -- striker
          78  => 17,          ## 13000/udp  -- senna spy
          79  => 6,           ## 16969/tcp  -- priority
          80  => 6,           ## 9989/tcp   -- inikiller
          81  => 1,           ## icmp       -- smurf
          82  => 0,           ## ???        -- probable port scan (unsupported)
          83  => 0,           ## ???        -- probable port scan (unsupported)
          84  => 6,           ## tcp        -- syn port scan
          173 => 6            ## tcp        -- fin port scan
        );
        $proto = $protocvt{$fwm};
      } else {
        my(%protocvt) = (      ## packets dropped
           64  => 6,           ## tcp
           128 => 17,          ## udp
           256 => 1            ## icmp
        );
        $proto = $protocvt{$fwc};
      }

      ## check for fwdstport and icmp proto, if not defined assume it is
      ## type 0 icmp (echo-request)
      $fwdstport=0 if ($proto == 1 && !defined $fwdstport);

      ## check for fwsrcport, if not defined then assign it as -1, which is
      ## 'not displayed'
      $fwsrcport=-1 if (!defined $fwsrcport);

      ## must have all necessary fields, and protocol nonzero
      if (defined $fwtime && defined $fwsrcaddr && defined $fwsrcport &&
          defined $fwdstaddr && defined $fwdstport && $proto) {
        @last = ($fwtime,$proto,$fwsrcaddr,$fwsrcport,$fwdstaddr,$fwdstport);
        $match = 1;
        $success = 1;
      } else {
        $match = 0;
      }
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+portsentry\[\d+\]:\s+attackalert:\s+(.+\s+scan|Packet|Connect)\s+from\s+host:\s+\S+\/([0-9,\.]+)\s+to\s+(\w+)\s+port:\s+(\d+)/) {
      ## deal with portsentry log formatting
      $proto = $protonum{$4};
      @last = ($1,$proto,$3,-1,-1,$5);
      $match = 1;
      $success = 1;
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\S+:\s+ipfw:\s+\d+\s+(REJECT|DENY)\s+(TCP|UDP)\s+([0-9,\.]+):(\d+)\s+([0-9,\.]+):(\d+)\s+(\w+)\s+via\s+(\w+)/i) {
      ## deal with ipfw log formatting udp/tcp (freebsd)
      $proto = $protonum{$3};
      if (&ischain($8) && $9 eq $interface) {
        @last = ($1,$proto,$4,$5,$6,$7);
        $match = 1;
        $success = 1;
      } else {
        $match = 0;
      }
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\S+:\s+ipfw:\s+\d+\s+(REJECT|DENY)\s+(ICMP):(\d+)\.(\d+)\s+([0-9,\.]+)\s+([0-9,\.]+)\s+(\w+)\s+via\s+(\w+)/i) {
      ## deal with ipfw log formatting icmp (freebsd)
      if (&ischain($8) && $9 eq $interface) {
        @last = ($1,1,$6,$4,$7,$5);
        $match = 1;
        $success = 1;
      } else {
        $match = 0;
      }
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\d+:\s+([\*]*)(\w+\s+\d+\s+\d+:\d+:\d+)(?:\.\d+\s+\w+)?:\s+\S+:\s+list\s+(\d+)\s+denied\s+(tcp|udp)\s+([0-9,\.]+)\((\d+)\)\s+->\s+([0-9,\.]+)\((\d+)\),\s+(\d+)\s+packet/i) {
      ## deal with cisco format tcp/udp
      if (&ischain($4)) {
        $proto = $protonum{$5};
        @last = ($1,$proto,$6,$7,$8,$9);

        ## use date from router if not marked invalid
        @last = ($3,$proto,$6,$7,$8,$9) if ($2 eq "");

        $count = $10;
        $match = 1;
        $success = 1;
      } else {
        $match = 0;
      }
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\d+:\s+([\*]*)(\w+\s+\d+\s+\d+:\d+:\d+)(?:\.\d+\s+\w+)?:\s+\S+:\s+list\s+(\d+)\s+denied\s+(icmp)\s+([0-9,\.]+)\s+->\s+([0-9,\.]+)\s+\((\d+)\/(\d+)\),\s+(\d+)\s+packet/i) {
      ## deal with cisco format icmp
      if (&ischain($4)) {
        @last = ($1,1,$6,$8,$7,$9);

        ## use date from router if not marked invalid
        @last = ($3,1,$6,$8,$7,$9) if ($2 eq "");

        $count = $10;
        $match = 1;
        $success = 1;
      } else {
        $match = 0;
      }
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+named\[\d+\]:\s+(denied|unapproved)\s+query\s+from\s+\[([0-9,\.]+)\]\.(\d+)\s+for\s+\"version\.bind/i) {
      ## deal with version.bind named requests
      @last = ($1,6,$3,$4,-1,53);
      $match = 1;
      $success = 1;
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\S+\s+IP\[Src=([0-9,\.]+)\s+Dst=([0-9,\.]+)\s+(\w+)(?:\s+spo=(\d+)\s+dpo=(\d+))?\]\s*\}\s*S(\d+)>R(\d+)(m|n)D/) {
      ## (syslog format) zyxel prestige 314/netgear rt314 router
      ## only 'm'atched or 'n'ot matched 'D'rops
      if (&ischain($7)) {
        $proto = $protonum{$4};
        if ($proto == 1) {
          @last = ($1,$proto,$2,-1,$3,8);
        } else {
          @last = ($1,$proto,$2,$5,$3,$6);
        }

        $match = 1;
        $success = 1;
      } else {
        $match = 0;
      }
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+kernel:\s+(.*):\s+IN=(\S*)\s+OUT=(\S*)\s+(?:MAC=[\d,a-f,:]+\s+)?SRC=([\d,\.]+)\s+DST=([\d,\.]+)\s+LEN=\d+\s+TOS=[\w,x]+\s+PREC=[\w,x]+\s+TTL=\d+\s+ID=\d+\s+(?:DF\s+)?PROTO=(\w+)(?:\s+TYPE=(\d+)\s+CODE=(\d+))?(?:\s+SPT=(\d+)\s+DPT=(\d+))?/) {
      ## iptables syslog format
      if (&ischain($2) && $3 eq $interface) {
        $proto = $protonum{$7};
        if ($proto == 1) {
          ## icmp packet
          @last = ($1,$proto,$5,-1,$6,$8);
        } else {
          ## tcp/udp/? packet
          @last = ($1,$proto,$5,$10,$6,$11);
        }

        $match = 1;
        $success = 1;
      } else {
        $match = 0;
      }
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Deny\s+inbound\s+(UDP)\s+from\s+([\d,\.]+)\/(\d+)\s+to\s+([\d,\.]+)\/(\d+)/ ||
             m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Deny\s+inbound\s+(\w+)\s+src\s+\w+:\s*([\d,\.]+)\/(\d+)\s+dst\s+\w+:([\d,\.]+)\/(\d+)/ ||
             m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Dst\s+IP\s+is\s+network\/broadcast\s+IP,\s+translation\s+creation\s+failed\s+for\s+(\w+)\s+src\s+\w+:\s*([\d,\.]+)\/(\d+)\s+dst\s+\w+:\s*([\d,\.]+)\/(\d+)/ ||
             m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Inbound\s+(TCP)\s+connection\s+denied\s+from\s+([\d,\.]+)\/(\d+)\s+to\s+([\d,\.]+)\/(\d+)/) {
      ## PIX-2-106006, inbound UDP packet
      ## PIX-3-106010, inbound TCP/UDP packet, broadcast destination
      ## PIX-3-305006, inbound TCP/UDP packet, broadcast destination
      ## PIX-2-106001, inbound TCP packet
      $proto = $protonum{$4};
      @last = ($1,$proto,$5,$6,$7,$8);

      $match = 1;
      $success = 1;
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Deny\s+inbound\s+(icmp)\s+src\s+\w+:\s*([\d,\.]+)\s+dst\s+\w+:\s*([\d,\.]+)\s+\(type\s+(\d+),\s+code\s+(\d+)\)/ ||
             m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Dst\s+IP\s+is\s+network\/broadcast\s+IP,\s+translation\s+creation\s+failed\s+for\s+(icmp)\s+src\s+\w+:\s*([\d,\.]+)\s+dst\s+\w+:\s*([\d,\.]+)\s+\(type\s+(\d+),\s+code\s+(\d+)\)/) {
      ## PIX-3-106010, inbound ICMP packet, broadcast destination
      ## PIX-3-305006, inbound ICMP packet, broadcast destination
      $proto = $protonum{$4};
      @last = ($1,$proto,$5,-1,$6,$7);

      $match = 1;
      $success = 1;
    } elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Deny\s+(IP)\s+from\s+([\d,\.]+)\s+to\s+([\d,\.]+),\s+IP\s+options/) {
      ## PIX-2-106012, inbound IP packet
      ## currently we do nothing with this packet
    } elsif (m/^\w+\s+\d+\s+\d+:\d+:\d+\s+\S+\s+\%PIX-(\d+)-(\d+):\s+.{0,1}last\s+message\s+repeated\s+(\d+)\s+time/ && $match) {
      ## our last message was a packet log message, so lets repeated the
      ## previously collected data n times.
      $count = $3;
      $success = 1;
    } elsif (m/^\w+\s+\d+\s+\d+:\d+:\d+\s+\S+\s+last\s+message\s+repeated\s+(\d+)\s+times/ && $match) {
      ## our last message was a packet log message, so lets repeated the
      ## previously collected data n times.
      $count = $1;
      $success = 1;
    } else {
      ## reset match, and update offset
      $match = 0;
      $offset = tell(FD);
    }
    if ($success) {
      $offset = tell(FD);
      &queue_attack($last[0],$last[1],$last[2],$last[3],$last[4],$last[5],$count);
    }
  }
  close(FD);

  ## enter interval delay loop, we want to sleep currdqinterval seconds and
  ## pop a queued attack off the stack and upload it while we are waiting
  ## for the interval delay loop to elapse.
  local($then) = time;
  while ((time - $then) < $interval) {
    if (($currdqinterval - (time - $lastdq)) > $interval) {
      &printk("debug: (currdqinterval %lu - (time %lu - lastdq %lu)) > interval %lu\n",$currdqinterval,time,$lastdq,$interval) if ($debug >= 2);
      ## if interval is greater than current remaining dqinterval then
      ## just sleep the interval
      sleep($interval);
    } elsif (($currdqinterval - (time - $lastdq)) > $dqinterval) {
      &printk("debug: (currdqinterval %lu - (time %lu - lastdq %lu)) > dqinterval %lu\n",$currdqinterval,time,$lastdq,$dqinterval) if ($debug >= 2);
      ## if the current remaining dqinterval is greater than dqinterval then
      ## just sleep the remaining value less one dqinterval
      sleep($currdqinterval - (time - $lastdq) - $dqinterval);
    } else {
      &printk("debug: sleeping currdqinterval %lu - (time %lu - lastdq %lu)\n",$currdqinterval,time,$lastdq) if ($debug >= 2);
      ## otherwise just sleep the current remaining dqinterval, and then
      ## dequeue an attack
      sleep($currdqinterval - (time - $lastdq));
      &dequeue_attack;
      $lastdq = time;
    }
  }
}

## looks up protocol number in list and shows given name, only icmp, tcp and
## udp are in here, as they are likely most of the traffic.
sub show_proto_name {
  my($num) = shift if @_;
  my(%protonum) = (      ## protocol table
    1  => 'icmp',        ## icmp
    6  => 'tcp',         ## tcp
    17 => 'udp'          ## udp
  );

  &printk("debug: show_proto_name returning results %s\n",($protonum{$num} eq "" ? $num : $protonum{$num})) if ($debug >= 2);
  if ($protonum{$num} ne "") {
    ## we got a valid protocol number, return it's name
    return $protonum{$num};
  } else {
    ## we got a invalid protocol number, return it's number
    return $num;
  }
}

## checks to see if matches input chain
## 0 on failure, 1 on success
sub ischain {
  my($in) = shift;

  foreach (@chaintbl) {
    if ($in eq $_) {
      &printk("debug: ischain returning true, %s == %s\n",$in,$_) if ($debug >= 2);
      return 1;
    }
  }

  &printk("debug: ischain returning false\n") if ($debug >= 2);
  return 0;
}

## checks to see if source address, port, or port and protocol are filtered
sub isfiltered {
  my($proto)   = shift;
  my($srcaddr) = shift;
  my($srcport) = shift;
  my($dstaddr) = shift;
  my($dstport) = shift;
  my($newdstaddr);
  my($retcode) = 0;

  &printk("debug: isfiltered called with arguments %s,%s,%s,%s,%s\n",
          $$proto,$$srcaddr,$$srcport,$$dstaddr,$$dstport) if ($debug >= 2);

  ## parse through filter table
  foreach (@filtbl) {
    if (@$_[0] == 0) {          ## source addr filter
      if (&maskaddress(@$_[1],@$_[2]) == &maskaddress($$srcaddr,@$_[2])) {
        $retcode=1;
        last;
      }
    } elsif (@$_[0] == 1) {     ## target port filter
      if (@$_[1] == $$dstport) { ## target port is a filter match
        if (defined(@$_[2])) {  ## is proto specified, at all?
          if (@$_[2] eq &show_proto_name($$proto)) {
            $retcode=1;         ## proto and port match, reject
            last;
          }
        } else {                ## no proto, port already matchs, so reject
          $retcode=1;
          last;
        }
      }
    } elsif (@$_[0] == 2) {     ## proto filter
      if (@$_[1] eq &show_proto_name($$proto)) {
        $retcode=1;             ## protocol matches, reject
        last;
      }
    } elsif (@$_[0] == 3) {     ## destination addr filter
      if (&maskaddress(@$_[1],@$_[2]) == &maskaddress($$dstaddr,@$_[2])) {
        $retcode=1;
        last;
      }
    } elsif (@$_[0] == 4) {     ## source port filter
      if (@$_[1] == $$srcport) { ## source port is a filter match
        if (defined(@$_[2])) {  ## is proto specified, at all?
          if (@$_[2] eq &show_proto_name($$proto)) {
            $retcode=1;         ## proto and port match, reject
            last;
          }
        } else {                ## no proto, port already matchs, so reject
          $retcode=1;
          last;
        }
      }
    } elsif (@$_[0] == 5) {     ## target address exchange
      if (&maskaddress(@$_[1],@$_[2]) == &maskaddress($$dstaddr,@$_[2])) {
        $newdstaddr = @$_[3];   ## address is a match, store the new dstaddr
                                ## in a scalar for use after parsing further
                                ## filter rules
      }
    } else {                    ## unknown filter element
      &warning("unknown filter element, type=%d\n",@$_[0]);
    }
  }

  ## okay, we did a target...xchg, need to reparse filter table with new
  ## dstaddr.
  if (defined $newdstaddr) {
    $$dstaddr = $newdstaddr;
    $retcode = &isfiltered($proto,$srcaddr,$srcport,$dstaddr,$dstport);
  }

  &printk("debug: isfiltered returning results %s\n",$retcode) if ($debug >= 2);
  return $retcode;
}

## apply netmask to address and return result
sub maskaddress {
  my($address) = shift;
  my($netmask) = shift;

  &printk("debug: maskaddress returning results %s\n",&addr_to_32($address) & &addr_to_32($netmask)) if ($debug >= 2);
  return (&addr_to_32($address) & &addr_to_32($netmask));
}

## convert dotted ip notation to 32-bit number
sub addr_to_32 {
  my($address) = shift;
  my($a1,$a2,$a3,$a4);

  ($a1,$a2,$a3,$a4) = split(/\./,$address);
  &printk("debug: addr_to_32 returning results %s\n",($a1 << 24) | ($a2 << 16) | ($a3 << 8) | $a4) if ($debug >= 2);
  return ($a1 << 24) | ($a2 << 16) | ($a3 << 8) | $a4;
}

## translate date into format required, and utc
sub transdate {
  my($date) = shift;
  my($time_t);
  my(%monnum) = (
    'Jan' => 0,
    'Feb' => 1,
    'Mar' => 2,
    'Apr' => 3,
    'May' => 4,
    'Jun' => 5,
    'Jul' => 6,
    'Aug' => 7,
    'Sep' => 8,
    'Oct' => 9,
    'Nov' => 10,
    'Dec' => 11
  );
  my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);

  ## if date is in correct format, translate it to utc
  if ($date =~ m/^(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)/) {
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    $time_t = POSIX::mktime($5,$4,$3,$2,$monnum{$1},$year,0,0,$isdst);
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time_t + $gmt);
    return sprintf "%04d-%02d-%02d %02d:%02d:%02d",($year + 1900),
           ($mon + 1),$mday,$hour,$min,$sec;
  } elsif ($date =~ m/^(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)\s+UTC/) {
    return sprintf "%04d-%02d-%02d %02d:%02d:%02d",$1,$2,$3,$4,$5,$6;
  } elsif (($date =~ m/^(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/) ||
           ($date =~ m/^(\d+)\/(\d+)\/(\d+),(\d+):(\d+):(\d+)/)) {
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    $time_t = POSIX::mktime($6,$5,$4,$3,($2 - 1),($1 - 1900),0,0,$isdst);
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time_t + $gmt);
    return sprintf "%04d-%02d-%02d %02d:%02d:%02d",($year + 1900),
           ($mon + 1),$mday,$hour,$min,$sec;
  }

  ## otherwise we use current utc time
  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime(time);
  return sprintf "%04d-%02d-%02d %02d:%02d:%02d",($year + 1900),
         ($mon + 1),$mday,$hour,$min,$sec;
}

## adds attack data to outbound queue
sub queue_attack {
  my($datetime) = shift;
  my($proto)    = shift;
  my($srcaddr)  = shift;
  my($srcport)  = shift;
  my($dstaddr)  = shift;
  my($dstport)  = shift;
  my($count)    = shift;

  ## we are going to do some prefiltering, even though in some cases we
  ## don't know the destination address
  if (!&isfiltered(\$proto,\$srcaddr,\$srcport,\$dstaddr,\$dstport)) {
    ## initialize some local variables
    my($mqe);
    my($success) = 0;

    ## first thing we want to do is find a matching entry already in the
    ## queue, we report time on first attack, this shouldn't be a problem
    ## unless the interval is set too large, say more than 2 minutes.
    foreach $mqe (@msgq) {
      ## if this attack matches a previously queued one then increment
      ## the attack count.  criteria for matching is same proto,
      ## source address, dest address, dest port.
      if (@$mqe[1] == $proto && @$mqe[2] eq $srcaddr &&
          @$mqe[4] eq $dstaddr && @$mqe[5] == $dstport) {
        ## add the attack count of this one to the queued one
        @$mqe[6] += $count;
        &printk("debug: incq: %s,%s,%s,%s,%s,%s,%s\n",
               @$mqe[0],@$mqe[1],@$mqe[2],@$mqe[3],@$mqe[4],@$mqe[5],
               @$mqe[6]) if ($debug);
        $success = 1;
        last;
      }
    }

    ## if it wasn't already in the queue, add it now
    if (!$success) {
      ## add it to the outbound attack queue
      push(@msgq,[&transdate($datetime),$proto,$srcaddr,$srcport,$dstaddr,$dstport,$count]);
      &printk("debug: addq: %s,%s,%s,%s,%s,%s,%s\n",
             &transdate($datetime),$proto,$srcaddr,$srcport,$dstaddr,$dstport,
             $count) if ($debug);
    }
  }
}

## dequeue attack and upload to server
sub dequeue_attack {
  my($datetime,$proto,$srcaddr,$srcport,$dstaddr,$dstport,$count);
  my($lastmq,@mqe);

  ## only process if there is something in queue
  if ($#msgq >= 0) {
    ## pull last entry out, and store it in some local variables
    $lastmq = $msgq[$#msgq];
    @mqe = @$lastmq;
    $datetime = $mqe[0];
    $proto    = $mqe[1];
    $srcaddr  = $mqe[2];
    $srcport  = $mqe[3];
    $dstaddr  = $mqe[4];
    $dstport  = $mqe[5];
    $count    = $mqe[6];

    ## attempt to submit the report, if successful then pop it off the msgq
    if (&submit_report($datetime,$proto,$srcaddr,$srcport,$dstaddr,$dstport,$count)) {
      ## we can officially pop it off the stack now, since it was
      ## successfully uploaded.
      pop(@msgq);
      &printk("debug: popq: %s,%s,%s,%s,%s,%s\n",
             $datetime,$proto,$srcaddr,$srcport,$dstaddr,$dstport,
             $count) if ($debug);
    } else {
      ## backoff factor, calculate into currdqinterval
      $currdqinterval *= $backoff;

      ## set currdqinterval to maxbackoff if we exceed it
      $currdqinterval = $maxbackoff if ($currdqinterval > $maxbackoff);

      ## failed, dump whatever server responded with
      &warning("unable to upload %d attack(s) from %s:%d to %s:%d/%s, dequeue interval backing off to %lu seconds.\n",$count,$srcaddr,$srcport,$dstaddr,$dstport,&show_proto_name($proto),$currdqinterval);
    }
  }
}

## uploads data to server and parses
## returns 0 on failure, 1 on success
sub submit_report {
  my($datetime) = shift;
  my($proto)    = shift;
  my($srcaddr)  = shift;
  my($srcport)  = shift;
  my($dstaddr)  = shift;
  my($dstport)  = shift;
  my($count)    = shift;

  my($request);
  my($output);
  my($response);
  my($sd);
  my($success) = 0;

  if ($test) {
    if (!&isfiltered(\$proto,\$srcaddr,\$srcport,\$dstaddr,\$dstport)) {
      ## we are in 'test' mode, don't actually upload data
      &printk("upload %d attack(s) from %s%s to %s%d/%s successful (test mode).\n",$count,$srcaddr,($srcport >= 0 ? sprintf(":%d",$srcport) : ""),($dstaddr ne "-1" ? sprintf("%s:",$dstaddr) : ""),$dstport,&show_proto_name($proto));
    }
    return 1;
  }

  ## open new socket to server
  {
    local $^W = 0;
    if (defined $proxyserver && defined $proxyport) {
      $sd = IO::Socket::INET->new(
                                  PeerAddr => $proxyserver,
                                  PeerPort => $proxyport,
                                  Proto    => 'tcp');

      ## start building HTTP get request, via proxy
      $output  = sprintf "GET http://%s:%lu%s",$server,$port,$script;
    } else {
      $sd = IO::Socket::INET->new(
                                  PeerAddr => $server,
                                  PeerPort => $port,
                                  Proto    => 'tcp');

      ## start building HTTP get request
      $output  = sprintf "GET %s",$script;
    }
    if (!defined($sd)) {
      ## socket error, we bail out with a failure to retry later
      &warning("cannot connect to %s: socket: %s\n",$server,$@);
      return 0;
    }
  }

  ## we only want to probe the IP address if we don't know it, basically for
  ## log formats such as portsentry.
  if ($dstaddr eq "-1") {
    &printk("debug: dstaddr is %s, probing\n",$dstaddr) if ($debug);
    $dstaddr = sprintf("%s.%s.%s.%s",unpack("C4",(unpack("S n a4 x8",getsockname($sd)))[2]));
    &printk("debug: acquired %s address from socket probe\n",$dstaddr) if ($debug);
  }

  ## check to see if this firewall entry is filtered
  if (&isfiltered(\$proto,\$srcaddr,\$srcport,\$dstaddr,\$dstport)) {
    ## packet is filtered, return with a success code
    &printk("debug: packet is filtered, dropping\n") if ($debug);
    return 1;
  }

  ## build our data submission portion of url
  $request = sprintf "AgentEmail=%s&AgentPassword=%s&AttackerIP=%s&DestPort=%s&VictimIP=%s&AttackCount=%s&AttackDateTime=%s&ProtocolID=%s",$agtname,$agtpass,$srcaddr,$dstport,$dstaddr,$count,$datetime,$proto;

  ## convert spaces to %20
  $request =~ s/ /%20/g;

  ## attach data to end of get
  $output .= sprintf "?%s HTTP/1.0\n",$request;

  ## build out HTTP GET request
  $output .= sprintf "Host: %s\n",$server;
  $output .= "Content-Type: application/x-www-form-urlencoded\n";
  $output .= sprintf "User-Agent: myNetWatchman Perl Agent/%s\n\n",$mnwvers;

  ## send it via the socket created
  print $sd $output;

  ## print debugging, if requested
  &printk("debug: send [%s]\n",$output) if ($debug >= 10);

  ## read in data from socket, setup for failure
  $success=0;
  $response="";
  while (<$sd>) {
    $response .= $_;
    &printk("debug: read [%s]\n",$_) if ($debug >= 10);
    if (m/Attack\s+Report\s+Insert\s+Successful/) {
      ## we were successful, success should be 1
      $success=1;
    }
  }
  close($sd);

  if (!$success) {
    if ($response =~ m/Error:\s+(.*?)<BR>/) {
      &warning("error response returned: %s\n",$1);
    } else {
      &warning("unknown response on attack insert from %s.\n",$server);
    }
    return 0;
  } else {
    ## upload successful
    &printk("upload %d attack(s) from %s%s to %s:%d/%s successful.\n",$count,$srcaddr,($srcport >= 0 ? sprintf(":%d",$srcport) : ""),$dstaddr,$dstport,&show_proto_name($proto));
    $currdqinterval = $dqinterval;
    return 1;
  }

  ## should never reach this far
  return 0;
}

## warning message
sub warning
{
  printf STDERR "warning: " if (!$quiet);
  printf STDERR @_ if (!$quiet);
  &printk(@_);
}

## fatal message
sub fatal
{
  printf STDERR "fatal: ";
  printf STDERR @_;
  &printk(@_);
  exit 1;
}

## print kernel style message to custom log file
sub printk
{
  my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
  my(%months) = (
    0  => 'Jan',
    1  => 'Feb',
    2  => 'Mar',
    3  => 'Apr',
    4  => 'May',
    5  => 'Jun',
    6  => 'Jul',
    7  => 'Aug',
    8  => 'Sep',
    9  => 'Oct',
    10 => 'Nov',
    11 => 'Dec'
  );

  ## open log file for appending
  open(LOGMSG,">>".$errorlog) || die "fatal: unable to append to error log: $!\n";

  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  printf LOGMSG "%s %2s %02d:%02d:%02d mnwclient[%d]: ",$months{$mon},$mday,
                $hour,$min,$sec,$$;
  printf LOGMSG @_;

  close(LOGMSG);
}


On Sun, 17 Jun 2001, Mike Meyer wrote:

> Dru <genisis@istar.ca> types:
> > However, when I try to start the script manually or when I reboot, I get
> > an error message stating the script is not found:
> >
> > /etc/rc: /usr/local/etc/rc.d/mnwclient.sh: not found
> >
> > What am I missing here besides my sanity? I've attached the script if that
> > helps.
>
> The #! line in the script is fubar for some reason that's causing the
> kernel exec to fail. The report back to the shell is that the file
> isn't executable (stupid, but apparently required by Posix), so the
> shell reports that it can't find the executable.
>
> Joe Clark's guess - that it's pointing at the wrong place - is the
> usual cause for that. There are other things that might make it do
> that as well.
>
> Can you send just that line? I know you attached the script, but
> freebsd.org's mail digester eats the MIME headers, so my mailer can't
> decode what you sent :-(.
>
> 	<mike
> --
> Mike Meyer <mwm@mired.org>			http://www.mired.org/home/mwm/
> Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
>
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-questions" in the body of the message
>
>
>
>


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010617141853.S48172-100000>