mavis_tacplus_radius.pl

515 views
Skip to first unread message

Silver Fox

unread,
Jan 26, 2010, 8:20:08 PM1/26/10
to Event-Driven Servers
First, thank you for the extraordinary documentation on your
projects. Its excellent, and appreciated.

That being said, there is one thing I'm having trouble finding, how to
call mavis_tacplus_radius.pl from my tac_plus configuration file. I
have something like this:

id = tac_plus {
accounting log = /var/log/tac_plus/%Y/%m/%d.log
retire limit = 1000
mavis module = external {
exec = /usr/local/lib/mavis_tacplus_radius.pl
# see the MAVIS configuration manual for more options and
other modules

}
user backend = mavis
login backend = mavis

However, I don't know where I can specify the radius server that will
be contacted. Did I miss the explanation somewhere? Maybe this note
in the header of the script is a clue:

# Test input:
# 0 TACPLUS
# 4 $USER
# 8 $PASS
# 49 AUTH
# =

Thanks for the help,
Josh

Marc Huber

unread,
Jan 27, 2010, 11:26:39 AM1/27/10
to Event-Driven Servers
Hi Josh,

thanks a lot for the feedback.

On 27 Jan., 02:20, Silver Fox <silverfox...@gmail.com> wrote:
> That being said, there is one thing I'm having trouble finding, how to
> call mavis_tacplus_radius.pl from my tac_plus configuration file.  I

...
>         exec = /usr/local/lib/mavis_tacplus_radius.pl

The RADIUS server is specified in the Perl script itself:

my $RADIUS_HOST = 'radius.example.com';
my $RADIUS_SECRET = 'secret';

Just change those assignments to match your environment.

Alternatively, you may use the "radmavis" backend:

mavis module = external {
exec = /where/ever/radmavis radmavis
"authserver=localhost:1812:mYrAdIuSsEcReT"
}

>     user backend = mavis
This one won't work. The stock radius backend can only authenticate
users and doesn't return any group membership or service definitions.
That can be worked by modifying the Perl script to add a "TACPROFILE"
attribute-value pair (e.g.: $V[AV_A_TACPROFILE] = "{ member =
admins }") or by setting the TACPROFILE variable in the module's
"script out = " section.

Modifying the Perl script is probably the best option -- it could, for
example, allow for setting TACACS+ group membership based on RADIUS
attributes.

> login backend = mavis
This tells the daemon to use the MAVIS authentication backend to
authenticate dynamic users. By default, the password set in the user
profile will be used (e.g.: "user = cisco { login = clear cisco }").
The "login backend = mavis" configuration basically tells the daemon
to ignore the "login =" stanzas.

Locally defined users can authenticate against the MAVIS backend if
"login = mavis" is set in their profiles.

> However, I don't know where I can specify the radius server that will
> be contacted.  Did I miss the explanation somewhere?  Maybe this note
> in the header of the script is a clue:
>
> # Test input:
> # 0 TACPLUS
> # 4 $USER
> # 8 $PASS
> # 49 AUTH
> # =

Nope, that's just some sample test data for verifying script
functionality.

Cheers,

Marc

Silver Fox

unread,
Jan 31, 2010, 6:28:12 PM1/31/10
to Event-Driven Servers
Thank you for the quick reply. I've tried setting this, and I'm
running into trouble. Is there a quick easy way to test an
authentication against the radius server before proxying through
tac_plus? Any pointers on how to troubleshoot is appreciated.

Here is my log file:

$ tail -f /var/log/tac_plus/2010/01/31.log
2010-01-31 17:19:19 -0600 10.75.191.226 tty1 44.37.240.173 stop
task_id=4 timezone=UTC service=shell disc-cause=9 disc-cause-ext=2 pre-
session-time=4 elapsed_time=262
2010-01-31 17:19:19 -0600 10.75.191.226 tty1 44.37.240.173 stop
task_id=6 timezone=UTC service=shell priv-lvl=0 cmd=quit <cr>
2010-01-31 17:19:32 -0600 10.75.191.226 silverfox tty1 44.37.240.173
start task_id=8 timezone=UTC service=shell
2010-01-31 17:19:34 -0600 10.75.191.226 silverfox tty1 44.37.240.173
stop task_id=8 timezone=UTC service=shell priv-lvl=0 cmd=quit <cr>
2010-01-31 17:19:34 -0600 10.75.191.226 silverfox tty1 44.37.240.173
stop task_id=8 timezone=UTC service=shell disc-cause=9 disc-cause-
ext=2 pre-session-time=12 elapsed_time=1


From the tac_plus.conf man page, I take it the disc-cause is "NAS
error". How can I get ellaborated detail that will point me in the
right direction?

Thanks,
Josh

Silver Fox

unread,
Jan 31, 2010, 6:55:34 PM1/31/10
to Event-Driven Servers
I found freeradius tools, and have tried to authenticate from the
server with that. Does this indicate that there is a problem on my
radius server?

$ echo "User-Name=silverfox,Password=snipped " | radclient -s -x
10.10.61.20:1645 auth "foo\!"
Sending Access-Request of id 72 to 10.10.61.20 port 1645
User-Name = "silverfox"
Password = "snipped"
<...>
radclient: no response from server for ID 72 socket 3

Total approved auths: 0
Total denied auths: 0
Total lost auths: 1

If so, I'll focus on getting that working.

Thanks,
Josh

Silver Fox

unread,
Jan 31, 2010, 8:49:05 PM1/31/10
to Event-Driven Servers
Sorry, but I keep thinking of questions after the fact. When I
authenticate against tac_plus and its configured with the radius mavis
backend, what NAS source IP is sent to the radius server? The one of
my tac_plus server, or the one of the original NAS making the
request? Is this configurable?

Marc Huber

unread,
Feb 1, 2010, 1:36:28 AM2/1/10
to Event-Driven Servers
Hi Josh,

yes, this looks like you radius server isn't responding.

You can test the Perl script by feeding it some test data on stdin:

printf "0 TACPLUS\n4 silverfox\n8 yourpassword\n49 AUTH\n=\n" |
mavis_tacplus_radius.pl

Cheers,

Marc

Marc Huber

unread,
Feb 1, 2010, 1:40:10 AM2/1/10
to Event-Driven Servers
Hi Josh,

the source IP of the radius packets is the one from the tacacs server.

Is your radius server actually running on port 1645? Most recent
implementations run on 1812 by default.

Cheers,

Marc

Silver Fox

unread,
Feb 2, 2010, 1:45:23 PM2/2/10
to Event-Driven Servers
I got the radius server issue is sorted, and I have confirmed it from
the freeradius client:

$ echo "User-Name=silverfox,Password=<snip> " | radclient -s -x
10.10.61.20:1645 auth '<snip>'
Sending Access-Request of id 4 to 10.10.61.20 port 1645


User-Name = "silverfox"
Password = "<snip>"

rad_recv: Access-Accept packet from host 10.10.61.20 port 1645, id=4,
length=81
Juniper-Local-User-Name = "eng"
Service-Type = NAS-Prompt-User
Class =
0x434143533a302f356637662f31111439663061642f6a6f7368726f67657273

Total approved auths: 1
Total denied auths: 0
Total lost auths: 0


However, when trying with the mavis script, it says Permission
denied.:

$ printf "0 TACPLUS\n4 silverfox \n8 <snip>\n49 AUTH\n=\n" | /usr/
local/lib/mavis/mavis_tacplus_radius.pl
0 TACPLUS
4 silverfox
6 NAK
8 <snip>
32 Permission denied.
49 AUTH
=0

from the perl script:
my $RADIUS_HOST = 10.10.61.20:1645';
my $RADIUS_SECRET = '<snip>';

Am I reading this incorrectly?


-Josh

Marc Huber

unread,
Feb 3, 2010, 11:11:32 AM2/3/10
to Event-Driven Servers
Hi Josh,

judging from one of your older posts, your RADIUS secret contains an
exclamation mark, and in shell context you're correctly escaping that
with a backslash. However, you don't need that escape character in
Perl. Did you double-check that the RADIUS secret used in the script
is correct?

Cheers,

Marc

Silver Fox

unread,
Feb 6, 2010, 11:35:30 PM2/6/10
to Event-Driven Servers
I did pick up on that (which is why I intentionally included the ! in
the earlier post), and I've checked and rechecked, and the one in the
script is correct and not escaped. It is in single quotes. It also
includes the & and $ symbols in addition to the bang.

I believe that in single quotes, I shouldn't need to escape anything
though, and this should work.

Thanks for your time/expertise,
Josh

Marc Huber

unread,
Feb 7, 2010, 4:13:31 AM2/7/10
to Event-Driven Servers
Hi Josh,

I'm still pretty certain that there's some problem with the secret.
Can you please check whether

#!/usr/bin/perl
use Authen::Simple::RADIUS;
$radius = Authen::Simple::RADIUS->new(host=>"10.10.61.20:1645",
secret=>'foo!');
print 1 == $radius->authenticate('silverfox', 'yourpasswordhere') ? "OK
\n" : "FAIL\n";

returns the expected result?

Cheers,

Marc

Silver Fox

unread,
Feb 7, 2010, 2:07:40 PM2/7/10
to Event-Driven Servers
OK. Your test script results in 'OK'

I've and rechecked the server port, secret, user and pass in the mavis
script, and they are the same.

Silver Fox

unread,
Feb 7, 2010, 2:14:36 PM2/7/10
to Event-Driven Servers
Oh no... I think I had a trailing space on the username... Gah.

$ printf "0 TACPLUS\n4 silverfox\n8 password\n49 AUTH\n=\n" | /usr/


local/lib/mavis/mavis_tacplus_radius.pl
0 TACPLUS
4 silverfox

6 ACK
8 password
36 password
49 AUTH
52 1
=16

That looks right?

Silver Fox

unread,
Feb 7, 2010, 2:27:14 PM2/7/10
to Event-Driven Servers
Now, for the configuration. I understand that this radius client only
does authentication for me, and does not do authorization or
accounting.

I'm still not authenticating correctly via tacplus

Here is my config file:

<blockquote>
#!/usr/local/bin/tac_plus
id = spawnd { listen = { port = 49 } }


id = tac_plus {
accounting log = /var/log/tac_plus/%Y/%m/%d.log
retire limit = 1000

mavis module = auth {
}
# mavis module = userdb {
# user = test {
# password = mavis
# root = /tmp/
# home = /
# userid = 100
# groupid = 100
# }
# }
mavis module = external {
exec = /usr/local/lib/mavis/mavis_tacplus_radius.pl


# see the MAVIS configuration manual for more options and
other modules
}

# mavis module = external {
# exec = /usr/local/lib/mavis/mavis_tacplus_passwd.pl
# }


user backend = mavis
login backend = mavis

host = world {
prompt = "\nHitherto shalt thou come, but no further. (Job
38.11)\n\n"
key = foo!
enable 15 = clear test
address = 0.0.0.0/0
}

group = readwrite {
default service = permit
service = shell {
default command = permit
set priv-lvl = 15
}
}

group = getconfig {
default service = permit
service = shell {
set autocmd = "sho run"
set priv-lvl = 15
}
}

user = silverfox {
login = mavis
member = readwrite@world
member = getc...@10.10.0.0/16
}
}
</blockquote>

I'm adding the 'silverfox' user because I'm under the impression that
tacplus needs every user defined for the sake of the authorization
piece. Am I correct? And am I going about this correctly?


When I use the radclient, it returns an AV pair for the attribute
Juniper-Local-User-Name. Do you think there is a way to treat the
value of this attribute as the name of the tacplus group I expect the
user to be in, and assign permissions to that group?

This would allow me to NOT have to maintain a list of users in the
tacplus config, but instead just give permissions to any user on the
radius server with a certain Juniper-Local-User-Name value.

Clearly I'm capable of overlooking the obvious, so I'm going to read
over the tacplus and mavis documentation you have at
http://www.pro-bono-publico.de/projects/ again.

-Josh

Marc Huber

unread,
Feb 7, 2010, 3:08:37 PM2/7/10
to Event-Driven Servers
Hi Josh,

glad the authentication issue is resolved :-)

Using the Juniper-Local-User-Name (or any other) attribute goes
somewhat beyond what Authen::Simple::RADIUS is capable of.

Rewriting the authentication script to use Authen::RADIUS (which is
capable of accessing the attributes sent by the RADIUS server) instead
should be pretty trivial. Basically, an add_attributes-send-packet-
recv_packet-get_attributes sequence will do. It *might* be non-trivial
to tell Authen::RADIUS about the Juniper VSA extensions, however.

Alas, I'll be kind-of offline for the better part of the next week.
I'll have a closer look at the modifications necessary next weekend.

Cheers,

Marc

>        member = getcon...@10.10.0.0/16

> ...
>
> Erfahren Sie mehr »

Marc Huber

unread,
Feb 12, 2010, 1:45:16 PM2/12/10
to Event-Driven Servers
Hi Josh,

the current snapshot (DEVEL.201002121934.tar.bz2) includes a Perl
script named "mavis_tacplus_radius2.pl". The script depends on
Authen::Radius and optionally sets a member attribute in the user's
profile.

The following should work, provided that your RADIUS dictionary
(probably /etc/raddb/dictionary) actually knows about "Juniper-Local-
User-Name":

mavis module = external {
env RADIUS_HOST = 10.10.61.20:1645
env RADIUS_SECRET = 'foo!'
env RADIUS_GROUP_ATTR = Juniper-Local-User-Name
exec = /path/to/mavis_tacplus_radius2.pl
}

Cheers,

Marc

Marc Huber

unread,
Feb 12, 2010, 3:00:55 PM2/12/10
to Event-Driven Servers
I did mess up the syntax in my last mail. Keyword for setting
environment variables is actually "setenv":

mavis module = external {
setenv RADIUS_HOST = 10.10.61.20:1645
setenv RADIUS_SECRET = 'foo!'
setenv RADIUS_GROUP_ATTR = Juniper-Local-User-Name
exec = /path/to/mavis_tacplus_radius2.pl

Marc Huber

unread,
Feb 13, 2010, 5:22:09 AM2/13/10
to Event-Driven Servers
I've just merged mavis_tacplus_radius2.pl functionality into the
mavis_tacplus_radius.pl script and removed the former script from the
distribution. The documentation is updated, too.

Cheers,

Marc

On 12 Feb., 19:45, Marc Huber <marc.j.hu...@googlemail.com> wrote:

Silver Fox

unread,
Feb 28, 2010, 1:11:45 PM2/28/10
to Event-Driven Servers
Fantastic! You're efforts are appreciated.
Reply all
Reply to author
Forward
0 new messages