#  -*- text -*- $Id: 5d6de148b39ce3fd3f9ad0a17678b8245fcd5b24 $

#######################################################################
#
#  = The default Virtual Server
#
#  The `default` virtual server is the first one that is enabled on a
#  default installation of FreeRADIUS. This configuration is designed
#  to work in the widest possible set of circumstances, with the
#  widest possible number of authentication methods. This means that
#  in general, you should need to make very few changes to this file.
#
#  The usual approach is as follows:
#
#  * configure users in a database (e.g. the `files` module, or in
#    `sql`)
#  * configure the relevant module to talk to the database
#    (e.g. `sql`)
#  * If using EAP / 802.1X, configure the certificates in
#    the `certs/` directory.
#
#  Then, run the server. This process will ensure that users can log
#  in via PAP, CHAP, MS-CHAP, etc. You should also test the server via
#  `radtest` to verify that it works.
#
#  == Editing this file
#
#  Please read "man radiusd" before editing this file. See the section
#  titled DEBUGGING. It outlines a method where you can quickly obtain
#  the configuration you want, without running into trouble. And
#  finally, the debug output can be complex. Please read
#  https://www.freeradius.org/documentation/freeradius-server/4.0.0/debugging/radiusd_X.html
#
#  The best way to configure the server for your local system is to
#  *carefully* edit this file. Most attempts to make large edits to
#  this file will *break the server*. Any edits should be small, and
#  tested by running the server with `radiusd -X`. Once the edits have
#  been verified to work, save a copy of these configuration files
#  somewhere. We recommend using a revision control system such as
#  `git`, or even a "tar" file. Then, make more edits, and test, as
#  above.
#
#  There are many "commented out" references to modules and
#  configurations These references serve as place-holders, and as
#  documentation. If you need the functionality of that module, then:
#
#  * configure the module in `mods-available/`
#  * enable the module in `mods-enabled/`.  e.g. for LDAP, do:  `cd mods-enabled;ln -s ../mods-available/ldap`
#  * uncomment the references to it in this file.
#
#  In most cases, those small changes will result in the server being
#  able to connect to the database, and to authenticate users.
#

#
#  == The Virtual Server
#
#  This is the `default` virtual server.
#
server default {
	#
	#  namespace:: The protocol namespace (i.e. dictionary) to use.
	#
	#  In v4, all "server" sections MUST start with a "namespace"
	#  parameter. This tells the server which protocol is being used.
	#
	#  All of the "listen" sections in this virtual server will only
	#  accept packets for that protocol.
	#
	namespace = radius

	#
	#  log:: The name of the logging section to use.
	#
	#  The top configuration section can contain multiple section "log
	#  foo { ... }". Each of those sections is a different named logging
	#  destination.
	#
	#  This configuration item allows setting a different logging
	#  destination for an individual virtual server.
	#
	#  There are some limitations.
	#
	#  * this logging is in _addition_ to the default logging to "log { .... }".
	#  * it is not currently possible to _replace_ the default logging destination
	#  * the name given here _must_ be a fixed string, and is not dynamically expanded.
	#
#	log = some_other_logging_destination

	#
	#  === RADIUS Configuration
	#
	#  All of the configuration for processing RADIUS packets goes here.
	#
	radius {
		#
		#  ==== Access-Request subsection
		#
		#  This section contains configuration which is specific to
		#  processing `Access-Request` 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.
		#
		Access-Request {
			#
			#  session:: Controls how ongoing (multi-round) sessions are
			#  handled
			#
			#  This section is primarily useful for EAP. It controls the number
			#  of EAP authentication attempts that can occur concurrently.
			#
			session {
				#
				#  max:: The maximum number of ongoing sessions
				#
#				max = 4096


				#
				#  max_rounds:: The maximum number of message exchanges before the server
				#  gives up
				#
#				max_rounds = 40

				#
				#  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

				#
				#  dedup_key:: Key to enforce only one active session per supplicant.
				#
				#  Some supplicants may misbehave by starting many thousands of EAP
				#  sessions, but never finishing them. These sessions can cause the server
				#  to hit 'max_sessions' very quickly. The 'timer_expire' configuration
				#  above does not help as much as it could, because the old (duplicate)
				#  session should be deleted as soon as the new one comes in.
				#
				#  If you set the 'dedup_key' below, whenever the EAP module starts a new
				#  session, it will check for a previous session which has the same dedup
				#  key. If a previous session is found, it is deleted.
				#
				#  Setting this configuration item may cause issues if the same device
				#  uses multiple EAP sessions at the same time. But that device behavior
				#  should be rare to non-existent.
				#
				#  The configuration item is commented out so that upgrades do not change
				#  existing behavior.
				#
#				dedup_key = Calling-Station-Id
			}
		}

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

	#
	#  === Local Dictionaries
	#
	#  It is now possible to have dictionaries which are local to a
	#  virtual server. The attributes defined here can be used in
	#  policies in this virtual server.
	#
	#  Any attribute defined in this section can only be used in policies
	#  in this virtual server. The attributes are "internal", and cannot
	#  go into a packet which is sent on the network.
	#
	#  When a request is proxied internally to another virtual server,
	#  these attributes are still sent with the proxied request. However,
	#  as the definitions do not exist in the other virtual server, they
	#  cannot be used in policies.
	#
	#  The other virtual server can even define attributes of the same
	#  name. That virtual server will use those definitions for its
	#  policies, and will never match the proxied attributes.
	#
	#  In all other aspects, the attributes defined here are just the
	#  same as if they had been assigned in a dictionary file.
	#
	dictionary {
		#
		#  The syntax is _<type>_ followed by _<name>_.
		#
		#  The _<type>_ MUST be a leaf type or a `group`. i.e. not `struct`,
		#  `vsa`, or `vendor`.
		#
		#  The _<name>_ MUST NOT exist in the `namespace` dictionary.
		#
		#		uint32 foo

		#
		#  tlv:: Define a TLV variable using _tlv <name> { ...}_.
		#
		#  The contents of the `tlv` subsection are more variable
		#  definitions, including child `tlv`s.
		#
		#		tlv bar {
		#		    uint32 baz
		#		    string arg
		#		}

		#
		#  values:: Define a set of values for attribute _<name>_.
		#
		#  The contents of the `values` section are a list of names and
		#  values.
		#
		#		values foo {
		#
		#  _<name>_ = _<value>_
		#
		#  The _<name>_ must be unique.
		#
		#  The _<value>_ is parsed according to the data type of the
		#  attribute.
		#
#			bar = 1
#			baz = 2
		#		}
	}


	#
	#  === The listen section
	#
	#  The `listen` sections in v4 are very different from the `listen
	#  sections in v3. The changes were necessary in order to make
	#  FreeRADIUS more flexible, and to make the configuration simpler
	#  and more consistent.
	#
	#  If there are multiple `listen` sections in the same virtual
	#  server, they need to be given a second name.
	#
	#  Listen sections are identified by virtual server name, then by the
	#  namespace, then by transport, finally by a second name.
	#
	listen authentication {
		#
		#  type:: The type of packet to accept.
		#
		#  Multiple types can be accepted by using multiple lines of `type =
		#  ...`.
		#
		#  This change from v3 makes it much clearer what kind of packet is
		#  being accepted. The old `auth+acct` configuration was awkward and
		#  potentially confusing.
		#
		type = Access-Request
		type = Status-Server

		#
		#  transport:: The transport protocol.
		#
		#  The allowed transports for RADIUS are currently `udp` and `tcp`.
		#  A `listen` section can only have one `transport` defined. For
		#  multiple transports, use multiple `listen` sections.
		#
		#  You can have a "headless" server by commenting out the
		#  "transport" configuration. A "headless" server will process
		#  packets from other virtual servers, but will not accept packets
		#  from the network.
		#
		#  The `inner-tunnel` server is an example of a headless server. It
		#  accepts packets from the "inner tunnel" portion of PEAP and TTLS.
		#  But it does not accept those packets from the network.
		#
		transport = udp

		#
		#  require_message_authenticator::Require Message-Authenticator in
		#  Access-Requests.
		#
		#  RFC 5080 suggests that all clients *should* include it in an
		#  Access-Request. The configuration item below allows the server to
		#  require it. If a client is required to include a
		#  `Message-Authenticator` and it does not, then the packet will be
		#  silently discarded.
		#
		#  If value is auto, then if any packet received from the client
		#  contains a valid Message-Authenticator attribute, then the server
		#  will require it from all future packets from that client.
		#
		#  Allowed values: yes, no, auto
		#
		#  The default is "no".
		#
		require_message_authenticator = auto

		#
		#  limit_proxy_state:: Control whether Proxy-State is allowed in
		#  packets from this client which do not have a
		#  Message-Authenticator.
		#
		#  The blastradius prefix attack allows an attacker to manipulate
		#  the contents of response packets without knowing the shared
		#  secret.
		#
		#  The attack relies on controlling a portion of the data sent back
		#  in the response by the RADIUS server. As Proxy-State is always
		#  echoed back verbatim from the request, it can be leveraged to
		#  manipulate the data sent back from the server and facilitate the
		#  attack.
		#
		#  The attack also relies on defficiencies in the original RADIUS
		#  standards that provided no integrity protection for
		#  Access-Requests.
		#
		#  The attack is mitigated by requiring the Message-Authenticator,
		#  which contains a HMAC over the entire request, preventing
		#  modification of the request by the attacker.
		#
		#  If value is auto, and the first packet received from the client
		#  does not contain a Proxy-State attribute, Proxy-State will be
		#  disallowed in any future packets which do not contain a
		#  Message-Authenticator.
		#
		#  This provides some level of protection against the blastradius
		#  attack, without requiring Message-Authenticator, or breaking
		#  existing deployments.
		#
		#  Allowed values: yes, no, auto
		#
		#  The default is "auto".
		#
		limit_proxy_state = auto

		#
		#  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_clients:: The maximum number of dynamic clients which can be
			#  defined for this listener.
			#
			#  If dynamic clients are not used, then this configuration item is
			#  ignored.
			#
			#  The special value of `0` means "no limit". We do not recommend
			#  using `0`, as attackers could forge packets from the entire
			#  Internet, and cause FreeRADIUS to run out of memory.
			#
			#  This configuration item should be set to the number of
			#  individual RADIUS clients (e.g. NAS, AP, etc.) which will be
			#  sending packets to FreeRADIUS.
			#
			max_clients = 256

			#
			#  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

			#
			#  dynamic_timeout:: Time after which idle dynamic clients are
			#  deleted.
			#
			dynamic_timeout = 600.0

			#
			#  nak_lifetime:: Time for which blocked clients are placed into a
			#  NAK cache.
			#
			#  If a dynamic client is disallowed, it is placed onto a "NAK"
			#  list for a period of time. This process helps to prevent DoS
			#  attacks. When subsequent packets are received from that IP
			#  address, they hit the "NAK" cache, and are immediately
			#  discarded.
			#
			#  After `nak_timeout` seconds, the blocked entry will be removed,
			#  and the IP will be allowed to try again to define a dynamic
			#  client.
			#
			#  Useful range of values: 1 to 600
			#
			nak_lifetime = 30.0

			#
			#  cleanup_delay:: The time to wait (in seconds) before cleaning up
			#  a reply to an `Access-Request` packet.
			#
			#  The reply is normally cached internally for a short period of
			#  time, after it is sent to the NAS. The reply packet may be lost
			#  in the network, and the NAS will not see it. The NAS will then
			#  resend the request, and the server will respond quickly with the
			#  cached reply.
			#
			#  If this value is set too low, then duplicate requests from the
			#  NAS MAY NOT be detected, and will instead be handled as separate
			#  requests.
			#
			#  If this value is set too high, then the server will use more
			#  memory for no benefit.
			#
			#  This value can include a decimal number of seconds, e.g. "4.1".
			#
			#  Useful range of values: 2 to 30
			#
			cleanup_delay = 5.0
		}

		#
		#  ==== UDP Transport
		#
		#  When the `listen` section contains `transport = udp`, it looks
		#  for a "udp" subsection. This subsection contains all of the
		#  configuration for the UDP transport.
		#
		udp {
			#
			#  ipaddr:: The IP address where FreeRADIUS accepts packets.
			#
			#  The address can be IPv4, IPv6, a numbered IP address, or a host
			#  name. If a host name is used, the IPv4 address is preferred.
			#  When there is no IPv4 address for a host name, the IPv6 address
			#  is used.
			#
			#  As with UDP, `ipaddr`, `ipv4addr`, and `ipv6addr` are all
			#  allowed.
			#
			#  ipv4addr:: Use IPv4 addresses.
			#
			#  The same as `ipaddr`, but will only use IPv4 addresses.
			#
			#  ipv6addr:: Use IPv6 addresses.
			#
			#  The same as `ipaddr`, but will only use IPv6 addresses.
			#
			ipaddr = *

			#
			#  port:: the UDP where FreeRADIUS accepts packets.
			#
			#  The default port for Access-Accept packets is `1812`.
			#
			port = 1812

			#
			#  dynamic_clients:: Whether or not we allow dynamic clients.
			#
			#  If set to `true`, then packets from unknown clients are passed
			#  through the `new client` subsection below. See that section for
			#  more information about how dynamic clients work.
			#
#			dynamic_clients = true

			#
			#  networks:: The list of networks which are allowed to send
			#  packets to FreeRADIUS for dynamic clients.
			#
			#  If there are no dynamic clients, then this section is ignored.
			#
			#  The purpose of the `networks` subsection is to ensure that only
			#  a small set of source IPs can trigger dynamic clients. If anyone
			#  could trigger dynamic clients, then the server would be subject
			#  to a DoS attack.
			#
			networks {
				#
				#  allow:: Allow packets from these networks to define dynamic clients.
				#
				#  Packets from all other sources will be rejected.
				#
				#  When a packet is from an allowed network, it will be run through the
				#  `new client` subsection below. That subsection can still reject the
				#  client request.
				#
				#  There is no limit to the number of networks which can be listed here.
				#
				allow = 127/8
				allow = 192.0.2/24

				#
				#  deny:: deny some networks.
				#
				#  The default behavior is to only allow packets from the `allow`
				#  networks. The `deny` directive allows you to carve out a subset of an
				#  `allow` network, where some packets are denied.
				#
				#  That is, a `deny` network MUST exist within a previous `allow` network.
				#
				#  The `allow` and `deny` rules apply only to networks. The order which
				#  they appear in the configuration file does not matter.
				#
#				deny = 127.0.0/24
			}
		}

		#
		#  ==== TCP Transport
		#
		#  When the configuration has `transport = tcp`, it looks for a
		#  `tcp` subsection. That subsection contains all of the
		#  configuration for the TCP transport.
		#
		#  Since UDP and TCP are similar, the majority of the configuration
		#  items are the same for both of them.
		#
		tcp {
			#
			#  ipaddr:: The IP address where FreeRADIUS accepts packets.
			#
			#  It has the same definition and meaning as the UDP `ipaddr`
			#  configuration above.
			#
			ipaddr = *

			#
			#  NOTE: As with v3, `ipaddr`, `ipv4addr`, and `ipv6addr` are all
			#  allowed.
			#

			#
			#  port:: the TCP where FreeRADIUS accepts packets.
			#
			#  The default port for Access-Accept packets is `1812`.
			#
			port = 1812

			#
			#  dynamic_clients:: Whether or not we allow dynamic clients.
			#
			#  If set to true, then packets from unknown clients are passed
			#  through the "new client" subsection below. See that section for
			#  more information.
			#
#			dynamic_clients = true

			#
			#  networks { ... }::
			#
			#  If dynamic clients are allowed, then limit them to only a small
			#  set of source networks.
			#
			#  If dynamic clients are not allowed, then this section is
			#  ignored.
			#
			networks {
				#
				#  allow:: Allow packets from a network.
				#
				#  deny:: Deny packets from a network.
				#
				#  Allow or deny packets from these networks to define dynamic clients.
				#
				#  Packets from all other sources will be discarded.
				#
				#  Even if a packet is from an allowed network, it still must be permitted
				#  by the "new client" subsection.
				#
				#  There is no limit to the number of networks which can be listed here.
				#
				#  The allow / deny checks are organised by address. The order of the
				#  items given here does not matter.
				#
				allow = 127/8
				allow = 192.0.2/24
#				deny = 127.0.0/24
			}
		}
	}

	listen authentication {
		type = Access-Request
		type = Status-Server

		transport = tcp

		tcp {
			#
			#  As with v3, "ipaddr", "ipv4addr", and "ipv6addr" are all
			#  allowed.
			#
			ipaddr = *
			port = 1812

			#
			#  Whether or not we allow dynamic clients.
			#
			#  If set to true, then packets from unknown clients are passed
			#  through the "new client" subsection below. See that section for
			#  more information.
			#
#			dynamic_clients = true

			#
			#  If dynamic clients are allowed, then limit them to only a small
			#  set of source networks.
			#
			#  If dynamic clients are not allowed, then this section is
			#  ignored.
			#
			networks {
				#
				#  Allow packets from these networks to define dynamic clients.
				#
				#  Packets from all other sources will be rejected.
				#
				#  Even if a packet is from an allowed network, it still must be allowed
				#  by the "new client" subsection.
				#
				#  There is no limit to the number of networks which can be listed here.
				#
				allow = 127/8
				allow = 192.0.2/24
#				deny = 127.0.0/24
			}
		}
	}

	#
	#  === Listen for Accounting-Request packets
	#
	listen accounting {
		type = Accounting-Request

		transport = udp

		udp {
			ipaddr = *
			port = 1813
		}
	}


	#
	#  === Local Clients
	#
	#  The "client" sections can can also be placed here. Unlike v3, they
	#  do not need to be wrapped in a "clients" section. They can just
	#  co-exist beside the "listen" sections.
	#
	#  Clients listed here will apply to *all* listeners in this virtual
	#  server.
	#
	#  The clients listed here take precedence over the global clients.
	#
	client localhost {
		shortname = sample
		ipaddr = 192.0.2.1
		secret = testing123

		#  The other "client" configuration items can be added here, too.
	}


######################################################################
#
#  == Packet Processing sections
#
#  The sections below are called when a RADIUS packet has been
#  received.
#
#  * recv Access-Request - for authorization and authentication
#  * recv Status-Server  - for checking the server is responding
#
######################################################################

#
#  === Receive Access-Request packets
#
recv Access-Request {
	#
	#  Take a `User-Name`, and perform some checks on it, for spaces and
	#  other invalid characters. If the `User-Name` is invalid, reject
	#  the request.
	#
	#  See policy.d/filter for the definition of the filter_username
	#  policy.
	#
	filter_username

	#
	#  Some broken equipment sends passwords with embedded zeros, i.e.
	#  the debug output will show:
	#
	#      User-Password = "password\000\000"
	#
	#  This policy will fix the password to just be "password".
	#
	#	filter_password

	#
	#  If you intend to use CUI and you require that the Operator-Name be
	#  set for CUI generation and you want to generate CUI also for your
	#  local clients, then uncomment operator-name below and set the
	#  operator-name for your clients in clients.conf.
	#
	#	operator-name

	#
	#  Proxying example
	#
	#  The following example will proxy the request if the username ends
	#  in example.com.
	#
	#	if (User-Name =~ /@example\.com$/) {
	#		control.Auth-Type := "proxy-example.com"
	#	}

	#
	#  If you want to generate CUI for some clients that do not send
	#  proper CUI requests, then uncomment cui below and set "add_cui =
	#  yes" for these clients in clients.conf.
	#
	#	cui

	#
	#  The `auth_log` module will write all `Access-Request` packets to a
	#  file.
	#
	#  Uncomment the next bit in order to have a log of authentication
	#  requests. For more information, see `mods-available/detail.log`.
	#
	#	auth_log

	#
	#  The `chap` module will set `Auth-Type := ::CHAP` if the packet
	#  contains a `CHAP-Challenge` attribute. The module does this only
	#  if the `Auth-Type` attribute has not already been set.
	#
	chap

	#
	#  The `mschap` module will set `Auth-Type := ::mschap` if the packet
	#  contains an `MS-CHAP-Challenge` attribute. The module does this
	#  only if the `Auth-Type` attribute has not already been set.
	#
	mschap

	#
	#  The `digest` module implements the SIP Digest authentication
	#  method.
	#
	#  Note that the module does not implement RFC 4590. Instead, it
	#  implements an earlier draft of the specification. Since all of the
	#  NAS equipment also implements the earlier draft, this limitation
	#  is fine.
	#
	#  If you have a Cisco SIP server authenticating against FreeRADIUS,
	#  the `digest` module will set `Auth-Type := "Digest"` if we are
	#  handling a SIP Digest request and the `Auth-Type` has not already
	#  been set.
	#
	digest

	#
	#  The `eap` module takes care of all EAP authentication, including
	#  EAP-MD5, EAP-TLS, PEAP and EAP-TTLS.
	#
	#  The module also sets the EAP-Type attribute in the request list,
	#  to the incoming EAP type.
	#
	#  The `eap` module returns `ok` or `updated` if it is not yet ready
	#  to authenticate the user. The configuration below checks for that
	#  return value, and if so, stops processing the current section.
	#
	#  The result is that any LDAP and/or SQL servers will not be queried
	#  during the initial set of packets that go back and forth to set up
	#  EAP-TTLS or PEAP.
	#
	#  We also recommend doing user lookups in the `inner-tunnel` virtual
	#  server.
	#
	eap {
		ok = return
		updated = return
	}

	#
	#  The `unix` module will obtain passwords from `/etc/passwd` or
	#  `/etc/shadow`. It does this via the system API's, which are not
	#  thread-safe. We do not recommend using the `unix` module.
	#
	#	unix

	#
	#  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.
	#
	-sql

	#
	#  If you are using /etc/smbpasswd, and are also doing mschap
	#  authentication, the uncomment this line, configure the module.
	#
	#	smbpasswd

	#
	#  The `ldap` module reads passwords and other attributes from an
	#  LDAP database.
	#
	-ldap

	#
	#  Enforce daily limits on time spent logged in. This module is a
	#  variant of the `counter` module.
	#
	#	dailycounter

	#
	#  See if the account has expired: check the time in the `Expiration`
	#  attribute and reject if we are past it. If the account has not
	#  expired, set `Session-Timeout`.
	#
	expiration

	#
	#  The `pap` module will set `Auth-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. `Password.NT` 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 Auth-Type for themselves.
	#
	pap
}


#
#  === Receive Status-Server packets
#
#
#  This section is processed when the server receives a
#  `Status-Server` packet.
#
recv Status-Server {
	#
	#  We are still here and responding.
	#
	ok
}


######################################################################
#
#  == Authentication Sections
#
#  The sub-sections below are called based on the value of the
#  `Auth-Type` attribute, which should have been set by the `recv
#  Access-Request` section, above.
#
#  Since version 4, proxying also happens in this section. For more
#  information on how proxying has changed in version 4, please see
#  https://www.freeradius.org/documentation/freeradius-server/4.0.0/howto/upgrade/proxy.html
#
#  For authentication, you should generally NOT set the `Auth-Type`
#  attribute. As noted above, the modules will usually figure it what
#  to do, and will do the right thing. The most common side effect of
#  erroneously setting the `Auth-Type` attribute is that one
#  authentication method will work, but all of the others will not.
#
#  The common reasons to set the `Auth-Type` attribute by hand are to
#  forcibly reject the user (`Auth-Type := ::Reject`), to or forcibly
#  accept the user (`Auth-Type := ::Accept`), or for proxying.
#
#  Note that `Auth-Type := ::Accept` will NOT work with EAP. The EAP
#  authentication protocol uses a series of handshake messages. All of
#  the messages must be exchanged correctly in order for EAP
#  authentication to succeed. Bypassing that process with `Auth-Type
#  := Accept` will just result in the user being rejected.
#
#  Policy configuration should generally go in the `send ...` sections
#  below, after authentication has completed.
#
######################################################################

#
#  === PAP Authentication
#
#  For users who are using PAP authentication. A back-end database
#  listed in the "recv Access-Request" section MUST supply a "known
#  good" password for the user. The password can be clear-text, or
#  encrypted via `crypt`, `bcrypt`, or other hashing.
#
authenticate pap {
	pap
}

#
#  === CHAP Authentication
#
#  For users who are using CHAP authentication. A back-end database
#  listed in the "recv Access-Request" section MUST supply a
#  Password.Cleartext attribute. Encrypted passwords won't work.
#
authenticate chap {
	chap
}

#
#  === MS-CHAP authentication
#
#  For users who are using MS-CHAP authentication. A back-end database
#  listed in the "recv Access-Request" section MUST supply either a
#  Password.Cleartext attribute, or a Password.NT attribute. Encrypted
#  passwords won't work.
#
authenticate mschap {
	mschap
}

#
#  === SIP Digest Authentication
#
#  For users who are using SIP Digest authentication.
#
#  The `digest` line in the `recv Access-Request` section should also
#  be uncommented.
#
authenticate digest {
	digest
}

#
#  === PAM (Pluggable Authentication Modules) Authentication
#
#  Authenticate with PAM (Pluggable Authentication Modules).
#
#  We do not recommend using PAM. The server has enough functionality
#  that anything that can be done in PAM can be done easier in
#  FreeRADIUS.
#
##authenticate pam {
##	pam
##}

#
#  === LDAP Authentication
#
#  For users who are using PAP, and when you can't get the "known
#  good" password from LDAP. The module binds to the LDAP directory as
#  the user, along with the password taken from the User-Password
#  attribute. The "bind as user" method means that CHAP, MS-CHAP, and
#  EAP won't work, as they do not supply a plain-text password.
#
#  We do NOT recommend using this. LDAP servers are databases, not
#  authentication servers. It is only here as a last resort for
#  databases such as Active Directory.
#
#  We strongly recommend using `ldap` in the `recv Access-Request`
#  section. And, ensuring that the account used by FreeRADIUS has read
#  permission on all of the users, groups, and passwords.
#
authenticate ldap {
	-ldap
}

#
#  === EAP Authentication
#
#  For EAP-MD5, EAP-MSCHAP, EAP-TLS, EAP-TTLS, EAP-PEAP, EAP-PWD, etc.
#
authenticate eap {
	eap
}


#
#  === Proxying
#
#  Proxying has changed substantially from v3 to v4. These changes are
#  complex, but were necessary in order to support new features. The
#  result is that configurations which were impossible in v3 are now
#  trivial in v4. For example:
#
#  * sending the same packet to multiple destinations, along with retransmissions
#  * sending the same packet to multiple destinations in parallel
#  * trying to proxy, and if it fails, programmatically doing something else
#  * trying to proxy, and if it fails, authenticating the user locally
#    * note that this won't work for EAP.
#
#  For more information, see:
#  https://www.freeradius.org/documentation/freeradius-server/4.0.0/howto/upgrade/proxy.html
#

#
#  The following example shows how proxying to three remote servers
#  can be configured.
#
#  Proxying will be done by setting `Auth-Type := example.com`, and
#  defining the home servers in `mods-available/radius`.
#
#  If you need to edit the request and/or the reply, you should use
#  the `subrequest` keyword. See the `subrequest` documentation for
#  more information.
#

##authenticate example.com {
##	#
##	#  Log the request before proxying.
##	#
##	pre_proxy_log
##
##	#
##	#  Send the request to remote RADIUS servers, with
##	#  fail-over from one to the other if there's no response.
##	#
##	redundant {
##		radius1.example.com
##		radius2.example.com
##		radius3.example.com
##	}
##
##	#
##	#  Log the reply after proxying.
##	#
##	post_proxy_log.post-proxy
##}



#
#  == Send replies to Access-Request packets
#

#
#  === send Access-Challenge packets
#
#
#  This section is called when sending an Access-Challenge response.
#  It is configured to filter out all attributes that should not be in
#  the packet.
#
send Access-Challenge {
	attr_filter.access_challenge
	handled
}

#
#  === send Access-Accept packets
#
#  Once we know that the user has been authenticated successfully,
#  there are additional things that can be done.
#
send Access-Accept {
	#
	#  If you need to have a State attribute, you can add it here. e.g.
	#  for later CoA-Request with State, and Service-Type =
	#  ::Authorize-Only.
	#
	#	if (!reply.State) {
	#		reply.State := "0x%str.rand(16h)"
	#	}

	#
	#  For EAP-TTLS and PEAP, add any cached attributes to the reply. The
	#  "session-state" attributes are automatically cached when an
	#  Access-Challenge is sent, and retrieved when an `Access-Request`
	#  is received.
	#
	#  The `session-state` attributes are deleted after an
	#  `Access-Reject` or `Access-Accept` packet has been sent.
	#
	reply += session-state

	#
	#  For EAP, ensure that the Access-Accept contains a User-Name
	#  attribute.
	#
	eap

	#
	#  Get an address from the IP Pool.
	#
	#	sqlippool


	#
	#  Create the CUI value and add the attribute to Access-Accept.
	#  Uncomment the line below if *returning* the CUI to the NAS.
	#
	#	cui

	#
	#  If you want to have a log of authentication replies, uncomment the
	#  following line. This is defined in `mods-available/detail.log`.
	#
	#	reply_log

	#
	#  After authenticating the user, do another SQL query.
	#
	-sql

	#
	#  Uncomment the following if you want to modify the user's object in
	#  LDAP after a successful login.
	#
	#	ldap

	#
	#  If there is a client certificate (EAP-TLS, and very occasionally
	#  PEAP and EAP-TTLS), then some attributes are filled out after the
	#  certificate verification has been performed. These fields MAY be
	#  available during the authentication, or they may be available only
	#  in the appropriate "send" section.
	#
	#  The first set of attributes contains information about the issuing
	#  certificate which is being used. The second contains information
	#  about the client certificate (if available).
	#
##	reply += {
##		Reply-Message = "%{session-state.TLS-Certificate.Serial}"
##		Reply-Message = "%{session-state.TLS-Certificate.Not-After}"
##		Reply-Message = "%{session-state.TLS-Certificate.Subject}"
##		Reply-Message = "%{session-state.TLS-Certificate.Issuer}"
##		Reply-Message = "%{session-state.TLS-Certificate.Common-Name}"
##		Reply-Message = "%{session-state.TLS-Certificate.Subject-Alt-Name-Email}"
##	}

	#
	#  Insert the `Class` attribute with a unique value into the
	#  response, which aids matching auth and acct records and protects
	#  against duplicate Acct-Session-Id.
	#
	#  NOTE: This only works if the NAS has implemented RFC 2865
	#  behaviour for the Class attribute, AND if the NAS supports long
	#  Class attributes. Many older or cheap NASes only support 16-octet
	#  Class attributes.
	#
	#	insert_acct_class

	#
	#  MacSEC requires the use of `EAP-Key-Name`. However, we don't want
	#  to send it for all EAP sessions. Therefore, the EAP modules put
	#  required data into the `EAP-Session-Id` attribute. This attribute
	#  is never put into a request or reply packet.
	#
	#  Uncomment the next few lines to copy the required data into the
	#  EAP-Key-Name attribute.
	#
##	if (reply.EAP-Session-Id) {
##		reply.EAP-Key-Name := reply.EAP-Session-Id
##	}

	#
	#  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_access_accept

	#
	#  Remove `Reply-Message` if the response contains an `EAP-Message`
	#  attribute. Some NAS equipment will automatically convert the
	#  `Reply-Message` to an "EAP notification" packet, which will cause
	#  end-user machines to drop the network connection.
	#
	remove_reply_message_if_eap
}

#
#  === send Access-Reject packets
#
#  This section processes `Access-Reject` packets before they are sent
#  to the NAS.
#
#  The `session-state` list is available while this section is being
#  processed. But all of the attributes in that list are discarded as
#  soon as the section is finished.
#
send Access-Reject {
	#
	#  Log failed authentications in SQL, too.
	#
	-sql

	#
	#  Filter out attributes that should not be in Access-Reject packets.
	#
	attr_filter.access_reject

	#
	#  Insert an EAP-Failure message if the request was rejected by
	#  policy, instead of from an authentication failure.
	#
	eap

	#
	#  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_access_reject

	#
	#  Remove `Reply-Message` if the response contains an `EAP-Message`
	#  attribute. Some NAS equipment will automatically convert the
	#  `Reply-Message` to an "EAP notification" packet, which will cause
	#  end-user machines to drop the network connection.
	#
	remove_reply_message_if_eap

	#
	#  Delay sending the `Access-Reject` packet. This is no longer
	#  automatic as it was in version 3.
	#
	delay_reject
}



######################################################################
#
#  == Accounting
#
#
#  This section deals with receiving Accounting requests and sending
#  Accounting responses.
#
######################################################################

#
#  === Receive Accounting-Request packets
#
#  An Accounting-Request packet has been received. Decide which
#  accounting type to use.
#
recv Accounting-Request {
	#
	#  Merge Acct-[Input|Output]-Gigawords and Acct-[Input-Output]-Octets
	#  into a single 64-bit counter, Acct-[Input|Output]-Octets64.
	#
	#	acct_counters64

	#
	#  Session start times are *implied* in RADIUS. The NAS never sends a
	#  "start time". Instead, it sends a start packet, *possibly* with an
	#  Acct-Delay-Time, or an Event-Timestamp. The server is supposed to
	#  conclude that the start time was "Acct-Delay-Time" seconds in the
	#  past.
	#
	#  If there's no Event-Timestamp, then we create one, using
	#  Acct-Delay-Time as an offset if it exists. BUT we only do this if
	#  Acct-Delay-Time exists, and has a reasonable value.
	#
	if (!Event-Timestamp) {
		Event-Timestamp := %time.request()

		if (Acct-Delay-Time && (Acct-Delay-Time < 86400 * 7)) {
			Event-Timestamp -= Acct-Delay-Time
		}
	}

	#
	#  Ensure that we have a semi-unique identifier for every request, as
	#  many NAS boxes are broken.
	#
	acct_unique

	#
	#  Read the 'accounting' file.
	#
	files_accounting
}

#
#  Version 4 allows for sections specific to Acct-Status-Type.
#
#  Once the `recv Accounting-Request` section is processed, one of the
#  `accounting ... { ... }` sections will be run, based on the value
#  of the `Acct-Status-Type` attribute.
#
#  After the `accounting ... { ... }` section has been run, it will
#  then process the `send Accounting-Response` section
#

#
#  == Sections for Acct-Status-Type
#
#  === Session start
#
accounting Start {
	#
	#  Log traffic to an SQL database.
	#
	#  See "Accounting Queries" in `mods-available/sql`.
	#
	-sql

	#
	#  Refresh leases when we see a start.
	#
	#  Ensure that control.IP-Pool.Name is set to determine which pool of
	#  IPs are used. Set this in `recv Accounting-Request` so it is
	#  available for all the accounting sections.
	#
	#	sqlippool
}

#
#  === Session stop
#
accounting Stop {
	#
	#  Log traffic to an SQL database.
	#
	-sql

	#
	#  If you receive stop packets with zero session length, they will
	#  NOT be logged in the database. The SQL module will print a message
	#  (only in debugging mode), and will return "noop".
	#
	#  You can ignore these packets by uncommenting the following three
	#  lines. Otherwise, the server will not respond to the accounting
	#  request, and the NAS will retransmit.
	#
##	if (noop) {
##		ok
##	}

	#
	#  Return an address to the IP Pool when we see a stop record.
	#
	#	sqlippool
}

#
#  === Session is still alive
#
accounting Interim-Update {
	#
	#  Log traffic to an SQL database.
	#
	-sql

	#
	#  Refresh leases when we see an alive.
	#
	#	sqlippool
}

#
#  === The NAS has just booted up.
#
accounting Accounting-On {
	#
	#  Record that the NAS has booted to an SQL database
	#
	-sql

	#
	#  Return all addresses related to this NAS to the IP Pool
	#
	#	sqlippool
}

#
#  === The NAS is about to shut down
#
accounting Accounting-Off {
	#
	#  Record that the NAS is shutting down to an SQL database
	#
	-sql

	#
	#  Return all addresses related to this NAS to the IP Pool
	#
	#	sqlippool
}

#
#  === The user session failed in some way
#
accounting Failed {

}

#
#  There are many other values for `Acct-Status-Type` such as:
#
#  * Tunnel-Start
#  * Tunnel-Stop
#  * Tunnel-Reject
#  * Tunnel-Link-Start
#  * Tunnel-Link-Stop
#  * Tunnel-Link-Reject
#
#  Some vendors also define their own values, which is a very bad
#  idea.
#

#
#  === Send Accounting-Response.
#
#  Log the accounting data before replying. If logging fails then the
#  reply will not be sent, which means the NAS will send the request
#  again.
#
send Accounting-Response {
	#
	#  Add the CUI attribute from the corresponding Access-Accept to the
	#  Accounting-Response.
	#
	#  Use it only if your NAS boxes do not support CUI themselves.
	#
	#	cui

	#
	#  Create a 'detail'ed log of the packets. Note that accounting
	#  requests which are proxied are also logged in the detail file.
	#
	detail

	#
	#  Update counters for daily usage calculations.
	#
	#	daily

	#
	#  Cisco VoIP specific bulk accounting.
	#
	#	pgsql-voip

	#
	#  Filter attributes from the accounting response.
	#
	attr_filter.accounting_response
}

#
#  == Finally
#
#  If a `finally` section is defined, then all packets will be
#  processed through it.
#
#  This includes packets whose processing has been stopped due to
#  reaching `request.timeout`. Such packets can be detected by testing
#  for the `timeout` rcode.
#
#  The `finally` section can be used as a common logging section for
#  all packets, allowing their final state to be captured.
#
##finally {
##	if (timeout) {
##		logging relating to timeouts
##		return
##	}
##
##	normal packet logging
##}
}
