#!/usr/bin/perl
$| = 1;

use strict;
use warnings;

#------------------- Beginn Konfiguration ------------------------
# Es wird ein Hash von Kommandos angelegt, der die Zuordnung
# von Namen zu einen Programmpfad festlegt.
#
# Beginnt der Name mit 'P-', ist ein Parameter zwingend
# erforderlich, 
# beginnt der Name mit 'N-' ist ein optionaler Parameter
# möglich,
# beginnt der Name mit 'R-', darf kein Parameter angegeben sein.
#
# Wurde kein Hostname (target) angegeben, verwendet das Programm
# die Environment-Variable 'REMOTE_ADDR'

my %commands = (
  'N-PING',  '/bin/ping -c 5 -w 5 ',
  'N-TRACE', '/usr/sbin/traceroute ',
  'P-LOOK',  '/usr/bin/host -a ',
  'P-LOOKA', '/usr/bin/host -l -v -t any ',
  'R-UP',    '/usr/bin/uptime'
            );
#--------------------- Ende Konfiguration ------------------------

my $PROGRAMM = '';   # Programmname (1. Wert des Hashes %commands)
my $ZIELHOST = '';   # Eingabeparameter
my $temp = '';       # Hilfvariable
my $i = 0;           # Zaehlvariable
my $content = '';    # Variablen zur Aufbereitung der CGI-Parameter
my $key = '';
my %FORM = ();       # Formulardaten

# Abbruch nach spätestens 60 Sekunden 
# (wichtig bei ping/traceroute
$SIG{'ALRM'} =\&alarm_handle;
alarm(60);     

# Header ausgeben
print "Content-type: text/html\n\n";
print "<HTML><HEAD><TITLE>Network Tools</TITLE></HEAD>", "\n";
print "<BODY>", "\n";
print "<H2>Netzmafia Network Tools</H2>", "\n";

# Formulareingabpen pruefen
ParseForm();

if (defined($FORM{'program'}))
  {
  # Antwort vom Formular
  DoIt();
  # Vermeiden einer Denial-of-Service-Attacke
  sleep(2);
  }
else
  # leerer Aufruf, Formular anzeigen
  { ShowForm(); }
  
print "<P><B>***** FERTIG *****</B></P>\n</BODY></HTML>\n";


sub DoIt
  {
  $PROGRAMM = $FORM{'program'};
  # gibt's das Programm?
  unless (defined($commands{$PROGRAMM}))
    {
    print "<H2>Fehler</H2>", "\n";
    print "Kein Kommando angegeben!\n";
    print "</BODY></HTML>", "\n";
    exit 0;           
    }
  # Parameterpruefung
  #  1. Eingabe auf zulaessige Zeichen beschraenken
  if ($FORM{'target'} =~ /^([-\@\w.]+)$/ || $FORM{'target'} eq "") 
    {
    $ZIELHOST = $FORM{'target'};
    }
  else 
    {
    print "Unzul\&auml;ssige Zeichen im Parameter. Abbruch!";      
    print "</BODY></HTML>", "\n";
    exit 0;
    }                                              
  #  2. Laengenueberpruefung der Eingabe
  if (length($ZIELHOST) > 255)
    {
    print "Parameter zu lang (mehr als 255 Zeichen). Abbruch!";      
    print "</BODY></HTML>", "\n";
    exit 0;
    }                                              
  #  3. Parameter erlaubt/notwendig/verboten?
  if ($ZIELHOST eq "")
    {
    if ($PROGRAMM =~ /^P-/)
      {
      print "<H2>Fehler</H2>", "\n";
      print "Das Kommando ben\&ouml;tigt eine Angabe im Eingabefeld!\n";
      print "</BODY></HTML>", "\n";
      exit 0;           
      }
    else
      { $ZIELHOST = $ENV{'REMOTE_ADDR'}; } # Default
    }
  if ($PROGRAMM =~ /^R-/) # Parameter loeschen
    { $ZIELHOST = ""; }

  $temp = $commands{$PROGRAMM};
  # Programmnamen aufbereiten fuer Ausgabe --> Pfad weg
  $temp =~ s/^..*\///;
  print "Bitte etwas Geduld, bis die Daten ermittelt sind.<P>", "\n";
  print "<B>Ergebnisse von Kommando: $temp</B>", "\n";
  print "<B> $ZIELHOST</B>\n" if ($ZIELHOST ne "");
  print "<PRE>\n";
  open (INP, "$commands{$PROGRAMM} $ZIELHOST |");
  print while (<INP>);
  close (INP);
  print "</PRE>\n";
  }

sub ShowForm
  {
  print qq~  
  <FORM ACTION="/cgi-bin/nettool.cgi" METHOD="POST">
  <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="5">
  <TR>
  <TD VALIGN="TOP" ALIGN="LEFT">
  <INPUT TYPE="RADIO" NAME="program" VALUE="N-PING">
  </TD>
  <TD VALIGN="TOP" ALIGN="LEFT">
  Ping auf einen Host oder von hier zu Ihrem Rechner, falls Sie nichts eingeben.
  </TD>
  </TR><TR>
  <TD VALIGN="TOP" ALIGN="LEFT">
  <INPUT TYPE="RADIO" NAME="program" VALUE="N-TRACE">
  </TD>
  <TD VALIGN="TOP" ALIGN="LEFT">
  Traceroute von hier zu einem Host oder von hier zu Ihrem Rechner, 
  falls Sie nichts eingeben.
  </TD>
  </TR><TR>
  <TD VALIGN="TOP" ALIGN="LEFT">
  <INPUT TYPE="RADIO" NAME="program" VALUE="P-LOOK">
  </TD>
  <TD VALIGN="TOP" ALIGN="LEFT">
  Einzelhost-Nameserverabfrage mit dem Programm "host". Bitte Hostname oder IP-Nummer
  angeben.
  </TD>
  </TR><TR>
  <TD VALIGN="TOP" ALIGN="LEFT">
  <INPUT TYPE="RADIO" NAME="program" VALUE="P-LOOKA">
  </TD>
  <TD VALIGN="TOP" ALIGN="LEFT">
  Nameserverabfrage einer kompletten Domain mit dem Programm "host". 
  Vorsicht! Das kann unter Umst&auml;nden sehr viel Output ergeben.
  Bitte Domainnamen angeben.
  </TD>
  </TR><TR>
  <TD VALIGN="TOP" ALIGN="LEFT">
  <INPUT TYPE="RADIO" NAME="program" VALUE="R-UP" CHECKED>
  </TD>
  <TD VALIGN="TOP" ALIGN="LEFT">
  Uptime und Load.
  </TD>
  </TR><TR>
  <TD VALIGN="TOP" ALIGN="LEFT">
  Hostadresse: 
  </TD>
  <TD VALIGN="TOP" ALIGN="LEFT">
  <INPUT TYPE="TEXT" NAME="target" VALUE="" SIZE=40 MAXLENGTH=100> 
  </TD>
  </TR><TR>
  <TD VALIGN="TOP" ALIGN="LEFT">&nbsp;</TD>
  <TD VALIGN="TOP" ALIGN="LEFT">
  <INPUT TYPE="SUBMIT" VALUE=" Anfrage absenden ">
  </TD>
  </TR>
  </TABLE>
  </FORM>
  ~;
  }

sub ParseForm
    {
    my ($buffer, @pairs, $pair, $name, $value);
    # Read in text
    if ($ENV{'REQUEST_METHOD'} eq "POST")
      { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
    else
      { $buffer = $ENV{'QUERY_STRING'};  }
    @pairs = split(/&/, $buffer);
    foreach $pair (@pairs)
      {
      # Name-Wert-Paare trennen
      ($name, $value) = split(/=/, $pair);
      # Leerzeichen wieder einsetzen
      $value =~ tr/+/ /;
      # URL-codierte Zeichen (%xx) ersetzen
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
      # im hash speichern
      if (defined $FORM{$name})    # vermutlich checkbox
        { $FORM{$name} = $FORM{$name} . ", " . $value; }
      else
        { $FORM{$name} = $value; }
      }
    }


# Unterprogramm fuer Timeout
#
sub alarm_handle        
  {                  
  alarm(0);        
  print "<P><H2>Fehler</H2>", "\n";
  print "Zeit\&uuml;berschreitung, Abbruch!", "\n";
  print "</BODY></HTML>", "\n";
  exit 0;           
  }                  
                   
