######################################################################
server tacacs {
+ #
+ # namespace:: Needs to be "tacacs" for TACACS+ functionality.
+ #
namespace = tacacs
listen {
- ipaddr = *
+ #
+ # type:: The type of packet to accept.
+ #
+ # Multiple types can be accepted by using multiple
+ # lines of `type = ...`.
+ #
+ # As described in RFC https://tools.ietf.org/id/draft-ietf-opsawg-tacacs-07.html#rfc.section.5,
+ # the packet types are:
+ #
+ type = Authentication-Start
+ type = Authentication-Continue
+# type = Authorization-Request
+# type = Accounting-Request
+
+ #
+ # transport:: The transport protocol.
+ #
+ # Only `tcp` is allowed.
+ #
transport = tcp
+ #
+ # ## Protocols
+ #
+ # For now, only TCP is supported.
+ #
+ # tcp { ... }:: TCP is configured here.
+ #
tcp {
- # Port on which to listen.
- # Allowed values are:
- # integer port number
- # 49 is the default TACACS+ port.
- port = 49
+ #
+ # port:: The port where we accept packets.
+ #
+ # The port should be 49 for a production network.
+ #
+ port = 4900
- # Type of packets to listen for. Here, it is TACACS+.
- type = tacacs
+ #
+ # ipaddr:: The IP address where we accept packets.
+ #
+ ipaddr = *
- # Some systems support binding to an interface, in addition
- # to the IP address. This feature isn't strictly necessary,
- # but for sites with many IP addresses on one interface,
- # it's useful to say "listen on all addresses for
- # eth0".
#
- # If your system does not support this feature, you will
- # get an error if you try to use it.
+ # interface:: Interface to bind to.
#
- # interface = eth0
- }
+# interface = eth0
+
+ #
+ # max_packet_size:: Our max packet size. may be different from the parent.
+ #
+# max_packet_size = 4096
- type = Authentication
- type = Authorization
+ #
+ # recv_buff:: How big the kernel's receive buffer should be.
+ #
+# recv_buff = 1048576
+
+ #
+ # send_buff:: How big the kernel's send buffer should be.
+ #
+# send_buff = 1048576
+
+ #
+ # src_ipaddr:: IP we open our socket on.
+ #
+# src_ipaddr = ""
+ }
}
#
- # This section is called when it receives an Authentication.
+ # ## Authentication-Start
#
- recv Authentication {
- if (&TACACS-Sequence-Number > 1) {
- update request {
- TACACS-Authentication-Type = &session-state:TACACS-Authentication-Type
- }
- }
- # draft-ietf-opsawg-tacacs section 4.4.2
+ #
+ # ### Recv
+ #
+ recv Authentication-Start {
switch &TACACS-Authentication-Type {
- # ASCII is very generic and driven via unlang so go wild!
- case "ASCII" {
- if (&TACACS-Sequence-Number == 1) {
- update request {
- &User-Name = &TACACS-User-Name
- }
- } else {
- update request {
- User-Name = &session-state:User-Name
- User-Password = &session-state:User-Password
- }
- }
-
- if (!&User-Name) {
- if (&TACACS-User-Message) {
- update request {
- &User-Name = &TACACS-User-Message
- &TACACS-User-Message !* "*"
- }
- } else {
- update reply {
- TACACS-Authentication-Status = Get-User
- TACACS-Server-Message = "username: "
- }
- handled
- }
- }
- if (!&User-Password) {
- if (&TACACS-User-Message) {
- update request {
- &User-Password = &TACACS-User-Message
- &TACACS-User-Message !* "*"
- }
- } else {
- update reply {
- TACACS-Authentication-Status = Get-Pass
- TACACS-Server-Message = "password: "
- }
- handled
- }
- }
- #if (&User-Name && &User-Password) {
- # if (!&TACACS-User-Message) {
- # update reply {
- # TACACS-Authentication-Status = Get-Data
- # TACACS-Authentication-Flags = No-Echo
- # TACACS-Server-Message = "pin: "
- # }
- # handled
- # }
- # if (&TACACS-User-Message != "1234") {
- # reject
- # }
- #}
- }
- case "PAP" {
- if (&TACACS-Sequence-Number == 1) {
- if (!&TACACS-User-Name) {
- update reply {
- &TACACS-Server-Message = "missing User-Name field"
- }
- invalid
- }
-
- update request {
- &User-Name = &TACACS-User-Name
- &User-Password = &TACACS-Data
- }
- } else {
- update request {
- User-Name = &session-state:User-Name
- }
- }
-
- if (!&User-Password) {
- if (&TACACS-User-Message) {
- update request {
- &User-Password = &TACACS-User-Message
- }
- } else {
- update reply {
- TACACS-Authentication-Status = Get-Pass
- TACACS-Server-Message = "password: "
- }
- handled
- }
- }
- }
- case "CHAP" {
- if (&TACACS-Sequence-Number > 1) {
- invalid
+ case PAP {
+ update request {
+ &User-Name := &TACACS-User-Name
+ &User-Password := &TACACS-Data
+ &Cleartext-Password := &TACACS-Data
}
- if (&TACACS-User-Name && &TACACS-Data =~ /^(.)(.{16})(.{16})$/) {
- update request {
- &User-Name = &TACACS-User-Name
- &CHAP-Challenge = "%{2}"
- &CHAP-Password = "%{1}%{3}"
- }
- } else {
- update reply {
- &TACACS-Server-Message = "missing User-Name and/or Data fields"
- }
- invalid
- }
+ #
+ # Read what used to be the `users` file. Since v3, this file
+ # is located in `mods-config/files/authorize`.
+ #
+ files
+
+ #
+ # Look in an SQL database. The schema of the database is
+ # meant to mirror the `users` file. For a full description
+ # of the module behavior, please see
+ # https://wiki.freeradius.org/modules/Rlm_sql
+ #
+ -sql
+
+ #
+ # The `pap` module will set `TACACS-Authentication-Type := PAP` if the
+ # packet contains a `User-Password` attribute. The module
+ # does this only if the `Auth-Type` attribute has not already
+ # been set.
+ #
+ # The `pap` module is also responsible for "normalizing" the
+ # various kinds of "known good" passwords.
+ # e.g. `NT-Password` may come as a 16 byte blob, or as a
+ # 32-byte hex string, or as a base-64 encoded string. The
+ # `pap` module will look for common variations of password
+ # encoding, and convert them all to a normal form.
+ #
+ # This module should be listed last, so that the other
+ # modules get a chance to set TACACS-Authentication-Type for themselves.
+ #
+ pap
}
- case "MSCHAP" { # UNTESTED
- if (&TACACS-Sequence-Number > 1) {
- invalid
- }
- if (&TACACS-User-Name && &TACACS-Data =~ /^(.)(.{8})(.{50})$/) {
- update request {
- &User-Name = &TACACS-User-Name
- &MS-CHAP-Challenge = "%{2}"
- &MS-CHAP-Response = "%{1}%{3}"
- }
- } else {
- update reply {
- &TACACS-Server-Message = "missing User-Name and/or Data fields"
- }
- invalid
- }
- }
- case "MSCHAPv2" { # UNTESTED
- if (&TACACS-Sequence-Number > 1) {
- invalid
- }
-
- if (&TACACS-User-Name && &TACACS-Data =~ /^(.)(.{16})(.{50})$/) {
- update request {
- &User-Name = &TACACS-User-Name
- &MS-CHAP-Challenge = "%{2}"
- &MS-CHAP2-Response = "%{1}%{3}"
- }
- } else {
- update reply {
- &TACACS-Server-Message = "missing User-Name and/or Data fields"
- }
- invalid
- }
- }
- case {
- update reply {
- &TACACS-Server-Message = "unsupported authentication type"
- }
- invalid
- }
+ #
+ # For now the 'chap' is only supported with RADIUS
+ #
+# case CHAP {
+# chap
+# }
}
- files
+ -sql
+ }
- mschap
+ authenticate PAP {
+ pap
+ }
+ authenticate CHAP {
chap
-
- pap
}
#
- # This section is called when it sends an Authentication.
+ # ### Send
#
- send Authentication {
- switch &TACACS-Authentication-Type {
- case "ASCII" {
- update session-state {
- &TACACS-Authentication-Type := &TACACS-Authentication-Type
- &User-Name := &User-Name
- &User-Password := &User-Password
- }
- }
- case {
- update reply {
- &reply:TACACS-Server-Message = &reply:Reply-Message
- }
- }
- }
+ send Authentication-Start-Reply {
+# if (&TACACS-Authentication-Status == Pass) {
+# update reply {
+# &TACACS-Server-Message := "Hello %{TACACS-User-Name}"
+# }
+# }
}
- recv Authorization {
- update config {
- &Auth-Type = Accept
- }
+ #
+ # ## Authentication-Continue
+ #
+
+ #
+ # ### Recv
+ #
+ recv Authentication-Continue {
+ #
+ # https://tools.ietf.org/id/draft-ietf-opsawg-tacacs-07.html#rfc.section.4.3
+ #
+ "%{TACACS-Authentication-Continue-Flags}"
+ "%{TACACS-User-Message}"
+ "%{TACACS-Data}"
}
- send Authorization {
+ #
+ # ### Send
+ #
+ send Authentication-Continue-Reply {
+# if (&TACACS-Authentication-Status == Pass) {
+# update reply {
+# &TACACS-Server-Message := "Hello %{TACACS-User-Name}"
+# }
+# }
}
- recv Accounting-Request {
- update config {
- &Auth-Type = Accept
- }
+ #
+ # ## Authorization
+ #
+
+ #
+ # ### Recv
+ #
+ recv Authorization-Request {
+ "%{TACACS-Authentication-Method}"
+ "%{TACACS-Privilege-Level}"
+ "%{TACACS-Authentication-Type}"
+ "%{TACACS-Authentication-Service}"
+ "%{TACACS-User-Name}"
+ "%{TACACS-Client-Port}"
+ "%{TACACS-Remote-Address}"
+ "%{TACACS-ArgumentList}"
}
- send Accounting-Response {
+ #
+ # ### Send
+ #
+ send Authorization-Response {
+ update reply {
+ &TACACS-Authorization-Status := Pass-Add
+ &TACACS-Server-Message := "authorization-response-server"
+ &TACACS-Data := "authorization-response-data"
+ &TACACS-ArgumentList := "key1=var1"
+ }
}
- # Proxying of TACACS+ requests is NOT supported.
+ #
+ # ## Accounting
+ #
- authenticate mschap {
- mschap
+ #
+ # ### Recv
+ #
+ recv Accounting-Request {
+ "%{TACACS-Accounting-Flags}"
+ "%{TACACS-Authentication-Method}"
+ "%{TACACS-Privilege-Level}"
+ "%{TACACS-Authentication-Type}"
+ "%{TACACS-Authentication-Service}"
+ "%{TACACS-User-Name}"
+ "%{TACACS-Client-Port}"
+ "%{TACACS-Remote-Address}"
+ "%{TACACS-ArgumentList}"
}
- authenticate chap {
- chap
+ #
+ # ### Send
+ #
+ send Accounting-Response {
+ update reply {
+ &TACACS-Accounting-Status := Success
+ &TACACS-Server-Message := "acct-response-server"
+ &TACACS-Data := "acct-response-data"
+ }
}
- authenticate pap {
- pap
- }
+ #
+ # NOTE: Proxying of TACACS+ requests is NOT supported.
+ #
}