1package Netdot::Radius;
2
3use strict;
4use warnings;
5use Authen::Radius;
6use APR::SockAddr;
7use Netdot::AuthLocal;
8
9=head1 NAME
10
11Netdot::Radius - RADIUS module for Netdot
12
13=head1 SYNOPSIS
14
15In Apache configuration:
16
17=over 4
18
19   PerlSetVar SiteControlMethod Netdot::Radius
20
21   <Location /netdot/NetdotLogin>
22       PerlSetVar NetdotRadiusHost "localhost"
23       PerlSetVar NetdotRadiusSecret "testing123"
24       PerlSetVar NetdotRadiusHost2 "otherhost"
25       PerlSetVar NetdotRadiusSecret2 "testing123"
26       PerlSetVar NetdotRadiusTimeOut "5"
27       PerlSetVar NetdotRadiusFailToLocal "yes"
28   </Location>
29
30=back
31
32=head1 DESCRIPTION
33
34    Netdot::Radius uses Authen::Radius to issue authentication and authorization queries
35    for Netdot.  It supports failover by querying one RADIUS server first, then the second.
36    It also returns any available Netdot-specific attributes for a given user.
37
38=cut
39
40#Be sure to return 1
411;
42
43
44############################################################################
45
46=head2 check_credentials
47
48  Arguments:
49    Apache Request Object
50    Username
51    Password
52  Returns:
53    True or false
54  Examples:
55    if ( Netdot::Radius::check_credentials($r, $user, $pass) {...}
56
57=cut
58
59sub check_credentials {
60    my ($r, $username, $password) = @_;
61    unless ( $username && $password ){
62	$r->log_error("Missing username and/or password");
63	return 0;
64    }
65
66    my $fail_to_local = ($r->dir_config("NetdotRadiusFailToLocal") eq "yes")? 1 : 0;
67
68    my $radius;
69    unless ( $radius = Netdot::Radius::_connect($r) ){
70	if ( $fail_to_local ){
71	    $r->log_error("Netdot::Radius::check_credentials: Trying local auth");
72	    return Netdot::AuthLocal::check_credentials($r, $username, $password);
73	}else{
74	    return 0;
75	}
76    }
77
78    # Get my IP address to pass as the Source IP and NAS IP Address
79    my $c = $r->connection;
80    my $sockaddr = $c->local_addr if defined($c);
81    my $nas_ip_address = $sockaddr->ip_get if defined($sockaddr);
82
83
84    if ( $radius->check_pwd($username, $password, $nas_ip_address) ) {
85	return 1;
86    }else{
87	$r->log_error("Netdot::Radius::check_credentials: User $username failed RADIUS authentication: "
88		      . $radius->strerror);
89	if ( $fail_to_local ){
90	    $r->log_error("Netdot::Radius::check_credentials: Trying local auth");
91	    return Netdot::AuthLocal::check_credentials($r, $username, $password);
92	}
93    }
94    return 0;
95}
96
97############################################################################
98# _connect - Connect to an available RADIUS server
99#
100#   Arguments:
101#     Apache Request Object
102#   Returns:
103#     Authen::Radius object
104#   Examples:
105#     my $radius = Netdot::Radius::connect($r);
106#
107#
108sub _connect {
109    my ($r) = @_;
110
111    my $host     = $r->dir_config("NetdotRadiusHost")    || "localhost";
112    my $host2    = $r->dir_config("NetdotRadiusHost2");
113    my $secret   = $r->dir_config("NetdotRadiusSecret")  || "unknown";
114    my $secret2  = $r->dir_config("NetdotRadiusSecret2") || "unknown";
115    my $timeout  = $r->dir_config("NetdotRadiusTimeOut") || "5";
116    my $radius;
117
118    $r->log_error("WARNING: Shared secret is not set. Use RadiusSiteControlSecret in httpd.conf")
119	if $secret eq "unknown";
120
121    $radius = new Authen::Radius(Host=>$host, Secret=>$secret, TimeOut=>$timeout);
122    if ( !$radius ) {
123	$r->log_error("Could not contact radius server: $host.");
124	if ( $host2 ){
125	    # Try second RADIUS server
126	    $radius = new Authen::Radius(Host=>$host2, Secret => $secret2);
127	    if ( !$radius ) {
128		$r->log_error("Could not contact radius server: $host2");
129		return 0;
130	    }
131	}else{
132	    return 0;
133	}
134    }
135    return $radius;
136}
137
138=head1 SEE ALSO
139
140Apache2::SiteControl
141
142=head1 AUTHORS
143
144Carlos Vicente, C<< <cvicente at ns.uoregon.edu> >>
145
146=head1 COPYRIGHT & LICENSE
147
148Copyright 2012 University of Oregon, all rights reserved.
149
150This program is free software; you can redistribute it and/or modify
151it under the terms of the GNU General Public License as published by
152the Free Software Foundation; either version 2 of the License, or
153(at your option) any later version.
154
155This program is distributed in the hope that it will be useful, but
156WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
157or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
158License for more details.
159
160You should have received a copy of the GNU General Public License
161along with this program; if not, write to the Free Software Foundation,
162Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
163
164=cut
165
166
167
168