Apache2-AuthenRadius
view release on metacpan or search on metacpan
AuthenRadius.pm view on Meta::CPAN
use Apache2::RequestRec;
use Apache2::Access;
use Apache2::RequestUtil;
use Apache2::Log;
use APR::SockAddr;
use Authen::Radius;
$VERSION = '0.9';
# Create my own method to check a password
# The Authen::Radius->check_pwd method was too restrictive
# to use. We needed a function that returned all possible
# values.
sub chk_passwd {
my ($rad, $uname, $upwd, $nas) = @_;
$rad->clear_attributes;
$rad->add_attributes (
{Name => 1, Value => $uname, Type => 'string' },
{Name => 2, Value => $upwd, Type => 'string' },
{Name => 4, Value => $nas, Type => 'ipaddr' }
);
$rad->send_packet(ACCESS_REQUEST);
my $rcv = $rad->recv_packet();
return($rcv);
}
sub handler {
my $r = shift;
# Continue only if the first request.
return OK unless $r->is_initial_req();
my $reqs_arr = $r->requires;
return OK unless $reqs_arr;
# Grab the password, or return if HTTP_UNAUTHORIZED
my($res,$pass) = $r->get_basic_auth_pw;
return $res if $res;
# Get the user name.
my $user = $r->user;
# Primary Radius Server and port.
my $host1 = $r->dir_config("Auth_Radius_host1") or return DECLINED;
my $port1 = $r->dir_config("Auth_Radius_port1") || 1647;
# Shared secret for the primary host we are running on.
my $secret1 = $r->dir_config("Auth_Radius_secret1") or return DECLINED;
# Secondary Radius Server and port.
my $host2 = $r->dir_config("Auth_Radius_host2");
my $port2 = $r->dir_config("Auth_Radius_port2") || 1647;
# Shared secret for the secondary host we are running on.
my $secret2 = $r->dir_config("Auth_Radius_secret2");
# Timeout to wait for a response from the radius server.
my $timeout = $r->dir_config("Auth_Radius_timeout") || 5;
# Sanity for usernames and passwords.
if (length $user > 64 or $user =~ /[^A-Za-z0-9\@\.\-\_\#\:]/) {
$r->log_reason("Apache2::AuthenRadius username too long or"
."contains illegal characters. URI:", $r->uri);
$r->note_basic_auth_failure;
return HTTP_UNAUTHORIZED;
}
# Prepend realm if set
if ($r->dir_config("Auth_Radius_prependToUsername")) {
$user = $r->dir_config("Auth_Radius_prependToUsername") . $user;
}
# Postfix realm if set
if ($r->dir_config("Auth_Radius_postfixToUsername")) {
$user .= $r->dir_config("Auth_Radius_postfixToUsername");
}
if (length $pass > 256) {
$r->log_reason("Apache2::AuthenRadius password too long. URI:",$r->uri);
$r->note_basic_auth_failure;
return HTTP_UNAUTHORIZED;
}
# Create the object for the primary RADIUS query
my $radius = Authen::Radius->new(
Host => "$host1:$port1",
Secret => $secret1,
TimeOut => $timeout
);
# Fail if we can't create object for primary
# RADIUS server
if (!defined $radius) {
$r->log_reason("Apache2::AuthenRadius failed to"
."create object for $host1:$port1. URI:",$r->uri);
return HTTP_INTERNAL_SERVER_ERROR;
}
# Get my IP address to pass as the
# NAS IP Address
my $c = $r->connection;
my $sockaddr = $c->local_addr;
my $nas_ip_address = $sockaddr->ip_get;
# Check with the primary RADIUS server.
my $access = chk_passwd($radius,$user,$pass,$nas_ip_address);
if ($access == ACCESS_ACCEPT) {
# Good ... we're in
return OK;
} elsif ($access == ACCESS_REJECT) {
# Sorry, you can't get in
$r->log_reason("Apache2::AuthenRadius failed for user $user. URI:",
$r->uri);
$r->note_basic_auth_failure;
return HTTP_UNAUTHORIZED;
} elsif (!defined($access)) {
# We didn't get a response from the primary
( run in 0.928 second using v1.01-cache-2.11-cpan-39bf76dae61 )