On Tue, 7 Aug 2001, Andrew Ryan wrote:

> Does anyone have a simpler, perl-based one that  works?

i use the one attached to this mail, and it works fine for me. i'm not
certain of its exact lineage, but it is probably attributable to James
FitzGibbon <[EMAIL PROTECTED]> and Brian Moore <[EMAIL PROTECTED]>. i think i've
tweaked it a little, too.

the entry in the users file looks like this:

Pmontest Auth-Type = Crypt-Local, Password = "sefjKaLm7zybE"
        Service-Type = Framed-User,
        Framed-Protocol = PPP,
        Framed-Routing = None,
        Framed-Compression = Van-Jacobson-TCP-IP,
        Framed-MTU = 1500,
        NAS-Identifier = "watchdog"

in the radius "clients" file, i have a separate key for my mon server.
it looks like this:

# Client Name           Key
#----------------       ----------
watchdog                secret-key

i have this configuration in radius.monitor, which is run from
the host named "watchdog":

$options{username} = "Pmontest";
$options{password} = "secret";
$options{secret} = "secret-key";
$options{dictionary} = "/etc/radius/dictionary";

the password in the "Password =" in the users file is the
output of this:

: dp ~$; perl -e 'print crypt ("secret", "secret"), "\n"'
sefjKaLm7zybE

i'm using the cistron radius server.

the config in mon.cf for testing radius looks like this:

#
# RADIUS servers
#
hostgroup radius radius-primary radius-secondary

watch radius
    service radius
        interval 5m
        monitor radius.monitor
        period wd {Sun-Sat}
            alert mail.alert trockij
            alert qpage.alert trockij
            alertevery 12h

#!/usr/bin/perl
#
# Monitor radius processes
#
# Based upon radius.monitor by Brian Moore, posted to the mon mailing list
#
# Arguments are:
#
# --username=user --password=pass --secret=secret
#       [--port=#] [--attempts=#] [--dictionary=/path/to/dictionary]
#       hostname [hostname ...]
#
# Arguments are in standard POSIX format and can be given as the least
# significant part (i.e. -p is the same as --password).
#
# This monitor performs a real RADIUS check, attempting to be as much like a
# terminal server as possible.  This requires that you include a username,
# password, and secret in your mon.cf file.  Depending on your unix
# implementation, this may allow unscrupulous users to view the command line
# arguments, including your RADIUS secret.  If you prefer, you can uncomment
# three lines below (see comments) to provide defaults for username,
# password, and secret.
#
# This monitor attempts to check a username and password up to n times
# (defaults to 9, but can be set via the --attempts=# command line switch). 
# It only registers a failure to mon after failing to receive a satisfactory
# response n times.  It returns an immediate failure to mon if it receives a
# failed authentication.  For this reason, you will need to create a dummy
# user on your RADIUS server for authentication testing.
#
#
#    Copyright (C) 1998, ACC TelEnterprises
#    Written by James FitzGibbon <[EMAIL PROTECTED]>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

use Authen::Radius;
use Sys::Hostname;
use Getopt::Long;

GetOptions( \%options, "port=i", "secret=s", "username=s", "password=s", "attempts=i", 
"dictionary=s" );

$options{port} ||= 1645;
$options{attempts} ||= 9;

# uncomment these three lines and replace with appropriate info if you'd prefer
# not to pass sensitive information on the command line
$options{username} = "";
$options{password} = "";
$options{secret} = "";
$options{dictionary} = "";

foreach my $key ("username", "password", "secret", "dictionary")
{
    if ($options{$key} eq "")
    {
        die "$key not configured\n";
    }
}

Authen::Radius->load_dictionary( $options{dictionary} );

undef $diag;

@failed_hosts = ();

foreach $host (@ARGV) {
    $auth = new Authen::Radius(Host   => "$host:$options{port}",
                               Secret => $options{secret} );
        $auth->add_attributes(
                { Name => "User-Name", Value => $options{username} },
                { Name => "Password", Value => $options{password} },
                { Name => "NAS-IP-Address", Value => join( ".", unpack ( "C4", 
(gethostbyname( hostname() ))[4] ) ) },
        );
        $done = 0;
        $attempts = 0;
        while( ! $done ) {
                $auth->send_packet( ACCESS_REQUEST );
                $err = $auth->get_error();
                if( $err ne "ENONE" ) {
                        $attempts++;
                        if( $attempts > $options{attempts} ) {
                                push @failed_hosts, $host;
                                push( @failures, "$host failed for user 
$options{username}: " . $auth->strerror( $err ) );
                                $done = 1;
                        }
                        next;
                }
                $resptype = $auth->recv_packet();
                $err = $auth->get_error();
                if( $err ne "ENONE" ) {
                        $attempts++;
                        if( $attempts > $options{attempts} ) {
                                push @failed_hosts, $host;
                                push( @failures, "$host failed for user 
$options{username}: " . $auth->strerror( $err ) );
                                $done = 1;
                        }
                } elsif( $resptype == ACCESS_REJECT ) {
                                push @failed_hosts, $host;
                                push( @failures, "$host returned bad auth for user 
$options{username}" );
                                $done = 1;
                } else {
                        $done = 1;
                }
        }
}

if (@failed_hosts) {
    print "@failed_hosts\n\n";
    print join (", ", @failures), "\n";
    exit 1;
};


exit 0;

Reply via email to