rcon.pl: add a mode rcon_secure=2 using the more secure challenge-based mode.
authordiv0 <div0@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Fri, 2 Oct 2009 08:20:54 +0000 (08:20 +0000)
committerdiv0 <div0@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Fri, 2 Oct 2009 08:20:54 +0000 (08:20 +0000)
NOTE: this mode will be bad for rcon2irc.

git-svn-id: svn://svn.icculus.org/nexuiz/trunk@8005 f962a42d-fe04-0410-a3ab-8c8b0445ebaa

server/rcon.pl

index 58a41cb..b6a136e 100755 (executable)
@@ -407,7 +407,15 @@ sub join_commands($@)
 sub send($$$)
 {
        my ($self, $line, $nothrottle) = @_;
-       if($self->{secure})
+       if($self->{secure} > 1)
+       {
+               $self->{connector}->send("\377\377\377\377getchallenge");
+               my $c = $self->recvchallenge();
+               return 0 if not defined $c;
+               my $key = Digest::HMAC::hmac("$c $line", $self->{password}, \&Digest::MD4::md4);
+               return $self->{connector}->send("\377\377\377\377srcon HMAC-MD4 CHALLENGE $key $c $line");
+       }
+       elsif($self->{secure})
        {
                my $t = sprintf "%ld.%06d", time(), int rand 1000000;
                my $key = Digest::HMAC::hmac("$t $line", $self->{password}, \&Digest::MD4::md4);
@@ -429,6 +437,38 @@ sub quote($$)
        return $data;
 }
 
+sub recvchallenge($)
+{
+       my ($self) = @_;
+
+       my $sel = IO::Select->new($self->fds());
+       my $endtime_max = Time::HiRes::time() + 1;
+       my $endtime = $endtime_max;
+
+       while((my $dt = $endtime - Time::HiRes::time()) > 0)
+       {
+               if($sel->can_read($dt))
+               {
+                       for(;;)
+                       {
+                               my $s = $self->{connector}->recv();
+                               die "read error\n"
+                                       if not defined $s;
+                               length $s
+                                       or last;
+                               if($s =~ /^\377\377\377\377challenge (.*)$/s)
+                               {
+                                       return $1;
+                               }
+                               next
+                                       if $s !~ /^\377\377\377\377n(.*)$/s;
+                               $self->{recvbuf} .= $1;
+                       }
+               }
+       }
+       return undef;
+}
+
 sub recv($)
 {
        my ($self) = @_;