#!/usr/bin/perl

use IO::Socket;
use Sys::Hostname;
use Crypt::Rijndael;

# -------------------------------------------------------------------------

$yourpass = 'PASSWORD';   # ваш пароль
$server = 'IP-SERVER';            # сервер авторизации
$portno = 7723;                  # порт

# -------------------------------------------------------------------------
$ver = 14;                       # protocol version
$v = 0;                          # 1 - verbose
# =========================================================================

sub SEND
 {
  $sock1->send($_[0]);
 }

 sub GET
 {
   my ($i,$n,$str,$tmout,$rin,$txt,$ip,$addr) = (0,10,'',5,'','','','');
   vec($rin,fileno($sock2),1) = 1;
   while (select($txt = $rin, undef, undef, $tmout) && ++$i<$n)
     {
       $tmout = 0;
       $addr = recv($sock2, $txt, 100, 0);
       ($ip, $addr) = sockaddr_in($addr);
       $ip = join(".",unpack ("C4", $addr));
       next if $ip ne $server;
       $str=$txt;
     }
   unless ($str)
     {
       $noanswer++;
       if ($noanswer>10) {$noanswer=0; sleep 20;}
       print "no answer...\n" if $v;
     }
   return($str);
 }

# ==============================================================================

$passwd_in  = substr((substr $yourpass, 0, 3)."Z" x 16, 0, 16);
$passwd_out = substr((substr $yourpass, 3, 16)."0" x 16, 0, 16);

$sock1 = IO::Socket::INET->new(Proto => 'udp', PeerPort => $portno, PeerAddr => $server);
unless ($sock1) {print "Cannot create socket...exit\n"; exit;}

$proto = getprotobyname('udp');
unless (socket($sock2, PF_INET, SOCK_DGRAM, $proto) &&
        bind($sock2, sockaddr_in($portno, INADDR_ANY)) )
       {print "Cannot bind socket...exit\n"; exit;}

$id = substr(rand,2,6);
$noanswer = 0;

while(1)
{
  $id = 999999 unless $id--;
  &SEND("$ver$id");
  print "BEGIN SESSION\n" if $v;

  $p = &GET;
  next unless $p;
  if ($p !~ /^id(.{16})$ver$id$/s)
     {
      &GET;
      &GET;
      sleep 1;
      next;
     }
  $cipher = new Crypt::Rijndael $passwd_in,Crypt::Rijndael::MODE_CBC;
  $key = $cipher->decrypt($1);
  $cipher = new Crypt::Rijndael $passwd_out,Crypt::Rijndael::MODE_CBC;
  $skey = $cipher->encrypt($key);
  &SEND($skey."a$ver$id");
  $p = &GET;
  next unless $p;
  $stat = substr $p,0,2;
  $stat = $stat eq 'ok' || $stat eq 'sv' ? "OK" : "NO";
  print "AUTH $stat\n" if $v;

  sleep 40;
}



