Skip to content

Commit 6a59647

Browse files
committed
Add TACACS+
1 parent c7b26bb commit 6a59647

22 files changed

+2302
-7
lines changed

configure

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ with_ascend_binary
755755
with_tcp
756756
with_vmps
757757
with_dhcp
758+
with_tacacs
758759
with_udpfromto
759760
with_static_modules
760761
with_shared_libs
@@ -1444,6 +1445,7 @@ Optional Packages:
14441445
--with-tcp compile in support for tcp (default=yes)
14451446
--with-vmps compile in support for vmps (default=yes)
14461447
--with-dhcp compile in support for dhcp (default=yes)
1448+
--with-tacacs compile in support for tacacs (default=yes)
14471449
--with-udpfromto compile in support for udpfromto (default=yes)
14481450
--with-static-modules=QUOTED-MODULE-LIST
14491451
--with-shared-libs build dynamic libraries and link against them.
@@ -5555,6 +5557,34 @@ $as_echo "#define WITH_DHCP /**/" >>confdefs.h
55555557
fi
55565558
55575559
5560+
WITH_TACACS=yes
5561+
5562+
5563+
# Check whether --with-tacacs was given.
5564+
if test "${with_tacacs+set}" = set; then :
5565+
withval=$with_tacacs; case "$withval" in
5566+
yes|no|'')
5567+
;;
5568+
no|'')
5569+
;;
5570+
*)
5571+
as_fn_error $? "--with[out]-tacacs expects yes|no" "$LINENO" 5
5572+
;;
5573+
esac
5574+
fi
5575+
5576+
5577+
if test x"$withval" == x"yes"; then
5578+
5579+
$as_echo "#define WITH_TACACS 1" >>confdefs.h
5580+
5581+
else
5582+
5583+
$as_echo "#define WITH_TACACS /**/" >>confdefs.h
5584+
5585+
fi
5586+
5587+
55585588
WITH_UDPFROMTO=yes
55595589
55605590

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ fi
483483
AX_WITH_FEATURE_ARGS([tcp],[yes])
484484
AX_WITH_FEATURE_ARGS([vmps],[yes])
485485
AX_WITH_FEATURE_ARGS([dhcp],[yes])
486+
AX_WITH_FEATURE_ARGS([tacacs],[yes])
486487
AX_WITH_FEATURE_ARGS([udpfromto],[yes])
487488

488489
dnl #

raddb/sites-available/tacacs

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
# -*- text -*-
2+
######################################################################
3+
#
4+
# As of version 4.0.0, the server also supports the TACACS+
5+
# protocol.
6+
#
7+
# $Id$
8+
#
9+
######################################################################
10+
11+
server tacacs {
12+
# namespace = tacacs
13+
14+
listen {
15+
ipaddr = *
16+
17+
# TACACS+ runs over TCP only
18+
proto = tcp
19+
20+
# Port on which to listen.
21+
# Allowed values are:
22+
# integer port number
23+
# 49 is the default TACACS+ port.
24+
port = 49
25+
26+
# Type of packets to listen for. Here, it is TACACS+.
27+
type = tacacs
28+
29+
# Some systems support binding to an interface, in addition
30+
# to the IP address. This feature isn't strictly necessary,
31+
# but for sites with many IP addresses on one interface,
32+
# it's useful to say "listen on all addresses for
33+
# eth0".
34+
#
35+
# If your system does not support this feature, you will
36+
# get an error if you try to use it.
37+
#
38+
# interface = eth0
39+
}
40+
41+
#
42+
# This section is called when it receives an Authentication.
43+
#
44+
recv Authentication {
45+
if (&TACACS-Sequence-Number > 1) {
46+
update request {
47+
TACACS-Authentication-Type = &session-state:TACACS-Authentication-Type
48+
}
49+
}
50+
51+
# draft-ietf-opsawg-tacacs section 4.4.2
52+
switch &TACACS-Authentication-Type {
53+
# ASCII is very generic and driven via unlang so go wild!
54+
case "ASCII" {
55+
if (&TACACS-Sequence-Number == 1) {
56+
update request {
57+
&User-Name = &TACACS-User-Name
58+
}
59+
} else {
60+
update request {
61+
User-Name = &session-state:User-Name
62+
User-Password = &session-state:User-Password
63+
}
64+
}
65+
66+
if (!&User-Name) {
67+
if (&TACACS-User-Message) {
68+
update request {
69+
&User-Name = &TACACS-User-Message
70+
&TACACS-User-Message !* "*"
71+
}
72+
} else {
73+
update reply {
74+
TACACS-Authentication-Status = Get-User
75+
TACACS-Server-Message = "username: "
76+
}
77+
handled
78+
}
79+
}
80+
if (!&User-Password) {
81+
if (&TACACS-User-Message) {
82+
update request {
83+
&User-Password = &TACACS-User-Message
84+
&TACACS-User-Message !* "*"
85+
}
86+
} else {
87+
update reply {
88+
TACACS-Authentication-Status = Get-Pass
89+
TACACS-Server-Message = "password: "
90+
}
91+
handled
92+
}
93+
}
94+
#if (&User-Name && &User-Password) {
95+
# if (!&TACACS-User-Message) {
96+
# update reply {
97+
# TACACS-Authentication-Status = Get-Data
98+
# TACACS-Authentication-Flags = No-Echo
99+
# TACACS-Server-Message = "pin: "
100+
# }
101+
# handled
102+
# }
103+
# if (&TACACS-User-Message != "1234") {
104+
# reject
105+
# }
106+
#}
107+
}
108+
case "PAP" {
109+
if (&TACACS-Sequence-Number == 1) {
110+
if (!&TACACS-User-Name) {
111+
update reply {
112+
&TACACS-Server-Message = "missing User-Name field"
113+
}
114+
invalid
115+
}
116+
117+
update request {
118+
&User-Name = &TACACS-User-Name
119+
&User-Password = &TACACS-Data
120+
}
121+
} else {
122+
update request {
123+
User-Name = &session-state:User-Name
124+
}
125+
}
126+
127+
if (!&User-Password) {
128+
if (&TACACS-User-Message) {
129+
update request {
130+
&User-Password = &TACACS-User-Message
131+
}
132+
} else {
133+
update reply {
134+
TACACS-Authentication-Status = Get-Pass
135+
TACACS-Server-Message = "password: "
136+
}
137+
handled
138+
}
139+
}
140+
}
141+
case "CHAP" {
142+
if (&TACACS-Sequence-Number > 1) {
143+
invalid
144+
}
145+
146+
if (&TACACS-User-Name && &TACACS-Data =~ /^(.)(.{16})(.{16})$/) {
147+
update request {
148+
&User-Name = &TACACS-User-Name
149+
&CHAP-Challenge = "%{2}"
150+
&CHAP-Password = "%{1}%{3}"
151+
}
152+
} else {
153+
update reply {
154+
&TACACS-Server-Message = "missing User-Name and/or Data fields"
155+
}
156+
invalid
157+
}
158+
}
159+
case "MSCHAP" { # UNTESTED
160+
if (&TACACS-Sequence-Number > 1) {
161+
invalid
162+
}
163+
164+
if (&TACACS-User-Name && &TACACS-Data =~ /^(.)(.{8})(.{50})$/) {
165+
update request {
166+
&User-Name = &TACACS-User-Name
167+
&MS-CHAP-Challenge = "%{2}"
168+
&MS-CHAP-Response = "%{1}%{3}"
169+
}
170+
} else {
171+
update reply {
172+
&TACACS-Server-Message = "missing User-Name and/or Data fields"
173+
}
174+
invalid
175+
}
176+
}
177+
case "MSCHAPv2" { # UNTESTED
178+
if (&TACACS-Sequence-Number > 1) {
179+
invalid
180+
}
181+
182+
if (&TACACS-User-Name && &TACACS-Data =~ /^(.)(.{16})(.{50})$/) {
183+
update request {
184+
&User-Name = &TACACS-User-Name
185+
&MS-CHAP-Challenge = "%{2}"
186+
&MS-CHAP2-Response = "%{1}%{3}"
187+
}
188+
} else {
189+
update reply {
190+
&TACACS-Server-Message = "missing User-Name and/or Data fields"
191+
}
192+
invalid
193+
}
194+
}
195+
case {
196+
update reply {
197+
&TACACS-Server-Message = "unsupported authentication type"
198+
}
199+
invalid
200+
}
201+
}
202+
203+
files
204+
205+
mschap
206+
207+
chap
208+
209+
pap
210+
}
211+
212+
#
213+
# This section is called when it sends an Authentication.
214+
#
215+
send Authentication {
216+
switch &TACACS-Authentication-Type {
217+
case "ASCII" {
218+
update session-state {
219+
&TACACS-Authentication-Type := &TACACS-Authentication-Type
220+
&User-Name := &User-Name
221+
&User-Password := &User-Password
222+
}
223+
}
224+
case {
225+
update reply {
226+
&reply:TACACS-Server-Message = &reply:Reply-Message
227+
}
228+
}
229+
}
230+
}
231+
232+
recv Authorization {
233+
update config {
234+
&Auth-Type = Accept
235+
}
236+
}
237+
238+
send Authorization {
239+
}
240+
241+
recv Accounting {
242+
update config {
243+
&Auth-Type = Accept
244+
}
245+
}
246+
247+
send Accounting {
248+
}
249+
250+
# Proxying of TACACS+ requests is NOT supported.
251+
252+
process MSCHAP {
253+
mschap
254+
}
255+
256+
process CHAP {
257+
chap
258+
}
259+
260+
process PAP {
261+
pap
262+
}
263+
}

share/dictionary.freeradius.internal

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,14 @@ ATTRIBUTE Sigtran-MAP-Version 1230 integer
378378
ATTRIBUTE Sigtran-Mobile-Network-Code 1231 integer
379379
ATTRIBUTE Sigtran-Mobile-Country-Code 1232 integer
380380

381+
#
382+
# For TACACS+, some attribute definitions for database interface
383+
#
384+
ATTRIBUTE TACACS-Root 1240 tlv
385+
BEGIN-TLV TACACS-Root
386+
$INCLUDE dictionary.tacacs
387+
END-TLV TACACS-Root
388+
381389
#
382390
# Server-side "listen type = foo"
383391
#

0 commit comments

Comments
 (0)