Mar 24

Here is Check_Honeynet v1.7

check_honeynet.pl:

PERL:
  1. #!/usr/bin/perl
  2. # $Id: check_honeynet.pl,v 1.48.2.3 2008/03/24 14:46:14 remko Exp $
  3. ###########################################################################
  4.  
  5. ###########################################################################
  6. # Copyright (C) 2005-2008, Remko Lodder <remko@FreeBSD.org>. All rights reserved.
  7. #
  8. # Redistribution and use in source and binary forms, with or without
  9. # modification, are permitted provided that the following conditions
  10. # are met:
  11. # 1. Redistributions of source code must retain the above copyright
  12. #    notice, this list of conditions and the following disclaimer.
  13. # 2. Redistributions in binary form must reproduce the above copyright
  14. #    notice, this list of conditions and the following disclaimer in the
  15. #    documentation and/or other materials provided with the distribution.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. # ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
  21. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. # SUCH DAMAGE.
  28. ###########################################################################
  29.  
  30. ###########################################################################
  31. # Contributors:
  32. # Ivo Naninck, (Language)
  33. # Marc Plaisier, (Language)
  34. # Mart van de Wege, (suggested a different mailer in 2006, told me that it
  35. # should run on a high level interface as easy as possible, I discarded
  36. # the idea back then, till Richard came with a good idea).
  37. # Lance Spitzner (the most valueable feedback regarding the script).
  38. # Richard Arends (suggested the actual perl mailer; and gave a good example
  39. # on how to use the module)
  40. # Robert Blacquiere (showed me Simple::Config, which I am using now to
  41. # obtain configuration informatin, as well as write statistics to a
  42. # temporary file)
  43. #
  44. # Script:
  45. # This is a stand alone script written for honeynet.org. It's purpose is
  46. # to check the listed mirrors to see which one is outdated and notify
  47. # the administrator of the outdated mirror if needed. This way the
  48. # mirrors will always be within a certain timeframe and can be removed
  49. # if they are too outdated.
  50. #
  51. # A while ago Mart vd Wege told me that a higher level mail module would be
  52. # much easier to cope with. This had been implemented as of version 1.6.2
  53. #
  54. # Written in colaboration with Lance Spitzner <lance@honeynet.org>
  55. ###########################################################################
  56.  
  57. ###########################################################################
  58. # Differences between releases, started this between 1.5 and 1.6 sorry
  59. # for the loss of potential usefull information (although I might be able
  60. # to retrieve the missing data from my CVS branches).
  61. # Note that all the three version based versions are just bugfixes to some
  62. # degree.
  63. # Version       Who             What
  64. # 1.1           Remko           Initial script to check the mirrors.
  65. # 1.1->1.2      Remko
  66. # 1.2->1.3      Remko
  67. # 1.3->1.4      Remko
  68. # 1.4->1.5      Remko           Code cleanups, restructure of code; corrected
  69. #                               some bugs between various releases spotted
  70. #                               by Lance.
  71. # 1.5->1.6      Remko           Cleanups, changed structure for timestamp
  72. #                               retrieval; make it human readable and match
  73. #                               on a specific pattern. Made the version dependend
  74. #                               on the configuration version and visa-versa
  75. #                               to be able to make big config changes.
  76. #                               BF-1: Fix the email send options by using the
  77. #                                     correct Net::SMTP commands.
  78. #                               BF-1: Fix the parsing of the new mirrorprobe
  79. #                                     layout.
  80. #                               BF-2: Change the Mailer used to send out the
  81. #                                     report.
  82. # 1.6->1.7      Remko           Implement Config::Simple, makes configuration
  83. #                               much easier!
  84. ###########################################################################
  85.  
  86. use strict;
  87. use warnings;
  88. use LWP::Simple;
  89. use Getopt::Std;
  90. use Mail::Sendmail;
  91. use Config::Simple;
  92.  
  93. ###########################################################################
  94. # variables. All configurable options are defined below. Please adjust them
  95. # to your need.
  96. ###########################################################################
  97.  
  98. # Hash to store our entire configuration in.
  99. my %CONFIG              = ();
  100.  
  101. # create the option hash, we will use that later to add our option flags.
  102. my %option              = ();
  103.  
  104. # Template some standard variables
  105. my ($CONFIGFILE, $status, $reporthost, $timestamp,$target, @MIRRORS, $enable_mail, $cfg);
  106.  
  107. # Prototype functions
  108. sub fetch_data ($$);
  109. sub email_report ($$);
  110. sub convert_input ($);
  111. sub process_mirrors (@);
  112. sub create_timestamp ($);
  113.  
  114. # Version, author and script specific behaviour
  115. my $author              = 'Remko Lodder <remko@FreeBSD.org>';   # Name of the author, respect the license.
  116. my $name                = __FILE__;                             # Our scriptname.
  117. my $MAJOR               = '1';                                  # Our major version number
  118. my $MINOR               = '7';                                  # Our minor version number
  119. my $PATCHLEVEL          = '0';                                  # Our patchlevel
  120. my $version             = "$MAJOR.$MINOR.$PATCHLEVEL";          # Our version.
  121.  
  122. ###########################################################################
  123. # Do not edit anything below this line unless you know what you are doing.
  124. ###########################################################################
  125.  
  126. getopts("cC:f:F:hpR:t", \%option);
  127.  
  128. my $config_flag   = 1 if $option{f};
  129. my $config_option = $option{f};
  130.  
  131. my $create_flag   = 1 if $option{c};
  132. my $help_flag     = 1 if $option{h};
  133. my $process_flag  = 1 if $option{p};
  134. my $test_flag     = 1 if $option{t};
  135. my $convert_flag  = 1 if $option{C};
  136. my $fetch_flag    = 1 if $option{F};
  137. my $retrieve_flag = 1 if $option{R};
  138.  
  139. # Simply assign the contents of the configuration parameter to the
  140. # configuration file variable, otherwise overrule it with the
  141. # default value
  142.  
  143. $CONFIGFILE = $config_option || "./honeynet.cf";
  144.  
  145. $cfg = new Config::Simple($CONFIGFILE);
  146.  
  147. %CONFIG = $cfg->vars();
  148. @MIRRORS = $cfg->param('CONFIG.mirrors');
  149.  
  150. $enable_mail = $cfg->param('CONFIG.enable_mail');
  151.  
  152. # Temporary to write out the exact config to our statistics file, later we will use this to write
  153. # down our run-time statistics into a "peristent" file.
  154. $cfg->write($cfg->param('CONFIG.statisticsfile'));
  155.  
  156. # Make sure that there us a version statement in the configuration file, so that we can see whether we are
  157. # compabible or not.
  158.  
  159. if (!$cfg->param('CONFIG.version'))
  160. {
  161.         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
  162. too old, make sure that you obtain the latest one and update that to your needs.";
  163.         exit(1);
  164. }
  165.  
  166. if ($cfg->param('CONFIG.version'))
  167. {
  168.         my($version_def_major,$version_def_minor) = $cfg->param('CONFIG.version') =~ /(\d+)\.(\d+)/;
  169.  
  170.         # the script can defer between MAJOR and MINOR releases; bugfixes aka patchlevels are
  171.         # not affected by this and can thus be ignored.
  172.         # TODO: This check should be made more flexible in the future, version 1.4 and 1.5 share
  173.         # the same configuration file and should both pass.
  174.  
  175.         if(($version_def_major lt $MAJOR) or ($version_def_minor lt $MINOR))
  176.         {
  177.                 print "You appear to be using an older configuration file that might not be compatible with the current version of the
  178. script, please validate that you have the latest options included and copy over the version statement from the latest available configuration
  179. file. Make sure that the old version statement is overwritten!
  180. The current script runs on version: $version, while the configuration is for version $cfg->param('CONFIG.version')\n";
  181.                 exit(1);
  182.         }
  183. }
  184.  
  185. # Create a new timestamp that will be fed into the mirrors, which we can use to test the
  186. # age of the mirror.
  187.  
  188. if ($create_flag) {
  189.         create_timestamp($cfg->param('CONFIG.probefile'));
  190. }
  191.  
  192. elsif ($process_flag) {
  193.         # Process the mirrors using the hash we have for them.
  194.         process_mirrors(@MIRRORS);
  195. }
  196.  
  197. # test mode, printout information on screen.
  198. elsif($test_flag)
  199. {
  200.         # In test mode we dont send out emails.
  201.         $enable_mail = 0;
  202.  
  203.         print("$name: Starting\n");
  204.         print("$name: Processing mirrors\n");
  205.  
  206.         # Process the mirrors using the hash we have for them.
  207.         process_mirrors(@MIRRORS);
  208.  
  209.         print("$name: Finishing\n");
  210. }
  211.  
  212. # convert input from unixtime to human readable time.
  213. elsif($convert_flag)
  214. {
  215.         print "$option{C} resolves to " . convert_input($option{C}) . "\n";
  216. }
  217.  
  218. # fetch the mirrorprobe file from the given host
  219. elsif($fetch_flag)
  220. {
  221.         my $result = fetch_data($option{F}, $cfg->param('CONFIG.sourcefile'));
  222.         open(OUT, "> $cfg->param('CONFIG.outdir')/$option{F}.timestamp");
  223.                 print OUT $result;
  224.         close(OUT);
  225. }
  226.  
  227. # Fetch the mirror timestamp and parse it. Print the output back on the screen.
  228. elsif($retrieve_flag)
  229. {
  230.         my $result = fetch_data($option{R}, $cfg->param('CONFIG.sourcefile'));
  231.         print("$option{R} was last modified " . convert_input($result) . "\n");
  232. }
  233.  
  234. # People expect a help option, provide it for them.
  235. elsif ($help_flag)
  236. {
  237.         print_help();
  238. }
  239.  
  240. # No valid options had been given, fallback to the help information.
  241. else
  242. {
  243.         print_help();
  244. }
  245.  
  246. sub print_help
  247. {
  248.         print("Usage:\t$name [ -c ] [ -C <value> ] [ -f <configurationfile> ] [ -F <host> ] [ -h ] [ -p ] [ -R <host> ] [ -t ]
  249. \t-c\tCreate the timestamp for the localmachine. This timestamp can be used to determine when the mirror was last updated.
  250. \t-C\t<value> converts the unix timestamp to human readable format
  251. \t-f\t<filename> Use the specified configuration file
  252. \t-F\t<host> fetch the timestamp for an external host, for example: www.honeynet.nl
  253. \t-h\tprint this help.
  254. \t-p\tCheck the status of the mirrors, and report the output to us
  255. \t-t\tTest mode, does not send out emails, but prints the information on the screen.
  256. Version: $version
  257. Originally written by Remko Lodder <remko\@FreeBSD.org, for the honeynet project.\n");
  258. }
  259.  
  260. sub create_timestamp ($)
  261. {
  262.         my $probefile = shift;
  263.         open(F_OUT, "> $probefile");
  264.                 print F_OUT "Mirrorprobe time: " . time() . "
  265. Local time: " . convert_input(time());
  266.         close F_OUT;
  267. }
  268.  
  269. sub convert_input ($)
  270. {
  271.         my $output      = scalar localtime(shift);
  272.         return $output;
  273. }
  274.  
  275. sub fetch_data ($$)
  276. {
  277.         my $source      = shift;
  278.         my $sourcefile  = shift;
  279.  
  280.         my $return_data = ();
  281.         my $data        = get("http://$source$sourcefile");
  282.  
  283.         # IF the remote data is present, take out the numberic time value and return that
  284.         # ELSE obscure the data, which will revert to 1969/1970 (depending on what the machine
  285.         # considers EPOCH).
  286.         if ($data)
  287.         {
  288.                 chomp $data;
  289.  
  290.                 $return_data = $data;
  291.                 $return_data =~ s/\n/\ /;
  292.                 if ($return_data =~ /\S+ \S+ (\d+) \S+/)
  293.                 {
  294.                         $return_data = $1;
  295.                 }
  296.                 return $return_data;
  297.         }
  298.  
  299.         else
  300.         {
  301.                 $data = 0;
  302.                 return $data;
  303.         }
  304. }
  305.  
  306. sub process_mirrors (@) {
  307.         my %mirror_time;
  308.         my @mirror_list = @_;
  309.  
  310.         for my $target(@mirror_list)
  311.         {
  312.                 $mirror_time{$target} = fetch_data($target,$cfg->param('CONFIG.sourcefile'));
  313.  
  314.                 # We should probably dont need to use this since it is implied in the routine itself.
  315.                 if(!$mirror_time{$target})
  316.                 {
  317.                         $mirror_time{$target} = 0;
  318.                 }
  319.  
  320.                 # declare our local time before continueing.
  321.                 my $honeynet_ctime      = time();
  322.                 my $mirror_ctime        = $mirror_time{$target};
  323.                 my $mirror_difftime     = $honeynet_ctime - $mirror_time{$target};
  324.  
  325.                 # If the resulting number is less then zero, the remote host is outdated.
  326.                 my $mirror_timediff     = $cfg->param('CONFIG.timeout') - $mirror_difftime;
  327.  
  328.                 if ($mirror_timediff gt "0")
  329.                 {
  330.                         if($cfg->param('CONFIG.verbose') ne "0")
  331.                         {
  332.                                 $status = "OK";
  333.                                 $timestamp = scalar localtime($mirror_time{$target});
  334.                                 $reporthost = $target;
  335.                                 write;
  336.                         }
  337.                                 next;
  338.                 }
  339.                 else
  340.                 {
  341.                         # The email option is enabled and we found an outdated mirror
  342.                         # jump to the email_report function.
  343.  
  344.                         if($enable_mail)
  345.                         {
  346.                                 email_report($target,$mirror_time{$target});
  347.                         }
  348.  
  349.                         if($cfg->param('CONFIG.verbose') ne "0")
  350.                         {
  351.                                 $status = "FAIL";
  352.                                 $timestamp = scalar localtime($mirror_time{$target});
  353.  
  354.                                 # Only override if the message has the old timestamp and thus is broken.
  355.                                 if($timestamp =~ /19[6-7]\d/)
  356.                                 {
  357.                                         $timestamp = "Mirrorprobe file problems!";
  358.                                 }
  359.                                 $reporthost = $target;
  360.                                 write;
  361.                         }
  362.                 }
  363.         }
  364.  
  365. format STDOUT_TOP =
  366. ----------------------------------------------------------------------------
  367. --------------------------- Honeynet Check results -------------------------
  368. ----------------------------------------------------------------------------
  369. Status  Site                                    Last changed
  370. .
  371.  
  372. format STDOUT =
  373. @<<<<  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<&l