#  -*- text -*-
######################################################################
#
#######################################################################
#
#  = The tacacs Virtual Server
#
#  The `tacacs` virtual server processes TACACS+ packets.
#
#	https://www.rfc-editor.org/rfc/rfc8907
#
#	$Id: 035988ccd2688ad10dfe438b0664a42ee4b01afe $
#
######################################################################

#
#  ## The Virtual Server
#
#  This is the `tacacs` virtual server.
#
server tacacs {
	#
	#  namespace:: Needs to be "tacacs" for TACACS+ functionality.
	#
	namespace = tacacs

	#
	#  ### TACACS+ Configuration
	#
	#  All of the configuration for processing TACACS+ packets goes here.
	#
	tacacs {
		#
		#  #### Authentication subsection
		#
		#  This section contains configuration which is
		#  specific to processing `Authentication` packets.
		#
		#  Similar sections can be added, but are not
		#  necessary for Accounting-Request (and other)
		#  packets.  At this time, there is no configuration
		#  needed for other packet types.
		#
		Authentication {
			#
			#  session:: Controls how ongoing
			#  (multi-round) sessions are handled
			#
			#  This section is only useful for ASCII authentications.
			#  It is the only authentication type which supports
			#  sending challenges for further data.
			#
			session {
				#
				#  max:: The maximum number of concurrent ongoing sessions
				#
#				max = 4096

				#
				#  max_rounds: The maximum number of round trips which are allowed
				#
				#  This is only enforced for `Authentication-Type = ASCII`, when
				#  the server replies with `GetUser` or `GetPass` or `GetData`.
				#
				#  Some broken clients will send packets in a loop, forever.
				#  This configuration helps to catch and prevent that.
				#
				max_rounds = 4

				#
				#  timeout:: How long to wait before expiring a
				#  session.
				#
				#  The timer starts when a response
				#  with a state value is sent.  The
				#  timer stops when a request
				#  containing the previously sent
				#  state value is received.
				#
#				timeout = 15
			}
		}

		#
		#  There is currently no configuration for other packet types.
		#
	}

	listen {
		#
		#  type:: The type of packet to accept.
		#
		#  Multiple types can be accepted by using multiple
		#  lines of `type = ...`.
		#
		#  As described in RFC 8907, the packet types are:
		#
		type = Authentication-Start
		type = Authentication-Continue
		type = Authorization-Request
		type = Accounting-Request

		#
		#  transport:: The transport protocol.
		#
		#  Only `tcp` is allowed.  TACACS+ does not use UDP or TLS.
		#
		transport = tcp

		#
		#  ## Protocols
		#
		#  tcp { ... }:: TCP is configured here.
		#
		tcp {
			#
			#  NOTE: Don't change anything if you are not sure.
			#

			#
			#  port:: The port where we accept packets.
			#
			#  The port should be 49 for a production network.
			#
			port = 49

			#
			#  ipaddr:: The IP address where we accept packets.
			#
			ipaddr = *

			#
			#  interface:: Interface to bind to.
			#
#			interface = eth0

			#
			#  max_packet_size:: Our max packet size. may be different from the parent.
			#
#			max_packet_size = 4096

			#
			#  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 = ""
		}

		#
		#  limit:: limits for this socket.
		#
		#  The `limit` section contains configuration items
		#  which enforce various limits on the socket.  These
		#  limits are usually transport-specific.
		#
		#  Limits are used to prevent "run-away" problems.
		#
		limit {
			#
			#  max_connections:: The maximum number of
			#  connected sockets which will be accepted
			#  for this listener.
			#
			#  Each connection opens a new socket, so be
			#  aware of system file descriptor
			#  limitations.
			#
			#  If the listeners do not use connected
			#  sockets (e.g. TCP), then this configuration
			#  item is ignored.
			#
			max_connections = 256

			#
			#  idle_timeout:: Time after which idle
			#  connections are deleted.
			#
			#  Useful range of values: 5 to 600
			#
			idle_timeout = 60.0
		}
	}

	#
	#  ## Clients
	#
	#  A virtual server can have multiple `client` definitions.  These clients take priority
	#  over  the global `client` definitions.
	#
	#  See the main `clients.conf` file for documentation on the `client` section.
	#
	client tacacs {
		ipaddr = 127.0.0.1

		#
		#  This has to be specified for all TACACS+ clients.
		#
		#  There is no standard for TACACS+ over UDP.
		#
		proto = tcp

		#
		#  The TACACS+ key, or secret.  If a secret is defined, then
		#  it will be used.  All packets coming from this client MUST be
		#  encrypted with the shared secret.
		#
		#  The `secret` configuration item can be omitted or deleted,
		#  in which case all of the information (including passwords)
		#  are sent over the network in the clear.  This practice is
		#  not recommended.
		#
		secret = testing123
	}

	#
	#  ## Authentication-Start
	#

	#
	#  ### Recv
	#
	#
	#  In general, it is not necessary to set `Auth-Type` in this section.  The packet header
	#  contains a TACACS `Authentication-Type` with value `PAP`, `CHAP`, etc.  That value will
	#  be used automatically by the server to set `Auth-Type`.
	#
	#  The only reason to set `Auth-Type` here is when you want to use a custom
	#  authentication method, such as `ldap`.  You should ONLY set `Auth-Type := ldap` when
	#  the packet contains `Authentication-Type = PAP` _and_ the passwords in LDAP are stored
	#  in "crypt" or hashed form.
	#
	recv Authentication-Start {
		-sql
	}

	authenticate PAP {
		pap
	}

	authenticate CHAP {
		chap
	}

	authenticate MSCHAP {
		mschap
	}

	authenticate MSCHAPv2 {
		mschap
	}

	#
	#  LDAP authentication will only work with PAP authentication
	#
#	authenticate ldap {
#		if (Authentication-Type != PAP) {
#			%log.warn("The packet is not PAP.  LDAP authentication is likely to fail!")
#		}
#
#		ldap
#	}

	#
	#  The automatic state machine will ensure that both User-Name
	#  and User-Password have been provided by this point making
	#  ASCII authentication equivalent to PAP.
	#
	#  Alternatively, if extra data is required, set
	#  &reply.Authentication-Status := Getdata
	#  to request the extra data, which will be in &User-Message in
	#  the next packet (if the client provides it)
	#
	authenticate ASCII {
		pap
	}

	#
	#  ### Send
	#
	#  Note that "follow" is officially deprecated, and is not supported.
	#
	send Authentication-Pass {
		&reply.Server-Message := "Hello %{User-Name}"

		#
		#  Call an instance of `linelog` to log the authentication success
		#  - equivalent to the previous log `auth = yes` option in v3.
		#  See `mods-enabled/linelog` for message formats and destinations.
		#
#		log_auth_authentication_pass
	}

	send Authentication-Fail {
		&reply.Server-Message := "Failed login!"

		#
		#  Call an instance of `linelog` to log the authentication failure
		#  - equivalent to the previous log `auth = yes` option in v3.
		#  See `mods-enabled/linelog` for message formats and destinations.
		#
#		log_auth_authentication_fail
	}

	#
	#  With ASCII methods, GetUser and GetPass typically send a prompt
	#  for the client to present to the user.
	#
	send Authentication-GetUser {
		&reply.Server-Message := "Username:"
	}

	send Authentication-GetPass {
		&reply.Server-Message := "Password:"
	}

	#
	#  ## Authentication-Continue
	#
	#  This section handles responses to challenges for `Authentication-Type = ASCII`
	#
	#  i.e. The server receives an `Authentication-Start` packet
	#  with `Authentication-Type = ASCII`, and replies with a
	#  challenge.  The client returns the username or password in
	#  an `Authentication-Continue` packet.  The server should
	#  then check the username or password.
	#
	#  The TACACS+ protocol puts the response username or password
	#  into the "data" field.  For simplicity, the server copies
	#  that field into the User-Name or User-Password attribute as
	#  appropriate.  This automatic copyinh means that it is a lot
	#  easier to understand and configure TACACS+.
	#

	#
	#  ### Recv
	#
	#  Receive `Authentication-Continue` packet.  When this
	#  section is done and has a User-Password, the server will
	#  run an `authenticate ... { }` section.  It will then call
	#  one of the `send` sections to send the reply.
	#
	recv Authentication-Continue {
		#
		#	https://tools.ietf.org/id/draft-ietf-opsawg-07.html#rfc.section.4.3
		#
		"%{Authentication-Continue-Flags}"
		"%{User-Message}"
		"%{Data}"
	}

	#
	#	## Authorization
	#

	#
	#	### Recv
	#
	recv Authorization-Request {
		"%{Authentication-Method}"
		"%{Privilege-Level}"
		"%{Authentication-Type}"
		"%{Authentication-Service}"
		"%{User-Name}"
		"%{Client-Port}"
		"%{Remote-Address}"
		"%{Argument-List}"
	}

	#
	#	### Send
	#
	#	Add the arguments to whatever the user entered.
	#
	send Authorization-Pass-Add {
		&reply.Authorization-Status := Pass-Add
		&reply.Server-Message := "authorization-response-server"
		&reply.Data := "authorization-response-data"
		&reply.Argument-List := "key1=var1"
	}

	#
	#	Replace whatever the user entered with the following arguments
	#
	send Authorization-Pass-Reply {
		&reply.Authorization-Status := Pass-Repl
		&reply.Server-Message := "authorization-response-server"
		&reply.Data := "authorization-response-data"
		&reply.Argument-List := "key1=var1"
	}

	#
	#	Reject the request
	#
	send Authorization-Fail {
		&reply.Authorization-Status := Fail
	}

	#
	#	## Accounting
	#

	#
	#	### Recv
	#
	recv Accounting-Request {
		#
		#  Create a 'detail'ed log of the packets.
		#
		detail
	}

	#  First packet for a session
	accounting Start {
	}

	#  Updates a previous start
	accounting Watchdog-Update {
	}

	#  Updates a session
	accounting Watchdog {
	}

	#  Stops a session
	accounting Stop {
	}

	#
	#	### Send
	#
	send Accounting-Success {
		&reply.Server-Message := "Success"
	}

	send Accounting-Error {
		&reply.Server-Message := "Error"
	}

	#
	#	NOTE: Proxying of TACACS+ requests is NOT supported.
	#
}
