Add TACACS+ support per #660 (#662)

This commit is contained in:
Oliver Gorwits
2019-10-15 18:23:51 +01:00
committed by GitHub
parent ecc9c6f209
commit 4e3bfee214
9 changed files with 45 additions and 2 deletions

View File

@@ -27,6 +27,7 @@ Module::Build->new(
'App::local::lib::helper' => '0.07', 'App::local::lib::helper' => '0.07',
'Archive::Extract' => '0', 'Archive::Extract' => '0',
'Authen::Radius' => '0', 'Authen::Radius' => '0',
'Authen::TacacsPlus' => '0',
'CGI::Expand' => '2.05', 'CGI::Expand' => '2.05',
'Data::Printer' => '0', 'Data::Printer' => '0',
'DBD::Pg' => '0', 'DBD::Pg' => '0',

View File

@@ -11,7 +11,7 @@ __PACKAGE__->load_namespaces(
); );
our # try to hide from kwalitee our # try to hide from kwalitee
$VERSION = 60; # schema version used for upgrades, keep as integer $VERSION = 61; # schema version used for upgrades, keep as integer
use Path::Class; use Path::Class;
use File::ShareDir 'dist_dir'; use File::ShareDir 'dist_dir';

View File

@@ -31,6 +31,8 @@ __PACKAGE__->add_columns(
{ data_type => "boolean", default_value => \"false", is_nullable => 1 }, { data_type => "boolean", default_value => \"false", is_nullable => 1 },
"radius", "radius",
{ data_type => "boolean", default_value => \"false", is_nullable => 1 }, { data_type => "boolean", default_value => \"false", is_nullable => 1 },
"tacacs",
{ data_type => "boolean", default_value => \"false", is_nullable => 1 },
"admin", "admin",
{ data_type => "boolean", default_value => \"false", is_nullable => 1 }, { data_type => "boolean", default_value => \"false", is_nullable => 1 },
"fullname", "fullname",

View File

@@ -23,6 +23,9 @@ __PACKAGE__->result_source_instance->view_definition(<<ENDSQL
SELECT username, 'radius' AS role FROM users SELECT username, 'radius' AS role FROM users
WHERE radius WHERE radius
UNION UNION
SELECT username, 'tacacs' AS role FROM users
WHERE tacacs
UNION
SELECT username, 'api' AS role FROM users SELECT username, 'api' AS role FROM users
WHERE token IS NOT NULL AND token_from IS NOT NULL WHERE token IS NOT NULL AND token_from IS NOT NULL
ENDSQL ENDSQL

View File

@@ -14,6 +14,7 @@ use Dancer::Plugin::Passphrase;
use Digest::MD5; use Digest::MD5;
use Net::LDAP; use Net::LDAP;
use Authen::Radius; use Authen::Radius;
use Authen::TacacsPlus;
use Try::Tiny; use Try::Tiny;
sub authenticate_user { sub authenticate_user {
@@ -113,6 +114,9 @@ sub match_password {
elsif ($user->radius) { elsif ($user->radius) {
$pwmatch_result = $self->match_with_radius($password, $username); $pwmatch_result = $self->match_with_radius($password, $username);
} }
elsif ($user->tacacs) {
$pwmatch_result = $self->match_with_tacacs($password, $username);
}
else { else {
$pwmatch_result = $self->match_with_local_pass($password, $user); $pwmatch_result = $self->match_with_local_pass($password, $user);
} }
@@ -251,4 +255,24 @@ sub match_with_radius {
return $radius_return; return $radius_return;
} }
sub match_with_tacacs {
my($self, $pass, $user) = @_;
return unless setting('tacacs') and ref {} eq ref setting('tacacs');
my $conf = setting('tacacs');
my $tacacs = new Authen::TacacsPlus(Host => $conf->{server}, Key => $conf->{key});
if (not $tacacs) {
debug sprintf('auth error: Authen::TacacsPlus: %s', Authen::TacacsPlus::errmsg());
return undef;
}
my $tacacs_return = $tacacs->authen($user,$pass);
if (not $tacacs_return) {
debug sprintf('error: Authen::TacacsPlus: %s', Authen::TacacsPlus::errmsg());
}
$tacacs->close();
return $tacacs_return;
}
1; 1;

View File

@@ -42,6 +42,7 @@ ajax '/ajax/control/admin/users/add' => require_role setting('defanged_admin') =
fullname => param('fullname'), fullname => param('fullname'),
ldap => (param('ldap') ? \'true' : \'false'), ldap => (param('ldap') ? \'true' : \'false'),
radius => (param('radius') ? \'true' : \'false'), radius => (param('radius') ? \'true' : \'false'),
tacacs => (param('tacacs') ? \'true' : \'false'),
port_control => (param('port_control') ? \'true' : \'false'), port_control => (param('port_control') ? \'true' : \'false'),
admin => (param('admin') ? \'true' : \'false'), admin => (param('admin') ? \'true' : \'false'),
note => param('note'), note => param('note'),
@@ -73,6 +74,7 @@ ajax '/ajax/control/admin/users/update' => require_role setting('defanged_admin'
fullname => param('fullname'), fullname => param('fullname'),
ldap => (param('ldap') ? \'true' : \'false'), ldap => (param('ldap') ? \'true' : \'false'),
radius => (param('radius') ? \'true' : \'false'), radius => (param('radius') ? \'true' : \'false'),
tacacs => (param('tacacs') ? \'true' : \'false'),
port_control => (param('port_control') ? \'true' : \'false'), port_control => (param('port_control') ? \'true' : \'false'),
admin => (param('admin') ? \'true' : \'false'), admin => (param('admin') ? \'true' : \'false'),
note => param('note'), note => param('note'),

View File

@@ -0,0 +1,5 @@
BEGIN;
ALTER TABLE users ADD COLUMN "tacacs" boolean DEFAULT false;
COMMIT;

View File

@@ -6,6 +6,7 @@
<th class="nd_center-cell">Password</th> <th class="nd_center-cell">Password</th>
<th class="nd_center-cell">LDAP Auth</th> <th class="nd_center-cell">LDAP Auth</th>
<th class="nd_center-cell">RADIUS Auth</th> <th class="nd_center-cell">RADIUS Auth</th>
<th class="nd_center-cell">TACACS+ Auth</th>
<th class="nd_center-cell">Port Control</th> <th class="nd_center-cell">Port Control</th>
<th class="nd_center-cell">Administrator</th> <th class="nd_center-cell">Administrator</th>
<th class="nd_center-cell">Created</th> <th class="nd_center-cell">Created</th>
@@ -21,6 +22,7 @@
<td class="nd_center-cell"><input class="span2" data-form="add" name="password" type="password"></td> <td class="nd_center-cell"><input class="span2" data-form="add" name="password" type="password"></td>
<td class="nd_center-cell"><input data-form="add" type="checkbox" name="ldap"></td> <td class="nd_center-cell"><input data-form="add" type="checkbox" name="ldap"></td>
<td class="nd_center-cell"><input data-form="add" type="checkbox" name="radius"></td> <td class="nd_center-cell"><input data-form="add" type="checkbox" name="radius"></td>
<td class="nd_center-cell"><input data-form="add" type="checkbox" name="tacacs"></td>
<td class="nd_center-cell"><input data-form="add" type="checkbox" name="port_control"></td> <td class="nd_center-cell"><input data-form="add" type="checkbox" name="port_control"></td>
<td class="nd_center-cell"><input data-form="add" type="checkbox" name="admin"></td> <td class="nd_center-cell"><input data-form="add" type="checkbox" name="admin"></td>
<td class="nd_center-cell"></td> <td class="nd_center-cell"></td>
@@ -50,6 +52,9 @@
<td class="nd_center-cell"> <td class="nd_center-cell">
<input data-form="update" name="radius" type="checkbox" [% ' checked="checked"' IF row.radius %]> <input data-form="update" name="radius" type="checkbox" [% ' checked="checked"' IF row.radius %]>
</td> </td>
<td class="nd_center-cell">
<input data-form="update" name="tacacs" type="checkbox" [% ' checked="checked"' IF row.tacacs %]>
</td>
<td class="nd_center-cell"> <td class="nd_center-cell">
<input data-form="update" name="port_control" type="checkbox" [% ' checked="checked"' IF row.port_control %]> <input data-form="update" name="port_control" type="checkbox" [% ' checked="checked"' IF row.port_control %]>
</td> </td>

View File

@@ -1,6 +1,6 @@
[% USE CSV -%] [% USE CSV -%]
[% CSV.dump([ 'Full Name' 'Username' [% CSV.dump([ 'Full Name' 'Username'
'LDAP Auth' 'RADIUS Auth' 'Port Control' 'Administrator' 'Created' 'LDAP Auth' 'RADIUS Auth' 'TACACS+ Auth' 'Port Control' 'Administrator' 'Created'
'Last Login' 'Note']) %] 'Last Login' 'Note']) %]
[% FOREACH row IN results %] [% FOREACH row IN results %]
@@ -9,6 +9,7 @@
[% mylist.push(row.username) %] [% mylist.push(row.username) %]
[% mylist.push(row.ldap) %] [% mylist.push(row.ldap) %]
[% mylist.push(row.radius) %] [% mylist.push(row.radius) %]
[% mylist.push(row.tacacs) %]
[% mylist.push(row.port_control) %] [% mylist.push(row.port_control) %]
[% mylist.push(row.admin) %] [% mylist.push(row.admin) %]
[% mylist.push(row.created) %] [% mylist.push(row.created) %]