(RADIATOR) Patch against 3.13 to support per-client TACACS+ keys

James FitzGibbon jfitzgibbon at primustel.ca
Fri Oct 7 10:22:14 CDT 2005


In Radiator v3.13, ServerTACACSPLUS uses a global key to decrypt the
packets.  I'm trying to replace a Cisco TACACS+ server by enabling TACACS+
in Radiator, but each of our devices uses a different key.

The following patch against Radius/ServerTACACSPLUS.pm allows for the
"secret" defined in the <Client> block for each device to be used as the
TACACS+ key.  If there is no secret defined for the client, the global key
is still used (so this shouldn't break anything for people currently using
the global key configuration).

I've tested this using Perl's Authen::TACACS module and with Radiator's
tacacsplustest and it works properly.  What I haven't been able to test due
to the way both of those tools work is an unencrypted TACACS+ request.
Neither tool can set up an unencrypted request such that
$Radius::ServerTACACSPLUS::TAC_PLUS_UNENCRYPTED_FLAG is set.  If you don't
provide a key to tacacsplustest, it uses the default secret of 'mysecret'.

I've yet to update documentation, but I would like to get some feedback as
to usefulness before I polish this off to submit to OSC for possible
inclusion in an upcoming release.

Thanks

Index: Radius/ServerTACACSPLUS.pm
===================================================================
--- Radius/ServerTACACSPLUS.pm  (.../vendor/Radiator-3.13)      (revision
173)
+++ Radius/ServerTACACSPLUS.pm  (.../trunk)     (revision 173)
@@ -17,6 +17,7 @@

 package Radius::ServerTACACSPLUS;
 @ISA = qw(Radius::Configurable);
+use Radius::Client;
 use Radius::Configurable;
 use Radius::Context;
 use Digest::MD5;
@@ -150,8 +151,6 @@

     my $self = $class->SUPER::new($file, @args);

-    $self->log($main::LOG_WARNING, "No Key defined for $class at
'$main::config_file' line $.")
-       if !defined $self->{Key};

     # Create a TCP socket to listen on each BindAddress, register it with
select
     # Set up the TCP listener
@@ -234,10 +233,30 @@
        return;
     }

+    # Try to find a key to decrypt the payload (per-client, falling back to
server global)
+    my $key;
+    my $peer = getpeername($newsocket);
+    my(undef, $peeraddr) = Socket::unpack_sockaddr_in($peer);
+    if( my $client = &Radius::Client::find($peeraddr) ) {
+        if( defined $client->{Secret} ) {
+            $key = $client->{Secret};
+            $self->log($main::LOG_EXTRA_DEBUG, "Found per-client TACACS+
key");
+        }
+    }
+    if( !defined $key ) {
+        if( defined $self->{Key} ) {
+            $key = $self->{Key};
+            $self->log($main::LOG_EXTRA_DEBUG, "Using Global TACACS+ Key");
+        }
+        else {
+            $self->log($main::LOG_WARNING, "No Global TACACS+ Key
defined");
+        }
+    }
+
     Radius::TacacsplusConnection->new
        ($self, $newsocket,
         MaxBufferSize             => $self->{MaxBufferSize},
-        Key                       => $self->{Key},
+        Key                       => $key,
         AuthorizationTimeout      => $self->{AuthorizationTimeout},
         AddToRequest              => $self->{AddToRequest},
         GroupCacheFile            => $self->{GroupCacheFile},
@@ -362,8 +381,14 @@
     $self->{session_id} = $session_id;

     # Maybe decrypt the payload
-    $body = &crypt($session_id, $self->{Key}, $version, $seq_no, $body) if
defined($self->{Key});
-    $self->{parent}->log($main::LOG_EXTRA_DEBUG, "TacacsPlus request
decrypted body: " . unpack('H*', $body));
+    if( defined($self->{Key}) ) {
+        $self->{parent}->log($main::LOG_EXTRA_DEBUG, "Decrypting TacacsPlus
request");
+        $body = &crypt($session_id, $self->{Key}, $version, $seq_no,
$body);
+        $self->{parent}->log($main::LOG_EXTRA_DEBUG, "TacacsPlus request
decrypted body: " . unpack('H*', $body));
+    }
+    else {
+        $self->{parent}->log($main::LOG_EXTRA_DEBUG, "TacacsPlus request
body: " . unpack('H*', $body));
+    }

     if ($type == $Radius::ServerTACACSPLUS::TAC_PLUS_AUTHEN && $seq_no ==
1)
     {

-- 
j.
 
James FitzGibbon
Systems Developer, Primus Telecommunications Canada Inc.
416.644.6111

-- 
No virus found in this outgoing message.
Checked by AVG Anti-Virus.
Version: 7.0.344 / Virus Database: 267.11.9/116 - Release Date: 9/30/2005
 



-- 
----------------------------------------------------------------------------
This electronic message contains information from Primus Telecommunications
Canada Inc. ("PRIMUS") , which may be legally privileged and confidential.
The information is intended to be for the use of the individual(s) or entity
named above. If you are not the intended recipient, be aware that any
disclosure, copying, distribution or use of the contents of this information
is prohibited. If you have received this electronic message in error, please
notify us by telephone or e-mail (to the number or address above)
immediately. Any views, opinions or advice expressed in this electronic
message are not necessarily the views, opinions or advice of PRIMUS.
It is the responsibility of the recipient to ensure that
any attachments are virus free and PRIMUS bears no responsibility
for any loss or damage arising in any way from the use
thereof.The term "PRIMUS" includes its affiliates.
----------------------------------------------------------------------------
Pour la version en français de ce message, veuillez voir
 http://www.primustel.ca/fr/legal/cs.htm
----------------------------------------------------------------------------

--
Archive at http://www.open.com.au/archives/radiator/
Announcements on radiator-announce at open.com.au
To unsubscribe, email 'majordomo at open.com.au' with
'unsubscribe radiator' in the body of the message.


More information about the radiator mailing list