Category Archives: Downloads

check_honeynet v2.0.a2

Release 2.0.a2 (Alpha quality) for check_honeynet is here :-), go check it out!

[perl]
#!/usr/bin/perl
# $Id: check_honeynet.pl 801 2008-06-03 20:40:53Z remko $
###########################################################################

###########################################################################
# Copyright (C) 2005-2008, Remko Lodder . All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS “AS IS” AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
###########################################################################

###########################################################################
# Contributors:
# Ivo Naninck, (Language), Marc Plaisier (language), Mart vd Wege (Mailer
# suggestion),
# Lance Spitzner (the most valueable feedback regarding the script).
# Richard Arends (suggested the actual perl mailer; and gave a good example
# on how to use the module),
# Robert Blacquiere (showed me Simple::Config, which I am using now to
# obtain configuration informatin, as well as write statistics to a
# temporary file)
#
# Script:
# This is a stand alone script written for honeynet.org. It’s purpose is
# to check the listed mirrors to see which one is outdated and notify
# the administrator of the outdated mirror if needed. This way the
# mirrors will always be within a certain timeframe and can be removed
# if they are too outdated.
#
# Written in colaboration with Lance Spitzner
###########################################################################

###########################################################################
# Differences between releases, started this between 1.5 and 1.6 sorry
# for the loss of potential usefull information (although I might be able
# to retrieve the missing data from my CVS branches).
# Note that all the three version based versions are just bugfixes to some
# degree.
# Version Who What
# 1.1 Remko Initial script to check the mirrors.
# 1.1->1.2 Remko
# 1.2->1.3 Remko
# 1.3->1.4 Remko
# 1.4->1.5 Remko Code cleanups, restructure of code; corrected
# some bugs between various releases spotted
# by Lance.
# 1.5->1.6 Remko Cleanups, changed structure for timestamp
# retrieval; make it human readable and match
# on a specific pattern. Made the version dependend
# on the configuration version and visa-versa
# to be able to make big config changes.
# BF-1: Fix the email send options by using the
# correct Net::SMTP commands.
# BF-1: Fix the parsing of the new mirrorprobe
# layout.
# BF-2: Change the Mailer used to send out the
# report.
# 1.6->1.7 Remko Implement Config::Simple, makes configuration
# much easier!
# 1.7->2.0 Remko a1: Implement that we can trace various sites with
# multiple problems more easily by using a
# semi-persisent configuration file. This brings
# the entire branch to an entirely new world.
# Which is why we bump the version to 2.0
# a2: Implement file-statistics checker, if the
# file does not exist yet, we need to make sure
# we know and that we can bypass certain readins
# so that we are not going to get into trouble
# later on.
###########################################################################

use strict;
use warnings;
use LWP::Simple;
use Getopt::Std;
use Mail::Sendmail;
use Config::Simple;

###########################################################################
# variables. All configurable options are defined below. Please adjust them
# to your need.
###########################################################################

# Version, author and script specific behaviour
my $author = ‘Remko Lodder ‘; # Name of the author
my $name = __FILE__; # Our scriptname.
my $MAJOR = ’2′; # Our major version
my $MINOR = ’0′; # Our minor version
my $PATCHLEVEL = ‘a2′; # Our patchlevel
my $version = “$MAJOR.$MINOR.$PATCHLEVEL”; # Our version.

###########################################################################
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Do not edit anything below this line unless you know what you are doing.
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
###########################################################################

###########################################################################
# Prototypes, specify upfront what we are going to use if globally needed
# and prototype arrays, hashes and functions.
###########################################################################

# create the option hash, we will use that later to add our option flags.
my %option = ();

# Template our arrays
my (@MIRRORS);

# Template some standard variables
my ($CONFIGFILE, $status, $reporthost, $timestamp,$target,
$enable_mail, $cfg, $cfg_out, $outfile, $alert_max,
$alert_min, $alert_mid, $mail_from, $mail_bcc, $mail_cc);

# Prototype functions
sub fetch_data ($$);
sub email_report ($$$);
sub convert_input ($);
sub process_mirrors (@);
sub create_timestamp ($);

###########################################################################
# Script itself
###########################################################################

getopts(“cC:f:F:hpR:tv”, \%option);

my $config_flag = 1 if $option{f};
my $config_option = $option{f};

my $create_flag = 1 if $option{c};
my $help_flag = 1 if $option{h};
my $process_flag = 1 if $option{p};
my $test_flag = 1 if $option{t};
my $convert_flag = 1 if $option{C};
my $fetch_flag = 1 if $option{F};
my $retrieve_flag = 1 if $option{R};

# Simply assign the contents of the configuration parameter to the
# configuration file variable, otherwise overrule it with the
# default value

$CONFIGFILE = $config_option || “./honeynet.cf”;

# Read in current configuration.
# This should always succeed, in case it doesn’t then we cannot do
# anything at all.

$cfg = new Config::Simple($CONFIGFILE);

#####
##### Global variable assignment after reading config
#####

# Read in some variales upfront, so that we can more
# easily use them later on.

@MIRRORS = $cfg->param(‘CONFIG.mirrors’);
$outfile = $cfg->param(‘CONFIG.outfile’);
$enable_mail = $cfg->param(‘CONFIG.enable_mail’);
$alert_max = $cfg->param(‘CONFIG.alert_max’);
$alert_mid = $cfg->param(‘CONFIG.alert_mid’);
$alert_min = $cfg->param(‘CONFIG.alert_min’);
$mail_from = $cfg->param(‘CONFIG.fromaddr’);
$mail_bcc = $cfg->param(‘CONFIG.ccaddr’);
$mail_cc = $cfg->param(‘CONFIG.mirroradmin’);

if (-e “$outfile”)
{

# Read in the statistics from our last run
$cfg_out = new Config::Simple($outfile);

# Make an instant backup before we do a new run.
$cfg_out->write(“$outfile.orig”);
}
else
{
# Create the statistics file for our entire run
$cfg_out = new Config::Simple(syntax=>’ini’);
}

# Make sure that there us a version statement in the configuration file, so that we can see whether we are
# compabible or not.

if (!$cfg->param(‘CONFIG.version’))
{
print “It appears that you do not have a version statement in your configuration file. This means that the version you are using now is
too old, make sure that you obtain the latest one and update that to your needs.”;
exit(1);
}

if ($cfg->param(‘CONFIG.version’))
{
my($version_def_major,$version_def_minor) = $cfg->param(‘CONFIG.version’) =~ /(\d+)\.(\d+)/;

# the script can defer between MAJOR and MINOR releases; bugfixes aka patchlevels are
# not affected by this and can thus be ignored.
# TODO: This check should be made more flexible in the future, version 1.4 and 1.5 share
# the same configuration file and should both pass.

if(($version_def_major lt $MAJOR) or ($version_def_minor lt $MINOR))
{
print “You appear to be using an older configuration file that might not be compatible with the current version of the
script, please validate that you have the latest options included and copy over the version statement from the latest available configuration
file. Make sure that the old version statement is overwritten!
The current script runs on version: $version, while the configuration is for version $cfg->param(‘CONFIG.version’)\n”;
exit(1);
}
}

# Create a new timestamp that will be fed into the mirrors, which we can use to test the
# age of the mirror.

if ($create_flag) {
create_timestamp($cfg->param(‘CONFIG.probefile’));
}

elsif ($process_flag) {
# Process the mirrors using the hash we have for them.
process_mirrors(@MIRRORS);
}

# test mode, printout information on screen.
elsif($test_flag)
{
# In test mode we dont send out emails.
$enable_mail = 0;

print(“$name: Starting\n”);
print(“$name: Processing mirrors\n”);

# Process the mirrors using the hash we have for them.
process_mirrors(@MIRRORS);

print(“$name: Finishing\n”);
}

# convert input from unixtime to human readable time.
elsif($convert_flag)
{
print “$option{C} resolves to ” . convert_input($option{C}) . “\n”;
}

# fetch the mirrorprobe file from the given host
elsif($fetch_flag)
{
my $result = fetch_data($option{F}, $cfg->param(‘CONFIG.sourcefile’));
open(OUT, “> $cfg->param(‘CONFIG.outdir’)/$option{F}.timestamp”);
print OUT $result;
close(OUT);
}

# Fetch the mirror timestamp and parse it. Print the output back on the screen.
elsif($retrieve_flag)
{
my $result = fetch_data($option{R}, $cfg->param(‘CONFIG.sourcefile’));
print(“$option{R} was last modified ” . convert_input($result) . “\n”);
}

# People expect a help option, provide it for them.
elsif ($help_flag)
{
print_help();
}

# No valid options had been given, fallback to the help information.
else
{
print_help();
}

# print_help: expects no input, just prints the help information on how
# the application should work.
sub print_help
{
print(“Usage:\t$name [ -c ] [ -C ] [ -f ] [ -F ] [ -h ] [ -p ] [ -R ] [ -t ]
\t-c\tCreate the timestamp for the localmachine. This timestamp can be used to determine when the mirror was last updated.
\t-C\t converts the unix timestamp to human readable format
\t-f\t Use the specified configuration file
\t-F\t fetch the timestamp for an external host, for example: www.honeynet.nl
\t-h\tprint this help.
\t-p\tCheck the status of the mirrors, and report the output to us
\t-t\tTest mode, does not send out emails, but prints the information on the screen.
Version: $version
Originally written by Remko Lodder }

# create_timestamp: expects a variable filled with where we should store
# the unixtime (for remote mirrors).
sub create_timestamp ($)
{
my $probefile = shift;
open(F_OUT, "> $probefile”);
print F_OUT “Mirrorprobe time: ” . time() . ”
Local time: ” . convert_input(time());
close F_OUT;
}

# convert_input: expects unixtime and converts it to human readable time.
sub convert_input ($)
{
my $output = scalar localtime(shift);
return $output;
}

# fetch_data: gets two variables as input, one with the fqdn of the remote host and one
# with the location of where we expect the remote file. XXX: This looks a bit ugly at the
# moment.
sub fetch_data ($$)
{
my $source = shift;
my $sourcefile = shift;

my $return_data = ();
my $data = get(“http://$source$sourcefile”);

# IF the remote data is present, take out the numberic time value and return that
# ELSE obscure the data, which will revert to 1969/1970 (depending on what the machine
# considers EPOCH).
if ($data)
{
chomp $data;

$return_data = $data;
$return_data =~ s/\n/\ /;
if ($return_data =~ /\S+ \S+ (\d+) \S+/)
{
$return_data = $1;
}
return $return_data;
}

else
{
$data = 0;
return $data;
}
}

# proccess_mirrors: gets an array as input with all the mirrors in it. It will walk through all hosts
# and do specific actions with them, like printing out a report, or emailing it to the remote
# administrator. It keeps a record of the current statustime.
sub process_mirrors (@) {
my %mirror_time;
my @mirror_list = @_;

for my $target(@mirror_list)
{
$mirror_time{$target} = fetch_data($target,$cfg->param(‘CONFIG.sourcefile’));

# We should probably dont need to use this since it is implied in the routine itself.
if(!$mirror_time{$target})
{
$mirror_time{$target} = 0;
}

# declare our local time before continueing.
my $honeynet_ctime = time();
my $mirror_ctime = $mirror_time{$target};
my $mirror_difftime = $honeynet_ctime – $mirror_time{$target};

# If the resulting number is less then zero, the remote host is outdated.
my $mirror_timediff = $cfg->param(‘CONFIG.timeout’) – $mirror_difftime;

# Everything that has a calculated time which is bigger then the timeout is
# on the right track, everything that isn’t, gets either notified or the
# output will be present on screen.
if ($mirror_timediff gt “0″)
{
if($cfg->param(‘CONFIG.verbose’) ne “0″)
{
$status = “OK”;
$timestamp = scalar localtime($mirror_time{$target});
$reporthost = $target;
write; # Write out our template.
}
next;
}
else
{
my $info = $cfg_out->param(“mirrors.$target”);
if (defined $info && $info gt 0)
{
if ($info eq $alert_max || $info eq $alert_mid || $info eq $alert_min)
{
# The email option is enabled and we found an outdated mirror
# jump to the email_report function.
if($enable_mail)
{
email_report($target,$mirror_time{$target},$info);
}
}

# Update our local statistics first before anything else
$cfg_out->param(“mirrors.$target”, $info+1);
$cfg_out->param(“checktime.$target”, scalar localtime($mirror_time{$target}));
}
else
{
# The email option is enabled and we found an outdated mirror
# jump to the email_report function.
if ($enable_mail)
{
email_report($target,$mirror_time{$target}, $alert_min);
}

# Begin our statistics with 1.
$cfg_out->param(“mirrors.$target”, 1);
$cfg_out->param(“checktime.$target”, scalar localtime($mirror_time{$target}));
}

if($cfg->param(‘CONFIG.verbose’) ne “0″)
{
$status = “FAIL”;
$timestamp = scalar localtime($mirror_time{$target});

# Only override if the message has the old timestamp and thus is broken.
if($timestamp =~ /19[6-7]\d/)
{
$timestamp = “Mirrorprobe file problems!”;
}
$reporthost = $target;
write; # Write out our template.
}
}
}

# Specify how our output is going to look like. This generates a nice overview
# on the current status of the various mirrors. This is only being used if we
# print verbose.
# Below: HEADER
format STDOUT_TOP =
—————————————————————————-
————————— Honeynet Check results ————————-
—————————————————————————-
Status Site Last changed
.

# Format specifier for the content of the printout.
format STDOUT =
@<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<
$status, $reporthost, $timestamp
.
}

# email_report: expects a target and a mirror_time, sends out an email to
# the desired administrator and informs them about the current status of
# the mirror.
sub email_report ($$$)
{
my $status = ();
my $alert_msg = ();
my $target = shift;
my $mirror_time = shift;
my $alert = shift;
my $recipient = $cfg->param(“MIRRORS.$target”) || $mail_cc;

# Make the mirror time a human parseable time, if this matches the beginning of time
# (For computers at least). Tell that there is a problem.
$mirror_time = scalar localtime($mirror_time);

if ($mirror_time =~ /19[6-7]\d/)
{
$status = “Your mirror seems to have troubles fetching the mirrorprobe file.”;
}
else
{
$status = “At this moment it seems that your mirror was last updated on $mirror_time.”;
}
if ($alert eq $alert_max)
{
$alert_msg = “NOTE WELL: This is the final warning you will be receiving. Please repair the mirror as soon as possible. In the meantime we will remove your mirror.”;
}
else
{
$alert_msg = “NOTE WELL: This is alert number $alert for your host. Please be advised that our current maximum is at $alert_max.\n”;
}

my $message = “Hello $recipient,

You are recieving this email because your Honeynet Project mirror ($target) seems to be outdated.
$status

Could you please check whether everything is working as expected?
If there is something wrong or you do no longer wish to be a mirror, please notify $mail_cc

Thanks for supporting the Honeynet Project!

If you have questions or concerts, please do not hesitate to contact us!

$alert_msg


The Honeynet Project Mirror Admins”;

# Fill our mailhash with information that we are going to send.
my %mail = (
To => “$recipient”,
From => “$mail_from”,
Bcc => “$mail_bcc”,
# only addresses are extracted from Bcc, real names disregarded
Cc => “$mail_cc”,
# Cc will appear in the header. (Bcc will not)
Subject => “$target seems to be outdated, please investigate”,
‘X-Mailer’ => “$name $version using Mail::Sendmail version $Mail::Sendmail::VERSION”,
message => “$message”,
);

# Add an additional header so that we can show that this is our thing.
$mail{‘Honeynet.org : ‘} = “http://www.honeynet.org”;

# Send out the mail, if succesfull print that we did OK else
# give error.
if (sendmail %mail)
{
print “Mail alert sent OK.\n”;
}
else
{
print “Error sending mail: $Mail::Sendmail::error \n”
}
}

# And as a final action make sure we write out our configuration file.
# Temporary to write out the exact config to our statistics file, later we will use this to write
# down our run-time statistics into a “peristent” file.

$cfg_out->write($outfile);

# End of the script.
[/perl]

Check_Honeynet v1.7

Here is Check_Honeynet v1.7

check_honeynet.pl:

[perl]
#!/usr/bin/perl
# $Id: check_honeynet.pl,v 1.48.2.3 2008/03/24 14:46:14 remko Exp $
###########################################################################

###########################################################################
# Copyright (C) 2005-2008, Remko Lodder . All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS “AS IS” AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
###########################################################################

###########################################################################
# Contributors:
# Ivo Naninck, (Language)
# Marc Plaisier, (Language)
# Mart van de Wege, (suggested a different mailer in 2006, told me that it
# should run on a high level interface as easy as possible, I discarded
# the idea back then, till Richard came with a good idea).
# Lance Spitzner (the most valueable feedback regarding the script).
# Richard Arends (suggested the actual perl mailer; and gave a good example
# on how to use the module)
# Robert Blacquiere (showed me Simple::Config, which I am using now to
# obtain configuration informatin, as well as write statistics to a
# temporary file)
#
# Script:
# This is a stand alone script written for honeynet.org. It’s purpose is
# to check the listed mirrors to see which one is outdated and notify
# the administrator of the outdated mirror if needed. This way the
# mirrors will always be within a certain timeframe and can be removed
# if they are too outdated.
#
# A while ago Mart vd Wege told me that a higher level mail module would be
# much easier to cope with. This had been implemented as of version 1.6.2
#
# Written in colaboration with Lance Spitzner
###########################################################################

###########################################################################
# Differences between releases, started this between 1.5 and 1.6 sorry
# for the loss of potential usefull information (although I might be able
# to retrieve the missing data from my CVS branches).
# Note that all the three version based versions are just bugfixes to some
# degree.
# Version Who What
# 1.1 Remko Initial script to check the mirrors.
# 1.1->1.2 Remko
# 1.2->1.3 Remko
# 1.3->1.4 Remko
# 1.4->1.5 Remko Code cleanups, restructure of code; corrected
# some bugs between various releases spotted
# by Lance.
# 1.5->1.6 Remko Cleanups, changed structure for timestamp
# retrieval; make it human readable and match
# on a specific pattern. Made the version dependend
# on the configuration version and visa-versa
# to be able to make big config changes.
# BF-1: Fix the email send options by using the
# correct Net::SMTP commands.
# BF-1: Fix the parsing of the new mirrorprobe
# layout.
# BF-2: Change the Mailer used to send out the
# report.
# 1.6->1.7 Remko Implement Config::Simple, makes configuration
# much easier!
###########################################################################

use strict;
use warnings;
use LWP::Simple;
use Getopt::Std;
use Mail::Sendmail;
use Config::Simple;

###########################################################################
# variables. All configurable options are defined below. Please adjust them
# to your need.
###########################################################################

# Hash to store our entire configuration in.
my %CONFIG = ();

# create the option hash, we will use that later to add our option flags.
my %option = ();

# Template some standard variables
my ($CONFIGFILE, $status, $reporthost, $timestamp,$target, @MIRRORS, $enable_mail, $cfg);

# Prototype functions
sub fetch_data ($$);
sub email_report ($$);
sub convert_input ($);
sub process_mirrors (@);
sub create_timestamp ($);

# Version, author and script specific behaviour
my $author = ‘Remko Lodder ‘; # Name of the author, respect the license.
my $name = __FILE__; # Our scriptname.
my $MAJOR = ’1′; # Our major version number
my $MINOR = ’7′; # Our minor version number
my $PATCHLEVEL = ’0′; # Our patchlevel
my $version = “$MAJOR.$MINOR.$PATCHLEVEL”; # Our version.

###########################################################################
# Do not edit anything below this line unless you know what you are doing.
###########################################################################

getopts(“cC:f:F:hpR:t”, \%option);

my $config_flag = 1 if $option{f};
my $config_option = $option{f};

my $create_flag = 1 if $option{c};
my $help_flag = 1 if $option{h};
my $process_flag = 1 if $option{p};
my $test_flag = 1 if $option{t};
my $convert_flag = 1 if $option{C};
my $fetch_flag = 1 if $option{F};
my $retrieve_flag = 1 if $option{R};

# Simply assign the contents of the configuration parameter to the
# configuration file variable, otherwise overrule it with the
# default value

$CONFIGFILE = $config_option || “./honeynet.cf”;

$cfg = new Config::Simple($CONFIGFILE);

%CONFIG = $cfg->vars();
@MIRRORS = $cfg->param(‘CONFIG.mirrors’);

$enable_mail = $cfg->param(‘CONFIG.enable_mail’);

# Temporary to write out the exact config to our statistics file, later we will use this to write
# down our run-time statistics into a “peristent” file.
$cfg->write($cfg->param(‘CONFIG.statisticsfile’));

# Make sure that there us a version statement in the configuration file, so that we can see whether we are
# compabible or not.

if (!$cfg->param(‘CONFIG.version’))
{
print “It appears that you do not have a version statement in your configuration file. This means that the version you are using now is
too old, make sure that you obtain the latest one and update that to your needs.”;
exit(1);
}

if ($cfg->param(‘CONFIG.version’))
{
my($version_def_major,$version_def_minor) = $cfg->param(‘CONFIG.version’) =~ /(\d+)\.(\d+)/;

# the script can defer between MAJOR and MINOR releases; bugfixes aka patchlevels are
# not affected by this and can thus be ignored.
# TODO: This check should be made more flexible in the future, version 1.4 and 1.5 share
# the same configuration file and should both pass.

if(($version_def_major lt $MAJOR) or ($version_def_minor lt $MINOR))
{
print “You appear to be using an older configuration file that might not be compatible with the current version of the
script, please validate that you have the latest options included and copy over the version statement from the latest available configuration
file. Make sure that the old version statement is overwritten!
The current script runs on version: $version, while the configuration is for version $cfg->param(‘CONFIG.version’)\n”;
exit(1);
}
}

# Create a new timestamp that will be fed into the mirrors, which we can use to test the
# age of the mirror.

if ($create_flag) {
create_timestamp($cfg->param(‘CONFIG.probefile’));
}

elsif ($process_flag) {
# Process the mirrors using the hash we have for them.
process_mirrors(@MIRRORS);
}

# test mode, printout information on screen.
elsif($test_flag)
{
# In test mode we dont send out emails.
$enable_mail = 0;

print(“$name: Starting\n”);
print(“$name: Processing mirrors\n”);

# Process the mirrors using the hash we have for them.
process_mirrors(@MIRRORS);

print(“$name: Finishing\n”);
}

# convert input from unixtime to human readable time.
elsif($convert_flag)
{
print “$option{C} resolves to ” . convert_input($option{C}) . “\n”;
}

# fetch the mirrorprobe file from the given host
elsif($fetch_flag)
{
my $result = fetch_data($option{F}, $cfg->param(‘CONFIG.sourcefile’));
open(OUT, “> $cfg->param(‘CONFIG.outdir’)/$option{F}.timestamp”);
print OUT $result;
close(OUT);
}

# Fetch the mirror timestamp and parse it. Print the output back on the screen.
elsif($retrieve_flag)
{
my $result = fetch_data($option{R}, $cfg->param(‘CONFIG.sourcefile’));
print(“$option{R} was last modified ” . convert_input($result) . “\n”);
}

# People expect a help option, provide it for them.
elsif ($help_flag)
{
print_help();
}

# No valid options had been given, fallback to the help information.
else
{
print_help();
}

sub print_help
{
print(“Usage:\t$name [ -c ] [ -C ] [ -f ] [ -F ] [ -h ] [ -p ] [ -R ] [ -t ]
\t-c\tCreate the timestamp for the localmachine. This timestamp can be used to determine when the mirror was last updated.
\t-C\t converts the unix timestamp to human readable format
\t-f\t Use the specified configuration file
\t-F\t fetch the timestamp for an external host, for example: www.honeynet.nl
\t-h\tprint this help.
\t-p\tCheck the status of the mirrors, and report the output to us
\t-t\tTest mode, does not send out emails, but prints the information on the screen.
Version: $version
Originally written by Remko Lodder }

sub create_timestamp ($)
{
my $probefile = shift;
open(F_OUT, "> $probefile”);
print F_OUT “Mirrorprobe time: ” . time() . ”
Local time: ” . convert_input(time());
close F_OUT;
}

sub convert_input ($)
{
my $output = scalar localtime(shift);
return $output;
}

sub fetch_data ($$)
{
my $source = shift;
my $sourcefile = shift;

my $return_data = ();
my $data = get(“http://$source$sourcefile”);

# IF the remote data is present, take out the numberic time value and return that
# ELSE obscure the data, which will revert to 1969/1970 (depending on what the machine
# considers EPOCH).
if ($data)
{
chomp $data;

$return_data = $data;
$return_data =~ s/\n/\ /;
if ($return_data =~ /\S+ \S+ (\d+) \S+/)
{
$return_data = $1;
}
return $return_data;
}

else
{
$data = 0;
return $data;
}
}

sub process_mirrors (@) {
my %mirror_time;
my @mirror_list = @_;

for my $target(@mirror_list)
{
$mirror_time{$target} = fetch_data($target,$cfg->param(‘CONFIG.sourcefile’));

# We should probably dont need to use this since it is implied in the routine itself.
if(!$mirror_time{$target})
{
$mirror_time{$target} = 0;
}

# declare our local time before continueing.
my $honeynet_ctime = time();
my $mirror_ctime = $mirror_time{$target};
my $mirror_difftime = $honeynet_ctime – $mirror_time{$target};

# If the resulting number is less then zero, the remote host is outdated.
my $mirror_timediff = $cfg->param(‘CONFIG.timeout’) – $mirror_difftime;

if ($mirror_timediff gt “0″)
{
if($cfg->param(‘CONFIG.verbose’) ne “0″)
{
$status = “OK”;
$timestamp = scalar localtime($mirror_time{$target});
$reporthost = $target;
write;
}
next;
}
else
{
# The email option is enabled and we found an outdated mirror
# jump to the email_report function.

if($enable_mail)
{
email_report($target,$mirror_time{$target});
}

if($cfg->param(‘CONFIG.verbose’) ne “0″)
{
$status = “FAIL”;
$timestamp = scalar localtime($mirror_time{$target});

# Only override if the message has the old timestamp and thus is broken.
if($timestamp =~ /19[6-7]\d/)
{
$timestamp = “Mirrorprobe file problems!”;
}
$reporthost = $target;
write;
}
}
}

format STDOUT_TOP =
—————————————————————————-
————————— Honeynet Check results ————————-
—————————————————————————-
Status Site Last changed
.

format STDOUT =
@<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<
$status, $reporthost, $timestamp
.
}

sub email_report ($$)
{
my $status = ();
my $target = shift;
my $mirror_time = shift;
my $recipient = $cfg->param(“MIRRORS.$target”) || “$cfg->param(‘CONFIG.ccaddr’)”;

# Make the mirror time a human parseable time, if this matches the beginning of time
# (For computers at least). Tell that there is a problem.
$mirror_time = scalar localtime($mirror_time);
if ($mirror_time =~ /19[6-7]\d/)
{
$status = “Your mirror seems to have troubles fetching the mirrorprobe file.”;
}
else
{
$status = “At this moment it seems that your mirror was last updated on $mirror_time.”;
}

my $message = “Hello $recipient,

You are recieving this email because your Honeynet Project mirror ($target) seems to be outdated.
$status

Could you please check whether everything is working as expected?
If there is something wrong or you do no longer wish to be a mirror, please notify $cfg->param(‘CONFIG.mirroradmin’)

Thanks for supporting the Honeynet Project!

If you have questions or concerts, please do not hesitate to contact us!


The Honeynet Project Mirror Admins”;

my %mail = (
To => “$recipient”,
From => “$cfg->param(‘CONFIG.fromaddr’)”,
Bcc => “$cfg->param(‘CONFIG.ccaddr’)”,
# only addresses are extracted from Bcc, real names disregarded
Cc => “$cfg->param(‘CONFIG.mirroradmin’)”,
# Cc will appear in the header. (Bcc will not)
Subject => “$target seems to be outdated, please investigate”,
‘X-Mailer’ => “$name $version using Mail::Sendmail version $Mail::Sendmail::VERSION”,
message => “$message”,
);

$mail{‘Honeynet.org : ‘} = “http://www.honeynet.org”;

if (sendmail %mail)
{
print “Mail alert sent OK.\n”;
}
else
{
print “Error sending mail: $Mail::Sendmail::error \n”
}
}
[/perl]

configuration file:
[perl]
# $Id: honeynet.cf,v 1.24 2008/03/24 11:36:29 remko Exp $
#
# Used to automate the checking of Honeynet Project website mirrors.
#
# Config last updated 14 June, 2006
#
#
[CONFIG]
# Version information to see whether the current script can run with the
# current configuration file. Do note that this has three digits to match
# the least available update, normally this should only be matched on the
# second version because of dramatic changes, but you never know :)
version = 1.7

# Misc config, site settings, location of the probe file and the local path to the
# probe file.
source = http://www.honeynet.org
sourcefile = /misc/mirrorprobe.txt
probefile = /var/www/html/misc/mirrorprobe.txt
# Time is 10 days. (Seconds).
timeout = 864000
# Settings regarding output and details on screen.
verbose = 1
statisticsfile = ./honeynet-statistics.cf

# Mail config
enable_mail = 1
# The email addresses of the administrator(s).
mirroradmin = Lance Spitzner
fromaddr = Hostmaster
ccaddr = Remko Lodder
mirrors = honeynet.lss.hr, honeynet.startx.fr, honeynet.fh.net, honeynet.securityinfos.com, www.honeynet.nl

# Mirror details
[MIRRORS]
www.honeynet.nl = remko@elvandar.org
[/perl]

Honeynet Checkscript version 1.4.2 was released

We released another version for the Honeynet check script. It includes a better reporting template, reporting when the mirrorprobe file fetch failed; some style cleanups and some few feature changes. Checkout the file below to obtain more information. You can also request a ”diff” file from me to update your local version (use the contactform for that, or normalise the email address in the script) Continue reading

honeynet mirror check script v1.3

The lacking features of v1.2 had been integrated into v1.3, we now support a configuration file not only for the configureable items but also for the listed mirrors. You can now easily define the mirrors and their administrators which should give you much more flexibility. You can see the script down here, included is a sample configuration file with the configureable options. Comments? Please let me know!

#!/usr/bin/perl
###########################################################################
# $Id: check_honeynet.pl,v 1.8 2006/02/20 07:40:25 remko Exp $
###########################################################################

###########################################################################
# Copyright (C) 2005, Remko Lodder <remko @ FreeBSD.org>. All rights reserved.
# Copyright (C) 2006, Remko Lodder <remko @ FreeBSD.org>. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS “AS IS” AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
###########################################################################

###########################################################################
# Contributors:
# Ivo Naninck,
# Marc Plaisier,
# Mart van de Wege
#
# Script:
# This is a stand alone script written for honeynet.org. It’s purpose is
# to check the listed mirrors to see which one is outdated and notify
# the administrator of the outdated mirror if needed. This way the
# mirrors will always be within a certain timeframe and can be removed
# if they are too outdated.
#
# Mart van de Wege recently told me that it would be nice to have a
# higher level mail module.  I do not want to do so because i think
# this script should be as low level as possible, requiring as less
# modules as possible.  Making it easier to run this on various
# machines without needing to install the entire CPAN to function.
#
# Written in colaboration with Lance Spitzner <lance @ honeynet.org>
###########################################################################

use strict;
use warnings;
use Net::SMTP;
use Getopt::Std;
use LWP::Simple;

###########################################################################
# variables. All configurable options are defined below. Please adjust them
# to your need.
###########################################################################

# create two hashes which can be used to read our config variables from the
# configuration file. Devided between configuration items and mirror
# information.

my %CONFIG              = ();
my %MIRRORS             = ();

# create the option hash, we will use that later to add our option flags.
my %option              = ();

# Version, author and script specific behaviour
my $CONFIGFILE          = "./honeynet.cf";
my $author              = ‘Remko Lodder <remko @ FreeBSD.org>’;           # Name of the author, respect the license.
my $name                = ‘check_honeynet.pl’;                          # Our scriptname.
my $version             = ’1.3′;                                        # Our version.
my $honeynet_ctime      = time();

###########################################################################
# Do not edit anything below this line unless you know what you are doing.
###########################################################################

# Read the configuration before we will use anything else.
open (CONF, "< $CONFIGFILE") || die "Unable to open $CONFIGFILE: $!\n";

my ($config,$mirrors);

while (<CONF>) {
        chomp;
        if ( /\[CONFIG\]/ )
        {
                $config = 1;
                $mirrors = 0;
                next;
        }

        if ( /\[MIRRORS\]/ )
        {
                $config = 0;
                $mirrors = 1;
                next;
        }

        s/#.*//;
        s/^\s+//;
        s/\s+$//;
        next unless length;
        my ($var, $value) = split(/\s*=\s*/, $_, 2);

        if ( $config eq "1" )
        {
                $CONFIG{$var} = $value;
        }

        elsif ( $mirrors eq "1" )
        {
                $MIRRORS{$var} = $value;
        }

        else
        {
                print "It seems that your configurationfile is empty, please investigate\n";
        }
}
close CONF;

getopts("chpt", \%option);

if ($option{c})
{
        if (defined $CONFIG{verbose})
        {
                writeln("$name: Starting");
                writeln("$name: Writing timestamp");
        }

        create_timestamp($CONFIG{probefile});

        if (defined $CONFIG{verbose})
        {
                writeln("$name: Finishing");
        }
}

elsif ($option{p})
{
        if (defined $CONFIG{verbose})
        {
                writeln("$name: Starting");
                writeln("$name: Processing mirrors");
        }

        process_mirrors(%MIRRORS);

        if (defined $CONFIG{verbose})
        {
                writeln("$name: Finishing");
        }
}

# test mode, printout information on screen.
elsif ($option{t})
{
        $CONFIG{enable_mail} = 0;
        writeln("$name: Starting");
        writeln("$name: Processing mirrors");
        process_mirrors(%MIRRORS);
        writeln("$name: Finishing");
}

# People expect a help option, provide it for them.
elsif ($option{h})
{
        print_help();
}
# No valid options had been given, fallback to the help
# information.
else
{
        print_help();
}

sub print_help
{
        writeln("$name");
        writeln("Syntax: $name [-c | -h | -p | -t ]\n");
        writeln("-c");
        writeln("  Create the timestamp for the local machine.  This timestamp");
        writeln("  can be used to determine when the mirrors were last updated.");
        writeln("");
        writeln("-h");
        writeln("  Print this help information");
        writeln("");
        writeln("-p");
        writeln("  Check the status of the mirrors and report that status.");
        writeln("");
        writeln("-t");
        writeln("  Test mode, do not send emails but print the information on");
        writeln("  the screen. This overrides the email settings you might have");
        writeln("  set in the file");
        writeln("Version: $version");
        writeln("Originally written by: $author");
}

sub writeln
{
        # Write the string provided in the function
        my $message     = shift;
        print "$message\n";

}
sub create_timestamp
{
        my $probefile   = shift;

        open(F_OUT, "> $probefile");

        print F_OUT time();

        close F_OUT;
}

sub fetch_data
{
        my $source      = shift;
        my $sourcefile  = shift;

        my $data = get "${source}${sourcefile}";

        if ($data)
        {
                return $data;
        }
        else
        {
                # It seems we encountered an error, give an explaination of what happened
                # and exit the program with an error flag raised.
                writeln("There were problems fetching the status information from $source");
                writeln("We cannot continue right now, the problem will cause the program");
                writeln("to exit.  Please investigate this.");
                exit(1);
        }
}

sub process_mirrors
{
        my %mirror_time;
        my %mirror_list = @_;

        for my $target ( sort keys %mirror_list )
        {
                $mirror_time{$target} = fetch_data($target,$CONFIG{sourcefile});

                my $mirror_ctime        = $mirror_time{$target};
                my $mirror_difftime     = $honeynet_ctime – $mirror_ctime;

                if ($CONFIG{mirror_difftime} < $CONFIG{timeout} )
                {
                        writeln("OK: $target\t\tchanged: ");
                        print scalar localtime($mirror_ctime);
                        writeln("");
                }
                else
                {
                        # The email option is enabled and we found an outdated mirror
                        # jump to the email_report function.
                        if ($CONFIG{enable_mail})
                        {
                                email_report($target,$mirror_ctime);
                        }

                        # We do not want to send a email, print a warning instead.
                        else
                        {
                                writeln("BAD: $target\t\tchanged: ");
                                print scalar localtime($mirror_ctime);
                                writeln("");
                        }
                }
        }
}

sub email_report
{
        my $target              = shift;
        my $mirror_ctime        = shift;
        my $smtp                = Net::SMTP->new("$CONFIG{mailhost}", Hello => "$CONFIG{ehlohost}");

        $mirror_ctime           = scalar localtime($mirror_ctime);

        $smtp->to("$MIRRORS{$target}");

        $smtp->data();
        $smtp->datasend("EHLO $CONFIG{ehlohost}\r\n");
        $smtp->datasend("MAIL FROM: <$CONFIG{fromaddr}>\n");
        $smtp->datasend("RCPT TO: <$MIRRORS{$target}>\n");

        # We need to sleep a little so that all smtp servers can process the email.
        # For example: postfix complains about unauthorized pipelining when this is not defined.
        sleep(2);

        $smtp->datasend("DATA\r\n");
        $smtp->datasend("To: <$MIRRORS{$target}>\n");
        $smtp->datasend("From: $CONFIG{fromaddr}\n");
        $smtp->datasend("Subject: $target seems to be outdated, please investigate\n");
        $smtp->datasend("\n\n");
        $smtp->datasend("Hello $MIRRORS{$target},\n\n");
        $smtp->datasend("You are recieving this email because your mirror ($target) seems to be outdated.\n");
        $smtp->datasend("\n");
        $smtp->datasend("At this moment it seems that your mirror was last updated on $mirror_ctime.\n");
        $smtp->datasend("Could you please check if everything is working as expected?\n\n");
        $smtp->datasend("If there is something wrong or you do no longer wish to be a mirror, please notify $CONFIG{honeyadmin}\n\n");
        $smtp->datasend("–\n");
        $smtp->datasend("Thanks for supporting the efforts of Honeynet\n");
        $smtp->datasend("The Honeynet mirror admins\n");
        $smtp->dataend();

        $smtp->quit;
}

$ cat honeynet.cf
# $Id: honeynet.cf,v 1.3 2006/02/20 08:00:50 remko Exp $

[CONFIG]
# Misc config
source = http://www.honeynet.org
sourcefile = /misc/mirrorprobe.txt
probefile = ./mirrorprobe.txt
# Timeout is one week. (Seconds).
timeout = 604800
verbose = 1

# Mail config
enable_mail = 1
mailhost = caelis.elvandar.org
ehlohost = caelis.elvandar.org
honeyadmin = "Lance Spitzner" <lancename@honeynet.org>
fromaddr = "Remko Lodder" <myname@elvandar.org>

[MIRRORS]
http://www.evilcoder.org = youremail@elvandar.org
http://www.freebsd-nl.org = youremail@elvandar.org

honeynet mirror check script v1.2

After feedback and a little development, 1.2 has seen the light.

#!/usr/bin/perl
###########################################################################
# $Id: check_honeynet-evilcoder.pl,v 1.7 2006/02/10 10:59:51 remko Exp $
###########################################################################

###########################################################################
# Copyright (C) 2005, Remko Lodder <remko at FreeBSD.org>. All rights reserved.
# Copyright (C) 2006, Remko Lodder <remko at FreeBSD.org>. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS “AS IS” AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
###########################################################################

###########################################################################
# Contributors:
# Ivo Naninck,
# Marc Plaisier,
# Mart van de Wege
#
# Script:
# This is a stand alone script written for honeynet.org. It’s purpose is
# to check the listed mirrors to see which one is outdated and notify
# the administrator of the outdated mirror if needed. This way the
# mirrors will always be within a certain timeframe and can be removed
# if they are too outdated.
#
# Mart van de Wege recently told me that it would be nice to have a
# higher level mail module.  I do not want to do so because i think
# this script should be as low level as possible, requiring as less
# modules as possible.  Making it easier to run this on various
# machines without needing to install the entire CPAN to function.
#
# Written in colaboration with Lance Spitzner <lance at honeynet.org>
###########################################################################

use strict;
use warnings;
use Net::SMTP;
use Getopt::Std;
use LWP::Simple;

###########################################################################
# variables. All configurable options are defined below. Please adjust them
# to your need.
###########################################################################

# create the option hash, we will use that later to add our option flags.
my %option              = ();

# Online resources (not everything is used yet).
my $source              = ‘http://www.honeynet.org’;
my $sourcefile          = ‘/path/to/mirrorprobe.txt’;
my $totalpath           = "${source}${sourcefile}";

# path to the local mirrorprobe file
my $probefile           = ‘/path/to/mirrorprobe.txt’;

# Timeout and current time declaration
my $timeout             = 60*60*24*7;
my $honeynet_ctime      = time();

# Email settings.
my $enable_mail         = 1;
my $mailhost            = ‘caelis.elvandar.org’;
my $ehlohost            = "$mailhost";                                  # The EHLO host is the host used
                                                                        # for greeting the other server.
                                                                        # You can use the mailhost, or define
                                                                        # your own.

# Honeynet mirror admins.
my $honeyadmin          = ‘"Lance Spitzner" <lancename@honeynet.org>’;
my $fromaddr            = ‘"Remko Lodder" <myname@elvandar.org>’;       # Change me before production.

# Version, author and script specific behaviour
my $author              = ‘Remko Lodder <myname@elvandar.org>’;         # Name of the author, respect the license.
my $name                = ‘check_honeynet.pl’;                          # Our scriptname.
my $version             = ’1.2′;                                        # Our version.
my $verbose             = 1;                                            # Do we want to have more info when the script runs?

# Example mirror_list.
my %mirror_list = ( ‘http://www.evilcoder.org’          => ‘youremail@elvandar.org’,
                    ‘http://www.freebsd-nl.org’         => ‘youremail@elvandar.org’
                  );

###########################################################################
# Do not edit anything below this line unless you know what you are doing.
###########################################################################
getopts("chpt", \%option);

if ($option{c})
{
        if (defined $verbose)
        {
                writeln("$name: Starting");
                writeln("$name: Writing timestamp");
        }

        create_timestamp($probefile);

        if (defined $verbose)
        {
                writeln("$name: Finishing");
        }
}

elsif ($option{p})
{
        if (defined $verbose)
        {
                writeln("$name: Starting");
                writeln("$name: Processing mirrors");
        }

        process_mirrors(%mirror_list);

        if (defined $verbose)
        {
                writeln("$name: Finishing");
        }
}

# test mode, printout information on screen.
elsif ($option{t})
{
        my $enable_mail = 0;
        writeln("$name: Starting");
        writeln("$name: Processing mirrors");
        process_mirrors(%mirror_list);
        writeln("$name: Finishing");
}

# People expect a help option, provide it for them.
elsif ($option{h})
{
        print_help();
}
# No valid options had been given, fallback to the help
# information.
else
{
        print_help();
}

sub print_help
{
        writeln("$name");
        writeln("Syntax: $name [-c | -h | -p | -t ]\n");
        writeln("-c");
        writeln("  Create the timestamp for the local machine.  This timestamp");
        writeln("  can be used to determine when the mirrors were last updated.");
        writeln("");
        writeln("-h");
        writeln("  Print this help information");
        writeln("");
        writeln("-p");
        writeln("  Check the status of the mirrors and report that status.");
        writeln("");
        writeln("-t");
        writeln("  Test mode, do not send emails but print the information on");
        writeln("  the screen. This overrides the email settings you might have");
        writeln("  set in the file");
        writeln("Version: $version");
        writeln("Originally written by: $author");
}

sub writeln
{
        # Write the string provided in the function
        my $message     = shift;
        print "$message\n";

}
sub create_timestamp
{
        my $probefile   = shift;

        open(F_OUT, "> $probefile");

        print F_OUT time();

        close F_OUT;
}

sub fetch_data
{
        my $source      = shift;
        my $sourcefile  = shift;

        my $data = get "${source}${sourcefile}";

        if ($data)
        {
                return $data;
        }
        else
        {
                # It seems we encountered an error, give an explaination of what happened
                # and exit the program with an error flag raised.
                writeln("There were problems fetching the status information from $source");
                writeln("We cannot continue right now, the problem will cause the program");
                writeln("to exit.  Please investigate this.");
                exit(1);
        }
}

sub process_mirrors
{
        my %mirror_time;
        my %mirror_list = @_;

        for my $target ( sort keys %mirror_list )
        {
                $mirror_time{$target} = fetch_data($target,$sourcefile);

                my $mirror_ctime        = $mirror_time{$target};
                my $mirror_difftime     = $honeynet_ctime – $mirror_ctime;

                if ($mirror_difftime < $timeout )
                {
                        writeln("OK: $target\t\tchanged: ");
                        print scalar localtime($mirror_ctime);
                        writeln("");
                }
                else
                {
                        # The email option is enabled and we found an outdated mirror
                        # jump to the email_report function.
                        if ($enable_mail)
                        {
                                email_report($target,$mirror_ctime);
                        }

                        # We do not want to send a email, print a warning instead.
                        else
                        {
                                writeln("BAD: $target\t\tchanged: ");
                                print scalar localtime($mirror_ctime);
                                writeln("");
                        }
                }
        }
}

sub email_report
{
        my $target              = shift;
        my $mirror_ctime        = shift;
        my $smtp                = Net::SMTP->new("$mailhost", Hello => "$ehlohost");

        $mirror_ctime           = scalar localtime($mirror_ctime);

        $smtp->to("$mirror_list{$target}");

        $smtp->data();
        $smtp->datasend("EHLO $ehlohost\r\n");
        $smtp->datasend("MAIL FROM: <$fromaddr>\n");
        $smtp->datasend("RCPT TO: <$mirror_list{$target}>\n");

        # We need to sleep a little so that all smtp servers can process the email.
        # For example: postfix complains about unauthorized pipelining when this is not defined.
        sleep(2);

        $smtp->datasend("DATA\r\n");
        $smtp->datasend("To: <$mirror_list{$target}>\n");
        $smtp->datasend("From: $fromaddr\n");
        $smtp->datasend("Subject: $target seems to be outdated, please investigate\n");
        $smtp->datasend("\n\n");
        $smtp->datasend("Hello $mirror_list{$target},\n\n");
        $smtp->datasend("You are recieving this email because your mirror ($target) seems to be outdated.\n");
        $smtp->datasend("\n");
        $smtp->datasend("At this moment it seems that your mirror was last updated on $mirror_ctime.\n");
        $smtp->datasend("Could you please check if everything is working as expected?\n\n");
        $smtp->datasend("If there is something wrong or you do no longer wish to be a mirror, please notify $honeyadmin\n\n");
        $smtp->datasend("–\n");
        $smtp->datasend("Thanks for supporting the efforts of Honeynet\n");
        $smtp->datasend("The Honeynet mirror admins\n");
        $smtp->dataend();

        $smtp->quit;
}

Simple image/movie index generator

One day it became needed for me to generate the most simple index one could find to index some JPG and MOV files (yes capitals), therefor i wrote the below script (really easy). You can use it with the BSD License ofcourse.

 

#!/usr/bin/perl T

use CGI;
use warnings;
use diagnostics;
use strict;

my $CGI = new CGI;
my $file;
my $URI = "http://yourdomain/yoururl";
my $path = "/local/path/to/your/images/and/movies";
my $title = "The title of the generated index file";

opendir(DIR, $path);
my @files = grep { /\.JPG|.MOV$/ } readdir(DIR);
closedir(DIR);

print $CGI->header();
  print $CGI->start_html("$title");
    print $CGI->p({-align=>"center"}, "$title");
    print "<table width=’100%’>";
      foreach $file (@files) {
        print "<tr>";
          print "<td align=’center’>";
            print $CGI->a({href=>"$URI/$file"},"$file");
          print "</td>";
        print "</tr>";
      }
    print "</table>";
  print $CGI->end_html();

Continue reading

honeynet mirror check script v1.1

There is a new version available for the honeynet check script. This script is more advanced and more developed. Licensed under the BSD license, written by remko _at_ FreeBSD dot org.

#!/usr/bin/perl -w
###########################################################################
# $Id: check_honeynet.pl,v 1.1 2006/02/05 20:07:41 remko Exp $
###########################################################################

###########################################################################
# Copyright (C) 2005, Remko Lodder <remko@FreeBSD.org>. All rights reserved.
# Copyright (C) 2006, Remko Lodder <remko@FreeBSD.org>. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS “AS IS” AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
###########################################################################

###########################################################################
# This is a stand alone script written for honeynet.org. It’s purpose is
# to check the listed mirrors to see which one is outdated and notify
# the administrator of the outdated mirror if needed. This way the
# mirrors will always be within a certain timeframe and can be removed
# if they are too outdated.
# Written in colaboration with Lance Spitzner <lancename@honeynet.org>
###########################################################################

use strict;
use warnings;
use Net::SMTP;
use Getopt::Std;
use LWP::Simple;

###########################################################################
# variables. All configurable options are defined below. Please adjust them
# to your need.
###########################################################################

# create the option hash, we will use that later to add our option flags.
my %option              = ();

# Online resources (not everything is used yet).
my $source              = ‘http://www.honeynet.org’;
my $sourcefile          = ‘/path/to/mirrorprobe.txt’;
my $totalpath           = "${source}${sourcefile}";

# path to the local mirrorprobe file
my $probefile           = ‘/path/to/mirrorprobe.txt’;

# Timeout and current time declaration
my $timeout             = 60*60*24*7;;
my $honeynet_ctime      = time();

# Email settings.
my $enable_mail         = 1;
my $mailhost            = ‘caelis.elvandar.org’;
my $ehlohost            = ‘caelis.elvandar.org’;

# Honeynet mirror admins.
my $honeyadmin          = ‘"Lance Spitzner" <lancename@honeynet.org>’;
my $fromaddr            = ‘"Remko Lodder" <myname@elvandar.org>’;       # Change me before production.

# Version, author and script specific behaviour
my $author              = ‘Remko Lodder <myname@elvandar.org’;
my $name                = ‘check_honeynet.pl’;
my $version             = ’1.1b’;
my $verbose             = 1;                                            # Enable this if you want the
                                                                        # script to ouput something at all.
# Example mirror_list.
my %mirror_list = ( ‘http://www.evilcoder.org’          => ‘youremail@elvandar.org’,
                    ‘http://www.freebsd-nl.org’         => ‘youremail@elvandar.org’
                  );

###########################################################################
# Do not edit anything below this line unless you know what you are doing.
###########################################################################
getopts("chp", \%option);

if ($option{c})
{
        if (defined $verbose)
        {
                writeln("$name: Starting");
                writeln("$name: Writing timestamp");
        }

        create_timestamp($probefile);

        if (defined $verbose)
        {
                writeln("$name: Finishing");
        }
}
elsif ($option{p})
{
        if (defined $verbose)
        {
                writeln("$name: Starting");
                writeln("$name: Processing mirrors");
        }

        process_mirrors(%mirror_list);

        if (defined $verbose)
        {
                writeln("$name: Finishing");
        }
}
# People expect a help option, provide it for them.
elsif ($option{h})
{
        print_help();
}
# No valid options had been given, fallback to the help
# information.
else
{
        print_help();
}

sub print_help
{
        writeln("$name");
        writeln("Syntax: $name [-c | -h | -p]\n");
        writeln("-c");
        writeln("  Create the timestamp for the local machine.  This timestamp");
        writeln("  can be used to determine when the mirrors were last updated.");
        writeln("");
        writeln("-h");
        writeln("  Print this help information");
        writeln("");
        writeln("-p");
        writeln("  Check the status of the mirrors and report that status.");
        writeln("");
        writeln("Version: $version");
        writeln("Originally written by: $author");
}

sub writeln
{
        # Write the string provided in the function
        my $message     = shift;
        print "$message\n";

}
sub create_timestamp
{
        my $probefile   = shift;

        open(F_OUT, "> $probefile");

        print F_OUT time();

        close F_OUT;
}

sub process_mirrors
{
        my %mirror_list = @_;

        check_status(%mirror_list);
}

sub fetch_data
{
        my $source      = shift;
        my $sourcefile  = shift;

        my $data = get "${source}${sourcefile}";

        if ($data)
        {
                return $data;
        }
        else
        {
                # It seems we encountered an error, give a explaination of what happened
                # and exit the program with an error flag raised.
                writeln("There were problems fetching the status information from $source");
                writeln("We cannot continue right now, the problem will cause the program");
                writeln("to exit.  Please investigate this.");
                exit(1);
        }
}

sub check_status
{
        my %mirror_time;
        my %mirror_list = @_;

        for my $target ( sort keys %mirror_list )
        {
                $mirror_time{$target} = fetch_data($target,$sourcefile);

                my $mirror_ctime        = $mirror_time{$target};
                my $mirror_difftime     = $honeynet_ctime – $mirror_ctime;

                if ($mirror_difftime < $timeout )
                {
                        writeln("OK: $target\t\tchanged: ");
                        print scalar localtime($mirror_ctime);
                        writeln("");
                }
                else
                {
                        # The email option is enabled and we found an outdated mirror
                        # jump to the email_report function.
                        if ($enable_mail)
                        {
                                email_report($target,$mirror_ctime);
                        }

                        # We do not want to send a email, print a warning instead.
                        else
                        {
                                writeln("BAD: $target\t\tchanged: ");
                                print scalar localtime($mirror_ctime);
                                writeln("");
                        }
                }
        }
}

sub email_report
{
        my $target              = shift;
        my $mirror_ctime        = shift;
        my $smtp                = Net::SMTP->new("$mailhost", Hello => "$ehlohost");

        $mirror_ctime           = scalar localtime($mirror_ctime);

        $smtp->to("$mirror_list{$target}");

        $smtp->data();
        $smtp->datasend("EHLO $ehlohost\r\n");
        $smtp->datasend("MAIL FROM: <$fromaddr>\n");
        $smtp->datasend("RCPT TO: <$mirror_list{$target}>\n");

        # We need to sleep a little so that all smtp servers can process the email.
        # For example: postfix complains about unauthorized pipelining when this is not defined.
        sleep(2);

        $smtp->datasend("DATA\r\n");
        $smtp->datasend("To: <$mirror_list{$target}>\n");
        $smtp->datasend("From: $fromaddr\n");
        $smtp->datasend("Subject: $target seems to be outdated, please investigate\n");
        $smtp->datasend("\n\n");
        $smtp->datasend("Hello $mirror_list{$target},\n\n");
        $smtp->datasend("You are recieving this email because your mirror ($target) seems to be outdated.\n");
        $smtp->datasend("\n");
        $smtp->datasend("At this moment it seems that your mirror was last updated on $mirror_ctime.\n");
        $smtp->datasend("Could you please check if everything is working as expected?\n\n");
        $smtp->datasend("If there is something wrong or you do no longer wish to be a mirror, please notify $honeyadmin\n\n");
        $smtp->datasend("–\n");
        $smtp->datasend("Thanks for supporting the efforts of Honeynet\n");
        $smtp->datasend("The honeynet mirror admins\n");
        $smtp->dataend();

        $smtp->quit;
}

Honeynet mirror check script

As people might know, i have a mirror of the www.honeynet.org project at www.honeynet.nl. Recently Lance Spitzner and I reviewed some of the mirrors and since it takes a little time I thought it would be good if there is an automated script available.

Currently the script checks what the last modification time of the index file is (of the official server first) and then scans the other mirrors to see their last modification time. They should be the same after about an week (not sure how we can check that though).

And ofcourse since my script is BSD licensed; i attached it below (click on the read more link).

If you have suggestions on how to make the script better. Please let me know. I will also put this script in the download section and make a reference to an text file so that you can use it.

Continue reading

PF statistics into MRTG

Below is a short little script that i wrote with some help of some FreeBSD Perl developers (Thanks mat and siks).

The script should be runned with root permissions, sudo could be used for that:

For example with the follwing information in /usr/local/etc/sudoers (or where your configfile lives)

User_Alias MRTG = mrtg
MRTG NOPASSWD: /sbin/pfctl -si

The script will run /sbin/pfctl -si which will give you statistical output which can be used for processing by mrtg after running pf.pl. Do note that the current markup might not fit on the script. Please click on the Plain text button to see the original script in a new window, which will fit.

[perl]
#!/usr/bin/perl -w

# $Id: pf-to-mrtg.pl 831 2008-09-07 13:45:27Z remko $
#
# (c) 2005 Remko Lodder
# (c) 2008 Remko Lodder
# Based upon ipf.pl by Ronald Florence
# last modified remko@elvandar.org, 05 Sept 2009
# Made the script working again.

# Example output from pfctl -si
#Interface Stats for fxp0 IPv4 IPv6
# Bytes In 156041 0
# Bytes Out 1895602 0
# Packets In
# Passed 1504 0
# Blocked 256 0
# Packets Out
# Passed 1756 0
# Blocked 0 0
#
#State Table Total Rate
# current entries 33
# searches 8865 10.7/s
# inserts 204 0.2/s
# removals 171 0.2/s
#Counters
# match 460 0.6/s
# bad-offset 0 0.0/s
# fragment 0 0.0/s
# short 0 0.0/s
# normalize 0 0.0/s
# memory 0 0.0/s

use strict;
use Getopt::Std;

# prototype variables.
my($inp,$outp) = 0;

my ($out,$in,$uptime,$firewall);
my(@pfctl);
my(%option);

# define some variables upfront
my $scriptname = __FILE__;
my $version = “2.0″;

# Index our options
getopts(“bBfimMnpsS”, \%option);

my $pass_flag = 1 if $option{p};
my $block_flag = 1 if $option{b};
my $bytes_flag = 1 if $option{B};
my $state_flag = 1 if $option{s};
my $search_flag = 1 if $option{S};
my $inres_flag = 1 if $option{i};
my $match_flag = 1 if $option{m};
my $frag_flag = 1 if $option{f};
my $short_flag = 1 if $option{n};
my $memory_flag = 1 if $option{M};

@pfctl=`/sbin/pfctl -si`;

foreach my $packetfilter (@pfctl) {
if ($pass_flag || $block_flag) {
if ($packetfilter =~ /Packets In/) { $in = 1; $out = 0; }
if ($packetfilter =~ /Packets Out/) { $in = 0; $out = 1; }
if ($pass_flag) {
if ($packetfilter =~ /Passed\s+(\d+)/) { if ($in) { $inp += $1; } }
if ($packetfilter =~ /Passed\s+(\d+)/) { if ($out) { $outp += $1; } }
}
if ($block_flag) {
if ($packetfilter =~ /Blocked\s+(\d+)/) { if ($in) { $inp += $1; } }
if ($packetfilter =~ /Blocked\s+(\d+)/) { if ($out) { $outp += $1; } }
}
}

elsif ($bytes_flag) {
if ($packetfilter =~ /Bytes\sIn\s+(\d+)/) { $inp += $1; }
if ($packetfilter =~ /Bytes\sOut\s+(\d+)/) { $outp += $1; }
}
elsif ($state_flag) {
if ($packetfilter =~ /current entries\s+(\d+)/) { $inp += $1 }
$outp = 0;
}
elsif ($search_flag) {
if ($packetfilter =~ /searches\s+(\d+)/) { $inp += $1 }
if ($packetfilter =~ /searches\s+\d+\s+(\d+)/) { $outp += $1 }
}
elsif ($inres_flag) {
if ($packetfilter =~ /inserts\s+(\d+)/) { $inp += $1 }
if ($packetfilter =~ /removals\s+(\d+)/) { $outp += $1 }
}
elsif ($match_flag) {
if ($packetfilter =~ /match\s+(\d+)/) { $inp += $1 }
if ($packetfilter =~ /match\s+\d+\s+(\d+)/) { $outp += $1 }
}
elsif ($frag_flag) {
if ($packetfilter =~ /bad-offset\s+(\d+)/) { $inp += $1 }
if ($packetfilter =~ /fragment\s+(\d+)/) { $outp += $1 }
}
elsif ($short_flag) {
if ($packetfilter =~ /short\s+(\d+)/) { $inp += $1 }
if ($packetfilter =~ /normalize\s+(\d+)/) { $outp += $1 }
}
elsif ($memory_flag) {
if ($packetfilter =~ /memory\s+(\d+)/) { $inp += $1 }
if ($packetfilter =~ /memory\s+\d+\s+(\d+)/) { $outp += $1 }
}
else {
print(“Usage:\t$scriptname [ -b ] [ -B ] [ -f ] [ -i ] [ -m ] [ -M ] [ -n ] [ -p ] [ -s ] [ -S ]
\t-b\tIndex blocked packets incoming and outgoing.
\t-B\tIndex bytes incoming and outgoing
\t-f\tIndex bad-offsets and fragments
\t-i\tIndex inserts and removals
\t-m\tIndex matched packets current values and usage rate
\t-M\tIndex memory usage current values and usage rate
\t-n\tIndex short packets and normalized packets
\t-p\tIndex passed packets incoming and outgoing.
\t-s\tIndex states other value will be zero (0)
\t-S\tIndex searches current searches and search rate
Version: $version
Originally written by Remko Lodder .\n”);
exit(1);
}
}

print “$inp\n”,
“$outp\n”;

$_ = `/usr/bin/uptime`;
($uptime) = /up\s+(.*),\s+.+user/;
$uptime =~ s/(^1\s+day)\s/1/;

chop($firewall = `uname -nm`);
print “$uptime\n”,

__END__

=head1 NAME

pf-to-mrtg.pl – generates statistics for use with MRTG

=head1 SYNOPSIS

Two example configuration options for MRTG:

Target[connections]: `/path/to/pf-to-mrtg.pl -p`
Options[connections]: growright, perhour
MaxBytes[connections]: 50000
Title[connections]: Firewall Connections
PageTop[connections]:

Firewall Connections

YLegend[connections]: packets/hr
ShortLegend[connections]: pkts/h
Legend1[connections]: Incoming Connections
Legend2[connections]: Outgoing Connections

Target[state]: `/path/to/pf-to-mrtg.pl -s`
Options[state]: growright, gauge, integer
MaxBytes[state]: 2048
Title[state]: State Table
PageTop[state]:

NAT & IP state tables

YLegend[state]: states
ShortLegend[state]: states
Legend1[state]: NAT states
Legend2[state]: IP states
LegendI[state]: nat:
LegendO[state]: ip:

Other available targets are `pf-to-mrtg.pl -b`
`pf-to-mrtg.pl -B`
`pf-to-mrtg.pl -f`
`pf-to-mrtg.pl -i`
`pf-to-mrtg.pl -m`
`pf-to-mrtg.pl -M`
`pf-to-mrtg.pl -n`
`pf-to-mrtg.pl -p`
`pf-to-mrtg.pl -s`
`pf-to-mrtg.pl -S`

See the instructions in the help to see what they represent.

=head1 DESCRIPTION

The purpose of this script is to be able to create statistics
from various PF counters. By using this script you will be
able to see what your firewall does, how it behaves, and see
trends. Note: Due to MRTG’s nature you will get spikes after
rebooting the machine.

=head1 LICENSE

This module is licensed under the BSD license.

=head1 AUTHOR

Remko Lodder with additional help from
Mattieu Arnold and Pasi Hirvonen.

Originally based on work from Ron James (before this was entirely rewritten).

=cut
[/perl]