#!/usr/bin/perl

use strict;
use IO::Socket;

$|=1;

# Init Variables
my $hostname = '';
my $targethost = 'localhost';

my $lowport = 1;
my $highport = 1024;

my $name = '';
my $aliases = '';
my $type = '';
my $len = '';
my $proto = '';
my $port = '';
my $srv_name = '';
my $srv_aliases = '';
my $srv_proto = '';
my $srv_port = '';
my $localaddr = 0;
my $targetaddr = 0;
my $local = 0;
my $target = 0;

my $AF_INET = 2;
my $SOCK_STREAM = 1;
my $sockaddr = 'S n a4 x8';

my %ein = ();                      # fuer Formulareingaben
my $input = '';
my $pname = '';
my $value = '';

# Netzmafia selbst einrichten
chop ($hostname = `hostname`);
# Remote-Host
my $raddr = $ENV{REMOTE_ADDR};
my $rhost = &get_host($raddr);

# Get the input
read(STDIN,$input,$ENV{CONTENT_LENGTH});

# Split the name-value pairs
foreach (split("&",$input)) {
  /(.*)=(.*)/;
  $pname = $1;
  $value = $2;
  $value =~ s/\+/ /g;
  $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
  $ein{$pname} = $value;
  }

# Print HTML-Header
print "Content-type: text/html", "\r\n\r\n";
print "<HTHL>", "\n";
print "<HEAD><TITLE>Portscanner</TITLE></HEAD>", "\n";
print "<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\" LINK=\"#0000FF\" VLINK=\"#0000CC\" ALINK=\"#FF0000\">", "\n";
print "<H2>TCP-Portscanner</H2>", "\n";

# Eingaben uebernehmen,
$targethost = $ein{'targethost'};
$lowport = $ein{'lowport'};
$highport = $ein{'highport'};

if (! defined($targethost))
  { &formular; }
elsif (defined($lowport) && defined($highport))
  { 
  if ($lowport=~ m/[a-z]/g)  { &error("Falscher Anfangsport!"); }
  if ($highport=~ m/[a-z]/g) { &error("Falscher Endeport!"); }
  &portscan; 
  }
else
  { &error("Bitte alle Felder ausf&uuml;llen!"); }
print "</BODY></HTML>", "\n";
exit(0);


# Portscanner
sub portscan
  {
  print "Scanning $targethost, Ports: $lowport bis $highport.<BR>\n";
  print "(Scanning from $hostname)<BR>\n";
  $port = $lowport;
  while ($port <= $highport ) 
    {
    ($name,$aliases,$proto) = getprotobyname('tcp');
    ($name,$aliases,$port) = getservbyname($port,'tcp') unless $port=~ /^\d+$/;

    ($name,$aliases,$type,$len,$localaddr) = gethostbyname($hostname);
    $local = pack($sockaddr,$AF_INET,0,$localaddr);
    ($name,$aliases,$type,$len,$targetaddr) = gethostbyname($targethost);
    $target = pack($sockaddr,$AF_INET,$port,$targetaddr);

    socket(S,$AF_INET,$SOCK_STREAM,$proto);
    bind(S,$local);

    if (connect(S,$target)) 
     {
     # Verbindung vorhanden
     ($srv_name,$srv_aliases,$srv_port,$srv_proto) = getservbyport($port,'tcp');
     print "$port ($srv_name) O. K.<BR>\n";
     }
    close(S);
    $port++;
    }
  }

sub error
  {
  my $errors = $_[0];
  print "<H4>Fehler aufgetreten:</H4>\n";
  print "$errors<br>$!<P>\n";
  print "</body></html>\n";
  exit;
  }

sub formular
  {
  print "<FORM ACTION=\"/cgi-bin/pscan.cgi\" METHOD=\"POST\">\n";
  print "<TABLE BORDER=0 CELLPADDING=5>\n";
  print "<TR><TD>Hostname:</TD><TD> <INPUT TYPE=\"text\" NAME=\"targethost\" SIZE=\"40\" MAXLENGTH=\"90\" VALUE=\"$rhost\"></TD></TR>\n";
  print "<TR><TD>Anfangsport:</TD><TD> <INPUT TYPE=\"text\" NAME=\"lowport\" SIZE=\"4\" MAXLENGTH=\"4\" VALUE=\"1\"></TD></TR>\n";
  print "<TR><TD>Endeport:</TD><TD> <INPUT TYPE=\"text\" NAME=\"highport\" SIZE=\"4\" MAXLENGTH=\"4\" VALUE=\"1024\"></TD></TR>\n";
  print "<TR><TD>&nbsp;";
  print "</TD><TD><INPUT TYPE=\"submit\" NAME=\"submit\" VALUE=\"Senden\">\n";
  print "<INPUT TYPE=\"reset\" NAME=\"reset\" VALUE=\"Reset\"></TD></TR>\n";
  print "</TABLE></FORM>\n";
  print "<P>Ich versichere, da&szlig; der oben unter \"Hostname\" eingetragene Rechner\n";
  print "mein eigener Rechner ist und ich den Portscan nur zum Zweck der\n";
  print "Sicherheits&uuml;berpr&uuml;fung starte.<P>\n";
  }

sub get_host 
  {
  # Arg 1: IP-Adresse als String
  # Return: Host-Name als String
  my ($i_addr, $i_host);
  # String in numerisches Formmat wandeln
  $i_addr = inet_aton($_[0]);
  $i_host = gethostbyaddr ( $i_addr , 2 ) or return "";
  return $i_host;
  }


