#!/usr/bin/perl 
#
# s0t4ipv6@Shellcode.com.ar
#
# smtp-users.pl
# 
# Este programa, aprovechando el comando interno "EXPN" de los sendmail
# intenta descubrir desde un diccionario, la existencia de usuarios validos en el servidor.
# El proceso padre divide el diccionario en 3 bloques, y dispara 3 procesos hijos que conectan
# simultaneamente con el servidor. En caso de time out o muerte de alguno de los procesos hijos
# el proceso padre vuelve a disparar un nuevo hijo heredando la posicion del diccionario donde se
# encontraba el anterior.
# La salida y el estado de conexion se da en el standard output y ademas en el archivo que hayan 
# puesto como "output"
#
# Sera necesario que posean instalado el perl5.6, y la libreria CPAN de Telnet, que pueden encontrarla
# en: http://www.cpan.org/

use Net::Telnet ();
use POSIX ":sys_wait_h";

my ($username, $password,  $cantidad, $a, $finded);

$version="0.0.1";
$a=0; $cantidad=0;
$port=25;
$logging="log";
$guia="guia";
$o=0;

if($ARGV[0] eq "-h"||!defined($ARGV[0])) 
{
    print "smtp-users v".$version." coded by s0t4ipv6\n";
    print "use: smtp-users [-h] | <hostname> <wordlist> <output>\n";
    exit(0);
}

if (!defined($ARGV[1])) { exit(0); }
if (!defined($ARGV[2])) { exit(0); }

$hostname=$ARGV[0];
$wordlist=$ARGV[1];
$output=$ARGV[2];
$inicio=1;
$final=3;
$continue=0;

&check_host;

open(OUT, "> $output") ;
print OUT "=================================================\n";
print STDOUT "=================================================\n";
print OUT "HOSTNAME:".$hostname."\n";
print STDOUT "HOSTNAME:".$hostname."\n";
print OUT "WORDLIST:".$wordlist."\n";
print STDOUT "WORDLIST:".$wordlist."\n";
print OUT "-------------------------------------------------\n";
print STDOUT "-------------------------------------------------\n";
print OUT "Sequencia\tUsuario Valido\t\tEstado\n";
print STDOUT "Sequencia\tUsuario Valido\t\tEstado\n";
close(OUT);

open(ABRIR,"< $wordlist") ;
while (<ABRIR>) { $a++;chomp; $vc_user[$a]=$_; }
close (ABRIR);
&conectar;

while ( 1 ) {
	$pid = waitpid(-1,&WUNTRACED);
	$estado=waitpid(-1,&WNOHANG);
	&process;
} 
system("rm -rf guia.*");
print "\n\n";
exit(0);

# SUB #
sub conectar() {
for ($out=$inicio;$out<=$final;$out++)
{
if ( ($kids[$out]=fork()) == 0)
{
$smtp[$out]=new Net::Telnet (   Timeout         => 10,
				Errmode		=> &error,
                                Input_log       => "$logging.$out",
                                port            => $port);
$smtp[$out]->open($hostname) ;

        for ($o=$continue+$out;$o<=$a;$o +=3)
        {
	open(TOUCH, "> $guia.$out");
	print TOUCH $o-3;
	close(TOUCH);
        $smtp[$out]->print("EXPN ".$vc_user[$o]);
                if ( ($smtp[$out]->getline) =~ /^250/)
                {
                $finded++;
                open(OUT, ">> $output");
                print OUT $out."\t\t".$vc_user[$o-3]."\n";
                print STDOUT $out."\t\t".$vc_user[$o-3]."\n";
                close(OUT);
                }
        }
	$smtp[$out]->close;
}
}
		}
sub error() { $o.""; }
sub process() {
	if ($estado == 0)
	{
		for ($i=1;$i<=3;$i++)
		{
			if ($pid == $kids[$i] ) 
			{
			print STDOUT $i."\t\t\t\t\tReiniciada en:";
			$inicio=$i; $final=$i;
			open(TOUCH,"< $guia.$i"); while (<TOUCH>) { chomp; $continue=$_; } close(TOUCH);
			print STDOUT $continue."\n";
			&conectar;
			}
		}
	}
}
sub check_host() {
	my $chkhost=new Net::Telnet (	Timeout	=>15,
					Errmode	=>&error,
					port	=>$port);
	$chkhost->open($hostname) or die "No puede encontrarse $hostname.\n";
	print $chkhost->getline;
	$chkhost->print("EXPN test");
	if ( ($chkhost->getline) =~ /^502/)
	 {
	 print "$hostname, no soporta el comando EXPN\n";
	 $chkhost->close;
	 exit(0);
 	 }
}
		
